13 changed files with 1281 additions and 0 deletions
@ -0,0 +1,286 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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