Jump to content

Recommended Posts

Posted

Hi, I've started getting in getting DCS ME and would like to use scripting within a mission that I am building. (I've got very little experience with coding or DCS ME, but keen to learn!)

I want an infantry unit to spawn from a specific vehicle that the player has destroyed.

I saw a suggestion on the DCS forums for something similar (spawning infantry from landing craft), so came up with the below code but it does not work. Grateful for suggestions on how to make it work, or perhaps an alternative approach?


-- vehicle_destroyed_test is the group name of the vehicle that the player destroys

-- escaper is the infantry unit that is supposed to escape the vehicle (set to late activation)

-- trigger has the condition UNIT DEAD (vehicle_destroyed_test)

-- DO SCRIPT Action using the below...

local vehicle01 = GROUP:FindByName("vehicle_destroyed_test")
local infantry01 = SPAWN:New("escaper")

escape_from_vehicle = infantry01:SpawnFromUnit(vehicle01)

Posted (edited)

First of all you have to load MOOSE, since you've not mentioned anywhere is worth to mention.

After that, you have to make sure of what code you have to use, since you're trying to retrieve information from a DEAD unit, that is not possible in DCS.
So you have to save the coordinate from dead event if available, and use that for spawn the infantry.

 

Edited by Maverick87Shaka

FlighRIG => CPU: RyZen 5900x | RAM: 64GB Corsair 3000Mhz | GPU: nVIDIA RTX 4090 FE | OS Storage: SSD NVMe Samsung 850 Pro 512GB, DCS Storage: SSD NVMe Sabrent 1TB | Device: Multipurpose-UFC, VirPil T-50, TM WARTHOG Throttle, TrackHat, MFD Cougar with screen.

Our Servers => [ITA] Banshee | Krasnodar - PvE | PersianConquest PvE Live Map&Stats | Syria Liberation PvE Conquest

Support us on twitch subscribing with amazon prime account linked, it's free!

Posted

Thanks @Maverick87Shaka, MOOSE is loaded at the start of the mission (and MIST), and I didn't realise that once a unit is dead, information can't be retrieved. How would I save a coordinate from a dead event? Is that using MOOSE?

Posted
5 minutes ago, srhZSOC said:

Thanks @Maverick87Shaka, MOOSE is loaded at the start of the mission (and MIST), and I didn't realise that once a unit is dead, information can't be retrieved. How would I save a coordinate from a dead event? Is that using MOOSE?

Yes, with moose you can subscribe for events and use it.

Dead event doesn't contain position, so you have to deal with it (welcome to the workaround zone!)

If it's not a fast moving vehicle that you have to track, you can create a scheduler that check and update position every 10 seconds for example, and after event dead retrieve that information updated from the scheduler, and spawn the infantry from there.
 

  • Thanks 1

FlighRIG => CPU: RyZen 5900x | RAM: 64GB Corsair 3000Mhz | GPU: nVIDIA RTX 4090 FE | OS Storage: SSD NVMe Samsung 850 Pro 512GB, DCS Storage: SSD NVMe Sabrent 1TB | Device: Multipurpose-UFC, VirPil T-50, TM WARTHOG Throttle, TrackHat, MFD Cougar with screen.

Our Servers => [ITA] Banshee | Krasnodar - PvE | PersianConquest PvE Live Map&Stats | Syria Liberation PvE Conquest

Support us on twitch subscribing with amazon prime account linked, it's free!

Posted (edited)

I'm rather new to mist/MOOSE scripting for DCS, but this was one of the first things I wanted to use it for too
There's surely a much better/cleaner method of doing this, but it was fun to figure out, seems to work well enough, and it's been a nice addition for my missions...
(this uses a mist scheduler, I've been meaning to convert this to 100% moose functions... but BG3 came out :P) 

load mist & moose. No need to add infantry templates in the ME, uses vehicle type & coalition/country to determine troop-types; 

(this includes spawning wwii troops from wwii units, & some insurgent mods I've picked up somewhere for other vehicle types....) 
 

-- script to spawn crew from destroyed/disabled ground vehicles, populate Bodies.on.Battlefield (BoB)
env.info("GROUND CREW LOADING...")

local survivalRate = 75 -- (of 100), aka 3/4ths survival rate

-- min & max radus from vehicle
local spawnRadiusMin = 1
local spawnRadiusMax = 8

-- match crew number to vehicle
local crewManifest = {
    ["BTR-80"] = { crew = 3 },          --
    ["BTR-82A"] = { crew = 3 },          --
    ["AAV7"] = { crew = 3 },          --
    ["BMP-1"] = { crew = 3 },          --
    ["BMP-2"] = { crew = 3 },          --
    ["BMP-3"] = { crew = 3 },          --
    ["T-55"] = { crew = 4 },          --
    ["T-72B"] = { crew = 3 },          --
    ["T-72B3"] = { crew = 4 },          --
    ["T-80UD"] = { crew = 3 },          --
    ["T-90"] = { crew = 3 },          --
    ["SA-11 Buk LN 9A310M1"] = { crew = 2 },      --?
    ["SA-11 Buk CC 9S470M1"] = { crew = 3 },      --?
    ["SA-11 Buk SR 9S18M1"] = { crew = 3 },       --?
    ["M1126_Stryker"] = { crew = 2 },         --? For M1126 Stryker, the typical crew is 2, including the driver and commander.
    ["M1134 Stryker ATGM"] = { crew = 2 },       --
    ["M113"] = { crew = 2 },           -- For M113, the typical crew is 2, including the driver and commander.
    ["M-1 Abrams"] = { crew = 4 },         --?
    ["M2_Bradley"] = { crew = 3 },          --? For M2 Bradley, the typical crew is 3, including the driver, gunner, and commander.
 ["M-2 Bradley"] = { crew = 3 },         --? For M2 Bradley, the typical crew is 3, including the driver, gunner, and commander.
    ["M2A2_ODS_Bradley"] = { crew = 3 },       --?
    ["Marder"] = { crew = 3 },          --?
    ["Leopard-2"] = { crew = 4 },         --?
    ["Challenger2"] = { crew = 4 },         --?
    ["M-109"] = { crew = 5 },          --?
    ["2S19_Msta"] = { crew = 5 },         --?
    ["Kub 2P25 ln"] = { crew = 3 },         --
    ["M1043 HMMWV Armament"] = { crew = 2 },      --
    ["M1045 HMMWV TOW"] = { crew = 2 },        --
    ["M1126 Stryker ICV"] = { crew = 3 },       --
    ["BRDM-2"] = { crew = 2 },          --
    ["TPZ"] = { crew = 2 },              --
    ["MTLB"] = { crew = 4 },          --
    ["M-60"] = { crew = 4 },          --
    ["M-113"] = { crew = 4 },          --
    ["BTR_D"] = { crew = 4 },          --
    ["LAV-25"] = { crew = 4 },          --
 ["VAB_Mephisto"] = { crew = 4 },        --
 ["ZSU-23-4 Shilka"] = { crew = 3 },        --
 ["Ural-375"] = { crew = 4 },         --
 ["CH_TigrM"] = { crew = 4 },         -- CurrentHill Mods
 ["CH_OshkoshLATV_M2"] = { crew = 4 },       -- CurrentHill Mods
 ["CH_OshkoshMATV_M2"] = { crew = 4 },       -- CurrentHill Mods
 ["CH_OshkoshLATV_MK19"] = { crew = 4 },       -- CurrentHill Mods
 ["CH_OshkoshMATV_MK19"] = { crew = 4 },       -- CurrentHill Mods
 ["Cobra"] = { crew = 4 },          -- CurrentHill Mods
    ["HPG_Toyota_ISIS"] = { crew = 2, isInsurgent = true },   -- Insurgent vehicles should spawn insurgents
    ["HPG_Ural_Isis_Troops"] = { crew = 4, isInsurgent = true},  --
    ["HPG_Ural_Isis_Covered"] = { crew = 7, isInsurgent = true}, --
    ["HPGToyotaISISDShK"] = { crew = 2, isInsurgent = true },  --
    ["HPGUralIsisFlak"] = { crew = 2, isInsurgent = true },   --
    ["HPGUralIsisZU23"] = { crew = 2, isInsurgent = true },   --
    ["ERO_Toyota_White"] = { crew = 2, isInsurgent = true },  --
 ["ERO_TOYOTA_Desert"] = { crew = 2, isInsurgent = true },  --
 ["ERO_Toyota_Camo"] = { crew = 2, isInsurgent = true },   --
 ["ERO_Toyota_Clown"] = { crew = 2, isInsurgent = true },  --
 ["ERO_ZU23_Toyota_armored"] = { crew = 2, isInsurgent = true }, --
    ["tt_DSHK"] = { crew = 1, isInsurgent = true },     --
    ["tt_KORD"] = { crew = 1, isInsurgent = true },     --
    ["HL_DSHK"] = { crew = 1, isInsurgent = true },     --
    ["HL_KORD"] = { crew = 1, isInsurgent = true },     --
    ["Centaur_IV"] = { crew = 5, WWII = true },       -- WWII allies --
    ["Cromwell_IV"] = { crew = 5, WWII = true },      --
    ["Churchill_VII"] = { crew = 5, WWII = true },     --
    ["M4_Sherman"] = { crew = 5, WWII = true },      --
    ["M4A4_Sherman_FF"] = { crew = 5, WWII = true },    --
    ["Tetrarch"] = { crew = 2, WWII = true },      --
    ["M2A1_halftrack"] = { crew = 2, WWII = true },     --
    ["M4_Tractor"] = { crew = 2, WWII = true },      --
    ["M10_GMC"] = { crew = 5, WWII = true },      --
    ["SPH_M109_Paladin_155mm"] = { crew = 5, WWII = true },   --?
    ["M8_Greyhound"] = { crew = 2, WWII = true },     --
    ["Truck_Bedford"] = { crew = 2, WWII = true },     --?
 ["Bedford_MWD"] = { crew = 2, WWII = true },      --
    ["Car_Willys_Jeep"] = { crew = 1, WWII = true },    --?
    ["Truck_GMC_Jimmy_6x6"] = { crew = 2, WWII = true },   --?
    ["Tiger_II_H"] = { crew = 5, WWII = true },       -- WWII axis --
    ["Tiger_I"] = { crew = 5, WWII = true },      --
    ["Pz_IV_H"] = { crew = 5, WWII = true },      --
    ["Pz_V_Panther_G"] = { crew = 5, WWII = true },     --
    ["Stug_IV"] = { crew = 4, WWII = true },      --
    ["Stug_III"] = { crew = 4, WWII = true },      --
    ["JagdPz_IV"] = { crew = 4, WWII = true },      --
    ["Jagdpanther_G1"] = { crew = 4, WWII = true },     --
    ["Elefant_SdKfz_184"] = { crew = 6, WWII = true },     -- The Elefant had a crew of 6, including the driver, radio operator, commander, gunner, and two loaders.
    ["SPG_Brummbaer_AG"] = { crew = 5, WWII = true },    --?
    ["Sd_Kfz_234_2_Puma"] = { crew = 4, WWII = true },    -- The Puma had a crew of 4, including the driver, radio operator, commander, and gunner.
 ["Sd_Kfz_251"] = { crew = 4, WWII = true },      -- The Puma had a crew of 4, including the driver, radio operator, commander, and gunner.
    ["APC_Sd.Kfz.251_Halftrack"] = { crew = 2, WWII = true },  --? For the Sd.Kfz.251 Halftrack, the typical crew is 2, including the driver and commander.
    ["SturmPzIV"] = { crew = 2, WWII = true },      --
    ["Daimler_AC"] = { crew = 1, WWII = true },      --
 --["Bedford_MWD"] = { crew = 2, WWII = true },     --
}

-- Modern soldier types
local BlueSoldiers = {
 "Soldier M4",  --repitition = odds 1/10 for stinger / rpg
 "Soldier M4",
 "Soldier M4",
 "Soldier M4",
 "Soldier M4",
 "Soldier M4",
 "Soldier M4",
 "Soldier M4",
 "Soldier M249",
 "Soldier stinger",
}

local RedSoldiers = {
 "Infantry AK",
 --"Infantry AK ver1", causes "unknown unit" error?
 "Infantry AK ver2",
 "Infantry AK ver3",
 "Infantry AK",
 "Infantry AK ver2",
 "Infantry AK ver3",
 "Infantry AK",
 "Infantry AK ver2",
 "Infantry AK ver3",
 --"Soldier RPG",
}

-- for WWII, we'll make use of specific soldiers by name as well as randomized
local USsoldier = "soldier_wwii_us"
local UKsoldier = "soldier_wwii_br_01"
local GermanSoldier = "soldier_mauser98"

local WWII_BlueSoldiers = {
 USsoldier,
 UKsoldier,
}

local WWII_RedSoldiers = {
 GermanSoldier,
}

local Insurgents = {
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "InsurgentMod",
 "Soldier RPG",
 --"Insurgent AK-74",
}

local targetBailPercentage = 50 -- at what health percentage does the crew bail? (must be monitoring S_EVENT_HIT) -- DEPRECATED

local spawnedGroups = {} --track units that have spawned crew

local debugFlag = USERFLAG:New( "debug" ) --flag set in mission editor?
local debugFlagValue = debugFlag:Get()
--BASE:TraceAll(true)
--BASE:TraceOnOff( true )
--BASE:TraceLevel( 3 )

-- define template data for crew
local function SoldierTemplate (groupName, groupType)   --bare minimum template data; populate name & type here
 local unitTemplate = {
  ["name"] = groupName,
  ["units"] = {
   [1] = {
    ["skill"] = "Average",
    ["coldAtStart"] = false,
    ["type"] = groupType,
    ["playerCanDrive"] = false,
   }, -- end of [1]
  }, -- end of ["units"]
 }
 return unitTemplate
end

-- Define the vehicle destruction event handler
function onGroundVehicleDamaged(event)
    --if event.id == world.event.S_EVENT_HIT then
 if event.id == world.event.S_EVENT_BDA then

  local survivalCoinFlip = math.random(1, 100)

  if survivalCoinFlip <= survivalRate then

          if event.initiator ~= nil and event.target ~= nil then
    -- Get details on participants to the event
    local InitiatorUnit = event.initiator:getName()
    local InitiatorType = event.initiator:getTypeName()
    local InitiatorCoal = event.initiator:getCoalition()

    local TargetName = event.target:getName()
    local TargetType = event.target:getTypeName()
    local TargetCat =  event.target:getDesc().category
    local TargetCoal = event.target:getCoalition() or 3
    local TargetPos = event.target:getPosition().p
    local TargetCountry = event.target:getCountry()

    if debugFlagValue == 1 then
     MESSAGE:New("DEBUG EVENT: " .. InitiatorUnit .. " type(" .. InitiatorType .. ") -> " .. TargetName .. " type(" .. TargetType .. ")(" .. TargetCat .. ") TargetCoal: " .. TargetCoal, 10,"Ground Crew"):ToAll()
    end

    if TargetCat == 2 then -- if ground targets ...

     if crewManifest[TargetType] then -- if unit included on crewManifest, returns true
      local targetHealth = event.target:getLife()

      local targetMaxHealth = event.target:getLife0()
      local targetHealthPercentage = targetHealth / targetMaxHealth * 100

      -- When unit is injured beyond certain point, crew bails
      --if targetHealthPercentage < targetBailPercentage then

       --track spawnedGroups so no dupes
      local groupKey = TargetName .. "_" .. TargetType

      if not spawnedGroups[groupKey] then
       spawnedGroups[groupKey] = true

       if debugFlagValue == 1 then
        MESSAGE:New(TargetName .. "'s (" .. TargetType .. ") health is below 10% = " .. targetHealthPercentage .. "% at " .. TargetPos.x .. " x " .. TargetPos.z, 10,"Ground Crew"):ToAll()
       end

       --define crew compliment according to manifest, randomize crewAlive
       local crewMax = crewManifest[TargetType].crew or 2 -- Default to 2 if TargetType not found (should be crewmax)
       local crewAlive = math.random(1, crewMax)
       local crewCount = 0

       for i = 1, crewAlive do -- for each member of the crew...
        crewCount = crewCount + 1
        -- Define the randomized radius around the damaged vehicle where infantry will be spawned
        local radius = math.random(spawnRadiusMin, spawnRadiusMax)
        local heading = math.random(0, 360) -- Randomize the heading of the infantry units
        local offsetX = radius * math.cos(math.rad(heading + (i * 360 / crewAlive)))
        local offsetY = radius * math.sin(math.rad(heading + (i * 360 / crewAlive)))
        local spawnPosition = {
         x = TargetPos.x,
         y = TargetPos.z, -- CRITICAL mis-match -- y-to-z here makes correct placement??
         z = land.getHeight({ x = TargetPos.x, y = TargetPos.y }) -- Get the ground altitude at the target's x, y position
        }
        -- Add the offsets to the spawn position
        spawnPosition.x = spawnPosition.x + offsetX
        spawnPosition.y = spawnPosition.y + offsetY

        -- get them to run away from vehicle by routing to a further WP
           local waypointDistance = math.random(50, 300)
           local waypointHeading = math.random(0, 360)
           local waypointPosition = {
               x = spawnPosition.x + waypointDistance * math.cos(math.rad(heading)),
               y = spawnPosition.y + waypointDistance * math.sin(math.rad(heading)),
               z = land.getHeight({ x = spawnPosition.x, y = spawnPosition.y })
           }

        --random selection from the list of coalition groups
        local initCoal = nil
        local initSide = nil
        local RandomUnit = nil
        -- select solider type on some conditions...
        if TargetCoal == 1 then
         if crewManifest[TargetType].WWII == true then
          --RandomUnit = WWII_RedSoldiers[math.random(1, #WWII_RedSoldiers)]
          RandomUnit = GermanSoldier
         else
          RandomUnit = RedSoldiers[math.random(1, #RedSoldiers)] -- move to puremoose no ME
         end
         initSide = coalition.side.RED

        elseif TargetCoal == 2 then
         if crewManifest[TargetType].WWII == true then
          if TargetCountry == country.id.UK then
           RandomUnit = UKsoldier
          elseif TargetCountry == country.id.USA then
           RandomUnit = USsoldier
          else
           RandomUnit = WWII_BlueSoldiers[math.random(1, #WWII_BlueSoldiers)]
          end
         else
          RandomUnit = BlueSoldiers[math.random(1, #BlueSoldiers)] -- see if you can replace the previous method
         end
         initSide = coalition.side.BLUE
        end

        -- insurgents could be from anywhere/anytime
        if crewManifest[TargetType].isInsurgent == true then
         RandomUnit = Insurgents[math.random(1, #Insurgents)]
        end

        local RandomN = math.random(1,1000000)
        local newGroupName = RandomUnit .. "_" .. TargetName .. "-" .. i
        local Template = SoldierTemplate(newGroupName, RandomUnit) --populate customized template
        local newAlias = "Soldier-" .. RandomN      -- generic name, can be same alias among soldiers
        local initCoal = TargetCountry         --units should inherit the vehicle country
        local initCat = Group.Category.GROUND      -- must be set on init
        local heading = math.random(1, 360)     -- random heading for everyone
        local walkSpeed = 10          -- WP travel speed

        -- spawn from modified template rather than require placed unit
        local soldier = SPAWN:NewFromTemplate(Template, newGroupName, newAlias)
         :InitCountry(initCoal)
         :InitCoalition(initSide)
         :InitCategory(initCat)
         :InitHeading(heading)
         :InitLimit(1, 1)  --TEST: (maxunits, maxgroups to spawn)
         :InitDelayOn()   --TEST
         --:InitPositionVec2(spawnPosition) --TEST
         :OnSpawnGroup(
          function(grp)
           if debugFlagValue == 1 then
            MESSAGE:New(initSide .. " Spawned: "..grp:GetName(),15,"Ground Crew"):ToAll()
           end
           grp:RouteToVec2(waypointPosition, walkSpeed)  --get them to run away
          end
         )
         :SpawnScheduled(5, 0.5) --TEST
         :SpawnFromVec2(spawnPosition)

         --soldier:SpawnScheduleStop() --TEST

        if debugFlagValue == 1 then
         MESSAGE:New(" ... SPAWN from '" .. TargetType .. "' (" .. RandomUnit .. ") " .. crewCount .. " of " .. crewMax .. " crew at " .. spawnPosition.x .. " x " .. spawnPosition.y , 10,"Ground Crew"):ToAll()
        end
       end -- end crew foreach
      end
     else
      -- log VechicleTypes we don't have included on the CrewManifest, but ignore soldier types
      local isBlueSoldier = false
      local isRedSoldier = false
      local isWWIIBlueSoldier = false
      local isWWIIRedSoldier = false
      local isInsurgent = false

      for _, unitType in ipairs(RedSoldiers) do
       if unitType == TargetType then
        isRedSoldier = true
        break
       end
      end
      for _, unitType in ipairs(BlueSoldiers) do
       if unitType == TargetType then
        isBlueSoldier = true
        break
       end
      end
      for _, unitType in ipairs(WWII_RedSoldiers) do
       if unitType == TargetType then
        isWWIIRedSoldier = true
        break
       end
      end
      for _, unitType in ipairs(WWII_BlueSoldiers) do
       if unitType == TargetType then
        isWWIIBlueSoldier = true
        break
        end
       end
      for _, unitType in ipairs(Insurgents) do
       if unitType == TargetType then
        isInsurgent = true
        break
       end
      end

      if not (isRedSoldier or isBlueSoldier or isWWIIRedSoldier or isWWIIBlueSoldier or isInsurgent) then
       --if debugFlagValue == 1 then
       MESSAGE:New("ADD MISSING VEHICLE in script :----> No crewManifest for TargetType '" .. TargetType .. "' ", 15,"Ground Crew"):ToAll()
       --end
       env.info("GROUND CREW NOTICE: ADD MISSING VECHILE ----> No crewManifest for TargetType: " .. TargetType .. " ")
      end
      --end --if targetHealthPercentage
     end
    end
   end
  end --coinflip
 end
end

-- Register the event handler for the unit damage event
mist.addEventHandler(onGroundVehicleDamaged)
--local eventHandler = EVENTHANDLER:New()
--eventHandler:OnEvent(onGroundVehicleDamaged)

--sendMessageToAll("Ground Vehicle Crews LOADED", 10)
MESSAGE:New("Ground Vehicle Crews LOADED", 10,"Ground Crew"):ToAll()

env.info("GROUND CREW LOADED.")

 

 

Spawn_Vehicle_Crew_on_Destruction.lua

Edited by MegaTherion666
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...