Jump to content
Sign in to follow this  
seba1985

Ho to detect if there are no more vehicles alive

Recommended Posts

Hi,

Is there any way to detect when all anemy vehicles are destroyed, despite the fact that some crew may have survived?

I'm talking of MANY vehicles so I'd like a shortcut to the obvious !alive sentence for each vehicle in the area.

Thanks in advance.

Share this post


Link to post
Share on other sites

Try experimenting with something like

{! canmove _x} foreach units thislist

in a large trigger covering the whole battle area.

Share this post


Link to post
Share on other sites

Is there any infantry in the area where the vehicles are? If not you could have a trigger covering them that stores the vehicles in an array in the beginning of the mission (I'm assuming east is the enemy side):

Activated by east present, once

condition: this

onActivation: eastvehicles = thislist

...then the trigger that detects if they are destroyed:

activated once

condition: {canmove _x} count eastvehicles == 0

onActivation: hint "Vehicles destroyed"

Share this post


Link to post
Share on other sites

Another way :

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

condition : "vehicle _x != driver _x" count thislist == 0

will check if vehicles have drivers. No driver = no danger, cause the crew disembark when the driver is dead. It works even if infantry is in the area (because for infantry, vehicle _x != driver _x is false).

Share this post


Link to post
Share on other sites

Thanks a lot everyone. I knew the answer would involve something a didn't know about scripting. I search the command reference for each of your answers and got the meaning now. Thanks again, and everyone in the community - I read the forum from a long time ago, but so far every question had an answer searching for past topics. Salve OFP  notworthy.gif

Share this post


Link to post
Share on other sites

I rather would do it this way:

First trigger, covering whole mission, condition: true, onActivation:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">EastVehicles = []; {if (driver _x != _x) then {EastVehicles = EastVehicles + [_x]}} forEach thislist

Second trigger = detection trigger, condition:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">{canMove _x} count EastVehicles == 0

Share this post


Link to post
Share on other sites

I have a follow question. How many times is that trigger condition evaluated during the mission? What's the impact on frame rate of this kind of triggers?

Share this post


Link to post
Share on other sites
As you see, a trigger checks its condition every 0.5 second. But "count" command creates some lag, even more when testing a condition (as canmove).

But it only counts the units in the array as opposed to all units in the trigger's list. This should really be possible, since triggers were designed exactly for that.

Share this post


Link to post
Share on other sites
Quote[/b] ]OK, but does destroyed units exist in the trigger's list?

Yes it should. You can test it during the mission, through repeatable radio trigger, with on activation :

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">hint format ["%1", EastVehicles]

if eastvehicles is the name of the list.

When a vehicle is destroyed, you'll see some "east alpha 1" become some "NOID + number" for example.

Share this post


Link to post
Share on other sites

That's what I thought, so it would be safe to say that the way you suggested - using a trigger condition - will be faster to evaluate as you advance through the mission and more units gets detroyed, as opposed to the method of generating one EastVehicles [] at the begining, as indicated by HardRock? (assuming no new east units enter the trigger area, of course)

Share this post


Link to post
Share on other sites

I think the idea was to generate the array only in the beginning.

If the performance really is an issue:

-deletevehicle the eastvehicles trigger after it's done

-use a script for canMove with a delayed loop that removes destroyed vehicles from the array:

#loop

~3

_c=0

{if(canMove _x) then {_c=_c+1} else {EastVehicles = EastVehicles - [_x]}} forEach EastVehicles

?_c > 0 : goto "loop"

VehiclesDestroyed=true

You could improve it so it doesn't evaluate every vehicle at once but would rather go slowly trough the array, one by one and then back to the beginning if you really want to save the valuable few cycles it takes smile_o.gif

Share this post


Link to post
Share on other sites
I think the idea was to generate the array only in the beginning.

That's the point. The trigger triggers only once in the beginning and fills the array EastVehicles. This array should be much smaller than the array of all vehicles in the trigger's area, that's why I suggested to use this for the condition of the second trigger.

Share this post


Link to post
Share on other sites

Oh I see. So if I get you right, the more time consuming task would be the recreation of the array each time the trigger has to be evaluated. In your method the filling of the array occurs only once, hence reducing workload.

Share this post


Link to post
Share on other sites

If it was repopulated each cycle there wouldn't be any use for it in the first place. You could then just go trough the thislist of the trigger something like:

condition: {driver _x != _x AND canmove _x} count thislist == 0

onActivation: hint "done"

Share this post


Link to post
Share on other sites

OK, to sum it up, you have presented two methods. Both worked well. But I'd like to know if the two people who give them agreed in what method is the best. Let's leave behind all others considerations, and focuse only in CPU. Which method is less CPU demanding under normal circunstances?

Share this post


Link to post
Share on other sites

I guess the best method would depend on how many vehicles there are. Say it's less than 10, 20 or maybe even some more and you might as well use a trigger without any hit in the performance.

Generally using scripts is more efficent because you can use delays, iterate arrays slowly, use local variables and so on. Like in this case there's no need to check the vehicles every 0.5 seconds, you could have a 5 second delay between each count and it wouldn't really hurt the mission but would use 10 times less CPU in theory (assuming the delay wouldn't cause any load).

If there's a really insane amount of vehicles the count might result in a noticeable fps drop every time it's done so then it would be better to go trough the array one by one with a tiny delay in between.

Share this post


Link to post
Share on other sites

There is one more method that does not involve loops running during the mission. Using event handlers, you can setup a basic check like this:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">This AddEVentHandler ["Killed",{KILLEDCOUNT=KILLEDCOUNT+1}]

Then in your end game trigger you would have:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">KILLEDCOUNT>=NUMOFVEHICLESATSTART

But as already mentioned, it will not cater for vehicles that have been disabled.

To do that you need to add more code:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">This AddEVentHandler ["Killed",{KILLEDCOUNT=KILLEDCOUNT+1; ARRAYOFALLVEHICLES=ARRAYOFALLVEHICLES-[_This Select 0]}]

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">This AddEventHandler ["GetOut",{If !(CanMove (_This Select 0)) Then {If ((_This Select 0) In ARRAYOFALLVEHICLES) Then {KILLEDCOUNT=KILLEDCOUNT+1; ARRAYOFALLVEHICLES=ARRAYOFALLVEHICLES-[_This Select 0]}}}]

Technically speaking the in command will loop through your array, same for when you’re deducting the vehicle from the array. But they are pretty efficient and they are only called during certain circumstances. So it's worthwhile too at least test this method, along side the others.

Share this post


Link to post
Share on other sites

Did you guys yet test if this works or are you just

discussing about which way is using less performance?

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">EastVehicles = []; {if (driver _x != _x) then {EastVehicles = EastVehicles + [_x]}} forEach thislist

Will create an array of vehicles - that's right.

But ...

When placing let's say: 3 west jeeps will feature

an array like with their unit names.

Now if you let GET OUT them, the array will contain only:

west jeep1 #noid something. Thus you cannot remove

the unit from the array since it's reference to the check

is not matching anymore.

There's another command that could be useful in your case:

counttype

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">typeName countType array

Operand types:

typeName: String

array: Array

Type of returned value:

Number

Description:

Count how many vehicles in the array are of given type. For type see CfgVehicles.

Example:

"Tank" countType list triggerOne

For ground vehicles you can use type: "land"

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">"land" countType thislist would return all ground

vehicles in the trigger's list.

I can't test anything before sunday, so maybe someone else

will come with a solution before - if not i'll give it a go at the

weekend.

~S~ CD

Share this post


Link to post
Share on other sites

True but :

Quote[/b] ]"land" countType thislist

will count men, because class man inherits from class land...but "landvehicle" will count "real vehicles", and "tank" will count armored ones.

Share this post


Link to post
Share on other sites
Quote[/b] ]Did you guys yet test if this works or are you just

discussing about which way is using less performance?

I would say the later, all seba1985 said was he wanted to count vehicles. Now we could bombard him with lots of code that covers everything from aircraft to cars and all the other possible combinations of empty, disabled, single driver and grouped crews e.t.c

Hardrocks code will work fine for any occupied vehicles on the map, but not for empty vehicles as you pointed out. But again, we don't know if there are any empty vehicles in the first place. It's really up to seba1985 to decide which method best fits his mission and try it out. He can always ask if he hits any problems.

The method I posted, will also need modifying depending on what type of vehicles are on the map and also how he populates the initial array. I think just conveying the basic ideas is enough at this point?

Counting a list of vehicles every 0.5 seconds, for an end game condition, is a bit excessive. So alternative ideas were being suggested, we simple do not have enough info on the mission to provide a complete, efficient, off the shelf solution.

Share this post


Link to post
Share on other sites

Yes, but I did leave the details out of this on purpose, for every solution you have suggested took a general and generic way, not tied up to any specific mission. This way I've learned not only to solve my problem, but to deal with similar situations in other missions.

In this particular mission, a SEAD pack - sort of like - of 2 F-16 (the player and his wingman) approach the desert of Tonal. After they destroy 3 SAM units, 4 A-10s approach the area and engage all the remaining units. The player can attack any target, as he keeps an eye on securing the air space.

There are 38 enemy units on the ground, most of them are tanks. No unit enter nor leave the trigger area (EAST Present - Repeatedly). I went with the solution given here, putting a condition for that trigger in the way of "vehicle _x != driver _x" count thislist == 0 and it worked like a charm.

As I understand it, every time the trigger got to be evaluated, it's list is generated again, and it will be smaller as the vehicles are destroyed, so the CPU will suffer less and less as time passes by. It's difficult to say, because I have had no noticeably frame rate drop from the mission start. Though I would really like to give it a try to the rest of the solutions, I barelly have time to end my campaing, so I'll probably try another method with another mission. I thank you a lot one more time, you've been kind to solve my problem and I've know more scripting than before. Some of the solutions will certainly help me with some missions I had in my head, but didn't knew how to make them.

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  

×