Jump to content

Recommended Posts

Hello, im making a stealth mission where  if my guys get detected they lose, but i want them to have a chance to kill the the ai who spotted them before he communicates to the rest of his fellow ai waht he saw, for this i tried to set the condition on my trigger Timeout for 20 sec, so that the condition of the guys being spotted by enemeis must happen for at least 20 sec before it triggers, the problem is that even if we kill the ai within a short time we are still considered spwaned. any suggestions how to make thai forget us after we killed the ai who spotted and there is no other ai around?

 

 

 

Share this post


Link to post
Share on other sites

but how do i make them forget only when i killed the spotter in a certain amount of time

Share this post


Link to post
Share on other sites

Well, you can use an event handler for this purpose and try to make the whole group forget about the target. If they can still see the target, they will revert back to the previous (most probably aggressive) behavior.

 

This could possibly look like (inside each unit's init field)

// Add the event handler to the unit
this addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];

	// Run the forgetTarget command for all units of the group
	(units (group _unit)) apply {_x forgetTarget _killer};
}];

Now, this is very naive and there's a lot of room for improvement. One major issue here is that the units will "forget" about the killer but not the rest of the units they "know about". So, this may serve as a base for further development, depending on your needs. If this is intended for solo ("lone wolf") SP missions it will most probably work quite OK for isolated groups. Otherwise, further refinement is needed. Furthermore, if you intend to use it with all AI units you should most probably find a better way (than the init field) to add the event handler to the units.

 

Please note that the provided code snippet is not tested and it should be treated with caution. Feel free to ask for more help and/or clarifications if the need arises.

  • Like 1

Share this post


Link to post
Share on other sites
11 hours ago, ZaellixA said:

Well, you can use an event handler for this purpose and try to make the whole group forget about the target. If they can still see the target, they will revert back to the previous (most probably aggressive) behavior.

 

This could possibly look like (inside each unit's init field)


// Add the event handler to the unit
this addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];

	// Run the forgetTarget command for all units of the group
	(units (group _unit)) apply {_x forgetTarget _killer};
}];

Now, this is very naive and there's a lot of room for improvement. One major issue here is that the units will "forget" about the killer but not the rest of the units they "know about". So, this may serve as a base for further development, depending on your needs. If this is intended for solo ("lone wolf") SP missions it will most probably work quite OK for isolated groups. Otherwise, further refinement is needed. Furthermore, if you intend to use it with all AI units you should most probably find a better way (than the init field) to add the event handler to the units.

 

Please note that the provided code snippet is not tested and it should be treated with caution. Feel free to ask for more help and/or clarifications if the need arises.

 Thx, how do i get the unit and killer? these variables change cause any player can kill anu ai.

ive thought maby to do somthing like this: 

 

-----------------------------
waitUntil {{alive _x} count units _myGroup == 0};

_enemy Group forgetTarget _myPlayer;

-------------------------------

worked, but the problem is that now i need to define all the enemy groups and set a code for each:

 

while {true} do {
waitUntil {({alive _x} count units A == 0) or ({alive _x} count units B == 0)};
A forgetTarget player1;
B forgetTarget player1;
}

Share this post


Link to post
Share on other sites

Well, if you have a look at the event handler you'll see that they area passed to the code that will be run when the event handler is called automatically. So, all you have to do is get them as input parameters (this is what the params["_unit", "_killer"] line does).

 

Just to clarify a bit, the event handler is first "added" to the unit (in the example above this refers to the unit as it is given in the init field) and is called when the unit is killed (there are other event handlers which are called on different "events" - this is what the first variable "Killed" defines). The code provided as the second argument will be executed when the handler is called/triggered (please don't confuse the event handler "triggering" with the triggers used in the game, they are not the same thing). For each event handler some variables are passed as input parameters to the code. In the "Killed" event handler the first two are the unit that got killed (_unit) and the unit that did the killing (_killer). So, this is how you get the units.

 

So, the first line in the code (to be executed when the event handler is called) is to get the two units. In the next (and last) line I get the units in the group of the unit that was killed (in an array) and apply a command (forgetTarget) to each one of them. So, when the unit is killed, all the units in its group will "forget" the unit that did the killing (of course if the unit is visible, they will immediately go back to "know" about it).

 

As I said, this is a wee bit naive and rather unrealistic. Nevertheless, I believe that this a quite good way to tackle the issue. In order to add the event handler to all units you could possibly do something like (the example is for all units that are not in the player's side)

// Get all units that are not in the player's side
private _enemies = allUnits select {!((side _x) isEqualTo playerSide)};

// Add the event handler to all the units
_enemies apply {
	_x addEventHandler["Killed", {
		// Get the unit and the killer
		params["_unit", "_killer"];

		// Run the forgetTarget command for all units of the group
		(units (group _unit)) apply {_x forgetTarget _killer};
	}];
};

Now, of course you could code a more complex behavior than that. One example could be to make all units on the side of the killed unit to forget about the killer. In this way you could make all units on the side of the killed unit to forget about the unit that did the killing. In this way, all units (or someone in their group) that do not have line of sight to the killer will lose track of him, with the units (and their groups) that can see the killer keep up the fight (they will forget and immediately go back to "know" again). This could be done like (presenting only the code for the event handler)

_x addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];
	
	// Get the units on the side of the dead unit
	private _enemies = allUnits select {(side _x) isEqualTo (side _unit)};

	// Run the forgetTarget command for all units of the group
	_enemies apply {_x forgetTarget _killer};
}];

So, in this way, you apply the forgetTarget command to all the units on the side of the dead unit. One more thing you could possibly do is to apply the forgetTarget command to all the units on the side of the dead unit for all units in the group of the killer (I believe that if a unit knows about another unit it automatically knows about all the units in the spotted unit's group. I am not 100% sure about it though so you will have to check that). This could look like (again I only present the code for the event handler)

_x addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];
	
	// Get the units on the side of the dead unit
	private _enemies = allUnits select {(side _x) isEqualTo (side _unit)};

	// Run the forgetTarget command for all units of the group
	_enemies apply {
		// Get the current enemy in a variable to be used in the forEach below
		private _curEnemy = _x;

		// Get the units in the killer's group
		private _killGroup = units (group _killer);

		// Apply the forget target for each unit in killer's group
		{
			// Forget the unit of killer's group
			_curEnemy forgetTarget _x;
		} forEach _killGroup;
	};
}];

Please note that all code presented here is not tested and should be treated with caution. I hope that this provides some help and clarification somehow. Do not hesitate to ask again if this does not solve your problem, help or you may need further assistance.

  • Thanks 1

Share this post


Link to post
Share on other sites
21 hours ago, ZaellixA said:

Well, if you have a look at the event handler you'll see that they area passed to the code that will be run when the event handler is called automatically. So, all you have to do is get them as input parameters (this is what the params["_unit", "_killer"] line does).

 

Just to clarify a bit, the event handler is first "added" to the unit (in the example above this refers to the unit as it is given in the init field) and is called when the unit is killed (there are other event handlers which are called on different "events" - this is what the first variable "Killed" defines). The code provided as the second argument will be executed when the handler is called/triggered (please don't confuse the event handler "triggering" with the triggers used in the game, they are not the same thing). For each event handler some variables are passed as input parameters to the code. In the "Killed" event handler the first two are the unit that got killed (_unit) and the unit that did the killing (_killer). So, this is how you get the units.

 

So, the first line in the code (to be executed when the event handler is called) is to get the two units. In the next (and last) line I get the units in the group of the unit that was killed (in an array) and apply a command (forgetTarget) to each one of them. So, when the unit is killed, all the units in its group will "forget" the unit that did the killing (of course if the unit is visible, they will immediately go back to "know" about it).

 

As I said, this is a wee bit naive and rather unrealistic. Nevertheless, I believe that this a quite good way to tackle the issue. In order to add the event handler to all units you could possibly do something like (the example is for all units that are not in the player's side)


// Get all units that are not in the player's side
private _enemies = allUnits select {!((side _x) isEqualTo playerSide)};

// Add the event handler to all the units
_enemies apply {
	_x addEventHandler["Killed", {
		// Get the unit and the killer
		params["_unit", "_killer"];

		// Run the forgetTarget command for all units of the group
		(units (group _unit)) apply {_x forgetTarget _killer};
	}];
};

Now, of course you could code a more complex behavior than that. One example could be to make all units on the side of the killed unit to forget about the killer. In this way you could make all units on the side of the killed unit to forget about the unit that did the killing. In this way, all units (or someone in their group) that do not have line of sight to the killer will lose track of him, with the units (and their groups) that can see the killer keep up the fight (they will forget and immediately go back to "know" again). This could be done like (presenting only the code for the event handler)


_x addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];
	
	// Get the units on the side of the dead unit
	private _enemies = allUnits select {(side _x) isEqualTo (side _unit)};

	// Run the forgetTarget command for all units of the group
	_enemies apply {_x forgetTarget _killer};
}];

So, in this way, you apply the forgetTarget command to all the units on the side of the dead unit. One more thing you could possibly do is to apply the forgetTarget command to all the units on the side of the dead unit for all units in the group of the killer (I believe that if a unit knows about another unit it automatically knows about all the units in the spotted unit's group. I am not 100% sure about it though so you will have to check that). This could look like (again I only present the code for the event handler)


_x addEventHandler["Killed", {
	// Get the unit and the killer
	params["_unit", "_killer"];
	
	// Get the units on the side of the dead unit
	private _enemies = allUnits select {(side _x) isEqualTo (side _unit)};

	// Run the forgetTarget command for all units of the group
	_enemies apply {
		// Get the current enemy in a variable to be used in the forEach below
		private _curEnemy = _x;

		// Get the units in the killer's group
		private _killGroup = units (group _killer);

		// Apply the forget target for each unit in killer's group
		{
			// Forget the unit of killer's group
			_curEnemy forgetTarget _x;
		} forEach _killGroup;
	};
}];

Please note that all code presented here is not tested and should be treated with caution. I hope that this provides some help and clarification somehow. Do not hesitate to ask again if this does not solve your problem, help or you may need further assistance.

Thanks alot, im only just started coding so htis is  alot of help!

  • Like 1

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

×