Skip to content

Commit

Permalink
feat: add action costs (#903)
Browse files Browse the repository at this point in the history
Signed-off-by: hxtree <[email protected]>
  • Loading branch information
hxtree authored Jun 16, 2024
1 parent a70c84b commit 4121bc8
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 17 deletions.
50 changes: 50 additions & 0 deletions services/character-sheet/src/data/action-cost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Duration } from 'luxon';
import { ItemId } from './item';
import { StatusEffectId } from './status-effect';
import { EffectTag } from './tag.effect';
import { Attribute } from './attribute';

/**
* What must be paid ahead of time to peform the action
*/
export enum ActionCostTarget {
// The cost of the action is paid by the performer
PERFORMER = 'PERFORMER',

// The cost of the action is paid by the target
TARGET = 'TARGET',

// The cost of the action is paid by the performer's inventory
INVENTORY = 'INVENTORY',
}

export type ActionCostInventory = {
remove: ItemId; // TODO what about stealable items?
quanity: number;
};

export type ActionCostStatusEffect = {
add: StatusEffectId;
chance?: number;
duration?: Duration;
tags?: Array<EffectTag>;
};

// TODO: By holding button longer how can additional cost can be consumed for some skills.
// e.g. min cost max cost? cost per second?

export type ActionCostAttribute = {
remove: Attribute;
quantity: string;
chance?: number;
tags?: Array<EffectTag>;
};

/**
* Cost is the resource expenditure that must be given up by Target prior to
* the action being able to be perform.
*/
export type ActionCost =
| ActionCostInventory
| ActionCostStatusEffect
| ActionCostAttribute;
23 changes: 23 additions & 0 deletions services/character-sheet/src/data/action-target.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Enum representing possible targets for actions.
* These area related to costs to peform an action but the impacts of the action
*/
export enum ActionTarget {
// An ally of the player
ALLY = 'ALLY',

// A region within the AOE map affecting all entities
AREA = 'AREA',

// Object or entity for interaction
INTERACTION_OBJECT = 'INTERACTION_OBJECT',

// The performers inventory or equipment
INVENTORY = 'INVENTORY',

// The player initiating the action
PERFORMER = 'PERFORMER',

// An opponent of the player
OPPONENT = 'OPPONENT',
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO some shapes do not tranlate well to 45 degree angles
export namespace AoeMap {
export namespace AreaOfEffect {
/**
* [z axis][y axis][x axis]
* 7 = hit, caster facing left
Expand Down
17 changes: 17 additions & 0 deletions services/character-sheet/src/data/skill-level.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Represents proficiency levels for active and passive skills, determining their effectiveness.
*/
export enum SkillLevel {
LV1 = 'LV1',
LV2 = 'LV2',
LV3 = 'LV3',
LV4 = 'LV4',
LV5 = 'LV5',
LV6 = 'LV6',
LV7 = 'LV7',
LV8 = 'LV8',
LV9 = 'LV9',
MAX = 'MAX',
}

// TODO : format skills as "Slash Lv.1" on frontend
27 changes: 24 additions & 3 deletions services/character-sheet/src/data/skill/drive.skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import { Duration } from 'luxon';
import { MenuSlot } from '../menu-slot';
import { ActionEffects } from '../table.effect';
import { Attribute } from '../attribute';
import { AreaOfEffect } from '../area-of-effect';

/**
* Drive Actions are special actions that consume drive gauge
Expand All @@ -13,6 +15,7 @@ export namespace Drive {
description: string;
conditions?: string;
menuSlot: MenuSlot;
areaOfEffect?: AreaOfEffect.Type;
actionEffects?: ActionEffects;
};

Expand All @@ -21,7 +24,7 @@ export namespace Drive {
description: 'Become completely focused on winning',
menuSlot: MenuSlot.THIRD,
actionEffects: {
CASTER: [
PERFORMER: [
{
add: 'BERSERK',
chance: 1.0,
Expand All @@ -34,8 +37,9 @@ export namespace Drive {

export const TOXIC_THRUST: Type = {
name: 'Toxic Thrust',
description: '',
description: 'Thrusts forward using posion',
menuSlot: MenuSlot.THIRD,
areaOfEffect: AreaOfEffect.LINE_10FT,
actionEffects: {
OPPONENT: [
{
Expand All @@ -52,14 +56,31 @@ export namespace Drive {
name: 'Aerial Assault',
description: 'Jump into air and throws boomerang (jump attack)',
menuSlot: MenuSlot.THIRD,
areaOfEffect: AreaOfEffect.LINE_10FT,
actionEffects: {
OPPONENT: [
{
remove: Attribute.LIFE,
quantity: '1d6',
chance: 0.3,
tags: [],
},
{
add: 'STUNNED',
chance: 0.3,
duration: Duration.fromObject({ seconds: 20 }),
tags: [],
},
],
},
};

export const ONI: Type = {
name: 'Oni',
description: `Become engulfed in a blood thirsty rage that multiplies your power but drains spirit.
If character stays in Oni too long they will go Berserk`,
actionEffects: {
CASTER: [
PERFORMER: [
{
add: 'ONI',
chance: 1.0,
Expand Down
45 changes: 43 additions & 2 deletions services/character-sheet/src/data/skill/interaction.skill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MenuSlot } from '../menu-slot';
import { ActionEffects } from '../table.effect';

/**
* Interaction skills are actions that can only be used when a compatible object is present.
Expand All @@ -10,6 +11,7 @@ export namespace Interaction {
description: string;
target: ObjectCategory;
menuSlot: MenuSlot;
actionEffects?: ActionEffects;
};

export enum ObjectCategory {
Expand All @@ -23,6 +25,15 @@ export namespace Interaction {
description: 'Grab an object.',
target: ObjectCategory.MOVEABLE,
menuSlot: MenuSlot.INTERACTION,
actionEffects: {
INTERACTION_OBJECT: [
{
add: 'BERSERK', // TODO figure out how to handle this
chance: 1.0,
tags: [],
},
],
},
};

export const PUSH: Type = {
Expand Down Expand Up @@ -58,16 +69,46 @@ export namespace Interaction {
description: 'Attempt to pick a lock.',
target: ObjectCategory.LOCKED,
menuSlot: MenuSlot.INTERACTION,
actionEffects: {
INVENTORY: [
{
add: 'BERSERK', // TODO figure out how to handle this, e.g. state UNLOCKED
chance: 0.7,
tags: [],
},
],
INTERACTION_OBJECT: [
{
add: 'BERSERK', // TODO figure out how to handle this, e.g. state UNLOCKED
chance: 0.7,
tags: [],
},
],
},
};

export const UNLOCK: Type = {
name: 'Unlock',
description: 'Open a lock using a key.',
// consumes a key
target: ObjectCategory.LOCKED,
menuSlot: MenuSlot.INTERACTION,
actionEffects: {
INVENTORY: [
{
remove: 'BERSERK', // TODO figure out how to handle this, e.g. state UNLOCKED
chance: 0.7,
tags: [],
},
],
INTERACTION_OBJECT: [
{
add: 'BERSERK', // TODO figure out how to handle this, e.g. state UNLOCKED
chance: 0.7,
tags: [],
},
],
},
};

// which essentially means that they take up a slot on the players Command
// Menu. InteractionSkill Actions take up the InteractionSkill Slot on the
// Command Menu. What distinguishes InteractionSkill Actions from the rest
Expand Down
4 changes: 2 additions & 2 deletions services/character-sheet/src/data/table.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SkillType } from './skill';
import { EffectTag } from './tag.effect';
import { StatusEffectId } from './status-effect';
import { Attribute } from './attribute';
import { Target } from './target.effect';
import { ActionTarget } from './action-target';

export enum Modifier {
ADD = 'ADD',
Expand Down Expand Up @@ -74,5 +74,5 @@ export type EffectTable = EffectRecord[];
* Each target is mapped to an array of EffectRecords capturing the effects.
*/
export type ActionEffects = {
[key in Target]?: EffectRecord[];
[key in ActionTarget]?: EffectRecord[];
};
9 changes: 0 additions & 9 deletions services/character-sheet/src/data/target.effect.ts

This file was deleted.

0 comments on commit 4121bc8

Please sign in to comment.