Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
74cf37a
Read RepairOtherVehicles and add cargo row and ejection seat counts
jaymar921 Oct 31, 2026
d3a4aed
Add the supply rules for fuel slots, ammunition trucks and repair veh…
jaymar921 Oct 31, 2026
f9f09a6
Test the fuel, ammunition and repair supply amounts
jaymar921 Oct 31, 2026
b8f2586
Test the inventory and supply definition keys
jaymar921 Oct 31, 2026
8619200
Add the vehicle inventory with fuel and parachute slots and the cargo…
jaymar921 Oct 31, 2026
7d82cc6
Resupply one weapon at a time, only while the vehicle is on the ground
jaymar921 Oct 31, 2026
5974f40
Add the vehicle screen menu
jaymar921 Oct 31, 2026
68093c5
Register the vehicle menu type
jaymar921 Oct 31, 2026
fbc4052
Declare the menu types at startup
jaymar921 Oct 31, 2026
756f95e
Give vehicles an inventory, supply vehicles and parachute-limited eje…
jaymar921 Oct 31, 2026
f8e3afb
Replace the resupply action with opening the vehicle screen
jaymar921 Oct 31, 2026
55c57cf
Bump the network protocol to 8
jaymar921 Oct 31, 2026
eb5df87
Add the vehicle screen
jaymar921 Oct 31, 2026
2585f72
Replace the resupply key with the vehicle screen key
jaymar921 Oct 31, 2026
124f342
Open the vehicle screen from its key
jaymar921 Oct 31, 2026
6878a26
Drop the resupply key handling
jaymar921 Oct 31, 2026
3e492f6
Point the empty magazine hint at the vehicle screen key
jaymar921 Oct 31, 2026
9d7cc59
Add the thermal view shader
jaymar921 Oct 31, 2026
e807cc4
Add the thermal view post effect
jaymar921 Oct 31, 2026
54af1e7
Add thermal view as the third camera mode
jaymar921 Oct 31, 2026
54142d9
Register the vehicle screen and keep the thermal filter applied
jaymar921 Oct 31, 2026
808bbc6
Register menu screens during Forge client setup
jaymar921 Oct 31, 2026
241a832
Pass the mod bus to the Forge client setup
jaymar921 Oct 31, 2026
b907a54
Describe the fuel slots in the fuel can documentation
jaymar921 Oct 31, 2026
f0f553b
Add English text for the vehicle screen, thermal view and parachute m…
jaymar921 Oct 31, 2026
eb86552
Add Japanese text for the vehicle screen, thermal view and parachute …
jaymar921 Oct 31, 2026
786e85b
Document InventorySize, supply ranges, RepairOtherVehicles and ejecti…
jaymar921 Oct 31, 2026
a82bf92
Describe the vehicle inventory, the vehicle screen and thermal view
jaymar921 Oct 31, 2026
6883096
Add the phase 9 checklist and move resupply to the vehicle screen
jaymar921 Oct 31, 2026
f861944
Tick thermal view, the vehicle inventory and resupply in phase 9
jaymar921 Oct 31, 2026
4b8ef29
Document the vehicle screen, cargo chest and thermal view for players
jaymar921 Oct 31, 2026
5a167b0
Add the unreleased phase 9 changes to the changelog
jaymar921 Oct 31, 2026
463c1eb
Keep helicopters level while they stand on the ground
jaymar921 Oct 31, 2026
8f4e613
Show fuel as a percentage and gauge, and give long vehicle names room
jaymar921 Oct 31, 2026
69054b1
Word the vehicle screen fuel label as a percentage
jaymar921 Oct 31, 2026
30a0268
Word the Japanese vehicle screen fuel label as a percentage
jaymar921 Oct 31, 2026
9d1330b
Add the thermal view screenshot
jaymar921 Oct 31, 2026
00c0d8e
Add the vehicle screen screenshot with an empty reserve
jaymar921 Oct 31, 2026
3113bb5
Add the vehicle screen screenshot after a reload
jaymar921 Oct 31, 2026
1f17f42
Add the ejection seat screenshot
jaymar921 Oct 31, 2026
beb5d09
Add the open ejection parachute screenshot
jaymar921 Oct 31, 2026
5a5ccec
Add the cargo chest screenshot
jaymar921 Oct 31, 2026
d15f1f9
Show the phase 9 screenshots in the README
jaymar921 Oct 31, 2026
01905ee
Check that helicopters stay level on the ground and the fuel gauge fills
jaymar921 Oct 31, 2026
8d94ab1
Note that betas 4 to 8 build only the Forge 26.3 jar
jaymar921 Oct 31, 2026
e4e59b6
Mark phase 9 as released in beta.5 and move the open equipment to pha…
jaymar921 Oct 31, 2026
1599089
Release the changelog section as 1.1.0-beta.5
jaymar921 Oct 31, 2026
7ed49cb
Set the version to 1.1.0-beta.5
jaymar921 Oct 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,43 @@ All notable changes to this project are documented here. The format follows
[Semantic Versioning](https://semver.org/). Pre-releases (`1.0.0-alpha.N`) mark the phases on the
way to 1.0.0; see [docs/ROADMAP.md](docs/ROADMAP.md).

## [1.1.0-beta.5] - 2026-10-31

Phase 9 of the road to 1.1.0: the vehicle screen and what goes with it, supply vehicles and
thermal view. Betas are not uploaded to CurseForge, and this one ships the Forge 26.3 jar only.
Worlds from 1.1.0-beta.4 load as before; their vehicles come back with empty slots. Players and
servers need the same version, since the network protocol changed.

### Added

- The vehicle screen, on I in any seat (the original's GUI key, R, switches seats here). It has
three fuel slots that empty fuel cans into the tank while the vehicle stands on something, a
parachute slot for each ejection seat, and a weapon panel that shows every weapon's rounds and
reload cost and reloads it from your own items. Closing it after a reload loads every magazine.
- The cargo chest of vehicles with an `InventorySize`, from the vehicle screen's Cargo button or
with Shift + right-click on the vehicle from outside. Sizes between rows round up to a whole row.
What a vehicle carries drops when it is destroyed or packed up.
- Ammunition trucks (`AmmoSupplyRange`) rearm every vehicle around them that stands on something,
a tenth of each weapon's maximum every two seconds.
- Repair vehicles: `RepairOtherVehicles = range[, value]` mends every vehicle in range by `value`
hit points a second (10 by default). None of the original vehicles uses it; packs can.
- Thermal view: K now steps from night vision to a white hot thermal view with outlines and back
to normal. The HUD's `cam_mode` reads 2 in it, as in the original. The original's vanilla
"pencil" shader no longer exists, so the filter is our own.

### Changed

- Ejection seats need a parachute in the vehicle screen's parachute slots, one per ejection, as in
the original. Without one the seat stays put and says so. Creative players need none.
- Reloading a weapon from your inventory moved from the N key to the vehicle screen and only works
on the ground, as in the original. The empty magazine hint on the HUD names the new key.
- The network protocol is now version 8.

### Fixed

- A helicopter on the ground no longer tilts with the pilot's mouse; it stays level until it
lifts off.

## [1.1.0-beta.4] - 2026-10-30

Phase 8 of the road to 1.1.0: fuel, the first equipment carried over from phase 4, hit boxes that
Expand Down Expand Up @@ -515,6 +552,7 @@ Phase 1: foundation and flyable helicopters.
- Free look moved from Left Ctrl to Left Alt, because Left Ctrl is now the vanilla sprint key.
- Roll damping runs per tick instead of per frame, so handling no longer depends on frame rate.

[1.1.0-beta.5]: https://github.com/JnH-Projects/MCHeli-Rework-Forge/releases/tag/v1.1.0-beta.5
[1.1.0-beta.4]: https://github.com/JnH-Projects/MCHeli-Rework-Forge/releases/tag/v1.1.0-beta.4
[1.1.0-beta.3]: https://github.com/JnH-Projects/MCHeli-Rework-Forge/releases/tag/v1.1.0-beta.3
[1.1.0-beta.2]: https://github.com/JnH-Projects/MCHeli-Rework-Forge/releases/tag/v1.1.0-beta.2
Expand Down
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ Phase 4 clips (click a picture to open the video):

## Screenshots

Phase 9 in a development build (`1.1.0-beta.5`): thermal view, the vehicle screen, ejection seats
with parachutes from the vehicle, and cargo.

| | |
|---|---|
| ![The AH-64 cockpit in thermal view: the desert in white hot greys with outlines, the green HUD reading THERMAL VISION](docs/images/phase-9/ah-64-thermal-view.png) | ![The cargo chest of a B1 Centauro, two rows of slots above the player inventory](docs/images/phase-9/centauro-cargo-chest.png) |
| Thermal view from the AH-64's cockpit | The Centauro's cargo chest, opened from outside |
| ![The AH-64's vehicle screen: fuel slots on the left, the M230 chain gun at 15 of 1200 rounds with its reload cost of iron and gunpowder](docs/images/phase-9/vehicle-screen-empty-reserve.png) | ![The same screen after reloading, the chain gun at 1200 of 1200 in green and the Reload button greyed out](docs/images/phase-9/vehicle-screen-reloaded.png) |
| The vehicle screen with the chain gun's reserve empty | Reloaded from the player's own iron and gunpowder |
| ![A player in an ejection seat climbing away above a desert lake after leaving an F-35B](docs/images/phase-9/ejection-seat.png) | ![Looking down the parachute's rigging lines at the player in the seat, the F-35B and an AH-64 below](docs/images/phase-9/ejection-parachute-open.png) |
| Ejecting from an F-35B, with a parachute from its slot | The canopy opens once the seat falls |

Phase 8 in a development build (`1.1.0-beta.4`): hit boxes that cover the whole vehicle, and shot
down planes that spiral in.

Expand Down Expand Up @@ -228,7 +240,8 @@ to climb.
| J | Load nearby vehicles onto your racks, or drive onto a carrier's rack |
| U | Unload the last vehicle from your racks, or leave the carrier |
| Z | Through a camera, gunner sight or gunner mode: zoom (2x, 4x and so on up to the vehicle's limit, then back) |
| K | Night vision on and off, in vehicles that have it |
| K | Night vision, then thermal view, then back to normal, in vehicles that have night vision |
| I | The vehicle screen: fuel and parachute slots, reloading, and the cargo chest |
| Shift | Leave the vehicle |

**Weapons**
Expand All @@ -239,7 +252,6 @@ to climb.
| Middle mouse or G | Next weapon for your seat; with Shift, the previous one |
| X | Fire mode, for weapons that have one (HE rounds, top attack, TV guidance) |
| C | Release flares (pilot and first crew seat) |
| N | Resupply the selected weapon, paying its item cost from your inventory |

Each seat fires the weapons its vehicle assigns to it; the pilot also fires a gunner's weapons
while that seat has no player. Creative players have unlimited ammunition. A small readout at the
Expand All @@ -249,12 +261,18 @@ bottom right shows hit points, the weapon, ammunition, reload, heat, lock and fl

Vehicles burn fuel while the throttle is open; the HUD shows the tank and warns below 10%. With
an empty tank the engine winds down. Refuel with the **fuel can** from the Equipment tab:
right-click a vehicle to pour in up to 100 units, and right-click in the air with coal or
charcoal in your inventory to fill the can again. A fuel truck tops up every vehicle around it.
The **wrench** repairs 10 hit points per click, once a second; with Shift it switches the
vehicle's paint. The **parachute** opens when used in mid-air; hold W to glide forward.
Ejection seats come down on a parachute of their own. All three are crafted with the original's
recipes.
right-click a vehicle to pour in up to 100 units, or put cans in the fuel slots of the vehicle
screen (I), which empty into the tank while the vehicle is on the ground. Right-click in the air
with coal or charcoal in your inventory to fill a can again. A fuel truck tops up every vehicle
around it, and an ammunition truck rearms them. The **wrench** repairs 10 hit points per click,
once a second; with Shift it switches the vehicle's paint. The **parachute** opens when used in
mid-air; hold W to glide forward. Ejection seats need a parachute in the vehicle screen's
parachute slots, one per ejection. All three are crafted with the original's recipes.

The vehicle screen also reloads weapons from your own items, one supply per click, while the
vehicle is on the ground; closing it loads every magazine. Vehicles with cargo space have a
**Cargo** button there, and Shift + right-click opens their cargo chest from outside. What a
vehicle carries drops when it is destroyed.

## Commands and server settings

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public abstract class AircraftDefinition extends Definition {
public float fuelConsumption = 1.0F;
public float fuelSupplyRange;
public float ammoSupplyRange;
/** {@code RepairOtherVehicles}: how far this vehicle repairs others, and by how much a second. */
public float repairOtherVehiclesRange;
public int repairOtherVehiclesValue = 10;
public int inventorySize;

// Body and physics
Expand Down Expand Up @@ -268,6 +271,26 @@ public int seatCount() {
return seats.size();
}

/**
* Rows of the cargo chest: {@code InventorySize} rounded up to whole rows of nine, the only
* sizes a chest screen comes in. Zero means the vehicle has no chest.
*/
public int cargoRows() {
return (inventorySize + 8) / 9;
}

/**
* Seats that can bail out, one parachute slot each in the vehicle screen: seats zero and one
* with {@code EnableEjectionSeat}, except the pilot seat of a drone, whose pilot is not aboard.
*/
public int ejectionSeats() {
if (!ejectionSeat) {
return 0;
}
int seats = Math.min(seatCount(), 2);
return uav && seats > 0 ? seats - 1 : seats;
}

/** Crew seats followed by racks, the index space used by {@code ExclusionSeat} and the seat map. */
public int seatAndRackCount() {
return seats.size() + racks.size();
Expand Down Expand Up @@ -312,6 +335,13 @@ protected void registerKeys(KeyTable keys) {
keys.put("FuelConsumption", v -> fuelConsumption = toFloat(v, 0.0F, 10000.0F));
keys.put("FuelSupplyRange", v -> fuelSupplyRange = toFloat(v, 0.0F, 1000.0F));
keys.put("AmmoSupplyRange", v -> ammoSupplyRange = toFloat(v, 0.0F, 1000.0F));
keys.put("RepairOtherVehicles", v -> {
String[] s = split(v);
repairOtherVehiclesRange = toFloat(s[0], 0.0F, 1000.0F);
if (s.length >= 2) {
repairOtherVehiclesValue = toInt(s[1], 0, 10000000);
}
});
keys.put("InventorySize", v -> inventorySize = toInt(v, 0, 54));

keys.put("Width", v -> bodyWidth = toFloat(v, 0.1F, 1000.0F));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.jnhprojects.mcheli.supply;

/**
* How much fuel, ammunition and repair one supply step moves, after the original's
* {@code updateFuel}, {@code supplyAmmoToOtherAircraft} and {@code repairOtherAircraft}. Kept apart
* from the entities so the numbers can be checked without a game.
*/
public final class SupplyRules {
/** The most a fuel slot pours into the tank per step, every half second. */
public static final int FUEL_SLOT_POUR = 100;
/** Ticks between two steps of the fuel slots: half a second. */
public static final int FUEL_SLOT_INTERVAL = 10;
/** Ticks between two rounds of resupply from an ammunition truck: two seconds. */
public static final int AMMO_TRUCK_INTERVAL = 40;
/** Ticks between two repairs from a repair vehicle: one second. */
public static final int REPAIR_INTERVAL = 20;

private SupplyRules() {
}

/**
* Fuel one slot pours this step.
*
* @param missing room left in the tank
* @param contents fuel left in the can
*/
public static int fuelFromCan(int missing, int contents) {
return Math.max(Math.min(Math.min(missing, FUEL_SLOT_POUR), contents), 0);
}

/**
* Rounds an ammunition truck adds to one weapon per step: a tenth of the weapon's
* {@code MaxAmmo}, at least one, and never past the maximum.
*
* @param carried magazine and reserve together
*/
public static int roundsFromTruck(int carried, int maxAmmo) {
if (carried >= maxAmmo) {
return 0;
}
return Math.min(Math.max(maxAmmo / 10, 1), maxAmmo - carried);
}

/** Hit points a repair vehicle gives back per step, never past the maximum. */
public static int repair(int hp, int maxHp, int value) {
return Math.max(Math.min(value, maxHp - hp), 0);
}
}
13 changes: 10 additions & 3 deletions common/src/main/resources/assets/mcheli/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
"entity.mcheli.torpedo": "Torpedo",
"entity.mcheli.tv_missile": "TV-Guided Missile",
"entity.mcheli.vehicle": "Ground Vehicle",
"gui.mcheli.vehicle.cargo": "Cargo",
"gui.mcheli.vehicle.fuel": "Fuel %s%%",
"gui.mcheli.vehicle.no_weapons": "No weapons",
"gui.mcheli.vehicle.parachute": "Parachutes",
"gui.mcheli.vehicle.reload": "Reload",
"gui.mcheli.vehicle.reload_hint": "Land to reload",
"hud.mcheli.ammo": "%s / %s",
"hud.mcheli.ammo_infinite": "%s / Infinite",
"hud.mcheli.ammo_none": "No ammunition needed",
Expand All @@ -41,7 +47,7 @@
"hud.mcheli.overheat": "OVERHEAT",
"hud.mcheli.preparing": "Preparing",
"hud.mcheli.reloading": "Reloading",
"hud.mcheli.resupply": "Empty, resupply with [%s]",
"hud.mcheli.resupply": "Empty, reload on the ground [%s]",
"item.mcheli.helicopter": "Helicopter",
"item.mcheli.plane": "Plane",
"item.mcheli.tank": "Tank",
Expand All @@ -52,21 +58,22 @@
"itemGroup.mcheli.tanks": "MCHeli Tanks and Cars",
"itemGroup.mcheli.vehicles": "MCHeli Ground Vehicles",
"key.category.mcheli.main": "MCHeli",
"key.mcheli.camera_mode": "Night Vision",
"key.mcheli.camera_mode": "Night Vision / Thermal",
"key.mcheli.flare": "Flares",
"key.mcheli.fold": "Zoom / Fold Wings / Hatch",
"key.mcheli.free_look": "Free Look",
"key.mcheli.landing_gear": "Landing Gear",
"key.mcheli.rack_load": "Load Rack / Board Carrier",
"key.mcheli.rack_unload": "Unload Rack / Leave Carrier",
"key.mcheli.resupply": "Resupply Weapon",
"key.mcheli.switch_camera": "Camera / Gunner Sight",
"key.mcheli.switch_seat": "Switch Seat",
"key.mcheli.switch_weapon": "Switch Weapon",
"key.mcheli.vehicle_screen": "Vehicle Screen",
"key.mcheli.vtol": "VTOL Mode",
"key.mcheli.weapon_mode": "Weapon Mode",
"message.mcheli.content.import_failed": "MCHeli could not import the original vehicles: %s. See logs/latest.log.",
"message.mcheli.content.missing": "MCHeli has no vehicles yet. Download %s from the MCHeli CurseForge page, put it in %s and restart the game.",
"message.mcheli.no_parachute": "No parachute in the vehicle: put one in its parachute slot first",
"message.mcheli.pack.downloading": "MCHeli: downloading %s content packs (%s MB) from the server",
"message.mcheli.pack.failed": "MCHeli: content pack %s could not be downloaded: %s",
"message.mcheli.pack.more_problems": "MCHeli: and %s more problems with content packs, see logs/latest.log",
Expand Down
10 changes: 9 additions & 1 deletion common/src/main/resources/assets/mcheli/lang/ja_jp.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
"entity.mcheli.plane": "飛行機",
"entity.mcheli.tank": "戦車",
"entity.mcheli.vehicle": "地上兵器",
"gui.mcheli.vehicle.cargo": "積荷",
"gui.mcheli.vehicle.fuel": "燃料 %s%%",
"gui.mcheli.vehicle.no_weapons": "武装なし",
"gui.mcheli.vehicle.parachute": "パラシュート",
"gui.mcheli.vehicle.reload": "補給",
"gui.mcheli.vehicle.reload_hint": "着陸すると補給できます",
"item.mcheli.helicopter": "ヘリコプター",
"item.mcheli.plane": "飛行機",
"item.mcheli.tank": "戦車",
Expand All @@ -14,17 +20,19 @@
"itemGroup.mcheli.tanks": "MCHeli 戦車・車両",
"itemGroup.mcheli.vehicles": "MCHeli 地上兵器",
"key.category.mcheli.main": "MCHeli",
"key.mcheli.camera_mode": "暗視",
"key.mcheli.camera_mode": "暗視 / 熱線映像",
"key.mcheli.fold": "ズーム / 翼・ハッチの折りたたみ",
"key.mcheli.free_look": "フリールック",
"key.mcheli.landing_gear": "着陸脚",
"key.mcheli.rack_load": "ラックに積載 / 搭載",
"key.mcheli.rack_unload": "ラックから降ろす / 離脱",
"key.mcheli.switch_camera": "カメラ / 照準切り替え",
"key.mcheli.switch_seat": "座席切り替え",
"key.mcheli.vehicle_screen": "機体画面",
"key.mcheli.vtol": "VTOLモード",
"message.mcheli.content.import_failed": "MCHeli: 元の機体データを読み込めませんでした: %s。logs/latest.log を確認してください。",
"message.mcheli.content.missing": "MCHeli: 機体データがありません。MCHeli の CurseForge ページから %s をダウンロードし、%s に置いてからゲームを再起動してください。",
"message.mcheli.no_parachute": "機体にパラシュートがありません。先にパラシュート欄に入れてください",
"message.mcheli.pack.downloading": "MCHeli: サーバーからコンテンツパックを %s 個 (%s MB) ダウンロードしています",
"message.mcheli.pack.failed": "MCHeli: コンテンツパック %s をダウンロードできませんでした: %s",
"message.mcheli.pack.ready": "MCHeli: コンテンツパック %s 個のダウンロードが完了しました",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ void appliesHelicopterDefaults() throws IOException {
assertEquals(List.of("heli", "heli_gnr"), def.huds);
}

@Test
void readsInventoryAndSupplyKeys() throws IOException {
HelicopterDefinition def = parse("cargo", """
AddSeat = 0, 1, 0
AddSeat = 0, 1, 1
AddSeat = 0, 1, 2
InventorySize = 10
EnableEjectionSeat = true
RepairOtherVehicles = 20, 5
""");

// Ten slots need two rows of nine; only seats zero and one have ejection seats.
assertEquals(2, def.cargoRows());
assertEquals(2, def.ejectionSeats());
assertEquals(20.0F, def.repairOtherVehiclesRange);
assertEquals(5, def.repairOtherVehiclesValue);

HelicopterDefinition bare = parse("bare", "AddSeat = 0, 1, 0");
assertEquals(0, bare.cargoRows());
assertEquals(0, bare.ejectionSeats());
assertEquals(10, bare.repairOtherVehiclesValue);
}

@Test
void rejectsDefinitionWithoutSeats() throws IOException {
DefinitionReader.Result<HelicopterDefinition> result = parseResult("empty", "DisplayName = Nothing");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.jnhprojects.mcheli.supply;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class SupplyRulesTest {

@Test
void fuelSlotPoursAtMostOneHundred() {
assertEquals(100, SupplyRules.fuelFromCan(450, 600));
assertEquals(30, SupplyRules.fuelFromCan(30, 600));
assertEquals(12, SupplyRules.fuelFromCan(450, 12));
assertEquals(0, SupplyRules.fuelFromCan(0, 600));
assertEquals(0, SupplyRules.fuelFromCan(450, 0));
}

@Test
void ammunitionTruckAddsATenthOfTheMaximum() {
assertEquals(40, SupplyRules.roundsFromTruck(0, 400));
// Never past the maximum, and at least one round for small magazines.
assertEquals(10, SupplyRules.roundsFromTruck(390, 400));
assertEquals(1, SupplyRules.roundsFromTruck(2, 4));
assertEquals(0, SupplyRules.roundsFromTruck(400, 400));
}

@Test
void repairStopsAtFullHealth() {
assertEquals(10, SupplyRules.repair(50, 100, 10));
assertEquals(3, SupplyRules.repair(97, 100, 10));
assertEquals(0, SupplyRules.repair(100, 100, 10));
}
}
Loading
Loading