After further reading, re-combined the interfaces
= There wasn't really any point in trying to split the interfaces all the way up to the top level - this is a game; it is inevitable that some object data will change and some will stay the same
This commit is contained in:
parent
8a9d5414f8
commit
88129a87ba
3 changed files with 106 additions and 70 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
--An attempt to profile the speed of TweenService:GetValue
|
||||||
local TweenService = game:GetService("TweenService")
|
local TweenService = game:GetService("TweenService")
|
||||||
local clock = os.clock
|
local clock = os.clock
|
||||||
local first = clock()
|
local first = clock()
|
|
@ -1,12 +1,19 @@
|
||||||
// "EntityManager": Create entity objects and apply transformations to them.
|
// "EntityManager": Create entity objects and apply transformations to them.
|
||||||
// A bold attempt at functional programming in a videogame entity system
|
// A bold (or just foolish) attempt at functional programming in a videogame entity system
|
||||||
import { makePuppet, puppet, puppetEntry } from "./Puppetmaster";
|
import { makePuppet, puppet, puppetEntry } from "./Puppetmaster";
|
||||||
// import { ability } from "./AbilityManager";
|
// import { ability } from "./AbilityManager";
|
||||||
const entityTags = ["minion"] as const
|
const entityTags = ["minion"] as const;
|
||||||
type modifiers = readonly [power: number, speed: number, defense: number, resistance: number]; // values used for calculation, only modified by buffs and debuffs
|
type modifiers = readonly [power: number, speed: number, defense: number, resistance: number]; // values used for calculation, only modified by buffs and debuffs
|
||||||
type statuses = readonly [health: number, barrier: number]; // values used to store an entity's current status (more existential than stats)
|
type statuses = readonly [health: number, barrier: number]; // values used to store an entity's current status (more existential than stats)
|
||||||
type statusEffect = readonly [string, modifiers, entityTransformTemplate, number];
|
type statusEffect = readonly [
|
||||||
type entityTag = typeof entityTags[number]
|
name: string,
|
||||||
|
type: string,
|
||||||
|
strength: number,
|
||||||
|
modifiers?: modifiers,
|
||||||
|
effect?: entityTransformTemplate,
|
||||||
|
]; // Should also be able to cause a visual effect somehow - maybe rather than having an entityTransformTemplate, it should broadcast a message back to the top
|
||||||
|
// ...that can affect other entities or communicate with the client
|
||||||
|
type entityTag = typeof entityTags[number];
|
||||||
export interface entityId {
|
export interface entityId {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly team: "players" | "enemies";
|
readonly team: "players" | "enemies";
|
||||||
|
@ -15,20 +22,21 @@ export interface entityId {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface entityProperties {
|
export interface entityProperties {
|
||||||
readonly id: entityId,
|
readonly id: entityId;
|
||||||
readonly baseModifiers: modifiers,
|
readonly maxStatuses: statuses;
|
||||||
readonly maxStatuses: statuses,
|
readonly baseModifiers: modifiers;
|
||||||
readonly baseStatusEffects: statusEffect[],// Permanent immunities/status effects
|
readonly baseStatusEffects: statusEffect[]; // Permanent immunities/status effects
|
||||||
}
|
}
|
||||||
export interface entityStatuses {
|
export interface entity {
|
||||||
readonly statuses: statuses; // Health and stuff that change constantly
|
statuses: statuses;
|
||||||
readonly statusEffects: statusEffect[]; // Burn, poison, etc.
|
statusEffects: statusEffect[];
|
||||||
|
readonly properties: entityProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
type entityTransformType = "support" | "attack";
|
type entityTransformType = "support" | "attack";
|
||||||
type healthTransformValue = [magnitude: number, affectsHealth: boolean, affectsBarrier: boolean]
|
type healthTransformValue = [magnitude: number, affectsHealth: boolean, affectsBarrier: boolean];
|
||||||
interface entityTransformTemplate {
|
interface entityTransformTemplate {
|
||||||
healthTransformValue: healthTransformValue,
|
healthTransformValue: healthTransformValue;
|
||||||
statusEffectsGranted?: placeholder[]; // TBA (Stuff like burn, slow, stun, etc.)
|
statusEffectsGranted?: placeholder[]; // TBA (Stuff like burn, slow, stun, etc.)
|
||||||
}
|
}
|
||||||
type entityTransformDeterminer = (
|
type entityTransformDeterminer = (
|
||||||
|
@ -43,7 +51,8 @@ interface ability {
|
||||||
// Immunities are just status effects that take the place of a damaging status effect (so ones of that type can't be added) but don't do anything
|
// Immunities are just status effects that take the place of a damaging status effect (so ones of that type can't be added) but don't do anything
|
||||||
// Status effects have a strength value that determines whether they can override another status effect of the same type (holy inferno can replace burn but burn can't replace holy inferno)
|
// Status effects have a strength value that determines whether they can override another status effect of the same type (holy inferno can replace burn but burn can't replace holy inferno)
|
||||||
|
|
||||||
export interface entityController {//Deprecated
|
export interface entityController {
|
||||||
|
//Deprecated
|
||||||
setPosition: (location: Vector3) => void;
|
setPosition: (location: Vector3) => void;
|
||||||
useAbility: (abilityName: string, activating: boolean) => void;
|
useAbility: (abilityName: string, activating: boolean) => void;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +133,12 @@ function applyAttackToEntityStatuses(
|
||||||
): statuses {
|
): statuses {
|
||||||
// + Apply status effects of receiving entity to damage (e.g. armor break)
|
// + Apply status effects of receiving entity to damage (e.g. armor break)
|
||||||
const modifiedDamage = applyModifiersToDamage(entityTransformTemplate.magnitude, entityModifiers);
|
const modifiedDamage = applyModifiersToDamage(entityTransformTemplate.magnitude, entityModifiers);
|
||||||
const newStatuses = applyDamageToStatuses(entityStatuses, modifiedDamage, entityTransformTemplate.affectsHealth, entityTransformTemplate.affectsBarrier);
|
const newStatuses = applyDamageToStatuses(
|
||||||
|
entityStatuses,
|
||||||
|
modifiedDamage,
|
||||||
|
entityTransformTemplate.affectsHealth,
|
||||||
|
entityTransformTemplate.affectsBarrier,
|
||||||
|
);
|
||||||
return entityStatuses;
|
return entityStatuses;
|
||||||
}
|
}
|
||||||
/*function applyHealToEntityStats() {//if (transformType === "attack") {
|
/*function applyHealToEntityStats() {//if (transformType === "attack") {
|
||||||
|
@ -150,7 +164,13 @@ function applyHealToEntityStatuses(
|
||||||
entityStatusEffects: statusEffect[],
|
entityStatusEffects: statusEffect[],
|
||||||
): statuses {
|
): statuses {
|
||||||
// + Apply status effects of receiving entity to damage (e.g. heal up)
|
// + Apply status effects of receiving entity to damage (e.g. heal up)
|
||||||
const newStatuses = applyHealToStatuses(entityStatuses, entityTransformTemplate.magnitude, entityTransformTemplate.affectsHealth, entityTransformTemplate.affectsBarrier, entityMaxStatuses);
|
const newStatuses = applyHealToStatuses(
|
||||||
|
entityStatuses,
|
||||||
|
entityTransformTemplate.magnitude,
|
||||||
|
entityTransformTemplate.affectsHealth,
|
||||||
|
entityTransformTemplate.affectsBarrier,
|
||||||
|
entityMaxStatuses,
|
||||||
|
);
|
||||||
return entityStatuses;
|
return entityStatuses;
|
||||||
}
|
}
|
||||||
// ? Are you meant to pipe determineEntityTransform into the resulting function?
|
// ? Are you meant to pipe determineEntityTransform into the resulting function?
|
||||||
|
@ -178,7 +198,7 @@ function applyEntityToHeal(
|
||||||
entityTransformTemplate: entityTransformTemplate,
|
entityTransformTemplate: entityTransformTemplate,
|
||||||
): entityTransformTemplate {
|
): entityTransformTemplate {
|
||||||
// + Apply user's status effects to outgoing heal
|
// + Apply user's status effects to outgoing heal
|
||||||
return entityTransformTemplate // There could be a heal modifier later
|
return entityTransformTemplate; // There could be a heal modifier later
|
||||||
}
|
}
|
||||||
/*function transformEntityStats(
|
/*function transformEntityStats(
|
||||||
entityStats: entityStats,
|
entityStats: entityStats,
|
||||||
|
@ -307,17 +327,19 @@ function getEntityByName(entityList: entity[], entityName: string): success<enti
|
||||||
return [false, "Entity not found"];
|
return [false, "Entity not found"];
|
||||||
}
|
}
|
||||||
function getAbility() {}
|
function getAbility() {}
|
||||||
function applyEntityTransformToEntityStatuses(entityTransform: entityTransformTemplate, statuses: statuses, maxStatuses: statuses) {
|
function applyEntityTransformToEntityStatuses(
|
||||||
|
entityTransform: entityTransformTemplate,
|
||||||
}
|
statuses: statuses,
|
||||||
|
maxStatuses: statuses,
|
||||||
|
) {}
|
||||||
function applyEntityTransformToEntityList(
|
function applyEntityTransformToEntityList(
|
||||||
entityList: entity[],
|
entityList: entity[],
|
||||||
entityTransformDeterminer: entityTransformDeterminer,
|
entityTransformDeterminer: entityTransformDeterminer,
|
||||||
entityPerformingTransform: entity,
|
entityPerformingTransform: entity,
|
||||||
aim: Vector3,
|
aim: Vector3,
|
||||||
): [entity[], placeholder[]?] {
|
): [entity[], placeholder[]?] {
|
||||||
const entityPerformingTransformModifiers = entityPerformingTransform.baseModifiers
|
const entityPerformingTransformModifiers = entityPerformingTransform.baseModifiers;
|
||||||
const entityPerformingTransformStatusEffects = entityPerformingTransform.stats.statusEffects // Not good
|
const entityPerformingTransformStatusEffects = entityPerformingTransform.stats.statusEffects; // Not good
|
||||||
const newEntityList = entityList.map(function (entityReceivingTransform: entity): entity {
|
const newEntityList = entityList.map(function (entityReceivingTransform: entity): entity {
|
||||||
const entityTransform = entityTransformDeterminer(
|
const entityTransform = entityTransformDeterminer(
|
||||||
entityPerformingTransform.id,
|
entityPerformingTransform.id,
|
||||||
|
@ -326,13 +348,13 @@ function applyEntityTransformToEntityList(
|
||||||
entityReceivingTransform.puppet,
|
entityReceivingTransform.puppet,
|
||||||
);
|
);
|
||||||
if (entityTransform) {
|
if (entityTransform) {
|
||||||
const entityStatuses = entityPerformingTransform.stats.statuses
|
const entityStatuses = entityPerformingTransform.stats.statuses;
|
||||||
const [entityTransformType, entityTransformTemplate] = entityTransform
|
const [entityTransformType, entityTransformTemplate] = entityTransform;
|
||||||
if (entityTransformType === "attack") {
|
if (entityTransformType === "attack") {
|
||||||
const outgoingTransformTemplate = applyEntityToAttack(
|
const outgoingTransformTemplate = applyEntityToAttack(
|
||||||
entityPerformingTransformModifiers,
|
entityPerformingTransformModifiers,
|
||||||
entityPerformingTransformStatusEffects,
|
entityPerformingTransformStatusEffects,
|
||||||
entityTransformTemplate
|
entityTransformTemplate,
|
||||||
);
|
);
|
||||||
const newEntityStatuses = outgoingTransformTemplate
|
const newEntityStatuses = outgoingTransformTemplate
|
||||||
? applyAttackToEntityStatuses(
|
? applyAttackToEntityStatuses(
|
||||||
|
@ -343,11 +365,12 @@ function applyEntityTransformToEntityList(
|
||||||
)
|
)
|
||||||
: entityStatuses; // Also cringe
|
: entityStatuses; // Also cringe
|
||||||
} else {
|
} else {
|
||||||
assert(entityTransformType === "heal")
|
assert(entityTransformType === "heal");
|
||||||
const outgoingTransformTemplate = applyEntityToHeal( // Lots of DRY violations here
|
const outgoingTransformTemplate = applyEntityToHeal(
|
||||||
|
// Lots of DRY violations here
|
||||||
entityPerformingTransformModifiers,
|
entityPerformingTransformModifiers,
|
||||||
entityPerformingTransformStatusEffects,
|
entityPerformingTransformStatusEffects,
|
||||||
entityTransformTemplate
|
entityTransformTemplate,
|
||||||
);
|
);
|
||||||
const newEntityStatuses = outgoingTransformTemplate
|
const newEntityStatuses = outgoingTransformTemplate
|
||||||
? applyHealToEntityStatuses(
|
? applyHealToEntityStatuses(
|
||||||
|
|
|
@ -1,28 +1,37 @@
|
||||||
// "The": Handle events.
|
// "The": Handle events.
|
||||||
import { entityId, entityProperties, entityStatuses/*entityManagerRequest /*makeEntity, entityController*/ } from "./EntityManager";
|
import { entity } from "./EntityManager";
|
||||||
import { applyRequestsToPlayerStorage, playerManagerRequest } from "./PlayerManager"
|
import { applyRequestsToPlayerStorage, playerManagerRequest } from "./PlayerManager";
|
||||||
export type sceneManagerRequest = [Player, "useAbility", Vector3] | [Player, "foo", "bar"]
|
export type sceneManagerRequest = [Player, "useAbility", Vector3] | [Player, "foo", "bar"];
|
||||||
type endConditionFunction = (containedScenes: scene[], containedEntities: entity[], timeElapsed: number) => boolean
|
type endConditionFunction = (containedEntities: entity[], timeElapsed: number) => boolean;
|
||||||
export interface sceneTemplate {
|
export interface sceneTemplate {
|
||||||
readonly sceneComplete: endConditionFunction // Checks conditions that need to pass for the scene to end (e.g. entityX.Alive == false || timeSpent > 1000)
|
readonly sceneComplete: endConditionFunction; // Checks conditions that need to pass for the scene to end (e.g. entityX.Alive == false || timeSpent > 1000)
|
||||||
readonly onCompletion: readonly playerManagerRequest[] // Requests to get sent out when the scene ends
|
readonly onCompletion: readonly playerManagerRequest[]; // Requests to get sent out when the scene ends
|
||||||
}
|
}
|
||||||
export interface scene extends sceneTemplate {
|
export interface scene {
|
||||||
|
entities: entity[];
|
||||||
|
}
|
||||||
|
/*export interface sceneBackstage {
|
||||||
|
readonly entityProperties: {
|
||||||
|
[glumph: string]: entityProperties;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// export interface scene extends sceneTemplate {
|
||||||
/*containedScenes?: {
|
/*containedScenes?: {
|
||||||
[sceneName: string]: scene | undefined
|
[sceneName: string]: scene | undefined
|
||||||
}; // Scenes within this scene that are isolated from each other and can be run in parallel
|
}; // Scenes within this scene that are isolated from each other and can be run in parallel
|
||||||
// Not necessarily "A list of events that need to return true (in sequence) to complete this event", but such events would go there
|
// Not necessarily "A list of events that need to return true (in sequence) to complete this event", but such events would go there
|
||||||
*/ //Scene nesting is currently cancelled
|
*/ //Scene nesting is currently cancelled
|
||||||
containedEntities: string[]; // "A list of entities that need to die to complete the event" (not really but kinda)
|
// containedEntities: string[]; // "A list of entities that need to die to complete the event" (not really but kinda)
|
||||||
containedEntityProperties: {
|
// containedEntityProperties: {
|
||||||
[entityName: string]: entityProperties
|
// [entityName: string]: entityProperties
|
||||||
}
|
// }
|
||||||
containedEntityStatuses
|
// containedEntityStatuses
|
||||||
players: {
|
// players: {
|
||||||
[userId: number]: [inThisScene: true] | [inThisScene: false, subScene: string] | undefined
|
// [userId: number]: [inThisScene: true] | [inThisScene: false, subScene: string] | undefined
|
||||||
}
|
// }
|
||||||
//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 runScene(scene: scene, now: number): success<[scene, playerManagerRequest[]]> {
|
export function runScene(scene: scene, now: number): success<[scene, playerManagerRequest[]]> {
|
||||||
return [true, [scene, []]];
|
return [true, [scene, []]];
|
||||||
}
|
}
|
||||||
|
@ -60,19 +69,22 @@ function applyRequestToScene(scene: scene, now: number, request: sceneManagerReq
|
||||||
return [scene, sceneRequestResult[1]]
|
return [scene, sceneRequestResult[1]]
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
export function applyRequestsToScene(scene: scene, now: number, requests: sceneManagerRequest[]): success<[scene, playerManagerRequest[]]> {
|
export function applyRequestsToScene(
|
||||||
|
scene: scene,
|
||||||
|
now: number,
|
||||||
|
requests: sceneManagerRequest[],
|
||||||
|
): success<[scene, playerManagerRequest[]]> {
|
||||||
try {
|
try {
|
||||||
let newScene: scene = scene
|
let newScene: scene = scene;
|
||||||
let outgoingRequests: playerManagerRequest[] = []
|
let outgoingRequests: playerManagerRequest[] = [];
|
||||||
requests.forEach(function (request: sceneManagerRequest) {
|
requests.forEach(function (request: sceneManagerRequest) {
|
||||||
const sceneRequestResult = applyRequestToScene(newScene, now, request);
|
const sceneRequestResult = applyRequestToScene(newScene, now, request);
|
||||||
newScene = sceneRequestResult[0]
|
newScene = sceneRequestResult[0];
|
||||||
outgoingRequests = [...outgoingRequests, ...sceneRequestResult[1]]
|
outgoingRequests = [...outgoingRequests, ...sceneRequestResult[1]];
|
||||||
})
|
});
|
||||||
return [true, [newScene, outgoingRequests]];
|
return [true, [newScene, outgoingRequests]];
|
||||||
}
|
} catch (error) {
|
||||||
catch(error) {
|
return [false, error];
|
||||||
return [false, error]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function initScene(sceneTemplate: sceneTemplate): scene {
|
export function initScene(sceneTemplate: sceneTemplate): scene {
|
||||||
|
@ -82,6 +94,6 @@ export function initScene(sceneTemplate: sceneTemplate): scene {
|
||||||
players: [],
|
players: [],
|
||||||
sceneComplete: sceneTemplate.sceneComplete,
|
sceneComplete: sceneTemplate.sceneComplete,
|
||||||
onCompletion: sceneTemplate.onCompletion,
|
onCompletion: sceneTemplate.onCompletion,
|
||||||
}
|
|
||||||
return newScene;
|
|
||||||
};
|
};
|
||||||
|
return newScene;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue