diff --git a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java index ebcb381..a3a9ef4 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java +++ b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java @@ -69,7 +69,6 @@ import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.viewer5.Scene; import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound; import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; -import com.etheller.warsmash.viewer5.handlers.w3x.environment.RenderCorner; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderDestructable; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.ItemUI; @@ -84,6 +83,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.GetAbilityByRawcodeVisitor; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.ai.AIDifficulty; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CPlayerAPI; @@ -1027,7 +1027,7 @@ public class Jass2 { final TriggerBooleanExpression filter = nullable(arguments, 3, ObjectJassValueVisitor.getInstance()); CommonEnvironment.this.simulation.getWorldCollision().enumUnitsInRect( - tempRect.set(x - radius, y - radius, radius, radius), new CUnitEnumFunction() { + tempRect.set(x - radius, y - radius, radius * 2, radius * 2), new CUnitEnumFunction() { @Override public boolean call(final CUnit unit) { @@ -1262,7 +1262,7 @@ public class Jass2 { final JassFunction callback = arguments.get(1).visit(JassFunctionJassValueVisitor.getInstance()); try { for (final CUnit unit : group) { - globalScope.queueFunction(callback, + callback.call(Collections.emptyList(), globalScope, CommonTriggerExecutionScope.enumScope(triggerScope, unit)); } } @@ -2541,9 +2541,19 @@ public class Jass2 { final double y = arguments.get(2).visit(RealJassValueVisitor.getInstance()); final double facing = arguments.get(3).visit(RealJassValueVisitor.getInstance()); final War3ID blightedMineRawcode = War3ID.fromString("ugol"); + final War3ID goldMineRawcode = War3ID.fromString("ngol"); player.addTechtreeUnlocked(blightedMineRawcode); - return new HandleJassValue(unitType, CommonEnvironment.this.simulation - .createUnit(blightedMineRawcode, player.getId(), (float) x, (float) y, (float) facing)); + final CUnit blightedMine = CommonEnvironment.this.simulation.createUnit(blightedMineRawcode, + player.getId(), (float) x, (float) y, (float) facing); + final CUnit goldMine = CommonEnvironment.this.simulation.createUnit(goldMineRawcode, + WarsmashConstants.MAX_PLAYERS - 1, (float) x, (float) y, (float) facing); + goldMine.setHidden(true); + for (final CAbility ability : blightedMine.getAbilities()) { + if (ability instanceof CAbilityBlightedGoldMine) { + ((CAbilityBlightedGoldMine) ability).setParentMine(goldMine, goldMine.getGoldMineData()); + } + } + return new HandleJassValue(unitType, blightedMine); } }); jassProgramVisitor.getJassNativeManager().createNative("SetUnitColor", new JassFunction() { @@ -2567,6 +2577,14 @@ public class Jass2 { return null; } }); + jassProgramVisitor.getJassNativeManager().createNative("GetResourceAmount", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + return new IntegerJassValue(whichUnit.getGold()); + } + }); jassProgramVisitor.getJassNativeManager().createNative("SetUnitState", new JassFunction() { @Override public JassValue call(final List arguments, final GlobalScope globalScope, @@ -3432,7 +3450,7 @@ public class Jass2 { @Override public JassValue call(final List arguments, final GlobalScope globalScope, final TriggerExecutionScope triggerScope) { - final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + final CUnit whichUnit = nullable(arguments, 0, ObjectJassValueVisitor.getInstance()); if (whichUnit == null) { return new IntegerJassValue(0); } @@ -3589,48 +3607,9 @@ public class Jass2 { final Point2D.Double whichLocation = arguments.get(1).visit(ObjectJassValueVisitor.getInstance()); final float radius = arguments.get(2).visit(RealJassValueVisitor.getInstance()).floatValue(); final boolean addBlight = arguments.get(3).visit(BooleanJassValueVisitor.getInstance()); - float whichLocationX = (float) whichLocation.x; - float whichLocationY = (float) whichLocation.y; - final int cellX = war3MapViewer.terrain.get128CellX(whichLocationX); - final int cellY = war3MapViewer.terrain.get128CellY(whichLocationY); - whichLocationX = war3MapViewer.terrain.get128WorldCoordinateFromCellX(cellX); - whichLocationY = war3MapViewer.terrain.get128WorldCoordinateFromCellY(cellY); - final Rectangle blightRectangle = new Rectangle(whichLocationX - radius, whichLocationY - radius, - radius * 2, radius * 2); - final float blightRectangleMaxX = blightRectangle.x + blightRectangle.width; - final float blightRectangleMaxY = blightRectangle.y + blightRectangle.height; - final float rSquared = radius * radius; - for (float x = blightRectangle.x; x < blightRectangleMaxX; x += 128.0f) { - for (float y = blightRectangle.y; y < blightRectangleMaxY; y += 128.0f) { - final float dx = x - whichLocationX; - final float dy = y - whichLocationY; - final float distSquared = (dx * dx) + (dy * dy); - if (distSquared <= rSquared) { - for (float pathX = -64; pathX < 64; pathX += 32f) { - for (float pathY = -64; pathY < 64; pathY += 32f) { - final float blightX = x + pathX + 16; - final float blightY = y + pathY + 16; - if (CommonEnvironment.this.simulation.getPathingGrid().contains(blightX, - blightY)) { - CommonEnvironment.this.simulation.getPathingGrid().setBlighted(blightX, - blightY, addBlight); - } - } - } - final RenderCorner corner = war3MapViewer.terrain.getCorner(x, y); - if (corner != null) { - corner.setBlight(true); - } - } - } - } - final int cellMinX = war3MapViewer.terrain.get128CellX(blightRectangle.x); - final int cellMinY = war3MapViewer.terrain.get128CellY(blightRectangle.y); - final int cellMaxX = war3MapViewer.terrain.get128CellX(blightRectangleMaxX); - final int cellMaxY = war3MapViewer.terrain.get128CellY(blightRectangleMaxY); - final Rectangle blightRectangleCellUnits = new Rectangle(cellMinX, cellMinY, cellMaxX - cellMinX, - cellMaxY - cellMinY); - war3MapViewer.terrain.updateGroundTextures(blightRectangleCellUnits); + final float whichLocationX = (float) whichLocation.x; + final float whichLocationY = (float) whichLocation.y; + war3MapViewer.setBlight(whichLocationX, whichLocationY, radius, addBlight); return null; } }); 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 4ffaebc..5394b40 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java @@ -84,6 +84,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag; import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover; import com.etheller.warsmash.viewer5.handlers.w3x.environment.BuildingShadow; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.RemovablePathingMapInstance; +import com.etheller.warsmash.viewer5.handlers.w3x.environment.RenderCorner; import com.etheller.warsmash.viewer5.handlers.w3x.environment.Terrain; import com.etheller.warsmash.viewer5.handlers.w3x.environment.Terrain.Splat; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderAttackInstant; @@ -1010,6 +1011,11 @@ public class War3MapViewer extends AbstractMdxModelViewer { oldRenderPeer.setPreferredSelectionReplacement(newRenderPeer); } + + @Override + public void setBlight(final float x, final float y, final float radius, final boolean blighted) { + War3MapViewer.this.setBlight(x, y, radius, blighted); + } }, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, this.commandErrorListener); this.walkableObjectsTree = new Quadtree<>(this.terrain.getEntireMap()); @@ -2495,4 +2501,45 @@ public class War3MapViewer extends AbstractMdxModelViewer { } return (MdxModel) load(mdxPath, War3MapViewer.this.mapPathSolver, War3MapViewer.this.solverParams); } + + public void setBlight(float whichLocationX, float whichLocationY, final float radius, final boolean blighted) { + final int cellX = this.terrain.get128CellX(whichLocationX); + final int cellY = this.terrain.get128CellY(whichLocationY); + whichLocationX = this.terrain.get128WorldCoordinateFromCellX(cellX); + whichLocationY = this.terrain.get128WorldCoordinateFromCellY(cellY); + final Rectangle blightRectangle = new Rectangle(whichLocationX - radius, whichLocationY - radius, radius * 2, + radius * 2); + final float blightRectangleMaxX = blightRectangle.x + blightRectangle.width; + final float blightRectangleMaxY = blightRectangle.y + blightRectangle.height; + final float rSquared = radius * radius; + for (float x = blightRectangle.x; x < blightRectangleMaxX; x += 128.0f) { + for (float y = blightRectangle.y; y < blightRectangleMaxY; y += 128.0f) { + final float dx = x - whichLocationX; + final float dy = y - whichLocationY; + final float distSquared = (dx * dx) + (dy * dy); + if (distSquared <= rSquared) { + for (float pathX = -64; pathX < 64; pathX += 32f) { + for (float pathY = -64; pathY < 64; pathY += 32f) { + final float blightX = x + pathX + 16; + final float blightY = y + pathY + 16; + if (this.simulation.getPathingGrid().contains(blightX, blightY)) { + this.simulation.getPathingGrid().setBlighted(blightX, blightY, blighted); + } + } + } + final RenderCorner corner = this.terrain.getCorner(x, y); + if (corner != null) { + corner.setBlight(blighted); + } + } + } + } + final int cellMinX = this.terrain.get128CellX(blightRectangle.x); + final int cellMinY = this.terrain.get128CellY(blightRectangle.y); + final int cellMaxX = this.terrain.get128CellX(blightRectangleMaxX); + final int cellMaxY = this.terrain.get128CellY(blightRectangleMaxY); + final Rectangle blightRectangleCellUnits = new Rectangle(cellMinX, cellMinY, cellMaxX - cellMinX, + cellMaxY - cellMinY); + this.terrain.updateGroundTextures(blightRectangleCellUnits); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderWidget.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderWidget.java index 5b7821d..0fd5658 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderWidget.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderWidget.java @@ -125,7 +125,8 @@ public interface RenderWidget { final boolean allowRarityVariations) { this.animationQueue.clear(); if (force || (animationName != this.currentAnimation) - || !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags)) { + || !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags) + || this.instance.sequenceEnded) { this.currentSpeedRatio = speedRatio; this.recycleSet.clear(); this.recycleSet.addAll(this.secondaryAnimationTags); @@ -147,6 +148,7 @@ public interface RenderWidget { } } + @Override public void playAnimationWithDuration(final boolean force, final PrimaryTag animationName, final EnumSet secondaryAnimationTags, final float duration, final boolean allowRarityVariations) { 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 8cad469..c993fd6 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 @@ -667,4 +667,8 @@ public class CSimulation implements CPlayerAPI { return !this.daytime; } + public void setBlight(final float x, final float y, final float radius, final boolean blighted) { + this.simulationRenderController.setBlight(x, y, radius, blighted); + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java index fbcf449..e39a72f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java @@ -27,6 +27,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; @@ -42,7 +43,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorMove; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorPatrol; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorStop; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.AbilityDisableWhileUnderConstructionVisitor; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.AbilityDisableWhileUpgradingVisitor; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CRegenType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; @@ -1180,6 +1181,11 @@ public class CUnit extends CWidget { } } } + for (int i = this.abilities.size() - 1; i >= 0; i--) { + // okay if it removes self from this during onDeath() because of reverse + // iteration order + this.abilities.get(i).onDeath(simulation, this); + } fireDeathEvents(simulation); final List eventList = getEventList(JassGameEventsWar3.EVENT_UNIT_DEATH); if (eventList != null) { @@ -1863,6 +1869,9 @@ public class CUnit extends CWidget { if (ability instanceof CAbilityGoldMine) { return ((CAbilityGoldMine) ability).getGold(); } + if (ability instanceof CAbilityBlightedGoldMine) { + return ((CAbilityBlightedGoldMine) ability).getGold(); + } } return 0; } @@ -1872,6 +1881,9 @@ public class CUnit extends CWidget { if (ability instanceof CAbilityGoldMine) { ((CAbilityGoldMine) ability).setGold(goldAmount); } + if (ability instanceof CAbilityBlightedGoldMine) { + ((CAbilityBlightedGoldMine) ability).setGold(goldAmount); + } } } @@ -1980,6 +1992,9 @@ public class CUnit extends CWidget { else { player.removeTechtreeUnlocked(this.unitType.getTypeId()); } + setHidden(true); + // setting hidden to let things that refer to this before it gets garbage + // collected see it as basically worthless } simulation.getWorldCollision().removeUnit(this); } @@ -2061,7 +2076,7 @@ public class CUnit extends CWidget { player.charge(goldCost, lumberCost); add(game, new CAbilityBuildInProgress(game.getHandleIdAllocator().createId())); for (final CAbility ability : getAbilities()) { - ability.visit(AbilityDisableWhileUnderConstructionVisitor.INSTANCE); + ability.visit(AbilityDisableWhileUpgradingVisitor.INSTANCE); } player.addTechtreeInProgress(rawcode); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java index c0e5ff5..98578fe 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java @@ -86,6 +86,8 @@ public class CUnitType { private final List> requirementTiers; private final float castBackswingPoint; private final float castPoint; + private final boolean canBeBuiltOnThem; + private final boolean canBuildOnMe; public CUnitType(final String name, final String legacyName, final War3ID typeId, final int maxLife, final float lifeRegen, final float manaRegen, final CRegenType lifeRegenType, final int manaInitial, @@ -104,7 +106,8 @@ public class CUnitType { final float agilityPerLevel, final int intelligence, final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute, final List heroAbilityList, final List heroProperNames, final int properNamesCount, final boolean canFlee, final int priority, - final boolean revivesHeroes, final int pointValue, final float castBackswingPoint, final float castPoint) { + final boolean revivesHeroes, final int pointValue, final float castBackswingPoint, final float castPoint, + final boolean canBeBuiltOnThem, final boolean canBuildOnMe) { this.name = name; this.legacyName = legacyName; this.typeId = typeId; @@ -167,6 +170,8 @@ public class CUnitType { this.pointValue = pointValue; this.castBackswingPoint = castBackswingPoint; this.castPoint = castPoint; + this.canBeBuiltOnThem = canBeBuiltOnThem; + this.canBuildOnMe = canBuildOnMe; } public String getName() { @@ -422,4 +427,13 @@ public class CUnitType { public float getCastPoint() { return this.castPoint; } + + // "isCan" - these method names are computer generated, cut me some slack + public boolean isCanBeBuiltOnThem() { + return this.canBeBuiltOnThem; + } + + public boolean isCanBuildOnMe() { + return this.canBuildOnMe; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWorldCollision.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWorldCollision.java index ee3b23d..e7799d5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWorldCollision.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWorldCollision.java @@ -45,7 +45,8 @@ public class CWorldCollision { // buildings are here so that we can include them when enumerating all units in // a rect, but they don't really move dynamically, this is kind of pointless this.buildingUnitCollision.add(unit, bounds); - } else { + } + else { final MovementType movementType = unit.getUnitType().getMovementType(); if (movementType != null) { switch (movementType) { @@ -88,7 +89,8 @@ public class CWorldCollision { if (bounds != null) { if (unit.isBuilding()) { this.buildingUnitCollision.remove(unit, bounds); - } else { + } + else { final MovementType movementType = unit.getUnitType().getMovementType(); if (movementType != null) { switch (movementType) { @@ -126,6 +128,14 @@ public class CWorldCollision { this.buildingUnitCollision.intersect(rect, this.eachUnitOnlyOnceIntersector); } + public void enumBuildingsInRect(final Rectangle rect, final QuadtreeIntersector callback) { + this.buildingUnitCollision.intersect(rect, callback); + } + + public void enumBuildingsAtPoint(final float x, final float y, final QuadtreeIntersector callback) { + this.buildingUnitCollision.intersect(x, y, callback); + } + public void enumDestructablesInRect(final Rectangle rect, final CDestructableEnumFunction callback) { this.destructablesForEnum.intersect(rect, this.destructableEnumIntersector.reset(callback)); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbility.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbility.java index 7664f44..48b36a1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbility.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbility.java @@ -16,6 +16,8 @@ public interface CAbility extends CAbilityView { void onTick(CSimulation game, CUnit unit); + void onDeath(CSimulation game, CUnit cUnit); + void onCancelFromQueue(CSimulation game, CUnit unit, int orderId); /* return false to not do anything, such as for toggling autocast */ diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java index d37610c..b2690b0 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java @@ -187,4 +187,8 @@ public class CAbilityAttack extends AbstractCAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityGenericDoNothing.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityGenericDoNothing.java index 273708a..f3c0308 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityGenericDoNothing.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityGenericDoNothing.java @@ -87,4 +87,8 @@ public class CAbilityGenericDoNothing extends AbstractGenericAliasedAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityMove.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityMove.java index ac37866..fd39091 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityMove.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityMove.java @@ -93,13 +93,15 @@ public class CAbilityMove extends AbstractCAbility { } @Override - public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) { + public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, + final AbilityTarget target) { return true; } @Override public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) { - CBehavior followBehavior = caster.getFollowBehavior().reset(orderId == OrderIds.smart ? OrderIds.move : orderId, (CUnit) target); + final CBehavior followBehavior = caster.getFollowBehavior() + .reset(orderId == OrderIds.smart ? OrderIds.move : orderId, (CUnit) target); caster.setDefaultBehavior(followBehavior); return followBehavior; } @@ -134,4 +136,8 @@ public class CAbilityMove extends AbstractCAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/blight/CAbilityBlight.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/blight/CAbilityBlight.java new file mode 100644 index 0000000..2588361 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/blight/CAbilityBlight.java @@ -0,0 +1,120 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.blight; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.util.WarsmashConstants; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +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.abilities.generic.AbstractGenericNoIconAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver; + +public class CAbilityBlight extends AbstractGenericNoIconAbility { + + private boolean createsBlight; + private float expansionAmount; + private float areaOfEffect; + private int ticksPerBlightExpansion; + + private float currentArea; + private int lastExpansionTick; + + public CAbilityBlight(final int handleId, final War3ID alias, final boolean createsBlight, + final float expansionAmount, final float areaOfEffect, final float gameSecondsPerBlightExpansion) { + super(handleId, alias); + this.createsBlight = createsBlight; + this.expansionAmount = expansionAmount; + this.areaOfEffect = areaOfEffect; + setGameSecondsPerBlightExpansion(gameSecondsPerBlightExpansion); + } + + public void setGameSecondsPerBlightExpansion(final float gameSecondsPerBlightExpansion) { + this.ticksPerBlightExpansion = (int) StrictMath + .ceil(gameSecondsPerBlightExpansion / WarsmashConstants.SIMULATION_STEP_TIME); + } + + @Override + public void onAdd(final CSimulation game, final CUnit unit) { + } + + @Override + public void onRemove(final CSimulation game, final CUnit unit) { + } + + @Override + public void onTick(final CSimulation game, final CUnit unit) { + if (!isDisabled()) { + final int currentTick = game.getGameTurnTick(); + if ((currentTick - this.lastExpansionTick) >= this.ticksPerBlightExpansion) { + if (this.currentArea < this.areaOfEffect) { + this.currentArea = Math.min(this.areaOfEffect, this.currentArea + this.expansionAmount); + game.setBlight(unit.getX(), unit.getY(), this.currentArea, this.createsBlight); + } + this.lastExpansionTick = currentTick; + } + } + } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + + @Override + public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { + } + + @Override + public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) { + return null; + } + + @Override + public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, + final AbilityPointTarget point) { + return null; + } + + @Override + public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) { + return null; + } + + @Override + public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target, + final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, + final AbilityPointTarget target, final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId, + final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId, + final AbilityActivationReceiver receiver) { + receiver.notAnActiveAbility(); + } + + public void setCreatesBlight(final boolean createsBlight) { + this.createsBlight = createsBlight; + } + + public void setExpansionAmount(final float expansionAmount) { + this.expansionAmount = expansionAmount; + } + + public void setAreaOfEffect(final float areaOfEffect) { + this.areaOfEffect = areaOfEffect; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/AbstractCAbilityBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/AbstractCAbilityBuild.java index a75a5e4..b2a5726 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/AbstractCAbilityBuild.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/AbstractCAbilityBuild.java @@ -135,4 +135,8 @@ public abstract class AbstractCAbilityBuild extends AbstractCAbility implements @Override public void onTick(final CSimulation game, final CUnit unit) { } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java index 4b1c02b..8e523e4 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java @@ -43,14 +43,25 @@ public class CAbilityBuildInProgress extends AbstractCAbility { caster.cancelUpgrade(game); } else { - final CUnitType unitType = caster.getUnitType(); - player.refundFor(unitType); - player.removeTechtreeInProgress(unitType.getTypeId()); caster.setLife(game, 0); } return false; } + @Override + public void onDeath(final CSimulation game, final CUnit caster) { + final CPlayer player = game.getPlayer(caster.getPlayerIndex()); + if (caster.isUpgrading()) { + player.removeTechtreeInProgress(caster.getUpgradeIdType()); + caster.cancelUpgrade(game); + } + else { + final CUnitType unitType = caster.getUnitType(); + player.refundFor(unitType); + player.removeTechtreeInProgress(unitType.getTypeId()); + } + } + @Override public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) { return null; diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityColdArrows.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityColdArrows.java index 88df0d3..6aef41a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityColdArrows.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityColdArrows.java @@ -128,4 +128,8 @@ public class CAbilityColdArrows extends AbstractGenericAliasedAbility { @Override public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityInvulnerable.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityInvulnerable.java index 4d14ecd..66d84a1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityInvulnerable.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/combat/CAbilityInvulnerable.java @@ -74,4 +74,8 @@ public class CAbilityInvulnerable extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/generic/AbstractGenericSingleIconActiveAbility.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/generic/AbstractGenericSingleIconActiveAbility.java index ef823b9..df2cec5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/generic/AbstractGenericSingleIconActiveAbility.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/generic/AbstractGenericSingleIconActiveAbility.java @@ -97,4 +97,8 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractGen return 0; } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityAcolyteHarvest.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityAcolyteHarvest.java new file mode 100644 index 0000000..52ed0e5 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityAcolyteHarvest.java @@ -0,0 +1,145 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +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.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericSingleIconActiveAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver.TeamType; + +public class CAbilityAcolyteHarvest extends AbstractGenericSingleIconActiveAbility { + private float castRange; + private float duration; + private CBehaviorAcolyteHarvest behaviorAcolyteHarvest; + + public CAbilityAcolyteHarvest(final int handleId, final War3ID alias, final float castRange, final float duration) { + super(handleId, alias); + this.castRange = castRange; + this.duration = duration; + } + + @Override + public void onAdd(final CSimulation game, final CUnit unit) { + this.behaviorAcolyteHarvest = new CBehaviorAcolyteHarvest(unit, this); + } + + @Override + public void onRemove(final CSimulation game, final CUnit unit) { + } + + @Override + public void onTick(final CSimulation game, final CUnit unit) { + } + + @Override + public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) { + return this.behaviorAcolyteHarvest.reset(target); + } + + @Override + public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, + final AbilityPointTarget point) { + return caster.pollNextOrderBehavior(game); + } + + @Override + public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) { + return caster.pollNextOrderBehavior(game); + } + + @Override + public int getBaseOrderId() { + return OrderIds.acolyteharvest; + } + + @Override + public boolean isToggleOn() { + return false; + } + + @Override + protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId, + final AbilityActivationReceiver receiver) { + receiver.useOk(); + } + + @Override + protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId, + final CWidget target, final AbilityTargetCheckReceiver receiver) { + if (target instanceof CUnit) { + final CUnit targetUnit = (CUnit) target; + boolean isBlightedMine = false; + for (final CAbility ability : targetUnit.getAbilities()) { + if (ability instanceof CAbilityBlightedGoldMine) { + isBlightedMine = true; + } + } + if (isBlightedMine) { + if (targetUnit.getPlayerIndex() == unit.getPlayerIndex()) { + receiver.targetOk(target); + } + else { + receiver.mustTargetTeamType(TeamType.PLAYER_UNITS); + } + } + else { + receiver.mustTargetResources(); + } + } + else { + receiver.mustTargetResources(); + } + } + + @Override + protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId, + final CWidget target, final AbilityTargetCheckReceiver receiver) { + innerCheckCanTarget(game, unit, orderId, target, receiver); + } + + @Override + protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId, + final AbilityPointTarget target, final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId, + final AbilityPointTarget target, final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId, + final AbilityTargetCheckReceiver receiver) { + receiver.orderIdNotAccepted(); + } + + @Override + public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { + } + + public void setCastRange(final float castRange) { + this.castRange = castRange; + } + + public float getCastRange() { + return this.castRange; + } + + public void setDuration(final float duration) { + this.duration = duration; + } + + public float getDuration() { + return this.duration; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityReturnResources.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityReturnResources.java index b18ff19..92381b7 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityReturnResources.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/harvest/CAbilityReturnResources.java @@ -99,4 +99,8 @@ public class CAbilityReturnResources extends AbstractGenericAliasedAbility { public void setAcceptedResourceTypes(final EnumSet acceptedResourceTypes) { this.acceptedResourceTypes = acceptedResourceTypes; } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/hero/CAbilityHero.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/hero/CAbilityHero.java index 2a26aa0..ce9b274 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/hero/CAbilityHero.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/hero/CAbilityHero.java @@ -397,4 +397,8 @@ public class CAbilityHero extends AbstractCAbility { public Set getSkillsAvailable() { return this.skillsAvailable; } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/inventory/CAbilityInventory.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/inventory/CAbilityInventory.java index 309ed34..29113b8 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/inventory/CAbilityInventory.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/inventory/CAbilityInventory.java @@ -361,4 +361,15 @@ public class CAbilityInventory extends AbstractGenericNoIconAbility { } } + @Override + public void onDeath(final CSimulation game, final CUnit hero) { + if (this.dropItemsOnDeath) { + for (int i = 0; i < this.itemsHeld.length; i++) { + if (this.itemsHeld[i] != null) { + dropItem(game, hero, i, hero.getX(), hero.getY(), false); + } + } + } + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemAttackBonus.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemAttackBonus.java index 112b93e..6982f2c 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemAttackBonus.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemAttackBonus.java @@ -81,4 +81,8 @@ public class CAbilityItemAttackBonus extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemDefenseBonus.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemDefenseBonus.java index 3b6b4bd..fdf01e6 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemDefenseBonus.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemDefenseBonus.java @@ -76,4 +76,8 @@ public class CAbilityItemDefenseBonus extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemLifeBonus.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemLifeBonus.java index c6724c7..867dad0 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemLifeBonus.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemLifeBonus.java @@ -86,4 +86,8 @@ public class CAbilityItemLifeBonus extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemPermanentStatGain.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemPermanentStatGain.java index eb251cc..d1c67c7 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemPermanentStatGain.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemPermanentStatGain.java @@ -88,4 +88,8 @@ public class CAbilityItemPermanentStatGain extends AbstractGenericNoIconAbility public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemStatBonus.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemStatBonus.java index 38bfe12..25c6697 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemStatBonus.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/item/CAbilityItemStatBonus.java @@ -88,4 +88,8 @@ public class CAbilityItemStatBonus extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityBlightedGoldMine.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityBlightedGoldMine.java index b029b99..554d895 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityBlightedGoldMine.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityBlightedGoldMine.java @@ -1,21 +1,32 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine; +import com.badlogic.gdx.math.Vector2; import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; 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.abilities.generic.AbstractGenericNoIconAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType; public class CAbilityBlightedGoldMine extends AbstractGenericNoIconAbility { - private int gold; - private final int goldPerInterval; - private final float intervalDuration; - private final int maxNumberOfMiners; - private final float radiusOfMiningRing; + public static final int NO_MINER = -1; + private CUnit parentGoldMineUnit; + private CAbilityGoldMine parentGoldMineAbility; + private int goldPerInterval; + private float intervalDuration; + private int maxNumberOfMiners; + private float radiusOfMiningRing; + private final CBehaviorAcolyteHarvest[] activeMiners; + private final Vector2[] minerLocs; + private int currentActiveMinerCount; + private int lastIncomeTick; public CAbilityBlightedGoldMine(final int handleId, final War3ID alias, final int goldPerInterval, final float intervalDuration, final int maxNumberOfMiners, final float radiusOfMiningRing) { @@ -24,11 +35,26 @@ public class CAbilityBlightedGoldMine extends AbstractGenericNoIconAbility { this.intervalDuration = intervalDuration; this.maxNumberOfMiners = maxNumberOfMiners; this.radiusOfMiningRing = radiusOfMiningRing; + this.activeMiners = new CBehaviorAcolyteHarvest[maxNumberOfMiners]; + this.minerLocs = new Vector2[maxNumberOfMiners]; + } + + public void setParentMine(final CUnit parentGoldMineUnit, final CAbilityGoldMine parentGoldMineAbility) { + this.parentGoldMineUnit = parentGoldMineUnit; + this.parentGoldMineAbility = parentGoldMineAbility; } @Override public void onAdd(final CSimulation game, final CUnit unit) { - + for (int i = 0; i < this.minerLocs.length; i++) { + final double angleSize = (StrictMath.PI * 2) / this.maxNumberOfMiners; + final double thisMinerAngle = (angleSize * i) + (StrictMath.PI / 2); + final float harvestStandX = unit.getX() + + (float) (StrictMath.cos(thisMinerAngle) * this.radiusOfMiningRing); + final float harvestStandY = unit.getY() + + (float) (StrictMath.sin(thisMinerAngle) * this.radiusOfMiningRing); + this.minerLocs[i] = new Vector2(harvestStandX, harvestStandY); + } } @Override @@ -38,6 +64,21 @@ public class CAbilityBlightedGoldMine extends AbstractGenericNoIconAbility { @Override public void onTick(final CSimulation game, final CUnit unit) { + if (this.currentActiveMinerCount > 0) { + final float currentInterval = this.intervalDuration + * (this.maxNumberOfMiners / this.currentActiveMinerCount); + final int nextIncomeTick = this.lastIncomeTick + + (int) (currentInterval / WarsmashConstants.SIMULATION_STEP_TIME); + final int currentTurnTick = game.getGameTurnTick(); + if ((currentTurnTick >= nextIncomeTick) && (this.parentGoldMineAbility != null) + && (this.parentGoldMineAbility.getGold() > 0)) { + this.lastIncomeTick = currentTurnTick; + final CPlayer player = game.getPlayer(unit.getPlayerIndex()); + player.setGold(player.getGold() + this.goldPerInterval); + this.parentGoldMineAbility.setGold(this.parentGoldMineAbility.getGold() - this.goldPerInterval); + game.unitGainResourceEvent(unit, ResourceType.GOLD, this.goldPerInterval); + } + } // final boolean empty = this.activeMiners.isEmpty(); // if (empty != this.wasEmpty) { // if (empty) { @@ -107,12 +148,86 @@ public class CAbilityBlightedGoldMine extends AbstractGenericNoIconAbility { public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } - public int getGold() { - return this.gold; + public int tryAddMiner(final CUnit acolyte, final CBehaviorAcolyteHarvest behaviorAcolyteHarvest) { + if (behaviorAcolyteHarvest == null) { + throw new NullPointerException(); + } + int minerIndex = NO_MINER; + double minerDistSq = Float.MAX_VALUE; + for (int i = 0; i < this.activeMiners.length; i++) { + if (this.activeMiners[i] == null) { + final double thisMineDistSq = acolyte.distanceSquaredNoCollision(this.minerLocs[i].x, + this.minerLocs[i].y); + if (minerDistSq > thisMineDistSq) { + minerIndex = i; + minerDistSq = thisMineDistSq; + } + } + } + if (minerIndex != NO_MINER) { + this.activeMiners[minerIndex] = behaviorAcolyteHarvest; + this.currentActiveMinerCount++; + } + return minerIndex; + } + + public void removeMiner(final CBehaviorAcolyteHarvest behaviorAcolyteHarvest) { + if (behaviorAcolyteHarvest == null) { + throw new NullPointerException(); + } + for (int i = 0; i < this.activeMiners.length; i++) { + if (this.activeMiners[i] == behaviorAcolyteHarvest) { + this.activeMiners[i] = null; + this.currentActiveMinerCount--; + } + } + } + + public int getMaxNumberOfMiners() { + return this.maxNumberOfMiners; + } + + public float getRadiusOfMiningRing() { + return this.radiusOfMiningRing; + } + + public void setGoldPerInterval(final int goldPerInterval) { + this.goldPerInterval = goldPerInterval; + } + + public void setIntervalDuration(final float intervalDuration) { + this.intervalDuration = intervalDuration; + } + + public void setMaxNumberOfMiners(final int maxNumberOfMiners) { + this.maxNumberOfMiners = maxNumberOfMiners; + } + + public void setRadiusOfMiningRing(final float radiusOfMiningRing) { + this.radiusOfMiningRing = radiusOfMiningRing; + } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + if (this.parentGoldMineUnit != null) { + this.parentGoldMineUnit.setHidden(false); + } + } + + public Vector2 getMinerLoc(final int index) { + return this.minerLocs[index]; } public void setGold(final int gold) { - this.gold = gold; + if (this.parentGoldMineAbility != null) { + this.parentGoldMineAbility.setGold(gold); + } } + public int getGold() { + if (this.parentGoldMineAbility != null) { + return this.parentGoldMineAbility.getGold(); + } + return 0; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityGoldMine.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityGoldMine.java index bd54687..3254156 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityGoldMine.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/mine/CAbilityGoldMine.java @@ -58,15 +58,21 @@ public class CAbilityGoldMine extends AbstractGenericNoIconAbility { final CBehaviorHarvest activeMiner = this.activeMiners.get(i); if (game.getGameTurnTick() >= activeMiner.getPopoutFromMineTurnTick()) { - final int goldMined = Math.min(this.gold, activeMiner.getGoldCapacity()); - this.gold -= goldMined; - if (this.gold <= 0) { - unit.setLife(game, 0); + int goldMined; + if (this.gold > 0) { + goldMined = Math.min(this.gold, activeMiner.getGoldCapacity()); + this.gold -= goldMined; + } + else { + goldMined = 0; } activeMiner.popoutFromMine(goldMined); this.activeMiners.remove(i); } } + if (this.gold <= 0) { + unit.setLife(game, 0); + } } @Override @@ -144,4 +150,8 @@ public class CAbilityGoldMine extends AbstractGenericNoIconAbility { public void setMiningDuration(final float miningDuration) { this.miningDuration = miningDuration; } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityQueue.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityQueue.java index bba44c6..0620a75 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityQueue.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityQueue.java @@ -206,4 +206,12 @@ public final class CAbilityQueue extends AbstractCAbility { this.unitsTrained.addAll(unitType.getUnitsTrained()); this.researchesAvailable.addAll(unitType.getResearchesAvailable()); } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + // refund stuff when building dies + while (cUnit.getBuildQueueTypes()[0] != null) { + cUnit.cancelBuildQueueItem(game, 0); + } + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityRally.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityRally.java index 2fdf536..b508dfd 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityRally.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityRally.java @@ -119,4 +119,8 @@ public class CAbilityRally extends AbstractCAbility implements CLevelingAbility public void setLevel(final int level) { } + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityReviveHero.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityReviveHero.java index 5767087..d298b05 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityReviveHero.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/queue/CAbilityReviveHero.java @@ -137,4 +137,12 @@ public final class CAbilityReviveHero extends AbstractCAbility { @Override public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) { } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + // refund stuff when building dies + while (cUnit.getBuildQueueTypes()[0] != null) { + cUnit.cancelBuildQueueItem(game, 0); + } + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/targeting/AbilityTargetStillAliveAndTargetableVisitor.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/targeting/AbilityTargetStillAliveAndTargetableVisitor.java index 571a3c1..0d2a562 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/targeting/AbilityTargetStillAliveAndTargetableVisitor.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/targeting/AbilityTargetStillAliveAndTargetableVisitor.java @@ -39,7 +39,8 @@ public final class AbilityTargetStillAliveAndTargetableVisitor implements Abilit @Override public Boolean accept(final CItem target) { - return !target.isDead() && target.canBeTargetedBy(this.simulation, this.unit, this.targetsAllowed); + return !target.isDead() && !target.isHidden() + && target.canBeTargetedBy(this.simulation, this.unit, this.targetsAllowed); } } \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionAcolyteHarvest.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionAcolyteHarvest.java new file mode 100644 index 0000000..663977f --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionAcolyteHarvest.java @@ -0,0 +1,33 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl; + +import java.util.EnumSet; +import java.util.List; + +import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject; +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeAcolyteHarvestLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeDefinitionAcolyteHarvest + extends AbstractCAbilityTypeDefinition implements CAbilityTypeDefinition { + + @Override + protected CAbilityTypeAcolyteHarvestLevelData createLevelData(final MutableGameObject abilityEditorData, + final int level) { + final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level); + final EnumSet targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString); + final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level); + final float duration = abilityEditorData.getFieldAsFloat(DURATION, level); + return new CAbilityTypeAcolyteHarvestLevelData(targetsAllowedAtLevel, castRange, duration); + } + + @Override + protected CAbilityType innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData, + final List levelData) { + return new CAbilityTypeAcolyteHarvest(alias, abilityEditorData.getCode(), levelData); + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlight.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlight.java new file mode 100644 index 0000000..a3c96a4 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlight.java @@ -0,0 +1,36 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl; + +import java.util.EnumSet; +import java.util.List; + +import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject; +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeBlight; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeBlightLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeDefinitionBlight extends AbstractCAbilityTypeDefinition + implements CAbilityTypeDefinition { + protected static final War3ID EXPANSION_AMOUNT = War3ID.fromString("Bli1"); + protected static final War3ID CREATES_BLIGHT = War3ID.fromString("Bli2"); + + @Override + protected CAbilityTypeBlightLevelData createLevelData(final MutableGameObject abilityEditorData, final int level) { + final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level); + final EnumSet targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString); + final boolean createsBlight = abilityEditorData.getFieldAsBoolean(CREATES_BLIGHT, level); + final float expansionAmount = abilityEditorData.getFieldAsFloat(EXPANSION_AMOUNT, level); + final float area = abilityEditorData.getFieldAsFloat(AREA, level); + final float duration = abilityEditorData.getFieldAsFloat(DURATION, level); + return new CAbilityTypeBlightLevelData(targetsAllowedAtLevel, createsBlight, expansionAmount, area, duration); + } + + @Override + protected CAbilityType innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData, + final List levelData) { + return new CAbilityTypeBlight(alias, abilityEditorData.getCode(), levelData); + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlightedGoldMine.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlightedGoldMine.java new file mode 100644 index 0000000..e9cf656 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionBlightedGoldMine.java @@ -0,0 +1,40 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl; + +import java.util.EnumSet; +import java.util.List; + +import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject; +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeBlightedGoldMine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeBlightedGoldMineLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeDefinitionBlightedGoldMine extends + AbstractCAbilityTypeDefinition implements CAbilityTypeDefinition { + protected static final War3ID GOLD_PER_INTERVAL = War3ID.fromString("Bgm1"); + protected static final War3ID INTERVAL_DURATION = War3ID.fromString("Bgm2"); + protected static final War3ID MAX_NUMBER_OF_MINERS = War3ID.fromString("Bgm3"); + protected static final War3ID RADIUS_OF_MINING_RING = War3ID.fromString("Bgm4"); + + @Override + protected CAbilityTypeBlightedGoldMineLevelData createLevelData(final MutableGameObject abilityEditorData, + final int level) { + final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level); + final EnumSet targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString); + final int goldPerInterval = abilityEditorData.getFieldAsInteger(GOLD_PER_INTERVAL, level); + final float intervalDuration = abilityEditorData.getFieldAsFloat(INTERVAL_DURATION, level); + final int maxNumberOfMiners = abilityEditorData.getFieldAsInteger(MAX_NUMBER_OF_MINERS, level); + final float radiusOfMiningRing = abilityEditorData.getFieldAsFloat(RADIUS_OF_MINING_RING, level); + return new CAbilityTypeBlightedGoldMineLevelData(targetsAllowedAtLevel, goldPerInterval, intervalDuration, + maxNumberOfMiners, radiusOfMiningRing); + } + + @Override + protected CAbilityType innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData, + final List levelData) { + return new CAbilityTypeBlightedGoldMine(alias, abilityEditorData.getCode(), levelData); + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvest.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvest.java new file mode 100644 index 0000000..dd7ede2 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvest.java @@ -0,0 +1,35 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.List; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; + +public class CAbilityTypeAcolyteHarvest extends CAbilityType { + + public CAbilityTypeAcolyteHarvest(final War3ID alias, final War3ID code, + final List levelData) { + super(alias, code, levelData); + } + + @Override + public CAbility createAbility(final int handleId) { + final CAbilityTypeAcolyteHarvestLevelData levelData = getLevelData(0); + return new CAbilityAcolyteHarvest(handleId, getAlias(), levelData.getCastRange(), levelData.getDuration()); + } + + @Override + public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) { + final CAbilityTypeAcolyteHarvestLevelData levelData = getLevelData(level - 1); + final CAbilityAcolyteHarvest heroAbility = ((CAbilityAcolyteHarvest) existingAbility); + + heroAbility.setCastRange(levelData.getCastRange()); + heroAbility.setDuration(levelData.getDuration()); + + heroAbility.setLevel(level); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvestLevelData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvestLevelData.java new file mode 100644 index 0000000..4010fe6 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeAcolyteHarvestLevelData.java @@ -0,0 +1,27 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.EnumSet; + +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeAcolyteHarvestLevelData extends CAbilityTypeLevelData { + private final float castRange; + private final float duration; + + public CAbilityTypeAcolyteHarvestLevelData(final EnumSet targetsAllowed, final float castRange, + final float duration) { + super(targetsAllowed); + this.castRange = castRange; + this.duration = duration; + } + + public float getCastRange() { + return this.castRange; + } + + public float getDuration() { + return this.duration; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlight.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlight.java new file mode 100644 index 0000000..fca6706 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlight.java @@ -0,0 +1,38 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.List; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.blight.CAbilityBlight; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; + +public class CAbilityTypeBlight extends CAbilityType { + + public CAbilityTypeBlight(final War3ID alias, final War3ID code, + final List levelData) { + super(alias, code, levelData); + } + + @Override + public CAbility createAbility(final int handleId) { + final CAbilityTypeBlightLevelData levelData = getLevelData(0); + return new CAbilityBlight(handleId, getAlias(), levelData.isCreatesBlight(), levelData.getExpansionAmount(), + levelData.getAreaOfEffect(), levelData.getGameSecondsPerBlightExpansion()); + } + + @Override + public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) { + final CAbilityTypeBlightLevelData levelData = getLevelData(level - 1); + final CAbilityBlight heroAbility = ((CAbilityBlight) existingAbility); + + heroAbility.setCreatesBlight(levelData.isCreatesBlight()); + heroAbility.setAreaOfEffect(levelData.getAreaOfEffect()); + heroAbility.setExpansionAmount(levelData.getExpansionAmount()); + heroAbility.setGameSecondsPerBlightExpansion(levelData.getGameSecondsPerBlightExpansion()); + + heroAbility.setLevel(level); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightLevelData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightLevelData.java new file mode 100644 index 0000000..f8c7d20 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightLevelData.java @@ -0,0 +1,40 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.EnumSet; + +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeBlightLevelData extends CAbilityTypeLevelData { + + private final boolean createsBlight; + private final float expansionAmount; + private final float areaOfEffect; + private final float gameSecondsPerBlightExpansion; + + public CAbilityTypeBlightLevelData(final EnumSet targetsAllowed, final boolean createsBlight, + final float expansionAmount, final float areaOfEffect, final float gameSecondsPerBlightExpansion) { + super(targetsAllowed); + this.createsBlight = createsBlight; + this.expansionAmount = expansionAmount; + this.areaOfEffect = areaOfEffect; + this.gameSecondsPerBlightExpansion = gameSecondsPerBlightExpansion; + } + + public boolean isCreatesBlight() { + return this.createsBlight; + } + + public float getExpansionAmount() { + return this.expansionAmount; + } + + public float getAreaOfEffect() { + return this.areaOfEffect; + } + + public float getGameSecondsPerBlightExpansion() { + return this.gameSecondsPerBlightExpansion; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMine.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMine.java new file mode 100644 index 0000000..8aa6bb1 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMine.java @@ -0,0 +1,38 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.List; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; + +public class CAbilityTypeBlightedGoldMine extends CAbilityType { + + public CAbilityTypeBlightedGoldMine(final War3ID alias, final War3ID code, + final List levelData) { + super(alias, code, levelData); + } + + @Override + public CAbility createAbility(final int handleId) { + final CAbilityTypeBlightedGoldMineLevelData levelData = getLevelData(0); + return new CAbilityBlightedGoldMine(handleId, getAlias(), levelData.getGoldPerInterval(), + levelData.getIntervalDuration(), levelData.getMaxNumberOfMiners(), levelData.getRadiusOfMiningRing()); + } + + @Override + public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) { + final CAbilityTypeBlightedGoldMineLevelData levelData = getLevelData(level - 1); + final CAbilityBlightedGoldMine heroAbility = ((CAbilityBlightedGoldMine) existingAbility); + + heroAbility.setGoldPerInterval(levelData.getGoldPerInterval()); + heroAbility.setIntervalDuration(levelData.getIntervalDuration()); + heroAbility.setRadiusOfMiningRing(levelData.getRadiusOfMiningRing()); + heroAbility.setMaxNumberOfMiners(levelData.getMaxNumberOfMiners()); + + heroAbility.setLevel(level); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMineLevelData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMineLevelData.java new file mode 100644 index 0000000..c651fe1 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeBlightedGoldMineLevelData.java @@ -0,0 +1,38 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; + +import java.util.EnumSet; + +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; + +public class CAbilityTypeBlightedGoldMineLevelData extends CAbilityTypeLevelData { + private final int goldPerInterval; + private final float intervalDuration; + private final int maxNumberOfMiners; + private final float radiusOfMiningRing; + + public CAbilityTypeBlightedGoldMineLevelData(final EnumSet targetsAllowed, final int goldPerInterval, + final float intervalDuration, final int maxNumberOfMiners, final float radiusOfMiningRing) { + super(targetsAllowed); + this.goldPerInterval = goldPerInterval; + this.intervalDuration = intervalDuration; + this.maxNumberOfMiners = maxNumberOfMiners; + this.radiusOfMiningRing = radiusOfMiningRing; + } + + public int getGoldPerInterval() { + return this.goldPerInterval; + } + + public float getIntervalDuration() { + return this.intervalDuration; + } + + public int getMaxNumberOfMiners() { + return this.maxNumberOfMiners; + } + + public float getRadiusOfMiningRing() { + return this.radiusOfMiningRing; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeWispHarvestLevelData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeWispHarvestLevelData.java index 878a898..d378c70 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeWispHarvestLevelData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeWispHarvestLevelData.java @@ -1,10 +1,10 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl; +import java.util.EnumSet; + import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; -import java.util.EnumSet; - public class CAbilityTypeWispHarvestLevelData extends CAbilityTypeLevelData { private final int lumberPerInterval; private final float artAttachmentHeight; @@ -12,7 +12,7 @@ public class CAbilityTypeWispHarvestLevelData extends CAbilityTypeLevelData { private final float duration; public CAbilityTypeWispHarvestLevelData(final EnumSet targetsAllowed, final int lumberPerInterval, - float artAttachmentHeight, final float castRange, final float duration) { + final float artAttachmentHeight, final float castRange, final float duration) { super(targetsAllowed); this.lumberPerInterval = lumberPerInterval; this.artAttachmentHeight = artAttachmentHeight; @@ -21,11 +21,11 @@ public class CAbilityTypeWispHarvestLevelData extends CAbilityTypeLevelData { } public int getLumberPerInterval() { - return lumberPerInterval; + return this.lumberPerInterval; } public float getArtAttachmentHeight() { - return artAttachmentHeight; + return this.artAttachmentHeight; } public float getCastRange() { diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/upgrade/CAbilityUpgrade.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/upgrade/CAbilityUpgrade.java index bcede2b..fa7b477 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/upgrade/CAbilityUpgrade.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/upgrade/CAbilityUpgrade.java @@ -188,4 +188,8 @@ public final class CAbilityUpgrade extends AbstractCAbility { this.upgradesTo.clear(); this.upgradesTo.addAll(unitType.getUpgradesTo()); } + + @Override + public void onDeath(final CSimulation game, final CUnit cUnit) { + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUnderConstructionVisitor.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUnderConstructionVisitor.java index 9ecd56e..6b271bb 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUnderConstructionVisitor.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUnderConstructionVisitor.java @@ -145,6 +145,8 @@ public class AbilityDisableWhileUnderConstructionVisitor implements CAbilityVisi @Override public Void accept(final CAbilityReturnResources ability) { + ability.setDisabled(true); + ability.setIconShowing(false); return null; } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUpgradingVisitor.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUpgradingVisitor.java new file mode 100644 index 0000000..af550fc --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/AbilityDisableWhileUpgradingVisitor.java @@ -0,0 +1,159 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build; + +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityGenericDoNothing; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNagaBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNeutralBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityReturnResources; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityReviveHero; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.upgrade.CAbilityUpgrade; + +public class AbilityDisableWhileUpgradingVisitor implements CAbilityVisitor { + public static final AbilityDisableWhileUpgradingVisitor INSTANCE = new AbilityDisableWhileUpgradingVisitor(); + + @Override + public Void accept(final CAbilityAttack ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityMove ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityOrcBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityHumanBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityUndeadBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityNightElfBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityGenericDoNothing ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityColdArrows ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityNagaBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityNeutralBuild ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityBuildInProgress ability) { + ability.setDisabled(false); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityQueue ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityUpgrade ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityReviveHero ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final GenericSingleIconActiveAbility ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityRally ability) { + ability.setDisabled(false); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final GenericNoIconAbility ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + + @Override + public Void accept(final CAbilityReturnResources ability) { + // NOTE: while upgrading, this ability is not disabled! + return null; + } + + @Override + public Void accept(final CAbilityHero ability) { + ability.setDisabled(true); + ability.setIconShowing(false); + return null; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorUndeadBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorUndeadBuild.java index b47f07a..56f871f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorUndeadBuild.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorUndeadBuild.java @@ -12,21 +12,27 @@ 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.abilities.CAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CBuildingPathingType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit.BuildOnBuildingIntersector; public class CBehaviorUndeadBuild extends CAbstractRangedBehavior { + private static int delayAnimationTicks = (int) (2.267f / WarsmashConstants.SIMULATION_STEP_TIME); private int highlightOrderId; private War3ID orderId; private boolean unitCreated = false; private int doneTick = 0; + private final BuildOnBuildingIntersector buildOnBuildingIntersector; public CBehaviorUndeadBuild(final CUnit unit) { super(unit); + this.buildOnBuildingIntersector = new BuildOnBuildingIntersector(); } public CBehavior reset(final AbilityPointTarget target, final int orderId, final int highlightOrderId) { @@ -68,10 +74,15 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior { final CUnitType unitTypeToCreate = simulation.getUnitData().getUnitType(this.orderId); final BufferedImage buildingPathingPixelMap = unitTypeToCreate.getBuildingPathingPixelMap(); boolean buildLocationObstructed = false; - if (buildingPathingPixelMap != null) { + final boolean canBeBuiltOnThem = unitTypeToCreate.isCanBeBuiltOnThem(); + if (canBeBuiltOnThem) { + simulation.getWorldCollision().enumBuildingsAtPoint(this.target.getX(), this.target.getY(), + this.buildOnBuildingIntersector.reset(this.target.getX(), this.target.getY())); + buildLocationObstructed = (this.buildOnBuildingIntersector.getUnitToBuildOn() == null); + } + else if (buildingPathingPixelMap != null) { final EnumSet preventedPathingTypes = unitTypeToCreate.getPreventedPathingTypes(); final EnumSet requiredPathingTypes = unitTypeToCreate.getRequiredPathingTypes(); - if (!simulation.getPathingGrid().checkPathingTexture(this.target.getX(), this.target.getY(), (int) simulation.getGameplayConstants().getBuildingAngle(), buildingPathingPixelMap, preventedPathingTypes, requiredPathingTypes, simulation.getWorldCollision(), this.unit)) { @@ -82,6 +93,25 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior { if (!buildLocationObstructed) { final CUnit constructedStructure = simulation.createUnit(this.orderId, playerIndex, this.target.getX(), this.target.getY(), simulation.getGameplayConstants().getBuildingAngle()); + if (canBeBuiltOnThem) { + CAbilityGoldMine abilityGoldMine = null; + if (this.buildOnBuildingIntersector.getUnitToBuildOn() != null) { + for (final CAbility ability : this.buildOnBuildingIntersector.getUnitToBuildOn() + .getAbilities()) { + if ((ability instanceof CAbilityGoldMine) && !ability.isDisabled()) { + abilityGoldMine = (CAbilityGoldMine) ability; + } + } + } + for (final CAbility ability : constructedStructure.getAbilities()) { + if (ability instanceof CAbilityBlightedGoldMine) { + final CAbilityBlightedGoldMine blightedGoldMine = (CAbilityBlightedGoldMine) ability; + blightedGoldMine.setParentMine(this.buildOnBuildingIntersector.getUnitToBuildOn(), + abilityGoldMine); + this.buildOnBuildingIntersector.getUnitToBuildOn().setHidden(true); + } + } + } constructedStructure.setConstructing(true); constructedStructure.setLife(simulation, constructedStructure.getMaximumLife() * WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE); @@ -155,5 +185,4 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior { refund(player, unitTypeToCreate); } } - } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/harvest/CBehaviorAcolyteHarvest.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/harvest/CBehaviorAcolyteHarvest.java new file mode 100644 index 0000000..b61a80c --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/harvest/CBehaviorAcolyteHarvest.java @@ -0,0 +1,146 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest; + +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; +import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; +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.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityBlightedGoldMine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; + +public class CBehaviorAcolyteHarvest extends CAbstractRangedBehavior { + private final CAbilityAcolyteHarvest abilityAcolyteHarvest; + private boolean harvesting = false; + private float harvestStandX, harvestStandY; + + public CBehaviorAcolyteHarvest(final CUnit unit, final CAbilityAcolyteHarvest abilityWispHarvest) { + super(unit); + this.abilityAcolyteHarvest = abilityWispHarvest; + } + + public CBehaviorAcolyteHarvest reset(final CWidget target) { + innerReset(target, false); + return this; + } + + @Override + protected CBehavior update(final CSimulation simulation, final boolean withinFacingWindow) { + if (!this.harvesting) { + final HarvestStartResult result = onStartHarvesting(simulation); + if (result == HarvestStartResult.DENIED) { + simulation.getCommandErrorListener().showBlightRingFullError(this.unit.getPlayerIndex()); + return this.unit.pollNextOrderBehavior(simulation); + } + else if (result == HarvestStartResult.ACCEPTED) { + this.harvesting = true; + } + else { + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, SequenceUtils.EMPTY, 1.0f, + true); + } + } + if (this.harvesting) { + if ((this.harvestStandX != this.unit.getX()) || (this.harvestStandY != this.unit.getY())) { + this.unit.setX(this.harvestStandX, simulation.getWorldCollision(), simulation.getRegionManager()); + this.unit.setY(this.harvestStandY, simulation.getWorldCollision(), simulation.getRegionManager()); + simulation.unitRepositioned(this.unit); // dont interpolate, instant jump + } + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, SequenceUtils.WORK, 1.0f, true); + } + return this; + } + + private HarvestStartResult onStartHarvesting(final CSimulation simulation) { + // TODO maybe use visitor instead of cast + final CUnit targetUnit = (CUnit) this.target; + for (final CAbility ability : targetUnit.getAbilities()) { + if ((ability instanceof CAbilityBlightedGoldMine) && !ability.isDisabled()) { + final CAbilityBlightedGoldMine abilityBlightedGoldMine = (CAbilityBlightedGoldMine) ability; + final int newIndex = abilityBlightedGoldMine.tryAddMiner(this.unit, this); + if (newIndex == CAbilityBlightedGoldMine.NO_MINER) { + return HarvestStartResult.DENIED; + } + + final double angleSize = (StrictMath.PI * 2) / abilityBlightedGoldMine.getMaxNumberOfMiners(); + final float radiusOfMiningRing = abilityBlightedGoldMine.getRadiusOfMiningRing(); + final double thisMinerAngle = angleSize * newIndex; + this.harvestStandX = targetUnit.getX() + (float) (StrictMath.cos(thisMinerAngle) * radiusOfMiningRing); + this.harvestStandY = targetUnit.getY() + (float) (StrictMath.sin(thisMinerAngle) * radiusOfMiningRing); + simulation.unitSoundEffectEvent(this.unit, this.abilityAcolyteHarvest.getAlias()); + return HarvestStartResult.ACCEPTED; + } + } + return HarvestStartResult.WAITING; + } + + private void onStopHarvesting(final CSimulation simulation) { + final CUnit targetUnit = (CUnit) this.target; + for (final CAbility ability : targetUnit.getAbilities()) { + if (ability instanceof CAbilityBlightedGoldMine) { + ((CAbilityBlightedGoldMine) ability).removeMiner(this); + } + + } + } + + @Override + protected CBehavior updateOnInvalidTarget(final CSimulation simulation) { + if (this.harvesting) { + onStopHarvesting(simulation); + this.harvesting = false; + } + return this.unit.pollNextOrderBehavior(simulation); + } + + @Override + protected boolean checkTargetStillValid(final CSimulation simulation) { + return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE); + } + + @Override + protected void resetBeforeMoving(final CSimulation simulation) { + if (this.harvesting) { + onStopHarvesting(simulation); + this.harvesting = false; + } + } + + @Override + public boolean isWithinRange(final CSimulation simulation) { + return this.unit.canReach(this.target, this.abilityAcolyteHarvest.getCastRange()); + } + + @Override + public void endMove(final CSimulation game, final boolean interrupted) { + + } + + @Override + public void begin(final CSimulation game) { + + } + + @Override + public void end(final CSimulation game, final boolean interrupted) { + if (this.harvesting) { + onStopHarvesting(game); + this.harvesting = false; + } + } + + @Override + public int getHighlightOrderId() { + return OrderIds.acolyteharvest; + } + + private static enum HarvestStartResult { + WAITING, + DENIED, + ACCEPTED + }; +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CAbilityData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CAbilityData.java index 6a7e7af..41982a8 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CAbilityData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CAbilityData.java @@ -11,6 +11,9 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityGenericDoNothing; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionAcolyteHarvest; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionBlight; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionBlightedGoldMine; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionCarrionSwarmDummy; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionChannelTest; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionColdArrows; @@ -52,6 +55,9 @@ public class CAbilityData { this.codeToAbilityTypeDefinition.put(War3ID.fromString("AHca"), new CAbilityTypeDefinitionColdArrows()); this.codeToAbilityTypeDefinition.put(War3ID.fromString("Agld"), new CAbilityTypeDefinitionGoldMine()); + this.codeToAbilityTypeDefinition.put(War3ID.fromString("Abgm"), new CAbilityTypeDefinitionBlightedGoldMine()); + this.codeToAbilityTypeDefinition.put(War3ID.fromString("Abli"), new CAbilityTypeDefinitionBlight()); + this.codeToAbilityTypeDefinition.put(War3ID.fromString("Aaha"), new CAbilityTypeDefinitionAcolyteHarvest()); this.codeToAbilityTypeDefinition.put(War3ID.fromString("Artn"), new CAbilityTypeDefinitionReturnResources()); this.codeToAbilityTypeDefinition.put(War3ID.fromString("Ahar"), new CAbilityTypeDefinitionHarvest()); this.codeToAbilityTypeDefinition.put(War3ID.fromString("Awha"), new CAbilityTypeDefinitionWispHarvest()); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java index 316d110..2124113 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java @@ -187,6 +187,9 @@ public class CUnitData { private static final War3ID POINT_VALUE = War3ID.fromString("upoi"); + private static final War3ID CAN_BE_BUILT_ON_THEM = War3ID.fromString("uibo"); + private static final War3ID CAN_BUILD_ON_ME = War3ID.fromString("ucbo"); + private final CGameplayConstants gameplayConstants; private final MutableObjectData unitData; private final Map unitIdToUnitType = new HashMap<>(); @@ -315,6 +318,9 @@ public class CUnitData { final boolean canFlee = unitType.getFieldAsBoolean(CAN_FLEE, 0); + final boolean canBeBuiltOnThem = unitType.getFieldAsBoolean(CAN_BE_BUILT_ON_THEM, 0); + final boolean canBuildOnMe = unitType.getFieldAsBoolean(CAN_BUILD_ON_ME, 0); + final float strPlus = unitType.getFieldAsFloat(STR_PLUS, 0); final float agiPlus = unitType.getFieldAsFloat(AGI_PLUS, 0); final float intPlus = unitType.getFieldAsFloat(INT_PLUS, 0); @@ -564,7 +570,7 @@ public class CUnitData { foodUsed, foodMade, buildTime, preventedPathingTypes, requiredPathingTypes, propWindow, turnRate, requirements, requirementTiers, unitLevel, hero, strength, strPlus, agility, agiPlus, intelligence, intPlus, primaryAttribute, heroAbilityList, heroProperNames, properNamesCount, canFlee, priority, - revivesHeroes, pointValue, castBackswingPoint, castPoint); + revivesHeroes, pointValue, castBackswingPoint, castPoint, canBeBuiltOnThem, canBuildOnMe); this.unitIdToUnitType.put(typeId, unitTypeInstance); this.jassLegacyNameToUnitId.put(legacyName, typeId); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/BuildOnBuildingIntersector.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/BuildOnBuildingIntersector.java new file mode 100644 index 0000000..b8620ba --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/BuildOnBuildingIntersector.java @@ -0,0 +1,34 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit; + +import com.etheller.warsmash.util.QuadtreeIntersector; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; + +public final class BuildOnBuildingIntersector implements QuadtreeIntersector { + private CUnit unitToBuildOn; + private float x; + private float y; + + public BuildOnBuildingIntersector reset(final float x, final float y) { + this.x = x; + this.y = y; + this.unitToBuildOn = null; + return this; + } + + @Override + public boolean onIntersect(final CUnit intersectingObject) { + if (intersectingObject.isHidden() || !intersectingObject.getUnitType().isCanBuildOnMe()) { + return false; + } + if ((Math.abs(this.x - intersectingObject.getX()) <= 0.0001) + && (Math.abs(this.y - intersectingObject.getY()) <= 0.0001)) { + this.unitToBuildOn = intersectingObject; + return true; + } + return false; + } + + public CUnit getUnitToBuildOn() { + return this.unitToBuildOn; + } +} \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/SimulationRenderController.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/SimulationRenderController.java index f039ef1..4ed5ed2 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/SimulationRenderController.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/SimulationRenderController.java @@ -83,4 +83,6 @@ public interface SimulationRenderController { void unitUpgradingEvent(CUnit unit, War3ID upgradeIdType); void unitCancelUpgradingEvent(CUnit unit, War3ID upgradeIdType); + + void setBlight(float x, float y, float radius, boolean blighted); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java index 8e5481a..78ba6bd 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java @@ -158,6 +158,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnitOrderListener; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit.BuildOnBuildingIntersector; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationErrorHandler; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver; @@ -366,6 +367,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma private final AnyTargetableUnitFilter anyTargetableUnitFilter; private final DataTable musicSLK; + private final BuildOnBuildingIntersector buildOnBuildingIntersector = new BuildOnBuildingIntersector(); + public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene, final Scene portraitScene, final CameraPreset[] cameraPresets, final CameraRates cameraRates, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener, @@ -1313,6 +1316,14 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma } } + @Override + public void showBlightRingFullError(final int playerIndex) { + if (playerIndex == this.war3MapViewer.getLocalPlayerIndex()) { + showCommandError(playerIndex, this.rootFrame.getErrorString("Blightringfull")); + this.war3MapViewer.getUiSounds().getSound("InterfaceError").play(this.uiScene.audioContext, 0, 0, 0); + } + } + public void update(final float deltaTime) { this.portrait.update(); @@ -1932,6 +1943,12 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma || (cellY > (pathingGrid.getHeight() - halfCursorHeightCells))) { blockAll = true; } + final boolean canBeBuiltOnThem = MeleeUI.this.cursorBuildingUnitType.isCanBeBuiltOnThem(); + if (canBeBuiltOnThem) { + viewer.simulation.getWorldCollision().enumBuildingsAtPoint(clickLocationTemp.x, clickLocationTemp.y, + MeleeUI.this.buildOnBuildingIntersector.reset(clickLocationTemp.x, clickLocationTemp.y)); + blockAll = (MeleeUI.this.buildOnBuildingIntersector.getUnitToBuildOn() == null); + } if (blockAll) { for (int i = 0; i < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getWidth(); i++) { for (int j = 0; j < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight(); j++) { @@ -1941,7 +1958,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma } } } - else { + else if (!canBeBuiltOnThem) { for (int i = 0; i < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getWidth(); i++) { for (int j = 0; j < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight(); j++) { boolean blocked = false; @@ -1966,6 +1983,15 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma } } } + else { + for (int i = 0; i < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getWidth(); i++) { + for (int j = 0; j < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight(); j++) { + MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.drawPixel(i, + MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight() - 1 - j, + Color.rgba8888(0, 1, 0, 1.0f)); + } + } + } MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTexture .load(MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTextureData); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/CommandErrorListener.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/CommandErrorListener.java index ad0b1fe..dbcafd9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/CommandErrorListener.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/CommandErrorListener.java @@ -13,4 +13,6 @@ public interface CommandErrorListener { void showUnableToFindCoupleTargetError(int playerIndex); + void showBlightRingFullError(int playerIndex); + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/SettableCommandErrorListener.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/SettableCommandErrorListener.java index 2749574..aab2b1a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/SettableCommandErrorListener.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/command/SettableCommandErrorListener.java @@ -36,4 +36,9 @@ public class SettableCommandErrorListener implements CommandErrorListener { public void showUnableToFindCoupleTargetError(final int playerIndex) { this.delegate.showUnableToFindCoupleTargetError(playerIndex); } + + @Override + public void showBlightRingFullError(final int playerIndex) { + this.delegate.showBlightRingFullError(playerIndex); + } }