You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
8.5 KiB
230 lines
8.5 KiB
import {Affinity, AffinityDisplay} from "./Messages";
|
|
|
|
export enum MeteredResource {
|
|
Experience = "EXP",
|
|
Health = "HP",
|
|
Magic = "MP",
|
|
Items = "IP",
|
|
Zero = "Zero Charge",
|
|
Blood = "BP",
|
|
Turns = "Turns",
|
|
Segments = "Segments",
|
|
}
|
|
|
|
export function isMeteredResource(r: Resource): r is MeteredResource {
|
|
return Object.values<Resource>(MeteredResource).includes(r)
|
|
}
|
|
|
|
export enum UnmeteredResource {
|
|
Fabula = "FP",
|
|
Ultima = "UP",
|
|
Special = "SP",
|
|
Level = "Levels",
|
|
Materials = "Zenit of Materials",
|
|
Zenit = "Zenit",
|
|
Order = "Order",
|
|
}
|
|
|
|
export function formatResourceDelta(r: Resource, a: Affinity, n: number): string {
|
|
const delta = `${n > 0 ? "+" : n === 0 ? "±" : ""}${n.toFixed(0)}${AffinityDisplay[a]}`
|
|
if (Math.abs(n) === 1) {
|
|
switch (r) {
|
|
case MeteredResource.Turns:
|
|
return `${delta} Turn`
|
|
case MeteredResource.Segments:
|
|
return `${delta} Segment`
|
|
case UnmeteredResource.Level:
|
|
return `${delta} Level`
|
|
}
|
|
}
|
|
return `${delta} ${r}`
|
|
}
|
|
|
|
export function formatMeteredResource(r: MeteredResource, n: number, mx: number): string {
|
|
const value = `${n}/${mx}`
|
|
if (n === 1 && mx === 1) {
|
|
switch (r) {
|
|
case MeteredResource.Turns:
|
|
return `${value} Turn`
|
|
case MeteredResource.Segments:
|
|
return `${value} Segment`
|
|
}
|
|
}
|
|
return `${value} ${r}`
|
|
}
|
|
|
|
export function formatResourceValue(r: Resource, n: number): string {
|
|
const value = `${n}`
|
|
if (r === UnmeteredResource.Level) {
|
|
return `Lv. ${value}`
|
|
}
|
|
if (n === 1) {
|
|
switch (r) {
|
|
case MeteredResource.Turns:
|
|
return `${value} Turn`
|
|
case MeteredResource.Segments:
|
|
return `${value} Segment`
|
|
}
|
|
}
|
|
return `${value} ${r}`
|
|
}
|
|
|
|
export function formatResourceMax(r: MeteredResource, n: number): string {
|
|
const value = `${n}`
|
|
if (n === 1) {
|
|
switch (r) {
|
|
case MeteredResource.Turns:
|
|
return `Max ${value} Turn`
|
|
case MeteredResource.Segments:
|
|
return `Max ${value} Segment`
|
|
}
|
|
}
|
|
return `Max ${value} ${r}`
|
|
}
|
|
|
|
export function isUnmeteredResource(r: Resource): r is UnmeteredResource {
|
|
return Object.values<Resource>(UnmeteredResource).includes(r)
|
|
}
|
|
|
|
export type Resource = MeteredResource|UnmeteredResource
|
|
|
|
export function getResourceValue<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT): number|undefined {
|
|
const field = valueMap[resource]
|
|
if (typeof field === "undefined") {
|
|
return undefined
|
|
}
|
|
return object[field]
|
|
}
|
|
|
|
export function setResourceValue<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT, value: number): ObjectT {
|
|
const valueField = valueMap[resource]
|
|
const maxField = maxMap[resource]
|
|
|
|
if (typeof valueField === "undefined") {
|
|
return object
|
|
}
|
|
|
|
if (typeof maxField !== "undefined") {
|
|
const max = getResourceValue(maxMap, object, resource)
|
|
if (typeof max === "undefined") {
|
|
return object
|
|
}
|
|
return setMeteredResource(valueMap, maxMap, object, resource, value, max)
|
|
}
|
|
|
|
const effectiveValue = Math.max(0, value)
|
|
return {
|
|
...object,
|
|
[valueField as KeySetT]: effectiveValue,
|
|
}
|
|
}
|
|
export function applyResourceDelta<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT, delta: number): ObjectT {
|
|
const value = getResourceValue(valueMap, object, resource)
|
|
if (typeof value === "undefined") {
|
|
return object
|
|
}
|
|
|
|
return setResourceValue(valueMap, maxMap, object, resource, value + delta)
|
|
}
|
|
|
|
export function setResourceMax<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT, max: number): ObjectT {
|
|
const valueField = valueMap[resource]
|
|
const maxField = maxMap[resource]
|
|
|
|
if (typeof valueField === "undefined" || typeof maxField === "undefined") {
|
|
return object
|
|
}
|
|
const value = getResourceValue(valueMap, object, resource)
|
|
if (typeof value === "undefined") {
|
|
return object
|
|
}
|
|
return setMeteredResource(valueMap, maxMap, object, resource, value, max)
|
|
}
|
|
|
|
export function setMeteredResource<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT, value: number, max: number): ObjectT {
|
|
const valueField = valueMap[resource]
|
|
const maxField = maxMap[resource]
|
|
|
|
if (typeof valueField === "undefined" || typeof maxField === "undefined") {
|
|
return object
|
|
}
|
|
const effectiveMax = Math.max(0, max)
|
|
const effectiveValue = Math.max(0, Math.min(value, effectiveMax))
|
|
return {
|
|
...object,
|
|
[valueField as KeySetT]: effectiveValue,
|
|
[maxField as KeySetT]: effectiveMax,
|
|
}
|
|
}
|
|
|
|
export function clearResource<
|
|
KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>
|
|
(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}, object: ObjectT, resource: ResourceT): ObjectT {
|
|
const valueField = valueMap[resource]
|
|
const maxField = maxMap[resource]
|
|
|
|
const isValidValue = typeof valueField !== "undefined" && object.hasOwnProperty(valueField)
|
|
const isValidMax = typeof maxField !== "undefined" && object.hasOwnProperty(maxField)
|
|
|
|
const result: { -readonly [key in keyof ObjectT]: ObjectT[key] } = {...object}
|
|
if (isValidValue) {
|
|
delete result[valueField as KeySetT]
|
|
}
|
|
if (isValidMax) {
|
|
delete result[maxField as KeySetT]
|
|
}
|
|
return result as ObjectT
|
|
}
|
|
|
|
export interface ResourceManipulator<ObjectT, ResourceT> {
|
|
getValue(object: ObjectT, resource: ResourceT): number|undefined
|
|
getMax(object: ObjectT, resource: ResourceT): number|undefined
|
|
setValue(object: ObjectT, resource: ResourceT, value: number): ObjectT
|
|
setMax(object: ObjectT, resource: ResourceT, max: number): ObjectT
|
|
setMetered(object: ObjectT, resource: ResourceT, value: number, max: number): ObjectT
|
|
applyDelta(object: ObjectT, resource: ResourceT, delta: number): ObjectT
|
|
clear(object: ObjectT, resource: ResourceT): ObjectT
|
|
}
|
|
|
|
export function createResourceManipulator<KeySetT extends string|number|symbol, ObjectT extends {[key in KeySetT]?: number},
|
|
ResourceT extends string|number|symbol>(valueMap: {[key in ResourceT]: KeySetT|undefined}, maxMap: {[key in ResourceT]: KeySetT|undefined}): ResourceManipulator<ObjectT, ResourceT> {
|
|
return {
|
|
getValue(object: ObjectT, resource: ResourceT): number | undefined {
|
|
return getResourceValue(valueMap, object, resource)
|
|
},
|
|
applyDelta(object: ObjectT, resource: ResourceT, delta: number): ObjectT {
|
|
return applyResourceDelta(valueMap, maxMap, object, resource, delta)
|
|
},
|
|
getMax(object: ObjectT, resource: ResourceT): number | undefined {
|
|
return getResourceValue(maxMap, object, resource)
|
|
},
|
|
setMax(object: ObjectT, resource: ResourceT, max: number): ObjectT {
|
|
return setResourceMax(valueMap, maxMap, object, resource, max)
|
|
},
|
|
setMetered(object: ObjectT, resource: ResourceT, value: number, max: number): ObjectT {
|
|
return setMeteredResource(valueMap, maxMap, object, resource, value, max);
|
|
},
|
|
setValue(object: ObjectT, resource: ResourceT, value: number): ObjectT {
|
|
return setResourceValue(valueMap, maxMap, object, resource, value);
|
|
},
|
|
clear(object: ObjectT, resource: ResourceT): ObjectT {
|
|
return clearResource(valueMap, maxMap, object, resource)
|
|
}
|
|
}
|
|
}
|
|
|