Compare commits
3 Commits
ecc82a9dce
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 3faab5e206 | |||
| d2435eee7f | |||
| 5858e2808d |
@@ -1,4 +1,4 @@
|
|||||||
<div class="bg-red-100 w-full max-w-[1024px] aspect-square">
|
<div class="bg-red-100 w-full max-w-[1024px] aspect-square">
|
||||||
<div class="text-lg text-primary-700">{{ chibi().state }}</div>
|
<div class="text-lg text-primary-700">{{ chibi().currentStateName }}</div>
|
||||||
<canvas class="w-full h-full" #canvas></canvas>
|
<canvas class="w-full h-full" #canvas></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
import { Chibi, ChibiId } from "../../types/chibi/chibi";
|
import { Chibi, ChibiId, ChibiStatBar } from "../../types/chibi/chibi";
|
||||||
import { EChibiName } from "../../types/chibi/chibi-name";
|
import { EChibiName } from "../../types/chibi/chibi-name";
|
||||||
import { EChibiStateName } from "../../types/chibi/chibi-state-name";
|
import { EChibiStateName } from "../../types/chibi/chibi-state-name";
|
||||||
|
|
||||||
|
export const statBar = (current: number, max: number): ChibiStatBar => {
|
||||||
|
return {
|
||||||
|
current,
|
||||||
|
max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const MAX_STAT_VALUE: number = 100000;
|
export const MAX_STAT_VALUE: number = 100000;
|
||||||
|
|
||||||
export const CHIBIS: Chibi[] = [
|
export const CHIBIS: Chibi[] = [
|
||||||
@@ -12,16 +19,35 @@ export const CHIBIS: Chibi[] = [
|
|||||||
spritePath: '',
|
spritePath: '',
|
||||||
experience: 0,
|
experience: 0,
|
||||||
unlocked: true,
|
unlocked: true,
|
||||||
happyness: MAX_STAT_VALUE,
|
happyness: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
health: MAX_STAT_VALUE,
|
health: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
hunger: MAX_STAT_VALUE,
|
hunger: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
boredom: MAX_STAT_VALUE,
|
boredom: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
energy: MAX_STAT_VALUE,
|
energy: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
attentionSpan: 1000,
|
attentionSpan: 1000,
|
||||||
recoveryRate: 1000,
|
recoveryRate: 1000,
|
||||||
constitution: 1000,
|
constitution: 1000,
|
||||||
power: 1000,
|
power: 1000,
|
||||||
maintenanceCals: 0,
|
maintenanceCals: 0,
|
||||||
state: EChibiStateName.Sleeping
|
currentStateName: EChibiStateName.Sleeping
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '238df3e7-3003-4471-91f5-a7ecf3151e18' as ChibiId,
|
||||||
|
name: EChibiName.Caethya,
|
||||||
|
iconPath: '',
|
||||||
|
spritePath: '',
|
||||||
|
experience: 0,
|
||||||
|
unlocked: true,
|
||||||
|
happyness: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
|
health: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
|
hunger: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
|
boredom: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
|
energy: statBar(MAX_STAT_VALUE, MAX_STAT_VALUE),
|
||||||
|
attentionSpan: 1000,
|
||||||
|
recoveryRate: 1000,
|
||||||
|
constitution: 1000,
|
||||||
|
power: 1000,
|
||||||
|
maintenanceCals: 0,
|
||||||
|
currentStateName: EChibiStateName.Idle
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
91
src/app/logic/chibi-behaviour/basic.brain.ts
Normal file
91
src/app/logic/chibi-behaviour/basic.brain.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import { Chibi } from "../../types/chibi/chibi";
|
||||||
|
import { EChibiInteraction } from "../../types/chibi/chibi-interaction";
|
||||||
|
import { ChibiState, STATES } from "../../types/chibi/chibi-state";
|
||||||
|
import { EChibiStateName } from "../../types/chibi/chibi-state-name";
|
||||||
|
import { RandomService } from "../random.service";
|
||||||
|
import { IBrain } from "./brain";
|
||||||
|
|
||||||
|
export type InteractionMap = { [key in EChibiStateName]: InteractionRecord | undefined }
|
||||||
|
|
||||||
|
export type ChibiInteraction<T = null> = {
|
||||||
|
name: EChibiInteraction;
|
||||||
|
payload: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InteractionResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
|
||||||
|
export type InteractionRecord = Partial<Record<EChibiInteraction, InteractionResolutionFunction>>;
|
||||||
|
|
||||||
|
export type ResolutionFunction = () => ChibiState | undefined;
|
||||||
|
export type ResolutionMap = { [key in EChibiStateName]: ResolutionFunction | undefined }
|
||||||
|
|
||||||
|
export abstract class BasicBrain implements IBrain {
|
||||||
|
|
||||||
|
protected randomService!: RandomService;
|
||||||
|
protected chibi!: Chibi;
|
||||||
|
|
||||||
|
protected readonly defaultState: EChibiStateName = EChibiStateName.Sleeping;
|
||||||
|
|
||||||
|
protected hasBeenAwakeFor: number = 0;
|
||||||
|
protected timeSinceLastInteraction: number = 0;
|
||||||
|
protected timeInCurrentState: number = 0;
|
||||||
|
|
||||||
|
protected abstract interactionMap: InteractionMap;
|
||||||
|
protected abstract resolutionMap: ResolutionMap;
|
||||||
|
|
||||||
|
get state(): ChibiState {
|
||||||
|
return STATES[this.chibi.currentStateName];
|
||||||
|
}
|
||||||
|
|
||||||
|
init(chibi: Chibi, randomService: RandomService): void {
|
||||||
|
this.randomService = randomService;
|
||||||
|
this.chibi = chibi;
|
||||||
|
}
|
||||||
|
|
||||||
|
exist(): void {
|
||||||
|
this.timeInCurrentState++;
|
||||||
|
const resolution = this.matchResolution(this.resolutionMap, STATES[this.chibi.currentStateName]);
|
||||||
|
if (resolution) {
|
||||||
|
const newState = resolution();
|
||||||
|
if (newState && newState != STATES[this.chibi.currentStateName]) {
|
||||||
|
this.changeState(newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveInteraction(interaction: ChibiInteraction): void {
|
||||||
|
this.timeSinceLastInteraction = 0;
|
||||||
|
const resolution = this.matchInteraction(this.interactionMap, interaction.name, STATES[this.chibi.currentStateName]);
|
||||||
|
console.log('resolution', resolution);
|
||||||
|
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
|
||||||
|
if (resolution) {
|
||||||
|
this.changeState(resolution(interaction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matchInteraction(map: InteractionMap, interaction: EChibiInteraction, state: ChibiState): InteractionResolutionFunction | undefined {
|
||||||
|
const directMatch = map?.[state.name]?.[interaction];
|
||||||
|
if (directMatch) {
|
||||||
|
return directMatch;
|
||||||
|
}
|
||||||
|
if (state.parent) {
|
||||||
|
return this.matchInteraction(map, interaction, state.parent);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
matchResolution(map: ResolutionMap, state: ChibiState): ResolutionFunction | undefined {
|
||||||
|
const directMatch = map?.[state.name];
|
||||||
|
if (directMatch) {
|
||||||
|
return directMatch;
|
||||||
|
}
|
||||||
|
if (state.parent) {
|
||||||
|
return this.matchResolution(map, state.parent);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected changeState(state: ChibiState): void {
|
||||||
|
this.chibi.currentStateName = state.name;
|
||||||
|
this.timeInCurrentState = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,15 +1,20 @@
|
|||||||
import { EChibiName } from "../../types/chibi/chibi-name";
|
import { EChibiName } from "../../types/chibi/chibi-name";
|
||||||
import { IBrain } from "./brain";
|
import { IBrain } from "./brain";
|
||||||
import { Aperio } from "./brains/aperio.brain";
|
import { Aperio } from "./brains/aperio.brain";
|
||||||
|
import { Caethya } from "./brains/caethya.brain";
|
||||||
|
import { Haetor } from "./brains/haetor.brain";
|
||||||
|
|
||||||
const APERIO = new Aperio();
|
const APERIO = new Aperio();
|
||||||
|
const CAETHYA = new Caethya();
|
||||||
|
const HAETOR = new Haetor();
|
||||||
|
|
||||||
export const BRAIN_MAP: Record<EChibiName, IBrain> = {
|
export const BRAIN_MAP: Record<EChibiName, IBrain> = {
|
||||||
[EChibiName.Aperio]: APERIO,
|
[EChibiName.Aperio]: APERIO,
|
||||||
[EChibiName.Basra]: APERIO,
|
[EChibiName.Basra]: APERIO,
|
||||||
[EChibiName.Caethya]: APERIO,
|
[EChibiName.Caethya]: CAETHYA,
|
||||||
[EChibiName.Eos]: APERIO,
|
[EChibiName.Eos]: APERIO,
|
||||||
[EChibiName.Evina]: APERIO,
|
[EChibiName.Evina]: APERIO,
|
||||||
|
[EChibiName.Haetor]: HAETOR,
|
||||||
[EChibiName.Sol]: APERIO,
|
[EChibiName.Sol]: APERIO,
|
||||||
[EChibiName.Sybil]: APERIO,
|
[EChibiName.Sybil]: APERIO,
|
||||||
[EChibiName.Vinera]: APERIO
|
[EChibiName.Vinera]: APERIO
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Chibi } from "../../types/chibi/chibi";
|
import { Chibi } from "../../types/chibi/chibi";
|
||||||
import { RandomService } from "../random.service";
|
import { RandomService } from "../random.service";
|
||||||
import { ChibiInteraction } from "./brains/aperio.brain";
|
import { ChibiInteraction } from "./basic.brain";
|
||||||
|
|
||||||
export interface IBrain {
|
export interface IBrain {
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
import { Chibi } from "../../../types/chibi/chibi";
|
|
||||||
import { EChibiInteraction } from "../../../types/chibi/chibi-interaction";
|
import { EChibiInteraction } from "../../../types/chibi/chibi-interaction";
|
||||||
import { ChibiState, isState, STATE_AWAKE, STATE_EATING, STATE_GRUMBLING, STATE_IDLE, STATE_SLEEPING, STATES } from "../../../types/chibi/chibi-state";
|
import { ChibiState, STATE_AWAKE, STATE_EATING, STATE_GRUMBLING, STATE_IDLE, STATE_SLEEPING } from "../../../types/chibi/chibi-state";
|
||||||
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
|
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
|
||||||
import { Food } from "../../../types/food";
|
import { Food } from "../../../types/food";
|
||||||
import { RandomOutcome, RandomService } from "../../random.service";
|
import { RandomOutcome, } from "../../random.service";
|
||||||
import { IBrain } from "../brain";
|
import { BasicBrain, ChibiInteraction, InteractionMap, ResolutionMap } from "../basic.brain";
|
||||||
|
|
||||||
export type ChibiInteraction<T = null> = {
|
|
||||||
name: EChibiInteraction;
|
|
||||||
payload: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResolutionFunction = (interaction: ChibiInteraction<any>) => ChibiState;
|
|
||||||
type InteractionRecord = Partial<Record<EChibiInteraction, ResolutionFunction>>;
|
|
||||||
|
|
||||||
const MAX_TIME_AWAKE: number = 10;
|
const MAX_TIME_AWAKE: number = 10;
|
||||||
|
|
||||||
@@ -22,22 +13,12 @@ const SADNESS_FROM_NEGLECT: number = 50;
|
|||||||
const MAX_DURATION_GRUMBLE: number = 1;
|
const MAX_DURATION_GRUMBLE: number = 1;
|
||||||
const MAX_DURATION_EATING: number = 1;
|
const MAX_DURATION_EATING: number = 1;
|
||||||
|
|
||||||
export class Aperio implements IBrain {
|
export class Aperio extends BasicBrain {
|
||||||
|
|
||||||
private randomService!: RandomService;
|
|
||||||
private chibi!: Chibi;
|
|
||||||
|
|
||||||
private readonly defaultState: EChibiStateName = EChibiStateName.Sleeping;
|
|
||||||
private previousState: EChibiStateName = this.defaultState;
|
|
||||||
|
|
||||||
private hasBeenAwakeFor: number = 0;
|
|
||||||
private timeSinceLastInteraction: number = 0;
|
|
||||||
private timeInCurrentState: number = 0;
|
|
||||||
private lastConsumedFoods: string[] = [];
|
private lastConsumedFoods: string[] = [];
|
||||||
private preferredFoods: string[] = [];
|
private preferredFoods: string[] = [];
|
||||||
|
|
||||||
private state: ChibiState = STATES[this.defaultState];
|
protected override interactionMap: InteractionMap = {
|
||||||
private interactionMap: { [key in EChibiStateName]: InteractionRecord | undefined } = {
|
|
||||||
[EChibiStateName.Sleeping]: {
|
[EChibiStateName.Sleeping]: {
|
||||||
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
|
[EChibiInteraction.WakeUp]: (interaction: ChibiInteraction): ChibiState => this.wakeUp(interaction),
|
||||||
},
|
},
|
||||||
@@ -56,102 +37,77 @@ export class Aperio implements IBrain {
|
|||||||
[EChibiStateName.Depressed]: undefined,
|
[EChibiStateName.Depressed]: undefined,
|
||||||
[EChibiStateName.Tired]: undefined
|
[EChibiStateName.Tired]: undefined
|
||||||
}
|
}
|
||||||
|
protected override resolutionMap: ResolutionMap = {
|
||||||
init(chibi: Chibi, randomService: RandomService): void {
|
[EChibiStateName.Sleeping]: (): ChibiState | undefined => this.resolveSleeping(),
|
||||||
this.randomService = randomService;
|
[EChibiStateName.Awake]: (): ChibiState | undefined => this.resolveAwake(),
|
||||||
this.chibi = chibi;
|
[EChibiStateName.Snoring]: undefined,
|
||||||
this.state = STATES[chibi.state];
|
[EChibiStateName.Nightmare]: undefined,
|
||||||
}
|
[EChibiStateName.Grumbling]: (): ChibiState | undefined => this.resolveGrumbling(),
|
||||||
|
[EChibiStateName.Bored]: undefined,
|
||||||
exist(): void {
|
[EChibiStateName.Idle]: undefined,
|
||||||
this.timeInCurrentState++;
|
[EChibiStateName.Exited]: undefined,
|
||||||
this.resolveAwake();
|
[EChibiStateName.Fighting]: undefined,
|
||||||
this.resolveSleeping();
|
[EChibiStateName.Eating]: (): ChibiState | undefined => this.resolveEating(),
|
||||||
this.resolveGrumbling();
|
[EChibiStateName.Hungry]: undefined,
|
||||||
this.resolveEating();
|
[EChibiStateName.Depressed]: undefined,
|
||||||
}
|
[EChibiStateName.Tired]: undefined
|
||||||
|
|
||||||
resolveInteraction(interaction: ChibiInteraction): void {
|
|
||||||
this.timeSinceLastInteraction = 0;
|
|
||||||
const specificMatch: ResolutionFunction | undefined = this.interactionMap[this.state.name]?.[interaction.name];
|
|
||||||
const awakeMatch: ResolutionFunction | undefined = this.interactionMap[EChibiStateName.Awake]?.[interaction.name];
|
|
||||||
const asleepMatch: ResolutionFunction | undefined = this.interactionMap[EChibiStateName.Sleeping]?.[interaction.name];
|
|
||||||
const resolution: ResolutionFunction | undefined = specificMatch || (this.isAwake() ? awakeMatch : asleepMatch);
|
|
||||||
console.log(`specific match: ${specificMatch}`);
|
|
||||||
console.log(`${this.chibi.name} should ${interaction.name} with payload: ${interaction.payload}`);
|
|
||||||
if (resolution) {
|
|
||||||
this.changeState(resolution(interaction));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isAwake(): boolean {
|
|
||||||
return isState(this.state, EChibiStateName.Awake);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolvers
|
// resolvers
|
||||||
// functions which auitomatically resolve based on the existence cycle
|
// functions which automatically resolve based on the existence cycle
|
||||||
|
|
||||||
resolveAwake(): void {
|
resolveAwake(): ChibiState | undefined {
|
||||||
if (this.isAwake()) {
|
console.log(`${this.chibi.name} is awake.`);
|
||||||
console.log(`${this.chibi.name} is awake.`);
|
this.timeSinceLastInteraction++;
|
||||||
this.timeSinceLastInteraction++;
|
this.hasBeenAwakeFor++;
|
||||||
this.hasBeenAwakeFor++;
|
|
||||||
|
|
||||||
if (this.timeInCurrentState % 10 === 0) {
|
if (this.timeInCurrentState % 10 === 0) {
|
||||||
this.saddenedByNeglect(this.timeSinceLastInteraction, SADNESS_FROM_NEGLECT);
|
this.saddenedByNeglect(this.timeSinceLastInteraction, SADNESS_FROM_NEGLECT);
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
|
|
||||||
this.changeState(STATE_SLEEPING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.hasBeenAwakeFor > MAX_TIME_AWAKE) {
|
||||||
|
return STATE_SLEEPING;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
increaseHappyness(increase: number): void {
|
resolveSleeping(): ChibiState | undefined {
|
||||||
|
console.log(`${this.chibi.name} is sleeping.`);
|
||||||
|
this.hasBeenAwakeFor = 0;
|
||||||
|
this.increaseHappyness(HAPPINESS_FROM_SLEEP);
|
||||||
|
const awakeChance = this.randomService.obtainRandom(2048);
|
||||||
|
if (awakeChance.matchesChance(1)) {
|
||||||
|
return STATE_AWAKE;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveGrumbling(): ChibiState | undefined {
|
||||||
|
console.log(`${this.chibi.name} is grumbling. ${this.timeInCurrentState}`);
|
||||||
|
if (this.timeInCurrentState > MAX_DURATION_GRUMBLE) {
|
||||||
|
return STATE_SLEEPING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveEating(): ChibiState | undefined {
|
||||||
|
console.log(`${this.chibi.name} is eating. ${this.timeInCurrentState}`);
|
||||||
|
if (this.timeInCurrentState > MAX_DURATION_EATING) {
|
||||||
|
return STATE_IDLE;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private increaseHappyness(increase: number): void {
|
||||||
console.log(`${this.chibi.name} happyness increases.`);
|
console.log(`${this.chibi.name} happyness increases.`);
|
||||||
this.chibi.happyness = this.chibi.happyness + increase;
|
this.chibi.happyness.current = this.chibi.happyness.current + increase;
|
||||||
}
|
}
|
||||||
|
|
||||||
saddenedByNeglect(neglectTime: number, sadness: number): void {
|
private saddenedByNeglect(neglectTime: number, sadness: number): void {
|
||||||
console.log(`${this.chibi.name} happyness decreases.`);
|
console.log(`${this.chibi.name} happyness decreases.`);
|
||||||
this.chibi.happyness = this.chibi.happyness - (neglectTime * sadness);
|
this.chibi.happyness.current = this.chibi.happyness.current - (neglectTime * sadness);
|
||||||
}
|
|
||||||
|
|
||||||
resolveSleeping(): void {
|
|
||||||
if (isState(this.state, EChibiStateName.Sleeping)) {
|
|
||||||
console.log(`${this.chibi.name} is sleeping.`);
|
|
||||||
this.hasBeenAwakeFor = 0;
|
|
||||||
this.increaseHappyness(HAPPINESS_FROM_SLEEP);
|
|
||||||
const awakeChance = this.randomService.obtainRandom(2048);
|
|
||||||
if (awakeChance.matchesChance(1)) {
|
|
||||||
this.changeState(STATE_AWAKE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveGrumbling(): void {
|
|
||||||
if (isState(this.state, EChibiStateName.Grumbling)) {
|
|
||||||
console.log(`${this.chibi.name} is grumbling.`);
|
|
||||||
if (this.timeInCurrentState > MAX_DURATION_GRUMBLE) {
|
|
||||||
this.changeState(STATE_SLEEPING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveEating(): void {
|
|
||||||
if (isState(this.state, EChibiStateName.Eating)) {
|
|
||||||
console.log(`${this.chibi.name} is eating.`);
|
|
||||||
if (this.timeInCurrentState > MAX_DURATION_EATING) {
|
|
||||||
this.changeState(STATES[this.previousState]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private changeState(state: ChibiState): void {
|
|
||||||
this.previousState = this.state.name;
|
|
||||||
this.state = state;
|
|
||||||
this.chibi.state = this.state.name;
|
|
||||||
this.timeInCurrentState = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
36
src/app/logic/chibi-behaviour/brains/caethya.brain.ts
Normal file
36
src/app/logic/chibi-behaviour/brains/caethya.brain.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
|
||||||
|
import { BasicBrain, InteractionMap, ResolutionMap } from "../basic.brain";
|
||||||
|
|
||||||
|
export class Caethya extends BasicBrain {
|
||||||
|
protected override interactionMap: InteractionMap = {
|
||||||
|
[EChibiStateName.Sleeping]: undefined,
|
||||||
|
[EChibiStateName.Awake]: undefined,
|
||||||
|
[EChibiStateName.Snoring]: undefined,
|
||||||
|
[EChibiStateName.Nightmare]: undefined,
|
||||||
|
[EChibiStateName.Grumbling]: undefined,
|
||||||
|
[EChibiStateName.Bored]: undefined,
|
||||||
|
[EChibiStateName.Idle]: undefined,
|
||||||
|
[EChibiStateName.Exited]: undefined,
|
||||||
|
[EChibiStateName.Fighting]: undefined,
|
||||||
|
[EChibiStateName.Eating]: undefined,
|
||||||
|
[EChibiStateName.Hungry]: undefined,
|
||||||
|
[EChibiStateName.Depressed]: undefined,
|
||||||
|
[EChibiStateName.Tired]: undefined
|
||||||
|
};
|
||||||
|
protected override resolutionMap: ResolutionMap = {
|
||||||
|
[EChibiStateName.Sleeping]: undefined,
|
||||||
|
[EChibiStateName.Snoring]: undefined,
|
||||||
|
[EChibiStateName.Nightmare]: undefined,
|
||||||
|
[EChibiStateName.Grumbling]: undefined,
|
||||||
|
[EChibiStateName.Awake]: undefined,
|
||||||
|
[EChibiStateName.Bored]: undefined,
|
||||||
|
[EChibiStateName.Idle]: undefined,
|
||||||
|
[EChibiStateName.Exited]: undefined,
|
||||||
|
[EChibiStateName.Fighting]: undefined,
|
||||||
|
[EChibiStateName.Eating]: undefined,
|
||||||
|
[EChibiStateName.Hungry]: undefined,
|
||||||
|
[EChibiStateName.Depressed]: undefined,
|
||||||
|
[EChibiStateName.Tired]: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
36
src/app/logic/chibi-behaviour/brains/haetor.brain.ts
Normal file
36
src/app/logic/chibi-behaviour/brains/haetor.brain.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { EChibiStateName } from "../../../types/chibi/chibi-state-name";
|
||||||
|
import { BasicBrain, InteractionMap, ResolutionMap } from "../basic.brain";
|
||||||
|
|
||||||
|
export class Haetor extends BasicBrain {
|
||||||
|
protected override interactionMap: InteractionMap = {
|
||||||
|
[EChibiStateName.Sleeping]: undefined,
|
||||||
|
[EChibiStateName.Awake]: undefined,
|
||||||
|
[EChibiStateName.Snoring]: undefined,
|
||||||
|
[EChibiStateName.Nightmare]: undefined,
|
||||||
|
[EChibiStateName.Grumbling]: undefined,
|
||||||
|
[EChibiStateName.Bored]: undefined,
|
||||||
|
[EChibiStateName.Idle]: undefined,
|
||||||
|
[EChibiStateName.Exited]: undefined,
|
||||||
|
[EChibiStateName.Fighting]: undefined,
|
||||||
|
[EChibiStateName.Eating]: undefined,
|
||||||
|
[EChibiStateName.Hungry]: undefined,
|
||||||
|
[EChibiStateName.Depressed]: undefined,
|
||||||
|
[EChibiStateName.Tired]: undefined
|
||||||
|
};
|
||||||
|
protected override resolutionMap: ResolutionMap = {
|
||||||
|
[EChibiStateName.Sleeping]: undefined,
|
||||||
|
[EChibiStateName.Snoring]: undefined,
|
||||||
|
[EChibiStateName.Nightmare]: undefined,
|
||||||
|
[EChibiStateName.Grumbling]: undefined,
|
||||||
|
[EChibiStateName.Awake]: undefined,
|
||||||
|
[EChibiStateName.Bored]: undefined,
|
||||||
|
[EChibiStateName.Idle]: undefined,
|
||||||
|
[EChibiStateName.Exited]: undefined,
|
||||||
|
[EChibiStateName.Fighting]: undefined,
|
||||||
|
[EChibiStateName.Eating]: undefined,
|
||||||
|
[EChibiStateName.Hungry]: undefined,
|
||||||
|
[EChibiStateName.Depressed]: undefined,
|
||||||
|
[EChibiStateName.Tired]: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,43 +14,45 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="h-1/3 min-h-20 bg-primary-300 relative">
|
<div class="h-1/3 min-h-20 bg-primary-300 relative">
|
||||||
<ff-food-pantry
|
@if (chibi()) {
|
||||||
[isVisible]="shownMenu == EInteractionMenuState.Pantry"
|
<ff-food-pantry
|
||||||
(onClose)="closeMenu()"
|
[isVisible]="shownMenu == EInteractionMenuState.Pantry"
|
||||||
(onFoodChosen)="interact(EChibiInteraction.Feed, $event)"
|
(onClose)="closeMenu()"
|
||||||
></ff-food-pantry>
|
(onFoodChosen)="interact(EChibiInteraction.Feed, $event)"
|
||||||
|
></ff-food-pantry>
|
||||||
|
|
||||||
<ff-inventory
|
<ff-inventory
|
||||||
[isVisible]="shownMenu == EInteractionMenuState.Inventory"
|
[isVisible]="shownMenu == EInteractionMenuState.Inventory"
|
||||||
(onClose)="closeMenu()"
|
(onClose)="closeMenu()"
|
||||||
></ff-inventory>
|
></ff-inventory>
|
||||||
|
|
||||||
<ff-visitor-list
|
<ff-visitor-list
|
||||||
[isVisible]="shownMenu == EInteractionMenuState.VisitorList"
|
[isVisible]="shownMenu == EInteractionMenuState.VisitorList"
|
||||||
(onClose)="closeMenu()"
|
(onClose)="closeMenu()"
|
||||||
[host]="chibi()"
|
[host]="chibi()"
|
||||||
[visitors]="[]"
|
[visitors]="[]"
|
||||||
></ff-visitor-list>
|
></ff-visitor-list>
|
||||||
|
|
||||||
<div class="flex flex-row gap-5 py-4 container mx-auto">
|
<div class="flex flex-row gap-5 py-4 container mx-auto">
|
||||||
<ff-button (click)="openInventory()">{{
|
<ff-button (click)="openInventory()">{{
|
||||||
lang.game.actions.giveItem
|
lang.game.actions.giveItem
|
||||||
}}</ff-button>
|
|
||||||
<ff-button (click)="openFoodPantry()">{{
|
|
||||||
lang.game.actions.feed
|
|
||||||
}}</ff-button>
|
|
||||||
<ff-button (click)="openVisitorList()">{{
|
|
||||||
lang.game.actions.inviteVisitor
|
|
||||||
}}</ff-button>
|
|
||||||
@if (isAwake()) {
|
|
||||||
<ff-button (click)="interact(EChibiInteraction.WakeUp)">{{
|
|
||||||
lang.game.actions.wakeUp
|
|
||||||
}}</ff-button>
|
}}</ff-button>
|
||||||
} @else {
|
<ff-button (click)="openFoodPantry()">{{
|
||||||
<ff-button (click)="interact(EChibiInteraction.PutToSleep)">{{
|
lang.game.actions.feed
|
||||||
lang.game.actions.putToSleep
|
|
||||||
}}</ff-button>
|
}}</ff-button>
|
||||||
}
|
<ff-button (click)="openVisitorList()">{{
|
||||||
</div>
|
lang.game.actions.inviteVisitor
|
||||||
|
}}</ff-button>
|
||||||
|
@if (isAwake()) {
|
||||||
|
<ff-button (click)="interact(EChibiInteraction.PutToSleep)">{{
|
||||||
|
lang.game.actions.putToSleep
|
||||||
|
}}</ff-button>
|
||||||
|
} @else {
|
||||||
|
<ff-button (click)="interact(EChibiInteraction.WakeUp)">{{
|
||||||
|
lang.game.actions.wakeUp
|
||||||
|
}}</ff-button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import { IBrain } from '../../logic/chibi-behaviour/brain';
|
|||||||
import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map';
|
import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map';
|
||||||
import { TranslateableComponent } from '../../components/translateable.component';
|
import { TranslateableComponent } from '../../components/translateable.component';
|
||||||
import { Food } from '../../types/food';
|
import { Food } from '../../types/food';
|
||||||
import { interval, Subscribable, Subscription } from 'rxjs';
|
import { interval, Subscription } from 'rxjs';
|
||||||
import { RandomService } from '../../logic/random.service';
|
import { RandomService } from '../../logic/random.service';
|
||||||
import { ChibiInteraction } from '../../logic/chibi-behaviour/brains/aperio.brain';
|
|
||||||
import { isState, STATES } from '../../types/chibi/chibi-state';
|
import { isState, STATES } from '../../types/chibi/chibi-state';
|
||||||
import { EChibiStateName } from '../../types/chibi/chibi-state-name';
|
import { EChibiStateName } from '../../types/chibi/chibi-state-name';
|
||||||
import { VisitorListComponent } from "../../components/interaction-menus/visitor-list/visitor-list.component";
|
import { VisitorListComponent } from "../../components/interaction-menus/visitor-list/visitor-list.component";
|
||||||
|
import { ChibiInteraction } from '../../logic/chibi-behaviour/basic.brain';
|
||||||
|
|
||||||
enum EInteractionMenuState {
|
enum EInteractionMenuState {
|
||||||
Neutral,
|
Neutral,
|
||||||
@@ -70,7 +70,7 @@ export class InteractionsComponent extends TranslateableComponent implements OnD
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isAwake(): boolean {
|
public isAwake(): boolean {
|
||||||
return isState(STATES[this.chibi().state], EChibiStateName.Awake);
|
return isState(STATES[this.chibi().currentStateName], EChibiStateName.Awake);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interact(interaction: EChibiInteraction, item?: Food): void {
|
public interact(interaction: EChibiInteraction, item?: Food): void {
|
||||||
@@ -78,6 +78,7 @@ export class InteractionsComponent extends TranslateableComponent implements OnD
|
|||||||
this.brain.resolveInteraction({ name: interaction, payload: item } as ChibiInteraction<Food>);
|
this.brain.resolveInteraction({ name: interaction, payload: item } as ChibiInteraction<Food>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public openFoodPantry(): void {
|
public openFoodPantry(): void {
|
||||||
this.interactionMenuState.set(EInteractionMenuState.Pantry);
|
this.interactionMenuState.set(EInteractionMenuState.Pantry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export enum EChibiName {
|
|||||||
Caethya = 'Caethya',
|
Caethya = 'Caethya',
|
||||||
Eos = 'Eos',
|
Eos = 'Eos',
|
||||||
Evina = 'Evina',
|
Evina = 'Evina',
|
||||||
|
Haetor = 'Haetor',
|
||||||
Sol = 'Sol',
|
Sol = 'Sol',
|
||||||
Sybil = 'Sybil',
|
Sybil = 'Sybil',
|
||||||
Vinera = 'Vinera'
|
Vinera = 'Vinera'
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export type ChibiPreview = {
|
|||||||
id: ChibiId;
|
id: ChibiId;
|
||||||
name: EChibiName;
|
name: EChibiName;
|
||||||
iconPath: string;
|
iconPath: string;
|
||||||
happyness: number;
|
happyness: ChibiStatBar;
|
||||||
level: number;
|
level: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,15 +19,15 @@ export type Chibi = {
|
|||||||
spritePath: string;
|
spritePath: string;
|
||||||
experience: number;
|
experience: number;
|
||||||
unlocked: boolean;
|
unlocked: boolean;
|
||||||
state: EChibiStateName;
|
currentStateName: EChibiStateName;
|
||||||
} & ChibiWellnessStats & ChibiTraits;
|
} & ChibiWellnessStats & ChibiTraits;
|
||||||
|
|
||||||
export type ChibiWellnessStats = {
|
export type ChibiWellnessStats = {
|
||||||
happyness: number;
|
happyness: ChibiStatBar;
|
||||||
health: number;
|
health: ChibiStatBar;
|
||||||
hunger: number; //feed them
|
hunger: ChibiStatBar; //feed them
|
||||||
boredom: number; //do activities to alleviate boredom
|
boredom: ChibiStatBar; //do activities to alleviate boredom
|
||||||
energy: number; //let them rest
|
energy: ChibiStatBar; //let them rest
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChibiTraits = {
|
export type ChibiTraits = {
|
||||||
@@ -37,3 +37,8 @@ export type ChibiTraits = {
|
|||||||
power: number; //how much damage they deal
|
power: number; //how much damage they deal
|
||||||
maintenanceCals: number; //how quickly they get hungry
|
maintenanceCals: number; //how quickly they get hungry
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ChibiStatBar = {
|
||||||
|
current: number;
|
||||||
|
max: number;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user