diff --git a/data/base/stats/weapons.json b/data/base/stats/weapons.json index a9d487b00b7..91de842e2d2 100644 --- a/data/base/stats/weapons.json +++ b/data/base/stats/weapons.json @@ -2957,8 +2957,6 @@ "lightWorld": 1, "longHit": 80, "longRange": 12032, - "maxElevation": 90, - "minElevation": -30, "minRange": 512, "minimumDamage": 33, "missGfx": "FXMExp.PIE", diff --git a/data/mods/campaign/wz2100_camclassic/stats/weapons.json b/data/mods/campaign/wz2100_camclassic/stats/weapons.json index 3055a7cbf17..3f5dccc69c2 100644 --- a/data/mods/campaign/wz2100_camclassic/stats/weapons.json +++ b/data/mods/campaign/wz2100_camclassic/stats/weapons.json @@ -2289,8 +2289,6 @@ "lightWorld": 1, "longHit": 80, "longRange": 12000, - "maxElevation": 90, - "minElevation": -30, "minRange": 512, "minimumDamage": 33, "missGfx": "FXMExp.PIE", diff --git a/data/mp/multiplay/script/rules/events/gameinit.js b/data/mp/multiplay/script/rules/events/gameinit.js index cfd2205c3bd..23a6d10ba4a 100644 --- a/data/mp/multiplay/script/rules/events/gameinit.js +++ b/data/mp/multiplay/script/rules/events/gameinit.js @@ -4,7 +4,7 @@ function eventGameInit() setupGame(); //From script/rules/printsettings.js - printGameSettings(); + queue("printGameSettings", TICK_TIME); //From script/rules/oildrum.js oilDrumInit(); @@ -49,7 +49,7 @@ function eventGameInit() //Structures might have been removed so we need to update the reticule button states again //From script/rules/reticule.js - setMainReticule(); + queue("setMainReticule", TICK_TIME); if (tilesetType === "URBAN" || tilesetType === "ROCKIES") { diff --git a/data/mp/multiplay/script/rules/includes.js b/data/mp/multiplay/script/rules/includes.js index d0f84e8216e..b12e78c70fe 100644 --- a/data/mp/multiplay/script/rules/includes.js +++ b/data/mp/multiplay/script/rules/includes.js @@ -7,7 +7,7 @@ include("multiplay/script/rules/variables.js"); // This file contain functions which contains the logic of technology research equated to time include("multiplay/script/functions/camTechEnabler.js"); -// Spectial effects of weather. +// Special effects of weather. include("multiplay/script/functions/weather.js"); /* *** SETUP *** */ @@ -35,7 +35,7 @@ include("multiplay/script/rules/reticule.js"); // Logic and rules of "End conditions" of the match. include("multiplay/script/rules/endconditions.js"); -// Logic of places oil barrels on the battlefield +// Logic of placing oil barrels on the battlefield include("multiplay/script/rules/oildrum.js"); /* *** EVENTS *** */ @@ -55,5 +55,5 @@ include("multiplay/script/rules/events/chat.js"); /* *** MODS *** */ //All mods, as well as modpacks, must start in this file. -//At the moment, it's an empty stub doll. +//At the moment, it's an empty stub. include("multiplay/script/mods/init.js"); diff --git a/data/mp/multiplay/script/rules/reticule.js b/data/mp/multiplay/script/rules/reticule.js index 2e2350ec82f..5b449f501f4 100644 --- a/data/mp/multiplay/script/rules/reticule.js +++ b/data/mp/multiplay/script/rules/reticule.js @@ -154,7 +154,6 @@ function reticuleUpdate(obj, eventType) if (mainReticule && update_reticule) { //Wait a tick for the counts to update - const TICK_TIME = 100; queue("setMainReticule", TICK_TIME); } } diff --git a/data/mp/multiplay/script/rules/setup/components.js b/data/mp/multiplay/script/rules/setup/components.js index 6e3337bfe88..3154de22da9 100644 --- a/data/mp/multiplay/script/rules/setup/components.js +++ b/data/mp/multiplay/script/rules/setup/components.js @@ -1,5 +1,4 @@ function setupComponents(player) // inside hackNetOff() { - // enable cyborgs components that can't be enabled with research - makeComponentAvailable("CyborgSpade", player); + // Use makeComponentAvailable() here to enable components at the start of a match. } diff --git a/data/mp/multiplay/script/rules/setupgame.js b/data/mp/multiplay/script/rules/setupgame.js index 2fc9e8087d6..70b87a66c7c 100644 --- a/data/mp/multiplay/script/rules/setupgame.js +++ b/data/mp/multiplay/script/rules/setupgame.js @@ -35,6 +35,6 @@ function setupGame() setDesign(true); showInterface(); // init buttons. This MUST come before setting the reticule button data - setMainReticule(); + queue("setMainReticule", TICK_TIME); mainReticule = true; } diff --git a/data/mp/multiplay/script/rules/variables.js b/data/mp/multiplay/script/rules/variables.js index 99648f1acb2..6dab54caa95 100644 --- a/data/mp/multiplay/script/rules/variables.js +++ b/data/mp/multiplay/script/rules/variables.js @@ -7,6 +7,8 @@ var oilDrumData = { maxOilDrums: 0 // maximum amount of random oil drums allowed on the map }; +const TICK_TIME = 100; + const CREATE_LIKE_EVENT = 0; const DESTROY_LIKE_EVENT = 1; const TRANSFER_LIKE_EVENT = 2; diff --git a/data/mp/stats/research.json b/data/mp/stats/research.json index fe0b5011e35..d40d063d579 100644 --- a/data/mp/stats/research.json +++ b/data/mp/stats/research.json @@ -3129,9 +3129,6 @@ "name": "Engineering", "researchPoints": 1200, "researchPower": 37, - "resultComponents": [ - "CyborgSpade" - ], "results": [ { "class": "Construct", @@ -3426,7 +3423,8 @@ "name": "Construction Unit", "researchPoints": 10, "resultComponents": [ - "Spade1Mk1" + "Spade1Mk1", + "CyborgSpade" ], "statID": "Spade1Mk1", "techCode": 1 diff --git a/data/mp/stats/weapons.json b/data/mp/stats/weapons.json index 03465362bad..cba1c4d0d24 100644 --- a/data/mp/stats/weapons.json +++ b/data/mp/stats/weapons.json @@ -3183,8 +3183,6 @@ "lightWorld": 1, "longHit": 65, "longRange": 1920, - "maxElevation": 90, - "minElevation": -30, "minRange": 256, "minimumDamage": 33, "missGfx": "FXMExp.PIE", @@ -4100,8 +4098,6 @@ "lightWorld": 1, "longHit": 55, "longRange": 1280, - "maxElevation": 90, - "minElevation": -60, "minRange": 128, "minimumDamage": 33, "missGfx": "FXMNExp.PIE", diff --git a/doc/js-objects.md b/doc/js-objects.md index a026e21c89f..c1e04993072 100644 --- a/doc/js-objects.md +++ b/doc/js-objects.md @@ -25,6 +25,7 @@ In addition, the following properties are defined: * ```status``` The completeness status of the structure. It will be one of ```BEING_BUILT``` and ```BUILT```. * ```type``` The type will always be ```STRUCTURE```. * ```cost``` What it would cost to build this structure. (3.2+ only) +* ```direction``` The direction the structure is facing. (4.5+ only) * ```stattype``` The stattype defines the type of structure. It will be one of ```HQ```, ```FACTORY```, ```POWER_GEN```, ```RESOURCE_EXTRACTOR```, ```LASSAT```, ```DEFENSE```, ```WALL```, ```RESEARCH_LAB```, ```REPAIR_FACILITY```, ```CYBORG_FACTORY```, ```VTOL_FACTORY```, ```REARM_PAD```, ```SAT_UPLINK```, ```GATE``` and ```COMMAND_CONTROL```. diff --git a/lib/wzmaplib/CMakeLists.txt b/lib/wzmaplib/CMakeLists.txt index 0abccc44490..3bdc0d29135 100644 --- a/lib/wzmaplib/CMakeLists.txt +++ b/lib/wzmaplib/CMakeLists.txt @@ -3,7 +3,7 @@ set(WZMAPLIB_VERSION_MAJOR 1) set(WZMAPLIB_VERSION_MINOR 2) -set(WZMAPLIB_VERSION_REV 4) +set(WZMAPLIB_VERSION_REV 5) ################### # Determine minimum CMake version @@ -22,7 +22,7 @@ endif() ############################## # wzmaplib project -cmake_minimum_required(VERSION ${_cmake_min_ver_supported}...3.18) +cmake_minimum_required(VERSION ${_cmake_min_ver_supported}...3.24) project (wzmaplib CXX) if(${CMAKE_VERSION} VERSION_LESS 3.12) @@ -78,7 +78,7 @@ if(NOT TARGET nlohmann_json) FetchContent_Declare( nlohmannjson GIT_REPOSITORY https://github.com/nlohmann/json.git - GIT_TAG v3.11.2 + GIT_TAG v3.11.3 GIT_SHALLOW TRUE ) FetchContent_GetProperties(nlohmannjson) @@ -97,7 +97,7 @@ if(NOT TARGET optional-lite) FetchContent_Declare( optionallite GIT_REPOSITORY https://github.com/martinmoene/optional-lite.git - GIT_TAG v3.5.0 + GIT_TAG v3.6.0 GIT_SHALLOW TRUE ) FetchContent_GetProperties(optionallite) diff --git a/lib/wzmaplib/src/map_package.cpp b/lib/wzmaplib/src/map_package.cpp index 64c74e2ea25..dd1578f495b 100644 --- a/lib/wzmaplib/src/map_package.cpp +++ b/lib/wzmaplib/src/map_package.cpp @@ -1448,6 +1448,8 @@ bool MapPackage::exportMapPackageFiles(std::string basePath, LevelFormat levelFo } // 5.) Output the level info file + LevelDetails outputLevelDetails = m_levelDetails; + outputLevelDetails.mapFolderPath = mapFolderPath; std::string fullPathToOutputLevelDetailsFolder = exportIO->pathJoin(basePath, levelFileOutputFolder); if (!fullPathToOutputLevelDetailsFolder.empty()) { @@ -1457,7 +1459,7 @@ bool MapPackage::exportMapPackageFiles(std::string basePath, LevelFormat levelFo // for now, treat this as non-fatal... } } - if (!exportLevelDetails(m_levelDetails, levelFormat, fullPathToOutputLevelDetailsFolder, *exportIO, pCustomLogger)) + if (!exportLevelDetails(outputLevelDetails, levelFormat, fullPathToOutputLevelDetailsFolder, *exportIO, pCustomLogger)) { debug(pCustomLogger, LOG_ERROR, "Failed to export level details"); return false; diff --git a/src/multimenu.cpp b/src/multimenu.cpp index 2cab39efa57..8db636445d3 100644 --- a/src/multimenu.cpp +++ b/src/multimenu.cpp @@ -508,7 +508,7 @@ void addMultiRequest(const char *searchDir, const char *fileExtension, UDWORD mo searchBox->setString(WzString::fromUtf8(current_searchString)); searchBox->setOnEditingStoppedHandler([searchDir, fileExtension, mode, numPlayers](W_EDITBOX& widg) { - const std::string &value = widg.getString().toUtf8(); + std::string value = widg.getString().toUtf8(); if (value == current_searchString) { return; } diff --git a/src/projectile.cpp b/src/projectile.cpp index 2e519042f1d..1cfb348b460 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -551,15 +551,16 @@ static PROJECTILE* proj_SendProjectileAngledInternal(WEAPON* psWeap, SIMPLE_OBJE proj.state = PROJ_INFLIGHT; // If droid or structure, set muzzle pitch. + // Don't allow pitching the muzzle above outside the weapon's limits. if (psAttacker != nullptr && weapon_slot >= 0) { if (psAttacker->type == OBJ_DROID) { - ((DROID *)psAttacker)->asWeaps[weapon_slot].rot.pitch = proj.rot.pitch; + ((DROID *)psAttacker)->asWeaps[weapon_slot].rot.pitch = (uint16_t)clip(angleDelta(proj.rot.pitch), (int32_t)DEG(psStats->minElevation), (int32_t)DEG(psStats->maxElevation)); } else if (psAttacker->type == OBJ_STRUCTURE) { - ((STRUCTURE *)psAttacker)->asWeaps[weapon_slot].rot.pitch = proj.rot.pitch; + ((STRUCTURE *)psAttacker)->asWeaps[weapon_slot].rot.pitch = (uint16_t)clip(angleDelta(proj.rot.pitch), (int32_t)DEG(psStats->minElevation), (int32_t)DEG(psStats->maxElevation)); } } diff --git a/src/quickjs_backend.cpp b/src/quickjs_backend.cpp index 4f08002cf3d..abf9a7ac419 100644 --- a/src/quickjs_backend.cpp +++ b/src/quickjs_backend.cpp @@ -794,6 +794,7 @@ JSValue convResearch(const RESEARCH *psResearch, JSContext *ctx, int player) //;; * ```status``` The completeness status of the structure. It will be one of ```BEING_BUILT``` and ```BUILT```. //;; * ```type``` The type will always be ```STRUCTURE```. //;; * ```cost``` What it would cost to build this structure. (3.2+ only) +//;; * ```direction``` The direction the structure is facing. (4.5+ only) //;; * ```stattype``` The stattype defines the type of structure. It will be one of ```HQ```, ```FACTORY```, ```POWER_GEN```, //;; ```RESOURCE_EXTRACTOR```, ```LASSAT```, ```DEFENSE```, ```WALL```, ```RESEARCH_LAB```, ```REPAIR_FACILITY```, //;; ```CYBORG_FACTORY```, ```VTOL_FACTORY```, ```REARM_PAD```, ```SAT_UPLINK```, ```GATE```, ```STRUCT_GENERIC```, and ```COMMAND_CONTROL```. @@ -835,6 +836,7 @@ JSValue convStructure(const STRUCTURE *psStruct, JSContext *ctx) QuickJS_DefinePropertyValue(ctx, value, "status", JS_NewInt32(ctx, (int)psStruct->status), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, value, "health", JS_NewInt32(ctx, 100 * psStruct->body / MAX(1, psStruct->structureBody())), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, value, "cost", JS_NewInt32(ctx, psStruct->pStructureType->powerToBuild), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "direction", JS_NewInt32(ctx, UNDEG(psStruct->rot.direction)), JS_PROP_ENUMERABLE); int stattype = 0; switch (psStruct->pStructureType->type) // don't bleed our source insanities into the scripting world {