Lua解読分析集/Survivors Script

Last-modified: 2024-04-23 (火) 23:50:04

ユニット損失時に被救助ユニットを生成し,さらに救助ユニットを近くに移動させることで救助を行うイベントを生成するスクリプト

各関数は順不同.一部修正した部分がある.

目次

設定部分

local maxSuccessScore = 25
local maxFailureScore = -35
local successScore = 1 --amount to increase score if survivor picked up, per survivor
local failureScore = -3 --amount to decrease score if survivor lost, per survivor
local lostOverLandDBID = 2441 --must be facility
local lostOverSeaDBID = 2553  -- must be ship
local survivorSide = "Survivors" --side for survivors, can't be your own or over water they will pick themselves up - must exist
local maxPickupSpeed = 11
local maxPickupAltitude = 101
local crewSurvivalPercentage = 9 -- between 1 and 9, higher is more likely to survive
local survivorTimeToRescue = 35 -- amount of time in seconds rescuers must remain in the area to recover each survivor - multiplied by the number of survivors

maxSuccessScore = 25(加点の上限)
maxFailureScore = -35(減点の下限)
successScore = 1(救助イベント発生時の被救助ユニット人数一人あたり加点)
failureScore = -3(救助失敗イベント発生時の被救助ユニット人数一人あたり減点)
lostOverLandDBID = 2441(地上被救助ユニットのDBID)
lostOverSeaDBID = 2553(海上被救助ユニットのDBID)
survivorSide = "Survivors"(被救助ユニットが生成される陣営名)
maxPickupSpeed = 11(救助ユニットが救助を行える最大速力)
maxPickupAltitude = 101(救助ユニットが救助を行える最大高度m)
crewSurvivalPercentage = 9(1-9で高いほど被救助ユニットの生成に成功しやすく,人数が増加する)
survivorTimeToRescue = 35(被救助ユニット人数一人あたりの救助ユニットがエリア内に残存すべき秒数,人数に応じて増加)

サブ関数

split(s, sep)

sepで区切られた文字列sを分割し,各部分をfieldsとして返す

例:s=ABC,DEF,GHI sep=,とする(sepは指定しなければ半角スペース).
string.formatにより(%sは文字列を表す書式文字列),string.gsubで使用されるパターン([^,]+)ができる.
string.gsubでs内のパターン一致部分,すなわちABC DEF GHIを引数としてfunction(c)を呼び出し,テーブルfieldsに各部分を格納していく.

パターン([^,]+)の各要素について解説すると:

(…) = キャプチャ.カッコ内に一致する部分を引数としてfunction(c)を呼び出す

[^,] = カッコ内の文字に一致しない(^記号があるため)部分,すなわち,以外の文字列

+ = 直前の文字によって繰り返されるできるだけ長い文字列,ここでは[^,]の繰り返し,つまり,により区切られるまでの文字列

fields = { [1] = 'ABC', [2] = ' DEF', [3] = ' GHI' }となる

function split(s, sep)
    local fields = {}
    local sep = sep or " "
    local pattern = string.format("([^%s]+)", sep)
    string.gsub(s, pattern, function(c) fields[#fields + 1] = c end)
    return fields
end

AddSARTargetGUID(pilotKey)

KeyValue"CONST_SAR_TARGET_GUID"としてpilotKey(被救助ユニットのGUID)を格納していく(GUID1,GUID2,GUID3…という形式になる)

function AddSARTargetGUID(pilotKey)
    local pilotString = ScenEdit_GetKeyValue("CONST_SAR_TARGET_GUID")
    if pilotString == nil then
        pilotString = pilotKey
    else
        pilotString = pilotString..","..pilotKey
    end
    ScenEdit_SetKeyValue("CONST_SAR_TARGET_GUID",pilotString)
end

GetSARTargetsGUID()

KeyValue"CONST_SAR_TARGET_GUID"に対して関数splitを実行し,被救助ユニットGUIDのテーブルを取得する

function GetSARTargetsGUID()
    local pilotString = ScenEdit_GetKeyValue("CONST_SAR_TARGET_GUID")
    if pilotString == nil then
        pilotString = ""
    end
    return split(pilotString,",")
end

SARTargetGUIDExists(guid)

GetSARTargetsGUIDで取得したtable内にguidが含まれていればtrue,なければfalseを返す

function SARTargetGUIDExists(guid)
    local table = GetSARTargetsGUID()
    for k, v in pairs(table) do
        if guid == v then
            return true
        end
    end
    return false
end

RemoveSARTargetGUID(guid)

被救助ユニットGUIDのテーブルから指定guidを除く.すなわち指定guidでないGUID値をpilotStringとして順番につなげていき,KeyValueとして再設定する

function RemoveSARTargetGUID(guid) --もとスクリプトでは(pilotKey)となっているがこれでは機能しない
    local table = GetSARTargetsGUID()
    local pilotString = nil
    for k, v in pairs(table) do
        if guid ~= v then
            if pilotString then
                pilotString = pilotString..","..v
            else
                pilotString = v
            end
        end
    end
    ScenEdit_SetKeyValue("CONST_SAR_TARGET_GUID",pilotString)
end

GetTargetGUIDCloseToSAR(sarUnit)

救助ユニットがどの被救助ユニット周囲RPエリア内にいるかを判定し被救助ユニットGUIDを返す

function GetTargetGUIDCloseToSAR(sarUnit)
    local pilotsTable = GetSARTargetsGUID()
    for i,v in pairs(pilotsTable) do
        -- Check In Area
        if sarUnit:inArea({v.."-1",v.."-2",v.."-3",v.."-4"}) then
            return v
        end
    end
    return ""
end

timeFromNowDotNetTime(addSeconds)

UNIX時間により表現される現在のシナリオ時間+addSecond秒数をTimeイベントトリガーで使用できる数値「(0001-01-01 12:00:00からの経過秒数)*10000000」に変換する
参考:Event Triggers and time - what kind of time is it using?

function timeFromNowDotNetTime(addSeconds)
    local time = ScenEdit_CurrentTime()
    local offSet = 62135596801 --number of seconds from 01-01-0001 to 01-01-1970
    local newTime = (time + offSet + addSeconds)*10000000
    local timeToUse = string.format("%18.0f",newTime)
    return timeToUse
end

AddScoreToSide(side,score,reason)

function AddScoreToSide(side,score,reason)
    local currentScore = ScenEdit_GetScore(side)
    currentScore = currentScore + score
    ScenEdit_SetScore(side,currentScore,reason)
end

LongKeyValue関連

救助失敗イベントで失敗イベントGUIDと被救助ユニットGUIDをそれぞれkey, valueとして保存する関数なのだがこんな回りくどいことせずにイベントGUIDはScenEdit_EventX(),ユニットGUIDはScenEdit_UnitX().guidでいいのでは?

SetLongKeyValuePairs(key,value)

KeyValue"CONST_SAR_TARGET_GUID"にkey|vaueで表される文字列を格納する

function SetLongKeyValuePairs(key,value)
    -- Local Values
    local keyValueString = ScenEdit_GetKeyValue("CONST_LONG_KEY_VALUE")

    -- Check Key Value
    if keyValueString == ”” then --訂正済
        keyValueString = key.."|"..value --訂正済
    else
        keyValueString = keyValueString..","..key.."|"..value
    end

    -- Adding To Key Value
    ScenEdit_SetKeyValue("CONST_LONG_KEY_VALUE",keyValueString)
end

GetLongKeyValuePairs(key)

KeyValue"CONST_SAR_TARGET_GUID"内のkey|vaue形式である部分のうち,keyを含む個所のvalueを返す

例:keyValueString = ABC,DEF,GHI,JKL|MNOとする
split(keyValueString,",")によってtable = {[1] = ABC, [2] = DEF, [3] = GHI, [4] = JKL|MNO}に分割される
table内の各値bに対してsplit(b,"|")を行うと分割されず要素が一つだけとなる場合(subTable = {[1] = ABC})と分割され要素が二つある場合(subTable = {[1] = JKL [2] = MNO})が生じる

要素が二つあるときにsubTable[1] = keyであることを確認し,subTable[2] = valueとして返す

function GetLongKeyValuePairs(key)
    -- Local Values
    local keyValueString = ScenEdit_GetKeyValue("CONST_LONG_KEY_VALUE")

    -- Check Key Value
    if keyValueString == nil then
        return ""
    end

    -- Split
    local table = split(keyValueString,",")
    for a, b in pairs(table) do
        -- Split Some More
        local subTable = split(b,"|")
        if #subTable == 2 then
            if subTable[1] == key then
                return subTable[2]
            end
        end
    end
end

RemoveLongKeyValuePairs(key)

function RemoveLongKeyValuePairs(key)
    -- Local Values
    local keyValueString = ScenEdit_GetKeyValue("CONST_LONG_KEY_VALUE")
    local newKeyValueString = ""

    -- Check Key Value
    if keyValueString == nil then
        return ""
    end

    -- Split
    local table = split(keyValueString,",")
    for a, b in pairs(table) do
        -- Split Some More
        local subTable = split(b,"|")
        if #subTable == 2 then
            if subTable[1] ~= key then
                if newKeyValueString ~= "" then
                    newKeyValueString = newKeyValueString..","..b
                else
                    newKeyValueString = b
                end
            end
        end
    end

    -- Save To Key Value
    ScenEdit_SetKeyValue("CONST_LONG_KEY_VALUE",newKeyValueString)
end

OOB取得

--------------------------------------------------------------------------------------------------------------------------------
-- michaelm75au's OOB script http://www.matrixgames.com/forums/tm.asp?m=4233608
-- slightly modified to display subtype, used to get subtype of units to set individual crew counts
-- run GetOOBWithSubType() in the lua console
--------------------------------------------------------------------------------------------------------------------------------

function GetOOBWithSubType()
    local s = VP_GetSide({name=ScenEdit_PlayerSide()})
    local function split(str, pat)
        local t = {}
        local fpat = "(.-)" .. pat
        local last_end = 1
        local s, e, cap = str:find(fpat, 1)
        while s do
            if s ~= 1 or cap ~= "" then
                table.insert(t,cap)
            end
            last_end = e+1
            s, e, cap = str:find(fpat, last_end)
        end
        if last_end <= #str then
        cap = str:sub(last_end)
        table.insert(t, cap)
    end
    return t
end
local function sortName(a,b)
    return(ScenEdit_GetUnit({guid=a}).name<ScenEdit_GetUnit({guid=b}).name)
end
local function orderedPairs(t,f)
    local array = {}
    for n in pairs(t) do array[#array +1] = n end
    table.sort(array,f)
    local index = 0
    return function ()
    index = index + 1
    return array[index],t[array[index]]
end
end

-- main logic
local base = {}
for k,v in pairs(s.units)
    do
    local unit = ScenEdit_GetUnit({guid=v.guid})
    if unit.base ~= nil then
        local b = unit.base
        if b.group ~= nil then
-- has a parent group; use it rather than the group members
if base[b.group.guid] == nil and b.group.guid ~= v.guid then
    base[b.group.guid] = v.guid
    elseif b.group.guid ~= v.guid then
        base[b.group.guid] = base[b.group.guid] .. ',' .. v.guid
    end
    elseif base[b.guid] == nil and b.guid ~= v.guid then
        base[b.guid] = v.guid
        elseif b.guid ~= v.guid then
            base[b.guid] = base[b.guid] .. ',' .. v.guid
        end
        elseif unit.group ~= nil then
            local b = unit.group
            if base[b.guid] == nil and b.guid ~= v.guid then
                base[b.guid] = v.guid
                elseif b.guid ~= v.guid then
                    base[b.guid] = base[b.guid] .. ',' .. v.guid
                end
            else
-- units not based somewhere
if base['xindependent'] == nil then
base['xindependent'] = v.guid
else
    base['xindependent'] = base['xindependent'] .. ',' .. v.guid
end
end
end
local k,v
for k,v in orderedPairs(base)
    do
    print('\n')
    if k == 'xindependent' then
    print('Un-based units');
else
    print('Base: ' .. ScenEdit_GetUnit({guid=k}).name);
end
local k1,v1
local t = split(v,',')
if t ~= nil then
-- group like names together
table.sort(t, sortName)
for k1,v1 in pairs(t)
    do
    if v1 == k then next(t) end
    local unit = ScenEdit_GetUnit({guid=v1})
    if unit.condition ~= nil then
          print(string.format(" %s %s (%s)",unit.name, unit.classname, unit.subtype));
    else
        print(string.format(" %s ",unit.name, unit.classname, unit.subtype));
    end
end
end
end
end

メイン関数

CreateDownedPilotFromTriggerUnit(triggerUnit,passengers)

被救助ユニットを生成し,救助イベント"Event - Start SAR Target Pickup"にトリガーを追加する
救助失敗イベント"Event - Cancel Pilote(被救助ユニットGUID)"を生成する

triggerUnit = 破壊ユニットのGUID
passengers = 被救助ユニットの「人数」(救助所要時間等に影響)

長いので各部分に分けて解説する

関数の実行中止判定

以下の条件に一致するなら関数の実行中止(被救助ユニットおよび救助イベントを生成しない)

  • triggerUnitのGUIDが存在しない場合
  • SARTargetGUIDExistsがTrueを返す場合(すでにCONST_SAR_TARGET_GUID内に存在)
  • triggerUnitユニットタイプがAircraftでユニットの高度-現在位置の高度が5m以下で着陸中とみなされる場合
  • triggerUnitサブタイプが8201 (UAV)あるいは8202 (UCAV)である場合
  • (triggerUnitユニットタイプがShipあるいはSubmarineで)コンディションがDocked(基地ユニットに収容中)の場合
  • 1-10のランダム値didAnyoneSurviveがcrewSurvivalPercentageを上回る場合
function CreateDownedPilotFromTriggerUnit(triggerUnit,passengers)

     if triggerUnit and not SARTargetGUIDExists(triggerUnit.guid) then
        print("------attempting to create survivors-----")
        print("Subtype: "..triggerUnit.subtype)
        print("unit.condition: "..triggerUnit.condition)
        local worldElevation = World_GetElevation({latitude= triggerUnit.latitude, longitude=triggerUnit.longitude})
        if triggerUnit.type == "Aircraft" and (triggerUnit.altitude - worldElevation) < 5 then --check f AC is on the ground
            return
        end
        if triggerUnit.subtype == '8201' or triggerUnit.subtype == '8202' then --check if it is uav, if so quit, may be more subtypes for uav that need to be added here
            return
        end
       if triggerUnit.condition == 'Docked' then --ship is not at sea, no survivors
		return
	   end

       math.randomseed(os.time())
        --are there survivors?
        local didAnyoneSurvive = math.random(1,10)
            if didAnyoneSurvive > crewSurvivalPercentage then--they did not survive, exit
                  print("no Survivors, percent chance did not work out " ..didAnyoneSurvive)
                  return
                   end

被救助ユニット生成

triggerUnitから0.001nm斜め方向(被救助ユニットが爆風効果により破壊されるのを避けるためらしい)の地形標高を確認し,標高-1m以下の海上ならShipユニットlostOverSeaDBIDを,-1m以上の地上ならFacilityユニットlostOverLandDBIDを生成する

        -- Add Unit, check if over water or land
        local elevation = World_GetElevation({latitude= triggerUnit.latitude+ 0.001, longitude=triggerUnit.longitude+ 0.001}) --survivor will be offset slightly to avoid blast damage
        local unitLostDBID = lostOverSeaDBID --default is lost over sea
        local unitType = "Ship"
        if elevation > -1 then
        	unitLostDBID = lostOverLandDBID
        	unitType = "Facility"
        end

numberWhoSurvived = 被救助ユニットの人数とtimeToRescue = 被救助ユニットの救助所要秒数決定
passengersの指定がなければ1
passengersが1以上の場合passengers * (didAnyoneSurvive/10)の小数点切り捨て
timeToRescue = numberWhoSurvived * survivorTimeToRescue
(timeToRescueMinutesはメッセージ用に使用)

        local numberWhoSurvived = 1
        local timeToRescue = survivorTimeToRescue
        local timeToRescueMinutes =  math.ceil((numberWhoSurvived * survivorTimeToRescue)/ 60)
        if passengers then
            if passengers == 0 then --if 0 is passed in as the crew count then quit
                return
            end
            print("Passengers: " ..passengers)
            numberWhoSurvived = math.floor(passengers * (didAnyoneSurvive/10))
            if numberWhoSurvived < 1 then
                numberWhoSurvived = 1
            end
            print("Survivors "..numberWhoSurvived)
            timeToRescue  = numberWhoSurvived * survivorTimeToRescue
            print("Time needed to rescue: "..timeToRescue)
            timeToRescueMinutes = math.ceil(timeToRescue/ 60)
         end
            print(unitType.." "..numberWhoSurvived.." Survivor(s) of "..triggerUnit.name.." dbid: "..unitLostDBID)

「(人数) Survivor(s) of (損失ユニット名)」の名称で被救助ユニットを生成しさらに周囲0.02nmに被救助ユニットGUIDの名称でRPを4点生成する

        local downedPilot = ScenEdit_AddUnit({type=unitType, name =numberWhoSurvived.." Survivor(s) of "..triggerUnit.name, side = survivorSide, DBID = unitLostDBID, Latitude=triggerUnit.latitude  + 0.001, Longitude=triggerUnit.longitude + 0.001})
        print("guid of survivor unit: "..downedPilot.guid)
        -- Set Attributes
        downedPilot.manualSpeed  = 0

        -- Check Downed Pilot Is Created
        if downedPilot then
            -- Create Reference Points Box
            local referencePointOne = ScenEdit_AddReferencePoint( {side = survivorSide, name = downedPilot.guid.."-1",lat = triggerUnit.latitude - 0.02, lon = triggerUnit.longitude - 0.02, clear=true})
            local referencePointTwo = ScenEdit_AddReferencePoint( {side = survivorSide, name = downedPilot.guid.."-2",lat = triggerUnit.latitude + 0.02, lon = triggerUnit.longitude - 0.02, clear=true})
            local referencePointThree = ScenEdit_AddReferencePoint( {side = survivorSide, name = downedPilot.guid.."-3",lat = triggerUnit.latitude + 0.02, lon = triggerUnit.longitude + 0.02, clear=true})
            local referencePointFour = ScenEdit_AddReferencePoint( {side = survivorSide, name = downedPilot.guid.."-4",lat = triggerUnit.latitude - 0.02, lon = triggerUnit.longitude + 0.02, clear=true})

救助イベント設定

救助ユニットが被救助ユニットの周囲エリアに残存している場合のUnitRemainInAreaイベントトリガーをAir,Ship,Sub,Facility (Ground)ユニットタイプごとに生成し,既存の救助イベント"Event - Start SAR Target Pickup"のトリガーに追加する

さらにAddSARTargetGUIDを実行しKeyValue"CONST_SAR_TARGET_GUID"に被救助ユニットのGUIDを格納する

            -- create triggers, probably could do it with one trigger for any type of unit but targettype =0 doesn't work
            -- Create Trigger With Reference Points for Aircraft
            local addedTrigger = ScenEdit_SetTrigger({mode="add",type='UnitRemainsInArea',name="air-"..downedPilot.guid, targetfilter={TargetType = '1' , TargetSide=triggerUnit.side},area={referencePointOne.name,referencePointTwo.name,referencePointThree.name,referencePointFour.name},TD=timeToRescue})

            -- Create Trigger With Reference Points for Ship
            local addedTrigger = ScenEdit_SetTrigger({mode="add",type='UnitRemainsInArea',name="ship-"..downedPilot.guid, targetfilter={TargetType = '2' , TargetSide=triggerUnit.side},area={referencePointOne.name,referencePointTwo.name,referencePointThree.name,referencePointFour.name},TD=timeToRescue})

            -- Create Trigger With Reference Points for Subs
            local addedTrigger = ScenEdit_SetTrigger({mode="add",type='UnitRemainsInArea',name="sub-"..downedPilot.guid, targetfilter={TargetType = '3' , TargetSide=triggerUnit.side},area={referencePointOne.name,referencePointTwo.name,referencePointThree.name,referencePointFour.name},TD=timeToRescue})

             -- Create Trigger With Reference Points for Ground Units
            local addedTrigger = ScenEdit_SetTrigger({mode="add",type='UnitRemainsInArea',name="ground-"..downedPilot.guid,
            targetfilter={TargetType = '4' , TargetSide=triggerUnit.side},area={referencePointOne.name,referencePointTwo.name,referencePointThree.name,referencePointFour.name},TD=timeToRescue})

            -- Add GUID
            AddSARTargetGUID(downedPilot.guid)

            -- Set Trigger To SAR Mission
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="add", name="air-"..downedPilot.guid})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="add", name="ship-"..downedPilot.guid})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="add", name="sub-"..downedPilot.guid})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="add", name="ground-"..downedPilot.guid})

救助失敗イベント生成

Event - Cancel Pilot(被救助ユニットGUID)という名称のイベントを生成する
timeToLiveを1800-108000秒(30分-30時間)として設定(1回目の判定で50000以上の場合もう一度判定)する

イベントトリガー:現在のシナリオ時間にtimeToLiveを加えたTimeトリガー
イベントアクション:StartSARFailedTargetPickup()を実行する

救助説明メッセージに表示されるtimeToLiveMessage
36000秒(10時間)超の場合 = good condition
7200-36000秒の間 = fair condition
7200秒(2時間)未満の場合 = poor condition

            -- Create Event For Destruction
            ScenEdit_SetEvent("Event - Cancel Pilot"..downedPilot.guid, {mode="add",IsRepeatable=0})
            local cancelEvent = ScenEdit_GetEvent("Event - Cancel Pilot"..downedPilot.guid)
            SetLongKeyValuePairs(cancelEvent.guid,downedPilot.guid)

            local timeToLive =  math.random(1800,108000) --time to live in seconds
                if  timeToLive > 50000 then --if it is over 50k then try it again, just trying to give greater chance of it being lower
                     timeToLive =  math.random(1800,108000)
                 end
            local timeToLiveMessage = "Surviving crew members are in fair condition, likely to survive for several hours."
                if timeToLive < 7200 then
                    timeToLiveMessage = "Surviving crew members are in poor condition, immediate evacuation required!"
                elseif timeToLive > 36000 then
                    timeToLiveMessage = "Surviving crew members are in good condition, likely to survive for at least 10 hours."
                end
            print("Time they will survive in seconds: "..timeToLive)
            local randInterval = timeFromNowDotNetTime(timeToLive)
            -- Add Create Trigger
            local addedTrigger = ScenEdit_SetTrigger({mode="add", type="Time", name="Trigger - Cancel Pilot"..downedPilot.guid, Time= randInterval})

            -- Add Create Action
            ScenEdit_SetAction({mode="add", type="LuaScript", name="Action - Cancel Pilot"..downedPilot.guid, scriptText="StartSARFailedTargetPickup(" ..ScenEdit_EventX().guid.. ")"}) --一部修正
--ScenEdit_EventX()最後に発生したイベントをトリガーしたユニットGUIDを引数に関数を実行するので,イベントの発生具合によりべつの被救助ユニットに対して実行してしまう可能性がある...ScenEdit_EventX().guid..として被救助ユニットGUIDを指定すべきである

            -- Set Triggers And Actions
            ScenEdit_SetEventTrigger("Event - Cancel Pilot"..downedPilot.guid, {mode="add", name="Trigger - Cancel Pilot"..downedPilot.guid})
            ScenEdit_SetEventAction("Event - Cancel Pilot"..downedPilot.guid, {mode="add", name="Action - Cancel Pilot"..downedPilot.guid})

ユニット損失時の救助説明メッセージ

			-- Message Pilot Ejected
            ScenEdit_SpecialMessage(ScenEdit_PlayerSide(),triggerUnit.name.." has been destroyed but there are survivors!<br><br>Number of Survivors: "..numberWhoSurvived.."<br><br>"..timeToLiveMessage..
                "<br><br>In order to rescue them you will need to move a unit (sub, ship, AC or ground unit) to their location and remain on site for "..timeToRescueMinutes.." minutes, at an altitude of less than "..maxPickupAltitude.." feet and a speed of less that " ..maxPickupSpeed.." kts. Submarines will need to be on the surface in order to perform a rescue.")
        print("------end create survivors-----")
		end
    end
end

StartSARTargetPickup(triggerUnit)

救助の判定と実施

救助ユニットtriggerUnitの高度から地形高度を差し引いた対地高度altitudeAGLを計算する

function StartSARTargetPickup(triggerUnit)
    local elevation = World_GetElevation({latitude= triggerUnit.latitude, longitude=triggerUnit.longitude})
    if elevation < 0 then
        elevation = 0
        end
    local altitudeAGL = triggerUnit.altitude - elevation

triggerUnitの速力がmaxPickupSpeed未満であり,かつaltitudeAGLがmaxPickupAltitude未満であるときに救助実施

    if triggerUnit and triggerUnit.speed < maxPickupSpeed and altitudeAGL < maxPickupAltitude then
    --print(maxPickupAltitude)
    -- print("triggerunit alt: " ..triggerUnit.altitude)

Unit.areaTriggersFiredで救助ユニットが既にトリガーしたEnterInAreaトリガーのGUID一覧を返すのだがRemainInAreaトリガーでは使えないし他にtriggeredGUIDを使っている箇所もないので無視して良いと思われる

        -- Get Triggered Areas
        local triggeredAreas = triggerUnit.areaTriggersFired
        local triggeredGUID = ""

        -- Get Trigger GUID
        for k, v in pairs(triggeredAreas) do
            triggeredGUID = v
        end

GetTargetGUIDCloseToSAR(triggerUnit)により被救助ユニットをunitとしてプロパティ取得

        -- Find Pilot
        local keyGUID = GetTargetGUIDCloseToSAR(triggerUnit)
        local unit = ScenEdit_GetUnit({guid=keyGUID})

unitが存在する(破壊されていない)なら処理実行
被救助ユニットのユニット名から人数部分sを探して得点totalSuccessScore = successScore * s()を計算し加点する(上限maxSuccessScore)
救助完了のメッセージ表示

        -- Scoring
        if unit then
            -- Add Score
            local s = string.gmatch(unit.name, "[^ ]+") -- get first part of name which is the number of survivors
            local totalSuccessScore = successScore *  s()  --calculate total score
            print("Total calculated score for " ..unit.name..": " ..totalSuccessScore)
                if  totalSuccessScore > maxSuccessScore then  totalSuccessScore = maxSuccessScore end -- check to see if score is outside max limits
            AddScoreToSide(ScenEdit_PlayerSide(),totalSuccessScore ,"Pilot Saved- "..unit.name.." safely on board of "..triggerUnit.name)
            print("Total score used (max/min checked): " ..totalSuccessScore)
            -- Message Pilot Saved
            ScenEdit_SpecialMessage(ScenEdit_PlayerSide (),unit.name.." safely on board of "..triggerUnit.name..".")

被救助ユニット,"Event - Start SAR Target Pickup"イベントの関連トリガー,救助失敗イベントを削除する
KeyValue"CONST_SAR_TARGET_GUID"から被救助ユニットのGUIDを削除する
被救助ユニットの周辺RPを削除する

            -- Remove Pilot Unit
            ScenEdit_DeleteUnit({side=triggerUnit.side, guid=keyGUID})

            -- Remove All Triggers From Events
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="air-"..keyGUID})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="ship-"..keyGUID})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="sub-"..keyGUID})
            ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="ground-"..keyGUID})
            ScenEdit_SetEventTrigger("Event - Cancel Pilot"..keyGUID, {mode="remove", name="Trigger - Cancel Pilot"..keyGUID})

            -- Remove All Actions From Events
            ScenEdit_SetEventAction("Event - Cancel Pilot"..keyGUID, {mode="remove", name="Action - Cancel Pilot"..keyGUID})

            -- Remove Actual Trigger
            ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="air-"..keyGUID})
            ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="ship-"..keyGUID})
            ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="sub-"..keyGUID})
            ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="ground-"..keyGUID})
            ScenEdit_SetTrigger({mode="remove",type="RegularTime",name="Trigger - Cancel Pilot"..keyGUID})

            -- Remove Actual Action
            ScenEdit_SetAction({mode="remove", name="Action - Cancel Pilot"..keyGUID})

            -- Remove Actual Event
             ScenEdit_SetEvent("Event - Cancel Pilot"..keyGUID, {mode="remove"})

            -- Remove GUID
            RemoveSARTargetGUID(keyGUID)

            -- Remove All Reference Points
            ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-1"})
            ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-2"})
            ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-3"})
            ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-4"})
        end
    end
end

StartSARFailedTargetPickup(triggerEvent)

救助失敗イベントEvent - Cancel Pilot(被救助ユニットGUID)のアクション.
基本的にStartSARTargetPickup(triggerUnit)の逆.得点を減点しいろいろ削除する.

得点減点

function StartSARFailedTargetPickup(triggerEvent)
    -- Triggered Id
    local keyGUID = GetLongKeyValuePairs(triggerEvent.guid)
    local unit = ScenEdit_GetUnit({guid=keyGUID})

    -- Scoring
    if unit then
        -- Add Score
        local s = string.gmatch(unit.name, "[^ ]+") -- get first part of name which is the number of survivors
        local totalSuccessScore = failureScore *  s()  --calculate total score
        print("Total calculated score for " ..unit.name..": " ..totalSuccessScore)
        if  totalSuccessScore < maxFailureScore then  totalSuccessScore = maxFailureScore end
         print("Total score used (max/min checked): " ..totalSuccessScore)
        AddScoreToSide(ScenEdit_PlayerSide(),totalSuccessScore,"Survivor Lost-"..unit.name)
        -- Remove Pilot Unit
        ScenEdit_DeleteUnit({side=survivorSide , guid=keyGUID})
        -- Message Lost Pilot
        ScenEdit_SpecialMessage(ScenEdit_PlayerSide (),"Sorry, we lost contact with "..unit.name)
    end

"Event - Start SAR Target Pickup"イベントの関連トリガー,救助失敗イベントを削除する
KeyValue"CONST_SAR_TARGET_GUID"から被救助ユニットのGUIDを削除する
被救助ユニットの周辺RPを削除する

    -- Remove All Triggers From Events
    ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="air-"..keyGUID})
    ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="ship-"..keyGUID})
    ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="sub-"..keyGUID})
    ScenEdit_SetEventTrigger("Event - Start SAR Target Pickup", {mode="remove", name="ground-"..keyGUID})
    ScenEdit_SetEventTrigger("Event - Cancel Pilot"..keyGUID, {mode="remove", name="Trigger - Cancel Pilot"..keyGUID})

    -- Remove All Actions From Events
    ScenEdit_SetEventAction("Event - Cancel Pilot"..keyGUID, {mode="remove", name="Action - Cancel Pilot"..keyGUID})

    -- Remove Actual Trigger
    ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="air-"..keyGUID})
    ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="ship-"..keyGUID})
    ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="sub-"..keyGUID})
    ScenEdit_SetTrigger({mode="remove",type="UnitRemainsInArea",name="ground-"..keyGUID})
    ScenEdit_SetTrigger({mode="remove",type="RegularTime",name="Trigger - Cancel Pilot"..keyGUID})

    -- Remove Actual Action
    ScenEdit_SetAction({mode="remove", name="Action - Cancel Pilot"..keyGUID})

    -- Remove Actual Event --
    ScenEdit_SetEvent("Event - Cancel Pilot"..keyGUID, {mode="remove"})

    -- Remove GUID
    RemoveSARTargetGUID(keyGUID)
    RemoveLongKeyValuePairs(triggerEvent.guid)

    -- Remove All Reference Points
    ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-1"})
    ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-2"})
    ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-3"})
    ScenEdit_DeleteReferencePoint({side=survivorSide,name=keyGUID.."-4"})
end

}}