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

View file

@ -1,4 +1,5 @@
import { entityModifier } from "./EntityManager"
export interface ability { 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 // ... 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 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) 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; 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) { constructor(baseStats: stats, baseAmounts: amounts, puppetEntry: puppetEntry) {
this.baseStats = baseStats; this.baseStats = baseStats;
this.baseAmounts = baseAmounts; this.baseAmounts = baseAmounts;
@ -22,46 +24,39 @@ class entityHandler implements entity {
canUseAbility(abilityName: string): boolean { canUseAbility(abilityName: string): boolean {
// ! Not concurrency safe // ! Not concurrency safe
// + buncha status checks // + buncha status checks
for (let i = 1; i <= 2; i++) { const cooldown = this.cooldowns[abilityName];
const cooldown = this.cooldowns[abilityName]; if (cooldown) {
if (cooldown !== undefined) { const now = os.clock();
const now = os.clock(); if (now - cooldown[0] < cooldown[1]) {
if (now - cooldown[0] >= cooldown[1]) { return false
this.cooldowns[abilityName] = undefined;
}
} else {
return true;
} }
} }
return false; return true;
} }
ability(abilityName: string, activated: boolean) { useAbility(abilityName: string, activating: boolean) {
const abilities = this.abilities; const abilities = this.abilities;
if (abilities) { if (activating) {
if (activated) { if (this.canUseAbility(abilityName)) {
if (this.canUseAbility(abilityName)) { const ability = abilities[abilityName];
const ability = abilities[abilityName]; if (ability != undefined) {
if (ability !== undefined) { const abilityResult = ability.use();
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 // Blah blah blah
} }
baseStats: stats;
baseAmounts: amounts;
puppet: puppet; puppet: puppet;
abilities?: { abilities: {
[key: string]: ability; [key: string]: ability | undefined;
}; } = {};
cooldowns: { cooldowns: {
[key: string]: [start: number, length: number] | undefined; [key: string]: [start: number, length: number] | undefined;
} = {}; } = {};
baseStats: stats;
baseAmounts: amounts;
} }
export function makeEntity( export function makeEntity(

View file

@ -1,9 +1,10 @@
// "The": Handle events. // "The": Handle events.
// WORST CONDITION RigHT NOW // 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 { interface event {
winEvents?: event[]; // A list of events that need to return true (in sequence) to complete this 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 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) { 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. // "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 { interface saveDataEntry {
// + May need to move this to archiver // + May need to move this to archiver
@ -29,7 +29,7 @@ class storedPlayerHandler implements storedPlayer {
} }
ability(ability: string, state: boolean) { ability(ability: string, state: boolean) {
if (this.entity) { if (this.entity) {
this.entity.ability(ability, state); this.entity.useAbility(ability, state);
} }
} }
loadIn() { loadIn() {
@ -40,7 +40,7 @@ class storedPlayerHandler implements storedPlayer {
inMainMenu: boolean; inMainMenu: boolean;
// + Other data that is unique to players but does not persist between sessions // + Other data that is unique to players but does not persist between sessions
saveData: saveDataEntry; // This gets synced with the actual datastore saveData: saveDataEntry; // This gets synced with the actual datastore
entity?: entity; entity?: entityController;
} }
export interface playerStorage { export interface playerStorage {