diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f00af69cd..a407417ca 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -34,6 +34,7 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
runs-on: ${{ matrix.os }}
permissions:
+ checks: write
contents: read
env:
JAVA_TOOL_OPTIONS: >-
diff --git a/.gitignore b/.gitignore
index fb5e25193..7b7bf5ad3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,5 @@ WurstSetup/proguard.map
de.peeeq.wurstscript/output.txt
/HelperScripts/gamedata
/HelperScripts/.gradle
+/.gradle-user-home
+/gradle-home-temp
diff --git a/de.peeeq.wurstscript/deploy.gradle b/de.peeeq.wurstscript/deploy.gradle
index bae051470..1e5d9577e 100644
--- a/de.peeeq.wurstscript/deploy.gradle
+++ b/de.peeeq.wurstscript/deploy.gradle
@@ -42,6 +42,7 @@ def jreImageDir = layout.buildDirectory.dir("jre-wurst-25")
def distRoot = layout.buildDirectory.dir("dist/slim-${plat}")
def releasesDir = layout.buildDirectory.dir("releases")
+def appCdsArchive = distRoot.map { it.file("wurst-runtime/wurst-lsp.jsa") }
// ----------------------- Toolchain / tool paths (providers) -------------------------
def toolchainSvc = extensions.getByType(JavaToolchainService)
@@ -223,11 +224,51 @@ tasks.named("assembleSlimCompilerDist", Copy) { t ->
}
}
+tasks.register("generateAppCdsArchive", Exec) {
+ description = "Best-effort AppCDS archive generation for language-server startup."
+ group = "distribution"
+ dependsOn("assembleSlimCompilerDist")
+
+ inputs.file(fatJar)
+ inputs.dir(distRoot)
+ outputs.file(appCdsArchive)
+ ignoreExitValue = true
+
+ doFirst {
+ def distDir = distRoot.get().asFile
+ def archiveFile = appCdsArchive.get().asFile
+ def runtimeJava = new File(distDir, "wurst-runtime/bin/java${os.isWindows() ? '.exe' : ''}")
+ def compilerJar = new File(distDir, "wurst-compiler/${fatJar.get().asFile.name}")
+
+ archiveFile.parentFile.mkdirs()
+ if (archiveFile.exists()) {
+ archiveFile.delete()
+ }
+
+ executable = runtimeJava.absolutePath
+ args "-Xshare:auto",
+ "-XX:ArchiveClassesAtExit=${archiveFile.absolutePath}",
+ "-jar", compilerJar.absolutePath,
+ "-languageServerAppCdsTrain"
+
+ logger.lifecycle("[appcds] Training LS startup with ${runtimeJava.absolutePath}")
+ }
+
+ doLast {
+ def archiveFile = appCdsArchive.get().asFile
+ if (executionResult.get().exitValue != 0 || !archiveFile.exists()) {
+ logger.warn("[appcds] Archive generation did not succeed on ${plat}; continuing without shipped AppCDS archive.")
+ } else {
+ logger.lifecycle("[appcds] Wrote ${archiveFile.absolutePath}")
+ }
+ }
+}
+
// 4) Package ZIP on all platforms
tasks.register("packageSlimCompilerDistZip", Zip) {
description = "Packages slim dist as a ZIP archive (all platforms)."
group = "distribution"
- dependsOn("assembleSlimCompilerDist")
+ dependsOn("generateAppCdsArchive")
from(distRoot)
destinationDirectory.set(releasesDir)
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java
index 0f6bb78ac..161895aff 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java
@@ -79,6 +79,11 @@ public static void main(String[] args) {
return;
}
+ if (runArgs.isLanguageServerAppCdsTrain()) {
+ LanguageServerStarter.trainForAppCds();
+ return;
+ }
+
if (runArgs.isLanguageServer()) {
LanguageServerStarter.start();
return;
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java
index 45c632e04..c6b5d28f7 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java
@@ -616,9 +616,11 @@ public static void exportToWurst(List extends ObjMod.Obj> customObjs, ObjectFi
*
Fields that have no known wrapper method are emitted as commented-out raw
* calls so the output is still useful even when coverage is incomplete.
*
- *
Returns {@code false} only when there is no wrapper class at all for this
+ *
Returns {@code false} when there is no wrapper class at all for this
* object type / base ID (e.g. doodads, upgrades, or an unknown ability base ID),
- * in which case the caller should fall back to the fully raw format.
+ * or when a mapped wrapper setter exists but its parameter type is not yet
+ * supported for source re-emission. In those cases the caller should fall back
+ * to the fully raw format so no object data is lost on re-export.
*/
private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileType,
String newId, String oldId,
@@ -677,11 +679,8 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT
return false;
}
- for (ObjMod.Obj.Mod m : mods) {
- StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(m, fileType));
- if (info != null && !canUseWrapperForMod(m, info)) {
- return false;
- }
+ if (hasUnsupportedMappedWrapperField(mods, fieldMethods, fileType)) {
+ return false;
}
out.append("@compiletime function create_").append(fileType.getExt()).append("_").append(newId)
@@ -690,7 +689,7 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT
for (ObjMod.Obj.Mod m : mods) {
StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(m, fileType));
- if (info != null) {
+ if (info != null && canUseWrapperForMod(m, info)) {
out.append("\t..").append(info.methodName()).append("(");
if (info.hasLevel() && m instanceof ObjMod.Obj.ExtendedMod) {
out.append(String.valueOf(((ObjMod.Obj.ExtendedMod) m).getLevel())).append(", ");
@@ -707,6 +706,21 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT
return true;
}
+ private static boolean hasUnsupportedMappedWrapperField(List mods,
+ Map fieldMethods,
+ ObjectFileType fileType) {
+ for (ObjMod.Obj.Mod mod : mods) {
+ StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(mod, fileType));
+ if (info == null) {
+ continue;
+ }
+ if (!canUseWrapperForMod(mod, info)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Returns the lookup key used to match a mod to a {@link StdlibObjectMappings.FieldMethodInfo}.
* Uses the mod's actual dataPtr when it is an {@link ObjMod.Obj.ExtendedMod}, regardless of
@@ -724,8 +738,7 @@ static String fieldKey(ObjMod.Obj.Mod m, ObjectFileType fileType) {
}
private static boolean canUseWrapperForMod(ObjMod.Obj.Mod m, StdlibObjectMappings.FieldMethodInfo info) {
- if (!info.parameterType().isEmpty() && !isPrimitiveParameter(info.parameterType())
- && !isEnumParameter(info.parameterType())) {
+ if (!supportsWrapperParameterType(info.parameterType())) {
return false;
}
if (isEnumParameter(info.parameterType())) {
@@ -734,6 +747,12 @@ private static boolean canUseWrapperForMod(ObjMod.Obj.Mod m, StdlibObjectMapping
return true;
}
+ private static boolean supportsWrapperParameterType(String parameterType) {
+ return parameterType.isEmpty()
+ || isPrimitiveParameter(parameterType)
+ || isEnumParameter(parameterType);
+ }
+
private static boolean isEnumParameter(String parameterType) {
return ENUM_OBJECT_STRING_TO_CONSTANT.containsKey(parameterType);
}
@@ -848,6 +867,7 @@ private static Map enumConstants(String... valueConstantPairs) {
"mline", "MissileLine"
),
"WeaponSound", enumConstants(
+ "", "Nothing",
"Nothing", "Nothing",
"AxeMediumChop", "AxeMediumChop",
"MetalHeavyBash", "MetalHeavyBash",
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageServerStarter.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageServerStarter.java
index dfb2d07b6..1caffd5ca 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageServerStarter.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageServerStarter.java
@@ -22,5 +22,15 @@ public static void start() {
server.setRemoteEndpoint(launcher.getRemoteEndpoint());
}
+ public static void trainForAppCds() {
+ WurstLanguageServer server = new WurstLanguageServer();
+ try {
+ server.getTextDocumentService();
+ server.getWorkspaceService();
+ } finally {
+ server.shutdown().join();
+ }
+ }
+
}
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java
index d56813e25..e293319dc 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java
@@ -58,6 +58,7 @@ public void setRootPath(WFile rootPath) {
lock.notify();
}
});
+ private boolean initialBuildPending = false;
private final BufferManager bufferManager = new BufferManager();
private LanguageClient languageClient;
@@ -200,9 +201,6 @@ private Workitem getNextWorkItem() {
changesToReconcile = ModelManager.Changes.empty();
reconcileNowRequested = false;
return new Workitem("reconcile files (save)", () -> modelManager.reconcile(changes));
- } else if (!userRequests.isEmpty()) {
- UserRequest> req = userRequests.remove();
- return new Workitem(req.toString(), () -> req.run(modelManager));
} else if (!changes.isEmpty()) {
// TODO this can be done more efficiently than doing one at a time
PendingChange change = removeFirst(changes);
@@ -246,6 +244,12 @@ private Workitem getNextWorkItem() {
return new Workitem("reconcile files", () -> {
modelManager.reconcile(changes);
});
+ } else if (initialBuildPending) {
+ initialBuildPending = false;
+ return new Workitem("initial full build", () -> doInitialBuild());
+ } else if (!userRequests.isEmpty()) {
+ UserRequest> req = userRequests.remove();
+ return new Workitem(req.toString(), () -> req.run(modelManager));
}
return null;
}
@@ -271,11 +275,20 @@ private void doInit(WFile rootPath) {
log("Handle init " + rootPath);
modelManager = new ModelManagerImpl(rootPath.getFile(), bufferManager);
modelManager.onCompilationResult(this::onCompilationResult);
+ initialBuildPending = true;
+ } catch (Exception e) {
+ WLogger.severe(e);
+ }
+ }
- log("Start building " + rootPath);
+ private void doInitialBuild() {
+ try {
+ if (modelManager == null || rootPath == null) {
+ return;
+ }
+ log("Start background full build " + rootPath);
modelManager.buildProject();
-
- log("Finished building " + rootPath);
+ log("Finished background full build " + rootPath);
} catch (Exception e) {
WLogger.severe(e);
}
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java
index 2945229bc..dface9274 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java
@@ -516,20 +516,11 @@ private void resolveImports(WurstGui gui) {
}
private void replaceCompilationUnit(WFile filename) {
- File f;
try {
- f = filename.getFile();
- } catch (FileNotFoundException e) {
- WLogger.info("Cannot replaceCompilationUnit for " + filename + "\n" + e);
- return;
- }
- if (!f.exists()) {
- removeCompilationUnit(filename);
- return;
- }
- try {
- String contents = Files.toString(f, Charsets.UTF_8);
- bufferManager.updateFile(WFile.create(f), contents);
+ String contents = readCompilationUnitContents(filename, true);
+ if (contents == null) {
+ return;
+ }
replaceCompilationUnit(filename, contents, true);
} catch (IOException e) {
WLogger.severe(e);
@@ -582,13 +573,10 @@ public Changes syncCompilationUnit(WFile f) {
WLogger.debug("syncCompilationUnit File " + f);
String contents;
try {
- File file = f.getFile();
- if (!file.exists()) {
- removeCompilationUnit(f);
+ contents = readCompilationUnitContents(f, true);
+ if (contents == null) {
return Changes.empty();
}
- contents = Files.toString(file, Charsets.UTF_8);
- bufferManager.updateFile(WFile.create(file), contents);
} catch (IOException e) {
WLogger.severe(e);
throw new ModelManagerException(e);
@@ -608,6 +596,28 @@ public Changes syncCompilationUnit(WFile f) {
return new Changes(io.vavr.collection.HashSet.of(f), oldPackages);
}
+ private @Nullable String readCompilationUnitContents(WFile filename, boolean preferOpenBuffer) throws IOException {
+ if (preferOpenBuffer && bufferManager.getTextDocumentVersion(filename) >= 0) {
+ return bufferManager.getBuffer(filename);
+ }
+ File file;
+ try {
+ file = filename.getFile();
+ } catch (FileNotFoundException e) {
+ WLogger.info("Cannot read compilation unit for " + filename + "\n" + e);
+ return null;
+ }
+ if (!file.exists()) {
+ removeCompilationUnit(filename);
+ return null;
+ }
+ String contents = Files.toString(file, Charsets.UTF_8);
+ if (bufferManager.getTextDocumentVersion(filename) < 0) {
+ bufferManager.updateFile(WFile.create(file), contents);
+ }
+ return contents;
+ }
+
private CompilationUnit replaceCompilationUnit(WFile filename, String contents, boolean reportErrors) {
if (!isInWurstFolder(filename) && !isAlreadyLoaded(filename)) {
return null;
diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/RunArgs.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/RunArgs.java
index a6fb6b95c..fa5be557c 100644
--- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/RunArgs.java
+++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/RunArgs.java
@@ -42,6 +42,7 @@ public class RunArgs {
private final RunOption optionExtractImports;
private final RunOption optionStartServer;
private final RunOption optionLanguageServer;
+ private final RunOption optionLanguageServerAppCdsTrain;
private final RunOption optionNoExtractMapScript;
private final RunOption optionFixInstall;
private final RunOption optionCopyMap;
@@ -136,6 +137,7 @@ public RunArgs(String... args) {
optionLanguageServer = addOption("languageServer", "Starts a language server which can be used by editors to get services "
+ "like code completion, validations, and find declaration. The communication to the language server is via standard input output.");
+ optionLanguageServerAppCdsTrain = addOption("languageServerAppCdsTrain", "Starts and immediately stops a lightweight language-server startup path for AppCDS training.");
optionHelp = addOption("help", "Prints this help message.");
optionDisablePjass = addOption("noPJass", "Disables PJass checks for the generated code.");
@@ -352,6 +354,10 @@ public boolean isLanguageServer() {
return optionLanguageServer.isSet;
}
+ public boolean isLanguageServerAppCdsTrain() {
+ return optionLanguageServerAppCdsTrain.isSet;
+ }
+
public boolean isNoExtractMapScript() {
return optionNoExtractMapScript.isSet;
}
diff --git a/de.peeeq.wurstscript/src/main/resources/stdlib-obj-mappings.json b/de.peeeq.wurstscript/src/main/resources/stdlib-obj-mappings.json
index 6050085fc..2d8539f2e 100644
--- a/de.peeeq.wurstscript/src/main/resources/stdlib-obj-mappings.json
+++ b/de.peeeq.wurstscript/src/main/resources/stdlib-obj-mappings.json
@@ -3,6 +3,7 @@
"Aabr": "AbilityDefinitionAuraRegenerationStatue",
"Aabs": "AbilityDefinitionAbsorbMana",
"Aadm": "AbilityDefinitionAbolishMagic",
+ "Aaha": "AbilityDefinitionAcolyteHarvest",
"Aakb": "AbilityDefinitionAuraWarDrumsKodobeast",
"Aall": "AbilityDefinitionShopSharing",
"Aalr": "AbilityDefinitionAlarm",
@@ -22,6 +23,7 @@
"Aatk": "AbilityDefinitionAttack",
"Aatp": "AbilityDefinitionAttackTargetPriority",
"Aave": "AbilityDefinitionAvengerForm",
+ "Aawa": "AbilityDefinitionAwaken",
"Abdl": "AbilityDefinitionBlightDispelLarge",
"Abds": "AbilityDefinitionBlightDispelSmall",
"Abdt": "AbilityDefinitionBurrowDetectionFlyers",
@@ -41,6 +43,7 @@
"Abur": "AbilityDefinitionBurrow",
"ACac": "AbilityDefinitionAuraCommandCreep",
"ACad": "AbilityDefinitionAnimateDeadcreep",
+ "ACah": "AbilityDefinitionThornsAuraCreep",
"ACam": "AbilityDefinitionAntimagicShieldcreep",
"Acan": "AbilityDefinitionCannibalize",
"ACat": "AbilityDefinitionAuraTrueshotCreep",
@@ -58,6 +61,7 @@
"ACc3": "AbilityDefinitionCrushingWaveLesser",
"ACca": "AbilityDefinitionCarrionSwarmcreep",
"ACcb": "AbilityDefinitionFrostBolt",
+ "ACce": "AbilityDefinitionCleavingAttackCreep",
"ACch": "AbilityDefinitionCharm",
"ACcl": "AbilityDefinitionChainLightningcreep",
"ACcn": "AbilityDefinitionCannibalizecreep",
@@ -74,6 +78,7 @@
"Acdh": "AbilityDefinitionChenDrunkenHaze",
"ACdm": "AbilityDefinitionAbolishMagicCreep",
"ACdr": "AbilityDefinitionDrainLifeCreep",
+ "ACds": "AbilityDefinitionDivineShieldCreep",
"ACdv": "AbilityDefinitionDevourCreep",
"Acef": "AbilityDefinitionChenStormEarthAndFire",
"ACen": "AbilityDefinitionEnsnareCreep",
@@ -130,7 +135,7 @@
"ACrg": "AbilityDefinitionRainOfFireCreepGreater",
"Acri": "AbilityDefinitionCripple",
"ACrj": "AbilityDefinitionRejuvinationcreep",
- "ACrk": "AbilityDefinitionResistantSkin",
+ "ACrk": "AbilityDefinitionResistantSkinCreep",
"ACrn": "AbilityDefinitionReincarnationcreep",
"ACro": "AbilityDefinitionRoarcreep",
"Acrs": "AbilityDefinitionCurse",
@@ -144,6 +149,7 @@
"ACsk": "AbilityDefinitionResistantSkin31PosCreep",
"ACsl": "AbilityDefinitionSleepcreep",
"ACsm": "AbilityDefinitionSiphonManaCreep",
+ "ACsp": "AbilityDefinitionCreepSleep",
"ACss": "AbilityDefinitionShadowStrikeCreep",
"ACst": "AbilityDefinitionShockwaveTrap",
"ACsw": "AbilityDefinitionSlowCreep",
@@ -166,6 +172,8 @@
"Adet": "AbilityDefinitionAdet",
"Adev": "AbilityDefinitionDevour",
"Adis": "AbilityDefinitionDispelMagic",
+ "Adri": "AbilityDefinitionDropInstant",
+ "Adro": "AbilityDefinitionDrop",
"Adsm": "AbilityDefinitionDispelMagiccreep",
"Adt1": "AbilityDefinitionDetectSentryWard",
"Adtg": "AbilityDefinitionDetectgeneral",
@@ -177,6 +185,7 @@
"AEar": "AbilityDefinitionMoonPriestessTrueshotAura",
"Aeat": "AbilityDefinitionEatTree",
"AEbl": "AbilityDefinitionWardenBlink",
+ "AEbu": "AbilityDefinitionBuildNightElf",
"AEer": "AbilityDefinitionKeeperoftheGroveEntanglingRoots",
"AEev": "AbilityDefinitionDemonHunterEvasion",
"AEfk": "AbilityDefinitionWardenFanofKnives",
@@ -231,6 +240,7 @@
"Afrz": "AbilityDefinitionFreezingBreath",
"Afsh": "AbilityDefinitionFragShards",
"Afzy": "AbilityDefinitionFrenzy",
+ "AGbu": "AbilityDefinitionBuildNaga",
"Agho": "AbilityDefinitionGhost",
"Agld": "AbilityDefinitionGoldMine",
"Agra": "AbilityDefinitionGrabTree",
@@ -244,6 +254,7 @@
"AHav": "AbilityDefinitionMountainKingAvatar",
"AHbh": "AbilityDefinitionMountainKingBash",
"AHbn": "AbilityDefinitionBloodMageBanish",
+ "AHbu": "AbilityDefinitionBuildHuman",
"AHbz": "AbilityDefinitionArchMageBlizzard",
"AHca": "AbilityDefinitionRangerColdArrows",
"AHdr": "AbilityDefinitionBloodMageSiphonMana",
@@ -327,7 +338,9 @@
"AIdd": "AbilityDefinitionDefendItem",
"AIde": "AbilityDefinitionAIde",
"AIdf": "AbilityDefinitionOrbofDarkness",
+ "AIdg": "AbilityDefinitionItemRitualDaggerInstant",
"AIdi": "AbilityDefinitionItemDispelAoe",
+ "AIdm": "AbilityDefinitionItemDamageAoe",
"AIdn": "AbilityDefinitionShadowOrbAbility",
"AIdp": "AbilityDefinitionDeathPactItem",
"AIds": "AbilityDefinitionItemDispelAoeWithCooldown",
@@ -341,9 +354,14 @@
"AIfa": "AbilityDefinitionFlareGun",
"AIfb": "AbilityDefinitionFireDamageBonus",
"AIfd": "AbilityDefinitionFigurineRedDrake",
+ "AIfe": "AbilityDefinitionFlagUndead",
"AIff": "AbilityDefinitionFigurineFurbolg",
"AIfg": "AbilityDefinitionCloudofFogItem",
"AIfh": "AbilityDefinitionFigurineFelHound",
+ "AIfl": "AbilityDefinitionFlag",
+ "AIfm": "AbilityDefinitionFlagHuman",
+ "AIfn": "AbilityDefinitionFlagNightElf",
+ "AIfo": "AbilityDefinitionFlagOrc",
"AIfr": "AbilityDefinitionFigurineRockGolem",
"AIfs": "AbilityDefinitionFigurineSkeleton",
"AIft": "AbilityDefinitionFrostguardFrostMelee",
@@ -351,6 +369,7 @@
"AIfw": "AbilityDefinitionSearingBladeFireMelee",
"AIfx": "AbilityDefinitionFlagOrcBattleStandard",
"AIfz": "AbilityDefinitionFingerOfDeathItem",
+ "AIg2": "AbilityDefinitionItemRitualDaggerRegen",
"AIgd": "AbilityDefinitionOrbOfGuldan",
"AIgf": "AbilityDefinitionFortificationGlyph",
"AIgm": "AbilityDefinitionAgilityModPlus2",
@@ -364,6 +383,7 @@
"AIhb": "AbilityDefinitionItemHealAoeGreater",
"AIhe": "AbilityDefinitionAIhe",
"AIhl": "AbilityDefinitionHolyLightItem",
+ "AIhm": "AbilityDefinitionShadowMeldItem",
"Aihn": "AbilityDefinitionInventory2SlotUnitHuman",
"AIhw": "AbilityDefinitionHealingWardAIhw",
"AIhx": "AbilityDefinitionItemHealLeastest",
@@ -406,6 +426,7 @@
"AInd": "AbilityDefinitionAnimateDeaditemspecial",
"Ainf": "AbilityDefinitionInnerFire",
"AInm": "AbilityDefinitionStrengthModPlus2",
+ "AIno": "AbilityDefinitionSlow2",
"AInv": "AbilityDefinitionInventory",
"AIob": "AbilityDefinitionFrostDamageBonus",
"Aion": "AbilityDefinitionInventory2SlotUnitOrc",
@@ -453,6 +474,7 @@
"AIsi": "AbilityDefinitionSightBonus",
"AIsl": "AbilityDefinitionScrollofLifeRegen",
"AIsm": "AbilityDefinitionStrengthMod",
+ "AIso": "AbilityDefinitionSoulTrap",
"AIsp": "AbilityDefinitionItemSpeed",
"AIsr": "AbilityDefinitionRunedBracers",
"AIsw": "AbilityDefinitionSentryWardAIsw",
@@ -487,6 +509,7 @@
"AIvl": "AbilityDefinitionItemInvulLesser",
"AIvm": "AbilityDefinitionReassignableAttributeBonusPlus1",
"Aivs": "AbilityDefinitionInvisibility",
+ "AIvu": "AbilityDefinitionItemInvulNormal",
"AIwb": "AbilityDefinitionItemWeb",
"AIwd": "AbilityDefinitionItemAuraWarDrums",
"AIwm": "AbilityDefinitionWateryMinionItem",
@@ -499,6 +522,7 @@
"AIxm": "AbilityDefinitionPermanentAllPlus1",
"AIxs": "AbilityDefinitionAntimagicShieldAIxs",
"AIzb": "AbilityDefinitionFreezeDamageBonus",
+ "Alam": "AbilityDefinitionSacrificeAcolyte",
"Aliq": "AbilityDefinitionLiquidFire",
"Alit": "AbilityDefinitionLightningAttack",
"Aloa": "AbilityDefinitionLoad",
@@ -510,10 +534,13 @@
"Ambt": "AbilityDefinitionManaBattery",
"Amdf": "AbilityDefinitionMagicDefense",
"Amec": "AbilityDefinitionMechanicalCritter",
+ "Amed": "AbilityDefinitionMeatDrop",
+ "Amel": "AbilityDefinitionMeatLoad",
"Amfl": "AbilityDefinitionManaFlare",
"Amgi": "AbilityDefinitionBouncingMissileFilter",
"Amgl": "AbilityDefinitionMoonGlaive",
"Amgr": "AbilityDefinitionMoonGlaiveNoResearch",
+ "Amic": "AbilityDefinitionMilitiaConversion",
"Amil": "AbilityDefinitionMilitia",
"Amim": "AbilityDefinitionMagicImmunity",
"Amin": "AbilityDefinitionMine",
@@ -524,6 +551,7 @@
"Amov": "AbilityDefinitionMove",
"Amrf": "AbilityDefinitionRavenFormMedivh",
"ANab": "AbilityDefinitionAlchemistAcidBomb",
+ "ANak": "AbilityDefinitionOrbOfAnnihilationQuillSpray",
"ANav": "AbilityDefinitionAvatarGarithos",
"ANb2": "AbilityDefinitionBashmaulSPBearlevel3",
"ANba": "AbilityDefinitionDarkRangerBlackArrow",
@@ -532,6 +560,7 @@
"ANbl": "AbilityDefinitionBlinkBeastmasterBear",
"ANbr": "AbilityDefinitionBattleRoar",
"ANbs": "AbilityDefinitionOrbofDarknessBlackArrow",
+ "ANbu": "AbilityDefinitionBuildNeutral",
"ANc1": "AbilityDefinitionTinkererClusterRocketsLevel1",
"ANc2": "AbilityDefinitionTinkererClusterRocketsLevel2",
"ANc3": "AbilityDefinitionTinkererClusterRocketsLevel3",
@@ -624,6 +653,7 @@
"Aoar": "AbilityDefinitionAuraRegenerationHealingWard",
"Aobk": "AbilityDefinitionPassiveOrcBerserkersRobk",
"Aobs": "AbilityDefinitionPassiveOrcGruntBerserkRobs",
+ "AObu": "AbilityDefinitionBuildOrc",
"AOcl": "AbilityDefinitionFarseerChainLightning",
"AOcr": "AbilityDefinitionBladeMasterCriticalStrike",
"AOeq": "AbilityDefinitionFarseerEarthquake",
@@ -643,6 +673,7 @@
"AOsw": "AbilityDefinitionShadowHunterSerpentWard",
"Aoth": "AbilityDefinitionPassiveOrcGhostIconOnlyOrcAethUnused",
"Aotr": "AbilityDefinitionPassiveOrcTrollRegenerationRotr",
+ "AOvd": "AbilityDefinitionShadowHunterVoodooo",
"AOw2": "AbilityDefinitionCairneWarStomp",
"AOwk": "AbilityDefinitionBladeMasterWindWalk",
"AOws": "AbilityDefinitionTaurenChieftainWarStomp",
@@ -656,6 +687,7 @@
"APh3": "AbilityDefinitionPowerupHealAoeGreater",
"Aphx": "AbilityDefinitionPhoenix",
"Apig": "AbilityDefinitionPermanentImmolationgraphic",
+ "Apit": "AbilityDefinitionPurchaseItem",
"Apiv": "AbilityDefinitionPermanentInvisibility",
"Aply": "AbilityDefinitionPolymorph",
"Apmf": "AbilityDefinitionPermanentImmolationflying",
@@ -676,6 +708,7 @@
"Apxf": "AbilityDefinitionPhoenixFire",
"Ara2": "AbilityDefinitionRoarAra2",
"Arai": "AbilityDefinitionRaiseDead",
+ "ARal": "AbilityDefinitionRally",
"Arav": "AbilityDefinitionRavenFormDruidoftheTalon",
"Arbr": "AbilityDefinitionReinforcedBurrows",
"Arej": "AbilityDefinitionRejuvination",
@@ -683,6 +716,7 @@
"Aren": "AbilityDefinitionRenew",
"Arep": "AbilityDefinitionRepairOrc",
"Aret": "AbilityDefinitionRetrain",
+ "Arev": "AbilityDefinitionRevive",
"Argd": "AbilityDefinitionReturnGold",
"Argl": "AbilityDefinitionReturnGoldLumber",
"Arll": "AbilityDefinitionRegenLifeArll",
@@ -697,11 +731,13 @@
"Arpl": "AbilityDefinitionReplenishLife",
"Arpm": "AbilityDefinitionReplenishMana",
"Arsg": "AbilityDefinitionRexxarSummonBear",
+ "Arsk": "AbilityDefinitionResistantSkin",
"Arsp": "AbilityDefinitionRexxarStampede",
"Arsq": "AbilityDefinitionRexxarSummonQuilbeast",
"Arst": "AbilityDefinitionRestoration",
"Arsw": "AbilityDefinitionRokhanSerpentWard",
"Artn": "AbilityDefinitionArtn",
+ "Asac": "AbilityDefinitionSacrificeSacrificialPit",
"Asal": "AbilityDefinitionPillage",
"Asb1": "AbilityDefinitionSubmergeMyrmidon",
"Asb2": "AbilityDefinitionSubmergeRoyalGuard",
@@ -710,13 +746,14 @@
"Asd3": "AbilityDefinitionSelfDestruct3ClockwerkGoblins",
"Asdg": "AbilityDefinitionSelfDestructClockwerkGoblins",
"Asds": "AbilityDefinitionSelfDestruct",
- "Asel": "AbilityDefinitionSellUnit",
"Ashm": "AbilityDefinitionShadowMeld",
"Ashs": "AbilityDefinitionShadowSight",
+ "Asid": "AbilityDefinitionSellItem",
"Asla": "AbilityDefinitionSleepAlways",
"Aslo": "AbilityDefinitionSlow",
"Aslp": "AbilityDefinitionSummonLobstrokPrawns",
"Asod": "AbilityDefinitionSpawnOnDeathskeleton",
+ "Asou": "AbilityDefinitionSoulPossession",
"Asp1": "AbilityDefinitionSphereSoVLevel1",
"Asp2": "AbilityDefinitionSphereSoVLevel2",
"Asp3": "AbilityDefinitionSphereSoVLevel3",
@@ -742,17 +779,21 @@
"Aste": "AbilityDefinitionManaSteal",
"Asth": "AbilityDefinitionStormHammers",
"Astn": "AbilityDefinitionStoneForm",
+ "Asud": "AbilityDefinitionSellUnit",
"Atau": "AbilityDefinitionTaunt",
"Atdg": "AbilityDefinitionTornadoDamage",
"Atdp": "AbilityDefinitionDropPilot",
"Atlp": "AbilityDefinitionLoadPilot",
+ "Atol": "AbilityDefinitionTreeOfLifeForAttachingArt",
"Atru": "AbilityDefinitionDetectShade",
"Atsp": "AbilityDefinitionTornadoSpin",
"Attu": "AbilityDefinitionTankTurret",
"Atwa": "AbilityDefinitionTornadoWander",
+ "AUa2": "AbilityDefinitionDeathKnightAnimateDead1",
"AUan": "AbilityDefinitionDeathKnightAnimateDead",
"AUau": "AbilityDefinitionDeathKnightUnholyAura",
"AUav": "AbilityDefinitionDreadlordVampiricAura",
+ "AUbu": "AbilityDefinitionBuildUndead",
"AUcb": "AbilityDefinitionCryptLordCarrionScarabs",
"Auco": "AbilityDefinitionUnstableConcoction",
"AUcs": "AbilityDefinitionDreadlordCarrionSwarm",
@@ -829,6 +870,7 @@
"AbilityDefinitionAbolishMagicNaga": "AbilityDefinition",
"AbilityDefinitionAbsorbMana": "AbilityDefinition",
"AbilityDefinitionAcha": "AbilityDefinition",
+ "AbilityDefinitionAcolyteHarvest": "AbilityDefinition",
"AbilityDefinitionAdet": "AbilityDefinition",
"AbilityDefinitionAerialShackles": "AbilityDefinition",
"AbilityDefinitionAgilityBonusPlus1": "AbilityDefinition",
@@ -911,6 +953,7 @@
"AbilityDefinitionAuraWarDrumsKodobeast": "AbilityDefinition",
"AbilityDefinitionAvatarGarithos": "AbilityDefinition",
"AbilityDefinitionAvengerForm": "AbilityDefinition",
+ "AbilityDefinitionAwaken": "AbilityDefinition",
"AbilityDefinitionBallsofFire": "AbilityDefinition",
"AbilityDefinitionBanishCreep": "AbilityDefinition",
"AbilityDefinitionBashBeastmasterBear": "AbilityDefinition",
@@ -957,6 +1000,11 @@
"AbilityDefinitionBrewmasterDrunkenBrawler": "AbilityDefinition",
"AbilityDefinitionBrewmasterDrunkenHaze": "AbilityDefinition",
"AbilityDefinitionBrewmasterStormEarthandFire": "AbilityDefinition",
+ "AbilityDefinitionBuildHuman": "AbilityDefinition",
+ "AbilityDefinitionBuildNaga": "AbilityDefinition",
+ "AbilityDefinitionBuildNeutral": "AbilityDefinition",
+ "AbilityDefinitionBuildNightElf": "AbilityDefinition",
+ "AbilityDefinitionBuildOrc": "AbilityDefinition",
"AbilityDefinitionBuildTinyAltar": "AbilityDefinition",
"AbilityDefinitionBuildTinyBarracks": "AbilityDefinition",
"AbilityDefinitionBuildTinyBlacksmith": "AbilityDefinition",
@@ -965,6 +1013,7 @@
"AbilityDefinitionBuildTinyGreatHall": "AbilityDefinition",
"AbilityDefinitionBuildTinyLumberMill": "AbilityDefinition",
"AbilityDefinitionBuildTinyScoutTower": "AbilityDefinition",
+ "AbilityDefinitionBuildUndead": "AbilityDefinition",
"AbilityDefinitionBurrow": "AbilityDefinition",
"AbilityDefinitionBurrowBarbedArachnathid": "AbilityDefinition",
"AbilityDefinitionBurrowDetectionFlyers": "AbilityDefinition",
@@ -1001,6 +1050,7 @@
"AbilityDefinitionChenDrunkenBrawler": "AbilityDefinition",
"AbilityDefinitionChenDrunkenHaze": "AbilityDefinition",
"AbilityDefinitionChenStormEarthAndFire": "AbilityDefinition",
+ "AbilityDefinitionCleavingAttackCreep": "AbilityDefinition",
"AbilityDefinitionCloudofFog": "AbilityDefinition",
"AbilityDefinitionCloudofFogItem": "AbilityDefinition",
"AbilityDefinitionColdArrows": "AbilityDefinition",
@@ -1013,6 +1063,7 @@
"AbilityDefinitionCoupleHippogryph": "AbilityDefinition",
"AbilityDefinitionCoupleInstantArcher": "AbilityDefinition",
"AbilityDefinitionCoupleInstantHippogryph": "AbilityDefinition",
+ "AbilityDefinitionCreepSleep": "AbilityDefinition",
"AbilityDefinitionCripple": "AbilityDefinition",
"AbilityDefinitionCripplecreep": "AbilityDefinition",
"AbilityDefinitionCrippleWarlock": "AbilityDefinition",
@@ -1046,6 +1097,7 @@
"AbilityDefinitionDeathDamageAOEmineBIG": "AbilityDefinition",
"AbilityDefinitionDeathDamageAOEsapper": "AbilityDefinition",
"AbilityDefinitionDeathKnightAnimateDead": "AbilityDefinition",
+ "AbilityDefinitionDeathKnightAnimateDead1": "AbilityDefinition",
"AbilityDefinitionDeathKnightDeathCoil": "AbilityDefinition",
"AbilityDefinitionDeathKnightDeathPact": "AbilityDefinition",
"AbilityDefinitionDeathKnightUnholyAura": "AbilityDefinition",
@@ -1080,13 +1132,16 @@
"AbilityDefinitionDisenchantold": "AbilityDefinition",
"AbilityDefinitionDispelMagic": "AbilityDefinition",
"AbilityDefinitionDispelMagiccreep": "AbilityDefinition",
+ "AbilityDefinitionDivineShieldCreep": "AbilityDefinition",
"AbilityDefinitionDivineShieldItem": "AbilityDefinition",
"AbilityDefinitionDrainLifeCreep": "AbilityDefinition",
"AbilityDefinitionDreadlordCarrionSwarm": "AbilityDefinition",
"AbilityDefinitionDreadlordInferno": "AbilityDefinition",
"AbilityDefinitionDreadlordSleep": "AbilityDefinition",
"AbilityDefinitionDreadlordVampiricAura": "AbilityDefinition",
+ "AbilityDefinitionDrop": "AbilityDefinition",
"AbilityDefinitionDrop1": "AbilityDefinition",
+ "AbilityDefinitionDropInstant": "AbilityDefinition",
"AbilityDefinitionDropPilot": "AbilityDefinition",
"AbilityDefinitionDustofAppearance": "AbilityDefinition",
"AbilityDefinitionEatTree": "AbilityDefinition",
@@ -1145,7 +1200,12 @@
"AbilityDefinitionFirelordSoulBurn": "AbilityDefinition",
"AbilityDefinitionFirelordSummonLavaSpawn": "AbilityDefinition",
"AbilityDefinitionFirelordVolcano": "AbilityDefinition",
+ "AbilityDefinitionFlag": "AbilityDefinition",
+ "AbilityDefinitionFlagHuman": "AbilityDefinition",
+ "AbilityDefinitionFlagNightElf": "AbilityDefinition",
+ "AbilityDefinitionFlagOrc": "AbilityDefinition",
"AbilityDefinitionFlagOrcBattleStandard": "AbilityDefinition",
+ "AbilityDefinitionFlagUndead": "AbilityDefinition",
"AbilityDefinitionFlakCannon": "AbilityDefinition",
"AbilityDefinitionFlameStrikeCreep": "AbilityDefinition",
"AbilityDefinitionFlameStrikeImprovedCreep": "AbilityDefinition",
@@ -1236,6 +1296,7 @@
"AbilityDefinitionItemChangeTOD": "AbilityDefinition",
"AbilityDefinitionItemCloakOfFlames": "AbilityDefinition",
"AbilityDefinitionItemCommand": "AbilityDefinition",
+ "AbilityDefinitionItemDamageAoe": "AbilityDefinition",
"AbilityDefinitionItemDefenseAoe": "AbilityDefinition",
"AbilityDefinitionItemDefenseAoePlusHealing": "AbilityDefinition",
"AbilityDefinitionItemDetectAoe": "AbilityDefinition",
@@ -1254,6 +1315,7 @@
"AbilityDefinitionItemInvisLesser": "AbilityDefinition",
"AbilityDefinitionItemInvulDivinity": "AbilityDefinition",
"AbilityDefinitionItemInvulLesser": "AbilityDefinition",
+ "AbilityDefinitionItemInvulNormal": "AbilityDefinition",
"AbilityDefinitionItemManaRestoreAoe": "AbilityDefinition",
"AbilityDefinitionItemManaRestoreGreater": "AbilityDefinition",
"AbilityDefinitionItemManaRestoreLesser": "AbilityDefinition",
@@ -1268,6 +1330,8 @@
"AbilityDefinitionItemRestore": "AbilityDefinition",
"AbilityDefinitionItemRestoreAoe": "AbilityDefinition",
"AbilityDefinitionItemRevealMap": "AbilityDefinition",
+ "AbilityDefinitionItemRitualDaggerInstant": "AbilityDefinition",
+ "AbilityDefinitionItemRitualDaggerRegen": "AbilityDefinition",
"AbilityDefinitionItemSpeed": "AbilityDefinition",
"AbilityDefinitionItemSpeedAoe": "AbilityDefinition",
"AbilityDefinitionItemTownPortal": "AbilityDefinition",
@@ -1323,8 +1387,11 @@
"AbilityDefinitionMaxManaBonusLeastest": "AbilityDefinition",
"AbilityDefinitionMaxManaBonusLeastestReally": "AbilityDefinition",
"AbilityDefinitionMaxManaBonusMost": "AbilityDefinition",
+ "AbilityDefinitionMeatDrop": "AbilityDefinition",
+ "AbilityDefinitionMeatLoad": "AbilityDefinition",
"AbilityDefinitionMechanicalCritter": "AbilityDefinition",
"AbilityDefinitionMilitia": "AbilityDefinition",
+ "AbilityDefinitionMilitiaConversion": "AbilityDefinition",
"AbilityDefinitionMindRot": "AbilityDefinition",
"AbilityDefinitionMine": "AbilityDefinition",
"AbilityDefinitionMonsoon": "AbilityDefinition",
@@ -1355,6 +1422,7 @@
"AbilityDefinitionOnFireOrc": "AbilityDefinition",
"AbilityDefinitionOnFireUndead": "AbilityDefinition",
"AbilityDefinitionOrbofAnnihilation": "AbilityDefinition",
+ "AbilityDefinitionOrbOfAnnihilationQuillSpray": "AbilityDefinition",
"AbilityDefinitionOrbofCorruption": "AbilityDefinition",
"AbilityDefinitionOrbofDarkness": "AbilityDefinition",
"AbilityDefinitionOrbofDarknessBlackArrow": "AbilityDefinition",
@@ -1425,6 +1493,7 @@
"AbilityDefinitionPreservation": "AbilityDefinition",
"AbilityDefinitionPulverize": "AbilityDefinition",
"AbilityDefinitionPulverizecreep": "AbilityDefinition",
+ "AbilityDefinitionPurchaseItem": "AbilityDefinition",
"AbilityDefinitionPurge": "AbilityDefinition",
"AbilityDefinitionPurgeApg2": "AbilityDefinition",
"AbilityDefinitionPurgeCreep": "AbilityDefinition",
@@ -1439,6 +1508,7 @@
"AbilityDefinitionRaiseDead": "AbilityDefinition",
"AbilityDefinitionRaiseDeadCreep": "AbilityDefinition",
"AbilityDefinitionRaiseDeadItem": "AbilityDefinition",
+ "AbilityDefinitionRally": "AbilityDefinition",
"AbilityDefinitionRangerColdArrows": "AbilityDefinition",
"AbilityDefinitionRavenFormDruidoftheTalon": "AbilityDefinition",
"AbilityDefinitionRavenFormMedivh": "AbilityDefinition",
@@ -1460,6 +1530,7 @@
"AbilityDefinitionReplenishMana": "AbilityDefinition",
"AbilityDefinitionResistantSkin": "AbilityDefinition",
"AbilityDefinitionResistantSkin31PosCreep": "AbilityDefinition",
+ "AbilityDefinitionResistantSkinCreep": "AbilityDefinition",
"AbilityDefinitionRestoration": "AbilityDefinition",
"AbilityDefinitionResurrection": "AbilityDefinition",
"AbilityDefinitionResurrectionItem": "AbilityDefinition",
@@ -1469,6 +1540,7 @@
"AbilityDefinitionReturnLumber": "AbilityDefinition",
"AbilityDefinitionRevealArcaneTower": "AbilityDefinition",
"AbilityDefinitionRevenge": "AbilityDefinition",
+ "AbilityDefinitionRevive": "AbilityDefinition",
"AbilityDefinitionRexxarStampede": "AbilityDefinition",
"AbilityDefinitionRexxarStormBolt": "AbilityDefinition",
"AbilityDefinitionRexxarSummonBear": "AbilityDefinition",
@@ -1495,6 +1567,8 @@
"AbilityDefinitionRuneOfTheWatcher": "AbilityDefinition",
"AbilityDefinitionRuneRestoreAoe": "AbilityDefinition",
"AbilityDefinitionRuneSpeedAoe": "AbilityDefinition",
+ "AbilityDefinitionSacrificeAcolyte": "AbilityDefinition",
+ "AbilityDefinitionSacrificeSacrificialPit": "AbilityDefinition",
"AbilityDefinitionSanctuary": "AbilityDefinition",
"AbilityDefinitionScrollofLifeRegen": "AbilityDefinition",
"AbilityDefinitionScrollofRejuvI": "AbilityDefinition",
@@ -1509,6 +1583,7 @@
"AbilityDefinitionSelfDestruct2ClockwerkGoblins": "AbilityDefinition",
"AbilityDefinitionSelfDestruct3ClockwerkGoblins": "AbilityDefinition",
"AbilityDefinitionSelfDestructClockwerkGoblins": "AbilityDefinition",
+ "AbilityDefinitionSellItem": "AbilityDefinition",
"AbilityDefinitionSellUnit": "AbilityDefinition",
"AbilityDefinitionSentinel": "AbilityDefinition",
"AbilityDefinitionSentinelNoResearch": "AbilityDefinition",
@@ -1518,9 +1593,11 @@
"AbilityDefinitionShadowHunterHealingWave": "AbilityDefinition",
"AbilityDefinitionShadowHunterHex": "AbilityDefinition",
"AbilityDefinitionShadowHunterSerpentWard": "AbilityDefinition",
+ "AbilityDefinitionShadowHunterVoodooo": "AbilityDefinition",
"AbilityDefinitionShadowMeld": "AbilityDefinition",
"AbilityDefinitionShadowMeldAkama": "AbilityDefinition",
"AbilityDefinitionShadowMeldInstant": "AbilityDefinition",
+ "AbilityDefinitionShadowMeldItem": "AbilityDefinition",
"AbilityDefinitionShadowOrbAbility": "AbilityDefinition",
"AbilityDefinitionShadowSight": "AbilityDefinition",
"AbilityDefinitionShadowStrikeCreep": "AbilityDefinition",
@@ -1536,10 +1613,13 @@
"AbilityDefinitionSleepcreep": "AbilityDefinition",
"AbilityDefinitionSlow": "AbilityDefinition",
"AbilityDefinitionSlow1": "AbilityDefinition",
+ "AbilityDefinitionSlow2": "AbilityDefinition",
"AbilityDefinitionSlowAIos": "AbilityDefinition",
"AbilityDefinitionSlowCreep": "AbilityDefinition",
"AbilityDefinitionSlowPoison": "AbilityDefinition",
"AbilityDefinitionSlowPoisonItem": "AbilityDefinition",
+ "AbilityDefinitionSoulPossession": "AbilityDefinition",
+ "AbilityDefinitionSoulTrap": "AbilityDefinition",
"AbilityDefinitionSpawnHydra": "AbilityDefinition",
"AbilityDefinitionSpawnHydraHatchling": "AbilityDefinition",
"AbilityDefinitionSpawnOnDeathskeleton": "AbilityDefinition",
@@ -1590,6 +1670,7 @@
"AbilityDefinitionTaurenChieftainReincarnation": "AbilityDefinition",
"AbilityDefinitionTaurenChieftainShockWave": "AbilityDefinition",
"AbilityDefinitionTaurenChieftainWarStomp": "AbilityDefinition",
+ "AbilityDefinitionThornsAuraCreep": "AbilityDefinition",
"AbilityDefinitionThornyShieldCreep": "AbilityDefinition",
"AbilityDefinitionThornyShieldDragonTurtle": "AbilityDefinition",
"AbilityDefinitionThunderBoltCreep": "AbilityDefinition",
@@ -1617,6 +1698,7 @@
"AbilityDefinitionTornadoDamage": "AbilityDefinition",
"AbilityDefinitionTornadoSpin": "AbilityDefinition",
"AbilityDefinitionTornadoWander": "AbilityDefinition",
+ "AbilityDefinitionTreeOfLifeForAttachingArt": "AbilityDefinition",
"AbilityDefinitionUltravision": "AbilityDefinition",
"AbilityDefinitionUltraVisionGlyph": "AbilityDefinition",
"AbilityDefinitionUnholyAuracreep": "AbilityDefinition",
@@ -5355,8 +5437,8 @@
"setMorphingFlags",
true,
false,
- "String",
- "string"
+ "Int",
+ "int"
],
"Eme3:3": [
"setAltitudeAdjustmentDuration",
@@ -5932,8 +6014,8 @@
"setAttacksPrevented",
true,
false,
- "String",
- "string"
+ "Int",
+ "int"
],
"Nsi2:2": [
"setChanceToMiss",
@@ -5966,6 +6048,15 @@
"string"
]
},
+ "AbilityDefinitionCleavingAttackCreep": {
+ "nca1:1": [
+ "setDistributedDamageFactor",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ]
+ },
"AbilityDefinitionCloudofFog": {
"Nsi1:1": [
"setAttacksPrevented",
@@ -6052,8 +6143,8 @@
"setStackFlags",
true,
false,
- "String",
- "string"
+ "Int",
+ "int"
]
},
"AbilityDefinitionColdArrowscreep": {
@@ -7085,6 +7176,29 @@
"bool"
]
},
+ "AbilityDefinitionDeathKnightAnimateDead1": {
+ "Hre2:2": [
+ "setRaisedUnitsAreInvulnerable",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ],
+ "Uan1:1": [
+ "setNumberofCorpsesRaised",
+ true,
+ false,
+ "Int",
+ "int"
+ ],
+ "Uan3:3": [
+ "setInheritUpgrades",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionDeathKnightDeathCoil": {
"Udc1:1": [
"setAmountHealedDamaged",
@@ -7734,6 +7848,15 @@
"real"
]
},
+ "AbilityDefinitionDivineShieldCreep": {
+ "Hds1:1": [
+ "setCanDeactivate",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionDivineShieldItem": {
"Hds1:1": [
"setCanDeactivate",
@@ -11382,6 +11505,15 @@
"bool"
]
},
+ "AbilityDefinitionItemInvulNormal": {
+ "AIvu:1": [
+ "setData",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionItemManaRestoreAoe": {
"Impg:1": [
"setManaPointsGained",
@@ -11569,6 +11701,80 @@
"string"
]
},
+ "AbilityDefinitionItemRitualDaggerInstant": {
+ "Idg1:2": [
+ "setData",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ],
+ "Idg2:3": [
+ "setData1",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ],
+ "Idg3:8": [
+ "setData2",
+ true,
+ false,
+ "String",
+ "string"
+ ],
+ "Ihpg:1": [
+ "setHitPointsGained",
+ true,
+ false,
+ "Int",
+ "int"
+ ],
+ "Udp5:5": [
+ "setLeaveTargetAlive",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
+ "AbilityDefinitionItemRitualDaggerRegen": {
+ "Idg1:2": [
+ "setData",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ],
+ "Idg2:3": [
+ "setData1",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ],
+ "Idg3:8": [
+ "setData2",
+ true,
+ false,
+ "String",
+ "string"
+ ],
+ "Ihpg:1": [
+ "setHitPointsGained",
+ true,
+ false,
+ "Int",
+ "int"
+ ],
+ "Udp5:5": [
+ "setLeaveTargetAlive",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionItemSpeed": {
"Ispi:1": [
"setMovementSpeedIncrease",
@@ -13037,6 +13243,43 @@
"real"
]
},
+ "AbilityDefinitionOrbOfAnnihilationQuillSpray": {
+ "fak1:1": [
+ "setDamageBonus",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "fak2:2": [
+ "setMediumDamageFactor",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "fak3:3": [
+ "setSmallDamageFactor",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "fak4:4": [
+ "setFullDamageRadius",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "fak5:5": [
+ "setHalfDamageRadius",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ]
+ },
"AbilityDefinitionOrbofCorruption": {
"Iarp:2": [
"setArmorPenalty",
@@ -13439,8 +13682,8 @@
"setStackingType",
true,
false,
- "String",
- "string"
+ "Int",
+ "int"
]
},
"AbilityDefinitionPenguinSqueek": {
@@ -16854,6 +17097,36 @@
"bool"
]
},
+ "AbilityDefinitionShadowMeldItem": {
+ "Shm1:1": [
+ "setFadeDuration",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Shm2:2": [
+ "setDayNightDuration",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Shm3:3": [
+ "setActionDuration",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Shm4:4": [
+ "setPermanentCloak",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionShadowOrbAbility": {
"Idam:1": [
"setDamageBonus",
@@ -17246,6 +17519,29 @@
"bool"
]
},
+ "AbilityDefinitionSlow2": {
+ "Slo1:1": [
+ "setMovementSpeedFactor",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Slo2:2": [
+ "setAttackSpeedFactor",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Slo3:3": [
+ "setAlwaysAutocast",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionSlowAIos": {
"Slo1:1": [
"setMovementSpeedFactor",
@@ -17348,8 +17644,8 @@
"setStackingType",
true,
false,
- "String",
- "string"
+ "Int",
+ "int"
]
},
"AbilityDefinitionSpawnHydra": {
@@ -18210,6 +18506,22 @@
"real"
]
},
+ "AbilityDefinitionThornsAuraCreep": {
+ "Eah1:1": [
+ "setDamageDealttoAttackers",
+ true,
+ false,
+ "Unreal",
+ "real"
+ ],
+ "Eah2:2": [
+ "setDamageisPercentReceived",
+ true,
+ true,
+ "Boolean",
+ "bool"
+ ]
+ },
"AbilityDefinitionThornyShieldCreep": {
"Uts1:1": [
"setReturnedDamageFactor",
diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ExportToWurstTest.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ExportToWurstTest.java
index 28828e238..5eebb70b4 100644
--- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ExportToWurstTest.java
+++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ExportToWurstTest.java
@@ -117,6 +117,154 @@ public void abilityWithKnownBaseIdUsesWrapperClass() throws IOException {
"Should not fall back to raw format for known base ID");
}
+ @Test
+ public void abilityAliasBaseIdsUseAliasSpecificWrapperClasses() throws IOException {
+ Object[][] cases = {
+ {"A9C1", "ACce", "AbilityDefinitionCleavingAttackCreep", "AbilityDefinitionPitLordCleavingAttack",
+ "nca1", ObjMod.ValType.UNREAL, 1, 1, 0.25, "..setDistributedDamageFactor(1, 0.25)"},
+ {"A9C2", "ACds", "AbilityDefinitionDivineShieldCreep", "AbilityDefinitionPaladinDivineShield",
+ "Hds1", ObjMod.ValType.INT, 1, 1, 1, "..setCanDeactivate(1, true)"},
+ {"A9C3", "ANak", "AbilityDefinitionOrbOfAnnihilationQuillSpray", "AbilityDefinitionOrbofAnnihilation",
+ "fak1", ObjMod.ValType.UNREAL, 1, 1, 15.0, "..setDamageBonus(1, 15.0)"},
+ {"A9C4", "AIhm", "AbilityDefinitionShadowMeldItem", "AbilityDefinitionShadowMeld",
+ "Shm1", ObjMod.ValType.UNREAL, 1, 1, 1.5, "..setFadeDuration(1, 1.5)"},
+ {"A9C5", "ACah", "AbilityDefinitionThornsAuraCreep", "AbilityDefinitionKeeperoftheGroveThornsAura",
+ "Eah1", ObjMod.ValType.UNREAL, 1, 1, 0.1, "..setDamageDealttoAttackers(1, 0.1)"}
+ };
+
+ for (Object[] c : cases) {
+ W3A w3a = new W3A();
+ String newId = (String) c[0];
+ String baseId = (String) c[1];
+ String expectedClass = (String) c[2];
+ String implementationCodeClass = (String) c[3];
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf(newId), ObjId.valueOf(baseId));
+ addLvlMod(obj, (String) c[4], (ObjMod.ValType) c[5], (int) c[6], (int) c[7], c[8]);
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains("new " + expectedClass + "('" + newId + "')"), baseId + " export:\n" + out);
+ assertTrue(out.contains((String) c[9]), baseId + " export:\n" + out);
+ assertFalse(out.contains("new " + implementationCodeClass + "("), baseId + " must not export via implementation-code class:\n" + out);
+ assertFalse(out.contains("createObjectDefinition"), baseId + " must not fall back to raw export:\n" + out);
+ assertExportCompiles(out, "import AbilityObjEditing");
+ }
+ }
+
+ @Test
+ public void abilityCoverageGapsFromPristineExportUseTypedWrappers() throws IOException {
+ W3A w3a = new W3A();
+ W3A.Obj resistantSkin = w3a.addObj(ObjId.valueOf("A07B"), ObjId.valueOf("Arsk"));
+ addLvlMod(resistantSkin, "arac", ObjMod.ValType.STRING, 0, 0, "human");
+ addLvlMod(resistantSkin, "areq", ObjMod.ValType.STRING, 0, 0, "");
+
+ String resistantSkinOut = export(resistantSkin, ObjectFileType.ABILITIES);
+
+ assertTrue(resistantSkinOut.contains("new AbilityDefinitionResistantSkin('A07B')"), resistantSkinOut);
+ assertTrue(resistantSkinOut.contains("..setRace(Race.Human)"), resistantSkinOut);
+ assertTrue(resistantSkinOut.contains("..setRequirements(\"\")"), resistantSkinOut);
+ assertFalse(resistantSkinOut.contains("createObjectDefinition"), resistantSkinOut);
+
+ W3A.Obj undeadBuild = w3a.addObj(ObjId.valueOf("AUbu"), null);
+ addLvlMod(undeadBuild, "aart", ObjMod.ValType.STRING, 0, 0,
+ "ReplaceableTextures\\CommandButtons\\BTNAdvStruct.blp");
+
+ String undeadBuildOut = export(undeadBuild, ObjectFileType.ABILITIES);
+
+ assertTrue(undeadBuildOut.contains("new AbilityDefinitionBuildUndead('AUbu')"), undeadBuildOut);
+ assertTrue(undeadBuildOut.contains("..setIconNormal(\"ReplaceableTextures\\\\CommandButtons\\\\BTNAdvStruct.blp\")"), undeadBuildOut);
+ assertFalse(undeadBuildOut.contains("createObjectDefinition"), undeadBuildOut);
+
+ W3A.Obj rally = w3a.addObj(ObjId.valueOf("ARal"), null);
+ addLvlMod(rally, "anam", ObjMod.ValType.STRING, 0, 0, "Sync");
+ addLvlMod(rally, "atp1", ObjMod.ValType.STRING, 0, 0, "");
+
+ String rallyOut = export(rally, ObjectFileType.ABILITIES);
+
+ assertTrue(rallyOut.contains("new AbilityDefinitionRally('ARal')"), rallyOut);
+ assertTrue(rallyOut.contains("..setName(\"Sync\")"), rallyOut);
+ assertTrue(rallyOut.contains("..setTooltipNormal(0, \"\")"), rallyOut);
+ assertFalse(rallyOut.contains("createObjectDefinition"), rallyOut);
+ }
+
+ @Test
+ public void abilityDataBaseIdsHaveWrapperCoverageForPreviouslyMissingRows() throws IOException {
+ Object[][] cases = {
+ {"AOvd", "AbilityDefinitionShadowHunterVoodooo"},
+ {"Aaha", "AbilityDefinitionAcolyteHarvest"},
+ {"Aawa", "AbilityDefinitionAwaken"},
+ {"ANbu", "AbilityDefinitionBuildNeutral"},
+ {"AHbu", "AbilityDefinitionBuildHuman"},
+ {"AObu", "AbilityDefinitionBuildOrc"},
+ {"AEbu", "AbilityDefinitionBuildNightElf"},
+ {"AGbu", "AbilityDefinitionBuildNaga"},
+ {"ACsp", "AbilityDefinitionCreepSleep"},
+ {"Adri", "AbilityDefinitionDropInstant"},
+ {"Adro", "AbilityDefinitionDrop"},
+ {"Amed", "AbilityDefinitionMeatDrop"},
+ {"Amel", "AbilityDefinitionMeatLoad"},
+ {"Amic", "AbilityDefinitionMilitiaConversion"},
+ {"Apit", "AbilityDefinitionPurchaseItem"},
+ {"Arev", "AbilityDefinitionRevive"},
+ {"Asac", "AbilityDefinitionSacrificeSacrificialPit"},
+ {"Alam", "AbilityDefinitionSacrificeAcolyte"},
+ {"Asid", "AbilityDefinitionSellItem"},
+ {"Asud", "AbilityDefinitionSellUnit"},
+ {"Atol", "AbilityDefinitionTreeOfLifeForAttachingArt"},
+ {"AIfl", "AbilityDefinitionFlag"},
+ {"AIfm", "AbilityDefinitionFlagHuman"},
+ {"AIfo", "AbilityDefinitionFlagOrc"},
+ {"AIfn", "AbilityDefinitionFlagNightElf"},
+ {"AIfe", "AbilityDefinitionFlagUndead"},
+ {"AIso", "AbilityDefinitionSoulTrap"},
+ {"Asou", "AbilityDefinitionSoulPossession"},
+ {"AIdm", "AbilityDefinitionItemDamageAoe"},
+ {"AIvu", "AbilityDefinitionItemInvulNormal"},
+ {"AIdg", "AbilityDefinitionItemRitualDaggerInstant"},
+ {"AIg2", "AbilityDefinitionItemRitualDaggerRegen"},
+ {"AIno", "AbilityDefinitionSlow2"},
+ {"AUa2", "AbilityDefinitionDeathKnightAnimateDead1"}
+ };
+
+ for (int i = 0; i < cases.length; i++) {
+ W3A w3a = new W3A();
+ String baseId = (String) cases[i][0];
+ String expectedClass = (String) cases[i][1];
+ String newId = String.format("Z%03d", i);
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf(newId), ObjId.valueOf(baseId));
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains("new " + expectedClass + "('" + newId + "')"), baseId + " export:\n" + out);
+ assertFalse(out.contains("createObjectDefinition"), baseId + " must not fall back to raw export:\n" + out);
+ }
+ }
+
+ @Test
+ public void abilityDataBaseIdsWithSpecificFieldsUseTypedSetters() throws IOException {
+ Object[][] cases = {
+ {"AIvu", "AIvu", ObjMod.ValType.INT, 1, 1, 1, "..setData(1, true)"},
+ {"AIdg", "Idg1", ObjMod.ValType.INT, 1, 2, 1, "..setData(1, true)"},
+ {"AIg2", "Ihpg", ObjMod.ValType.INT, 1, 1, 50, "..setHitPointsGained(1, 50)"},
+ {"AIno", "Slo1", ObjMod.ValType.UNREAL, 1, 1, 0.5, "..setMovementSpeedFactor(1, 0.5)"},
+ {"AUa2", "Uan1", ObjMod.ValType.INT, 1, 1, 6, "..setNumberofCorpsesRaised(1, 6)"}
+ };
+
+ for (int i = 0; i < cases.length; i++) {
+ W3A w3a = new W3A();
+ String baseId = (String) cases[i][0];
+ String newId = String.format("Y%03d", i);
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf(newId), ObjId.valueOf(baseId));
+ addLvlMod(obj, (String) cases[i][1], (ObjMod.ValType) cases[i][2],
+ (int) cases[i][3], (int) cases[i][4], cases[i][5]);
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains((String) cases[i][6]), baseId + " export:\n" + out);
+ assertFalse(out.contains("createObjectDefinition"), baseId + " must not fall back to raw export:\n" + out);
+ }
+ }
+
@Test
public void abilityWrapperIncludesAllKnownFields() throws IOException {
W3A w3a = new W3A();
@@ -225,6 +373,36 @@ public void abilityEnumFieldEmitsEnumConstantAndCompiles() throws IOException {
assertExportCompiles(out, "import AbilityObjEditing");
}
+ @Test
+ public void abilityUnknownEnumFieldFallsBackToRawObjectExport() throws IOException {
+ W3A w3a = new W3A();
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf("A01O"), ObjId.valueOf("Aslo"));
+ addLvlMod(obj, "arac", ObjMod.ValType.STRING, 0, 0, "not-a-race");
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains("createObjectDefinition(\"w3a\", 'A01O', 'Aslo')"), out);
+ assertTrue(out.contains("..setLvlDataString(\"arac\", 0, 0, \"not-a-race\")"), out);
+ assertFalse(out.contains("new AbilityDefinitionSlow('A01O')"), out);
+ assertFalse(out.contains("// TODO no wrapper:"), out);
+ }
+
+ @Test
+ public void abilityUnsupportedMappedWrapperParameterFallsBackToRawExport() throws IOException {
+ W3A w3a = new W3A();
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf("A0RJ"), ObjId.valueOf("Arej"));
+ addLvlMod(obj, "acdn", ObjMod.ValType.UNREAL, 1, 0, 4.0);
+ addLvlMod(obj, "Rej3", ObjMod.ValType.INT, 1, 3, 1);
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains("createObjectDefinition(\"w3a\", 'A0RJ', 'Arej')"), out);
+ assertTrue(out.contains("..setLvlDataUnreal(\"acdn\", 1, 0, 4.0)"), out);
+ assertTrue(out.contains("..setLvlDataInt(\"Rej3\", 1, 3, 1)"), out);
+ assertFalse(out.contains("new AbilityDefinitionRejuvination('A0RJ')"), out);
+ assertFalse(out.contains("// TODO no wrapper:"), out);
+ }
+
// -------------------------------------------------------------------------
// Unit (w3u)
// -------------------------------------------------------------------------
@@ -291,15 +469,16 @@ public void unitEnumFieldsEmitEnumConstantsAndCompile() throws IOException {
}
@Test
- public void emptyEnumValueFallsBackToRawExportAndCompiles() throws IOException {
+ public void emptyWeaponSoundEnumValueKeepsTypedExportAndCompiles() throws IOException {
W3U w3u = new W3U();
W3U.Obj obj = w3u.addObj(ObjId.valueOf("n011"), ObjId.valueOf("hfoo"));
addMod(obj, "ucs1", ObjMod.ValType.STRING, "");
String out = export(obj, ObjectFileType.UNITS);
- assertTrue(out.contains("createObjectDefinition(\"w3u\", 'n011', 'hfoo')"), out);
- assertTrue(out.contains("..setString(\"ucs1\", \"\")"), out);
+ assertTrue(out.contains("new UnitDefinition('n011', 'hfoo')"), out);
+ assertTrue(out.contains("..setAttack1WeaponSound(WeaponSound.Nothing)"), out);
+ assertFalse(out.contains("createObjectDefinition"), out);
assertExportCompiles(out, "import UnitObjEditing");
}
@@ -476,7 +655,7 @@ public void parasiteEredarInheritsParentFields() throws IOException {
W3A.Obj obj = w3a.addObj(ObjId.valueOf("A017"), ObjId.valueOf("ACpa"));
addLvlMod(obj, "Npa6", ObjMod.ValType.UNREAL, 1, 0, 0.01);
addLvlMod(obj, "Poi1", ObjMod.ValType.UNREAL, 1, 1, 0.0);
- addLvlMod(obj, "Poi4", ObjMod.ValType.STRING, 1, 4, "0");
+ addLvlMod(obj, "Poi4", ObjMod.ValType.INT, 1, 4, 0);
addLvlMod(obj, "ipmu", ObjMod.ValType.STRING, 1, 0, "nfbr");
String out = export(obj, ObjectFileType.ABILITIES);
@@ -485,6 +664,32 @@ public void parasiteEredarInheritsParentFields() throws IOException {
"ACpa should use wrapper, not raw fallback");
assertFalse(out.contains("// TODO no wrapper"),
"All ACpa fields should be mapped via inheritance, got:\n" + out);
+ assertTrue(out.contains("..setStackingType(1, 0)"), out);
+ assertExportCompiles(out, "import AbilityObjEditing");
+ }
+
+ @Test
+ public void abilityIntegerLevelFieldsWithWrapperMethodsCompile() throws IOException {
+ Object[][] cases = {
+ // baseId, fieldId, dataPtr, wrapper class, setter method, newId
+ {"ACpa", "Poi4", 4, "AbilityDefinitionParasiteEredar", "setStackingType", "Zp04"},
+ {"AIsz", "Spo4", 4, "AbilityDefinitionSlowPoisonItem", "setStackingType", "Zs04"},
+ {"Abu5", "Eme2", 2, "AbilityDefinitionBurrowBarbedArachnathid", "setMorphingFlags", "Ze02"},
+ {"Acdh", "Nsi1", 1, "AbilityDefinitionChenDrunkenHaze", "setAttacksPrevented", "Zn01"},
+ {"AHca", "Hca4", 4, "AbilityDefinitionRangerColdArrows", "setStackFlags", "Zh04"},
+ };
+
+ for (Object[] c : cases) {
+ W3A w3a = new W3A();
+ W3A.Obj obj = w3a.addObj(ObjId.valueOf((String) c[5]), ObjId.valueOf((String) c[0]));
+ addLvlMod(obj, (String) c[1], ObjMod.ValType.INT, 1, (int) c[2], 0);
+
+ String out = export(obj, ObjectFileType.ABILITIES);
+
+ assertTrue(out.contains("new " + c[3] + "('" + c[5] + "')"), out);
+ assertTrue(out.contains(".." + c[4] + "(1, 0)"), out);
+ assertExportCompiles(out, "import AbilityObjEditing");
+ }
}
// -------------------------------------------------------------------------
diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java
index f67c1d19e..8933d24f7 100644
--- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java
+++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java
@@ -186,8 +186,6 @@ public void testStdLib() throws IOException {
assertTrue(compiled.contains("MagicFunctions_compiletime"));
assertTrue(compiled.contains("function __wurst_InitHashtable("));
assertTrue(compiled.contains("function __wurst_SaveInteger("));
- assertTrue(compiled.contains("function __wurst_LoadInteger("));
- assertFunctionBodyContains(compiled, "__wurst_LoadInteger", "return 0", true);
}
@Test
diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java
index 0f22679d2..6a4dc9b1d 100644
--- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java
+++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java
@@ -23,7 +23,7 @@ public class StdLib {
/**
* version to use for the tests
*/
- private final static String version = "85f9debf4f53207e1ffcc23ce2bf5e759a07ba06";
+ private final static String version = "16729fa07197bdc331dc5e30eb0f91d444eece85";
/**
* flag so that initialization in only done once