@reldens/modifiers
v0.34.0
Published
Reldens - Modifiers
Maintainers
Readme
Reldens - Modifiers
About
This package provides a modifiers system originally created for the Reldens project, but designed to be used anywhere.
The package includes:
- Modifier: Apply and revert value modifications to object properties with conditions and limits
- Condition: Define conditions that must be met before applying modifiers
- Calculator: Handle mathematical operations (increase, decrease, multiply, divide, percentages, set values)
- PropertyManager: Access and modify deep object properties using path notation
- Constants: Pre-defined operation types, comparison operators, and state constants
Installation
npm install @reldens/modifiersQuick Start
const { Modifier, ModifierConst } = require('@reldens/modifiers');
// Create a player object
let player = {
health: 100,
maxHealth: 150,
attack: 50
};
// Create a modifier to increase attack by 20
let attackBoost = new Modifier({
key: 'attack-boost',
propertyKey: 'attack',
operation: ModifierConst.OPS.INC,
value: 20
});
// Apply the modifier
attackBoost.apply(player);
console.log(player.attack); // 70
// Revert the modifier
attackBoost.revert(player);
console.log(player.attack); // 50Detailed Usage Examples
Modifier Class
The Modifier class is the core component for applying value changes to object properties.
Basic Operations
const { Modifier, ModifierConst } = require('@reldens/modifiers');
let character = {
strength: 100,
intelligence: 80,
gold: 500
};
// Increase (INC)
let strengthBonus = new Modifier({
key: 'str-bonus',
propertyKey: 'strength',
operation: ModifierConst.OPS.INC,
value: 25
});
strengthBonus.apply(character);
console.log(character.strength); // 125
// Decrease (DEC)
let goldCost = new Modifier({
key: 'shop-cost',
propertyKey: 'gold',
operation: ModifierConst.OPS.DEC,
value: 150
});
goldCost.apply(character);
console.log(character.gold); // 350
// Multiply (MUL)
let criticalHit = new Modifier({
key: 'crit-damage',
propertyKey: 'strength',
operation: ModifierConst.OPS.MUL,
value: 2
});
criticalHit.apply(character);
console.log(character.strength); // 250
// Divide (DIV)
let weakness = new Modifier({
key: 'weakness-debuff',
propertyKey: 'strength',
operation: ModifierConst.OPS.DIV,
value: 2
});
weakness.apply(character);
console.log(character.strength); // 125Percentage Operations
let stats = { damage: 200, defense: 100 };
// Increase by percentage (INC_P)
let damageIncrease = new Modifier({
key: 'damage-boost',
propertyKey: 'damage',
operation: ModifierConst.OPS.INC_P,
value: 50 // 50% increase
});
damageIncrease.apply(stats);
console.log(stats.damage); // 300 (200 + 50% of 200)
// Decrease by percentage (DEC_P)
let armorPiercing = new Modifier({
key: 'armor-pierce',
propertyKey: 'defense',
operation: ModifierConst.OPS.DEC_P,
value: 25 // 25% reduction
});
armorPiercing.apply(stats);
console.log(stats.defense); // 75 (100 - 25% of 100)Set Operations
let player = { level: 1, status: 'normal' };
// Set numeric value (SET)
let levelUp = new Modifier({
key: 'level-up',
propertyKey: 'level',
operation: ModifierConst.OPS.SET,
value: 10
});
levelUp.apply(player);
console.log(player.level); // 10
// Set string value (SET with string type)
let statusEffect = new Modifier({
key: 'poison-status',
propertyKey: 'status',
operation: ModifierConst.OPS.SET,
type: ModifierConst.TYPES.STRING,
value: 'poisoned'
});
statusEffect.apply(player);
console.log(player.status); // 'poisoned'Value Limits
let character = { health: 50, maxHealth: 100 };
// Modifier with min/max limits
let healing = new Modifier({
key: 'healing-potion',
propertyKey: 'health',
operation: ModifierConst.OPS.INC,
value: 80,
minValue: 0,
maxValue: 100
});
healing.apply(character);
console.log(character.health); // 100 (capped at maxValue)
// Using property-based limits
let manaRestore = new Modifier({
key: 'mana-potion',
propertyKey: 'mana',
operation: ModifierConst.OPS.INC,
value: 50,
maxProperty: 'maxMana' // Use maxMana property as limit
});Deep Property Access
let character = {
stats: {
combat: {
attack: 100,
defense: 80
},
magic: {
power: 60
}
}
};
// Modify nested property using path notation
let magicBoost = new Modifier({
key: 'magic-boost',
propertyKey: 'stats/magic/power',
operation: ModifierConst.OPS.INC,
value: 25
});
magicBoost.apply(character);
console.log(character.stats.magic.power); // 85Condition Class
Conditions allow you to control when modifiers should be applied.
Basic Conditions
const { Condition, ModifierConst } = require('@reldens/modifiers');
let player = { level: 15, health: 80, maxHealth: 100 };
// Create conditions
let levelCondition = new Condition({
key: 'min-level',
propertyKey: 'level',
conditional: ModifierConst.COMPARE.GE, // Greater or equal
value: 10
});
let healthCondition = new Condition({
key: 'low-health',
propertyKey: 'health',
conditional: ModifierConst.COMPARE.LT, // Less than
value: 90
});
// Test conditions
console.log(levelCondition.isValidOn(player)); // true (15 >= 10)
console.log(healthCondition.isValidOn(player)); // true (80 < 90)Available Comparison Operators
// All available comparison operators
let conditions = {
equals: ModifierConst.COMPARE.EQ, // ===
notEquals: ModifierConst.COMPARE.NE, // !==
lessThan: ModifierConst.COMPARE.LT, // <
greaterThan: ModifierConst.COMPARE.GT, // >
lessOrEqual: ModifierConst.COMPARE.LE, // <=
greaterOrEqual: ModifierConst.COMPARE.GE // >=
};Modifiers with Conditions
let player = { level: 5, experience: 1200, strength: 50 };
// Create condition
let experienceCondition = new Condition({
key: 'exp-check',
propertyKey: 'experience',
conditional: ModifierConst.COMPARE.GE,
value: 1000
});
// Create modifier with condition
let experienceBonus = new Modifier({
key: 'exp-strength-bonus',
propertyKey: 'strength',
operation: ModifierConst.OPS.INC,
value: 10,
conditions: [experienceCondition]
});
// This will apply because experience >= 1000
experienceBonus.apply(player);
console.log(player.strength); // 60
// Change experience and test again
player.experience = 500;
let newBonus = new Modifier({
key: 'another-bonus',
propertyKey: 'strength',
operation: ModifierConst.OPS.INC,
value: 20,
conditions: [experienceCondition]
});
// This won't apply because experience < 1000
newBonus.apply(player);
console.log(player.strength); // Still 60PropertyManager Class
The PropertyManager handles deep property access using path notation.
const { PropertyManager } = require('@reldens/modifiers');
let propertyManager = new PropertyManager();
let gameObject = {
player: {
inventory: {
weapons: {
sword: { damage: 50, durability: 100 }
}
}
}
};
// Get deep property value
let swordDamage = propertyManager.getPropertyValue(gameObject, 'player/inventory/weapons/sword/damage');
console.log(swordDamage); // 50
// Set deep property value
propertyManager.setOwnerProperty(gameObject, 'player/inventory/weapons/sword/damage', 65);
console.log(gameObject.player.inventory.weapons.sword.damage); // 65Calculator Class
The Calculator class handles mathematical operations and can be used independently.
const { Calculator, ModifierConst } = require('@reldens/modifiers');
let calculator = new Calculator();
// Basic operations
console.log(calculator.calculateNewValue(100, ModifierConst.OPS.INC, 25, false)); // 125
console.log(calculator.calculateNewValue(100, ModifierConst.OPS.DEC, 30, false)); // 70
console.log(calculator.calculateNewValue(50, ModifierConst.OPS.MUL, 3, false)); // 150
console.log(calculator.calculateNewValue(60, ModifierConst.OPS.DIV, 2, false)); // 30
// Percentage operations
console.log(calculator.calculateNewValue(200, ModifierConst.OPS.INC_P, 50, false)); // 300
console.log(calculator.calculateNewValue(100, ModifierConst.OPS.DEC_P, 25, false)); // 75
// Revert operations (using revert = true)
console.log(calculator.calculateNewValue(125, ModifierConst.OPS.INC, 25, true)); // 100
console.log(calculator.calculateNewValue(70, ModifierConst.OPS.DEC, 30, true)); // 100Real-World Examples
RPG Character System
const { Modifier, Condition, ModifierConst } = require('@reldens/modifiers');
// Character data
let character = {
level: 20,
class: 'warrior',
stats: {
strength: 100,
agility: 60,
intelligence: 40
},
equipment: {
weapon: null,
armor: null
}
};
// Equipment modifiers
let magicSword = new Modifier({
key: 'magic-sword',
propertyKey: 'stats/strength',
operation: ModifierConst.OPS.INC,
value: 35
});
let agilityBoots = new Modifier({
key: 'agility-boots',
propertyKey: 'stats/agility',
operation: ModifierConst.OPS.INC_P,
value: 25 // 25% increase
});
// Class-specific bonuses with conditions
let warriorCondition = new Condition({
key: 'warrior-class',
propertyKey: 'class',
conditional: ModifierConst.COMPARE.EQ,
type: ModifierConst.TYPES.STRING,
value: 'warrior'
});
let classBonus = new Modifier({
key: 'warrior-strength-bonus',
propertyKey: 'stats/strength',
operation: ModifierConst.OPS.INC_P,
value: 20,
conditions: [warriorCondition]
});
// Apply equipment
magicSword.apply(character);
agilityBoots.apply(character);
classBonus.apply(character);
console.log('Final stats:', character.stats);
// strength: 162 (100 + 35 + 20% of 135)
// agility: 75 (60 + 25% of 60)
// intelligence: 40 (unchanged)Temporary Buff System
// Buff system with time limits and conditions
let player = { health: 200, maxHealth: 300, mana: 50 };
// Health condition for mana regeneration
let lowManaCondition = new Condition({
key: 'low-mana',
propertyKey: 'mana',
conditional: ModifierConst.COMPARE.LT,
value: 100
});
// Conditional mana regeneration
let manaRegen = new Modifier({
key: 'mana-regen-buff',
propertyKey: 'mana',
operation: ModifierConst.OPS.INC,
value: 25,
maxProperty: 'maxMana',
conditions: [lowManaCondition]
});
// Apply buff (will work because mana < 100)
manaRegen.apply(player);
console.log(player.mana); // 75
// Try to apply again (still works because mana < 100)
manaRegen.apply(player);
console.log(player.mana); // 100
// Try once more (won't work because mana >= 100)
let player2 = { ...player };
manaRegen.apply(player2);
console.log(player2.mana); // Still 100 (condition not met)Constants Reference
Operations (ModifierConst.OPS)
INC(1): Increase valueDEC(2): Decrease valueDIV(3): Divide valueMUL(4): Multiply valueINC_P(5): Increase by percentageDEC_P(6): Decrease by percentageSET(7): Set absolute valueMETHOD(8): Call custom methodSET_N(9): Set value (alternative)
Comparison Operators (ModifierConst.COMPARE)
EQ: Equal to (===)NE: Not equal to (!==)LT: Less than (<)GT: Greater than (>)LE: Less than or equal (<=)GE: Greater than or equal (>=)
Data Types (ModifierConst.TYPES)
INT: Integer typeSTRING: String type
Modifier States
MOD_MISSING_KEY: Missing key parameterMOD_MISSING_PROPERTY_KEY: Missing propertyKey parameterMOD_MISSING_OPERATION: Missing operation parameterMOD_MISSING_VALUE: Missing value parameterMOD_READY: Modifier ready to applyMOD_APPLIED: Modifier successfully appliedMOD_REVERTED: Modifier successfully revertedMOD_UNDEFINED_TARGET: No target object specifiedMOD_INVALID_CONDITIONS: Conditions not metMOD_MISSING_CONDITION_INSTANCE: Invalid condition instanceMOD_MODIFIER_ERROR: General modifier error
Advanced Features
Base Property Operations
Use different properties for calculation and application:
let character = {
currentHealth: 50,
baseHealth: 100,
maxHealth: 120
};
// Calculate from baseHealth but apply to currentHealth
let healing = new Modifier({
key: 'healing-spell',
propertyKey: 'currentHealth',
basePropertyKey: 'baseHealth',
operation: ModifierConst.OPS.INC_P,
value: 30 // 30% of baseHealth
});
// Use baseHealth for calculation, apply to currentHealth
healing.apply(character, true, false);
console.log(character.currentHealth); // 80 (50 + 30% of 100)Custom Method Operations
class CustomModifier extends Modifier
{
customCalculation(modifier, currentValue)
{
// Custom logic here
return Math.floor(currentValue * 1.5) + 10;
}
}
let customMod = new CustomModifier({
key: 'custom-boost',
propertyKey: 'attack',
operation: ModifierConst.OPS.METHOD,
value: 'customCalculation'
});Error Handling
The package includes comprehensive error handling and state management:
let invalidModifier = new Modifier({
// Missing required parameters
key: 'invalid'
});
console.log(invalidModifier.state); // Will show error state codeNeed something specific?
Request a feature here: https://www.reldens.com/features-request
Documentation
https://www.reldens.com/documentation/modifiers

