Haymaker 13 Posted March 30, 2016 Working on a little Arma 3 farm simulator action... fairly noob to scripting, don'n know why I can't seem to get it to work. private["_tractor","_crop","_item"]; _tractor = "RDS_Zetor6945_Base"; _crop = nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],1] select 0; _item= binocular; while { player in _tractor player distance _crop < 10 } do { deleteVehicle _crop; _tractor addItemCargo binocular; }; The binoculars serve as a placeholder for actual wheat, which I will be creating a gear item for. The idea is, if you're in a tractor and you run over a wheat plant, it adds wheat to the vehicle inventory. I call the script via: player execVM "Scripts\Functions\fn_HarvestWheat.sqf"; ...and it doesn't work at all. I run right over the wheat and nothing happens. I'm working on several other similar scripts and none of them seem to work. Help would be greatly appreciated! Share this post Link to post Share on other sites
beno_83au 1369 Posted March 30, 2016 _crop = nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],1] select 0; You're searching a 1m radius for the objects. nearestObjects [position, types, radius] Also, it may help to write your loop like this: while {_condition} do { //code }; But, double also, if you run this script when the player is more than 10m from the object it'll go straight past the while loop and finish the script. At a guess (and I'm making some assumptions here about what you're doing), you'd be better off running this whole thing in a loop with a waitUntil, and executing it at any time before the player gets within 10m: private["_tractor","_crop","_item"]; _tractor = "RDS_Zetor6945_Base"; _item= binocular; while {true} do { waitUntil {(count (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],10])) > 0}; {deleteVehicle _x} forEach (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],10]); }; 1 Share this post Link to post Share on other sites
SirMrE 18 Posted March 30, 2016 It's been a bit since I have done any arma scripting, so I cannot say for sure if this works, but hopefully you will understand that idea behind it. I am at work, but procrastinating (when I posted this) - so I might not answer right away to any replies :P. private["_tractor","_loop"]; _tractor = "RDS_Zetor6945_Base"; _loop = true; // loop until we tell it to stop while {_loop} do { private ["_crop"]; // check for nearest crop on every loop so we always check and get the closest one to the player at every moment. _crop = nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],1] select 0; // if the player is no longer in the tractor, kill the loop (we check what vehicle the player is in, "vehicle player" it will return the player object if in no vehicle). if (vehicle player == player) then { _loop = false; } else { if (player distance _crop < 10) then { deleteVehicle _crop; _tractor addItemCargo binocular; }; // might as well save a few cycles (helps to keep the server running a bit better) - no need to hammer it if its not needed. sleep 0.2; }; }; Quick edit: using waitUntil as stated in the previous answer might not be a bad idea, though you should break it if the player leaves the tractor/vehicle.Edit edit: actually waitUntil might be a bad idea (let me know people). As I believe it will run quite a lot of times a second. Might be a better option to just sleep within the while loop as in the above code snippet. 1 Share this post Link to post Share on other sites
flyinpenguin 30 Posted March 30, 2016 Yup, above guys are correct. I think a basic explanation of what a while loop does would be good for you. A 'do while' will run a set of code every time it's condition returns true. The very first time it returns false, it exits the while loop and continues the remaining code. It checks the condition each time before it executes, including the very first time. So your first script failed because it checked the values and probably returned false immediately. Hope that explanation of the while loop helps you in the future. SirMre is correct in waitUntil is worse that a sleep function in a while loop. waitUntil will execute as fast as possible which is bad for performance. Better to do a while with a " sleep 0.01; " in it instead. Doesn't have to be 0.01, but you get the idea. Feel free to ask about anything you may be confused on with scripting and how or what to use to accomplish something. 1 Share this post Link to post Share on other sites
dreadedentity 278 Posted March 31, 2016 Reminds me of farma 2, that's awesome that you want to do this for real Share this post Link to post Share on other sites
Tajin 349 Posted March 31, 2016 A guy named "Haymaker" askes for a farming script ? :rolleyes: That made my day. :) Anyway, do pay attention to what flyinpenguin said about putting "sleep" into a while loop. Always good to get used to that. There are very few occasions where a loop really has to run at full speed, so safe some performance by adjusting those sleep times. Share this post Link to post Share on other sites
Haymaker 13 Posted March 31, 2016 You're searching a 1m radius for the objects. nearestObjects [position, types, radius] Also, it may help to write your loop like this: while {_condition} do { //code }; But, double also, if you run this script when the player is more than 10m from the object it'll go straight past the while loop and finish the script. At a guess (and I'm making some assumptions here about what you're doing), you'd be better off running this whole thing in a loop with a waitUntil, and executing it at any time before the player gets within 10m: private["_tractor","_crop","_item"]; _tractor = "RDS_Zetor6945_Base"; _item= binocular; while {true} do { waitUntil {(count (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],10])) > 0}; {deleteVehicle _x} forEach (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],10]); }; Okay so now I have private["_tractor","_condition","_item"]; _tractor = "RDS_Zetor6945_Base"; _item= "binocular"; while {((typeOf (vehicle player)) == _tractor)} do { waitUntil {(count (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],5])) > 0}; {deleteVehicle _x} forEach (nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],5]); vehicle player addItemCargo ["binocular",1]; }; For some weird reason it adds 4-24 binoculars per wheat plant. PS thanks for the help guys! Share this post Link to post Share on other sites
flyinpenguin 30 Posted March 31, 2016 Use this instead. I of course could not test it, so excuse any small typos/bugs _tractor = "RDS_Zetor6945_Base"; _item= "binocular"; _query = []; _num = 0; _sleepTime = 0.02; while {((typeOf (vehicle player)) == _tractor)} do { //store variables for zero chance of mismatch reference _query = nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],5]; _num = count _query; //check to see if there is any wheat if (_num > 0) do { //delete each instance of wheat found {deleteVehicle _x} forEach _query; //add all wheat found vehicle player addItemCargo ["binocular",_num]; //gives wheat a better chance to despawn first time sleep _sleepTime; //check and wait until all wheat has been removed so its not added multiple times _continue = true; _del = []; _total = 0; while {_continue} do { //checks if wheat is still there, adds 1 if its still there and 0 if its not to array _del { if (isNull _x) then { _del pushBack 0; } else { _del pushBack 1; }; } forEach _query; //adds up elements of _del { _total = _total + _x; } forEach _del; //sets condition for loop if all wheat was deleted if (_total == 0) then { _continue = false; }; //reset variables _del = []; _total = 0; //doesn't need to sleep if not continueing as it would double sleep time if (_continue) then { sleep _sleepTime; }; }; }; //makes sure script doesnt hog rescources sleep _sleepTime; }; If sleep is popping an error, its not running in a threaded environment. In that case, use this instead [] spawn { _tractor = "RDS_Zetor6945_Base"; _item= "binocular"; _query = []; _num = 0; _sleepTime = 0.02; while {((typeOf (vehicle player)) == _tractor)} do { //store variables for zero chance of mismatch reference _query = nearestObjects[getPos player,["CUP_A2_p_wheat_ep1"],5]; _num = count _query; //check to see if there is any wheat if (_num > 0) do { //delete each instance of wheat found {deleteVehicle _x} forEach _query; //add all wheat found vehicle player addItemCargo ["binocular",_num]; //gives wheat a better chance to despawn first time sleep _sleepTime; //check and wait until all wheat has been removed so its not added multiple times _continue = true; _del = []; _total = 0; while {_continue} do { //checks if wheat is still there, adds 1 if its still there and 0 if its not to array _del { if (isNull _x) then { _del pushBack 0; } else { _del pushBack 1; }; } forEach _query; //adds up elements of _del { _total = _total + _x; } forEach _del; //sets condition for loop if all wheat was deleted if (_total == 0) then { _continue = false; }; //reset variables _del = []; _total = 0; //doesn't need to sleep if not continueing as it would double sleep time if (_continue) then { sleep _sleepTime; }; }; }; //makes sure script doesnt hog rescources sleep _sleepTime; }; }; 1 Share this post Link to post Share on other sites
Haymaker 13 Posted April 1, 2016 Okay that works! Just changed the if do statement to if then and it works fine! I also added this //add all wheat found (if there's space in your vehicle) if (vehicle player canAdd "Binocular") then { vehicle player addItemCargo ["binocular",_num]; } else { Hint "Your tractor can't hold any more wheat!" }; so that you can't infinitely fill the tractor. I have noticed there is one problem where after the first wheat plant is harvested the script stops working and wont harvest anymore until re-executed, I figure that'd be a problem with sleep? I've also started the plant script: while {player distance haystack < 50} do{ if ("Chemlight_blue" in Magazines Player) then { if (vehicle player == player) then { player addAction ["Plant Wheat", { "CUP_A2_p_wheat_ep1" createVehicle position player; player removeItem "Chemlight_blue"; player playMove "Acts_TreatingWounded04"; sleep 5; player switchmove ""; removeAllActions player; }]; } else { removeAllActions player }; sleep 6; }; }; Also, will I have any trouble running these scripts in multiplayer? Share this post Link to post Share on other sites
sarogahtyp 1108 Posted April 1, 2016 i think one can use a waitUntil, too. but one should use it with sleep. waitUntil{sleep 0.01; (condition)}; or is that g3nerally a bad idea? 1 Share this post Link to post Share on other sites
flyinpenguin 30 Posted April 1, 2016 i think one can use a waitUntil, too. but one should use it with sleep. waitUntil{sleep 0.01; (condition)}; or is that g3nerally a bad idea? I think it technically would work, but I wouldn't recommend it. Haymaker, try removing my part of the script that waits until it's deleted for now, I'm guessing that's what is erroring. Is there a specific error that it pops when you run game with showscripterrors? Also for the planting part, do _act = player addiction.... You should be able to store the ID of the added action and later remove it. Don't want to remove all actions because that can mess with other mods and in game stuff. So far, it looks like everything should work in multiplayer as is. 1 Share this post Link to post Share on other sites
Haymaker 13 Posted April 2, 2016 Okay so the act works but it doesn't remove the action once the player is more than 50 meters away or drops all of his stuff, until he actually uses the action and it removes. I guess I still don't quite understand while - do - else. Share this post Link to post Share on other sites
sarogahtyp 1108 Posted April 2, 2016 if (vehicle player == player) then this line means to do something if player is not in a vehicle the code of the else statement will run if he is in a vehicle. means your action will be deleted only if player is in a vehicle within 50 meters why within 50 m? because ur while loop will break if player is farer and the else code is not executed then Share this post Link to post Share on other sites
flyinpenguin 30 Posted April 2, 2016 Define _act before the while loop with _act = 0 so that it stays in scope. Then after the while loop ends, put in an if statement that checks to see if _act is not 0 (IE it was changed). And make sure to reset _act to 0 after each time you use it to remove an addaction. So something like If (_act != 0) then { //remove action }; On while do else, I don't know if Arma scripting supports that, so just throw whatever you need after the while loop as that will be executed when the loop ends anyways. Share this post Link to post Share on other sites
Haymaker 13 Posted April 3, 2016 Okay I see. I supposed I should tell you what I'm doing here. I'm creating a multiplayer monetary economy with shops and ways to make money! This will be one of the many ways to make money. Also, I've found the issue with the harvesting. If you are out of the tractor when the script is executed it won't harvest. Then once you get into the tractor the script must be re-executed for it to work. Is there any way I could just make it initialize in the init.sqf and never have to be re-executed? Share this post Link to post Share on other sites
flyinpenguin 30 Posted April 3, 2016 You could tie the script to an event handler instead. Have it be attached to the player and do a getin event handler. Check to see if it's the correct vehicle and launch that script. Share this post Link to post Share on other sites
Haymaker 13 Posted April 5, 2016 You could tie the script to an event handler instead. Have it be attached to the player and do a getin event handler. Check to see if it's the correct vehicle and launch that script. I think I'll try that, I've also implemented that over to fishing where if you're in a trawler and you come within a certain distance of a Tuna, it will add an item to your cargo :D As for the event Handler, I can't get one running for GetinMan for all vehicles. It will work for specific variables, but not for all of a specific classname. In the meantime as a workaround I used: player addEventHandler ["InventoryOpened", {_this execVM "Scripts\Functions\fn_HarvestWheat.sqf"}]; Share this post Link to post Share on other sites