The Fighting 99th Air Wing

AIR : LAND : SEA : FIGHT!

Fighting 99th Forum

Scripting Noob Cygon's Developing Experiments

7 years 11 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #557
Yes, I'm a noob. A laughable, scripting noob.

But I'm trying.

Blowing cobwebs off old programming thought process not used in several years and getting to grips (slowly) with Lua and DCS Scripting Engine. I've asked a few, minimal questions on ED Forums, always wary of how cheesed off coders get at the slightest, from past experience, and even considering that I've managed to cheese them off to an extent (Jeez, how the hell do they expect you to learn with that patchy documentation? Magic?). Oh well.

So now that I have managed to finally cobble together a standalone script that does something, I bid ED Forums a temporary fair adieu, and will cheese all of you guys off some more...

This is just a repository, so to speak, of my "snippets", basically for my own reference. If anyone more in the know wants to point out a major blunder of mine or recommend a better way to do something, please feel free to say so. Conversely, if someone as big a noob as I wants to know how I did something, also say so. I'll try and explain, which will be good for my revision. This way we would all be helping each other and shedding the veil of mystery of this subject, little by little (personally, I dislike veils of mystery, and have never shunned the opportunity to rip 'em down if and whenever I can).

Enough hot air, right? Here's the script I've given myself a headache doing this afternoon.
_name_unit_C2 = ""
_name_unit_C1 = ""

	for _i, _group_C2 in pairs(coalition.getGroups(2)) do

		_name_group_C2 = Group.getName(_group_C2)
		
		for _j, _unit_C2 in pairs(Group.getByName(_name_group_C2):getUnits()) do 

			_name_unit_C2 = Unit.getName(_unit_C2)
			_name_type_C2 = Unit.getTypeName(_unit_C2)
			
			if _name_type_C2 == "AAV7" then
			
				for _k, _group_C1 in pairs(coalition.getGroups(1)) do
					
					_name_group_C1 = Group.getName(_group_C1)
					
					for _j, _unit_C1 in pairs(Group.getByName(_name_group_C1):getUnits()) do
					
						_name_unit_C1 = Unit.getName(_unit_C1)
						_name_type_C1 = Unit.getTypeName(_unit_C1)

						--trigger.action.outText(_name_unit_C2, 5)
						--trigger.action.outText(_name_unit_C1, 5)
						
						if _name_type_C1 == "BTR-80" then
						
						if _name_unit_C2 ~= nil and _name_unit_C1 ~= nil then
						
							_position_C2 = _unit_C2:getPosition().p
							_position_C1 = _unit_C1:getPosition().p
							
														
							_range_x = _position_C2.x - _position_C1.x
							_range_y = _position_C2.z - _position_C1.z
							_range_total = math.sqrt(_range_x^2 + _range_y^2)
							
							trigger.action.outText(_range_total, 5)
							
						end
						
						end
					end
				end
			end
		end

	end

All it does it measure horizontal distances between units of coalition 1 and 2, if they are an AAV-7 and a BTR-80. Yeah, probably been done many times before and almost anyone here can probably do it in their sleep. But I couldn't, and had to start somewhere.

Thank you for your patience!

Please Log in or Create an account to join the conversation.

7 years 11 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #3980
OK. This one almost seems a step backwards. However...

I went quite far afield this afternoon with some experiments obtaining locations, spawning groups, destroying (erasing) units, timing, flags, and such. One thing became obvious; I am going to have to get to grips with DCS's way of event queuing, it is probably similar to SDL or Allegro 5, in a way, once you get used to it, but it sure looks alien to me at the moment. However, none of the experiments came to the level of completion I wanted. That is; for integration into a scenario.

The quality of the documentation has interfered again. One thing that really is a hold up is "Type Names". Of course, a good part of knowledge is knowing where to look for your references, as needed. However, I find nothing related to that anywhere. And you cannot trust the type names as given in the encyclopedia, or even the "type" field in the ME. The script / program has a different textual handle for unit types. So the only way to obtain them (I decided before I pulled my hair out, which would be a shame as it has defied falling out for nearly 50 years now) is to make a script that allows the running game to tell you the names itself.
for _i = 1, 2 do
	for _j, _group in pairs(coalition.getGroups(_i), Group.Category.GROUND) do
		
		_name_group = Group.getName(_group)
		
		if _i == 1 then
			_coalition = "RED"
		else
			_coalition = "BLUE"
		end
		trigger.action.outText("coalition " .. _coalition .. ": " .. _name_group, 20)
		
		for _k, _unit in pairs(Group.getByName(_name_group):getUnits()) do
			_unit_type = Unit.getTypeName(_unit)
			trigger.action.outText("Unit " .. _k .. " type is: " .. _unit_type, 30)
		end
		
	end
end

As said, not much different from the distance obtaining script before, and a tip of the iceberg of what I have played around with today, but at least it is useful, for me.

Make a scenario with whatever ground units you want to know the names of in it. Do a "Mission Start" trigger condition, and put this as a "do script action". Viola!




PS: Forgot to add another utility one I'd done to get base coords and names. I'll stick it here for reference in case I erase or overwrite it by accident...
_airbases = world.getAirbases()

for _i, _base in pairs(_airbases) do
	_base_name = Airbase.getName(_base)
	_base_position = _base:getPosition().p
	trigger.action.outText(_i .. " " .. _base_name, 30)
	trigger.action.outText(_i .. " Pos X " .. _base_position.x .. " Pos Y(as z) " .. _base_position.z,  30)
end
Better script next time!

Please Log in or Create an account to join the conversation.

7 years 11 months ago
runny
New Member
New Member
More
Scripting Noob Cygon's Developing Experiments #3987
Someone else was looking for and succeeded in finding a list of all the classnames. I think it was EightBit or Shadow but I can't recall.

Please Log in or Create an account to join the conversation.

7 years 11 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #3998
Well, I expect they had no trouble with it, at their level, but my apologies, I never saw if and where that may have been posted. In any case, it was a good exercise for me, so I'm not complaining! :cheer:

Another repository post, as I am petrified of erasing or irrecoverably altering things that partially work to expectations, as yet. This does not do much yet, it is basically unusable in a practical sense, but is needed as part of a two script function. Part 1, here, gets and sets userflags for countdown upon destruction of units in a SAM group. When I finally understand the Event Queue of the script engine, I'll be able to put all of the objective of the scripts in one file.

Note: There are some issues with this script, which are documented in comments. As I'm not going to be anywhere near DCS for the next three days, I want to paste it here as a WIP up to this point post, pending future modification...
-- ON DESTROY event fired script.
-- Make sure these groups are the same group names in the game.
-- Include all SAM unit groups that regeneration is required for.

_SAM_GROUPS = {
	{"R_SAM_G1", "R_SAM_G2"}, 
	{"B_SAM_G1", "B_SAM_G2"}
}
_SR_RADARS = {"p-19 s-125 sr", "Hawk sr"}
_TR_RADARS = {"snr s-125 tr", "Hawk tr"}
_OTHER_REQ = {"Hawk pcp"}
_LAUNCHERS = {"5p73 s-125 ln", "Hawk ln"}

_sr_radar_alive = 0
_tr_radar_alive = 0
_other_req_alive = 0
_launcher_alive = 0

for _i = 1, 2 do
	for _j, _sam_Group in pairs(_SAM_GROUPS[_i]) do
		
		_sam_Group_name = _SAM_GROUPS[_i][_j]
		_sam_Group_handle = Group.getByName(_sam_Group_name) 
		_sam_Group_init_size = _sam_Group_handle:getInitialSize()
		_sam_Group_current_size = _sam_Group_handle:getSize()
		
		if _sam_Group_init_size > _sam_Group_current_size then

		-- Some work with conditions needed here.
		-- DCS registers the ON DESTROY event, yes, but leaves the affected unit
		-- alive for a moment, presumably so you can collect data on the unit
		-- through scripts.
		-- The only function that registers it dead during this short moment,
		-- is the isExist() function.
		-- Therefore this condition will need to use this function in future,
		-- as getSize() also seems to count the dead unit as alive during that
		-- brief period of grace.
		-- Check if a unit has been lost from the group.

			if trigger.misc.getUserFlag(_i * 100 + _j) == 0 then

				-- check if the group regen flag has already been accounted for.
				-- if not, got to figure out if it is at least 
				-- one radar or all the launchers of the group have been killed.

				_sr_radar_alive = 0
				_tr_radar_alive = 0
				_other_req_alive = 0
				_launcher_alive = 0
				for _k, _sam_Unit_handle in pairs(_sam_Group_handle:getUnits()) do
					_sam_Unit_name = Unit.getName(_sam_Unit_handle)
					_sam_Unit_type = _sam_Unit_handle:getTypeName()

					-- Check SR
					for _l, _type_index in pairs(_SR_RADARS) do
						if _sam_Unit_type == _type_index then
							_sr_radar_alive = _sr_radar_alive + 1
						end
					end

					-- Check TR
					for _l, _type_index in pairs(_TR_RADARS) do
						if _sam_Unit_type == _type_index then
							_tr_radar_alive = _tr_radar_alive + 1
						end
					end

					-- Check Other
					for _l, _type_index in pairs(_OTHER_REQ) do
						if _sam_Unit_type == _type_index then
							_other_req_alive = _other_req_alive + 1
						end
					end

					-- Check Launchers
					for _l, _type_index in pairs(_LAUNCHERS) do
						if _sam_Unit_type == _type_index then
							_launcher_alive = _launcher_alive + 1
						end
					end

				end

				if _sr_radar_alive == 0 or _tr_radar_alive == 0 or _other_req_alive == 0 or _launcher_alive == 0 then
					trigger.action.setUserFlag(_i * 100 + _j, 60)
					-- trigger.action.outText("Flag " .. (_i * 100 + _j) .. " is set to: " .. trigger.misc.getUserFlag(_i * 100 + _j), 20)
				end
			end
		end
	end
end

Please Log in or Create an account to join the conversation.

7 years 8 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #4642
One of the scripts I needed for the Six Day War scenario is functional now (at last!) in a test form. This is another "repository" progress anchor post for me, BTW. Here it is, and blurb afterwards...
HELO_TRANSPORTS = {
	"R-HGP-01", "R-HGP-02", "R-HGP-03", "R-HGP-04",
	"B-HGP-01", "B-HGP-02", "B-HGP-03", "B-HGP-04"}

SUPPLY_POINTS = {
	"R-SP-01", "R-SP-02",
	"B-SP-01", "B-SP-02"}	
	
local Collect_Radius = 100
	
local Event_Handler = {}

function Event_Handler:onEvent(Event)

	if Event.id == world.event.S_EVENT_LAND then
		if Event.initiator then
			local Init_Name = Event.initiator:getName()
			
			for i, Helo_Unit in pairs (HELO_TRANSPORTS) do
				-- makes sure all subsequent actions in this block only apply to the helo that has landed
				if Helo_Unit == Init_Name then
					local STATIC_OBJECTS
					Helo_Unit_Coalition = Event.initiator:getCoalition()
					
					if Helo_Unit_Coalition == 1 then
						STATIC_OBJECTS = coalition.getStaticObjects(1)
					elseif Helo_Unit_Coalition == 2 then
						STATIC_OBJECTS = coalition.getStaticObjects(2)
					end
					
					local Collect_Flag = false
					
					for j, Static_Object in pairs (STATIC_OBJECTS) do
						for k, Supply_Point in pairs (SUPPLY_POINTS) do
							if Static_Object:getName() == Supply_Point then
																
								local Supply_Pos = Static_Object:getPosition().p
								local Helo_Pos = Event.initiator:getPosition().p
								local Dist_x = Helo_Pos.x - Supply_Pos.x
								local Dist_y = Helo_Pos.z - Supply_Pos.z
								local Total_Dist = math.sqrt(Dist_x^2 + Dist_y^2)
								
								--trigger.action.outText("Distance is " .. Total_Dist, 5)
								
								if Total_Dist < Collect_Radius then
									Collect_Flag = true
									if trigger.misc.getUserFlag(500 + i) == 0 then
										trigger.action.setUserFlag(500 + i, 1)
										--trigger.action.outText("You can collect troops here" , 5)
									end
								end
																					
							end
						end
					end
					
					if Collect_Flag == false then
						if trigger.misc.getUserFlag(500 + i) == 1 then
							local Helo_Pos = Event.initiator:getPosition().p
							RPG_MAN_SPAWN =
							{
								["visible"] = false,
								["groupId"] = math.random(999),
								["name"] = string.format("RPG_" .. math.random(10, 10000)),
								["hidden"] = false,
								["units"] = 
								{
									[1] = 
									{
										["type"] = "Soldier RPG",
										["name"] = string.format("RPG_U_" .. math.random(10,10000)),
										["unitId"] = math.random(10,10000),
										["heading"] = 0,
										["playerCanDrive"] = false,
										["skill"] = "Excellent",
										["x"] = Helo_Pos.x + (math.random(40) - 20),
										["y"] = Helo_Pos.z + (math.random(40) - 20),
									},
								},
							}
							trigger.action.setUserFlag(500 + i, 0)
							
							if Helo_Unit_Coalition == 1 then
								coalition.addGroup(country.id.RUSSIA, Group.Category.GROUND, RPG_MAN_SPAWN)
							elseif Helo_Unit_Coalition == 2 then
								coalition.addGroup(country.id.USA, Group.Category.GROUND, RPG_MAN_SPAWN)
							end
						end
					end
				end
				
			end
		
		end
	end

end

world.addEventHandler(Event_Handler)

First, thanks to Tracer and Magnet for the brief but extremely helpful chats on TS that pointed me in the right direction, plus some few, short but informative answers on ED Forum from a couple of people who really know their stuff regarding getting the Event Handler procedures to work. There are sure to be a couple of faults in there, and I can already see where some optimization can be done to avoid redundant calls to some functions, but it seems to be working, so far.

What does it do? Well, nothing CTLD doesn't do, but CTLD had far too many things included for the simplicity of the Six Day War mission, plus CTLD does permit some unrealistic transportation of heavy units (admit it, lol!). Now, I could just use CTLD, I know, but I wouldn't learn anything about DCS scripting if I did not do the script from scratch.

1. Set up the map with a few static objects that will work as supply depots, for each side. Name them as per the SUPPLY_POINTS array in the script (or edit the names in the script to suit yours).

2. Set up some helos on the map and name them according to the HELO_TRANSPORTS array (or edit).

3. Include the script in the mission as a ONCE condition. This turned out to be important, as I was originally firing it as a continuous condition and it was generating dozens of landing events for each single landing.

Land the helo at one of the assigned supply depots. Fly away and land anywhere else. The helo automatically drops one RPG man. The script is simple, and can be modified to deploy more units, or sections of groups, and so on. The main advantage, from my point of view is it does not require all that fiddling with menus if you are trying to drop some troops in while under fire. Just touch and go!

PS: BTW, a known issue at present. If the helo is loaded and gets destroyed, an on death event needs to be fired to reset the "troops loaded" user flag back to zero, or the next user starts with a pre-loaded helo. Not a big thing to implement, having come this far.

Please Log in or Create an account to join the conversation.

7 years 8 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #4653
All issues appeared to be solved with this script, and I have a working version now for my scenario, pending testing. If anyone wants to try it, please go ahead and report anything if it breaks!
HELO_TRANSPORTS = {
	"R-HGP-01", "R-HGP-02", "R-HGP-03", "R-HGP-04",
	"B-HGP-01", "B-HGP-02", "B-HGP-03", "B-HGP-04"}

SUPPLY_POINTS = {
	"R-SP-01", "R-SP-02",
	"B-SP-01", "B-SP-02"}	
-- Flags 500 + number of helo transports reserved for helo loaded troops
-- Flag 1000 reserved for New Group ID numbers
trigger.action.setUserFlag(1000, 900) --New Group ID Value
-- Flag 2000 reserved for New Unit ID numbers
trigger.action.setUserFlag(2000, 5000) --New Unit ID Value

local Event_Handler = {}

-- Main Event Handler Block...
function Event_Handler:onEvent(_Event)

	if _Event.id == world.event.S_EVENT_LAND then
		if _Event.initiator then
			Troop_Deploy(_Event)
		end
	end

	if _Event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT then
		if _Event.initiator then
			Clear_Troop_Flag(_Event)
		end
	end
	
	if _Event.id == world.event.S_EVENT_DEAD then
		if _Event.initiator then
			Clear_Troop_Flag(_Event)
		end
	end
	
end

-- Functions called from event handler

function Troop_Deploy(Event)
	local Init_Name = Event.initiator:getName()
			
	for i, Helo_Unit in pairs (HELO_TRANSPORTS) do
	-- makes sure all subsequent actions in this block only apply to the helo that has landed
		if Helo_Unit == Init_Name then
			local STATIC_OBJECTS
			
			local Helo_Unit_Coalition = Event.initiator:getCoalition()
			--local Helo_Pos = Event.initiator:getPosition().p
			local Helo_Pos = Event.initiator:getPosition()
			local Helo_Group_ID = Event.initiator:getID()
			--local Helo_Group = Group.getByName(Init_Name)
			
			local Helo_Hdg = math.atan2(Helo_Pos.x.z, Helo_Pos.x.x)
			--trigger.action.outText("Heading is " .. Helo_Hdg, 5) 
						
			local Collect_Radius = 100
			local Collect_Flag = false
			
			if Helo_Unit_Coalition == 1 then
				STATIC_OBJECTS = coalition.getStaticObjects(1)
			elseif Helo_Unit_Coalition == 2 then
				STATIC_OBJECTS = coalition.getStaticObjects(2)
			end
					
			for j, Static_Object in pairs (STATIC_OBJECTS) do
				for k, Supply_Point in pairs (SUPPLY_POINTS) do
					if Static_Object:getName() == Supply_Point then
																
						local Supply_Pos = Static_Object:getPosition() --.p
						--local Helo_Pos = Event.initiator:getPosition().p
						local Dist_x = Helo_Pos.p.x - Supply_Pos.p.x
						local Dist_y = Helo_Pos.p.z - Supply_Pos.p.z
						local Total_Dist = math.sqrt(Dist_x^2 + Dist_y^2)
								
						--trigger.action.outText("Distance is " .. Total_Dist, 5)
								
						if Total_Dist < Collect_Radius then
							Collect_Flag = true
							--if trigger.misc.getUserFlag(500 + i) == 0 then
							if trigger.misc.getUserFlag(500 + i) < 3 then
								trigger.action.setUserFlag(500 + i, 3)
								
								trigger.action.outTextForGroup(Helo_Group_ID, "You have collected RPG Squads. You have " .. trigger.misc.getUserFlag(500 + i) .. " on board.", 5)
							end
						end
																					
					end
				end
			end
					
			if Collect_Flag == false then
				
				if trigger.misc.getUserFlag(500 + i) > 0 then
					
					local Troop_Deploy_Dist = 50.0
					local Troop_Deploy_Spread = 30.0
					
					local x_drop_extend = math.cos(Helo_Hdg) * Troop_Deploy_Dist
					local y_drop_extend = math.sin(Helo_Hdg) * Troop_Deploy_Dist
					
					local Group_Name = string.format("Helo_Squad_" .. trigger.misc.getUserFlag(1000))
					local New_Group_ID = trigger.misc.getUserFlag(1000)
					--once the New Group ID is set, raise the flag value for the next new group.
					trigger.action.setUserFlag(1000, trigger.misc.getUserFlag(1000) + 1)
					
					HELO_SQUAD_SPAWN =
					{
						["visible"] = false,
						["groupId"] = New_Group_ID,
						["name"] = Group_Name,
						["hidden"] = false,
						["units"] = 
						{
							[1] = 
							{
								["type"] = "Soldier M249",
								["name"] = string.format("M249_1_" .. trigger.misc.getUserFlag(1000)),
								["unitId"] = trigger.misc.getUserFlag(2000),
								["heading"] = Helo_Hdg,
								["playerCanDrive"] = false,
								["skill"] = "Excellent",
								["x"] = Helo_Pos.p.x + x_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								["y"] = Helo_Pos.p.z + y_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
							},
							[2] = 
							{
								["type"] = "Soldier M249",
								["name"] = string.format("M249_2_" .. trigger.misc.getUserFlag(1000)),
								["unitId"] = trigger.misc.getUserFlag(2000) + 1,
								["heading"] = Helo_Hdg,
								["playerCanDrive"] = false,
								["skill"] = "Excellent",
								["x"] = Helo_Pos.p.x + x_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								["y"] = Helo_Pos.p.z + y_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
							},
							[3] = 
							{
								["type"] = "Soldier RPG",
								["name"] = string.format("RPG_3_" .. trigger.misc.getUserFlag(1000)),
								["unitId"] = trigger.misc.getUserFlag(2000) + 2,
								["heading"] = Helo_Hdg,
								["playerCanDrive"] = false,
								["skill"] = "Excellent",
								["x"] = Helo_Pos.p.x + x_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								["y"] = Helo_Pos.p.z + y_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
							},
							[4] = 
							{
								["type"] = "Soldier RPG",
								["name"] = string.format("RPG_4_" .. trigger.misc.getUserFlag(1000)),
								["unitId"] = trigger.misc.getUserFlag(2000) + 3,
								["heading"] = Helo_Hdg,
								["playerCanDrive"] = false,
								["skill"] = "Excellent",
								["x"] = Helo_Pos.p.x + x_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								["y"] = Helo_Pos.p.z + y_drop_extend + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
							},
						},
					}
					--Increase the value of the New unit ID flag for the next new units...
					trigger.action.setUserFlag(2000, trigger.misc.getUserFlag(2000) + 5)

					--Reduces the number of Squads on board by one...
					trigger.action.setUserFlag(500 + i, trigger.misc.getUserFlag(500 + i) - 1)
					trigger.action.outTextForGroup(Helo_Group_ID, "You have dropped an RPG Squad, " .. trigger.misc.getUserFlag(500 + i) .. " remaining on board.", 5)

							
					if Helo_Unit_Coalition == 1 then
						coalition.addGroup(country.id.RUSSIA, Group.Category.GROUND, HELO_SQUAD_SPAWN)
					elseif Helo_Unit_Coalition == 2 then
						coalition.addGroup(country.id.USA, Group.Category.GROUND, HELO_SQUAD_SPAWN)
					end
					--Set the group to weapons free ROE
					local Group_Control = Group.getByName(Group_Name):getController()
					Group_Control:setOption(0, 0)
					
				end
			end
		end
				
	end
end

function Clear_Troop_Flag(Event)
	--This justs resets the troops loaded flag to 0 for the respective helicopter
	--that was either killed or that the player left.
	local Init_Name = Event.initiator:getName()
	
	for i, Helo_Unit in pairs (HELO_TRANSPORTS) do
		if Helo_Unit == Init_Name then
			trigger.action.setUserFlag(500 + i, 0)
		end
	end

end

world.addEventHandler(Event_Handler)

OK, not quite cooking with an industrial gas oven yet, as far as programming like I used to goes, but maybe a bunsen burner, LOL!

Changes and improvements;

1. If a player leaves or gets killed in a loaded helo unit, the "cargo" of RPG Squads is reset to zero.

2. The helo now collects 12 troops from the supply area (3 Squads of 4 troops). The RPG squad consists of two machine gun soldiers, and two RPG soldiers.

3. Once loaded, to deploy a squad, just land. To deploy another, take off and land again.

4. Troops are now deployed in front of the helicopter, facing the same way the helicopter faces.

5. ROE is set to weapons free so that they start firing immediately if an enemy is in range.

6. The random values for new Group and Unit IDs is stored in reserve flags now, so that no accidental duplicating of IDs occurs with random numbers.

That's it. My first script. Yay!

More to come for the Six Day War scenario;

SAM site complete regeneration script.
APC carried troops deployment upon being hit (basically, an evacuation before boom! script).
Armor Group Reserves activation (spawn) script.

Please Log in or Create an account to join the conversation.

7 years 8 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #4669
Another one done, to a larger extent. This is the APC evacuation script.
APC_TYPE_NAMES = {
	"MTLB", "M-113"}

local Event_Handler = {}

function Event_Handler:onEvent(_Event)
	--trigger.action.outText("Event Handler Active", 5)
	if _Event.id == world.event.S_EVENT_HIT then
		--need to verify that the hit object was a ground unit
		--Category 1 is GROUND unit
		local Target_Category = _Event.target:getCategory()
		
		if Target_Category == 1 then
			Target_Type = _Event.target:getTypeName()
			--Verify if hit unit was an APC of the listed type in APC_TYPE_NAMES
			for i, APC_Type in pairs (APC_TYPE_NAMES) do
				if Target_Type == APC_Type then
					--trigger.action.outText("Target Category: " .. Target_Category .. ", Name " .. Target_Type, 5)
					local Target_Coalition = _Event.target:getCoalition()
					local Target_Pos = _Event.target:getPosition()
					local Target_Hdg = math.atan2(Target_Pos.x.z, Target_Pos.x.x)
					
					local G_Hdg = {}
					G_Hdg[1] = Target_Hdg + 1.5
					G_Hdg[2] = Target_Hdg - 1.5
					
					local Troop_Deploy_Dist = 70.0
					local Troop_Deploy_Spread = 35.0
					
					local x_drop_extend = {}
					local y_drop_extend = {}
					x_drop_extend[1] = math.cos(G_Hdg[1]) * Troop_Deploy_Dist
					y_drop_extend[1] = math.sin(G_Hdg[1]) * Troop_Deploy_Dist
					x_drop_extend[2] = math.cos(G_Hdg[2]) * Troop_Deploy_Dist
					y_drop_extend[2] = math.sin(G_Hdg[2]) * Troop_Deploy_Dist
					
					local Group_Name = string.format("APC_Squad_" .. trigger.misc.getUserFlag(1000))
					local New_Group_ID = trigger.misc.getUserFlag(1000)
					trigger.action.setUserFlag(1000, trigger.misc.getUserFlag(1000) + 1)
					
					local Group_iterator = 2
					local Group_Name = ""
					local New_Group_ID = 0
					local Group_Control
					
					while Group_iterator > 0 do
						Group_Name = string.format("APC_Squad_" .. trigger.misc.getUserFlag(1000))
						New_Group_ID = trigger.misc.getUserFlag(1000)
						trigger.action.setUserFlag(1000, trigger.misc.getUserFlag(1000) + 1)
						
						APC_SQUAD_SPAWN =
						{
							["visible"] = false,
							["groupId"] = New_Group_ID,
							["name"] = Group_Name,
							["hidden"] = false,
							["units"] = 
							{
								[1] = 
								{
									["type"] = "Soldier M249",
									["name"] = string.format("M249_1_" .. trigger.misc.getUserFlag(1000)),
									["unitId"] = trigger.misc.getUserFlag(2000),
									["heading"] = G_Hdg[Group_iterator],
									["playerCanDrive"] = false,
									["skill"] = "Excellent",
									["x"] = Target_Pos.p.x + x_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
									["y"] = Target_Pos.p.z + y_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								},
								[2] = 
								{
									["type"] = "Soldier M249",
									["name"] = string.format("M249_2_" .. trigger.misc.getUserFlag(1000)),
									["unitId"] = trigger.misc.getUserFlag(2000) + 1,
									["heading"] = G_Hdg[Group_iterator],
									["playerCanDrive"] = false,
									["skill"] = "Excellent",
									["x"] = Target_Pos.p.x + x_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
									["y"] = Target_Pos.p.z + y_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								},
								[3] = 
								{
									["type"] = "Soldier RPG",
									["name"] = string.format("RPG_3_" .. trigger.misc.getUserFlag(1000)),
									["unitId"] = trigger.misc.getUserFlag(2000) + 2,
									["heading"] = G_Hdg[Group_iterator],
									["playerCanDrive"] = false,
									["skill"] = "Excellent",
									["x"] = Target_Pos.p.x + x_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
									["y"] = Target_Pos.p.z + y_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								},
								[4] = 
								{
									["type"] = "Soldier RPG",
									["name"] = string.format("RPG_4_" .. trigger.misc.getUserFlag(1000)),
									["unitId"] = trigger.misc.getUserFlag(2000) + 3,
									["heading"] = G_Hdg[Group_iterator],
									["playerCanDrive"] = false,
									["skill"] = "Excellent",
									["x"] = Target_Pos.p.x + x_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
									["y"] = Target_Pos.p.z + y_drop_extend[Group_iterator] + (math.random(Troop_Deploy_Spread) - (Troop_Deploy_Spread / 2)),
								},
							},
						}
						--Increase the value of the New unit ID flag for the next new units...
						trigger.action.setUserFlag(2000, trigger.misc.getUserFlag(2000) + 5)
						Group_iterator = Group_iterator - 1
						
						if Target_Coalition == 1 then
							coalition.addGroup(country.id.RUSSIA, Group.Category.GROUND, APC_SQUAD_SPAWN)
						elseif Target_Coalition == 2 then
							coalition.addGroup(country.id.USA, Group.Category.GROUND, APC_SQUAD_SPAWN)
						end
						
						Group_Control = Group.getByName(Group_Name):getController()
						Group_Control:setOption(0, 0)
						
					end
				end
			end
			
		end
	end
end

world.addEventHandler(Event_Handler)

Right here I have it as a separate script, but it will be included in the final along with the previous helo-rpg script, as they are commonly event driven and there's no reason to have too many event handlers registered if you can optimize into one.

What happens here, then? Again, simple. If an APC is hit, it generates a spawn of 8 "survivors" who deploy around the APC.

Due to the radius I have them deploying to at the moment, if the APC is hit by a big missile or bomb from an aircraft, these survivors are actually also killed by the blast. However, if the APC is hit by a tank, cooks off and blows up by itself, the blast does not kill the deployed squads. It is, in fact, quite good as is.

I am currently asking questions on ED Forums about how the group waypoint system is organized. It is not very intuitive, just looking at it, and as usual, I cannot find any docs regarding. The ultimate aim for this script is for the troops to advance to a point between the APC they deployed from and the "vehicle" that fired on the APC, which is in range of the RPGs, therefore exacting their vengeance, Muahaha!

Please Log in or Create an account to join the conversation.

7 years 6 months ago
Cygon_Parrot
New Member
New Member
Posts: 1
More
Topic Author
Scripting Noob Cygon's Developing Experiments #5092
Haven't had all the time to work on these scripts as might have been ideal lately, but I did get to the very bottom of how group paths work in scripting, finally. Coding and its results testing can be a lot of fun. I'm working on several, when I can, at present and learning more about DCS scripting language and lua with every session.

Here's a video of the APC evacuation script in action...

<a href="vid.me/KyNF" class="bbvideo" data-bbvideo="640,360" target="_blank">vid.me/KyNF

That was recorded SP. Unfortunately, there seems to be a bit of an MP Combined Arms bug at the moment, evident on servers 2.0 when you move ground units. Ie; after moving a few groups around on the F-10 map, the game crashes. It does not seem to have much to do with the scenario, it happened to me on the Alamo and the Cold War scenarios, and also on another server, with a script-less scenario. Seems to be some core issue; anyone else experiencing this? Is it known?

In any case, I'm waiting for the solution/fix/update. My own scenarios always seem to be highly dependent on CA for objective accomplishment.

EDIT: Added reference to a post that has a script I was working on. Just centralizing the info here. No panic...

Headings and Bearings DCS script

Please Log in or Create an account to join the conversation.

Time to create page: 0.077 seconds