Minor refactoring across several modules

~ InputHandler action types made more logical and easy to maintain
~ "entity" type renamed to "entityController" in anticipation of another
entity interface for use by modules that damage and apply statuses to entities
~ Entities' CanUseAbility function changed to fall back to false rather than true
This commit is contained in:
loplkc loplkc 2022-04-12 21:23:33 -04:00
parent 991fce6103
commit 436cbde19d
5 changed files with 40 additions and 53 deletions

View file

@ -16,7 +16,7 @@ type validInput = Enum.KeyCode; // + Include controller "keys"
function isValidInput(value: unknown): value is validInput {
return enumTypeIs<Enum.KeyCode>(value, Enum.KeyCode);
}
const actionAssignmentsReference: string[] = [
const actionList = [
"clicker1", // What is used to click on things (enemies in game, UI elements)
"diamond1", // Diamond controls
"diamond2",
@ -24,21 +24,11 @@ const actionAssignmentsReference: string[] = [
"diamond4",
"special1", // Special controls
"special2",
];
export interface actionAssignments {
// Based on the reference array
clicker1?: validInput; // What is used to click on things (enemies in game, UI elements)
diamond1?: validInput; // Diamond controls
diamond2?: validInput;
diamond3?: validInput;
diamond4?: validInput;
special1?: validInput; // Special controls
special2?: validInput;
}
type action = keyof actionAssignments;
function isValidAction(value: string): value is keyof actionAssignments {
return value in actionAssignmentsReference; // uh oh
}
] as const;
type action = typeof actionList[number]
export type actionAssignments = {
[actionName in action]?: validInput;
};
type actionBinding = [action, (actionName: string, state: Enum.UserInputState, inputObject: InputObject) => void];
function getMouseLocation(filterDescendantsInstances: Instance[]): [Vector3, Vector3, Instance | undefined] {
@ -82,9 +72,9 @@ class actionHandler implements actionBinder {
}
assignInputsToActions(actionAssignments: unknownTable) {
const newActionAssignments: actionAssignments = {};
actionAssignmentsReference.forEach((action) => {
actionList.forEach((action) => {
const input: unknown = actionAssignments[action];
if (isValidAction(action) && isValidInput(input)) {
if (isValidInput(input)) {
newActionAssignments[action] = input;
}
});

View file

@ -1,4 +1,5 @@
import { entityModifier } from "./EntityManager"
export interface ability {
use: () => void; // ? Does it pass back information to the entity manager that it does something with? Is an ability really just a transform of entities?
use: (entities?: entityModifier[]) => void; // ? Does it pass back information to the entity manager that it does something with? Is an ability really just a transform of entities?
// ... this transform would need the positions and stats of the entities involved as well as potential obstacles
}

View file

@ -5,12 +5,14 @@ import { ability } from "./AbilityManager";
type stats = [maxHealth: number, attack: number, speed: number, defense: number]; // values used for calculation, only modified by buffs and debuffs
type amounts = [health: number, barrier: number]; // values used to store an entity's current status (more existential than stats)
export interface entity {
export interface entityController {
setPosition: (location: Vector3) => void;
ability: (ability: string, state: boolean) => void;
useAbility: (abilityName: string, activating: boolean) => void;
}
class entityHandler implements entity {
export interface entityModifier {}
class entityHandler implements entityController {
constructor(baseStats: stats, baseAmounts: amounts, puppetEntry: puppetEntry) {
this.baseStats = baseStats;
this.baseAmounts = baseAmounts;
@ -22,46 +24,39 @@ class entityHandler implements entity {
canUseAbility(abilityName: string): boolean {
// ! Not concurrency safe
// + buncha status checks
for (let i = 1; i <= 2; i++) {
const cooldown = this.cooldowns[abilityName];
if (cooldown !== undefined) {
const now = os.clock();
if (now - cooldown[0] >= cooldown[1]) {
this.cooldowns[abilityName] = undefined;
}
} else {
return true;
const cooldown = this.cooldowns[abilityName];
if (cooldown) {
const now = os.clock();
if (now - cooldown[0] < cooldown[1]) {
return false
}
}
return false;
return true;
}
ability(abilityName: string, activated: boolean) {
useAbility(abilityName: string, activating: boolean) {
const abilities = this.abilities;
if (abilities) {
if (activated) {
if (this.canUseAbility(abilityName)) {
const ability = abilities[abilityName];
if (ability !== undefined) {
ability.use();
}
if (activating) {
if (this.canUseAbility(abilityName)) {
const ability = abilities[abilityName];
if (ability != undefined) {
const abilityResult = ability.use();
}
} else {
// + Ability cancellation - perhaps the useAbility inside the entity returns a function to store that the ability watches that ceases the ability when executed
}
} else {
// + Ability cancellation - perhaps the useAbility inside the entity returns a function to store that the ability watches that ceases the ability when executed
}
// Blah blah blah
}
baseStats: stats;
baseAmounts: amounts;
puppet: puppet;
abilities?: {
[key: string]: ability;
};
abilities: {
[key: string]: ability | undefined;
} = {};
cooldowns: {
[key: string]: [start: number, length: number] | undefined;
} = {};
baseStats: stats;
baseAmounts: amounts;
}
export function makeEntity(

View file

@ -1,9 +1,10 @@
// "The": Handle events.
// WORST CONDITION RigHT NOW
import { makeEntity, entity } from "./EntityManager";
// Consider that this is the second module coupled to the EntityManager
import { makeEntity, entityController } from "./EntityManager";
interface event {
winEvents?: event[]; // A list of events that need to return true (in sequence) to complete this event
winEntities?: entity[]; // A list of entities that need to die to complete the event
winEntities?: entityController[]; // A list of entities that need to die to complete the event
timeout?: number; // A timeout for the event; passes a lose condition if there are other completion requirements that have not been satisfied
}
export function runEvent(event: event) {

View file

@ -1,5 +1,5 @@
// "PlayerManager": Handle the data of players. This involves receiving them when they arrive, cleaning up after they exit, teleporting them, etc.
import { makeEntity, entity } from "./EntityManager";
import { makeEntity, entityController } from "./EntityManager";
interface saveDataEntry {
// + May need to move this to archiver
@ -29,7 +29,7 @@ class storedPlayerHandler implements storedPlayer {
}
ability(ability: string, state: boolean) {
if (this.entity) {
this.entity.ability(ability, state);
this.entity.useAbility(ability, state);
}
}
loadIn() {
@ -40,7 +40,7 @@ class storedPlayerHandler implements storedPlayer {
inMainMenu: boolean;
// + Other data that is unique to players but does not persist between sessions
saveData: saveDataEntry; // This gets synced with the actual datastore
entity?: entity;
entity?: entityController;
}
export interface playerStorage {