add hospital visual

This commit is contained in:
1brucben
2025-06-05 18:02:38 +02:00
parent 71e677ce4c
commit 65115eb4ee
10 changed files with 59 additions and 15 deletions
+4 -2
View File
@@ -52,8 +52,10 @@ export class NewsModal extends LitElement {
<div class="news-content"> <div class="news-content">
<p> <p>
This test version introduces a new building: This test version introduces a new building:
<strong>Hospitals</strong>. Each hospital reduces your troop <strong>Hospitals</strong>. Each hospital restores some of
losses in both offensive and defensive combat. your troop losses from both offensive and defensive combat.
The restored troops are displayed next to your population
growth count in your control panel.
</p> </p>
<p> <p>
The first hospital provides a The first hospital provides a
+10 -3
View File
@@ -34,6 +34,9 @@ export class ControlPanel extends LitElement implements Layer {
@state() @state()
private popRate: number; private popRate: number;
@state()
private _hospitalReturns: number = 0;
@state() @state()
private _troops: number; private _troops: number;
@@ -121,6 +124,7 @@ export class ControlPanel extends LitElement implements Layer {
this._population = player.population(); this._population = player.population();
this._maxPopulation = this.game.config().maxPopulation(player); this._maxPopulation = this.game.config().maxPopulation(player);
this._hospitalReturns = player.hospitalReturns() * 10;
this._gold = player.gold(); this._gold = player.gold();
this._troops = player.troops(); this._troops = player.troops();
this._workers = player.workers(); this._workers = player.workers();
@@ -221,9 +225,12 @@ export class ControlPanel extends LitElement implements Layer {
? "text-green-500" ? "text-green-500"
: "text-yellow-500"}" : "text-yellow-500"}"
translate="no" translate="no"
>(+${renderTroops(this.popRate)})</span >
></span (+${renderTroops(
> this.popRate,
)}${`/ +${renderTroops(this._hospitalReturns)}`})
</span>
</span>
</div> </div>
<div class="flex justify-between"> <div class="flex justify-between">
<span class="font-bold" <span class="font-bold"
+5 -1
View File
@@ -10,6 +10,7 @@ export class TopBar extends LitElement implements Layer {
public game: GameView; public game: GameView;
private isVisible = false; private isVisible = false;
private _population = 0; private _population = 0;
private _hospitalReturns = 0;
private _lastPopulationIncreaseRate = 0; private _lastPopulationIncreaseRate = 0;
private _popRateIsIncreasing = false; private _popRateIsIncreasing = false;
@@ -36,6 +37,7 @@ export class TopBar extends LitElement implements Layer {
popIncreaseRate >= this._lastPopulationIncreaseRate; popIncreaseRate >= this._lastPopulationIncreaseRate;
this._lastPopulationIncreaseRate = popIncreaseRate; this._lastPopulationIncreaseRate = popIncreaseRate;
} }
this._hospitalReturns = player.hospitalReturns?.() ?? 0;
} }
render() { render() {
@@ -72,8 +74,10 @@ export class TopBar extends LitElement implements Layer {
class="${this._popRateIsIncreasing class="${this._popRateIsIncreasing
? "text-green-500" ? "text-green-500"
: "text-yellow-500"}" : "text-yellow-500"}"
>(+${renderTroops(popRate)})</span
> >
(+${renderTroops(popRate)} /
+${renderTroops(this._hospitalReturns)})
</span>
</div> </div>
<!-- Gold section (takes 1 column on desktop) --> <!-- Gold section (takes 1 column on desktop) -->
<div <div
+1 -8
View File
@@ -569,12 +569,6 @@ export class DefaultConfig implements Config {
const traitorDebuff = defender.isTraitor() const traitorDebuff = defender.isTraitor()
? this.traitorDefenseDebuff() ? this.traitorDefenseDebuff()
: 1; : 1;
const attackerHospitalBonus =
0.6 + 0.4 * Math.pow(0.75, attacker.units(UnitType.Hospital).length);
const defenderHospitalBonus =
0.6 + 0.4 * Math.pow(0.75, defender.units(UnitType.Hospital).length);
console.log(attackerHospitalBonus, defenderHospitalBonus);
const baseTroopLoss = 10; const baseTroopLoss = 10;
const attackLossModifier = 1.35; const attackLossModifier = 1.35;
const baseTileCost = 45; const baseTileCost = 45;
@@ -582,10 +576,9 @@ export class DefaultConfig implements Config {
return { return {
attackerTroopLoss: attackerTroopLoss:
mag * mag *
attackerHospitalBonus *
(baseTroopLoss + (baseTroopLoss +
attackLossModifier * defenderDensity * traitorDebuff), attackLossModifier * defenderDensity * traitorDebuff),
defenderTroopLoss: defenderDensity * defenderHospitalBonus, defenderTroopLoss: defenderDensity,
tilesPerTickUsed: tilesPerTickUsed:
baseTileCost * baseTileCost *
within(defenderDensity, 3, 50) ** 0.2 * within(defenderDensity, 3, 50) ** 0.2 *
+15
View File
@@ -9,6 +9,7 @@ import {
PlayerType, PlayerType,
TerrainType, TerrainType,
TerraNullius, TerraNullius,
UnitType,
} from "../game/Game"; } from "../game/Game";
import { TileRef } from "../game/GameMap"; import { TileRef } from "../game/GameMap";
import { PseudoRandom } from "../PseudoRandom"; import { PseudoRandom } from "../PseudoRandom";
@@ -294,6 +295,20 @@ export class AttackExecution implements Execution {
if (targetPlayer) { if (targetPlayer) {
targetPlayer.removeTroops(defenderTroopLoss); targetPlayer.removeTroops(defenderTroopLoss);
} }
const attackerMultiplier =
0.6 + 0.4 * Math.pow(0.75, this._owner.units(UnitType.Hospital).length);
const defenderMultiplier = targetPlayer
? 0.6 +
0.4 * Math.pow(0.75, this._owner.units(UnitType.Hospital).length)
: 1;
const attackerReturns = attackerTroopLoss * (1 - attackerMultiplier);
const defenderReturns = defenderTroopLoss * (1 - defenderMultiplier);
this._owner.addHospitalReturns(attackerReturns);
if (targetPlayer) {
targetPlayer.addHospitalReturns(defenderReturns);
}
this._owner.conquer(tileToConquer); this._owner.conquer(tileToConquer);
this.handleDeadDefender(); this.handleDeadDefender();
} }
+4 -1
View File
@@ -74,7 +74,10 @@ export class PlayerExecution implements Execution {
return; return;
} }
const popInc = this.config.populationIncreaseRate(this.player); const popInc =
this.config.populationIncreaseRate(this.player) +
this.player.hospitalReturns();
this.player.resetHospitalReturns();
this.player.addWorkers(popInc * (1 - this.player.targetTroopRatio())); this.player.addWorkers(popInc * (1 - this.player.targetTroopRatio()));
this.player.addTroops(popInc * this.player.targetTroopRatio()); this.player.addTroops(popInc * this.player.targetTroopRatio());
const goldFromWorkers = this.config.goldAdditionRate(this.player); const goldFromWorkers = this.config.goldAdditionRate(this.player);
+3
View File
@@ -461,6 +461,9 @@ export interface Player {
setTroops(troops: number): void; setTroops(troops: number): void;
addTroops(troops: number): void; addTroops(troops: number): void;
removeTroops(troops: number): number; removeTroops(troops: number): number;
hospitalReturns(): number;
addHospitalReturns(amount: number): void;
resetHospitalReturns(): void;
// Units // Units
units(...types: UnitType[]): Unit[]; units(...types: UnitType[]): Unit[];
+1
View File
@@ -107,6 +107,7 @@ export interface PlayerUpdate {
gold: Gold; gold: Gold;
population: number; population: number;
totalPopulation: number; totalPopulation: number;
hospitalReturns: number;
workers: number; workers: number;
troops: number; troops: number;
targetTroopRatio: number; targetTroopRatio: number;
+3
View File
@@ -292,6 +292,9 @@ export class PlayerView {
hasSpawned(): boolean { hasSpawned(): boolean {
return this.data.hasSpawned; return this.data.hasSpawned;
} }
hospitalReturns(): number {
return this.data.hospitalReturns ?? 0;
}
} }
export class GameView implements GameMap { export class GameView implements GameMap {
+13
View File
@@ -82,6 +82,7 @@ export class PlayerImpl implements Player {
private _flag: string | undefined; private _flag: string | undefined;
private _name: string; private _name: string;
private _displayName: string; private _displayName: string;
private _hospitalReturns: number = 0;
public pastOutgoingAllianceRequests: AllianceRequest[] = []; public pastOutgoingAllianceRequests: AllianceRequest[] = [];
@@ -139,6 +140,7 @@ export class PlayerImpl implements Player {
gold: this._gold, gold: this._gold,
population: this.population(), population: this.population(),
totalPopulation: this.totalPopulation(), totalPopulation: this.totalPopulation(),
hospitalReturns: this.hospitalReturns(),
workers: this.workers(), workers: this.workers(),
troops: this.troops(), troops: this.troops(),
targetTroopRatio: this.targetTroopRatio(), targetTroopRatio: this.targetTroopRatio(),
@@ -720,6 +722,17 @@ export class PlayerImpl implements Player {
return Number(toRemove); return Number(toRemove);
} }
hospitalReturns(): number {
return this._hospitalReturns;
}
addHospitalReturns(count: number): void {
this._hospitalReturns += count;
}
resetHospitalReturns(): void {
this._hospitalReturns = 0;
}
captureUnit(unit: Unit): void { captureUnit(unit: Unit): void {
if (unit.owner() === this) { if (unit.owner() === this) {
throw new Error(`Cannot capture unit, ${this} already owns ${unit}`); throw new Error(`Cannot capture unit, ${this} already owns ${unit}`);