Advertisement
Guest User

Lumberjack Job

a guest
Jun 5th, 2016
3,611
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 36.86 KB | None | 0 0
  1. #define     FILTERSCRIPT
  2. #include    <a_samp>
  3. #include    <evf>           // by Emmet_ - http://forum.sa-mp.com/showthread.php?t=486060
  4. #include    <izcmd>         // by Yashas - http://forum.sa-mp.com/showthread.php?t=576114
  5. #include    <progress2>     // by [HLF]Southclaw - http://forum.sa-mp.com/showthread.php?t=537468
  6. #include    <sqlitei>       // by Slice - http://forum.sa-mp.com/showthread.php?t=303682
  7. #include    <sscanf2>       // by Y_Less - http://forum.sa-mp.com/showthread.php?t=602923
  8. #include    <streamer>      // by Incognito - http://forum.sa-mp.com/showthread.php?t=102865
  9. #include    <YSI\y_iterate> // by Y_Less - http://forum.sa-mp.com/showthread.php?t=570884
  10.  
  11. #define     MAX_TREES       (100)   // tree limit
  12. #define     MAX_LOGS        (300)   // dropped log limit
  13. #define     MAX_BUYERS      (20)    // log buyer limit
  14.  
  15. #define     CUTTING_TIME    (8)     // required seconds to cut a tree down (Default: 8)
  16. #define     LOG_LIMIT       (10)    // how many logs a player can load to a bobcat (if you change this, don't forget to modify LogAttachOffsets array) (Default: 10)
  17. #define     ATTACH_INDEX    (7)     // for setplayerattachedobject (Default: 7)
  18. #define     TREE_RESPAWN    (300)   // required seconds to respawn a tree (Default: 300)
  19. #define     LOG_LIFETIME    (120)   // life time of a dropped log, in seconds (Default: 120)
  20. #define     LOG_PRICE       (50)    // price of a log (Default: 50)
  21. #define     CSAW_PRICE      (500)   // price of a chainsaw (Default: 500)
  22.  
  23. enum    E_TREE
  24. {
  25.     // loaded from db
  26.     Float: treeX,
  27.     Float: treeY,
  28.     Float: treeZ,
  29.     Float: treeRX,
  30.     Float: treeRY,
  31.     Float: treeRZ,
  32.     // temp
  33.     treeLogs,
  34.     treeSeconds,
  35.     bool: treeGettingCut,
  36.     treeObjID,
  37.     Text3D: treeLabel,
  38.     treeTimer
  39. }
  40.  
  41. enum    E_LOG
  42. {
  43.     // temp
  44.     logDroppedBy[MAX_PLAYER_NAME],
  45.     logSeconds,
  46.     logObjID,
  47.     logTimer,
  48.     Text3D: logLabel
  49. }
  50.  
  51. enum    E_BUYER
  52. {
  53.     // loaded from db
  54.     buyerSkin,
  55.     Float: buyerX,
  56.     Float: buyerY,
  57.     Float: buyerZ,
  58.     Float: buyerA,
  59.     // temp
  60.     buyerActorID,
  61.     Text3D: buyerLabel
  62. }
  63.  
  64. new
  65.     TreeData[MAX_TREES][E_TREE],
  66.     LogData[MAX_LOGS][E_LOG],
  67.     BuyerData[MAX_BUYERS][E_BUYER];
  68.    
  69. new
  70.     Iterator: Trees<MAX_TREES>,
  71.     Iterator: Logs<MAX_LOGS>,
  72.     Iterator: Buyers<MAX_BUYERS>;
  73.  
  74. new
  75.     LogObjects[MAX_VEHICLES][LOG_LIMIT];
  76.    
  77. new
  78.     CuttingTreeID[MAX_PLAYERS] = {-1, ...},
  79.     CuttingTimer[MAX_PLAYERS] = {-1, ...},
  80.     PlayerBar: CuttingBar[MAX_PLAYERS] = {INVALID_PLAYER_BAR_ID, ...},
  81.     bool: CarryingLog[MAX_PLAYERS],
  82.     EditingTreeID[MAX_PLAYERS] = {-1, ...};
  83.  
  84. new
  85.     Float: LogAttachOffsets[LOG_LIMIT][4] = {
  86.         {-0.223, -1.089, -0.230, -90.399},
  87.         {-0.056, -1.091, -0.230, 90.399},
  88.         {0.116, -1.092, -0.230, -90.399},
  89.         {0.293, -1.088, -0.230, 90.399},
  90.         {-0.123, -1.089, -0.099, -90.399},
  91.         {0.043, -1.090, -0.099, 90.399},
  92.         {0.216, -1.092, -0.099, -90.399},
  93.         {-0.033, -1.090, 0.029, -90.399},
  94.         {0.153, -1.089, 0.029, 90.399},
  95.         {0.066, -1.091, 0.150, -90.399}
  96.     };
  97.  
  98. new
  99.     DB: ScriptDBHandle;
  100.  
  101. new
  102.     DBStatement: LoadTrees,
  103.     DBStatement: AddTree,
  104.     DBStatement: UpdateTree,
  105.     DBStatement: RemoveTree;
  106.    
  107. new
  108.     DBStatement: LoadBuyers,
  109.     DBStatement: AddBuyer,
  110.     DBStatement: UpdateBuyer,
  111.     DBStatement: RemoveBuyer;
  112.  
  113. SetPlayerLookAt(playerid, Float:x, Float:y)
  114. {
  115.     // somewhere on samp forums, couldn't find the source
  116.     new Float:Px, Float:Py, Float: Pa;
  117.     GetPlayerPos(playerid, Px, Py, Pa);
  118.     Pa = floatabs(atan((y-Py)/(x-Px)));
  119.     if (x <= Px && y >= Py) Pa = floatsub(180, Pa);
  120.     else if (x < Px && y < Py) Pa = floatadd(Pa, 180);
  121.     else if (x >= Px && y <= Py) Pa = floatsub(360.0, Pa);
  122.     Pa = floatsub(Pa, 90.0);
  123.     if (Pa >= 360.0) Pa = floatsub(Pa, 360.0);
  124.     SetPlayerFacingAngle(playerid, Pa);
  125. }
  126.  
  127. ConvertToMinutes(time)
  128. {
  129.     // http://forum.sa-mp.com/showpost.php?p=3223897&postcount=11
  130.     new string[15];//-2000000000:00 could happen, so make the string 15 chars to avoid any errors
  131.     format(string, sizeof(string), "%02d:%02d", time / 60, time % 60);
  132.     return string;
  133. }
  134.  
  135. GetClosestTree(playerid, Float: range = 2.0)
  136. {
  137.     new id = -1, Float: dist = range, Float: tempdist;
  138.     foreach(new i : Trees)
  139.     {
  140.         tempdist = GetPlayerDistanceFromPoint(playerid, TreeData[i][treeX], TreeData[i][treeY], TreeData[i][treeZ]);
  141.  
  142.         if(tempdist > range) continue;
  143.         if(tempdist <= dist)
  144.         {
  145.             dist = tempdist;
  146.             id = i;
  147.         }
  148.     }
  149.  
  150.     return id;
  151. }
  152.  
  153. GetClosestLog(playerid, Float: range = 2.0)
  154. {
  155.     new id = -1, Float: dist = range, Float: tempdist, Float: pos[3];
  156.     foreach(new i : Logs)
  157.     {
  158.         GetDynamicObjectPos(LogData[i][logObjID], pos[0], pos[1], pos[2]);
  159.         tempdist = GetPlayerDistanceFromPoint(playerid, pos[0], pos[1], pos[2]);
  160.  
  161.         if(tempdist > range) continue;
  162.         if(tempdist <= dist)
  163.         {
  164.             dist = tempdist;
  165.             id = i;
  166.         }
  167.     }
  168.  
  169.     return id;
  170. }
  171.  
  172. IsPlayerNearALogBuyer(playerid)
  173. {
  174.     foreach(new i : Buyers)
  175.     {
  176.         if(IsPlayerInRangeOfPoint(playerid, 2.0, BuyerData[i][buyerX], BuyerData[i][buyerY], BuyerData[i][buyerZ])) return 1;
  177.     }
  178.    
  179.     return 0;
  180. }
  181.  
  182. Player_Init(playerid)
  183. {
  184.     CuttingTreeID[playerid] = -1;
  185.     CuttingTimer[playerid] = -1;
  186.     CarryingLog[playerid] = false;
  187.     EditingTreeID[playerid] = -1;
  188.    
  189.     CuttingBar[playerid] = CreatePlayerProgressBar(playerid, 498.0, 104.0, 113.0, 6.2, 0x61381BFF, CUTTING_TIME, 0);
  190.     ApplyAnimation(playerid, "CHAINSAW", "null", 0.0, 0, 0, 0, 0, 0, 0);
  191.     ApplyAnimation(playerid, "CARRY", "null", 0.0, 0, 0, 0, 0, 0, 0);
  192.     return 1;
  193. }
  194.  
  195. Player_ResetCutting(playerid)
  196. {
  197.     if(!IsPlayerConnected(playerid) || CuttingTreeID[playerid] == -1) return 0;
  198.     new id = CuttingTreeID[playerid];
  199.     TreeData[id][treeGettingCut] = false;
  200.     if(TreeData[id][treeSeconds] < 1) Streamer_SetIntData(STREAMER_TYPE_3D_TEXT_LABEL, TreeData[id][treeLabel], E_STREAMER_COLOR, 0x2ECC71FF);
  201.    
  202.     ClearAnimations(playerid);
  203.     TogglePlayerControllable(playerid, 1);
  204.     CuttingTreeID[playerid] = -1;
  205.    
  206.     if(CuttingTimer[playerid] != -1)
  207.     {
  208.         KillTimer(CuttingTimer[playerid]);
  209.         CuttingTimer[playerid] = -1;
  210.     }
  211.    
  212.     SetPlayerProgressBarValue(playerid, CuttingBar[playerid], 0.0);
  213.     HidePlayerProgressBar(playerid, CuttingBar[playerid]);
  214.     return 1;
  215. }
  216.  
  217. Player_GiveLog(playerid)
  218. {
  219.     if(!IsPlayerConnected(playerid)) return 0;
  220.     CarryingLog[playerid] = true;
  221.     SetPlayerSpecialAction(playerid, SPECIAL_ACTION_CARRY);
  222.     SetPlayerAttachedObject(playerid, ATTACH_INDEX, 19793, 6, 0.077999, 0.043999, -0.170999, -13.799953, 79.70, 0.0);
  223.    
  224.     SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}You can press {F1C40F}~k~~CONVERSATION_NO~ {FFFFFF}to drop your log.");
  225.     return 1;
  226. }
  227.  
  228. Player_DropLog(playerid, death_drop = 0)
  229. {
  230.     if(!IsPlayerConnected(playerid) || !CarryingLog[playerid]) return 0;
  231.     new id = Iter_Free(Logs);
  232.     if(id != -1)
  233.     {
  234.         new Float: x, Float: y, Float: z, Float: a, label[128];
  235.         GetPlayerPos(playerid, x, y, z);
  236.         GetPlayerFacingAngle(playerid, a);
  237.         GetPlayerName(playerid, LogData[id][logDroppedBy], MAX_PLAYER_NAME);
  238.  
  239.         if(!death_drop)
  240.         {
  241.             x += (1.0 * floatsin(-a, degrees));
  242.             y += (1.0 * floatcos(-a, degrees));
  243.            
  244.             ApplyAnimation(playerid, "CARRY", "putdwn05", 4.1, 0, 1, 1, 0, 0, 1);
  245.         }
  246.  
  247.         LogData[id][logSeconds] = LOG_LIFETIME;
  248.         LogData[id][logObjID] = CreateDynamicObject(19793, x, y, z - 0.9, 0.0, 0.0, a);
  249.        
  250.         format(label, sizeof(label), "Log (%d)\n\n{FFFFFF}Dropped By {F1C40F}%s\n{FFFFFF}%s\nUse {F1C40F}/log take {FFFFFF}to take it.", id, LogData[id][logDroppedBy], ConvertToMinutes(LOG_LIFETIME));
  251.         LogData[id][logLabel] = CreateDynamic3DTextLabel(label, 0xF1C40FFF, x, y, z - 0.7, 5.0, .testlos = 1);
  252.        
  253.         LogData[id][logTimer] = SetTimerEx("RemoveLog", 1000, true, "i", id);
  254.         Iter_Add(Logs, id);
  255.     }
  256.    
  257.     Player_RemoveLog(playerid);
  258.     return 1;
  259. }
  260.  
  261. Player_RemoveLog(playerid)
  262. {
  263.     if(!IsPlayerConnected(playerid) || !CarryingLog[playerid]) return 0;
  264.     RemovePlayerAttachedObject(playerid, ATTACH_INDEX);
  265.     SetPlayerSpecialAction(playerid, SPECIAL_ACTION_NONE);
  266.     CarryingLog[playerid] = false;
  267.     return 1;
  268. }
  269.  
  270. Vehicle_LogCount(vehicleid)
  271. {
  272.     if(GetVehicleModel(vehicleid) == 0) return 0;
  273.     new count;
  274.     for(new i; i < LOG_LIMIT; i++) if(IsValidDynamicObject(LogObjects[vehicleid][i])) count++;
  275.     return count;
  276. }
  277.  
  278. Vehicle_RemoveLogs(vehicleid)
  279. {
  280.     if(GetVehicleModel(vehicleid) == 0) return 0;
  281.     for(new i; i < LOG_LIMIT; i++)
  282.     {
  283.         if(IsValidDynamicObject(LogObjects[vehicleid][i]))
  284.         {
  285.             DestroyDynamicObject(LogObjects[vehicleid][i]);
  286.             LogObjects[vehicleid][i] = -1;
  287.         }
  288.     }
  289.    
  290.     return 1;
  291. }
  292.  
  293. Tree_BeingEdited(id)
  294. {
  295.     if(!Iter_Contains(Trees, id)) return 0;
  296.     foreach(new i : Player) if(EditingTreeID[i] == id) return 1;
  297.     return 0;
  298. }
  299.  
  300. Tree_UpdateLogLabel(id)
  301. {
  302.     if(!Iter_Contains(Trees, id)) return 0;
  303.     new label[96];
  304.    
  305.     if(TreeData[id][treeLogs] > 0) {
  306.         format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}Logs: {F1C40F}%d\n{FFFFFF}Use {F1C40F}/log takefromtree {FFFFFF}to take a log.", id, TreeData[id][treeLogs]);
  307.         UpdateDynamic3DTextLabelText(TreeData[id][treeLabel], 0xE74C3CFF, label);
  308.     }else{
  309.         TreeData[id][treeTimer] = SetTimerEx("RespawnTree", 1000, true, "i", id);
  310.        
  311.         format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}%s", id, ConvertToMinutes(TreeData[id][treeSeconds]));
  312.         UpdateDynamic3DTextLabelText(TreeData[id][treeLabel], 0xE74C3CFF, label);
  313.     }
  314.    
  315.     return 1;
  316. }
  317.  
  318. public OnFilterScriptInit()
  319. {
  320.     print("  [Lumberjack] Initializing...");
  321.    
  322.     // assign default values to variables
  323.     for(new i; i < MAX_TREES; i++)
  324.     {
  325.         TreeData[i][treeObjID] = TreeData[i][treeTimer] = -1;
  326.         TreeData[i][treeLabel] = Text3D: -1;
  327.     }
  328.    
  329.     for(new i; i < MAX_LOGS; i++)
  330.     {
  331.         LogData[i][logObjID] = LogData[i][logTimer] = -1;
  332.         LogData[i][logLabel] = Text3D: -1;
  333.     }
  334.    
  335.     for(new i; i < MAX_BUYERS; i++)
  336.     {
  337.         BuyerData[i][buyerActorID] = -1;
  338.         BuyerData[i][buyerLabel] = Text3D: -1;
  339.     }
  340.    
  341.     for(new i; i < MAX_VEHICLES; i++) for(new x; x < LOG_LIMIT; x++) LogObjects[i][x] = -1;
  342.    
  343.     foreach(new i : Player) Player_Init(i);
  344.    
  345.     // open database & create tables
  346.     ScriptDBHandle = db_open("lumberjack.db");
  347.     db_query(ScriptDBHandle, "CREATE TABLE IF NOT EXISTS trees (ID INTEGER, PosX FLOAT, PosY FLOAT, PosZ FLOAT, RotX FLOAT, RotY FLOAT, RotZ FLOAT)");
  348.     db_query(ScriptDBHandle, "CREATE TABLE IF NOT EXISTS buyers (ID INTEGER, Skin INTEGER, PosX FLOAT, PosY FLOAT, PosZ FLOAT, PosA FLOAT)");
  349.    
  350.     // prepare tree queries
  351.     LoadTrees = db_prepare(ScriptDBHandle, "SELECT * FROM trees");
  352.     AddTree = db_prepare(ScriptDBHandle, "INSERT INTO trees (ID, PosX, PosY, PosZ, RotX, RotY, RotZ) VALUES (?, ?, ?, ?, ?, ?, ?)");
  353.     UpdateTree = db_prepare(ScriptDBHandle, "UPDATE trees SET PosX=?, PosY=?, PosZ=?, RotX=?, RotY=?, RotZ=? WHERE ID=?");
  354.     RemoveTree = db_prepare(ScriptDBHandle, "DELETE FROM trees WHERE ID=?");
  355.    
  356.     // prepare buyer queries
  357.     LoadBuyers = db_prepare(ScriptDBHandle, "SELECT * FROM buyers");
  358.     AddBuyer = db_prepare(ScriptDBHandle, "INSERT INTO buyers (ID, Skin, PosX, PosY, PosZ, PosA) VALUES (?, ?, ?, ?, ?, ?)");
  359.     UpdateBuyer = db_prepare(ScriptDBHandle, "UPDATE buyers SET Skin=?, PosX=?, PosY=?, PosZ=?, PosA=? WHERE ID=?");
  360.     RemoveBuyer = db_prepare(ScriptDBHandle, "DELETE FROM buyers WHERE ID=?");
  361.    
  362.     // load trees
  363.     new id, Float: pos[3], Float: rot[3];
  364.     stmt_bind_result_field(LoadTrees, 0, DB::TYPE_INTEGER, id);
  365.     stmt_bind_result_field(LoadTrees, 1, DB::TYPE_FLOAT, pos[0]);
  366.     stmt_bind_result_field(LoadTrees, 2, DB::TYPE_FLOAT, pos[1]);
  367.     stmt_bind_result_field(LoadTrees, 3, DB::TYPE_FLOAT, pos[2]);
  368.     stmt_bind_result_field(LoadTrees, 4, DB::TYPE_FLOAT, rot[0]);
  369.     stmt_bind_result_field(LoadTrees, 5, DB::TYPE_FLOAT, rot[1]);
  370.     stmt_bind_result_field(LoadTrees, 6, DB::TYPE_FLOAT, rot[2]);
  371.  
  372.     if(stmt_execute(LoadTrees))
  373.     {
  374.         print("  [Lumberjack] Loading trees...");
  375.  
  376.         new label[96];
  377.         while(stmt_fetch_row(LoadTrees))
  378.         {
  379.             TreeData[id][treeX] = pos[0];
  380.             TreeData[id][treeY] = pos[1];
  381.             TreeData[id][treeZ] = pos[2];
  382.             TreeData[id][treeRX] = rot[0];
  383.             TreeData[id][treeRY] = rot[1];
  384.             TreeData[id][treeRZ] = rot[2];
  385.  
  386.             TreeData[id][treeObjID] = CreateDynamicObject(657, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ], TreeData[id][treeRX], TreeData[id][treeRY], TreeData[id][treeRZ]);
  387.            
  388.             format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}Press {F1C40F}~k~~CONVERSATION_NO~ {FFFFFF}to cut down.", id);
  389.             TreeData[id][treeLabel] = CreateDynamic3DTextLabel(label, 0x2ECC71FF, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ] + 1.5, 5.0);
  390.  
  391.             Iter_Add(Trees, id);
  392.         }
  393.  
  394.         printf("  [Lumberjack] Loaded %d trees.", Iter_Count(Trees));
  395.     }
  396.    
  397.     // load buyers
  398.     new skin, Float: bpos[4];
  399.     stmt_bind_result_field(LoadBuyers, 0, DB::TYPE_INTEGER, id);
  400.     stmt_bind_result_field(LoadBuyers, 1, DB::TYPE_INTEGER, skin);
  401.     stmt_bind_result_field(LoadBuyers, 2, DB::TYPE_FLOAT, bpos[0]);
  402.     stmt_bind_result_field(LoadBuyers, 3, DB::TYPE_FLOAT, bpos[1]);
  403.     stmt_bind_result_field(LoadBuyers, 4, DB::TYPE_FLOAT, bpos[2]);
  404.     stmt_bind_result_field(LoadBuyers, 5, DB::TYPE_FLOAT, bpos[3]);
  405.  
  406.     if(stmt_execute(LoadBuyers))
  407.     {
  408.         print("  [Lumberjack] Loading buyers...");
  409.  
  410.         new label[172];
  411.         while(stmt_fetch_row(LoadBuyers))
  412.         {
  413.             BuyerData[id][buyerSkin] = skin;
  414.             BuyerData[id][buyerX] = bpos[0];
  415.             BuyerData[id][buyerY] = bpos[1];
  416.             BuyerData[id][buyerZ] = bpos[2];
  417.             BuyerData[id][buyerA] = bpos[3];
  418.  
  419.             BuyerData[id][buyerActorID] = CreateActor(BuyerData[id][buyerSkin], BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ], BuyerData[id][buyerA]);
  420.             SetActorInvulnerable(BuyerData[id][buyerActorID], 1);
  421.  
  422.             format(label, sizeof(label), "Log Buyer (%d)\n\n{FFFFFF}Use {F1C40F}/chainsaw {FFFFFF}to buy a chainsaw for {2ECC71}$%d.\n{FFFFFF}Use {F1C40F}/log sell {FFFFFF}to sell a log for {2ECC71}$%d.", id, CSAW_PRICE, LOG_PRICE);
  423.             BuyerData[id][buyerLabel] = CreateDynamic3DTextLabel(label, 0xF1C40FFF, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ] + 0.25, 5.0, .testlos = 1);
  424.  
  425.             Iter_Add(Buyers, id);
  426.         }
  427.  
  428.         printf("  [Lumberjack] Loaded %d buyers.", Iter_Count(Buyers));
  429.     }
  430.    
  431.     return 1;
  432. }
  433.  
  434. public OnFilterScriptExit()
  435. {
  436.     foreach(new i : Player)
  437.     {
  438.         Player_ResetCutting(i);
  439.         Player_RemoveLog(i);
  440.        
  441.         DestroyPlayerProgressBar(i, CuttingBar[i]);
  442.     }
  443.    
  444.     foreach(new i : Buyers) DestroyActor(BuyerData[i][buyerActorID]);
  445.    
  446.     db_close(ScriptDBHandle);
  447.     print("  [Lumberjack] Unloaded.");
  448.     return 1;
  449. }
  450.  
  451. public OnPlayerConnect(playerid)
  452. {
  453.     Player_Init(playerid);
  454.     return 1;
  455. }
  456.  
  457. public OnPlayerDisconnect(playerid, reason)
  458. {
  459.     Player_ResetCutting(playerid);
  460.     Player_RemoveLog(playerid);
  461.    
  462.     EditingTreeID[playerid] = -1;
  463.     return 1;
  464. }
  465.  
  466. public OnVehicleSpawn(vehicleid)
  467. {
  468.     Vehicle_RemoveLogs(vehicleid);
  469.     return 1;
  470. }
  471.  
  472. public OnVehicleDeath(vehicleid, killerid)
  473. {
  474.     Vehicle_RemoveLogs(vehicleid);
  475.     return 1;
  476. }
  477.  
  478. public OnPlayerDeath(playerid, killerid, reason)
  479. {
  480.     Player_ResetCutting(playerid);
  481.     Player_DropLog(playerid, 1);
  482.     return 1;
  483. }
  484.  
  485. public OnPlayerStateChange(playerid, newstate, oldstate)
  486. {
  487.     if(newstate != PLAYER_STATE_WASTED)
  488.     {
  489.         Player_ResetCutting(playerid);
  490.         Player_RemoveLog(playerid);
  491.     }
  492.    
  493.     return 1;
  494. }
  495.  
  496. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
  497. {
  498.     if(GetPlayerState(playerid) == PLAYER_STATE_ONFOOT && (newkeys & KEY_NO))
  499.     {
  500.         if(CarryingLog[playerid]) return Player_DropLog(playerid);
  501.        
  502.         if(GetPlayerWeapon(playerid) == WEAPON_CHAINSAW && CuttingTreeID[playerid] == -1 && !CarryingLog[playerid])
  503.         {
  504.             new id = GetClosestTree(playerid);
  505.  
  506.             if(id != -1)
  507.             {
  508.                 if(!Tree_BeingEdited(id) && !TreeData[id][treeGettingCut] && TreeData[id][treeSeconds] < 1)
  509.                 {
  510.                     SetPlayerLookAt(playerid, TreeData[id][treeX], TreeData[id][treeY]);
  511.  
  512.                     Streamer_SetIntData(STREAMER_TYPE_3D_TEXT_LABEL, TreeData[id][treeLabel], E_STREAMER_COLOR, 0xE74C3CFF);
  513.                     CuttingTimer[playerid] = SetTimerEx("CutTree", 1000, true, "i", playerid);
  514.                     CuttingTreeID[playerid] = id;
  515.                     SetPlayerProgressBarValue(playerid, CuttingBar[playerid], 0.0);
  516.                     ShowPlayerProgressBar(playerid, CuttingBar[playerid]);
  517.                     TogglePlayerControllable(playerid, 0);
  518.                     SetPlayerArmedWeapon(playerid, WEAPON_CHAINSAW);
  519.                     ApplyAnimation(playerid, "CHAINSAW", "WEAPON_csaw", 4.1, 1, 0, 0, 1, 0, 1);
  520.  
  521.                     TreeData[id][treeGettingCut] = true;
  522.                 }
  523.             }
  524.         }
  525.     }
  526.  
  527.     return 1;
  528. }
  529.  
  530. public OnPlayerEditDynamicObject(playerid, STREAMER_TAG_OBJECT objectid, response, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz)
  531. {
  532.     if(EditingTreeID[playerid] != -1 && Iter_Contains(Trees, EditingTreeID[playerid]))
  533.     {
  534.         if(response == EDIT_RESPONSE_FINAL)
  535.         {
  536.             new id = EditingTreeID[playerid];
  537.             TreeData[id][treeX] = x;
  538.             TreeData[id][treeY] = y;
  539.             TreeData[id][treeZ] = z;
  540.             TreeData[id][treeRX] = rx;
  541.             TreeData[id][treeRY] = ry;
  542.             TreeData[id][treeRZ] = rz;
  543.  
  544.             SetDynamicObjectPos(objectid, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ]);
  545.             SetDynamicObjectRot(objectid, TreeData[id][treeRX], TreeData[id][treeRY], TreeData[id][treeRZ]);
  546.  
  547.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, TreeData[id][treeLabel], E_STREAMER_X, TreeData[id][treeX]);
  548.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, TreeData[id][treeLabel], E_STREAMER_Y, TreeData[id][treeY]);
  549.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, TreeData[id][treeLabel], E_STREAMER_Z, TreeData[id][treeZ] + 1.5);
  550.  
  551.             stmt_bind_value(UpdateTree, 0, DB::TYPE_FLOAT, TreeData[id][treeX]);
  552.             stmt_bind_value(UpdateTree, 1, DB::TYPE_FLOAT, TreeData[id][treeY]);
  553.             stmt_bind_value(UpdateTree, 2, DB::TYPE_FLOAT, TreeData[id][treeZ]);
  554.             stmt_bind_value(UpdateTree, 3, DB::TYPE_FLOAT, TreeData[id][treeRX]);
  555.             stmt_bind_value(UpdateTree, 4, DB::TYPE_FLOAT, TreeData[id][treeRY]);
  556.             stmt_bind_value(UpdateTree, 5, DB::TYPE_FLOAT, TreeData[id][treeRZ]);
  557.             stmt_bind_value(UpdateTree, 6, DB::TYPE_INTEGER, id);
  558.             stmt_execute(UpdateTree);
  559.  
  560.             EditingTreeID[playerid] = -1;
  561.         }
  562.  
  563.         if(response == EDIT_RESPONSE_CANCEL)
  564.         {
  565.             new id = EditingTreeID[playerid];
  566.             SetDynamicObjectPos(objectid, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ]);
  567.             SetDynamicObjectRot(objectid, TreeData[id][treeRX], TreeData[id][treeRY], TreeData[id][treeRZ]);
  568.             EditingTreeID[playerid] = -1;
  569.         }
  570.     }
  571.  
  572.     return 1;
  573. }
  574.  
  575. forward CutTree(playerid);
  576. public CutTree(playerid)
  577. {
  578.     if(CuttingTreeID[playerid] != -1)
  579.     {
  580.         new id = CuttingTreeID[playerid], Float: value = GetPlayerProgressBarValue(playerid, CuttingBar[playerid]) + 1.0;
  581.        
  582.         if(value >= CUTTING_TIME) {
  583.             Player_ResetCutting(playerid);
  584.             MoveDynamicObject(TreeData[id][treeObjID], TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ] + 0.03, 0.025, TreeData[id][treeRX], TreeData[id][treeRY] - 80.0, TreeData[id][treeRZ]);
  585.  
  586.             TreeData[id][treeLogs] = 5;
  587.             TreeData[id][treeSeconds] = TREE_RESPAWN;
  588.             Tree_UpdateLogLabel(id);
  589.         }else{
  590.             SetPlayerProgressBarValue(playerid, CuttingBar[playerid], value);
  591.         }
  592.     }
  593.  
  594.     return 1;
  595. }
  596.  
  597. forward RespawnTree(id);
  598. public RespawnTree(id)
  599. {
  600.     new label[96];
  601.     if(TreeData[id][treeSeconds] > 1) {
  602.         TreeData[id][treeSeconds]--;
  603.        
  604.         format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}%s", id, ConvertToMinutes(TreeData[id][treeSeconds]));
  605.         UpdateDynamic3DTextLabelText(TreeData[id][treeLabel], 0xE74C3CFF, label);
  606.     }else if(TreeData[id][treeSeconds] == 1) {
  607.         KillTimer(TreeData[id][treeTimer]);
  608.  
  609.         TreeData[id][treeLogs] = 0;
  610.         TreeData[id][treeSeconds] = 0;
  611.         TreeData[id][treeTimer] = -1;
  612.        
  613.         SetDynamicObjectPos(TreeData[id][treeObjID], TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ]);
  614.         SetDynamicObjectRot(TreeData[id][treeObjID], TreeData[id][treeRX], TreeData[id][treeRY], TreeData[id][treeRZ]);
  615.        
  616.         format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}Press {F1C40F}~k~~CONVERSATION_NO~ {FFFFFF}to cut down.", id);
  617.         UpdateDynamic3DTextLabelText(TreeData[id][treeLabel], 0x2ECC71FF, label);
  618.     }
  619.    
  620.     return 1;
  621. }
  622.  
  623. forward RemoveLog(id);
  624. public RemoveLog(id)
  625. {
  626.     if(!Iter_Count(Logs, id)) return 1;
  627.    
  628.     if(LogData[id][logSeconds] > 1) {
  629.         LogData[id][logSeconds]--;
  630.  
  631.         new label[128];
  632.         format(label, sizeof(label), "Log (%d)\n\n{FFFFFF}Dropped By {F1C40F}%s\n{FFFFFF}%s\nUse {F1C40F}/log take {FFFFFF}to take it.", id, LogData[id][logDroppedBy], ConvertToMinutes(LogData[id][logSeconds]));
  633.         UpdateDynamic3DTextLabelText(LogData[id][logLabel], 0xF1C40FFF, label);
  634.     }else if(LogData[id][logSeconds] == 1) {
  635.         KillTimer(LogData[id][logTimer]);
  636.         DestroyDynamicObject(LogData[id][logObjID]);
  637.         DestroyDynamic3DTextLabel(LogData[id][logLabel]);
  638.        
  639.         LogData[id][logTimer] = -1;
  640.         LogData[id][logObjID] = -1;
  641.         LogData[id][logLabel] = Text3D: -1;
  642.  
  643.         Iter_Remove(Logs, id);
  644.     }
  645.    
  646.     return 1;
  647. }
  648.  
  649. // Player Commands
  650. CMD:chainsaw(playerid, params[])
  651. {
  652.     if(IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't use this command in a vehicle.");
  653.     if(!IsPlayerNearALogBuyer(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Log Buyer.");
  654.     if(GetPlayerMoney(playerid) < CSAW_PRICE) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You don't have enough money.");
  655.     GivePlayerMoney(playerid, -CSAW_PRICE);
  656.     GivePlayerWeapon(playerid, WEAPON_CHAINSAW, 1);
  657.    
  658.     new string[64];
  659.     format(string, sizeof(string), "LUMBERJACK: {FFFFFF}Bought a chainsaw for {2ECC71}$%d.", CSAW_PRICE);
  660.     SendClientMessage(playerid, 0x3498DBFF, string);
  661.     return 1;
  662. }
  663.  
  664. CMD:log(playerid, params[])
  665. {
  666.     if(IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't use this command in a vehicle.");
  667.     if(isnull(params)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/log [load/take/takefromcar/takefromtree/sell]");
  668.    
  669.     if(!strcmp(params, "load", true)) {
  670.         // loading to a bobcat
  671.         if(!CarryingLog[playerid]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not carrying a log.");
  672.         new id = GetNearestVehicle(playerid);
  673.         if(GetVehicleModel(id) != 422) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Bobcat.");
  674.         new Float: x, Float: y, Float: z;
  675.         GetVehicleBoot(id, x, y, z);
  676.         if(!IsPlayerInRangeOfPoint(playerid, 3.0, x, y, z)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Bobcat's back.");
  677.         if(Vehicle_LogCount(id) >= LOG_LIMIT) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't load any more logs to this vehicle.");
  678.         for(new i; i < LOG_LIMIT; i++)
  679.         {
  680.             if(!IsValidDynamicObject(LogObjects[id][i]))
  681.             {
  682.                 LogObjects[id][i] = CreateDynamicObject(19793, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  683.                 AttachDynamicObjectToVehicle(LogObjects[id][i], id, LogAttachOffsets[i][0], LogAttachOffsets[i][1], LogAttachOffsets[i][2], 0.0, 0.0, LogAttachOffsets[i][3]);
  684.                 break;
  685.             }
  686.         }
  687.        
  688.         Streamer_Update(playerid);
  689.         Player_RemoveLog(playerid);
  690.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Loaded a log.");
  691.         // done
  692.     }else if(!strcmp(params, "take")) {
  693.         // taking from ground
  694.         if(CarryingLog[playerid]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're already carrying a log.");
  695.         new id = GetClosestLog(playerid);
  696.         if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a log.");
  697.         LogData[id][logSeconds] = 1;
  698.         RemoveLog(id);
  699.        
  700.         Player_GiveLog(playerid);
  701.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}You've taken a log from ground.");
  702.         // done
  703.     }else if(!strcmp(params, "takefromcar")) {
  704.         // taking from a bobcat
  705.         if(CarryingLog[playerid]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're already carrying a log.");
  706.         new id = GetNearestVehicle(playerid);
  707.         if(GetVehicleModel(id) != 422) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Bobcat.");
  708.         new Float: x, Float: y, Float: z;
  709.         GetVehicleBoot(id, x, y, z);
  710.         if(!IsPlayerInRangeOfPoint(playerid, 3.0, x, y, z)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Bobcat's back.");
  711.         if(Vehicle_LogCount(id) < 1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}This Bobcat doesn't have any logs.");
  712.         for(new i = (LOG_LIMIT - 1); i >= 0; i--)
  713.         {
  714.             if(IsValidDynamicObject(LogObjects[id][i]))
  715.             {
  716.                 DestroyDynamicObject(LogObjects[id][i]);
  717.                 LogObjects[id][i] = -1;
  718.                 break;
  719.             }
  720.         }
  721.  
  722.         Streamer_Update(playerid);
  723.         Player_GiveLog(playerid);
  724.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}You've taken a log from the Bobcat.");
  725.         // done
  726.     }else if(!strcmp(params, "takefromtree")) {
  727.         // taking from a cut tree
  728.         if(CarryingLog[playerid]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're already carrying a log.");
  729.         new id = GetClosestTree(playerid);
  730.         if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a tree.");
  731.         if(TreeData[id][treeSeconds] < 1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}This tree isn't cut.");
  732.         if(TreeData[id][treeLogs] < 1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}This tree doesn't have any logs.");
  733.         TreeData[id][treeLogs]--;
  734.         Tree_UpdateLogLabel(id);
  735.        
  736.         Player_GiveLog(playerid);
  737.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}You've taken a log from the cut tree.");
  738.         // done
  739.     }else if(!strcmp(params, "sell")) {
  740.         // selling a log
  741.         if(!CarryingLog[playerid]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not carrying a log.");
  742.         if(!IsPlayerNearALogBuyer(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a Log Buyer.");
  743.         Player_RemoveLog(playerid);
  744.         GivePlayerMoney(playerid, LOG_PRICE);
  745.        
  746.         new string[64];
  747.         format(string, sizeof(string), "LUMBERJACK: {FFFFFF}Sold a log for {2ECC71}$%d.", LOG_PRICE);
  748.         SendClientMessage(playerid, 0x3498DBFF, string);
  749.         // done
  750.     }
  751.  
  752.     return 1;
  753. }
  754.  
  755. // Admin Commands - Trees
  756. CMD:createtree(playerid, params[])
  757. {
  758.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  759.     new id = Iter_Free(Trees);
  760.     if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't add any more trees.");
  761.     new Float: x, Float: y, Float: z, Float: a;
  762.     GetPlayerPos(playerid, x, y, z);
  763.     GetPlayerFacingAngle(playerid, a);
  764.     x += (3.0 * floatsin(-a, degrees));
  765.     y += (3.0 * floatcos(-a, degrees));
  766.     z -= 1.0;
  767.    
  768.     TreeData[id][treeX] = x;
  769.     TreeData[id][treeY] = y;
  770.     TreeData[id][treeZ] = z;
  771.     TreeData[id][treeRX] = TreeData[id][treeRY] = TreeData[id][treeRZ] = 0.0;
  772.    
  773.     TreeData[id][treeObjID] = CreateDynamicObject(657, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ], TreeData[id][treeRX], TreeData[id][treeRY], TreeData[id][treeRZ]);
  774.  
  775.     new label[96];
  776.     format(label, sizeof(label), "Tree (%d)\n\n{FFFFFF}Press {F1C40F}~k~~CONVERSATION_NO~ {FFFFFF}to cut down.", id);
  777.     TreeData[id][treeLabel] = CreateDynamic3DTextLabel(label, 0x2ECC71FF, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ] + 1.5, 5.0);
  778.     Iter_Add(Trees, id);
  779.    
  780.     stmt_bind_value(AddTree, 0, DB::TYPE_INTEGER, id);
  781.     stmt_bind_value(AddTree, 1, DB::TYPE_FLOAT, TreeData[id][treeX]);
  782.     stmt_bind_value(AddTree, 2, DB::TYPE_FLOAT, TreeData[id][treeY]);
  783.     stmt_bind_value(AddTree, 3, DB::TYPE_FLOAT, TreeData[id][treeZ]);
  784.     stmt_bind_value(AddTree, 4, DB::TYPE_FLOAT, TreeData[id][treeRX]);
  785.     stmt_bind_value(AddTree, 5, DB::TYPE_FLOAT, TreeData[id][treeRY]);
  786.     stmt_bind_value(AddTree, 6, DB::TYPE_FLOAT, TreeData[id][treeRZ]);
  787.    
  788.     if(stmt_execute(AddTree))
  789.     {
  790.         EditingTreeID[playerid] = id;
  791.         EditDynamicObject(playerid, TreeData[id][treeObjID]);
  792.        
  793.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Tree created.");
  794.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}You can edit it right now, or cancel editing and edit it some other time.");
  795.     }
  796.    
  797.     return 1;
  798. }
  799.  
  800. CMD:edittree(playerid, params[])
  801. {
  802.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  803.     if(EditingTreeID[playerid] != -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're already editing a tree.");
  804.     new id;
  805.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/edittree [tree id]");
  806.     if(!Iter_Contains(Trees, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ID.");
  807.     if(TreeData[id][treeGettingCut]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't edit specified tree because its getting cut down.");
  808.     if(!IsPlayerInRangeOfPoint(playerid, 30.0, TreeData[id][treeX], TreeData[id][treeY], TreeData[id][treeZ])) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near the tree you want to edit.");
  809.     EditingTreeID[playerid] = id;
  810.     EditDynamicObject(playerid, TreeData[id][treeObjID]);
  811.     return 1;
  812. }
  813.  
  814. CMD:removetree(playerid, params[])
  815. {
  816.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  817.     new id;
  818.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/removetree [tree id]");
  819.     if(!Iter_Contains(Trees, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ID.");
  820.     if(TreeData[id][treeGettingCut]) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't remove specified tree because its getting cut down.");
  821.     if(Tree_BeingEdited(id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't remove specified tree because its being edited.");
  822.     DestroyDynamicObject(TreeData[id][treeObjID]);
  823.     DestroyDynamic3DTextLabel(TreeData[id][treeLabel]);
  824.     if(TreeData[id][treeTimer] != -1) KillTimer(TreeData[id][treeTimer]);
  825.    
  826.     TreeData[id][treeLogs] = TreeData[id][treeSeconds] = 0;
  827.     TreeData[id][treeObjID] = TreeData[id][treeTimer] = -1;
  828.     TreeData[id][treeLabel] = Text3D: -1;
  829.     Iter_Remove(Trees, id);
  830.    
  831.     stmt_bind_value(RemoveTree, 0, DB::TYPE_INTEGER, id);
  832.     if(stmt_execute(RemoveTree)) SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Tree removed.");
  833.     return 1;
  834. }
  835.  
  836. // Admin Commands - Log Buyers
  837. CMD:createbuyer(playerid, params[])
  838. {
  839.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  840.     new skin;
  841.     if(sscanf(params, "i", skin)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/createbuyer [skin id]");
  842.     if(!(0 <= skin <= 311)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid skin ID.");
  843.     new id = Iter_Free(Buyers);
  844.     if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't add any more log buyers.");
  845.     GetPlayerPos(playerid, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ]);
  846.     GetPlayerFacingAngle(playerid, BuyerData[id][buyerA]);
  847.  
  848.     BuyerData[id][buyerActorID] = CreateActor(skin, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ], BuyerData[id][buyerA]);
  849.     SetActorInvulnerable(BuyerData[id][buyerActorID], 1);
  850.    
  851.     new label[172];
  852.     format(label, sizeof(label), "Log Buyer (%d)\n\n{FFFFFF}Use {F1C40F}/chainsaw {FFFFFF}to buy a chainsaw for {2ECC71}$%d.\n{FFFFFF}Use {F1C40F}/log sell {FFFFFF}to sell a log for {2ECC71}$%d.", id, CSAW_PRICE, LOG_PRICE);
  853.     BuyerData[id][buyerLabel] = CreateDynamic3DTextLabel(label, 0xF1C40FFF, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ] + 0.25, 5.0, .testlos = 1);
  854.     Iter_Add(Buyers, id);
  855.    
  856.     stmt_bind_value(AddBuyer, 0, DB::TYPE_INTEGER, id);
  857.     stmt_bind_value(AddBuyer, 1, DB::TYPE_INTEGER, skin);
  858.     stmt_bind_value(AddBuyer, 2, DB::TYPE_FLOAT, BuyerData[id][buyerX]);
  859.     stmt_bind_value(AddBuyer, 3, DB::TYPE_FLOAT, BuyerData[id][buyerY]);
  860.     stmt_bind_value(AddBuyer, 4, DB::TYPE_FLOAT, BuyerData[id][buyerZ]);
  861.     stmt_bind_value(AddBuyer, 5, DB::TYPE_FLOAT, BuyerData[id][buyerA]);
  862.  
  863.     if(stmt_execute(AddBuyer))
  864.     {
  865.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Buyer created.");
  866.         SetPlayerPos(playerid, BuyerData[id][buyerX] + (1.5 * floatsin(-BuyerData[id][buyerA], degrees)), BuyerData[id][buyerY] + (1.5 * floatcos(-BuyerData[id][buyerA], degrees)), BuyerData[id][buyerZ]);
  867.     }
  868.    
  869.     return 1;
  870. }
  871.  
  872. CMD:setbuyerskin(playerid, params[])
  873. {
  874.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  875.     new id, skin;
  876.     if(sscanf(params, "ii", id, skin)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/setbuyerskin [buyer id] [skin id]");
  877.     if(!Iter_Contains(Buyers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ID.");
  878.     if(!(0 <= skin <= 311)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid skin ID.");
  879.     BuyerData[id][buyerSkin] = skin;
  880.    
  881.     DestroyActor(BuyerData[id][buyerActorID]);
  882.     BuyerData[id][buyerActorID] = CreateActor(skin, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ], BuyerData[id][buyerA]);
  883.     SetActorInvulnerable(BuyerData[id][buyerActorID], 1);
  884.    
  885.     stmt_bind_value(UpdateBuyer, 0, DB::TYPE_INTEGER, skin);
  886.     stmt_bind_value(UpdateBuyer, 1, DB::TYPE_FLOAT, BuyerData[id][buyerX]);
  887.     stmt_bind_value(UpdateBuyer, 2, DB::TYPE_FLOAT, BuyerData[id][buyerY]);
  888.     stmt_bind_value(UpdateBuyer, 3, DB::TYPE_FLOAT, BuyerData[id][buyerZ]);
  889.     stmt_bind_value(UpdateBuyer, 4, DB::TYPE_FLOAT, BuyerData[id][buyerA]);
  890.     stmt_bind_value(UpdateBuyer, 5, DB::TYPE_INTEGER, id);
  891.  
  892.     if(stmt_execute(UpdateBuyer)) SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Buyer updated.");
  893.     return 1;
  894. }
  895.  
  896. CMD:setbuyerpos(playerid, params[])
  897. {
  898.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  899.     new id;
  900.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/setbuyerpos [buyer id]");
  901.     if(!Iter_Contains(Buyers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ID.");
  902.     GetPlayerPos(playerid, BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ]);
  903.     GetPlayerFacingAngle(playerid, BuyerData[id][buyerA]);
  904.  
  905.     DestroyActor(BuyerData[id][buyerActorID]);
  906.     BuyerData[id][buyerActorID] = CreateActor(BuyerData[id][buyerSkin], BuyerData[id][buyerX], BuyerData[id][buyerY], BuyerData[id][buyerZ], BuyerData[id][buyerA]);
  907.     SetActorInvulnerable(BuyerData[id][buyerActorID], 1);
  908.  
  909.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BuyerData[id][buyerLabel], E_STREAMER_X, BuyerData[id][buyerX]);
  910.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BuyerData[id][buyerLabel], E_STREAMER_Y, BuyerData[id][buyerY]);
  911.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BuyerData[id][buyerLabel], E_STREAMER_Z, BuyerData[id][buyerZ] + 0.25);
  912.  
  913.     stmt_bind_value(UpdateBuyer, 0, DB::TYPE_INTEGER, BuyerData[id][buyerSkin]);
  914.     stmt_bind_value(UpdateBuyer, 1, DB::TYPE_FLOAT, BuyerData[id][buyerX]);
  915.     stmt_bind_value(UpdateBuyer, 2, DB::TYPE_FLOAT, BuyerData[id][buyerY]);
  916.     stmt_bind_value(UpdateBuyer, 3, DB::TYPE_FLOAT, BuyerData[id][buyerZ]);
  917.     stmt_bind_value(UpdateBuyer, 4, DB::TYPE_FLOAT, BuyerData[id][buyerA]);
  918.     stmt_bind_value(UpdateBuyer, 5, DB::TYPE_INTEGER, id);
  919.  
  920.     if(stmt_execute(UpdateBuyer))
  921.     {
  922.         SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Buyer updated.");
  923.         SetPlayerPos(playerid, BuyerData[id][buyerX] + (1.5 * floatsin(-BuyerData[id][buyerA], degrees)), BuyerData[id][buyerY] + (1.5 * floatcos(-BuyerData[id][buyerA], degrees)), BuyerData[id][buyerZ]);
  924.     }
  925.    
  926.     return 1;
  927. }
  928.  
  929. CMD:removebuyer(playerid, params[])
  930. {
  931.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  932.     new id;
  933.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/removebuyer [buyer id]");
  934.     if(!Iter_Contains(Buyers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ID.");
  935.     DestroyActor(BuyerData[id][buyerActorID]);
  936.     DestroyDynamic3DTextLabel(BuyerData[id][buyerLabel]);
  937.    
  938.     BuyerData[id][buyerActorID] = -1;
  939.     BuyerData[id][buyerLabel] = Text3D: -1;
  940.     Iter_Remove(Buyers, id);
  941.    
  942.     stmt_bind_value(RemoveBuyer, 0, DB::TYPE_INTEGER, id);
  943.     if(stmt_execute(RemoveBuyer)) SendClientMessage(playerid, 0x3498DBFF, "LUMBERJACK: {FFFFFF}Buyer removed.");
  944.     return 1;
  945. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement