diff --git a/core/assets/warsmash.ini b/core/assets/warsmash.ini index 93417d2..cb2f17d 100644 --- a/core/assets/warsmash.ini +++ b/core/assets/warsmash.ini @@ -1,5 +1,5 @@ [DataSources] -Count=8 +Count=9 Type00=MPQ Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq" Type01=MPQ @@ -8,48 +8,13 @@ Type02=MPQ Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq" Type03=MPQ Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq" -Type04=Folder -Path04="..\..\resources" +Type04=MPQ +Path04="D:\Games\Warcraft III Patch 1.22\Warsmash\War3Mod.mpq" Type05=Folder -Path05="D:\Backups\Warsmash\Data" +Path05="..\..\resources" Type06=Folder -Path06="D:\Games\Warcraft III Patch 1.22\Maps" +Path06="D:\Backups\Warsmash\Data" Type07=Folder -Path07="." -Type08=MPQ -Path08="C:\Users\micro\Downloads\Warcraft III All In One\war3g.exe" - -[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" +Path07="D:\Games\Warcraft III Patch 1.22\Maps" +Type08=Folder +Path08="." diff --git a/core/assets/warsmash_myHD.ini b/core/assets/warsmash_myHD.ini new file mode 100644 index 0000000..9c68faa --- /dev/null +++ b/core/assets/warsmash_myHD.ini @@ -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" diff --git a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java index c8b1191..d71ee1a 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java +++ b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java @@ -2408,6 +2408,96 @@ public class Jass2 { return new HandleJassValue(unitType, ((CommonTriggerExecutionScope) triggerScope).getLeavingUnit()); } }); + jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterTrackableHitEvent", + new JassFunction() { + @Override + public JassValue call(final List 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 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 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 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 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 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 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 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 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 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 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, diff --git a/core/src/com/etheller/warsmash/parsers/jass/scope/CommonTriggerExecutionScope.java b/core/src/com/etheller/warsmash/parsers/jass/scope/CommonTriggerExecutionScope.java index 25513b0..492cfc6 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/scope/CommonTriggerExecutionScope.java +++ b/core/src/com/etheller/warsmash/parsers/jass/scope/CommonTriggerExecutionScope.java @@ -1,47 +1,139 @@ package com.etheller.warsmash.parsers.jass.scope; 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.CItem; 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.region.CRegion; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimerJass; public class CommonTriggerExecutionScope extends TriggerExecutionScope { - private final CUnit triggeringUnit; - private final CUnit filterUnit; - private final CUnit enumUnit; - private final CDestructable filterDestructable; - private final CDestructable enumDestructable; - private final CItem filterItem; - private final CItem enumItem; - private final CPlayerJass filterPlayer; - private final CPlayerJass enumPlayer; - private final CTimerJass expiringTimer; - private final CUnit enteringUnit; - private final CUnit leavingUnit; - private final CRegion triggeringRegion; + private CUnit triggeringUnit; + private CUnit filterUnit; + private CUnit enumUnit; + private CDestructable filterDestructable; + private CDestructable enumDestructable; + private CItem filterItem; + private CItem enumItem; + private CPlayerJass filterPlayer; + private CPlayerJass enumPlayer; + private CTimerJass expiringTimer; + private CUnit enteringUnit; + private CUnit leavingUnit; + 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, - final CUnit filterUnit, final CUnit enumUnit, final CDestructable filterDestructable, - 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 Trigger triggeringTrigger) { + super(triggeringTrigger); + } + + public CommonTriggerExecutionScope(final TriggerExecutionScope parentScope) { super(parentScope.getTriggeringTrigger()); - this.triggeringUnit = triggeringUnit; - this.filterUnit = filterUnit; - this.enumUnit = enumUnit; - this.filterDestructable = filterDestructable; - this.enumDestructable = enumDestructable; - this.filterItem = filterItem; - this.enumItem = enumItem; - this.filterPlayer = filterPlayer; - this.enumPlayer = enumPlayer; - this.expiringTimer = expiringTimer; - this.enteringUnit = enteringUnit; - this.leavingUnit = leavingUnit; - this.triggeringRegion = triggeringRegion; + if (parentScope instanceof CommonTriggerExecutionScope) { + copyFrom((CommonTriggerExecutionScope) parentScope); + } + } + + public CommonTriggerExecutionScope(final CommonTriggerExecutionScope parentScope) { + super(parentScope.getTriggeringTrigger()); + copyFrom(parentScope); + } + + private void copyFrom(final CommonTriggerExecutionScope parentScope) { + this.triggeringUnit = parentScope.triggeringUnit; + 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() { @@ -96,44 +188,225 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope { 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, final CUnit filterUnit) { - return new CommonTriggerExecutionScope(parentScope, null, filterUnit, null, null, null, null, null, null, null, - null, null, null, null); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + scope.filterUnit = filterUnit; + return scope; } public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CUnit enumUnit) { - return new CommonTriggerExecutionScope(parentScope, null, null, enumUnit, null, null, null, null, null, null, - null, null, null, null); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + scope.enumUnit = enumUnit; + return scope; } public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope, final CPlayerJass filterPlayer) { - return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, filterPlayer, - null, null, null, null, null); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + scope.filterPlayer = filterPlayer; + return scope; } public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CPlayerJass enumPlayer) { - return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, enumPlayer, - null, null, null, null); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + scope.enumPlayer = enumPlayer; + return scope; } public static CommonTriggerExecutionScope expiringTimer(final CTimerJass cTimerJass) { - return new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY, null, null, null, null, null, null, null, - null, null, cTimerJass, null, null, null); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(TriggerExecutionScope.EMPTY); + scope.expiringTimer = cTimerJass; + return scope; } public static CommonTriggerExecutionScope unitEnterRegionScope(final TriggerExecutionScope parentScope, final CUnit enteringUnit, final CRegion triggeringRegion) { - return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, null, null, - enteringUnit, null, triggeringRegion); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + scope.enteringUnit = enteringUnit; + scope.triggeringRegion = triggeringRegion; + return scope; } public static CommonTriggerExecutionScope unitLeaveRegionScope(final TriggerExecutionScope parentScope, final CUnit leavingUnit, final CRegion triggeringRegion) { - return new CommonTriggerExecutionScope(parentScope, null, null, null, null, null, null, null, null, null, null, - null, leavingUnit, triggeringRegion); + final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope); + 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; } } diff --git a/core/src/com/etheller/warsmash/util/WarsmashConstants.java b/core/src/com/etheller/warsmash/util/WarsmashConstants.java index 9d3e3f6..6fe01f9 100644 --- a/core/src/com/etheller/warsmash/util/WarsmashConstants.java +++ b/core/src/com/etheller/warsmash/util/WarsmashConstants.java @@ -29,4 +29,11 @@ public class WarsmashConstants { public static final boolean VERBOSE_LOGGING = true; public static final boolean ENABLE_DEBUG = false; 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; } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java b/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java index eefefeb..0b3ce1a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java @@ -516,7 +516,7 @@ public class MdxComplexInstance extends ModelInstance { } 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)"); } } @@ -532,7 +532,7 @@ public class MdxComplexInstance extends ModelInstance { group.render(this, this.scene.camera.viewProjectionMatrix); 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)"); } } @@ -883,22 +883,20 @@ public class MdxComplexInstance extends ModelInstance { public void setFrameByRatio(final float ratioOfAnimationCompleted) { if (this.sequence != -1) { 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; - float lastFloatingFrame = this.floatingFrame; - long sequenceLength = currentlyPlayingSequence.getInterval()[1] - start; - float newFloatingFrame = start - + (sequenceLength - * ratioOfAnimationCompleted); - float frameTime = newFloatingFrame-lastFloatingFrame; - if(frameTime < 0) { + final float lastFloatingFrame = this.floatingFrame; + final long sequenceLength = currentlyPlayingSequence.getInterval()[1] - start; + final float newFloatingFrame = start + (sequenceLength * ratioOfAnimationCompleted); + float frameTime = newFloatingFrame - lastFloatingFrame; + if (frameTime < 0) { frameTime += sequenceLength; } this.floatingFrame = newFloatingFrame; this.frame = (int) this.floatingFrame; this.blendTimeRemaining -= frameTime; int integerFrameTime = this.frame - lastIntegerFrame; - if(integerFrameTime < 0) { + if (integerFrameTime < 0) { integerFrameTime += sequenceLength; } 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 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 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; - } + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/tga/TgaFile.java b/core/src/com/etheller/warsmash/viewer5/handlers/tga/TgaFile.java index 8ac69dc..5552836 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/tga/TgaFile.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/tga/TgaFile.java @@ -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 { - throw new UnsupportedOperationException("Error " + name); + final int headerval = header[17] >> 4; + throw new UnsupportedOperationException("Error " + name + " (" + headerval + ")"); } return dst; diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java index df90328..178b166 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java @@ -466,24 +466,30 @@ public class War3MapViewer extends AbstractMdxModelViewer { // from either the map or the game, giving the map priority. SeekableByteChannel sbc; final CompoundDataSource compoundDataSource = war3Map.getCompoundDataSource(); - try (InputStream mapStream = compoundDataSource.getResourceAsStream(tileset + ".mpq")) { - if (mapStream == null) { + if (WarsmashConstants.FIX_FLAT_FILES_TILESET_LOADING) { + 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, 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, new SubdirDataSource(compoundDataSource, tileset + ".mpq/"), - new SubdirDataSource(compoundDataSource, "_tilesets/" + tileset + ".w3mod/"))); } } catch (final MPQException e) { @@ -723,29 +729,30 @@ public class War3MapViewer extends AbstractMdxModelViewer { } @Override - public void heroRevived(CUnit source) { + public void heroRevived(final CUnit source) { final AbilityUI reviveUI = War3MapViewer.this.abilityDataUI.getUI(ABILITY_REVIVE_RAWCODE); 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()); 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 final String unitShadow = row.getFieldAsString(UNIT_SHADOW, 0); - float unitX = source.getX(); - float unitY = source.getY(); + final float unitX = source.getX(); + final float unitY = source.getY(); if ((unitShadow != null) && !"_".equals(unitShadow)) { final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp"; final float shadowX = row.getFieldAsFloat(UNIT_SHADOW_X, 0); final float shadowY = row.getFieldAsFloat(UNIT_SHADOW_Y, 0); final float shadowWidth = row.getFieldAsFloat(UNIT_SHADOW_W, 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 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); } } @@ -770,8 +777,8 @@ public class War3MapViewer extends AbstractMdxModelViewer { } @Override - public void spawnSpellEffectOnUnit(CUnit unit, War3ID alias) { - AbilityUI abilityUI = abilityDataUI.getUI(alias); + public void spawnSpellEffectOnUnit(final CUnit unit, final War3ID alias) { + final AbilityUI abilityUI = War3MapViewer.this.abilityDataUI.getUI(alias); spawnEffectOnUnit(unit, abilityUI.getTargetArt(0)); } @@ -861,11 +868,10 @@ public class War3MapViewer extends AbstractMdxModelViewer { loadLightsAndShading(tileset); } - public void spawnFxOnOrigin(RenderUnit renderUnit, String heroLevelUpArt) { + public void spawnFxOnOrigin(final RenderUnit renderUnit, final String heroLevelUpArt) { final MdxModel heroLevelUpModel = loadModel(heroLevelUpArt); if (heroLevelUpModel != null) { - final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel - .addInstance(); + final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel.addInstance(); modelInstance.setTeamColor(renderUnit.playerIndex); final MdxModel model = (MdxModel) renderUnit.instance.model; @@ -880,15 +886,15 @@ public class War3MapViewer extends AbstractMdxModelViewer { if (index != -1) { final MdxNode attachment = renderUnit.instance.getAttachment(index); modelInstance.setParent(attachment); - } else { + } + else { modelInstance.setLocation(renderUnit.location); } modelInstance.setScene(War3MapViewer.this.worldScene); SequenceUtils.randomBirthSequence(modelInstance); - War3MapViewer.this.projectiles - .add(new RenderAttackInstant(modelInstance, War3MapViewer.this, - (float) Math.toRadians(renderUnit.getSimulationUnit().getFacing()))); + War3MapViewer.this.projectiles.add(new RenderAttackInstant(modelInstance, War3MapViewer.this, + (float) Math.toRadians(renderUnit.getSimulationUnit().getFacing()))); } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java index 9784c6a..1503580 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java @@ -364,6 +364,7 @@ public class Terrain { final String fileName = waterInfo.getField("texFile"); final List waterTextures = new ArrayList<>(); boolean anyWaterTextureNeedsSRGB = false; + int waterImageDimension = 128; for (int i = 0; i < this.waterTextureCount; i++) { final AnyExtensionImage imageInfo = ImageUtils.getAnyExtensionImageFixRGB(dataSource, fileName + (i < 10 ? "0" : "") + Integer.toString(i) + texturesExt, "water texture"); @@ -371,13 +372,15 @@ public class Terrain { if ((image.getWidth() != 128) || (image.getHeight() != 128)) { System.err .println("Odd water texture size detected of " + image.getWidth() + " x " + image.getHeight()); + waterImageDimension = image.getWidth(); } anyWaterTextureNeedsSRGB |= imageInfo.isNeedsSRGBFix(); waterTextures.add(image); } 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_T, GL30.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL30.GL_TEXTURE_2D_ARRAY, GL30.GL_TEXTURE_BASE_LEVEL, 0); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/TerrainShaders.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/TerrainShaders.java index 5cbe7a0..7d2c500 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/TerrainShaders.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/TerrainShaders.java @@ -153,7 +153,8 @@ public class TerrainShaders { " 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" + // "\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" + // " pathing_map_uv = (vPosition + pos) * 4; \r\n" + // "\r\n" + // diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java index f6d15ab..3bfa80f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java @@ -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.players.CAllianceType; 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.region.CRegionManager; 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 CWorldCollision worldCollision; private final CPathfindingProcessor[] pathfindingProcessors; - private final List[] playerHeroes; private final CGameplayConstants gameplayConstants; private final Random seededRandom; private float currentGameDayTimeElapsed; @@ -104,17 +104,15 @@ public class CSimulation implements CPlayerAPI { this.worldCollision = new CWorldCollision(entireMapBounds, this.gameplayConstants.getMaxCollisionRadius()); this.regionManager = new CRegionManager(entireMapBounds, pathingGrid); this.pathfindingProcessors = new CPathfindingProcessor[WarsmashConstants.MAX_PLAYERS]; - this.playerHeroes = new ArrayList[WarsmashConstants.MAX_PLAYERS]; for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) { this.pathfindingProcessors[i] = new CPathfindingProcessor(pathingGrid, this.worldCollision); - this.playerHeroes[i] = new ArrayList<>(); } this.seededRandom = seededRandom; this.players = new ArrayList<>(); for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) { final CBasePlayer configPlayer = config.getPlayer(i); 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() }, configPlayer); this.players.add(newPlayer); @@ -183,7 +181,7 @@ public class CSimulation implements CPlayerAPI { this.newUnits.add(unit); this.handleIdToUnit.put(unit.getHandleId(), unit); this.worldCollision.addUnit(unit); - if(unit.getHeroData() != null) { + if (unit.getHeroData() != null) { heroCreateEvent(unit); } return unit; @@ -269,7 +267,7 @@ public class CSimulation implements CPlayerAPI { } this.handleIdToUnit.remove(unit.getHandleId()); this.simulationRenderController.removeUnit(unit); - this.playerHeroes[unit.getPlayerIndex()].remove(unit); + getPlayerHeroes(unit.getPlayerIndex()).remove(unit); unit.onRemove(this); } } @@ -316,7 +314,7 @@ public class CSimulation implements CPlayerAPI { } this.handleIdToUnit.remove(unit.getHandleId()); this.simulationRenderController.removeUnit(unit); - this.playerHeroes[unit.getPlayerIndex()].remove(unit); + getPlayerHeroes(unit.getPlayerIndex()).remove(unit); unit.onRemove(this); } this.removedUnits.clear(); @@ -390,6 +388,7 @@ public class CSimulation implements CPlayerAPI { public void unitTrainedEvent(final CUnit trainingUnit, final CUnit trainedUnit) { this.simulationRenderController.spawnUnitReadySound(trainedUnit); } + public void heroReviveEvent(final CUnit trainingUnit, final CUnit trainedUnit) { this.simulationRenderController.heroRevived(trainedUnit); this.simulationRenderController.spawnUnitReadySound(trainedUnit); @@ -404,11 +403,12 @@ public class CSimulation implements CPlayerAPI { } public void unitGainLevelEvent(final CUnit unit) { + this.players.get(unit.getPlayerIndex()).fireHeroLevelEvents(unit); this.simulationRenderController.spawnGainLevelEffect(unit); } 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) { @@ -420,7 +420,7 @@ public class CSimulation implements CPlayerAPI { } public List getPlayerHeroes(final int playerIndex) { - return this.playerHeroes[playerIndex]; + return this.players.get(playerIndex).getHeroes(); } public void unitsLoaded() { @@ -455,8 +455,8 @@ public class CSimulation implements CPlayerAPI { this.simulationRenderController.spawnEffectOnUnit(unit, effectPath); } - public void createSpellEffectOnUnit(CUnit unit, War3ID alias) { - simulationRenderController.spawnSpellEffectOnUnit(unit, alias); + public void createSpellEffectOnUnit(final CUnit unit, final War3ID alias) { + this.simulationRenderController.spawnSpellEffectOnUnit(unit, alias); } public void unitSoundEffectEvent(final CUnit caster, final War3ID alias) { @@ -480,16 +480,16 @@ public class CSimulation implements CPlayerAPI { }; } - public void heroDeathEvent(CUnit cUnit) { - getPlayer(cUnit.getPlayerIndex()).onHeroDeath(); + public void heroDeathEvent(final CUnit cUnit) { + getPlayer(cUnit.getPlayerIndex()).onHeroDeath(cUnit); } - public void removeItem(CItem cItem) { + public void removeItem(final CItem cItem) { cItem.setHidden(true); // TODO fix cItem.setLife(this, 0); - } + } - private static final class TimeOfDayVariableEvent extends VariableEvent { + private static final class TimeOfDayVariableEvent extends VariableEvent { private final GlobalScope globalScope; public TimeOfDayVariableEvent(final Trigger trigger, final CLimitOp limitOp, final double doubleValue, @@ -502,4 +502,20 @@ public class CSimulation implements CPlayerAPI { 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; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/CBasePlayer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/CBasePlayer.java index 931d19a..3709093 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/CBasePlayer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/CBasePlayer.java @@ -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.trigger.enumtypes.CPlayerSlotState; -public class CBasePlayer implements CPlayerJass { +public abstract class CBasePlayer implements CPlayerJass { private final int id; private String name; private int team; @@ -59,6 +59,7 @@ public class CBasePlayer implements CPlayerJass { } } + @Override public int getId() { return this.id; } @@ -138,6 +139,7 @@ public class CBasePlayer implements CPlayerJass { } } + @Override public boolean hasAlliance(final int otherPlayerIndex, final CAllianceType allianceType) { final EnumSet alliancesWithOtherPlayer = this.alliances[otherPlayerIndex]; return alliancesWithOtherPlayer.contains(allianceType); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfig.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfig.java index dec0f41..d38e396 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfig.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfig.java @@ -30,7 +30,7 @@ public class War3MapConfig implements CPlayerAPI { this.players = new CBasePlayer[maxPlayers]; for (int i = 0; i < maxPlayers; i++) { this.startLocations[i] = new War3MapConfigStartLoc(); - this.players[i] = new CBasePlayer(i); + this.players[i] = new War3MapConfigPlayer(i); } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfigPlayer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfigPlayer.java new file mode 100644 index 0000000..ec7647f --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/config/War3MapConfigPlayer.java @@ -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) { + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java index b116505..0bf8ea4 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java @@ -1,14 +1,22 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players; +import java.util.ArrayList; +import java.util.EnumMap; import java.util.HashMap; +import java.util.List; 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.viewer5.handlers.w3x.simulation.CPlayerStateListener; 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.CUnitType; 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 { private final CRace race; @@ -18,6 +26,9 @@ public class CPlayer extends CBasePlayer { private int foodCap; private int foodUsed; private final Map rawcodeToTechtreeUnlocked = new HashMap<>(); + private final List heroes = new ArrayList<>(); + private final EnumMap> eventTypeToEvents = new EnumMap<>( + JassGameEventsWar3.class); // 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 @@ -139,7 +150,7 @@ public class CPlayer extends CBasePlayer { this.stateNotifier.goldChanged(); } - public void refund(int gold, int lumber) { + public void refund(final int gold, final int lumber) { this.gold += gold; this.lumber += lumber; this.stateNotifier.lumberChanged(); @@ -156,7 +167,57 @@ public class CPlayer extends CBasePlayer { this.stateNotifier.foodChanged(); } - public void onHeroDeath() { - stateNotifier.heroDeath(); - } + public void onHeroDeath(final CUnit hero) { + 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 eventList = getEventList(eventType); + if (eventList != null) { + for (final CPlayerEvent event : eventList) { + event.fire(hero, eventScope); + } + } + } + + public List getHeroes() { + return this.heroes; + } + + public void fireHeroLevelEvents(final CUnit hero) { + firePlayerUnitEvents(hero, CommonTriggerExecutionScope.playerHeroRevivableScope(hero), + JassGameEventsWar3.EVENT_PLAYER_HERO_LEVEL); + } + + private List getOrCreateEventList(final JassGameEventsWar3 eventType) { + List playerEvents = this.eventTypeToEvents.get(eventType); + if (playerEvents == null) { + playerEvents = new ArrayList<>(); + this.eventTypeToEvents.put(eventType, playerEvents); + } + return playerEvents; + } + + private List 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 eventList = getEventList(playerEvent.getEventType()); + if (eventList != null) { + eventList.remove(playerEvent); + } + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerEvent.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerEvent.java new file mode 100644 index 0000000..ce67ff3 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerEvent.java @@ -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); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerJass.java index 9a14f0b..3229ec5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerJass.java @@ -1,5 +1,9 @@ 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; public interface CPlayerJass { @@ -46,4 +50,9 @@ public interface CPlayerJass { boolean isRacePrefSet(CRacePreference pref); String getName(); + + RemovableTriggerEvent addEvent(final GlobalScope globalScope, final Trigger whichTrigger, + final JassGameEventsWar3 eventType); + + void removeEvent(CPlayerEvent playerEvent); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialog.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialog.java new file mode 100644 index 0000000..52ae6dc --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialog.java @@ -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 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); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialogButton.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialogButton.java new file mode 100644 index 0000000..3da2b0a --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/uidialog/JassUIDialogButton.java @@ -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; + } +} diff --git a/jassparser/src/com/etheller/interpreter/ast/scope/trigger/RemovableTriggerEvent.java b/jassparser/src/com/etheller/interpreter/ast/scope/trigger/RemovableTriggerEvent.java index b5b5da8..9606e3a 100644 --- a/jassparser/src/com/etheller/interpreter/ast/scope/trigger/RemovableTriggerEvent.java +++ b/jassparser/src/com/etheller/interpreter/ast/scope/trigger/RemovableTriggerEvent.java @@ -2,4 +2,10 @@ package com.etheller.interpreter.ast.scope.trigger; public interface RemovableTriggerEvent { void remove(); + + RemovableTriggerEvent DO_NOTHING = new RemovableTriggerEvent() { + @Override + public void remove() { + } + }; }