Skip to content

Instantly share code, notes, and snippets.

@hellos3b
Created February 22, 2019 07:34
Show Gist options
  • Save hellos3b/c450ab269bcb551ff922682d68131b6c to your computer and use it in GitHub Desktop.
Save hellos3b/c450ab269bcb551ff922682d68131b6c to your computer and use it in GitHub Desktop.
/**
* @typedef {import('@/ship/systems/Systems').System} System
*/
import { StatsType } from '@/ship/Stats'
/** @type {System} */
export const BasicShield = {
name: "Basic Shield",
id : "basic-shield",
layout: [
[{ image: 'tiles', frame: 3 }, { image: 'tiles', frame: 3 }]
],
buffs: [
{ type: 'add', target: StatsType.SHIELD, val: 100 }
]
}
/** @type {System} */
export const MediumShield = {
name: "Medium Shield",
id : "med-shield",
layout: [
[{ image: 'tiles', frame: 3 }, { image: 'tiles', frame: 3 }],
[{ image: 'tiles', frame: 3 }, { image: 'tiles', frame: 3 }]
],
buffs: [
{ type: 'add', target: StatsType.SHIELD, val: 300 }
]
}
/**
* @typedef {import('@/ship/TileBase').TileMapBase} TileMapBase
* @typedef {import('@/ship/systems/Systems').System} System
* @typedef {import('@/utils/Grid').Cell} Cell
*/
import * as TileBase from '@/ship/TileBase'
import * as Stats from './Stats'
import * as Grid from '@/utils/Grid'
export class Ship {
/** @type {TileMapBase} */
tileMapBase = null
/** @type {Stats.Stats} */
stats = Stats.empty()
/** @type {System[]} */
systems = []
/**
* @param {Object} config
* @param {TileMapBase} config.tileMapBase
*/
constructor({ tileMapBase }) {
this.tileMapBase = tileMapBase
}
/**
* @param {System} system
* @param {Game.Position} position
* @returns {Cell[]} Affected cells
*/
addSystem(system, position) {
this.systems.push(system)
const tiles = Grid.from2DArray(system.layout)
const area = this.tileMapBase.grid.area(position, tiles.size)
area.forEach( cell => {
cell.value.ref = system
})
this.updateStats()
return area
}
updateStats() {
this.stats = Stats.fromSystems(this.systems)
}
}
/**
*
* @param {object} config
* @param {number[][]} config.layout
*/
export const fromConfig = config => {
const base = TileBase.fromConfig(config.layout)
const ship = new Ship({ tileMapBase: base })
return ship
}
/**
* @typedef {import('@/ship/systems/Systems').System} System
* @typedef {import('@/ship/systems/Systems').Buff} Buff
*/
import { using } from '@/utils/Value'
/**
* @readonly
* @enum {string}
*/
export const StatsType = {
HEALTH : "health",
SHIELD : "shield"
}
export class Stat {
/** @type {number} */
base = 0
/** @type {number} */
bonus = 0
/**
*
* @param {number=} base
* @param {number=} bonus
*/
constructor(base=0, bonus=0) {
this.base = base
this.bonus = bonus
}
/**
* @param {number} val
*/
add(val) {
this.base += val
}
/**
* @param {number} val
*/
perc(val) {
this.bonus += val
}
/**
* @returns {number}
*/
val() {
return this.base
}
}
export class Stats {
/** @type {Map<StatsType,Stat>} */
stats = new Map()
/** @type {Buff[]} */
buffs=[]
/**
*
* @param {Map<StatsType,Stat>} stats
*/
constructor(stats) {
this.stats = stats
/** Add getters for each stat */
for (const [key, stat] of stats) {
this.defineStatProperty(key, stat)
}
}
/**
* Define each stat as a property on the stats object
* @private
* @param {string} key
* @param {Stat} stat
*/
defineStatProperty(key, stat) {
Object.defineProperty(this, key, {
get() {
return stat.val()
}
})
}
/**
* helper getter to make reading console output much easier
*/
get _simple() {
const json = {}
for (const [key, stat] of this.stats) {
json[key] = {
val : stat.val(),
base : stat.base,
bonus : stat.bonus
}
}
return json
}
}
/**
* @returns {Stats}
*/
export const empty = () => new Stats(baseStats())
/**
* @returns {Map<StatsType,Stat>}
*/
export const baseStats = () =>
using(StatsType)
.mapKeys(_ => [
StatsType[_],
new Stat()
])
.apply(_ => new Map(_))
.get()
/**
*
* @param {Buff[]} buffs
* @returns {Stats}
*/
export const withBuffs = buffs =>
using(buffs)
.apply(_ => calcBuffs(_))
.apply(_ => new Stats(_))
.get()
/**
*
* @param {Buff[]} buffs
*/
export const calcBuffs = buffs => {
const stats = baseStats()
buffs.forEach(buff => {
const stat = stats.get(buff.target.toString())
stat[buff.type].call(stat, buff.val)
})
return stats
}
/**
* @param {System[]} systems
* @returns {Stats}
*/
export const fromSystems = systems =>
using(systems)
.map(_ => _.buffs || [])
.flatten()
.apply(_ => withBuffs(_))
.get()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment