a bunch of stuff

materials
Bronwen 2021-07-19 01:53:30 -04:00
parent 64bcd9761f
commit a75c18d197
15 changed files with 194 additions and 65 deletions

View File

@ -30,6 +30,7 @@ export const LOG = new Item()
export const STICK = new Item()
.setName("Stick")
.plural('Sticks')
.setId('core:resources/stick')
export const PLANT_FIBRES = new Item()

View File

@ -80,5 +80,7 @@ export class Game extends Frigid implements Tickable, Renderable {
render() {
this.menu.render();
this.board.render();
// TODO this logic dont make sense
return '';
}
}

View File

@ -3,13 +3,13 @@ import faker from 'faker';
import { Task, TaskState } from './registries/Tasks.js';
import Time, { Tickable } from './Time.js';
import { Game } from './Game.js';
import { render } from './ui/UI.js';
import { render, Renderable, RenderMode } from './ui/UI.js';
import { Memory } from './Memory.js';
import { getTheme } from '@themes';
// TODO add stats getter to return % of all stats
export class Pawn extends Serializable implements Tickable {
export class Pawn extends Serializable implements Tickable, Renderable {
name: {
first: string,
last: string
@ -18,7 +18,7 @@ export class Pawn extends Serializable implements Tickable {
age: number;
memories: Memory[];
job: TaskState<unknown>;
job: TaskState<unknown, unknown>;
async tick() {
this.age ++;
@ -81,10 +81,22 @@ export class Pawn extends Serializable implements Tickable {
}
toString() {
if(this.name) {
return this.name.first + ' ' + this.name.last;
} else {
return '[Object Pawn]';
return this.render(RenderMode.ONELINE);
}
render(mode: RenderMode): string {
if(mode === RenderMode.ONELINE) {
if(this.name) {
return this.name.first + ' ' + this.name.last;
} else {
return '[Object Pawn]';
}
} else if (mode === RenderMode.DETAILS) {
return `${
this.toString()
}{|}${
this.status
}\nDETAILS\nDETAILS`
}
}
}

View File

@ -40,6 +40,7 @@ export class TaskList extends Serializable implements Renderable {
} ${
getTheme().dimmed(task.worker?.toString() ?? '')
}`).join('\n')}`);
return '';
// return this.tasks.map(task => task.toString()).join('\n');
}
}

View File

@ -4,11 +4,12 @@ import { Task, TaskState } from "@tasks";
import { Serializable } from "frigid";
import { RESOURCE_COLLECTION_TASK } from "./world/ResourceCollectionTask.js";
const explorationConstant = 0.001; // km ish
export class World extends Serializable {
places: PlaceState[] = [];
distanceExplored = 0; // km ish
explorationConstant = 0.001; // km ish
distanceExplored: number; // km ish
home: PlaceState = null;
@ -18,7 +19,7 @@ export class World extends Serializable {
explore() {
for(const [id, place] of places) {
const threshold = (this.explorationConstant * place.frequency);
const threshold = (explorationConstant * place.frequency);
if(Math.random() <= threshold) {
const angle = Math.random() * Math.PI * 2
const x = Math.sin(angle) * this.distanceExplored;
@ -34,10 +35,11 @@ export class World extends Serializable {
this.places.push(newPlaceState);
}
}
this.distanceExplored += this.explorationConstant;
this.distanceExplored += explorationConstant;
}
ctor() {
this.distanceExplored ??= 0;
this.home ??= null;
this.places ??= [];
if(this.home === null) {

View File

@ -7,6 +7,7 @@ import { fileURLToPath } from 'url';
import { Game } from '@game';
import { isStarted, stop } from './ui/UI.js';
import { writeFileSync } from 'fs';
import ansi from 'sisteransi';
console.clear();
@ -20,6 +21,7 @@ function gracefulShutdown() {
Game.current.sync();
}
console.log('exitting');
process.stdout.write(ansi.cursor.show);
process.exit(0);
}
process.on('exit', gracefulShutdown);
@ -50,11 +52,11 @@ for(const path of extensions) {
console.log('Setup Complete.');
for(let seconds = 2; seconds > 0; seconds --) {
for(let seconds = 0; seconds > 0; seconds --) {
process.stdout.write('Starting DF-Idle in ' + seconds + '\r');
await new Promise(res => setTimeout(res, 1000));
}
console.log();
console.clear();
// TODO move render logic into game, so that the ui doesnt exist until the game does...
// maybe, i mean, an argument could be made for not that, because the game

View File

@ -9,16 +9,25 @@ const items = new Map<ItemID, Item<any>>();
// ITEMS SHALL BE SINGULAR
export class Item<Data = any> extends Serializable {
name = '';
name = {
singular: '',
plural: ''
}
id: ItemID = '';
props: Map<string, any> = new Map();
setName(name: string) {
this.name = name;
this.name.singular = name;
this.name.plural = name;
this.register(false);
return this;
}
plural(name: string) {
this.name.plural = name;
return this;
}
setId(id: ItemID) {
this.id = id;
this.register(false);
@ -27,7 +36,7 @@ export class Item<Data = any> extends Serializable {
register(force = true) {
if((!this.id || !this.name) && !force) return;
console.log('Added item', (this.name ?? "[No Name]").padStart(20, ' '), `| (${this.id})`)
console.log('Added item', (this.name.singular ?? "[No Name]").padStart(20, ' '), `| (${this.id})`)
items.set(this.id, this);
return this;
}

View File

@ -54,7 +54,7 @@ export const backupTheme: Theme = {
selected: chalk.ansi256(117).inverse
},
border: {
focused: '#ffffff',
focused: '#00ff00',
normal: '#888888'
},
progressBar: {

View File

@ -0,0 +1,72 @@
import { Game } from "@game";
import { boxStyle, getTheme } from "@themes";
import { panels } from "@ui";
import blessed from 'neo-blessed';
// TODO convert all these popup-y things to be View based
// make them be boxes that have a view
export class EscapeMenu {
options = [
'RESUME',
'QUIT'
];
selected = 0;
box;
static show() {
new EscapeMenu();
}
protected constructor() {
this.box = blessed.box({
top: 3,
left: 'center',
width: 30,
height: 'shrink',
content: '',
tags: true,
...boxStyle(),
});
this.box.on('keypress', (evt: {}, key: {full: string}) => {
if(key.full === 'up') {
this.selected --;
if(this.selected === -1) this.selected = this.options.length - 1;
} else if (key.full === 'down') {
this.selected ++;
if(this.selected === this.options.length) this.selected = 0;
} else if (key.full === 'enter') {
switch(this.selected) {
case 0: {
Game.current.clock.start();
panels.screen.remove(this.box);
break;
}
case 1: {
Game.current.sync();
process.exit(0);
}
}
} else if(key.full === 'escape') {
Game.current.clock.start();
panels.screen.remove(this.box);
}
this.render();
});
panels.screen.append(this.box);
this.box.focus();
Game.current.clock.pause();
this.render();
}
render() {
this.box.setContent(' Paused\n\n' + this.options.map((v, i) => {
if(i === this.selected) {
return ` ${getTheme().bright(v)} `;
} else {
return ` ${getTheme().normal(v)} `;
}
}).join('\n'));
panels.screen.render();
}
}

View File

@ -10,8 +10,8 @@ import PawnsView from './view/PawnsView.js';
import InventoryView from './view/InventoryView.js';
import MultiplayerView from './view/MultiplayerView.js';
import { View } from './View.js';
import { ActionsView } from './view/ActionsView.js';
import WorldResourcesView from './view/WorldView.js';
import { EscapeMenu } from './EscapeMenu.js';
const clamp = (min: number, max: number, value: number) => Math.min(Math.max(value, min), max);
@ -28,7 +28,6 @@ export class Menu implements Renderable {
new PawnsView(),
new InventoryView(),
new MultiplayerView(),
new ActionsView(),
new WorldResourcesView()
]
@ -54,7 +53,7 @@ export class Menu implements Renderable {
} else if (key.full === 'right') {
this.advanceView();
} else if (key.full === 'escape') {
this.advanceView();
EscapeMenu.show();
// debugging hotkeys
} else if (key.full === '1') {
@ -113,5 +112,6 @@ export class Menu implements Renderable {
this.renderView(),
].join('\n');
panels.right.setContent(content);
return '';
}
}

View File

@ -11,7 +11,7 @@ export class Popup {
new Popup(content)
}
private constructor(content: string) {
protected constructor(content: string) {
this.box = blessed.box({
top: 'center',
left: 'center',

View File

@ -0,0 +1,49 @@
import { Renderable, RenderMode } from './UI.js';
import { KeypressAcceptor } from './Menu.js';
import { getTheme } from '@themes';
export class SelectionBox implements Renderable, KeypressAcceptor {
selectedIdx = 0;
stuff: Renderable[] = [];
height: number;
offset: number = 0;
getData: () => Renderable[];
// buffer =
constructor(height: number) {
this.height = height;
}
setGetData(fn: () => Renderable[]) {
this.getData = fn;
}
render() {
return this.stuff.map((renderable, idx) => {
if(idx === this.selectedIdx) {
return ` ${getTheme().bright(` ${renderable.render(RenderMode.DETAILS)}`)} `;
} else {
return ` ${getTheme().normal(` ${renderable.render(RenderMode.DETAILS)}`)} `;
}
}).join('\n')
}
up() {
this.selectedIdx --;
// if(this.selectedIdx === -1) {
// }
}
down() {
this.selectedIdx ++;
}
keypress(key: { full: string; }) {
if(key.full === 'up') {
}
};
}

View File

@ -5,7 +5,7 @@ import { boxStyle, getTheme } from '@themes';
export { Popup } from './Popup.js';
export interface Renderable {
render(): void
render(mode?: RenderMode): string
}
let leftPanel: any;
@ -58,7 +58,7 @@ export function render(thing?: Renderable) {
export function start() {
assertNotStarted();
process.stdout.write('\x1b[?1049h');
// process.stdout.write('\x1b[?1049h');
screen = blessed.screen({
smartCSR: true,
@ -99,12 +99,12 @@ export function start() {
process.stdout.write(ansi.cursor.hide);
// todo make a real menu
screen.key(['C-c'], function() {
process.stdout.write(ansi.cursor.show);
setTimeout(_ => {
process.exit(0);
})
});
// screen.key(['C-c'], function() {
// process.stdout.write(ansi.cursor.show);
// setTimeout(_ => {
// process.exit(0);
// })
// });
screen.key('f2', () => {
rightPanel.focus();
@ -120,7 +120,7 @@ export function start() {
export function stop() {
screen.destroy();
process.stdout.write('\x1b[?1049l');
// process.stdout.write('\x1b[?1049l');
}
// move to some debugging shit, idk
@ -144,4 +144,10 @@ ansiTestCard += '{/center}';
export {
ansiTestCard
};
};
export enum RenderMode {
ONELINE,
DETAILS,
DYNAMIC
}

View File

@ -1,33 +0,0 @@
import { getTheme } from "@themes";
import { Game } from "../../Game.js";
import { Renderable } from "../UI.js";
import { View } from "../View.js";
import { actions } from "@actions";
export class ActionsView extends View {
actionIdx: number = 0;
constructor() {
super();
this.name = 'Actions';
}
keypress(key: {full: string}) {
if(key.full === 'up') {
this.actionIdx --;
} else if (key.full === 'down') {
this.actionIdx ++;
} else if (key.full === 'enter') {
actions[this.actionIdx].invoke(1);
}
}
render() {
return actions.map((action, idx) => `${(() => {
if(this.actionIdx === idx) {
return getTheme().bright(' ' + action.name);
} else {
return getTheme().normal(' ' + action.name);
}
})()}`).join('\n');
}
}

View File

@ -17,7 +17,13 @@ export const RESOURCE_COLLECTION_TASK =
}))
.setToString((data, state) => {
return 'Collect ' + data.node.resources.item.name + ' from ' + data.node.place.place.name;
return 'Collect ' +
data.qty +
' ' +
(data.qty === 1 ? data.node.resources.item.name.singular :
data.node.resources.item.name.plural) +
' from ' +
data.node.place.place.name;
})
.setInitiate((data: Data) => {
return {