Jump to content
Grim5667

Automatic Spawning Mortor team that fires?

Recommended Posts

Hey, I have had a look around but I probs haven't looked hard enough to find a script that spawns a OPFOR mortor team that fires upon BLUFOR when other OPFOR see bluefor. I have nothing yet so any help would be very helpful

Share this post


Link to post
Share on other sites

Found the edited original here and edited it again:

My revised code for you to use:

Spoiler

/////
//Rewritten from original concept by Unkl on the TacticalGamer forum http://www.tacticalgamer.com/script-bin/194107-arma-3-enemy-mortar-team-script.html
/////
//Rewritten for Grim5667 by SpaceHippo Sep. 17, 2018.
/////

/*
		
	Descrition:
		Spawns a mortar that automatically engages enemies 
		once the crew knows about them.

	Parameters:
		Position of mortar: Position

	Execution Example:
		[[0,0,0]] execVM "whatEverYouNameIt.sqf";

*/

private ["_sideToAttack","_targets","_veh"];

_veh = createVehicle ["O_Mortar_01_F", (_this select 0), [], 0, "NONE"];
createVehicleCrew _veh;

_sideToAttack = WEST;


while { alive _veh } do 
{

	_targets = [];
	{
		if (side _x == _sideToAttack && { alive _x && (crew _veh select 0) knowsAbout _x > 1 } ) then {
			_targets set [count _targets, _x];
		};
	} forEach allUnits;


	if (count _targets > 0) then 
	{

		_chosenTarget = _targets select (floor (random (count _targets)));

		if (alive _veh) then 
		{
			_veh commandArtilleryFire [getPos _chosenTarget, (magazines _veh) select 0, floor (random 6)+1];
			sleep 15;
		};
		
		sleep ((floor random 30) + 45);

	};

	sleep 10;
};

 

  • Like 2

Share this post


Link to post
Share on other sites

Here's a quick mortar snippet that's pretty versatile:

 


//place markers and name them after which mortars you want there:
//a marker named "spawnmortar01_east" will spawn an east side mortar at the marker position

//init.sqf or wherever you seem fit
GOM_fnc_mortarAutoReveal = {

	params ["_mortar"];

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _mortar knowsAbout _x > 0 AND side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};


		//no enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			//it's not really needed to reveal enemies to the mortar if you want the mortar to only fire an exact number of rounds, otherwise they will keep firing until the target is dead
			/*
			{
			effectiveCommander _mortar reveal [_x,4];
			} forEach _nearby;
			*/
			//fire on a random target then look again


			_rounds = 4;
			(effectiveCommander _mortar) commandArtilleryFire [(getPosATL (selectRandom _nearby)),_mag,_rounds];
			systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];
			sleep _rounds * 6;//give enough time to fire all rounds, then start over
		};


		sleep (3 + random 3);


	};


};


GOM_fnc_spawnMortars = {

	params ["_side",["_debug",true]];

	_sides = [west,east,resistance];
	if !(_side in _sides) exitWith {systemChat "Wrong side parameter"};
	_mortarTypes = ["B_Mortar_01_F","O_Mortar_01_F","I_Mortar_01_F"];
	_mortar = _mortarTypes select (_sides find _side);
	_markers = allMapMarkers select {toUpper _x find toUpper str _side >= 0};//for east this returns all markers containing "east" in the name
	_mortars = [];
	if (_debug) then {systemchat format ["Spawning %1 mortars: %2",_side,_markers]};


	{

		_mortarSpawn = _mortar createVehicle getMarkerPos _x;
		createVehicleCrew _mortarSpawn;
		_mortars pushBack _mortarSpawn;

	} forEach _markers;

	{[_x] spawn GOM_fnc_mortarAutoReveal} forEach _mortars;

	if (_debug) then {systemchat format ["Spawn finished: %1",_mortars]};




};


//now when you want to spawn the mortars simply do this:
_spawn = [east] call GOM_fnc_spawnMortars;

Simply place markers on the map where you want mortars to spawn, name them mortarMarker_east01, mortarMarker_east02, etc.

Then call the function as shown above, this will automatically spawn one mortar per marker and make it fire at random targets that are within range and hostile.

Works simultaneously for all three main sides.

 

Cheers

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites
On 18/09/2018 at 9:51 AM, Grumpy Old Man said:

Here's a quick mortar snippet that's pretty versatile:

 



//place markers and name them after which mortars you want there:
//a marker named "spawnmortar01_east" will spawn an east side mortar at the marker position

//init.sqf or wherever you seem fit
GOM_fnc_mortarAutoReveal = {

	params ["_mortar"];

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _mortar knowsAbout _x > 0 AND side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};


		//no enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			//it's not really needed to reveal enemies to the mortar if you want the mortar to only fire an exact number of rounds, otherwise they will keep firing until the target is dead
			/*
			{
			effectiveCommander _mortar reveal [_x,4];
			} forEach _nearby;
			*/
			//fire on a random target then look again


			_rounds = 4;
			(effectiveCommander _mortar) commandArtilleryFire [(getPosATL (selectRandom _nearby)),_mag,_rounds];
			systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];
			sleep _rounds * 6;//give enough time to fire all rounds, then start over
		};


		sleep (3 + random 3);


	};


};


GOM_fnc_spawnMortars = {

	params ["_side",["_debug",true]];

	_sides = [west,east,resistance];
	if !(_side in _sides) exitWith {systemChat "Wrong side parameter"};
	_mortarTypes = ["B_Mortar_01_F","O_Mortar_01_F","I_Mortar_01_F"];
	_mortar = _mortarTypes select (_sides find _side);
	_markers = allMapMarkers select {toUpper _x find toUpper str _side >= 0};//for east this returns all markers containing "east" in the name
	_mortars = [];
	if (_debug) then {systemchat format ["Spawning %1 mortars: %2",_side,_markers]};


	{

		_mortarSpawn = _mortar createVehicle getMarkerPos _x;
		createVehicleCrew _mortarSpawn;
		_mortars pushBack _mortarSpawn;

	} forEach _markers;

	{[_x] spawn GOM_fnc_mortarAutoReveal} forEach _mortars;

	if (_debug) then {systemchat format ["Spawn finished: %1",_mortars]};




};


//now when you want to spawn the mortars simply do this:
_spawn = [east] call GOM_fnc_spawnMortars;

Simply place markers on the map where you want mortars to spawn, name them mortarMarker_east01, mortarMarker_east02, etc.

Then call the function as shown above, this will automatically spawn one mortar per marker and make it fire at random targets that are within range and hostile.

Works simultaneously for all three main sides.

 

Cheers

This almost works except it constantly fires upon me even if im somewhat hidden. Any way to fix this?

Share this post


Link to post
Share on other sites

 

1 hour ago, Grim5667 said:

This almost works except it constantly fires upon me even if im somewhat hidden. Any way to fix this?

 

What do you mean with "almost"? Your question was:

On 9/17/2018 at 10:06 PM, Grim5667 said:

a script that spawns a OPFOR mortor team that fires upon BLUFOR when other OPFOR see bluefor. I have nothing yet so any help would be very helpful

 

Does exactly what you asked for.

You can adjust the condition and other stuff as you seem fit.

 

Currently they're firing as long as anyone on their side knows about the target:

side _mortar knowsAbout _x > 0

You can increase the number from 0 up to 4, which means they will only fire if you've recently revealed yourself (it's a bit more complicated but that about sums it up).

Also you could use targetKnowledge (parameter 7) to fire on the position the enemy last saw you at:

//replace this line:
(effectiveCommander _mortar) commandArtilleryFire [(getPosATL (selectRandom _nearby)),_mag,_rounds];

//with the following:
_targetPos = (effectiveCommander _mortar targetKnowledge (selectRandom _nearby)#6);
(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

 

Cheers

Share this post


Link to post
Share on other sites
3 hours ago, Grumpy Old Man said:

What do you mean with "almost"? Your question was:

Yeah sorry i meant "this works but is there a way to make it so it doesnt constantly fire on me even when im out of sight?"

3 hours ago, Grumpy Old Man said:

//replace this line: (effectiveCommander _mortar) commandArtilleryFire [(getPosATL (selectRandom _nearby)),_mag,_rounds]; //with the following: _targetPos = (effectiveCommander _mortar targetKnowledge (selectRandom _nearby)#6); (effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

There is an error showing up with that code saying "Error #: Type Object, expected Array" any reason why? This is what i have currently:

 

Quote

//place markers and name them after which mortars you want there:

//a marker named "spawnmortar01_east" will spawn an east side mortar at the marker position

 

//init.sqf or wherever you seem fit

GOM_fnc_mortarAutoReveal = {

 

    params ["_mortar"];

 

    while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {

        _enemySides = side _mortar call BIS_fnc_enemySides;

        _mag = currentMagazine _mortar;

        _nearby = (getposatl _mortar nearEntities 4000) select {side _mortar knowsAbout _x > 4 AND side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};


 

        //no enemies found which are in range and have a firing solution, skip and wait

        if (count _nearby > 0) then {

 

            //it's not really needed to reveal enemies to the mortar if you want the mortar to only fire an exact number of rounds, otherwise they will keep firing until the target is dead

            

            {

            effectiveCommander _mortar reveal [_x,4];

            } forEach _nearby;

            

            //fire on a random target then look again


 

            _rounds = 1;

            _targetPos = (effectiveCommander _mortar targetKnowledge (selectRandom _nearby)#6);

            (effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

            systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];

            sleep 60;//give enough time to fire all rounds, then start over

        };


 

        sleep (3 + random 3);


 

    };


 

};


 

GOM_fnc_spawnMortars = {

 

    params ["_side",["_debug",true]];

 

    _sides = [west,east,resistance];

    if !(_side in _sides) exitWith {systemChat "Wrong side parameter"};

    _mortarTypes = ["B_Mortar_01_F","O_Mortar_01_F","I_Mortar_01_F"];

    _mortar = _mortarTypes select (_sides find _side);

    _markers = allMapMarkers select {toUpper _x find toUpper str _side >= 0};//for east this returns all markers containing "east" in the name

    _mortars = [];

    if (_debug) then {systemchat format ["Spawning %1 mortars: %2",_side,_markers]};


 

    {

 

        _mortarSpawn = _mortar createVehicle getMarkerPos _x;

        createVehicleCrew _mortarSpawn;

        _mortars pushBack _mortarSpawn;

 

    } forEach _markers;

 

    {[_x] spawn GRM_fnc_mortarAutoReveal} forEach _mortars;

 

    if (_debug) then {systemchat format ["Spawn finished: %1",_mortars]};




 

};


 

//now when you want to spawn the mortars simply do this:

//_spawn = [east] call GRM_fnc_spawnMortars;

 

Share this post


Link to post
Share on other sites
7 hours ago, Grim5667 said:

Yeah sorry i meant "this works but is there a way to make it so it doesnt constantly fire on me even when im out of sight?"

There is an error showing up with that code saying "Error #: Type Object, expected Array" any reason why? This is what i have currently:

 

 

Your example shouldn't run in the first place, the function definitions have the prefix GOM, then later down the line you changed it to GRM, so there's that.

 

The # command is greedy or whatever's the term, so an additional bracket is needed:

_targetPos = (effectiveCommander _mortar targetKnowledge (selectRandom _nearby))#6;
(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

Cheers

  • Like 1

Share this post


Link to post
Share on other sites
On 29/09/2018 at 4:21 AM, Grumpy Old Man said:

Your example shouldn't run in the first place, the function definitions have the prefix GOM, then later down the line you changed it to GRM, so there's that.

 

The # command is greedy or whatever's the term, so an additional bracket is needed:


_targetPos = (effectiveCommander _mortar targetKnowledge (selectRandom _nearby))#6;
(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

Cheers

But wouldnt that still be overridden by the knowsabout from earlier?

also tt still wont stop firing at me even when ive moved posiotion about 1km and now that the little bit of code was added it fires no where near my character is.

Share this post


Link to post
Share on other sites
11 minutes ago, Grim5667 said:

But wouldnt that still be overridden by the knowsabout from earlier?

also tt still wont stop firing at me even when ive moved posiotion about 1km and now that the little bit of code was added it fires no where near my character is.

Might be the position error of the command messing things up, you could simplify it like this:

_rndTarget = selectRandom _nearby;
_targetPos = getPosATL _rndTarget;

So the final snippet would look like this:

 

GOM_fnc_mortarAutoReveal = {

	params ["_mortar"];

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};


		//no enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			_rounds = 4;
			_rndTarget = selectRandom _nearby;
			_targetPos = getPosATL _rndTarget;
			(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

			systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];
			sleep _rounds * 6;//give enough time to fire all rounds, then start over
		};


		sleep (3 + random 3);


	};


};


GOM_fnc_spawnMortars = {

	params ["_side",["_debug",true]];

	_sides = [west,east,resistance];
	if !(_side in _sides) exitWith {systemChat "Wrong side parameter"};
	_mortarTypes = ["B_Mortar_01_F","O_Mortar_01_F","I_Mortar_01_F"];
	_mortar = _mortarTypes select (_sides find _side);
	_markers = allMapMarkers select {toUpper _x find toUpper str _side >= 0};//for east this returns all markers containing "east" in the name
	_mortars = [];
	if (_debug) then {systemchat format ["Spawning %1 mortars: %2",_side,_markers]};


	{

		_mortarSpawn = _mortar createVehicle getMarkerPos _x;
		createVehicleCrew _mortarSpawn;
		_mortars pushBack _mortarSpawn;

	} forEach _markers;

	{[_x] spawn GOM_fnc_mortarAutoReveal} forEach _mortars;

	if (_debug) then {systemchat format ["Spawn finished: %1",_mortars]};




};


//now when you want to spawn the mortars simply do this:
_spawn = [east] call GOM_fnc_spawnMortars;

Should be more precise.

 

Cheers

Share this post


Link to post
Share on other sites

@Grumpy Old Man Now that just fires on me and i havent even been seen by enemies. As soon as code execute it starts firing on me and i'm going to guess is that it selects random from the _nearby and doesnt have anything stopping it from choosing me.  Maybe an if statement checking if _nearby is known by _mortor and if so fire upon but as soon as it doesnt know about the player it stops firing?

Something like this 

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};
		_targetKnowledge = (_mortar targetKnowledge _nearby) select 3;

		// No enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			_rounds = 2;
			_rndTarget = selectRandom _nearby;
			if (_targetKnowledge > 20 && _targetKnowledge < 66.148) then {
				_targetPos = getPosATL _rndTarget;
				(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];
			
			[west, "HQ"] sidechat "Mortors Inbound!! Get to Cover!";
			sleep _rounds * 6;		// Give enough time to fire all rounds, then start over
			};
		};


		sleep (3 + random 3);


	};


};

But this doesnt work as it expecting a bool on line 9 which is "_targetKnowledge = ..."

Share this post


Link to post
Share on other sites
3 hours ago, Grim5667 said:

@Grumpy Old Man Now that just fires on me and i havent even been seen by enemies. As soon as code execute it starts firing on me and i'm going to guess is that it selects random from the _nearby and doesnt have anything stopping it from choosing me.  Maybe an if statement checking if _nearby is known by _mortor and if so fire upon but as soon as it doesnt know about the player it stops firing?

Something like this 


	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};
		_targetKnowledge = (_mortar targetKnowledge _nearby) select 3;

		// No enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			_rounds = 2;
			_rndTarget = selectRandom _nearby;
			if (_targetKnowledge > 20 && _targetKnowledge < 66.148) then {
				_targetPos = getPosATL _rndTarget;
				(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];
			
			[west, "HQ"] sidechat "Mortors Inbound!! Get to Cover!";
			sleep _rounds * 6;		// Give enough time to fire all rounds, then start over
			};
		};


		sleep (3 + random 3);


	};


};

But this doesnt work as it expecting a bool on line 9 which is "_targetKnowledge = ..."

 

You can add knowsAbout to the _nearby selection, as posted earlier in this thread.

 

 

Cheers

Share this post


Link to post
Share on other sites
19 hours ago, Grumpy Old Man said:

You can add knowsAbout to the _nearby selection, as posted earlier in this thread.

No still doesn't work.

GRM_fnc_mortarAutoReveal = {

	params ["_mortar"];

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		 _nearby = (getposatl _mortar nearEntities 4000) select {side _mortar knowsAbout _x > 3 AND side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};


		//no enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			_rounds = 4;
			_rndTarget = selectRandom _nearby;
			_targetPos = getPosATL _rndTarget;
			(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];

			systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];
			sleep _rounds * 6;//give enough time to fire all rounds, then start over
		};


		sleep (3 + random 3);


	};


};

now targetKnowledge select 1; Would be great because it is either true or false and I could use that in a if statement like, 

GRM_fnc_mortarAutoReveal = {

	params ["_mortar"];

	while {alive _mortar AND canFire _mortar AND count crew _mortar > 0} do {
		_enemySides = side _mortar call BIS_fnc_enemySides;
		_mag = currentMagazine _mortar;
		_nearby = (getposatl _mortar nearEntities 4000) select {side _mortar knowsAbout _x > 3 AND side _x in _enemySides AND _mortar getArtilleryETA [getposatl _x,_mag] > 0 AND getPosATL _x inRangeOfArtillery [[_mortar], _mag]};

		//no enemies found which are in range and have a firing solution, skip and wait
		if (count _nearby > 0) then {

			_rndTarget = selectRandom _nearby;
			_targetPos = getPosATL _rndTarget;
			_targetKnowledge = (_east targetKnowledge _rndTarget) select 1;

			if (_targetKnowledge isEqualTo true) then {
			
			_rounds = 1;
			(effectiveCommander _mortar) commandArtilleryFire [_targetPos,_mag,_rounds];
			systemchat format ["%1 targets: %2",effectivecommander _mortar,count _nearby];
			sleep 15;  //give enough time to fire all rounds, then start over
			};
		};


		sleep (3 + random 3);


	};


};

because this is all in a while statement too but for it to work I would need to get the whole of the EAST side as an object for targetKnowledge to work. If that is possible then it might work as as soon as it turns false it stops working or would that then need to be a while statement? What are your thoughts on this? The knowAbout doesn't seem to work. If it's 1,2 or 3 it always knows where I am but if it's 4 it never knows where i am and therefore will never fire and hence why the targetKnowledge is best for this. But I could make this a little smaller  so instead of an if statement I could replace the "Side _mortar knowsAbout _x > 3" with "(_east targetKnowledge _x) select 1 AND..."  and _east equals to the east side as an object.

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

×