Dcs lua tool (#66)
* custom drawings and animations for video * wip * Work in progress refactor for toolkit * wip * Refactored everything for Lua Compile Tool * Trying out the github action * updated the github action ref * initial working version --------- Co-authored-by: ex61wi <tim.rorije@ing.com> Co-authored-by: dutchie031 <dutchie031>
This commit is contained in:
co-authored by
ex61wi
dutchie031 <dutchie031>
parent
0baa65da2b
commit
14115c53a0
@@ -12,10 +12,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run SpearheadCompile
|
||||
run: |
|
||||
mkdir -p ./output
|
||||
python3 SpearheadCompile.py . ./output/spearhead.lua
|
||||
- name: Compile Spearhead
|
||||
uses: dutchie031/DcsMissionScriptingTools/github-action@actions/v1
|
||||
with:
|
||||
source-root: ./src
|
||||
output-file: ./output/spearhead.lua
|
||||
|
||||
- name: Upload spearhead.lua artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
+128
-131
@@ -1,131 +1,128 @@
|
||||
name: Publish Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_candidate:
|
||||
description: 'Is this a release candidate?'
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
change_size:
|
||||
type: choice
|
||||
description: Version Bump
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
default: patch
|
||||
branches:
|
||||
- main
|
||||
- automation
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all branches and tags
|
||||
|
||||
- name: Run SpearheadCompile
|
||||
run: |
|
||||
mkdir -p ./output
|
||||
python3 SpearheadCompile.py . ./output/spearhead.lua
|
||||
|
||||
- name: Calculate Tag
|
||||
id: calculate_tag
|
||||
run: |
|
||||
# Get latest tag with 'v' prefix
|
||||
latest_tag=$(git tag --sort=-v:refname | grep -E '^v' | head -n 1)
|
||||
if [ -z "$latest_tag" ]; then
|
||||
latest_tag="v0.0.0"
|
||||
fi
|
||||
echo "Latest tag: $latest_tag"
|
||||
# Remove 'v' prefix for version parsing
|
||||
version=${latest_tag#v}
|
||||
IFS='.' read -r major minor patch <<< "$version"
|
||||
bump="${{ inputs.change_size }}"
|
||||
if [ "$bump" = "major" ]; then
|
||||
major=$((major+1))
|
||||
minor=0
|
||||
patch=0
|
||||
elif [ "$bump" = "minor" ]; then
|
||||
minor=$((minor+1))
|
||||
patch=0
|
||||
else
|
||||
patch=$((patch+1))
|
||||
fi
|
||||
new_tag="v${major}.${minor}.${patch}"
|
||||
if [ "${{ inputs.release_candidate }}" = "true" ]; then
|
||||
new_tag="$new_tag-rc"
|
||||
fi
|
||||
echo "New tag: $new_tag"
|
||||
echo "new_tag=$new_tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check for existing tag
|
||||
id: check_tag
|
||||
run: |
|
||||
if git tag | grep -q "^${{ steps.calculate_tag.outputs.new_tag }}$"; then
|
||||
echo "Tag already exists. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Generate Release Notes
|
||||
id: generate_release_notes
|
||||
run: |
|
||||
if [ "${{ inputs.release_candidate }}" != "true" ]; then
|
||||
git log $(git describe --tags --abbrev=0 $(git tag --sort=-v:refname | grep -v '-rc' | head -n 1))..HEAD --pretty=format:'- %s%n %b' > release_notes.txt
|
||||
else
|
||||
git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:'- %s%n %b' > release_notes.txt
|
||||
fi
|
||||
awk -i inplace '!seen[$0]++' release_notes.txt
|
||||
cat release_notes.txt
|
||||
shell: bash
|
||||
|
||||
- name: Apply Tag to Current Commit
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
git tag ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
git push origin ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
|
||||
- name: Copy Release to Versioned File
|
||||
run: |
|
||||
cp ./output/spearhead.lua ./output/spearhead.${{ steps.calculate_tag.outputs.new_tag }}.lua
|
||||
echo "Versioned file created: spearhead.${{ steps.calculate_tag.outputs.new_tag }}.lua"
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: actions/create-release@v1
|
||||
id: create_release
|
||||
with:
|
||||
tag_name: ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
release_name: Release ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
draft: true
|
||||
body_path: release_notes.txt
|
||||
prerelease: ${{ inputs.release_candidate }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload Spearhead.lua Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/spearhead.lua
|
||||
asset_name: spearhead.lua
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Spearhead.lua Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/spearhead.${{steps.calculate_tag.outputs.new_tag}}.lua
|
||||
asset_name: spearhead.${{steps.calculate_tag.outputs.new_tag}}.lua
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
name: Publish Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_candidate:
|
||||
description: 'Is this a release candidate?'
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
change_size:
|
||||
type: choice
|
||||
description: Version Bump
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
default: patch
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all branches and tags
|
||||
|
||||
- name: Compile Spearhead
|
||||
uses: dutchie031/DcsMissionScriptingTools/github-action@actions/v1
|
||||
with:
|
||||
source-root: ./src
|
||||
output-file: ./output/spearhead.lua
|
||||
|
||||
- name: Calculate Tag
|
||||
id: calculate_tag
|
||||
run: |
|
||||
# Get latest tag with 'v' prefix
|
||||
latest_tag=$(git tag --sort=-v:refname | grep -E '^v' | head -n 1)
|
||||
if [ -z "$latest_tag" ]; then
|
||||
latest_tag="v0.0.0"
|
||||
fi
|
||||
echo "Latest tag: $latest_tag"
|
||||
# Remove 'v' prefix for version parsing
|
||||
version=${latest_tag#v}
|
||||
IFS='.' read -r major minor patch <<< "$version"
|
||||
bump="${{ inputs.change_size }}"
|
||||
if [ "$bump" = "major" ]; then
|
||||
major=$((major+1))
|
||||
minor=0
|
||||
patch=0
|
||||
elif [ "$bump" = "minor" ]; then
|
||||
minor=$((minor+1))
|
||||
patch=0
|
||||
else
|
||||
patch=$((patch+1))
|
||||
fi
|
||||
new_tag="v${major}.${minor}.${patch}"
|
||||
if [ "${{ inputs.release_candidate }}" = "true" ]; then
|
||||
new_tag="$new_tag-rc"
|
||||
fi
|
||||
echo "New tag: $new_tag"
|
||||
echo "new_tag=$new_tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check for existing tag
|
||||
id: check_tag
|
||||
run: |
|
||||
if git tag | grep -q "^${{ steps.calculate_tag.outputs.new_tag }}$"; then
|
||||
echo "Tag already exists. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Generate Release Notes
|
||||
id: generate_release_notes
|
||||
run: |
|
||||
if [ "${{ inputs.release_candidate }}" != "true" ]; then
|
||||
git log $(git describe --tags --abbrev=0 $(git tag --sort=-v:refname | grep -v '-rc' | head -n 1))..HEAD --pretty=format:'- %s%n %b' > release_notes.txt
|
||||
else
|
||||
git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:'- %s%n %b' > release_notes.txt
|
||||
fi
|
||||
awk -i inplace '!seen[$0]++' release_notes.txt
|
||||
cat release_notes.txt
|
||||
shell: bash
|
||||
|
||||
- name: Apply Tag to Current Commit
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
git tag ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
git push origin ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
|
||||
- name: Copy Release to Versioned File
|
||||
run: |
|
||||
cp ./output/spearhead.lua ./output/spearhead.${{ steps.calculate_tag.outputs.new_tag }}.lua
|
||||
echo "Versioned file created: spearhead.${{ steps.calculate_tag.outputs.new_tag }}.lua"
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: actions/create-release@v1
|
||||
id: create_release
|
||||
with:
|
||||
tag_name: ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
release_name: Release ${{ steps.calculate_tag.outputs.new_tag }}
|
||||
draft: true
|
||||
body_path: release_notes.txt
|
||||
prerelease: ${{ inputs.release_candidate }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload Spearhead.lua Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/spearhead.lua
|
||||
asset_name: spearhead.lua
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload Spearhead.lua Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/spearhead.${{steps.calculate_tag.outputs.new_tag}}.lua
|
||||
asset_name: spearhead.${{steps.calculate_tag.outputs.new_tag}}.lua
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
|
||||
+5
-1
@@ -1,2 +1,6 @@
|
||||
**/.DS_Store
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
/dist
|
||||
|
||||
.vscode/settings.json
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,721 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor",
|
||||
"elements": [
|
||||
{
|
||||
"id": "HiVK1huIbL16ZCy3rz5t8",
|
||||
"type": "rectangle",
|
||||
"x": 1622.7441591132324,
|
||||
"y": 984.6777917946865,
|
||||
"width": 1578.7433546522943,
|
||||
"height": 836.7851776620863,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2L",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 645107296,
|
||||
"version": 227,
|
||||
"versionNonce": 1642809248,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "lTQAmT-q3EhB8l4OFoV4r",
|
||||
"type": "rectangle",
|
||||
"x": 2308.0518724509566,
|
||||
"y": 1544.7916707023237,
|
||||
"width": 211.02211156486123,
|
||||
"height": 96.5527520526872,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2M",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 28492384,
|
||||
"version": 449,
|
||||
"versionNonce": 702648928,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "23RNiECmee0GZfyG42WJU",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "AS-wLfqmrJICLegtTjwKA",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "9aRWFt8Ol6hDDEvOstOxf",
|
||||
"type": "text",
|
||||
"x": 2340.7060558234443,
|
||||
"y": 1563.9495282342684,
|
||||
"width": 154.26666259765625,
|
||||
"height": 55.62747030529269,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2N",
|
||||
"roundness": null,
|
||||
"seed": 384530016,
|
||||
"version": 204,
|
||||
"versionNonce": 2083905440,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Mission",
|
||||
"fontSize": 44.50197624423415,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Mission",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "23RNiECmee0GZfyG42WJU",
|
||||
"type": "arrow",
|
||||
"x": 2519.9815623115946,
|
||||
"y": 1608.9632387014556,
|
||||
"width": 185.6851361459012,
|
||||
"height": 84.58953522783993,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2O",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1793960544,
|
||||
"version": 1436,
|
||||
"versionNonce": 1331590752,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
132.75987383519941,
|
||||
-15.5442452755197
|
||||
],
|
||||
[
|
||||
185.6851361459012,
|
||||
-84.58953522783993
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "lTQAmT-q3EhB8l4OFoV4r",
|
||||
"focus": 0.46767568934546344,
|
||||
"gap": 1
|
||||
},
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "K6jAODe27_os5DPh8967u",
|
||||
"type": "text",
|
||||
"x": 2689.444812908036,
|
||||
"y": 1465.552661128815,
|
||||
"width": 222.53535431824844,
|
||||
"height": 54.779302679674046,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2P",
|
||||
"roundness": null,
|
||||
"seed": 1753833056,
|
||||
"version": 808,
|
||||
"versionNonce": 1186625440,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "The Story",
|
||||
"fontSize": 43.823442143739236,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "The Story",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "AS-wLfqmrJICLegtTjwKA",
|
||||
"type": "arrow",
|
||||
"x": 2384.330334167984,
|
||||
"y": 1544.3197414150743,
|
||||
"width": 49.364397989861686,
|
||||
"height": 80.37199821269722,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2Q",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 546214496,
|
||||
"version": 1667,
|
||||
"versionNonce": 1614569056,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-38.3710655807796,
|
||||
-28.81586470940509
|
||||
],
|
||||
[
|
||||
-49.364397989861686,
|
||||
-80.37199821269722
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "lTQAmT-q3EhB8l4OFoV4r",
|
||||
"focus": 0.21013738563944281,
|
||||
"gap": 1
|
||||
},
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "m8Er51Ess3j92_Q_brntE",
|
||||
"type": "rectangle",
|
||||
"x": 2159.6497125177334,
|
||||
"y": 1335.721614644765,
|
||||
"width": 363.99766551946664,
|
||||
"height": 127.50624664551411,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [
|
||||
"cNSAgbnsi3PlOKVDl2tCl"
|
||||
],
|
||||
"frameId": null,
|
||||
"index": "b2R",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 164447840,
|
||||
"version": 969,
|
||||
"versionNonce": 2063142816,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "XCGW5ooPSVuaaam9AVDz-",
|
||||
"type": "text",
|
||||
"x": 2173.9396997857207,
|
||||
"y": 1357.9865705806305,
|
||||
"width": 333.6248911062344,
|
||||
"height": 83.92658771184712,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [
|
||||
"cNSAgbnsi3PlOKVDl2tCl"
|
||||
],
|
||||
"frameId": null,
|
||||
"index": "b2S",
|
||||
"roundness": null,
|
||||
"seed": 1091926624,
|
||||
"version": 1089,
|
||||
"versionNonce": 1148591008,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Spearhead",
|
||||
"fontSize": 67.14127016947768,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Spearhead",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "moW1_uGfHzYIjzGogGQGK",
|
||||
"type": "text",
|
||||
"x": 2104.0596241560615,
|
||||
"y": 1034.5614167492809,
|
||||
"width": 646.7199096679688,
|
||||
"height": 64.22500341608406,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2T",
|
||||
"roundness": null,
|
||||
"seed": 1228353120,
|
||||
"version": 349,
|
||||
"versionNonce": 1920051104,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Mission making, made easy",
|
||||
"fontSize": 51.380002732867254,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "Mission making, made easy",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "o2jZSQLCW3jrv6pCqie6_",
|
||||
"type": "arrow",
|
||||
"x": 2159.733022744733,
|
||||
"y": 1387.9176228888964,
|
||||
"width": 160.53319080851742,
|
||||
"height": 70.53888252157658,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2U",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1258447456,
|
||||
"version": 260,
|
||||
"versionNonce": 1897640864,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-92.03884598362902,
|
||||
-5.663893806853778
|
||||
],
|
||||
[
|
||||
-160.53319080851742,
|
||||
-70.53888252157658
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "W9vcoug4Anqo3kphgtT9I",
|
||||
"type": "text",
|
||||
"x": 1878.031940531582,
|
||||
"y": 1271.37874036732,
|
||||
"width": 241.1999053955078,
|
||||
"height": 45,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2V",
|
||||
"roundness": null,
|
||||
"seed": 1430722144,
|
||||
"version": 123,
|
||||
"versionNonce": 648298400,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "quick creation",
|
||||
"fontSize": 36,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "quick creation",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "vKiHSOYVz3WA8hsPa4Gz_",
|
||||
"type": "text",
|
||||
"x": 2048.097445465383,
|
||||
"y": 1156.4671681391064,
|
||||
"width": 291.2398681640625,
|
||||
"height": 45,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2W",
|
||||
"roundness": null,
|
||||
"seed": 483740256,
|
||||
"version": 118,
|
||||
"versionNonce": 859524000,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "multiplayer ready",
|
||||
"fontSize": 36,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "multiplayer ready",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "slm2yLO4dbFEB4unTSEBM",
|
||||
"type": "arrow",
|
||||
"x": 2272.711713817616,
|
||||
"y": 1335.0347744783633,
|
||||
"width": 66.5822620861594,
|
||||
"height": 126.32077628211141,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2X",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1014824544,
|
||||
"version": 263,
|
||||
"versionNonce": 823187360,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-54.89666258783586,
|
||||
-52.65193572538732
|
||||
],
|
||||
[
|
||||
-66.5822620861594,
|
||||
-126.32077628211141
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "AzL0eyJGalMEJhcGJm2_F",
|
||||
"type": "arrow",
|
||||
"x": 2416.5200398307725,
|
||||
"y": 1335.3880374127152,
|
||||
"width": 114.58165799006088,
|
||||
"height": 125.00113779000418,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2Y",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1963864672,
|
||||
"version": 298,
|
||||
"versionNonce": 1951720352,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
81.1107899245286,
|
||||
-56.913107137971394
|
||||
],
|
||||
[
|
||||
114.58165799006088,
|
||||
-125.00113779000418
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "9XYksy7fqu89wA1b8KHk4",
|
||||
"type": "text",
|
||||
"x": 2479.4611352261527,
|
||||
"y": 1164.386899622711,
|
||||
"width": 122.79595947265625,
|
||||
"height": 45,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2Z",
|
||||
"roundness": null,
|
||||
"seed": 1834542688,
|
||||
"version": 150,
|
||||
"versionNonce": 1261924256,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "flexible",
|
||||
"fontSize": 36,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "flexible",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "O8kJBNxfzL8ncxdD2kZRM",
|
||||
"type": "arrow",
|
||||
"x": 2527.9914421715134,
|
||||
"y": 1376.2823093418706,
|
||||
"width": 161.921133337549,
|
||||
"height": 61.23797674760587,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2a",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1915558496,
|
||||
"version": 341,
|
||||
"versionNonce": 1038646176,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
110.30502983196084,
|
||||
-8.630813890686284
|
||||
],
|
||||
[
|
||||
161.921133337549,
|
||||
-61.23797674760587
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "1SS8AR95vxynNN_GgSOm-",
|
||||
"type": "text",
|
||||
"x": 2670.559620709462,
|
||||
"y": 1266.635895233043,
|
||||
"width": 207.61192321777344,
|
||||
"height": 45,
|
||||
"angle": 0,
|
||||
"strokeColor": "#ffffff",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b2b",
|
||||
"roundness": null,
|
||||
"seed": 911920736,
|
||||
"version": 322,
|
||||
"versionNonce": 1318586272,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1766927996013,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "easy to use",
|
||||
"fontSize": 36,
|
||||
"fontFamily": 5,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "easy to use",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 20,
|
||||
"gridStep": 5,
|
||||
"gridModeEnabled": false,
|
||||
"viewBackgroundColor": "#1b1d27"
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
Vendored
+5
-1
@@ -16,5 +16,9 @@
|
||||
"disableFolding": false
|
||||
}
|
||||
},
|
||||
"livePreview.serverRoot": "/_docs"
|
||||
"livePreview.serverRoot": "/_docs",
|
||||
"Lua.workspace.library": [
|
||||
"/Users/ex61wi/Developer/personal/DcsMissionScriptingTools/dutchies-dcs-scripting-tools/lua-addons",
|
||||
"c:\\Users\\Tim\\.vscode\\extensions\\dutchie031.dutchies-dcs-scripting-tools-0.0.3\\lua-addons"
|
||||
],
|
||||
}
|
||||
-1272
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 330 KiB |
+18
-11
@@ -32,21 +32,28 @@
|
||||
<div class="content-wrapper">
|
||||
|
||||
|
||||
<h1 id="welcome">Welcome to Spearhead!</h1>
|
||||
<h1 id="welcome">Welcome to Spearhead!</h1>
|
||||
|
||||
<p>Welcome to the story teller friendly mission framework in DCS (at least, that's what we hope to create).</p>
|
||||
<p>Together with mission editors we've tried to build a framework that makes creating multiplayer missions as easy as possible.
|
||||
|
||||
With the help of naming conventions, trigger zones, pre-configured logic and custom configuration items, it gives a huge amount of versatility.
|
||||
we're trying to strike a balance between no-code and low-code with the possibility to hook into it for the hard core scripters (like ourselves).
|
||||
|
||||
<note-box type="info">
|
||||
<b>For the scripters</b>: If you yourself are a scripter, and you're missing interfaces, please reach out to us! We want to make sure that the framework is as easy to use for scripters as it is for non-scripters, and we can't do that without your help!
|
||||
</note-box>
|
||||
</p>
|
||||
<p>
|
||||
Whether this is your first mission or your hundredth, we hope Spearhead will make your life easier.
|
||||
</p>
|
||||
|
||||
<download-spearhead></download-spearhead>
|
||||
|
||||
<p>Welcome to the story teller friendly mission framework in DCS (at least, that's what we hope to create).</p>
|
||||
<p>Together with mission editors we've tried to build a framework that
|
||||
makes creating multiplayer missions as easy as possible.
|
||||
With the help of naming conventions, trigger zones, pre-configured
|
||||
logic and custom configuration items, it gives a huge amount of versatility.
|
||||
we're trying to strike a balance between no-code and low-code with the possibility to hook into it for
|
||||
the hard core scripters.</p>
|
||||
|
||||
<p id="latest-version">Latest Version: #{VERSION}# created at: #{VERSION_DATE}#</p>
|
||||
<p id="latest-version">Latest Beta Version: #{BETA_VERSION}# created at: #{BETA_VERSION_DATE}#</p>
|
||||
<a style="text-decoration: underline;" target="_blank" href="https://github.com/dutchie031/Spearhead/releases">See All releases here</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
|
||||
@@ -3,3 +3,4 @@ import * as sidebar from "./components/sidebar.js";
|
||||
import './components/code-block.js';
|
||||
import './components/code-inline.js';
|
||||
import './components/note.js';
|
||||
import './components/latest-version-download.js';
|
||||
|
||||
@@ -6,7 +6,7 @@ class Header extends HTMLElement {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
this.innerHTML = /*html*/`
|
||||
<div class="header-box">
|
||||
<a class="logo" href="/index.html">Spearhead</a>
|
||||
<span class="subTitle">mission making, made easy</span>
|
||||
@@ -17,9 +17,11 @@ class Header extends HTMLElement {
|
||||
<div class="dropdown">
|
||||
<a href="/pages/tutorials.html">Tutorials</a>
|
||||
<div class="dropdown-content">
|
||||
<a href="/pages/tutorials.html">Quick Starts</a>
|
||||
<a href="/pages/advanced/CAP.html">Advanced: CAP</a>
|
||||
<a href="/pages/advanced/missions.html">Advanced: Missions</a>
|
||||
<a href="/pages/include-script.html">Include the Script</a>
|
||||
<a href="/pages/first-start.html">First Start</a>
|
||||
<a href="/pages/advanced/CAP.html">Advanced: CAP</a>
|
||||
<a href="/pages/advanced/missions.html">Advanced: Missions</a>
|
||||
<a href="/pages/advanced/map-markings.html">Map Markings</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
class DownloadScript extends HTMLElement {
|
||||
|
||||
constructor(){
|
||||
super();
|
||||
this.cacheKey = 'spearhead-latest-release';
|
||||
this.cacheExpiryMinutes = 15;
|
||||
}
|
||||
|
||||
getCachedData() {
|
||||
const cached = localStorage.getItem(this.cacheKey);
|
||||
if (!cached) return null;
|
||||
|
||||
const { data, timestamp } = JSON.parse(cached);
|
||||
const now = Date.now();
|
||||
const expiry = this.cacheExpiryMinutes * 60 * 1000; // 15 minutes in ms
|
||||
|
||||
if (now - timestamp > expiry) {
|
||||
localStorage.removeItem(this.cacheKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
setCachedData(data) {
|
||||
const cacheItem = {
|
||||
data: data,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
localStorage.setItem(this.cacheKey, JSON.stringify(cacheItem));
|
||||
}
|
||||
|
||||
async fetchLatestRelease() {
|
||||
// Check cache first
|
||||
const cachedData = this.getCachedData();
|
||||
if (cachedData) {
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('https://api.github.com/repos/dutchie031/Spearhead/releases/latest');
|
||||
const data = await response.json();
|
||||
|
||||
// Cache the data
|
||||
this.setCachedData(data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching latest release:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchReleaseAssets(url){
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching release assets:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
|
||||
var version = "?";
|
||||
var timestamp = "?";
|
||||
var size = "?";
|
||||
var href = "https://github.com/dutchie031/Spearhead/releases"
|
||||
|
||||
const latestRelease = await this.fetchLatestRelease();
|
||||
if (latestRelease) {
|
||||
version = latestRelease.tag_name;
|
||||
timestamp = new Date(latestRelease.published_at).toLocaleDateString('en-CA');
|
||||
|
||||
const assets = await this.fetchReleaseAssets(latestRelease.assets_url);
|
||||
if (assets && assets.length > 0) {
|
||||
const spearheadAsset = assets.find(asset => asset.name.includes('spearhead'));
|
||||
if (spearheadAsset) {
|
||||
size = (spearheadAsset.size / 1024).toFixed(2) + 'kb';
|
||||
href = spearheadAsset.browser_download_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.innerHTML = /*html*/`
|
||||
<div class="latest-version-download-box">
|
||||
<style>
|
||||
.latest-version-download-box {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.latest-version-download-content {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
padding: 0px 16px;
|
||||
}
|
||||
|
||||
.version-text {
|
||||
font-weight: bold;
|
||||
color: #f5efefff
|
||||
}
|
||||
</style>
|
||||
<div class="latest-version-download-content">
|
||||
<p>
|
||||
<span class="version-text">${version}</span> (${timestamp}) <br>
|
||||
<a style="text-decoration: underline;" target="_blank" href="${href}">Download</a> (${size}) <br>
|
||||
<a style="text-decoration: underline;" target="_blank" href="https://github.com/dutchie031/Spearhead/releases">See All Versions here</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define('download-spearhead', DownloadScript);
|
||||
@@ -37,10 +37,8 @@
|
||||
Even though, at the time of writing this, I've written every single line of code myself, I could not have done it without the help of these members.<br>
|
||||
Therefore it's something WE created.
|
||||
|
||||
Our goal was very simple, make it possible to make big dynamic missions, without having to either give away all controll or having to get knee deep into scripting. <br>
|
||||
We struck a balance.
|
||||
|
||||
|
||||
Our goal was very simple, make it possible to make big dynamic missions, without having to either give away all control or having to get knee deep into scripting. <br>
|
||||
We struck a balance.
|
||||
|
||||
</p>
|
||||
|
||||
@@ -63,5 +61,4 @@
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
</html>
|
||||
@@ -220,5 +220,4 @@
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
</html>
|
||||
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spearhead Missions</title>
|
||||
<link rel="stylesheet" href="/style/style.css">
|
||||
<script src="/js/site.js"></script>
|
||||
<style>
|
||||
.side-nav a.active {
|
||||
font-weight: bold;
|
||||
color: #4fc3f7;
|
||||
}
|
||||
</style>
|
||||
<script type="module" src="/js/components.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<app-header></app-header>
|
||||
</header>
|
||||
<main>
|
||||
<div class="reference-container">
|
||||
<app-sidebar></app-sidebar>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<h1>Map Markings</h1>
|
||||
|
||||
<p>
|
||||
Drawings can be very powerful in DCS missions. <br>
|
||||
They can guide players towards the right objectives or warn them of dangers ahead. <br>
|
||||
In Spearhead, we have both automatic markers and drawings as well as the possibility to integrate custom drawings.<br>
|
||||
</p>
|
||||
|
||||
<h2 id="automatic_drawings">Automated</h2>
|
||||
|
||||
|
||||
<h3 id="stage_drawings">Stages</h3>
|
||||
<p>
|
||||
Spearhead automatically draws stage markings on the map for players to see. <br>
|
||||
These are drawn when a stage becomes active and removed when the stage is completed. <br>
|
||||
This gives players a clear visual indication of where they need to go next. <br>
|
||||
<br>
|
||||
These can however be disabled in the configuration if desired. <br>
|
||||
<code-inline>SpearheadConfig.StageConfig.drawStages</code-inline> <br>
|
||||
<code-inline>SpearheadConfig.StageConfig.drawPreActived</code-inline> <br>
|
||||
</p>
|
||||
|
||||
<h3 id="lastcontact_markings">Last Contact</h3>
|
||||
<p>
|
||||
If enabled, Spearhead will draw a marker on the map where the enemy was last killed. <br>
|
||||
This might help in big multiplayer missions where players log off without sharing intel. <br>
|
||||
This can be enabled or disabled in the configuration. <br>
|
||||
<code-inline>SpearheadConfig.StageConfig.markLastContact</code-inline>
|
||||
</p>
|
||||
|
||||
<h2 id="custom_drawings">Custom</h2>
|
||||
<p>
|
||||
Adding a custom drawing is easy. <br>
|
||||
Simply create the drawing and then name it according to the following convention: <br>
|
||||
<code-inline>DRAWING_[a]:[b]_[FreeForm]</starting></code-inline> <br>
|
||||
Where:
|
||||
<ul>
|
||||
<li><code-inline>[a]</code-inline> is the stage number at which the drawing should appear.</li>
|
||||
<li><code-inline>[b]</code-inline> is the stage number at which the drawing should be removed again.</li>
|
||||
<li><code-inline>[FreeForm]</code-inline> is any name you want to make it unique or findables.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<note-box type="warning" title="Author Layer">
|
||||
The custom drawings need to be in the "Author" layer of the mission editor to be managed by Spearhead.
|
||||
This is due to other layers being visible by default and cannot be as easily removed when not needed.
|
||||
The author layer is not visible by default in multiplayer, making it perfect for this use case.
|
||||
</note-box>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2025 Spearhead Project</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -68,5 +68,4 @@
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
</html>
|
||||
@@ -0,0 +1,208 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spearhead Tutorials</title>
|
||||
|
||||
<link rel="stylesheet" href="/style/prism.css">
|
||||
<link rel="stylesheet" href="/style/style.css">
|
||||
|
||||
<script src="/js/prism.js"></script>
|
||||
<script src="/js/site.js"></script>
|
||||
<style>
|
||||
.side-nav a.active {
|
||||
font-weight: bold;
|
||||
color: #4fc3f7;
|
||||
}
|
||||
</style>
|
||||
<script type="module" src="../js/components.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<app-header></app-header>
|
||||
</header> <main>
|
||||
<div class="reference-container">
|
||||
<app-sidebar></app-sidebar>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<h1>Tutorials</h1>
|
||||
<p>
|
||||
This guide is to get you started building your first Spearhead mission. <br />
|
||||
Spearhead was created to enable the mission maker to worry as little about the running, timing and scripting
|
||||
and most about the setting and looks and feel of the mission. <br />
|
||||
In the example we'll show how you can create a simple island hopping mission
|
||||
</p>
|
||||
|
||||
<h2>Include the script</h2>
|
||||
<p>
|
||||
Read <a href="/pages/include-script.html">here</a> how to include the Spearhead script in your mission first. <br />
|
||||
</p>
|
||||
|
||||
<h2 id="stages">Stages</h2>
|
||||
|
||||
<p>
|
||||
In general, stages are the backbone of a Spearhead mission. <br>
|
||||
They define the flow of the mission and what is active at what time. <br>
|
||||
|
||||
Don't worry, it can be changed and adapted later on, but it's best to translate your mission idea into stages first. <br>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Stages are defined by trigger zones. <br>
|
||||
They'll be picked up by Spearhead when named according to the naming convention: <br>
|
||||
<code-inline>MISSIONSTAGE_[OrderNumber]_[FreeForm]</code-inline> <br>
|
||||
<br>
|
||||
Stages are divided in primary stages: <code-inline>MISSIONSTAGE_[number]</code-inline> <br>
|
||||
or secondary stages: <code-inline>MISSIONSTAGE_x[number]</code-inline> <br>
|
||||
Note the x before the number. This marks it as "extra" <br>
|
||||
Secondary stages will follow the order number, but are not required to be completed before moving on to the next stage numbers. <br>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For this Demo mission we'll create 3 stages. <br>
|
||||
<code-inline>MissionStage_1_start</code-inline><br>
|
||||
<code-inline>MissionStage_2_continuation</code-inline><br>
|
||||
<code-inline>MissionStage_3_finale</code-inline> <br>
|
||||
Each stage will have it's own trigger zone. <br/>
|
||||
</p>
|
||||
<img src="../img/first-start/1.png" alt="The first stages displayed" style="width: 100%;"></img>
|
||||
|
||||
<p>
|
||||
There's 3 stages now. <br>
|
||||
The first <code-inline>MissionStage_1_start</code-inline> is the first stage and will be active at mission start. <br>
|
||||
The second <code-inline>MissionStage_2_continuation</code-inline> will be pre-activated when stage 1 is active. <br>
|
||||
But will be fully activated when stage 1 is complete. <br>
|
||||
Pre-activated means that the SAM missions and Airbase units will be activated. <br>
|
||||
This is the difference between SAM and DEAD missions, but let's not get into too much detail at this time. <br>
|
||||
|
||||
You can ofcourse create as many stages as you want. <br>
|
||||
You can also change the amount of stages that get pre-activated. <br>
|
||||
By default Spearhead will pre-activate 1 stage ahead. <br/>
|
||||
This can be changed in the configuration. <br/>
|
||||
</p>
|
||||
|
||||
<h2 id="create-missions">Create Missions</h2>
|
||||
<p>
|
||||
Now that we've created the stages we can start adding missions to them. <br>
|
||||
Missions are also defined by trigger zones. <br>
|
||||
They'll be picked up by Spearhead when named according to the naming convention: <br>
|
||||
<code-inline>MISSION_[Type]_[FreeForm]</code-inline> <br>
|
||||
Where <code-inline>[Type]</code-inline> is the type of mission. <a href="./reference.html#mission-zones">See all</a><br>
|
||||
|
||||
</p>
|
||||
|
||||
<h3 id="mission-cas">CAS</h3>
|
||||
<p>
|
||||
Personally CAS is one of my favorite mission types. <br>
|
||||
Mostly because it's easy to set up and creates a truly immersive experience. <br>
|
||||
|
||||
</p>
|
||||
|
||||
<h3 id="mission-sam">SAM</h3>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
|
||||
<h3 id="mission-strike">STRIKE</h3>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="setting-up-cap">Setting up CAP</h2>
|
||||
<p>
|
||||
If you don't want to use the CAP managers withing Spearhead you can skip this and continue to <a href="#setting-up-the-missions">Setting up Missions</a>. <br />
|
||||
However CAP is one of the painpoints in a lot of missions and setting up a dynamic feeling airspace can be
|
||||
quite the challenge. <br />
|
||||
With the CAP managers we've tried to make this a lot easier. <br />
|
||||
|
||||
A CAP group needs to follow the following naming convention: <code-inline>CAP_[A|B][CONFIG]_[Free Form]</code-inline>
|
||||
|
||||
For details on config read this: <code-inline>CAP Group Config</code-inline>
|
||||
|
||||
For now I set up 3 groups with the following names. <code-inline>CAP_A[1]1_Rota1</code-inline>, <code-inline>CAP_A[1]1_Rota1-1</code-inline>,
|
||||
<code-inline>CAP_B[1]1_Rota1</code-inline> <br />
|
||||
The first two are marked with <code-inline>A</code-inline> and will therefore be primary CAP units. They will be
|
||||
scheduled and make up for the total count. <br />
|
||||
Meaning that for this airbase there is 2 CAP units max at a time flying out. <br />
|
||||
In this case all groups have <code-inline>[1]1</code-inline> in the name, (This would be the same as <code-inline>[1]A</code-inline>) which means
|
||||
that when stage 1 is active the groups will activate and fly out to stage 1.
|
||||
|
||||
I also set up a few groups further back. One example: <code-inline>CAP_A[1-3]3_Group1</code-inline>. This group will
|
||||
protect zone 3 when zones 1 through 3 are active.
|
||||
|
||||
CAP units fly out, fly their CAP zone for x amount of minutes and will then RTB. <br />
|
||||
Before they actually RTB an event is triggered 10 minutes before the actual RTB task. This event
|
||||
will trigger a backup unit to startup and fly out to take over. <br />
|
||||
</p>
|
||||
|
||||
<note-box type="info" title="Tip">
|
||||
You can start a mission, speed up the simulation and make the CAP fly out to see what happens
|
||||
</note-box>
|
||||
|
||||
<h3 id="creating-cap-routes">Creating CAP Routes</h3>
|
||||
<p>
|
||||
Creating CAP routes is not needed per se, but with a multi-stage stage (we have 2 stages with <code-inline>_1_</code-inline>) it is recommended. <br/>
|
||||
Similarly with huge stages. <br/>
|
||||
If there is multiple zones it will "round-robin" over them. <br/>
|
||||
</p>
|
||||
<p>
|
||||
If no CAP route is present the unit will fly a route generated differently per zone: <br/>
|
||||
<code-inline>quad zone</code-inline> => race-track between the corner closest to the origin airbase to the center point of the zone <br/>
|
||||
<code-inline>circle zone</code-inline> => race-track between the closest point on circle to the origin airbase to the center <br/>
|
||||
</p>
|
||||
<p>
|
||||
If you want to create your own CAP Routes you can! <br/>
|
||||
For this example I created 2 CAP routes inside of the 2 <code-inline>_1_</code-inline> stages. <br/>
|
||||
</p>
|
||||
<p>
|
||||
As you can see below there's a nice feature you can exploit. As long as the <code-inline>X</code-inline> of the zone is inside of the the <code-inline>CAPROUTE</code-inline> will be used for that stage!
|
||||
</p>
|
||||
<img src="../img/cap_routes.png" alt="CAP Routes Image" style="width: 100%;"></img>
|
||||
|
||||
<p>
|
||||
Well, nice, we're done setting up the initial CAP effort. <br/>
|
||||
If you want to change values for the CAP routes please read about how to configure it here: <a href="./Reference.html#cap-config">Cap Config</a>
|
||||
</p>
|
||||
|
||||
<h2 id="mission-briefings">Mission Briefings</h2>
|
||||
<p>
|
||||
So now we've created some missions we also want to add briefings to them. This is pretty easy with Spearhead. <br/>
|
||||
</p>
|
||||
<p>
|
||||
To do so click on <code-inline>draw</code-inline> on the left hand pane in the mission editor. This opens up the drawing tools in the editor. <br/>
|
||||
On the right click <code-inline>TextBox</code-inline> and click somewhere inside the zone to which you want to add the briefing. <br/>
|
||||
Give the briefing a name (It's not used, but can be nice to use to reference the briefing later) and add the briefing. <br/>
|
||||
The text box is quite small, but can have a lot of text. Easiest is to edit the text in an editor of choice and paste it into the box afterwards. <br/>
|
||||
</p>
|
||||
<p>
|
||||
Keep the binding layer to "Author" only. That way it doesn't show up for anyone other than in the mission editor.
|
||||
</p>
|
||||
<p>
|
||||
See the two images below. The left shows the <code-inline>Text Box</code-inline> drawing. The right shows the briefing as shown in the mission.
|
||||
</p>
|
||||
<div style="display: flex">
|
||||
<div style="flex: 50%">
|
||||
<img src="../img/briefing_me.png"/>
|
||||
</div>
|
||||
<div style="flex: 50%">
|
||||
<img src="../img/briefing_mission.png"/>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
We are now done creating a first mission. Hit fly and test it. <br/>
|
||||
Check all references for way more features and keep up to date with the latest changes as they come along! <br/>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2025 Spearhead Project</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spearhead Tutorials</title>
|
||||
|
||||
<link rel="stylesheet" href="/style/prism.css">
|
||||
<link rel="stylesheet" href="/style/style.css">
|
||||
|
||||
<script src="/js/prism.js"></script>
|
||||
<script src="/js/site.js"></script>
|
||||
<style>
|
||||
.side-nav a.active {
|
||||
font-weight: bold;
|
||||
color: #4fc3f7;
|
||||
}
|
||||
</style>
|
||||
<script type="module" src="../js/components.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<app-header></app-header>
|
||||
</header> <main>
|
||||
<div class="reference-container">
|
||||
<app-sidebar></app-sidebar>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<h1>Include the Spearhead Script</h1>
|
||||
|
||||
<h2 id="include-the-script">Include the Script</h2>
|
||||
<p>
|
||||
Download the latest version of Spearhead. You can choose which version you feel comfortable with. <br />
|
||||
Versions that end in -rc are not stable. Versions that do not have the "release candidate" (rc) tag are. <br>
|
||||
Stable does not mean bug-free, so if you find any issues let us know!
|
||||
<br />
|
||||
Here is the latest stable version:
|
||||
<download-spearhead></download-spearhead>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Then run the script in the mission. <br />
|
||||
Please do exactly as it's done below. <br />
|
||||
</p>
|
||||
<div style="width: 100%;">
|
||||
<img style="width: 100%;" src="../img/script_install.png"></img>
|
||||
</div>
|
||||
|
||||
<note-box type="info" title="Note">
|
||||
Spearhead does not require any dependencies (eg. MIST or MOOSE). Compatibility with other frameworks is
|
||||
not tested at this time, so cannot be guaranteed, but there should be no conflicts if they are not
|
||||
controlling the same units.
|
||||
</note-box>
|
||||
|
||||
<div class="next-steps">
|
||||
<a href="/pages/first-start.html">Next: Getting started with Spearhead →</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<p>© 2025 Spearhead Project</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -123,4 +123,3 @@
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
@@ -80,11 +80,22 @@
|
||||
<strong>Example:</strong> <code-inline>MISSION_DEAD_BYRON</code-inline>
|
||||
</p>
|
||||
<p>
|
||||
Missions are completable objectives with specific types, such as DEAD, BAI, STRIKE, or SAM. <br />
|
||||
Missions are completable objectives with specific types. <br />
|
||||
Randomized missions can be defined using the format: <span
|
||||
class="inline-lua"><span class="lua-variable">RANDOMMISSION_[Type]_[Name]_[Index]</span></span>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Valid Types:
|
||||
<ul>
|
||||
<li>SAM</li>
|
||||
<li>DEAD</li>
|
||||
<li>BAI</li>
|
||||
<li>CAS</li>
|
||||
<li>STRIKE</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3 id="cap-routes">CAP Routes</h3>
|
||||
<p>
|
||||
<strong>Format:</strong> <code-inline>CAPROUTE_[routeID]_[Name]</code-inline> <br />
|
||||
|
||||
+35
-37
@@ -66,24 +66,23 @@
|
||||
These are logically ordered zones that will activate one by one based on the mission status in them. <br />
|
||||
There is a little more to it, but you'll find out. <br />
|
||||
|
||||
Stages need to be named according to the convention: <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_[OrderNumber]_[FreeForm]</span></span> <br />
|
||||
The first stage will be called <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1</span></span> or <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_EAST</span></span> for example. <br />
|
||||
Stages need to be named according to the convention: <code-inline>MISSIONSTAGE_[OrderNumber]_[FreeForm]</code-inline> <br />
|
||||
The first stage will be called <code-inline>MISSIONSTAGE_1</code-inline> or <code-inline>MISSIONSTAGE_1_EAST</code-inline> for example. <br />
|
||||
<br /><br />
|
||||
Stages are divided in primary stages: <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_[number]</span></span> <br />
|
||||
or secondary stages: <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_x[number]</span></span> <br />
|
||||
Stages are divided in primary stages: <code-inline>MISSIONSTAGE_[number]</code-inline> <br />
|
||||
or secondary stages: <code-inline>MISSIONSTAGE_x[number]</code-inline> <br />
|
||||
Note the x before the number. This marks it as "extra"
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For this mission we started with the three stages: <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_GROUND</span></span>,
|
||||
<span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_2_WATER</span></span> and <span
|
||||
class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_AIRBASE</span></span> as you see in the image.
|
||||
For this mission we started with the three stages: <code-inline>MISSIONSTAGE_1_GROUND</code-inline>,
|
||||
<code-inline>MISSIONSTAGE_2_WATER</code-inline> and <code-inline>MISSIONSTAGE_1_AIRBASE</code-inline> as you see in the image.
|
||||
</p>
|
||||
<img src="../img/starting_stages.png" style="width: 100%;"></img>
|
||||
<p>
|
||||
<span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_GROUND</span></span> will be activated when the mission starts <br />
|
||||
<span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_WATER</span></span> will be also be activated <br />
|
||||
<span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_2_AIRBASE</span></span> will be activated when the player enters the zone.
|
||||
<code-inline>MISSIONSTAGE_1_GROUND</code-inline>will be activated when the mission starts <br />
|
||||
<code-inline>MISSIONSTAGE_1_WATER</code-inline> will be also be activated <br />
|
||||
<code-inline>MISSIONSTAGE_2_AIRBASE</code-inline> will be activated when the player enters the zone.
|
||||
<br />
|
||||
</p>
|
||||
|
||||
@@ -94,20 +93,19 @@
|
||||
quite the challenge. <br />
|
||||
With the CAP managers we've tried to make this a lot easier. <br />
|
||||
|
||||
A CAP group needs to follow the following naming convention: <span
|
||||
class="inline-lua"><span class="lua-variable">CAP_[A|B][CONFIG]_[Free Form]</span></span>
|
||||
A CAP group needs to follow the following naming convention: <code-inline>CAP_[A|B][CONFIG]_[Free Form]</code-inline>
|
||||
|
||||
For details on config read this: <span class="inline-ref">CAP Group Config</span>
|
||||
For details on config read this: <code-inline>CAP Group Config</code-inline>
|
||||
|
||||
For now I set up 3 groups with the following names. <span class="inline-lua"><span class="lua-variable">CAP_A[1]1_Rota1</span></span>, <span class="inline-lua"><span class="lua-variable">CAP_A[1]1_Rota1-1</span></span>,
|
||||
<span class="inline-lua"><span class="lua-variable">CAP_B[1]1_Rota1</span></span> <br />
|
||||
The first two are marked with <span class="inline-lua"><span class="lua-variable">A</span></span> and will therefore be primary CAP units. They will be
|
||||
For now I set up 3 groups with the following names. <code-inline>CAP_A[1]1_Rota1</code-inline>, <code-inline>CAP_A[1]1_Rota1-1</code-inline>,
|
||||
<code-inline>CAP_B[1]1_Rota1</code-inline> <br />
|
||||
The first two are marked with <code-inline>A</code-inline> and will therefore be primary CAP units. They will be
|
||||
scheduled and make up for the total count. <br />
|
||||
Meaning that for this airbase there is 2 CAP units max at a time flying out. <br />
|
||||
In this case all groups have <span class="inline-lua"><span class="lua-variable">[1]1</span></span> in the name, (This would be the same as <span class="inline-lua"><span class="lua-variable">[1]A</span></span>) which means
|
||||
In this case all groups have <code-inline>[1]1</code-inline> in the name, (This would be the same as <code-inline>[1]A</code-inline>) which means
|
||||
that when stage 1 is active the groups will activate and fly out to stage 1.
|
||||
|
||||
I also set up a few groups further back. One example: <span class="inline-lua"><span class="lua-variable">CAP_A[1-3]3_Group1</span></span>. This group will
|
||||
I also set up a few groups further back. One example: <code-inline>CAP_A[1-3]3_Group1</code-inline>. This group will
|
||||
protect zone 3 when zones 1 through 3 are active.
|
||||
|
||||
CAP units fly out, fly their CAP zone for x amount of minutes and will then RTB. <br />
|
||||
@@ -121,21 +119,21 @@
|
||||
|
||||
<h3 id="creating-cap-routes">Creating CAP Routes</h3>
|
||||
<p>
|
||||
Creating CAP routes is not needed per se, but with a multi-stage stage (we have 2 stages with <span class="inline-lua"><span class="lua-variable">_1_</span></span>) it is recommended. <br/>
|
||||
Creating CAP routes is not needed per se, but with a multi-stage stage (we have 2 stages with <code-inline>_1_</code-inline>) it is recommended. <br/>
|
||||
Similarly with huge stages. <br/>
|
||||
If there is multiple zones it will "round-robin" over them. <br/>
|
||||
</p>
|
||||
<p>
|
||||
If no CAP route is present the unit will fly a route generated differently per zone: <br/>
|
||||
<span class="inline-lua"><span class="lua-variable">quad zone</span></span> => race-track between the corner closest to the origin airbase to the center point of the zone <br/>
|
||||
<span class="inline-lua"><span class="lua-variable">circle zone</span></span> => race-track between the closest point on circle to the origin airbase to the center <br/>
|
||||
<code-inline>quad zone</code-inline> => race-track between the corner closest to the origin airbase to the center point of the zone <br/>
|
||||
<code-inline>circle zone</code-inline> => race-track between the closest point on circle to the origin airbase to the center <br/>
|
||||
</p>
|
||||
<p>
|
||||
If you want to create your own CAP Routes you can! <br/>
|
||||
For this example I created 2 CAP routes inside of the 2 <span class="inline-lua"><span class="lua-variable">_1_</span></span> stages. <br/>
|
||||
For this example I created 2 CAP routes inside of the 2 <code-inline>_1_</code-inline> stages. <br/>
|
||||
</p>
|
||||
<p>
|
||||
As you can see below there's a nice feature you can exploit. As long as the <span class="inline-lua"><span class="lua-variable">X</span></span> of the zone is inside of the the <span class="inline-lua"><span class="lua-variable">CAPROUTE</span></span> will be used for that stage!
|
||||
As you can see below there's a nice feature you can exploit. As long as the <code-inline>X</code-inline> of the zone is inside of the the <code-inline>CAPROUTE</code-inline> will be used for that stage!
|
||||
</p>
|
||||
<img src="../img/cap_routes.png" alt="CAP Routes Image" style="width: 100%;"></img>
|
||||
|
||||
@@ -155,7 +153,7 @@
|
||||
By default DCS will always keep 1 static object in 1 groups.
|
||||
</note-box>
|
||||
<p>
|
||||
For this example I'll set up two missions. The first one is <span class="inline-lua"><span class="lua-variable">DEAD</span></span> mission and will consist of an SA-2 site with an additional "control center".
|
||||
For this example I'll set up two missions. The first one is <code-inline>DEAD</code-inline> mission and will consist of an SA-2 site with an additional "control center".
|
||||
</p>
|
||||
|
||||
<h3 id="mission-1-dead">Mission: DEAD</h3>
|
||||
@@ -173,32 +171,32 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Important to note. It's all inside the triggerzone <span class="inline-lua"><span class="lua-variable">MISSION_DEAD_BYRON</span></span>. Which means it's a <span class="inline-lua"><span class="lua-variable">MISSION</span></span> of type <span class="inline-lua"><span class="lua-variable">DEAD</span></span> and with name <span class="inline-lua"><span class="lua-variable">BYRON</span></span>. <br/>
|
||||
Important to note. It's all inside the triggerzone <code-inline>MISSION_DEAD_BYRON</code-inline>. Which means it's a <code-inline>MISSION</code-inline> of type <code-inline>DEAD</code-inline> and with name <code-inline>BYRON</code-inline>. <br/>
|
||||
At the start Spearhead will detect the triggerzone, take all units and despawn them and only spawn when needed for better performance. <br/>
|
||||
</p>
|
||||
<p>
|
||||
The current list of mission types are:
|
||||
<span class="inline-lua"><span class="lua-variable">DEAD</span></span>
|
||||
<span class="inline-lua"><span class="lua-variable">STRIKE</span></span>
|
||||
<span class="inline-lua"><span class="lua-variable">BAI</span></span>
|
||||
<span class="inline-lua"><span class="lua-variable">SAM</span></span> <br/>
|
||||
<code-inline>DEAD</code-inline>
|
||||
<code-inline>STRIKE</code-inline>
|
||||
<code-inline>BAI</code-inline>
|
||||
<code-inline>SAM</code-inline> <br/>
|
||||
For specific differences, please check the reference page.
|
||||
</p>
|
||||
<p>
|
||||
Each type has some additional completion logic to it. <br/>
|
||||
<span class="inline-lua"><span class="lua-variable">DEAD</span></span> and <span class="inline-lua"><span class="lua-variable">SAM</span></span> missions will be marked complete when all air defences are destroyed. This includes Tracking Radars, Self tracking launchers and AAA guns if they are inside the zone. <br/>
|
||||
If you want to add the Search radar or another random unit like the command tent to the target list you can add a <span class="inline-lua"><span class="lua-variable">TGT_</span></span> prefix to the unit or group you want destroyed. <br/>
|
||||
Please be aware that adding <span class="inline-lua"><span class="lua-variable">TGT_</span></span> to a group will make the entire group a target and therefore each unit needs to be destroyed. <br/>
|
||||
<code-inline>DEAD</code-inline> and <code-inline>SAM</code-inline> missions will be marked complete when all air defences are destroyed. This includes Tracking Radars, Self tracking launchers and AAA guns if they are inside the zone. <br/>
|
||||
If you want to add the Search radar or another random unit like the command tent to the target list you can add a <code-inline>TGT_</code-inline> prefix to the unit or group you want destroyed. <br/>
|
||||
Please be aware that adding <code-inline>TGT_</code-inline> to a group will make the entire group a target and therefore each unit needs to be destroyed. <br/>
|
||||
</p>
|
||||
|
||||
<h3 id="mission-2-strike">Mission: STRIKE</h3>
|
||||
<p>
|
||||
To show the power of <span class="inline-lua"><span class="lua-variable">TGT_</span></span> targets I'll create a strike mission next.
|
||||
To show the power of <code-inline>TGT_</code-inline> targets I'll create a strike mission next.
|
||||
</p>
|
||||
<p>
|
||||
A nice supply strike mission will do. Add a ship, some containers and some additional units. <br/>
|
||||
Even some SHORADS to spice the whole thing up. <br/>
|
||||
In the picture below all units that are selected and who show up as white (they are actually red) have the prefix <span class="inline-lua"><span class="lua-variable">TGT_</span></span> in front of their name. <br/>
|
||||
In the picture below all units that are selected and who show up as white (they are actually red) have the prefix <code-inline>TGT_</code-inline> in front of their name. <br/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -261,8 +259,8 @@
|
||||
So now we've created some missions we also want to add briefings to them. This is pretty easy with Spearhead. <br/>
|
||||
</p>
|
||||
<p>
|
||||
To do so click on <span class="inline-ref">draw</span> on the left hand pane in the mission editor. This opens up the drawing tools in the editor. <br/>
|
||||
On the right click <span class="inline-ref">TextBox</span> and click somewhere inside the zone to which you want to add the briefing. <br/>
|
||||
To do so click on <code-inline>draw</code-inline> on the left hand pane in the mission editor. This opens up the drawing tools in the editor. <br/>
|
||||
On the right click <code-inline>TextBox</code-inline> and click somewhere inside the zone to which you want to add the briefing. <br/>
|
||||
Give the briefing a name (It's not used, but can be nice to use to reference the briefing later) and add the briefing. <br/>
|
||||
The text box is quite small, but can have a lot of text. Easiest is to edit the text in an editor of choice and paste it into the box afterwards. <br/>
|
||||
</p>
|
||||
@@ -270,7 +268,7 @@
|
||||
Keep the binding layer to "Author" only. That way it doesn't show up for anyone other than in the mission editor.
|
||||
</p>
|
||||
<p>
|
||||
See the two images below. The left shows the <span class="inline-ref">Text Box</span> drawing. The right shows the briefing as shown in the mission.
|
||||
See the two images below. The left shows the <code-inline>Text Box</code-inline> drawing. The right shows the briefing as shown in the mission.
|
||||
</p>
|
||||
<div style="display: flex">
|
||||
<div style="flex: 50%">
|
||||
|
||||
@@ -270,11 +270,11 @@ header nav a:hover::after {
|
||||
border-radius: 8px;
|
||||
|
||||
max-height: 0px;
|
||||
transition: all 1.5s ease;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
max-height: 200px;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
header.collapsible {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
|
||||
local GlobalFleetManager = {}
|
||||
|
||||
local fleetGroups = {}
|
||||
|
||||
GlobalFleetManager.start = function(database)
|
||||
|
||||
local logger = Spearhead.LoggerTemplate.new("CARRIERFLEET", "INFO")
|
||||
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
for _, groupName in pairs(all_groups) do
|
||||
if Spearhead.Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||
local carrierGroup = Spearhead.internal.FleetGroup:new(groupName, database, logger)
|
||||
table.insert(fleetGroups, carrierGroup)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not Spearhead.internal then Spearhead.internal = {} end
|
||||
Spearhead.internal.GlobalFleetManager = GlobalFleetManager
|
||||
+621
-621
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
||||
--Single player purpose
|
||||
|
||||
local defaultLogLevel = "INFO"
|
||||
|
||||
if SpearheadConfig and SpearheadConfig.debugEnabled == true then
|
||||
defaultLogLevel = "DEBUG"
|
||||
end
|
||||
|
||||
local startTime = timer.getTime() * 1000
|
||||
|
||||
Spearhead.Events.Init(defaultLogLevel)
|
||||
|
||||
local dbLogger = Spearhead.LoggerTemplate.new("database", defaultLogLevel)
|
||||
local standardLogger = Spearhead.LoggerTemplate.new("", defaultLogLevel)
|
||||
local databaseManager = Spearhead.DB.New(dbLogger)
|
||||
Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(defaultLogLevel) -- initiate
|
||||
|
||||
local capConfig = Spearhead.internal.configuration.CapConfig:new();
|
||||
local stageConfig = Spearhead.internal.configuration.StageConfig:new();
|
||||
|
||||
local startingStage = stageConfig.startingStage or 1
|
||||
if SpearheadConfig and SpearheadConfig.Persistence and SpearheadConfig.Persistence.enabled == true then
|
||||
standardLogger:info("Persistence enabled")
|
||||
local persistenceLogger = Spearhead.LoggerTemplate.new("Persistence", defaultLogLevel)
|
||||
Spearhead.classes.persistence.Persistence.Init(persistenceLogger)
|
||||
|
||||
local persistanceStage = Spearhead.classes.persistence.Persistence.GetActiveStage()
|
||||
if persistanceStage then
|
||||
standardLogger:info("Persistance activated and using persistant active stage: " .. persistanceStage)
|
||||
startingStage = persistanceStage
|
||||
end
|
||||
else
|
||||
standardLogger:info("Persistence disabled")
|
||||
end
|
||||
|
||||
local spawnLogger = Spearhead.LoggerTemplate.new("SpawnManager", defaultLogLevel)
|
||||
local spawnManager = Spearhead.classes.helpers.SpawnManager.new(spawnLogger)
|
||||
local detectionLogger = Spearhead.LoggerTemplate.new("DetectionManager", defaultLogLevel)
|
||||
local detectionManager = Spearhead.classes.capClasses.detection.DetectionManager.New(detectionLogger)
|
||||
|
||||
Spearhead.classes.capClasses.GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
Spearhead.internal.GlobalStageManager:NewAndStart(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
|
||||
Spearhead.internal.GlobalFleetManager.start(databaseManager)
|
||||
|
||||
local SetStageDelayed = function(number, time)
|
||||
Spearhead.Events.PublishStageNumberChanged(number)
|
||||
return nil
|
||||
end
|
||||
|
||||
timer.scheduleFunction(SetStageDelayed, startingStage, timer.getTime() + 3)
|
||||
|
||||
env.info(startTime .. "ms / " .. timer.getTime() * 1000 .. "ms")
|
||||
local duration = (timer.getTime() * 1000) - startTime
|
||||
standardLogger:info("Spearhead Initialisation duration: " .. tostring(duration) .. "ms")
|
||||
|
||||
Spearhead.LoadingDone()
|
||||
|
||||
Spearhead.internal.GlobalStageManager:printFullOverview()
|
||||
|
||||
--Check lines of code in directory per file:
|
||||
-- Get-ChildItem . -Include *.lua -Recurse | foreach {""+(Get-Content $_).Count + " => " + $_.name }; GCI . -Include *.lua* -Recurse | foreach{(GC $_).Count} | measure-object -sum | % Sum
|
||||
-- find . -name '*.lua' | xargs wc -l
|
||||
|
||||
--- ==================== DEBUG ORDER OR ZONE VEC ===========================
|
||||
-- local zone = Spearhead.DcsUtil.getZoneByName("MISSIONSTAGE_99")
|
||||
|
||||
-- local count = Spearhead.Util.tableLength(zone.verts)
|
||||
|
||||
-- for i = 1, count - 1 do
|
||||
|
||||
-- local a = zone.verts[i]
|
||||
-- local b = zone.verts[i+1]
|
||||
|
||||
-- local color = {0,0,0,1}
|
||||
|
||||
-- color[i] = 1
|
||||
|
||||
-- trigger.action.textToAll(-1, 46+i , { x= a.x, y = 0, z = a.z } , color, {0,0,0}, 24 , true , "" .. i )
|
||||
-- trigger.action.lineToAll(-1 , 56+i , { x= a.x, y = 0, z = a.z } , { x = b.x, y = 0, z = b.z } , color , 1, true)
|
||||
|
||||
-- end
|
||||
@@ -44,7 +44,4 @@ function Queue:toList()
|
||||
return items
|
||||
end
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead._baseClasses == nil then Spearhead._baseClasses = {} end
|
||||
Spearhead._baseClasses.Queue = Queue
|
||||
return Queue
|
||||
@@ -1,3 +1,6 @@
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local GlobalStageManager = require("classes.stageClasses.GlobalStageManager")
|
||||
|
||||
---@type Array<OnMissionCompleteListener>
|
||||
local MissionCompleteListeners = {}
|
||||
|
||||
@@ -16,18 +19,18 @@ SpearheadAPI = {
|
||||
return false, "stageNumber " .. stageNumber .. " is not a valid number"
|
||||
end
|
||||
|
||||
Spearhead.Events.PublishStageNumberChanged(stageNumber)
|
||||
SpearheadEvents.PublishStageNumberChanged(stageNumber)
|
||||
return true, ""
|
||||
end,
|
||||
getCurrentStage = function()
|
||||
return Spearhead.StageNumber or nil
|
||||
return GlobalStageManager.getCurrentStage() or nil
|
||||
end,
|
||||
isStageComplete = function(stageNumber)
|
||||
if type(stageNumber) ~= "number" then
|
||||
return false, "stageNumber " .. stageNumber .. " is not a valid number"
|
||||
end
|
||||
|
||||
local isComplete = Spearhead.internal.GlobalStageManager.isStageComplete(stageNumber)
|
||||
local isComplete = GlobalStageManager.isStageComplete(stageNumber)
|
||||
if isComplete == nil then
|
||||
return nil, "no stage found with number " .. stageNumber
|
||||
end
|
||||
@@ -1,3 +1,11 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
||||
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
||||
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
||||
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
||||
|
||||
---@class CapBase : OnStageChangedListener
|
||||
---@field private airbaseName string
|
||||
---@field private logger table
|
||||
@@ -54,7 +62,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
local baseData = database:getAirbaseDataForZone(airbaseName)
|
||||
if baseData and baseData.CapGroups then
|
||||
for key, name in pairs(baseData.CapGroups) do
|
||||
local capGroup = Spearhead.classes.capClasses.airGroups.CapGroup.New(name, capConfig, logger, spawnManager)
|
||||
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
||||
if capGroup then
|
||||
self.capGroupsByName[name] = capGroup
|
||||
end
|
||||
@@ -63,7 +71,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
|
||||
if baseData and baseData.SweepGroups then
|
||||
for key, name in pairs(baseData.SweepGroups) do
|
||||
local sweepGroup = Spearhead.classes.capClasses.airGroups.SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||
if sweepGroup then
|
||||
self.sweepGroupsByName[name] = sweepGroup
|
||||
end
|
||||
@@ -72,22 +80,21 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
|
||||
if baseData and baseData.InterceptGroups then
|
||||
for key, name in pairs(baseData.InterceptGroups) do
|
||||
local interceptGroup = Spearhead.classes.capClasses.airGroups.InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||
if interceptGroup then
|
||||
self.interceptGroupsByName[name] = interceptGroup
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local capFlights = Spearhead.Util.tableLength(self.capGroupsByName)
|
||||
local sweepFlights = Spearhead.Util.tableLength(self.sweepGroupsByName)
|
||||
local interceptFlights = Spearhead.Util.tableLength(self.interceptGroupsByName)
|
||||
local capFlights = Util.tableLength(self.capGroupsByName)
|
||||
local sweepFlights = Util.tableLength(self.sweepGroupsByName)
|
||||
local interceptFlights = Util.tableLength(self.interceptGroupsByName)
|
||||
|
||||
logger:info(airbaseName .. " : " .. capFlights .." CAP | " .. sweepFlights .. " SWEEP | " .. interceptFlights .. " INTERCEPT")
|
||||
|
||||
self:CreateRunwayStrikeMission(database)
|
||||
|
||||
Spearhead.Events.AddStageNumberChangedListener(self)
|
||||
SpearheadEvents.AddStageNumberChangedListener(self)
|
||||
|
||||
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
||||
|
||||
@@ -111,7 +118,7 @@ function CapBase:CreateRunwayStrikeMission(database)
|
||||
" at airbase " ..
|
||||
self.airbaseName ..
|
||||
" with heading " .. runway.course .. " and length " .. runway.length .. " and width " .. runway.width)
|
||||
local mission = Spearhead.classes.stageClasses.missions.RunwayStrikeMission.new(runway, self.airbaseName,
|
||||
local mission = RunwayStrikeMission.new(runway, self.airbaseName,
|
||||
database, self.logger, self.runwayBombingTracker)
|
||||
self.runwayStrikeMissions[runway.Name] = mission
|
||||
end
|
||||
@@ -338,7 +345,7 @@ function CapBase:CheckAndScheduleIntercept()
|
||||
local unit = Unit.getByName(unitName)
|
||||
if unit and unit:isExist() then
|
||||
local unitPos = unit:getPoint()
|
||||
if Spearhead.Util.is3dPointInZone(unitPos, zone) == true then
|
||||
if Util.is3dPointInZone(unitPos, zone) == true then
|
||||
if not unitsToInterceptPerZone[zone.name] then
|
||||
unitsToInterceptPerZone[zone.name] = {}
|
||||
end
|
||||
@@ -356,7 +363,7 @@ function CapBase:CheckAndScheduleIntercept()
|
||||
|
||||
for name, targets in pairs(unitsToInterceptPerZone) do
|
||||
local required = 0
|
||||
local nrTargets = Spearhead.Util.tableLength(targets)
|
||||
local nrTargets = Util.tableLength(targets)
|
||||
if targets and nrTargets > 0 then
|
||||
required = math.ceil(nrTargets / ratio)
|
||||
end
|
||||
@@ -424,7 +431,4 @@ function CapBase:IsBaseActiveWhenStageIsActive(stageNumber)
|
||||
return false
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
Spearhead.classes.capClasses.CapAirbase = CapBase
|
||||
return CapBase
|
||||
+14
-17
@@ -1,3 +1,9 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
|
||||
local CapAirbase = require("classes.capClasses.CapAirbase")
|
||||
|
||||
---@class GlobalCapManager
|
||||
local GlobalCapManager = {}
|
||||
do
|
||||
local airbasesPerStage = {}
|
||||
@@ -17,9 +23,9 @@ do
|
||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager)
|
||||
if initiated == true then return end
|
||||
|
||||
local logger = Spearhead.LoggerTemplate.new("AirbaseManager", logLevel)
|
||||
local bombTrackLogger = Spearhead.LoggerTemplate.new("RunwayBombingTracker", logLevel)
|
||||
local runwayBombingTracker = Spearhead.classes.capClasses.runwayBombing.RunwayBombingTracker.new(bombTrackLogger)
|
||||
local logger = Logger.new("AirbaseManager", logLevel)
|
||||
local bombTrackLogger = Logger.new("RunwayBombingTracker", logLevel)
|
||||
local runwayBombingTracker = RunwayBombingTracker.new(bombTrackLogger)
|
||||
|
||||
local zones = database:getStagezoneNames()
|
||||
if zones then
|
||||
@@ -32,9 +38,9 @@ do
|
||||
if airbaseNames then
|
||||
for _, airbaseName in pairs(airbaseNames) do
|
||||
if airbaseName then
|
||||
local airbaseSpecificLogger = Spearhead.LoggerTemplate.new("CAP_" .. airbaseName, logLevel)
|
||||
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
||||
|
||||
local airbase = Spearhead.classes.capClasses.CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
|
||||
if airbase then
|
||||
table.insert(airbasesPerStage[stageName], airbase)
|
||||
@@ -46,16 +52,14 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
logger:info("Initiated " .. Spearhead.Util.tableLength(allAirbasesByName) .. " airbases for cap")
|
||||
logger:info("Initiated " .. Util.tableLength(allAirbasesByName) .. " airbases for cap")
|
||||
initiated = true
|
||||
|
||||
local InfoFunctions = {}
|
||||
|
||||
---returns if there is CAP active
|
||||
---@param zoneName any
|
||||
---@param activeZoneNumber number
|
||||
---@return boolean
|
||||
InfoFunctions.IsCapActiveWhenZoneIsActive = function(zoneName, activeZoneNumber)
|
||||
GlobalCapManager.IsCapActiveWhenZoneIsActive = function(zoneName, activeZoneNumber)
|
||||
for _, airbase in pairs(airbasesPerStage[zoneName]) do
|
||||
if airbase:IsBaseActiveWhenStageIsActive(activeZoneNumber) == true then
|
||||
return true
|
||||
@@ -63,14 +67,7 @@ do
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
Spearhead.capInfo = InfoFunctions
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
Spearhead.classes.capClasses.GlobalCapManager = GlobalCapManager
|
||||
return GlobalCapManager
|
||||
+14
-13
@@ -1,3 +1,8 @@
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local RTBMission = require("classes.capClasses.taskings.RTB")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class AirGroup : OnUnitLostListener
|
||||
---@field protected _logger Logger
|
||||
---@field protected _groupName string
|
||||
@@ -26,13 +31,13 @@ function AirGroup:New(groupName, groupType, config, logger, spawnManager)
|
||||
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group then
|
||||
Spearhead.Events.addOnGroupRTBListener(self._groupName, self)
|
||||
Spearhead.Events.addOnGroupRTBInTenListener(self._groupName, self)
|
||||
Spearhead.Events.addOnGroupOnStationListener(self._groupName, self)
|
||||
SpearheadEvents.addOnGroupRTBListener(self._groupName, self)
|
||||
SpearheadEvents.addOnGroupRTBInTenListener(self._groupName, self)
|
||||
SpearheadEvents.addOnGroupOnStationListener(self._groupName, self)
|
||||
|
||||
for _, unit in pairs(group:getUnits()) do
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
Spearhead.Events.addOnUnitLandEventListener(unit:getName(), self)
|
||||
SpearheadEvents.addOnUnitLostEventListener(unit:getName(), self)
|
||||
SpearheadEvents.addOnUnitLandEventListener(unit:getName(), self)
|
||||
end
|
||||
|
||||
spawnManager:DestroyGroup(groupName)
|
||||
@@ -105,7 +110,7 @@ function AirGroup:SendRTB(airbase)
|
||||
end
|
||||
end
|
||||
if location then
|
||||
local mission = Spearhead.classes.capClasses.taskings.RTB.getAsMission(airbase, { x= location.x, y= location.z }, self._config)
|
||||
local mission = RTBMission.getAsMission(airbase, { x= location.x, y= location.z }, self._config)
|
||||
group:getController():setTask(mission)
|
||||
self._logger:debug("AirGroup:SendRTB - Task set for group: " .. self._groupName)
|
||||
end
|
||||
@@ -248,7 +253,7 @@ function AirGroup:OnLastUnitLanded()
|
||||
return time + 5
|
||||
end
|
||||
|
||||
if pos and Spearhead.Util.VectorDistance3d(pos, data.lastLocations[unit:getName()]) > 10 then
|
||||
if pos and Util.VectorDistance3d(pos, data.lastLocations[unit:getName()]) > 10 then
|
||||
data.lastChangeTime = time
|
||||
end
|
||||
data.lastLocations[unit:getName()] = pos
|
||||
@@ -426,14 +431,10 @@ do --EVENT LISTENERS
|
||||
end
|
||||
|
||||
function AirGroup:Destroy()
|
||||
Spearhead.DcsUtil.DestroyGroup(self._groupName)
|
||||
self._spawnManager:DestroyGroup(self._groupName)
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.airGroups then Spearhead.classes.capClasses.airGroups = {} end
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup = AirGroup
|
||||
return AirGroup
|
||||
|
||||
---@alias AirGroupState
|
||||
---| "UnSpawned"
|
||||
+21
-21
@@ -1,3 +1,7 @@
|
||||
local AirGroup = require("classes.capClasses.airGroups.AirGroup")
|
||||
local CAP = require("classes.capClasses.taskings.CAP")
|
||||
local Util = require("classes.util.Util")
|
||||
local MissionEditorWarner = require("classes.util.MissionEditorWarnings")
|
||||
|
||||
---@class CapGroup : AirGroup
|
||||
---@field private _targetZoneIdPerStage table<string, string>
|
||||
@@ -14,9 +18,9 @@ CapGroup.__index = CapGroup
|
||||
---@return CapGroup
|
||||
function CapGroup.New(groupName, config, logger, spawnManager)
|
||||
|
||||
setmetatable(CapGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
setmetatable(CapGroup, AirGroup)
|
||||
local self = setmetatable({}, CapGroup) --[[@as CapGroup]]
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "CAP", config, logger, spawnManager)
|
||||
AirGroup.New(self, groupName, "CAP", config, logger, spawnManager)
|
||||
|
||||
self._targetZoneIdPerStage = {}
|
||||
|
||||
@@ -65,10 +69,10 @@ function CapGroup:SendToZone(zone, targetZoneID, airbase)
|
||||
end
|
||||
|
||||
if isInAir == true then
|
||||
local mission = Spearhead.classes.capClasses.taskings.CAP.getAsMission(self._groupName, airbase, zone, self._config)
|
||||
local mission = CAP.getAsMission(self._groupName, airbase, zone, self._config)
|
||||
self:SetMission(mission)
|
||||
else
|
||||
local mission = Spearhead.classes.capClasses.taskings.CAP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||
local mission = CAP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||
if mission then
|
||||
self:SetMission(mission)
|
||||
else
|
||||
@@ -80,8 +84,8 @@ end
|
||||
|
||||
---@private
|
||||
function CapGroup:InitWithName(groupName)
|
||||
local split_string = Spearhead.Util.split_string(groupName, "_")
|
||||
local partCount = Spearhead.Util.tableLength(split_string)
|
||||
local split_string = Util.split_string(groupName, "_")
|
||||
local partCount = Util.tableLength(split_string)
|
||||
if partCount >= 3 then
|
||||
|
||||
local configPart = split_string[2]
|
||||
@@ -95,34 +99,34 @@ function CapGroup:InitWithName(groupName)
|
||||
elseif first == "[" then
|
||||
self._isBackup = false
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("Could not parse the CAP config for group: " .. groupName)
|
||||
MissionEditorWarner.Add("Could not parse the CAP config for group: " .. groupName)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
local subsplit = Spearhead.Util.split_string(configPart, "|")
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Spearhead.Util.split_string(value, "]")
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Spearhead.Util.split_string(allActives, ",")
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Spearhead.Util.split_string(value, "-")
|
||||
if Spearhead.Util.tableLength(dashSeperated) > 1 then
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
for i = from, till do
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(i)] = string.gsub(targetZone, "A", tostring(i))
|
||||
else
|
||||
self._targetZoneIdPerStage[tostring(i)] = targetZone
|
||||
end
|
||||
end
|
||||
else
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(dashSeperated[1])] = string.gsub(targetZone, "A", tostring(dashSeperated[1]))
|
||||
else
|
||||
self._targetZoneIdPerStage[tostring(dashSeperated[1])] = targetZone
|
||||
@@ -132,15 +136,11 @@ function CapGroup:InitWithName(groupName)
|
||||
end
|
||||
end
|
||||
|
||||
env.info("Capgroup parsed with table: " .. Spearhead.Util.toString(self._targetZoneIdPerStage))
|
||||
env.info("Capgroup parsed with table: " .. Util.toString(self._targetZoneIdPerStage))
|
||||
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("CAP Group with name: " .. groupName .. "should have at least 3 parts, but has " .. partCount)
|
||||
MissionEditorWarner.Add("CAP Group with name: " .. groupName .. "should have at least 3 parts, but has " .. partCount)
|
||||
end
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.airGroups then Spearhead.classes.capClasses.airGroups = {} end
|
||||
Spearhead.classes.capClasses.airGroups.CapGroup = CapGroup
|
||||
return CapGroup
|
||||
+29
-25
@@ -1,3 +1,9 @@
|
||||
local AirGroup = require("classes.capClasses.airGroups.AirGroup")
|
||||
local INTERCEPT = require("classes.capClasses.taskings.INTERCEPT")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local MissionEditorWarner = require("classes.util.MissionEditorWarnings")
|
||||
|
||||
---@class InterceptGroup : AirGroup
|
||||
---@field private _targetNames Array<string>
|
||||
---@field private _targetZoneName string
|
||||
@@ -22,9 +28,9 @@ InterceptGroup.__index = InterceptGroup
|
||||
---@return InterceptGroup?
|
||||
function InterceptGroup.New(groupName, config, logger, detectionManager, spawnManager)
|
||||
|
||||
setmetatable(InterceptGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
setmetatable(InterceptGroup, AirGroup)
|
||||
local self = setmetatable({}, InterceptGroup)
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "INTERCEPT", config, logger, spawnManager)
|
||||
AirGroup.New(self, groupName, "INTERCEPT", config, logger, spawnManager)
|
||||
|
||||
local group = Group.getByName(groupName)
|
||||
if not group then
|
||||
@@ -80,7 +86,9 @@ function InterceptGroup:SetTargetUnits(unitNames)
|
||||
self:UpdateTask()
|
||||
|
||||
if self._updateTaskID then
|
||||
timer.removeFunction(self._updateTaskID)
|
||||
pcall(function()
|
||||
timer.removeFunction(self._updateTaskID)
|
||||
end)
|
||||
end
|
||||
|
||||
local updateContinous = function(selfA, time)
|
||||
@@ -133,7 +141,7 @@ function InterceptGroup:GetClosestTarget()
|
||||
local targetUnit = Unit.getByName(targetName)
|
||||
if targetUnit and targetUnit:isExist() then
|
||||
local pos = targetUnit:getPoint()
|
||||
local distance = Spearhead.Util.VectorDistance3d(groupPoint, pos)
|
||||
local distance = Util.VectorDistance3d(groupPoint, pos)
|
||||
if distance < closestDistance then
|
||||
closestDistance = distance
|
||||
closestUnit = targetUnit
|
||||
@@ -177,7 +185,7 @@ function InterceptGroup:UpdateTask()
|
||||
end
|
||||
end
|
||||
|
||||
if Spearhead.DcsUtil.IsBingoFuel(self._groupName) then
|
||||
if DcsUtil.IsBingoFuel(self._groupName) then
|
||||
self._logger:debug("InterceptGroup: " .. self._groupName .. " is at bingo fuel, returning to base")
|
||||
self:SendRTB(self._airbase)
|
||||
return nil -- Return to base if bingo fuel
|
||||
@@ -185,7 +193,7 @@ function InterceptGroup:UpdateTask()
|
||||
|
||||
if selfDetected and self:IsInAir() == true then
|
||||
if self._currentTargetName and self._currentTargetName == closestUnit:getName() then
|
||||
local distance = Spearhead.Util.VectorDistance3d(closestUnit:getPoint(), groupPoint)
|
||||
local distance = Util.VectorDistance3d(closestUnit:getPoint(), groupPoint)
|
||||
if distance < 30 * 1852 then
|
||||
-- If the target is within 10 nautical miles, continue attacking
|
||||
self._logger:debug("InterceptGroup: " .. self._groupName .. " continues attacking target " .. closestUnit:getName())
|
||||
@@ -197,7 +205,7 @@ function InterceptGroup:UpdateTask()
|
||||
local vec3 = closestUnit:getPoint()
|
||||
local vec2 = { x = vec3.x, y = vec3.z }
|
||||
local groupPointVec2 = { x = groupPoint.x, y = groupPoint.z }
|
||||
local mission = Spearhead.classes.capClasses.taskings.INTERCEPT.getUnitInterceptMissionFromAir(self._groupName, groupPointVec2, vec2, closestUnit, self._airbase, self._config, self._maxSpeed, alt)
|
||||
local mission = INTERCEPT.getUnitInterceptMissionFromAir(self._groupName, groupPointVec2, vec2, closestUnit, self._airbase, self._config, self._maxSpeed, alt)
|
||||
self:SetMission(mission)
|
||||
self._currentTargetName = closestUnit:getName()
|
||||
return 15 -- Just continue attacking the detected target
|
||||
@@ -217,7 +225,7 @@ function InterceptGroup:UpdateTask()
|
||||
local mission = nil
|
||||
if self:IsInAir() == true then
|
||||
-- If the group is in the air, create an intercept mission
|
||||
mission = Spearhead.classes.capClasses.taskings.INTERCEPT.getMissionFromInAir(
|
||||
mission = INTERCEPT.getMissionFromInAir(
|
||||
self._groupName,
|
||||
{ x = groupPoint.x, y = groupPoint.z },
|
||||
interceptPoint,
|
||||
@@ -227,7 +235,7 @@ function InterceptGroup:UpdateTask()
|
||||
alt
|
||||
)
|
||||
else
|
||||
mission = Spearhead.classes.capClasses.taskings.INTERCEPT.getMissionFromAirbase(
|
||||
mission = INTERCEPT.getMissionFromAirbase(
|
||||
self._groupName,
|
||||
interceptPoint,
|
||||
self._airbase,
|
||||
@@ -308,33 +316,33 @@ end
|
||||
|
||||
---@private
|
||||
function InterceptGroup:InitWithName(groupName)
|
||||
local split_string = Spearhead.Util.split_string(groupName, "_")
|
||||
local partCount = Spearhead.Util.tableLength(split_string)
|
||||
local split_string = Util.split_string(groupName, "_")
|
||||
local partCount = Util.tableLength(split_string)
|
||||
if partCount >= 3 then
|
||||
local configPart = split_string[2]
|
||||
configPart = string.sub(configPart, 2, #configPart)
|
||||
local subsplit = Spearhead.Util.split_string(configPart, "|")
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Spearhead.Util.split_string(value, "]")
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Spearhead.Util.split_string(allActives, ",")
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Spearhead.Util.split_string(value, "-")
|
||||
if Spearhead.Util.tableLength(dashSeperated) > 1 then
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
for i = from, till do
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(i)] = string.gsub(targetZone, "A", tostring(i))
|
||||
else
|
||||
self._targetZoneIdPerStage[tostring(i)] = targetZone
|
||||
end
|
||||
end
|
||||
else
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(dashSeperated[1])] = string.gsub(targetZone, "A", tostring(dashSeperated[1]))
|
||||
else
|
||||
self._targetZoneIdPerStage[tostring(dashSeperated[1])] = targetZone
|
||||
@@ -344,16 +352,12 @@ function InterceptGroup:InitWithName(groupName)
|
||||
end
|
||||
end
|
||||
|
||||
env.info("interceptGroup parsed with table: " .. Spearhead.Util.toString(self._targetZoneIdPerStage))
|
||||
env.info("interceptGroup parsed with table: " .. Util.toString(self._targetZoneIdPerStage))
|
||||
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("CAP Group with name: " .. groupName .. "should have at least 3 parts, but has " .. partCount)
|
||||
MissionEditorWarner.Add("CAP Group with name: " .. groupName .. "should have at least 3 parts, but has " .. partCount)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.airGroups then Spearhead.classes.capClasses.airGroups = {} end
|
||||
Spearhead.classes.capClasses.airGroups.InterceptGroup = InterceptGroup
|
||||
return InterceptGroup
|
||||
+20
-19
@@ -1,3 +1,8 @@
|
||||
local AirGroup = require("classes.capClasses.airGroups.AirGroup")
|
||||
local SWEEP = require("classes.capClasses.taskings.SWEEP")
|
||||
local Util = require("classes.util.Util")
|
||||
local MissionEditorWarner = require("classes.util.MissionEditorWarnings")
|
||||
|
||||
---@class SweepGroup : AirGroup
|
||||
---@field _targetZoneIdPerStage table<number, string>
|
||||
---@field _currentTargetZoneID string?
|
||||
@@ -11,9 +16,9 @@ SweepGroup.__index = SweepGroup
|
||||
---@param spawnManager SpawnManager
|
||||
---@return SweepGroup
|
||||
function SweepGroup.New(groupName, config, logger, spawnManager)
|
||||
setmetatable(SweepGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
setmetatable(SweepGroup, AirGroup)
|
||||
local self = setmetatable({}, SweepGroup) --[[@as SweepGroup]]
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "SWEEP", config, logger, spawnManager)
|
||||
AirGroup.New(self, groupName, "SWEEP", config, logger, spawnManager)
|
||||
|
||||
self._targetZoneIdPerStage = {}
|
||||
self:InitWithName(groupName)
|
||||
@@ -47,7 +52,7 @@ function SweepGroup:SendToZone(zone, targetZoneID, airbase)
|
||||
|
||||
local group = Group.getByName(self._groupName)
|
||||
|
||||
local mission = Spearhead.classes.capClasses.taskings.SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||
if mission then
|
||||
---@type SetTaskParams
|
||||
local params = {
|
||||
@@ -68,35 +73,35 @@ end
|
||||
|
||||
---@private
|
||||
function SweepGroup:InitWithName(groupName)
|
||||
local split_string = Spearhead.Util.split_string(groupName, "_")
|
||||
local partCount = Spearhead.Util.tableLength(split_string)
|
||||
local split_string = Util.split_string(groupName, "_")
|
||||
local partCount = Util.tableLength(split_string)
|
||||
if partCount >= 3 then
|
||||
|
||||
local configPart = split_string[2]
|
||||
configPart = string.sub(configPart, 2, #configPart)
|
||||
|
||||
local subsplit = Spearhead.Util.split_string(configPart, "|")
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Spearhead.Util.split_string(value, "]")
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Spearhead.Util.split_string(allActives, ",")
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Spearhead.Util.split_string(value, "-")
|
||||
if Spearhead.Util.tableLength(dashSeperated) > 1 then
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
for i = from, till do
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(i)] = string.gsub(targetZone, "A", tostring(i))
|
||||
else
|
||||
self._targetZoneIdPerStage[tostring(i)] = targetZone
|
||||
end
|
||||
end
|
||||
else
|
||||
if Spearhead.Util.strContains(targetZone, "A") == true then
|
||||
if Util.strContains(targetZone, "A") == true then
|
||||
self._targetZoneIdPerStage[tostring(dashSeperated[1])] = string.gsub(targetZone, "A",
|
||||
tostring(dashSeperated[1]))
|
||||
else
|
||||
@@ -107,15 +112,11 @@ function SweepGroup:InitWithName(groupName)
|
||||
end
|
||||
end
|
||||
|
||||
env.info("SweepGroup parsed with table: " .. Spearhead.Util.toString(self._targetZoneIdPerStage))
|
||||
env.info("SweepGroup parsed with table: " .. Util.toString(self._targetZoneIdPerStage))
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("SWEEP Group with name: " ..
|
||||
MissionEditorWarner.Add("SWEEP Group with name: " ..
|
||||
groupName .. "should have at least 3 parts, but has " .. partCount)
|
||||
end
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.airGroups then Spearhead.classes.capClasses.airGroups = {} end
|
||||
Spearhead.classes.capClasses.airGroups.SweepGroup = SweepGroup
|
||||
return SweepGroup
|
||||
+1
-5
@@ -161,8 +161,4 @@ function DetectionManager:UpdateDetectedUnitsByCoalition(coalitionSide)
|
||||
end
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.detection then Spearhead.classes.capClasses.detection = {} end
|
||||
Spearhead.classes.capClasses.detection.DetectionManager = DetectionManager
|
||||
return DetectionManager
|
||||
+6
-9
@@ -1,3 +1,6 @@
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class RunwayBombingTracker : OnWeaponFiredListener
|
||||
---@field trackedRunways table<Runway, RunwayStrikeMission>
|
||||
---@field private _logger Logger
|
||||
@@ -11,8 +14,7 @@ function RunwayBombingTracker.new(logger)
|
||||
local self = setmetatable({}, RunwayBombingTracker)
|
||||
|
||||
self._logger = logger
|
||||
|
||||
Spearhead.Events.AddWeaponFiredListener(self)
|
||||
SpearheadEvents.AddWeaponFiredListener(self)
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -111,15 +113,10 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
|
||||
|
||||
local zone= strikeMission:GetRunwayZone()
|
||||
|
||||
if Spearhead.Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||
strikeMission:RunwayHit(impactPoint, explosiveMass)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.runwayBombing then Spearhead.classes.capClasses.runwayBombing = {} end
|
||||
Spearhead.classes.capClasses.runwayBombing.RunwayBombingTracker = RunwayBombingTracker
|
||||
return RunwayBombingTracker
|
||||
@@ -1,3 +1,6 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local RTB = require("classes.capClasses.taskings.RTB")
|
||||
|
||||
---@class CAPTasking
|
||||
local CAP = {}
|
||||
|
||||
@@ -38,7 +41,7 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
||||
for indexA, pointA in ipairs(capZone.verts) do
|
||||
for indexB, pointB in ipairs(capZone.verts) do
|
||||
if pointA ~= pointB then
|
||||
local distance = Spearhead.Util.VectorDistance2d(pointA, pointB)
|
||||
local distance = Util.VectorDistance2d(pointA, pointB)
|
||||
if distance > furthestDistance then
|
||||
furthestDistance = distance
|
||||
furthestA = indexA
|
||||
@@ -58,12 +61,12 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
||||
local furthest = pointA
|
||||
local closest = pointB
|
||||
|
||||
local heading = Spearhead.Util.vectorHeadingFromTo(pointA, pointB)
|
||||
local heading = Util.vectorHeadingFromTo(pointA, pointB)
|
||||
|
||||
if Spearhead.Util.VectorDistance2d(baseVec2, pointB) > Spearhead.Util.VectorDistance2d(baseVec2, pointA) then
|
||||
if Util.VectorDistance2d(baseVec2, pointB) > Util.VectorDistance2d(baseVec2, pointA) then
|
||||
furthest = pointB
|
||||
closest = pointA
|
||||
heading = Spearhead.Util.vectorHeadingFromTo(pointB, pointA)
|
||||
heading = Util.vectorHeadingFromTo(pointB, pointA)
|
||||
end
|
||||
|
||||
local distance = furthestDistance
|
||||
@@ -87,8 +90,8 @@ end
|
||||
local GetOutboundTask = function(airbase, capZone, capConfig)
|
||||
local airbaseVec3 = airbase:getPoint()
|
||||
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
||||
local heading = Spearhead.Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
|
||||
local point = Spearhead.Util.vectorMove(airbaseVec2, heading, 18520)
|
||||
local heading = Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
|
||||
local point = Util.vectorMove(airbaseVec2, heading, 18520)
|
||||
|
||||
return {
|
||||
alt = 2000,
|
||||
@@ -130,9 +133,9 @@ function CAP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
||||
[1] = GetOutboundTask(airbase, capZone, capConfig),
|
||||
[2] = GetOutboundTask(airbase, capZone, capConfig),
|
||||
[3] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
|
||||
[4] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[5] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[6] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[4] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[5] = RTB.getInitialPoint(airbase),
|
||||
[6] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -155,9 +158,9 @@ end
|
||||
function CAP.getAsMission(groupName, airbase, capZone, capConfig)
|
||||
local points = {
|
||||
[1] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
|
||||
[2] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[3] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[4] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[2] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[3] = RTB.getInitialPoint(airbase),
|
||||
[4] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -320,8 +323,4 @@ function CAP.getAsTasking(groupName, airbase, capZone, capConfig)
|
||||
}
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.taskings then Spearhead.classes.capClasses.taskings = {} end
|
||||
Spearhead.classes.capClasses.taskings.CAP = CAP
|
||||
return CAP
|
||||
+14
-17
@@ -1,4 +1,5 @@
|
||||
|
||||
local Util = require("classes.util.Util")
|
||||
local RTB = require("classes.capClasses.taskings.RTB")
|
||||
|
||||
---@class InterceptTasking
|
||||
local INTERCEPT = {}
|
||||
@@ -14,11 +15,11 @@ function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, con
|
||||
|
||||
local airbaseVec3 = airbase:getPoint()
|
||||
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
||||
local heading = Spearhead.Util.vectorHeadingFromTo(airbaseVec2, interceptPoint)
|
||||
local heading = Util.vectorHeadingFromTo(airbaseVec2, interceptPoint)
|
||||
|
||||
env.info("BLAAT: heading from runway to first point: " .. heading)
|
||||
|
||||
local point = Spearhead.Util.vectorMove(airbaseVec2, heading, 3*1852)
|
||||
local point = Util.vectorMove(airbaseVec2, heading, 3*1852)
|
||||
|
||||
local pointA, pointB, pointC, pointD = INTERCEPT.getInterceptTaskPoint(groupName, point, interceptPoint, airbaseVec2, config, speed, alt)
|
||||
|
||||
@@ -28,9 +29,9 @@ function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, con
|
||||
[3] = pointB,
|
||||
[4] = pointC,
|
||||
[5] = pointD,
|
||||
[6] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, interceptPoint, config),
|
||||
[7] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[8] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[6] = RTB.getApproachPoint(airbase, interceptPoint, config),
|
||||
[7] = RTB.getInitialPoint(airbase),
|
||||
[8] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -67,9 +68,9 @@ function INTERCEPT.getMissionFromInAir(groupName, currentPosition, interceptPoin
|
||||
[3] = pointB,
|
||||
[4] = pointC,
|
||||
[5] = pointD,
|
||||
[6] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, interceptPoint, config),
|
||||
[7] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[8] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[6] = RTB.getApproachPoint(airbase, interceptPoint, config),
|
||||
[7] = RTB.getInitialPoint(airbase),
|
||||
[8] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -109,9 +110,9 @@ function INTERCEPT.getUnitInterceptMissionFromAir(groupName, currentPoint, targe
|
||||
[3] = pointB,
|
||||
[4] = pointC,
|
||||
[5] = pointD,
|
||||
[6] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, currentPoint, config),
|
||||
[7] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[8] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[6] = RTB.getApproachPoint(airbase, currentPoint, config),
|
||||
[7] = RTB.getInitialPoint(airbase),
|
||||
[8] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -392,8 +393,4 @@ function INTERCEPT.getUnitInterceptTaskPoint(groupName, currentPoint, targetPosi
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.taskings then Spearhead.classes.capClasses.taskings = {} end
|
||||
Spearhead.classes.capClasses.taskings.INTERCEPT = INTERCEPT
|
||||
return INTERCEPT
|
||||
@@ -1,3 +1,4 @@
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class RTBTasking
|
||||
local RTB = {}
|
||||
@@ -33,7 +34,7 @@ local getRunwayIntoWindCourseRad = function(airbase)
|
||||
local runways = airbase:getRunways()
|
||||
|
||||
local windVec = atmosphere.getWind(airbase:getPoint())
|
||||
local mPerS = Spearhead.Util.vectorMagnitude(windVec)
|
||||
local mPerS = Util.vectorMagnitude(windVec)
|
||||
|
||||
if mPerS > 0 then
|
||||
for i = 1, #runways do
|
||||
@@ -48,7 +49,7 @@ local getRunwayIntoWindCourseRad = function(airbase)
|
||||
end
|
||||
|
||||
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
||||
local alignment = Spearhead.Util.vectorAlignment(windVec, runwayVec)
|
||||
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
||||
|
||||
if minAlignment == nil or alignment < minAlignment then
|
||||
activeCourse = i
|
||||
@@ -68,7 +69,7 @@ local getRunwayIntoWindCourseRad = function(airbase)
|
||||
end
|
||||
|
||||
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
||||
local alignment = Spearhead.Util.vectorAlignment(windVec, runwayVec)
|
||||
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
||||
|
||||
if minAlignment == nil or alignment < minAlignment then
|
||||
activeCourse = i
|
||||
@@ -102,7 +103,7 @@ local function calcInitialPoint(airbase)
|
||||
local flipped = (heading + 180) % 360
|
||||
local basePoint = airbase:getPoint()
|
||||
local basePointVec2 = {x = basePoint.x, y = basePoint.z}
|
||||
local point = Spearhead.Util.vectorMove(basePointVec2, flipped, 22000)
|
||||
local point = Util.vectorMove(basePointVec2, flipped, 22000)
|
||||
|
||||
return point, flipped
|
||||
|
||||
@@ -116,10 +117,10 @@ end
|
||||
function RTB.getApproachPoint(airbase, missionPoint, capConfig)
|
||||
|
||||
local initialPoint, headingFromRunway = calcInitialPoint(airbase)
|
||||
local pointA = Spearhead.Util.vectorMove(initialPoint, headingFromRunway - 45, 9000)
|
||||
local pointB = Spearhead.Util.vectorMove(initialPoint, headingFromRunway + 45, 9000)
|
||||
local pointA = Util.vectorMove(initialPoint, headingFromRunway - 45, 9000)
|
||||
local pointB = Util.vectorMove(initialPoint, headingFromRunway + 45, 9000)
|
||||
|
||||
if Spearhead.Util.VectorDistance2d(missionPoint, pointA) > Spearhead.Util.VectorDistance2d(missionPoint, pointB) then
|
||||
if Util.VectorDistance2d(missionPoint, pointA) > Util.VectorDistance2d(missionPoint, pointB) then
|
||||
pointA = pointB
|
||||
end
|
||||
|
||||
@@ -194,8 +195,4 @@ function RTB.getLandingPoint(airbase)
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.taskings then Spearhead.classes.capClasses.taskings = {} end
|
||||
Spearhead.classes.capClasses.taskings.RTB = RTB
|
||||
return RTB
|
||||
@@ -1,3 +1,6 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local RTB = require("classes.capClasses.taskings.RTB")
|
||||
|
||||
---@class SWEEPTasking
|
||||
local SWEEP = {}
|
||||
|
||||
@@ -31,7 +34,7 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
||||
for indexA, pointA in ipairs(capZone.verts) do
|
||||
for indexB, pointB in ipairs(capZone.verts) do
|
||||
if pointA ~= pointB then
|
||||
local distance = Spearhead.Util.VectorDistance2d(pointA, pointB)
|
||||
local distance = Util.VectorDistance2d(pointA, pointB)
|
||||
if distance > furthestDistance then
|
||||
furthestDistance = distance
|
||||
furthestA = indexA
|
||||
@@ -51,12 +54,12 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
||||
local furthest = pointA
|
||||
local closest = pointB
|
||||
|
||||
local heading = Spearhead.Util.vectorHeadingFromTo(pointA, pointB)
|
||||
local heading = Util.vectorHeadingFromTo(pointA, pointB)
|
||||
|
||||
if Spearhead.Util.VectorDistance2d(baseVec2, pointB) > Spearhead.Util.VectorDistance2d(baseVec2, pointA) then
|
||||
if Util.VectorDistance2d(baseVec2, pointB) > Util.VectorDistance2d(baseVec2, pointA) then
|
||||
furthest = pointB
|
||||
closest = pointA
|
||||
heading = Spearhead.Util.vectorHeadingFromTo(pointB, pointA)
|
||||
heading = Util.vectorHeadingFromTo(pointB, pointA)
|
||||
end
|
||||
|
||||
local distance = furthestDistance
|
||||
@@ -80,8 +83,8 @@ end
|
||||
local GetOutboundTask = function(airbase, capZone, capConfig)
|
||||
local airbaseVec3 = airbase:getPoint()
|
||||
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
||||
local heading = Spearhead.Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
|
||||
local point = Spearhead.Util.vectorMove(airbaseVec2, heading, 18520)
|
||||
local heading = Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
|
||||
local point = Util.vectorMove(airbaseVec2, heading, 18520)
|
||||
|
||||
return {
|
||||
alt = 2000,
|
||||
@@ -128,9 +131,9 @@ function SWEEP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
||||
[3] = pointA,
|
||||
[4] = pointB,
|
||||
[5] = pointC,
|
||||
[6] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[7] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
|
||||
[8] = Spearhead.classes.capClasses.taskings.RTB.getLandingPoint(airbase)
|
||||
[6] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
|
||||
[7] = RTB.getInitialPoint(airbase),
|
||||
[8] = RTB.getLandingPoint(airbase)
|
||||
}
|
||||
|
||||
local mission = {
|
||||
@@ -280,8 +283,4 @@ function SWEEP.getAsTasking(groupName, airbase, capZone, capConfig)
|
||||
return pointA, pointB, pointC
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
|
||||
if not Spearhead.classes.capClasses.taskings then Spearhead.classes.capClasses.taskings = {} end
|
||||
Spearhead.classes.capClasses.taskings.SWEEP = SWEEP
|
||||
return SWEEP
|
||||
@@ -95,6 +95,4 @@ function CapConfig:getDeathDelay()
|
||||
return self._deathDelay
|
||||
end
|
||||
|
||||
if not Spearhead.internal then Spearhead.internal = {} end
|
||||
if not Spearhead.internal.configuration then Spearhead.internal.configuration = {} end
|
||||
Spearhead.internal.configuration.CapConfig = CapConfig;
|
||||
return CapConfig
|
||||
@@ -29,6 +29,5 @@ function GlobalConfig:getBriefingTime()
|
||||
end
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
Spearhead.GlobalConfig = GlobalConfig.New()
|
||||
return GlobalConfig
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
--- @field startingStage integer
|
||||
--- @field maxMissionsPerStage integer
|
||||
--- @field AmountPreactivateStage integer
|
||||
|
||||
|
||||
local StageConfig = {};
|
||||
|
||||
---comment
|
||||
@@ -34,6 +32,4 @@ function StageConfig:new()
|
||||
return o;
|
||||
end
|
||||
|
||||
if not Spearhead.internal then Spearhead.internal = {} end
|
||||
if not Spearhead.internal.configuration then Spearhead.internal.configuration = {} end
|
||||
Spearhead.internal.configuration.StageConfig = StageConfig;
|
||||
return StageConfig
|
||||
@@ -1,3 +1,10 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local MissionEditorWarning = require("classes.util.MissionEditorWarnings")
|
||||
local RouteUtil = require("classes.spearhead_routeutil")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
|
||||
---@class FleetGroup
|
||||
local FleetGroup = {}
|
||||
|
||||
---comment
|
||||
@@ -13,9 +20,9 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
o.fleetGroupName = fleetGroupName
|
||||
o.logger = logger
|
||||
|
||||
local split_name = Spearhead.Util.split_string(fleetGroupName, "_")
|
||||
if Spearhead.Util.tableLength(split_name) < 2 then
|
||||
Spearhead.AddMissionEditorWarning("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
||||
local split_name = Util.split_string(fleetGroupName, "_")
|
||||
if Util.tableLength(split_name) < 2 then
|
||||
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
||||
return nil
|
||||
end
|
||||
o.fleetNameIdentifier = split_name[2]
|
||||
@@ -27,12 +34,12 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
do --INIT
|
||||
local carrierRouteZones = database:getCarrierRouteZones()
|
||||
for _, zoneName in pairs(carrierRouteZones) do
|
||||
if Spearhead.Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
if zone and zone.zone_type == Spearhead.DcsUtil.ZoneType.Polygon then
|
||||
local split_string = Spearhead.Util.split_string(zoneName, "_")
|
||||
if Spearhead.Util.tableLength(split_string) < 3 then
|
||||
Spearhead.AddMissionEditorWarning(
|
||||
if Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then
|
||||
local zone = DcsUtil.getZoneByName(zoneName)
|
||||
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
||||
local split_string = Util.split_string(zoneName, "_")
|
||||
if Util.tableLength(split_string) < 3 then
|
||||
MissionEditorWarning.Add(
|
||||
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
||||
else
|
||||
|
||||
@@ -48,7 +55,7 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
for ii = i + 1, 4 do
|
||||
local a = zone.verts[i]
|
||||
local b = zone.verts[ii]
|
||||
local dist = Spearhead.Util.VectorDistance2d(a, b)
|
||||
local dist = Util.VectorDistance2d(a, b)
|
||||
|
||||
if biggest == nil or dist > biggest then
|
||||
biggestA = a
|
||||
@@ -65,17 +72,17 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
if Spearhead.Util.startswith(namePart, "%[") == true then
|
||||
namePart = Spearhead.Util.split_string(namePart, "[")[1]
|
||||
if Util.startswith(namePart, "%[") == true then
|
||||
namePart = Util.split_string(namePart, "[")[1]
|
||||
end
|
||||
|
||||
if Spearhead.Util.strContains(namePart, "%]") == true then
|
||||
namePart = Spearhead.Util.split_string(namePart, "]")[1]
|
||||
if Util.strContains(namePart, "%]") == true then
|
||||
namePart = Util.split_string(namePart, "]")[1]
|
||||
end
|
||||
|
||||
local split_numbers = Spearhead.Util.split_string(namePart, "-")
|
||||
if Spearhead.Util.tableLength(split_numbers) < 2 then
|
||||
Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
local split_numbers = Util.split_string(namePart, "-")
|
||||
if Util.tableLength(split_numbers) < 2 then
|
||||
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
@@ -83,7 +90,7 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
local second = tonumber(split_numbers[2])
|
||||
|
||||
if first == nil or second == nil then
|
||||
Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
return nil, nil
|
||||
end
|
||||
return first, second
|
||||
@@ -97,11 +104,11 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
end
|
||||
o.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
end
|
||||
end
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("CARRIERROUTE cannot be a cilinder: " .. zoneName)
|
||||
MissionEditorWarning.Add("CARRIERROUTE cannot be a cilinder: " .. zoneName)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -115,7 +122,7 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
|
||||
local group = Group.getByName(groupName)
|
||||
if group then
|
||||
logger:info("Sending " .. fleetGroupName .. " to " .. targetZone)
|
||||
logger:info("Sending " .. groupName .. " to " .. targetZone)
|
||||
group:getController():setTask(task)
|
||||
end
|
||||
end
|
||||
@@ -124,14 +131,13 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
||||
local targetZone = self.targetZonePerStage[tostring(number)]
|
||||
if targetZone and targetZone ~= self.currentTargetZone then
|
||||
local points = self.pointsPerZone[targetZone]
|
||||
local task = Spearhead.RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
||||
end
|
||||
end
|
||||
|
||||
Spearhead.Events.AddStageNumberChangedListener(o)
|
||||
SpearheadEvents.AddStageNumberChangedListener(o)
|
||||
return o
|
||||
end
|
||||
|
||||
if not Spearhead.internal then Spearhead.internal = {} end
|
||||
Spearhead.internal.FleetGroup = FleetGroup
|
||||
return FleetGroup
|
||||
@@ -0,0 +1,26 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local FleetGroup = require("classes.fleetClasses.FleetGroup")
|
||||
local MizGroupsManager = require("classes.helpers.MizGroupsManager")
|
||||
|
||||
|
||||
---@class GlobalFleetManager
|
||||
local GlobalFleetManager = {}
|
||||
|
||||
local fleetGroups = {}
|
||||
|
||||
GlobalFleetManager.start = function(database)
|
||||
|
||||
local logger = Logger.new("CARRIERFLEET", "INFO")
|
||||
|
||||
local all_groups = MizGroupsManager.getAllGroupNames()
|
||||
for _, groupName in pairs(all_groups) do
|
||||
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||
local carrierGroup = FleetGroup:new(groupName, database, logger)
|
||||
table.insert(fleetGroups, carrierGroup)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return GlobalFleetManager
|
||||
@@ -1,3 +1,5 @@
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class SpawnData
|
||||
---@field groupTemplate table
|
||||
---@field isStatic boolean
|
||||
@@ -14,17 +16,17 @@ MizGroupsManager._spawnTemplateData = {}
|
||||
|
||||
do --init
|
||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
||||
local coalition_nr = Spearhead.DcsUtil.stringToCoalition(coalition_name)
|
||||
local coalition_nr = DcsUtil.stringToCoalition(coalition_name)
|
||||
if coalition_data.country then
|
||||
for country_index, country_data in pairs(coalition_data.country) do
|
||||
for category_name, categorydata in pairs(country_data) do
|
||||
local category_id = Spearhead.DcsUtil.stringToGroupCategory(category_name)
|
||||
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
||||
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
|
||||
for group_index, group in pairs(categorydata.group) do
|
||||
local name = group.name
|
||||
local skippable = false
|
||||
local isStatic = false
|
||||
if category_id == Spearhead.DcsUtil.GroupCategory.STATIC then
|
||||
if category_id == DcsUtil.GroupCategory.STATIC then
|
||||
isStatic = true
|
||||
local unit = group.units[1]
|
||||
if unit and unit.category == "Heliports" then
|
||||
@@ -75,7 +77,4 @@ function MizGroupsManager.getSpawnTemplateData(groupName)
|
||||
return MizGroupsManager._spawnTemplateData[groupName]
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.helpers then Spearhead.classes.helpers = {} end
|
||||
Spearhead.classes.helpers.MizGroupsManager = MizGroupsManager
|
||||
return MizGroupsManager
|
||||
@@ -1,3 +1,8 @@
|
||||
local MizGroupsManager = require("classes.helpers.MizGroupsManager")
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class SpawnManager : OnUnitLostListener
|
||||
---@field private _persistedUnits table<string,boolean>
|
||||
---@field private _logger Logger
|
||||
@@ -29,7 +34,7 @@ end
|
||||
---@return boolean isStatic
|
||||
function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
||||
|
||||
local spawnData = Spearhead.classes.helpers.MizGroupsManager.getSpawnTemplateData(groupName)
|
||||
local spawnData = MizGroupsManager.getSpawnTemplateData(groupName)
|
||||
|
||||
if spawnData == nil then
|
||||
env.error("SpawnManager:SpawnGroup - No spawn template found for group: " .. groupName)
|
||||
@@ -67,7 +72,7 @@ end
|
||||
---@param groupName string
|
||||
---@return boolean
|
||||
function SpawnManager:IsGroupStatic(groupName)
|
||||
local isStatic = Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName)
|
||||
local isStatic = MizGroupsManager.IsGroupStatic(groupName)
|
||||
if isStatic ~= nil then return isStatic end
|
||||
|
||||
return StaticObject.getByName(groupName) ~= nil
|
||||
@@ -89,7 +94,7 @@ function SpawnManager:OnUnitLost(object)
|
||||
heading = heading
|
||||
end
|
||||
|
||||
Spearhead.classes.persistence.Persistence.UnitKilled(
|
||||
Persistence.UnitKilled(
|
||||
name,
|
||||
object:getPoint(),
|
||||
heading,
|
||||
@@ -119,7 +124,7 @@ do --- privates
|
||||
country = override.countryID or spawnData.country
|
||||
end
|
||||
|
||||
local spawnTemplate = Spearhead.Util.deepCopyTable(spawnData.groupTemplate)
|
||||
local spawnTemplate = Util.deepCopyTable(spawnData.groupTemplate)
|
||||
---@type Array<string>
|
||||
local removeableUnitNames = {}
|
||||
--[[
|
||||
@@ -131,8 +136,8 @@ do --- privates
|
||||
for _, unit in pairs(spawnTemplate["units"]) do
|
||||
local name = unit["name"]
|
||||
|
||||
Spearhead.Events.addOnUnitLostEventListener(name, self)
|
||||
local state = Spearhead.classes.persistence.Persistence.UnitState(name)
|
||||
SpearheadEvents.addOnUnitLostEventListener(name, self)
|
||||
local state = Persistence.UnitState(name)
|
||||
if state then
|
||||
if state.isDead == true then
|
||||
removeableUnitNames[#removeableUnitNames+1] = name
|
||||
@@ -170,7 +175,7 @@ do --- privates
|
||||
if isPersistent == true then
|
||||
self._persistedUnits[unit:getName()] = true
|
||||
end
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
SpearheadEvents.addOnUnitLostEventListener(unit:getName(), self)
|
||||
end
|
||||
|
||||
return group
|
||||
@@ -195,10 +200,10 @@ do --- privates
|
||||
country = overrides.countryID or spawnData.country
|
||||
end
|
||||
|
||||
local spawnTemplate = Spearhead.Util.deepCopyTable(spawnData.groupTemplate)
|
||||
local spawnTemplate = Util.deepCopyTable(spawnData.groupTemplate)
|
||||
|
||||
--for static Objecst groupNames and unit names are the same and is always 1:1
|
||||
local persistentState = Spearhead.classes.persistence.Persistence.UnitState(groupName)
|
||||
local persistentState = Persistence.UnitState(groupName)
|
||||
if persistentState then
|
||||
if persistentState.isDead == true then
|
||||
spawnTemplate["dead"] = true
|
||||
@@ -226,7 +231,7 @@ do --- privates
|
||||
|
||||
if isPersistent == true then
|
||||
self._persistedUnits[groupName] = true
|
||||
Spearhead.Events.addOnUnitLostEventListener(groupName, self)
|
||||
SpearheadEvents.addOnUnitLostEventListener(groupName, self)
|
||||
end
|
||||
|
||||
return object
|
||||
@@ -238,7 +243,7 @@ do --- privates
|
||||
|
||||
if not unit then return end
|
||||
|
||||
local deadState = Spearhead.classes.persistence.Persistence.UnitState(unit:getName())
|
||||
local deadState = Persistence.UnitState(unit:getName())
|
||||
if deadState and deadState.isDead == true then
|
||||
unit:destroy() -- Destroy the unit if it is dead
|
||||
local staticObject = {
|
||||
@@ -255,10 +260,7 @@ do --- privates
|
||||
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.helpers then Spearhead.classes.helpers = {} end
|
||||
Spearhead.classes.helpers.SpawnManager = SpawnManager
|
||||
return SpawnManager
|
||||
|
||||
--Old Spawn Method
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class Perstistence
|
||||
---@field private _path string
|
||||
---@field private _updateRequired boolean
|
||||
@@ -81,7 +83,7 @@ do
|
||||
|
||||
if lua then
|
||||
tables = lua
|
||||
logger:debug("Loaded persistence data: " .. Spearhead.Util.toString(lua))
|
||||
logger:debug("Loaded persistence data: " .. Util.toString(lua))
|
||||
else
|
||||
logger:error("Could not load persistence file, using default tables")
|
||||
end
|
||||
@@ -143,8 +145,8 @@ do
|
||||
local latestFile, lastNumber = default, 0
|
||||
for file in lfs.dir(dir) do
|
||||
|
||||
local split = Spearhead.Util.split_string(file, ".")
|
||||
local doesStartWith = Spearhead.Util.startswith(file, startsWith, true)
|
||||
local split = Util.split_string(file, ".")
|
||||
local doesStartWith = Util.startswith(file, startsWith, true)
|
||||
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
||||
local numberString = split[#split-1]
|
||||
local number = tonumber(numberString)
|
||||
@@ -179,7 +181,7 @@ do
|
||||
if SpearheadConfig.Persistence.fileName then
|
||||
|
||||
local userFileName = SpearheadConfig.Persistence.fileName
|
||||
local split = Spearhead.Util.split_string(userFileName, ".")
|
||||
local split = Util.split_string(userFileName, ".")
|
||||
|
||||
if not split and #split < 3 then
|
||||
split[#split+1] = "0"
|
||||
@@ -199,12 +201,12 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
local split = Spearhead.Util.split_string(fileName, ".")
|
||||
local matchingPart = table.concat(Spearhead.Util.sublist(split, 1, #split-2), ".")
|
||||
local split = Util.split_string(fileName, ".")
|
||||
local matchingPart = table.concat(Util.sublist(split, 1, #split-2), ".")
|
||||
|
||||
local lastFile = getLastFileOrDefault(dir--[[@as string]], matchingPart, fileName)
|
||||
|
||||
local fileSplit = Spearhead.Util.split_string(lastFile, ".")
|
||||
local fileSplit = Util.split_string(lastFile, ".")
|
||||
fileSplit[#fileSplit-1] = tostring(tonumber(fileSplit[#fileSplit-1]) + 1)
|
||||
fileName = table.concat(fileSplit, ".")
|
||||
|
||||
@@ -329,7 +331,4 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.persistence == nil then Spearhead.classes.persistence = {} end
|
||||
Spearhead.classes.persistence.Persistence = Persistence
|
||||
return Persistence
|
||||
@@ -1,3 +1,10 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
local MizGroupsManager = require("classes.helpers.MizGroupsManager")
|
||||
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
||||
|
||||
|
||||
---@class DatabaseTables
|
||||
---@field AllZoneNames Array<string> All Zone Names
|
||||
---@field StageZoneNames Array<string> All Stage Zone Names
|
||||
@@ -20,7 +27,7 @@
|
||||
---@field MissionZoneData table<string, MissionZoneData>
|
||||
---@field FarpZoneData table<string,FarpZoneData>
|
||||
---@field missionCodes table<string, boolean>
|
||||
|
||||
---@field CustomDrawings Array<CustomDrawing>
|
||||
|
||||
---@class CapRoute
|
||||
---@field zones Array<SpearheadTriggerZone>
|
||||
@@ -99,7 +106,8 @@ function Database.New(Logger)
|
||||
MissionZoneData = {},
|
||||
FarpZoneData = {},
|
||||
missionCodes = {},
|
||||
SupplyHubZones = {}
|
||||
SupplyHubZones = {},
|
||||
CustomDrawings = {}
|
||||
}
|
||||
|
||||
Database.__index = Database
|
||||
@@ -111,13 +119,13 @@ function Database.New(Logger)
|
||||
self._logger:debug("Initiating tables")
|
||||
|
||||
do -- INIT ZONE TABLES
|
||||
for zone_ind, zone_data in pairs(Spearhead.DcsUtil.__trigger_zones) do
|
||||
for zone_ind, zone_data in pairs(DcsUtil.__trigger_zones) do
|
||||
local zone_name = zone_data.name
|
||||
|
||||
---@type Vec2
|
||||
local zoneLocation = { x = zone_data.location.x, y = zone_data.location.y }
|
||||
|
||||
local split_string = Spearhead.Util.split_string(zone_name, "_")
|
||||
local split_string = Util.split_string(zone_name, "_")
|
||||
table.insert(self._tables.AllZoneNames, zone_name)
|
||||
|
||||
if string.lower(split_string[1]) == "missionstage" then
|
||||
@@ -187,7 +195,7 @@ function Database.New(Logger)
|
||||
end
|
||||
|
||||
if lowered == "scenerytarget" or lowered == "scenerytargets" then
|
||||
local sceneryObjects = Spearhead.DcsUtil.getSceneryObjectsInZone(zone_data)
|
||||
local sceneryObjects = DcsUtil.getSceneryObjectsInZone(zone_data)
|
||||
for _, sceneryObject in pairs(sceneryObjects) do
|
||||
table.insert(self._tables.AllSceneryObjects, sceneryObject)
|
||||
end
|
||||
@@ -201,7 +209,7 @@ function Database.New(Logger)
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Spearhead.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)
|
||||
if airbaseData then
|
||||
self._logger:debug("found airbase data for " .. layer_object.name)
|
||||
@@ -215,6 +223,23 @@ function Database.New(Logger)
|
||||
end
|
||||
end
|
||||
|
||||
---@type table<integer, boolean>
|
||||
do -- custom drawings
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Util.startswith(layer_object.name, "drawing_", true) then
|
||||
local object = layer_object --[[@as DrawingObject]]
|
||||
local customDrawing = CustomDrawing.New(object)
|
||||
table.insert(self._tables.CustomDrawings, customDrawing)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@type table<string, boolean>
|
||||
local availableSupplyHubs = {}
|
||||
for _, supplyHubZoneName in pairs(self._tables.SupplyHubZones) do
|
||||
@@ -230,10 +255,10 @@ function Database.New(Logger)
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Spearhead.Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(stageZoneName)
|
||||
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||
local zone = DcsUtil.getZoneByName(stageZoneName)
|
||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||
if zone and Spearhead.Util.is2dPointInZone(vec2, zone) == true then
|
||||
if zone and Util.is2dPointInZone(vec2, zone) == true then
|
||||
local description = layer_object.text
|
||||
if description and description ~= "" then
|
||||
stageData.StageBriefing = description
|
||||
@@ -247,18 +272,18 @@ function Database.New(Logger)
|
||||
|
||||
-- fill blue sams
|
||||
for _, blueSamStageName in pairs(self._tables.BlueSams) do
|
||||
if Spearhead.DcsUtil.isZoneInZone(blueSamStageName, stageZoneName) == true then
|
||||
if DcsUtil.isZoneInZone(blueSamStageName, stageZoneName) == true then
|
||||
table.insert(stageData.BlueSamZones, blueSamStageName)
|
||||
end
|
||||
end
|
||||
|
||||
--- fill farp zones
|
||||
for _, farpZoneName in pairs(self._tables.AllFarpZones) do
|
||||
if Spearhead.DcsUtil.isZoneInZone(farpZoneName, stageZoneName) then
|
||||
if DcsUtil.isZoneInZone(farpZoneName, stageZoneName) then
|
||||
table.insert(stageData.FarpZones, farpZoneName)
|
||||
|
||||
for hubZoneName, available in pairs(availableSupplyHubs) do
|
||||
if available == true and Spearhead.DcsUtil.isZoneInZone(hubZoneName, farpZoneName) == true then
|
||||
if available == true and DcsUtil.isZoneInZone(hubZoneName, farpZoneName) == true then
|
||||
local farpZoneData = self:getOrCreateFarpDataForZone(farpZoneName)
|
||||
if farpZoneData then
|
||||
table.insert(farpZoneData.supplyHubNames, hubZoneName)
|
||||
@@ -273,15 +298,15 @@ function Database.New(Logger)
|
||||
for _, airbase in pairs(world.getAirbases()) do
|
||||
local point = airbase:getPoint()
|
||||
|
||||
if Spearhead.DcsUtil.isPositionInZone(point.x, point.z, stageZoneName) == true then
|
||||
if DcsUtil.isPositionInZone(point.x, point.z, stageZoneName) == true then
|
||||
if airbase:getDesc().category == 0 then
|
||||
table.insert(stageData.AirbaseNames, airbase:getName())
|
||||
|
||||
local airbaseZone = Spearhead.DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
local airbaseZone = DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
for hubZoneName, available in pairs(availableSupplyHubs) do
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(hubZoneName)
|
||||
local zone = DcsUtil.getZoneByName(hubZoneName)
|
||||
if zone and airbaseZone then
|
||||
if available == true and Spearhead.Util.is2dPointInZone(zone.location, airbaseZone) == true then
|
||||
if available == true and Util.is2dPointInZone(zone.location, airbaseZone) == true then
|
||||
local airbaseData = self:getOrCreateAirbaseData(airbase:getName())
|
||||
if airbaseData then
|
||||
table.insert(airbaseData.supplyHubNames, hubZoneName)
|
||||
@@ -296,14 +321,14 @@ function Database.New(Logger)
|
||||
|
||||
-- fill supply hubs
|
||||
for supplyHubZone, available in pairs(availableSupplyHubs) do
|
||||
if available == true and Spearhead.DcsUtil.isZoneInZone(supplyHubZone, stageZoneName) == true then
|
||||
if available == true and DcsUtil.isZoneInZone(supplyHubZone, stageZoneName) == true then
|
||||
table.insert(stageData.SupplyHubZones, supplyHubZone)
|
||||
end
|
||||
end
|
||||
|
||||
for _, farpZoneName in pairs(stageData.FarpZones) do
|
||||
for _, supplyHubZone in pairs(self._tables.SupplyHubZones) do
|
||||
if Spearhead.DcsUtil.isZoneInZone(supplyHubZone, farpZoneName) == true then
|
||||
if DcsUtil.isZoneInZone(supplyHubZone, farpZoneName) == true then
|
||||
stageData.SupplyHubZonesInFarp[supplyHubZone] = farpZoneName
|
||||
end
|
||||
end
|
||||
@@ -311,14 +336,14 @@ function Database.New(Logger)
|
||||
|
||||
-- fill missions
|
||||
for key, missionZone in pairs(self._tables.MissionZones) do
|
||||
if Spearhead.DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
table.insert(stageData.MissionZones, missionZone)
|
||||
end
|
||||
end
|
||||
|
||||
-- fill random missions
|
||||
for key, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||
if Spearhead.DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
table.insert(stageData.RandomMissionZones, missionZone)
|
||||
end
|
||||
end
|
||||
@@ -327,13 +352,13 @@ function Database.New(Logger)
|
||||
|
||||
for _, missionZone in pairs(self._tables.MissionZones) do
|
||||
if self._tables.MissionZoneData[missionZone] == nil or self._tables.MissionZoneData[missionZone].description == nil then
|
||||
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing")
|
||||
MissionEditorWarnings.Add("Mission with zonename: " .. missionZone .. " does not have a briefing")
|
||||
end
|
||||
end
|
||||
|
||||
for _, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||
if self._tables.MissionZoneData[missionZone] == nil or self._tables.MissionZoneData[missionZone].description == nil then
|
||||
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing")
|
||||
MissionEditorWarnings.Add("Mission with zonename: " .. missionZone .. " does not have a briefing")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -350,7 +375,7 @@ function Database.New(Logger)
|
||||
}
|
||||
end
|
||||
local position = airbase:getPoint()
|
||||
if Spearhead.DcsUtil.isPositionInZone(position.x, position.z, farpZoneName) == true then
|
||||
if DcsUtil.isPositionInZone(position.x, position.z, farpZoneName) == true then
|
||||
table.insert(self._tables.FarpZoneData[farpZoneName].padNames, name)
|
||||
end
|
||||
end
|
||||
@@ -369,7 +394,7 @@ function Database.New(Logger)
|
||||
|
||||
|
||||
for _, cap_route_zone in pairs(self._tables.AllCapRoutes) do
|
||||
local split = Spearhead.Util.split_string(cap_route_zone, "_")
|
||||
local split = Util.split_string(cap_route_zone, "_")
|
||||
local zoneID = split[2]
|
||||
|
||||
if zoneID then
|
||||
@@ -380,7 +405,7 @@ function Database.New(Logger)
|
||||
}
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(cap_route_zone)
|
||||
local zone = DcsUtil.getZoneByName(cap_route_zone)
|
||||
if zone then
|
||||
table.insert(tables.capZonesByCapZoneID[zoneID].zones, zone)
|
||||
end
|
||||
@@ -388,7 +413,7 @@ function Database.New(Logger)
|
||||
end
|
||||
|
||||
for _, interceptZone in pairs(self._tables.AllInterceptZones) do
|
||||
local split = Spearhead.Util.split_string(interceptZone, "_")
|
||||
local split = Util.split_string(interceptZone, "_")
|
||||
local zoneID = split[2]
|
||||
|
||||
if zoneID then
|
||||
@@ -396,7 +421,7 @@ function Database.New(Logger)
|
||||
tables.interceptZonesByZoneID[zoneID] = {}
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(interceptZone)
|
||||
local zone = DcsUtil.getZoneByName(interceptZone)
|
||||
if zone then
|
||||
table.insert(tables.interceptZonesByZoneID[zoneID], zone)
|
||||
end
|
||||
@@ -425,12 +450,12 @@ function Database.New(Logger)
|
||||
if missions == 0 then missions = 1 end
|
||||
|
||||
self._logger:info("initiated the database with amount of zones: ")
|
||||
self._logger:info("Stages: " .. Spearhead.Util.tableLength(self._tables.StageZones))
|
||||
self._logger:info("Total Missions: " .. Spearhead.Util.tableLength(self._tables.MissionZoneData))
|
||||
self._logger:info("Stages: " .. Util.tableLength(self._tables.StageZones))
|
||||
self._logger:info("Total Missions: " .. Util.tableLength(self._tables.MissionZoneData))
|
||||
self._logger:info("Average units per mission: " .. totalUnits / missions)
|
||||
self._logger:info("Random Missions: " .. Spearhead.Util.tableLength(self._tables.RandomMissionZones))
|
||||
self._logger:info("Farps: " .. Spearhead.Util.tableLength(self._tables.AllFarpZones))
|
||||
self._logger:info("Airbases: " .. Spearhead.Util.tableLength(self._tables.AirbaseDataPerAirfield))
|
||||
self._logger:info("Random Missions: " .. Util.tableLength(self._tables.RandomMissionZones))
|
||||
self._logger:info("Farps: " .. Util.tableLength(self._tables.AllFarpZones))
|
||||
self._logger:info("Airbases: " .. Util.tableLength(self._tables.AirbaseDataPerAirfield))
|
||||
|
||||
|
||||
return self
|
||||
@@ -452,7 +477,7 @@ end
|
||||
local getAvailableCAPGroups = function()
|
||||
local result = {}
|
||||
for name, value in pairs(is_group_taken) do
|
||||
if value == false and Spearhead.Util.startswith(name, "CAP") then
|
||||
if value == false and Util.startswith(name, "CAP") then
|
||||
table.insert(result, name)
|
||||
end
|
||||
end
|
||||
@@ -462,7 +487,7 @@ end
|
||||
---@private
|
||||
function Database:initAvailableUnits()
|
||||
do
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
local all_groups = MizGroupsManager.getAllGroupNames()
|
||||
for _, value in pairs(all_groups) do
|
||||
is_group_taken[value] = false
|
||||
end
|
||||
@@ -474,9 +499,9 @@ end
|
||||
---@return AirbaseData?
|
||||
function Database:getAirbaseDataForDrawLayer(layer_object)
|
||||
for _, airbase in pairs(world.getAirbases()) do
|
||||
local zone = Spearhead.DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
local zone = DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
|
||||
if zone and Spearhead.Util.is2dPointInZone({ x = layer_object.mapX, y = layer_object.mapY }, zone) == true then
|
||||
if zone and Util.is2dPointInZone({ x = layer_object.mapX, y = layer_object.mapY }, zone) == true then
|
||||
return self:getOrCreateAirbaseData(airbase:getName())
|
||||
end
|
||||
end
|
||||
@@ -537,7 +562,7 @@ function Database:loadCapUnits()
|
||||
local point = airbase:getPoint()
|
||||
|
||||
---@type SpearheadTriggerZone?
|
||||
local zone = Spearhead.DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
local zone = DcsUtil.getAirbaseZoneByName(airbase:getName())
|
||||
|
||||
if zone == nil then
|
||||
zone = {
|
||||
@@ -551,15 +576,15 @@ function Database:loadCapUnits()
|
||||
|
||||
|
||||
local baseData = self:getOrCreateAirbaseData(airbase:getName())
|
||||
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, zone)
|
||||
local groups = DcsUtil.areGroupsInCustomZone(all_groups, zone)
|
||||
for _, groupName in pairs(groups) do
|
||||
is_group_taken[groupName] = true
|
||||
|
||||
if Spearhead.Util.startswith(groupName, "CAP_A", true) or Spearhead.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)
|
||||
elseif Spearhead.Util.startswith(groupName, "CAP_I", true) then
|
||||
elseif Util.startswith(groupName, "CAP_I", true) then
|
||||
table.insert(baseData.InterceptGroups, groupName)
|
||||
elseif Spearhead.Util.startswith(groupName, "CAP_S", true) then
|
||||
elseif Util.startswith(groupName, "CAP_S", true) then
|
||||
table.insert(baseData.SweepGroups, groupName)
|
||||
end
|
||||
end
|
||||
@@ -570,19 +595,19 @@ end
|
||||
|
||||
---@private
|
||||
function Database:loadBlueSamUnits()
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
local all_groups = MizGroupsManager.getAllGroupNames()
|
||||
for _, blueSamZone in pairs(self._tables.BlueSams) do
|
||||
local samData = self:getOrCreateBlueSamDataForZone(blueSamZone)
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, blueSamZone)
|
||||
local groups = DcsUtil.getGroupsInZone(all_groups, blueSamZone)
|
||||
for _, groupName in pairs(groups) do
|
||||
is_group_taken[groupName] = true
|
||||
table.insert(samData.groups, groupName)
|
||||
end
|
||||
|
||||
local triggerZone = Spearhead.DcsUtil.getZoneByName(blueSamZone)
|
||||
local triggerZone = DcsUtil.getZoneByName(blueSamZone)
|
||||
if triggerZone then
|
||||
for _, kvPair in pairs(triggerZone.properties) do
|
||||
if kvPair.key and Spearhead.Util.startswith(kvPair.key, "buildable") then
|
||||
if kvPair.key and Util.startswith(kvPair.key, "buildable") then
|
||||
local number = tonumber(kvPair.value)
|
||||
if number and number > 0 then
|
||||
samData.buildingKilos = number
|
||||
@@ -593,6 +618,14 @@ function Database:loadBlueSamUnits()
|
||||
end
|
||||
end
|
||||
|
||||
---@return Array<CustomDrawing>
|
||||
function Database:getCustomDrawings()
|
||||
if self._tables.CustomDrawings == nil then
|
||||
return {}
|
||||
end
|
||||
return self._tables.CustomDrawings
|
||||
end
|
||||
|
||||
---Loads all units, data and briefings
|
||||
---@private
|
||||
function Database:LoadZoneData(missionZoneName)
|
||||
@@ -605,9 +638,9 @@ function Database:LoadZoneData(missionZoneName)
|
||||
dependsOn = {}
|
||||
}
|
||||
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
|
||||
local groups = DcsUtil.getGroupsInZone(all_groups, missionZoneName)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
if MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
|
||||
if object and object:getCoalition() == coalition.side.RED then
|
||||
@@ -630,26 +663,26 @@ function Database:LoadZoneData(missionZoneName)
|
||||
for _, sceneryObject in pairs(self._tables.AllSceneryObjects) do
|
||||
local point = sceneryObject:GetPoint()
|
||||
if point then
|
||||
if Spearhead.DcsUtil.isPositionInZone(point.x, point.z, missionZoneName) == true then
|
||||
if DcsUtil.isPositionInZone(point.x, point.z, missionZoneName) == true then
|
||||
table.insert(self._tables.MissionZoneData[missionZoneName].SceneryTargets, sceneryObject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for properties and adds the settings to the mission data
|
||||
local triggerZone = Spearhead.DcsUtil.getZoneByName(missionZoneName)
|
||||
local triggerZone = DcsUtil.getZoneByName(missionZoneName)
|
||||
if triggerZone and triggerZone.properties then
|
||||
for _, kvPair in pairs(triggerZone.properties) do
|
||||
local key = kvPair.key
|
||||
if Spearhead.Util.startswith(key, "dependson", true) == true then
|
||||
if Util.startswith(key, "dependson", true) == true then
|
||||
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
|
||||
elseif Spearhead.Util.startswith(key, "completeat") == true then
|
||||
elseif Util.startswith(key, "completeat") == true then
|
||||
local value = tonumber(kvPair.value)
|
||||
if value then
|
||||
if value > 1 and value <= 100 then
|
||||
value = value / 100
|
||||
elseif value > 100 then
|
||||
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZoneName .. " has a complete at value of " .. value .. " which is higher than 100, this will not work as intended")
|
||||
MissionEditorWarnings.Add("Mission with zonename: " .. missionZoneName .. " has a complete at value of " .. value .. " which is higher than 100, this will not work as intended")
|
||||
end
|
||||
self._tables.MissionZoneData[missionZoneName].completeAt = value
|
||||
end
|
||||
@@ -664,8 +697,8 @@ function Database:LoadZoneData(missionZoneName)
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
|
||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||
if triggerZone and Spearhead.Util.is2dPointInZone(vec2, triggerZone) then
|
||||
if layer_object.name and Spearhead.Util.startswith(layer_object.name, "briefing_", true) then
|
||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||
if layer_object.name and Util.startswith(layer_object.name, "briefing_", true) then
|
||||
local description = layer_object.text
|
||||
if description and description ~= "" then
|
||||
self._tables.MissionZoneData[missionZoneName].description = description
|
||||
@@ -699,16 +732,16 @@ function Database:loadFarpData()
|
||||
for _, farpZone in pairs(self._tables.AllFarpZones) do
|
||||
local farpzoneData = self:getOrCreateFarpDataForZone(farpZone)
|
||||
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, farpZone)
|
||||
local groups = DcsUtil.getGroupsInZone(all_groups, farpZone)
|
||||
for _, groupName in pairs(groups) do
|
||||
is_group_taken[groupName] = true
|
||||
table.insert(farpzoneData.groups, groupName)
|
||||
end
|
||||
|
||||
local triggerZone = Spearhead.DcsUtil.getZoneByName(farpZone)
|
||||
local triggerZone = DcsUtil.getZoneByName(farpZone)
|
||||
if triggerZone then
|
||||
for _, kvPair in pairs(triggerZone.properties) do
|
||||
if kvPair.key and Spearhead.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)
|
||||
if number and number > 0 then
|
||||
farpzoneData.buildingKilos = number
|
||||
@@ -728,7 +761,7 @@ function Database:loadAirbaseGroups()
|
||||
if base then
|
||||
local basedata = self:getOrCreateAirbaseData(baseName)
|
||||
local point = base:getPoint()
|
||||
local airbaseZone = Spearhead.DcsUtil.getAirbaseZoneByName(baseName)
|
||||
local airbaseZone = DcsUtil.getAirbaseZoneByName(baseName)
|
||||
|
||||
if airbaseZone == nil then
|
||||
airbaseZone = {
|
||||
@@ -742,9 +775,9 @@ function Database:loadAirbaseGroups()
|
||||
|
||||
|
||||
if airbaseZone and base:getDesc().category == Airbase.Category.AIRDROME then
|
||||
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, airbaseZone)
|
||||
local groups = DcsUtil.areGroupsInCustomZone(all_groups, airbaseZone)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
if MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object then
|
||||
if object:getCoalition() == coalition.side.RED then
|
||||
@@ -780,9 +813,9 @@ function Database:loadMiscGroupsInStages()
|
||||
for _, stageZone in pairs(self._tables.StageZones) do
|
||||
stageZone.MiscGroups = {}
|
||||
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, stageZone.StageZoneName)
|
||||
local groups = DcsUtil.getGroupsInZone(all_groups, stageZone.StageZoneName)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
if MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object and object:getCoalition() ~= coalition.side.NEUTRAL then
|
||||
is_group_taken[groupName] = true
|
||||
@@ -820,14 +853,14 @@ function Database:GetCapZoneForZoneID(zoneID)
|
||||
|
||||
if capZonesForID and capZonesForID.zones then
|
||||
|
||||
local count = Spearhead.Util.tableLength(capZonesForID.zones)
|
||||
local count = Util.tableLength(capZonesForID.zones)
|
||||
if count == 0 then
|
||||
self._logger:warn("Tried to get cap zone for zoneID: " .. zoneID .. " but cap zones were empty for this ID")
|
||||
return nil
|
||||
end
|
||||
|
||||
capZonesForID.current = capZonesForID.current + 1
|
||||
if Spearhead.Util.tableLength(capZonesForID.zones) < capZonesForID.current then
|
||||
if Util.tableLength(capZonesForID.zones) < capZonesForID.current then
|
||||
capZonesForID.current = 1
|
||||
end
|
||||
return capZonesForID.zones[capZonesForID.current]
|
||||
@@ -983,5 +1016,4 @@ function Database:GetNewMissionCode()
|
||||
]]
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
Spearhead.DB = Database
|
||||
return Database
|
||||
@@ -1,4 +1,8 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class SpearheadEvents
|
||||
local SpearheadEvents = {}
|
||||
do
|
||||
|
||||
@@ -7,10 +11,9 @@ do
|
||||
|
||||
---@param logLevel LogLevel
|
||||
SpearheadEvents.Init = function(logLevel)
|
||||
logger = Spearhead.LoggerTemplate.new("Events", logLevel)
|
||||
logger = Logger.new("Events", logLevel)
|
||||
end
|
||||
|
||||
|
||||
local warn = function(text)
|
||||
if logger then
|
||||
logger:warn(text)
|
||||
@@ -50,7 +53,7 @@ do
|
||||
---@param newStageNumber number
|
||||
SpearheadEvents.PublishStageNumberChanged = function(newStageNumber)
|
||||
pcall(function ()
|
||||
Spearhead.classes.persistence.Persistence.SetActiveStage(newStageNumber)
|
||||
Persistence.SetActiveStage(newStageNumber)
|
||||
end)
|
||||
|
||||
for _, callable in pairs(OnStageNumberChangedListeners) do
|
||||
@@ -68,8 +71,7 @@ do
|
||||
logError(err)
|
||||
end
|
||||
end
|
||||
Spearhead.LoggerTemplate.new("Events", "INFO"):info("Published stage number changed to: " .. tostring(newStageNumber))
|
||||
Spearhead.StageNumber = newStageNumber
|
||||
Logger.new("Events", "INFO"):info("Published stage number changed to: " .. tostring(newStageNumber))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -349,7 +351,7 @@ do
|
||||
end
|
||||
|
||||
if event.id == world.event.S_EVENT_MISSION_END then
|
||||
Spearhead.classes.persistence.Persistence.UpdateNow()
|
||||
Persistence.UpdateNow()
|
||||
end
|
||||
|
||||
local AI_GROUPS = {}
|
||||
@@ -370,7 +372,7 @@ do
|
||||
return false
|
||||
end
|
||||
|
||||
local players = Spearhead.DcsUtil.getAllPlayerUnits()
|
||||
local players = DcsUtil.getAllPlayerUnits()
|
||||
local unitName = unit:getName()
|
||||
for i, unit in pairs(players) do
|
||||
if unit:getName() == unitName then
|
||||
@@ -398,5 +400,4 @@ do
|
||||
world.addEventHandler(e)
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
Spearhead.Events = SpearheadEvents
|
||||
return SpearheadEvents
|
||||
@@ -1,3 +1,7 @@
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class SpearheadRouteUtil
|
||||
local ROUTE_UTIL = {}
|
||||
do --setup route util
|
||||
---comment
|
||||
@@ -22,7 +26,7 @@ do --setup route util
|
||||
---@return table task
|
||||
local RtbTask = function(airdromeId, basePoint, speed)
|
||||
if basePoint == nil then
|
||||
basePoint = Spearhead.Util.getAirbaseById(airdromeId):getPoint()
|
||||
basePoint = DcsUtil.getAirbaseById(airdromeId):getPoint()
|
||||
end
|
||||
|
||||
return {
|
||||
@@ -214,7 +218,7 @@ do --setup route util
|
||||
---@param deviationDistance number
|
||||
---@return table? route
|
||||
ROUTE_UTIL.createCapMission = function(groupName, airdromeId, capPoint, racetrackSecondPoint, altitude, speed, durationOnStation, attackHelos, deviationDistance)
|
||||
local baseName = Spearhead.DcsUtil.getAirbaseName(airdromeId)
|
||||
local baseName = DcsUtil.getAirbaseName(airdromeId)
|
||||
if baseName == nil then
|
||||
return nil
|
||||
end
|
||||
@@ -294,7 +298,7 @@ do --setup route util
|
||||
TODO: Test the creation and pubishing of event and the timing of said event
|
||||
]] --
|
||||
|
||||
local base = Spearhead.DcsUtil.getAirbaseById(airdromeId)
|
||||
local base = DcsUtil.getAirbaseById(airdromeId)
|
||||
if base == nil then
|
||||
return nil, "No airbase found for ID " .. tostring(airdromeId)
|
||||
end
|
||||
@@ -307,7 +311,7 @@ do --setup route util
|
||||
end
|
||||
|
||||
local units = group:getUnits()
|
||||
while pos == nil and i <= Spearhead.Util.tableLength(units) do
|
||||
while pos == nil and i <= Util.tableLength(units) do
|
||||
local unit = units[i]
|
||||
if unit and unit:isExist() == true and unit:inAir() == true then
|
||||
pos = unit:getPoint()
|
||||
@@ -461,5 +465,4 @@ do --setup route util
|
||||
end
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
Spearhead.RouteUtil = ROUTE_UTIL
|
||||
return ROUTE_UTIL
|
||||
+102
-79
@@ -1,4 +1,11 @@
|
||||
local Events = require("classes.spearhead_events")
|
||||
local Util = require("classes.util.Util")
|
||||
local Logger = require("classes.util.Logger")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
|
||||
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
||||
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
||||
local WaitingStage = require("classes.stageClasses.Stages.WaitingStage")
|
||||
|
||||
local StagesByName = {}
|
||||
|
||||
@@ -13,8 +20,14 @@ local WaitingStagesByIndex = {}
|
||||
|
||||
local currentStage = -99
|
||||
|
||||
---@class GlobalStageManager : StageCompleteListener
|
||||
---@field private database Database
|
||||
---@field private logger Logger
|
||||
---@field private stageConfig StageConfig
|
||||
local GlobalStageManager = {}
|
||||
GlobalStageManager.__index = GlobalStageManager
|
||||
|
||||
GlobalStageManager = {}
|
||||
GlobalStageManager.getCurrentStage = function() return currentStage end
|
||||
|
||||
---comment
|
||||
---@param database Database
|
||||
@@ -22,13 +35,14 @@ GlobalStageManager = {}
|
||||
---@param logLevel LogLevel
|
||||
---@param spawnManager SpawnManager
|
||||
---@return nil
|
||||
function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnManager)
|
||||
local logger = Spearhead.LoggerTemplate.new("StageManager", logLevel)
|
||||
function GlobalStageManager.NewAndStart(database, stageConfig, logLevel, spawnManager)
|
||||
local logger = Logger.new("StageManager", logLevel)
|
||||
logger:info("Using Stage Log Level: " .. logLevel)
|
||||
local o = {}
|
||||
setmetatable(o, { __index = self })
|
||||
local self = setmetatable({}, GlobalStageManager)
|
||||
self.database = database
|
||||
self.stageConfig = stageConfig
|
||||
|
||||
o.logger = logger
|
||||
self.logger = logger
|
||||
if stageConfig.isAutoStages ~= true then
|
||||
logger:warn("Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
|
||||
end
|
||||
@@ -40,75 +54,29 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
end
|
||||
}
|
||||
|
||||
Spearhead.Events.AddStageNumberChangedListener(OnStageNumberChangedListener)
|
||||
|
||||
---@type StageCompleteListener
|
||||
local OnStageCompleteListener = {
|
||||
OnStageComplete = function(self, stage)
|
||||
logger:debug("Receiving stage complete event from: " .. stage.zoneName)
|
||||
Events.AddStageNumberChangedListener(OnStageNumberChangedListener)
|
||||
|
||||
local anyIncomplete = false
|
||||
logger:debug("Checking stages for index: " .. tostring(currentStage))
|
||||
for index, stage in pairs(StagesByIndex[tostring(currentStage)]) do
|
||||
if stage:IsComplete() == false then
|
||||
anyIncomplete = true
|
||||
logger:debug("Need to wait for Stage " .. stage.zoneName .. " to be completed")
|
||||
else
|
||||
logger:debug("Stage verified to be completed: " .. stage.zoneName)
|
||||
end
|
||||
end
|
||||
|
||||
if anyIncomplete == false and stageConfig.isAutoStages == true then
|
||||
|
||||
-- CHECK WAITING STAGES
|
||||
local nextStage = currentStage + 1
|
||||
|
||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
||||
if waitingStage:IsActive() == false then
|
||||
waitingStage:ActivateStage()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local anyWaiting = false
|
||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
||||
if waitingStage:IsComplete() == false then
|
||||
anyWaiting = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if anyWaiting == false then
|
||||
logger:debug("Setting next stage to: " .. tostring(currentStage + 1))
|
||||
Spearhead.Events.PublishStageNumberChanged(currentStage + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
for _, stageName in pairs(database:getStagezoneNames()) do
|
||||
logger:debug("Found stage zone with name: " .. stageName)
|
||||
|
||||
if Spearhead.Util.startswith(stageName, "missionstage", true) then
|
||||
if Util.startswith(stageName, "missionstage", true) then
|
||||
local valid = true
|
||||
local split = Spearhead.Util.split_string(stageName, "_")
|
||||
if Spearhead.Util.tableLength(split) < 2 then
|
||||
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
||||
local split = Util.split_string(stageName, "_")
|
||||
if Util.tableLength(split) < 2 then
|
||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
||||
valid = false
|
||||
end
|
||||
|
||||
if Spearhead.Util.tableLength(split) < 3 then
|
||||
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a stage name")
|
||||
if Util.tableLength(split) < 3 then
|
||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a stage name")
|
||||
end
|
||||
|
||||
local orderNumber = nil
|
||||
local isSideStage = false
|
||||
if valid == true then
|
||||
local orderNumberString = string.lower(split[2])
|
||||
if Spearhead.Util.startswith(orderNumberString, "x") == true then
|
||||
if Util.startswith(orderNumberString, "x") == true then
|
||||
isSideStage = true
|
||||
|
||||
orderNumberString = string.gsub(orderNumberString, "x", "")
|
||||
@@ -118,13 +86,13 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
end
|
||||
|
||||
if orderNumber == nil then
|
||||
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a valid order number : " .. split[2])
|
||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a valid order number : " .. split[2])
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
|
||||
local stageDisplayName = split[3]
|
||||
local stagelogger = Spearhead.LoggerTemplate.new(stageName, logLevel)
|
||||
local stagelogger = Logger.new(stageName, logLevel)
|
||||
if valid == true and orderNumber then
|
||||
|
||||
---@type StageInitData
|
||||
@@ -135,14 +103,14 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
}
|
||||
|
||||
if isSideStage == true then
|
||||
local stage = Spearhead.classes.stageClasses.Stages.ExtraStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(OnStageCompleteListener)
|
||||
local stage = ExtraStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(self)
|
||||
|
||||
if SideStageByIndex[tostring(orderNumber)] == nil then SideStageByIndex[tostring(orderNumber)] = {} end
|
||||
table.insert(SideStageByIndex[tostring(orderNumber)], stage)
|
||||
else
|
||||
local stage = Spearhead.classes.stageClasses.Stages.PrimaryStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(OnStageCompleteListener)
|
||||
local stage = PrimaryStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(self)
|
||||
|
||||
if StagesByIndex[tostring(orderNumber)] == nil then StagesByIndex[tostring(orderNumber)] = {} end
|
||||
table.insert(StagesByIndex[tostring(orderNumber)], stage)
|
||||
@@ -150,13 +118,13 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
end
|
||||
end
|
||||
|
||||
if Spearhead.Util.startswith(stageName, "waitingstage", true) then
|
||||
if Util.startswith(stageName, "waitingstage", true) then
|
||||
local valid = true
|
||||
|
||||
local split = Spearhead.Util.split_string(stageName, "_")
|
||||
local split = Util.split_string(stageName, "_")
|
||||
|
||||
if Spearhead.Util.tableLength(split) < 3 then
|
||||
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
||||
if Util.tableLength(split) < 3 then
|
||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a order number or valid format")
|
||||
valid = false
|
||||
end
|
||||
|
||||
@@ -165,19 +133,19 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
local stageIndex = tonumber(stageIndexString)
|
||||
|
||||
if not stageIndex then
|
||||
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a valid order number")
|
||||
MissionEditorWarnings.Add("Stage zone with name " .. stageName .. " does not have a valid order number")
|
||||
valid = false
|
||||
end
|
||||
|
||||
local waitingSecondsString = split[3]
|
||||
local waitingSeconds = tonumber(waitingSecondsString)
|
||||
if not waitingSeconds then
|
||||
Spearhead.AddMissionEditorWarning("Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter")
|
||||
MissionEditorWarnings.Add("Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter")
|
||||
valid = false
|
||||
end
|
||||
|
||||
if valid == true then
|
||||
local stagelogger = Spearhead.LoggerTemplate.new(stageName, logLevel)
|
||||
local stagelogger = Logger.new(stageName, logLevel)
|
||||
|
||||
---@type WaitingStageInitData
|
||||
local initData = {
|
||||
@@ -186,28 +154,84 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnMa
|
||||
stageZoneName = stageName,
|
||||
waitingSeconds = waitingSeconds --[[@as integer]]
|
||||
}
|
||||
local waitingStage = Spearhead.classes.stageClasses.Stages.WaitingStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
local waitingStage = WaitingStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
|
||||
if WaitingStagesByIndex[tostring(stageIndex)] == nil then
|
||||
WaitingStagesByIndex[tostring(stageIndex)] = {}
|
||||
end
|
||||
table.insert(WaitingStagesByIndex[tostring(stageIndex)], waitingStage)
|
||||
|
||||
waitingStage:AddStageCompleteListener(OnStageCompleteListener)
|
||||
waitingStage:AddStageCompleteListener(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function GlobalStageManager:OnStageComplete(stage)
|
||||
self.logger:debug("Receiving stage complete event from: " .. stage.zoneName)
|
||||
|
||||
return o
|
||||
local anyIncomplete = false
|
||||
self.logger:debug("Checking stages for index: " .. tostring(currentStage))
|
||||
for index, stage in pairs(StagesByIndex[tostring(currentStage)]) do
|
||||
if stage:IsComplete() == false then
|
||||
anyIncomplete = true
|
||||
self.logger:debug("Need to wait for Stage " .. stage.zoneName .. " to be completed")
|
||||
else
|
||||
self.logger:debug("Stage verified to be completed: " .. stage.zoneName)
|
||||
end
|
||||
end
|
||||
|
||||
if anyIncomplete == false and self.stageConfig.isAutoStages == true then
|
||||
|
||||
-- CHECK WAITING STAGES
|
||||
local nextStage = currentStage + 1
|
||||
|
||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
||||
if waitingStage:IsActive() == false then
|
||||
waitingStage:ActivateStage()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local anyWaiting = false
|
||||
if WaitingStagesByIndex[tostring(nextStage)] then
|
||||
for _, waitingStage in pairs(WaitingStagesByIndex[tostring(nextStage)]) do
|
||||
if waitingStage:IsComplete() == false then
|
||||
anyWaiting = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if anyWaiting == false then
|
||||
local newStageNumber = currentStage + 1
|
||||
self:UpdateDrawings(newStageNumber)
|
||||
self.logger:debug("Setting next stage to: " .. tostring(newStageNumber))
|
||||
Events.PublishStageNumberChanged(newStageNumber)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
function GlobalStageManager:UpdateDrawings(stageNumber)
|
||||
local drawings = self.database:getCustomDrawings()
|
||||
for _, drawing in pairs(drawings) do
|
||||
local startStage, stopStage = drawing:GetStartAndStop()
|
||||
if stageNumber >= startStage and stageNumber < stopStage then
|
||||
drawing:Draw()
|
||||
else
|
||||
drawing:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
GlobalStageManager.printFullOverview = function ()
|
||||
|
||||
local logger = Spearhead.LoggerTemplate.new("StageOverview", "INFO")
|
||||
local logger = Logger.new("StageOverview", "INFO")
|
||||
logger:info("Stage overview:")
|
||||
|
||||
local max = 0
|
||||
@@ -268,5 +292,4 @@ GlobalStageManager.isStageComplete = function (stageNumber)
|
||||
return true
|
||||
end
|
||||
|
||||
if not Spearhead.internal then Spearhead.internal = {} end
|
||||
Spearhead.internal.GlobalStageManager = GlobalStageManager
|
||||
return GlobalStageManager
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
|
||||
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class SpearheadGroup : OnUnitLostListener
|
||||
---@field private _groupName string
|
||||
@@ -149,7 +149,7 @@ end
|
||||
function SpearheadGroup:SetInvisible()
|
||||
|
||||
if self._isStatic == true then
|
||||
local country = Spearhead.DcsUtil.GetNeutralCountry()
|
||||
local country = DcsUtil.GetNeutralCountry()
|
||||
|
||||
---@type SpawnOverrides
|
||||
local overrides = {
|
||||
@@ -187,7 +187,4 @@ function SpearheadGroup:SetVisible()
|
||||
end
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end
|
||||
Spearhead.classes.stageClasses.Groups.SpearheadGroup = SpearheadGroup
|
||||
return SpearheadGroup
|
||||
+5
-6
@@ -1,3 +1,5 @@
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
|
||||
---@class SpearheadSceneryObject
|
||||
---@field private persistentName string The persistent name of the scenery object
|
||||
---@field private objectID number The ID of the scenery object
|
||||
@@ -47,7 +49,7 @@ end
|
||||
function SpearheadSceneryObject:MarkDead()
|
||||
if self.isDead == true then return end
|
||||
self.isDead = true
|
||||
Spearhead.classes.persistence.Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery")
|
||||
Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery")
|
||||
end
|
||||
|
||||
function SpearheadSceneryObject:UpdateStatePersistently()
|
||||
@@ -55,7 +57,7 @@ function SpearheadSceneryObject:UpdateStatePersistently()
|
||||
return
|
||||
end
|
||||
|
||||
local state = Spearhead.classes.persistence.Persistence.UnitState(self.persistentName)
|
||||
local state = Persistence.UnitState(self.persistentName)
|
||||
if state and state.isDead == true then
|
||||
trigger.action.explosion(self:GetPoint(), 1000)
|
||||
self.isDead = true
|
||||
@@ -71,7 +73,4 @@ function SpearheadSceneryObject:GetPoint()
|
||||
return Object.getPoint(self.internalObj)
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end
|
||||
Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject = SpearheadSceneryObject
|
||||
return SpearheadSceneryObject
|
||||
+20
-22
@@ -1,3 +1,7 @@
|
||||
local BuildableZone = require("classes.stageClasses.SpecialZones.abstract.BuildableZone")
|
||||
local SpearheadGroup = require("classes.stageClasses.Groups.SpearheadGroup")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class BlueSam : BuildableZone
|
||||
---@field Activate fun(self: BlueSam)
|
||||
@@ -20,7 +24,7 @@ BlueSam.__index = BlueSam
|
||||
---@return BlueSam?
|
||||
function BlueSam.New(database, logger, zoneName, spawnManager)
|
||||
|
||||
setmetatable(BlueSam, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
setmetatable(BlueSam, BuildableZone)
|
||||
local self = setmetatable({}, BlueSam)
|
||||
|
||||
self._database = database
|
||||
@@ -53,39 +57,39 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
||||
end
|
||||
|
||||
for _, groupName in pairs(blueSamData.groups) do
|
||||
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
if SpearheadGroup then
|
||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
if spearheadGroup then
|
||||
|
||||
if SpearheadGroup:GetCoalition() == 2 or SpearheadGroup:GetCoalition() == 0 then
|
||||
table.insert(self._blueGroups, SpearheadGroup)
|
||||
if spearheadGroup:GetCoalition() == 2 or spearheadGroup:GetCoalition() == 0 then
|
||||
table.insert(self._blueGroups, spearheadGroup)
|
||||
end
|
||||
|
||||
for _, unit in pairs(SpearheadGroup:GetObjects()) do
|
||||
if SpearheadGroup:GetCoalition() == 1 then
|
||||
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
||||
if spearheadGroup:GetCoalition() == 1 then
|
||||
table.insert(blueUnitsPos, unit:getPoint())
|
||||
elseif SpearheadGroup:GetCoalition() == 2 then
|
||||
elseif spearheadGroup:GetCoalition() == 2 then
|
||||
table.insert(redUnitsPos, unit:getPoint())
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
SpearheadGroup:Destroy()
|
||||
spearheadGroup:Destroy()
|
||||
end
|
||||
|
||||
--Cleanup units
|
||||
local cleanup_distance = 5
|
||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||
local distance = Spearhead.Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
if distance <= cleanup_distance then
|
||||
self._cleanupUnits[redUnitName] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
local zone = DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, self._buildableCrateKilos or 0, "SAM_CRATE", self._blueGroups, logger, database)
|
||||
BuildableZone.New(self, zone, self._buildableCrateKilos or 0, "SAM_CRATE", self._blueGroups, logger, database)
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -104,9 +108,9 @@ function BlueSam:GetNoLandingZone()
|
||||
end
|
||||
end
|
||||
|
||||
local vecs = Spearhead.Util.getConvexHull(points)
|
||||
local vecs = Util.getConvexHull(points)
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(self._zoneName)
|
||||
local zone = DcsUtil.getZoneByName(self._zoneName)
|
||||
if zone == nil then
|
||||
self._logger:error("Zone not found: " .. self._zoneName)
|
||||
return nil
|
||||
@@ -136,7 +140,7 @@ end
|
||||
|
||||
function BlueSam:SpawnGroups()
|
||||
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
||||
Spearhead.DcsUtil.DestroyUnit(unitName)
|
||||
DcsUtil.DestroyUnit(unitName)
|
||||
end
|
||||
|
||||
for _, group in pairs(self._blueGroups) do
|
||||
@@ -148,10 +152,4 @@ function BlueSam:OnBuildingComplete()
|
||||
self:SpawnGroups()
|
||||
end
|
||||
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.SpecialZones == nil then Spearhead.classes.stageClasses.SpecialZones = {} end
|
||||
Spearhead.classes.stageClasses.SpecialZones.BlueSam = BlueSam
|
||||
return BlueSam
|
||||
+12
-12
@@ -1,4 +1,8 @@
|
||||
|
||||
local BuildableZone = require("classes.stageClasses.SpecialZones.abstract.BuildableZone")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local SupplyHub = require("classes.stageClasses.SpecialZones.SupplyHub")
|
||||
local SpearheadGroup = require("classes.stageClasses.Groups.SpearheadGroup")
|
||||
|
||||
---@class FarpZone: BuildableZone
|
||||
---@field private _startingFarp boolean
|
||||
@@ -18,14 +22,14 @@ FarpZone.__index = FarpZone
|
||||
---@param spawnManager SpawnManager
|
||||
---@return FarpZone
|
||||
function FarpZone.New(database, logger, zoneName, spawnManager)
|
||||
setmetatable(FarpZone, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
setmetatable(FarpZone, BuildableZone)
|
||||
local self = setmetatable({}, FarpZone)
|
||||
|
||||
self._database = database
|
||||
self._logger = logger
|
||||
self._zoneName = zoneName
|
||||
|
||||
local split = Spearhead.Util.split_string(zoneName, "_")
|
||||
local split = Util.split_string(zoneName, "_")
|
||||
if string.lower(split[2]) == "a" then
|
||||
self._startingFarp = true
|
||||
else
|
||||
@@ -44,7 +48,7 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
|
||||
self._padNames = farpData.padNames
|
||||
|
||||
for _, supplyHubName in pairs(farpData.supplyHubNames) do
|
||||
local supplyHub = Spearhead.classes.stageClasses.SpecialZones.SupplyHub.new(database, logger, supplyHubName)
|
||||
local supplyHub = SupplyHub.new(database, logger, supplyHubName)
|
||||
if supplyHub then
|
||||
table.insert(self._supplyHubs, supplyHub)
|
||||
end
|
||||
@@ -52,15 +56,15 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
|
||||
|
||||
|
||||
for _, groupName in pairs(farpData.groups) do
|
||||
local group = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
local group = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._groups, group)
|
||||
group:Destroy()
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
local zone = DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
self._logger:debug("Creating Buildable zone: " .. zoneName .. " with " .. (farpData.buildingKilos or "nil") .. " kilos")
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database)
|
||||
BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database)
|
||||
end
|
||||
end
|
||||
self:Deactivate()
|
||||
@@ -132,8 +136,4 @@ function FarpZone:SetPadsBlue()
|
||||
end
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.SpecialZones == nil then Spearhead.classes.stageClasses.SpecialZones = {} end
|
||||
Spearhead.classes.stageClasses.SpecialZones.FarpZone = FarpZone
|
||||
return FarpZone
|
||||
+17
-17
@@ -1,3 +1,9 @@
|
||||
local BuildableZone = require("classes.stageClasses.SpecialZones.abstract.BuildableZone")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local SpearheadGroup = require("classes.stageClasses.Groups.SpearheadGroup")
|
||||
local SupplyHub = require("classes.stageClasses.SpecialZones.SupplyHub")
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class StageBase : BuildableZone
|
||||
---@field private _database Database
|
||||
---@field private _logger Logger
|
||||
@@ -21,7 +27,7 @@ StageBase.__index = StageBase
|
||||
---@param spawnManager SpawnManager
|
||||
---@return StageBase?
|
||||
function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
setmetatable(StageBase, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
setmetatable(StageBase, BuildableZone)
|
||||
local self = setmetatable({}, StageBase)
|
||||
|
||||
self._database = databaseManager
|
||||
@@ -33,7 +39,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
self._supplyHubs = {}
|
||||
|
||||
self._airbase = Airbase.getByName(airbaseName)
|
||||
self._initialSide = Spearhead.DcsUtil.getStartingCoalition(self._airbase)
|
||||
self._initialSide = DcsUtil.getStartingCoalition(self._airbase)
|
||||
|
||||
do --init
|
||||
local airbaseData = databaseManager:getAirbaseDataForZone(airbaseName)
|
||||
@@ -49,7 +55,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
local blueUnitsPos = {}
|
||||
|
||||
for _, groupName in pairs(airbaseData.RedGroups) do
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
local shGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._red_groups, shGroup)
|
||||
|
||||
for _, unit in pairs(shGroup:GetObjects()) do
|
||||
@@ -60,7 +66,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
end
|
||||
|
||||
for _, groupName in pairs(airbaseData.BlueGroups) do
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
local shGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._blue_groups, shGroup)
|
||||
|
||||
for _, unit in pairs(shGroup:GetObjects()) do
|
||||
@@ -71,7 +77,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
end
|
||||
|
||||
for _, supplyHubName in pairs(airbaseData.supplyHubNames) do
|
||||
local supplyHub = Spearhead.classes.stageClasses.SpecialZones.SupplyHub.new(databaseManager, logger,
|
||||
local supplyHub = SupplyHub.new(databaseManager, logger,
|
||||
supplyHubName)
|
||||
if supplyHub then
|
||||
table.insert(self._supplyHubs, supplyHub)
|
||||
@@ -86,7 +92,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
|
||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||
local distance = Spearhead.Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
if distance <= cleanup_distance then
|
||||
self._cleanup_units[redUnitName] = true
|
||||
end
|
||||
@@ -94,9 +100,9 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
end
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getAirbaseZoneByName(airbaseName)
|
||||
local zone = DcsUtil.getAirbaseZoneByName(airbaseName)
|
||||
if zone then
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, airbaseData.buildingKilos or 0, "AIRBASE_CRATE", self._blue_groups, logger, databaseManager)
|
||||
BuildableZone.New(self, zone, airbaseData.buildingKilos or 0, "AIRBASE_CRATE", self._blue_groups, logger, databaseManager)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,8 +132,8 @@ function StageBase:CleanRedUnits()
|
||||
|
||||
for unitName, shouldClean in pairs(self._cleanup_units) do
|
||||
if shouldClean == true then
|
||||
Spearhead.DcsUtil.DestroyUnit(unitName)
|
||||
Spearhead.DcsUtil.CleanCorpse(unitName)
|
||||
DcsUtil.DestroyUnit(unitName)
|
||||
DcsUtil.CleanCorpse(unitName)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -187,10 +193,4 @@ function StageBase:OnBuildingComplete()
|
||||
self:FinaliseBlueStage()
|
||||
end
|
||||
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.SpecialZones == nil then Spearhead.classes.stageClasses.SpecialZones = {} end
|
||||
Spearhead.classes.stageClasses.SpecialZones.StageBase = StageBase
|
||||
return StageBase
|
||||
+12
-12
@@ -1,3 +1,8 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local SupplyUnitsTracker = require("classes.stageClasses.helpers.SupplyUnitsTracker")
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
|
||||
---@class SupplyHub
|
||||
---@field private _database Database
|
||||
---@field private _logger Logger
|
||||
@@ -26,18 +31,18 @@ function SupplyHub.new(database, logger, zoneName)
|
||||
self._logger = logger
|
||||
self._zoneName = zoneName
|
||||
|
||||
local split = Spearhead.Util.split_string(zoneName, "_")
|
||||
local split = Util.split_string(zoneName, "_")
|
||||
if string.lower(split[2]) == "a" then
|
||||
self._activeAtStart = true
|
||||
else
|
||||
self._activeAtStart = false
|
||||
end
|
||||
|
||||
self._zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
self._zone = DcsUtil.getZoneByName(zoneName)
|
||||
|
||||
self._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logger.LogLevel)
|
||||
self._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate(logger.LogLevel)
|
||||
self._inZone = {}
|
||||
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
|
||||
self._logger:debug("Creating Supply Hub zone: " .. self._zoneName)
|
||||
|
||||
@@ -66,23 +71,18 @@ function SupplyHub:Activate()
|
||||
|
||||
self._logger:debug("Activating Supply Hub zone: " .. self._zoneName)
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(self._zoneName)
|
||||
local zone = DcsUtil.getZoneByName(self._zoneName)
|
||||
if zone and self._drawID == nil then
|
||||
---@type DrawColor
|
||||
local fillColor = { r=0, g=1, b=0, a=0.2 }
|
||||
---@type DrawColor
|
||||
local lineColor = { r=0, g=1, b=0, a=1}
|
||||
local lineStyle = 1
|
||||
self._drawID = Spearhead.DcsUtil.DrawZone(zone, lineColor, fillColor, lineStyle)
|
||||
self._drawID = DcsUtil.DrawZone(zone, lineColor, fillColor, lineStyle)
|
||||
end
|
||||
|
||||
self._supplyUnitsTracker:RegisterHub(self)
|
||||
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.SpecialZones == nil then Spearhead.classes.stageClasses.SpecialZones = {} end
|
||||
Spearhead.classes.stageClasses.SpecialZones.SupplyHub = SupplyHub
|
||||
return SupplyHub
|
||||
+9
-11
@@ -1,3 +1,6 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
local BuildableMission = require("classes.stageClasses.missions.BuildableMission")
|
||||
|
||||
---@class BuildableZone : OnCrateDroppedListener
|
||||
---@field protected _targetZone SpearheadTriggerZone
|
||||
@@ -22,11 +25,11 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
||||
self._requiredKilos = kilosRequired or 0
|
||||
self._buildableGroups = buildableGroups or {}
|
||||
self._buildableLogger = logger
|
||||
local totalGroups = Spearhead.Util.tableLength(self._buildableGroups)
|
||||
local totalGroups = Util.tableLength(self._buildableGroups)
|
||||
self._groupsPerKilo = totalGroups / self._requiredKilos
|
||||
|
||||
self._receivedBuildingKilos = 0
|
||||
local persistedKilos = Spearhead.classes.persistence.Persistence.GetZoneDeliveredKilos(targetZone.name)
|
||||
local persistedKilos = Persistence.GetZoneDeliveredKilos(targetZone.name)
|
||||
if persistedKilos and persistedKilos > 0 then
|
||||
self._buildableLogger:debug("Zone " .. targetZone.name .. " already has " .. persistedKilos .. " kilos delivered")
|
||||
self._receivedBuildingKilos = persistedKilos
|
||||
@@ -66,7 +69,7 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
||||
|
||||
local noLandingZone = self:GetNoLandingZone()
|
||||
if kilosRequired and kilosRequired > 0 then
|
||||
self._buildableMission = Spearhead.classes.stageClasses.missions.BuildableMission.new(database, logger, targetZone, noLandingZone, kilosRequired, crateType)
|
||||
self._buildableMission = BuildableMission.new(database, logger, targetZone, noLandingZone, kilosRequired, crateType)
|
||||
self._buildableMission:AddOnCrateDroppedOfListener(self)
|
||||
else
|
||||
self._buildableMission = nil
|
||||
@@ -138,7 +141,7 @@ end
|
||||
---@param kilos number
|
||||
function BuildableZone:FinaliseCrate(kilos)
|
||||
self._receivedBuildingKilos = self._receivedBuildingKilos + kilos
|
||||
Spearhead.classes.persistence.Persistence.SetZoneDeliveredKilos(self._targetZone.name, self._receivedBuildingKilos)
|
||||
Persistence.SetZoneDeliveredKilos(self._targetZone.name, self._receivedBuildingKilos)
|
||||
if self._receivedBuildingKilos >= self._requiredKilos then
|
||||
self:OnBuildingComplete()
|
||||
end
|
||||
@@ -157,7 +160,7 @@ function BuildableZone:GetNoLandingZone()
|
||||
end
|
||||
end
|
||||
|
||||
local vecs = Spearhead.Util.getConvexHull(points)
|
||||
local vecs = Util.getConvexHull(points)
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local spearheadZone = {
|
||||
@@ -197,9 +200,4 @@ function BuildableZone:SpawnAmount(amount)
|
||||
return true
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
Spearhead.classes = Spearhead.classes or {}
|
||||
Spearhead.classes.stageClasses = Spearhead.classes.stageClasses or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones = Spearhead.classes.stageClasses.SpecialZones or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract = Spearhead.classes.stageClasses.SpecialZones.abstract or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone = BuildableZone
|
||||
return BuildableZone
|
||||
+37
-30
@@ -1,3 +1,16 @@
|
||||
local SpearheadGroup = require("classes.stageClasses.Groups.SpearheadGroup")
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local FarpZone = require("classes.stageClasses.SpecialZones.FarpZone")
|
||||
local SupplyHub = require("classes.stageClasses.SpecialZones.SupplyHub")
|
||||
local Util = require("classes.util.Util")
|
||||
local ZoneMission = require("classes.stageClasses.missions.ZoneMission")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
local StageBase = require("classes.stageClasses.SpecialZones.StageBase")
|
||||
local BlueSam = require("classes.stageClasses.SpecialZones.BlueSam")
|
||||
local Events = require("classes.spearhead_events")
|
||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||
|
||||
---@alias StageColor
|
||||
---| "RED"
|
||||
@@ -71,8 +84,6 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
|
||||
logger:debug("[BaseStage] Initiating stage with name: " .. initData.stageZoneName)
|
||||
|
||||
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup
|
||||
|
||||
self.zoneName = initData.stageZoneName
|
||||
self.stageNumber = initData.stageNumber
|
||||
self._isActive = false
|
||||
@@ -101,11 +112,11 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
self._activeStage = -99
|
||||
self._preActivated = false
|
||||
self._stageConfig = stageConfig or {}
|
||||
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(self.zoneName)
|
||||
local zone = DcsUtil.getZoneByName(self.zoneName)
|
||||
if zone then
|
||||
self._stageDrawingId = Spearhead.DcsUtil.DrawZone(zone, Stage.StageColors.INVISIBLE, Stage.StageColors.INVISIBLE, 4)
|
||||
self._stageDrawingId = DcsUtil.DrawZone(zone, Stage.StageColors.INVISIBLE, Stage.StageColors.INVISIBLE, 4)
|
||||
end
|
||||
|
||||
self._spawnedGroups = {}
|
||||
@@ -114,13 +125,13 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
|
||||
local farpNames = database:getFarpNamesInStage(self.zoneName)
|
||||
for _, farpName in pairs(farpNames) do
|
||||
local farp = Spearhead.classes.stageClasses.SpecialZones.FarpZone.New(database, logger, farpName, spawnManager)
|
||||
local farp = FarpZone.New(database, logger, farpName, spawnManager)
|
||||
table.insert(self._db.farps, farp)
|
||||
end
|
||||
|
||||
local supplyHubNames = database:getSupplyHubsInStage(self.zoneName)
|
||||
for _, supplyHubName in pairs(supplyHubNames) do
|
||||
local supplyHub = Spearhead.classes.stageClasses.SpecialZones.SupplyHub.new(database, logger, supplyHubName)
|
||||
local supplyHub = SupplyHub.new(database, logger, supplyHubName)
|
||||
table.insert(self._db.supplyHubs, supplyHub)
|
||||
end
|
||||
|
||||
@@ -144,17 +155,17 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
|
||||
do -- load tables
|
||||
local missionZones = database:getMissionsForStage(self.zoneName)
|
||||
self._logger:debug("Found " .. Spearhead.Util.tableLength(missionZones) .. " mission zones for stage: " .. self.zoneName)
|
||||
self._logger:debug("Found " .. Util.tableLength(missionZones) .. " mission zones for stage: " .. self.zoneName)
|
||||
for _, missionZone in pairs(missionZones) do
|
||||
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZone, self._missionPriority, database, logger, self, spawnManager)
|
||||
local mission = ZoneMission.new(missionZone, self._missionPriority, database, logger, self, spawnManager)
|
||||
if mission then
|
||||
self._db.missionsByCode[mission.code] = mission
|
||||
|
||||
if mission.name and self._db.missionsByName[mission.name] == nil then
|
||||
self._db.missionsByName[mission.name] = mission
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("DUPLICATE MISSION NAME ALERT: " .. mission.name .. " in zone: " .. self.zoneName)
|
||||
MissionEditorWarnings.Add("DUPLICATE MISSION NAME ALERT: " .. mission.name .. " in zone: " .. self.zoneName)
|
||||
end
|
||||
|
||||
if mission.missionType == "SAM" then
|
||||
@@ -170,7 +181,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
---@type table<string, Array<Mission>>
|
||||
local randomMissionByName = {}
|
||||
for _, missionZoneName in pairs(randomMissionNames) do
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZoneName, self._missionPriority, database, logger, self, spawnManager)
|
||||
local mission = ZoneMission.new(missionZoneName, self._missionPriority, database, logger, self, spawnManager)
|
||||
if mission then
|
||||
if randomMissionByName[mission.name] == nil then
|
||||
randomMissionByName[mission.name] = {}
|
||||
@@ -181,18 +192,18 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
|
||||
for missionName, missions in pairs(randomMissionByName) do
|
||||
|
||||
local missionZonePicked = Spearhead.classes.persistence.Persistence.GetPickedRandomMission(missionName)
|
||||
local missionZonePicked = Persistence.GetPickedRandomMission(missionName)
|
||||
if missionZonePicked == nil then
|
||||
local mission = Spearhead.Util.randomFromList(missions) --[[@as Mission]]
|
||||
local mission = Util.randomFromList(missions) --[[@as Mission]]
|
||||
if mission then
|
||||
Spearhead.classes.persistence.Persistence.RegisterPickedRandomMission(mission.name, mission.zoneName)
|
||||
Persistence.RegisterPickedRandomMission(mission.name, mission.zoneName)
|
||||
|
||||
self._db.missionsByCode[mission.code] = mission
|
||||
|
||||
if mission.name and self._db.missionsByName[mission.name] == nil then
|
||||
self._db.missionsByName[mission.name] = mission
|
||||
else
|
||||
Spearhead.AddMissionEditorWarning("DUPLICATE MISSION NAME ALERT: " .. mission.name .. " in zone: " .. self.zoneName)
|
||||
MissionEditorWarnings.Add("DUPLICATE MISSION NAME ALERT: " .. mission.name .. " in zone: " .. self.zoneName)
|
||||
end
|
||||
|
||||
if mission.missionType == "SAM" then
|
||||
@@ -223,13 +234,13 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
local airbaseNames = database:getAirbaseNamesInStage(self.zoneName)
|
||||
if airbaseNames ~= nil and type(airbaseNames) == "table" then
|
||||
for _, airbaseName in pairs(airbaseNames) do
|
||||
local airbase = Spearhead.classes.stageClasses.SpecialZones.StageBase.New(database, logger, airbaseName, spawnManager)
|
||||
local airbase = StageBase.New(database, logger, airbaseName, spawnManager)
|
||||
table.insert(self._db.airbases, airbase)
|
||||
end
|
||||
end
|
||||
|
||||
for _, samZoneName in pairs(database:getBlueSamsInStage(self.zoneName)) do
|
||||
local blueSam = Spearhead.classes.stageClasses.SpecialZones.BlueSam.New(database, logger, samZoneName, spawnManager)
|
||||
local blueSam = BlueSam.New(database, logger, samZoneName, spawnManager)
|
||||
table.insert(self._db.blueSams, blueSam)
|
||||
end
|
||||
|
||||
@@ -242,7 +253,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
end
|
||||
end
|
||||
|
||||
Spearhead.Events.AddStageNumberChangedListener(self)
|
||||
Events.AddStageNumberChangedListener(self)
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -304,14 +315,14 @@ function Stage:CheckAndUpdateSelf()
|
||||
end
|
||||
|
||||
local max = dbTables.maxMissions
|
||||
local availableMissionsCount = Spearhead.Util.tableLength(getAvailableMissions())
|
||||
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
||||
local activeCount = getActiveMissionsCount()
|
||||
if activeCount < max and availableMissionsCount > 0 then
|
||||
for i = activeCount+1, max do
|
||||
if availableMissionsCount == 0 then
|
||||
i = max+1 --exits this loop
|
||||
else
|
||||
local mission = Spearhead.Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
||||
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
||||
if mission then
|
||||
mission:SpawnActive()
|
||||
activeCount = activeCount + 1;
|
||||
@@ -391,8 +402,8 @@ function Stage:MarkStage(stageColor)
|
||||
end
|
||||
|
||||
if self._stageDrawingId and self._stageConfig.isDrawStagesEnabled == true then
|
||||
Spearhead.DcsUtil.SetLineColor(self._stageDrawingId, lineColor)
|
||||
Spearhead.DcsUtil.SetFillColor(self._stageDrawingId, fillColor)
|
||||
DcsUtil.SetLineColor(self._stageDrawingId, lineColor)
|
||||
DcsUtil.SetFillColor(self._stageDrawingId, fillColor)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -405,7 +416,7 @@ function Stage:ActivateStage()
|
||||
|
||||
self:PreActivate(false)
|
||||
|
||||
self._logger:debug("Activating Misc groups for zone. Count: " .. Spearhead.Util.tableLength(self._db.miscGroups))
|
||||
self._logger:debug("Activating Misc groups for zone. Count: " .. Util.tableLength(self._db.miscGroups))
|
||||
for _, miscGroup in pairs(self._db.miscGroups) do
|
||||
miscGroup:Spawn()
|
||||
end
|
||||
@@ -452,7 +463,7 @@ function Stage:OnStageNumberChanged(number)
|
||||
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
||||
self._logger:debug("Pre-activating stage: " .. self.zoneName .. " with number: " .. number)
|
||||
self:PreActivate(true)
|
||||
elseif Spearhead.capInfo.IsCapActiveWhenZoneIsActive(self.zoneName, number) == true then
|
||||
elseif GlobalCapManager.IsCapActiveWhenZoneIsActive(self.zoneName, number) == true then
|
||||
self:PreActivate(false)
|
||||
end
|
||||
|
||||
@@ -547,7 +558,7 @@ end
|
||||
|
||||
function Stage:ActivateBlueStage()
|
||||
|
||||
self._logger:debug("Setting stage '" .. Spearhead.Util.toString(self.zoneName) .. "' to blue")
|
||||
self._logger:debug("Setting stage '" .. Util.toString(self.zoneName) .. "' to blue")
|
||||
|
||||
for _, mission in pairs(self._db.missions) do
|
||||
mission:SpawnPersistedState()
|
||||
@@ -575,11 +586,7 @@ function Stage:ActivateBlueStage()
|
||||
timer.scheduleFunction(ActivateBlueAsync, self, timer.getTime() + 3)
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Stages then Spearhead.classes.stageClasses.Stages = {} end
|
||||
if not Spearhead.classes.stageClasses.Stages.BaseStage then Spearhead.classes.stageClasses.Stages.BaseStage = {} end
|
||||
Spearhead.classes.stageClasses.Stages.BaseStage.Stage = Stage
|
||||
return Stage
|
||||
|
||||
|
||||
|
||||
+5
-6
@@ -1,4 +1,7 @@
|
||||
|
||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||
|
||||
---@class ExtraStage : Stage
|
||||
local ExtraStage = {}
|
||||
ExtraStage.__index = ExtraStage
|
||||
@@ -13,7 +16,6 @@ ExtraStage.__index = ExtraStage
|
||||
---@return ExtraStage
|
||||
function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(ExtraStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = ExtraStage }) --[[@as ExtraStage]]
|
||||
@@ -46,7 +48,7 @@ function ExtraStage:OnStageNumberChanged(number)
|
||||
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
||||
self._logger:debug("Pre-activating stage: " .. self.zoneName .. " with number: " .. number)
|
||||
self:PreActivate(true)
|
||||
elseif Spearhead.capInfo.IsCapActiveWhenZoneIsActive(self.zoneName, number) == true then
|
||||
elseif GlobalCapManager.IsCapActiveWhenZoneIsActive(self.zoneName, number) == true then
|
||||
self:PreActivate(false)
|
||||
end
|
||||
|
||||
@@ -61,9 +63,6 @@ function ExtraStage:OnStageNumberChanged(number)
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Stages then Spearhead.classes.stageClasses.Stages = {} end
|
||||
Spearhead.classes.stageClasses.Stages.ExtraStage = ExtraStage
|
||||
return ExtraStage
|
||||
|
||||
|
||||
+3
-5
@@ -1,4 +1,6 @@
|
||||
|
||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||
|
||||
---@class PrimaryStage : Stage
|
||||
local PrimaryStage = {}
|
||||
|
||||
@@ -13,7 +15,6 @@ PrimaryStage.__index = PrimaryStage
|
||||
---@return PrimaryStage
|
||||
function PrimaryStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(PrimaryStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = PrimaryStage }) --[[@as PrimaryStage]]
|
||||
@@ -22,9 +23,6 @@ function PrimaryStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Stages then Spearhead.classes.stageClasses.Stages = {} end
|
||||
Spearhead.classes.stageClasses.Stages.PrimaryStage = PrimaryStage
|
||||
return PrimaryStage
|
||||
|
||||
|
||||
+2
-6
@@ -1,3 +1,4 @@
|
||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||
|
||||
---@class WaitingStage : Stage
|
||||
---@field private _waitTimeSeconds integer
|
||||
@@ -18,8 +19,6 @@ local WaitingStageInitData = {}
|
||||
---@param spawnManager SpawnManager
|
||||
---@return WaitingStage
|
||||
function WaitingStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(WaitingStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = WaitingStage }) --[[@as WaitingStage]]
|
||||
@@ -69,9 +68,6 @@ function WaitingStage:GetExpectedTime()
|
||||
return self._startTime + self._waitTimeSeconds
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.Stages then Spearhead.classes.stageClasses.Stages = {} end
|
||||
Spearhead.classes.stageClasses.Stages.WaitingStage = WaitingStage
|
||||
return WaitingStage
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@class CustomDrawing
|
||||
---@field private _id integer?
|
||||
---@field private _drawingObject DrawingObject
|
||||
---@field private _startingStage number
|
||||
---@field private _removeAtStage number
|
||||
local CustomDrawing = {}
|
||||
CustomDrawing.__index = CustomDrawing
|
||||
|
||||
|
||||
---@param drawingObject DrawingObject
|
||||
---@param id integer?
|
||||
---@return CustomDrawing
|
||||
function CustomDrawing.New(drawingObject, id)
|
||||
local self = setmetatable({}, CustomDrawing)
|
||||
self._drawingObject = drawingObject
|
||||
self._id = id
|
||||
|
||||
local name = drawingObject.name
|
||||
local split = Util.split_string(name or "", "_")
|
||||
local secondPart = split[2] or "1"
|
||||
local splitPart = Util.split_string(secondPart, ":")
|
||||
self._startingStage = tonumber(splitPart[1]) or 1
|
||||
self._removeAtStage = tonumber(splitPart[2]) or math.huge
|
||||
return self
|
||||
end
|
||||
|
||||
---@return number start
|
||||
---@return number stop
|
||||
function CustomDrawing:GetStartAndStop()
|
||||
return self._startingStage, self._removeAtStage
|
||||
end
|
||||
|
||||
function CustomDrawing:Draw()
|
||||
self._id = DrawingHelper.Draw(self._drawingObject)
|
||||
end
|
||||
|
||||
function CustomDrawing:Remove()
|
||||
if self._id ~= nil then
|
||||
DrawingHelper.Remove(self._id)
|
||||
self._id = nil
|
||||
end
|
||||
end
|
||||
|
||||
return CustomDrawing
|
||||
@@ -0,0 +1,223 @@
|
||||
|
||||
|
||||
---@class DrawingHelper
|
||||
local DrawingHelper = {}
|
||||
DrawingHelper.__index = DrawingHelper
|
||||
|
||||
local customDrawingIdIncrementer = 4210
|
||||
|
||||
---@param object DrawingObject
|
||||
---@return integer? id
|
||||
function DrawingHelper.Draw(object)
|
||||
if object == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local id = DrawingHelper.GetAndAddId()
|
||||
if(object.primitiveType == "Polygon") then
|
||||
DrawingHelper.DrawPolygon(object--[[@as Polygon]], id)
|
||||
elseif(object.primitiveType == "Line") then
|
||||
DrawingHelper.DrawLine(object--[[@as Line]], id)
|
||||
elseif(object.primitiveType == "TextBox") then
|
||||
DrawingHelper.DrawTextBox(object--[[@as TextBox]], id)
|
||||
end
|
||||
|
||||
return id
|
||||
end
|
||||
|
||||
function DrawingHelper.GetAndAddId()
|
||||
customDrawingIdIncrementer = customDrawingIdIncrementer + 1
|
||||
return customDrawingIdIncrementer
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param shapeID ShapeId
|
||||
---@param drawID integer
|
||||
---@param points Array<Vec3>
|
||||
---@param fillColor table
|
||||
---@param lineColor table
|
||||
local function MarkupToAll(shapeID, drawID, points, fillColor, lineColor, lineStyle)
|
||||
|
||||
local functionString = "trigger.action.markupToAll(" .. shapeID .. ", -1, " .. drawID .. ","
|
||||
for _, point in ipairs(points) do
|
||||
functionString = functionString .. " { x=" .. point.x .. ", y=0,z=" .. point.z .. "},"
|
||||
end
|
||||
functionString = functionString ..
|
||||
"{ " .. lineColor[1] .. "," .. lineColor[2] .. "," .. lineColor[3] .. "," .. lineColor[4] .. "}, " ..
|
||||
"{ " .. fillColor[1] .. "," .. fillColor[2] .. "," .. fillColor[3] .. "," .. fillColor[4] .. "}, " ..
|
||||
lineStyle .. ")"
|
||||
|
||||
---@diagnostic disable-next-line: deprecated
|
||||
local f, err = loadstring(functionString)
|
||||
if f then
|
||||
f()
|
||||
else
|
||||
env.error("Something failed when drawing complex drawing" .. err)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param object Polygon
|
||||
---@param id integer
|
||||
function DrawingHelper.DrawPolygon(object, id)
|
||||
if object == nil then
|
||||
return
|
||||
end
|
||||
|
||||
---@param circle Circle
|
||||
local function DrawCircle(circle)
|
||||
local vec3 = { x = circle.mapX, y = 0, z = circle.mapY }
|
||||
local fillColor = DrawingHelper.ColorToColorTable(circle.fillColorString)
|
||||
local colorString = DrawingHelper.ColorToColorTable(circle.colorString)
|
||||
local style = DrawingHelper.ToLineStyleInteger(circle.style)
|
||||
trigger.action.circleToAll(-1, id, vec3, circle.radius, colorString, fillColor, style, true)
|
||||
end
|
||||
|
||||
---@param oval Oval
|
||||
local function DrawOval(oval)
|
||||
---@type Array<Vec3>
|
||||
local points = {}
|
||||
local pointsNo = 30
|
||||
local angleStep = (2 * math.pi) / points
|
||||
|
||||
local fillColor = DrawingHelper.ColorToColorTable(oval.fillColorString)
|
||||
local color = DrawingHelper.ColorToColorTable(oval.colorString)
|
||||
local lineStyle = DrawingHelper.ToLineStyleInteger(oval.style)
|
||||
|
||||
for i = 1, pointsNo do
|
||||
local angle = i * angleStep
|
||||
local x = oval.mapX + (oval.r1 * math.cos(angle))
|
||||
local y = oval.mapY + (oval.r2 * math.sin(angle))
|
||||
table.insert(points, { x = x, y = 0, z = y } )
|
||||
end
|
||||
MarkupToAll(7, id, points, fillColor, color, lineStyle)
|
||||
end
|
||||
|
||||
---@param free Free
|
||||
local function DrawFree(free)
|
||||
local fillColor = DrawingHelper.ColorToColorTable(free.fillColorString)
|
||||
local color = DrawingHelper.ColorToColorTable(free.colorString)
|
||||
local lineStyle = DrawingHelper.ToLineStyleInteger(free.style)
|
||||
|
||||
local points = {}
|
||||
for _, point in ipairs(free.points) do
|
||||
table.insert(points, { x = point.x, y = 0, z = point.y } )
|
||||
end
|
||||
MarkupToAll(7, id, points, fillColor, color, lineStyle)
|
||||
end
|
||||
|
||||
---@param rect Rect
|
||||
local function DrawRect(rect)
|
||||
local fillColor = DrawingHelper.ColorToColorTable(rect.fillColorString)
|
||||
local color = DrawingHelper.ColorToColorTable(rect.colorString)
|
||||
local lineStyle = DrawingHelper.ToLineStyleInteger(rect.style)
|
||||
|
||||
local pointA = { x = rect.mapX, y = 0, z = rect.mapY }
|
||||
local pointB = { x = rect.mapX + rect.width, y = 0, z = rect.mapY + rect.height }
|
||||
trigger.action.rectToAll(-1, id, pointA, pointB, color, fillColor, lineStyle, true)
|
||||
end
|
||||
|
||||
---@param arrow Arrow
|
||||
local function DrawArrow(arrow)
|
||||
local fillColor = DrawingHelper.ColorToColorTable(arrow.fillColorString)
|
||||
local color = DrawingHelper.ColorToColorTable(arrow.colorString)
|
||||
local lineStyle = DrawingHelper.ToLineStyleInteger(arrow.style)
|
||||
|
||||
local startPoint = { x = arrow.mapX, y = 0, z = arrow.mapY }
|
||||
local rad = math.rad(arrow.angle or 0)
|
||||
local length = arrow.length or 100
|
||||
local endPoint = { x = arrow.mapX + length * math.cos(rad), y = 0, z = arrow.mapY + length * math.sin(rad) }
|
||||
trigger.action.arrowToAll(-1, id, startPoint, endPoint, color, fillColor, lineStyle, true)
|
||||
end
|
||||
|
||||
if object.polygonMode == "circle" then
|
||||
DrawCircle(object--[[@as Circle]])
|
||||
elseif object.polygonMode == "oval" then
|
||||
DrawOval(object--[[@as Oval]])
|
||||
elseif object.polygonMode == "free" then
|
||||
DrawFree(object--[[@as Free]])
|
||||
elseif object.polygonMode == "rect" then
|
||||
DrawRect(object--[[@as Rect]])
|
||||
elseif object.polygonMode == "arrow" then
|
||||
DrawArrow(object--[[@as Arrow]])
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param object Line
|
||||
---@param id integer
|
||||
function DrawingHelper.DrawLine(object, id)
|
||||
|
||||
---@type Array<Vec3>
|
||||
local points = {}
|
||||
|
||||
for _, point in ipairs(object.points) do
|
||||
table.insert(points, { x = point.x, y = 0, z = point.y } )
|
||||
end
|
||||
|
||||
local color = DrawingHelper.ColorToColorTable(object.colorString)
|
||||
local lineStyle = DrawingHelper.ToLineStyleInteger(object.style)
|
||||
MarkupToAll(1, id, points, color, color, lineStyle)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param object TextBox
|
||||
---@param id integer
|
||||
function DrawingHelper.DrawTextBox(object, id)
|
||||
trigger.action.textToAll(-1, id, { x= object.mapX, y = 0, z = object.mapY },
|
||||
DrawingHelper.ColorToColorTable(object.colorString),
|
||||
DrawingHelper.ColorToColorTable(object.fillColorString),
|
||||
object.fontSize or 12,
|
||||
true,
|
||||
object.text or "")
|
||||
end
|
||||
|
||||
function DrawingHelper.Remove(id)
|
||||
trigger.action.removeMark(id)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param hexStr string
|
||||
---@return table
|
||||
function DrawingHelper.ColorToColorTable(hexStr)
|
||||
hexStr = hexStr:gsub("0x", "")
|
||||
local a = tonumber(hexStr:sub(1, 2), 16) / 255
|
||||
local r = tonumber(hexStr:sub(3, 4), 16) / 255
|
||||
local g = tonumber(hexStr:sub(5, 6), 16) / 255
|
||||
local b = tonumber(hexStr:sub(7, 8), 16) / 255
|
||||
|
||||
return { r, g , b , a }
|
||||
end
|
||||
|
||||
---@param lineStyle string
|
||||
function DrawingHelper.ToLineStyleInteger(lineStyle)
|
||||
lineStyle = lineStyle:lower()
|
||||
if lineStyle == "no line" then
|
||||
return 0
|
||||
elseif lineStyle == "solid" then
|
||||
return 1
|
||||
elseif lineStyle == "dashed" then
|
||||
return 2
|
||||
elseif lineStyle == "dotted" then
|
||||
return 3
|
||||
elseif lineStyle == "dot dash" then
|
||||
return 4
|
||||
elseif lineStyle == "long dash" then
|
||||
return 5
|
||||
elseif lineStyle == "two dash" then
|
||||
return 6
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
---@class ARGB
|
||||
---@field public a number
|
||||
---@field public r number
|
||||
---@field public g number
|
||||
---@field public b number
|
||||
|
||||
|
||||
return DrawingHelper
|
||||
+14
-14
@@ -1,3 +1,7 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class BattleManager
|
||||
---@field private _name string
|
||||
---@field private _logger Logger
|
||||
@@ -21,7 +25,7 @@ function BattleManager.New(redGroups, blueGroups, name, logLevel)
|
||||
|
||||
self._isActive = false
|
||||
self._name = name
|
||||
self._logger = Spearhead.LoggerTemplate.new("BattleManager_" .. name, logLevel)
|
||||
self._logger = Logger.new("BattleManager_" .. name, logLevel)
|
||||
|
||||
self._redGroups = redGroups
|
||||
self._blueGroups = blueGroups
|
||||
@@ -167,7 +171,7 @@ function BattleManager:getBestAmmo(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local entry = Spearhead.Util.randomFromList(shells)
|
||||
local entry = Util.randomFromList(shells)
|
||||
if entry and entry.desc and entry.desc.warhead then
|
||||
local caliber = entry.desc.warhead.caliber
|
||||
if caliber > 50 then
|
||||
@@ -213,10 +217,10 @@ function BattleManager:ToShootingHulls(groups)
|
||||
end
|
||||
end
|
||||
|
||||
local hulls = Spearhead.Util.getSeparatedConvexHulls(points, 50)
|
||||
local hulls = Util.getSeparatedConvexHulls(points, 50)
|
||||
local enlargedHulls = {}
|
||||
for _, hull in pairs(hulls) do
|
||||
local enlarged = Spearhead.Util.enlargeConvexHull(hull, 25)
|
||||
local enlarged = Util.enlargeConvexHull(hull, 25)
|
||||
if enlarged then
|
||||
table.insert(enlargedHulls, enlarged)
|
||||
end
|
||||
@@ -237,15 +241,15 @@ end
|
||||
---@return Vec2?
|
||||
function BattleManager:GetRandomPoint(origin, groupHulls)
|
||||
|
||||
local hull = Spearhead.Util.randomFromList(groupHulls) --[[@as Array<Vec2>]]
|
||||
local hull = Util.randomFromList(groupHulls) --[[@as Array<Vec2>]]
|
||||
if not hull then return nil end
|
||||
local shootPoints = Spearhead.Util.GetTangentHullPointsFromOrigin(hull, origin)
|
||||
local shootPoints = Util.GetTangentHullPointsFromOrigin(hull, origin)
|
||||
|
||||
if debugDrawing == true then
|
||||
self:DrawDebugZone({ hull })
|
||||
end
|
||||
|
||||
return Spearhead.Util.randomFromList(shootPoints) --[[@as Vec2]]
|
||||
return Util.randomFromList(shootPoints) --[[@as Vec2]]
|
||||
end
|
||||
|
||||
do --DEBUG
|
||||
@@ -258,7 +262,7 @@ do --DEBUG
|
||||
color = {r = 0, g = 0, b = 1, a = 1}
|
||||
end
|
||||
|
||||
Spearhead.DcsUtil.DrawLine(unit:getPoint(), {x = target.x, y = 0, z = target.y}, color, 1)
|
||||
DcsUtil.DrawLine(unit:getPoint(), {x = target.x, y = 0, z = target.y}, color, 1)
|
||||
end
|
||||
|
||||
---@param hulls Array<Array<Vec2>>
|
||||
@@ -274,13 +278,9 @@ do --DEBUG
|
||||
location = { x=drawHull[1].x, y=drawHull[1].y },
|
||||
}
|
||||
|
||||
Spearhead.DcsUtil.DrawZone(zone, {r =0, g=0, b =1, a = 0.5} ,{r =0, g= 0, b =1, a = 0}, 1)
|
||||
DcsUtil.DrawZone(zone, {r =0, g=0, b =1, a = 0.5} ,{r =0, g= 0, b =1, a = 0}, 1)
|
||||
end
|
||||
end
|
||||
end --DEBUG
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.helpers == nil then Spearhead.classes.stageClasses.helpers = {} end
|
||||
Spearhead.classes.stageClasses.helpers.BattleManager = BattleManager
|
||||
return BattleManager
|
||||
@@ -0,0 +1,20 @@
|
||||
---@class MaxLoadConfig
|
||||
---@field maxInternalLoad number
|
||||
|
||||
---@type table<string, MaxLoadConfig>
|
||||
local MaxLoadConfig = {
|
||||
["Mi-8MT"] = {
|
||||
maxInternalLoad = 4000,
|
||||
},
|
||||
["CH-47Fbl1"] = {
|
||||
maxInternalLoad = 10000
|
||||
},
|
||||
["Mi-24P"] = {
|
||||
maxInternalLoad = 2000
|
||||
},
|
||||
["UH-1H"] = {
|
||||
maxInternalLoad = 2000
|
||||
}
|
||||
}
|
||||
|
||||
return MaxLoadConfig
|
||||
+37
-31
@@ -1,3 +1,10 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Logger = require("classes.util.Logger")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local SupplyUnitsTracker = require("classes.stageClasses.helpers.SupplyUnitsTracker")
|
||||
local SupplyConfigHelper = require("classes.stageClasses.helpers.SupplyConfigHelper")
|
||||
|
||||
|
||||
---@class MissionCommandsHelper
|
||||
---@field missionsByCode table<string, Mission> @table of missions by their code
|
||||
@@ -17,8 +24,8 @@ MissionCommandsHelper.__index = MissionCommandsHelper
|
||||
---@param groupPos Vec2
|
||||
local function sortMissions(list, groupPos)
|
||||
table.sort(list, function(a, b)
|
||||
local distA = Spearhead.Util.VectorDistance2d(groupPos, a.location or {x=0, y=0})
|
||||
local distB = Spearhead.Util.VectorDistance2d(groupPos, b.location or {x=0, y=0})
|
||||
local distA = Util.VectorDistance2d(groupPos, a.location or {x=0, y=0})
|
||||
local distB = Util.VectorDistance2d(groupPos, b.location or {x=0, y=0})
|
||||
return distA < distB;
|
||||
end)
|
||||
end
|
||||
@@ -33,7 +40,7 @@ function MissionCommandsHelper.getOrCreate(logLevel)
|
||||
if instance == nil then
|
||||
instance = setmetatable({}, MissionCommandsHelper)
|
||||
|
||||
instance._logger = Spearhead.LoggerTemplate.new("MissionCommandsHelper", logLevel)
|
||||
instance._logger = Logger.new("MissionCommandsHelper", logLevel)
|
||||
|
||||
instance._logger:info("Creating MissionCommandsHelper instance")
|
||||
|
||||
@@ -45,7 +52,7 @@ function MissionCommandsHelper.getOrCreate(logLevel)
|
||||
instance._supplyHubGroups = {}
|
||||
instance._stageBriefings = {}
|
||||
|
||||
instance._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logLevel)
|
||||
instance._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate(logLevel)
|
||||
|
||||
---comment
|
||||
---@param selfA MissionCommandsHelper
|
||||
@@ -56,7 +63,7 @@ function MissionCommandsHelper.getOrCreate(logLevel)
|
||||
return time + 10
|
||||
end
|
||||
|
||||
for _, unit in pairs(Spearhead.DcsUtil.getAllPlayerUnits()) do
|
||||
for _, unit in pairs(DcsUtil.getAllPlayerUnits()) do
|
||||
if unit and unit:isExist() then
|
||||
local group = unit:getGroup()
|
||||
if group then
|
||||
@@ -71,7 +78,7 @@ function MissionCommandsHelper.getOrCreate(logLevel)
|
||||
end
|
||||
|
||||
timer.scheduleFunction(instance.updateContinuous, instance, timer.getTime() + 5)
|
||||
Spearhead.Events.AddOnPlayerEnterUnitListener(instance)
|
||||
SpearheadEvents.AddOnPlayerEnterUnitListener(instance)
|
||||
|
||||
end
|
||||
|
||||
@@ -174,7 +181,7 @@ function MissionCommandsHelper:AddOverviewCommand(groupID)
|
||||
|
||||
local text = "Missions Overview\n\n"
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(id)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(id)
|
||||
---@type Vec2
|
||||
local groupPos = { x=0, y=0 }
|
||||
if group then
|
||||
@@ -193,7 +200,7 @@ function MissionCommandsHelper:AddOverviewCommand(groupID)
|
||||
if lead and lead:isExist() == true then
|
||||
local pos = lead:getPoint()
|
||||
local Vec2Pos = { x= pos.x, y=pos.z }
|
||||
local distance = Spearhead.Util.VectorDistance2d(Vec2Pos, mission.location) / 1852
|
||||
local distance = Util.VectorDistance2d(Vec2Pos, mission.location) / 1852
|
||||
distanceText = string.format("~%d", math.floor(distance))
|
||||
end
|
||||
end
|
||||
@@ -323,7 +330,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
||||
|
||||
local perFolder = 9
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
---@type Vec2
|
||||
local groupPos = { x=0, y=0 }
|
||||
if group then
|
||||
@@ -351,7 +358,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
||||
for _, mission in pairs(primaryMissions) do
|
||||
count = count + 1
|
||||
if count <= perFolder then
|
||||
local copied = Spearhead.Util.deepCopyTable(path)
|
||||
local copied = Util.deepCopyTable(path)
|
||||
self:addMissionCommands(groupID, copied, mission)
|
||||
else
|
||||
local name = "Next Menu ..."
|
||||
@@ -380,7 +387,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
||||
for _, mission in pairs(secondaryMissions) do
|
||||
count = count + 1
|
||||
if count <= perFolder then
|
||||
local copied = Spearhead.Util.deepCopyTable(path)
|
||||
local copied = Util.deepCopyTable(path)
|
||||
self:addMissionCommands(groupID, copied, mission)
|
||||
else
|
||||
local name = "Next Menu ..."
|
||||
@@ -401,14 +408,14 @@ function MissionCommandsHelper:addMissionCommands(groupId, path, mission)
|
||||
|
||||
if path then
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
local distance = "[?]"
|
||||
if group then
|
||||
local lead = group:getUnit(1)
|
||||
if lead and lead:isExist() == true then
|
||||
local pos = lead:getPoint()
|
||||
local Vec2Pos = { x= pos.x, y=pos.z }
|
||||
local dist = Spearhead.Util.VectorDistance2d(Vec2Pos, mission.location) / 1852
|
||||
local dist = Util.VectorDistance2d(Vec2Pos, mission.location) / 1852
|
||||
distance = "[" .. string.format("~%dnM", math.floor(dist)) .. "]"
|
||||
end
|
||||
end
|
||||
@@ -435,7 +442,7 @@ function MissionCommandsHelper:AddSupplyHubCommandsIfApplicable(groupID)
|
||||
|
||||
self._logger:debug("Adding supply hub commands for group: " .. tostring(groupID))
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group == nil then return end
|
||||
|
||||
local unit = group:getUnit(1)
|
||||
@@ -446,6 +453,7 @@ function MissionCommandsHelper:AddSupplyHubCommandsIfApplicable(groupID)
|
||||
---@field groupID number
|
||||
---@field crateType CrateType
|
||||
---@field supplyUnitsTracker SupplyUnitsTracker
|
||||
---@field commandHelper MissionCommandsHelper
|
||||
|
||||
---comment
|
||||
---@param params LoadCargoCommandParams
|
||||
@@ -453,36 +461,36 @@ function MissionCommandsHelper:AddSupplyHubCommandsIfApplicable(groupID)
|
||||
local crateType = params.crateType
|
||||
local supplyUnitsTracker = params.supplyUnitsTracker
|
||||
if supplyUnitsTracker then
|
||||
supplyUnitsTracker:UnitRequestCrateLoading(params.groupID, crateType)
|
||||
supplyUnitsTracker:UnitRequestCrateLoading(params.groupID, crateType, params.commandHelper)
|
||||
end
|
||||
end
|
||||
|
||||
local path = { [1] = folderNames.supplyHub }
|
||||
|
||||
---@type LoadCargoCommandParams
|
||||
local farpParams1000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "FARP_CRATE_1000", supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
local farpParams1000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "FARP_CRATE_1000", supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Load FARP Crate (1000)", path, loadCargoCommand, farpParams1000)
|
||||
|
||||
---@type LoadCargoCommandParams
|
||||
local farpParams2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "FARP_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
local farpParams2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "FARP_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Load FARP Crate (2000)", path, loadCargoCommand, farpParams2000)
|
||||
|
||||
---@type LoadCargoCommandParams
|
||||
local samParms1000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "SAM_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
local samParms1000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "SAM_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Load SAM Crate (1000)", path, loadCargoCommand, samParms1000)
|
||||
|
||||
---@type LoadCargoCommandParams
|
||||
local samParms2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "SAM_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
local samParms2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "SAM_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Load SAM Crate (2000)", path, loadCargoCommand, samParms2000)
|
||||
|
||||
---@type LoadCargoCommandParams
|
||||
local samParms2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "AIRBASE_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
missionCommands.addCommandForGroup(groupID, "Airbase Crate (2000)", path, loadCargoCommand, samParms2000)
|
||||
local airbaseParms2000 = { unitID = unit:getID(), groupID = group:getID(), crateType = "AIRBASE_CRATE_2000", supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Airbase Crate (2000)", path, loadCargoCommand, airbaseParms2000)
|
||||
end
|
||||
|
||||
function MissionCommandsHelper:AddCargoCommands(groupID)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group == nil then return end
|
||||
|
||||
local unit = group:getUnit(1)
|
||||
@@ -492,24 +500,26 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
||||
---@field unitID number
|
||||
---@field crateType CrateType
|
||||
---@field supplyUnitsTracker SupplyUnitsTracker
|
||||
---@field commandHelper MissionCommandsHelper
|
||||
|
||||
---comment
|
||||
---@param params UnloadCargoCommandParams
|
||||
local unloadCargoCommand = function(params)
|
||||
local unitID = params.unitID
|
||||
local crateType = params.crateType
|
||||
params.supplyUnitsTracker:UnloadRequested(unitID, crateType)
|
||||
local supplyUnitsTracker = params.supplyUnitsTracker
|
||||
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
||||
end
|
||||
|
||||
local cargo = self._supplyUnitsTracker:GetCargoInUnit(unit:getID())
|
||||
if cargo then
|
||||
for cargoType, amount in pairs(cargo) do
|
||||
local cargoConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(cargoType)
|
||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
||||
if cargoConfig then
|
||||
for i = 1, amount do
|
||||
local path = { [1] = folderNames.cargo }
|
||||
---@type UnloadCargoCommandParams
|
||||
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self._supplyUnitsTracker }
|
||||
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self._supplyUnitsTracker, commandHelper = self }
|
||||
missionCommands.addCommandForGroup(groupID, "Unload " .. cargoConfig.displayName, path, unloadCargoCommand, params)
|
||||
end
|
||||
end
|
||||
@@ -531,7 +541,7 @@ function MissionCommandsHelper:addMissionFolders(groupId)
|
||||
missionCommands.addSubMenuForGroup(groupId, folderNames.supplyHub)
|
||||
end
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
if group == nil then return end
|
||||
|
||||
local unit = group:getUnit(1)
|
||||
@@ -561,8 +571,4 @@ function MissionCommandsHelper:ResetFolders(groupID)
|
||||
self:addMissionFolders(groupID)
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.helpers == nil then Spearhead.classes.stageClasses.helpers = {} end
|
||||
Spearhead.classes.stageClasses.helpers.MissionCommandsHelper = MissionCommandsHelper
|
||||
return MissionCommandsHelper
|
||||
+5
-26
@@ -1,4 +1,6 @@
|
||||
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
---@alias SupplyType
|
||||
---| "FARP_CRATE"
|
||||
---| "SAM_CRATE"
|
||||
@@ -65,24 +67,6 @@ local SupplyConfig = {
|
||||
},
|
||||
}
|
||||
|
||||
---@class MaxLoadConfig
|
||||
---@field maxInternalLoad number
|
||||
|
||||
---@type table<string, MaxLoadConfig>
|
||||
MaxLoadConfig = {
|
||||
["Mi-8MT"] = {
|
||||
maxInternalLoad = 4000,
|
||||
},
|
||||
["CH-47Fbl1"] = {
|
||||
maxInternalLoad = 10000
|
||||
},
|
||||
["Mi-24P"] = {
|
||||
maxInternalLoad = 2000
|
||||
},
|
||||
["UH-1H"] = {
|
||||
maxInternalLoad = 2000
|
||||
}
|
||||
}
|
||||
|
||||
---@class SupplyConfigHelper
|
||||
local SupplyConfigHelper = {}
|
||||
@@ -92,7 +76,7 @@ local SupplyConfigHelper = {}
|
||||
---@return SupplyConfig?
|
||||
function SupplyConfigHelper.fromObjectName(name)
|
||||
for configName, config in pairs(SupplyConfig) do
|
||||
if Spearhead.Util.startswith(name, configName, true) == true then
|
||||
if Util.startswith(name, configName, true) == true then
|
||||
return config
|
||||
end
|
||||
end
|
||||
@@ -104,11 +88,6 @@ function SupplyConfigHelper.getSupplyConfig(type)
|
||||
return SupplyConfig[type]
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.helpers == nil then Spearhead.classes.stageClasses.helpers = {} end
|
||||
if Spearhead.classes.stageClasses.helpers.supplies == nil then Spearhead.classes.stageClasses.helpers.supplies = {} end
|
||||
Spearhead.classes.stageClasses.helpers.supplies.MaxLoadConfig = MaxLoadConfig
|
||||
Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper = SupplyConfigHelper
|
||||
|
||||
return SupplyConfigHelper
|
||||
|
||||
+81
-46
@@ -1,15 +1,24 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local SupplyConfigHelper = require("classes.stageClasses.helpers.SupplyConfigHelper")
|
||||
local MaxLoadConfig = require("classes.stageClasses.helpers.MaxLoadConfig")
|
||||
|
||||
env.info("Spearhead SupplyUnitsTracker loaded")
|
||||
---@class SupplyUnitEventListener
|
||||
---@field supplyUnitSpawned fun(self:SupplyUnitEventListener, unit:Unit) | nil
|
||||
---@field enteredSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
||||
---@field exitedSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
||||
|
||||
---@class SupplyUnitsTracker
|
||||
---@field private _supplyUnitsByName table<string, Unit>
|
||||
---@field private _cargoInUnits table<string, table<CrateType, number>>
|
||||
---@field private _logger Logger
|
||||
---@field private _unitPositions table<string, Vec3>
|
||||
---@field private _commandsHelper MissionCommandsHelper
|
||||
---@field private _unitInSupplyHub table<string, boolean>
|
||||
---@field private _droppedCrates table<string, StaticObject>
|
||||
---@field private _registeredHubs table<SupplyHub, boolean>
|
||||
---@field private _supplyUnitSpawnedListener Array<SupplyUnitSpawnedListener>
|
||||
---@field private _supplyUnitEventsListeners Array<SupplyUnitEventListener>
|
||||
local SupplyUnitsTracker = {}
|
||||
SupplyUnitsTracker.__index = SupplyUnitsTracker
|
||||
|
||||
@@ -23,17 +32,16 @@ function SupplyUnitsTracker.getOrCreate(logLevel)
|
||||
|
||||
if singleton == nil then
|
||||
singleton = setmetatable({}, SupplyUnitsTracker)
|
||||
singleton._logger = Spearhead.LoggerTemplate.new("SupplyUnitsTracker", logLevel)
|
||||
singleton._logger = Logger.new("SupplyUnitsTracker", logLevel)
|
||||
singleton._unitPositions = {}
|
||||
singleton._cargoInUnits = {}
|
||||
singleton._supplyUnitsByName = {}
|
||||
singleton._droppedCrates = {}
|
||||
singleton._registeredHubs = {}
|
||||
singleton._supplyUnitSpawnedListener = {}
|
||||
singleton._supplyUnitEventsListeners = {}
|
||||
singleton._unitInSupplyHub = {}
|
||||
|
||||
singleton._commandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(singleton._logger.LogLevel)
|
||||
|
||||
Spearhead.Events.AddOnPlayerEnterUnitListener(singleton)
|
||||
SpearheadEvents.AddOnPlayerEnterUnitListener(singleton)
|
||||
|
||||
---@param selfA SupplyUnitsTracker
|
||||
local function updateTask(selfA, time)
|
||||
@@ -70,33 +78,34 @@ function SupplyUnitsTracker:OnPlayerEntersUnit(unit)
|
||||
if self:IsSupplyUnit(unit) == true then
|
||||
self._supplyUnitsByName[unit:getName()] = unit
|
||||
self._cargoInUnits[tostring(unit:getID())] = nil
|
||||
self._unitInSupplyHub[tostring(unit:getID())] = false
|
||||
self._unitPositions[tostring(unit:getID())] = unit:getPoint()
|
||||
end
|
||||
|
||||
for _, listener in pairs(self._supplyUnitSpawnedListener) do
|
||||
for _, listener in pairs(self._supplyUnitEventsListeners) do
|
||||
pcall(function()
|
||||
listener:SupplyUnitSpawned(unit)
|
||||
if listener.supplyUnitSpawned then
|
||||
listener:supplyUnitSpawned(unit)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
---@class SupplyUnitSpawnedListener
|
||||
---@field SupplyUnitSpawned fun(self:SupplyUnitSpawnedListener, unit:Unit)
|
||||
|
||||
---@param listener SupplyUnitSpawnedListener
|
||||
---@param listener SupplyUnitEventListener
|
||||
function SupplyUnitsTracker:AddOnSupplyUnitSpawnedListener(listener)
|
||||
if listener == nil then return end
|
||||
|
||||
if self._supplyUnitSpawnedListener == nil then
|
||||
self._supplyUnitSpawnedListener = {}
|
||||
if self._supplyUnitEventsListeners == nil then
|
||||
self._supplyUnitEventsListeners = {}
|
||||
end
|
||||
|
||||
table.insert(self._supplyUnitSpawnedListener, listener)
|
||||
table.insert(self._supplyUnitEventsListeners, listener)
|
||||
end
|
||||
|
||||
function SupplyUnitsTracker:Update()
|
||||
local players = Spearhead.DcsUtil.getAllPlayerUnits()
|
||||
local players = DcsUtil.getAllPlayerUnits()
|
||||
for _, player in pairs(players) do
|
||||
if player ~= nil and player:isExist() and self:IsSupplyUnit(player) == true then
|
||||
self._supplyUnitsByName[player:getName()] = player
|
||||
@@ -127,7 +136,7 @@ function SupplyUnitsTracker:AddCargoToUnit(unitID, crateType)
|
||||
|
||||
if unitID == nil or crateType == nil then return end
|
||||
|
||||
local unit = Spearhead.DcsUtil.GetPLayerUnitByID(unitID)
|
||||
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
||||
if unit == nil then return end
|
||||
|
||||
if self._cargoInUnits[unitID] == nil then
|
||||
@@ -142,6 +151,7 @@ function SupplyUnitsTracker:AddCargoToUnit(unitID, crateType)
|
||||
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param unitID number
|
||||
---@param crateType CrateType
|
||||
function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
|
||||
@@ -168,13 +178,14 @@ function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
|
||||
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param unit Unit
|
||||
function SupplyUnitsTracker:UpdateWeightForUnit(unit)
|
||||
|
||||
local weight = 0
|
||||
if self._cargoInUnits[tostring(unit:getID())] then
|
||||
for crateType, count in pairs(self._cargoInUnits[tostring(unit:getID())]) do
|
||||
local crateConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
local crateConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
if crateConfig and count then
|
||||
weight = weight + (crateConfig.weight * count)
|
||||
end
|
||||
@@ -197,10 +208,30 @@ function SupplyUnitsTracker:CheckUnitsInZones()
|
||||
if enabled == true then
|
||||
local zone = hub:GetZone()
|
||||
if zone ~= nil then
|
||||
if Spearhead.Util.is3dPointInZone(pos, zone) then
|
||||
self._commandsHelper:MarkUnitInSupplyHub(group:getID())
|
||||
if Util.is3dPointInZone(pos, zone) then
|
||||
if self._unitInSupplyHub[tostring(unit:getID())] ~= true then
|
||||
self._unitInSupplyHub[tostring(unit:getID())] = true
|
||||
|
||||
for _, listener in pairs(self._supplyUnitEventsListeners) do
|
||||
pcall(function()
|
||||
if listener.enteredSupplyHub then
|
||||
listener:enteredSupplyHub(unit, hub)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
self._commandsHelper:MarkUnitOutsideSupplyHub(group:getID())
|
||||
if self._unitInSupplyHub[tostring(unit:getID())] == true then
|
||||
self._unitInSupplyHub[tostring(unit:getID())] = false
|
||||
for _, listener in pairs(self._supplyUnitEventsListeners) do
|
||||
pcall(function()
|
||||
if listener.exitedSupplyHub then
|
||||
listener:exitedSupplyHub(unit, hub)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -237,11 +268,16 @@ function SupplyUnitsTracker:GetUnits()
|
||||
end
|
||||
|
||||
local cargoCount = 0
|
||||
function SupplyUnitsTracker:UnloadRequested(unitID, crateType)
|
||||
|
||||
---comment
|
||||
---@param unitID number
|
||||
---@param crateType CrateType
|
||||
---@param missionCommandsHelper MissionCommandsHelper
|
||||
function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHelper)
|
||||
|
||||
self._logger:debug("Unload requested for unit: " .. unitID .. " crateType: " .. crateType)
|
||||
|
||||
local unit = Spearhead.DcsUtil.GetPLayerUnitByID(unitID)
|
||||
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
||||
if unit == nil or unit:isExist() == false then return end
|
||||
local group = unit:getGroup()
|
||||
if group == nil then
|
||||
@@ -251,7 +287,7 @@ function SupplyUnitsTracker:UnloadRequested(unitID, crateType)
|
||||
self:RemoveCargoFromUnit(unitID, crateType)
|
||||
self:UpdateWeightForUnit(unit)
|
||||
|
||||
local cargoConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
|
||||
if cargoConfig == nil then
|
||||
self._logger:error("Invalid crate type: " .. crateType)
|
||||
@@ -270,7 +306,7 @@ function SupplyUnitsTracker:UnloadRequested(unitID, crateType)
|
||||
|
||||
local spawned = coalition.addStaticObject(unit:getCoalition(), cargoSpawnObject)
|
||||
self._droppedCrates[cargoSpawnObject.name] = spawned
|
||||
self._commandsHelper:updateCommandsForGroup(group:getID())
|
||||
missionCommandsHelper:updateCommandsForGroup(group:getID())
|
||||
end
|
||||
|
||||
---@return table<string,StaticObject>
|
||||
@@ -281,14 +317,15 @@ end
|
||||
---Loads a crate directly into the unit
|
||||
---@param groupID number
|
||||
---@param crateType CrateType
|
||||
function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType)
|
||||
---@param missionCommandsHelper MissionCommandsHelper
|
||||
function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType, missionCommandsHelper)
|
||||
|
||||
self._logger:debug("UnitRequestCrateLoading called with groupID: " .. groupID .. " and crateType: " .. crateType)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group ~= nil then
|
||||
|
||||
local crateConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
local crateConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
if crateConfig == nil then
|
||||
self._logger:error("Invalid crate type: " .. crateType)
|
||||
return
|
||||
@@ -312,11 +349,12 @@ function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType)
|
||||
---@field unit Unit
|
||||
---@field groupID number
|
||||
---@field crateType CrateType
|
||||
---@field commandHelper MissionCommandsHelper
|
||||
|
||||
---@param params LoadCargoParams
|
||||
local LoadCrateTask = function(params)
|
||||
|
||||
local loaded = params.self:TryLoadCrateInUnit(params.unit, params.crateType)
|
||||
local loaded = params.self:TryLoadCrateInUnit(params.unit, params.crateType, params.commandHelper)
|
||||
if loaded ~= false then
|
||||
trigger.action.outTextForUnit(unit:getID(), "Loaded crate :" .. params.crateType, 10)
|
||||
end
|
||||
@@ -327,7 +365,8 @@ function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType)
|
||||
self = self,
|
||||
unit = unit,
|
||||
crateType = crateType,
|
||||
groupID = groupID
|
||||
groupID = groupID,
|
||||
commandHelper = missionCommandsHelper
|
||||
}
|
||||
|
||||
timer.scheduleFunction(LoadCrateTask, params, timer.getTime() + 15)
|
||||
@@ -338,10 +377,11 @@ end
|
||||
---comment
|
||||
---@param unit Unit
|
||||
---@param crateType CrateType
|
||||
---@param commandHelper MissionCommandsHelper
|
||||
---@return boolean
|
||||
function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType)
|
||||
function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType, commandHelper)
|
||||
|
||||
local crateConfigA = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
local crateConfigA = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
if crateConfigA == nil then
|
||||
trigger.action.outTextForUnit(unit:getID(), "Invalid crate type: " .. crateType, 5)
|
||||
return false
|
||||
@@ -354,7 +394,7 @@ function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType)
|
||||
end
|
||||
end
|
||||
|
||||
local unitConfig = Spearhead.classes.stageClasses.helpers.supplies.MaxLoadConfig[unit:getTypeName()]
|
||||
local unitConfig = MaxLoadConfig[unit:getTypeName()]
|
||||
if unitConfig == nil then
|
||||
trigger.action.outTextForUnit(unit:getID(), "Your unit type is not configured for logistics: " .. crateType, 5)
|
||||
self._logger:error("Invalid unit type: " .. unit:getTypeName())
|
||||
@@ -373,7 +413,7 @@ function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType)
|
||||
local group = unit:getGroup()
|
||||
if group == nil then return false end
|
||||
local groupID = group:getID()
|
||||
self._commandsHelper:updateCommandsForGroup(groupID)
|
||||
commandHelper:updateCommandsForGroup(groupID)
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -383,10 +423,10 @@ end
|
||||
---@param crateType CrateType
|
||||
function SupplyUnitsTracker:UnitRequestCrateSpawn(groupID, crateType)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group == nil then
|
||||
|
||||
local crateConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
local crateConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||
if crateConfig == nil then
|
||||
self._logger:error("Invalid crate type: " .. crateType)
|
||||
return
|
||||
@@ -404,19 +444,19 @@ end
|
||||
function SupplyUnitsTracker:GetCargoPlacePosition(unit)
|
||||
|
||||
local pos = unit:getPosition()
|
||||
local preferedPos = {
|
||||
local preferredPos = {
|
||||
x = pos.p.x - 10 * pos.x.x,
|
||||
y = pos.p.y - 10 * pos.x.y,
|
||||
z = pos.p.z - 10 * pos.x.z
|
||||
}
|
||||
|
||||
return preferedPos
|
||||
return preferredPos
|
||||
|
||||
|
||||
-- local volume = {
|
||||
-- id = world.VolumeType.SPHERE,
|
||||
-- params = {
|
||||
-- point = preferedPos,
|
||||
-- point = preferredPos,
|
||||
-- radius = 10
|
||||
-- }
|
||||
-- }
|
||||
@@ -446,9 +486,4 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit)
|
||||
|
||||
end
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
if Spearhead.classes.stageClasses.helpers == nil then Spearhead.classes.stageClasses.helpers = {} end
|
||||
Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker = SupplyUnitsTracker
|
||||
return SupplyUnitsTracker
|
||||
+26
-24
@@ -1,6 +1,12 @@
|
||||
local Mission = require("classes.stageClasses.missions.baseMissions.Mission")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local SupplyUnitsTracker = require("classes.stageClasses.helpers.SupplyUnitsTracker")
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||
local SupplyConfigHelper = require("classes.stageClasses.helpers.SupplyConfigHelper")
|
||||
|
||||
|
||||
---@class BuildableMission : Mission, SupplyUnitSpawnedListener
|
||||
---@class BuildableMission : Mission, SupplyUnitEventListener
|
||||
---@field private _requiredKilos number
|
||||
---@field private _droppedKilos number
|
||||
---@field private _crateType SupplyType
|
||||
@@ -27,7 +33,6 @@ BuildableMission.__index = BuildableMission
|
||||
---@param logger Logger
|
||||
function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType)
|
||||
|
||||
local Mission = Spearhead.classes.stageClasses.missions.baseMissions.Mission
|
||||
setmetatable(BuildableMission, Mission)
|
||||
|
||||
local self = setmetatable({}, { __index = BuildableMission })
|
||||
@@ -42,7 +47,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
||||
if noLandingZone then
|
||||
|
||||
local verts = noLandingZone.verts
|
||||
local enlarged = Spearhead.Util.enlargeConvexHull(verts, 300)
|
||||
local enlarged = Util.enlargeConvexHull(verts, 300)
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local dropOfZone = {
|
||||
@@ -71,7 +76,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
||||
self._onCrateDroppedOfListeners = {}
|
||||
self._completeListeners = {}
|
||||
self._markIDsPerGroup = {}
|
||||
self._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logger.LogLevel)
|
||||
self._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate(logger.LogLevel)
|
||||
self._state = "NEW"
|
||||
|
||||
|
||||
@@ -82,7 +87,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
||||
|
||||
self.priority = "secondary"
|
||||
|
||||
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(self._logger.LogLevel)
|
||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate(self._logger.LogLevel)
|
||||
|
||||
self._crateType = requiredCrateType
|
||||
|
||||
@@ -96,11 +101,11 @@ end
|
||||
|
||||
function BuildableMission:ShowBriefing(groupID)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group == nil then return end
|
||||
|
||||
local unitType = Spearhead.DcsUtil.getUnitTypeFromGroup(group)
|
||||
local coords = Spearhead.DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
||||
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||
|
||||
local siteType = "FARP"
|
||||
if self._crateType == "SAM_CRATE" then
|
||||
@@ -119,18 +124,18 @@ function BuildableMission:ShowBriefing(groupID)
|
||||
"\n\n" ..
|
||||
"NOTE: Do not land in the orange construction zone!"
|
||||
|
||||
trigger.action.outTextForGroup(groupID, briefing, Spearhead.GlobalConfig:getBriefingTime())
|
||||
trigger.action.outTextForGroup(groupID, briefing, GlobalConfig:getBriefingTime())
|
||||
end
|
||||
|
||||
function BuildableMission:MarkMissionAreaToGroup(groupID)
|
||||
|
||||
if self._markIDsPerGroup[groupID] then
|
||||
Spearhead.DcsUtil.RemoveMark(self._markIDsPerGroup[groupID])
|
||||
DcsUtil.RemoveMark(self._markIDsPerGroup[groupID])
|
||||
end
|
||||
|
||||
local text = "[" .. self.code .. "] " .. self.name .. " | " .. self._crateType
|
||||
local location = { x= self.location.x, y=land.getHeight(self.location), z=self.location.y }
|
||||
local markID = Spearhead.DcsUtil.AddMarkToGroup(groupID, text, location)
|
||||
local markID = DcsUtil.AddMarkToGroup(groupID, text, location)
|
||||
|
||||
self._markIDsPerGroup[groupID] = markID
|
||||
end
|
||||
@@ -163,7 +168,7 @@ function BuildableMission:SpawnActive()
|
||||
local lineColor = { r=230/255, g=93/255, b=49/255, a=1}
|
||||
---@type DrawColor
|
||||
local fillColor = { r=230/255, g=93/255, b=49/255, a=0.2}
|
||||
self._noLandingZoneId = Spearhead.DcsUtil.DrawZone(self._noLandingZone, lineColor, fillColor, 6)
|
||||
self._noLandingZoneId = DcsUtil.DrawZone(self._noLandingZone, lineColor, fillColor, 6)
|
||||
|
||||
if self._dropOffZone == nil then
|
||||
self._logger:error("No drop off zone found for mission: " .. self.code)
|
||||
@@ -172,7 +177,7 @@ function BuildableMission:SpawnActive()
|
||||
|
||||
local lineColor2 = { r=0, g=0, b=1, a=1}
|
||||
local fillColor2 = { r=0, g=0, b=1, a=0}
|
||||
self._dropOffZoneId = Spearhead.DcsUtil.DrawZone(self._dropOffZone, lineColor2, fillColor2, 6)
|
||||
self._dropOffZoneId = DcsUtil.DrawZone(self._dropOffZone, lineColor2, fillColor2, 6)
|
||||
|
||||
---@param selfA BuildableMission
|
||||
---@param time number
|
||||
@@ -230,17 +235,17 @@ function BuildableMission:CheckCratesInZone()
|
||||
|
||||
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
||||
for _, staticObject in pairs(crates) do
|
||||
if staticObject and staticObject:isExist() and Spearhead.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()
|
||||
|
||||
if Spearhead.Util.is3dPointInZone(pos, self._dropOffZone) then
|
||||
if Util.is3dPointInZone(pos, self._dropOffZone) then
|
||||
table.insert(foundCrates, staticObject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, foundCrate in pairs(foundCrates) do
|
||||
local crateConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.fromObjectName(foundCrate:getName())
|
||||
local crateConfig = SupplyConfigHelper.fromObjectName(foundCrate:getName())
|
||||
if crateConfig then
|
||||
self._droppedKilos = self._droppedKilos + crateConfig.weight
|
||||
foundCrate:destroy()
|
||||
@@ -249,8 +254,8 @@ function BuildableMission:CheckCratesInZone()
|
||||
end
|
||||
|
||||
if self._droppedKilos >= self._requiredKilos then
|
||||
Spearhead.DcsUtil.RemoveMark(self._noLandingZoneId)
|
||||
Spearhead.DcsUtil.RemoveMark(self._dropOffZoneId)
|
||||
DcsUtil.RemoveMark(self._noLandingZoneId)
|
||||
DcsUtil.RemoveMark(self._dropOffZoneId)
|
||||
self:NotifyMissionComplete()
|
||||
self._state = "COMPLETED"
|
||||
end
|
||||
@@ -258,7 +263,7 @@ function BuildableMission:CheckCratesInZone()
|
||||
if self._state == "COMPLETED" then
|
||||
for groupID, markID in pairs(self._markIDsPerGroup) do
|
||||
if markID then
|
||||
Spearhead.DcsUtil.RemoveMark(markID)
|
||||
DcsUtil.RemoveMark(markID)
|
||||
self._markIDsPerGroup[groupID] = nil
|
||||
end
|
||||
end
|
||||
@@ -267,7 +272,4 @@ function BuildableMission:CheckCratesInZone()
|
||||
end
|
||||
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.missions then Spearhead.classes.stageClasses.missions = {} end
|
||||
Spearhead.classes.stageClasses.missions.BuildableMission = BuildableMission
|
||||
return BuildableMission
|
||||
+13
-15
@@ -1,3 +1,7 @@
|
||||
local Mission = require("classes.stageClasses.missions.baseMissions.Mission")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class RunwayStrikeMission : Mission
|
||||
---@field runwayBombingTracker RunwayBombingTracker
|
||||
---@field private _runway Runway
|
||||
@@ -22,8 +26,7 @@ local RunwayStrikeMission = {}
|
||||
---@param runwayBombingTracker RunwayBombingTracker
|
||||
---@return RunwayStrikeMission?
|
||||
function RunwayStrikeMission.new(runway, airbaseName, database, logger, runwayBombingTracker)
|
||||
|
||||
local Mission = Spearhead.classes.stageClasses.missions.baseMissions.Mission
|
||||
|
||||
RunwayStrikeMission.__index = RunwayStrikeMission
|
||||
setmetatable(RunwayStrikeMission, Mission)
|
||||
local self = setmetatable({}, RunwayStrikeMission)
|
||||
@@ -82,7 +85,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
||||
for _, section in pairs(self._runwaySections) do
|
||||
|
||||
local zone = self:SectionToSpearheadZone(section)
|
||||
if Spearhead.Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||
if section.kilosHit == nil then
|
||||
section.kilosHit = 0
|
||||
end
|
||||
@@ -153,10 +156,10 @@ function RunwayStrikeMission:Draw()
|
||||
|
||||
local color = { r=0, g=1, b=0, a=0.5 }
|
||||
|
||||
runwaySection.drawID = Spearhead.DcsUtil.DrawZone(zone, color, color, 5)
|
||||
runwaySection.drawID = DcsUtil.DrawZone(zone, color, color, 5)
|
||||
else
|
||||
Spearhead.DcsUtil.SetFillColor(runwaySection.drawID, fillColor)
|
||||
Spearhead.DcsUtil.SetLineColor(runwaySection.drawID, lineColor)
|
||||
DcsUtil.SetFillColor(runwaySection.drawID, fillColor)
|
||||
DcsUtil.SetLineColor(runwaySection.drawID, lineColor)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -342,7 +345,7 @@ local repairStaticConfigs = {
|
||||
---@private
|
||||
---@param section RunwaySection
|
||||
function RunwayStrikeMission:AddOrUpdateRepairStatics(section)
|
||||
if Spearhead.Util.tableLength(section.repairGroups) > 0 then
|
||||
if Util.tableLength(section.repairGroups) > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -351,7 +354,7 @@ function RunwayStrikeMission:AddOrUpdateRepairStatics(section)
|
||||
y = section.center.y,
|
||||
}
|
||||
|
||||
local repairGroup = Spearhead.Util.randomFromList(repairStaticConfigs)
|
||||
local repairGroup = Util.randomFromList(repairStaticConfigs)
|
||||
for _, repairStatic in pairs(repairGroup) do
|
||||
|
||||
repairStatic.x = location.x + repairStatic.x
|
||||
@@ -369,7 +372,7 @@ end
|
||||
---@private
|
||||
---@param section RunwaySection
|
||||
function RunwayStrikeMission:RemoveRepairStatics(section)
|
||||
if Spearhead.Util.tableLength(section.repairGroups) == 0 then
|
||||
if Util.tableLength(section.repairGroups) == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -537,9 +540,4 @@ function RunwayStrikeMission:RunwayToSpearheadZone(runway)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.missions then Spearhead.classes.stageClasses.missions = {} end
|
||||
Spearhead.classes.stageClasses.missions.RunwayStrikeMission = RunwayStrikeMission
|
||||
return RunwayStrikeMission
|
||||
+24
-22
@@ -1,3 +1,11 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
local Mission = require("classes.stageClasses.missions.baseMissions.Mission")
|
||||
local SpearheadGroup = require("classes.stageClasses.Groups.SpearheadGroup")
|
||||
local Events = require("classes.spearhead_events")
|
||||
local BattleManager = require("classes.stageClasses.helpers.BattleManager")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
--- ZoneMission is missions that are defined by zones in the ME
|
||||
---@class ZoneMission : Mission, OnUnitLostListener
|
||||
---@field private _state MissionState
|
||||
@@ -26,13 +34,13 @@ local ZoneMission = {}
|
||||
---@param input string
|
||||
---@return ParsedMissionName?
|
||||
local function ParseZoneName(input)
|
||||
local split_name = Spearhead.Util.split_string(input, "_")
|
||||
local split_length = Spearhead.Util.tableLength(split_name)
|
||||
if Spearhead.Util.startswith(input, "RANDOMMISSION") == true and split_length < 4 then
|
||||
Spearhead.AddMissionEditorWarning("Random Mission with zonename " .. input .. " not in right format")
|
||||
local split_name = Util.split_string(input, "_")
|
||||
local split_length = Util.tableLength(split_name)
|
||||
if Util.startswith(input, "RANDOMMISSION") == true and split_length < 4 then
|
||||
MissionEditorWarnings.Add("Random Mission with zonename " .. input .. " not in right format")
|
||||
return nil
|
||||
elseif split_length < 3 then
|
||||
Spearhead.AddMissionEditorWarning("Mission with zonename" .. input .. " not in right format")
|
||||
MissionEditorWarnings.Add("Mission with zonename" .. input .. " not in right format")
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -47,7 +55,7 @@ local function ParseZoneName(input)
|
||||
if inputType == "sam" then parsedType = "SAM" end
|
||||
|
||||
if parsedType == "nil" then
|
||||
Spearhead.AddMissionEditorWarning("Mission with zonename '" ..
|
||||
MissionEditorWarnings.Add("Mission with zonename '" ..
|
||||
input .. "' has an unsupported type '" .. (type or "nil"))
|
||||
return nil
|
||||
end
|
||||
@@ -69,7 +77,6 @@ MINIMAL_UNITS_ALIVE_RATIO = 0.21
|
||||
---@param spawnManager SpawnManager
|
||||
---@return ZoneMission?
|
||||
function ZoneMission.new(zoneName, priority, database, logger, parentStage, spawnManager)
|
||||
local Mission = Spearhead.classes.stageClasses.missions.baseMissions.Mission
|
||||
ZoneMission.__index = ZoneMission
|
||||
setmetatable(ZoneMission, Mission)
|
||||
|
||||
@@ -112,8 +119,6 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
||||
self._parentStage = parentStage
|
||||
self._dependencies = {}
|
||||
|
||||
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup
|
||||
|
||||
if missionData.dependsOn then
|
||||
for _, dependency in pairs(missionData.dependsOn) do
|
||||
self._dependencies[dependency] = false
|
||||
@@ -129,7 +134,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
||||
end
|
||||
|
||||
self._missionGroups.sceneryTargets = missionData.SceneryTargets or {}
|
||||
if Spearhead.Util.tableLength(self._missionGroups.sceneryTargets) > 0 then
|
||||
if Util.tableLength(self._missionGroups.sceneryTargets) > 0 then
|
||||
self._missionGroups.hasTargets = true
|
||||
end
|
||||
|
||||
@@ -145,10 +150,10 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
||||
|
||||
local isGroupTarget = Spearhead.Util.startswith(string.lower(groupName), "tgt_")
|
||||
local isGroupTarget = Util.startswith(string.lower(groupName), "tgt_")
|
||||
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
||||
local unitName = unit:getName()
|
||||
local isUnitTarget = Spearhead.Util.startswith(string.lower(unitName), "tgt_")
|
||||
local isUnitTarget = Util.startswith(string.lower(unitName), "tgt_")
|
||||
|
||||
if self._missionGroups.unitsAlive[groupName] == nil then
|
||||
self._missionGroups.unitsAlive[groupName] = {}
|
||||
@@ -167,18 +172,18 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
||||
self._missionGroups.targetsAlive[groupName][unitName] = true
|
||||
end
|
||||
|
||||
Spearhead.Events.addOnUnitLostEventListener(unitName, self)
|
||||
Events.addOnUnitLostEventListener(unitName, self)
|
||||
end
|
||||
|
||||
spearheadGroup:Destroy()
|
||||
end
|
||||
|
||||
if self.missionType == "CAS" then
|
||||
self._battleManager = Spearhead.classes.stageClasses.helpers.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
|
||||
|
||||
self._logger:debug("Mission " .. self.name .. " group count: " .. Spearhead.Util.tableLength(missionData.RedGroups))
|
||||
self._logger:debug("Mission " .. self.name .. " group count: " .. Util.tableLength(missionData.RedGroups))
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -327,7 +332,7 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
||||
end
|
||||
|
||||
if self._state == "COMPLETED" and self._lastContactMarkerID then
|
||||
Spearhead.DcsUtil.RemoveMark(self._lastContactMarkerID)
|
||||
DcsUtil.RemoveMark(self._lastContactMarkerID)
|
||||
end
|
||||
|
||||
if self._state == "COMPLETED" and self._battleManager then
|
||||
@@ -511,13 +516,10 @@ function ZoneMission:MarkLastContact(unit)
|
||||
|
||||
|
||||
if self._lastContactMarkerID then
|
||||
Spearhead.DcsUtil.RemoveMark(self._lastContactMarkerID)
|
||||
DcsUtil.RemoveMark(self._lastContactMarkerID)
|
||||
end
|
||||
|
||||
self._lastContactMarkerID = Spearhead.DcsUtil.AddMarkToAll("Last Contact: " .. self.name .. " [" .. self.code .. "]", point)
|
||||
self._lastContactMarkerID = DcsUtil.AddMarkToAll("Last Contact: " .. self.name .. " [" .. self.code .. "]", point)
|
||||
end
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.missions then Spearhead.classes.stageClasses.missions = {} end
|
||||
Spearhead.classes.stageClasses.missions.ZoneMission = ZoneMission
|
||||
return ZoneMission
|
||||
+12
-17
@@ -1,5 +1,8 @@
|
||||
|
||||
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Util = require("classes.util.Util")
|
||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||
|
||||
---@class Mission
|
||||
---@field name string
|
||||
@@ -49,7 +52,7 @@ function Mission.newSuper(self, zoneName, missionName, missionType, missionBrief
|
||||
self.location = database:GetLocationForMissionZone(zoneName)
|
||||
self.missionTypeDisplay = self.missionType
|
||||
|
||||
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate(logger.LogLevel)
|
||||
|
||||
return true, "success"
|
||||
end
|
||||
@@ -77,11 +80,11 @@ end
|
||||
---@param groupId number
|
||||
function Mission:ShowBriefing(groupId)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
local group = DcsUtil.GetPlayerGroupByGroupID(groupId)
|
||||
if group == nil then return end
|
||||
|
||||
local unitType = Spearhead.DcsUtil.getUnitTypeFromGroup(group)
|
||||
local coords = Spearhead.DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
||||
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||
self._logger:debug("Coords converted: " .. coords)
|
||||
|
||||
local stateString = self:ToStateString()
|
||||
@@ -89,12 +92,12 @@ function Mission:ShowBriefing(groupId)
|
||||
|
||||
local briefing = self._missionBriefing
|
||||
|
||||
briefing = Spearhead.Util.replaceString(briefing, "{{coords}}", coords)
|
||||
briefing = Spearhead.Util.replaceString(briefing, "{{ coords }}", coords)
|
||||
briefing = Util.replaceString(briefing, "{{coords}}", coords)
|
||||
briefing = Util.replaceString(briefing, "{{ coords }}", coords)
|
||||
|
||||
local text = "Mission [" ..
|
||||
self.code .. "] " .. self.name .. "\n \n" .. briefing .. " \n \n" .. stateString
|
||||
trigger.action.outTextForGroup(groupId, text, Spearhead.GlobalConfig:getBriefingTime());
|
||||
trigger.action.outTextForGroup(groupId, text, GlobalConfig:getBriefingTime());
|
||||
end
|
||||
|
||||
|
||||
@@ -135,14 +138,6 @@ function Mission:ToStateString() return "status: in progress" end
|
||||
|
||||
--endregion
|
||||
|
||||
|
||||
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
|
||||
if not Spearhead.classes.stageClasses.missions then Spearhead.classes.stageClasses.missions = {} end
|
||||
if not Spearhead.classes.stageClasses.missions.baseMissions then Spearhead.classes.stageClasses.missions.baseMissions = {} end
|
||||
Spearhead.classes.stageClasses.missions.baseMissions.Mission = Mission
|
||||
|
||||
do --aliases
|
||||
|
||||
--- @alias MissionPriority
|
||||
@@ -168,4 +163,4 @@ do --aliases
|
||||
|
||||
end
|
||||
|
||||
|
||||
return Mission
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
|
||||
local Util = require("classes.util.Util")
|
||||
|
||||
--- @class Logger
|
||||
--- @field LoggerName string the name of the logger
|
||||
--- @field LogLevel string the log level of the logger
|
||||
local LOGGER = {}
|
||||
do
|
||||
local PreFix = "Spearhead"
|
||||
|
||||
---comment
|
||||
---@param logger_name any
|
||||
---@param logLevel LogLevel
|
||||
---@return Logger
|
||||
function LOGGER.new(logger_name, logLevel)
|
||||
LOGGER.__index = LOGGER
|
||||
local self = setmetatable({}, LOGGER)
|
||||
self.LoggerName = logger_name or "(loggername not set)"
|
||||
self.LogLevel = logLevel or "INFO"
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---@param message any the message
|
||||
function LOGGER:info(message)
|
||||
if message == nil then
|
||||
return
|
||||
end
|
||||
message = Util.toString(message)
|
||||
|
||||
if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" then
|
||||
env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message)
|
||||
end
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param message string
|
||||
function LOGGER:warn(message)
|
||||
if message == nil then
|
||||
return
|
||||
end
|
||||
message = Util.toString(message)
|
||||
|
||||
if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" then
|
||||
env.warning("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message any -- the message
|
||||
function LOGGER:error(message)
|
||||
if message == nil then
|
||||
return
|
||||
end
|
||||
|
||||
message = Util.toString(message)
|
||||
|
||||
if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" or self.LogLevel == "ERROR" then
|
||||
env.error("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message any the message
|
||||
function LOGGER:debug(message)
|
||||
if message == nil then
|
||||
return
|
||||
end
|
||||
|
||||
message = Util.toString(message)
|
||||
if self.LogLevel == "DEBUG" then
|
||||
env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "][DEBUG] " .. message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return LOGGER
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
---@class MissionEditingWarnings
|
||||
local MissionEditingWarnings = {}
|
||||
function MissionEditingWarnings.Add(warningMessage)
|
||||
table.insert(MissionEditingWarnings, warningMessage or "skip")
|
||||
end
|
||||
|
||||
---@param logger Logger
|
||||
function MissionEditingWarnings.WriteAll(logger)
|
||||
|
||||
if not logger then
|
||||
return
|
||||
end
|
||||
|
||||
if not MissionEditingWarnings or #MissionEditingWarnings == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
logger:warn("Mission Editor Warnings:")
|
||||
for _, warning in ipairs(MissionEditingWarnings) do
|
||||
logger:warn("- " .. warning)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return MissionEditingWarnings
|
||||
@@ -0,0 +1,503 @@
|
||||
---@class Util
|
||||
local UTIL = {}
|
||||
do -- INIT UTIL
|
||||
---splits a string in sub parts by seperator
|
||||
---@param input string
|
||||
---@param seperator string
|
||||
---@return table result list of strings
|
||||
function UTIL.split_string(input, seperator)
|
||||
if seperator == nil then
|
||||
seperator = " "
|
||||
end
|
||||
|
||||
local result = {}
|
||||
if input == nil then
|
||||
return result
|
||||
end
|
||||
|
||||
for str in string.gmatch(input, "[^" .. seperator .. "]+") do
|
||||
table.insert(result, str)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param table any
|
||||
---@return number
|
||||
function UTIL.tableLength(table)
|
||||
if table == nil then return 0 end
|
||||
|
||||
local count = 0
|
||||
for _ in pairs(table) do count = count + 1 end
|
||||
return count
|
||||
end
|
||||
|
||||
---@param orig table
|
||||
---@return table copy
|
||||
function UTIL.deepCopyTable(orig)
|
||||
local orig_type = type(orig)
|
||||
local copy
|
||||
if orig_type == 'table' then
|
||||
copy = {}
|
||||
for orig_key, orig_value in next, orig, nil do
|
||||
copy[UTIL.deepCopyTable(orig_key)] = UTIL.deepCopyTable(orig_value)
|
||||
end
|
||||
setmetatable(copy, UTIL.deepCopyTable(getmetatable(orig)))
|
||||
else -- number, string, boolean, etc
|
||||
copy = orig
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
---Gets a random from the list
|
||||
---@param list Array
|
||||
---@return any @random element from the list
|
||||
function UTIL.randomFromList(list)
|
||||
local max = #list
|
||||
|
||||
if max == 0 or max == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local random = math.random(0, max)
|
||||
if random == 0 then random = 1 end
|
||||
|
||||
return list[random]
|
||||
end
|
||||
|
||||
---@param list Array
|
||||
---@param start number start
|
||||
---@param n number length
|
||||
---@return Array
|
||||
function UTIL.sublist(list, start, n)
|
||||
local result = {}
|
||||
for i = start, n do
|
||||
result[#result + 1] = list[i]
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
---@param str string
|
||||
---@param find string
|
||||
---@param replace string
|
||||
---@return string
|
||||
function UTIL.replaceString(str, find, replace)
|
||||
if str == nil then return "" end
|
||||
if find == nil or replace == nil then return str end
|
||||
|
||||
local result = str:gsub(find, replace)
|
||||
return result
|
||||
end
|
||||
|
||||
local function table_print(tt, indent, done)
|
||||
done = done or {}
|
||||
indent = indent or 0
|
||||
if type(tt) == "table" then
|
||||
local sb = {}
|
||||
for key, value in pairs(tt) do
|
||||
table.insert(sb, string.rep(" ", indent)) -- indent it
|
||||
if type(value) == "table" and not done[value] then
|
||||
done[value] = true
|
||||
table.insert(sb, "[\"" ..key .. "\"]" .. " = {\n");
|
||||
table.insert(sb, table_print(value, indent + 2, done))
|
||||
table.insert(sb, string.rep(" ", indent)) -- indent it
|
||||
table.insert(sb, "},\n");
|
||||
elseif "number" == type(key) then
|
||||
table.insert(sb, string.format("\"%s\",\n", tostring(value)))
|
||||
else
|
||||
table.insert(sb, string.format(
|
||||
"[\"%s\"] = \"%s\",\n", tostring(key), tostring(value)))
|
||||
end
|
||||
end
|
||||
return table.concat(sb)
|
||||
else
|
||||
return tt .. "\n"
|
||||
end
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param str string
|
||||
---@param findable string
|
||||
---@param ignoreCase boolean?
|
||||
---@return boolean
|
||||
UTIL.startswith = function(str, findable, ignoreCase)
|
||||
if ignoreCase == true then
|
||||
return string.lower(str):find('^' .. string.lower(findable)) ~= nil
|
||||
end
|
||||
|
||||
return str:find('^' .. findable) ~= nil
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param str string
|
||||
---@param findable string
|
||||
---@return boolean
|
||||
UTIL.strContains = function(str, findable)
|
||||
return str:find(findable) ~= nil
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param str string
|
||||
---@param findableTable table
|
||||
---@return boolean
|
||||
UTIL.startswithAny = function(str, findableTable)
|
||||
for key, value in pairs(findableTable) do
|
||||
if type(value) == "string" and UTIL.startswith(str, value) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function UTIL.toString(something)
|
||||
if something == nil then
|
||||
return "nil"
|
||||
elseif "table" == type(something) then
|
||||
return table_print(something)
|
||||
elseif "string" == type(something) then
|
||||
return something
|
||||
else
|
||||
return tostring(something)
|
||||
end
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param a Vec2
|
||||
---@param b Vec2
|
||||
---@return number
|
||||
function UTIL.VectorDistance2d(a, b)
|
||||
return math.sqrt((b.x - a.x) ^ 2 + (b.y - a.y) ^ 2)
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param a Vec3
|
||||
---@param b Vec3
|
||||
---@return number
|
||||
function UTIL.VectorDistance3d(a, b)
|
||||
return UTIL.vectorMagnitude({ x = a.x - b.x, y = a.y - b.y, z = a.z - b.z })
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param vec Vec3
|
||||
---@return number
|
||||
function UTIL.vectorMagnitude(vec)
|
||||
return (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5
|
||||
end
|
||||
|
||||
---@param vec Vec3
|
||||
---@return Vec3
|
||||
function UTIL.vectorNormalize(vec)
|
||||
local magnitude = UTIL.vectorMagnitude(vec)
|
||||
if magnitude == 0 then
|
||||
return { x = 0, y = 0, z = 0 }
|
||||
end
|
||||
return { x = vec.x / magnitude, y = vec.y / magnitude, z = vec.z / magnitude }
|
||||
end
|
||||
|
||||
---@param vec Vec2
|
||||
---@param direction number @in degrees
|
||||
---@param distance number
|
||||
---@return Vec2
|
||||
function UTIL.vectorMove(vec, direction, distance)
|
||||
local rad = math.rad(direction)
|
||||
local x = vec.x + (math.cos(rad) * distance)
|
||||
local y = vec.y + (math.sin(rad) * distance)
|
||||
|
||||
return { x = x, y = y}
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param vec1 Vec2
|
||||
---@param vec2 Vec2
|
||||
---@return number in degrees
|
||||
function UTIL.vectorHeadingFromTo(vec1, vec2)
|
||||
local dx = vec2.x - vec1.x
|
||||
local dy = vec2.y - vec1.y
|
||||
local heading = math.deg(math.atan2(dy, dx))
|
||||
if heading < 0 then
|
||||
heading = heading + 360
|
||||
end
|
||||
return heading
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param vec1 Vec3
|
||||
---@param vec2 Vec3
|
||||
---@return number alignment a number in range [-1,1]. > 0 same direction. < 0 opposite direction
|
||||
function UTIL.vectorAlignment(vec1, vec2)
|
||||
local vec1Norm = UTIL.vectorNormalize(vec1)
|
||||
local vec2Norm = UTIL.vectorNormalize(vec2)
|
||||
|
||||
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
||||
end
|
||||
|
||||
local function isInComplexPolygon(polygon, x, y)
|
||||
local function getEdges(poly)
|
||||
local result = {}
|
||||
for i = 1, #poly do
|
||||
local point1 = poly[i]
|
||||
local point2Index = i + 1
|
||||
if point2Index > #poly then point2Index = 1 end
|
||||
local point2 = poly[point2Index]
|
||||
local edge = { x1 = point1.x, z1 = point1.y, x2 = point2.x, z2 = point2.y }
|
||||
table.insert(result, edge)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local edges = getEdges(polygon)
|
||||
local count = 0;
|
||||
for _, edge in pairs(edges) do
|
||||
if (x < edge.x1) ~= (x < edge.x2) and y < edge.z1 + ((x - edge.x1) / (edge.x2 - edge.x1)) * (edge.z2 - edge.z1) then
|
||||
count = count + 1
|
||||
-- if (yp < y1) != (yp < y2) and xp < x1 + ((yp-y1)/(y2-y1))*(x2-x1) then
|
||||
-- count = count + 1
|
||||
end
|
||||
end
|
||||
return count % 2 == 1
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param polygon Array<Vec2> of pairs { x, y }
|
||||
---@param x number X location
|
||||
---@param y number Y location
|
||||
---@return boolean
|
||||
function UTIL.IsPointInPolygon(polygon, x, y)
|
||||
return isInComplexPolygon(polygon, x, y)
|
||||
end
|
||||
|
||||
---@param point Vec3
|
||||
---@param zone SpearheadTriggerZone
|
||||
function UTIL.is3dPointInZone(point, zone)
|
||||
if zone.zone_type == "Polygon" and zone.verts then
|
||||
if UTIL.IsPointInPolygon(zone.verts, point.x, point.z) == true then
|
||||
return true
|
||||
end
|
||||
else
|
||||
if (((point.x - zone.location.x) ^ 2 + (point.z - zone.location.y) ^ 2) ^ 0.5 <= zone.radius) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---@param point Vec2
|
||||
---@param zone SpearheadTriggerZone
|
||||
function UTIL.is2dPointInZone(point, zone)
|
||||
if zone.zone_type == "Polygon" and zone.verts then
|
||||
if UTIL.IsPointInPolygon(zone.verts, point.x, point.y) == true then
|
||||
return true
|
||||
end
|
||||
else
|
||||
if (((point.x - zone.location.x) ^ 2 + (point.y - zone.location.y) ^ 2) ^ 0.5 <= zone.radius) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param points Array<Vec2> points
|
||||
---@return Array<Vec2> hullPoints
|
||||
function UTIL.getConvexHull(points)
|
||||
if #points == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param a Vec2
|
||||
---@param b Vec2
|
||||
---@param c Vec2
|
||||
---@return boolean
|
||||
local function ccw(a, b, c)
|
||||
return (b.y - a.y) * (c.x - a.x) > (b.x - a.x) * (c.y - a.y)
|
||||
end
|
||||
|
||||
table.sort(points, function(left, right)
|
||||
return left.y < right.y
|
||||
end)
|
||||
|
||||
local hull = {}
|
||||
-- lower hull
|
||||
for _, point in pairs(points) do
|
||||
while #hull >= 2 and not ccw(hull[#hull - 1], hull[#hull], point) do
|
||||
table.remove(hull, #hull)
|
||||
end
|
||||
table.insert(hull, point)
|
||||
end
|
||||
|
||||
-- upper hull
|
||||
local t = #hull + 1
|
||||
for i = #points, 1, -1 do
|
||||
local point = points[i]
|
||||
while #hull >= t and not ccw(hull[#hull - 1], hull[#hull], point) do
|
||||
table.remove(hull, #hull)
|
||||
end
|
||||
table.insert(hull, point)
|
||||
end
|
||||
table.remove(hull, #hull)
|
||||
return hull
|
||||
end
|
||||
|
||||
---Splits points into clusters with at least minSeparation between clusters, returns convex hull for each cluster
|
||||
---@param points Array<Vec2>
|
||||
---@param minSeparation number
|
||||
---@return Array<Array<Vec2>> hulls
|
||||
function UTIL.getSeparatedConvexHulls(points, minSeparation)
|
||||
if #points == 0 then return {} end
|
||||
|
||||
-- Simple clustering: group points that are within minSeparation of each other
|
||||
local clusters = {}
|
||||
local assigned = {}
|
||||
|
||||
for i, p in ipairs(points) do
|
||||
if not assigned[i] then
|
||||
local cluster = { p }
|
||||
assigned[i] = true
|
||||
-- Find all points close to p (BFS)
|
||||
local queue = { i }
|
||||
while #queue > 0 do
|
||||
local idx = table.remove(queue)
|
||||
local base = points[idx]
|
||||
for j, q in ipairs(points) do
|
||||
if not assigned[j] then
|
||||
local dx = base.x - q.x
|
||||
local dy = base.y - q.y
|
||||
if (dx * dx + dy * dy) <= (minSeparation * minSeparation) then
|
||||
table.insert(cluster, q)
|
||||
assigned[j] = true
|
||||
table.insert(queue, j)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(clusters, cluster)
|
||||
end
|
||||
end
|
||||
|
||||
-- Compute convex hull for each cluster
|
||||
local hulls = {}
|
||||
for _, cluster in ipairs(clusters) do
|
||||
local hull = UTIL.getConvexHull(cluster)
|
||||
if #hull > 0 then
|
||||
table.insert(hulls, hull)
|
||||
end
|
||||
end
|
||||
|
||||
return hulls
|
||||
end
|
||||
|
||||
---@param points Array<Vec2>
|
||||
function UTIL.enlargeConvexHull(points, meters)
|
||||
if points == nil or #points == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
---@type Array<Vec2>
|
||||
local allpoints = {}
|
||||
|
||||
for _, point in pairs(points) do
|
||||
table.insert(allpoints, point)
|
||||
|
||||
allpoints[#allpoints + 1] = point
|
||||
allpoints[#allpoints+1] = { x = point.x + meters, y = point.y, }
|
||||
allpoints[#allpoints+1] = { x = point.x - meters, y = point.y, }
|
||||
allpoints[#allpoints+1] = { x = point.x, y = point.y + meters, }
|
||||
allpoints[#allpoints+1] = { x = point.x, y = point.y - meters, }
|
||||
|
||||
allpoints[#allpoints+1] = { x = point.x + math.cos(math.rad(45)) * meters, y = point.y + math.sin(math.rad(45)) * meters, }
|
||||
allpoints[#allpoints+1] = { x = point.x - math.cos(math.rad(45)) * meters, y = point.y - math.sin(math.rad(45)) * meters, }
|
||||
allpoints[#allpoints+1] = { x = point.x - math.cos(math.rad(45)) * meters, y = point.y + math.sin(math.rad(45)) * meters, }
|
||||
allpoints[#allpoints+1] = { x = point.x + math.cos(math.rad(45)) * meters, y = point.y - math.sin(math.rad(45)) * meters, }
|
||||
end
|
||||
|
||||
return UTIL.getConvexHull(allpoints)
|
||||
end
|
||||
|
||||
---Returns hull points visible from origin (not blocked by hull edges)
|
||||
---@param hull Array<Vec2>
|
||||
---@param origin Vec2
|
||||
---@return Array<Vec2>
|
||||
function UTIL.GetVisibleHullPointsFromOrigin(hull, origin)
|
||||
local function segmentsIntersect(a, b, c, d)
|
||||
-- Helper: returns true if segment ab intersects cd (excluding endpoints)
|
||||
local function ccw(p1, p2, p3)
|
||||
return (p3.y - p1.y) * (p2.x - p1.x) > (p2.y - p1.y) * (p3.x - p1.x)
|
||||
end
|
||||
return (ccw(a, c, d) ~= ccw(b, c, d)) and (ccw(a, b, c) ~= ccw(a, b, d))
|
||||
end
|
||||
|
||||
local n = #hull
|
||||
local visible = {}
|
||||
|
||||
for i = 1, n do
|
||||
local p = hull[i]
|
||||
local isVisible = true
|
||||
|
||||
-- Check against all hull edges except those incident to p
|
||||
for j = 1, n do
|
||||
local a = hull[j]
|
||||
local b = hull[(j % n) + 1]
|
||||
-- skip edges incident to p
|
||||
if (a ~= p and b ~= p) then
|
||||
if segmentsIntersect(origin, p, a, b) then
|
||||
isVisible = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isVisible then
|
||||
table.insert(visible, p)
|
||||
end
|
||||
end
|
||||
|
||||
return visible
|
||||
end
|
||||
|
||||
---Returns the two tangent points ("scratch points") from origin to the convex hull
|
||||
---@param hull Array<Vec2>
|
||||
---@param origin Vec2
|
||||
---@return Array<Vec2>
|
||||
function UTIL.GetTangentHullPointsFromOrigin(hull, origin)
|
||||
|
||||
if hull == nil or #hull <= 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local function orientation(a, b, c)
|
||||
-- Returns >0 if c is to the left of ab, <0 if to the right, 0 if colinear
|
||||
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
|
||||
end
|
||||
|
||||
local n = #hull
|
||||
if n == 0 then return {} end
|
||||
if n == 1 then return { hull[1] } end
|
||||
|
||||
-- Find left tangent: the hull point where all other points are to the right of the line from origin to that point
|
||||
local function findTangent(isLeft)
|
||||
local best = 1
|
||||
for i = 2, n do
|
||||
local o = orientation(origin, hull[best], hull[i])
|
||||
if (isLeft and o < 0) or (not isLeft and o > 0) then
|
||||
best = i
|
||||
end
|
||||
end
|
||||
return hull[best]
|
||||
end
|
||||
|
||||
local leftTangent = findTangent(true)
|
||||
local rightTangent = findTangent(false)
|
||||
|
||||
-- If tangents are the same (can happen if origin is colinear), only return one
|
||||
if leftTangent.x == rightTangent.x and leftTangent.y == rightTangent.y then
|
||||
return { leftTangent }
|
||||
else
|
||||
return { leftTangent, rightTangent }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return UTIL
|
||||
@@ -0,0 +1,96 @@
|
||||
--Single player purpose
|
||||
|
||||
local Logger = require("classes.util.Logger")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Database = require("classes.spearhead_db")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
local CapConfig = require("classes.configuration.CapConfig")
|
||||
local StageConfig = require("classes.configuration.StageConfig")
|
||||
local Persistence = require("classes.persistence.Persistence")
|
||||
local SpawnManager = require("classes.helpers.SpawnManager")
|
||||
local DetectionManager = require("classes.capClasses.detection.DetectionManager")
|
||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||
local GlobalStageManager = require("classes.stageClasses.GlobalStageManager")
|
||||
local GlobalFleetManager = require("classes.fleetClasses.GlobalFleetManager")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
|
||||
local defaultLogLevel = "INFO"
|
||||
|
||||
if SpearheadConfig and SpearheadConfig.debugEnabled == true then
|
||||
defaultLogLevel = "DEBUG"
|
||||
end
|
||||
|
||||
local startTime = timer.getTime() * 1000
|
||||
|
||||
SpearheadEvents.Init(defaultLogLevel)
|
||||
|
||||
local dbLogger = Logger.new("database", defaultLogLevel)
|
||||
local standardLogger = Logger.new("", defaultLogLevel)
|
||||
local databaseManager = Database.New(dbLogger)
|
||||
MissionCommandsHelper.getOrCreate(defaultLogLevel) -- initiate
|
||||
|
||||
local capConfig = CapConfig:new();
|
||||
local stageConfig = StageConfig:new();
|
||||
|
||||
local startingStage = stageConfig.startingStage or 1
|
||||
if SpearheadConfig and SpearheadConfig.Persistence and SpearheadConfig.Persistence.enabled == true then
|
||||
standardLogger:info("Persistence enabled")
|
||||
local persistenceLogger = Logger.new("Persistence", defaultLogLevel)
|
||||
Persistence.Init(persistenceLogger)
|
||||
|
||||
local persistanceStage = Persistence.GetActiveStage()
|
||||
if persistanceStage then
|
||||
standardLogger:info("Persistance activated and using persistant active stage: " .. persistanceStage)
|
||||
startingStage = persistanceStage
|
||||
end
|
||||
else
|
||||
standardLogger:info("Persistence disabled")
|
||||
end
|
||||
|
||||
local spawnLogger = Logger.new("SpawnManager", defaultLogLevel)
|
||||
local spawnManager = SpawnManager.new(spawnLogger)
|
||||
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
||||
local detectionManager = DetectionManager.New(detectionLogger)
|
||||
|
||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
GlobalStageManager.NewAndStart(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
GlobalFleetManager.start(databaseManager)
|
||||
|
||||
local SetStageDelayed = function(number, time)
|
||||
SpearheadEvents.PublishStageNumberChanged(number)
|
||||
return nil
|
||||
end
|
||||
|
||||
timer.scheduleFunction(SetStageDelayed, startingStage, timer.getTime() + 3)
|
||||
|
||||
env.info(startTime .. "ms / " .. timer.getTime() * 1000 .. "ms")
|
||||
local duration = (timer.getTime() * 1000) - startTime
|
||||
standardLogger:info("Spearhead Initialisation duration: " .. tostring(duration) .. "ms")
|
||||
|
||||
local missionEditorWarningsLogger = Logger.new("MissionEditorWarnings", defaultLogLevel)
|
||||
MissionEditorWarnings.WriteAll(missionEditorWarningsLogger)
|
||||
GlobalStageManager:printFullOverview()
|
||||
|
||||
--Check lines of code in directory per file:
|
||||
-- Get-ChildItem . -Include *.lua -Recurse | foreach {""+(Get-Content $_).Count + " => " + $_.name }; GCI . -Include *.lua* -Recurse | foreach{(GC $_).Count} | measure-object -sum | % Sum
|
||||
-- find . -name '*.lua' | xargs wc -l
|
||||
|
||||
--- ==================== DEBUG ORDER OR ZONE VEC ===========================
|
||||
-- local zone = Spearhead.DcsUtil.getZoneByName("MISSIONSTAGE_99")
|
||||
|
||||
-- local count = Spearhead.Util.tableLength(zone.verts)
|
||||
|
||||
-- for i = 1, count - 1 do
|
||||
|
||||
-- local a = zone.verts[i]
|
||||
-- local b = zone.verts[i+1]
|
||||
|
||||
-- local color = {0,0,0,1}
|
||||
|
||||
-- color[i] = 1
|
||||
|
||||
-- trigger.action.textToAll(-1, 46+i , { x= a.x, y = 0, z = a.z } , color, {0,0,0}, 24 , true , "" .. i )
|
||||
-- trigger.action.lineToAll(-1 , 56+i , { x= a.x, y = 0, z = a.z } , { x = b.x, y = 0, z = b.z } , color , 1, true)
|
||||
|
||||
-- end
|
||||
Reference in New Issue
Block a user