Commit Graph
1259 Commits
Author SHA1 Message Date
c99f939fe6 stop pasting a directive name onto the comma after it
DIRECTIVE_TEXT builds four enumerator names from one directive name:

    #define DIRECTIVE_TEXT(id)  RCDT_##id##, RCDT_##id##_EFFECT, ...

The last ## on the first name has nothing to paste onto but the comma that
follows, and RCDT_GATHER_SUPPLIES, is not a token. The other three pastes are
well formed; only this one runs off the end of the name.

MSVC concatenates the text and re-lexes it, so it recovers the identifier and
the comma and produces the right enumerators; clang diagnoses it. Removing the
stray ## gives the same ten enumerations, and MISSION_TEXT just below already
spells it this way.

Verification:

    grep -rn '##[A-Za-z_]*##[,)]' --include=*.h --include=*.cpp .   # nothing
    ninja -C build parse         # token-paste class gone: 55 -> 45 sites
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
70b11ee120 make narrowing conversions in braced initialisers explicit
A braced initialiser does not allow a narrowing conversion unless the value
is a constant expression the compiler can prove fits. Every site here holds a
runtime value: WORLD_COLS is the global guiWorldCols, the laptop screen
coordinates are built from iScreenWidthOffset, the sector limits come from the
externalised options. MSVC accepts all of it silently; clang rejects it, and
it is ill-formed.

Nothing about the generated code changes. MSVC was already performing these
conversions; the casts only say so out loud, at the 73 places where it was
happening implicitly.

The invariant: each site is wrapped in a static_cast to the element type the
initialiser already had, and nothing else is touched. No type is widened, no
expression is reassociated, no value is clamped or checked. static_cast rather
than a C-style cast so that a later reader can grep for the narrowings, and so
that none of these can quietly become a reinterpret_cast if a type changes.

Verification:

    # every changed line differs only by inserted casts and their parentheses
    git show HEAD -U0 | grep '^[+-][^+-]' |
      sed -E 's/static_cast<[A-Za-z0-9_]+>//g; s/[()]//g; s/^[+-]//' |
      sort | uniq -c | awk '$1 % 2'          # no output

    git show HEAD -U0 | grep -c '^+[^+]'     # 38 lines, 73 casts

    ninja -C build parse                     # narrowing class gone: 129 -> 91 sites
    ninja -C build -k 0                      # Release, four applications, green
    ninja -C build-debug -k 0                # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
5e2982c509 take popup option names by const reference, not by pointer
POPUP_OPTION copies the name it is given -- `this->name = *newName` into a
std::wstring member -- but its constructor took a std::wstring*, so 64 call
sites spelled the argument `&std::wstring( pStr )`. Taking the address of a
temporary is ill-formed, and clang refuses it outright:

    error: taking the address of a temporary object of type 'std::wstring'

It happens to work under MSVC because the temporary outlives the call, dying
at the end of the full expression rather than before the copy. Nothing was
corrupt; the code was just spelling "pass me a string" in a way the language
does not allow.

A const reference says what these functions actually want, so the call sites
lose the &, and the two places that allocated a string purely to have an
address to pass -- POPUP_SUB_POPUP_OPTION's default constructor, which carried
a "TODO: possible memmory leak!" saying as much, and a "Dummy generator"
option -- stop leaking one.

Converted: POPUP_OPTION's constructor and setName, POPUP::addOption and
addSubMenuOption, and both POPUP_SUB_POPUP_OPTION constructors. The popupDef
family in popup_definition.* keeps its std::wstring* because it owns what it
is handed and stores the pointer; that is a different design and a different
change. The three calls it makes into the converted API now dereference.

Verification:
    grep -rn '&std::wstring' --include=*.cpp --include=*.h .   # nothing
    ninja -C build parse             # no popup_* or SkillMenu sites remain
    ninja -C build -k 0              # Release, four applications, green
    ninja -C build-debug -k 0        # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
fd2c74727e Make LANGUAGE switchable in runtime (#653)
squashed into a single commit because doing it in steps that all
compiled involved a lot of boilerplate that is pointless to commit to
the repository. GH still has the PR for reference.

g_lang, MAX_MESSAGES_ON_MAP_BOTTOM, and GetLanguagePrefix() were
compile-time constants selected by the ENGLISH/GERMAN/... build
define. They're now runtime, defaulting to the same per-exe value the
define used to pick, and overridable at startup from [Ja2 Settings]
LANGUAGE in Ja2.ini.

-

XMLTacticalMessages is filled at runtime from NewTacticalMessages.xml,
never from compiled-in per-language data: all 8 per-language definitions
were the identical all-zero { L"" }. Delete them and define one shared
buffer in Utils/XML_Language.cpp (the loader) instead of pointer-rebinding
it like the static tables — this drops 9 dead 800KB zero-buffers (8
namespaced copies in LanguageStrings.cpp plus the standalone one) and
leaves no bind-ordering hazard for the XML load path.

-

ExportStrings.cpp privately recompiled one language's full text table
by #including the raw _<LANG>Text.cpp inside namespace Loc, keyed off
the exe-level ENGLISH/GERMAN/... compile macro (whichever the build
happened to select). That's redundant with the pointer globals every
other subsystem already uses (Text.h / LanguageStrings.cpp).

Drop the private copy; the unqualified table names in Loc::ExportStrings
now resolve to the global pointer externs, which BindLanguageStrings has
already rebound to the runtime g_lang by the time this runs (EXPORT_STRINGS
ini flag, checked after GetRuntimeSettings in sgp.cpp). gs_Lang (used only
by Loc::Translate for the Polish/Russian byte remap on raw .edt exports) is
now derived from g_lang via ToLocLanguage, so the export always matches
whatever language is actually active instead of a compile-time pick.

-

Editor/popupmenu.cpp and Strategic/Scheduling.cpp kept their own
call-site extern of gszScheduleActions as CHAR16[NUM_SCHEDULE_ACTIONS][20]
after the real definition changed into a rebindable pointer
(CHAR16 (*)[20], LanguageStrings.cpp). MSVC decays the outer array
dimension when mangling globals, so both declarations produce the same
symbol (?gszScheduleActions@@3PAY0BE@_WA) and the mismatch linked
silently -- but the array-typed TUs then indexed the 4-byte pointer
slot itself as string data, so the editor schedule popup and the map
schedule message text read garbage.

-

add text.def to be single-source of truth on symbol names and use it
 .much simpler, less error prone if adding more strings

-

add pseudo interface for language state. MAX_SAGES_ON_BOTTOM must always
 change in lockstep with g_lang. this isn't foolproof but better

---------

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-07-21 05:33:03 -03:00
Asdow 2801af552e Set moved item old entry to not existing 2026-06-20 17:11:37 +03:00
Asdow ef30192b29 Leave merc equipment to current sector in UB 2026-06-20 08:49:56 +03:00
Asdow 392ba66df3 Enable dismissing mercs in UB before game start
Jerry Melo complains about too many mercs if player has hired over 6 mercs and refuses to fly. This allows player to dismiss mercs until the pilot is happy.
2026-06-20 08:49:56 +03:00
Asdow d4dd5f07df Disable contract renewal in UB 2026-06-20 08:49:56 +03:00
db29feed11 Don't strip robot's installed components on mapscreen drop-all
The mapscreen "drop everything" hotkey (Shift+W) looped over every
inventory slot from HELMETPOS to NUM_INV_SLOTS and dumped each one.
Madlab's robot stores its installed gear in those same slots - ammo (14),
targeting (15), chassis/armour (16) and utility (17). Dropping these left
the robot defenceless, and the player cannot re-install the components
through normal inventory, so the loss was permanent.

Skip the robot's component slots in the drop loop; only its general cargo
slot (ROBOT_INVENTORY_SLOT) may still be emptied. Regular mercs are
unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:06:33 +03:00
Asdow 1fc5f939bf Use new RandomGridNoUnloadedSector() for autoresolve
* Load required mapinfo for checking suitable gridnos
* Modify SOLDIERTYPE::DropSectorEquipment( ) to take an external gridno when placing items into an unloaded sector
2026-06-15 22:01:07 +03:00
Asdow db15679ec1 Add missing Iter->Exists() checks 2026-06-12 15:52:24 +03:00
Asdow 6a8a22aba2 Move iter->exists() check to first 2026-06-12 15:52:24 +03:00
Asdow 9b654ff3f1 Fix typo 2026-06-12 15:51:03 +03:00
Asdow a67f4b8a8f Formatting 2026-06-12 15:51:03 +03:00
Asdow 673dea01af Use correct sector for Chitzena 2026-06-12 15:51:03 +03:00
Asdow 8bc3dbd0aa Prevent RebelCommand::DailyUpdate() from running twice when loading autosave 2026-06-02 23:59:30 +03:00
Asdow 99a4ff1527 Guard against invalid value 2026-05-02 09:31:09 +03:00
GreysaandGitHub 0a758179c2 Advanced repairs skill check (#581)
* Add technician level skill check for advanced repair

* changed readability
2026-03-17 10:35:29 +01:00
noooooo4499andAsdow 481e95d42d Avoid breaking compatibility with gamedirs with old HourlyUpdate scripts
They are mapped to the right variable now
2026-02-25 10:47:47 +02:00
noooooo4499andAsdow 7d5a1c2e9e Remove useless lua gameclock variables, add lua externalized function to heal boxers
- These gameclock variables were not updated properly so it created a discrepancy between it and the proper gameclock variables, and it was causing issues with the lua hourly update script

- Function that heals boxers after they finish resting
2026-02-12 10:24:47 +02:00
Asdow 1c86d96e9d Remove custom_email.edt
Unfinished feature as far as I can tell and new emails will be easier to add via Emails.xml
2026-01-03 17:27:43 +02:00
Asdow 1368962244 Rename function to be more descriptive 2026-01-03 17:27:43 +02:00
Asdow 6f6aadf89c Remove unused & unfinished email externalizations 2026-01-03 17:27:43 +02:00
Asdow f8b6ee1672 Use externalized emails 2026-01-03 17:27:43 +02:00
Asdow aba3688b4b Add framework for adding externalized emails
Emails from new GameDir file TableData/Email/Emails.xml can be added via lua scripting using calls to AddEmailFromXML & AddPreReadEmailFromXML. The order of emails in Emails.xml acts as the index to be referenced and provided when calling lua  functions.

An error message  will be displayed if an email is added with an out-of-scope index but game will be able to continue.

Localization is supported and was tested on Chinese localization.
2026-01-03 17:27:43 +02:00
Asdow 03edc532e1 Clean up Strategic/*:cpp includes 2025-12-09 00:35:18 +02:00
Asdow 1db41f4c36 Fix helicopter airspace view when switching to travel mode
* Clicking destination column in teamlist for a squad in a helicopter will switch to first airspace view that shows safe / unsafe air sectors instead of the second sector.

* Clicking destination column in teamlist for a squad not in a helicopter while in either airspace view will now correctly turn it off
2025-12-04 23:06:08 +02:00
Asdow b226f2a21d set functions static 2025-12-03 23:52:05 +02:00
Asdow 6629562b34 Formatting 2025-12-03 23:52:05 +02:00
Asdow 91d7620c0b include cleanup 2025-12-03 23:52:05 +02:00
Asdow c341402fe1 set functions static 2025-12-03 23:52:05 +02:00
Asdow 80b1af930a include cleanup 2025-12-03 23:52:05 +02:00
Asdow 608eb8e4e6 set functions static 2025-12-03 23:52:05 +02:00
Asdow ec1c6fc112 include cleanup 2025-12-03 23:52:05 +02:00
Asdow 4fabab680f set functions static 2025-12-03 23:52:05 +02:00
Asdow def815988b include cleanup 2025-12-03 23:52:05 +02:00
Asdow 21df179941 Set function static 2025-12-03 23:52:05 +02:00
Asdow ff674e79b9 Set function static 2025-12-03 23:52:05 +02:00
Asdow 9efa5e1108 Include cleanup 2025-12-03 23:52:05 +02:00
Asdow c235345a22 formatting 2025-12-03 23:52:05 +02:00
Asdow 97791bfcc3 include cleanup 2025-12-03 23:52:05 +02:00
Asdow d49185c291 Move nullptr check to be checked first
Kinda defeats the purpose of checking for nullptr if we dereference it before the check, no?
2025-12-03 23:52:05 +02:00
Asdow 41eba8ff3a include cleanup 2025-12-03 23:52:05 +02:00
Asdow 2fd5e2c255 set functions static 2025-12-03 23:52:05 +02:00
Asdow a83bb00d52 include cleanup 2025-12-03 23:52:05 +02:00
Asdow cb27d0cd72 Set functions static 2025-12-03 23:52:05 +02:00
Asdow 020cd270c0 include cleanup 2025-12-03 23:52:05 +02:00
Asdow a6e1b93af0 Set functions static 2025-12-03 23:52:05 +02:00
Asdow 5dd4043f00 Formatting 2025-12-03 23:52:05 +02:00
Asdow 61f8efaac0 include cleanup 2025-12-03 23:52:05 +02:00