Files
source/Editor/EditorMercs.h
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

440 lines
11 KiB
C

#pragma once
#include "builddefines.h"
//-----------------------------------------------
//
// civilian "sub teams":
enum
{
NON_CIV_GROUP = 0,
REBEL_CIV_GROUP,
KINGPIN_CIV_GROUP,
SANMONA_ARMS_GROUP,
ANGELS_GROUP,
BEGGARS_CIV_GROUP,
TOURISTS_CIV_GROUP,
ALMA_MILITARY_CIV_GROUP,
DOCTORS_CIV_GROUP,
COUPLE1_CIV_GROUP,
HICKS_CIV_GROUP,
WARDEN_CIV_GROUP,
JUNKYARD_CIV_GROUP,
FACTORY_KIDS_GROUP,
QUEENS_CIV_GROUP,
UNNAMED_CIV_GROUP_15,
UNNAMED_CIV_GROUP_16,
UNNAMED_CIV_GROUP_17,
UNNAMED_CIV_GROUP_18,
UNNAMED_CIV_GROUP_19,
ASSASSIN_CIV_GROUP, // Flugente: enemy assassins belong to this group
POW_PRISON_CIV_GROUP, // Flugente: prisoners of war the player caught are in this group
UNNAMED_CIV_GROUP_22,
UNNAMED_CIV_GROUP_23,
VOLUNTEER_CIV_GROUP, // Flugente: civilians that the player recruited
BOUNTYHUNTER_CIV_GROUP, // Flugente: hostile bounty hunters
DOWNEDPILOT_CIV_GROUP, // Flugente: downed pilots
SCIENTIST_GROUP, // Flugente: enemy civilian personnel
RADAR_TECHNICIAN_GROUP,
AIRPORT_STAFF_GROUP,
BARRACK_STAFF_GROUP,
FACTORY_GROUP,
ADMINISTRATIVE_STAFF_GROUP,
LOYAL_CIV_GROUP, // civil population deeply loyal to the queen
BLACKMARKET_GROUP, // black market dealer and bodyguards
UNNAMED_CIV_GROUP_35,
UNNAMED_CIV_GROUP_36,
UNNAMED_CIV_GROUP_37,
UNNAMED_CIV_GROUP_38,
UNNAMED_CIV_GROUP_39,
UNNAMED_CIV_GROUP_40,
UNNAMED_CIV_GROUP_41,
UNNAMED_CIV_GROUP_42,
UNNAMED_CIV_GROUP_43,
UNNAMED_CIV_GROUP_44,
UNNAMED_CIV_GROUP_45,
UNNAMED_CIV_GROUP_46,
UNNAMED_CIV_GROUP_47,
UNNAMED_CIV_GROUP_48,
UNNAMED_CIV_GROUP_49,
UNNAMED_CIV_GROUP_50,
UNNAMED_CIV_GROUP_51,
UNNAMED_CIV_GROUP_52,
UNNAMED_CIV_GROUP_53,
UNNAMED_CIV_GROUP_54,
UNNAMED_CIV_GROUP_55,
UNNAMED_CIV_GROUP_56,
UNNAMED_CIV_GROUP_57,
UNNAMED_CIV_GROUP_58,
UNNAMED_CIV_GROUP_59,
UNNAMED_CIV_GROUP_60,
UNNAMED_CIV_GROUP_61,
UNNAMED_CIV_GROUP_62,
UNNAMED_CIV_GROUP_63,
UNNAMED_CIV_GROUP_64,
UNNAMED_CIV_GROUP_65,
UNNAMED_CIV_GROUP_66,
UNNAMED_CIV_GROUP_67,
UNNAMED_CIV_GROUP_68,
UNNAMED_CIV_GROUP_69,
UNNAMED_CIV_GROUP_70,
UNNAMED_CIV_GROUP_71,
UNNAMED_CIV_GROUP_72,
UNNAMED_CIV_GROUP_73,
UNNAMED_CIV_GROUP_74,
UNNAMED_CIV_GROUP_75,
UNNAMED_CIV_GROUP_76,
UNNAMED_CIV_GROUP_77,
UNNAMED_CIV_GROUP_78,
UNNAMED_CIV_GROUP_79,
UNNAMED_CIV_GROUP_80,
UNNAMED_CIV_GROUP_81,
UNNAMED_CIV_GROUP_82,
UNNAMED_CIV_GROUP_83,
UNNAMED_CIV_GROUP_84,
UNNAMED_CIV_GROUP_85,
UNNAMED_CIV_GROUP_86,
UNNAMED_CIV_GROUP_87,
UNNAMED_CIV_GROUP_88,
UNNAMED_CIV_GROUP_89,
UNNAMED_CIV_GROUP_90,
UNNAMED_CIV_GROUP_91,
UNNAMED_CIV_GROUP_92,
UNNAMED_CIV_GROUP_93,
UNNAMED_CIV_GROUP_94,
UNNAMED_CIV_GROUP_95,
UNNAMED_CIV_GROUP_96,
UNNAMED_CIV_GROUP_97,
UNNAMED_CIV_GROUP_98,
UNNAMED_CIV_GROUP_99,
UNNAMED_CIV_GROUP_100,
UNNAMED_CIV_GROUP_101,
UNNAMED_CIV_GROUP_102,
UNNAMED_CIV_GROUP_103,
UNNAMED_CIV_GROUP_104,
UNNAMED_CIV_GROUP_105,
UNNAMED_CIV_GROUP_106,
UNNAMED_CIV_GROUP_107,
UNNAMED_CIV_GROUP_108,
UNNAMED_CIV_GROUP_109,
UNNAMED_CIV_GROUP_110,
UNNAMED_CIV_GROUP_111,
UNNAMED_CIV_GROUP_112,
UNNAMED_CIV_GROUP_113,
UNNAMED_CIV_GROUP_114,
UNNAMED_CIV_GROUP_115,
UNNAMED_CIV_GROUP_116,
UNNAMED_CIV_GROUP_117,
UNNAMED_CIV_GROUP_118,
UNNAMED_CIV_GROUP_119,
UNNAMED_CIV_GROUP_120,
UNNAMED_CIV_GROUP_121,
UNNAMED_CIV_GROUP_122,
UNNAMED_CIV_GROUP_123,
UNNAMED_CIV_GROUP_124,
UNNAMED_CIV_GROUP_125,
UNNAMED_CIV_GROUP_126,
UNNAMED_CIV_GROUP_127,
UNNAMED_CIV_GROUP_128,
UNNAMED_CIV_GROUP_129,
UNNAMED_CIV_GROUP_130,
UNNAMED_CIV_GROUP_131,
UNNAMED_CIV_GROUP_132,
UNNAMED_CIV_GROUP_133,
UNNAMED_CIV_GROUP_134,
UNNAMED_CIV_GROUP_135,
UNNAMED_CIV_GROUP_136,
UNNAMED_CIV_GROUP_137,
UNNAMED_CIV_GROUP_138,
UNNAMED_CIV_GROUP_139,
UNNAMED_CIV_GROUP_140,
UNNAMED_CIV_GROUP_141,
UNNAMED_CIV_GROUP_142,
UNNAMED_CIV_GROUP_143,
UNNAMED_CIV_GROUP_144,
UNNAMED_CIV_GROUP_145,
UNNAMED_CIV_GROUP_146,
UNNAMED_CIV_GROUP_147,
UNNAMED_CIV_GROUP_148,
UNNAMED_CIV_GROUP_149,
UNNAMED_CIV_GROUP_150,
UNNAMED_CIV_GROUP_151,
UNNAMED_CIV_GROUP_152,
UNNAMED_CIV_GROUP_153,
UNNAMED_CIV_GROUP_154,
UNNAMED_CIV_GROUP_155,
UNNAMED_CIV_GROUP_156,
UNNAMED_CIV_GROUP_157,
UNNAMED_CIV_GROUP_158,
UNNAMED_CIV_GROUP_159,
UNNAMED_CIV_GROUP_160,
UNNAMED_CIV_GROUP_161,
UNNAMED_CIV_GROUP_162,
UNNAMED_CIV_GROUP_163,
UNNAMED_CIV_GROUP_164,
UNNAMED_CIV_GROUP_165,
UNNAMED_CIV_GROUP_166,
UNNAMED_CIV_GROUP_167,
UNNAMED_CIV_GROUP_168,
UNNAMED_CIV_GROUP_169,
UNNAMED_CIV_GROUP_170,
UNNAMED_CIV_GROUP_171,
UNNAMED_CIV_GROUP_172,
UNNAMED_CIV_GROUP_173,
UNNAMED_CIV_GROUP_174,
UNNAMED_CIV_GROUP_175,
UNNAMED_CIV_GROUP_176,
UNNAMED_CIV_GROUP_177,
UNNAMED_CIV_GROUP_178,
UNNAMED_CIV_GROUP_179,
UNNAMED_CIV_GROUP_180,
UNNAMED_CIV_GROUP_181,
UNNAMED_CIV_GROUP_182,
UNNAMED_CIV_GROUP_183,
UNNAMED_CIV_GROUP_184,
UNNAMED_CIV_GROUP_185,
UNNAMED_CIV_GROUP_186,
UNNAMED_CIV_GROUP_187,
UNNAMED_CIV_GROUP_188,
UNNAMED_CIV_GROUP_189,
UNNAMED_CIV_GROUP_190,
UNNAMED_CIV_GROUP_191,
UNNAMED_CIV_GROUP_192,
UNNAMED_CIV_GROUP_193,
UNNAMED_CIV_GROUP_194,
UNNAMED_CIV_GROUP_195,
UNNAMED_CIV_GROUP_196,
UNNAMED_CIV_GROUP_197,
UNNAMED_CIV_GROUP_198,
UNNAMED_CIV_GROUP_199,
UNNAMED_CIV_GROUP_200,
UNNAMED_CIV_GROUP_201,
UNNAMED_CIV_GROUP_202,
UNNAMED_CIV_GROUP_203,
UNNAMED_CIV_GROUP_204,
UNNAMED_CIV_GROUP_205,
UNNAMED_CIV_GROUP_206,
UNNAMED_CIV_GROUP_207,
UNNAMED_CIV_GROUP_208,
UNNAMED_CIV_GROUP_209,
UNNAMED_CIV_GROUP_210,
UNNAMED_CIV_GROUP_211,
UNNAMED_CIV_GROUP_212,
UNNAMED_CIV_GROUP_213,
UNNAMED_CIV_GROUP_214,
UNNAMED_CIV_GROUP_215,
UNNAMED_CIV_GROUP_216,
UNNAMED_CIV_GROUP_217,
UNNAMED_CIV_GROUP_218,
UNNAMED_CIV_GROUP_219,
UNNAMED_CIV_GROUP_220,
UNNAMED_CIV_GROUP_221,
UNNAMED_CIV_GROUP_222,
UNNAMED_CIV_GROUP_223,
UNNAMED_CIV_GROUP_224,
UNNAMED_CIV_GROUP_225,
UNNAMED_CIV_GROUP_226,
UNNAMED_CIV_GROUP_227,
UNNAMED_CIV_GROUP_228,
UNNAMED_CIV_GROUP_229,
UNNAMED_CIV_GROUP_230,
UNNAMED_CIV_GROUP_231,
UNNAMED_CIV_GROUP_232,
UNNAMED_CIV_GROUP_233,
UNNAMED_CIV_GROUP_234,
UNNAMED_CIV_GROUP_235,
UNNAMED_CIV_GROUP_236,
UNNAMED_CIV_GROUP_237,
UNNAMED_CIV_GROUP_238,
UNNAMED_CIV_GROUP_239,
UNNAMED_CIV_GROUP_240,
UNNAMED_CIV_GROUP_241,
UNNAMED_CIV_GROUP_242,
UNNAMED_CIV_GROUP_243,
UNNAMED_CIV_GROUP_244,
UNNAMED_CIV_GROUP_245,
UNNAMED_CIV_GROUP_246,
UNNAMED_CIV_GROUP_247,
UNNAMED_CIV_GROUP_248,
UNNAMED_CIV_GROUP_249,
UNNAMED_CIV_GROUP_250,
UNNAMED_CIV_GROUP_251,
UNNAMED_CIV_GROUP_252,
UNNAMED_CIV_GROUP_253,
UNNAMED_CIV_GROUP_254,
NUM_CIV_GROUPS
};
#define CIV_GROUP_NEUTRAL 0
#define CIV_GROUP_WILL_EVENTUALLY_BECOME_HOSTILE 1
#define CIV_GROUP_WILL_BECOME_HOSTILE 2
#define CIV_GROUP_HOSTILE 3
#ifdef JA2EDITOR
#ifndef __EDITORMERCS_H
#define __EDITORMERCS_H
//Merc editing modes. These are used to determine which buttons to show and hide.
enum
{
MERC_NOMODE, //used for shutting down mercs tab, to extract any changed information
MERC_GETITEMMODE, //when selecting a specific piece of inventory from inventorymode
MERC_TEAMMODE, //selecting a team with no merc selected.
MERC_BASICMODE, //basic placement mode
MERC_GENERALMODE, //detailed placement mode for general information and NPC info
MERC_ATTRIBUTEMODE, //detailed placement mode for specifying attributes
MERC_INVENTORYMODE, //detailed placement mode for specifying inventory
MERC_APPEARANCEMODE, //detailed placement mode for specifying appearance
MERC_PROFILEMODE, //specifying a valid profile index will generate the merc automatically.
MERC_SCHEDULEMODE, //specifying a schedule for that particular individual
};
extern UINT8 gubCurrMercMode, gubPrevMercMode;
#define EDIT_NUM_COLORS 4
#define EDIT_COLOR_HEAD 0
#define EDIT_COLOR_PANTS 1
#define EDIT_COLOR_SKIN 2
#define EDIT_COLOR_VEST 3
#define EDIT_MERC_NONE 0
#define EDIT_MERC_DEC_STAT 1
#define EDIT_MERC_INC_STAT 2
#define EDIT_MERC_PREV_ORDER 3
#define EDIT_MERC_NEXT_ORDER 4
#define EDIT_MERC_PREV_ATT 5
#define EDIT_MERC_NEXT_ATT 6
#define EDIT_MERC_SET_DIR 7
#define EDIT_MERC_FIND 8
#define EDIT_MERC_DONE 9
#define EDIT_MERC_TO_COLOR 10
#define EDIT_MERC_TO_STATS 11
#define EDIT_MERC_PREV_COLOR 12
#define EDIT_MERC_NEXT_COLOR 13
#define NUM_MERC_BUTTONS 40
#define NUM_DIFF_LVLS 5
extern STR16 *zDiffNames;
extern INT16 sCurBaseDiff;
extern INT16 gsSelectedMercID;
extern INT32 gsSelectedMercGridNo;
extern UINT8 gubCurrMercMode;
enum _ForUseWithIndicateSelectedMerc
{
SELECT_NEXT_CREATURE = -7,
SELECT_NEXT_REBEL = -6,
SELECT_NEXT_CIV = -5,
SELECT_NEXT_ENEMY = -4,
SELECT_NEXT_TEAMMATE = -3,
SELECT_NEXT_MERC = -2,
SELECT_NO_MERC = -1
// >= 0 select merc with matching ID
};
void IndicateSelectedMerc( INT16 sID );
void GameInitEditorMercsInfo();
void GameShutdownEditorMercsInfo();
void EntryInitEditorMercsInfo();
void UpdateMercsInfo();
void ProcessMercEditing();
void AddMercToWorld( INT32 iMapIndex );
void HandleRightClickOnMerc( INT32 iMapIndex );
void SetMercEditingMode( UINT8 ubNewMode );
void ResetAllMercPositions();
void EraseMercWaypoint();
void AddMercWaypoint( INT32 iMapIndex );
void SetEnemyColorCode( UINT8 ubColorCode );
void SpecifyEntryPoint(INT32 iMapIndex);//dnl ch41 290909
//Modify stats of current soldiers
void SetMercOrders( INT8 bOrders );
void SetMercAttitude( INT8 bAttitude );
void SetMercDirection( INT8 bDirection );
void SetMercRelativeEquipment( INT8 bLevel );
void SetMercRelativeAttributes( INT8 bLevel );
void DeleteSelectedMerc();
void CreateEditMercWindow( void );
void DisplayEditMercWindow( void );
INT32 IsMercHere( INT32 iMapIndex );
void ExtractCurrentMercModeInfo( BOOLEAN fKillTextInputMode );
void SetMercEditability( BOOLEAN fEditable );
void HandleMercInventoryPanel( INT16 sX, INT16 sY, INT8 bEvent );
extern UINT16 gusMercsNewItemIndex;
extern BOOLEAN gfRenderMercInfo;
//NOTE: The editor uses these enumerations, so please update the text as well if you modify or
// add new groups. Try to abbreviate the team name as much as possible. The text is in
// EditorMercs.c
extern CHAR16 gszCivGroupNames[ NUM_CIV_GROUPS ][ 128 ];
//
//-----------------------------------------------
void ChangeCivGroup( UINT8 ubNewCivGroup );
#define MERCINV_LGSLOT_WIDTH 48
#define MERCINV_SMSLOT_WIDTH 24
#define MERCINV_SLOT_HEIGHT 18
extern BOOLEAN gfRoofPlacement;
extern void SetEnemyDroppableStatus( UINT32 uiSlot, BOOLEAN fDroppable );
void RenderMercStrings();
extern BOOLEAN gfShowPlayers;
extern BOOLEAN gfShowEnemies;
extern BOOLEAN gfShowCreatures;
extern BOOLEAN gfShowRebels;
extern BOOLEAN gfShowCivilians;
void SetMercTeamVisibility( INT8 bTeam, BOOLEAN fVisible );
extern UINT8 gubCurrentScheduleActionIndex;
extern BOOLEAN gfSingleAction;
extern BOOLEAN gfUseScheduleData2;
void UpdateScheduleAction( UINT8 ubNewAction );
void FindScheduleGridNo( UINT8 ubScheduleData );
void ClearCurrentSchedule();
void CancelCurrentScheduleAction();
void RegisterCurrentScheduleAction( INT32 iMapIndex );
void StartScheduleAction();
void InitDetailedPlacementForMerc();
void KillDetailedPlacementForMerc();
void CopyMercPlacement( INT32 iMapIndex );
void PasteMercPlacement( INT32 iMapIndex );
#endif
#endif