Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c33465611f | ||
|
|
fccdc2dee4 | ||
|
|
0344418aae | ||
|
|
520a860414 | ||
|
|
5813aeb6e9 | ||
|
|
840bc96cc1 | ||
|
|
72e1e59d8e | ||
|
|
b591bae273 | ||
|
|
a712002fec | ||
|
|
f76dc05f46 | ||
|
|
16fca6c4f1 | ||
|
|
c768f7c46b | ||
|
|
24825ff396 | ||
|
|
0ceba9c778 | ||
|
|
55b9bfc521 |
Binary file not shown.
Binary file not shown.
@@ -292,3 +292,363 @@ At the time this doc was written:
|
||||
- non-playable mechs are explicitly marked `No`
|
||||
- Templar and other mechs with rear or side mounts have facing visible in the CSV
|
||||
- the file is intended to be a living audit artifact for future data cleanup and enablement work
|
||||
|
||||
---
|
||||
|
||||
## MechEditor Web App — Data Sources, Fields, and Conversions (documented 2026-07-23)
|
||||
|
||||
The MechEditor is a single-file Python HTTP server at `/home/rich/Repositories/MechEditor/mech_editor.py`.
|
||||
It runs at `localhost:8765`, parses the firestorm content tree, and presents a full mech configuration editor in the browser.
|
||||
This section documents every data field it reads, every conversion it performs, and every naming rule it enforces.
|
||||
|
||||
---
|
||||
|
||||
### Data Files Parsed Per Mech
|
||||
|
||||
All files live under `Gameleap/mw4/Content/Mechs/<MechDir>/`.
|
||||
|
||||
#### `.data` file (`parse_data()`)
|
||||
|
||||
| Field in file | Editor key | Notes |
|
||||
|---|---|---|
|
||||
| `VehicleTonnage` | `tonnage` | chassis base tonnage (float) |
|
||||
| `MaxVehicleTonnage` | `max_tonnage` | max loadout tonnage (float) |
|
||||
| `TechType` | `tech` | `$(Tech_IS)` ? `"IS"`, `$(Tech_Clan)` ? `"Clan"` |
|
||||
| `MaxHeat` | `max_heat` | heat capacity (int) |
|
||||
| `VehicleTradeValue` | `trade_value` | C-bills |
|
||||
| `DragoonValue` | `dragoon` | used in Power Rating bar scaling |
|
||||
| `MinMaxSpeed` | `min_max_speed` | base speed ceiling in **m/s** |
|
||||
| `MaxSpeed` | `max_speed` | absolute speed ceiling in **m/s** (engine upgrades may not exceed this) |
|
||||
| `FullStopTurnRate` | `full_stop_turn` | turn rate at zero speed, in **degrees/sec** |
|
||||
| `TopSpeedTurnRate` | `top_speed_turn` | turn rate at top speed, in **degrees/sec** |
|
||||
| `Acceleration` | `acceleration` | forward acceleration in **m/s²** |
|
||||
| `Decceleration` | `decceleration` | forward braking in **m/s²** — **double-c spelling is canonical in the engine source** |
|
||||
| `ReverseAccelerationMultiplier` | `rev_accel_mult` | multiplier applied to Acceleration for reverse |
|
||||
| `ReverseDeccelerationMultiplier` | `rev_decel_mult` | multiplier applied to Decceleration for reverse — double-c canonical |
|
||||
| `MinStandTransitionSpeed` | not surfaced | animation threshold only — see note below |
|
||||
| `CanLoadJumpJets` | `can_jj` | Yes/No |
|
||||
| `CanLoadECM` | `can_ecm` | Yes/No |
|
||||
| `CanLoadBeagle` | `can_bap` | Yes/No |
|
||||
| `CanLoadLightAmp` | `can_lightamp` | Yes/No |
|
||||
| `CanLoadAMS` | `can_ams` | Yes/No |
|
||||
| `CanLoadLAMS` | `can_lams` | Yes/No |
|
||||
| `CanLoadIFF_Jammer` | `can_iff` | Yes/No |
|
||||
|
||||
**MinStandTransitionSpeed** is the speed (m/s) below which the mech switches from its walking animation to its idle/standing animation.
|
||||
It is NOT a hard movement limit. It is purely an animation state machine threshold in `Mech.cpp`.
|
||||
Code path: `animStateEngine?RequestState(StandState)` when `currentSpeedMPS <= minStandTransitionSpeed`.
|
||||
Must be > 0 (validated in `Vehicle_Tool.cpp`). Argus = 12.631 m/s = 45.5 kph.
|
||||
|
||||
#### `.instance` file (`parse_instance()`)
|
||||
|
||||
| Field | Editor key | Notes |
|
||||
|---|---|---|
|
||||
| `PowerRating` | `PowerRating` | mechlab bar value, 0–100 |
|
||||
| `ArmorRating` | `ArmorRating` | mechlab bar value, 0–100 |
|
||||
| `SpeedRating` | `SpeedRating` | mechlab bar value, 0–100 |
|
||||
| `HeatRating` | `HeatRating` | mechlab bar value, 0–100 |
|
||||
| `DoesHaveLightAmp` | `has_lightamp` | 0 or 1, default 1 — whether LightAmp is currently installed |
|
||||
|
||||
#### `.subsystems` file (`parse_subsystems()`)
|
||||
|
||||
Provides: armor type + per-zone multipliers, installed heatsinks, jump jets, engine upgrades, weapons, electronics.
|
||||
|
||||
**Armor block:**
|
||||
- `ArmorType=` ? armor type string (`Standard`, `FerroFiberus`, `Reactive`, `Reflective`, `Solarian`)
|
||||
- Per-zone entries: `LeftArm=1.0`, `RightTorso=2.5`, etc. — multiplier for that zone
|
||||
|
||||
**Engine:**
|
||||
- `EngineUpgrade` blocks counted ? `engine_upgrades` (0–5)
|
||||
|
||||
**Weapons** — each weapon block contains:
|
||||
- `Model=` ? weapon subsystem resource path (name extracted)
|
||||
- `InternalLocation=` ? zone name
|
||||
- `Site=` ? mount port name (from armature)
|
||||
- `GroupIndex=` ? weapon group number
|
||||
- `WeaponFacing=` ? 0=Front, 1=Rear, 2=Side (absent = Front)
|
||||
- `AmmoCount=` ? rounds for ammo-using weapons
|
||||
- `EjectSite=` ? optional ejection site for ammo
|
||||
|
||||
**Electronics:** ECM, Beagle (BAP), AMS, LAMS, IFF_Jammer detected by subsystem model path.
|
||||
|
||||
#### `.damage` file (`parse_damage()`)
|
||||
|
||||
Per zone section `[ZoneInternal]`:
|
||||
- `BaseArmorValue` ? starting armor (float)
|
||||
- `MaxArmorValue` ? hard cap on armor pts for that zone
|
||||
- `InternalHPValue` ? internal structure HP
|
||||
- `OmniSlots`, `BeamSlots`, `MissileSlots`, `ProjectileSlots` ? weapon slot counts
|
||||
|
||||
Special zones:
|
||||
- `SpecialAttachedToZone=` ? which body section this special zone is attached to
|
||||
- `DamagePropagationZone=` ? where overflow damage propagates
|
||||
|
||||
#### `.engine` file (`parse_engine()`)
|
||||
|
||||
| Field | Editor key | Notes |
|
||||
|---|---|---|
|
||||
| `NumHeatSinks` | `NumHeatSinks` | free heatsinks from engine (not in subsystems) |
|
||||
| `TonsPerUpgrade` | `TonsPerUpgrade` | tonnage cost per engine upgrade tier |
|
||||
| `MPSPerUpgrade` | `MPSPerUpgrade` | m/s speed gain per upgrade tier |
|
||||
|
||||
#### `.torso` file (`parse_torso()`)
|
||||
|
||||
| Field | Notes |
|
||||
|---|---|
|
||||
| `TwistSpeed` | torso horizontal rotation speed — may be a macro reference |
|
||||
| `PitchSpeed` | torso vertical rotation speed — may be a macro reference |
|
||||
| `TwistRadius` | max horizontal twist angle — may be a macro reference |
|
||||
| `PitchRadius` | max vertical pitch angle — may be a macro reference |
|
||||
| `ArmRatioAngle` | ratio of arm tracking vs torso rotation — may be a macro reference |
|
||||
|
||||
All torso fields may reference macros from `Content/Defines/MechTorso.defines`.
|
||||
The editor resolves them using a preloaded `TORSO_DEFINES` dict. Notable values:
|
||||
|
||||
```
|
||||
NORMAL_RATIO = 40
|
||||
SNAIL_TSPEED = 40
|
||||
NORMAL_TSPEED = 60
|
||||
FAST_TSPEED = 80
|
||||
WIDE_TRADIUS = 160
|
||||
NORMAL_PRADIUS = 40
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Calculated Ratings and Conversions
|
||||
|
||||
#### Speed (kph)
|
||||
|
||||
```
|
||||
top_speed_kph = min(MinMaxSpeed + MPSPerUpgrade × engine_upgrades, MaxSpeed) × 3.6
|
||||
```
|
||||
|
||||
- `MinMaxSpeed` and `MaxSpeed` from `.data` (m/s)
|
||||
- `MPSPerUpgrade` from `.engine` (m/s per tier)
|
||||
- `engine_upgrades` from `.subsystems` (0–5)
|
||||
- Multiply by 3.6 to convert m/s ? kph
|
||||
- Argus example: (20.28 + 1.11 × 10) × 3.6 = 113.5 kph
|
||||
|
||||
#### Speed Rating (bar)
|
||||
|
||||
```
|
||||
speed_rating = (top_speed_mps / MaxSpeed) × 100 [capped at 100]
|
||||
```
|
||||
|
||||
#### Turn Rate — degrees to radians
|
||||
|
||||
The `.data` file stores turn rates in **degrees/sec**. The mechlab UI label was changed to show rad/sec:
|
||||
- `StringResource.rc`: `IDS_ML_CH_TURNRATE` ? `"Turn Rate (Top Speed Rad/Sec):"`
|
||||
- Conversion: `radians = degrees × ?/180` where `?/180 ? 0.017453`
|
||||
- Argus: FullStopTurn = 75° = **1.309 rad/sec**, TopSpeedTurn = 45° = **0.785 rad/sec**
|
||||
|
||||
#### Acceleration / Deceleration (m/s²)
|
||||
|
||||
Stored directly in `.data`. Reverse values are derived:
|
||||
```
|
||||
reverse_accel = Acceleration × ReverseAccelerationMultiplier
|
||||
reverse_decel = Decceleration × ReverseDeccelerationMultiplier
|
||||
```
|
||||
|
||||
**The double-c spelling (`Decceleration`, `ReverseDeccelerationMultiplier`) is canonical — it matches the engine source. Do not "fix" the spelling.**
|
||||
|
||||
#### Heat Rating (bar)
|
||||
|
||||
```
|
||||
total_hs = NumHeatSinks (engine) + installed_heatsinks (subsystems)
|
||||
effective_hs = total_hs × (2 if Double else 1)
|
||||
heat_rating = (effective_hs / MaxHeat) × 100 [capped at 100]
|
||||
```
|
||||
|
||||
#### Power Rating (bar)
|
||||
|
||||
```
|
||||
total_damage = ? (DamageAmount × NumFire) for each installed weapon
|
||||
power_rating = (total_damage / 80) × 100 [capped at 100]
|
||||
```
|
||||
|
||||
- `DamageAmount` and `NumFire` come from `WeaponSubsystems/<weapon>.data` following `!include` chains
|
||||
- Parsed by `load_weapon_damages()` at server startup, cached in `Handler.weapon_damages`
|
||||
- Argus example with default load: ~36.2 total damage ? 45 rating (stored = 42)
|
||||
|
||||
#### Armor Rating (bar)
|
||||
|
||||
```
|
||||
for each zone:
|
||||
pts = multiplier × ARMOR_PTS_PER_TON[armor_type]
|
||||
effective = min(pts, MaxArmorValue[zone])
|
||||
armor_rating = (? effective / ? MaxArmorValue) × 100
|
||||
```
|
||||
|
||||
Armor pts per ton by type (from `Adept/ResourceImagePool.cpp` and game design):
|
||||
|
||||
| Type | Pts/ton |
|
||||
|---|---|
|
||||
| Standard | 32 |
|
||||
| FerroFiberus | 38 |
|
||||
| Reactive | 30 |
|
||||
| Reflective | 30 |
|
||||
| Solarian | 60 |
|
||||
|
||||
Note: `FerroFiberus` is the canonical internal token (not player-visible). The player sees `DNL_FERROFIB = "Ferro Fibrous"` via string lookup.
|
||||
|
||||
---
|
||||
|
||||
### Active-in-Game Detection
|
||||
|
||||
Source: `Gameleap/mw4/Content/Tables/MechChassisTable.tbl`
|
||||
|
||||
Format:
|
||||
```
|
||||
DisplayKey=Mechs\DirName\FileName.data
|
||||
//CommentedKey=Mechs\DirName\FileName.data <- inactive
|
||||
```
|
||||
|
||||
- Active = entry exists AND is not prefixed with `//`
|
||||
- Currently the only inactive mech: **Dasher** (commented out)
|
||||
- The editor shows a green **ACTIVE IN GAME** or red **NOT IN GAME** banner at top of Stats tab
|
||||
|
||||
---
|
||||
|
||||
### hsh/ Image Naming Conventions
|
||||
|
||||
The `hsh/` directory under `Gameleap/mw4/` holds loose BMP files loaded at runtime (not packed into `.mw4`).
|
||||
There are four relevant subdirectories, each with a different naming authority.
|
||||
|
||||
#### `hsh/hud/` — in-game HUD damage silhouette (own mech)
|
||||
#### `hsh/MFD/` — MFD target display silhouette (target mech)
|
||||
#### `hsh/radar/hud/` — radar damage overlay
|
||||
|
||||
**All three use identical stems** sourced from `huddamage.cpp` `texturename[]` array.
|
||||
|
||||
Load path:
|
||||
- hud/MFD: `hsh\<texturename>.bmp` where texturename = `hud\<stem>` ? file = `hsh/hud/<stem>.bmp`
|
||||
- radar: `hsh\radar\<texturename>.bmp` ? file = `hsh/radar/hud/<stem>.bmp`
|
||||
|
||||
Code: `render.cpp` `CRadar_Device::LoadRadarDamageTexture()` and `huddamage.cpp` `HUDDamage`.
|
||||
|
||||
#### `hsh/Mechs/` — mw4print scorecard portrait
|
||||
|
||||
Load path: `recscore.cpp` ? `GetLocString(model->m_nameIndex)` ? `DNL_*` string from `StringResource.rc` ? lowercased filename.
|
||||
Different naming authority from the other three.
|
||||
|
||||
---
|
||||
|
||||
### Complete Canonical Name Table
|
||||
|
||||
Key: mech directory name (case-insensitive) ? canonical stem for `hsh/hud/`, `hsh/MFD/`, `hsh/radar/hud/`.
|
||||
Entries in **bold** differ from the directory name.
|
||||
|
||||
| Directory | hud/MFD/radar stem | hsh/Mechs/ portrait filename |
|
||||
|---|---|---|
|
||||
| Annihilator | annihilator | annihilator.bmp |
|
||||
| Archer | archer | archer.bmp |
|
||||
| ArcticWolf | arcticwolf | arctic wolf.bmp |
|
||||
| Ares | ares | ares.bmp |
|
||||
| Argus | argus | argus.bmp |
|
||||
| Assassin2 | assassin2 | **assassin ii.bmp** |
|
||||
| Atlas | atlas | atlas.bmp |
|
||||
| Avatar | avatar | avatar.bmp |
|
||||
| Awesome | awesome | awesome.bmp |
|
||||
| Battlemaster | battlemaster | battlemaster.bmp |
|
||||
| Battlemaster2c | **battlemasteriic** | **battlemaster iic.bmp** |
|
||||
| Behemoth | behemoth | behemoth.bmp |
|
||||
| Behemoth2 | **behemothii** | **behemoth ii.bmp** |
|
||||
| Blackhawk | blackhawk | black hawk.bmp |
|
||||
| Blacknight | **blackknight** | black knight.bmp |
|
||||
| Blacklanner | blacklanner | black lanner.bmp |
|
||||
| Brigand | brigand | brigand.bmp |
|
||||
| Bushwacker | bushwacker | bushwacker.bmp |
|
||||
| Catapult | catapult | catapult.bmp |
|
||||
| CauldronBorn | cauldronborn | **cauldronborn.bmp** (table key has hyphen; DNL does not) |
|
||||
| Chimera | chimera | chimera.bmp |
|
||||
| Commando | commando | commando.bmp |
|
||||
| Cougar | cougar | cougar.bmp |
|
||||
| Cyclops | cyclops | cyclops.bmp |
|
||||
| Daishi | daishi | daishi.bmp |
|
||||
| Deimos | deimos | deimos.bmp |
|
||||
| Dragon | dragon | dragon.bmp |
|
||||
| Fafnir | fafnir | fafnir.bmp |
|
||||
| Flea | flea | flea.bmp |
|
||||
| Gladiator | gladiator | gladiator.bmp |
|
||||
| Grizzly | grizzly | grizzly.bmp |
|
||||
| Hauptmann | hauptmann | hauptmann.bmp |
|
||||
| Hellhound | hellhound | hellhound.bmp |
|
||||
| Hellspawn | hellspawn | hellspawn.bmp |
|
||||
| Highlander | highlander | highlander.bmp |
|
||||
| Hollander | **hollanderii** | **hollander ii.bmp** |
|
||||
| Hunchback | hunchback | hunchback.bmp |
|
||||
| Kodiak | kodiak | kodiak.bmp |
|
||||
| Loki | loki | loki.bmp |
|
||||
| Longbow | longbow | longbow.bmp |
|
||||
| Madcat | madcat | mad cat.bmp |
|
||||
| Madcat_MKII | **madcat2** | mad cat mkii.bmp |
|
||||
| Masakari | masakari | masakari.bmp |
|
||||
| Mauler | mauler | mauler.bmp |
|
||||
| Novacat | novacat | nova cat.bmp |
|
||||
| Osiris | osiris | osiris.bmp |
|
||||
| Owens | owens | owens.bmp |
|
||||
| Puma | puma | puma.bmp |
|
||||
| Raven | raven | raven.bmp |
|
||||
| Rifleman | rifleman | rifleman.bmp |
|
||||
| Ryoken | ryoken | ryoken.bmp |
|
||||
| Shadowcat | shadowcat | shadow cat.bmp |
|
||||
| Solitaire | solitaire | solitaire.bmp |
|
||||
| Sunder | sunder | sunder.bmp |
|
||||
| Templar | templar | templar.bmp |
|
||||
| Thanatos | thanatos | thanatos.bmp |
|
||||
| Thor | thor | thor.bmp |
|
||||
| Uller | uller | uller.bmp |
|
||||
| Urbanmech | urbanmech | urbanmech.bmp |
|
||||
| Uziel | uziel | uziel.bmp |
|
||||
| Victor | victor | victor.bmp |
|
||||
| Vulture | vulture | vulture.bmp |
|
||||
| Warhammer | warhammer | warhammer.bmp |
|
||||
| Wolfhound | wolfhound | wolfhound.bmp |
|
||||
| Zeus | zeus | zeus.bmp |
|
||||
|
||||
**Critical mismatches where directory name ? hud/MFD stem (files must use the stem, not the dir name):**
|
||||
|
||||
| Directory | Wrong name (dir-based) | Correct name (stem) |
|
||||
|---|---|---|
|
||||
| Battlemaster2c | battlemaster2c.bmp | **battlemasteriic.bmp** |
|
||||
| Behemoth2 | behemoth2.bmp | **behemothii.bmp** |
|
||||
| Blacknight | blacknight.bmp | **blackknight.bmp** |
|
||||
| Hollander | hollander.bmp | **hollanderii.bmp** |
|
||||
| Madcat_MKII | madcat_mkii.bmp | **madcat2.bmp** |
|
||||
|
||||
**Portrait mismatches for hsh/Mechs/ (table key ? DNL string):**
|
||||
|
||||
The `MechChassisTable.tbl` display key and `GetLocString()` DNL string differ for these mechs.
|
||||
mw4print uses the DNL string. The table key is NOT the correct portrait filename for these 5 mechs.
|
||||
|
||||
| Directory | Table key (wrong for mw4print) | DNL string (correct portrait stem) |
|
||||
|---|---|---|
|
||||
| Assassin2 | AssassinII ? assassinii | `DNL_ASSASSIN2 "Assassin II"` ? **assassin ii.bmp** |
|
||||
| Battlemaster2c | BattlemasterIIC ? battlemasteriic | `DNL_BATTLEMASTERIIC "Battlemaster IIc"` ? **battlemaster iic.bmp** |
|
||||
| Behemoth2 | BehemothII ? behemothii | `DNL_BEHEMOTHII "Behemoth II"` ? **behemoth ii.bmp** |
|
||||
| CauldronBorn | Cauldron-Born ? cauldron-born | `DNL_CAULDRONBORN "Cauldronborn"` ? **cauldronborn.bmp** |
|
||||
| Hollander | HollanderII ? hollanderii | `DNL_HOLLANDERII "Hollander II"` ? **hollander ii.bmp** |
|
||||
|
||||
---
|
||||
|
||||
### MechEditor Implementation Notes
|
||||
|
||||
The editor encodes all of the above knowledge in two Python dicts:
|
||||
|
||||
**`MECH_HSH_STEMS`** (in `mech_editor.py`)
|
||||
Maps lowercase dir name ? canonical stem for `hsh/hud/`, `hsh/MFD/`, `hsh/radar/hud/`.
|
||||
Source: `huddamage.cpp` `texturename[]` array.
|
||||
|
||||
**`MECH_PORTRAIT_OVERRIDES`** (in `mech_editor.py`)
|
||||
Maps lowercase dir name ? portrait stem for `hsh/Mechs/` where the DNL string differs from the chassis table key.
|
||||
Source: `DNL_*` entries in `Gameleap/code/mw4/Code/scriptstrings/StringResource.rc`.
|
||||
|
||||
For all other mechs, the portrait stem is derived dynamically from `MechChassisTable.tbl` (display key, lowercased).
|
||||
|
||||
The Assets tab in the editor shows all four image types. When an image is missing, it displays:
|
||||
```
|
||||
Wants: hsh/<subdir>/<expected_filename>.bmp
|
||||
```
|
||||
so the user knows exactly what to rename or create.
|
||||
|
||||
|
||||
@@ -795,6 +795,118 @@ keeping old-RIO (type 0) protocol behavior byte-identical:
|
||||
alongside `mw4print.exe`.
|
||||
- Version bumped to **2.0**, copyright year updated to **2026**.
|
||||
|
||||
## 📋 MFD mode 4: right device stagger fix (2026-07-18, eaa5fd3)
|
||||
Root cause: `CMFD_Device::BeginScene()` cleared BOTH MFD device back-buffers at `sh_step==0`.
|
||||
But in mode 4 the right MFD flip also fires at `sh_step==1` (= old `sh_step==0` after the
|
||||
stagger increment), so it presented a just-cleared buffer — only the grid, no channel data.
|
||||
|
||||
Fix: `BeginScene()` now only clears/grids the LEFT device at `sh_step==0`. New `BeginSceneRight()`
|
||||
(added to `render.cpp` / `render.hpp`, called from `WinMain.cpp`) clears/grids the RIGHT device at
|
||||
`sh_step==1` — one frame AFTER the right flip — so channels 3–4 render into a fresh buffer before
|
||||
the next flip. Mode 1 is unchanged.
|
||||
|
||||
Mode 4 cycle (with stagger):
|
||||
- `sh_step 0`: radar + left `BeginScene` (clear + grid); no flip
|
||||
- `sh_step 1`: flip right MFD (shows channels 3–4 from previous cycle) + right `BeginScene` (clear + grid)
|
||||
- `sh_step 2–4`: channels 0–2 → left device
|
||||
- `sh_step 5–6`: channels 3–4 → right device
|
||||
- `sh_step 0` (next): flip radar + left MFD (shows channels 0–2 from previous cycle)
|
||||
|
||||
Files: `CoreTech/Libraries/GameOS/WinMain.cpp`, `render.cpp`, `render.hpp`.
|
||||
|
||||
## 📋 Linux→Windows development workflow (2026-07-19, 55b9bfc5)
|
||||
`build-env/sync-to-windows.sh` — rsync script that pushes all source, content, toolchain, and
|
||||
assets to the Windows build machine at `/vwe/firestorm`. Excludes generated build outputs
|
||||
(`rel.bin/`, `dbg.bin/`, `*.mw4`, `*.dep`), `.git`/LFS objects, `_UNUSED/`, and the game deploy
|
||||
dir (`MW4/`). Run from Linux before triggering a Windows build.
|
||||
|
||||
## 📋 ddraw.dll removed from repo; build script moves it aside (2026-07-19, 0ceba9c7, 24825ff3)
|
||||
`Gameleap/mw4/ddraw.dll` (DDrawCompat) removed from git (was LFS-tracked); now lives as
|
||||
`ddraw.dll.old` in the same dir for reference. `deploy-editor.ps1` installs DDrawCompat as
|
||||
`ddraw.dll` at deploy time (the editor needs it for its windowed D3D7 viewport).
|
||||
`build-resources.ps1` moves `ddraw.dll` aside (`.buildaside`) before running `MW4pro.exe`
|
||||
because **DDrawCompat is fatal to MW4pro.exe in BOTH windowed and fullscreen modes**, then
|
||||
restores it in `finally`. The same block also defensively covers dgVoodoo2 interceptors
|
||||
(`D3D8/D3D9/D3DImm.dll`) in case they reappear.
|
||||
|
||||
## 📋 Branch `5.1.0b-in-progress`: multiplayer + RIO + source cleanup (2026-07-19)
|
||||
|
||||
### ConLobby V5.1.0b1 — Super6 mech rotation (c768f7c4)
|
||||
Changes from Buddy 'Highlight' Taylor (MCHL), merged manually:
|
||||
- Console version string bumped to **V5.1.0b1**.
|
||||
- `ROOKIEMECH` defines expanded from 4 → **6 mechs**: added Archer (ID=1) and Warhammer (ID=62).
|
||||
- 16-slot default assignments cycle through all 6 Super6 mechs.
|
||||
- Right-click randomizer expanded from `random(0,3)` → `random(0,5)`.
|
||||
|
||||
### CRIOMAIN.CPP — Korean translation + RIO poll timeout scaling (16fca6c4, a712002f)
|
||||
- Translated all EUC-KR/CP949 Korean developer comments (~35 lines) to English. File re-saved
|
||||
as clean UTF-8. CRLF line endings preserved (`* -text` in `.gitattributes`).
|
||||
⚠️ **Encoding hazard:** always read/write CRIOMAIN.CPP as binary (or with an explicit encoding
|
||||
codec). Python text-mode `readlines()` silently strips `\r`, causing a 3000+-line git diff when
|
||||
every line's `\r\n` becomes `\n`. If that happens, restore CRLF with `re.sub(b'(?<!\r)\n', b'\r\n', data)` in binary mode, then amend the commit.
|
||||
- Added **`g_dwRIOPollTimeout`** global (default 50 ms). Computed in `SetupConnection` before the
|
||||
receive loop using: `clamp(⌈480000/baud⌉, 5, 50)`. Preserves 50 ms at 9600 baud; floors at
|
||||
5 ms for 115200 baud. Implemented with explicit ternary — **`min`/`max` are undeclared in this
|
||||
translation unit under VC6** (not pulled in by CRIOMAIN's includes); use ternary or `__min`/`__max`.
|
||||
|
||||
### 16 pilots + 1 cameraship in multiplayer (f76dc05f)
|
||||
`MW4Shell.cpp`:
|
||||
- `CTCL_DefaultHostSetup` (non-coop): `Environment.NetworkMaxPlayers` set to
|
||||
`params->m_maxPlayers + (CTCL_GetTeslaCountAll() - CTCL_GetTeslaCount())`.
|
||||
The delta = camera-only seats (Tesla seats not assigned to pilots), reserving one extra
|
||||
DirectPlay slot per cameraship so the 17th connection isn't rejected.
|
||||
- `SetNetworkMissionParamater / PLAYER_LIMIT_PARAMETER`: same formula applied at runtime when
|
||||
host changes the player limit. `gos_NetServerCommands(gos_Commend_UpdateMaxPlayers)` still called;
|
||||
`break` must be present in this case (was accidentally dropped once — fall-through to
|
||||
`JOIN_IN_PROGRESS_PARAMETER` corrupts `m_joinInProgress`).
|
||||
- COOP branch unchanged (capped at 9+bots; no camera seat needed there).
|
||||
|
||||
`ConLobby.script`: launch guard `nTempPlayerCount > 16` raised to `> 17` so the cameraship
|
||||
connection doesn't trigger "Too many player/bots".
|
||||
|
||||
### hsh/ BMP canonical renames (5813aeb6, 2026-07-23)
|
||||
All `hsh/MFD/*.bmp` and `hsh/Mechs/*.bmp` filenames reconciled against the canonical stems
|
||||
expected by game code. The engine loads MFD images via `huddamage.cpp` `texturename[]` array
|
||||
(lowercase, no spaces) and Mechs portraits via `GetLocString` DNL strings (mixed-case with
|
||||
spaces). Any mismatch = silently missing image at runtime.
|
||||
Key renames:
|
||||
- `hsh/MFD/assassinii.bmp` → `assassin2.bmp` (matches `texturename[]` canonical)
|
||||
- `hsh/Mechs/battlemasteriic.bmp` → `battlemaster iic.bmp`
|
||||
- `hsh/Mechs/mad cat mk.ii.bmp` → `mad cat mkii.bmp`
|
||||
- `hsh/Mechs/behemoth ii.bmp` added (was absent)
|
||||
Most other files in both directories are LFS pointer updates only (content unchanged).
|
||||
|
||||
### RookieMission configurable defaults via options.ini (5813aeb6, 2026-07-23)
|
||||
CTCL (console) arcade mode has a "Rookie Mission" quick-launch that previously hardcoded all
|
||||
game params. Now all 13 params are overridable from an `[RookieMission]` section in
|
||||
`options.ini` (read by `CTCL_SetCDSP` at startup):
|
||||
- `MW4Shell.cpp`: added 14 `g_` globals (`g_szRookieMission`, `g_nRookieGameType`, and 12
|
||||
numeric params); registered as `gosScript_RegisterVariable` in `StartUp`/`ShutDown`;
|
||||
`CTCL_SetCDSP` reads the `[RookieMission]` page via `NotationFile` and populates them.
|
||||
Defaults: `"ScarabStronghold - Attrition"`, GameType=2 (Attrition), UnlimitedAmmo=1, all
|
||||
others zero. `g_nRookieTimeLimit=-1` means "use the server's current time setting".
|
||||
- `ConLobbyMission.script`: all hardcoded values in `MAIL_SET_ROOKIE_MISSION` handler replaced
|
||||
with `$$g_szRookieMission$$` / `$$g_nRookieXxx$$` references.
|
||||
- Requires rebuild: `MW4.exe` (Release + Profile).
|
||||
|
||||
### Mechlab turn rate label (5813aeb6, 2026-07-23)
|
||||
`StringResource.rc` `IDS_ML_CH_TURNRATE`: "Turn Rate (Degrees/Sec.):" →
|
||||
"Turn Rate (Top Speed Rad/Sec):" to match the actual `.data` field semantics
|
||||
(`TopSpeedTurnRate` is in rad/s at top speed, not deg/s).
|
||||
Requires rebuild: `ScriptStrings.dll`.
|
||||
|
||||
### BTFrstrm design documentation (840bc96c, 2026-07-23)
|
||||
Two Word documents added to `BTFrstrm/`:
|
||||
- `MechDependencyTree.docx` — dependency relationships between mech chassis/variants.
|
||||
- `Special_Zones.docx` — documentation of special zone types used in maps/missions.
|
||||
|
||||
### mech_loadouts.md: MechEditor data model (0344418a, 2026-07-23)
|
||||
`BTFrstrm/mech_loadouts.md` extended with a full reference section documenting the
|
||||
MechEditor web app (`/home/rich/Repositories/MechEditor/mech_editor.py`, localhost:8765):
|
||||
every `.data`/`.instance`/`.subsystems` field parsed, conversions performed (m/s ↔ kph,
|
||||
rad/s ↔ deg/s), and `hsh/` naming rules for MFD/Mechs/HUD/Radar images. Canonical
|
||||
reference for future mech data work.
|
||||
|
||||
## Next steps (proposed)
|
||||
- [x] ~~Windowed 3D viewport on Win11~~ — DONE via DDrawCompat (see STEP 8 viewport section).
|
||||
- [ ] (Optional) Curate remaining WIP content as features are exercised (editor loads dev `Content\`).
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "recscore.h"
|
||||
#endif // !defined(CTCLS_EXPORTS) && !defined(CTCL_LAUNCHER)
|
||||
|
||||
#define MAX_TESLAS 31
|
||||
#define MAX_TESLAS 16
|
||||
#define MAX_CAMERAS 4
|
||||
|
||||
#define PORT_Launcher 1000
|
||||
@@ -260,7 +260,7 @@ CInviteCOOP g_InviteCOOP;
|
||||
// Mech4 only
|
||||
int g_nMech4Comm = 0;
|
||||
BOOL g_bIsServer = FALSE;
|
||||
SPlayerInfo g_aPlayerInfos[35]; // 31 pilots + 1 CS + 3 spare
|
||||
SPlayerInfo g_aPlayerInfos[20];
|
||||
int g_nPlayerInfos;
|
||||
int g_nServer;
|
||||
int g_nTeslas;
|
||||
|
||||
@@ -43,7 +43,7 @@ LONG g_LeftPedalLast = 0;
|
||||
LONG g_RightPedalLast = 0;
|
||||
BOOL g_StartGame = FALSE;
|
||||
|
||||
static int g_nOpenComState = 0; // 鉉
|
||||
static int g_nOpenComState = 0; // hyun
|
||||
|
||||
DWORD g_dwLastAnalogUpdate = 0;
|
||||
|
||||
@@ -54,7 +54,7 @@ DWORD g_dwLastAnalogUpdate = 0;
|
||||
#define RESTART_CHAR 0xFE
|
||||
#define IDLE_CHAR 0xFF
|
||||
|
||||
//member 변수처럼 활용할것.
|
||||
//Use it like a member variable.
|
||||
static HANDLE g_hCom = INVALID_HANDLE_VALUE;
|
||||
static OVERLAPPED wos;
|
||||
static OVERLAPPED ros;
|
||||
@@ -108,6 +108,7 @@ int g_nRIOPacketCountB = (sizeof(g_baRIOLengthsB) / sizeof(g_baRIOLengthsB[0]));
|
||||
|
||||
int g_nRIOType = 0; // 0: old(original) type, 1: new type
|
||||
DWORD g_dwRIOBaud = 0; // [tbaud] 0: default by RIO type; else COM1 baud forced by -tbaud (high-speed replica of the original RIO board, protocol unchanged)
|
||||
DWORD g_dwRIOPollTimeout = 50; // [tbaud] WaitForMultipleObjects timeout (ms); computed from baud rate before the receive loop starts
|
||||
int g_nEjectButton = 61; // 61: original, 31: new type
|
||||
BYTE* g_pbRIOLengths = NULL;
|
||||
int g_nRIOPacketCount = 0;
|
||||
@@ -318,7 +319,7 @@ void RequestVersion();
|
||||
void RequestAnalogUpdate(BYTE bFreq = 3);
|
||||
|
||||
// start - for new RIO Board only...
|
||||
//received packet은 각각 다른 스레드에서 처리하므로.. ciritical section이 필요하다..
|
||||
//Received packets are handled in different threads.. a critical section is needed..
|
||||
BYTE received_buffer[128][16];
|
||||
int received_packet=0;//packets count in the received_buffer.
|
||||
DWORD received_serial=0;
|
||||
@@ -569,7 +570,7 @@ BOOL SetupConnection(HANDLE hCom)
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
원래 처리 루틴..
|
||||
Original processing routine..
|
||||
NPTTYINFO npTTYInfo=0 ;
|
||||
BYTE bset1 = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_DTRDSR) != 0) ;
|
||||
BYTE bset2 = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_RTSCTS) != 0) ;
|
||||
@@ -603,7 +604,7 @@ BOOL SetupConnection(HANDLE hCom)
|
||||
|
||||
|
||||
|
||||
//처리되지 않는 항목들.. GetCommState의 기본값으로 처리한다.
|
||||
//Unhandled items.. handled using GetCommState default values.
|
||||
DWORD fDsrSensitivity:1; // DSR sensitivity
|
||||
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
|
||||
DWORD fErrorChar: 1; // enable error replacement
|
||||
@@ -647,7 +648,7 @@ HANDLE OpenConnection(int port)
|
||||
g_hLampEvent = CreateEvent(0,FALSE,0,0);
|
||||
g_hCommWatchThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)CommWatchProc, NULL, CREATE_SUSPENDED, &g_dwThreadID);
|
||||
if (g_hCommWatchThread) {
|
||||
//Thread까지 정상적으로 생성되었다.
|
||||
//Thread was created successfully.
|
||||
//////////////////////////////////////////////
|
||||
//All OK
|
||||
//Exit Point <======
|
||||
@@ -744,11 +745,11 @@ retry:
|
||||
for(int i=0;i<(int)dwLength;i++){
|
||||
int ch=(BYTE)lpszBlock[i];
|
||||
|
||||
//받은 문자만큼 루프를 돈다.
|
||||
//현재.. 받고 있는 packet이 없고.. 어떤 control문자라도 올 수 있는 상태이다.
|
||||
//Loop for the number of received characters.
|
||||
//Currently.. no packet is being received.. can receive any control character.
|
||||
|
||||
if(packetbyteremain!=0){
|
||||
//패킷에 해당하는 문자가 도착했다.. 나머지 문자들을 받는다.
|
||||
//Character corresponding to a packet has arrived.. receive the remaining characters.
|
||||
if (ch & 0x80) {
|
||||
packetbyteremain=0;
|
||||
chinpacket=0;
|
||||
@@ -758,7 +759,7 @@ retry:
|
||||
packetbytes[chinpacket] = ch;
|
||||
chinpacket++;
|
||||
if (packetbyteremain == 0) {
|
||||
//하나의 패킷이 완성되었다. 도착했다.. 즉시 반응한다.
|
||||
//A packet has been completed and arrived.. respond immediately.
|
||||
chinpacket--; // exclude check byte
|
||||
int packettype=packetbytes[0];
|
||||
BYTE bCheckByte = 0;
|
||||
@@ -837,21 +838,21 @@ retry:
|
||||
packettype++;
|
||||
packettype--;
|
||||
#endif // _DEBUG
|
||||
case rio_Ack2://◆◆◆◆◆◆◆◆◆◆
|
||||
case rio_Ack2:
|
||||
if (g_nRIOType != 0) {
|
||||
BYTE id=packetbytes[1];
|
||||
int popped_index=PopPacket(id);
|
||||
ack_timeout=GetTickCount()+30;
|
||||
if(popped_index==0){
|
||||
//맨처음것... 정상적인 경우이다.
|
||||
//This is the very first one... Normal case.
|
||||
}else if(popped_index>0){
|
||||
//맨처음것이 아닌것.
|
||||
//이전것들이 정상적으로 보내지지 않았으므로 다시 보낸다...
|
||||
ReSendPackets(popped_index);//잘못된 개수 만큼..
|
||||
//Not the very first one.
|
||||
//Previous ones were not sent successfully, resend...
|
||||
ReSendPackets(popped_index);//By the number of incorrect ones..
|
||||
}else{
|
||||
//실패 했다는것은.. 없는 id가 왔다는 것인데..
|
||||
//명백한 에러.. 그러나 특별히 대처할 방법은 없다.
|
||||
//그냥 무시한다.
|
||||
//Failure means an id that does not exist arrived..
|
||||
//An obvious error.. but there is no particular way to handle it.
|
||||
//Simply ignore it.
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -870,9 +871,9 @@ retry:
|
||||
// WriteTTYBlock(hWnd,"|",1);
|
||||
chinpacket=0;
|
||||
|
||||
//packetbytes버퍼를 지운다.
|
||||
//Clear the packetbytes buffer.
|
||||
} else {
|
||||
//아직 패킷 문자들이 다 도착하지 않았다.. 아무것도 하지 않는다.
|
||||
//Packet characters have not all arrived yet.. do nothing.
|
||||
;
|
||||
}
|
||||
}else{
|
||||
@@ -889,7 +890,7 @@ retry:
|
||||
}//for(int i=0;i<(int)dwLength;i++)
|
||||
|
||||
|
||||
//상훈 뒤
|
||||
//sanghoon end
|
||||
if (!fReadStat){
|
||||
if (GetLastError() == ERROR_IO_PENDING){
|
||||
while(!GetOverlappedResult( g_hCom,&ros, &dwLength, TRUE )){
|
||||
@@ -1000,12 +1001,24 @@ DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
|
||||
}
|
||||
|
||||
g_dwLastAnalogUpdate = GetTickCount() + 2800;
|
||||
// [tbaud] Scale the poll timeout proportionally to baud rate so faster links
|
||||
// poll more frequently. Formula: clamp(ceil(480000/baud), 5, 50)
|
||||
// preserves the existing 50ms at 9600 baud, floors at 5ms for high speeds.
|
||||
// effectiveBaud: use -tbaud override if set, else the RIO type's default.
|
||||
{
|
||||
DWORD effectiveBaud = (g_dwRIOBaud != 0) ? g_dwRIOBaud
|
||||
: ((g_nRIOType == 0) ? 9600UL : 115200UL);
|
||||
{
|
||||
DWORD t = (480000UL + effectiveBaud - 1) / effectiveBaud;
|
||||
g_dwRIOPollTimeout = (t < 5UL) ? 5UL : (t > 50UL ? 50UL : t);
|
||||
}
|
||||
}
|
||||
while(1) {
|
||||
DWORD dwEvtMask = 0;
|
||||
|
||||
WaitCommEvent( g_hCom, &dwEvtMask,&wcos );
|
||||
|
||||
DWORD ret=WaitForMultipleObjects(3,events,FALSE,50/*INFINITE*/);
|
||||
DWORD ret=WaitForMultipleObjects(3,events,FALSE,g_dwRIOPollTimeout);
|
||||
if(ret==WAIT_OBJECT_0){
|
||||
//An Comm Event has arrived.
|
||||
DWORD bytesread;
|
||||
@@ -1022,10 +1035,10 @@ DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
|
||||
}
|
||||
} else {*/
|
||||
if (g_nRIOType != 0) {
|
||||
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆위의 ReadCommBlock에서 ack를 받았을 경우 duetime을 update시킨다.
|
||||
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆CheckSentBuffer...
|
||||
///When ack is received from ReadCommBlock above, update duetime.
|
||||
///CheckSentBuffer...
|
||||
if(GetTickCount()>ack_timeout)
|
||||
ReSendPackets(sent_packet);//sent_buffer에 있는 모든것들을 다시 보내본다.
|
||||
ReSendPackets(sent_packet);//Resend everything in sent_buffer.
|
||||
}
|
||||
/*}*/
|
||||
}else if(ret==WAIT_OBJECT_0+1){
|
||||
@@ -1039,9 +1052,9 @@ DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
|
||||
//break;
|
||||
}else if (ret==WAIT_TIMEOUT) {
|
||||
if (g_nRIOType != 0) {
|
||||
///◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆CheckSentBuffer...
|
||||
///CheckSentBuffer...
|
||||
if(GetTickCount()>ack_timeout)
|
||||
ReSendPackets(sent_packet);//sent_buffer에 있는 모든것들을 다시 보내본다.
|
||||
ReSendPackets(sent_packet);//Resend everything in sent_buffer.
|
||||
}
|
||||
if (packetbyteremain == 0) {
|
||||
RequestAnalogUpdate();
|
||||
@@ -1236,8 +1249,8 @@ bool SaveReceivedPacket(const BYTE*ba,int length)
|
||||
|
||||
bool GetSerialFromReceivedBuffer(char * ba)
|
||||
{
|
||||
//ButtonPressed/Released만 저장해 놓는다..
|
||||
//모든 serial packet을 옮긴다.
|
||||
//Store only ButtonPressed/Released..
|
||||
//Transfer all serial packets.
|
||||
if(received_packet>0){
|
||||
if(received_buffer[0][2]==received_serial){
|
||||
CopyMemory(ba,received_buffer[0],16);
|
||||
@@ -1264,7 +1277,7 @@ bool QueuePacket(const BYTE *ba,int length)
|
||||
|
||||
int PopPacket(BYTE id)
|
||||
{
|
||||
//lamp는.. id가..
|
||||
//lamp.. check by id..
|
||||
//search the packet..
|
||||
for(int i=0;i<sent_packet;i++){
|
||||
if(sent_buffer[i][3]==id){
|
||||
@@ -1427,7 +1440,7 @@ void CBUTTON_GROUP::SetTable(BOOL bFlag/* = true*/)
|
||||
|
||||
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
|
||||
s_aCtrlLamp[b] = s_aSaveLamp[b];// = s_aButtonTable[b].lamp;
|
||||
// s_aButtonTable는 Old값이므로 초기치는 Off
|
||||
// s_aButtonTable is the old value, so the initial value is Off
|
||||
s_aButtonTable[b].lamp = LAMP_OFF;
|
||||
}
|
||||
|
||||
@@ -1439,7 +1452,7 @@ void CBUTTON_GROUP::SetTable(BOOL bFlag/* = true*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
// 모든 테이블을 원래 상태로
|
||||
// Restore all tables to original state
|
||||
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
|
||||
s_aCtrlLamp[b] = s_aSaveLamp[b];
|
||||
}
|
||||
@@ -1534,7 +1547,7 @@ void CBUTTON_GROUP::ResetTable(BOOL bFlag/* = true*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
// 모든 테이블을 Off
|
||||
// Turn off all tables
|
||||
for (int b = 0; b < MAXBUTTON_TABLE; b++) {
|
||||
switch(b)
|
||||
{
|
||||
@@ -2212,13 +2225,13 @@ void CRIOMAIN::UpdatePadal (DIJOYSTATE &js)
|
||||
|
||||
Down Up
|
||||
======================
|
||||
← (+) (-) →
|
||||
<-- (+) (-) -->
|
||||
======================
|
||||
↗
|
||||
/^
|
||||
g_LeftPedalStart: INT_MAX (+)
|
||||
|
||||
lP = (LONG)g_LeftPedalStart - g_LeftPedal;
|
||||
lP 결과값은 무조건 음수
|
||||
lP result value is always negative
|
||||
*/
|
||||
|
||||
LONG lP = 0;
|
||||
@@ -2362,9 +2375,9 @@ void CRIOMAIN::UpdateThrottle (DIJOYSTATE &js)
|
||||
|
||||
Up Down
|
||||
======================
|
||||
← (-) (+) →
|
||||
<-- (-) (+) -->
|
||||
======================
|
||||
↗
|
||||
/^
|
||||
g_ThrottleStart: INT_MIN (-)
|
||||
*/
|
||||
|
||||
@@ -2447,11 +2460,11 @@ void CRIOMAIN::UpdateJoystick (DIJOYSTATE &js)
|
||||
*/
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
80 의 의미
|
||||
Meaning of 80
|
||||
|
||||
RIO (LEFT :120 ~ RIGHT :-80) 까지의 수를 돌려준다고 가정하고
|
||||
(LEFT의경우) RIGHT 의 최대값 80 이상인 값을 잘라버리고 나머지는
|
||||
버릴경우 LEFT 와 RIGHT가 동일한 속도로 움직일수 있다
|
||||
Assuming RIO returns values in range (LEFT:120 ~ RIGHT:-80)
|
||||
(In the LEFT case) clip values above the RIGHT maximum of 80, and the rest
|
||||
if discarded, LEFT and RIGHT can move at the same speed
|
||||
*/
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
LONG lJ;
|
||||
|
||||
@@ -132,6 +132,10 @@ extern SCRIPTCALLBACK(CTCL_GetMissionState);
|
||||
extern SCRIPTCALLBACK(CTCL_DoBreak);
|
||||
extern SCRIPTCALLBACK(CTCL_IsGameLoaded);
|
||||
extern SCRIPTCALLBACK(CTCL_DoReprint);
|
||||
extern SCRIPTCALLBACK(CTCL_LoadAutoFile);
|
||||
extern SCRIPTCALLBACK(CTCL_GetAutoSlotName);
|
||||
extern SCRIPTCALLBACK(CTCL_GetAutoSlotMech);
|
||||
extern SCRIPTCALLBACK(CTCL_GetAutoSlotInt);
|
||||
extern SCRIPTCALLBACK(CTCL_CheckPlayMovie);
|
||||
extern SCRIPTCALLBACK(CTCL_CheckCoinCounts);
|
||||
extern SCRIPTCALLBACK(CTCL_CheckUseJPD);
|
||||
@@ -158,6 +162,35 @@ int g_nWhyPaused = 0; // 0: not paused - invitation in menu-state, 1: briefing,
|
||||
extern SCRIPTCALLBACK(CTCL_WhyPaused);
|
||||
int g_nTimeList_Index = 3; // 3rd item in listbox...
|
||||
int g_nTimeList_Value = 7; // 7 minutes
|
||||
// [RookieMission] options.ini overrides ? defaults match the hardcoded script values
|
||||
char g_szRookieMission[256] = "ScarabStronghold - Attrition";
|
||||
char* g_pszRookieMission = g_szRookieMission; // pointer used for script registration
|
||||
int g_nRookieGameType = 2; // Attrition index in game-type list
|
||||
int g_nRookieVisibility = 0; // 0=clear
|
||||
int g_nRookieWeather = 0; // 0=off
|
||||
int g_nRookieTimeOfDay = 0; // 0=day
|
||||
int g_nRookieTimeLimit = -1; // -1=use g_nTimeList_Value
|
||||
int g_nRookieRadar = 0; // 0=novice
|
||||
int g_nRookieHeat = 0; // 0=off
|
||||
int g_nRookieFriendlyFire= 0;
|
||||
int g_nRookieSplash = 0;
|
||||
int g_nRookieUnlimitedAmmo = 1; // 1=on (be cautious)
|
||||
int g_nRookieWeaponJam = 0;
|
||||
int g_nRookieAdvanceMode = 0;
|
||||
int g_nRookieArmorMode = 0;
|
||||
// [automaticmode] options.ini ? Load File button
|
||||
struct SAutoFileSlot {
|
||||
char szName[64]; // pilot name
|
||||
char szMech[64]; // mech display name (matched against mech[] array)
|
||||
int nType; // 0=empty, 1=player, 2-9=bot difficulty level
|
||||
int nTeam;
|
||||
int nSkin;
|
||||
int nDecal;
|
||||
};
|
||||
static SAutoFileSlot g_aAutoSlots[16];
|
||||
static int g_nAutoSlotsCount = 0;
|
||||
static int g_bAutomaticMode = 0;
|
||||
static char g_szAutomaticFile[MAX_PATH] = "";
|
||||
// MSL 5.06
|
||||
int g_nMechVariant = 0;
|
||||
int g_nMechLabOp = 0;
|
||||
@@ -727,6 +760,36 @@ void MW4Shell::StartUp()
|
||||
gosScript_RegisterCallback("CTCL_WhyPaused",&CTCL_WhyPaused,GOSVAR_INT,0,NULL);
|
||||
gosScript_RegisterVariable("g_nTimeList_Index", &g_nTimeList_Index, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nTimeList_Value", &g_nTimeList_Value, GOSVAR_INT, 0, NULL);
|
||||
// [RookieMission] ini-driven defaults
|
||||
gosScript_RegisterVariable("g_szRookieMission", &g_pszRookieMission, GOSVAR_STRING, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieGameType", &g_nRookieGameType, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieVisibility", &g_nRookieVisibility, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieWeather", &g_nRookieWeather, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieTimeOfDay", &g_nRookieTimeOfDay, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieTimeLimit", &g_nRookieTimeLimit, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieRadar", &g_nRookieRadar, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieHeat", &g_nRookieHeat, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieFriendlyFire",&g_nRookieFriendlyFire, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieSplash", &g_nRookieSplash, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieUnlimitedAmmo",&g_nRookieUnlimitedAmmo,GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieWeaponJam", &g_nRookieWeaponJam, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieAdvanceMode", &g_nRookieAdvanceMode, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nRookieArmorMode", &g_nRookieArmorMode, GOSVAR_INT, 0, NULL);
|
||||
// [automaticmode] callbacks
|
||||
gosScript_RegisterCallback("CTCL_LoadAutoFile", &CTCL_LoadAutoFile, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterCallback("CTCL_GetAutoSlotName", &CTCL_GetAutoSlotName, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterCallback("CTCL_GetAutoSlotMech", &CTCL_GetAutoSlotMech, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterCallback("CTCL_GetAutoSlotInt", &CTCL_GetAutoSlotInt, GOSVAR_INT, 0, NULL);
|
||||
{
|
||||
NotationFile opts("options.ini", NotationFile::Standard, true);
|
||||
Page *pAuto = opts.FindPage("automaticmode");
|
||||
if (pAuto) {
|
||||
pAuto->GetEntry("automaticmode", &g_bAutomaticMode);
|
||||
const char *sz = NULL;
|
||||
if (pAuto->GetEntry("automaticfile", &sz) && sz)
|
||||
strncpy(g_szAutomaticFile, sz, sizeof(g_szAutomaticFile)-1);
|
||||
}
|
||||
}
|
||||
// MSL 5.06
|
||||
gosScript_RegisterVariable("g_nMechVariant", &g_nMechVariant, GOSVAR_INT, 0, NULL);
|
||||
gosScript_RegisterVariable("g_nMechLabOp", &g_nMechLabOp, GOSVAR_INT, 0, NULL);
|
||||
@@ -1108,6 +1171,26 @@ void MW4Shell::ShutDown()
|
||||
// jcem - start
|
||||
gosScript_UnregisterVariable("g_nTimeList_Value");
|
||||
gosScript_UnregisterVariable("g_nTimeList_Index");
|
||||
// [RookieMission] globals
|
||||
gosScript_UnregisterVariable("g_szRookieMission");
|
||||
gosScript_UnregisterVariable("g_nRookieGameType");
|
||||
gosScript_UnregisterVariable("g_nRookieVisibility");
|
||||
gosScript_UnregisterVariable("g_nRookieWeather");
|
||||
gosScript_UnregisterVariable("g_nRookieTimeOfDay");
|
||||
gosScript_UnregisterVariable("g_nRookieTimeLimit");
|
||||
gosScript_UnregisterVariable("g_nRookieRadar");
|
||||
gosScript_UnregisterVariable("g_nRookieHeat");
|
||||
gosScript_UnregisterVariable("g_nRookieFriendlyFire");
|
||||
gosScript_UnregisterVariable("g_nRookieSplash");
|
||||
gosScript_UnregisterVariable("g_nRookieUnlimitedAmmo");
|
||||
gosScript_UnregisterVariable("g_nRookieWeaponJam");
|
||||
gosScript_UnregisterVariable("g_nRookieAdvanceMode");
|
||||
gosScript_UnregisterVariable("g_nRookieArmorMode");
|
||||
// [automaticmode] callbacks
|
||||
gosScript_UnregisterCallback("CTCL_GetAutoSlotInt");
|
||||
gosScript_UnregisterCallback("CTCL_GetAutoSlotMech");
|
||||
gosScript_UnregisterCallback("CTCL_GetAutoSlotName");
|
||||
gosScript_UnregisterCallback("CTCL_LoadAutoFile");
|
||||
// MSL 5.06
|
||||
gosScript_UnregisterVariable("g_nBlackMech");
|
||||
gosScript_UnregisterVariable("g_nMechVariant");
|
||||
@@ -1828,7 +1911,8 @@ int MW4Shell::SetNetworkMissionParamater(void * instance, int numParms, void **d
|
||||
case PLAYER_LIMIT_PARAMETER:
|
||||
params->m_playerLimit = INTPARM(1);
|
||||
Min_Clamp(params->m_playerLimit, Network::GetInstance()->GetPlayerCount());
|
||||
Environment.NetworkMaxPlayers = params->m_playerLimit;
|
||||
// Add camera slots on top of the pilot limit so cameraships can still connect
|
||||
Environment.NetworkMaxPlayers = params->m_playerLimit + (CTCL_GetTeslaCountAll() - CTCL_GetTeslaCount());
|
||||
gos_NetServerCommands(gos_Commend_UpdateMaxPlayers,0);
|
||||
break;
|
||||
|
||||
@@ -12731,6 +12815,132 @@ int __stdcall CTCL_SetCDSP(void* instance, int args, void* data[])
|
||||
{
|
||||
ASSERT(CTCL_IsConsole());
|
||||
CTCL_DefaultHostSetup(1);
|
||||
// Read [RookieMission] section from options.ini and populate script globals.
|
||||
// Missing keys leave globals at their initialised defaults (backward-compatible).
|
||||
{
|
||||
NotationFile options_ini("options.ini", NotationFile::Standard, true);
|
||||
Page *page = options_ini.FindPage("RookieMission");
|
||||
if (page)
|
||||
{
|
||||
const char *sz = NULL;
|
||||
if (page->GetEntry("MissionName", &sz) && sz)
|
||||
{
|
||||
strncpy(g_szRookieMission, sz, sizeof(g_szRookieMission) - 1);
|
||||
g_szRookieMission[sizeof(g_szRookieMission) - 1] = '\0';
|
||||
}
|
||||
page->GetEntry("GameType", &g_nRookieGameType);
|
||||
page->GetEntry("Visibility", &g_nRookieVisibility);
|
||||
page->GetEntry("Weather", &g_nRookieWeather);
|
||||
page->GetEntry("TimeOfDay", &g_nRookieTimeOfDay);
|
||||
page->GetEntry("TimeLimit", &g_nRookieTimeLimit);
|
||||
page->GetEntry("Radar", &g_nRookieRadar);
|
||||
page->GetEntry("HeatOn", &g_nRookieHeat);
|
||||
page->GetEntry("FriendlyFire", &g_nRookieFriendlyFire);
|
||||
page->GetEntry("SplashDamage", &g_nRookieSplash);
|
||||
page->GetEntry("UnlimitedAmmo", &g_nRookieUnlimitedAmmo);
|
||||
page->GetEntry("WeaponJam", &g_nRookieWeaponJam);
|
||||
page->GetEntry("AdvanceMode", &g_nRookieAdvanceMode);
|
||||
page->GetEntry("ArmorMode", &g_nRookieArmorMode);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// [automaticmode] Load File button ? reads automatic file into Rookie Mission globals + per-slot data.
|
||||
// Returns 1 if the file was found and loaded, 0 otherwise. File is NOT consumed (stays on disk).
|
||||
int __stdcall CTCL_LoadAutoFile(void* instance, int args, void* data[])
|
||||
{
|
||||
if (!g_bAutomaticMode || !g_szAutomaticFile[0])
|
||||
return 0;
|
||||
if (GetFileAttributes(g_szAutomaticFile) == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
NotationFile autofile(g_szAutomaticFile, NotationFile::Standard, true);
|
||||
|
||||
// Game options ? overwrite Rookie Mission globals so the existing
|
||||
// MAIL_SET_ROOKIE_MISSION script flow picks them up automatically.
|
||||
Page *pMission = autofile.FindPage("mission");
|
||||
if (pMission) {
|
||||
const char *sz = NULL;
|
||||
if (pMission->GetEntry("MissionName", &sz) && sz) {
|
||||
strncpy(g_szRookieMission, sz, sizeof(g_szRookieMission)-1);
|
||||
g_szRookieMission[sizeof(g_szRookieMission)-1] = '\0';
|
||||
}
|
||||
pMission->GetEntry("GameType", &g_nRookieGameType);
|
||||
pMission->GetEntry("Visibility", &g_nRookieVisibility);
|
||||
pMission->GetEntry("Weather", &g_nRookieWeather);
|
||||
pMission->GetEntry("TimeOfDay", &g_nRookieTimeOfDay);
|
||||
pMission->GetEntry("TimeLimit", &g_nRookieTimeLimit);
|
||||
pMission->GetEntry("Radar", &g_nRookieRadar);
|
||||
pMission->GetEntry("HeatOn", &g_nRookieHeat);
|
||||
pMission->GetEntry("FriendlyFire", &g_nRookieFriendlyFire);
|
||||
pMission->GetEntry("SplashDamage", &g_nRookieSplash);
|
||||
pMission->GetEntry("UnlimitedAmmo", &g_nRookieUnlimitedAmmo);
|
||||
pMission->GetEntry("WeaponJam", &g_nRookieWeaponJam);
|
||||
pMission->GetEntry("AdvanceMode", &g_nRookieAdvanceMode);
|
||||
pMission->GetEntry("ArmorMode", &g_nRookieArmorMode);
|
||||
}
|
||||
|
||||
// Per-slot data (up to 16 slots via [slot0]..[slot15] pages)
|
||||
g_nAutoSlotsCount = 0;
|
||||
memset(g_aAutoSlots, 0, sizeof(g_aAutoSlots));
|
||||
char szPageName[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
sprintf(szPageName, "slot%d", i);
|
||||
Page *pSlot = autofile.FindPage(szPageName);
|
||||
if (!pSlot) break;
|
||||
g_nAutoSlotsCount = i + 1;
|
||||
const char *sz = NULL;
|
||||
if (pSlot->GetEntry("PilotName", &sz) && sz)
|
||||
strncpy(g_aAutoSlots[i].szName, sz, sizeof(g_aAutoSlots[i].szName)-1);
|
||||
sz = NULL;
|
||||
if (pSlot->GetEntry("Mech", &sz) && sz)
|
||||
strncpy(g_aAutoSlots[i].szMech, sz, sizeof(g_aAutoSlots[i].szMech)-1);
|
||||
pSlot->GetEntry("Type", &g_aAutoSlots[i].nType);
|
||||
pSlot->GetEntry("Team", &g_aAutoSlots[i].nTeam);
|
||||
pSlot->GetEntry("Skin", &g_aAutoSlots[i].nSkin);
|
||||
pSlot->GetEntry("Decal", &g_aAutoSlots[i].nDecal);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns pilot name string for slot k ? data[0]=string output buffer, data[1]=int k
|
||||
int __stdcall CTCL_GetAutoSlotName(void* instance, int args, void* data[])
|
||||
{
|
||||
int k = INTPARM(1);
|
||||
const char *sz = (k >= 0 && k < 16) ? g_aAutoSlots[k].szName : "";
|
||||
if (STRPARM(0)) gos_Free(STRPARM(0));
|
||||
STRPARM(0) = (char *)gos_Malloc(64);
|
||||
strncpy(STRPARM(0), sz, 63);
|
||||
STRPARM(0)[63] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns mech display name for slot k ? data[0]=string output buffer, data[1]=int k
|
||||
int __stdcall CTCL_GetAutoSlotMech(void* instance, int args, void* data[])
|
||||
{
|
||||
int k = INTPARM(1);
|
||||
const char *sz = (k >= 0 && k < 16) ? g_aAutoSlots[k].szMech : "";
|
||||
if (STRPARM(0)) gos_Free(STRPARM(0));
|
||||
STRPARM(0) = (char *)gos_Malloc(64);
|
||||
strncpy(STRPARM(0), sz, 63);
|
||||
STRPARM(0)[63] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns int field for slot k ? data[0]=int k, data[1]=int field (0=Type 1=Team 2=Skin 3=Decal)
|
||||
int __stdcall CTCL_GetAutoSlotInt(void* instance, int args, void* data[])
|
||||
{
|
||||
int k = INTPARM(0);
|
||||
int field = INTPARM(1);
|
||||
if (k < 0 || k >= 16) return 0;
|
||||
switch (field) {
|
||||
case 0: return g_aAutoSlots[k].nType;
|
||||
case 1: return g_aAutoSlots[k].nTeam;
|
||||
case 2: return g_aAutoSlots[k].nSkin;
|
||||
case 3: return g_aAutoSlots[k].nDecal;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13307,19 +13517,17 @@ void CTCL_API CTCL_DefaultHostSetup(int nMode)
|
||||
params->m_allowdecaltransfer = 0;
|
||||
if (g_bCOOP) {
|
||||
Environment.NetworkMaxPlayers = 16;
|
||||
//if (CTCL_GetTeslaCount() < CTCL_GetTeslaCountAll()) {
|
||||
// any cameraship installed... so 1 more player can join
|
||||
//params->m_maxPlayers = 9;
|
||||
//params->m_maxBots = 8;
|
||||
//} else {
|
||||
// Reserve extra DirectPlay slots for camera seats (tracked separately from pilots in CTCL)
|
||||
// Original commented-out intent preserved and now implemented for non-COOP below
|
||||
params->m_maxPlayers = 9;
|
||||
params->m_maxBots = 8;
|
||||
//}
|
||||
} else {
|
||||
params->m_maxPlayers = 31; // 31: max that fits in 5-bit bitstream (0-31)
|
||||
Environment.NetworkMaxPlayers = 31;
|
||||
params->m_maxBots = 31;
|
||||
gos_NetServerCommands(gos_Commend_UpdateMaxPlayers, 0); // push the updated limit to the live DirectPlay session
|
||||
params->m_maxPlayers = 16;
|
||||
// Reserve extra DirectPlay slots for cameraships: they share the session but are tracked
|
||||
// separately from pilot seats in CTCL (CTCL_GetTeslaCountAll - CTCL_GetTeslaCount = camera count).
|
||||
// Without this, cameraship connection is rejected by DirectPlay because slot 17 doesn't exist.
|
||||
Environment.NetworkMaxPlayers = params->m_maxPlayers + (CTCL_GetTeslaCountAll() - CTCL_GetTeslaCount());
|
||||
params->m_maxBots = 16;
|
||||
}
|
||||
params->m_allow3rdPerson = 1;
|
||||
if ((nMode != 0) && (nMode != 4)) {
|
||||
|
||||
@@ -808,8 +808,8 @@ void NetMissionParameters::MWNetMissionParameters::SaveParameters(DynamicMemoryS
|
||||
stream->WriteBits(&m_pureMapCycle,1);
|
||||
|
||||
|
||||
stream->WriteBits(&m_maxPlayers, 5); // max 31 players
|
||||
stream->WriteBits(&m_maxBots, 5); // max 31
|
||||
stream->WriteBits(&m_maxPlayers, 5); // 16 players maximum
|
||||
stream->WriteBits(&m_maxBots, 5); // 16 players maximum
|
||||
stream->WriteBits(&m_mapID, 16); // 65535 maps available
|
||||
stream->WriteBits(&m_mapClientCRC, 64);
|
||||
|
||||
@@ -927,8 +927,8 @@ void NetMissionParameters::MWNetMissionParameters::LoadParameters(MemoryStream *
|
||||
stream->ReadBits(&m_useMapCycle,1);
|
||||
stream->ReadBits(&m_pureMapCycle,1);
|
||||
|
||||
stream->ReadBits(&m_maxPlayers, 5); // max 31 players
|
||||
stream->ReadBits(&m_maxBots, 5); // max 31
|
||||
stream->ReadBits(&m_maxPlayers, 5); // 16 players max
|
||||
stream->ReadBits(&m_maxBots, 5); // 16 players max
|
||||
stream->ReadBits(&m_mapID, 16); // 65535 maps available
|
||||
stream->ReadBits(&m_mapClientCRC, 64);
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ extern int g_nMech4Comm;
|
||||
// server & client only
|
||||
extern BOOL g_bIsServer;
|
||||
// console(All), server & client only(g_aPlayerInfos[0]), server only(g_aPlayerInfos[1..g_nBOTs]
|
||||
extern SPlayerInfo g_aPlayerInfos[35]; // 31 pilots + 1 CS + 3 spare
|
||||
extern SPlayerInfo g_aPlayerInfos[20];
|
||||
extern int g_nPlayerInfos;
|
||||
extern int g_nServer;
|
||||
extern int g_nTeslas;
|
||||
|
||||
@@ -885,7 +885,7 @@ void __stdcall GetGameOSEnvironment(char* CommandLine)
|
||||
Environment.allowMultipleApps = false;
|
||||
Environment.AllowJoinInProgress = true;
|
||||
Environment.NetworkGame = true;
|
||||
Environment.NetworkMaxPlayers = 31; // max 31 (fits in 5-bit bitstream)
|
||||
Environment.NetworkMaxPlayers = 16;
|
||||
Environment.NetworkGUID[0] = 0x95;
|
||||
Environment.NetworkGUID[1] = 0x78;
|
||||
Environment.NetworkGUID[2] = 0xFF;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "recscore.h"
|
||||
#endif // !defined(CTCLS_EXPORTS) && !defined(CTCL_LAUNCHER)
|
||||
|
||||
#define MAX_TESLAS 31
|
||||
#define MAX_TESLAS 16
|
||||
#define MAX_CAMERAS 4
|
||||
|
||||
#define PORT_Launcher 1000
|
||||
@@ -263,7 +263,7 @@ CInviteCOOP g_InviteCOOP;
|
||||
// Mech4 only
|
||||
int g_nMech4Comm = 0;
|
||||
BOOL g_bIsServer = FALSE;
|
||||
SPlayerInfo g_aPlayerInfos[35]; // 31 pilots + 1 CS + 3 spare
|
||||
SPlayerInfo g_aPlayerInfos[20];
|
||||
int g_nPlayerInfos;
|
||||
int g_nServer;
|
||||
int g_nTeslas;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "recscore.h"
|
||||
#endif // !defined(CTCLS_EXPORTS) && !defined(CTCL_LAUNCHER)
|
||||
|
||||
#define MAX_TESLAS 31
|
||||
#define MAX_TESLAS 16
|
||||
#define MAX_CAMERAS 4
|
||||
|
||||
#define PORT_Launcher 1000
|
||||
@@ -263,7 +263,7 @@ CInviteCOOP g_InviteCOOP;
|
||||
// Mech4 only
|
||||
int g_nMech4Comm = 0;
|
||||
BOOL g_bIsServer = FALSE;
|
||||
SPlayerInfo g_aPlayerInfos[35]; // 31 pilots + 1 CS + 3 spare
|
||||
SPlayerInfo g_aPlayerInfos[20];
|
||||
int g_nPlayerInfos;
|
||||
int g_nServer;
|
||||
int g_nTeslas;
|
||||
|
||||
@@ -806,7 +806,7 @@ STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_ML_CH_ACCELERATION "Acceleration (Meters/Sec.):"
|
||||
IDS_ML_CH_DECELERATION "Deceleration (Meters/Sec.):"
|
||||
IDS_ML_CH_TURNRATE "Turn Rate (Degrees/Sec.):"
|
||||
IDS_ML_CH_TURNRATE "Turn Rate (Top Speed Rad/Sec):"
|
||||
IDS_ML_CH_TWISTRANGE "Torso Twist Range (Degrees):"
|
||||
IDS_ML_CH_TWISTSPEED "Torso Twist Speed (Degrees/Sec.):"
|
||||
IDS_ML_CH_NEWMECH "NEW 'MECH"
|
||||
|
||||
@@ -86,7 +86,7 @@ void NetMissionParameters::AdeptNetMissionParameters::ResetParameters(void)
|
||||
{
|
||||
m_runDedicated = 0;
|
||||
m_closedGame = 0;
|
||||
m_playerLimit = 31; // max 31 (fits in 5-bit bitstream)
|
||||
m_playerLimit = 16;
|
||||
|
||||
m_visibility = 0;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "recscore.h"
|
||||
#endif // !defined(CTCLS_EXPORTS) && !defined(CTCL_LAUNCHER)
|
||||
|
||||
#define MAX_TESLAS 31
|
||||
#define MAX_TESLAS 16
|
||||
#define MAX_CAMERAS 4
|
||||
|
||||
#define PORT_Launcher 1000
|
||||
@@ -263,7 +263,7 @@ CInviteCOOP g_InviteCOOP;
|
||||
// Mech4 only
|
||||
int g_nMech4Comm = 0;
|
||||
BOOL g_bIsServer = FALSE;
|
||||
SPlayerInfo g_aPlayerInfos[35]; // 31 pilots + 1 CS + 3 spare
|
||||
SPlayerInfo g_aPlayerInfos[20];
|
||||
int g_nPlayerInfos;
|
||||
int g_nServer;
|
||||
int g_nTeslas;
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
// 10/10/03 MSL Added Cameraship to RESET_AFTER_LAUNCH
|
||||
// 10/17/05 MSL Added all remaining Mechs (55)
|
||||
// 06/19/18 AVB Update tab stops
|
||||
// 06/24/26 Cyd MechCorps is given access to this script and the loading method (-diskfirst). This includes the CS timer fix.
|
||||
// 06/27/26 MCHL MechCorps Highlight: Change Fab4 to Super6.
|
||||
// 07/19/26 RT Bumped console title to V5.1.0b1
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -72,8 +75,8 @@
|
||||
#define USE_O_MORE_PODS $$g_nMechPodNum$$ // 0 = use only 8
|
||||
|
||||
#if USE_O_MORE_PODS
|
||||
#define MAX_ROSTER_COUNT 31 // max within 5-bit bitstream (0-31)
|
||||
#define MAX_TEAMMATE_COUNT 15 // Was 4, then 8
|
||||
#define MAX_ROSTER_COUNT 16 // Was 8
|
||||
#define MAX_TEAMMATE_COUNT 8 // Was 4
|
||||
#else
|
||||
#define MAX_ROSTER_COUNT 8
|
||||
#define MAX_TEAMMATE_COUNT 4 // Was 4
|
||||
@@ -190,10 +193,13 @@
|
||||
|
||||
// MSL 5.06
|
||||
// MSL ADD MECH
|
||||
#define ROOKIEMECH1 38 // Loki
|
||||
#define ROOKIEMECH2 40 // Madcat
|
||||
#define ROOKIEMECH3 56 // Thor
|
||||
#define ROOKIEMECH4 61 // Vulture
|
||||
// MechCorps Highlight: expanded from Fab4 to Super6 (added Archer and Warhammer)
|
||||
#define ROOKIEMECH1 1 // Archer
|
||||
#define ROOKIEMECH2 38 // Loki
|
||||
#define ROOKIEMECH3 40 // Madcat
|
||||
#define ROOKIEMECH4 56 // Thor
|
||||
#define ROOKIEMECH5 61 // Vulture
|
||||
#define ROOKIEMECH6 62 // Warhammer
|
||||
|
||||
main
|
||||
{
|
||||
@@ -246,7 +252,7 @@ main
|
||||
o_frame.type = 0
|
||||
o_frame.location = 0, 0, 100
|
||||
// MSL Version
|
||||
o_frame.screen_name = "BattleTech Console V5.0.7Df" // localize$(IDS_MP_LOBBY_GAME_LOBBY)
|
||||
o_frame.screen_name = "BattleTech Console V5.1.0b1" // localize$(IDS_MP_LOBBY_GAME_LOBBY)
|
||||
initialize(o_frame)
|
||||
|
||||
int team_camo[16] // team_camo[selected team number] is skin number(0..36)...
|
||||
@@ -364,7 +370,7 @@ main
|
||||
cur_team_val = callback($$CTCL_GetTeamParams$$, cur_team_count[0])
|
||||
|
||||
int skin_id ///////VERY IMPORTANT FOR NEW SKIN INTERFACE
|
||||
int skin_ids[32]
|
||||
int skin_ids[17]
|
||||
int update_skin = false
|
||||
// MSL 5.05
|
||||
int decal_id ///////VERY IMPORTANT FOR NEW DECAL INTERFACE
|
||||
@@ -522,7 +528,7 @@ main
|
||||
|
||||
|
||||
///---------holds faction name for scroll list
|
||||
string faction_name[32]
|
||||
string faction_name[17]
|
||||
|
||||
callback($$Shell_CallbackHandler$$, ShellInitMPScreen)
|
||||
|
||||
@@ -645,12 +651,12 @@ main
|
||||
team_legal_to_join[8] = TRUE
|
||||
int update_team = 0
|
||||
|
||||
int max_players = 31 // max within 5-bit bitstream
|
||||
int max_players = 16
|
||||
|
||||
int player_num = 0
|
||||
// int num_of_teams = 8
|
||||
int mech_id
|
||||
int name_color[32]
|
||||
int name_color[17]
|
||||
int lupe
|
||||
|
||||
for lupe = 0; lupe < nRosterCount;lupe++
|
||||
@@ -675,33 +681,33 @@ main
|
||||
player_num = -1
|
||||
|
||||
// ComboBox for the Player Type
|
||||
object o_BotList[32]
|
||||
object o_BotList_bu[32]
|
||||
int m_naLastSelected[32]
|
||||
object o_BotList[17]
|
||||
object o_BotList_bu[17]
|
||||
int m_naLastSelected[17]
|
||||
for x = 0; x < nRosterCount; x++
|
||||
{
|
||||
m_naLastSelected[x] = 0
|
||||
}
|
||||
object o_Editbox[32]
|
||||
object o_print_text[32]
|
||||
object o_mech_variant[32]
|
||||
object o_mech_variant_bu[32]
|
||||
object o_Editbox[17]
|
||||
object o_print_text[17]
|
||||
object o_mech_variant[17]
|
||||
object o_mech_variant_bu[17]
|
||||
#if USE_O_MECH_VARIANT2
|
||||
object o_mech_variant2[32]
|
||||
object o_mech_variant2_bu[32]
|
||||
object o_mech_variant2[17]
|
||||
object o_mech_variant2_bu[17]
|
||||
#endif // USE_O_MECH_VARIANT2
|
||||
object o_mech_rand[32]
|
||||
object o_skins[32]
|
||||
object o_skins_bu[32]
|
||||
object o_mech_rand[17]
|
||||
object o_skins[17]
|
||||
object o_skins_bu[17]
|
||||
// MSL 5.05
|
||||
object o_decal[32]
|
||||
object o_decal_bu[32]
|
||||
object o_team[32]
|
||||
object o_team_bu[32]
|
||||
object o_decal_box[32]
|
||||
object o_skin_box[32]
|
||||
object o_status[32]
|
||||
int roster_posy[32]
|
||||
object o_decal[18]
|
||||
object o_decal_bu[18]
|
||||
object o_team[18]
|
||||
object o_team_bu[18]
|
||||
object o_decal_box[18]
|
||||
object o_skin_box[18]
|
||||
object o_status[18]
|
||||
int roster_posy[18]
|
||||
int coolbaby
|
||||
|
||||
int stock_size = 0
|
||||
@@ -1005,7 +1011,7 @@ main
|
||||
o_decal[x].list_item[15] = "16"
|
||||
o_decal[x].list_item[16] = "17"
|
||||
|
||||
for coolbaby = 17;coolbaby < o_decal[x].list_size;coolbaby++
|
||||
for coolbaby = 17;coolbaby < o_decal[x].list_size+1;coolbaby++
|
||||
o_decal[x].list_item[coolbaby] = conv$(coolbaby+1)
|
||||
|
||||
o_decal[x].nselected = 3
|
||||
@@ -1072,7 +1078,7 @@ main
|
||||
o_skins[x].list_item[14] = "15"
|
||||
o_skins[x].list_item[15] = "16"
|
||||
|
||||
for coolbaby = 16;coolbaby < o_skins[x].list_size;coolbaby++
|
||||
for coolbaby = 16;coolbaby < o_skins[x].list_size+1;coolbaby++
|
||||
o_skins[x].list_item[coolbaby] = conv$(coolbaby+1)
|
||||
|
||||
o_skins[x].nselected = 3
|
||||
@@ -1223,6 +1229,16 @@ main
|
||||
o_all_random_mech.state = 0 // initially enabled
|
||||
initialize(o_all_random_mech)
|
||||
|
||||
// [automaticmode] Load File button -- below Pick Cond., left of Reprint
|
||||
object o_load_file = s_multistatepane
|
||||
o_load_file.total_states = 3
|
||||
o_load_file.textsize = 1
|
||||
o_load_file.text = "Load File"
|
||||
o_load_file.file = WPATH "button_reg_138x23m_3state.tga"
|
||||
o_load_file.location = 467, 510, o_frame.location.z + 1
|
||||
o_load_file.state = 0 // initially enabled
|
||||
initialize(o_load_file)
|
||||
|
||||
// MSL Added default settings button
|
||||
object o_default = s_multistatepane
|
||||
o_default.total_states = 3
|
||||
@@ -1658,6 +1674,94 @@ main
|
||||
mail(MAIL_RESET_AFTER_LAUNCH, this) // reset
|
||||
return
|
||||
}
|
||||
// [automaticmode] Load File button handler
|
||||
if (sender == o_load_file)
|
||||
{
|
||||
play press, 1
|
||||
if callback($$CTCL_LoadAutoFile$$)
|
||||
{
|
||||
// Apply mission + game options via existing Rookie Mission flow
|
||||
mail(MAIL_SET_ROOKIE_MISSION, @ConLobbyMission@)
|
||||
// Clear all slots
|
||||
o_cam_list.nselected = 0
|
||||
for (k = 0; k < nRosterCount; k++)
|
||||
{
|
||||
if (1 <= o_BotList[k].nselected)
|
||||
{
|
||||
if (o_BotList[k].nselected == 1) && (k < MAXTESLA_P)
|
||||
{
|
||||
o_Editbox[k].boxValue = ""
|
||||
initialize(o_Editbox[k])
|
||||
deactivate(o_Editbox[k])
|
||||
}
|
||||
o_BotList[k].nselected = 0
|
||||
m_naLastSelected[k] = 0
|
||||
if (ROSTER_top_of_list <= k) && (k < ROSTER_top_of_list + ROSTER_DISPLAY_COUNT)
|
||||
mail(MAIL_PLAYER_TYPE_CHANGED, k, this)
|
||||
}
|
||||
}
|
||||
// Apply per-slot data from file
|
||||
string szAutoName
|
||||
string szAutoMech
|
||||
int nAutoType
|
||||
int j
|
||||
for (k = 0; k < nRosterCount; k++)
|
||||
{
|
||||
nAutoType = callback($$CTCL_GetAutoSlotInt$$, k, 0)
|
||||
if nAutoType > 0
|
||||
{
|
||||
o_BotList[k].nselected = nAutoType
|
||||
m_naLastSelected[k] = nAutoType
|
||||
if (o_BotList[k].nselected > 0)
|
||||
activate(o_BotList[k])
|
||||
if (nAutoType == 1) && (k < MAXTESLA_P)
|
||||
{
|
||||
callback($$CTCL_GetAutoSlotName$$, szAutoName, k)
|
||||
o_Editbox[k].boxValue = szAutoName
|
||||
initialize(o_Editbox[k])
|
||||
activate(o_Editbox[k])
|
||||
}
|
||||
callback($$CTCL_GetAutoSlotMech$$, szAutoMech, k)
|
||||
if (!equal$(szAutoMech, ""))
|
||||
{
|
||||
#if USE_ALLOWED_MECHS
|
||||
for (j = 0; j < MAX_ALLOWED_MECHS; j++)
|
||||
{
|
||||
if equal$(mech[allowed_mechs[j]], szAutoMech)
|
||||
{
|
||||
o_mech_variant[k].nselected = j
|
||||
break
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (j = 0; j < $$m_mechCount$$; j++)
|
||||
{
|
||||
if equal$(mech[j], szAutoMech)
|
||||
{
|
||||
o_mech_variant[k].nselected = j
|
||||
break
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if cur_team_val > 0
|
||||
o_team[k].nselected = callback($$CTCL_GetAutoSlotInt$$, k, 1)
|
||||
else
|
||||
o_skins[k].nselected = callback($$CTCL_GetAutoSlotInt$$, k, 2)
|
||||
o_decal[k].nselected = callback($$CTCL_GetAutoSlotInt$$, k, 3)
|
||||
initialize(o_mech_variant[k])
|
||||
if (ROSTER_top_of_list <= k) && (k < ROSTER_top_of_list + ROSTER_DISPLAY_COUNT)
|
||||
{
|
||||
activate(o_mech_variant[k])
|
||||
mail(MAIL_PLAYER_TYPE_CHANGED, k, this)
|
||||
}
|
||||
else
|
||||
deactivate(o_mech_variant[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if (sender == o_reprint)
|
||||
{
|
||||
play press,1
|
||||
@@ -1761,38 +1865,39 @@ main
|
||||
for (k = 0; k < nRosterCount; k++)
|
||||
{
|
||||
// MSL
|
||||
// MechCorps Highlight: Super6 slot assignments (16 slots, 6-mech cycle; Vulture+Warhammer appear twice)
|
||||
if k == 0
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Loki
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Archer
|
||||
if k == 1
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Madcat
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Loki
|
||||
if k == 2
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Thor
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Madcat
|
||||
if k == 3
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // vulture
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // Thor
|
||||
if k == 4
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Loki
|
||||
o_mech_variant[k].nselected = ROOKIEMECH5 // Vulture
|
||||
if k == 5
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Madcat
|
||||
o_mech_variant[k].nselected = ROOKIEMECH6 // Warhammer
|
||||
if k == 6
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Thor
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Archer
|
||||
if k == 7
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // Vulture
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Loki
|
||||
if k == 8
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Loki
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Madcat
|
||||
if k == 9
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Madcat
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // Thor
|
||||
if k == 10
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Thor
|
||||
o_mech_variant[k].nselected = ROOKIEMECH5 // Vulture
|
||||
if k == 11
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // vulture
|
||||
o_mech_variant[k].nselected = ROOKIEMECH6 // Warhammer
|
||||
if k == 12
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Loki
|
||||
o_mech_variant[k].nselected = ROOKIEMECH1 // Archer
|
||||
if k == 13
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Madcat
|
||||
o_mech_variant[k].nselected = ROOKIEMECH2 // Loki
|
||||
if k == 14
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Thor
|
||||
o_mech_variant[k].nselected = ROOKIEMECH3 // Madcat
|
||||
if k == 15
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // Vulture
|
||||
o_mech_variant[k].nselected = ROOKIEMECH4 // Thor
|
||||
#if USE_O_MECH_VARIANT2
|
||||
if (USE_ALLOWED_MECHS)
|
||||
last_count = stock_array[allowed_mechs[o_mech_variant[k].nselected]]
|
||||
@@ -2714,7 +2819,8 @@ main
|
||||
}
|
||||
}
|
||||
// MSL 5.06
|
||||
if nLaunchState == 0 && (nTempPlayerCount > 31)
|
||||
// RT 07/19/26: raised cap from 16 to 17 to allow 16 pilots + 1 cameraship
|
||||
if nLaunchState == 0 && (nTempPlayerCount > 17)
|
||||
{
|
||||
o_error_string.text = "Too many player/bots"
|
||||
nLaunchState = -7
|
||||
@@ -4000,17 +4106,24 @@ mech_randomizer
|
||||
else // right button
|
||||
{
|
||||
int pick_mech = 0
|
||||
pick_mech = random(0, 3)
|
||||
//pick_mech = random(0, 3) // Fab4
|
||||
// MechCorps Highlight: Super6 - expand right-click random range to 6
|
||||
pick_mech = random(0, 5)
|
||||
|
||||
// MSL
|
||||
// MechCorps Highlight: Super6 - added Archer (0) and Warhammer (5) to right-click mech pool
|
||||
if pick_mech = 0
|
||||
last_mech = ROOKIEMECH1 // Loki
|
||||
last_mech = ROOKIEMECH1 // Archer
|
||||
if pick_mech = 1
|
||||
last_mech = ROOKIEMECH2 // Madcat
|
||||
last_mech = ROOKIEMECH2 // Loki
|
||||
if pick_mech = 2
|
||||
last_mech = ROOKIEMECH3 // Thor
|
||||
last_mech = ROOKIEMECH3 // Madcat
|
||||
if pick_mech = 3
|
||||
last_mech = ROOKIEMECH4 // vulture
|
||||
last_mech = ROOKIEMECH4 // Thor
|
||||
if pick_mech = 4
|
||||
last_mech = ROOKIEMECH5 // Vulture
|
||||
if pick_mech = 5
|
||||
last_mech = ROOKIEMECH6 // Warhammer
|
||||
}
|
||||
if (USE_ALLOWED_MECHS)
|
||||
{
|
||||
|
||||
@@ -793,15 +793,15 @@ main
|
||||
if (getmessage() == MAIL_SET_ROOKIE_MISSION) // set rookie, see conlobby.script
|
||||
{
|
||||
// caution: actually 0 is not correct but who care? ^^
|
||||
if (o_game_options[0].nselected != 2)
|
||||
if (o_game_options[0].nselected != $$g_nRookieGameType$$)
|
||||
{
|
||||
o_game_options[0].nselected = 2
|
||||
o_game_options[0].nselected = $$g_nRookieGameType$$
|
||||
mail(MAIL_SET_ROOKIE_MISSION, this)
|
||||
}
|
||||
// find mission:
|
||||
for k = 0; k < o_game_options[1].list_size; k++
|
||||
{
|
||||
if equal$(o_game_options[1].list_item[k], ROOKIE_MISSION)
|
||||
if equal$(o_game_options[1].list_item[k], $$g_szRookieMission$$)
|
||||
{
|
||||
// found mission
|
||||
break
|
||||
@@ -855,24 +855,26 @@ main
|
||||
else
|
||||
{
|
||||
// visibility
|
||||
o_game_options[2].nselected = 0 // Default
|
||||
o_game_options[2].nselected = $$g_nRookieVisibility$$ // [RookieMission] ini
|
||||
callback($$SetNetworkMissionParamater$$, visibility, o_game_options[2].nselected)
|
||||
|
||||
// weather
|
||||
o_game_options[3].nselected = 0 // off
|
||||
o_game_options[3].nselected = $$g_nRookieWeather$$ // [RookieMission] ini
|
||||
callback($$SetNetworkMissionParamater$$, weather, o_game_options[3].nselected)
|
||||
|
||||
// time of day
|
||||
o_game_options[4].nselected = 0
|
||||
o_game_options[4].nselected = $$g_nRookieTimeOfDay$$ // [RookieMission] ini
|
||||
callback($$SetNetworkMissionParamater$$, night_parameter, o_game_options[4].nselected)
|
||||
callback($$Shell_CallbackHandler$$, ShellSetTime, o_game_options[4].nselected)
|
||||
}
|
||||
|
||||
// time limit
|
||||
// time limit - use ini override if set, else TIME_VALUE_DEFAULT
|
||||
if $$g_nRookieTimeLimit$$ >= 0
|
||||
temp_num = $$g_nRookieTimeLimit$$ // [RookieMission] ini
|
||||
else
|
||||
temp_num = TIME_VALUE_DEFAULT
|
||||
for k = 0; k < o_game_options[5].list_size; k++
|
||||
{
|
||||
temp_num = makeint(o_game_options[5].list_item[k])
|
||||
if (temp_num == TIME_VALUE_DEFAULT)
|
||||
if (makeint(o_game_options[5].list_item[k]) == temp_num)
|
||||
{
|
||||
o_game_options[5].nselected = k
|
||||
break
|
||||
@@ -935,31 +937,31 @@ main
|
||||
{
|
||||
// radar
|
||||
nTempParam = radar
|
||||
nTempValue = 0 // Novice
|
||||
nTempValue = $$g_nRookieRadar$$ // [RookieMission] ini (0=Novice)
|
||||
o_game_options[6].nselected = nTempValue
|
||||
callback($$SetNetworkMissionParamater$$, nTempParam, nTempValue)
|
||||
|
||||
// heat management
|
||||
nTempParam = HEAT_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieHeat$$ // [RookieMission] ini
|
||||
o_game_options[7].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
// friendly fire
|
||||
nTempParam = FRIENDLY_FIRE_PERCENTGE_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieFriendlyFire$$ // [RookieMission] ini
|
||||
o_game_options[8].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
// splash
|
||||
nTempParam = SPLASH_ON_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieSplash$$ // [RookieMission] ini
|
||||
o_game_options[9].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
// unlimited ammo
|
||||
nTempParam = UNLIMITED_AMMO_PARAMETER
|
||||
nTempValue = 1 // be cautious
|
||||
nTempValue = $$g_nRookieUnlimitedAmmo$$ // [RookieMission] ini
|
||||
o_game_options[10].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
@@ -975,7 +977,7 @@ main
|
||||
|
||||
// weapon jam
|
||||
nTempParam = WEAPON_JAM_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieWeaponJam$$ // [RookieMission] ini
|
||||
o_game_options[14].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
@@ -987,13 +989,13 @@ main
|
||||
|
||||
// advance mode
|
||||
nTempParam = ADVANCE_MODE_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieAdvanceMode$$ // [RookieMission] ini
|
||||
o_game_options[15].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
// armor mode
|
||||
nTempParam = ARMOR_MODE_PARAMETER
|
||||
nTempValue = 0
|
||||
nTempValue = $$g_nRookieArmorMode$$ // [RookieMission] ini
|
||||
o_game_options[16].state = 0
|
||||
callback($$SetNetworkMissionParamater$$,nTempParam, nTempValue)
|
||||
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user