local PARSE_WAVE_DEBUG_MODE = true -- TODO: validate WaitForAllSpawned & WaitForAllDead as well local VALID_SUBWAVE_KEYS = { Name = true, Where = true, WaitBeforeStarting = true, WaitBetweenSpawns = true, WaitBetweenSpawnsAfterDeath = true, WaitForAllSpawned = true, WaitForAllDead = true, TotalCount = true, SpawnCount = true, MaxActive = true, TotalCurrency = true, IsSquad = true, Templates = true, RandomChoice = true, RandomChoiceTemplateSets = true, SupportInfinite = true, SupportLimited = true, IsMission = true, MissionNoHideIcon = true, SendSpyAnnouncement = true, SendSniperAnnouncement = true, SpawnIndividualTemplate = true, PreAllocatedTemplates = true, _DefaultTemplates = true, Parsed = true, } function ValidateSubwave(subwaveData, waveData) local ok = true local subwaveName = subwaveData.Name if not subwaveName then util.PrintToChatAll(subwaveName, "Subwave has no name") ok = false end if not subwaveData.RandomChoice then if subwaveData.Templates == nil or #subwaveData.Templates <= 0 then util.PrintToChatAll(subwaveName, "Missing or empty Templates. Ensure that template name is valid") ok = false end end do local expectedLength = #subwaveData.Templates local trueOccupiedLength = 0 for _ in pairs(subwaveData.Templates) do trueOccupiedLength = trueOccupiedLength + 1 end if trueOccupiedLength < expectedLength then util.PrintToChatAll(subwaveName, "Contains nil in Templates, there may be a misspelled template index") ok = false end end if subwaveData.Where == nil then util.PrintToChatAll(subwaveName, "Missing Where") ok = false end if subwaveData.SpawnCount == nil then util.PrintToChatAll(subwaveName, "Missing SpawnCount") ok = false end if subwaveData.SpawnCount > 22 then util.PrintToChatAll(subwaveName, "Warning: spawn count surpasses 22") end if subwaveData.MaxActive == nil then util.PrintToChatAll(subwaveName, "Missing MaxActive") ok = false end if subwaveData.TotalCount == nil then util.PrintToChatAll( subwaveName, "Missing TotalCount (still required for SupportInfinite for currency distribution)" ) ok = false end if subwaveData.IsMission and not subwaveData.SupportInfinite then util.PrintToChatAll(subwaveName, "Contains IsMission but missing SupportInfinite") ok = false end if subwaveData.IsSquad then if subwaveData.SpawnCount % #subwaveData.Templates ~= 0 then util.PrintToChatAll( subwaveName, "Warning: Squad Templates cannot be distributed evenly across SpawnCount (" .. tostring(#subwaveData.Templates) .. "/" .. tostring(subwaveData.SpawnCount) .. ")" ) end end if subwaveData.SpawnCount > subwaveData.MaxActive then util.PrintToChatAll(subwaveName, "Has a higher SpawnCount than MaxActive") ok = false end if subwaveData.WaitForAllSpawned then local targetSubwave = subwaveData.WaitForAllSpawned local isTargetValid = false for _, otherSubwaveData in pairs(waveData) do if otherSubwaveData.Name == targetSubwave then isTargetValid = true break end end if not isTargetValid then util.PrintToChatAll(subwaveName, "WaitForAllSpawned targets invalid subwave " .. targetSubwave) ok = false end end if subwaveData.WaitForAllDead then local targetSubwave = subwaveData.WaitForAllDead local isTargetValid = false for _, otherSubwaveData in pairs(waveData) do if otherSubwaveData.Name == targetSubwave then isTargetValid = true break end end if not isTargetValid then util.PrintToChatAll(subwaveName, "WaitForAllDead targets invalid subwave " .. targetSubwave) ok = false end end if subwaveData.WaitBetweenSpawnsAfterDeath and subwaveData.WaitBetweenSpawns then util.PrintToChatAll(subwaveName, "Has both WaitBetweenSpawnsAfterDeath and WaitBetweenSpawns") end -- if subwaveData.WaitBetweenSpawns == nil then -- util.PrintToChatAll(subwaveName, "Missing WaitBetweenSpawns") -- ok = false -- end -- if subwaveData.WaitBeforeStarting == nil then -- util.PrintToChatAll(subwaveName, "Missing WaitBeforeStarting") -- ok = false -- end for key in pairs(subwaveData) do if not VALID_SUBWAVE_KEYS[key] then util.PrintToChatAll(subwaveName, string.format("Warning: Unknown subwave key '%s'", tostring(key))) end end return ok end function ParseWave(waveData, skipParsedSubwaves) if PARSE_WAVE_DEBUG_MODE then util.PrintToChatAll("[PARSE-WAVE]: PARSING WAVE") end local waveValid = true for _, subwaveData in pairs(waveData) do local canParse = true if skipParsedSubwaves and subwaveData.Parsed then canParse = false end if canParse then if not subwaveData.Templates then if subwaveData.RandomChoice or subwaveData.RandomChoiceTemplateSets then subwaveData.Templates = {} else util.PrintToChatAll("[PARSE-WAVE][ERROR]: no Templates defined for subwave " .. subwaveData.Name) end end if subwaveData._DefaultTemplates then subwaveData.Templates = DeepClone(subwaveData._DefaultTemplates) else subwaveData._DefaultTemplates = DeepClone(subwaveData.Templates) end if subwaveData.RandomChoiceTemplateSets then if PARSE_WAVE_DEBUG_MODE then util.PrintToChatAll("[PARSE-WAVE]: CHOOSING RandomChoiceTemplate") end local chosenTemplateSet = subwaveData.RandomChoiceTemplateSets[math.random(#subwaveData.RandomChoiceTemplateSets)] for _, templateData in pairs(chosenTemplateSet) do table.insert(subwaveData.Templates, DeepClone(templateData)) if PARSE_WAVE_DEBUG_MODE then util.PrintToChatAll( "[PARSE-WAVE]: CLONING TEMPLATE " .. tostring(templateData.Name or templateData.Class) ) end end elseif subwaveData.RandomChoice then local preAllocatedTemplates = {} for i = 1, subwaveData.TotalCount do local chosenTemplate = subwaveData.RandomChoice[math.random(#subwaveData.RandomChoice)] preAllocatedTemplates[i] = chosenTemplate end subwaveData.PreAllocatedTemplates = preAllocatedTemplates end subwaveData.Parsed = true end if not ValidateSubwave(subwaveData, waveData) then waveValid = false end end if waveValid then if PARSE_WAVE_DEBUG_MODE then util.PrintToChatAll("[PARSE-WAVE]: WAVE PARSED SUCCESSFULLY") end else util.PrintToChatAll("[PARSE-WAVE]: WAVE PARSING FAILED") end return waveData end