Commit Graph

904 Commits

Author SHA1 Message Date
Evan cb3128f390 Better CrazyGames integration (#3055)
## Description:

Better integration with CrazyGames:

* Don't show login because accounts have not been integrated with
CrazyGames yet
* Integrate CG invite links & usernames
* Refactor match making logic to Matchmaking.ts
* Allow periods to support crazy game usernames
* Create a no-crazygames class that disabled elements when on crazygames

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2026-01-28 11:29:27 -08:00
Evan 3d9f0aec6c Migrate from publift to playwire ads (#3039)
## Description:

Use playwire ad integration

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2026-01-26 13:34:04 -08:00
Mattia Migliorini dfd6a1f5f9 Replace donate buttons with attack ones for AFK friendly players in radial menu (#2987)
Resolves #2986

## Description:

Shows donate actions in radial menu only when friendly player is NOT
disconnected.
This is needed in order to let mobile/touch users attack AFK teammates.

Current behavior:
<img width="525" height="514" alt="image"
src="https://github.com/user-attachments/assets/78b95e27-443a-4dd5-934b-c8a841b4bf97"
/>

With this PR:
<img width="545" height="457" alt="image"
src="https://github.com/user-attachments/assets/e9792478-6ccd-415f-9199-cff7bfc9356f"
/>


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

deshack_82603
2026-01-23 14:18:50 -08:00
FloPinguin c90435fc20 Fix: Nuking an Ally that is Disconnected shows a Red background ghost. Shouldn't be Red as not a Betrayal (#2988)
## Description:

Previous behavior: https://youtu.be/Lv0RuBYh9qw?t=1359

New behavior:


https://github.com/user-attachments/assets/acfcc4f0-157e-44a0-be28-802927a3c787

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-22 14:35:19 -08:00
Vivacious Box ae3adf915c Fix nuke telegraph for allies (#2983)
## Description:

Adds back the nuke overlay for teammates

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Mr. Box
2026-01-21 15:48:52 -08:00
Arkadiusz Sygulski f6454963b2 Pathfinding refinements (#2959)
## Description:

### Short path for multi-source HPA*

Math was not mathing, increased the bounds to 260x260, it is a bit
slower but should work better. The short path was breaking when player
owned a lot of shores. This is because the bounding box of tiles with
less than 120 distance + 10 padding could be as big as 260x260 and the
optimized array was set to 140x140. I made mistake of calculating it as
`2 * (60 + 10)` instead of `2 * (120 + 10)`.

### LoS path refinement

Previously, we ran 2 passes of LoS smoothing on the path. However, since
we are effectively tracing the same path, the line of sight is
essentially the same. This PR makes second line of sight stop on water
tiles with magnitude `n + 1` compared to first path. Practically, this
means it'll attempt LoS exactly 1 tile after previous corner. See
screenshot.

<img width="1299" height="1151" alt="image"
src="https://github.com/user-attachments/assets/726be236-1ff8-406c-896a-02902a762ab0"
/>

### SendBoatAttackIntentEvent

The flow of sending transport ships is currently strange. This PR makes
the flow more sane.

**Old flow**
```
- Player clicks TARGET tile, it can be deep inland
- Client asks Worker for the best START tile to TARGET tile
- Worker answers `false`, since the tile is inland
- Client sends BoatAttackIntent with START=false and TARGET tiles set
- Worker accepts BoatAttackIntent, computes DESTINATION as closest shore to TARGET
- Worker re-computes best START to DESTINATION
- Worker sends boat from START to DESTINATION
```

**New flow**
```
- Player clicks TARGET tile, it can be deep inland
- Client sends BoatAttackIntent with TARGET
- Worker accepts BoatAttackIntent, computes DESTINATION as closest shore to TARGET
- Worker computes START as the best tile to DESTINATION
- Worker sends boat from START to DESTINATION
```

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

moleole
2026-01-19 19:28:45 -08:00
FloPinguin 21a035cdb4 Fix random spawn (#2958)
## Description:

"You can pick your spawn in random spawn games in v29. You need to open
the menu and click on the attack button. That's it."

Thats the fix for this problem.
Radial menu no longer allows to attack (pick a spawn) while random spawn
is enabled.
And SpawnExecution got a check so you cannot send malicious intents.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-19 16:28:14 -08:00
Wraith d2712d2f14 fix: performance overlay positioning (#2943)
## Description:

fix: performance overlay positioning

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081
2026-01-17 13:31:17 -08:00
evanpelle e1d4b9a00e allow name to be placed on shore tiles, this prevents rivers from bisecting player names causing them to be too small 2026-01-15 16:16:33 -08:00
opressorMk2 c40faecb95 Move indicator fx for warships. (#2871)
Been playing this game for months, and after i feel myself enough
experienced about the game, decided to start contributing to the
project. This is my first one!

## Description:

Move indicator fx for warships. Listening MoveWarshipIntentEvent to draw
the fx. Code is basic, respectly layered and written regarding project's
structure.


![warship](https://github.com/user-attachments/assets/7e286e2b-2331-40a3-b62b-ad03dceef676)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

420coder

---------

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-01-14 12:15:40 +00:00
Ryan 247c78151c Discord(et al.) embedded URLs (#2740)
## Description:

Changes URL embeds within other platforms, e.g. Discord, WhatsApp & X.

Updates game URLs to `/game/<code>` instead of `/#join=<code>` (required
for embedded URLs). An added benefit of this is that you would be able
to change a url from `openfront.io/game/RQDUy8nP?replay` to
`api.openfront.io/game/RQDUy8nP?replay` (add api. In front) and be in
the right place for the API data.

Updates URLs when joining/leaving private lobbies

Appends a random string to the end of the URL when inside a private
lobby and options change - this is to force discord to update the
embedded details.

Updates URL in different game states to ?lobby / ?live and ?replay.
These do nothing other than being used as a _cache-busting_ solution.


-----------------------------------------------
### **Lobby Info**

Discord:
<img width="556" height="487" alt="image"
src="https://github.com/user-attachments/assets/efd4a06d-506c-4036-9403-ee7c9a669e21"
/>

WhatsApp:
<img width="353" height="339" alt="image"
src="https://github.com/user-attachments/assets/3b2d0c69-988c-424f-9dee-f4e6a6868f6b"
/>


x.com:
<img width="588" height="325" alt="image"
src="https://github.com/user-attachments/assets/d9e78169-20be-4a3e-8df4-8ad41d08a750"
/>


-------------------------
### **Game Win Details**
Discord:
<img width="506" height="468" alt="image"
src="https://github.com/user-attachments/assets/69947774-c943-4a50-b470-5634ed3bf3d7"
/>

WhatsApp:
<img width="770" height="132" alt="image"
src="https://github.com/user-attachments/assets/eec28bf8-bf64-4ab8-954e-03dfdd1aae40"
/>

x.com
<img width="584" height="350" alt="image"
src="https://github.com/user-attachments/assets/168063e2-b707-422b-b7a1-0025f3ebeb92"
/>


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
2026-01-13 19:48:00 -08:00
FloPinguin 35b7213c5c Enhance nuke alliance breaking logic to account for allied structures in blast radius 💣 (#2887)
## Description:

Doesn't need a description :D


https://github.com/user-attachments/assets/8de576fd-050b-4b35-8526-e4c88d1a9f25


https://github.com/user-attachments/assets/c99147a1-efdf-426b-96d1-e996e01f89aa

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-13 12:30:25 -08:00
evanpelle e246289876 Revert "New Year's Eve FX (#2745)"
This reverts commit ec694593a6.
2026-01-12 20:56:17 -08:00
Arkadiusz Sygulski 0e3ced3bfa Pathfinding Refactor pt. 2 (#2866)
## Playtest

https://pf-pt-2.openfront.dev/

## Pathfinding Refactor pt. 2

<img width="1536" height="1024" alt="image"
src="https://github.com/user-attachments/assets/9477958e-54b7-4c83-b317-ba789e809e9e"
/>


This is a follow-up to a previous PR introducing pathfinding changes.
This time, it introduces a complete refactor of `pathfinding` directory
and breakdown into composable pieces.

### Unified PathFinder interface

`PathFinder<T>` and `SteppingPathFinder<T>` are introduced to unify
**all** pathfinding across the application. First one exposes complete
path, while stepping variant allows the callee to iterate over the path
by calling `.next`. All pathfinders share this one common interface,
which makes them easy to use in any scenario -
`PathFinding.Water(game).search(from, to)`.

`SteppingPathFinder<T>` extends `PathFinder<T>` with an ability to
iterate over the path. It handles caching, storing current index and
invalidation. This allows the units to not care about the inner workings
of the pathfinder and just call `pf.next(current, target)` and receive
instructions on what to do next.

### Common entry point

All pathfinders are now exposed from common `PathFinding` entrypoint:

- `PathFinding.Water`
- `PathFinding.Rail`
- `PathFinding.Stations`
- `PathFinding.Rail`

Additional entry point is introduced for pathfinders which need to work
both in the worker, but also on the frontend, which lacks `Game`
interface. Currently only `UniversalPathFinding.Parabola` is available.

### Spatial Query

New module has been introduced close to `pathfinding` - `SpatialQuery`.
It aims to resolve any questions game may have about finding tiles
meeting criteria. Currently `SpatialQuery.closestShore(player, target)`
and `SpatialQuery.closestShoreByWater(player, target)` are available -
they help answering questions about naval invasion: "What is the best
landing location from user's click?" and "Which our tile should be used
to launch the transport ship?". Under the hood they use very similar
mechanics to pathfinding, so it felt right to put them close by.

### Modular architecture

Pathfinders now support transformers: `MiniMapTransformer`,
`ShoreCoercingTransformer`, `ComponentCheckTransformer`,
`SmoothingTransformer`. Transformers functions like a middleware in the
pathfinding chain. They wrap around the pathfinder and provide
additional functionality. This allows the pathfinder to focus on
actually finding the path instead of doing unrelated things.

Example chain for simple (A*) water pathfinding:
```ts
static WaterSimple(game: Game): SteppingPathFinder<TileRef> {
  const miniMap = game.miniMap();
  const pf = new AStarWater(miniMap);

  return PathFinderBuilder.create(pf)
    .wrap((pf) => new ShoreCoercingTransformer(pf, miniMap))
    .wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap))
    .buildWithStepper(tileStepperConfig(game));
}
```

The Pathfinder - here `AStarWater` - does not care about the conversion
between minimap and main map tiles. It also does not care if the source
or destination is a land tile. The transformers take care of that. The
pathfinder gets a set of valid coordinates and produces the path -
that's it.

Modular approach makes working on a particular set of utilities much
easier - for example map upscaling is handled consistently across all
pathfinders. Additionally, the pathfinders are not tied to the
particular map resolution used. Pass them a different map and they will
work the same.

### Algorithms

Algorithms used are neatly organized inside
`src/core/pathfinding/algorithms`. They are prefixed with the algorithm
name and suffixed with the use case. File without suffix exposes generic
version ready to traverse any graph with adapters. Specialized versions
either use an adapter or inline logic when performance is critical -
using adapters leads to 20-30% performance loss.

The directory includes `A*` and `BFS` but also other useful utils, such
as `AbstractGraph` used to generate... an abstract graph on top of the
tile map and `ConnectedComponents` helping to identify whether two tiles
are connected by a path without actually computing the path.

### Playground

The playground have been updated with new algorithms, including tweaked
very greedy `A*`.

<img width="2175" height="1424" alt="image"
src="https://github.com/user-attachments/assets/1f833651-0024-4299-bf86-882f5368358c"
/>

### Tests

Yeah, there are some, a little too many if I say so myself. But there
are no useless tests. I had to ensure refactored code works somehow
reliably. This PR comes with trust me bro guarantee, but I would
appreciate someone confirming **naval invasions, nukes (esp. MIRV) and
warships**.

### Discord
`moleole`

GL & HF
2026-01-11 20:11:14 -08:00
Ryan 3e661752af UI refinements (#2859)
## Description:

UI Refinements requested by @evanpelle  check https://ui.openfront.dev

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
2026-01-11 14:52:03 -08:00
Mattia Migliorini a4209912a7 Consolidate formatPercentage to Utils (#2852)
## Description:

Removes code duplication by consolidating the `formatPercentage` utility
function to the `Utils.ts` file, removing the two identical
implementations in `TeamStats.ts` and `Leaderboard.ts`.

This is an improvement upon #2838 which is the PR that aligned the two
mentioned implementations.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

deshack_82603
2026-01-10 10:01:06 -08:00
DevelopingTom a26590473c Fix small UI issues (#2845)
## Description:

Changes a few small UI issues:
- Player info text transparency made it less legible:
<img width="367" height="445" alt="image"
src="https://github.com/user-attachments/assets/a08b2808-74a5-4783-93f3-182d97b36055"
/>

- Fix naval invasion target end fade which didn't work previously


![ui_fade](https://github.com/user-attachments/assets/a4867257-0962-4c0d-9e1c-bcac7eba8089)


- Rename rendering function since the UI layer doesn't only handle
target

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2026-01-09 20:39:04 -08:00
Ryan 5e6c90d9bb Main Menu UI Overhaul (#2829)
## Description:

Overhauls the Main Menu UI, visit https://menu.openfront.dev to see
everything.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
2026-01-09 20:26:34 -08:00
Mattia Migliorini cf1e67cd9c Fix team stats owned percentage 100% (#2838)
Resolves #2837

## Description:

This PR aligns the "Owned" percentage format in TeamStats to the same
data in Leaderboard, fixing the issue that currently happens when team
reaches 100%, and the percentage is displayed as "1.0e+2%".

Previous implementation to avoid this problem involved checking for the
"100" value, but we all know how floating point arithmetic works in
JS...

Before:

<img width="912" height="450" alt="image"
src="https://github.com/user-attachments/assets/a3ce03ab-53c6-4b7b-b3fd-7073a6095252"
/>

After:

<img width="441" height="233" alt="image"
src="https://github.com/user-attachments/assets/21b07834-e3ec-44c3-bd6f-3d5a5d6c851c"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

deshack_82603
2026-01-09 10:46:46 -08:00
DevelopingTom 971e7f4a45 Move UI elements from the FX layer to a new UI layer (#2827)
## Description:

Some FX animations were previously used as UI elements (e.g. nuke area,
naval invasion target, gold text).
This PR moves those animations to a dedicated UI layer.

Those UI elements handle correctly the current zoom level and remain
sharply rendered at all zoom levels.

The new UI layer can be disabled using the same setting that disables
the FX layer.

Performance-wise, this layer is equivalent to the FX layer, as it reuses
the same animations.

### Naval target
Don't scale with the zoom level, but has a minimum zoom level so the
targeted tile can still be easily highlighted by zooming


![ui_naval_invasion](https://github.com/user-attachments/assets/43c36c80-ffba-4443-bd53-05617c793fc8)

### Nukes
Has to scale because the size is set, but the border radius is not so
the area is more visible from afar.


![ui_nukes](https://github.com/user-attachments/assets/7ca0685c-0432-4b72-8c6d-48a814a02326)


### Popup text
Scale with zoom level, and stop showing when zoomed-out:

![ui_text](https://github.com/user-attachments/assets/d92c085e-9e20-4cad-bf3a-ae5d320dde33)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2026-01-08 19:21:40 -08:00
bijx c769e4a99a Feat: SAM Radius arcs show when building cities (#2828)
## Description:

Simple PR, but adds the feature where using the hotkey to build a city
will show SAM radius layer to let user know safe areas to build.

<img width="2126" height="1398" alt="image"
src="https://github.com/user-attachments/assets/8aed5514-51c4-40f4-a446-e3c52346abc8"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2026-01-09 01:10:22 +00:00
Mattia Migliorini 2dada6f516 Handle Nation win condition (#2824)
Resolves #2823

## Description:

When playing in single-player mode, if an NPC reaches 80% land control
before the player, the game enters a broken state where:

- The game clock stops
- Win checking stops permanently
- Even if the player later conquers 100% of land, victory is never
awarded
- The game becomes "stuck" in a zombie state.

This PR addresses this allowing Nations to be set as winners in single
mode, and in this case showing a "Nation {nation} has won" modal to the
user. This WinModal is the same as the "{player} has won", with the only
change being the title.

Nation wins in FFA, from the human player perspective:

<img width="1457" height="837" alt="image"
src="https://github.com/user-attachments/assets/1ce569bd-6616-4a23-b4a4-afedad2c64f8"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

deshack_82603
2026-01-08 13:51:23 -08:00
bijx 5d9b834696 Feat: Infocard shows wilderness / irradiated terrain state (#2807)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2516

## Description:

Introduces a state to the Player Info Overlay which simply shows what
type of terrain the player is hovering on. This just builds on the
principles of continuous feedback when designing UX because players
react positively when the game responds to input action.

<img width="839" height="846" alt="image"
src="https://github.com/user-attachments/assets/4b2969e0-127d-4032-9c49-9cbff9bb2aeb"
/>

<img width="666" height="602" alt="image"
src="https://github.com/user-attachments/assets/5fd15ab1-98b1-472f-a83e-a1ee10338673"
/>



https://github.com/user-attachments/assets/7e39f53e-6d2e-479e-badd-b41484591b8b



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2026-01-07 19:49:49 -08:00
aConifer effce3d14a add teammate pulse highlight during spawn phase in team games (#2768)
Adds a pulsing highlight effect for teammates during the spawn phase in
team games. This helps colorblind players identify their teammates on
the map more easily.

- Teammates show a subtle green/team-colored pulse (5-14px radius)
- Player's own pulse remains unchanged (8-24px white pulse)
- Only activates during spawn phase in team games
- Animation stays synchronized with player's own pulse

I didn't want to come empty handed with my request so I generated the
code
I do know python and a little rust, but don't have TypeScript experience
- I know you guys are probably getting flooded with AI slop so I hope
its okay.
Please implement the feature at the very least because its SO much
better not having to hunt around.
🤖 Generated with [Claude Code](https://claude.com/claude-code)

So the code calls drawTeammateHighlights() inside of
drawFocusedPlayerHighlight() so it can only occur where current
highlighting occurs
Then uses the existing isOnSameTeam() to find teammates
Then uses the existing drawBreathingRing() function 


- [x] I have added screenshots for all UI updates
I took a video since it best captures the feature
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
I'm not that good at coding formally, I tested it manually by loading
into team games, but I'm going to need help with the code being tested.
(Please help)
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
I did load into multiple lobbies and made sure the feature works, its a
really simple feature so I am confident there isn't any Lovecraftian bug
lurking in it. It also uses mostly existing functions and features
within the code base.




https://github.com/user-attachments/assets/857cce43-4fb2-4c5d-bc04-1a6617570dee

Co-authored-by: Daniel <daniel@mangoit.ca>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-01-06 14:22:57 -08:00
Wraith e79c805804 refactor(ui): migrate tailwindcss v3 to v4 (#2735)
## Description:

migrate tailwindcss v3 to v4

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-01-06 14:21:52 -08:00
DevelopingTom af0b8a8d50 Configurable immunity timer (#2763)
## Description:

Resolve discussions about stalled PR
https://github.com/openfrontio/OpenFrontIO/pull/2460

<img width="724" height="348" alt="image"
src="https://github.com/user-attachments/assets/c2c9fa79-cace-431a-9ca4-b3656612fa9d"
/>

Changes:
- Added a `Player::canAttackPlayer(other)` function to determine whether
a player can be attacked.
- This function is now used in most places where a fight can occur:
    - AttackExecution (land attacks)
    - Naval invasion
    - Warship fight
- Nukes can't be thrown during the truce
- Immunity only affect human players. Nations and bot will fight as
usual, and can be fought against.
- The immunity timer uses minutes in the modal window.

UI:

- The immunity phase is displayed with a timer bar at the top. This is
from the original PR, to be discussed if it's not deemed visible enough:

<img width="632" height="215" alt="image"
src="https://github.com/user-attachments/assets/f5ab9aa0-bd4f-4503-b8d6-b40b121fba65"
/>


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom

---------

Co-authored-by: newyearnewphil <git@nynp.dev>
2026-01-03 20:04:48 -08:00
Arkadiusz Sygulski ab5b044362 Fix train was destroyed message spam (#2774)
## Description:

Trains are made of a primary unit (`TrainExecution.train`) followed by 6
cars (`TrainExecution.cars`). Currently when any of the units is
destroyed, a message "Your Train was destroyed" is shown. In worst case
scenario, when all cars are blasted by a nuke, 7 messages are displayed
to the user, but the train continues.

Since the actual logic is unaffected as long as the primary unit stays
alive, displaying messages is confusing. This PR fixes it. The message
is only displayed when the primary unit is destroyed. The following cars
are only there for fancy visuals.



## Screencast

##### Current - multiple messages for single train


https://github.com/user-attachments/assets/3df04c71-d899-4f68-af83-36c9d0ffa730

First nuke was a test.
Second nuke destroyed the entire train, prompting 7 messages.
Third nuke destroyed one full train and then some. Prompting many too
many messages.

##### Fixed - one message, only if train was fully destroyed


https://github.com/user-attachments/assets/1f3840a7-6c62-487d-af3a-82de39dad9e8

First train was only partially destroyed, no message was shown, delivery
mission completed A+.
Following 2 trains had the front engine destroyed and therefore were
promptly decommissioned.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

moleole
2026-01-02 18:53:24 -08:00
bijx cdecdc5fa5 Feat: Add troop count bar to PlayerInfoOverlay (#2773)
## Description:

This feature adds a troop count bar into the PlayerInfoOverlay that
visualizes how many troops a player/nation has, how big of an attack
they are sending, and in general the percentages of their overall troop
count. I originally added the toggling of this feature as a setting but
thought it might be too narrow to need it's own setting. Would
appreciate anyone's thoughts on adding it back in or not.

Inspired by [this
comment](https://discord.com/channels/1359946986937258015/1359949371956789289/1452559404401430674)
in the Dev Discord.

### Video Demo


https://github.com/user-attachments/assets/4a4397f7-c0a1-475a-867d-ef00b57661c4



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2026-01-02 16:19:51 -08:00
Ryan 72f8924a7f add mobile bomb flip support (#2737)
closes #2678 

## Description:

Update to enable bomb flip support by mobile users too

<img width="420" height="666" alt="image"
src="https://github.com/user-attachments/assets/eb2155a4-2012-4f40-8caa-bd23ebd28521"
/>


----------------------------------------------------------------------------------------------------------------------------------------------------

Also, I slightly updated the player panel to make it more even and take
up less space;
- removed the huge header bar which took up too much space
- fixed ui divider spacing

Before:
<img width="372" height="179" alt="image"
src="https://github.com/user-attachments/assets/2cf82cda-d466-4911-be4f-36eb6e788d5b"
/>
After:
<img width="383" height="134" alt="image"
src="https://github.com/user-attachments/assets/4d827221-f456-48fe-940b-a9ba84d1f4a5"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
2026-01-02 08:48:24 -08:00
evanpelle f5f89e4aa7 Merge branch 'v28' 2026-01-01 14:25:45 -08:00
DevelopingTom ec694593a6 New Year's Eve FX (#2745)
## Description:

Happy new year! 

- Atom and hydro:


![test_firework](https://github.com/user-attachments/assets/892004fe-372d-4718-9b44-a311049dab20)

- Mirv:


![firework_mirv](https://github.com/user-attachments/assets/10ee4b64-7123-47e2-92d5-7d8fb6cbc992)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2025-12-30 16:10:00 -08:00
DevelopingTom 33deb66ba6 Remove christmas FX (#2744)
## Description:

Santa will be back.

Reverted all FX to the regular theme.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2025-12-30 13:57:35 -08:00
Abdallah Bahrawi 09a1cf885f Add red warning circle when nuke would break alliance (#2728)
## Description:

When placing a nuke (Atom Bomb or Hydrogen Bomb), the range circle now
turns red to warn players when the attack would break an alliance.

<img width="456" height="333" alt="Screenshot 2025-12-28 211927"
src="https://github.com/user-attachments/assets/dfe6f874-3f8b-4662-8877-0af30aa20139"
/>


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

abodcraft1

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-30 17:55:15 +00:00
Evan 4f3d9df46a vite: fix docker build (#2738)
## Description:

The sync-assets wasn't executing on docker-build. so instead just import
it from resources/ directory, vite logs a warning but I think that's
okay for now.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-29 18:37:51 -08:00
Ryan f1561df470 Bomb Direction (#2435)
Resolves #2434 

## Description:

Allows bomb direction to be inverted by pressing a hotkey - currently
"U".

**Check the issue for screenshots / videos.**

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n

---------

Co-authored-by: Evan <evanpelle@gmail.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-29 09:03:46 -08:00
Wraith 26f5d40819 build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)
- Replace Webpack with Vite for faster client bundling and HMR.
- Migrate tests from Jest to Vitest and update configuration.
- Update Web Worker instantiation to standard ESM syntax.
- Implement Env utility in `src/core` for safe, hybrid environment
variable access (Vite vs Node).
- Refactor configuration loaders to remove direct `process.env`
dependencies in shared code.
- Update TypeScript environment definitions and project scripts for the
new toolchain.
- Remove the [depracated usage of the
husky](https://github.com/typicode/husky/releases/tag/v9.0.1).

## Description:

migrate build system to Vite and test runner to Vitest & Remove
depracated husky usage

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
2025-12-28 22:10:26 -08:00
Achim Marius 5a065d71c5 Fix alliance renewal popup not being removed when alliance is broken (#2722)
Resolves #2464

## Description

This PR fixes a bug where the alliance renewal popup remained visible
after an alliance was broken or betrayed.
The issue occurred because renewal UI events were tied to player
identifiers instead of the unique allianceId.
When a player had multiple alliances, breaking one alliance did not
correctly remove the associated renewal popup.
This change ensures that renewal popups are correctly removed only for
the specific alliance that was broken.


### What was wrong
Alliance renewal UI events were previously associated implicitly with
players.
This caused incorrect behavior when a player had **multiple alliances**,
because **players are not unique identifiers of an alliance**.

As a result, breaking one alliance could leave stale renewal popups
visible.

### What was changed
- Alliance break logic now relies on **allianceId**, not player IDs
- Renewal popups are removed **only for the specific broken alliance**
- Alliances involving the same player but different allianceIds are
unaffected
- Added tests to ensure this bug cannot reappear

### Result
- Renewal popup disappears immediately when an alliance is
betrayed/broken
- No unintended removal of other alliance renewal popups
- Correct behavior even when a player is involved in multiple alliances

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

assessin.
2025-12-28 13:35:05 -08:00
bijx 7284ded290 Feat: Quick donate troops via radial menu (#2708)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2705 

## Description:

Introduces a quick donation feature in games where the `canDonateTroops`
option is enabled. It works by converting the center button in the
radial menu from a disabled attack button to a troop donate button when
the player right clicked on is friendly (teammate or ally).

Also adds donate gold button to Attack slot on radial menu when right
clicking friendly troops.

### Video Example


https://github.com/user-attachments/assets/d9b2c3f7-b6c0-482a-9dbd-b3841676cbe5

### New Icon
<img width="1310" height="931" alt="image"
src="https://github.com/user-attachments/assets/85225858-6971-470d-92f6-db68a5d05bb2"
/>

### Donate Gold


https://github.com/user-attachments/assets/b116bc06-d53d-47c7-9504-871eada6a21e


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-27 13:05:02 -08:00
YoussfeCantCode 7339c968c9 uniformed HeadsUpMessage text (#2710)
## Description:

Moves pause-related translation keys from their own object into
```heads_up_message``` to keep all heads-up message text in one place.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

furo18
2025-12-27 11:52:11 -08:00
YoussfeCantCode 1c52d20e83 Added pause functionality for private multiplayer games (#2657)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2491

## Description:
Adds pause/unpause functionality for private multiplayer games. Only the
lobby creator can pause the game, and all players see a pause overlay
when the game is paused.

  **Key features:**
- Lobby creator sees pause/play button in control panel (alongside
existing singleplayer/replay controls)
  - Server validates that only lobby creator can toggle pause
  - All players see "Game paused by Lobby Creator" overlay when paused
  - Game state freezes (no turn execution) while paused
  - Unpause resumes normal gameplay

  **Implementation details:**
- Server-side pause state (`isPaused`) prevents turn execution during
pause
- Each client receives `isLobbyCreator` flag in `GameStartInfo` to
show/hide pause button
- Added `TogglePauseIntent` that broadcasts to all clients via
`NoOpExecution`
  - New `PauseOverlay` component (shows in single player also)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

furo18

<img width="1459" height="861" alt="Screenshot 2025-12-20 at 15 16 33"
src="https://github.com/user-attachments/assets/f5a3222f-f54b-473c-b0f6-104ce4c1e7a8"
/>
2025-12-26 10:21:18 -08:00
scamiv 7f3ca3c97e Update GameRenderer to disable alpha channel in GameRenderer 2D context (#2699)
## Description:

Updated the main onscreen canvas context to opaque: 
Impact: avoids alpha compositing for the main canvas (we already paint a
full opaque background each frame), which can slightly reduce GPU work.

## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [ ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

DISCORD_USERNAME
2025-12-26 10:11:05 -08:00
scamiv 6ce6e16837 make TerrainLayer opaque (alpha:false) (#2700)
## Description:

Make the terrain backing canvas explicitly opaque by requesting a 2D
context with alpha: false.
Remove confusing latent alpha support in TerrainLayer

Current themes always generate opaque terrain colors, but the code
previously looked like it supported per-tile alpha (via
terrainColor.rgba.a), which is misleading.
Being explicit about opacity can avoid unnecessary alpha compositing
work and clarifies intent.

No visual change expected with current themes (terrain was already
effectively opaque).

## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [ ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

DISCORD_USERNAME
2025-12-26 10:09:57 -08:00
evanpelle fcabf49a74 Merge branch 'v28' 2025-12-25 12:49:12 -08:00
Evan a810e0ad34 crazy games integrations (#2675)
## Description:

Integrate with crazy games SDK

## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [ ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-23 09:11:00 -08:00
DevelopingTom 3612667bcd Improve SAM Radius layer rendering and performances (#2667)
## Description:

This PR updates the SAM radius layer to render sharply at all zoom
levels instead of pixelated.


![cleam_sam](https://github.com/user-attachments/assets/9e1a23e1-ea47-428f-a3a5-635874b3029c)

The radius is now drawn using primitives directly on the parent
rendering context, rather than via an intermediary canvas and
`drawImage`.

### Performance improvement:

Since the radius computation is quite heavy, it could lead to bad
performances previously because radii were recomputed and redrawn on
every frame.
With 1k SAM:

<img width="559" height="33" alt="image"
src="https://github.com/user-attachments/assets/207e4fca-2b30-4a32-a69b-be3aacc3d7cf"
/>


This PR separates radius computation from rendering:
- radius values are now recomputed only on the first frame after a SAM
changes.
- subsequent frames reuse the cached results and only handle rendering.

Now with 1k SAM:

<img width="624" height="67" alt="image"
src="https://github.com/user-attachments/assets/9facdf04-1dc2-4908-8ebc-fd80933f0232"
/>



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2025-12-21 14:59:38 -08:00
bijx 4ee3319397 Feat: Added cursor price option to user and basic settings (#2655)
## Description:

Following the hotkey cursor price textbox addition of #2650, this
feature adds the option to enable and disable the visual feature via the
User Settings menu or the Basic Settings modal in game. Also added a
[new icon](https://thenounproject.com/icon/pay-per-click-2586454/) for
the Basic Settings modal from the Noun Project and added credit for it
to the `CREDITS.md` file.

### Video Demo


https://github.com/user-attachments/assets/1667081e-45e3-4b11-9bda-3f00c341e03c

### User Settings Menu
<img width="1029" height="1436" alt="image"
src="https://github.com/user-attachments/assets/e4e6bf6d-db59-463a-81fb-f622ef6e3931"
/>

### Basic Settings Menu
<img width="964" height="1545" alt="image"
src="https://github.com/user-attachments/assets/6b083655-b96e-4937-95d6-f3458858f03d"
/>



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-20 11:09:44 -08:00
bijx 4e8aa1f066 Feat: Add cost to ghost structure icon when using keyboard shortcuts (#2650)
## Description:

Introduces a dynamic textbox under the cursor and populates it with
price when a keyboard hotkey is pressed. Prices update correctly based
on current value of the structure or strike being purchased, even if the
value is 0 (during `Infinite Gold` mode). Price value updates live even
if the price box is currently being shown (for example, when voluntarily
removing a structure causes the price to change. See video below).

### Video Demo 


https://github.com/user-attachments/assets/3f974268-c14b-4129-9629-5a0f7db8b30c


The more in depth demo was too big for GitHub, but I uploaded it on the
Discord

https://discord.com/channels/1284581928254701718/1447907175522504704/1451483322260914297

### Live price updates on tooltip


https://github.com/user-attachments/assets/0d98739c-6f24-4fcd-a047-cc304e7e86aa

### Works with `Infinite Gold` mode


https://github.com/user-attachments/assets/25bd2919-77cd-4735-8c3f-043306f53b8f




## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-19 19:06:21 -08:00
Mateusz Żołdak b63744834d fix: area right from control-panel is clickable (#2640)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #[2638](https://github.com/openfrontio/OpenFrontIO/issues/2638)

## Description:

Describe the PR.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Not on discord yet, but this bug makes me crazy. :)

Edit:
Also, I wasn't sure from which branch to start from.
2025-12-18 16:21:27 -08:00
FloPinguin 4d5bb7a835 Cleanup nations (Part 1) 🧹 (#2637)
## Description:

1. Using the wording `"Nation"`, `"FakeHuman"` and `"NPC"` at the same
time is confusing.
So I renamed every mention of `"FakeHuman"` and `"NPC"` in the entire
project to `"Nation"`. Just like they are called ingame.

2. `BotBehavior.ts` was originally intended for sharing the logic
between nations and bots.
But at the moment, the logic there isn't really shared and it's
basically just about attacking.
So I renamed `BotBehavior.ts` to `AiAttackBehavior.ts`. I use "Ai" to
indicate that this file is used by bots AND nations.

3. Moved `execuction/utils/AllianceBehavior.ts` to
`execuction/nation/NationAllianceBehavior.ts` to make sure everybody
understands that this file is not about alliances in general. It's just
about nations and how they handle alliances.

4. Removed `difficultyModifier` from `DefaultConfig`. It's unused and I
think we usually want to finetune the difficulty instead of using that
method.

5. Added `assertNever` in all `switch (difficulty)` default cases.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-18 16:20:23 -08:00
evanpelle f4ed2a932f remove ofm advert in winmodal 2025-12-18 11:06:28 -08:00