Updates to harvesting, reduce max depth of the quad trees

This commit is contained in:
Retera 2021-01-17 21:40:22 -05:00
parent eeed5953cc
commit 9a2dc090ca
23 changed files with 369 additions and 64 deletions

View File

@ -18,7 +18,7 @@ Path06="."
[Map] [Map]
//FilePath="CombatUnitTests.w3x" //FilePath="CombatUnitTests.w3x"
//FilePath="PitchRoll.w3x" //FilePath="PitchRoll.w3x"
FilePath="PeonStartingBase.w3x" //FilePath="PeonStartingBase.w3x"
//FilePath="ColdArrows.w3m" //FilePath="ColdArrows.w3m"
//FilePath="DungeonGoldMine.w3m" //FilePath="DungeonGoldMine.w3m"
//FilePath="PlayerPeasants.w3m" //FilePath="PlayerPeasants.w3m"
@ -35,3 +35,6 @@ FilePath="PeonStartingBase.w3x"
//FilePath="Pathing.w3x" //FilePath="Pathing.w3x"
//FilePath="ItemFacing.w3x" //FilePath="ItemFacing.w3x"
//FilePath=SomeParticleTests.w3x //FilePath=SomeParticleTests.w3x
FilePath="PeonMiningMultiHall.w3x"
//FilePath="QuadtreeBugs.w3x"
//FilePath="test2.w3x"

View File

@ -6,7 +6,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
public class Quadtree<T> { public class Quadtree<T> {
private static final int MAX_DEPTH = 64; private static final int MAX_DEPTH = 9;
private static final int SPLIT_THRESHOLD = 6; private static final int SPLIT_THRESHOLD = 6;
private final Rectangle bounds; private final Rectangle bounds;
@ -75,7 +75,7 @@ public class Quadtree<T> {
} }
} }
public boolean intersect(float x, float y, final QuadtreeIntersector<T> intersector) { public boolean intersect(final float x, final float y, final QuadtreeIntersector<T> intersector) {
if (this.leaf) { if (this.leaf) {
for (int i = 0; i < this.nodes.size; i++) { for (int i = 0; i < this.nodes.size; i++) {
final Node<T> node = this.nodes.get(i); final Node<T> node = this.nodes.get(i);
@ -123,17 +123,25 @@ public class Quadtree<T> {
return; return;
} }
} }
boolean overlapsAny = false;
if (this.northeast.bounds.overlaps(node.bounds)) { if (this.northeast.bounds.overlaps(node.bounds)) {
this.northeast.add(node, depth + 1); this.northeast.add(node, depth + 1);
overlapsAny = true;
} }
if (this.northwest.bounds.overlaps(node.bounds)) { if (this.northwest.bounds.overlaps(node.bounds)) {
this.northwest.add(node, depth + 1); this.northwest.add(node, depth + 1);
overlapsAny = true;
} }
if (this.southwest.bounds.overlaps(node.bounds)) { if (this.southwest.bounds.overlaps(node.bounds)) {
this.southwest.add(node, depth + 1); this.southwest.add(node, depth + 1);
overlapsAny = true;
} }
if (this.southeast.bounds.overlaps(node.bounds)) { if (this.southeast.bounds.overlaps(node.bounds)) {
this.southeast.add(node, depth + 1); this.southeast.add(node, depth + 1);
overlapsAny = true;
}
if (!overlapsAny) {
throw new IllegalStateException("Does not overlap anything!");
} }
} }

View File

@ -15,6 +15,8 @@ public class Test {
else { else {
System.out.println("no match"); System.out.println("no match");
} }
// Quadtree<String> myQT = new Quadtree<>(new Rectangle(-, y, width, height))
} }
} }

View File

@ -7,4 +7,11 @@ public class WarsmashConstants {
public static final int PORT_NUMBER = 6115; public static final int PORT_NUMBER = 6115;
public static final float BUILDING_CONSTRUCT_START_LIFE = 0.1f; public static final float BUILDING_CONSTRUCT_START_LIFE = 0.1f;
public static final int BUILD_QUEUE_SIZE = 7; public static final int BUILD_QUEUE_SIZE = 7;
// It looks like in Patch 1.22, "Particle" in video settings will change this
// factor:
// Low - unknown ?
// Medium - 1.0f
// High - 1.5f
public static final float MODEL_DETAIL_PARTICLE_FACTOR = 1.5f;
public static final float MODEL_DETAIL_PARTICLE_FACTOR_INVERSE = 1f / MODEL_DETAIL_PARTICLE_FACTOR;
} }

View File

@ -57,9 +57,9 @@ public class Particle extends EmittedObject<MdxComplexInstance, ParticleEmitter>
// Local rotation // Local rotation
rotationHeap.idt(); rotationHeap.idt();
rotationHeap.mulLeft(rotationHeap2.setFromAxisRad(0, 0, 1, rotationHeap.mul(rotationHeap2.setFromAxisRad(0, 0, 1,
RenderMathUtils.randomInRange((float) -Math.PI, (float) Math.PI))); RenderMathUtils.randomInRange((float) -Math.PI, (float) Math.PI)));
rotationHeap.mulLeft(rotationHeap2.setFromAxisRad(0, 1, 0, rotationHeap.mul(rotationHeap2.setFromAxisRad(0, 1, 0,
RenderMathUtils.randomInRange(-latitudeHeap[0], latitudeHeap[0]))); RenderMathUtils.randomInRange(-latitudeHeap[0], latitudeHeap[0])));
velocity.set(RenderMathUtils.VEC3_UNIT_Z); velocity.set(RenderMathUtils.VEC3_UNIT_Z);
rotationHeap.transform(velocity); rotationHeap.transform(velocity);

View File

@ -1,5 +1,7 @@
package com.etheller.warsmash.viewer5.handlers.mdx; package com.etheller.warsmash.viewer5.handlers.mdx;
import com.etheller.warsmash.util.WarsmashConstants;
public class ParticleEmitter2 extends MdxEmitter<MdxComplexInstance, ParticleEmitter2Object, Particle2> { public class ParticleEmitter2 extends MdxEmitter<MdxComplexInstance, ParticleEmitter2Object, Particle2> {
private static final float[] emissionRateHeap = new float[1]; private static final float[] emissionRateHeap = new float[1];
@ -30,7 +32,7 @@ public class ParticleEmitter2 extends MdxEmitter<MdxComplexInstance, ParticleEmi
this.lastEmissionKey = keyframe; this.lastEmissionKey = keyframe;
} }
else { else {
this.currentEmission += emissionRateHeap[0] * dt; this.currentEmission += emissionRateHeap[0] * dt * WarsmashConstants.MODEL_DETAIL_PARTICLE_FACTOR;
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.etheller.warsmash.viewer5.handlers.mdx; package com.etheller.warsmash.viewer5.handlers.mdx;
import com.etheller.warsmash.parsers.mdlx.AnimationMap; import com.etheller.warsmash.parsers.mdlx.AnimationMap;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Texture; import com.etheller.warsmash.viewer5.Texture;
import com.etheller.warsmash.viewer5.handlers.EmitterObject; import com.etheller.warsmash.viewer5.handlers.EmitterObject;
@ -82,7 +83,8 @@ public class ParticleEmitter2Object extends GenericObject implements EmitterObje
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
final float[] color = colors[i]; final float[] color = colors[i];
this.colors[i] = new float[] { color[0], color[1], color[2], alpha[i] / 255f }; this.colors[i] = new float[] { color[0], color[1], color[2],
(alpha[i] / 255f) * WarsmashConstants.MODEL_DETAIL_PARTICLE_FACTOR_INVERSE };
} }
this.scaling = emitter.getSegmentScaling(); this.scaling = emitter.getSegmentScaling();

View File

@ -18,7 +18,7 @@ public class PathingGrid {
private static final Map<String, MovementType> movetpToMovementType = new HashMap<>(); private static final Map<String, MovementType> movetpToMovementType = new HashMap<>();
static { static {
for (final MovementType movementType : MovementType.values()) { for (final MovementType movementType : MovementType.values()) {
if (movementType != MovementType.DISABLED) { if (!movementType.typeKey.isEmpty()) {
movetpToMovementType.put(movementType.typeKey, movementType); movetpToMovementType.put(movementType.typeKey, movementType);
} }
} }
@ -360,6 +360,12 @@ public class PathingGrid {
return !PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNWALKABLE); return !PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNWALKABLE);
} }
}, },
FOOT_NO_COLLISION("") {
@Override
public boolean isPathable(final short pathingValue) {
return !PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNWALKABLE);
}
},
HORSE("horse") { HORSE("horse") {
@Override @Override
public boolean isPathable(final short pathingValue) { public boolean isPathable(final short pathingValue) {

View File

@ -571,6 +571,12 @@ public class CUnit extends CWidget {
return groundDistance; return groundDistance;
} }
public double distanceSquaredNoCollision(final AbilityTarget target) {
final double dx = Math.abs(target.getX() - getX());
final double dy = Math.abs(target.getY() - getY());
return (dx * dx) + (dy * dy);
}
public double distance(final float x, final float y) { public double distance(final float x, final float y) {
double dx = Math.abs(x - getX()); double dx = Math.abs(x - getX());
double dy = Math.abs(y - getY()); double dy = Math.abs(y - getY());
@ -687,7 +693,7 @@ public class CUnit extends CWidget {
: buildingPathingPixelMap.getHeight(); : buildingPathingPixelMap.getHeight();
final int relativeGridX = (int) Math.floor(relativeOffsetX / 32f) + (gridWidth / 2); final int relativeGridX = (int) Math.floor(relativeOffsetX / 32f) + (gridWidth / 2);
final int relativeGridY = (int) Math.floor(relativeOffsetY / 32f) + (gridHeight / 2); final int relativeGridY = (int) Math.floor(relativeOffsetY / 32f) + (gridHeight / 2);
final int rangeInCells = (int) Math.floor(range / 32f); final int rangeInCells = (int) Math.floor(range / 32f) + 1;
final int rangeInCellsSquare = rangeInCells * rangeInCells; final int rangeInCellsSquare = rangeInCells * rangeInCells;
int minCheckX = relativeGridX - rangeInCells; int minCheckX = relativeGridX - rangeInCells;
int minCheckY = relativeGridY - rangeInCells; int minCheckY = relativeGridY - rangeInCells;

View File

@ -9,6 +9,7 @@ import com.etheller.warsmash.util.QuadtreeIntersector;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
public class CWorldCollision { public class CWorldCollision {
private static final float MINIMUM_COLLISION_SIZE = 0.001f /* THIS IS TO STOP QUADTREE FROM BUSTING */;
private final Quadtree<CUnit> groundUnitCollision; private final Quadtree<CUnit> groundUnitCollision;
private final Quadtree<CUnit> airUnitCollision; private final Quadtree<CUnit> airUnitCollision;
private final Quadtree<CUnit> seaUnitCollision; private final Quadtree<CUnit> seaUnitCollision;
@ -30,7 +31,8 @@ public class CWorldCollision {
public void addUnit(final CUnit unit) { public void addUnit(final CUnit unit) {
Rectangle bounds = unit.getCollisionRectangle(); Rectangle bounds = unit.getCollisionRectangle();
if (bounds == null) { if (bounds == null) {
final float collisionSize = Math.min(this.maxCollisionRadius, unit.getUnitType().getCollisionSize()); final float collisionSize = Math.max(MINIMUM_COLLISION_SIZE,
Math.min(this.maxCollisionRadius, unit.getUnitType().getCollisionSize()));
bounds = new Rectangle(unit.getX() - collisionSize, unit.getY() - collisionSize, collisionSize * 2, bounds = new Rectangle(unit.getX() - collisionSize, unit.getY() - collisionSize, collisionSize * 2,
collisionSize * 2); collisionSize * 2);
unit.setCollisionRectangle(bounds); unit.setCollisionRectangle(bounds);
@ -54,9 +56,11 @@ public class CWorldCollision {
case FLY: case FLY:
this.airUnitCollision.add(unit, bounds); this.airUnitCollision.add(unit, bounds);
break; break;
default:
case DISABLED: case DISABLED:
break;
default:
case FOOT: case FOOT:
case FOOT_NO_COLLISION:
case HORSE: case HORSE:
case HOVER: case HOVER:
this.groundUnitCollision.add(unit, bounds); this.groundUnitCollision.add(unit, bounds);
@ -86,9 +90,11 @@ public class CWorldCollision {
case FLY: case FLY:
this.airUnitCollision.remove(unit, bounds); this.airUnitCollision.remove(unit, bounds);
break; break;
default:
case DISABLED: case DISABLED:
break;
default:
case FOOT: case FOOT:
case FOOT_NO_COLLISION:
case HORSE: case HORSE:
case HOVER: case HOVER:
this.groundUnitCollision.remove(unit, bounds); this.groundUnitCollision.remove(unit, bounds);
@ -133,8 +139,10 @@ public class CWorldCollision {
case FLY: case FLY:
return this.airUnitCollision.intersect(newPossibleRectangle, return this.airUnitCollision.intersect(newPossibleRectangle,
this.anyUnitExceptTwoIntersector.reset(sourceUnitToIgnore, sourceSecondUnitToIgnore)); this.anyUnitExceptTwoIntersector.reset(sourceUnitToIgnore, sourceSecondUnitToIgnore));
default:
case DISABLED: case DISABLED:
case FOOT_NO_COLLISION:
return false;
default:
case FOOT: case FOOT:
case HORSE: case HORSE:
case HOVER: case HOVER:
@ -167,9 +175,11 @@ public class CWorldCollision {
case FLY: case FLY:
this.airUnitCollision.translate(unit, bounds, xShift, yShift); this.airUnitCollision.translate(unit, bounds, xShift, yShift);
break; break;
default:
case DISABLED: case DISABLED:
break;
default:
case FOOT: case FOOT:
case FOOT_NO_COLLISION:
case HORSE: case HORSE:
case HOVER: case HOVER:
this.groundUnitCollision.translate(unit, bounds, xShift, yShift); this.groundUnitCollision.translate(unit, bounds, xShift, yShift);

View File

@ -7,6 +7,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAbility public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAbility
@ -29,6 +30,9 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAb
if (orderId == getBaseOrderId()) { if (orderId == getBaseOrderId()) {
innerCheckCanTarget(game, unit, orderId, target, receiver); innerCheckCanTarget(game, unit, orderId, target, receiver);
} }
else if (orderId == OrderIds.smart) {
innerCheckCanSmartTarget(game, unit, orderId, target, receiver);
}
else { else {
receiver.orderIdNotAccepted(); receiver.orderIdNotAccepted();
} }
@ -37,12 +41,18 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAb
protected abstract void innerCheckCanTarget(CSimulation game, CUnit unit, int orderId, CWidget target, protected abstract void innerCheckCanTarget(CSimulation game, CUnit unit, int orderId, CWidget target,
AbilityTargetCheckReceiver<CWidget> receiver); AbilityTargetCheckReceiver<CWidget> receiver);
protected abstract void innerCheckCanSmartTarget(CSimulation game, CUnit unit, int orderId, CWidget target,
AbilityTargetCheckReceiver<CWidget> receiver);
@Override @Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) { final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
if (orderId == getBaseOrderId()) { if (orderId == getBaseOrderId()) {
innerCheckCanTarget(game, unit, orderId, target, receiver); innerCheckCanTarget(game, unit, orderId, target, receiver);
} }
else if (orderId == OrderIds.smart) {
innerCheckCanSmartTarget(game, unit, orderId, target, receiver);
}
else { else {
receiver.orderIdNotAccepted(); receiver.orderIdNotAccepted();
} }
@ -51,6 +61,9 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAb
protected abstract void innerCheckCanTarget(CSimulation game, CUnit unit, int orderId, AbilityPointTarget target, protected abstract void innerCheckCanTarget(CSimulation game, CUnit unit, int orderId, AbilityPointTarget target,
AbilityTargetCheckReceiver<AbilityPointTarget> receiver); AbilityTargetCheckReceiver<AbilityPointTarget> receiver);
protected abstract void innerCheckCanSmartTarget(CSimulation game, CUnit unit, int orderId,
AbilityPointTarget target, AbilityTargetCheckReceiver<AbilityPointTarget> receiver);
@Override @Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId, public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) { final AbilityTargetCheckReceiver<Void> receiver) {

View File

@ -0,0 +1,28 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic;
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.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
public abstract class AbstractGenericSingleIconNoSmartActiveAbility extends AbstractGenericSingleIconActiveAbility {
public AbstractGenericSingleIconNoSmartActiveAbility(final int handleId, final War3ID alias) {
super(handleId, alias);
}
@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 innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
}

View File

@ -10,6 +10,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbi
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; 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.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorHarvest; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; 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.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
@ -20,6 +21,7 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
private final int goldCapacity; private final int goldCapacity;
private final int lumberCapacity; private final int lumberCapacity;
private CBehaviorHarvest behaviorHarvest; private CBehaviorHarvest behaviorHarvest;
private CBehaviorReturnResources behaviorReturnResources;
private int carriedResourceAmount; private int carriedResourceAmount;
private ResourceType carriedResourceType; private ResourceType carriedResourceType;
@ -34,6 +36,7 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
@Override @Override
public void onAdd(final CSimulation game, final CUnit unit) { public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorHarvest = new CBehaviorHarvest(unit, this); this.behaviorHarvest = new CBehaviorHarvest(unit, this);
this.behaviorReturnResources = new CBehaviorReturnResources(unit, this);
} }
@Override @Override
@ -97,12 +100,24 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
} }
} }
@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 @Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId, protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) { final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted(); 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 @Override
protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId, protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) { final AbilityTargetCheckReceiver<Void> receiver) {
@ -134,4 +149,12 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
this.carriedResourceAmount = carriedResourceAmount; this.carriedResourceAmount = carriedResourceAmount;
} }
public CBehaviorHarvest getBehaviorHarvest() {
return this.behaviorHarvest;
}
public CBehaviorReturnResources getBehaviorReturnResources() {
return this.behaviorReturnResources;
}
} }

View File

@ -6,9 +6,11 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
public abstract class CAbstractRangedBehavior implements CRangedBehavior { public abstract class CAbstractRangedBehavior implements CRangedBehavior {
protected final CUnit unit; protected final CUnit unit;
private final boolean disableCollision;
public CAbstractRangedBehavior(final CUnit unit) { public CAbstractRangedBehavior(final CUnit unit, final boolean disableCollision) {
this.unit = unit; this.unit = unit;
this.disableCollision = disableCollision;
} }
protected AbilityTarget target; protected AbilityTarget target;
@ -22,7 +24,7 @@ public abstract class CAbstractRangedBehavior implements CRangedBehavior {
this.wasInRange = false; this.wasInRange = false;
CBehaviorMove moveBehavior; CBehaviorMove moveBehavior;
if (!this.unit.isMovementDisabled()) { if (!this.unit.isMovementDisabled()) {
moveBehavior = this.unit.getMoveBehavior().reset(this.target, this); moveBehavior = this.unit.getMoveBehavior().reset(this.target, this, this.disableCollision);
} }
else { else {
moveBehavior = null; moveBehavior = null;

View File

@ -15,7 +15,7 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
private final AbilityTargetStillAliveAndTargetableVisitor abilityTargetStillAliveVisitor; private final AbilityTargetStillAliveAndTargetableVisitor abilityTargetStillAliveVisitor;
public CBehaviorAttack(final CUnit unit) { public CBehaviorAttack(final CUnit unit) {
super(unit); super(unit, false);
this.abilityTargetStillAliveVisitor = new AbilityTargetStillAliveAndTargetableVisitor(); this.abilityTargetStillAliveVisitor = new AbilityTargetStillAliveAndTargetableVisitor();
} }

View File

@ -11,7 +11,7 @@ public class CBehaviorFollow extends CAbstractRangedBehavior {
private int higlightOrderId; private int higlightOrderId;
public CBehaviorFollow(final CUnit unit) { public CBehaviorFollow(final CUnit unit) {
super(unit); super(unit, false);
} }
public CBehavior reset(final int higlightOrderId, final CUnit target) { public CBehavior reset(final int higlightOrderId, final CUnit target) {

View File

@ -40,17 +40,21 @@ public class CBehaviorMove implements CBehavior {
private CUnit followUnit; private CUnit followUnit;
private CRangedBehavior rangedBehavior; private CRangedBehavior rangedBehavior;
private boolean firstUpdate = true; private boolean firstUpdate = true;
private boolean disableCollision = false;
public CBehaviorMove reset(final int highlightOrderId, final AbilityTarget target) { public CBehaviorMove reset(final int highlightOrderId, final AbilityTarget target) {
target.visit(this.targetVisitingResetter.reset(highlightOrderId)); target.visit(this.targetVisitingResetter.reset(highlightOrderId));
this.rangedBehavior = null; this.rangedBehavior = null;
this.disableCollision = false;
return this; return this;
} }
public CBehaviorMove reset(final AbilityTarget target, final CRangedBehavior rangedBehavior) { public CBehaviorMove reset(final AbilityTarget target, final CRangedBehavior rangedBehavior,
final boolean disableCollision) {
final int highlightOrderId = rangedBehavior.getHighlightOrderId(); final int highlightOrderId = rangedBehavior.getHighlightOrderId();
target.visit(this.targetVisitingResetter.reset(highlightOrderId)); target.visit(this.targetVisitingResetter.reset(highlightOrderId));
this.rangedBehavior = rangedBehavior; this.rangedBehavior = rangedBehavior;
this.disableCollision = disableCollision;
return this; return this;
} }
@ -99,7 +103,13 @@ public class CBehaviorMove implements CBehavior {
final float prevX = this.unit.getX(); final float prevX = this.unit.getX();
final float prevY = this.unit.getY(); final float prevY = this.unit.getY();
final MovementType movementType = this.unit.getUnitType().getMovementType(); MovementType movementType = this.unit.getUnitType().getMovementType();
if (movementType == null) {
movementType = MovementType.DISABLED;
}
else if ((movementType == MovementType.FOOT) && this.disableCollision) {
movementType = MovementType.FOOT_NO_COLLISION;
}
final PathingGrid pathingGrid = simulation.getPathingGrid(); final PathingGrid pathingGrid = simulation.getPathingGrid();
final CWorldCollision worldCollision = simulation.getWorldCollision(); final CWorldCollision worldCollision = simulation.getWorldCollision();
final float collisionSize = this.unit.getUnitType().getCollisionSize(); final float collisionSize = this.unit.getUnitType().getCollisionSize();
@ -111,7 +121,7 @@ public class CBehaviorMove implements CBehavior {
this.target.y = this.followUnit.getY(); this.target.y = this.followUnit.getY();
} }
this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY, this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY,
this.target, movementType == null ? MovementType.FOOT : movementType, collisionSize, true); this.target, movementType, collisionSize, true);
System.out.println("init path " + this.path); System.out.println("init path " + this.path);
// check for smoothing // check for smoothing
if (!this.path.isEmpty()) { if (!this.path.isEmpty()) {
@ -130,8 +140,7 @@ public class CBehaviorMove implements CBehavior {
if ((totalPathDistance < (1.15 if ((totalPathDistance < (1.15
* nextPossiblePathElement.distance(smoothingGroupStartX, smoothingGroupStartY))) * nextPossiblePathElement.distance(smoothingGroupStartX, smoothingGroupStartY)))
&& pathingGrid.isPathable((smoothingGroupStartX + nextPossiblePathElement.x) / 2, && pathingGrid.isPathable((smoothingGroupStartX + nextPossiblePathElement.x) / 2,
(smoothingGroupStartY + nextPossiblePathElement.y) / 2, (smoothingGroupStartY + nextPossiblePathElement.y) / 2, movementType)) {
movementType == null ? MovementType.DISABLED : movementType)) {
if (smoothingStartIndex == -1) { if (smoothingStartIndex == -1) {
smoothingStartIndex = i; smoothingStartIndex = i;
} }
@ -164,8 +173,7 @@ public class CBehaviorMove implements CBehavior {
this.target.x = this.followUnit.getX(); this.target.x = this.followUnit.getX();
this.target.y = this.followUnit.getY(); this.target.y = this.followUnit.getY();
this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY, this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY,
this.target, movementType == null ? MovementType.FOOT : movementType, collisionSize, this.target, movementType, collisionSize, this.searchCycles < 4);
this.searchCycles < 4);
System.out.println("new path (for target) " + this.path); System.out.println("new path (for target) " + this.path);
if (this.path.isEmpty()) { if (this.path.isEmpty()) {
return this.unit.pollNextOrderBehavior(simulation); return this.unit.pollNextOrderBehavior(simulation);
@ -334,8 +342,7 @@ public class CBehaviorMove implements CBehavior {
this.target.y = this.followUnit.getY(); this.target.y = this.followUnit.getY();
} }
this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY, this.path = simulation.findNaiveSlowPath(this.unit, this.followUnit, startFloatingX, startFloatingY,
this.target, movementType == null ? MovementType.FOOT : movementType, collisionSize, this.target, movementType, collisionSize, this.searchCycles < 4);
this.searchCycles < 4);
this.searchCycles++; this.searchCycles++;
System.out.println("new path " + this.path); System.out.println("new path " + this.path);
if (this.path.isEmpty() || (this.searchCycles > 5)) { if (this.path.isEmpty() || (this.searchCycles > 5)) {

View File

@ -37,7 +37,7 @@ public class CBehaviorPatrol implements CRangedBehavior {
final AbilityPointTarget temp = this.target; final AbilityPointTarget temp = this.target;
this.target = this.startPoint; this.target = this.startPoint;
this.startPoint = temp; this.startPoint = temp;
return this.unit.getMoveBehavior().reset(this.target, this); return this.unit.getMoveBehavior().reset(this.target, this, false);
} }
} }

View File

@ -21,7 +21,7 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
private War3ID orderId; private War3ID orderId;
public CBehaviorOrcBuild(final CUnit unit) { public CBehaviorOrcBuild(final CUnit unit) {
super(unit); super(unit, false);
} }
public CBehavior reset(final AbilityPointTarget target, final int orderId, final int highlightOrderId) { public CBehavior reset(final AbilityPointTarget target, final int orderId, final int highlightOrderId) {

View File

@ -1,7 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest; package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest;
import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag; import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
@ -9,7 +11,6 @@ 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.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityHarvest; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine; 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.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;
@ -17,7 +18,6 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior; 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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
public class CBehaviorHarvest extends CAbstractRangedBehavior implements AbilityTargetVisitor<CBehavior> { public class CBehaviorHarvest extends CAbstractRangedBehavior implements AbilityTargetVisitor<CBehavior> {
@ -27,7 +27,7 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
private CAbilityGoldMine abilityGoldMine; private CAbilityGoldMine abilityGoldMine;
public CBehaviorHarvest(final CUnit unit, final CAbilityHarvest abilityHarvest) { public CBehaviorHarvest(final CUnit unit, final CAbilityHarvest abilityHarvest) {
super(unit); super(unit, true);
this.abilityHarvest = abilityHarvest; this.abilityHarvest = abilityHarvest;
} }
@ -44,8 +44,7 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
@Override @Override
public boolean isWithinRange(final CSimulation simulation) { public boolean isWithinRange(final CSimulation simulation) {
// TODO this is probably not what the CloseEnoughRange constant is for return this.unit.canReach(this.target, this.unit.getUnitType().getCollisionSize());
return this.unit.canReach(this.target, simulation.getGameplayConstants().getCloseEnoughRange());
} }
@Override @Override
@ -75,40 +74,31 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
final int activeMiners = abilityGoldMine.getActiveMiners(); final int activeMiners = abilityGoldMine.getActiveMiners();
if (activeMiners < abilityGoldMine.getMiningCapacity()) { if (activeMiners < abilityGoldMine.getMiningCapacity()) {
abilityGoldMine.setActiveMiners(activeMiners + 1); abilityGoldMine.setActiveMiners(activeMiners + 1);
if (activeMiners == 0) {
target.getUnitAnimationListener().addSecondaryTag(SecondaryTag.WORK);
}
this.unit.setHidden(true); this.unit.setHidden(true);
this.unit.setInvulnerable(true); this.unit.setInvulnerable(true);
this.popoutFromMineTurnTick = this.simulation.getGameTurnTick() this.popoutFromMineTurnTick = this.simulation.getGameTurnTick()
+ (int) (abilityGoldMine.getMiningDuration() + (int) (abilityGoldMine.getMiningDuration()
/ WarsmashConstants.SIMULATION_STEP_TIME); / WarsmashConstants.SIMULATION_STEP_TIME);
this.abilityGoldMine = abilityGoldMine; this.abilityGoldMine = abilityGoldMine;
break;
} }
else {
// we are stuck waiting to mine, let's make sure we play stand animation
this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND,
SequenceUtils.EMPTY, 1.0f, true);
}
return this;
} }
} }
// weird invalid target and we have no resources, consider harvesting done
return this.unit.pollNextOrderBehavior(this.simulation);
} }
else { else {
for (final CAbility ability : target.getAbilities()) { // we have some GOLD and we're not in a mine (?) lets do a return resources
if (ability instanceof CAbilityReturnResources) { // order
final CAbilityReturnResources abilityReturnResources = (CAbilityReturnResources) ability; return this.abilityHarvest.getBehaviorReturnResources().reset(this.simulation);
if (abilityReturnResources.accepts(this.abilityHarvest.getCarriedResourceType())) {
final CPlayer player = this.simulation.getPlayer(this.unit.getPlayerIndex());
switch (this.abilityHarvest.getCarriedResourceType()) {
case FOOD:
throw new IllegalStateException("Unit used Harvest skill to carry FOOD resource!");
case GOLD:
player.setGold(player.getGold() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.GOLD);
break;
case LUMBER:
player.setLumber(player.getLumber() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.LUMBER);
break;
}
this.abilityHarvest.setCarriedResources(null, 0);
return this.unit.pollNextOrderBehavior(this.simulation);
}
}
}
} }
} }
else { else {
@ -116,7 +106,11 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
this.popoutFromMineTurnTick = 0; this.popoutFromMineTurnTick = 0;
this.unit.setHidden(false); this.unit.setHidden(false);
this.unit.setInvulnerable(false); this.unit.setInvulnerable(false);
this.abilityGoldMine.setActiveMiners(this.abilityGoldMine.getActiveMiners() - 1); final int activeMiners = this.abilityGoldMine.getActiveMiners() - 1;
this.abilityGoldMine.setActiveMiners(activeMiners);
if (activeMiners == 0) {
target.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.WORK);
}
int mineGoldRemaining = this.abilityGoldMine.getGold(); int mineGoldRemaining = this.abilityGoldMine.getGold();
final int goldMined = Math.min(mineGoldRemaining, this.abilityHarvest.getGoldCapacity()); final int goldMined = Math.min(mineGoldRemaining, this.abilityHarvest.getGoldCapacity());
this.abilityHarvest.setCarriedResources(ResourceType.GOLD, goldMined); this.abilityHarvest.setCarriedResources(ResourceType.GOLD, goldMined);
@ -127,16 +121,25 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
} }
this.unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.GOLD); this.unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.GOLD);
this.simulation.unitRepositioned(this.unit); this.simulation.unitRepositioned(this.unit);
return this.unit.pollNextOrderBehavior(this.simulation); // we just finished getting gold, lets do a return resources order
return this.abilityHarvest.getBehaviorReturnResources().reset(this.simulation);
}
else {
// continue working inside mine
return this;
} }
} }
return this;
} }
@Override @Override
public CBehavior accept(final CDestructable target) { public CBehavior accept(final CDestructable target) {
// TODO cut trees! // TODO cut trees!
return this.unit.pollNextOrderBehavior(this.simulation); if (String.valueOf(target).length() > 5) {
return this.unit.pollNextOrderBehavior(this.simulation);
}
else {
return null;
}
} }
@Override @Override

View File

@ -0,0 +1,172 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityReturnResources;
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.abilities.targeting.AbilityTargetStillAliveVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetVisitor;
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;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
public class CBehaviorReturnResources extends CAbstractRangedBehavior implements AbilityTargetVisitor<CBehavior> {
private final CAbilityHarvest abilityHarvest;
private CSimulation simulation;
public CBehaviorReturnResources(final CUnit unit, final CAbilityHarvest abilityHarvest) {
super(unit, true);
this.abilityHarvest = abilityHarvest;
}
public CBehaviorReturnResources reset(final CSimulation simulation) {
innerReset(findNearestDropoffPoint(simulation));
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
// TODO this is probably not what the CloseEnoughRange constant is for
return this.unit.canReach(this.target, this.unit.getUnitType().getCollisionSize());
}
@Override
public int getHighlightOrderId() {
return OrderIds.returnresources;
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinRange) {
this.simulation = simulation;
return this.target.visit(this);
}
@Override
public CBehavior accept(final AbilityPointTarget target) {
return CBehaviorReturnResources.this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
public CBehavior accept(final CUnit target) {
for (final CAbility ability : target.getAbilities()) {
if (ability instanceof CAbilityReturnResources) {
final CAbilityReturnResources abilityReturnResources = (CAbilityReturnResources) ability;
if (abilityReturnResources.accepts(this.abilityHarvest.getCarriedResourceType())) {
final CPlayer player = this.simulation.getPlayer(this.unit.getPlayerIndex());
switch (this.abilityHarvest.getCarriedResourceType()) {
case FOOD:
throw new IllegalStateException("Unit used Harvest skill to carry FOOD resource!");
case GOLD:
player.setGold(player.getGold() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.GOLD);
break;
case LUMBER:
player.setLumber(player.getLumber() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.LUMBER);
break;
}
this.abilityHarvest.setCarriedResources(null, 0);
final CUnit nearestMine = findNearestMine(this.unit, this.simulation);
if (nearestMine != null) {
return this.abilityHarvest.getBehaviorHarvest().reset(nearestMine);
}
return this.unit.pollNextOrderBehavior(this.simulation);
}
}
}
return this;
}
@Override
public CBehavior accept(final CDestructable target) {
// TODO cut trees!
return this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
public CBehavior accept(final CItem target) {
return this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
protected boolean checkTargetStillValid(final CSimulation simulation) {
final boolean aliveCheck = this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
if (!aliveCheck) {
final CUnit nearestDropoff = findNearestDropoffPoint(simulation);
if (nearestDropoff == null) {
return false;
}
else {
this.target = nearestDropoff;
return true;
}
}
return true;
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
private CUnit findNearestDropoffPoint(final CSimulation simulation) {
CUnit nearestDropoffPoint = null;
double nearestDropoffDistance = Float.MAX_VALUE;
for (final CUnit unit : simulation.getUnits()) {
if (unit.getPlayerIndex() == this.unit.getPlayerIndex()) {
boolean acceptedUnit = false;
for (final CAbility ability : unit.getAbilities()) {
if (ability instanceof CAbilityReturnResources) {
final CAbilityReturnResources abilityReturnResources = (CAbilityReturnResources) ability;
if (abilityReturnResources.accepts(this.abilityHarvest.getCarriedResourceType())) {
acceptedUnit = true;
break;
}
}
}
if (acceptedUnit) {
// TODO maybe use distance squared, problem is that we're using this
// inefficient more complex distance function on unit
final double distance = unit.distanceSquaredNoCollision(this.unit);
if (distance < nearestDropoffDistance) {
nearestDropoffDistance = distance;
nearestDropoffPoint = unit;
}
}
}
}
return nearestDropoffPoint;
}
private static CUnit findNearestMine(final CUnit worker, final CSimulation simulation) {
CUnit nearestMine = null;
double nearestMineDistance = Float.MAX_VALUE;
for (final CUnit unit : simulation.getUnits()) {
boolean acceptedUnit = false;
for (final CAbility ability : unit.getAbilities()) {
if (ability instanceof CAbilityGoldMine) {
acceptedUnit = true;
break;
}
}
if (acceptedUnit) {
// TODO maybe use distance squared, problem is that we're using this
// inefficient more complex distance function on unit
final double distance = unit.distanceSquaredNoCollision(worker);
if (distance < nearestMineDistance) {
nearestMineDistance = distance;
nearestMine = unit;
}
}
}
return nearestMine;
}
}

View File

@ -39,6 +39,11 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
this.damageFactorSmall = damageFactorSmall; this.damageFactorSmall = damageFactorSmall;
} }
@Override
public int getRange() {
return super.getRange();
}
public int getAreaOfEffectFullDamage() { public int getAreaOfEffectFullDamage() {
return this.areaOfEffectFullDamage; return this.areaOfEffectFullDamage;
} }

View File

@ -1540,9 +1540,15 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
@Override @Override
public void foodChanged() { public void foodChanged() {
this.resourceBarSupplyText.setText(this.localPlayer.getFoodUsed() + "/" + this.localPlayer.getFoodCap()); final int foodCap = this.localPlayer.getFoodCap();
this.resourceBarSupplyText if (foodCap == 0) {
.setColor(this.localPlayer.getFoodUsed() > this.localPlayer.getFoodCap() ? Color.RED : Color.WHITE); this.resourceBarSupplyText.setText(Integer.toString(this.localPlayer.getFoodUsed()));
this.resourceBarSupplyText.setColor(Color.WHITE);
}
else {
this.resourceBarSupplyText.setText(this.localPlayer.getFoodUsed() + "/" + foodCap);
this.resourceBarSupplyText.setColor(this.localPlayer.getFoodUsed() > foodCap ? Color.RED : Color.WHITE);
}
} }
@Override @Override