Update with blighted gold mine and blight abilities, and buildOn mechanic

This commit is contained in:
Retera 2022-01-22 13:40:40 -05:00
parent ba2291f572
commit b5cab399b6
54 changed files with 1393 additions and 83 deletions

View File

@ -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.<TriggerBooleanExpression>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<JassValue> 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<JassValue> arguments, final GlobalScope globalScope,
@ -3432,7 +3450,7 @@ public class Jass2 {
@Override
public JassValue call(final List<JassValue> 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;
}
});

View File

@ -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);
}
}

View File

@ -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<SecondaryTag> secondaryAnimationTags, final float duration,
final boolean allowRarityVariations) {

View File

@ -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);
}
}

View File

@ -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<CWidgetEvent> 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);

View File

@ -86,6 +86,8 @@ public class CUnitType {
private final List<List<CUnitTypeRequirement>> 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<War3ID> heroAbilityList,
final List<String> 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;
}
}

View File

@ -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<CUnit> callback) {
this.buildingUnitCollision.intersect(rect, callback);
}
public void enumBuildingsAtPoint(final float x, final float y, final QuadtreeIntersector<CUnit> callback) {
this.buildingUnitCollision.intersect(x, y, callback);
}
public void enumDestructablesInRect(final Rectangle rect, final CDestructableEnumFunction callback) {
this.destructablesForEnum.intersect(rect, this.destructableEnumIntersector.reset(callback));
}

View File

@ -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 */

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> 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;
}
}

View File

@ -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) {
}
}

View File

@ -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;

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -97,4 +97,8 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractGen
return 0;
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
}

View File

@ -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<CWidget> 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<CWidget> 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<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> 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;
}
}

View File

@ -99,4 +99,8 @@ public class CAbilityReturnResources extends AbstractGenericAliasedAbility {
public void setAcceptedResourceTypes(final EnumSet<ResourceType> acceptedResourceTypes) {
this.acceptedResourceTypes = acceptedResourceTypes;
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
}

View File

@ -397,4 +397,8 @@ public class CAbilityHero extends AbstractCAbility {
public Set<War3ID> getSkillsAvailable() {
return this.skillsAvailable;
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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;
}
}

View File

@ -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) {
}
}

View File

@ -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);
}
}
}

View File

@ -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) {
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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<CAbilityTypeAcolyteHarvestLevelData> implements CAbilityTypeDefinition {
@Override
protected CAbilityTypeAcolyteHarvestLevelData createLevelData(final MutableGameObject abilityEditorData,
final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final EnumSet<CTargetType> 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<CAbilityTypeAcolyteHarvestLevelData> levelData) {
return new CAbilityTypeAcolyteHarvest(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -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<CAbilityTypeBlightLevelData>
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<CTargetType> 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<CAbilityTypeBlightLevelData> levelData) {
return new CAbilityTypeBlight(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -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<CAbilityTypeBlightedGoldMineLevelData> 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<CTargetType> 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<CAbilityTypeBlightedGoldMineLevelData> levelData) {
return new CAbilityTypeBlightedGoldMine(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -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<CAbilityTypeAcolyteHarvestLevelData> {
public CAbilityTypeAcolyteHarvest(final War3ID alias, final War3ID code,
final List<CAbilityTypeAcolyteHarvestLevelData> 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);
}
}

View File

@ -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<CTargetType> 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;
}
}

View File

@ -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<CAbilityTypeBlightLevelData> {
public CAbilityTypeBlight(final War3ID alias, final War3ID code,
final List<CAbilityTypeBlightLevelData> 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);
}
}

View File

@ -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<CTargetType> 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;
}
}

View File

@ -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<CAbilityTypeBlightedGoldMineLevelData> {
public CAbilityTypeBlightedGoldMine(final War3ID alias, final War3ID code,
final List<CAbilityTypeBlightedGoldMineLevelData> 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);
}
}

View File

@ -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<CTargetType> 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;
}
}

View File

@ -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<CTargetType> 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() {

View File

@ -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) {
}
}

View File

@ -145,6 +145,8 @@ public class AbilityDisableWhileUnderConstructionVisitor implements CAbilityVisi
@Override
public Void accept(final CAbilityReturnResources ability) {
ability.setDisabled(true);
ability.setIconShowing(false);
return null;
}

View File

@ -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<Void> {
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;
}
}

View File

@ -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<CBuildingPathingType> preventedPathingTypes = unitTypeToCreate.getPreventedPathingTypes();
final EnumSet<CBuildingPathingType> 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);
}
}
}

View File

@ -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
};
}

View File

@ -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());

View File

@ -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<War3ID, CUnitType> 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);
}

View File

@ -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<CUnit> {
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;
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -13,4 +13,6 @@ public interface CommandErrorListener {
void showUnableToFindCoupleTargetError(int playerIndex);
void showBlightRingFullError(int playerIndex);
}

View File

@ -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);
}
}