survivors: split between base stats, temp stats and effective stats for players

changed the way how stats are increased/decreased
This commit is contained in:
Sheldan
2025-09-09 22:39:14 +02:00
parent 28ef7b9c6f
commit fa477afb9a
7 changed files with 82 additions and 39 deletions

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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))
})

View File

@@ -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()
}

View File

@@ -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))
]
}

View File

@@ -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;
}
}