13 changed files with 1281 additions and 0 deletions
@ -0,0 +1,286 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak; |
||||||
|
|
||||||
|
import engine.gameManager.ConfigManager; |
||||||
|
import engine.mbEnums; |
||||||
|
import engine.wpak.data.ConditionEntry; |
||||||
|
import engine.wpak.data.Effect; |
||||||
|
import engine.wpak.data.ModifierEntry; |
||||||
|
import engine.wpakpowers.WpakPowerManager; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.nio.file.Files; |
||||||
|
import java.nio.file.Paths; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
public class EffectsParser { |
||||||
|
|
||||||
|
public static String effectsPath = ConfigManager.DEFAULT_DATA_DIR + "wpak/Effects.cfg"; |
||||||
|
private static final Pattern EFFECT_REGEX = Pattern.compile("(?<=EFFECTBEGIN)(.+?)(?=EFFECTEND)", Pattern.DOTALL); |
||||||
|
private static final Pattern SOURCE_REGEX = Pattern.compile("(?<=SOURCEBEGIN)(.+?)(?=SOURCEEND)", Pattern.DOTALL); |
||||||
|
private static final Pattern MODS_REGEX = Pattern.compile("(?<=MODSBEGIN)(.+?)(?=MODSEND)", Pattern.DOTALL); |
||||||
|
private static final Pattern CONDITIONS_REGEX = Pattern.compile("(?<=CONDITIONBEGIN)(.+?)(?=CONDITIONEND)", Pattern.DOTALL); |
||||||
|
private static final Pattern STRSPLIT_REGEX = Pattern.compile("([^\"]\\S*|\"[^\"]*\")\\s*"); // Regex ignores spaces within quotes
|
||||||
|
|
||||||
|
public static void parseWpakFile() { |
||||||
|
|
||||||
|
// Read .wpak file from disk
|
||||||
|
|
||||||
|
byte[] fileData; |
||||||
|
|
||||||
|
try { |
||||||
|
fileData = Files.readAllBytes(Paths.get(effectsPath)); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
String fileContents = new String(fileData); |
||||||
|
|
||||||
|
// Iterate over effect entries from .wpak data
|
||||||
|
|
||||||
|
Matcher matcher = EFFECT_REGEX.matcher(fileContents); |
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
try { |
||||||
|
Effect effect = parseEffectEntry(matcher.group()); |
||||||
|
WpakPowerManager._effectsLookup.put(effect.effect_id, effect); |
||||||
|
} catch (Exception e) { |
||||||
|
Logger.error("EFFECT PARSE FAILED: " + e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static Effect parseEffectEntry(String effectData) { |
||||||
|
|
||||||
|
Effect effect = new Effect(); |
||||||
|
|
||||||
|
// Parse fields that lie outside the other tags
|
||||||
|
|
||||||
|
effect.isItemEffect = effectData.contains("IsItemEffect"); |
||||||
|
effect.isSpireEffect = effectData.contains("IsSpireEffect"); |
||||||
|
effect.ignoreNoMod = effectData.contains("IgnoreNoMod"); |
||||||
|
effect.dontSave = effectData.contains("DontSave"); |
||||||
|
|
||||||
|
// Remove all lines that contain a # and leading/trailing blank lines
|
||||||
|
|
||||||
|
effectData = effectData.replaceAll("(?m)^(\\s*#.*|\\s*)\r?\n?", ""); |
||||||
|
effectData = effectData.trim(); |
||||||
|
|
||||||
|
// Parse effect entry header
|
||||||
|
|
||||||
|
String firstLine; |
||||||
|
ArrayList<String> effectHeader = new ArrayList<>(); |
||||||
|
|
||||||
|
// Some effects exist without sources/mods or conditions
|
||||||
|
// (ACID "MOB" 0)
|
||||||
|
|
||||||
|
if (effectData.indexOf('\n') > 0) |
||||||
|
firstLine = effectData.substring(0, effectData.indexOf('\n')); |
||||||
|
else |
||||||
|
firstLine = effectData; |
||||||
|
|
||||||
|
Matcher matcher = STRSPLIT_REGEX.matcher(firstLine); |
||||||
|
|
||||||
|
while (matcher.find()) |
||||||
|
effectHeader.add(matcher.group().trim()); |
||||||
|
|
||||||
|
effect.effect_id = effectHeader.get(0); |
||||||
|
effect.effect_name = effectHeader.get(1); |
||||||
|
effect.effect_name = effect.effect_name.replaceAll("\"", ""); |
||||||
|
|
||||||
|
// Some effect mods have no icon
|
||||||
|
// (SEEINVIS-SHADE "See Invis")
|
||||||
|
|
||||||
|
if (effectHeader.size() == 3) |
||||||
|
effect.icon = Integer.parseInt(effectHeader.get(2)); |
||||||
|
else |
||||||
|
effect.icon = 0; |
||||||
|
|
||||||
|
// Parse source entries
|
||||||
|
|
||||||
|
matcher = SOURCE_REGEX.matcher(effectData); |
||||||
|
|
||||||
|
while (matcher.find()) |
||||||
|
effect.sources.add(matcher.group().trim()); |
||||||
|
|
||||||
|
// Parse modifier entries
|
||||||
|
|
||||||
|
matcher = MODS_REGEX.matcher(effectData); |
||||||
|
|
||||||
|
// Iterate effect entries from .wpak config data
|
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
ModifierEntry modifierEntry = parseModEntry(matcher.group()); |
||||||
|
effect.mods.add(modifierEntry); |
||||||
|
} |
||||||
|
|
||||||
|
// Parse Conditions
|
||||||
|
|
||||||
|
matcher = CONDITIONS_REGEX.matcher(effectData); |
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
String[] conditions = matcher.group().trim().split("\n"); |
||||||
|
|
||||||
|
for (String condition : conditions) { |
||||||
|
List<String> parameters = Arrays.asList(condition.trim().split("\\s+")); |
||||||
|
Iterator<String> iterator = parameters.iterator(); |
||||||
|
|
||||||
|
ConditionEntry conditionEntry = new ConditionEntry(); |
||||||
|
conditionEntry.condition = iterator.next(); |
||||||
|
conditionEntry.arg = Integer.parseInt(iterator.next()); |
||||||
|
|
||||||
|
if (iterator.hasNext()) |
||||||
|
conditionEntry.curveType = mbEnums.CompoundCurveType.valueOf(iterator.next()); |
||||||
|
|
||||||
|
while (iterator.hasNext()) |
||||||
|
conditionEntry.damageTypes.add(mbEnums.DamageType.valueOf(iterator.next().toUpperCase())); |
||||||
|
|
||||||
|
effect.conditions.add(conditionEntry); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return effect; |
||||||
|
} |
||||||
|
|
||||||
|
private static ModifierEntry parseModEntry(String modData) { |
||||||
|
|
||||||
|
ModifierEntry modifierEntry = new ModifierEntry(); |
||||||
|
|
||||||
|
String[] modEntries = modData.trim().split("\n"); |
||||||
|
|
||||||
|
for (String modEntry : modEntries) { |
||||||
|
|
||||||
|
ArrayList<String> modValues = new ArrayList<>(); |
||||||
|
Matcher matcher = STRSPLIT_REGEX.matcher(modEntry.trim()); |
||||||
|
|
||||||
|
while (matcher.find()) |
||||||
|
modValues.add(matcher.group().trim()); |
||||||
|
|
||||||
|
modifierEntry.type = mbEnums.ModType.valueOf(modValues.get(0).trim()); |
||||||
|
|
||||||
|
switch (modifierEntry.type) { |
||||||
|
case AnimOverride: |
||||||
|
modifierEntry.min = Float.parseFloat(modValues.get(1).trim()); |
||||||
|
modifierEntry.max = Float.parseFloat(modValues.get(2).trim()); |
||||||
|
break; |
||||||
|
case Health: |
||||||
|
case Mana: |
||||||
|
case Stamina: |
||||||
|
modifierEntry.min = Float.parseFloat(modValues.get(1).trim()); |
||||||
|
modifierEntry.max = Float.parseFloat(modValues.get(2).trim()); |
||||||
|
modifierEntry.percentage = Float.parseFloat(modValues.get(3).trim()); |
||||||
|
modifierEntry.value = Float.parseFloat(modValues.get(4).trim()); // Always zero
|
||||||
|
modifierEntry.compoundCurveType = mbEnums.CompoundCurveType.valueOf(modValues.get(5).trim()); |
||||||
|
modifierEntry.arg1 = modValues.get(6).trim(); |
||||||
|
break; |
||||||
|
case Attr: |
||||||
|
case Resistance: |
||||||
|
case Skill: |
||||||
|
case HealthRecoverRate: |
||||||
|
case ManaRecoverRate: |
||||||
|
case StaminaRecoverRate: |
||||||
|
case DamageShield: |
||||||
|
case HealthFull: |
||||||
|
case ManaFull: |
||||||
|
case StaminaFull: |
||||||
|
case Slay: |
||||||
|
case Fade: |
||||||
|
case Durability: |
||||||
|
modifierEntry.min = Float.parseFloat(modValues.get(1).trim()); |
||||||
|
modifierEntry.max = Float.parseFloat(modValues.get(2).trim()); |
||||||
|
modifierEntry.compoundCurveType = mbEnums.CompoundCurveType.valueOf(modValues.get(3).trim()); |
||||||
|
|
||||||
|
if (modValues.size() > 4) |
||||||
|
modifierEntry.arg1 = modValues.get(4).trim(); // Some HeathFull entries do not have an argument
|
||||||
|
break; |
||||||
|
case MeleeDamageModifier: |
||||||
|
case OCV: |
||||||
|
case DCV: |
||||||
|
case AttackDelay: |
||||||
|
case AdjustAboveDmgCap: |
||||||
|
case DamageCap: |
||||||
|
case ArmorPiercing: |
||||||
|
case Speed: |
||||||
|
case PowerDamageModifier: |
||||||
|
case DR: |
||||||
|
case PassiveDefense: |
||||||
|
case MaxDamage: |
||||||
|
case Value: |
||||||
|
case WeaponSpeed: |
||||||
|
case MinDamage: |
||||||
|
case PowerCost: |
||||||
|
case Block: |
||||||
|
case Parry: |
||||||
|
case Dodge: |
||||||
|
case WeaponRange: |
||||||
|
case ScanRange: |
||||||
|
case ScaleHeight: |
||||||
|
case ScaleWidth: |
||||||
|
modifierEntry.min = Float.parseFloat(modValues.get(1).trim()); |
||||||
|
modifierEntry.max = Float.parseFloat(modValues.get(2).trim()); |
||||||
|
modifierEntry.compoundCurveType = mbEnums.CompoundCurveType.valueOf(modValues.get(3).trim()); |
||||||
|
break; |
||||||
|
case ItemName: |
||||||
|
case BlockedPowerType: |
||||||
|
case ImmuneTo: |
||||||
|
case BlackMantle: |
||||||
|
modifierEntry.arg1 = modValues.get(1).trim(); |
||||||
|
|
||||||
|
// Some BlockedPowerType entries have only one argument
|
||||||
|
|
||||||
|
if (modValues.size() > 2) |
||||||
|
modifierEntry.arg2 = modValues.get(2).trim(); |
||||||
|
break; |
||||||
|
case NoMod: |
||||||
|
case ConstrainedAmbidexterity: |
||||||
|
case ProtectionFrom: |
||||||
|
case ExclusiveDamageCap: |
||||||
|
case IgnoreDamageCap: |
||||||
|
modifierEntry.arg1 = modValues.get(1).trim(); |
||||||
|
break; |
||||||
|
case WeaponProc: |
||||||
|
modifierEntry.min = Float.parseFloat(modValues.get(1).trim()); |
||||||
|
modifierEntry.arg1 = modValues.get(2).trim(); |
||||||
|
modifierEntry.max = Float.parseFloat(modValues.get(3).trim()); |
||||||
|
break; |
||||||
|
case BladeTrails: // These tags have no parms or are not parsed
|
||||||
|
case ImmuneToAttack: |
||||||
|
case ImmuneToPowers: |
||||||
|
case Ambidexterity: |
||||||
|
case Silenced: |
||||||
|
case IgnorePassiveDefense: |
||||||
|
case Stunned: |
||||||
|
case PowerCostHealth: |
||||||
|
case Charmed: |
||||||
|
case Fly: |
||||||
|
case CannotMove: |
||||||
|
case CannotTrack: |
||||||
|
case CannotAttack: |
||||||
|
case CannotCast: |
||||||
|
case SpireBlock: |
||||||
|
case Invisible: |
||||||
|
case SeeInvisible: |
||||||
|
break; |
||||||
|
default: |
||||||
|
Logger.error("Unhandled type: " + modifierEntry.type); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return modifierEntry; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,310 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak; |
||||||
|
|
||||||
|
import engine.gameManager.ConfigManager; |
||||||
|
import engine.mbEnums; |
||||||
|
import engine.util.Hasher; |
||||||
|
import engine.wpak.data.Effect; |
||||||
|
import engine.wpak.data.PowerAction; |
||||||
|
import engine.wpak.data.StatTransfer; |
||||||
|
import engine.wpak.data.TrackEntry; |
||||||
|
import engine.wpakpowers.WpakPowerManager; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.nio.file.Files; |
||||||
|
import java.nio.file.Paths; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
public class PowerActionParser { |
||||||
|
private static final Pattern STRSPLIT_REGEX = Pattern.compile("([^\"]\\S*|\"[^\"]*\")\\s*"); |
||||||
|
private static final Pattern POWER_ACTION_REGEX = Pattern.compile("(?<=POWERACTIONBEGIN)(.+?)(?=POWERACTIONEND)", Pattern.DOTALL); |
||||||
|
private static final String powerActionPath = ConfigManager.DEFAULT_DATA_DIR + "wpak/PowerActions.cfg"; |
||||||
|
|
||||||
|
public static void parseWpakFile() { |
||||||
|
|
||||||
|
// Read .wpak file from disk
|
||||||
|
|
||||||
|
byte[] fileData; |
||||||
|
|
||||||
|
try { |
||||||
|
fileData = Files.readAllBytes(Paths.get(powerActionPath)); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
String fileContents = new String(fileData); |
||||||
|
|
||||||
|
// Iterate over power entries from .wpak data
|
||||||
|
|
||||||
|
Matcher matcher = POWER_ACTION_REGEX.matcher(fileContents); |
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
|
||||||
|
PowerAction powerAction = parsePowerActionEntry(matcher.group().trim()); |
||||||
|
WpakPowerManager._powerActionLookup.put(Hasher.SBStringHash(powerAction.action_id), powerAction); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static PowerAction parsePowerActionEntry(String powerActionData) { |
||||||
|
|
||||||
|
PowerAction powerAction = new PowerAction(); |
||||||
|
Effect effect; |
||||||
|
StatTransfer statTransfer; |
||||||
|
TrackEntry trackEntry; |
||||||
|
|
||||||
|
// Remove all lines that contain a # and leading/trailing blank lines
|
||||||
|
|
||||||
|
powerActionData = powerActionData.replaceAll("(?m)^(\\s*#.*|\\s*)\r?\n?", "").trim(); |
||||||
|
|
||||||
|
List<String> lineData = Arrays.asList(powerActionData.split("\n")); |
||||||
|
|
||||||
|
// Parse effect entry header
|
||||||
|
|
||||||
|
Iterator<String> entryIterator = lineData.iterator(); |
||||||
|
String headerLine = entryIterator.next(); |
||||||
|
List<String> headerData = new ArrayList<>(); |
||||||
|
|
||||||
|
Matcher matcher = STRSPLIT_REGEX.matcher(headerLine.trim()); |
||||||
|
|
||||||
|
while (matcher.find()) |
||||||
|
headerData.add(matcher.group().trim()); |
||||||
|
|
||||||
|
Iterator<String> headerIterator = headerData.iterator(); |
||||||
|
powerAction.action_id = headerIterator.next(); |
||||||
|
powerAction.action_type = mbEnums.PowerActionType.valueOf(headerIterator.next()); |
||||||
|
|
||||||
|
switch (powerAction.action_type) { |
||||||
|
case RemoveEffect: |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
break; |
||||||
|
case CreateMob: |
||||||
|
powerAction.petRace = Integer.parseInt(headerIterator.next()); |
||||||
|
powerAction.petLevel = Integer.parseInt(headerIterator.next()); |
||||||
|
break; |
||||||
|
case DamageOverTime: |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
effect.cycleDuration = Integer.parseInt(headerIterator.next()); |
||||||
|
effect.cycleDelay = Integer.parseInt(headerIterator.next()); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
break; |
||||||
|
case ApplyEffects: |
||||||
|
int level = Integer.parseInt(headerIterator.next()); |
||||||
|
|
||||||
|
while (headerIterator.hasNext()) { |
||||||
|
effect = new Effect(); |
||||||
|
effect.level = level; |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
} |
||||||
|
break; |
||||||
|
case Transform: |
||||||
|
case Invis: |
||||||
|
case ApplyEffect: |
||||||
|
case DeferredPower: |
||||||
|
case DirectDamage: |
||||||
|
case SpireDisable: |
||||||
|
while (headerIterator.hasNext()) { |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
|
||||||
|
// Some applyEffect entries are naked withot a level
|
||||||
|
|
||||||
|
if (headerData.size() > 3) |
||||||
|
effect.level = Integer.parseInt(headerIterator.next()); |
||||||
|
|
||||||
|
powerAction.effects.add(effect); |
||||||
|
} |
||||||
|
break; |
||||||
|
case TransferStat: |
||||||
|
statTransfer = new StatTransfer(); |
||||||
|
statTransfer.fromStat = mbEnums.CostType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.toStat = mbEnums.CostType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.ramp = Float.parseFloat(headerIterator.next()); |
||||||
|
statTransfer.rampCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.efficiency = Float.parseFloat(headerIterator.next()); |
||||||
|
statTransfer.efficiencyCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.fromStatBool = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
statTransfer.isDrain = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
powerAction.statTransfer = statTransfer; |
||||||
|
break; |
||||||
|
case TransferStatOT: |
||||||
|
statTransfer = new StatTransfer(); |
||||||
|
statTransfer.fromStat = mbEnums.CostType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.toStat = mbEnums.CostType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.ramp = Float.parseFloat(headerIterator.next()); |
||||||
|
statTransfer.rampCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.efficiency = Float.parseFloat(headerIterator.next()); |
||||||
|
statTransfer.efficiencyCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next()); |
||||||
|
statTransfer.fromStatBool = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
statTransfer.isDrain = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
statTransfer.transfer_action = headerIterator.next(); |
||||||
|
statTransfer.transfer_ticks = Integer.parseInt(headerIterator.next()); |
||||||
|
powerAction.statTransfer = statTransfer; |
||||||
|
break; |
||||||
|
case Charm: |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
effect.level = Integer.parseInt(headerIterator.next()); |
||||||
|
effect.type = headerIterator.next(); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
break; |
||||||
|
case Block: |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = headerIterator.next(); |
||||||
|
effect.level = Integer.parseInt(headerIterator.next()); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
break; |
||||||
|
case Resurrect: |
||||||
|
powerAction.levelCap = Integer.parseInt(headerIterator.next()); |
||||||
|
break; |
||||||
|
case SetItemFlag: |
||||||
|
powerAction.itemFlag = mbEnums.ItemFlags.valueOf(headerIterator.next()); |
||||||
|
break; |
||||||
|
case Track: |
||||||
|
trackEntry = new TrackEntry(); |
||||||
|
trackEntry.action_id = headerIterator.next(); |
||||||
|
trackEntry.trackPlayer = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
trackEntry.trackCorpse = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
trackEntry.filter = mbEnums.MonsterType.valueOf(headerIterator.next()); |
||||||
|
trackEntry.min = Integer.parseInt(headerIterator.next()); |
||||||
|
trackEntry.max = Integer.parseInt(headerIterator.next()); |
||||||
|
powerAction.trackEntry = trackEntry; |
||||||
|
break; |
||||||
|
case Teleport: |
||||||
|
if (headerIterator.hasNext()) |
||||||
|
powerAction.ignoreNoTeleSpire = Boolean.parseBoolean(headerIterator.next()); |
||||||
|
break; |
||||||
|
case Recall: // No arguments for these tags or not parsed
|
||||||
|
case Summon: |
||||||
|
case TreeChoke: |
||||||
|
case SimpleDamage: |
||||||
|
case MobRecall: // One argument always zero
|
||||||
|
case ClearAggro: |
||||||
|
case ClearNearbyAggro: |
||||||
|
case Peek: |
||||||
|
case ClaimMine: |
||||||
|
case RunegateTeleport: |
||||||
|
case Steal: |
||||||
|
break; |
||||||
|
default: |
||||||
|
Logger.error("Unhandled type " + powerAction.action_type + " for Pow4erAction: " + powerAction.action_id); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
// Process key value pairs after header
|
||||||
|
|
||||||
|
while (entryIterator.hasNext()) { |
||||||
|
String lineValue = entryIterator.next(); |
||||||
|
List<String> lineValues = Arrays.asList(lineValue.split("=")); |
||||||
|
String key = lineValues.get(0).trim(); |
||||||
|
List<String> arguments; |
||||||
|
|
||||||
|
switch (key) { |
||||||
|
case "BODYPARTS": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String bodyPart : arguments) |
||||||
|
powerAction.bodyParts.add(Integer.parseInt(bodyPart)); |
||||||
|
break; |
||||||
|
case "FEMALEBODYPARTS": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String bodyPart : arguments) |
||||||
|
powerAction.femaleBodyParts.add(Integer.parseInt(bodyPart)); |
||||||
|
break; |
||||||
|
case "SCALEFACTOR": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String scaleFactor : arguments) |
||||||
|
powerAction.scaleFactor.add(Float.parseFloat(scaleFactor)); |
||||||
|
break; |
||||||
|
case "ISRESISTABLE": |
||||||
|
powerAction.isResistible = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "ISAGGRESSIVE": |
||||||
|
powerAction.isAggressive = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "BLADETRAILS": |
||||||
|
powerAction.bladeTrails = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "SHOULDSHOWWEAPONS": |
||||||
|
powerAction.shouldShowWeapons = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "SHOULDSHOWARMOR": |
||||||
|
powerAction.shouldShowArmor = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "APPLYEFFECTBLANK": |
||||||
|
powerAction.applyEffectBlank = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "WEAROFFEFFECTBLANK": |
||||||
|
powerAction.wearOffEffectBlank = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "ATTACKANIMS": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String animation : arguments) |
||||||
|
powerAction.attackAnimations.add(Integer.parseInt(animation)); |
||||||
|
break; |
||||||
|
case "REMOVEALL": |
||||||
|
powerAction.removeAll = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "EFFECTID": |
||||||
|
effect = new Effect(); |
||||||
|
effect.effect_id = lineValues.get(1).trim(); |
||||||
|
powerAction.effects.add(effect); |
||||||
|
break; |
||||||
|
case "LEVELCAP": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
powerAction.levelCap = Integer.parseInt(arguments.get(0)); |
||||||
|
|
||||||
|
if (arguments.size() > 1) // Not all level caps have a curve
|
||||||
|
powerAction.levelCapCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1)); |
||||||
|
break; |
||||||
|
case "CLEARAGGRO": |
||||||
|
powerAction.clearAggro = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "TARGETBECOMESPET": |
||||||
|
powerAction.targetBecomesPet = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "DESTROYOLDPET": |
||||||
|
powerAction.destroyOldPet = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "DAMAGETYPE": |
||||||
|
powerAction.damageType = mbEnums.DamageType.valueOf(lineValues.get(1).trim().toUpperCase()); |
||||||
|
break; |
||||||
|
case "ROOTFSMID": |
||||||
|
powerAction.rootFsmID = mbEnums.MobBehaviourType.valueOf(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "SPLASHDAMAGE": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
powerAction.splashDamageMin = Integer.parseInt(arguments.get(0)); |
||||||
|
powerAction.splashDamageMax = Integer.parseInt(arguments.get(1)); |
||||||
|
break; |
||||||
|
case "APPLYEFFECTOTHER": |
||||||
|
case "APPLYEFFECTSELF": |
||||||
|
case "WEAROFFEFFECTOTHER": // Keys not parsed go here.
|
||||||
|
case "WEAROFFEFFECTSELF": |
||||||
|
break; |
||||||
|
default: |
||||||
|
Logger.error("Unhandled variable type:" + key + " for powerAction: " + powerAction.action_id); |
||||||
|
} |
||||||
|
} |
||||||
|
return powerAction; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,321 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak; |
||||||
|
|
||||||
|
import engine.gameManager.ConfigManager; |
||||||
|
import engine.mbEnums; |
||||||
|
import engine.util.Hasher; |
||||||
|
import engine.wpak.data.*; |
||||||
|
import engine.wpakpowers.WpakPowerManager; |
||||||
|
import org.pmw.tinylog.Logger; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.nio.file.Files; |
||||||
|
import java.nio.file.Paths; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
public class PowersParser { |
||||||
|
|
||||||
|
private static final Pattern POWER_REGEX = Pattern.compile("(?<=POWERBEGIN)(.+?)(?=POWEREND)", Pattern.DOTALL); |
||||||
|
private static final Pattern STRSPLIT_REGEX = Pattern.compile("([^\"]\\S*|\"[^\"]*\")\\s*"); |
||||||
|
private static final Pattern CONDITION_REGEX = Pattern.compile("(?<=CONDITIONBEGIN)(.+?)(?=CONDITIONEND)", Pattern.DOTALL); |
||||||
|
private static final String powersPath = ConfigManager.DEFAULT_DATA_DIR + "wpak/Powers.cfg"; |
||||||
|
|
||||||
|
public static void parseWpakFile() { |
||||||
|
|
||||||
|
// Read .wpak file from disk
|
||||||
|
|
||||||
|
byte[] fileData; |
||||||
|
|
||||||
|
try { |
||||||
|
fileData = Files.readAllBytes(Paths.get(powersPath)); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
String fileContents = new String(fileData); |
||||||
|
|
||||||
|
// Iterate over power entries from .wpak data
|
||||||
|
|
||||||
|
Matcher matcher = POWER_REGEX.matcher(fileContents); |
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
|
||||||
|
Power power = parsePowerEntry(matcher.group().trim()); |
||||||
|
WpakPowerManager._powersLookup.put(Hasher.SBStringHash(power.power_id), power); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static Power parsePowerEntry(String powerData) { |
||||||
|
|
||||||
|
Power powerEntry = new Power(); |
||||||
|
StringBuilder conditionBuilder = new StringBuilder(); |
||||||
|
StringBuilder powerBuilder = new StringBuilder(); |
||||||
|
String conditionString; |
||||||
|
String powerString; |
||||||
|
java.util.Iterator<String> iterator; |
||||||
|
java.util.Iterator<String> argumentIterator; |
||||||
|
int endPos = 0; |
||||||
|
|
||||||
|
// Separate out any conditions from the power data
|
||||||
|
|
||||||
|
Matcher matcher = CONDITION_REGEX.matcher(powerData); |
||||||
|
|
||||||
|
while (matcher.find()) { |
||||||
|
conditionBuilder.append(matcher.group().trim()); |
||||||
|
powerBuilder.append(powerData, endPos, matcher.start()); |
||||||
|
endPos = matcher.end(); |
||||||
|
} |
||||||
|
|
||||||
|
powerBuilder.append(powerData.substring(endPos)); |
||||||
|
|
||||||
|
// Cleanup dangling tags and lines that contain a # and leading/trailing blank lines
|
||||||
|
|
||||||
|
powerString = powerBuilder.toString().replaceAll("CONDITIONBEGINCONDITIONEND", "") |
||||||
|
.replaceAll("(?m)^(\\s*#.*|\\s*)\r?\n?", ""); |
||||||
|
conditionString = conditionBuilder.toString().replaceAll("(?m)^(\\s*#.*|\\s*)\r?\n?", ""); |
||||||
|
|
||||||
|
// Parse header line in power data
|
||||||
|
|
||||||
|
List<String> lineData = Arrays.asList(powerString.trim().split("\n")); |
||||||
|
List<String> powerHeader = new ArrayList<>(); |
||||||
|
|
||||||
|
String headerString = lineData.get(0); |
||||||
|
headerString = headerString.replace("\n", " "); |
||||||
|
|
||||||
|
matcher = STRSPLIT_REGEX.matcher(headerString); |
||||||
|
|
||||||
|
while (matcher.find()) |
||||||
|
powerHeader.add(matcher.group().trim()); |
||||||
|
|
||||||
|
iterator = powerHeader.iterator(); |
||||||
|
|
||||||
|
powerEntry.power_id = iterator.next(); |
||||||
|
powerEntry.power = iterator.next().replaceAll("\"", ""); |
||||||
|
|
||||||
|
PowerEntry power = new PowerEntry(); |
||||||
|
power.power_type = mbEnums.PowerType.valueOf(iterator.next()); |
||||||
|
power.icon = Integer.parseInt(iterator.next()); |
||||||
|
power.focusLine = iterator.next().replaceAll("\"", ""); |
||||||
|
powerEntry.powers.add(power); |
||||||
|
|
||||||
|
String nextValue = iterator.next(); |
||||||
|
|
||||||
|
// Account for second definition
|
||||||
|
|
||||||
|
if (nextValue.equals("SPELL") || nextValue.equals("SKILL")) { |
||||||
|
power = new PowerEntry(); |
||||||
|
power.power_type = mbEnums.PowerType.valueOf(nextValue); |
||||||
|
power.icon = Integer.parseInt(iterator.next()); |
||||||
|
power.focusLine = iterator.next().replaceAll("\"", ""); |
||||||
|
powerEntry.powers.add(power); |
||||||
|
powerEntry.target_type = mbEnums.PowerTargetType.valueOf(iterator.next()); |
||||||
|
} else |
||||||
|
powerEntry.target_type = mbEnums.PowerTargetType.valueOf(nextValue); |
||||||
|
|
||||||
|
powerEntry.range = Integer.parseInt(iterator.next()); |
||||||
|
powerEntry.areaType = mbEnums.AreaType.valueOf(iterator.next()); |
||||||
|
powerEntry.areaRange = Integer.parseInt(iterator.next()); |
||||||
|
powerEntry.excludeType = mbEnums.ExcludeType.valueOf(iterator.next()); |
||||||
|
powerEntry.costType = mbEnums.CostType.valueOf(iterator.next()); |
||||||
|
powerEntry.cost = Float.parseFloat(iterator.next()); |
||||||
|
powerEntry.difficulty = Float.parseFloat(iterator.next()); |
||||||
|
powerEntry.precision = Float.parseFloat(iterator.next()); |
||||||
|
// Cleanup init_time in client data which is 0.35.1 or some such
|
||||||
|
powerEntry.init_time = Float.parseFloat(iterator.next().replaceAll("(\\.0)+$", "")); |
||||||
|
powerEntry.release_time = Float.parseFloat(iterator.next()); |
||||||
|
powerEntry.recycle_time = Float.parseFloat(iterator.next()); |
||||||
|
powerEntry.hitRollYN = Integer.parseInt(iterator.next()); |
||||||
|
powerEntry.castingMode = mbEnums.CastingModeType.valueOf(iterator.next()); |
||||||
|
powerEntry.initAmin = Integer.parseInt(iterator.next()); |
||||||
|
powerEntry.releaseAnim = Integer.parseInt(iterator.next()); |
||||||
|
powerEntry.targetSelect = mbEnums.TargetSelectType.valueOf(iterator.next()); |
||||||
|
|
||||||
|
// Process key value pairs after header
|
||||||
|
|
||||||
|
iterator = lineData.iterator(); |
||||||
|
iterator.next(); // Ignore header
|
||||||
|
|
||||||
|
while (iterator.hasNext()) { |
||||||
|
|
||||||
|
String lineValue = iterator.next(); |
||||||
|
List<String> lineValues = Arrays.asList(lineValue.split("=")); |
||||||
|
String key = lineValues.get(0).trim(); |
||||||
|
ActionEntry actionEntry; |
||||||
|
List<String> arguments; |
||||||
|
Matcher argumentMatcher; |
||||||
|
|
||||||
|
switch (key) { |
||||||
|
case "ACTION": |
||||||
|
actionEntry = new ActionEntry(); |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
actionEntry.action_id = arguments.get(0); |
||||||
|
actionEntry.minTrains = Integer.parseInt(arguments.get(1)); |
||||||
|
actionEntry.maxTrains = Integer.parseInt(arguments.get(2)); |
||||||
|
actionEntry.duration = Float.parseFloat(arguments.get(3)); |
||||||
|
actionEntry.curve = mbEnums.CompoundCurveType.valueOf(arguments.get(4)); |
||||||
|
actionEntry.stackingCategory = arguments.get(5); |
||||||
|
actionEntry.stackingPriority = Integer.parseInt(arguments.get(6)); |
||||||
|
actionEntry.categoryToPower = mbEnums.CategoryToPowerType.valueOf(arguments.get(7)); |
||||||
|
powerEntry.actionEntries.add(actionEntry); |
||||||
|
break; |
||||||
|
case "MaxLevel": |
||||||
|
powerEntry.maxLevel = Integer.parseInt(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "HateValue": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
powerEntry.hateValue = Integer.parseInt(arguments.get(0)); |
||||||
|
|
||||||
|
// Not all entries have a curve. Defaults to DefaultFlat;
|
||||||
|
|
||||||
|
if (arguments.size() > 1) |
||||||
|
powerEntry.hateCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1)); |
||||||
|
break; |
||||||
|
case "LOOPANIMID": |
||||||
|
powerEntry.loopAnimID = Integer.parseInt(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "GRANTOVERRIDEVAR": |
||||||
|
powerEntry.grantOverrideVar = lineValues.get(1).trim(); |
||||||
|
break; |
||||||
|
case "DESCRIPTION": |
||||||
|
powerEntry.description.add(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "CATEGORY": |
||||||
|
powerEntry.category = mbEnums.PowerCategoryType.valueOf(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "CURVE": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
powerEntry.curves.put(arguments.get(0), mbEnums.CompoundCurveType.valueOf(arguments.get(1))); |
||||||
|
break; |
||||||
|
case "EQPREREQ": |
||||||
|
argumentMatcher = STRSPLIT_REGEX.matcher(lineValues.get(1).trim()); |
||||||
|
arguments = new ArrayList<>(); |
||||||
|
|
||||||
|
while (argumentMatcher.find()) |
||||||
|
arguments.add(argumentMatcher.group().trim()); |
||||||
|
|
||||||
|
argumentIterator = arguments.iterator(); |
||||||
|
|
||||||
|
while (argumentIterator.hasNext()) { |
||||||
|
EquipmentPreReq equipmentPreReq = new EquipmentPreReq(); |
||||||
|
equipmentPreReq.slot = mbEnums.EquipSlotType.valueOf(argumentIterator.next()); |
||||||
|
equipmentPreReq.skill = argumentIterator.next().replaceAll("\"", ""); |
||||||
|
|
||||||
|
if (argumentIterator.hasNext()) |
||||||
|
equipmentPreReq.required = Integer.parseInt(argumentIterator.next()); |
||||||
|
else |
||||||
|
equipmentPreReq.required = 0; |
||||||
|
|
||||||
|
powerEntry.equipmentPreReq.add(equipmentPreReq); |
||||||
|
} |
||||||
|
break; |
||||||
|
case "CANCASTWHILEMOVING": |
||||||
|
powerEntry.canCastWhileMoving = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "CANCASTWHILEFLYING": |
||||||
|
powerEntry.canCastWhileFlying = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "BLADETRAILS": |
||||||
|
powerEntry.bladeTrails = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "EFFECTPREREQ": |
||||||
|
Effect effectPreReq = new Effect(); |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
effectPreReq.effect_id = arguments.get(9); |
||||||
|
effectPreReq.level = Integer.parseInt(arguments.get(1)); |
||||||
|
effectPreReq.message = arguments.get(2); |
||||||
|
powerEntry.effectPreReqs.add(effectPreReq); |
||||||
|
break; |
||||||
|
case "MONSTERTYPERESTRICTS": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String restriction : arguments) |
||||||
|
powerEntry.monsterRestricts.add(mbEnums.MonsterType.valueOf(restriction.trim())); |
||||||
|
break; |
||||||
|
case "MONSTERTYPEPREREQS": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
|
||||||
|
for (String restriction : arguments) |
||||||
|
powerEntry.monsterPrereqs.add(mbEnums.MonsterType.valueOf(restriction.trim())); |
||||||
|
break; |
||||||
|
case "SHOULDCHECKPATH": |
||||||
|
powerEntry.shouldCheckPath = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "STICKY": |
||||||
|
powerEntry.sticky = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "PULSEINFO": |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
powerEntry.pulseCycle = Integer.parseInt(arguments.get(0)); |
||||||
|
powerEntry.pulseDuration = Integer.parseInt(arguments.get(1)); |
||||||
|
break; |
||||||
|
case "MAXNUMMOBTARGETS": |
||||||
|
powerEntry.maxMobTargets = Integer.parseInt(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "MAXNUMPLAYERTARGETS": |
||||||
|
powerEntry.maxPlayerTargets = Integer.parseInt(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "ISADMINPOWER": |
||||||
|
powerEntry.isAdminPower = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "ISPROJECTILE": |
||||||
|
powerEntry.isProjectile = Boolean.parseBoolean(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "CASTERSPULSEPARTICLE": |
||||||
|
powerEntry.casterPulseParticle = Integer.parseInt(lineValues.get(1).trim()); |
||||||
|
break; |
||||||
|
case "TARGETEFFECTPREREQS_ORED": |
||||||
|
Effect preReq = new Effect(); |
||||||
|
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+")); |
||||||
|
preReq.effect_id = arguments.get(0); |
||||||
|
preReq.level = Integer.parseInt(arguments.get(1)); |
||||||
|
powerEntry.targetEffectPrereqs.add(preReq); |
||||||
|
break; |
||||||
|
case "SOUNDS": // Values not parsed
|
||||||
|
case "APPLYDAMAGESELF": |
||||||
|
case "APPLYDAMAGECASTER": |
||||||
|
case "APPLYDAMAGEOTHER": |
||||||
|
case "APPLYDAMAGETARGET": |
||||||
|
case "APPLYEFFECTSELF": |
||||||
|
case "APPLYEFFECTOTHER": |
||||||
|
case "APPLYEFFECTCASTER": |
||||||
|
case "APPLYEFFECTTARGET": |
||||||
|
case "FIZZLEOTHER": |
||||||
|
case "FIZZLESELF": |
||||||
|
case "INITSTRING": |
||||||
|
case "SUCCESSOTHER": |
||||||
|
case "SUCCESSSELF": |
||||||
|
case "WEAROFFEFFECTOTHER": |
||||||
|
case "WEAROFFEFFECTSELF": |
||||||
|
break; |
||||||
|
default: |
||||||
|
Logger.error("Unhandled variable type:" + key + " for power: " + powerEntry.power_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Parse power conditions
|
||||||
|
|
||||||
|
if (conditionString.isEmpty() == false) { |
||||||
|
|
||||||
|
List<String> conditions = Arrays.asList(conditionString.split("\n")); |
||||||
|
|
||||||
|
for (String condition : conditions) { |
||||||
|
List<String> parameters = Arrays.asList(condition.trim().split("\\s+")); |
||||||
|
powerEntry.conditions.put(parameters.get(0), Float.parseFloat(parameters.get(1))); |
||||||
|
} |
||||||
|
} |
||||||
|
return powerEntry; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,24 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class ActionEntry { |
||||||
|
|
||||||
|
public String action_id; |
||||||
|
public int minTrains; |
||||||
|
public int maxTrains; |
||||||
|
public float duration; |
||||||
|
public String stackingCategory; |
||||||
|
public mbEnums.CompoundCurveType curve; |
||||||
|
public int stackingPriority; |
||||||
|
public mbEnums.CategoryToPowerType categoryToPower; |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
//
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
import java.util.EnumSet; |
||||||
|
|
||||||
|
public class ConditionEntry { |
||||||
|
public String condition; |
||||||
|
public int arg; |
||||||
|
public mbEnums.CompoundCurveType curveType; |
||||||
|
public EnumSet<mbEnums.DamageType> damageTypes = EnumSet.noneOf(mbEnums.DamageType.class); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
public class Effect { |
||||||
|
public String effect_id; |
||||||
|
public String effect_name; |
||||||
|
public int icon; |
||||||
|
public HashSet<String> sources = new HashSet<>(); |
||||||
|
public ArrayList<ModifierEntry> mods = new ArrayList<>(); |
||||||
|
public ArrayList<ConditionEntry> conditions = new ArrayList<>(); |
||||||
|
|
||||||
|
// Additional variables outside of tags or parsed
|
||||||
|
// elsewhere from Effects.cfg
|
||||||
|
|
||||||
|
public boolean isItemEffect; |
||||||
|
public boolean isSpireEffect; |
||||||
|
public boolean ignoreNoMod; |
||||||
|
public boolean dontSave; |
||||||
|
|
||||||
|
public String type; |
||||||
|
public int level; |
||||||
|
public String message; |
||||||
|
public int cycleDuration; |
||||||
|
public int cycleDelay; |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (this == o) |
||||||
|
return true; |
||||||
|
if (o == null || getClass() != o.getClass()) |
||||||
|
return false; |
||||||
|
|
||||||
|
Effect effect = (Effect) o; |
||||||
|
return Objects.equals(effect_id, effect.effect_id); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return effect_id.hashCode(); // Use only the id field for hashCode
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class EquipmentPreReq { |
||||||
|
|
||||||
|
public mbEnums.EquipSlotType slot; |
||||||
|
public String skill; |
||||||
|
public int required; |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class ModifierEntry { |
||||||
|
public mbEnums.ModType type; |
||||||
|
public float min; |
||||||
|
public float max; |
||||||
|
public float percentage; |
||||||
|
public float value; |
||||||
|
public mbEnums.CompoundCurveType compoundCurveType; |
||||||
|
public String arg1; // ItemName "Masterwork" ""
|
||||||
|
public String arg2; // ItemName "" "of the Defender"
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,96 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.EnumSet; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
public class Power { |
||||||
|
public String power_id; |
||||||
|
public String power; |
||||||
|
public ArrayList<PowerEntry> powers = new ArrayList<>(); |
||||||
|
public mbEnums.PowerTargetType target_type; |
||||||
|
public int range; |
||||||
|
public mbEnums.AreaType areaType; |
||||||
|
public int areaRange; |
||||||
|
public mbEnums.ExcludeType excludeType; |
||||||
|
public mbEnums.CostType costType; |
||||||
|
public float cost; |
||||||
|
public float difficulty; |
||||||
|
public float precision; |
||||||
|
public float init_time; |
||||||
|
public float release_time; |
||||||
|
public float recycle_time; |
||||||
|
public int hitRollYN; |
||||||
|
public mbEnums.CastingModeType castingMode; |
||||||
|
public int initAmin; |
||||||
|
public int releaseAnim; |
||||||
|
public mbEnums.TargetSelectType targetSelect; |
||||||
|
|
||||||
|
// Additional key/value type power entries
|
||||||
|
|
||||||
|
public ArrayList<ActionEntry> actionEntries = new ArrayList<>(); |
||||||
|
public int maxLevel; |
||||||
|
public int hateValue; |
||||||
|
public mbEnums.CompoundCurveType hateCurve = mbEnums.CompoundCurveType.DefaultFlat; |
||||||
|
public int loopAnimID; |
||||||
|
public String grantOverrideVar; |
||||||
|
public ArrayList<String> description = new ArrayList<>(); |
||||||
|
public HashMap<String, mbEnums.CompoundCurveType> curves = new HashMap<>(); |
||||||
|
public mbEnums.PowerCategoryType category; |
||||||
|
public boolean canCastWhileMoving = false; |
||||||
|
public boolean bladeTrails = false; |
||||||
|
public ArrayList<Effect> effectPreReqs = new ArrayList<>(); |
||||||
|
public ArrayList<EquipmentPreReq> equipmentPreReq = new ArrayList<>(); |
||||||
|
public EnumSet<mbEnums.MonsterType> monsterRestricts = EnumSet.noneOf(mbEnums.MonsterType.class); |
||||||
|
public EnumSet<mbEnums.MonsterType> monsterPrereqs = EnumSet.noneOf(mbEnums.MonsterType.class); |
||||||
|
public boolean shouldCheckPath = false; |
||||||
|
public boolean sticky = false; |
||||||
|
public int pulseCycle; |
||||||
|
public int pulseDuration; |
||||||
|
public int maxMobTargets; |
||||||
|
public int maxPlayerTargets; |
||||||
|
public boolean isAdminPower = false; |
||||||
|
public int casterPulseParticle; |
||||||
|
public ArrayList<Effect> targetEffectPrereqs = new ArrayList<>(); |
||||||
|
public boolean canCastWhileFlying = false; |
||||||
|
public boolean isProjectile = false; |
||||||
|
public HashMap<String, Float> conditions = new HashMap<>(); |
||||||
|
|
||||||
|
public boolean isSpell() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSkill() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isChant() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (this == o) |
||||||
|
return true; |
||||||
|
if (o == null || getClass() != o.getClass()) |
||||||
|
return false; |
||||||
|
|
||||||
|
Power power = (Power) o; |
||||||
|
return Objects.equals(power_id, power.power_id); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return power_id.hashCode(); // Use only the id field for hashCode
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
public class PowerAction { |
||||||
|
|
||||||
|
// Header values
|
||||||
|
|
||||||
|
public String action_id; |
||||||
|
public mbEnums.PowerActionType action_type; |
||||||
|
public ArrayList<Effect> effects = new ArrayList<>(); |
||||||
|
public int petLevel; |
||||||
|
public int petRace; |
||||||
|
public StatTransfer statTransfer; |
||||||
|
public int levelCap; |
||||||
|
public mbEnums.CompoundCurveType levelCapCurve; |
||||||
|
public TrackEntry trackEntry; |
||||||
|
|
||||||
|
// Additional variables after header go here.
|
||||||
|
|
||||||
|
public ArrayList<Integer> bodyParts = new ArrayList<>(); |
||||||
|
public ArrayList<Integer> femaleBodyParts = new ArrayList<>(); |
||||||
|
public boolean shouldShowWeapons = false; |
||||||
|
public boolean shouldShowArmor = false; |
||||||
|
public boolean bladeTrails = false; |
||||||
|
public boolean isResistible = false; |
||||||
|
public ArrayList<Float> scaleFactor = new ArrayList<>(); |
||||||
|
public ArrayList<Integer> attackAnimations = new ArrayList<>(); |
||||||
|
public boolean isAggressive; |
||||||
|
public mbEnums.DamageType damageType; |
||||||
|
public boolean applyEffectBlank = false; |
||||||
|
public boolean wearOffEffectBlank = false; |
||||||
|
public boolean removeAll = false; |
||||||
|
public boolean clearAggro = false; |
||||||
|
public boolean targetBecomesPet = false; |
||||||
|
public boolean destroyOldPet = false; |
||||||
|
public mbEnums.ItemFlags itemFlag; |
||||||
|
public mbEnums.MobBehaviourType rootFsmID; |
||||||
|
public int splashDamageMin; |
||||||
|
public int splashDamageMax; |
||||||
|
public boolean ignoreNoTeleSpire = false; |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (this == o) |
||||||
|
return true; |
||||||
|
if (o == null || getClass() != o.getClass()) |
||||||
|
return false; |
||||||
|
|
||||||
|
PowerAction powerAction = (PowerAction) o; |
||||||
|
return Objects.equals(action_id, powerAction.action_id); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return action_id.hashCode(); // Use only the id field for hashCode
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class PowerEntry { |
||||||
|
public mbEnums.PowerType power_type; |
||||||
|
public int icon; |
||||||
|
public String focusLine; |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2024
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class StatTransfer { |
||||||
|
public mbEnums.CostType fromStat; |
||||||
|
public float ramp; |
||||||
|
public mbEnums.CompoundCurveType rampCurve; |
||||||
|
public mbEnums.CostType toStat; |
||||||
|
public float efficiency; |
||||||
|
public mbEnums.CompoundCurveType efficiencyCurve; |
||||||
|
public boolean fromStatBool; |
||||||
|
public boolean isDrain; |
||||||
|
public String transfer_action; |
||||||
|
public int transfer_ticks; |
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.wpak.data; |
||||||
|
|
||||||
|
import engine.mbEnums; |
||||||
|
|
||||||
|
public class TrackEntry { |
||||||
|
|
||||||
|
public String action_id; |
||||||
|
public Boolean trackPlayer; |
||||||
|
public Boolean trackCorpse; |
||||||
|
public mbEnums.MonsterType filter; |
||||||
|
public int min; |
||||||
|
public int max; |
||||||
|
} |
||||||
Loading…
Reference in new issue