Jump to content
L.Trale

Help with if then nesting

Recommended Posts

Hello,

 

I'm trying to make a script that uses multiple if then else statements, but for some reason it won't change a variable.

 

(Messy code, sorry, still using notepad  :D )

//Inventory Slot 1.
_Item = nearestObject [player, "Thing"]; 
if ((HandInUse) && (BeltSlot1 == "isEmpty") && (_Item isKindOf "Land_Hammer_F")) then { //HandInUse is a bool variable on the player, BeltSlot1 is a string on the player
	_Item setVariable ["_isInCargo", true]; //_isInCargo is a bool variable on the object, same with below.
	_Item setVariable ["_InHand", false];
	BeltSlot1 = typeOf ItemInHand; //Setting the value of BeltSlot1 to the detected item in players hand. ItemInHand is  on the player
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 0; //Located on player
	HandInUse = false;
	sleep 0.1;
	_Item attachTo [player, [0.2,0,0], "Pelvis"];
	exit;
} else {
	if ((HandInUse) && (BeltSlot1 == "isEmpty") && (_Item isKindOf "Land_Axe_F")) then { //If its not hammer time, check if its a saw
	_Item setVariable ["_isInCargo", true];
	_Item setVariable ["_InHand", false];
	BeltSlot1 = typeOf ItemInHand;
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 0;
	HandInUse = false;
	sleep 0.1;
	_Item attachTo [player, [0.2,0,0], "Pelvis"];
	exit;
} else {
	if ((!HandInUse) && (BeltSlot1 == "Land_Hammer_F") && (_Item isKindOf "Land_Hammer_F")) then { //If you've got an item on your belt, take it into your hands
	_Item setVariable ["_isInCargo", false];
	_Item setVariable ["_InHand", true];
	BeltSlot1 = "isEmpty";
	HandInUse = true; //Where it goes south. Won't change this to true for some reason?
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 1;
	sleep 0.1;
	_Item attachTo [player, [0,0,0], "righthandmiddle1"];
	exit;
} else {
	if ((!HandInUse) && (BeltSlot1 == "Land_Saw_F") && (_Item isKindOf "Land_Saw_F")) then { //same as above, except for Saw
	_Item setVariable ["_isInCargo", false];
	_Item setVariable ["_InHand", true];
	BeltSlot1 = "isEmpty";
	HandInUse = true;
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 3;
	sleep 0.1;
	_Item attachTo [player, [0,0,0], "righthandmiddle1"];
	exit;
};
};
};
};

I know the code isn't very efficient, I'm just experimenting for the most part. The problem is that everything else works except for changing the "HandInUse" variable.

 

Any ideas on whats going on?

 

Update:

I've neatened up the code a little bit to make it a little bit less of an eye sore and changed some things around, but still have the same result. I'm calling this from the init, when the player presses the 1 key (shown below). 

waituntil {!isnull (finddisplay 46)};
(findDisplay 46) displayAddEventHandler ["KeyDown","_this select 1 call MY_KEYDOWN_FNC;false;"];

MY_KEYDOWN_FNC = {
    switch (_this) do {

//Key 1
        case 2: {
            nul = [] execVM "Mechanics\Inventory\Belt_Slot1.sqf";

};
};
};

Updated Code:

//File: Belt_Slot1.sqf
//Desc: Action for putting item on tool belt.

_Item = nearestObject [player, "Thing"];

if ((HandInUse) && (BeltSlot1 == "isEmpty")) then
{	
	if (_Item isKindOf "Land_Hammer_F") then
	{
	_Item setVariable ["_isInCargo", true];
	_Item setVariable ["_InHand", false];
	BeltSlot1 = typeOf ItemInHand;
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 0;
	HandInUse = false;
	sleep 0.1;
	_Item attachTo [player, [0.2,0,0], "Pelvis"];
	} else
		{
		if (_Item isKindOf "Land_Axe_F") then {
		_Item setVariable ["_isInCargo", true];
		_Item setVariable ["_InHand", false];
		BeltSlot1 = typeOf ItemInHand;
		player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
		sleep 0.9;
		Tool = 0;
		HandInUse = false;
		sleep 0.1;
		_Item attachTo [player, [0.2,0,0], "Pelvis"];
		};
	};
} else 
	{
	if ((!HandInUse) && (BeltSlot1 == "Land_Hammer_F")) then
	{
	_Item setVariable ["_isInCargo", false];
	_Item setVariable ["_InHand", true];
	BeltSlot1 = "isEmpty";
	HandInUse = true;
	player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
	sleep 0.9;
	Tool = 1;
	sleep 0.1;
	_Item attachTo [player, [0,0,0], "righthandmiddle1"];
	} else 
		{
		if ((!HandInUse) && (BeltSlot1 == "Land_Saw_F") && (_Item isKindOf "Land_Saw_F")) then
		{
		_Item setVariable ["_isInCargo", false];
		_Item setVariable ["_InHand", true];
		BeltSlot1 = "isEmpty";
		HandInUse = true;
		player playMove "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon";
		sleep 0.9;
		Tool = 3;
		sleep 0.1;
		_Item attachTo [player, [0,0,0], "righthandmiddle1"];
		};
	};
};

Share this post


Link to post
Share on other sites

I would take a serious look at switch case commads as it's easier to read for this sort of stuff.

I did try it but couldn't get very far as I can't seem to set it up correctly and a bit short of time.

 

Are the type of objects correct, "Land_Saw_F" seems to appear right at the end.

Share this post


Link to post
Share on other sites

I would take a serious look at switch case commads as it's easier to read for this sort of stuff.

I did try it but couldn't get very far as I can't seem to set it up correctly and a bit short of time.

 

Are the type of objects correct, "Land_Saw_F" seems to appear right at the end.

 

I did look into switch case, but It gives the same results.

The objects are correct, the saw part is to check if the item the player has in their hands is a saw. I'm trying to get it to check in this order:

 

1. Does the player have an item in their hands and the belt slot is empty?

Yes (go to 1a), No (go to 2)

 

1a. Does the player have a Hammer in their hands?

Yes (Put item in belt), No (go to 1b)

 

1b. Does the player have a Saw in their hands?

Yes (Put item in belt)

 

2. Does the player have no item in their hand and a Hammer in their belt?

Yes (Take the item out of belt and into hand), No (go to 2a)

 

2a. Does the player have no item in their hand and a Saw in their belt?

Yes (Take the item out of belt and into hand) 

Share this post


Link to post
Share on other sites

I'd recommend using exitWith instead of the old OFP exit command as I think it was for SQS but might still work with SQF.

https://community.bistudio.com/wiki/exitWith

To simply just exit, just do:

if (true) exitWith {};

Edit: Ah, just noticed the updated code part. My bad.

Edit 2: Going through your code now, will update this shortly.

Share this post


Link to post
Share on other sites

Not tested it, hope it's okay and does what you need. I've tried to comment some parts for you.

Also, add this in your init.sqf or somewhere... I usually use CfgFunctions but for now, this will do:

/*
	File: fn_Belt_Slot.sqf
	Author: L.Trale

	Description:
	Action for putting item on tool belt

	Parameter(s):
	OBJECT - Unit that you want to check

	Return(s):
	0: BOOL - TRUE if the unit has something in it's hand, and FALSE if not
	1: ARRAY - Retruns an array of items in the unit's slot belt, or [] if it's empty
*/

private ["_Unit", "_In_Hand", "_Slot_Items", "_Item"];

params [
	["_Unit", player]
];

if (isNil {player getVariable "Item_In_Hand"}) then {
	_Unit setVariable ["Item_In_Hand", [false, ""], true];
};

if (isNil {player getVariable "Belt_Slot_Items"}) then {
	_Unit setVariable ["Belt_Slot_Items", [], true];
};

_In_Hand = _Unit getVariable "Item_In_Hand"; // Returns the value of the variable on the unit
_Slot_Items = _Unit getVariable "Belt_Slot_Items";

_Item = nearestObject [_Unit, "Thing"]; // Returns the nearest object with the classname passed from parameter 1

if (isNil {_Item getVariable "Item_In_Use"}) then {
	_Item setVariable ["Item_In_Use", false, true];
};

_In_Use = _Item getVariable "Item_In_Use"; // Added incase you ever need to check in the item is in use

if ((_In_Hand select 0)) exitWith {};
if (typeOf _Item == "") exitWith {}; // Just incase nearestObject if fails :P
if (count _Slot_Items > 5) exitWith {}; // You can make less exitWith by merging them and using the || (OR) command but I just wanted to show you what's what, etc...
// Feel free to comment out or remove the above line, added it just incase you ever needed to check item count

switch (typeOf _Item) do {
	case "Land_Hammer_F" : {
		_Unit playMoveNow "AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon"; // Replaced playMove with playMoveNow - https://community.bistudio.com/wiki/playMoveNow
		_Unit setVariable ["Item_In_Hand", false, true]; // Sets the variable to the given value, on the unit - I'm not sure if public parameter is needed in this case, I know it's not needed but I added it so you can check if for returned BOOL on another unit's machine, however I'm not sure you need this for that... Maybe something can let me know xD
		_Item setVariable ["Item_In_Use", true, true];
		_Item attachTo [_Unit, [0.2, 0, 0], "Pelvis"];
	};
	case "Item" : {
		// Code
	};
	case "Item" : {
		// Code
	};
	case "Item" : {
		// Code
	};
	case "Item" : {
		// Code
	};
	case "Item" : {
		// Code
	};
	case "Item" : {
		// Code
	};
};

[_In_Hand, _Slot_Items]
LT_fnc_Belt_Slot = compile preprocessFileLineNumbers "fn_Belt_Slot.sqf";

To use it, just do:

[player] call LT_fnc_Belt_Slot;

Read the header section in the file too! You can check what it returns by:

_Return = [player] call LT_fnc_Belt_Slot;
if (!(_Return select 0)) then { // If there is NO item in hand then do code...
// Blah...
};
if ((_Slot_Items select 1) == "Land_Hammer_F") then { // If second belt slot item is hammer then do code...
// Blah...
};

Share this post


Link to post
Share on other sites

I would rethink your variables.

 

You have "handInUse" as a boolean and you store the item on your belt in a variable, yet for some reason you don't store the item in hand in a variable. That would make things easier, especially since you don't have to rely on nearestObject.

 

Personally I would just use these:

"HandItem"

"BeltSlot1"

 

 

Way I see it you wouldn't even have to differentiate between the tooltypes in that code. Just make a universal function for putting items from belt to hand and the other way around.

Furthermore, don't use global variables for playerspecific information. Objectspace is more useful and gives you better options for server/client interaction.

 

Here is what I would do:

beltSlots = [
	["BeltSlot1",[0.2,0,0],"Pelvis"],
	["BeltSlot2",[-0.2,0,0],"Pelvis"]
];

fnc_useBelt = {
	param ["_unit","_slotnum"];
        private ["_slot","_slotname","_slotpos","_slotpoint","_beltItem","_handItem","_beltitem","_InHand","_isInCargo"];

	_slot = beltSlots select _slotnum;
	_slotname = _slot select 0;
	_slotpos = _slot select 1;
	_slotpoint = _slot select 2;

	_beltItem = _unit getVariable [_slotname,objNull];
	_handItem = _unit getVariable ["handItem",objNull];

	if (isNull _handItem) then {
		// empty hand -> try to grab item from belt
		if (isNull _beltItem) then {
			_unit setVariable ["tool", "", true];
			"no Item in that slot."
		} else {
			_unit setVariable ["handItem", _beltItem, true];
			_unit setVariable [_slotname, objNull, true];
			_unit setVariable ["tool", typeOf _beltitem, true];

			_beltitem setVariable ["_InHand", true, true];
			_beltitem setVariable ["_isInCargo", false, true];

			[_unit,"AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon"] remoteExec ["playMove", 0, false];
			sleep 1;
			_beltItem attachTo [_unit, [0,0,0], "righthandmiddle1"];

			"took item from " + _slotname
		};
	} else {
		// item in hand -> check belt
		if (isNull _beltItem) then {
			_unit setVariable ["handItem", objNull, true];
			_unit setVariable [_slotname, _handItem, true];
			_unit setVariable ["tool", "", true];
			
			_handItem setVariable ["_InHand", false, true];
			_handItem setVariable ["_isInCargo", true, true];
			
			[_unit,"AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon"] remoteExec ["playMove", 0, false];
			sleep 1;
			_handItem attachTo [_unit, _slotpos, _slotpoint];

			"item stored in " + _slotname
		} else {
			"this slot is full."
		};
	};
};

This easily allows for multiple beltslots and doesn't care what Items you put on them.

Use like this:

 

_callback = [player,0] call fnc_useBelt;

 

_callback will give you a response of the function. Note that beltslot1 has id 0.

 

 

 

 

 

- - - - -

@HazJ

 

Why would you use this?

if (isNil {player getVariable "Item_In_Hand"}) then {
	_Unit setVariable ["Item_In_Hand", [false, ""], true];
};

When this is enough:

_Unit getVariable ["Item_In_Hand", [false, ""]];

There is no need to check for "isNil" with getVariable. Just put the default value as second parameter.

Share this post


Link to post
Share on other sites

Yeah, I orignally did that but it gave a very weird error saying it was undefined when I tried to check the variable. Odd. Probably just me. :)

Share this post


Link to post
Share on other sites

I would rethink your variables.

 

You have "handInUse" as a boolean and you store the item on your belt in a variable, yet for some reason you don't store the item in hand in a variable. That would make things easier, especially since you don't have to rely on nearestObject.

 

Personally I would just use these:

"HandItem"

"BeltSlot1"

 

 

Way I see it you wouldn't even have to differentiate between the tooltypes in that code. Just make a universal function for putting items from belt to hand and the other way around.

Furthermore, don't use global variables for playerspecific information. Objectspace is more useful and gives you better options for server/client interaction.

 

Here is what I would do:

beltSlots = [
	["BeltSlot1",[0.2,0,0],"Pelvis"],
	["BeltSlot2",[-0.2,0,0],"Pelvis"]
];

fnc_useBelt = {
	param ["_unit","_slotnum"];
        private ["_slot","_slotname","_slotpos","_slotpoint","_beltItem","_handItem","_beltitem","_InHand","_isInCargo"];

	_slot = beltSlots select _slotnum;
	_slotname = _slot select 0;
	_slotpos = _slot select 1;
	_slotpoint = _slot select 2;

	_beltItem = _unit getVariable [_slotname,objNull];
	_handItem = _unit getVariable ["handItem",objNull];

	if (isNull _handItem) then {
		// empty hand -> try to grab item from belt
		if (isNull _beltItem) then {
			_unit setVariable ["tool", "", true];
			"no Item in that slot."
		} else {
			_unit setVariable ["handItem", _beltItem, true];
			_unit setVariable [_slotname, objNull, true];
			_unit setVariable ["tool", typeOf _beltitem, true];

			_beltitem setVariable ["_InHand", true, true];
			_beltitem setVariable ["_isInCargo", false, true];

			[_unit,"AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon"] remoteExec ["playMove", 0, false];
			sleep 1;
			_beltItem attachTo [_unit, [0,0,0], "righthandmiddle1"];

			"took item from " + _slotname
		};
	} else {
		// item in hand -> check belt
		if (isNull _beltItem) then {
			_unit setVariable ["handItem", objNull, true];
			_unit setVariable [_slotname, _handItem, true];
			_unit setVariable ["tool", "", true];
			
			_handItem setVariable ["_InHand", false, true];
			_handItem setVariable ["_isInCargo", true, true];
			
			[_unit,"AmovPercMstpSrasWpstDnon_AmovPercMstpSnonWnonDnon"] remoteExec ["playMove", 0, false];
			sleep 1;
			_handItem attachTo [_unit, _slotpos, _slotpoint];

			"item stored in " + _slotname
		} else {
			"this slot is full."
		};
	};
};

This easily allows for multiple beltslots and doesn't care what Items you put on them.

Use like this:

 

_callback = [player,0] call fnc_useBelt;

 

_callback will give you a response of the function. Note that beltslot1 has id 0.

 

 

 

 

 

- - - - -

@HazJ

 

Why would you use this?

if (isNil {player getVariable "Item_In_Hand"}) then {
	_Unit setVariable ["Item_In_Hand", [false, ""], true];
};

When this is enough:

_Unit getVariable ["Item_In_Hand", [false, ""]];

There is no need to check for "isNil" with getVariable. Just put the default value as second parameter.

 

Ah, thank you very much for your help guys  :)

Share this post


Link to post
Share on other sites

You're welcome.

 

But please avoid fullquotes, they turn the forum into a real mess.

Use names to reply to someone or just quote the specific part you're replying to.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×