Build EffectsBase from Effects.cfg

Effects, their fail conditions and source types come from
EffectTemplate. IDs are assigned at boot in file order. The power
actions that the server also keys as effects (item enchantment parents
and the action tokens sent in effect messages) are built from the
ApplyEffect/ApplyEffects/Invis actions with no Effects.cfg block: 776
keys, the 712 old registry rows plus 64 such as BRD-014A, which live
also sent.

Value changes (cfg wins): BRD-016A/PRS-031A lose the Chant source,
RUC-002A..004A lose Buff/Effect, and PRS-031A/RNG-037A no longer break
on Attack. Effect modifiers still load from the DB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-26 04:37:58 -04:00
1 parent f8d764b5f5
commit 27c59749fa
4 files changed
+189 -17

No files matched your search

+40 -15
View File
@@ -11,7 +11,6 @@ package engine.gameManager;
import engine.InterestManagement.Terrain;
import engine.InterestManagement.WorldGrid;
import engine.db.handlers.dbEffectsBaseHandler;
import engine.db.handlers.dbPowerHandler;
import engine.db.handlers.dbSkillReqHandler;
import engine.job.AbstractJob;
import engine.job.AbstractScheduleJob;
@@ -28,7 +27,9 @@ import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.objects.*;
import engine.parsers.objects.wpak.EffectTemplate;
import engine.parsers.objects.wpak.PowActionCostTemplate;
import engine.parsers.objects.wpak.PowerActionTemplate;
import engine.parsers.objects.wpak.PowerTemplate;
import engine.powers.*;
import engine.powers.poweractions.AbstractPowerAction;
@@ -41,6 +42,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
@@ -103,6 +105,42 @@ public enum PowersManager {
Logger.info("Loaded " + PowersManager._effect_costMaps.size() + " effect cost maps from PowActionCostInfo.cfg");
}
// Effects.cfg in file order, then the ApplyEffect/ApplyEffects/Invis actions with no Effects.cfg block
private static void loadEffects() {
int effectID = 0;
int actionKeyCount = 0;
PowerActionTemplate powerActionTemplate;
for (EffectTemplate effectTemplate : EffectTemplate._effects.values())
addEffect(new EffectsBase(effectTemplate, ++effectID));
for (String actionID : new TreeSet<>(PowerActionTemplate._powerActions.keySet())) {
if (EffectTemplate._effects.containsKey(actionID))
continue;
powerActionTemplate = PowerActionTemplate._powerActions.get(actionID);
switch (powerActionTemplate.action_type) {
case ApplyEffect:
case ApplyEffects:
case Invis:
addEffect(new EffectsBase(powerActionTemplate, ++effectID));
actionKeyCount++;
break;
}
}
Logger.info("Loaded " + EffectTemplate._effects.size() + " effects from Effects.cfg and "
+ actionKeyCount + " effect keys from PowerActions.cfg");
}
private static void addEffect(EffectsBase effectsBase) {
PowersManager.effectsBaseByToken.put(effectsBase.getToken(), effectsBase);
PowersManager.effectsBaseByIDString.put(effectsBase.getIDString(), effectsBase);
}
// Powers.cfg target type wins over static_power_powerbase
private static void applyClientTargetTypes() {
@@ -153,24 +191,11 @@ public enum PowersManager {
// This pre-loads all powers and effects
public static void InitializePowers() {
// Add EffectsBase
ArrayList<EffectsBase> ebList = dbEffectsBaseHandler.getAllEffectsBase();
for (EffectsBase eb : ebList) {
PowersManager.effectsBaseByToken.put(eb.getToken(), eb);
PowersManager.effectsBaseByIDString.put(eb.getIDString(), eb);
}
// Add Fail Conditions
EffectsBase.getFailConditions(PowersManager.effectsBaseByIDString);
loadEffects();
// Add Modifiers to Effects
dbEffectsBaseHandler.cacheAllEffectModifiers();
// Add Source Types to Effects
dbPowerHandler.addAllSourceTypes();
// Add PowerActions
AbstractPowerAction.getAllPowerActions(PowersManager.powerActionsByIDString, PowersManager.powerActionsByID, PowersManager.effectsBaseByIDString);
+18 -1
View File
@@ -1097,11 +1097,28 @@ public class mbEnums {
public static EffectSourceType GetEffectSourceType(String modName) {
EffectSourceType returnMod;
String name;
if (modName.isEmpty())
return EffectSourceType.None;
name = modName.replace(",", "").replace("-", "").trim();
// Effects.cfg SOURCE blocks use the short damage names
switch (name) {
case "Crush":
name = "Crushing";
break;
case "Pierce":
name = "Piercing";
break;
case "Slash":
name = "Slashing";
break;
}
try {
returnMod = EffectSourceType.valueOf(modName.replace(",", ""));
returnMod = EffectSourceType.valueOf(name);
} catch (Exception e) {
Logger.error(e);
return EffectSourceType.None;
+2 -1
View File
@@ -15,6 +15,7 @@ import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Loads Effects.cfg. ModTypes.cfg and CompoundCurves.cfg must be loaded first:
// a mod's argument layout comes from its behavior, and curve names are checked.
@@ -25,7 +26,7 @@ public class EffectParser {
public static HashMap<String, EffectTemplate> parseEffectsFile() {
HashMap<String, EffectTemplate> effects = new HashMap<>();
HashMap<String, EffectTemplate> effects = new LinkedHashMap<>();
WpakBlock root;
EffectTemplate effect;
int blockCount = 0;
+129
View File
@@ -28,8 +28,12 @@ import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject;
import engine.objects.Effect;
import engine.objects.PlayerCharacter;
import engine.parsers.objects.wpak.CurveRamp;
import engine.parsers.objects.wpak.EffectTemplate;
import engine.parsers.objects.wpak.PowerActionTemplate;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -123,6 +127,131 @@ public class EffectsBase {
// getFailConditions();
}
public EffectsBase(EffectTemplate effectTemplate, int id) {
this.UUID = id;
this.IDString = effectTemplate.effect_id;
this.name = effectTemplate.effect_name;
this.token = effectToken(this.IDString);
this.isItemEffect = effectTemplate.isitemeffect;
this.isSpireEffect = effectTemplate.isspireeffect;
this.ignoreMod = effectTemplate.ignorenomod;
this.dontSave = effectTemplate.dontsave;
this.isPrefix = this.IDString.startsWith("PRE-");
this.isSuffix = this.IDString.startsWith("SUF-");
loadFailConditions(effectTemplate.conditions);
loadSourceTypes(effectTemplate.sources);
}
// A power action with no Effects.cfg block that the server still keys as an effect:
// item enchantment parents (PRE-/SUF-/ARM-) and the action tokens sent in effect messages.
public EffectsBase(PowerActionTemplate powerActionTemplate, int id) {
this.UUID = id;
this.IDString = powerActionTemplate.action_id;
this.token = effectToken(this.IDString);
this.isPrefix = this.IDString.startsWith("PRE-");
this.isSuffix = this.IDString.startsWith("SUF-");
}
// INVIS-D and SafeMode show as the SafeModeB/A action tokens on the client
private static int effectToken(String IDString) {
switch (IDString) {
case "INVIS-D":
return Hasher.SBStringHash("SafeModeB");
case "SafeMode":
return Hasher.SBStringHash("SafeModeA");
default:
return Hasher.SBStringHash(IDString);
}
}
private void loadFailConditions(ArrayList<EffectTemplate.ConditionEntry> conditions) {
CurveRamp curveRamp;
if (conditions.isEmpty())
return;
if (!EffectsBase.EffectFailConditions.containsKey(this.IDString))
EffectsBase.EffectFailConditions.put(this.IDString, new HashSet<>());
for (EffectTemplate.ConditionEntry condition : conditions) {
EffectsBase.EffectFailConditions.get(this.IDString).add(condition.condition);
switch (condition.condition) {
case TakeDamage:
this.cancelOnTakeDamage = true;
this.amount = condition.amount;
curveRamp = (condition.curve == null) ? null : CurveRamp.fromCurve(condition.curve);
if (condition.curve != null && curveRamp == null)
Logger.warn("Effect " + this.IDString + " TakeDamage curve " + condition.curve + " has no ramp form");
this.amountRamp = (curveRamp == null) ? 0 : curveRamp.ramp;
this.useRampAdd = (curveRamp == null) || curveRamp.useAdd;
if (condition.damage_types.isEmpty())
break;
if (!EffectsBase.EffectDamageTypes.containsKey(this.token))
EffectsBase.EffectDamageTypes.put(this.token, new HashSet<>());
EffectsBase.EffectDamageTypes.get(this.token).addAll(condition.damage_types);
break;
case Attack:
this.cancelOnAttack = true;
break;
case AttackSwing:
this.cancelOnAttackSwing = true;
break;
case Cast:
this.cancelOnCast = true;
break;
case CastSpell:
this.cancelOnCastSpell = true;
break;
case EquipChange:
this.cancelOnEquipChange = true;
break;
case Logout:
this.cancelOnLogout = true;
break;
case Move:
this.cancelOnMove = true;
break;
case NewCharm:
this.cancelOnNewCharm = true;
break;
case Sit:
this.cancelOnSit = true;
break;
case TerritoryClaim:
this.cancelOnTerritoryClaim = true;
break;
case UnEquip:
this.cancelOnUnEquip = true;
break;
}
}
}
private void loadSourceTypes(ArrayList<String> sources) {
if (sources.isEmpty())
return;
if (!EffectsBase.effectSourceTypeMap.containsKey(this.token))
EffectsBase.effectSourceTypeMap.put(this.token, new HashSet<>());
for (String source : sources)
EffectsBase.effectSourceTypeMap.get(this.token).add(EffectSourceType.GetEffectSourceType(source));
}
public static void getFailConditions(HashMap<String, EffectsBase> effects) {
try (Connection connection = DbManager.getConnection();