UNPKG

@zerospacegg/iolin

Version:

Pure TypeScript implementation of ZeroSpace game data processing (PKL-free)

321 lines 11.6 kB
"use strict"; /** * 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