Jump to content
Sign in to follow this  
zorrobyte

Using a switch for if A or B then

Recommended Posts

I'd like to use a switch (or any other performance friendly way) to write a function that returns true if A and/or B is true, false if A and B is false.

zbe_cacheEvent = {
switch (true) do
{
case (call zbe_nearPlayer): {exitWith { true}; };
case (!((_leader findNearestEnemy _leader) isequalto objNull)): {exitWith { true}; };
default {exitWith false};
};
};

This returns Error missing ;

Edited by zorrobyte

Share this post


Link to post
Share on other sites

If your only comparing two things, a switch is overkill:

_testVar = true;

if (!A && !B) then {

_testVar = false;

};

if (A || B) exitWith {_testVar;};

_testVar;

Share this post


Link to post
Share on other sites

A function that tests two conditions and returns true of either A and/or B is true otherwise false.

Share this post


Link to post
Share on other sites
How about this?

if(!A && {!B}) then
{
   //A and B are false
}
else
{
   //A and/or B is true
}

Lazy eval witchcraft! I feel like a noob but what is B is true and A is false? Wouldn't the function still return false?

Expected function return:

A true B false = true

A false B true = true

A true B true = true

A false B false = false

Share this post


Link to post
Share on other sites
What if B is true and A is false? Wouldn't the function still return false?

Yes. B only gets evaluated if !A is true. So if A is false, then !A is true, so then B will be evaluated.

Let's make it a bit more straight forward:

If A is true, this whole statement is false, no matter what B is.

If A is false and B is true, the statement is still false.

If A is false and B is false, the statement is true.

Edited by Heeeere's Johnny!

Share this post


Link to post
Share on other sites
Yes. B only gets evaluated if !A is true. So if A is false' date=' then [i']!A[/i] is true, so then B will be evaluated.

Ah, I need B to be evaluated regardless of A and return true if B is true while A is false.

Wait, this is a mindgame - need to think 0_o

---------- Post added at 08:55 PM ---------- Previous post was at 08:48 PM ----------

If A is true, this whole statement is false, no matter what B is.

If A is false and B is true, the statement is still false.

If A is false and B is false, the statement is true.

Sounds like a plan.

Edited by zorrobyte

Share this post


Link to post
Share on other sites
zbe_catchEvent = {
( call zbe_nearPlayer ) || !isNull (_leader findNearestEnemy _leader)
};

Share this post


Link to post
Share on other sites

Then to make it even faster as Jonny was showing, find which ever is the slowest performing of the two, either zbe_nearPlayer or findNearest (as we dont know what your nearPlayer involves) and put it last in the statement and wrap it in braces (lazy eval). So it does not have to do it if the first is true. Hope that makes sense.

Share this post


Link to post
Share on other sites
zbe_catchEvent = {
( call zbe_nearPlayer ) || !isNull (_leader findNearestEnemy _leader)
};

I'm using a FSM and FSM hates || in condition blocks but defining it this way and putting (call zbe_nearplayer) in the condition block works! I would of done a || immediately to solve the issue in the first place but I didn't think about using a call to work with FSM.

Thank you all!

Share this post


Link to post
Share on other sites

Zorrobyte, I don't think you need your exitwith in the switch, it naturally exits when the case is true.

zbe_cacheEvent = {
switch (true) do
{
   case (call zbe_nearPlayer): {true};
   case (!((_leader findNearestEnemy _leader) isequalto objNull)): {true};
   default {false};
};
};  

I have tested with 'placeholder' values for the case conditions, but there must be something not right with those checks.

I did a simple param 'one' and 'two' and in the editor for each of the case conditions, then changed these values to true/false, the switch works as intended.

In theory this works and will be quick.

Hmm, what is _leader? it is not defined in this script, is that the issue?

EDIT: Phew, that's a lot of replies, I gotta stop opening so many tabs when reading the forums.

Take or leave it, may not actually help now....

Edited by KevsnoTrev
WoW lots of replies

Share this post


Link to post
Share on other sites

This is slow as snot when multiplied by 144 times and checked every second:

({((_position distance _x) < _distance) } forEach ([] call BIS_fnc_listPlayers))

I need to return true if a player is near in a more performance friendly way. Any ideas?

BIS_fnc_codePerformance = 0.0231934ms x 144 = 3.33

Edited by zorrobyte

Share this post


Link to post
Share on other sites

[color=#FF8040][color=#191970][b]if[/b][/color][color=#8B3E2F][b]([/b][/color]
   [color=#8B3E2F][b]{[/b][/color]
       [color=#191970][b]if[/b][/color][color=#8B3E2F][b]([/b][/color][color=#191970][b]isPlayer[/b][/color] [color=#000000]_x[/color] [color=#8B3E2F][b]&[/b][/color][color=#8B3E2F][b]&[/b][/color] [color=#8B3E2F][b]{[/b][/color][color=#000000]_x[/color] [color=#191970][b]distance[/b][/color] [color=#000000]player[/color] [color=#8B3E2F][b]<[/b][/color] [color=#1874CD]_distance[/color][color=#8B3E2F][b]}[/b][/color][color=#8B3E2F][b])[/b][/color] [color=#191970][b]exitWith[/b][/color]
       [color=#8B3E2F][b]{[/b][/color]
           [color=#000000]true[/color]
       [color=#8B3E2F][b]}[/b][/color][color=#8B3E2F][b];[/b][/color]
       [color=#000000]false[/color]
   [color=#8B3E2F][b]}[/b][/color] [color=#191970][b]count[/b][/color] [color=#191970][b]playableUnits[/b][/color]
   [color=#191970][b]isEqualTo[/b][/color] [color=#FF0000]1[/color]
[color=#8B3E2F][b])[/b][/color] [color=#191970][b]then[/b][/color]
[color=#8B3E2F][b]{[/b][/color]
   [color=#006400][i]//do your business here...[/i][/color]
[color=#8B3E2F][b]}[/b][/color][color=#8B3E2F][b];[/b][/color][/color]

Kudos to Killzone_Kid for his SQF to BBCode Converter.

I think this is about the fastest you can get in that particular problem. Explanation:

The count iterates through all playable units on the map. Playable units are either players or AI which has been created with the status "playable". That's why in the if statement inside the count loop, you have to check if isPlayer.

Now, if a player is closer than _distance, the count loop exits with true. Now you need to know that a count either expects nothing or a boolean value in the loop. If the return value of the loop is nil or true, the unit will be counted. If it is false, it won't.

So if - in this example - a unit is either no player or is further away than _distance, the exitWith block will not be executed, so the loop will continue. And as the return value is false in that case, the unit won't be counted.

But IF the exitWith block is executed because the unit is both a player and closer than _distance, the unit will be counted and simultaniously, the count loop will be aborded.

So that way, this construction either returns 0 or 1 which is why you can compare using isEqualTo 1.

I hope that wasn't too cryptic...

Edited by Heeeere's Johnny!
Added code explanation

Share this post


Link to post
Share on other sites
['({(position player) distance _position < _distance} count playableUnits> 0)'] call BIS_fnc_codePerformance;

0.00400391ms

Yippie!

Share this post


Link to post
Share on other sites

But keep in mind that "playableUnits" also returns AI, not only players!

And "getPosATL" is faster than "position" or "getPos".

Edited by Heeeere's Johnny!

Share this post


Link to post
Share on other sites

LOVE you guys! This works @ 144 groups at 58/60 CPS/FPS with one second delay:

zbe_cacheEvent = {

_position = (getPosASL _leader);

({_x distance _position < _distance} count (switchableUnits + playableUnits) > 0) || !isNull (_leader findNearestEnemy _leader)

};

Share this post


Link to post
Share on other sites

Just out of curiosity, are you sure you want to use "getPosASL" (get position above sea level) there? I don't know if you're using this on boats and ships only, but if you use that for land vehicles or units, the distance check could be falsified. And you should defenitely not use that position together with "setPos" or "setPosATL" as the unit would fall to death.

Share this post


Link to post
Share on other sites
Just out of curiosity' date=' are you sure you want to use "[i']getPosASL[/i]" (get position above sea level) there? I don't know if you're using this on boats and ships only, but if you use that for land vehicles or units, the distance check could be falsified. And you should defenitely not use that position together with "setPos" or "setPosATL" as the unit would fall to death.

You are exactly right! My users reported in my thread that there is some funk using ASL. I was blindly following the Code Optimization Guide to squeeze any available peformance out of the loop.

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
Sign in to follow this  

×