Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77f4c41a6b | ||
|
|
07a234489f | ||
|
|
e363b3fe94 | ||
|
|
b68f95b748 | ||
|
|
8341a5fb6d | ||
|
|
e32518f48d | ||
|
|
2e7a930473 |
@@ -169,7 +169,7 @@ class Sidebar extends HTMLElement {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
var betaHtml = '';
|
var betaHtml = '';
|
||||||
if (true || window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
if (window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
||||||
betaHtml = '<note-box type="warning" title="Beta Version">You are looking at docs that are released with the beta version.</note-box>';
|
betaHtml = '<note-box type="warning" title="Beta Version">You are looking at docs that are released with the beta version.</note-box>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,39 +26,115 @@
|
|||||||
|
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<h1>Advanced Tutorial: Missions</h1>
|
<h1>Advanced Tutorial: Missions</h1>
|
||||||
<h2 id="strike">Strike</h2>
|
<div id="strike-region">
|
||||||
<p>
|
<h2 id="strike">Strike</h2>
|
||||||
Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br>
|
<p>
|
||||||
</p>
|
Naming: <code-inline>MISSION_STRIKE_[Name]</code-inline> <br>
|
||||||
<h3 id="specific_targets">Specific Targets</h3>
|
</p>
|
||||||
<p>TBD</p>
|
<h3 id="specific_targets">Specific Targets</h3>
|
||||||
|
<p>TBD</p>
|
||||||
|
|
||||||
|
<h3 id="scenery_targets">Scenery Targets</h3>
|
||||||
|
<p>
|
||||||
|
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
|
||||||
|
We wanted to make sure they were easily integrated in Spearhead.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="scenery_targets">Scenery Targets</h3>
|
<note-box type="info" title="Implementation details">
|
||||||
<p>
|
Spearhead detects scenery targets by the trigger zone name. A zone named
|
||||||
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
|
<strong>scenerytarget_[freeform]</strong> or
|
||||||
We wanted to make sure they were easily integrated in Spearhead.
|
<strong>scenerytargets</strong> (case-insensitive) will be scanned and any scenery objects that
|
||||||
</p>
|
has the attribute "Buildings" inside the zone
|
||||||
|
will be added as mission scenery targets.
|
||||||
|
</note-box>
|
||||||
|
|
||||||
<note-box type="info" title="Implementation details">
|
<p>
|
||||||
Spearhead detects scenery targets by the trigger zone name. A zone named <strong>scenerytarget_[freeform]</strong> or
|
Scenery targets are treated like mission targets: they are included in the mission completion
|
||||||
<strong>scenerytargets</strong> (case-insensitive) will be scanned and any scenery objects that has the attribute "Buildings" inside the zone
|
calculation
|
||||||
will be added as mission scenery targets.
|
(their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or
|
||||||
</note-box>
|
resume.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<note-box type="warning" title="Changing IDs">
|
||||||
Scenery targets are treated like mission targets: they are included in the mission completion calculation
|
Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality
|
||||||
(their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or resume.
|
does not work for scenery targets.
|
||||||
</p>
|
Hence the need to use trigger zones to define them.
|
||||||
|
|
||||||
<note-box type="warning" title="Changing IDs">
|
|
||||||
Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality does not work for scenery targets.
|
|
||||||
Hence the need to use trigger zones to define them.
|
|
||||||
</note-box>
|
</note-box>
|
||||||
|
|
||||||
|
|
||||||
<p>Here's two images showing how a bridge is added to a mission.</p>
|
<p>Here's two images showing how a bridge is added to a mission.</p>
|
||||||
<img src="/img/bridge.png" style="max-height: 35remrem;"/>
|
<img src="/img/bridge.png" style="max-height: 35remrem;" />
|
||||||
|
</div>
|
||||||
|
<div id="cas-region">
|
||||||
|
<h2 id="cas">CAS</h2>
|
||||||
|
<p>
|
||||||
|
Naming: <code-inline>MISSION_CAS_[Name]</code-inline> <br>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="BattleManager">Battle Manager</h3>
|
||||||
|
<p>TBD</p>
|
||||||
|
</div>
|
||||||
|
<div id="dead-region">
|
||||||
|
<h2 id="dead">DEAD</h2>
|
||||||
|
<p>
|
||||||
|
Naming: <code-inline>MISSION_DEAD_[Name]</code-inline> <br>
|
||||||
|
Naming: <code-inline>MISSION_SAM_[Name]</code-inline> <br>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="sam-vs-dead">SAM vs DEAD</h3>
|
||||||
|
<p>TBD</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="bai-region">
|
||||||
|
<h2 id="bai">BAI</h2>
|
||||||
|
<p>
|
||||||
|
Naming: <code-inline>MISSION_BAI_[Name]</code-inline> <br>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="deepstrike-region">
|
||||||
|
<h2 id="deepstrike">DEEPSTRIKE</h2>
|
||||||
|
<p>
|
||||||
|
Naming: <code-inline>MISSION_DEEPSTRIKE_[Name]</code-inline> <br>
|
||||||
|
<br>
|
||||||
|
When you, as a mission editor, want to create a mission that's further away from the current front-line you can use the Deep Strike mission type. <br>
|
||||||
|
This allows you to plan missions that require more strategic positioning and timing. <br>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="activation">Activation</h3>
|
||||||
|
<p>
|
||||||
|
Deep Strike missions are activated when the Stage in which they are located becomes "PreActive" or "Active". <br>
|
||||||
|
"PreActive" is when either the current active StageNumber is a certain number of stages away OR the stage has "CAP" airbases active . <br>
|
||||||
|
<code-inline>SpearheadConfig.StageConfig.preactivateStage</code-inline> changes the configuration. <br>
|
||||||
|
<br>
|
||||||
|
For example: <br>
|
||||||
|
If the current active stage is <code-inline>MissionStage_2_[name]</code-inline> and preActivate config is set to 2. <br>
|
||||||
|
Then both <code-inline>MissionStage_3_[name]</code-inline> and <code-inline>MissionStage_4_[name]</code-inline> would become "PreActive".
|
||||||
|
</p>
|
||||||
|
<h3 id="primary-vs-secondary">Make Primary</h3>
|
||||||
|
<p>
|
||||||
|
By default DEEPSTRIKE missions are "Secondary" missions when spawned as a pre-activated stage.<br>
|
||||||
|
Then when the stage they are in is "Active", the mission becomes a "Primary" mission. <br>
|
||||||
|
<br>
|
||||||
|
If you want to make it a "Primary" mission from the start, you can overwrite it.<br>
|
||||||
|
Click the mission's trigger zone. Add a property named <code-inline>primary</code-inline> and set it to <code-inline>true</code-inline>.
|
||||||
|
This will make the mission "Primary" from the start. <br>
|
||||||
|
<br>
|
||||||
|
If you want it to "Secondary" even when its stage is the active stage, you can set "primary" to false. <br>
|
||||||
|
<br>
|
||||||
|
If you want to have it be "Secondary" when its stage is "Pre-Active" and "primary" when its stage is "Active" you don't have to do anything.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="future-additions">Future</h3>
|
||||||
|
<p>
|
||||||
|
In the future we're thinking it would be cool to make the Deep Strike missions
|
||||||
|
be more integrated with the CAP airbases and/or logistics. <br>
|
||||||
|
Eg. Completing a DEEPSTRIKE mission would disable CAP for X amount of minutes after completion. <br>
|
||||||
|
This still needs to be refined, but we've already have ideas.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
--color-bg-hover: rgba(120, 140, 255, 0.12); /* More visible hover */
|
--color-bg-hover: rgba(120, 140, 255, 0.12); /* More visible hover */
|
||||||
--color-bg-note-dark: rgba(40, 35, 30, 0.85); /* Slightly darker note box */
|
--color-bg-note-dark: rgba(40, 35, 30, 0.85); /* Slightly darker note box */
|
||||||
|
|
||||||
--color-text-primary: #a5a5a5; /* Brighter text */
|
--color-text-primary: #b4b3b3; /* Brighter text */
|
||||||
--color-text-secondary: #bfc8d8; /* Lighter secondary text */
|
--color-text-secondary: #bfc8d8; /* Lighter secondary text */
|
||||||
--color-text-accent: #7ecbff; /* Brighter accent */
|
--color-text-accent: #7ecbff; /* Brighter accent */
|
||||||
--color-text-light: #ffffff;
|
--color-text-light: #ffffff;
|
||||||
|
|||||||
@@ -1,53 +1,43 @@
|
|||||||
# Spearhead
|
# Spearhead
|
||||||
|
|
||||||
|
Hello and welcome to Spearhead!
|
||||||
|
|
||||||
## Contributing.
|
If you're a developer that wants to contribute, look at the code or understand what we're doing, feel free to read on.
|
||||||
|
|
||||||
I'm always happy to see contributions! <br/>
|
If you're a mission maker that wants to see the documentation and build you mission with this framework. <br>
|
||||||
Especially if you've found an issue, annoyance or feature that you know how to solve, fix or create! <br/>
|
It's best to go to our fully fledged documentation website:
|
||||||
|
- Stable/Main: https://spearhead.rocks
|
||||||
|
- Beta/Develop: https://beta.spearhead.rocks
|
||||||
|
|
||||||
### Keep it small.
|
## Project Structure
|
||||||
|
|
||||||
Keeping your contributions small and to the point helps both me and yourself. <br/>
|
The Spearhead project is structured in a lot of separate files. <br>
|
||||||
It'll help the PR review and the speed of improvements. <br/>
|
While Lua isn't specifically created for it, most of it has been written with the standards of OOP in mind. <br>
|
||||||
If you have a big feature in mind? Go for it! <br/>
|
Classes, Objects and helper methods.
|
||||||
Does it require an entire refactor of parts or all of the program? Maybe make sure to do step 0 first.
|
|
||||||
|
|
||||||
### Steps (for first timers)
|
You're find in the `/src` folder all the files. <br>
|
||||||
0. Reach out (Optional)
|
They are separated in a somewhat logical order, but some things might feel out of place. <br>
|
||||||
|
|
||||||
If you want to let me know you want to do something to contribute, please do! <br/>
|
### Bundling, Intellisense, Linting
|
||||||
Maybe I'm already working on the thing you wanted to build, or someone else is. <br/>
|
|
||||||
Creating an issue is even better! <br/>
|
|
||||||
|
|
||||||
|
In DCS the easiest way to import a script is with 1 single file, however, that's not as "maintainable".
|
||||||
|
In order to keep it maintainable we're using a self-built tool to bundle, validate and rewrite some of the lua in order to get it into a single file.
|
||||||
|
The tool is open-source here: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools. <br>
|
||||||
|
It has a `VSCode` extensions and two `Github Action` steps. <br>
|
||||||
|
If your favorite IDE isn't `VSCode` (I respect that), it might be very easy to create an extension for it, if it does allow that.
|
||||||
|
|
||||||
1. Fork the repository
|
The `VSCode` extensions comes with Intellisense as well, in the form of a full file of DCS lua type annotations. <br>
|
||||||
|
This gives the Lua Language Server by Sumneko (which can be used in `VSCode`) all the type definitions it needs.
|
||||||
|
When writing Spearhead code it is also important to keep our own LuaLS Annotations up to date and complete. <br>
|
||||||
|
Read all about those annotations here: https://luals.github.io/wiki/annotations/
|
||||||
|
|
||||||
By forking you can create your own working set of code. <br/>
|
When a pull-request to the `develop` or `main` branches is created, before it can be merged it requires to pass the linter checks.
|
||||||
Whether you keep that fork public or private is up to you! <br/>
|
The first linting check is done by the Lua Language Server. It checks for whitespace and formatting, but it also checks if all types, type-checking and casts are in order. It marks unused variables etc. `.luarc.json` has all the config for those checks. <br>
|
||||||
|
The second linter job is with `luacheck` which first "bundles" the script, and then runs a full linter check over the bundled script. <br>
|
||||||
|
This is to make sure that also the bundled script does not contain any errors.
|
||||||
|
|
||||||
Keep in mind, forking is alright, but it's best with the intent to contribute back. <br/>
|
## Contributing
|
||||||
After all, instead of having 5 slightly different versions and products, it might be nicer to have 1 much better version. <br/>
|
|
||||||
|
|
||||||
2. Create a Draft PR as soon as possible!
|
### Setting up the project
|
||||||
|
|
||||||
As soon as you've found some times to create an initial version, please create a draft PR. <br/>
|
If you've kept on reading I assume you either want to brwose
|
||||||
That way you can let me and everyone know it's being worked on and people can see what conflicts might arise with their own changes. <br/>
|
|
||||||
|
|
||||||
3. Test, test, test
|
|
||||||
|
|
||||||
With DCS and Lua there's a bunch of edge cases that are really hard to get to. <br/>
|
|
||||||
However, you kinda need to make sure most if not all cases are caught and tested. <br/>
|
|
||||||
Since automated testing for now doesn't seem feasible, please make sure to verify and test functionality after touching stuff. <br/>
|
|
||||||
|
|
||||||
4. Finalise and publish the PR.
|
|
||||||
|
|
||||||
Finalise the PR and let the maintainers know! <br/>
|
|
||||||
We can all have a look and discuss the changes. <br/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
|
|
||||||
- Would it be possible to generate optional markers on mission briefing locations for Tomcat / Phantom navigation? Then Jester can type it in for the pilots automatically.
|
|
||||||
+10
-8
@@ -5,19 +5,21 @@
|
|||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Issue: #41
|
- Addresses #41
|
||||||
Adds Stage Complete debug methods for local testing of the Stage flow.
|
Adds Stage Complete debug methods for local testing of the Stage flow.
|
||||||
#40
|
PR #40
|
||||||
|
- Closes #35
|
||||||
- Issue: #35
|
|
||||||
Creating Lane option for stages.
|
Creating Lane option for stages.
|
||||||
Additionally to the primary stage lane, stages can now be created in different lanes.
|
Additionally to the primary stage lane, stages can now be created in different lanes.
|
||||||
These lanes can be used to create different stage progression flows and create different "side-stories".
|
These lanes can be used to create different stage progression flows and create different "side-stories".
|
||||||
#40
|
PR #40
|
||||||
|
- Closes #37
|
||||||
- Issue: #37
|
|
||||||
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
|
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
|
||||||
#44
|
PR #44
|
||||||
|
- Closes #42
|
||||||
|
DEEPSTRIKE now added as a possible feature.
|
||||||
|
This enables to have missions active in "Pre-Activated" Stages.
|
||||||
|
PR #48
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if Util.startswith(namePart, "%[") == true then
|
if Util.startsWith(namePart, "%[") == true then
|
||||||
namePart = Util.split_string(namePart, "[")[1]
|
namePart = Util.split_string(namePart, "[")[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ GlobalFleetManager.start = function(database)
|
|||||||
|
|
||||||
local all_groups = MizGroupsManager.getAllGroupNames()
|
local all_groups = MizGroupsManager.getAllGroupNames()
|
||||||
for _, groupName in pairs(all_groups) do
|
for _, groupName in pairs(all_groups) do
|
||||||
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
if Util.startsWith(string.lower(groupName), "carriergroup" ) == true then
|
||||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||||
local carrierGroup = FleetGroup.new(groupName, database, logger)
|
local carrierGroup = FleetGroup.new(groupName, database, logger)
|
||||||
table.insert(fleetGroups, carrierGroup)
|
table.insert(fleetGroups, carrierGroup)
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ do
|
|||||||
for file in lfs.dir(dir) do
|
for file in lfs.dir(dir) do
|
||||||
|
|
||||||
local split = Util.split_string(file, ".")
|
local split = Util.split_string(file, ".")
|
||||||
local doesStartWith = Util.startswith(file, startsWith, true)
|
local doesStartWith = Util.startsWith(file, startsWith, true)
|
||||||
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
||||||
local numberString = split[#split-1]
|
local numberString = split[#split-1]
|
||||||
local number = tonumber(numberString)
|
local number = tonumber(numberString)
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ local StageDrawing = require("classes.stageClasses.drawings.StageDrawing")
|
|||||||
---@field descriptionLocation Vec2?
|
---@field descriptionLocation Vec2?
|
||||||
---@field dependsOn Array<string>
|
---@field dependsOn Array<string>
|
||||||
---@field completeAt number?
|
---@field completeAt number?
|
||||||
|
---@field primaryOverwrite boolean?
|
||||||
|
|
||||||
---@class FarpZoneData
|
---@class FarpZoneData
|
||||||
---@field groups Array<string>
|
---@field groups Array<string>
|
||||||
@@ -211,7 +212,7 @@ function Database.New(Logger)
|
|||||||
for _, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for _, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
|
if Util.startsWith(string.lower(layer_object.name), "buildable", true) == true then
|
||||||
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
||||||
if airbaseData then
|
if airbaseData then
|
||||||
self._logger:debug("found airbase data for " .. layer_object.name)
|
self._logger:debug("found airbase data for " .. layer_object.name)
|
||||||
@@ -234,7 +235,7 @@ function Database.New(Logger)
|
|||||||
for _, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for _, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(layer_object.name, "drawing_", true) then
|
if Util.startsWith(layer_object.name, "drawing_", true) then
|
||||||
local object = layer_object --[[@as DrawingObject]]
|
local object = layer_object --[[@as DrawingObject]]
|
||||||
local stageDrawing = StageDrawing.New(object)
|
local stageDrawing = StageDrawing.New(object)
|
||||||
if stageDrawing then
|
if stageDrawing then
|
||||||
@@ -262,7 +263,7 @@ function Database.New(Logger)
|
|||||||
for _, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for _, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
if Util.startsWith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||||
local zone = DcsUtil.getZoneByName(stageZoneName)
|
local zone = DcsUtil.getZoneByName(stageZoneName)
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if zone and Util.is2dPointInZone(vec2, zone) == true then
|
if zone and Util.is2dPointInZone(vec2, zone) == true then
|
||||||
@@ -491,7 +492,7 @@ end
|
|||||||
local getAvailableCAPGroups = function()
|
local getAvailableCAPGroups = function()
|
||||||
local result = {}
|
local result = {}
|
||||||
for name, value in pairs(is_group_taken) do
|
for name, value in pairs(is_group_taken) do
|
||||||
if value == false and Util.startswith(name, "CAP") then
|
if value == false and Util.startsWith(name, "CAP") then
|
||||||
table.insert(result, name)
|
table.insert(result, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -594,11 +595,11 @@ function Database:loadCapUnits()
|
|||||||
for _, groupName in pairs(groups) do
|
for _, groupName in pairs(groups) do
|
||||||
is_group_taken[groupName] = true
|
is_group_taken[groupName] = true
|
||||||
|
|
||||||
if Util.startswith(groupName, "CAP_A", true) or Util.startswith(groupName, "CAP_B", true) then
|
if Util.startsWith(groupName, "CAP_A", true) or Util.startsWith(groupName, "CAP_B", true) then
|
||||||
table.insert(baseData.CapGroups, groupName)
|
table.insert(baseData.CapGroups, groupName)
|
||||||
elseif Util.startswith(groupName, "CAP_I", true) then
|
elseif Util.startsWith(groupName, "CAP_I", true) then
|
||||||
table.insert(baseData.InterceptGroups, groupName)
|
table.insert(baseData.InterceptGroups, groupName)
|
||||||
elseif Util.startswith(groupName, "CAP_S", true) then
|
elseif Util.startsWith(groupName, "CAP_S", true) then
|
||||||
table.insert(baseData.SweepGroups, groupName)
|
table.insert(baseData.SweepGroups, groupName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -621,7 +622,7 @@ function Database:loadBlueSamUnits()
|
|||||||
local triggerZone = DcsUtil.getZoneByName(blueSamZone)
|
local triggerZone = DcsUtil.getZoneByName(blueSamZone)
|
||||||
if triggerZone then
|
if triggerZone then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
if kvPair.key and Util.startswith(kvPair.key, "buildable") then
|
if kvPair.key and Util.startsWith(kvPair.key, "buildable") then
|
||||||
local number = tonumber(kvPair.value)
|
local number = tonumber(kvPair.value)
|
||||||
if number and number > 0 then
|
if number and number > 0 then
|
||||||
samData.buildingKilos = number
|
samData.buildingKilos = number
|
||||||
@@ -633,7 +634,7 @@ function Database:loadBlueSamUnits()
|
|||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
|
if layer_object.name and Util.startsWith(layer_object.name, "supplybriefing_", true) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
layer_object = layer_object --[[@as TextBox]]
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
@@ -710,9 +711,9 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
if triggerZone and triggerZone.properties then
|
if triggerZone and triggerZone.properties then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
local key = kvPair.key
|
local key = kvPair.key
|
||||||
if Util.startswith(key, "dependson", true) == true then
|
if Util.startsWith(key, "dependson", true) == true then
|
||||||
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
|
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
|
||||||
elseif Util.startswith(key, "completeat") == true then
|
elseif Util.startsWith(key, "completeat") == true then
|
||||||
local value = tonumber(kvPair.value)
|
local value = tonumber(kvPair.value)
|
||||||
if value then
|
if value then
|
||||||
if value > 1 and value <= 100 then
|
if value > 1 and value <= 100 then
|
||||||
@@ -722,6 +723,14 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
end
|
end
|
||||||
self._tables.MissionZoneData[missionZoneName].completeAt = value
|
self._tables.MissionZoneData[missionZoneName].completeAt = value
|
||||||
end
|
end
|
||||||
|
elseif Util.startsWith(key, "primary", true) == true then
|
||||||
|
if type(kvPair.value) == "string" then
|
||||||
|
if kvPair.value == "true" then
|
||||||
|
self._tables.MissionZoneData[missionZoneName].primaryOverwrite = true
|
||||||
|
elseif kvPair.value == "false" then
|
||||||
|
self._tables.MissionZoneData[missionZoneName].primaryOverwrite = false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -734,7 +743,7 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
if layer_object.name and Util.startswith(layer_object.name, "briefing_", true) then
|
if layer_object.name and Util.startsWith(layer_object.name, "briefing_", true) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
layer_object = layer_object --[[@as TextBox]]
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
@@ -778,7 +787,7 @@ function Database:loadFarpData()
|
|||||||
local triggerZone = DcsUtil.getZoneByName(farpZone)
|
local triggerZone = DcsUtil.getZoneByName(farpZone)
|
||||||
if triggerZone then
|
if triggerZone then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
if kvPair.key and Util.startswith(kvPair.key, "buildable", true) == true then
|
if kvPair.key and Util.startsWith(kvPair.key, "buildable", true) == true then
|
||||||
local number = tonumber(kvPair.value)
|
local number = tonumber(kvPair.value)
|
||||||
if number and number > 0 then
|
if number and number > 0 then
|
||||||
farpzoneData.buildingKilos = number
|
farpzoneData.buildingKilos = number
|
||||||
@@ -792,7 +801,7 @@ function Database:loadFarpData()
|
|||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
layer_object = layer_object --[[@as TextBox]]
|
||||||
if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
|
if layer_object.name and Util.startsWith(layer_object.name, "supplybriefing_", true) then
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
farpzoneData.briefing = description
|
farpzoneData.briefing = description
|
||||||
|
|||||||
@@ -435,6 +435,12 @@ function Stage:PreActivate()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for _, mission in pairs(self._db.missions) do
|
||||||
|
if mission and mission.missionType == "DEEPSTRIKE" then
|
||||||
|
mission:SpawnInactive() --Not Really "inactive"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, airbase in pairs(self._db.airbases) do
|
for _, airbase in pairs(self._db.airbases) do
|
||||||
airbase:ActivateRedStage()
|
airbase:ActivateRedStage()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ function MissionCommandsHelper:OverviewToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:getState() == "ACTIVE" and mission.priority == "primary" then
|
if mission and mission:getState() == "ACTIVE" and mission:GetPriority() == "primary" then
|
||||||
table.insert(primaryMissions, mission)
|
table.insert(primaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -230,7 +230,7 @@ function MissionCommandsHelper:OverviewToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:getState() == "ACTIVE" and mission.priority == "secondary" then
|
if mission and mission:getState() == "ACTIVE" and mission:GetPriority() == "secondary" then
|
||||||
table.insert(secondaryMissions, mission)
|
table.insert(secondaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -345,7 +345,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission.priority == "primary" then
|
if mission and mission:GetPriority() == "primary" then
|
||||||
table.insert(primaryMissions, mission)
|
table.insert(primaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -374,7 +374,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission.priority == "secondary" then
|
if mission and mission:GetPriority() == "secondary" then
|
||||||
table.insert(secondaryMissions, mission)
|
table.insert(secondaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -416,7 +416,7 @@ function MissionCommandsHelper:addMissionCommands(groupId, path, mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local missionFolderName = "[" ..
|
local missionFolderName = "[" ..
|
||||||
mission.code .. "]" .. distance .. mission.name .. "( " .. mission.missionTypeDisplay .. " )"
|
mission.code .. "]" .. distance .. mission.name .. "(" .. mission.missionTypeDisplay .. ")"
|
||||||
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
||||||
table.insert(path, missionFolderName)
|
table.insert(path, missionFolderName)
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ local SupplyConfigHelper = {}
|
|||||||
---@return SupplyConfig?
|
---@return SupplyConfig?
|
||||||
function SupplyConfigHelper.fromObjectName(name)
|
function SupplyConfigHelper.fromObjectName(name)
|
||||||
for configName, config in pairs(SupplyConfig) do
|
for configName, config in pairs(SupplyConfig) do
|
||||||
if Util.startswith(name, configName, true) == true then
|
if Util.startsWith(name, configName, true) == true then
|
||||||
return config
|
return config
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ function BuildableMission:CheckCratesInZone()
|
|||||||
|
|
||||||
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
||||||
for _, staticObject in pairs(crates) do
|
for _, staticObject in pairs(crates) do
|
||||||
if staticObject and staticObject:isExist() and Util.startswith(staticObject:getName(), self._crateType, true) then
|
if staticObject and staticObject:isExist() and Util.startsWith(staticObject:getName(), self._crateType, true) then
|
||||||
local pos = staticObject:getPoint()
|
local pos = staticObject:getPoint()
|
||||||
|
|
||||||
if Util.is3dPointInZone(pos, self._dropOffZone) then
|
if Util.is3dPointInZone(pos, self._dropOffZone) then
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ local DcsUtil = require("classes.util.DcsUtil")
|
|||||||
---@field private _completeAtIndex number
|
---@field private _completeAtIndex number
|
||||||
---@field private _parentStage Stage
|
---@field private _parentStage Stage
|
||||||
---@field private _battleManager? BattleManager
|
---@field private _battleManager? BattleManager
|
||||||
---@field private _lastContactMarkerID number;
|
---@field private _lastContactMarkerID number
|
||||||
local ZoneMission = {}
|
local ZoneMission = {}
|
||||||
|
|
||||||
--- @class MissionGroups
|
--- @class MissionGroups
|
||||||
@@ -24,7 +24,7 @@ local ZoneMission = {}
|
|||||||
--- @field unitsAlive table<string, table<string, boolean>>
|
--- @field unitsAlive table<string, table<string, boolean>>
|
||||||
--- @field targetsAlive table<string, table<string, boolean>>
|
--- @field targetsAlive table<string, table<string, boolean>>
|
||||||
--- @field sceneryTargets Array<SpearheadSceneryObject>
|
--- @field sceneryTargets Array<SpearheadSceneryObject>
|
||||||
--- @field groupNamesPerunit table<string,string>
|
--- @field groupNamesPerUnit table<string,string>
|
||||||
|
|
||||||
---@class ParsedMissionName
|
---@class ParsedMissionName
|
||||||
---@field missionName string
|
---@field missionName string
|
||||||
@@ -36,7 +36,7 @@ local ZoneMission = {}
|
|||||||
local function ParseZoneName(input)
|
local function ParseZoneName(input)
|
||||||
local split_name = Util.split_string(input, "_")
|
local split_name = Util.split_string(input, "_")
|
||||||
local split_length = Util.tableLength(split_name)
|
local split_length = Util.tableLength(split_name)
|
||||||
if Util.startswith(input, "RANDOMMISSION") == true and split_length < 4 then
|
if Util.startsWith(input, "RANDOMMISSION") == true and split_length < 4 then
|
||||||
MissionEditorWarnings.Add("Random Mission with zonename " .. input .. " not in right format")
|
MissionEditorWarnings.Add("Random Mission with zonename " .. input .. " not in right format")
|
||||||
return nil
|
return nil
|
||||||
elseif split_length < 3 then
|
elseif split_length < 3 then
|
||||||
@@ -53,9 +53,10 @@ local function ParseZoneName(input)
|
|||||||
if inputType == "cas" then parsedType = "CAS" end
|
if inputType == "cas" then parsedType = "CAS" end
|
||||||
if inputType == "bai" then parsedType = "BAI" end
|
if inputType == "bai" then parsedType = "BAI" end
|
||||||
if inputType == "sam" then parsedType = "SAM" end
|
if inputType == "sam" then parsedType = "SAM" end
|
||||||
|
if inputType == "deepstrike" then parsedType = "DEEPSTRIKE" end
|
||||||
|
|
||||||
if parsedType == "nil" then
|
if parsedType == "nil" then
|
||||||
MissionEditorWarnings.Add("Mission with zonename '" ..
|
MissionEditorWarnings.Add("Mission with zoneName '" ..
|
||||||
input .. "' has an unsupported type '" .. (type or "nil"))
|
input .. "' has an unsupported type '" .. (type or "nil"))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -110,7 +111,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
unitsAlive = {},
|
unitsAlive = {},
|
||||||
targetsAlive = {},
|
targetsAlive = {},
|
||||||
hasTargets = false,
|
hasTargets = false,
|
||||||
groupNamesPerunit = {},
|
groupNamesPerUnit = {},
|
||||||
sceneryTargets = {}
|
sceneryTargets = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,17 +149,17 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||||
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
||||||
|
|
||||||
local isGroupTarget = Util.startswith(string.lower(groupName), "tgt_")
|
local isGroupTarget = Util.startsWith(string.lower(groupName), "tgt_")
|
||||||
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
||||||
local unitName = unit:getName()
|
local unitName = unit:getName()
|
||||||
local isUnitTarget = Util.startswith(string.lower(unitName), "tgt_")
|
local isUnitTarget = Util.startsWith(string.lower(unitName), "tgt_")
|
||||||
|
|
||||||
if self._missionGroups.unitsAlive[groupName] == nil then
|
if self._missionGroups.unitsAlive[groupName] == nil then
|
||||||
self._missionGroups.unitsAlive[groupName] = {}
|
self._missionGroups.unitsAlive[groupName] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
self._missionGroups.unitsAlive[groupName][unitName] = true
|
self._missionGroups.unitsAlive[groupName][unitName] = true
|
||||||
self._missionGroups.groupNamesPerunit[unitName] = groupName
|
self._missionGroups.groupNamesPerUnit[unitName] = groupName
|
||||||
|
|
||||||
if isGroupTarget == true or isUnitTarget == true then
|
if isGroupTarget == true or isUnitTarget == true then
|
||||||
self._missionGroups.hasTargets = true
|
self._missionGroups.hasTargets = true
|
||||||
@@ -178,7 +179,6 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
|
|
||||||
if self.missionType == "CAS" then
|
if self.missionType == "CAS" then
|
||||||
self._battleManager = BattleManager.New(self._missionGroups.redGroups, self._missionGroups.blueGroups, self.zoneName, self._logger.LogLevel)
|
self._battleManager = BattleManager.New(self._missionGroups.redGroups, self._missionGroups.blueGroups, self.zoneName, self._logger.LogLevel)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self._logger:debug("Mission " .. self.name .. " group count: " .. Util.tableLength(missionData.RedGroups))
|
self._logger:debug("Mission " .. self.name .. " group count: " .. Util.tableLength(missionData.RedGroups))
|
||||||
@@ -353,6 +353,19 @@ end
|
|||||||
function ZoneMission:SpawnInactive()
|
function ZoneMission:SpawnInactive()
|
||||||
self._logger:info("PreActivating " .. self.name)
|
self._logger:info("PreActivating " .. self.name)
|
||||||
|
|
||||||
|
if self.missionType == "DEEPSTRIKE" then
|
||||||
|
local missionData = self._database:getMissionDataForZone(self.zoneName)
|
||||||
|
---@type MissionPriority
|
||||||
|
local priority = "secondary"
|
||||||
|
if missionData and missionData.primaryOverwrite ~= nil then
|
||||||
|
if missionData.primaryOverwrite == true then
|
||||||
|
priority = "primary"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self._priority = priority
|
||||||
|
self._missionCommandsHelper:AddMissionToCommands(self)
|
||||||
|
end
|
||||||
|
|
||||||
for _, group in pairs(self._missionGroups.redGroups) do
|
for _, group in pairs(self._missionGroups.redGroups) do
|
||||||
group:Spawn()
|
group:Spawn()
|
||||||
end
|
end
|
||||||
@@ -389,6 +402,17 @@ function ZoneMission:SpawnActive()
|
|||||||
self._battleManager:Start()
|
self._battleManager:Start()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self._missionCommandsHelper:RemoveMissionToCommands(self) -- Remove first
|
||||||
|
if self.missionType == "DEEPSTRIKE" then
|
||||||
|
local missionData = self._database:getMissionDataForZone(self.zoneName)
|
||||||
|
local priority = "primary"
|
||||||
|
if missionData and missionData.primaryOverwrite ~= nil then
|
||||||
|
if missionData.primaryOverwrite == false then
|
||||||
|
priority = "secondary"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self._priority = priority
|
||||||
|
end
|
||||||
self._missionCommandsHelper:AddMissionToCommands(self)
|
self._missionCommandsHelper:AddMissionToCommands(self)
|
||||||
|
|
||||||
self:StartCheckingContinuous()
|
self:StartCheckingContinuous()
|
||||||
@@ -480,7 +504,7 @@ function ZoneMission:OnUnitLost(object)
|
|||||||
local unitName = object:getName()
|
local unitName = object:getName()
|
||||||
self._logger:debug("UnitName:" .. unitName)
|
self._logger:debug("UnitName:" .. unitName)
|
||||||
|
|
||||||
local groupName = self._missionGroups.groupNamesPerunit[unitName]
|
local groupName = self._missionGroups.groupNamesPerUnit[unitName]
|
||||||
self._missionGroups.unitsAlive[groupName][unitName] = false
|
self._missionGroups.unitsAlive[groupName][unitName] = false
|
||||||
|
|
||||||
if self._missionGroups.targetsAlive[groupName] and self._missionGroups.targetsAlive[groupName][unitName] then
|
if self._missionGroups.targetsAlive[groupName] and self._missionGroups.targetsAlive[groupName][unitName] then
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ local GlobalConfig = require("classes.configuration.GlobalConfig")
|
|||||||
---@field zoneName string
|
---@field zoneName string
|
||||||
---@field missionType MissionType
|
---@field missionType MissionType
|
||||||
---@field missionTypeDisplay string
|
---@field missionTypeDisplay string
|
||||||
---@field priority MissionPriority
|
---@field protected _priority MissionPriority
|
||||||
---@field location Vec2?
|
---@field location Vec2?
|
||||||
---@field code string
|
---@field code string
|
||||||
---@field protected _state MissionState
|
---@field protected _state MissionState
|
||||||
@@ -40,7 +40,7 @@ function Mission.newSuper(self, zoneName, missionName, missionType, missionBrief
|
|||||||
self.zoneName = zoneName
|
self.zoneName = zoneName
|
||||||
self.name = missionName
|
self.name = missionName
|
||||||
self.missionType = missionType
|
self.missionType = missionType
|
||||||
self.priority = priority
|
self._priority = priority
|
||||||
self._state = "NEW"
|
self._state = "NEW"
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
self._database = database
|
self._database = database
|
||||||
@@ -64,6 +64,11 @@ end
|
|||||||
|
|
||||||
--region PUBLIC
|
--region PUBLIC
|
||||||
|
|
||||||
|
---@return MissionPriority
|
||||||
|
function Mission:GetPriority()
|
||||||
|
return self._priority
|
||||||
|
end
|
||||||
|
|
||||||
function Mission:SpawnPersistedState() end
|
function Mission:SpawnPersistedState() end
|
||||||
function Mission:SpawnActive() end
|
function Mission:SpawnActive() end
|
||||||
|
|
||||||
@@ -114,7 +119,7 @@ end
|
|||||||
function Mission:NotifyMissionComplete()
|
function Mission:NotifyMissionComplete()
|
||||||
self._missionCommandsHelper:RemoveMissionToCommands(self)
|
self._missionCommandsHelper:RemoveMissionToCommands(self)
|
||||||
self._logger:info("Mission Completed: " .. self.zoneName)
|
self._logger:info("Mission Completed: " .. self.zoneName)
|
||||||
trigger.action.outText("Mission " .. self.name .. " [" .. self.code .. "] was completed succesfully", 20)
|
trigger.action.outText("Mission " .. self.name .. " [" .. self.code .. "] was completed successfully", 20)
|
||||||
|
|
||||||
for _, listener in pairs(self._completeListeners) do
|
for _, listener in pairs(self._completeListeners) do
|
||||||
pcall(function()
|
pcall(function()
|
||||||
@@ -155,13 +160,14 @@ function Mission:ToStateString() return "status: in progress" end
|
|||||||
--- @alias MissionType
|
--- @alias MissionType
|
||||||
--- | "nil"
|
--- | "nil"
|
||||||
--- | "STRIKE"
|
--- | "STRIKE"
|
||||||
|
--- | "DEEPSTRIKE"
|
||||||
--- | "CAS"
|
--- | "CAS"
|
||||||
--- | "BAI"
|
--- | "BAI"
|
||||||
--- | "DEAD"
|
--- | "DEAD"
|
||||||
--- | "SAM"
|
--- | "SAM"
|
||||||
--- | "OCA"
|
--- | "OCA"
|
||||||
--- | "LOGISTICS"
|
--- | "LOGISTICS"
|
||||||
|
---
|
||||||
--- @alias MissionState
|
--- @alias MissionState
|
||||||
--- | "NEW"
|
--- | "NEW"
|
||||||
--- | "WAITING"
|
--- | "WAITING"
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
---@class Util
|
---@class Util
|
||||||
local UTIL = {}
|
local UTIL = {}
|
||||||
do -- INIT UTIL
|
do -- INIT UTIL
|
||||||
---splits a string in sub parts by seperator
|
---splits a string in sub parts by separator
|
||||||
---@param input string
|
---@param input string
|
||||||
---@param seperator string
|
---@param separator string
|
||||||
---@return Array<string> result list of strings
|
---@return Array<string> result list of strings
|
||||||
function UTIL.split_string(input, seperator)
|
function UTIL.split_string(input, separator)
|
||||||
if seperator == nil then
|
if separator == nil then
|
||||||
seperator = " "
|
separator = " "
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
@@ -15,7 +15,7 @@ do -- INIT UTIL
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
for str in string.gmatch(input, "[^" .. seperator .. "]+") do
|
for str in string.gmatch(input, "[^" .. separator .. "]+") do
|
||||||
table.insert(result, str)
|
table.insert(result, str)
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
@@ -134,7 +134,7 @@ do -- INIT UTIL
|
|||||||
---@param findable string
|
---@param findable string
|
||||||
---@param ignoreCase boolean?
|
---@param ignoreCase boolean?
|
||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startswith = function(str, findable, ignoreCase)
|
UTIL.startsWith = function(str, findable, ignoreCase)
|
||||||
if ignoreCase == true then
|
if ignoreCase == true then
|
||||||
return string.lower(str):find('^' .. string.lower(findable)) ~= nil
|
return string.lower(str):find('^' .. string.lower(findable)) ~= nil
|
||||||
end
|
end
|
||||||
@@ -164,7 +164,7 @@ do -- INIT UTIL
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startswithAny = function(str, findableTable)
|
UTIL.startswithAny = function(str, findableTable)
|
||||||
for _, value in pairs(findableTable) do
|
for _, value in pairs(findableTable) do
|
||||||
if type(value) == "string" and UTIL.startswith(str, value) then return true end
|
if type(value) == "string" and UTIL.startsWith(str, value) then return true end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user