@zerospacegg/iolin
Version:
Pure TypeScript implementation of ZeroSpace game data processing (PKL-free)
321 lines • 11.6 kB
JavaScript
;
/**
* Transformation Engine - Adapted from black-hole for iolin entity system
* Clean, idiomatic TypeScript transformation system for ZeroSpace entities
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransformationEngine = void 0;
exports.createStatTransformation = createStatTransformation;
exports.createTagTransformation = createTagTransformation;
exports.createAbilityTransformation = createAbilityTransformation;
exports.createUpgrade = createUpgrade;
exports.createSeedlingInfuseOverride = createSeedlingInfuseOverride;
/**
* Transformation Engine - applies transformations to entities
*/
class TransformationEngine {
/**
* Apply a list of transformations to an entity
* Can convert entity types through polymorphic transformations
*/
static applyTransformations(entity, transformations) {
const result = {
transformedEntity: {
...entity,
transformationStacks: { ...(entity.transformationStacks || {}) },
appliedTagTransformations: [...(entity.appliedTagTransformations || [])],
},
appliedTransformations: [],
skippedTransformations: [],
errors: [],
};
for (const transformation of transformations) {
try {
if (this.canApplyTransformation(result.transformedEntity, transformation)) {
result.transformedEntity = this.applyTransformation(result.transformedEntity, transformation);
result.appliedTransformations.push(transformation);
}
else {
result.skippedTransformations.push(transformation);
}
}
catch (error) {
result.errors?.push(`Failed to apply transformation ${transformation.name}: ${error}`);
}
}
return result;
}
/**
* Check if a transformation can be applied to an entity
*/
static canApplyTransformation(entity, transformation) {
const entityTags = entity.tags || [];
// Check required tags
if (transformation.requiredTags) {
const hasRequiredTags = transformation.requiredTags.every(tag => entityTags.includes(tag));
if (!hasRequiredTags)
return false;
}
// Check excluded tags
if (transformation.excludedTags) {
const hasExcludedTags = transformation.excludedTags.some(tag => entityTags.includes(tag));
if (hasExcludedTags)
return false;
}
// Check stacking limits
if (transformation.maxStacks) {
const currentStacks = this.getCurrentTransformationStacks(entity, transformation.type);
if (currentStacks >= transformation.maxStacks)
return false;
}
return true;
}
/**
* Apply a single transformation to an entity
* Can return different entity type for polymorphic transformations
*/
static applyTransformation(entity, transformation) {
switch (transformation.type) {
case "stat":
return this.applyStatTransformation(entity, transformation);
case "tag":
return this.applyTagTransformation(entity, transformation);
case "ability":
return this.applyAbilityTransformation(entity, transformation);
case "custom":
return transformation.apply(entity);
default:
throw new Error(`Unknown transformation type: ${transformation.type}`);
}
}
/**
* Apply stat transformation
*/
static applyStatTransformation(entity, transformation) {
const result = { ...entity };
// Update transformation stacks
result.transformationStacks = {
...result.transformationStacks,
[transformation.type]: this.getCurrentTransformationStacks(result, transformation.type) + 1,
};
// Apply each stat modification
const statMods = [
"hp",
"damage",
"speed",
"attackSpeed",
"armor",
"shields",
"vision",
"range",
"cooldown",
"energy",
];
for (const stat of statMods) {
const multiplier = transformation[`${stat}Multiplier`];
const addition = transformation[`${stat}Addition`];
const override = transformation[`${stat}Override`];
if (override !== undefined) {
result[stat] = override;
}
else {
let currentValue = result[stat] || 0;
if (multiplier !== undefined) {
currentValue *= multiplier;
}
if (addition !== undefined) {
currentValue += addition;
}
result[stat] = currentValue;
}
}
// Apply damage multiplier to attacks
// Apply damage multiplier to all attacks if applicable
if (transformation.damageMultiplier && result.attacks) {
result.attacks = { ...result.attacks };
for (const [attackName, attack] of Object.entries(result.attacks)) {
if (attack && typeof attack === "object" && "damage" in attack) {
result.attacks[attackName] = {
...attack,
damage: Math.round(attack.damage * transformation.damageMultiplier),
};
}
}
}
return result;
}
/**
* Apply tag transformation
*/
static applyTagTransformation(entity, transformation) {
const result = { ...entity };
// Update transformation stacks
result.transformationStacks = {
...result.transformationStacks,
[transformation.type]: this.getCurrentTransformationStacks(result, transformation.type) + 1,
};
if (!result.appliedTagTransformations) {
result.appliedTagTransformations = [];
}
result.appliedTagTransformations.push(transformation);
return result;
}
/**
* Apply ability transformation
*/
static applyAbilityTransformation(entity, transformation) {
const result = { ...entity };
// Update transformation stacks
result.transformationStacks = {
...result.transformationStacks,
[transformation.type]: this.getCurrentTransformationStacks(result, transformation.type) + 1,
};
// Add new abilities
if (transformation.addAbilities) {
result.abilities = {
...(result.abilities || {}),
...transformation.addAbilities,
};
}
// Modify existing abilities
if (transformation.modifyAbilities) {
result.abilities = { ...(result.abilities || {}) };
for (const [abilityName, modification] of Object.entries(transformation.modifyAbilities)) {
if (result.abilities[abilityName]) {
result.abilities[abilityName] = this.applyAbilityModification(result.abilities[abilityName], modification);
}
}
}
// Remove abilities
if (transformation.removeAbilities) {
result.abilities = { ...result.abilities };
for (const abilityName of transformation.removeAbilities) {
delete result.abilities[abilityName];
}
}
return result;
}
/**
* Apply ability modification
*/
static applyAbilityModification(ability, modification) {
const result = { ...ability };
// Apply numeric modifications
const numericMods = ["damage", "range", "cooldown", "energyCost"];
for (const stat of numericMods) {
const multiplier = modification[`${stat}Multiplier`];
const addition = modification[`${stat}Addition`];
const override = modification[`${stat}Override`];
if (override !== undefined) {
result[stat] = override;
}
else {
let currentValue = result[stat] || 0;
if (multiplier !== undefined) {
currentValue *= multiplier;
}
if (addition !== undefined) {
currentValue += addition;
}
result[stat] = currentValue;
}
}
// Apply target modifications
if (modification.addTargets) {
result.targets = [...(result.targets || []), ...modification.addTargets];
}
if (modification.removeTargets) {
result.targets = (result.targets || []).filter((target) => !modification.removeTargets.includes(target));
}
// Apply status effects
if (modification.appliesStatus) {
result.appliesStatus = [...(result.appliesStatus || []), ...modification.appliesStatus];
}
if (modification.appliesStatusTo) {
result.appliesStatusTo = modification.appliesStatusTo;
}
// Apply unlock/lock
if (modification.unlocked !== undefined) {
result.unlocked = modification.unlocked;
}
return result;
}
/**
* Get current number of stacks for a transformation type
*/
static getCurrentTransformationStacks(entity, transformationType) {
return entity.transformationStacks?.[transformationType] || 0;
}
/**
* Check if entity has specific transformation applied
*/
static hasTransformation(entity, transformationType) {
return this.getCurrentTransformationStacks(entity, transformationType) > 0;
}
/**
* Get all active transformations on an entity
*/
static getActiveTransformations(entity) {
return entity.transformationStacks || {};
}
}
exports.TransformationEngine = TransformationEngine;
/**
* Helper function to create stat transformations easily
*/
function createStatTransformation(name, modifications) {
return {
type: "stat",
name,
...modifications,
};
}
/**
* Helper function to create tag transformations easily
*/
function createTagTransformation(name, addTags, removeTags) {
return {
type: "tag",
name,
addTags,
removeTags,
};
}
/**
* Helper function to create ability transformations easily
*/
function createAbilityTransformation(name, modifications) {
return {
type: "ability",
name,
...modifications,
};
}
/**
* Helper function to create upgrades easily
*/
function createUpgrade(name, description, transformations, tier = "T1", fluxCost = 0, researchTime = 0) {
return {
name,
description,
tier: tier,
fluxCost,
researchTime,
transformations,
};
}
/**
* Create special Seedling transformation override
* Seedling undergoes complete metamorphosis when infused - becomes aerial constructor
*/
function createSeedlingInfuseOverride() {
return {
type: "stat",
name: "Seedling Aerial Transformation",
hpOverride: 120,
speedOverride: 575,
maxStacks: 1,
appliesStatus: ["infused", "aerial", "metamorphosed"],
};
}
//# sourceMappingURL=transformation.js.map