16 Commits

Author SHA1 Message Date
Ambroise Garel 31639b2ba9 Updated README for 0.1.250723 2025-07-23 17:11:39 +02:00
Ambroise Garel 97c1a4672f Added the new autoexec.cfg file required by DCS 2.9.18.12722 2025-07-23 17:04:45 +02:00
Ambroise Garel b0fd9c7eeb Fixed a typo in README 2025-07-23 11:42:03 +02:00
Ambroise Garel 693a280555 Fixed bug with convoys sometimes stuck in trees an buildings 2025-07-23 11:25:48 +02:00
Ambroise Garel 28927248b2 Improved "simulate player landing" command in debug menu 2025-07-22 19:51:01 +02:00
Ambroise Garel 08e34a1b93 Improved wording on "all XP will be lost" mission abort warning 2025-07-22 19:43:52 +02:00
Ambroise Garel 65cfe4f4bc Fixed bug with "intermission" menu not showing on mission completion 2025-07-22 19:42:54 +02:00
Ambroise Garel 580f924adc Improved wording on the "xp awarded" reminder 2025-07-22 19:40:25 +02:00
Ambroise Garel cdc9fbdb38 Fixed a bug with non-carrier capable aircraft spawning on carriers 2025-07-22 18:59:47 +02:00
Ambroise Garel 2fa3702763 Fixed a bug with "rockets!" launch call 2025-07-22 18:36:17 +02:00
Ambroise Garel d2d850799e Updated README for 0.1.250722-update1 2025-07-22 15:09:26 +02:00
Ambroise Garel 574125abf6 Added Marianas theater 2025-07-22 14:26:28 +02:00
Ambroise Garel cbb25cd67a Added Kola theater 2025-07-22 14:09:26 +02:00
Ambroise Garel c263428c7b Player score now reset in playerCareer.awardScore, added "xp added to your log" message 2025-07-22 13:09:00 +02:00
Ambroise Garel 6586b7a513 Slightly lowered required XP for promotions and medal 2025-07-22 13:00:07 +02:00
Ambroise Garel 121a4f01f8 Fixed bug when hit object isn't an unit 2025-07-22 12:58:30 +02:00
12 changed files with 330 additions and 39 deletions
+15
View File
@@ -0,0 +1,15 @@
if not net then net = {} end
net.allow_unsafe_api = { -- this defines the secure zones where net.dostring_in() can be called from
"userhooks",
"scripting",
"gui",
}
net.allow_dostring_in = { -- and this defines the zones that should be addressed from net.dostring_in()
"mission",
"scripting",
"gui",
"export",
"config",
}
+24 -12
View File
@@ -1,6 +1,6 @@
# The Universal Mission for DCS World
**Current version: open beta 0.1.250722** (see the "version history" section at the end of this file for a list of the latest changes)
**Current version: open beta 0.1.250723** (see the "version history" section at the end of this file for a list of the latest changes)
**This is a BETA version, there may be bugs and there WILL be unbalanced stuff.**
@@ -29,8 +29,8 @@ I think with The Universal Mission is, finally, the proper way to approach this
**Please read the "planned development" section below for more information.**
- The current version supports only modern (post-Cold War) units and Caucasus, Persian Gulf and Syria theaters
- Kola, Marianas and Germany support will come soon, others will follow later
- The current version supports only modern (post-Cold War) units and Caucasus, Kola, Marianas, Persian Gulf and Syria theaters
- Germany support will come soon, others will follow later
- Not all mission types are supported yet
- Career progress may be lost because of future updates, don't get too attached to it
@@ -39,7 +39,8 @@ I think with The Universal Mission is, finally, the proper way to approach this
### First setup
- Download the latest release from this GitHub page.
- Copy the .miz files for your theater(s) of choice into your **[Saved Games]\DCS World\Missions directory**
- Copy the provided autoexec.cfg file to your **[Saved Games]\DCS\Config directory**
- Copy the .miz files for your theater(s) of choice to your **[Saved Games]\DCS\Missions directory**
- _**(Optional but strongly recommended)**_ Unsanitize the Lua IO module. You don't have to do this, but the persistent career system won't work if you don't. To do it, open the file **[DCS World installation directory]\Scripts\MissionScripting.lua** with a text editor and comment or remove the line "sanitizeModule('io')". Make sure you restart DCS World once you've modified the file.
- Please note: should you want to backup, delete or transfer it, career progress is saved in **[DCS World installation directory]\TheUniversalMission.sav**
@@ -69,7 +70,7 @@ The Universal Mission is designed to be easily editable to suit your preferences
#### Player aircraft
- Change the player aircraft starting condition (runway, parking or parking hot). Air starts are not recommended as all players must be on the ground to begin a new mission
- Move it to another airbase, change its coalition (make sure blue players are spawned on an airbase located in a REDFOR zone are red players are spawned on an airbase located in a REDFOR zone)
- Move it to another airbase, change its coalition (make sure blue players are spawned on an airbase located in a BLUFOR zone are red players are spawned on an airbase located in a REDFOR zone)
- You may also add an aircraft carrier or a FARP for the player to take off from
- Change its default loadout if you plan to play a specific kind of mission and don't want to lose time asking the ground crew to rearm your aircraft (e.g. if you know you want to play SEAD missions, you may as well stock up on AGM-88s)
- Change the skill level from "Player" to "Client" and add other aircraft to create a multiplayer mission to play with your friends. Keep in mind that the persistent career/player stats system will be disabled in multiplayer missions and that all player aircraft must belong to the same coalition (TUM does not support PvP)
@@ -99,14 +100,11 @@ Please also note that PvP is not supported at the moment and that the mission wi
## Planned development
### Planned for next update (ASAP, before I leave for vacations :)
- Support for Kola, Marianas and Germany theaters
### VERY high priority
- New objectives: helicopter (drop/pickup units...), CAP, CAS, OCA (airbase attack)
- New menu for enemy contacts report, allowing both to quiery AWACS reports and to ask other AI pilots about what they see in the air and on the ground
- Support for Germany theater
### High priority
@@ -145,9 +143,9 @@ Please also note that PvP is not supported at the moment and that the mission wi
## How to build the miz files
_(this is only for developpers, end users should just download the latest release)_
_**(this is for developpers only, end users should just download the latest release)**_
I use a PHP script to "build" the .miz files as PHP is a pretty handy tool capable both of handling all requirement replacements and pack the miz files.
I use a PHP script to "build" the .miz files as PHP is a pretty handy tool capable both of handling all required replacements and pack the miz files.
If you want to build the .miz files yourself, you'll need to:
@@ -171,4 +169,18 @@ The core script is quite simple and small, I probably won't need too much help w
## Version history
- **0.1.250722** (07/22/2025): Initial public release
- **0.1.250723** (07/23/2025)
- Added new "autoexec.cfg" file required by DCS 2.9.18.12722. You have to copy it to **[Saved Games]\DCS\Config directory** or the script won't work.
- Fixed a bug with convoys sometimes stuck in trees and buildings
- Fixed a bug with "intermission" menu not showing properly on mission completion
- Fixed a bug with non carrier-capable aircraft spawning on carriers
- Fixed a bug with "rockets!" radio call causing an error message
- Improved wording on the "XP awarded" and "all XP will be lost" messages
- **0.1.250722-update1** (07/22/2025)
- Added Kola theater
- Added Marianas theater
- Added message when XP is awarded to player after landing
- Fixed bug when friendly non-unit object is hit
- Slightly lowered XP required for medals and promotions
- **0.1.250722** (07/22/2025)
- Initial public release
+6
View File
@@ -385,6 +385,12 @@ do
y = vec2.y + unitOffset.y
}
if options.onRoad then
local posOnRoads = DCSEx.world.getClosestPointOnRoadsVec2(unitTable)
unitTable.x = posOnRoads.x
unitTable.y = posOnRoads.y
end
if isAirUnit and aircraftDB then
unitTable.hardpoint_racks = true
unitTable.psi = 1.7703702498393
+8 -2
View File
@@ -115,8 +115,14 @@ do
if desiredUnitCount[side] <= 0 then return false end -- No airforce
if not TUM.DEBUG_MODE and #DCSEx.world.getPlayersInAir() == 0 then return false end -- No players currently in the air, don't spawn new AI aircraft (except in debug mode)
local validAirbases = {}
local airbases = coalition.getAirbases(side)
if not airbases or #airbases == 0 then return false end -- No airbases found for this coalition, nowhere to takeoff from
for _,ab in pairs(airbases) do
if ab:getDesc().category ~= Airbase.Category.SHIP then -- Ignore ships
table.insert(validAirbases, ab)
end
end
if not validAirbases or #validAirbases == 0 then return false end -- No airbases found for this coalition, nowhere to take off from
local center = nil
if side == TUM.settings.getPlayerCoalition() then
@@ -124,7 +130,7 @@ do
else
center = TUM.objectives.getCenter()
end
airbases = DCSEx.dcs.getNearestObjects(center, airbases)
validAirbases = DCSEx.dcs.getNearestObjects(center, validAirbases)
local airborneUnitCount = getAirborneUnitCount(side)
@@ -116,8 +116,10 @@ do
-- Friendly aircraft hit
if event.target:getDesc().category == Unit.Category.AIRPLANE or event.target:getDesc().category == Unit.Category.HELICOPTER then
if not event.initiator:getPlayerName() then -- Players don't radio out when they're hit
doAmbientChatter("pilotImHit", nil, event.target:getCallsign(), 3)
if Object.getCategory(event.initiator) == Object.Category.UNIT then
if not event.initiator:getPlayerName() then -- Players don't radio out when they're hit
doAmbientChatter("pilotImHit", nil, event.target:getCallsign(), 3)
end
end
end
end
@@ -323,7 +325,7 @@ do
if weaponDesc.category == Weapon.Category.BOMB then
doAmbientChatter("pilotLaunchPickle", nil, event.initiator:getCallsign(), 1)
elseif weaponDesc.category == Weapon.Category.ROCKET then
doAmbientChatter(event.initiator:getCoalition(),"pilotLaunchRocket", nil, event.initiator:getCallsign(), 1)
doAmbientChatter("pilotLaunchRocket", nil, event.initiator:getCallsign(), 1)
elseif weaponDesc.category == Weapon.Category.MISSILE then
if weaponDesc.missileCategory == Weapon.MissileCategory.AAM then
if weaponDesc.guidance == Weapon.GuidanceType.IR then
+5 -6
View File
@@ -56,14 +56,13 @@ do
end
local function doSimulatePlayerLanding()
-- TUM.playerCareer.awardScore(TUM.playerScore.getScore(), TUM.playerScore.getCompletedObjectives())
local playerUnit = coalition.getPlayers(TUM.settings.getPlayerCoalition())[1]
local event = {
id = world.event.S_EVENT_LAND,
initiator = coalition.getPlayers(TUM.settings.getPlayerCoalition())[1]
}
local runwayTouchEvent = { id = world.event.S_EVENT_RUNWAY_TOUCH, initiator = playerUnit }
TUM.onEvent(runwayTouchEvent)
TUM.onEvent(event)
local landingEvent = { id = world.event.S_EVENT_LAND, initiator = playerUnit }
timer.scheduleFunction(TUM.onEvent, landingEvent, timer.getTime() + 1)
end
function TUM.debugMenu.createMenu()
+1
View File
@@ -36,6 +36,7 @@ do
end
missionStatus = TUM.mission.status.NONE
TUM.intermission.createMenu()
end
function TUM.mission.checkMissionStatus(silent)
+1 -2
View File
@@ -8,7 +8,6 @@ TUM.missionMenu = {}
do
local function doCommandAbortMission()
TUM.mission.endMission(TUM.mission.endCause.ABORTED)
TUM.intermission.createMenu()
end
local function doCommandMissionStatus()
@@ -55,7 +54,7 @@ do
local abortRoot = missionCommands.addSubMenu("⬣ Abort mission")
if not TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) and DCSEx.io.canReadAndWrite() then
missionCommands.addCommand("✓ Confirm (all xp will be lost!)", abortRoot, doCommandAbortMission, nil)
missionCommands.addCommand("✓ Confirm (all xp since last landing will be lost!)", abortRoot, doCommandAbortMission, nil)
else
missionCommands.addCommand("✓ Confirm", abortRoot, doCommandAbortMission, nil)
end
+13 -11
View File
@@ -28,20 +28,20 @@ do
local OBJECTIVES_PER_RIBBON = 4 -- How many completed objectives to gain a new ribbon?
local MEDALS = {
{ "Air medal", 200 },
{ "Bronze star", 300 },
{ "Airman's medal", 400 },
{ "Distinguished Flying Cross", 500 },
{ "Silver Star for Valor", 600 },
{ "Air Force Cross", 700 },
{ "Congressional Medal of Honor", 800 },
{ "Air medal", 150 },
{ "Bronze star", 225 },
{ "Airman's medal", 300 },
{ "Distinguished Flying Cross", 375 },
{ "Silver Star for Valor", 450 },
{ "Air Force Cross", 525 },
{ "Congressional Medal of Honor", 600 },
}
local RANKS = {
{ "2d Lt.", "Second lieutenant", 0 },
{ "1st Lt.", "First lieutenant", 500 },
{ "Capt.", "Captain", 2000 },
{ "Maj.", "Major", 8000 },
{ "1st Lt.", "First lieutenant", 400 },
{ "Capt.", "Captain", 1600 },
{ "Maj.", "Major", 6400 },
{ "Lt Col.", "Lieutenant colonel", 16000 },
{ "Col.", "Colonel", 32000 },
}
@@ -103,7 +103,7 @@ do
careerStats.bestSortie = math.max(careerStats.bestSortie, score)
careerStats.score = careerStats.score + score
careerStats.completedObjectives = careerStats.completedObjectives + objectives
TUM.log("Awarded "..tostring(score).." xp and "..tostring(objectives).." completed objectives to player.")
trigger.action.outText(DCSEx.string.toStringThousandsSeparator(score).." xp and "..tostring(objectives).." completed objective(s) were registered in your flight log.", 5)
local newRibbonCount = getRibbonCount()
local somethingWasAwarded = false
@@ -137,6 +137,8 @@ do
TUM.playerCareer.displayMedalBox(false)
end
TUM.playerScore.reset(false)
return somethingWasAwarded
end
+1 -3
View File
@@ -171,8 +171,6 @@ do
TUM.radio.playForAll("atcSafeLandingPlayer", {event.initiator:getCallsign(), baseName}, baseName.." ATC")
end
TUM.playerScore.reset(false)
end
-------------------------------------
@@ -212,7 +210,7 @@ do
msg = string.format("You have completed %d objective(s).", completedObjectives)
end
trigger.action.outText("REMINDER: "..msg.." They will be awarded to your flight career once you've landed.", 5)
trigger.action.outText("[REMINDER] "..msg.." All progress will be recorded to your flight log upon landing.", 5)
trigger.action.outSound("UI-Ok.ogg")
return true
end
+160
View File
@@ -0,0 +1,160 @@
{
"displayName": "Kola",
"dcsID": "Kola",
"mapCenter": [116230.08849558, -22000],
"mapZoom": 1812979.3510324,
"dateTime": {
"day": 1,
"month": 6,
"year": 2010,
"hour": 12,
"minute": 0
},
"temperature": 14,
"airbasesIDs": [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33
],
"bullseye": {
"blue": [139562.64976911, 374853.373795],
"red": [42374.616404854, 102140.40086341]
},
"player": {
"airdromeID": 18,
"coordinates": [80495.585938, 197621.367188]
},
"territories": {
"blue": [
[
[-301532.15339233, 2863.7168141594],
[251167.55162242, 317804.12979351],
[355802.35988201, -111612.97935103],
[-76204.719764012, -471618.87905605]
],
[
[-289100.29498525, 24101.474926254],
[-303086.13569322, 206953.39233038],
[-221761.0619469, 342149.85250737],
[72977.581120944, 221975.22123894]
]
],
"red": [
[
[93179.351032448, 252536.87315634],
[-322769.91150442, 408453.09734513],
[153266.66666667, 569549.26253687],
[230447.78761062, 339559.8820059]
],
[
[-313446.01769912, 364423.59882006],
[-310856.04719764, 625492.62536873],
[120633.03834808, 630672.56637168],
[198850.14749263, 392913.27433628]
]
]
},
"water": [
[
[81265.486725664, -465920.9439528],
[17034.218289086, -443647.19764012],
[275513.27433628, -102807.07964602],
[308146.90265487, -198117.99410029]
],
[
[-206221.23893805, -544138.05309735],
[-17153.392330383, -341602.35988201],
[21178.171091445, -349372.27138643],
[-124378.17109145, -574699.70501475]
],
[
[293643.06784661, -78979.351032448],
[408119.7640118, 172247.78761062],
[444897.34513274, 161369.91150442],
[334564.60176991, -166002.35988201]
],
[
[384810.02949853, 177427.72861357],
[211800, 476310.32448378],
[195224.18879056, 621866.66666667],
[437127.43362832, 218349.26253687]
],
[
[-197415.33923304, 602700.88495575],
[-311892.03539823, 617722.71386431],
[-163227.72861357, 643104.42477876],
[-102622.41887906, 508943.95280236]
]
],
"targetZones": {
"Finland, Hosio": [
[-167889.67551623, 68130.973451302],
[-246106.78466077, 86778.761061921],
[-306712.09439528, 369603.53982297],
[-105730.38348083, 279472.56637165]
],
"Finland, Ivalo": [
[-53930.973451334, 51037.168141568],
[25322.123893796, 275846.60766959],
[220605.899705, 203845.42772858],
[62099.705014739, 7525.6637167904]
],
"Finland, Sodankyla": [
[-161155.75221239, 75900.884955727],
[-103658.40707965, 285170.5014749],
[24286.135693206, 285170.5014749],
[-55484.955752219, 58289.085545698]
],
"Norway, Alta": [
[95576.686393045, -11385.27604052],
[133697.8546523, 99208.003305013],
[281155.56044634, 180896.22100342],
[251412.67092539, 9141.5068683096]
],
"Norway, Evenes": [
[-97542.638524723, -393015.87256999],
[-109691.14269525, -293314.35558425],
[141238.30551677, -113181.36271084],
[161765.0884256, -265247.12181095]
],
"Russia, Alakurtti": [
[-110234.42866711, 318981.13768815],
[-58308.247474191, 494187.84429828],
[1035.9596034337, 455331.51823555],
[-11327.416871072, 323573.24895011]
],
"Russia, Murmansk": [
[118311.41644731, 247273.55413602],
[105594.80064496, 452505.60361281],
[186486.60672101, 512909.52867396],
[223576.73614453, 329225.0781956]
],
"Russia, Olenya": [
[-5322.3482977404, 320394.09499952],
[4215.1135540207, 457450.95420261],
[105241.56131712, 488182.77572495],
[110893.39056261, 298493.25667326]
],
"Sweden, Kiruna": [
[-84492.625368732, -174290.26548673],
[-136810.02949853, 58807.079646018],
[37753.982300885, 8043.6578171093],
[86963.421828909, -74835.398230088]
],
"Sweden, Jokkmokk": [
[-288064.30678466, -233859.58702065],
[-306712.09439528, -42719.7640118],
[-146651.91740413, 55181.120943953],
[-103658.40707965, -147354.57227139]
]
}
}
+91
View File
@@ -0,0 +1,91 @@
{
"displayName": "Marianas",
"dcsID": "MarianaIslands",
"mapCenter": [27127.980181969, 27815.505908842],
"mapZoom": 291324.5582713,
"dateTime": {
"day": 1,
"month": 6,
"year": 2010,
"hour": 12,
"minute": 0
},
"temperature": 20,
"airbasesIDs": [1, 2, 3, 4, 5, 6, 7, 8],
"bullseye": {
"blue": [72602.401902589, 43075.528198602],
"red": [-1146.3260903998, 2927.7219674316]
},
"player": {
"airdromeID": 6,
"coordinates": [10574.989746, 14548.833496]
},
"territories": {
"blue": [
[
[-10518.040931597, -27038.898846712],
[-31359.16028292, -10600.832879471],
[9861.8061604412, 19172.194765276],
[19716.258972435, 6801.7114480924]
]
],
"red": [
[
[66051.678054794, 42156.393816762],
[76063.104098543, 58325.927247133],
[81320.903387706, 50871.376200169],
[71849.662202433, 31244.659675554]
]
]
},
"water": [
[
[-15884.73423628, -36062.094281533],
[22439.206281211, 9704.8280836718],
[29785.771142219, -435.50087940996],
[-11213.14547633, -69260.193128838]
],
[
[-86256.752152125, -4056.7415005977],
[24301.715682593, 41052.992434618],
[15196.114164724, 24704.298800261],
[-50374.974655487, -24333.424628892]
],
[
[90938.163154274, -232.63262935835],
[10229.422427705, 17254.261194732],
[79970.052235022, 82442.090243115],
[65276.922513006, 40225.210478448]
],
[
[80564.489315105, 20511.445275523],
[80922.886029884, 83320.469540388],
[96513.143122732, 86098.044079918],
[93735.568583201, 2950.0062513955]
]
],
"targetZones": {
"Guam": [
[-10518.040931597, -27038.898846712],
[-31359.16028292, -10600.832879471],
[9861.8061604412, 19172.194765276],
[19716.258972435, 6801.7114480924]
],
"Rota Island": [
[66051.678054794, 42156.393816762],
[76063.104098543, 58325.927247133],
[81320.903387706, 50871.376200169],
[71849.662202433, 31244.659675554]
]
}
}