Merge branch 'main' of github.com:openfrontio/OpenFrontIO

This commit is contained in:
Evan
2025-03-19 08:24:33 -07:00
13 changed files with 830 additions and 420 deletions
@@ -165,6 +165,10 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
const myPlayer = this.myPlayer();
const isAlly = myPlayer?.isAlliedWith(player);
let relationHtml = null;
const attackingTroops = player
.outgoingAttacks()
.map((a) => a.troops)
.reduce((a, b) => a + b, 0);
if (player.type() == PlayerType.FakeHuman && myPlayer != null) {
const relation =
@@ -201,12 +205,29 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
${player.name()}
</div>
<div class="text-sm opacity-80">Type: ${playerType}</div>
<div class="text-sm opacity-80" translate="no">
Troops: ${renderTroops(player.troops())}
</div>
${player.troops() >= 1 &&
html`<div class="text-sm opacity-80" translate="no">
Defending troops: ${renderTroops(player.troops())}
</div>`}
${attackingTroops >= 1 &&
html`<div class="text-sm opacity-80" translate="no">
Attacking troops: ${renderTroops(attackingTroops)}
</div>`}
<div class="text-sm opacity-80" translate="no">
Gold: ${renderNumber(player.gold())}
</div>
<div class="text-sm opacity-80" translate="no">
Ports: ${player.units(UnitType.Port).length}
</div>
<div class="text-sm opacity-80" translate="no">
Cities: ${player.units(UnitType.City).length}
</div>
<div class="text-sm opacity-80" translate="no">
Missile launchers: ${player.units(UnitType.MissileSilo).length}
</div>
<div class="text-sm opacity-80" translate="no">
SAMs: ${player.units(UnitType.SAMLauncher).length}
</div>
${relationHtml}
</div>
`;
+1 -1
View File
@@ -409,7 +409,7 @@ export class DefaultConfig implements Config {
(defender.isTraitor() ? this.traitorDefenseDebuff() : 1),
defenderTroopLoss: defender.troops() / defender.numTilesOwned(),
tilesPerTickUsed:
within(defender.troops() / (4 * attackTroops), 0.2, 1.5) *
within(defender.troops() / (5 * attackTroops), 0.2, 1.5) *
speed *
largeModifier,
};
+12 -6
View File
@@ -20,9 +20,9 @@ export class SAMLauncherExecution implements Execution {
private target: Unit = null;
private searchRange = 100;
private searchRangeRadius = 75;
private missileAttackRate = 100; // 10 seconds
private missileAttackRate = 75; // 7.5 seconds
private lastMissileAttack = 0;
private pseudoRandom: PseudoRandom;
@@ -63,10 +63,16 @@ export class SAMLauncherExecution implements Execution {
const nukes = this.mg
.units(UnitType.AtomBomb, UnitType.HydrogenBomb)
.filter(
(u) =>
this.mg.manhattanDist(u.tile(), this.post.tile()) < this.searchRange,
)
.filter((u) => {
// (x - center_x)² + (y - center_y)² < radius²
const x = this.mg.x(u.tile());
const y = this.mg.y(u.tile());
const centerX = this.mg.x(this.post.tile());
const centerY = this.mg.y(this.post.tile());
const isInRange =
(x - centerX) ** 2 + (y - centerY) ** 2 < this.searchRangeRadius ** 2;
return isInRange;
})
.filter((u) => u.owner() !== this.player)
.filter((u) => !u.owner().isAlliedWith(this.player));
+7 -21
View File
@@ -23,10 +23,8 @@ export class SAMMissileExecution implements Execution {
private target: Unit,
private mg: Game,
private pseudoRandom: number,
private speed: number = 6,
// Regular atom bomb or warhead of MIRV
private speed: number = 12,
private hittingChance: number = 0.75,
private hittingChanceHydrogen: number = 0.1,
) {}
init(mg: Game, ticks: number): void {
@@ -45,10 +43,13 @@ export class SAMMissileExecution implements Execution {
this.active = false;
return;
}
// Mirv warheads are too fast, and mirv shouldn't be stopped ever
const nukesWhitelist = [UnitType.AtomBomb, UnitType.HydrogenBomb];
if (
!this.target.isActive() ||
!this.ownerUnit.isActive() ||
this.target.owner() == this.SAMMissile.owner()
this.target.owner() == this.SAMMissile.owner() ||
!nukesWhitelist.includes(this.target.type())
) {
this.SAMMissile.delete(false);
this.active = false;
@@ -63,22 +64,7 @@ export class SAMMissileExecution implements Execution {
switch (result.type) {
case PathFindResultType.Completed:
this.active = false;
let hit = false;
if (
this.target.type() == UnitType.HydrogenBomb &&
this.pseudoRandom < this.hittingChanceHydrogen
) {
hit = true;
} else if (
[UnitType.MIRVWarhead, UnitType.AtomBomb].includes(
this.target.type(),
) &&
this.pseudoRandom < this.hittingChance
) {
hit = true;
}
if (hit) {
if (this.pseudoRandom < this.hittingChance) {
this.target.delete();
this.mg.displayMessage(
@@ -88,7 +74,7 @@ export class SAMMissileExecution implements Execution {
);
} else {
this.mg.displayMessage(
`Missile failed to intercept ${this.target.type()}`,
`Missile failed to target ${this.target.type()}`,
MessageType.ERROR,
this._owner.id(),
);
+5 -2
View File
@@ -25,6 +25,7 @@ class Terrain {
export async function generateMap(
imageBuffer: Buffer,
removeSmall = true,
): Promise<{ map: Uint8Array; miniMap: Uint8Array }> {
const stream = Readable.from(imageBuffer);
const img = await decodePNGFromStream(stream);
@@ -56,8 +57,10 @@ export async function generateMap(
}
}
removeSmallIslands(terrain);
removeSmallLakes(terrain);
if (removeSmall) {
removeSmallIslands(terrain);
removeSmallLakes(terrain);
}
const shorelineWaters = processShore(terrain);
processDistToLand(shorelineWaters, terrain);
processOcean(terrain);