From fa477afb9ad0b51da0f5ea916ca203ed1f8fc523 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Tue, 9 Sep 2025 22:39:14 +0200 Subject: [PATCH] survivors: split between base stats, temp stats and effective stats for players changed the way how stats are increased/decreased --- absurd-survivors/src/Player.ts | 85 ++++++++++++++++++++++-------- absurd-survivors/src/drop.ts | 4 +- absurd-survivors/src/items.ts | 8 +-- absurd-survivors/src/main.ts | 8 +-- absurd-survivors/src/projectile.ts | 6 +-- absurd-survivors/src/ui.ts | 8 +-- absurd-survivors/src/weapons.ts | 2 +- 7 files changed, 82 insertions(+), 39 deletions(-) diff --git a/absurd-survivors/src/Player.ts b/absurd-survivors/src/Player.ts index 8cb0071..097a996 100644 --- a/absurd-survivors/src/Player.ts +++ b/absurd-survivors/src/Player.ts @@ -4,7 +4,9 @@ import {fillDot, getCoordinatesSplit} from "./utils.ts"; export class Player implements Drawable, Acting, Healthy { private _position: Vector; - private _stats: PlayerStats; + private _baseStats: PlayerStats; + private _effectiveStats: PlayerStats; + private _tempStats: PlayerStats; private _color: string; private _status: PlayerStatus; @@ -20,7 +22,7 @@ export class Player implements Drawable, Acting, Healthy { } draw(ctx: CanvasRenderingContext2D) { - fillDot(this.position, this._stats.size, this._color, ctx) + fillDot(this.position, this._effectiveStats.size, this._color, ctx) this._weapons.forEach(weapon => weapon.draw(ctx)) } @@ -30,7 +32,10 @@ export class Player implements Drawable, Acting, Healthy { } let player = new Player(position); player._color = 'blue'; - player._stats = PlayerStats.defaultPlayerStats(); + player._baseStats = PlayerStats.defaultPlayerStats(); + let tempStats = new PlayerStats(); + tempStats.resetToBasic() + player._tempStats = tempStats; player._speed = new Vector(0, 0) player._status = new PlayerStatus(10, 0, 0); return player; @@ -60,9 +65,15 @@ export class Player implements Drawable, Acting, Healthy { this._status.health -= damage; } + statsChanged() { + this._effectiveStats.resetToBasic() + this._effectiveStats.mergeStats(this._baseStats) + this._effectiveStats.mergeStats(this._tempStats) + } + heal(amount: number) { this._status.health += amount; - this._status.health = Math.min(this._status.health, this._stats.health) + this._status.health = Math.min(this._status.health, this._effectiveStats.health) } get health(): number { @@ -77,8 +88,8 @@ export class Player implements Drawable, Acting, Healthy { return this._color; } - get stats(): PlayerStats { - return this._stats; + get effectiveStats(): PlayerStats { + return this._effectiveStats; } get status(): PlayerStatus { @@ -101,19 +112,30 @@ export class Player implements Drawable, Acting, Healthy { } getSize() { - return this.stats.size + return this._effectiveStats.size } dead() { return this.status.dead } + changeBaseStat(value: number, statFun: (stats: PlayerStats, value: number) => void) { + this._baseStats.changeStat(value, statFun) + this.statsChanged() + } + + changeTempStat(value: number, statFun: (stats: PlayerStats, value: number) => void) { + this._tempStats.changeStat(value, statFun) + this.statsChanged() + } + increaseLevel() { this.status.increaseLevel() - this.stats.increaseLevel() + this._baseStats.increaseLevel() this._weapons.forEach(weapon => { weapon.increaseLevel() }) + this.statsChanged() } level() { @@ -179,6 +201,14 @@ export class PlayerStats { this._weaponRangeFactor = 1; } + resetToBasic() { + this._speed = 0; + this._health = 0; + this._pullRange = 0; + this._weaponRange = 0; + this._weaponRangeFactor = 1 + } + increaseLevel() { this._speed *= 1.1; this._health += 1 @@ -187,29 +217,42 @@ export class PlayerStats { this._weaponRangeFactor += 0.1 } - - set speed(value: number) { - this._speed = value; + mergeStats(otherStats: PlayerStats) { + this._speed += otherStats._speed; + this._health += otherStats._health; + this._pullRange += otherStats._pullRange; + this._weaponRange += otherStats._weaponRange + this._weaponRangeFactor += otherStats._weaponRangeFactor; } - set size(value: number) { - this._size = value; + clone() { + let newStats = new PlayerStats(); + newStats.mergeStats(this) + return newStats; } - set health(value: number) { - this._health = value; + changeStat(value: number, statFun: (stats: PlayerStats, value: number) => void) { + statFun(this, value) } - set pullRange(value: number) { - this._pullRange = value; + static increaseSpeed(stats: PlayerStats, value: number) { + stats._speed += value } - set weaponRange(value: number) { - this._weaponRange = value; + static factorSpeed(stats: PlayerStats, value: number) { + stats._speed *= value } - set weaponRangeFactor(value: number) { - this._weaponRangeFactor = value; + static increasePullRange(stats: PlayerStats, value: number) { + stats._pullRange += value + } + + static factorPullRange(stats: PlayerStats, value: number) { + stats._pullRange += value + } + + static increaseHealth(stats: PlayerStats, value: number) { + stats._health += value } get speed(): number { diff --git a/absurd-survivors/src/drop.ts b/absurd-survivors/src/drop.ts index d874136..c59c0fe 100644 --- a/absurd-survivors/src/drop.ts +++ b/absurd-survivors/src/drop.ts @@ -27,10 +27,10 @@ export abstract class BasicDrop implements Drop { act() { let distanceToPlayer = this._position.distanceTo(this.world.player.position); - if(distanceToPlayer < (this.world.player.stats.size + this.size)) { + if(distanceToPlayer < (this.world.player.effectiveStats.size + this.size)) { this.pickup() this.world.removeDrop(this) - } else if(distanceToPlayer < this.world.player.stats.pullRange) { + } else if(distanceToPlayer < this.world.player.effectiveStats.pullRange) { let speedFactor = 125 / distanceToPlayer; this._position = moveInDirectionOf(this._position, this.world.player.position, speedFactor) } diff --git a/absurd-survivors/src/items.ts b/absurd-survivors/src/items.ts index 57bf2ba..f58223c 100644 --- a/absurd-survivors/src/items.ts +++ b/absurd-survivors/src/items.ts @@ -1,5 +1,5 @@ import type {ChanceEntry, Item} from "./interfaces.ts"; -import {Player} from "./Player.ts"; +import {Player, PlayerStats} from "./Player.ts"; import {randomItem} from "./utils.ts"; import {ChainBall, HomingPistol, Pistol, Spear, SpreadWeapon} from "./weapons.ts"; import type {World} from "./World.ts"; @@ -85,7 +85,7 @@ export abstract class BaseItem implements Item { export class SpeedUp extends BaseItem { pickup(player: Player, world: World) { - player.stats.speed += 1 + player.changeBaseStat(1, PlayerStats.increaseSpeed) super.pickup(player, world) } @@ -100,7 +100,7 @@ export class SpeedUp extends BaseItem { export class PullRangeUp extends BaseItem { pickup(player: Player, world: World) { - player.stats.pullRange *= 1.1 + player.changeBaseStat(1.1, PlayerStats.factorPullRange) super.pickup(player, world) } @@ -115,7 +115,7 @@ export class PullRangeUp extends BaseItem { export class HealthUp extends BaseItem { pickup(player: Player, world: World) { - player.stats.health += 1 + player.changeBaseStat(1, PlayerStats.increaseHealth) super.pickup(player, world) } diff --git a/absurd-survivors/src/main.ts b/absurd-survivors/src/main.ts index cfac878..6b633bb 100644 --- a/absurd-survivors/src/main.ts +++ b/absurd-survivors/src/main.ts @@ -66,16 +66,16 @@ function makeKey(char, fun) { let keys = {}; makeKey('w', function (intensity: number) { - world.movePlayer(new Vector(0, -world.player.stats.speed * intensity)) + world.movePlayer(new Vector(0, -world.player.effectiveStats.speed * intensity)) }) makeKey('s', function (intensity: number) { - world.movePlayer(new Vector(0, world.player.stats.speed * intensity)) + world.movePlayer(new Vector(0, world.player.effectiveStats.speed * intensity)) }) makeKey('a', function (intensity: number) { - world.movePlayer(new Vector(-world.player.stats.speed * intensity, 0)) + world.movePlayer(new Vector(-world.player.effectiveStats.speed * intensity, 0)) }) makeKey('d', function (intensity: number) { - world.movePlayer(new Vector(world.player.stats.speed * intensity, 0)) + world.movePlayer(new Vector(world.player.effectiveStats.speed * intensity, 0)) }) diff --git a/absurd-survivors/src/projectile.ts b/absurd-survivors/src/projectile.ts index 18eabe0..db6e6fe 100644 --- a/absurd-survivors/src/projectile.ts +++ b/absurd-survivors/src/projectile.ts @@ -44,7 +44,7 @@ export abstract class Projectile implements Acting, Placeable { act() { this.move() if(this.parent !== this.world.player) { - if(this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.stats.size) && this.status.collisionCooldown.cooledDown()) { + if(this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.effectiveStats.size) && this.status.collisionCooldown.cooledDown()) { this.impactPlayer() this.status.collisionCooldown.resetCooldown() } @@ -171,7 +171,7 @@ export class ChainBallProjectile extends Projectile { } else { this.position = moveInDirectionOf(this.position, this.world.player.position, this.speedVec.vecLength()) } - if(this.movingBack && this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.stats.size)) { + if(this.movingBack && this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.effectiveStats.size)) { this.weapon.reset(); this.die() } @@ -233,7 +233,7 @@ export class StraightMeleeWeaponProjectile extends Projectile { } else { this.position = moveInDirectionOf(this.position, new Vector(0, 0), this.speedVec.vecLength()) } - if(this.movingBack && this.position.distanceTo(new Vector(0, 0)) < (this.stats.size + this.world.player.stats.size)) { + if(this.movingBack && this.position.distanceTo(new Vector(0, 0)) < (this.stats.size + this.world.player.effectiveStats.size)) { this.weapon.reset(); this.die() } diff --git a/absurd-survivors/src/ui.ts b/absurd-survivors/src/ui.ts index 83b0db9..cfa9eed 100644 --- a/absurd-survivors/src/ui.ts +++ b/absurd-survivors/src/ui.ts @@ -120,14 +120,14 @@ export class PlayerInfo implements DrawContainer { constructor(world: World) { this.world = world; - this.bar = new InfoBar(new Vector(0, 50), 50, 150, () => 'Health', () => this.world.player.status.health, () => this.world.player.stats.health) + this.bar = new InfoBar(new Vector(0, 50), 50, 150, () => 'Health', () => this.world.player.status.health, () => this.world.player.effectiveStats.health) this.statLabelBase = new Vector(0, 150) this.statLabels = [ new StatLabel(() => 'Money', () => this.world.player.status.wealth), new StatLabel(() => 'Level', () => this.world.player.status.level), - new StatLabel(() => 'Speed', () => Math.floor(this.world.player.stats.speed)), - new StatLabel(() => 'Pull range', () => Math.floor(this.world.player.stats.pullRange)), - new StatLabel(() => 'Weapon range', () => Math.floor(this.world.player.stats.effectiveWeaponRange)) + new StatLabel(() => 'Speed', () => Math.floor(this.world.player.effectiveStats.speed)), + new StatLabel(() => 'Pull range', () => Math.floor(this.world.player.effectiveStats.pullRange)), + new StatLabel(() => 'Weapon range', () => Math.floor(this.world.player.effectiveStats.effectiveWeaponRange)) ] } diff --git a/absurd-survivors/src/weapons.ts b/absurd-survivors/src/weapons.ts index 3ed794f..ac3b32b 100644 --- a/absurd-survivors/src/weapons.ts +++ b/absurd-survivors/src/weapons.ts @@ -80,7 +80,7 @@ export abstract class RangeWeapon extends BasicWeapon { } calculateRange(): number { - return this.world.player.stats.effectiveWeaponRange + this.stats.effectiveWeaponRange; + return this.world.player.effectiveStats.effectiveWeaponRange + this.stats.effectiveWeaponRange; } }