From c9474cf042088befdb9f30f052ac300d82dc96b5 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Mon, 26 Oct 2026 20:33:10 -0400 Subject: [PATCH] Read wpak booleans the way the client does boolToken follows Core.dll String::ToBool with a false default instead of throwing, and the five PowerActions keys the client compares to exact "TRUE" use the new optionalExactTrueToken. Co-Authored-By: Claude Opus 5.5 --- .../parsers/wpak/PowerActionParser.java | 10 +++--- src/engine/parsers/wpak/WpakLine.java | 35 +++++++++++++++---- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/engine/parsers/wpak/PowerActionParser.java b/src/engine/parsers/wpak/PowerActionParser.java index 32f254c1..144419c5 100644 --- a/src/engine/parsers/wpak/PowerActionParser.java +++ b/src/engine/parsers/wpak/PowerActionParser.java @@ -186,13 +186,13 @@ public class PowerActionParser { switch (line.token(0)) { case "ISAGGRESSIVE=": - powerAction.isaggressive = line.optionalBoolToken(1); + powerAction.isaggressive = line.optionalExactTrueToken(1); break; case "BLADETRAILS=": - powerAction.bladetrails = line.optionalBoolToken(1); + powerAction.bladetrails = line.optionalExactTrueToken(1); break; case "ISRESISTABLE=": - powerAction.isresistable = line.optionalBoolToken(1); + powerAction.isresistable = line.optionalExactTrueToken(1); break; case "APPLYEFFECTSELF=": powerAction.applyeffectself = line.token(1); @@ -225,10 +225,10 @@ public class PowerActionParser { powerAction.femalebodyparts.addAll(line.intTokensFrom(1)); break; case "SHOULDSHOWWEAPONS=": - powerAction.shouldshowweapons = line.optionalBoolToken(1); + powerAction.shouldshowweapons = line.optionalExactTrueToken(1); break; case "SHOULDSHOWARMOR=": - powerAction.shouldshowarmor = line.optionalBoolToken(1); + powerAction.shouldshowarmor = line.optionalExactTrueToken(1); break; case "ATTACKANIMS=": powerAction.attackanims.addAll(line.intTokensFrom(1)); diff --git a/src/engine/parsers/wpak/WpakLine.java b/src/engine/parsers/wpak/WpakLine.java index b7cb1d29..87a9d059 100644 --- a/src/engine/parsers/wpak/WpakLine.java +++ b/src/engine/parsers/wpak/WpakLine.java @@ -107,23 +107,44 @@ public class WpakLine { return intToken(index); } - // TRUE/FALSE, or a number where non-zero is true + // Core.dll String::ToBool with the false default every wpak loader passes: a leading '0' is + // false, '1'..'9' is true, then TRUE/FALSE in any case; anything else reads as false public boolean boolToken(int index) { String value = token(index); + char first = value.isEmpty() ? 0 : value.charAt(0); + + if (first == '0') + return false; + + if (first >= '1' && first <= '9') + return true; if (value.equalsIgnoreCase("TRUE")) return true; - if (value.equalsIgnoreCase("FALSE")) + if (!value.equalsIgnoreCase("FALSE")) + Logger.warn(location() + ": token " + index + " '" + value + "' read as false, as the client does"); + + return false; + } + + // Some PowerActions keys compare the token to "TRUE" exactly (String_EqualsCStr 0x546450), so "1" is false + + public boolean optionalExactTrueToken(int index) { + + String value; + + if (!has(index)) return false; - try { - return Integer.parseInt(value) != 0; - } catch (NumberFormatException e) { - throw error("token " + index + " '" + value + "' is not a boolean"); - } + value = token(index); + + if (!value.equals("TRUE") && !value.equals("FALSE")) + Logger.warn(location() + ": token " + index + " '" + value + "' read as false, as the client does"); + + return value.equals("TRUE"); } public boolean optionalBoolToken(int index) {