Author SHA1 Message Date
dutchie031 446a98dc3b merged develop
PR Prerequisites / Lua Check (pull_request) Successful in 21s
PR Prerequisites / Bundles Without Errors (pull_request) Successful in 29s
2026-09-20 18:43:32 +02:00
dutchie031 8cacad84a1 merged develop
PR Prerequisites / Lua Check (pull_request) Successful in 21s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-20 18:35:43 +02:00
dutchie031 f3a38db5ca added comment 2026-09-08 16:13:37 +02:00
dutchie031 81d9aa7265 Updated preactivate logic 2026-09-08 16:12:38 +02:00
dutchie031 52f840c270 Initial Deep Strike implementation 2026-09-08 15:47:11 +02:00
dutchie031 d14a0dc78e Added mission type deepstrike 2026-09-08 08:13:17 +02:00
4 changed files with 129 additions and 287 deletions
+39 -29
View File
@@ -1,43 +1,53 @@
# Spearhead
Hello and welcome to Spearhead!
If you're a developer that wants to contribute, look at the code or understand what we're doing, feel free to read on.
## Contributing.
If you're a mission maker that wants to see the documentation and build you mission with this framework. <br>
It's best to go to our fully fledged documentation website:
- Stable/Main: https://spearhead.rocks
- Beta/Develop: https://beta.spearhead.rocks
I'm always happy to see contributions! <br/>
Especially if you've found an issue, annoyance or feature that you know how to solve, fix or create! <br/>
## Project Structure
### Keep it small.
The Spearhead project is structured in a lot of separate files. <br>
While Lua isn't specifically created for it, most of it has been written with the standards of OOP in mind. <br>
Classes, Objects and helper methods.
Keeping your contributions small and to the point helps both me and yourself. <br/>
It'll help the PR review and the speed of improvements. <br/>
If you have a big feature in mind? Go for it! <br/>
Does it require an entire refactor of parts or all of the program? Maybe make sure to do step 0 first.
You're find in the `/src` folder all the files. <br>
They are separated in a somewhat logical order, but some things might feel out of place. <br>
### Steps (for first timers)
0. Reach out (Optional)
### Bundling, Intellisense, Linting
If you want to let me know you want to do something to contribute, please do! <br/>
Maybe I'm already working on the thing you wanted to build, or someone else is. <br/>
Creating an issue is even better! <br/>
In DCS the easiest way to import a script is with 1 single file, however, that's not as "maintainable".
In order to keep it maintainable we're using a self-built tool to bundle, validate and rewrite some of the lua in order to get it into a single file.
The tool is open-source here: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools. <br>
It has a `VSCode` extensions and two `Github Action` steps. <br>
If your favorite IDE isn't `VSCode` (I respect that), it might be very easy to create an extension for it, if it does allow that.
The `VSCode` extensions comes with Intellisense as well, in the form of a full file of DCS lua type annotations. <br>
This gives the Lua Language Server by Sumneko (which can be used in `VSCode`) all the type definitions it needs.
When writing Spearhead code it is also important to keep our own LuaLS Annotations up to date and complete. <br>
Read all about those annotations here: https://luals.github.io/wiki/annotations/
1. Fork the repository
When a pull-request to the `develop` or `main` branches is created, before it can be merged it requires to pass the linter checks.
The first linting check is done by the Lua Language Server. It checks for whitespace and formatting, but it also checks if all types, type-checking and casts are in order. It marks unused variables etc. `.luarc.json` has all the config for those checks. <br>
The second linter job is with `luacheck` which first "bundles" the script, and then runs a full linter check over the bundled script. <br>
This is to make sure that also the bundled script does not contain any errors.
By forking you can create your own working set of code. <br/>
Whether you keep that fork public or private is up to you! <br/>
## Contributing
Keep in mind, forking is alright, but it's best with the intent to contribute back. <br/>
After all, instead of having 5 slightly different versions and products, it might be nicer to have 1 much better version. <br/>
### Setting up the project
2. Create a Draft PR as soon as possible!
If you've kept on reading I assume you either want to brwose
As soon as you've found some times to create an initial version, please create a draft PR. <br/>
That way you can let me and everyone know it's being worked on and people can see what conflicts might arise with their own changes. <br/>
3. Test, test, test
With DCS and Lua there's a bunch of edge cases that are really hard to get to. <br/>
However, you kinda need to make sure most if not all cases are caught and tested. <br/>
Since automated testing for now doesn't seem feasible, please make sure to verify and test functionality after touching stuff. <br/>
4. Finalise and publish the PR.
Finalise the PR and let the maintainers know! <br/>
We can all have a look and discuss the changes. <br/>
# TODO:
- Would it be possible to generate optional markers on mission briefing locations for Tomcat / Phantom navigation? Then Jester can type it in for the pilots automatically.
+90 -87
View File
@@ -1,87 +1,90 @@
## [Unreleased]
### Breaking Changes
### New Features
- Addresses #41
Adds Stage Complete debug methods for local testing of the Stage flow.
PR #40
- Closes #35
Creating Lane option for stages.
Additionally to the primary stage lane, stages can now be created in different lanes.
These lanes can be used to create different stage progression flows and create different "side-stories".
PR #40
- Closes #37
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
PR #44
- Closes #42
DEEPSTRIKE now added as a possible feature.
This enables to have missions active in "Pre-Activated" Stages.
PR #48
### Bug Fixes
## [0.13.0] 2026-08
A good first release that finally has all major bugs fixed that were caused by the migration from both the underlying script transpiler and the migration to Gitea.
### Breaking Changes
### New Features
- Issue #26
Possibility to have Stage Overview briefings (which include current missions sorted by distance) to be shown on spawning of a player.
PR #31
### Bug Fixes
- Issue #11
Supply crate spawning now checks for free space and will not spawn if the area is too crowded.
Additionally different units will spawn in different areas depending on loading side.
PR #17
- Fixed command wiring for supply hubs for better and more accurate detection of units spawning and entering/exiting zone.
PR #15
- Fixed custom drawings not being drawn correctly.
PR #18
- Fixed CAP Callbacks not working since the change to a transpiled script. Now a global callback circumvents this issue.
PR #18
- Fixed #9
Changed order of checking mission briefings
PR #19
- Fixed Configuration defaulting to true for all booleans in StageConfig
PR #28
- Fixed Pre-Activated stages not always drawing or pre-activating correctly.
PR #28
- Addressed #24
CAP max commit range is now configurable in the config.lua file.
Issue remains open in order to apply further fine grained tuning.
PR #29
## [0.12.0] 2026-06
Migration to Gitea. <br>
First version of the Gitea repository. <br>
Everything is new, but also old.
### Breaking Changes
Nothing worth mentioning
### New Features
All and none
### Bug Fixes
No bugs fixed, they're all still there.
## [x.x.x] Year - Month Release Template
### Breaking Changes
### New Features
### Bug Fixes
## [Unreleased]
### Breaking Changes
### New Features
- Issue: #41
Adds Stage Complete debug methods for local testing of the Stage flow.
#40
- Issue: #35
Creating Lane option for stages.
Additionally to the primary stage lane, stages can now be created in different lanes.
These lanes can be used to create different stage progression flows and create different "side-stories".
#40
- Issue: #37
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
#44
- Issue: #42
DEEPSTRIKE now added as a possible feature.
This enables to have missions active in "Pre-Activated" Stages.
#48
### Bug Fixes
## [0.13.0] 2026-08
A good first release that finally has all major bugs fixed that were caused by the migration from both the underlying script transpiler and the migration to Gitea.
### Breaking Changes
### New Features
- Issue #26
Possibility to have Stage Overview briefings (which include current missions sorted by distance) to be shown on spawning of a player.
PR #31
### Bug Fixes
- Issue #11
Supply crate spawning now checks for free space and will not spawn if the area is too crowded.
Additionally different units will spawn in different areas depending on loading side.
PR #17
- Fixed command wiring for supply hubs for better and more accurate detection of units spawning and entering/exiting zone.
PR #15
- Fixed custom drawings not being drawn correctly.
PR #18
- Fixed CAP Callbacks not working since the change to a transpiled script. Now a global callback circumvents this issue.
PR #18
- Fixed #9
Changed order of checking mission briefings
PR #19
- Fixed Configuration defaulting to true for all booleans in StageConfig
PR #28
- Fixed Pre-Activated stages not always drawing or pre-activating correctly.
PR #28
- Addressed #24
CAP max commit range is now configurable in the config.lua file.
Issue remains open in order to apply further fine grained tuning.
PR #29
## [0.12.0] 2026-06
Migration to Gitea. <br>
First version of the Gitea repository. <br>
Everything is new, but also old.
### Breaking Changes
Nothing worth mentioning
### New Features
All and none
### Bug Fixes
No bugs fixed, they're all still there.
## [x.x.x] Year - Month Release Template
### Breaking Changes
### New Features
### Bug Fixes
@@ -1,112 +0,0 @@
local Logger = require("classes.util.Logger")
local logger = Logger.new("ImageDisplay")
---@class ImageDisplay
local ImageDisplay = {}
---@param unit Unit
---@param settings ImageDisplaySettings
function ImageDisplay.outImageToUnit(unit, settings)
if unit == nil then return end
settings:ValidateOrSetDefaults() --Overwrites wrong settings
if settings.picPath == nil then
logger:warn("No picture path provided for unit display.")
return -- Nothing to display
end
ImageDisplay.outImage("a_out_picture_u",
unit,
settings.picPath,
settings.duration,
settings.clearview,
settings.delay,
settings.horizontalAlignment,
settings.verticalAlignment,
settings.size,
settings.sizeUnits
)
end
---@param group Group
---@param settings ImageDisplaySettings
function ImageDisplay.outImageToGroup(group, settings)
if group == nil then return end
settings:ValidateOrSetDefaults() --Overwrites wrong settings
if settings.picPath == nil then
logger:warn("No picture path provided for group display.")
return -- Nothing to display
end
ImageDisplay.outImage("a_out_picture_g",
group,
settings.picPath,
settings.duration,
settings.clearview,
settings.delay,
settings.horizontalAlignment,
settings.verticalAlignment,
settings.size,
settings.sizeUnits
)
end
---@alias OutPictureTriggerName
---| "a_out_picture_u"
---| "a_out_picture_g"
---@private
---@param object Unit|Group
---@param triggerName OutPictureTriggerName
---@param picPath string
---@param duration number
---@param clearview boolean
---@param delay number
---@param horizontalAlignment ImageDisplaySettings.HorizontalAlignment
---@param verticalAlignment ImageDisplaySettings.VerticalAlignment
---@param size number
---@param sizeUnits ImageDisplaySettings.SizeUnits
function ImageDisplay.outImage(triggerName, object, picPath, duration, clearview, delay, horizontalAlignment, verticalAlignment, size, sizeUnits)
---@type number
local id
if triggerName == "a_out_picture_u" then
object = object --[[@as Unit]]
id = object:getID()
elseif triggerName == "a_out_picture_g" then
object = object --[[@as Group]]
id = object:getID()
end
--[[
a_out_picture_u(
unitID:number,
filePath:string,
showTime:number,
clearview:boolean,
startDelayTime:number,
horzAlignment:string,
vertAlignment:string,
size:number,
size_units:string
) -- args may not correct.
]]
local cmdString = string.format(triggerName .. '(%d, "%s", %d, %s, %d, "%d", "%d", %d, "%d")',
id,
picPath,
duration,
clearview,
delay,
horizontalAlignment,
verticalAlignment,
size,
sizeUnits)
local f, err = loadstring(cmdString)
if f then
f()
else
logger:error("Something failed when drawing complex drawing" .. err)
end
end
return ImageDisplay
@@ -1,59 +0,0 @@
---@class ImageDisplaySettings
---@field picPath string?
---@field duration number
---@field clearview boolean
---@field delay number
---@field horizontalAlignment ImageDisplaySettings.HorizontalAlignment
---@field verticalAlignment ImageDisplaySettings.VerticalAlignment
---@field size number
---@field sizeUnits ImageDisplaySettings.SizeUnits
local ImageDisplaySettings = {}
ImageDisplaySettings.__index = ImageDisplaySettings
---@enum ImageDisplaySettings.VerticalAlignment
ImageDisplaySettings.VerticalAlignment = {
Top = "0",
Center = "1",
Bottom = "2"
}
---@enum ImageDisplaySettings.HorizontalAlignment
ImageDisplaySettings.HorizontalAlignment = {
Left = "0",
Center = "1",
Right = "2"
}
---@enum ImageDisplaySettings.SizeUnits
ImageDisplaySettings.SizeUnits = {
OriginalSize = "0",
WindowSize = "1"
}
function ImageDisplaySettings.new()
local self = setmetatable({}, ImageDisplaySettings)
self.picPath = nil
self.duration = 30
self.clearview = false
self.delay = 0
self.horizontalAlignment = ImageDisplaySettings.HorizontalAlignment.Center
self.verticalAlignment = ImageDisplaySettings.VerticalAlignment.Center
self.size = 100
self.sizeUnits = ImageDisplaySettings.SizeUnits.OriginalSize
return self
end
function ImageDisplaySettings:ValidateOrSetDefaults()
if self.picPath == "" then self.picPath = nil end
if self.duration == nil or self.duration <= 0 then self.duration = 30 end
if self.clearview == nil then self.clearview = false end
if self.delay == nil then self.delay = 0 end
if self.horizontalAlignment == nil then self.horizontalAlignment = ImageDisplaySettings.HorizontalAlignment.Center end
if self.verticalAlignment == nil then self.verticalAlignment = ImageDisplaySettings.VerticalAlignment.Center end
if self.size == nil or self.size <= 0 then self.size = 100 end
if self.sizeUnits == nil then self.sizeUnits = ImageDisplaySettings.SizeUnits.OriginalSize end
end
return ImageDisplaySettings