Build power action lists from Powers.cfg ACTION= lines

ActionsBase(ActionEntry, powerID, id, powerAction) with the duration ramp
from CurveRamp; PowersManager.loadActionLists fills PowersBase.actions in
Powers.cfg order (ids 1..2278 + 10000), then the OPENGATE actions
(5001-5008, unchanged). StackType gains the 10 cfg stack types it lacked
and loses the DB-only ResistanceDebuff spelling.

Parity (JSON-Refactor-Plan/scripts/p49.py, dev export, every column):
2287 DB rows vs 2278 cfg lines; 1453/1455 powers have the same action
list; all curves have a ramp form, every action id exists.

Value changes (cfg wins):
- TRA-003..010 lose their DB OPENGATE row; the synthetic OPENGATE action
  was already added, so each gate power applied OPENGATE twice
- HFG-001 loses the DB-only third action HFG-001B (Str +25, attack
  delay -15, melee damage +15)
- SCT-004 applies SCT-004A (Speed SL0125Up, Buff/Effect) instead of
  RNG-033A (Speed SL0100Up, also Chant)
- durations: ALF-001A 180->60, COM-001A 60->30, FGM-002A/003A
  1800->900, RNG-033A 60->30
- stack priority: DEF/OFF/PRE/NOSTANCE A and B Always->GreaterThanOrEqualTo,
  BRD-016A and PRS-031A GreaterThan->GreaterThanOrEqualTo
- stack types: the 16 resist debuffs split from ResistanceDeBuff/
  ResistanceDebuff into Cold/Fire/Lightning/Holy/Unholy/Magic/Mental
  DeBuff (FUR-029A IgnoreStack->ElementalDeBuff), so debuffs of different
  elements now stack; HNT-023A..C StackableAttr*Buff->PersonalAttr*Buff
- IgnoreStack effect keys: action line ids follow cfg order (runtime only)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-26 10:20:34 -04:00
1 parent f44f1ca138
commit 2a19a85108
3 files changed
+84 -4

No files matched your search

+30 -3
View File
@@ -253,6 +253,35 @@ public enum PowersManager {
Logger.info("Loaded " + PowersManager.powersBaseByIDString.size() + " powers from Powers.cfg"); Logger.info("Loaded " + PowersManager.powersBaseByIDString.size() + " powers from Powers.cfg");
} }
// ACTION= lines in Powers.cfg order, ids 1..n (offset in ActionsBase), then the OPENGATE actions
private static void loadActionLists() {
int actionID = 0;
PowersBase powersBase;
AbstractPowerAction powerAction;
for (PowerTemplate powerTemplate : PowerTemplate._powers.values()) {
powersBase = PowersManager.powersBaseByIDString.get(powerTemplate.power_id);
for (PowerTemplate.ActionEntry actionEntry : powerTemplate.actions) {
powerAction = PowersManager.powerActionsByIDString.get(actionEntry.action_id);
if (powerAction == null) {
Logger.error("Power " + powerTemplate.power_id + " lists unknown action " + actionEntry.action_id);
continue;
}
powersBase.getActions().add(new ActionsBase(actionEntry, powerTemplate.power_id, ++actionID, powerAction));
}
}
ActionsBase.addOpenGateActions(PowersManager.powersBaseByIDString);
Logger.info("Loaded " + actionID + " power action lines from Powers.cfg");
}
// The login server needs only the token map // The login server needs only the token map
public static void InitializeLoginPowers() { public static void InitializeLoginPowers() {
loadPowers(); loadPowers();
@@ -277,9 +306,7 @@ public enum PowersManager {
loadPowers(); loadPowers();
// Add Actions Base loadActionLists();
ActionsBase.getActionsBase(PowersManager.powersBaseByIDString,
PowersManager.powerActionsByIDString);
} }
public static EffectsBase setEffectToken(int ID, int token) { public static EffectsBase setEffectToken(int ID, int token) {
+10 -1
View File
@@ -1148,6 +1148,7 @@ public class mbEnums {
BMHealing, BMHealing,
Charm, Charm,
ClassBoon, ClassBoon,
ColdDeBuff,
Confusion, Confusion,
DamageAbsorber, DamageAbsorber,
DamageDebuff, DamageDebuff,
@@ -1162,6 +1163,7 @@ public class mbEnums {
ElementalDeBuff, ElementalDeBuff,
EnchantWeapon, EnchantWeapon,
Fear, Fear,
FireDeBuff,
Flight, Flight,
Frenzy, Frenzy,
GroupHeal, GroupHeal,
@@ -1169,12 +1171,16 @@ public class mbEnums {
HealOverTime, HealOverTime,
HealResBuff, HealResBuff,
HealthPotion, HealthPotion,
HolyDeBuff,
IgnoreStack, IgnoreStack,
Invisible, Invisible,
LightningDeBuff,
MagicDeBuff,
ManaPotion, ManaPotion,
MangonelFire, MangonelFire,
MeleeDamageDeBuff, MeleeDamageDeBuff,
MeleeDeBuff, MeleeDeBuff,
MentalDeBuff,
MoveBuff, MoveBuff,
MoveDebuff, MoveDebuff,
NoFear, NoFear,
@@ -1187,6 +1193,9 @@ public class mbEnums {
NoTrack, NoTrack,
PassiveDefense, PassiveDefense,
PersAttrSPRBuff, PersAttrSPRBuff,
PersonalAttrCONBuff,
PersonalAttrDEXBuff,
PersonalAttrSTRBuff,
PetBuff, PetBuff,
PierceResistanceDebuff, PierceResistanceDebuff,
PoisonBuchinine, PoisonBuchinine,
@@ -1209,7 +1218,6 @@ public class mbEnums {
RecoveryStaminaDeBuff, RecoveryStaminaDeBuff,
ResistanceBuff, ResistanceBuff,
ResistanceDeBuff, ResistanceDeBuff,
ResistanceDebuff,
Root, Root,
SafeMode, SafeMode,
SelfOneAttrBuff, SelfOneAttrBuff,
@@ -1233,6 +1241,7 @@ public class mbEnums {
Stun, Stun,
Track, Track,
Transform, Transform,
UnholyDeBuff,
WeaponMove; WeaponMove;
public static StackType GetStackType(String modName) { public static StackType GetStackType(String modName) {
+44
View File
@@ -16,6 +16,8 @@ import engine.mbEnums.ModType;
import engine.mbEnums.SourceType; import engine.mbEnums.SourceType;
import engine.mbEnums.StackType; import engine.mbEnums.StackType;
import engine.objects.*; import engine.objects.*;
import engine.parsers.objects.wpak.CurveRamp;
import engine.parsers.objects.wpak.PowerTemplate;
import engine.powers.poweractions.AbstractPowerAction; import engine.powers.poweractions.AbstractPowerAction;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
@@ -89,6 +91,43 @@ public class ActionsBase {
this.powerAction = apa.get(this.effectID); this.powerAction = apa.get(this.effectID);
} }
public ActionsBase(PowerTemplate.ActionEntry actionEntry, String powerID, int id, AbstractPowerAction powerAction) {
CurveRamp durationRamp = CurveRamp.fromCurve(actionEntry.duration_curve);
if (durationRamp == null) {
Logger.warn("Power " + powerID + " action " + actionEntry.action_id + " duration curve "
+ actionEntry.duration_curve + " has no ramp form");
durationRamp = CurveRamp.NONE;
}
this.UUID = id + ACTION_ID_OFFSET;
this.IDString = powerID;
this.effectID = actionEntry.action_id;
this.minTrains = actionEntry.min_trains;
this.maxTrains = actionEntry.max_trains;
this.duration = actionEntry.duration;
this.ramp = durationRamp.ramp;
this.addFormula = durationRamp.useAdd;
this.stackType = actionEntry.stack_type;
this.stackTypeType = StackType.GetStackType(this.stackType);
this.stackOrder = actionEntry.stack_order;
this.stackPriority = actionEntry.stack_priority.name();
switch (actionEntry.stack_priority) {
case GreaterThanOrEqualTo:
this.greaterThanEqual = true;
break;
case Always:
this.always = true;
break;
case GreaterThan:
this.greaterThan = true;
break;
}
this.powerAction = powerAction;
}
protected ActionsBase(int uUID, String effectID, int minTrains, int maxTrains, float duration, float ramp, protected ActionsBase(int uUID, String effectID, int minTrains, int maxTrains, float duration, float ramp,
boolean addFormula, String stackType, int stackOrder, boolean greaterThanEqual, boolean always, boolean addFormula, String stackType, int stackOrder, boolean greaterThanEqual, boolean always,
boolean greaterThan, AbstractPowerAction powerAction) { boolean greaterThan, AbstractPowerAction powerAction) {
@@ -162,6 +201,11 @@ public class ActionsBase {
Logger.error(e.toString()); Logger.error(e.toString());
} }
addOpenGateActions(powers);
}
public static void addOpenGateActions(HashMap<String, PowersBase> powers) {
int gateID = 5000; int gateID = 5000;
for (String IDString : Runegate.GetAllOpenGateIDStrings()) { for (String IDString : Runegate.GetAllOpenGateIDStrings()) {