Implemented hunger mechanic
This commit is contained in:
parent
6b5c94d62e
commit
856809cade
2 changed files with 183 additions and 25 deletions
|
@ -49,7 +49,7 @@ enum LinkType {
|
||||||
// Links cause gain/loss of one resource to also affect other resources
|
// Links cause gain/loss of one resource to also affect other resources
|
||||||
type ResourceLink = {
|
type ResourceLink = {
|
||||||
resource: string;
|
resource: string;
|
||||||
amount: DecimalSource;
|
amount: DecimalSource | (() => DecimalSource);
|
||||||
linkType: LinkType;
|
linkType: LinkType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,11 +64,28 @@ type Resource = {
|
||||||
|
|
||||||
const resources = {
|
const resources = {
|
||||||
time: createResource("time", "#3EB489", 24 * 60 * 60, 24 * 60 * 60, [
|
time: createResource("time", "#3EB489", 24 * 60 * 60, 24 * 60 * 60, [
|
||||||
{ resource: "mental", amount: 1 / (120 * 60), linkType: LinkType.LossOnly }
|
{ resource: "mental", amount: 1 / (120 * 60), linkType: LinkType.LossOnly },
|
||||||
|
{ resource: "hunger", amount: -1 / (15 * 60), linkType: LinkType.LossOnly }
|
||||||
]),
|
]),
|
||||||
energy: createResource("energy", "#FFA500", 100, 100),
|
energy: createResource("energy", "#FFA500", 100, 100),
|
||||||
mental: createResource("mental", "#32CD32", 100, 100),
|
mental: createResource("mental", "#32CD32", 100, 100),
|
||||||
focus: createResource("focus", "#0000FF", 100, 0)
|
focus: createResource("focus", "#0000FF", 100, 0),
|
||||||
|
hunger: createResource("hunger", "#FFFF00", 100, 0, [
|
||||||
|
{
|
||||||
|
resource: "focus",
|
||||||
|
amount() {
|
||||||
|
// the higher hunger goes, the more focus it consumes
|
||||||
|
// the idea being the amount lost is the area under the y=x line
|
||||||
|
// that's right, using calculus in a video game :sunglasses:
|
||||||
|
return new Decimal(resources.hunger.amount)
|
||||||
|
.div(10)
|
||||||
|
.pow(1.5)
|
||||||
|
.div(1.5)
|
||||||
|
.neg();
|
||||||
|
},
|
||||||
|
linkType: LinkType.GainOnly
|
||||||
|
}
|
||||||
|
])
|
||||||
} as Record<string, Resource>;
|
} as Record<string, Resource>;
|
||||||
|
|
||||||
function createResource(
|
function createResource(
|
||||||
|
@ -279,7 +296,8 @@ const actions = {
|
||||||
],
|
],
|
||||||
baseChanges: [
|
baseChanges: [
|
||||||
{ resource: "time", amount: 16 * 60 * 60, assign: true },
|
{ resource: "time", amount: 16 * 60 * 60, assign: true },
|
||||||
{ resource: "energy", amount: 100, assign: true }
|
{ resource: "energy", amount: 100, assign: true },
|
||||||
|
{ resource: "hunger", amount: 20 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
forcedSleep: {
|
forcedSleep: {
|
||||||
|
@ -298,7 +316,10 @@ const actions = {
|
||||||
weight: 1
|
weight: 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
baseChanges: [{ resource: "mental", amount: -10 }]
|
baseChanges: [
|
||||||
|
{ resource: "mental", amount: -10 },
|
||||||
|
{ resource: "hunger", amount: 20 }
|
||||||
|
]
|
||||||
},
|
},
|
||||||
rest: {
|
rest: {
|
||||||
icon: "chair",
|
icon: "chair",
|
||||||
|
@ -306,10 +327,7 @@ const actions = {
|
||||||
events: [
|
events: [
|
||||||
{
|
{
|
||||||
event: () => {
|
event: () => {
|
||||||
resources.energy.amount = Decimal.sub(
|
resources.energy.amount = Decimal.add(resources.energy.amount, 10);
|
||||||
resources.energy.amount || 100,
|
|
||||||
Decimal.times(10, focusMult.value)
|
|
||||||
);
|
|
||||||
return { description: "You rest your eyes for a bit and wake up rejuvenated" };
|
return { description: "You rest your eyes for a bit and wake up rejuvenated" };
|
||||||
},
|
},
|
||||||
weight: 90
|
weight: 90
|
||||||
|
@ -324,10 +342,7 @@ const actions = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
event: () => {
|
event: () => {
|
||||||
resources.energy.amount = Decimal.add(
|
resources.energy.amount = Decimal.add(resources.energy.amount, 20);
|
||||||
resources.energy.amount,
|
|
||||||
Decimal.times(20, focusMult.value)
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
description:
|
description:
|
||||||
"You take an incredible power nap and wake up significantly more refreshed",
|
"You take an incredible power nap and wake up significantly more refreshed",
|
||||||
|
@ -380,6 +395,118 @@ const actions = {
|
||||||
{ resource: "energy", amount: -5 },
|
{ resource: "energy", amount: -5 },
|
||||||
{ resource: "mental", amount: 5 }
|
{ resource: "mental", amount: 5 }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
eat: {
|
||||||
|
icon: "restaurant",
|
||||||
|
tooltip: "Eat meal",
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
event: () => ({ description: `You eat a delicious meal. Nice!` }),
|
||||||
|
weight: 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
resources.mental.amount = Decimal.add(resources.mental.amount, 10);
|
||||||
|
return {
|
||||||
|
description: `This is your favorite meal! Oh, what a treat!`,
|
||||||
|
effectDescription: `+10% <span style="color: ${resources.mental.color}">Mental</span> `
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
resources.energy.amount = Decimal.sub(resources.energy.amount, 10);
|
||||||
|
resources.hunger.amount = Decimal.add(resources.hunger.amount, 25);
|
||||||
|
return {
|
||||||
|
description: `Oh no, I'm not sure that food was still good`,
|
||||||
|
effectDescription: `-10% <span style="color: ${resources.energy.color}">Energy</span>, -25% <span style="color: ${resources.hunger.color}">Hunger</span> depletion `
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
baseChanges: [
|
||||||
|
{ resource: "time", amount: -30 * 60 },
|
||||||
|
{ resource: "energy", amount: 10 },
|
||||||
|
{ resource: "hunger", amount: -70 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
snack: {
|
||||||
|
icon: "icecream",
|
||||||
|
tooltip: "Eat snack",
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
event: () => ({ description: `You have a nice, small snack. Nice!` }),
|
||||||
|
weight: 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
resources.energy.amount = Decimal.add(resources.energy.amount, 10);
|
||||||
|
return {
|
||||||
|
description: `You chose a healthy, delicious snack. You feel really good!`,
|
||||||
|
effectDescription: `+10% <span style="color: ${resources.energy.color}">Energy</span> `
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
resources.mental.amount = Decimal.sub(resources.mental.amount, 5);
|
||||||
|
resources.hunger.amount = Decimal.add(resources.hunger.amount, 10);
|
||||||
|
return {
|
||||||
|
description: `You gorge yourself on unhealthy foods, and don't feel so good`,
|
||||||
|
effectDescription: `-5% <span style="color: ${resources.mental.color}">Mental</span>, -10% <span style="color: ${resources.hunger.color}">Hunger</span> depletion `
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
baseChanges: [
|
||||||
|
{ resource: "time", amount: -20 * 60 },
|
||||||
|
{ resource: "mental", amount: 2 },
|
||||||
|
{ resource: "hunger", amount: -25 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
forcedSnack: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
resources.mental.amount = Decimal.sub(resources.mental.amount, 15);
|
||||||
|
return {
|
||||||
|
description: `You scarf down anything and everything around you. That can't be good for you.`,
|
||||||
|
effectDescription: `-15% <span style="color: ${resources.mental.color}">Mental</span> `
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
baseChanges: [
|
||||||
|
{ resource: "time", amount: -20 * 60 },
|
||||||
|
{ resource: "hunger", amount: -25 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
brush: {
|
||||||
|
icon: "mood",
|
||||||
|
tooltip: "Brush Teeth",
|
||||||
|
enabled: () =>
|
||||||
|
Decimal.lt(player.lastDayBrushed as DecimalSource, player.day as DecimalSource),
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
event: () => {
|
||||||
|
player.lastDayBrushed = player.day;
|
||||||
|
return {
|
||||||
|
description: `Brushing once a day is 33% of the way towards keeping the dentist at bay`
|
||||||
|
};
|
||||||
|
},
|
||||||
|
weight: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
baseChanges: [
|
||||||
|
{ resource: "time", amount: -5 * 60 },
|
||||||
|
{ resource: "energy", amount: -2 },
|
||||||
|
{ resource: "mental", amount: 2 }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
} as Record<string, Action>;
|
} as Record<string, Action>;
|
||||||
|
|
||||||
|
@ -425,6 +552,10 @@ const actionNodes = {
|
||||||
bed: {
|
bed: {
|
||||||
actions: ["sleep", "rest", "makeBed"],
|
actions: ["sleep", "rest", "makeBed"],
|
||||||
display: "Bed"
|
display: "Bed"
|
||||||
|
},
|
||||||
|
food: {
|
||||||
|
actions: ["eat", "snack", "brush"],
|
||||||
|
display: "Food"
|
||||||
}
|
}
|
||||||
} as Record<string, ActionNode>;
|
} as Record<string, ActionNode>;
|
||||||
|
|
||||||
|
@ -474,9 +605,10 @@ for (const id in resources) {
|
||||||
}
|
}
|
||||||
const resource = resources[link.resource];
|
const resource = resources[link.resource];
|
||||||
if (resource.amount != null) {
|
if (resource.amount != null) {
|
||||||
|
const amount = typeof link.amount === "function" ? link.amount() : link.amount;
|
||||||
resource.amount = Decimal.add(
|
resource.amount = Decimal.add(
|
||||||
resource.amount,
|
resource.amount,
|
||||||
Decimal.times(link.amount, resourceGain)
|
Decimal.times(amount, resourceGain)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -532,14 +664,17 @@ const resourceNodeType = {
|
||||||
const link = selectedResource.links.find(link => link.resource === resource.name);
|
const link = selectedResource.links.find(link => link.resource === resource.name);
|
||||||
if (link) {
|
if (link) {
|
||||||
let text;
|
let text;
|
||||||
|
const amount = new Decimal(
|
||||||
|
typeof link.amount === "function" ? link.amount() : link.amount
|
||||||
|
).neg();
|
||||||
if (resource.name === "time") {
|
if (resource.name === "time") {
|
||||||
text = formatTime(link.amount);
|
text = formatTime(amount);
|
||||||
} else if (Decimal.eq(resource.maxAmount, 100)) {
|
} else if (Decimal.eq(resource.maxAmount, 100)) {
|
||||||
text = formatWhole(link.amount) + "%";
|
text = formatWhole(amount) + "%";
|
||||||
} else {
|
} else {
|
||||||
text = format(link.amount);
|
text = format(amount);
|
||||||
}
|
}
|
||||||
let negativeLink = Decimal.lt(link.amount, 0);
|
let negativeLink = Decimal.gt(amount, 0);
|
||||||
if (link.linkType === LinkType.LossOnly) {
|
if (link.linkType === LinkType.LossOnly) {
|
||||||
negativeLink = !negativeLink;
|
negativeLink = !negativeLink;
|
||||||
}
|
}
|
||||||
|
@ -709,14 +844,19 @@ const actionNodeType = {
|
||||||
}
|
}
|
||||||
} as RawFeature<NodeType>;
|
} as RawFeature<NodeType>;
|
||||||
|
|
||||||
function registerResourceDepletedAction(resource: string, nodeID: string, action: string) {
|
function registerResourceDepletedAction(
|
||||||
|
resource: string,
|
||||||
|
nodeID: string,
|
||||||
|
action: string,
|
||||||
|
threshold: 0 | 100 = 0
|
||||||
|
) {
|
||||||
watch(
|
watch(
|
||||||
() => ({
|
() => ({
|
||||||
amount: resources[resource].amount,
|
amount: resources[resource].amount,
|
||||||
forcedAction: player.layers.main?.forcedAction
|
forcedAction: player.layers.main?.forcedAction
|
||||||
}),
|
}),
|
||||||
({ amount, forcedAction }) => {
|
({ amount, forcedAction }) => {
|
||||||
if (Decimal.eq(amount, 0) && forcedAction == null) {
|
if (Decimal.eq(amount, threshold) && forcedAction == null) {
|
||||||
toast.error(coerceComponent(`${camelToTitle(resources[resource].name)} depleted!`));
|
toast.error(coerceComponent(`${camelToTitle(resources[resource].name)} depleted!`));
|
||||||
player.layers.main.forcedAction = {
|
player.layers.main.forcedAction = {
|
||||||
resource,
|
resource,
|
||||||
|
@ -735,6 +875,7 @@ function registerResourceDepletedAction(resource: string, nodeID: string, action
|
||||||
|
|
||||||
registerResourceDepletedAction("time", "bed", "forcedSleep");
|
registerResourceDepletedAction("time", "bed", "forcedSleep");
|
||||||
registerResourceDepletedAction("energy", "bed", "forcedRest");
|
registerResourceDepletedAction("energy", "bed", "forcedRest");
|
||||||
|
registerResourceDepletedAction("hunger", "food", "forcedSnack", 100);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
id: "main",
|
id: "main",
|
||||||
|
@ -822,6 +963,14 @@ export default {
|
||||||
amount: new Decimal(100)
|
amount: new Decimal(100)
|
||||||
} as ResourceNodeData
|
} as ResourceNodeData
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
position: { x: 150, y: 0 },
|
||||||
|
type: "resource",
|
||||||
|
data: {
|
||||||
|
resourceType: "hunger",
|
||||||
|
amount: new Decimal(0)
|
||||||
|
} as ResourceNodeData
|
||||||
|
},
|
||||||
{
|
{
|
||||||
position: { x: -150, y: 150 },
|
position: { x: -150, y: 150 },
|
||||||
type: "action",
|
type: "action",
|
||||||
|
@ -837,6 +986,14 @@ export default {
|
||||||
actionType: "bed",
|
actionType: "bed",
|
||||||
log: []
|
log: []
|
||||||
} as ActionNodeData
|
} as ActionNodeData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: { x: -300, y: 150 },
|
||||||
|
type: "action",
|
||||||
|
data: {
|
||||||
|
actionType: "food",
|
||||||
|
log: []
|
||||||
|
} as ActionNodeData
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
@ -892,14 +1049,14 @@ export default {
|
||||||
links.push(
|
links.push(
|
||||||
...resource.links.map(link => {
|
...resource.links.map(link => {
|
||||||
const linkResource = resources[link.resource];
|
const linkResource = resources[link.resource];
|
||||||
let negativeLink = Decimal.lt(link.amount, 0);
|
const amount =
|
||||||
if (link.linkType === LinkType.LossOnly) {
|
typeof link.amount === "function"
|
||||||
negativeLink = !negativeLink;
|
? link.amount()
|
||||||
}
|
: link.amount;
|
||||||
return {
|
return {
|
||||||
from: selectedNode.value,
|
from: selectedNode.value,
|
||||||
to: linkResource.node,
|
to: linkResource.node,
|
||||||
stroke: negativeLink ? "red" : "green",
|
stroke: Decimal.gt(amount, 0) ? "red" : "green",
|
||||||
"stroke-width": 4,
|
"stroke-width": 4,
|
||||||
pulsing: true
|
pulsing: true
|
||||||
} as BoardNodeLink;
|
} as BoardNodeLink;
|
||||||
|
|
|
@ -14,6 +14,7 @@ export function getStartingData(): Record<string, unknown> {
|
||||||
points: new Decimal(10),
|
points: new Decimal(10),
|
||||||
day: new Decimal(1),
|
day: new Decimal(1),
|
||||||
lastDayBedMade: new Decimal(0),
|
lastDayBedMade: new Decimal(0),
|
||||||
|
lastDayBrushed: new Decimal(0),
|
||||||
devStep: 0
|
devStep: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue