Update with some jass changes and a config file for using my high resolution test assets

This commit is contained in:
Retera 2021-07-31 09:58:53 -04:00
parent a4b5da5af0
commit 4753bc1555
20 changed files with 764 additions and 158 deletions

View File

@ -1,5 +1,5 @@
[DataSources] [DataSources]
Count=8 Count=9
Type00=MPQ Type00=MPQ
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq" Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
Type01=MPQ Type01=MPQ
@ -8,48 +8,13 @@ Type02=MPQ
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq" Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
Type03=MPQ Type03=MPQ
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq" Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
Type04=Folder Type04=MPQ
Path04="..\..\resources" Path04="D:\Games\Warcraft III Patch 1.22\Warsmash\War3Mod.mpq"
Type05=Folder Type05=Folder
Path05="D:\Backups\Warsmash\Data" Path05="..\..\resources"
Type06=Folder Type06=Folder
Path06="D:\Games\Warcraft III Patch 1.22\Maps" Path06="D:\Backups\Warsmash\Data"
Type07=Folder Type07=Folder
Path07="." Path07="D:\Games\Warcraft III Patch 1.22\Maps"
Type08=MPQ Type08=Folder
Path08="C:\Users\micro\Downloads\Warcraft III All In One\war3g.exe" Path08="."
[Map]
//FilePath="CombatUnitTests.w3x"
//FilePath="PitchRoll.w3x"
//FilePath="PeonStartingBase_Simple.w3x"
FilePath="PeonStartingBase_Scythe.w3x"
//FilePath="MyStromguarde.w3m"
//FilePath="ColdArrows.w3m"
//FilePath="DungeonGoldMine.w3m"
//FilePath="PlayerPeasants.w3m"
//FilePath="FireLord.w3x"
//FilePath="Maps\Campaign\NightElf03.w3m"
//FilePath="PhoenixAttack.w3x"
//FilePath="LightEnvironmentTest.w3x"
//FilePath="TorchLight2.w3x"
//FilePath="OrcAssault.w3x"
//FilePath="FrostyVsFarm.w3m"
//FilePath="ModelTest.w3x"
//FilePath="SpinningSample.w3x"
//FilePath="Maps\Campaign\Prologue02.w3m"
//FilePath="Pathing.w3x"
//FilePath="ItemFacing.w3x"
//FilePath=SomeParticleTests.w3x
//FilePath="PeonMiningMultiHall.w3x"
//FilePath="QuadtreeBugs.w3x"
//FilePath="test2.w3x"
//FilePath="FarseerHoldPositionTest.w3x"
//FilePath="Ramps.w3m"
//FilePath="V1\Farm.w3x"
//FilePath="PenguinWorld.w3x"
//FilePath="Maps\FrozenThrone\Campaign\UndeadX09.w3x"
//FilePath="LavellaLagoon.w3x"
//FilePath="WiceOrc.w3x"
//FilePath="NorthrendPathingDoodle.w3x"
//FilePath="Maps\Campaign\Prologue01.w3m"

View File

@ -0,0 +1,47 @@
[DataSources]
Count=5
Type00=Folder
Path00="D:\Backups\Warcraft\Data\HiResFlat"
Type01=Folder
Path01="..\..\resources"
Type02=Folder
Path02="D:\Backups\Warsmash\Data"
Type03=Folder
Path03="D:\Games\Warcraft III Patch 1.22\Maps"
Type04=Folder
Path04="."
[Map]
//FilePath="CombatUnitTests.w3x"
//FilePath="PitchRoll.w3x"
//FilePath="PeonStartingBase_Simple.w3x"
FilePath="PeonStartingBase_Scythe.w3x"
//FilePath="MyStromguarde.w3m"
//FilePath="ColdArrows.w3m"
//FilePath="DungeonGoldMine.w3m"
//FilePath="PlayerPeasants.w3m"
//FilePath="FireLord.w3x"
//FilePath="Maps\Campaign\NightElf03.w3m"
//FilePath="PhoenixAttack.w3x"
//FilePath="LightEnvironmentTest.w3x"
//FilePath="TorchLight2.w3x"
//FilePath="OrcAssault.w3x"
//FilePath="FrostyVsFarm.w3m"
//FilePath="ModelTest.w3x"
//FilePath="SpinningSample.w3x"
//FilePath="Maps\Campaign\Prologue02.w3m"
//FilePath="Pathing.w3x"
//FilePath="ItemFacing.w3x"
//FilePath=SomeParticleTests.w3x
//FilePath="PeonMiningMultiHall.w3x"
//FilePath="QuadtreeBugs.w3x"
//FilePath="test2.w3x"
//FilePath="FarseerHoldPositionTest.w3x"
//FilePath="Ramps.w3m"
//FilePath="V1\Farm.w3x"
//FilePath="PenguinWorld.w3x"
//FilePath="Maps\FrozenThrone\Campaign\UndeadX09.w3x"
//FilePath="LavellaLagoon.w3x"
//FilePath="WiceOrc.w3x"
//FilePath="NorthrendPathingDoodle.w3x"
//FilePath="Maps\Campaign\Prologue01.w3m"

View File

@ -2408,6 +2408,96 @@ public class Jass2 {
return new HandleJassValue(unitType, ((CommonTriggerExecutionScope) triggerScope).getLeavingUnit()); return new HandleJassValue(unitType, ((CommonTriggerExecutionScope) triggerScope).getLeavingUnit());
} }
}); });
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterTrackableHitEvent",
new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException(
"TriggerRegisterTrackableHitEvent not yet implemented ???");
// dont feel like implementing this atm, although it probably wouldnt be that
// hard to do
}
});
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterTrackableTrackEvent",
new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException(
"TriggerRegisterTrackableTrackEvent not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetTriggeringTrackable", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetTriggeringTrackable not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetClickedButton", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetClickedButton not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetClickedDialog", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetClickedDialog not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetTournamentFinishSoonTimeRemaining",
new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException(
"GetTournamentFinishSoonTimeRemaining not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetTournamentFinishNowRule", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetTournamentFinishNowRule not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetTournamentFinishNowPlayer", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetTournamentFinishNowPlayer not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetTournamentScore", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetTournamentScore not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetSaveBasicFilename", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
throw new UnsupportedOperationException("GetSaveBasicFilename not yet implemented ???");
}
});
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterPlayerEvent", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final Trigger whichTrigger = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final CPlayerJass whichPlayer = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
final JassGameEventsWar3 whichPlayerEvent = arguments.get(2)
.visit(ObjectJassValueVisitor.getInstance());
return new HandleJassValue(eventType,
whichPlayer.addEvent(globalScope, whichTrigger, whichPlayerEvent));
}
});
} }
private void registerConfigNatives(final JassProgramVisitor jassProgramVisitor, final War3MapConfig mapConfig, private void registerConfigNatives(final JassProgramVisitor jassProgramVisitor, final War3MapConfig mapConfig,

View File

@ -1,47 +1,139 @@
package com.etheller.warsmash.parsers.jass.scope; package com.etheller.warsmash.parsers.jass.scope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope; import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegion; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegion;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimerJass; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimerJass;
public class CommonTriggerExecutionScope extends TriggerExecutionScope { public class CommonTriggerExecutionScope extends TriggerExecutionScope {
private final CUnit triggeringUnit; private CUnit triggeringUnit;
private final CUnit filterUnit; private CUnit filterUnit;
private final CUnit enumUnit; private CUnit enumUnit;
private final CDestructable filterDestructable; private CDestructable filterDestructable;
private final CDestructable enumDestructable; private CDestructable enumDestructable;
private final CItem filterItem; private CItem filterItem;
private final CItem enumItem; private CItem enumItem;
private final CPlayerJass filterPlayer; private CPlayerJass filterPlayer;
private final CPlayerJass enumPlayer; private CPlayerJass enumPlayer;
private final CTimerJass expiringTimer; private CTimerJass expiringTimer;
private final CUnit enteringUnit; private CUnit enteringUnit;
private final CUnit leavingUnit; private CUnit leavingUnit;
private final CRegion triggeringRegion; private CRegion triggeringRegion;
private CPlayerJass triggeringPlayer;
private CUnit levelingUnit;
private CUnit learningUnit;
private int learnedSkill;
private int learnedSkillLevel;
private CUnit revivableUnit;
private CUnit revivingUnit;
private CUnit attacker;
private CUnit rescuer;
private CUnit dyingUnit;
private CUnit killingUnit;
private CUnit decayingUnit;
private CUnit constructingStructure;
private CUnit cancelledStructure;
private CUnit constructedStructure;
private CUnit researchingUnit;
private int researched;
private int trainedUnitType;
private CUnit trainedUnit;
private CUnit detectedUnit;
private CUnit summoningUnit;
private CUnit summonedUnit;
private CUnit transportUnit;
private CUnit loadedUnit;
private CUnit sellingUnit;
private CUnit soldUnit;
private CUnit buyingUnit;
private CUnit soldItem;
private CUnit changingUnit;
private CPlayerJass changingUnitPrevOwner;
private CUnit manipulatingUnit;
private CItem manipulatedItem;
private CUnit orderedUnit;
private int issuedOrderId;
private float orderPointX;
private float orderPointY;
private CWidget orderTarget;
private CDestructable orderTargetDestructable;
private CItem orderTargetItem;
private CUnit orderTargetUnit;
public CommonTriggerExecutionScope(final TriggerExecutionScope parentScope, final CUnit triggeringUnit, public CommonTriggerExecutionScope(final Trigger triggeringTrigger) {
final CUnit filterUnit, final CUnit enumUnit, final CDestructable filterDestructable, super(triggeringTrigger);
final CDestructable enumDestructable, final CItem filterItem, final CItem enumItem, }
final CPlayerJass filterPlayer, final CPlayerJass enumPlayer, final CTimerJass expiringTimer,
final CUnit enteringUnit, final CUnit leavingUnit, final CRegion triggeringRegion) { public CommonTriggerExecutionScope(final TriggerExecutionScope parentScope) {
super(parentScope.getTriggeringTrigger()); super(parentScope.getTriggeringTrigger());
this.triggeringUnit = triggeringUnit; if (parentScope instanceof CommonTriggerExecutionScope) {
this.filterUnit = filterUnit; copyFrom((CommonTriggerExecutionScope) parentScope);
this.enumUnit = enumUnit; }
this.filterDestructable = filterDestructable; }
this.enumDestructable = enumDestructable;
this.filterItem = filterItem; public CommonTriggerExecutionScope(final CommonTriggerExecutionScope parentScope) {
this.enumItem = enumItem; super(parentScope.getTriggeringTrigger());
this.filterPlayer = filterPlayer; copyFrom(parentScope);
this.enumPlayer = enumPlayer; }
this.expiringTimer = expiringTimer;
this.enteringUnit = enteringUnit; private void copyFrom(final CommonTriggerExecutionScope parentScope) {
this.leavingUnit = leavingUnit; this.triggeringUnit = parentScope.triggeringUnit;
this.triggeringRegion = triggeringRegion; this.filterUnit = parentScope.filterUnit;
this.enumUnit = parentScope.enumUnit;
this.filterDestructable = parentScope.filterDestructable;
this.enumDestructable = parentScope.enumDestructable;
this.filterItem = parentScope.filterItem;
this.enumItem = parentScope.enumItem;
this.filterPlayer = parentScope.filterPlayer;
this.enumPlayer = parentScope.enumPlayer;
this.expiringTimer = parentScope.expiringTimer;
this.enteringUnit = parentScope.enteringUnit;
this.leavingUnit = parentScope.leavingUnit;
this.triggeringRegion = parentScope.triggeringRegion;
this.triggeringPlayer = parentScope.triggeringPlayer;
this.levelingUnit = parentScope.levelingUnit;
this.learningUnit = parentScope.learningUnit;
this.learnedSkill = parentScope.learnedSkill;
this.learnedSkillLevel = parentScope.learnedSkillLevel;
this.revivableUnit = parentScope.revivableUnit;
this.attacker = parentScope.attacker;
this.rescuer = parentScope.rescuer;
this.dyingUnit = parentScope.dyingUnit;
this.killingUnit = parentScope.killingUnit;
this.decayingUnit = parentScope.decayingUnit;
this.constructingStructure = parentScope.constructingStructure;
this.cancelledStructure = parentScope.cancelledStructure;
this.constructedStructure = parentScope.constructedStructure;
this.researchingUnit = parentScope.researchingUnit;
this.researched = parentScope.researched;
this.trainedUnitType = parentScope.trainedUnitType;
this.trainedUnit = parentScope.trainedUnit;
this.detectedUnit = parentScope.detectedUnit;
this.summoningUnit = parentScope.summoningUnit;
this.summonedUnit = parentScope.summonedUnit;
this.transportUnit = parentScope.transportUnit;
this.loadedUnit = parentScope.loadedUnit;
this.sellingUnit = parentScope.sellingUnit;
this.soldUnit = parentScope.soldUnit;
this.buyingUnit = parentScope.buyingUnit;
this.soldItem = parentScope.soldItem;
this.changingUnit = parentScope.changingUnit;
this.changingUnitPrevOwner = parentScope.changingUnitPrevOwner;
this.manipulatingUnit = parentScope.manipulatingUnit;
this.manipulatedItem = parentScope.manipulatedItem;
this.orderedUnit = parentScope.orderedUnit;
this.issuedOrderId = parentScope.issuedOrderId;
this.orderPointX = parentScope.orderPointX;
this.orderPointY = parentScope.orderPointY;
this.orderTarget = parentScope.orderTarget;
this.orderTargetDestructable = parentScope.orderTargetDestructable;
this.orderTargetItem = parentScope.orderTargetItem;
this.orderTargetUnit = parentScope.orderTargetUnit;
} }
public CUnit getEnumUnit() { public CUnit getEnumUnit() {
@ -96,44 +188,225 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
return this.triggeringRegion; return this.triggeringRegion;
} }
public CPlayerJass getTriggeringPlayer() {
return this.triggeringPlayer;
}
public CUnit getLevelingUnit() {
return this.levelingUnit;
}
public CUnit getLearningUnit() {
return this.learningUnit;
}
public int getLearnedSkill() {
return this.learnedSkill;
}
public int getLearnedSkillLevel() {
return this.learnedSkillLevel;
}
public CUnit getRevivableUnit() {
return this.revivableUnit;
}
public CUnit getRevivingUnit() {
return this.revivingUnit;
}
public CUnit getAttacker() {
return this.attacker;
}
public CUnit getRescuer() {
return this.rescuer;
}
public CUnit getDyingUnit() {
return this.dyingUnit;
}
public CUnit getKillingUnit() {
return this.killingUnit;
}
public CUnit getDecayingUnit() {
return this.decayingUnit;
}
public CUnit getConstructingStructure() {
return this.constructingStructure;
}
public CUnit getCancelledStructure() {
return this.cancelledStructure;
}
public CUnit getConstructedStructure() {
return this.constructedStructure;
}
public CUnit getResearchingUnit() {
return this.researchingUnit;
}
public int getResearched() {
return this.researched;
}
public int getTrainedUnitType() {
return this.trainedUnitType;
}
public CUnit getTrainedUnit() {
return this.trainedUnit;
}
public CUnit getDetectedUnit() {
return this.detectedUnit;
}
public CUnit getSummoningUnit() {
return this.summoningUnit;
}
public CUnit getSummonedUnit() {
return this.summonedUnit;
}
public CUnit getTransportUnit() {
return this.transportUnit;
}
public CUnit getLoadedUnit() {
return this.loadedUnit;
}
public CUnit getSellingUnit() {
return this.sellingUnit;
}
public CUnit getSoldUnit() {
return this.soldUnit;
}
public CUnit getBuyingUnit() {
return this.buyingUnit;
}
public CUnit getSoldItem() {
return this.soldItem;
}
public CUnit getChangingUnit() {
return this.changingUnit;
}
public CPlayerJass getChangingUnitPrevOwner() {
return this.changingUnitPrevOwner;
}
public CUnit getManipulatingUnit() {
return this.manipulatingUnit;
}
public CItem getManipulatedItem() {
return this.manipulatedItem;
}
public CUnit getOrderedUnit() {
return this.orderedUnit;
}
public int getIssuedOrderId() {
return this.issuedOrderId;
}
public float getOrderPointX() {
return this.orderPointX;
}
public float getOrderPointY() {
return this.orderPointY;
}
public CWidget getOrderTarget() {
return this.orderTarget;
}
public CDestructable getOrderTargetDestructable() {
return this.orderTargetDestructable;
}
public CItem getOrderTargetItem() {
return this.orderTargetItem;
}
public CUnit getOrderTargetUnit() {
return this.orderTargetUnit;
}
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope, public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
final CUnit filterUnit) { final CUnit filterUnit) {
return new CommonTriggerExecutionScope(parentScope, null, filterUnit, null, null, null, null, null, null, null, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
null, null, null, null); scope.filterUnit = filterUnit;
return scope;
} }
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CUnit enumUnit) { public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CUnit enumUnit) {
return new CommonTriggerExecutionScope(parentScope, null, null, enumUnit, null, null, null, null, null, null, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
null, null, null, null); scope.enumUnit = enumUnit;
return scope;
} }
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope, public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
final CPlayerJass filterPlayer) { final CPlayerJass filterPlayer) {
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, filterPlayer, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
null, null, null, null, null); scope.filterPlayer = filterPlayer;
return scope;
} }
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope,
final CPlayerJass enumPlayer) { final CPlayerJass enumPlayer) {
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, enumPlayer, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
null, null, null, null); scope.enumPlayer = enumPlayer;
return scope;
} }
public static CommonTriggerExecutionScope expiringTimer(final CTimerJass cTimerJass) { public static CommonTriggerExecutionScope expiringTimer(final CTimerJass cTimerJass) {
return new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY, null, null, null, null, null, null, null, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY);
null, null, cTimerJass, null, null, null); scope.expiringTimer = cTimerJass;
return scope;
} }
public static CommonTriggerExecutionScope unitEnterRegionScope(final TriggerExecutionScope parentScope, public static CommonTriggerExecutionScope unitEnterRegionScope(final TriggerExecutionScope parentScope,
final CUnit enteringUnit, final CRegion triggeringRegion) { final CUnit enteringUnit, final CRegion triggeringRegion) {
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, null, null, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
enteringUnit, null, triggeringRegion); scope.enteringUnit = enteringUnit;
scope.triggeringRegion = triggeringRegion;
return scope;
} }
public static CommonTriggerExecutionScope unitLeaveRegionScope(final TriggerExecutionScope parentScope, public static CommonTriggerExecutionScope unitLeaveRegionScope(final TriggerExecutionScope parentScope,
final CUnit leavingUnit, final CRegion triggeringRegion) { final CUnit leavingUnit, final CRegion triggeringRegion) {
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, null, null, final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope);
null, leavingUnit, triggeringRegion); scope.leavingUnit = leavingUnit;
scope.triggeringRegion = triggeringRegion;
return scope;
}
public static CommonTriggerExecutionScope playerHeroLevelScope(final CUnit hero) {
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY);
scope.levelingUnit = hero;
return scope;
}
public static CommonTriggerExecutionScope playerHeroRevivableScope(final CUnit hero) {
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY);
scope.revivableUnit = hero;
return scope;
} }
} }

View File

@ -29,4 +29,11 @@ public class WarsmashConstants {
public static final boolean VERBOSE_LOGGING = true; public static final boolean VERBOSE_LOGGING = true;
public static final boolean ENABLE_DEBUG = false; public static final boolean ENABLE_DEBUG = false;
public static final char SPECIAL_ESCAPE_KEYCODE = 0x7E; public static final char SPECIAL_ESCAPE_KEYCODE = 0x7E;
// My tileset loader is "always on top", even for local files. This is different
// from some MPQ loader engines that would use
// load index as a numeric value and could be changed. For now, I have this
// workaround to fix it if you need the local files
// to take priority over built-ins for tilesets.
public static final boolean FIX_FLAT_FILES_TILESET_LOADING = false;
} }

View File

@ -516,7 +516,7 @@ public class MdxComplexInstance extends ModelInstance {
} }
final int glGetError = Gdx.gl.glGetError(); final int glGetError = Gdx.gl.glGetError();
if (glGetError != GL20.GL_NO_ERROR) { if ((glGetError != GL20.GL_NO_ERROR) && WarsmashConstants.ENABLE_DEBUG) {
throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Opaque)"); throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Opaque)");
} }
} }
@ -532,7 +532,7 @@ public class MdxComplexInstance extends ModelInstance {
group.render(this, this.scene.camera.viewProjectionMatrix); group.render(this, this.scene.camera.viewProjectionMatrix);
final int glGetError = Gdx.gl.glGetError(); final int glGetError = Gdx.gl.glGetError();
if (glGetError != GL20.GL_NO_ERROR) { if ((glGetError != GL20.GL_NO_ERROR) && WarsmashConstants.ENABLE_DEBUG) {
throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Translucent)"); throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Translucent)");
} }
} }
@ -883,22 +883,20 @@ public class MdxComplexInstance extends ModelInstance {
public void setFrameByRatio(final float ratioOfAnimationCompleted) { public void setFrameByRatio(final float ratioOfAnimationCompleted) {
if (this.sequence != -1) { if (this.sequence != -1) {
final Sequence currentlyPlayingSequence = ((MdxModel) this.model).sequences.get(this.sequence); final Sequence currentlyPlayingSequence = ((MdxModel) this.model).sequences.get(this.sequence);
long start = currentlyPlayingSequence.getInterval()[0]; final long start = currentlyPlayingSequence.getInterval()[0];
final int lastIntegerFrame = this.frame; final int lastIntegerFrame = this.frame;
float lastFloatingFrame = this.floatingFrame; final float lastFloatingFrame = this.floatingFrame;
long sequenceLength = currentlyPlayingSequence.getInterval()[1] - start; final long sequenceLength = currentlyPlayingSequence.getInterval()[1] - start;
float newFloatingFrame = start final float newFloatingFrame = start + (sequenceLength * ratioOfAnimationCompleted);
+ (sequenceLength float frameTime = newFloatingFrame - lastFloatingFrame;
* ratioOfAnimationCompleted); if (frameTime < 0) {
float frameTime = newFloatingFrame-lastFloatingFrame;
if(frameTime < 0) {
frameTime += sequenceLength; frameTime += sequenceLength;
} }
this.floatingFrame = newFloatingFrame; this.floatingFrame = newFloatingFrame;
this.frame = (int) this.floatingFrame; this.frame = (int) this.floatingFrame;
this.blendTimeRemaining -= frameTime; this.blendTimeRemaining -= frameTime;
int integerFrameTime = this.frame - lastIntegerFrame; int integerFrameTime = this.frame - lastIntegerFrame;
if(integerFrameTime < 0) { if (integerFrameTime < 0) {
integerFrameTime += sequenceLength; integerFrameTime += sequenceLength;
} }
this.counter += integerFrameTime; this.counter += integerFrameTime;
@ -910,14 +908,14 @@ public class MdxComplexInstance extends ModelInstance {
} }
} }
public int clampFrame(int frameToClamp) { public int clampFrame(final int frameToClamp) {
final MdxModel model = (MdxModel) this.model; final MdxModel model = (MdxModel) this.model;
final int sequenceId = this.sequence; final int sequenceId = this.sequence;
if(sequenceId >= 0 && sequenceId < model.sequences.size()) { if ((sequenceId >= 0) && (sequenceId < model.sequences.size())) {
final Sequence sequence = model.sequences.get(sequenceId); final Sequence sequence = model.sequences.get(sequenceId);
final long[] interval = sequence.getInterval(); final long[] interval = sequence.getInterval();
return (int)Math.max(interval[0], Math.min(interval[1], frameToClamp)); return (int) Math.max(interval[0], Math.min(interval[1], frameToClamp));
} }
return frameToClamp; return frameToClamp;
} }
} }

View File

@ -132,8 +132,23 @@ public class TgaFile {
} }
} }
} }
else if ((header[17] >> 4) == 2) {
// flip horizontally and vertically
for (int y = 0; y < h; y++) {
final int w2 = w / 2;
for (int x = 0; x < w2; x++) {
final int a = (y * w) + x;
final int b = ((h - 1 - y) * w) + (w - 1 - x);
final int t = pixels[a];
pixels[a] = pixels[b];
pixels[b] = t;
}
}
}
else { else {
throw new UnsupportedOperationException("Error " + name); final int headerval = header[17] >> 4;
throw new UnsupportedOperationException("Error " + name + " (" + headerval + ")");
} }
return dst; return dst;

View File

@ -466,24 +466,30 @@ public class War3MapViewer extends AbstractMdxModelViewer {
// from either the map or the game, giving the map priority. // from either the map or the game, giving the map priority.
SeekableByteChannel sbc; SeekableByteChannel sbc;
final CompoundDataSource compoundDataSource = war3Map.getCompoundDataSource(); final CompoundDataSource compoundDataSource = war3Map.getCompoundDataSource();
try (InputStream mapStream = compoundDataSource.getResourceAsStream(tileset + ".mpq")) { if (WarsmashConstants.FIX_FLAT_FILES_TILESET_LOADING) {
if (mapStream == null) { tilesetSource = new CompoundDataSource(
Arrays.asList(compoundDataSource, new SubdirDataSource(compoundDataSource, tileset + ".mpq/")));
}
else {
try (InputStream mapStream = compoundDataSource.getResourceAsStream(tileset + ".mpq")) {
if (mapStream == null) {
tilesetSource = new CompoundDataSource(Arrays.asList(compoundDataSource,
new SubdirDataSource(compoundDataSource, tileset + ".mpq/"),
new SubdirDataSource(compoundDataSource, "_tilesets/" + tileset + ".w3mod/")));
}
else {
final byte[] mapData = IOUtils.toByteArray(mapStream);
sbc = new SeekableInMemoryByteChannel(mapData);
final DataSource internalMpqContentsDataSource = new MpqDataSource(new MPQArchive(sbc), sbc);
tilesetSource = new CompoundDataSource(
Arrays.asList(compoundDataSource, internalMpqContentsDataSource));
}
}
catch (final IOException exc) {
tilesetSource = new CompoundDataSource(Arrays.asList(compoundDataSource, tilesetSource = new CompoundDataSource(Arrays.asList(compoundDataSource,
new SubdirDataSource(compoundDataSource, tileset + ".mpq/"), new SubdirDataSource(compoundDataSource, tileset + ".mpq/"),
new SubdirDataSource(compoundDataSource, "_tilesets/" + tileset + ".w3mod/"))); new SubdirDataSource(compoundDataSource, "_tilesets/" + tileset + ".w3mod/")));
} }
else {
final byte[] mapData = IOUtils.toByteArray(mapStream);
sbc = new SeekableInMemoryByteChannel(mapData);
final DataSource internalMpqContentsDataSource = new MpqDataSource(new MPQArchive(sbc), sbc);
tilesetSource = new CompoundDataSource(
Arrays.asList(compoundDataSource, internalMpqContentsDataSource));
}
}
catch (final IOException exc) {
tilesetSource = new CompoundDataSource(
Arrays.asList(compoundDataSource, new SubdirDataSource(compoundDataSource, tileset + ".mpq/"),
new SubdirDataSource(compoundDataSource, "_tilesets/" + tileset + ".w3mod/")));
} }
} }
catch (final MPQException e) { catch (final MPQException e) {
@ -723,29 +729,30 @@ public class War3MapViewer extends AbstractMdxModelViewer {
} }
@Override @Override
public void heroRevived(CUnit source) { public void heroRevived(final CUnit source) {
final AbilityUI reviveUI = War3MapViewer.this.abilityDataUI.getUI(ABILITY_REVIVE_RAWCODE); final AbilityUI reviveUI = War3MapViewer.this.abilityDataUI.getUI(ABILITY_REVIVE_RAWCODE);
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(source); final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(source);
CPlayer player = simulation.getPlayer(source.getPlayerIndex()); final CPlayer player = War3MapViewer.this.simulation.getPlayer(source.getPlayerIndex());
final String heroReviveArt = reviveUI.getTargetArt(player.getRace().ordinal()); final String heroReviveArt = reviveUI.getTargetArt(player.getRace().ordinal());
spawnFxOnOrigin(renderUnit, heroReviveArt); spawnFxOnOrigin(renderUnit, heroReviveArt);
MutableGameObject row = allObjectData.getUnits().get(source.getTypeId()); final MutableGameObject row = War3MapViewer.this.allObjectData.getUnits()
.get(source.getTypeId());
// Recreate unit shadow.... is needed here // Recreate unit shadow.... is needed here
final String unitShadow = row.getFieldAsString(UNIT_SHADOW, 0); final String unitShadow = row.getFieldAsString(UNIT_SHADOW, 0);
float unitX = source.getX(); final float unitX = source.getX();
float unitY = source.getY(); final float unitY = source.getY();
if ((unitShadow != null) && !"_".equals(unitShadow)) { if ((unitShadow != null) && !"_".equals(unitShadow)) {
final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp"; final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp";
final float shadowX = row.getFieldAsFloat(UNIT_SHADOW_X, 0); final float shadowX = row.getFieldAsFloat(UNIT_SHADOW_X, 0);
final float shadowY = row.getFieldAsFloat(UNIT_SHADOW_Y, 0); final float shadowY = row.getFieldAsFloat(UNIT_SHADOW_Y, 0);
final float shadowWidth = row.getFieldAsFloat(UNIT_SHADOW_W, 0); final float shadowWidth = row.getFieldAsFloat(UNIT_SHADOW_W, 0);
final float shadowHeight = row.getFieldAsFloat(UNIT_SHADOW_H, 0); final float shadowHeight = row.getFieldAsFloat(UNIT_SHADOW_H, 0);
if (mapMpq.has(texture)) { if (War3MapViewer.this.mapMpq.has(texture)) {
final float x = unitX - shadowX; final float x = unitX - shadowX;
final float y = unitY - shadowY; final float y = unitY - shadowY;
renderUnit.shadow = terrain.addUnitShadowSplat(texture, x, y, renderUnit.shadow = War3MapViewer.this.terrain.addUnitShadowSplat(texture, x, y,
x + shadowWidth, y + shadowHeight, 3, 0.5f); x + shadowWidth, y + shadowHeight, 3, 0.5f);
} }
} }
@ -770,8 +777,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
} }
@Override @Override
public void spawnSpellEffectOnUnit(CUnit unit, War3ID alias) { public void spawnSpellEffectOnUnit(final CUnit unit, final War3ID alias) {
AbilityUI abilityUI = abilityDataUI.getUI(alias); final AbilityUI abilityUI = War3MapViewer.this.abilityDataUI.getUI(alias);
spawnEffectOnUnit(unit, abilityUI.getTargetArt(0)); spawnEffectOnUnit(unit, abilityUI.getTargetArt(0));
} }
@ -861,11 +868,10 @@ public class War3MapViewer extends AbstractMdxModelViewer {
loadLightsAndShading(tileset); loadLightsAndShading(tileset);
} }
public void spawnFxOnOrigin(RenderUnit renderUnit, String heroLevelUpArt) { public void spawnFxOnOrigin(final RenderUnit renderUnit, final String heroLevelUpArt) {
final MdxModel heroLevelUpModel = loadModel(heroLevelUpArt); final MdxModel heroLevelUpModel = loadModel(heroLevelUpArt);
if (heroLevelUpModel != null) { if (heroLevelUpModel != null) {
final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel.addInstance();
.addInstance();
modelInstance.setTeamColor(renderUnit.playerIndex); modelInstance.setTeamColor(renderUnit.playerIndex);
final MdxModel model = (MdxModel) renderUnit.instance.model; final MdxModel model = (MdxModel) renderUnit.instance.model;
@ -880,15 +886,15 @@ public class War3MapViewer extends AbstractMdxModelViewer {
if (index != -1) { if (index != -1) {
final MdxNode attachment = renderUnit.instance.getAttachment(index); final MdxNode attachment = renderUnit.instance.getAttachment(index);
modelInstance.setParent(attachment); modelInstance.setParent(attachment);
} else { }
else {
modelInstance.setLocation(renderUnit.location); modelInstance.setLocation(renderUnit.location);
} }
modelInstance.setScene(War3MapViewer.this.worldScene); modelInstance.setScene(War3MapViewer.this.worldScene);
SequenceUtils.randomBirthSequence(modelInstance); SequenceUtils.randomBirthSequence(modelInstance);
War3MapViewer.this.projectiles War3MapViewer.this.projectiles.add(new RenderAttackInstant(modelInstance, War3MapViewer.this,
.add(new RenderAttackInstant(modelInstance, War3MapViewer.this, (float) Math.toRadians(renderUnit.getSimulationUnit().getFacing())));
(float) Math.toRadians(renderUnit.getSimulationUnit().getFacing())));
} }
} }

View File

@ -364,6 +364,7 @@ public class Terrain {
final String fileName = waterInfo.getField("texFile"); final String fileName = waterInfo.getField("texFile");
final List<BufferedImage> waterTextures = new ArrayList<>(); final List<BufferedImage> waterTextures = new ArrayList<>();
boolean anyWaterTextureNeedsSRGB = false; boolean anyWaterTextureNeedsSRGB = false;
int waterImageDimension = 128;
for (int i = 0; i < this.waterTextureCount; i++) { for (int i = 0; i < this.waterTextureCount; i++) {
final AnyExtensionImage imageInfo = ImageUtils.getAnyExtensionImageFixRGB(dataSource, final AnyExtensionImage imageInfo = ImageUtils.getAnyExtensionImageFixRGB(dataSource,
fileName + (i < 10 ? "0" : "") + Integer.toString(i) + texturesExt, "water texture"); fileName + (i < 10 ? "0" : "") + Integer.toString(i) + texturesExt, "water texture");
@ -371,13 +372,15 @@ public class Terrain {
if ((image.getWidth() != 128) || (image.getHeight() != 128)) { if ((image.getWidth() != 128) || (image.getHeight() != 128)) {
System.err System.err
.println("Odd water texture size detected of " + image.getWidth() + " x " + image.getHeight()); .println("Odd water texture size detected of " + image.getWidth() + " x " + image.getHeight());
waterImageDimension = image.getWidth();
} }
anyWaterTextureNeedsSRGB |= imageInfo.isNeedsSRGBFix(); anyWaterTextureNeedsSRGB |= imageInfo.isNeedsSRGBFix();
waterTextures.add(image); waterTextures.add(image);
} }
gl.glTexImage3D(GL30.GL_TEXTURE_2D_ARRAY, 0, anyWaterTextureNeedsSRGB ? GL30.GL_SRGB8_ALPHA8 : GL30.GL_RGBA8, gl.glTexImage3D(GL30.GL_TEXTURE_2D_ARRAY, 0, anyWaterTextureNeedsSRGB ? GL30.GL_SRGB8_ALPHA8 : GL30.GL_RGBA8,
128, 128, this.waterTextureCount, 0, GL30.GL_RGBA, GL30.GL_UNSIGNED_BYTE, null); waterImageDimension, waterImageDimension, this.waterTextureCount, 0, GL30.GL_RGBA,
GL30.GL_UNSIGNED_BYTE, null);
gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_WRAP_S, GL30.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_WRAP_S, GL30.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_WRAP_T, GL30.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_WRAP_T, GL30.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_BASE_LEVEL, 0); gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_BASE_LEVEL, 0);

View File

@ -153,7 +153,8 @@ public class TerrainShaders {
" float hU = texelFetch(height_texture, height_pos + off.zy, 0).r;\r\n" + // " float hU = texelFetch(height_texture, height_pos + off.zy, 0).r;\r\n" + //
" vec3 normal = normalize(vec3(hL - hR, hD - hU, 2.0));\r\n" + // " vec3 normal = normalize(vec3(hL - hR, hD - hU, 2.0));\r\n" + //
"\r\n" + // "\r\n" + //
" UV = vec2(vPosition.x, 1 - vPosition.y);\r\n" + // // " UV = vec2(vPosition.x, 1 - vPosition.y);\r\n" + //
" UV = vec2(vPosition.x==0?0.01:0.99, vPosition.y==0?0.99:0.01);\r\n" + //
" texture_indices = texelFetch(terrain_texture_list, pos, 0);\r\n" + // " texture_indices = texelFetch(terrain_texture_list, pos, 0);\r\n" + //
" pathing_map_uv = (vPosition + pos) * 4; \r\n" + // " pathing_map_uv = (vPosition + pos) * 4; \r\n" + //
"\r\n" + // "\r\n" + //

View File

@ -41,6 +41,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CUnitData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionManager; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionManager;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer;
@ -67,7 +68,6 @@ public class CSimulation implements CPlayerAPI {
private final PathingGrid pathingGrid; private final PathingGrid pathingGrid;
private final CWorldCollision worldCollision; private final CWorldCollision worldCollision;
private final CPathfindingProcessor[] pathfindingProcessors; private final CPathfindingProcessor[] pathfindingProcessors;
private final List<CUnit>[] playerHeroes;
private final CGameplayConstants gameplayConstants; private final CGameplayConstants gameplayConstants;
private final Random seededRandom; private final Random seededRandom;
private float currentGameDayTimeElapsed; private float currentGameDayTimeElapsed;
@ -104,17 +104,15 @@ public class CSimulation implements CPlayerAPI {
this.worldCollision = new CWorldCollision(entireMapBounds, this.gameplayConstants.getMaxCollisionRadius()); this.worldCollision = new CWorldCollision(entireMapBounds, this.gameplayConstants.getMaxCollisionRadius());
this.regionManager = new CRegionManager(entireMapBounds, pathingGrid); this.regionManager = new CRegionManager(entireMapBounds, pathingGrid);
this.pathfindingProcessors = new CPathfindingProcessor[WarsmashConstants.MAX_PLAYERS]; this.pathfindingProcessors = new CPathfindingProcessor[WarsmashConstants.MAX_PLAYERS];
this.playerHeroes = new ArrayList[WarsmashConstants.MAX_PLAYERS];
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) { for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
this.pathfindingProcessors[i] = new CPathfindingProcessor(pathingGrid, this.worldCollision); this.pathfindingProcessors[i] = new CPathfindingProcessor(pathingGrid, this.worldCollision);
this.playerHeroes[i] = new ArrayList<>();
} }
this.seededRandom = seededRandom; this.seededRandom = seededRandom;
this.players = new ArrayList<>(); this.players = new ArrayList<>();
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) { for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer configPlayer = config.getPlayer(i); final CBasePlayer configPlayer = config.getPlayer(i);
final War3MapConfigStartLoc startLoc = config.getStartLoc(configPlayer.getStartLocationIndex()); final War3MapConfigStartLoc startLoc = config.getStartLoc(configPlayer.getStartLocationIndex());
CRace defaultRace = CRace.ORC; final CRace defaultRace = CRace.ORC;
final CPlayer newPlayer = new CPlayer(defaultRace, new float[] { startLoc.getX(), startLoc.getY() }, final CPlayer newPlayer = new CPlayer(defaultRace, new float[] { startLoc.getX(), startLoc.getY() },
configPlayer); configPlayer);
this.players.add(newPlayer); this.players.add(newPlayer);
@ -183,7 +181,7 @@ public class CSimulation implements CPlayerAPI {
this.newUnits.add(unit); this.newUnits.add(unit);
this.handleIdToUnit.put(unit.getHandleId(), unit); this.handleIdToUnit.put(unit.getHandleId(), unit);
this.worldCollision.addUnit(unit); this.worldCollision.addUnit(unit);
if(unit.getHeroData() != null) { if (unit.getHeroData() != null) {
heroCreateEvent(unit); heroCreateEvent(unit);
} }
return unit; return unit;
@ -269,7 +267,7 @@ public class CSimulation implements CPlayerAPI {
} }
this.handleIdToUnit.remove(unit.getHandleId()); this.handleIdToUnit.remove(unit.getHandleId());
this.simulationRenderController.removeUnit(unit); this.simulationRenderController.removeUnit(unit);
this.playerHeroes[unit.getPlayerIndex()].remove(unit); getPlayerHeroes(unit.getPlayerIndex()).remove(unit);
unit.onRemove(this); unit.onRemove(this);
} }
} }
@ -316,7 +314,7 @@ public class CSimulation implements CPlayerAPI {
} }
this.handleIdToUnit.remove(unit.getHandleId()); this.handleIdToUnit.remove(unit.getHandleId());
this.simulationRenderController.removeUnit(unit); this.simulationRenderController.removeUnit(unit);
this.playerHeroes[unit.getPlayerIndex()].remove(unit); getPlayerHeroes(unit.getPlayerIndex()).remove(unit);
unit.onRemove(this); unit.onRemove(this);
} }
this.removedUnits.clear(); this.removedUnits.clear();
@ -390,6 +388,7 @@ public class CSimulation implements CPlayerAPI {
public void unitTrainedEvent(final CUnit trainingUnit, final CUnit trainedUnit) { public void unitTrainedEvent(final CUnit trainingUnit, final CUnit trainedUnit) {
this.simulationRenderController.spawnUnitReadySound(trainedUnit); this.simulationRenderController.spawnUnitReadySound(trainedUnit);
} }
public void heroReviveEvent(final CUnit trainingUnit, final CUnit trainedUnit) { public void heroReviveEvent(final CUnit trainingUnit, final CUnit trainedUnit) {
this.simulationRenderController.heroRevived(trainedUnit); this.simulationRenderController.heroRevived(trainedUnit);
this.simulationRenderController.spawnUnitReadySound(trainedUnit); this.simulationRenderController.spawnUnitReadySound(trainedUnit);
@ -404,11 +403,12 @@ public class CSimulation implements CPlayerAPI {
} }
public void unitGainLevelEvent(final CUnit unit) { public void unitGainLevelEvent(final CUnit unit) {
this.players.get(unit.getPlayerIndex()).fireHeroLevelEvents(unit);
this.simulationRenderController.spawnGainLevelEffect(unit); this.simulationRenderController.spawnGainLevelEffect(unit);
} }
public void heroCreateEvent(final CUnit hero) { public void heroCreateEvent(final CUnit hero) {
this.playerHeroes[hero.getPlayerIndex()].add(hero); getPlayerHeroes(hero.getPlayerIndex()).add(hero);
} }
public void unitPickUpItemEvent(final CUnit cUnit, final CItem item) { public void unitPickUpItemEvent(final CUnit cUnit, final CItem item) {
@ -420,7 +420,7 @@ public class CSimulation implements CPlayerAPI {
} }
public List<CUnit> getPlayerHeroes(final int playerIndex) { public List<CUnit> getPlayerHeroes(final int playerIndex) {
return this.playerHeroes[playerIndex]; return this.players.get(playerIndex).getHeroes();
} }
public void unitsLoaded() { public void unitsLoaded() {
@ -455,8 +455,8 @@ public class CSimulation implements CPlayerAPI {
this.simulationRenderController.spawnEffectOnUnit(unit, effectPath); this.simulationRenderController.spawnEffectOnUnit(unit, effectPath);
} }
public void createSpellEffectOnUnit(CUnit unit, War3ID alias) { public void createSpellEffectOnUnit(final CUnit unit, final War3ID alias) {
simulationRenderController.spawnSpellEffectOnUnit(unit, alias); this.simulationRenderController.spawnSpellEffectOnUnit(unit, alias);
} }
public void unitSoundEffectEvent(final CUnit caster, final War3ID alias) { public void unitSoundEffectEvent(final CUnit caster, final War3ID alias) {
@ -480,16 +480,16 @@ public class CSimulation implements CPlayerAPI {
}; };
} }
public void heroDeathEvent(CUnit cUnit) { public void heroDeathEvent(final CUnit cUnit) {
getPlayer(cUnit.getPlayerIndex()).onHeroDeath(); getPlayer(cUnit.getPlayerIndex()).onHeroDeath(cUnit);
} }
public void removeItem(CItem cItem) { public void removeItem(final CItem cItem) {
cItem.setHidden(true); // TODO fix cItem.setHidden(true); // TODO fix
cItem.setLife(this, 0); cItem.setLife(this, 0);
} }
private static final class TimeOfDayVariableEvent extends VariableEvent { private static final class TimeOfDayVariableEvent extends VariableEvent {
private final GlobalScope globalScope; private final GlobalScope globalScope;
public TimeOfDayVariableEvent(final Trigger trigger, final CLimitOp limitOp, final double doubleValue, public TimeOfDayVariableEvent(final Trigger trigger, final CLimitOp limitOp, final double doubleValue,
@ -502,4 +502,20 @@ public class CSimulation implements CPlayerAPI {
fire(this.globalScope); fire(this.globalScope);
} }
} }
public RemovableTriggerEvent registerEventPlayerDefeat(final GlobalScope globalScope, final Trigger whichTrigger,
final CPlayerJass whichPlayer) {
if (true) {
throw new UnsupportedOperationException("registerEventPlayerDefeat is NYI");
}
return RemovableTriggerEvent.DO_NOTHING;
}
public RemovableTriggerEvent registerEventPlayerVictory(final GlobalScope globalScope, final Trigger whichTrigger,
final CPlayerJass whichPlayer) {
if (true) {
throw new UnsupportedOperationException("registerEventPlayerVictory is NYI");
}
return RemovableTriggerEvent.DO_NOTHING;
}
} }

View File

@ -11,7 +11,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerStat
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRacePreference; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRacePreference;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
public class CBasePlayer implements CPlayerJass { public abstract class CBasePlayer implements CPlayerJass {
private final int id; private final int id;
private String name; private String name;
private int team; private int team;
@ -59,6 +59,7 @@ public class CBasePlayer implements CPlayerJass {
} }
} }
@Override
public int getId() { public int getId() {
return this.id; return this.id;
} }
@ -138,6 +139,7 @@ public class CBasePlayer implements CPlayerJass {
} }
} }
@Override
public boolean hasAlliance(final int otherPlayerIndex, final CAllianceType allianceType) { public boolean hasAlliance(final int otherPlayerIndex, final CAllianceType allianceType) {
final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayerIndex]; final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayerIndex];
return alliancesWithOtherPlayer.contains(allianceType); return alliancesWithOtherPlayer.contains(allianceType);

View File

@ -30,7 +30,7 @@ public class War3MapConfig implements CPlayerAPI {
this.players = new CBasePlayer[maxPlayers]; this.players = new CBasePlayer[maxPlayers];
for (int i = 0; i < maxPlayers; i++) { for (int i = 0; i < maxPlayers; i++) {
this.startLocations[i] = new War3MapConfigStartLoc(); this.startLocations[i] = new War3MapConfigStartLoc();
this.players[i] = new CBasePlayer(i); this.players[i] = new War3MapConfigPlayer(i);
} }
} }

View File

@ -0,0 +1,29 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerEvent;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
public class War3MapConfigPlayer extends CBasePlayer {
public War3MapConfigPlayer(final CBasePlayer other) {
super(other);
}
public War3MapConfigPlayer(final int id) {
super(id);
}
@Override
public RemovableTriggerEvent addEvent(final GlobalScope globalScope, final Trigger whichTrigger,
final JassGameEventsWar3 eventType) {
return RemovableTriggerEvent.DO_NOTHING;
}
@Override
public void removeEvent(final CPlayerEvent playerEvent) {
}
}

View File

@ -1,14 +1,22 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players; package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.warsmash.parsers.jass.scope.CommonTriggerExecutionScope;
import com.etheller.warsmash.util.War3ID; import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener.CPlayerStateNotifier; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener.CPlayerStateNotifier;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
public class CPlayer extends CBasePlayer { public class CPlayer extends CBasePlayer {
private final CRace race; private final CRace race;
@ -18,6 +26,9 @@ public class CPlayer extends CBasePlayer {
private int foodCap; private int foodCap;
private int foodUsed; private int foodUsed;
private final Map<War3ID, Integer> rawcodeToTechtreeUnlocked = new HashMap<>(); private final Map<War3ID, Integer> rawcodeToTechtreeUnlocked = new HashMap<>();
private final List<CUnit> heroes = new ArrayList<>();
private final EnumMap<JassGameEventsWar3, List<CPlayerEvent>> eventTypeToEvents = new EnumMap<>(
JassGameEventsWar3.class);
// if you use triggers for this then the transient tag here becomes really // if you use triggers for this then the transient tag here becomes really
// questionable -- it already was -- but I meant for those to inform us // questionable -- it already was -- but I meant for those to inform us
@ -139,7 +150,7 @@ public class CPlayer extends CBasePlayer {
this.stateNotifier.goldChanged(); this.stateNotifier.goldChanged();
} }
public void refund(int gold, int lumber) { public void refund(final int gold, final int lumber) {
this.gold += gold; this.gold += gold;
this.lumber += lumber; this.lumber += lumber;
this.stateNotifier.lumberChanged(); this.stateNotifier.lumberChanged();
@ -156,7 +167,57 @@ public class CPlayer extends CBasePlayer {
this.stateNotifier.foodChanged(); this.stateNotifier.foodChanged();
} }
public void onHeroDeath() { public void onHeroDeath(final CUnit hero) {
stateNotifier.heroDeath(); this.stateNotifier.heroDeath();
} firePlayerUnitEvents(hero, CommonTriggerExecutionScope.playerHeroRevivableScope(hero),
JassGameEventsWar3.EVENT_PLAYER_HERO_REVIVABLE);
}
private void firePlayerUnitEvents(final CUnit hero, final CommonTriggerExecutionScope eventScope,
final JassGameEventsWar3 eventType) {
final List<CPlayerEvent> eventList = getEventList(eventType);
if (eventList != null) {
for (final CPlayerEvent event : eventList) {
event.fire(hero, eventScope);
}
}
}
public List<CUnit> getHeroes() {
return this.heroes;
}
public void fireHeroLevelEvents(final CUnit hero) {
firePlayerUnitEvents(hero, CommonTriggerExecutionScope.playerHeroRevivableScope(hero),
JassGameEventsWar3.EVENT_PLAYER_HERO_LEVEL);
}
private List<CPlayerEvent> getOrCreateEventList(final JassGameEventsWar3 eventType) {
List<CPlayerEvent> playerEvents = this.eventTypeToEvents.get(eventType);
if (playerEvents == null) {
playerEvents = new ArrayList<>();
this.eventTypeToEvents.put(eventType, playerEvents);
}
return playerEvents;
}
private List<CPlayerEvent> getEventList(final JassGameEventsWar3 eventType) {
return this.eventTypeToEvents.get(eventType);
}
@Override
public RemovableTriggerEvent addEvent(final GlobalScope globalScope, final Trigger whichTrigger,
final JassGameEventsWar3 eventType) {
final CPlayerEvent playerEvent = new CPlayerEvent(globalScope, this, whichTrigger, eventType);
getOrCreateEventList(eventType).add(playerEvent);
return playerEvent;
}
@Override
public void removeEvent(final CPlayerEvent playerEvent) {
final List<CPlayerEvent> eventList = getEventList(playerEvent.getEventType());
if (eventList != null) {
eventList.remove(playerEvent);
}
}
} }

View File

@ -0,0 +1,40 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
public class CPlayerEvent implements RemovableTriggerEvent {
private final GlobalScope globalScope;
private final CPlayerJass player;
private final Trigger trigger;
private final JassGameEventsWar3 eventType;
public CPlayerEvent(final GlobalScope globalScope, final CPlayerJass player, final Trigger trigger,
final JassGameEventsWar3 eventType) {
this.globalScope = globalScope;
this.player = player;
this.trigger = trigger;
this.eventType = eventType;
}
public Trigger getTrigger() {
return this.trigger;
}
public JassGameEventsWar3 getEventType() {
return this.eventType;
}
@Override
public void remove() {
this.player.removeEvent(this);
}
public void fire(final CUnit hero, final TriggerExecutionScope scope) {
this.trigger.evaluate(this.globalScope, scope);
}
}

View File

@ -1,5 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players; package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
public interface CPlayerJass { public interface CPlayerJass {
@ -46,4 +50,9 @@ public interface CPlayerJass {
boolean isRacePrefSet(CRacePreference pref); boolean isRacePrefSet(CRacePreference pref);
String getName(); String getName();
RemovableTriggerEvent addEvent(final GlobalScope globalScope, final Trigger whichTrigger,
final JassGameEventsWar3 eventType);
void removeEvent(CPlayerEvent playerEvent);
} }

View File

@ -0,0 +1,25 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.uidialog;
import java.util.ArrayList;
import java.util.List;
public class JassUIDialog {
private String title;
private final List<JassUIDialogButton> buttons = new ArrayList<>();
public void setTitle(final String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
public void add(final JassUIDialogButton button) {
this.buttons.add(button);
}
public boolean remove(final JassUIDialogButton button) {
return this.buttons.remove(button);
}
}

View File

@ -0,0 +1,13 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.uidialog;
public class JassUIDialogButton {
private String text;
public String getText() {
return this.text;
}
public void setText(final String text) {
this.text = text;
}
}

View File

@ -2,4 +2,10 @@ package com.etheller.interpreter.ast.scope.trigger;
public interface RemovableTriggerEvent { public interface RemovableTriggerEvent {
void remove(); void remove();
RemovableTriggerEvent DO_NOTHING = new RemovableTriggerEvent() {
@Override
public void remove() {
}
};
} }