Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
cbd1389
lobby fill time added to stats
ryanbarlow97 Nov 4, 2025
2842bd4
Merge branch 'main' into lobbytime
ryanbarlow97 Nov 5, 2025
a539ae4
Merge branch 'main' into lobbytime
ryanbarlow97 Nov 5, 2025
0af2e96
Merge branch 'main' into lobbytime
ryanbarlow97 Nov 6, 2025
d5f990d
Merge branch 'main' into lobbytime
ryanbarlow97 Nov 7, 2025
1d96e75
Merge branch 'main' into lobbytime
evanpelle Nov 8, 2025
e562a91
removed changes to compress in localserver
ryanbarlow97 Nov 9, 2025
146342b
Directional Bombs - Press "U"
ryanbarlow97 Nov 11, 2025
b188c75
Merge branch 'openfrontio:main' into swapdirection
ryanbarlow97 Nov 11, 2025
28b8069
remove incorrect comment
ryanbarlow97 Nov 11, 2025
d755514
Merge branch 'swapdirection' of https://github.com/ryanbarlow97/OpenF…
ryanbarlow97 Nov 11, 2025
60ddacf
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 11, 2025
17c10a9
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 11, 2025
1cddfcd
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 11, 2025
18845ef
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 13, 2025
2a07538
added instructions for new mechanic to hotkeys list
ryanbarlow97 Nov 14, 2025
6b12c03
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 15, 2025
ea6a05b
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 17, 2025
2973fb9
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 18, 2025
d37ffc4
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 19, 2025
78566c7
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 19, 2025
895f9ee
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 20, 2025
a209e7f
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 21, 2025
b55aae5
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 22, 2025
de4f36f
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 24, 2025
90734fa
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 25, 2025
487c2fe
Merge branch 'main' into swapdirection
ryanbarlow97 Nov 26, 2025
c72eeb9
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 1, 2025
fdafa19
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 2, 2025
95a5850
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 4, 2025
9fbf157
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 7, 2025
056cdd0
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 8, 2025
9a7944b
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 11, 2025
bf862f5
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 16, 2025
16988c4
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 18, 2025
ef9a24a
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 22, 2025
6263448
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 27, 2025
1b4ba4d
Merge branch 'main' into swapdirection
ryanbarlow97 Dec 28, 2025
fa4cec2
Merge branch 'main' into swapdirection
iiamlewis Dec 28, 2025
db8e057
Merge branch 'openfrontio:main' into swapdirection
ryanbarlow97 Dec 29, 2025
22b0e74
use within
ryanbarlow97 Dec 29, 2025
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
3 changes: 2 additions & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@
"icon_embargo": "Dollar stop sign - Embargo. This player has stopped trading with you automatically or manually.",
"icon_request": "Envelope - Alliance request. This player has sent you an alliance request.",
"info_enemy_panel": "Enemy info panel",
"exit_confirmation": "Are you sure you want to exit the game?"
"exit_confirmation": "Are you sure you want to exit the game?",
"bomb_direction": "Atom / Hydrogen bomb arc direction"
},
"single_modal": {
"title": "Single Player",
Expand Down
4 changes: 4 additions & 0 deletions src/client/HelpModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ export class HelpModal extends LitElement {
<td>${this.renderKey(keybinds.toggleView)}</td>
<td>${translateText("help_modal.action_alt_view")}</td>
</tr>
<tr>
<td><span class="key">U</span></td>
<td>${translateText("help_modal.bomb_direction")}</td>
</tr>
<tr>
<td>
<div class="scroll-combo-horizontal">
Expand Down
8 changes: 8 additions & 0 deletions src/client/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export class GhostStructureChangedEvent implements GameEvent {
constructor(public readonly ghostStructure: UnitType | null) {}
}

export class SwapRocketDirectionEvent implements GameEvent {}

export class ShowBuildMenuEvent implements GameEvent {
constructor(
public readonly x: number,
Expand Down Expand Up @@ -200,6 +202,7 @@ export class InputHandler {
attackRatioUp: "KeyY",
boatAttack: "KeyB",
groundAttack: "KeyG",
swapDirection: "KeyU",
modifierKey: isMac ? "MetaLeft" : "ControlLeft",
altKey: "AltLeft",
buildCity: "Digit1",
Expand Down Expand Up @@ -427,6 +430,11 @@ export class InputHandler {
this.setGhostStructure(UnitType.MIRV);
}

if (e.code === this.keybinds.swapDirection) {
e.preventDefault();
this.eventBus.emit(new SwapRocketDirectionEvent());
}

// Shift-D to toggle performance overlay
console.log(e.code, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey);
if (e.code === "KeyD" && e.shiftKey) {
Expand Down
2 changes: 2 additions & 0 deletions src/client/Transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class BuildUnitIntentEvent implements GameEvent {
constructor(
public readonly unit: UnitType,
public readonly tile: TileRef,
public readonly rocketDirectionUp?: boolean,
) {}
}

Expand Down Expand Up @@ -573,6 +574,7 @@ export class Transport {
clientID: this.lobbyConfig.clientID,
unit: event.unit,
tile: event.tile,
rocketDirectionUp: event.rocketDirectionUp,
});
}

Expand Down
9 changes: 7 additions & 2 deletions src/client/graphics/GameRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ export function createRenderer(
const transformHandler = new TransformHandler(game, eventBus, canvas);
const userSettings = new UserSettings();

const uiState = { attackRatio: 20, ghostStructure: null } as UIState;
const uiState = {
attackRatio: 20,
ghostStructure: null,
rocketDirectionUp: true,
} as UIState;

//hide when the game renders
const startingModal = document.querySelector(
Expand All @@ -73,6 +77,7 @@ export function createRenderer(
}
buildMenu.game = game;
buildMenu.eventBus = eventBus;
buildMenu.uiState = uiState;
buildMenu.transformHandler = transformHandler;

const leaderboard = document.querySelector("leader-board") as Leaderboard;
Expand Down Expand Up @@ -241,7 +246,7 @@ export function createRenderer(
new UnitLayer(game, eventBus, transformHandler),
new FxLayer(game),
new UILayer(game, eventBus, transformHandler),
new NukeTrajectoryPreviewLayer(game, eventBus, transformHandler),
new NukeTrajectoryPreviewLayer(game, eventBus, transformHandler, uiState),
new StructureIconsLayer(game, eventBus, uiState, transformHandler),
new NameLayer(game, transformHandler, eventBus),
eventsDisplay,
Expand Down
1 change: 1 addition & 0 deletions src/client/graphics/UIState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { UnitType } from "../../core/game/Game";
export interface UIState {
attackRatio: number;
ghostStructure: UnitType | null;
rocketDirectionUp: boolean;
}
11 changes: 10 additions & 1 deletion src/client/graphics/layers/BuildMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from "../../Transport";
import { renderNumber } from "../../Utils";
import { TransformHandler } from "../TransformHandler";
import { UIState } from "../UIState";
import { Layer } from "./Layer";
import warshipIcon from "/images/BattleshipIconWhite.svg?url";
import cityIcon from "/images/CityIconWhite.svg?url";
Expand Down Expand Up @@ -125,6 +126,7 @@ export const flattenedBuildTable = buildTable.flat();
export class BuildMenu extends LitElement implements Layer {
public game: GameView;
public eventBus: EventBus;
public uiState: UIState;
private clickedTile: TileRef;
public playerActions: PlayerActions | null;
private filteredBuildTable: BuildItemDisplay[][] = buildTable;
Expand Down Expand Up @@ -395,7 +397,14 @@ export class BuildMenu extends LitElement implements Layer {
),
);
} else if (buildableUnit.canBuild) {
this.eventBus.emit(new BuildUnitIntentEvent(buildableUnit.type, tile));
const rocketDirectionUp =
buildableUnit.type === UnitType.AtomBomb ||
buildableUnit.type === UnitType.HydrogenBomb
? this.uiState.rocketDirectionUp
: undefined;
this.eventBus.emit(
new BuildUnitIntentEvent(buildableUnit.type, tile, rocketDirectionUp),
);
}
this.hideMenu();
}
Expand Down
15 changes: 14 additions & 1 deletion src/client/graphics/layers/NukeTrajectoryPreviewLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { UnitType } from "../../../core/game/Game";
import { TileRef } from "../../../core/game/GameMap";
import { GameView } from "../../../core/game/GameView";
import { ParabolaPathFinder } from "../../../core/pathfinding/PathFinding";
import { GhostStructureChangedEvent, MouseMoveEvent } from "../../InputHandler";
import {
GhostStructureChangedEvent,
MouseMoveEvent,
SwapRocketDirectionEvent,
} from "../../InputHandler";
import { TransformHandler } from "../TransformHandler";
import { UIState } from "../UIState";
import { Layer } from "./Layer";

/**
Expand All @@ -27,6 +32,7 @@ export class NukeTrajectoryPreviewLayer implements Layer {
private game: GameView,
private eventBus: EventBus,
private transformHandler: TransformHandler,
private uiState: UIState,
) {}

shouldTransform(): boolean {
Expand All @@ -50,6 +56,12 @@ export class NukeTrajectoryPreviewLayer implements Layer {
this.cachedSpawnTile = null;
}
});
this.eventBus.on(SwapRocketDirectionEvent, () => {
// Toggle rocket direction
this.uiState.rocketDirectionUp = !this.uiState.rocketDirectionUp;
// Force trajectory recalculation
this.lastTargetTile = null;
});
}

tick() {
Expand Down Expand Up @@ -210,6 +222,7 @@ export class NukeTrajectoryPreviewLayer implements Layer {
targetTile,
speed,
distanceBasedHeight,
this.uiState.rocketDirectionUp,
);

this.trajectoryPoints = pathFinder.allTiles();
Expand Down
8 changes: 7 additions & 1 deletion src/client/graphics/layers/StructureIconsLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,16 @@ export class StructureIconsLayer implements Layer {
),
);
} else if (this.ghostUnit.buildableUnit.canBuild) {
const unitType = this.ghostUnit.buildableUnit.type;
const rocketDirectionUp =
unitType === UnitType.AtomBomb || unitType === UnitType.HydrogenBomb
? this.uiState.rocketDirectionUp
: undefined;
this.eventBus.emit(
new BuildUnitIntentEvent(
this.ghostUnit.buildableUnit.type,
unitType,
this.game.ref(tile.x, tile.y),
rocketDirectionUp,
),
);
}
Expand Down
1 change: 1 addition & 0 deletions src/core/Schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export const BuildUnitIntentSchema = BaseIntentSchema.extend({
type: z.literal("build_unit"),
unit: z.enum(UnitType),
tile: z.number(),
rocketDirectionUp: z.boolean().optional(),
});

export const UpgradeStructureIntentSchema = BaseIntentSchema.extend({
Expand Down
11 changes: 10 additions & 1 deletion src/core/execution/ConstructionExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class ConstructionExecution implements Execution {
private player: Player,
private constructionType: UnitType,
private tile: TileRef,
private rocketDirectionUp?: boolean,
) {}

init(mg: Game, ticks: number): void {
Expand Down Expand Up @@ -104,7 +105,15 @@ export class ConstructionExecution implements Execution {
case UnitType.AtomBomb:
case UnitType.HydrogenBomb:
this.mg.addExecution(
new NukeExecution(this.constructionType, player, this.tile),
new NukeExecution(
this.constructionType,
player,
this.tile,
null,
-1,
0,
this.rocketDirectionUp,
),
);
break;
case UnitType.MIRV:
Expand Down
7 changes: 6 additions & 1 deletion src/core/execution/ExecutionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ export class Executor {
case "embargo_all":
return new EmbargoAllExecution(player, intent.action);
case "build_unit":
return new ConstructionExecution(player, intent.unit, intent.tile);
return new ConstructionExecution(
player,
intent.unit,
intent.tile,
intent.rocketDirectionUp,
);
case "allianceExtension": {
return new AllianceExtensionExecution(player, intent.recipient);
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/execution/NukeExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class NukeExecution implements Execution {
private src?: TileRef | null,
private speed: number = -1,
private waitTicks = 0,
private rocketDirectionUp: boolean = true,
) {}

init(mg: Game, ticks: number): void {
Expand Down Expand Up @@ -137,6 +138,7 @@ export class NukeExecution implements Execution {
this.dst,
this.speed,
this.nukeType !== UnitType.MIRVWarhead,
this.rocketDirectionUp,
);
this.nuke = this.player.buildUnit(this.nukeType, spawn, {
targetTile: this.dst,
Expand Down
18 changes: 15 additions & 3 deletions src/core/pathfinding/PathFinding.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Game } from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
import { PseudoRandom } from "../PseudoRandom";
import { within } from "../Util";
import { DistanceBasedBezierCurve } from "../utilities/Line";
import { AStar, AStarResult, PathFindResultType } from "./AStar";
import { MiniAStar } from "./MiniAStar";
Expand All @@ -16,6 +17,7 @@ export class ParabolaPathFinder {
dst: TileRef,
increment: number = 3,
distanceBasedHeight = true,
directionUp = true,
) {
const p0 = { x: this.mg.x(orig), y: this.mg.y(orig) };
const p3 = { x: this.mg.x(dst), y: this.mg.y(dst) };
Expand All @@ -25,14 +27,24 @@ export class ParabolaPathFinder {
const maxHeight = distanceBasedHeight
? Math.max(distance / 3, parabolaMinHeight)
: 0;
// Use a bezier curve always pointing up
// Use a bezier curve pointing up or down based on directionUp parameter
const heightMultiplier = directionUp ? -1 : 1;
const mapHeight = this.mg.height();
const p1 = {
x: p0.x + (p3.x - p0.x) / 4,
y: Math.max(p0.y + (p3.y - p0.y) / 4 - maxHeight, 0),
y: within(
p0.y + (p3.y - p0.y) / 4 + heightMultiplier * maxHeight,
0,
mapHeight - 1,
),
};
const p2 = {
x: p0.x + ((p3.x - p0.x) * 3) / 4,
y: Math.max(p0.y + ((p3.y - p0.y) * 3) / 4 - maxHeight, 0),
y: within(
p0.y + ((p3.y - p0.y) * 3) / 4 + heightMultiplier * maxHeight,
0,
mapHeight - 1,
),
};

this.curve = new DistanceBasedBezierCurve(p0, p1, p2, p3, increment);
Expand Down
2 changes: 1 addition & 1 deletion tests/InputHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("InputHandler AutoUpgrade", () => {
eventBus = new EventBus();

inputHandler = new InputHandler(
{ attackRatio: 20, ghostStructure: null },
{ attackRatio: 20, ghostStructure: null, rocketDirectionUp: true },
mockCanvas,
eventBus,
);
Expand Down
Loading