mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Update to have lumber harvest, still bugged
This commit is contained in:
parent
600ec9536b
commit
581f51ef65
@ -20,7 +20,7 @@ Path07="."
|
||||
[Map]
|
||||
//FilePath="CombatUnitTests.w3x"
|
||||
//FilePath="PitchRoll.w3x"
|
||||
FilePath="PeonStartingBase.w3x"
|
||||
FilePath="PeonStartingBase_Simple.w3x"
|
||||
//FilePath="MyStromguarde.w3m"
|
||||
//FilePath="ColdArrows.w3m"
|
||||
//FilePath="DungeonGoldMine.w3m"
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.etheller.warsmash.viewer5;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
@ -310,10 +311,11 @@ public class Camera {
|
||||
final Rectangle viewport = this.rect;
|
||||
|
||||
vectorHeap.set(v);
|
||||
vectorHeap.prj(this.inverseViewMatrix);
|
||||
vectorHeap.prj(this.viewProjectionMatrix);
|
||||
|
||||
out.x = Math.round(((vectorHeap.x + 1) / 2) * viewport.width);
|
||||
out.y = Math.round(((vectorHeap.y + 1) / 2) * viewport.height);
|
||||
out.y = ((Gdx.graphics.getHeight() - viewport.y - viewport.height) + (viewport.height))
|
||||
- Math.round(((vectorHeap.y + 1) / 2) * viewport.height);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public class SequenceUtils {
|
||||
public static final EnumSet<SecondaryTag> FLESH = EnumSet.of(SecondaryTag.FLESH);
|
||||
public static final EnumSet<SecondaryTag> TALK = EnumSet.of(SecondaryTag.TALK);
|
||||
public static final EnumSet<SecondaryTag> BONE = EnumSet.of(SecondaryTag.BONE);
|
||||
public static final EnumSet<SecondaryTag> HIT = EnumSet.of(SecondaryTag.HIT);
|
||||
|
||||
private static final StandSequenceComparator STAND_SEQUENCE_COMPARATOR = new StandSequenceComparator();
|
||||
private static final SecondaryTagSequenceComparator SECONDARY_TAG_SEQUENCE_COMPARATOR = new SecondaryTagSequenceComparator(
|
||||
|
@ -0,0 +1,36 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
public class TextTag {
|
||||
private final Vector3 position;
|
||||
private final String text;
|
||||
private final Color color;
|
||||
private int lifetime = 0;
|
||||
|
||||
public TextTag(final Vector3 position, final String text, final Color color) {
|
||||
this.position = position;
|
||||
this.text = text;
|
||||
this.color = color;
|
||||
position.z += 64f;
|
||||
}
|
||||
|
||||
public boolean update() {
|
||||
this.position.z += 1.0f;
|
||||
this.lifetime++;
|
||||
return this.lifetime > 196;
|
||||
}
|
||||
|
||||
public Vector3 getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
@ -94,8 +95,10 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidgetFilterFunction;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.sound.KeyedSounds;
|
||||
@ -104,6 +107,8 @@ import mpq.MPQArchive;
|
||||
import mpq.MPQException;
|
||||
|
||||
public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
private static final Color PLACEHOLDER_LUMBER_COLOR = new Color(0.0f, 200f / 255f, 80f / 255f, 1.0f);
|
||||
private static final Color PLACEHOLDER_GOLD_COLOR = new Color(1.0f, 220f / 255f, 0f, 1.0f);
|
||||
private static final War3ID UNIT_FILE = War3ID.fromString("umdl");
|
||||
private static final War3ID UNIT_SPECIAL = War3ID.fromString("uspa");
|
||||
private static final War3ID UBER_SPLAT = War3ID.fromString("uubs");
|
||||
@ -203,6 +208,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
private int localPlayerIndex;
|
||||
private final CommandErrorListener commandErrorListener;
|
||||
|
||||
public final List<TextTag> textTags = new ArrayList<>();
|
||||
|
||||
public War3MapViewer(final DataSource dataSource, final CanvasProvider canvas,
|
||||
final CommandErrorListener errorListener) {
|
||||
super(dataSource, canvas);
|
||||
@ -449,7 +456,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
public CAttackProjectile createAttackProjectile(final CSimulation simulation, final float launchX,
|
||||
final float launchY, final float launchFacing, final CUnit source,
|
||||
final CUnitAttackMissile unitAttack, final AbilityTarget target, final float damage,
|
||||
final int bounceIndex) {
|
||||
final int bounceIndex, final CUnitAttackListener attackListener) {
|
||||
final War3ID typeId = source.getTypeId();
|
||||
final int projectileSpeed = unitAttack.getProjectileSpeed();
|
||||
final float projectileArc = unitAttack.getProjectileArc();
|
||||
@ -468,7 +475,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
final float height = War3MapViewer.this.terrain.getGroundHeight(x, y) + source.getFlyHeight()
|
||||
+ projectileLaunchZ;
|
||||
final CAttackProjectile simulationAttackProjectile = new CAttackProjectile(x, y,
|
||||
projectileSpeed, target, source, damage, unitAttack, bounceIndex);
|
||||
projectileSpeed, target, source, damage, unitAttack, bounceIndex, attackListener);
|
||||
|
||||
final MdxModel model = (MdxModel) load(missileArt, War3MapViewer.this.mapPathSolver,
|
||||
War3MapViewer.this.solverParams);
|
||||
@ -563,7 +570,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
@Override
|
||||
public void removeDestructable(final CDestructable dest) {
|
||||
final RenderDestructable renderPeer = War3MapViewer.this.destructableToRenderPeer.remove(dest);
|
||||
War3MapViewer.this.doodads.remove(renderPeer);
|
||||
War3MapViewer.this.worldScene.removeInstance(renderPeer.instance);
|
||||
if (renderPeer.walkableBounds != null) {
|
||||
War3MapViewer.this.walkableObjectsTree.remove((MdxComplexInstance) renderPeer.instance,
|
||||
@ -634,6 +640,24 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(cUnit);
|
||||
renderPeer.repositioned(War3MapViewer.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnGainResourceTextTag(final CUnit gainingUnit, final ResourceType resourceType,
|
||||
final int amount) {
|
||||
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(gainingUnit);
|
||||
switch (resourceType) {
|
||||
case FOOD:
|
||||
throw new IllegalArgumentException();
|
||||
case GOLD:
|
||||
War3MapViewer.this.textTags.add(new TextTag(new Vector3(renderPeer.location), "+" + amount,
|
||||
PLACEHOLDER_GOLD_COLOR));
|
||||
break;
|
||||
case LUMBER:
|
||||
War3MapViewer.this.textTags.add(new TextTag(new Vector3(renderPeer.location), "+" + amount,
|
||||
PLACEHOLDER_LUMBER_COLOR));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, w3iFile.getPlayers(),
|
||||
this.commandErrorListener);
|
||||
|
||||
@ -784,6 +808,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
final float y = doodad.getLocation()[1];
|
||||
final CDestructable simulationDestructable = this.simulation.createDestructable(row.getAlias(), x,
|
||||
y, destructablePathing, destructablePathingDeath);
|
||||
simulationDestructable.setLife(this.simulation,
|
||||
simulationDestructable.getLife() * (doodad.getLife() / 100f));
|
||||
final RenderDestructable renderDestructable = new RenderDestructable(this, model, row, doodad, type,
|
||||
maxPitch, maxRoll, doodad.getLife(), destructableShadow, simulationDestructable);
|
||||
if (row.readSLKTagBoolean("walkable")) {
|
||||
@ -796,7 +822,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
renderDestructableBounds);
|
||||
renderDestructable.walkableBounds = renderDestructableBounds;
|
||||
}
|
||||
this.doodads.add(renderDestructable);
|
||||
this.widgets.add(renderDestructable);
|
||||
}
|
||||
else {
|
||||
@ -1199,6 +1224,12 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
|
||||
super.update();
|
||||
|
||||
final Iterator<TextTag> textTagIterator = this.textTags.iterator();
|
||||
while (textTagIterator.hasNext()) {
|
||||
if (textTagIterator.next().update()) {
|
||||
textTagIterator.remove();
|
||||
}
|
||||
}
|
||||
for (final RenderWidget unit : this.widgets) {
|
||||
unit.updateAnimations(this);
|
||||
}
|
||||
@ -1683,4 +1714,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(final TextTag textTag) {
|
||||
this.textTags.add(textTag);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
||||
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
||||
@ -7,6 +8,7 @@ import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.BuildingShadow;
|
||||
@ -18,17 +20,21 @@ public class RenderDestructable extends RenderDoodad implements RenderWidget {
|
||||
private static final War3ID TEX_ID = War3ID.fromString("btxi");
|
||||
private static final War3ID SEL_CIRCLE_SIZE = War3ID.fromString("bgsc");
|
||||
|
||||
private final float life;
|
||||
private float life;
|
||||
public Rectangle walkableBounds;
|
||||
private final CDestructable simulationDestructable;
|
||||
private SplatMover selectionCircle;
|
||||
private final UnitAnimationListenerImpl unitAnimationListenerImpl;
|
||||
private boolean dead;
|
||||
private BuildingShadow destructableShadow;
|
||||
|
||||
public RenderDestructable(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
|
||||
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type,
|
||||
final float maxPitch, final float maxRoll, final float life, final BuildingShadow destructableShadow,
|
||||
final CDestructable simulationDestructable) {
|
||||
super(map, model, row, doodad, type, maxPitch, maxRoll);
|
||||
this.life = life;
|
||||
this.life = simulationDestructable.getLife();
|
||||
this.destructableShadow = destructableShadow;
|
||||
this.simulationDestructable = simulationDestructable;
|
||||
String replaceableTextureFile = row.getFieldAsString(TEX_FILE, 0);
|
||||
final int replaceableTextureId = row.getFieldAsInteger(TEX_ID, 0);
|
||||
@ -41,6 +47,9 @@ public class RenderDestructable extends RenderDoodad implements RenderWidget {
|
||||
this.instance.setReplaceableTexture(replaceableTextureId, replaceableTextureFile);
|
||||
}
|
||||
this.selectionScale *= row.getFieldAsFloat(SEL_CIRCLE_SIZE, 0);
|
||||
this.unitAnimationListenerImpl = new UnitAnimationListenerImpl((MdxComplexInstance) this.instance);
|
||||
simulationDestructable.setUnitAnimationListener(this.unitAnimationListenerImpl);
|
||||
this.unitAnimationListenerImpl.playAnimation(true, getAnimation(), SequenceUtils.EMPTY, 1.0f, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,6 +74,37 @@ public class RenderDestructable extends RenderDoodad implements RenderWidget {
|
||||
public void updateAnimations(final War3MapViewer war3MapViewer) {
|
||||
// TODO maybe move getAnimation behaviors to here and make this thing not a
|
||||
// doodad
|
||||
|
||||
final boolean dead = this.simulationDestructable.isDead();
|
||||
if (dead && !this.dead) {
|
||||
this.unitAnimationListenerImpl.playAnimation(true, PrimaryTag.DEATH, SequenceUtils.EMPTY, 1.0f, true);
|
||||
if (this.destructableShadow != null) {
|
||||
this.destructableShadow.remove();
|
||||
this.destructableShadow = null;
|
||||
}
|
||||
if (this.selectionCircle != null) {
|
||||
this.selectionCircle.destroy(Gdx.gl30, war3MapViewer.terrain.centerOffset);
|
||||
this.selectionCircle = null;
|
||||
}
|
||||
}
|
||||
else if (!dead) {
|
||||
if (this.dead) {
|
||||
this.unitAnimationListenerImpl.playAnimation(true, PrimaryTag.BIRTH, SequenceUtils.EMPTY, 1.0f, true);
|
||||
// TODO add back shadow here
|
||||
|
||||
}
|
||||
else {
|
||||
if (Math.abs(this.life - this.simulationDestructable.getLife()) > 0.003f) {
|
||||
if (this.life > this.simulationDestructable.getLife()) {
|
||||
this.unitAnimationListenerImpl.playAnimation(true, PrimaryTag.STAND, SequenceUtils.HIT, 1.0f,
|
||||
true);
|
||||
}
|
||||
this.life = this.simulationDestructable.getLife();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.dead = dead;
|
||||
this.unitAnimationListenerImpl.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
@ -11,7 +9,6 @@ import com.etheller.warsmash.util.RenderMathUtils;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.Sequence;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
|
||||
@ -27,7 +24,6 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.Comma
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandCardPopulatingAbilityVisitor;
|
||||
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.CUnitAnimationListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
||||
|
||||
@ -436,119 +432,6 @@ public class RenderUnit implements RenderWidget {
|
||||
return this.unitAnimationListenerImpl.secondaryAnimationTags;
|
||||
}
|
||||
|
||||
private static final class UnitAnimationListenerImpl implements CUnitAnimationListener {
|
||||
private final MdxComplexInstance instance;
|
||||
private final EnumSet<AnimationTokens.SecondaryTag> secondaryAnimationTags = EnumSet
|
||||
.noneOf(AnimationTokens.SecondaryTag.class);
|
||||
private final EnumSet<AnimationTokens.SecondaryTag> recycleSet = EnumSet
|
||||
.noneOf(AnimationTokens.SecondaryTag.class);
|
||||
private PrimaryTag currentAnimation;
|
||||
private EnumSet<SecondaryTag> currentAnimationSecondaryTags;
|
||||
private float currentSpeedRatio;
|
||||
private boolean currentlyAllowingRarityVariations;
|
||||
private final Queue<QueuedAnimation> animationQueue = new LinkedList<>();
|
||||
|
||||
public UnitAnimationListenerImpl(final MdxComplexInstance instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSecondaryTag(final AnimationTokens.SecondaryTag tag) {
|
||||
this.secondaryAnimationTags.add(tag);
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio,
|
||||
this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSecondaryTag(final AnimationTokens.SecondaryTag tag) {
|
||||
this.secondaryAnimationTags.remove(tag);
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio,
|
||||
this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAnimation(final boolean force, final PrimaryTag animationName,
|
||||
final EnumSet<SecondaryTag> secondaryAnimationTags, final float speedRatio,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.clear();
|
||||
if (force || (animationName != this.currentAnimation)
|
||||
|| !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags)) {
|
||||
this.currentSpeedRatio = speedRatio;
|
||||
this.recycleSet.clear();
|
||||
this.recycleSet.addAll(this.secondaryAnimationTags);
|
||||
this.recycleSet.addAll(secondaryAnimationTags);
|
||||
this.instance.setAnimationSpeed(speedRatio);
|
||||
if (SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
|
||||
allowRarityVariations) != null) {
|
||||
this.currentAnimation = animationName;
|
||||
this.currentAnimationSecondaryTags = secondaryAnimationTags;
|
||||
this.currentlyAllowingRarityVariations = allowRarityVariations;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void playAnimationWithDuration(final boolean force, final PrimaryTag animationName,
|
||||
final EnumSet<SecondaryTag> secondaryAnimationTags, final float duration,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.clear();
|
||||
if (force || (animationName != this.currentAnimation)
|
||||
|| !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags)) {
|
||||
this.recycleSet.clear();
|
||||
this.recycleSet.addAll(this.secondaryAnimationTags);
|
||||
this.recycleSet.addAll(secondaryAnimationTags);
|
||||
final Sequence sequence = SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
|
||||
allowRarityVariations);
|
||||
if (sequence != null) {
|
||||
this.currentAnimation = animationName;
|
||||
this.currentAnimationSecondaryTags = secondaryAnimationTags;
|
||||
this.currentlyAllowingRarityVariations = allowRarityVariations;
|
||||
this.currentSpeedRatio = ((sequence.getInterval()[1] - sequence.getInterval()[0]) / 1000.0f)
|
||||
/ duration;
|
||||
this.instance.setAnimationSpeed(this.currentSpeedRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueAnimation(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryAnimationTags,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.add(new QueuedAnimation(animationName, secondaryAnimationTags, allowRarityVariations));
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (this.instance.sequenceEnded || (this.instance.sequence == -1)) {
|
||||
// animation done
|
||||
if ((this.instance.sequence != -1) && (((MdxModel) this.instance.model).getSequences()
|
||||
.get(this.instance.sequence).getFlags() == 0)) {
|
||||
// animation is a looping animation
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags,
|
||||
this.currentSpeedRatio, this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
else {
|
||||
final QueuedAnimation nextAnimation = this.animationQueue.poll();
|
||||
if (nextAnimation != null) {
|
||||
playAnimation(true, nextAnimation.animationName, nextAnimation.secondaryAnimationTags, 1.0f,
|
||||
nextAnimation.allowRarityVariations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class QueuedAnimation {
|
||||
private final PrimaryTag animationName;
|
||||
private final EnumSet<SecondaryTag> secondaryAnimationTags;
|
||||
private final boolean allowRarityVariations;
|
||||
|
||||
public QueuedAnimation(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryAnimationTags,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationName = animationName;
|
||||
this.secondaryAnimationTags = secondaryAnimationTags;
|
||||
this.allowRarityVariations = allowRarityVariations;
|
||||
}
|
||||
}
|
||||
|
||||
public void repositioned(final War3MapViewer map) {
|
||||
final float prevX = this.location[0];
|
||||
final float prevY = this.location[1];
|
||||
|
@ -1,8 +1,19 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.Sequence;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens;
|
||||
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.SequenceUtils;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitAnimationListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||
|
||||
public interface RenderWidget {
|
||||
@ -23,4 +34,127 @@ public interface RenderWidget {
|
||||
void unassignSelectionCircle();
|
||||
|
||||
void assignSelectionCircle(SplatMover t);
|
||||
|
||||
public static final class UnitAnimationListenerImpl implements CUnitAnimationListener {
|
||||
private final MdxComplexInstance instance;
|
||||
protected final EnumSet<AnimationTokens.SecondaryTag> secondaryAnimationTags = EnumSet
|
||||
.noneOf(AnimationTokens.SecondaryTag.class);
|
||||
private final EnumSet<AnimationTokens.SecondaryTag> recycleSet = EnumSet
|
||||
.noneOf(AnimationTokens.SecondaryTag.class);
|
||||
private PrimaryTag currentAnimation;
|
||||
private EnumSet<SecondaryTag> currentAnimationSecondaryTags;
|
||||
private float currentSpeedRatio;
|
||||
private boolean currentlyAllowingRarityVariations;
|
||||
private final Queue<QueuedAnimation> animationQueue = new LinkedList<>();
|
||||
|
||||
public UnitAnimationListenerImpl(final MdxComplexInstance instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSecondaryTag(final AnimationTokens.SecondaryTag tag) {
|
||||
if (!secondaryAnimationTags.contains(tag)) {
|
||||
this.secondaryAnimationTags.add(tag);
|
||||
if (!animationQueue.isEmpty()) {
|
||||
final QueuedAnimation nextAnimation = animationQueue.poll();
|
||||
playAnimation(true, nextAnimation.animationName, nextAnimation.secondaryAnimationTags, 1.0f,
|
||||
nextAnimation.allowRarityVariations);
|
||||
}
|
||||
else {
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags,
|
||||
this.currentSpeedRatio, this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSecondaryTag(final AnimationTokens.SecondaryTag tag) {
|
||||
if (secondaryAnimationTags.contains(tag)) {
|
||||
this.secondaryAnimationTags.remove(tag);
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio,
|
||||
this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAnimation(final boolean force, final PrimaryTag animationName,
|
||||
final EnumSet<SecondaryTag> secondaryAnimationTags, final float speedRatio,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.clear();
|
||||
if (force || (animationName != this.currentAnimation)
|
||||
|| !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags)) {
|
||||
this.currentSpeedRatio = speedRatio;
|
||||
this.recycleSet.clear();
|
||||
this.recycleSet.addAll(this.secondaryAnimationTags);
|
||||
this.recycleSet.addAll(secondaryAnimationTags);
|
||||
this.instance.setAnimationSpeed(speedRatio);
|
||||
if (SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
|
||||
allowRarityVariations) != null) {
|
||||
this.currentAnimation = animationName;
|
||||
this.currentAnimationSecondaryTags = secondaryAnimationTags;
|
||||
this.currentlyAllowingRarityVariations = allowRarityVariations;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void playAnimationWithDuration(final boolean force, final PrimaryTag animationName,
|
||||
final EnumSet<SecondaryTag> secondaryAnimationTags, final float duration,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.clear();
|
||||
if (force || (animationName != this.currentAnimation)
|
||||
|| !secondaryAnimationTags.equals(this.currentAnimationSecondaryTags)) {
|
||||
this.recycleSet.clear();
|
||||
this.recycleSet.addAll(this.secondaryAnimationTags);
|
||||
this.recycleSet.addAll(secondaryAnimationTags);
|
||||
final Sequence sequence = SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
|
||||
allowRarityVariations);
|
||||
if (sequence != null) {
|
||||
this.currentAnimation = animationName;
|
||||
this.currentAnimationSecondaryTags = secondaryAnimationTags;
|
||||
this.currentlyAllowingRarityVariations = allowRarityVariations;
|
||||
this.currentSpeedRatio = ((sequence.getInterval()[1] - sequence.getInterval()[0]) / 1000.0f)
|
||||
/ duration;
|
||||
this.instance.setAnimationSpeed(this.currentSpeedRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueAnimation(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryAnimationTags,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationQueue.add(new QueuedAnimation(animationName, secondaryAnimationTags, allowRarityVariations));
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (this.instance.sequenceEnded || (this.instance.sequence == -1)) {
|
||||
// animation done
|
||||
if ((this.instance.sequence != -1) && (((MdxModel) this.instance.model).getSequences()
|
||||
.get(this.instance.sequence).getFlags() == 0)) {
|
||||
// animation is a looping animation
|
||||
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags,
|
||||
this.currentSpeedRatio, this.currentlyAllowingRarityVariations);
|
||||
}
|
||||
else {
|
||||
final QueuedAnimation nextAnimation = this.animationQueue.poll();
|
||||
if (nextAnimation != null) {
|
||||
playAnimation(true, nextAnimation.animationName, nextAnimation.secondaryAnimationTags, 1.0f,
|
||||
nextAnimation.allowRarityVariations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class QueuedAnimation {
|
||||
private final PrimaryTag animationName;
|
||||
private final EnumSet<SecondaryTag> secondaryAnimationTags;
|
||||
private final boolean allowRarityVariations;
|
||||
|
||||
public QueuedAnimation(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryAnimationTags,
|
||||
final boolean allowRarityVariations) {
|
||||
this.animationName = animationName;
|
||||
this.secondaryAnimationTags = secondaryAnimationTags;
|
||||
this.allowRarityVariations = allowRarityVariations;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.RemovablePathingMapInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderWidget.UnitAnimationListenerImpl;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetVisitor;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
|
||||
@ -12,6 +13,7 @@ public class CDestructable extends CWidget {
|
||||
private final CDestructableType destType;
|
||||
private final RemovablePathingMapInstance pathingInstance;
|
||||
private final RemovablePathingMapInstance pathingInstanceDeath;
|
||||
private UnitAnimationListenerImpl unitAnimationListenerImpl;
|
||||
|
||||
public CDestructable(final int handleId, final float x, final float y, final float life,
|
||||
final CDestructableType destTypeInstance, final RemovablePathingMapInstance pathingInstance,
|
||||
@ -65,4 +67,8 @@ public class CDestructable extends CWidget {
|
||||
public CDestructableType getDestType() {
|
||||
return this.destType;
|
||||
}
|
||||
|
||||
public void setUnitAnimationListener(final UnitAnimationListenerImpl unitAnimationListenerImpl) {
|
||||
this.unitAnimationListenerImpl = unitAnimationListenerImpl;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorMove;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CAbilityData;
|
||||
@ -31,6 +32,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceTy
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
|
||||
|
||||
@ -125,6 +127,10 @@ public class CSimulation {
|
||||
return this.units;
|
||||
}
|
||||
|
||||
public List<CDestructable> getDestructables() {
|
||||
return this.destructables;
|
||||
}
|
||||
|
||||
public CUnit createUnit(final War3ID typeId, final int playerIndex, final float x, final float y,
|
||||
final float facing, final BufferedImage buildingPathingPixelMap,
|
||||
final RemovablePathingMapInstance pathingInstance) {
|
||||
@ -164,9 +170,9 @@ public class CSimulation {
|
||||
|
||||
public CAttackProjectile createProjectile(final CUnit source, final float launchX, final float launchY,
|
||||
final float launchFacing, final CUnitAttackMissile attack, final AbilityTarget target, final float damage,
|
||||
final int bounceIndex) {
|
||||
final int bounceIndex, final CUnitAttackListener attackListener) {
|
||||
final CAttackProjectile projectile = this.simulationRenderController.createAttackProjectile(this, launchX,
|
||||
launchY, launchFacing, source, attack, target, damage, bounceIndex);
|
||||
launchY, launchFacing, source, attack, target, damage, bounceIndex, attackListener);
|
||||
this.newProjectiles.add(projectile);
|
||||
return projectile;
|
||||
}
|
||||
@ -292,6 +298,10 @@ public class CSimulation {
|
||||
this.simulationRenderController.unitRepositioned(cUnit);
|
||||
}
|
||||
|
||||
public void unitGainResourceEvent(final CUnit unit, final ResourceType resourceType, final int amount) {
|
||||
this.simulationRenderController.spawnGainResourceTextTag(unit, resourceType, amount);
|
||||
}
|
||||
|
||||
public void unitsLoaded() {
|
||||
// called on startup after the system loads the map's units layer, but not any
|
||||
// custom scripts yet
|
||||
|
@ -25,6 +25,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetVisitor;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorFollow;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorHoldPosition;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorMove;
|
||||
@ -591,12 +592,6 @@ public class CUnit extends CWidget {
|
||||
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) {
|
||||
double dx = Math.abs(x - getX());
|
||||
double dy = Math.abs(y - getY());
|
||||
@ -645,7 +640,8 @@ public class CUnit extends CWidget {
|
||||
CAllianceType.PASSIVE)) {
|
||||
for (final CUnitAttack attack : this.unitType.getAttacks()) {
|
||||
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
|
||||
this.currentBehavior = getAttackBehavior().reset(OrderIds.attack, attack, source, false);
|
||||
this.currentBehavior = getAttackBehavior().reset(OrderIds.attack, attack, source, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
this.currentBehavior.begin(simulation);
|
||||
break;
|
||||
}
|
||||
@ -695,6 +691,17 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (target instanceof CDestructable) {
|
||||
final CDestructable targetDest = (CDestructable) target;
|
||||
final CDestructableType targetDestType = targetDest.getDestType();
|
||||
final BufferedImage pathingPixelMap = targetDest.isDead() ? targetDestType.getPathingDeathPixelMap()
|
||||
: targetDestType.getPathingPixelMap();
|
||||
final float targetX = target.getX();
|
||||
final float targetY = target.getY();
|
||||
if ((pathingPixelMap != null) && canReachToPathing(range, 270, pathingPixelMap, targetX, targetY)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return distance <= range;
|
||||
}
|
||||
|
||||
@ -853,7 +860,7 @@ public class CUnit extends CWidget {
|
||||
this.source.currentBehavior.end(this.game);
|
||||
}
|
||||
this.source.currentBehavior = this.source.getAttackBehavior().reset(OrderIds.attack, attack,
|
||||
unit, this.disableMove);
|
||||
unit, this.disableMove, CBehaviorAttackListener.DO_NOTHING);
|
||||
this.source.currentBehavior.begin(this.game);
|
||||
this.foundAnyTarget = true;
|
||||
return true;
|
||||
|
@ -23,10 +23,12 @@ public abstract class CWidget implements AbilityTarget {
|
||||
return this.handleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getY() {
|
||||
return this.y;
|
||||
}
|
||||
@ -60,4 +62,10 @@ public abstract class CWidget implements AbilityTarget {
|
||||
|
||||
public abstract boolean canBeTargetedBy(CSimulation simulation, CUnit source,
|
||||
final EnumSet<CTargetType> targetsAllowed);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ 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.behaviors.CBehavior;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
|
||||
@ -36,6 +37,10 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
receiver.orderIdNotAccepted();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((orderId == OrderIds.smart) || (orderId == OrderIds.attack)) {
|
||||
boolean canTarget = false;
|
||||
@ -115,7 +120,8 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attack, attack, target, false);
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attack, attack, target, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -138,7 +144,8 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
if (attack.getWeaponType().isAttackGroundSupported()) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attackground, attack, point, false);
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attackground, attack, point, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractC
|
||||
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.behaviors.CBehavior;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
|
||||
@ -106,7 +107,8 @@ public class CAbilityColdArrows extends AbstractCAbility {
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.coldarrowstarg, attack, target, false);
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.coldarrowstarg, attack, target, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||
@ -12,6 +15,11 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
|
||||
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.CBehaviorReturnResources;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CWeaponType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackNormal;
|
||||
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;
|
||||
@ -21,23 +29,46 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
|
||||
private final int damageToTree;
|
||||
private final int goldCapacity;
|
||||
private final int lumberCapacity;
|
||||
private final float castRange;
|
||||
private final float duration;
|
||||
private CBehaviorHarvest behaviorHarvest;
|
||||
private CBehaviorReturnResources behaviorReturnResources;
|
||||
private int carriedResourceAmount;
|
||||
private ResourceType carriedResourceType;
|
||||
private CUnitAttack treeAttack;
|
||||
private CWidget lastHarvestTarget;
|
||||
|
||||
public CAbilityHarvest(final int handleId, final War3ID alias, final int damageToTree, final int goldCapacity,
|
||||
final int lumberCapacity) {
|
||||
final int lumberCapacity, final float castRange, final float duration) {
|
||||
super(handleId, alias);
|
||||
this.damageToTree = damageToTree;
|
||||
this.goldCapacity = goldCapacity;
|
||||
this.lumberCapacity = lumberCapacity;
|
||||
this.castRange = castRange;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdd(final CSimulation game, final CUnit unit) {
|
||||
this.behaviorHarvest = new CBehaviorHarvest(unit, this);
|
||||
this.behaviorReturnResources = new CBehaviorReturnResources(unit, this);
|
||||
|
||||
final List<CUnitAttack> unitAttacks = unit.getUnitType().getAttacks();
|
||||
CUnitAttack bestFitTreeAttack = null;
|
||||
for (final CUnitAttack attack : unitAttacks) {
|
||||
if (attack.getTargetsAllowed().contains(CTargetType.TREE)) {
|
||||
bestFitTreeAttack = attack;
|
||||
}
|
||||
}
|
||||
this.treeAttack = new CUnitAttackNormal(
|
||||
bestFitTreeAttack == null ? 0.433f : bestFitTreeAttack.getAnimationBackswingPoint(),
|
||||
bestFitTreeAttack == null ? 0.433f : bestFitTreeAttack.getAnimationDamagePoint(), CAttackType.NORMAL,
|
||||
this.duration, 0, 1, this.damageToTree * 2, 0, (int) this.castRange,
|
||||
bestFitTreeAttack == null ? 250 : bestFitTreeAttack.getRangeMotionBuffer(),
|
||||
bestFitTreeAttack == null ? false : bestFitTreeAttack.isShowUI(),
|
||||
bestFitTreeAttack == null ? EnumSet.of(CTargetType.TREE) : bestFitTreeAttack.getTargetsAllowed(),
|
||||
bestFitTreeAttack == null ? "AxeMediumChop" : bestFitTreeAttack.getWeaponSound(),
|
||||
bestFitTreeAttack == null ? CWeaponType.NORMAL : bestFitTreeAttack.getWeaponType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,8 +135,13 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
|
||||
receiver.mustTargetResources();
|
||||
}
|
||||
else if (target instanceof CDestructable) {
|
||||
if (target.canBeTargetedBy(game, unit, this.treeAttack.getTargetsAllowed())) {
|
||||
receiver.targetOk(target);
|
||||
}
|
||||
else {
|
||||
receiver.mustTargetResources();
|
||||
}
|
||||
}
|
||||
else {
|
||||
receiver.mustTargetResources();
|
||||
}
|
||||
@ -173,4 +209,16 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
|
||||
return this.behaviorReturnResources;
|
||||
}
|
||||
|
||||
public CUnitAttack getTreeAttack() {
|
||||
return this.treeAttack;
|
||||
}
|
||||
|
||||
public void setLastHarvestTarget(final CWidget lastHarvestTarget) {
|
||||
this.lastHarvestTarget = lastHarvestTarget;
|
||||
}
|
||||
|
||||
public CWidget getLastHarvestTarget() {
|
||||
return this.lastHarvestTarget;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class CAbilityGoldMine extends AbstractGenericNoIconAbility {
|
||||
private final float miningDuration;
|
||||
private final int miningCapacity;
|
||||
private final List<CBehaviorHarvest> activeMiners;
|
||||
private final boolean wasEmpty;
|
||||
private boolean wasEmpty;
|
||||
|
||||
public CAbilityGoldMine(final int handleId, final War3ID alias, final int maxGold, final float miningDuration,
|
||||
final int miningCapacity) {
|
||||
@ -52,6 +52,7 @@ public class CAbilityGoldMine extends AbstractGenericNoIconAbility {
|
||||
else {
|
||||
unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.WORK);
|
||||
}
|
||||
this.wasEmpty = empty;
|
||||
}
|
||||
for (int i = this.activeMiners.size() - 1; i >= 0; i--) {
|
||||
final CBehaviorHarvest activeMiner = this.activeMiners.get(i);
|
||||
|
@ -13,6 +13,8 @@ public abstract class AbstractCAbilityTypeDefinition<TYPE_LEVEL_DATA extends CAb
|
||||
implements CAbilityTypeDefinition {
|
||||
protected static final War3ID TARGETS_ALLOWED = War3ID.fromString("atar");
|
||||
private static final War3ID LEVELS = War3ID.fromString("alev");
|
||||
protected static final War3ID CAST_RANGE = War3ID.fromString("aran");
|
||||
protected static final War3ID DURATION = War3ID.fromString("adur");
|
||||
|
||||
@Override
|
||||
public CAbilityType<?> createAbilityType(final War3ID alias, final MutableGameObject abilityEditorData) {
|
||||
|
@ -24,7 +24,10 @@ public class CAbilityTypeDefinitionHarvest extends AbstractCAbilityTypeDefinitio
|
||||
final int damageToTree = abilityEditorData.getFieldAsInteger(DAMAGE_TO_TREE, level);
|
||||
final int goldCapacity = abilityEditorData.getFieldAsInteger(GOLD_CAPACITY, level);
|
||||
final int lumberCapacity = abilityEditorData.getFieldAsInteger(LUMBER_CAPACITY, level);
|
||||
return new CAbilityTypeHarvestLevelData(targetsAllowedAtLevel, damageToTree, goldCapacity, lumberCapacity);
|
||||
final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level);
|
||||
final float duration = abilityEditorData.getFieldAsFloat(DURATION, level);
|
||||
return new CAbilityTypeHarvestLevelData(targetsAllowedAtLevel, damageToTree, goldCapacity, lumberCapacity,
|
||||
castRange, duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,7 +18,7 @@ public class CAbilityTypeHarvest extends CAbilityType<CAbilityTypeHarvestLevelDa
|
||||
public CAbility createAbility(final int handleId) {
|
||||
final CAbilityTypeHarvestLevelData levelData = getLevelData(0);
|
||||
return new CAbilityHarvest(handleId, getAlias(), levelData.getDamageToTree(), levelData.getGoldCapacity(),
|
||||
levelData.getLumberCapacity());
|
||||
levelData.getLumberCapacity(), levelData.getCastRange(), levelData.getDuration());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,13 +9,17 @@ public class CAbilityTypeHarvestLevelData extends CAbilityTypeLevelData {
|
||||
private final int damageToTree;
|
||||
private final int goldCapacity;
|
||||
private final int lumberCapacity;
|
||||
private final float castRange;
|
||||
private final float duration;
|
||||
|
||||
public CAbilityTypeHarvestLevelData(final EnumSet<CTargetType> targetsAllowed, final int damageToTree,
|
||||
final int goldCapacity, final int lumberCapacity) {
|
||||
final int goldCapacity, final int lumberCapacity, final float castRange, final float duration) {
|
||||
super(targetsAllowed);
|
||||
this.damageToTree = damageToTree;
|
||||
this.goldCapacity = goldCapacity;
|
||||
this.lumberCapacity = lumberCapacity;
|
||||
this.castRange = castRange;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public int getDamageToTree() {
|
||||
@ -30,4 +34,12 @@ public class CAbilityTypeHarvestLevelData extends CAbilityTypeLevelData {
|
||||
return this.lumberCapacity;
|
||||
}
|
||||
|
||||
public float getCastRange() {
|
||||
return this.castRange;
|
||||
}
|
||||
|
||||
public float getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,11 +6,9 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
|
||||
|
||||
public abstract class CAbstractRangedBehavior implements CRangedBehavior {
|
||||
protected final CUnit unit;
|
||||
private final boolean disableCollision;
|
||||
|
||||
public CAbstractRangedBehavior(final CUnit unit, final boolean disableCollision) {
|
||||
public CAbstractRangedBehavior(final CUnit unit) {
|
||||
this.unit = unit;
|
||||
this.disableCollision = disableCollision;
|
||||
}
|
||||
|
||||
protected AbilityTarget target;
|
||||
@ -20,12 +18,16 @@ public abstract class CAbstractRangedBehavior implements CRangedBehavior {
|
||||
private CBehaviorMove moveBehavior;
|
||||
|
||||
protected final CAbstractRangedBehavior innerReset(final AbilityTarget target) {
|
||||
return innerReset(target, false);
|
||||
}
|
||||
|
||||
protected final CAbstractRangedBehavior innerReset(final AbilityTarget target, final boolean disableCollision) {
|
||||
this.target = target;
|
||||
this.wasWithinPropWindow = false;
|
||||
this.wasInRange = false;
|
||||
CBehaviorMove moveBehavior;
|
||||
if (!this.unit.isMovementDisabled()) {
|
||||
moveBehavior = this.unit.getMoveBehavior().reset(this.target, this, this.disableCollision);
|
||||
moveBehavior = this.unit.getMoveBehavior().reset(this.target, this, disableCollision);
|
||||
}
|
||||
else {
|
||||
moveBehavior = null;
|
||||
@ -36,6 +38,8 @@ public abstract class CAbstractRangedBehavior implements CRangedBehavior {
|
||||
|
||||
protected abstract CBehavior update(CSimulation simulation, boolean withinRange);
|
||||
|
||||
protected abstract CBehavior updateOnInvalidTarget(CSimulation simulation);
|
||||
|
||||
protected abstract boolean checkTargetStillValid(CSimulation simulation);
|
||||
|
||||
protected abstract void resetBeforeMoving(CSimulation simulation);
|
||||
@ -43,7 +47,7 @@ public abstract class CAbstractRangedBehavior implements CRangedBehavior {
|
||||
@Override
|
||||
public final CBehavior update(final CSimulation simulation) {
|
||||
if (!checkTargetStillValid(simulation)) {
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
return updateOnInvalidTarget(simulation);
|
||||
}
|
||||
if (!isWithinRange(simulation)) {
|
||||
if ((this.moveBehavior == null) || this.disableMove) {
|
||||
|
@ -15,7 +15,7 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
|
||||
private final AbilityTargetStillAliveAndTargetableVisitor abilityTargetStillAliveVisitor;
|
||||
|
||||
public CBehaviorAttack(final CUnit unit) {
|
||||
super(unit, false);
|
||||
super(unit);
|
||||
this.abilityTargetStillAliveVisitor = new AbilityTargetStillAliveAndTargetableVisitor();
|
||||
}
|
||||
|
||||
@ -23,10 +23,12 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
|
||||
private int damagePointLaunchTime;
|
||||
private int backSwingTime;
|
||||
private int thisOrderCooldownEndTime;
|
||||
private CBehaviorAttackListener attackListener;
|
||||
|
||||
public CBehaviorAttack reset(final int highlightOrderId, final CUnitAttack unitAttack, final AbilityTarget target,
|
||||
final boolean disableMove) {
|
||||
final boolean disableMove, final CBehaviorAttackListener attackListener) {
|
||||
this.highlightOrderId = highlightOrderId;
|
||||
this.attackListener = attackListener;
|
||||
super.innerReset(target);
|
||||
this.unitAttack = unitAttack;
|
||||
this.damagePointLaunchTime = 0;
|
||||
@ -63,6 +65,11 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
|
||||
this.thisOrderCooldownEndTime = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
|
||||
return this.attackListener.onFinish(simulation, this.unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior update(final CSimulation simulation, final boolean withinRange) {
|
||||
final int cooldownEndTime = this.unit.getCooldownEndTime();
|
||||
@ -85,7 +92,7 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
|
||||
else {
|
||||
damage = simulation.getSeededRandom().nextInt(maxDamage - minDamage) + minDamage;
|
||||
}
|
||||
this.unitAttack.launch(simulation, this.unit, this.target, damage);
|
||||
this.unitAttack.launch(simulation, this.unit, this.target, damage, this.attackListener);
|
||||
this.damagePointLaunchTime = 0;
|
||||
}
|
||||
}
|
||||
@ -114,6 +121,11 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
|
||||
false);
|
||||
}
|
||||
|
||||
if ((this.backSwingTime != 0) && (currentTurnTick >= this.backSwingTime)) {
|
||||
this.backSwingTime = 0;
|
||||
System.out.println("INTERRUPT AFTER BACKSWING");
|
||||
return this.attackListener.onFirstUpdateAfterBackswing(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors;
|
||||
|
||||
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.targeting.AbilityTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
|
||||
|
||||
public interface CBehaviorAttackListener extends CUnitAttackListener {
|
||||
|
||||
// For this function, return the current attack behavior to keep attacking, or
|
||||
// else return something else to interrupt it
|
||||
CBehavior onFirstUpdateAfterBackswing(CBehaviorAttack currentAttackBehavior);
|
||||
|
||||
CBehavior onFinish(CSimulation game, final CUnit finishingUnit);
|
||||
|
||||
CBehaviorAttackListener DO_NOTHING = new CBehaviorAttackListener() {
|
||||
@Override
|
||||
public void onHit(final AbilityTarget target, final float damage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLaunch() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior onFirstUpdateAfterBackswing(final CBehaviorAttack currentAttackBehavior) {
|
||||
return currentAttackBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior onFinish(final CSimulation game, final CUnit finishingUnit) {
|
||||
return finishingUnit.pollNextOrderBehavior(game);
|
||||
}
|
||||
};
|
||||
}
|
@ -11,7 +11,7 @@ public class CBehaviorFollow extends CAbstractRangedBehavior {
|
||||
private int higlightOrderId;
|
||||
|
||||
public CBehaviorFollow(final CUnit unit) {
|
||||
super(unit, false);
|
||||
super(unit);
|
||||
}
|
||||
|
||||
public CBehavior reset(final int higlightOrderId, final CUnit target) {
|
||||
@ -35,6 +35,11 @@ public class CBehaviorFollow extends CAbstractRangedBehavior {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkTargetStillValid(final CSimulation simulation) {
|
||||
return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
|
||||
|
@ -21,7 +21,7 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
|
||||
private War3ID orderId;
|
||||
|
||||
public CBehaviorOrcBuild(final CUnit unit) {
|
||||
super(unit, false);
|
||||
super(unit);
|
||||
}
|
||||
|
||||
public CBehavior reset(final AbilityPointTarget target, final int orderId, final int highlightOrderId) {
|
||||
@ -88,6 +88,11 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetBeforeMoving(final CSimulation simulation) {
|
||||
|
||||
|
@ -13,27 +13,30 @@ 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.mine.CAbilityGoldMine;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
|
||||
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.behaviors.CBehaviorAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||
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>, CBehaviorAttackListener {
|
||||
private final CAbilityHarvest abilityHarvest;
|
||||
private CSimulation simulation;
|
||||
private int popoutFromMineTurnTick = 0;
|
||||
private CAbilityGoldMine abilityGoldMine;
|
||||
|
||||
public CBehaviorHarvest(final CUnit unit, final CAbilityHarvest abilityHarvest) {
|
||||
super(unit, true);
|
||||
super(unit);
|
||||
this.abilityHarvest = abilityHarvest;
|
||||
}
|
||||
|
||||
public CBehaviorHarvest reset(final CWidget target) {
|
||||
innerReset(target);
|
||||
this.abilityGoldMine = null;
|
||||
innerReset(target, target instanceof CUnit);
|
||||
this.abilityHarvest.setLastHarvestTarget(target);
|
||||
if (this.popoutFromMineTurnTick != 0) {
|
||||
// TODO this check is probably only for debug and should be removed after
|
||||
// extensive testing
|
||||
@ -76,9 +79,9 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
|
||||
this.unit.setHidden(true);
|
||||
this.unit.setInvulnerable(true);
|
||||
this.unit.setPaused(true);
|
||||
this.unit.setAcceptingOrders(false);
|
||||
this.popoutFromMineTurnTick = this.simulation.getGameTurnTick()
|
||||
+ (int) (abilityGoldMine.getMiningDuration() / WarsmashConstants.SIMULATION_STEP_TIME);
|
||||
this.abilityGoldMine = abilityGoldMine;
|
||||
}
|
||||
else {
|
||||
// we are stuck waiting to mine, let's make sure we play stand animation
|
||||
@ -103,6 +106,8 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
|
||||
this.unit.setHidden(false);
|
||||
this.unit.setInvulnerable(false);
|
||||
this.unit.setPaused(false);
|
||||
this.unit.setAcceptingOrders(true);
|
||||
dropResources();
|
||||
this.abilityHarvest.setCarriedResources(ResourceType.GOLD, goldMined);
|
||||
this.unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.GOLD);
|
||||
this.simulation.unitRepositioned(this.unit);
|
||||
@ -110,15 +115,49 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
|
||||
|
||||
@Override
|
||||
public CBehavior accept(final CDestructable target) {
|
||||
// TODO cut trees!
|
||||
if (String.valueOf(target).length() > 5) {
|
||||
return this.unit.pollNextOrderBehavior(this.simulation);
|
||||
if ((this.abilityHarvest.getCarriedResourceType() != ResourceType.LUMBER)
|
||||
|| (this.abilityHarvest.getCarriedResourceAmount() < this.abilityHarvest.getLumberCapacity())) {
|
||||
return this.unit.getAttackBehavior().reset(getHighlightOrderId(), this.abilityHarvest.getTreeAttack(),
|
||||
target, false, this);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
// we have some LUMBER and we can't carry any more, time to return resources
|
||||
return this.abilityHarvest.getBehaviorReturnResources().reset(this.simulation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(final AbilityTarget target, final float damage) {
|
||||
if (this.abilityHarvest.getCarriedResourceType() != ResourceType.LUMBER) {
|
||||
dropResources();
|
||||
}
|
||||
this.abilityHarvest.setCarriedResources(ResourceType.LUMBER,
|
||||
Math.min(this.abilityHarvest.getCarriedResourceAmount() + this.abilityHarvest.getDamageToTree(),
|
||||
this.abilityHarvest.getLumberCapacity()));
|
||||
this.unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.LUMBER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLaunch() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior onFirstUpdateAfterBackswing(final CBehaviorAttack currentAttackBehavior) {
|
||||
if (this.abilityHarvest.getCarriedResourceAmount() >= this.abilityHarvest.getLumberCapacity()) {
|
||||
return this.abilityHarvest.getBehaviorReturnResources().reset(this.simulation);
|
||||
}
|
||||
return currentAttackBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior onFinish(final CSimulation game, final CUnit finishingUnit) {
|
||||
if (this.abilityHarvest.getCarriedResourceAmount() >= this.abilityHarvest.getLumberCapacity()) {
|
||||
return this.abilityHarvest.getBehaviorReturnResources().reset(this.simulation);
|
||||
}
|
||||
return updateOnInvalidTarget(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior accept(final CItem target) {
|
||||
return this.unit.pollNextOrderBehavior(this.simulation);
|
||||
@ -129,6 +168,20 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
|
||||
return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
|
||||
if (this.target instanceof CDestructable) {
|
||||
// wood
|
||||
final CDestructable nearestTree = CBehaviorReturnResources.findNearestTree(this.unit, this.abilityHarvest,
|
||||
simulation, (CDestructable) this.target);
|
||||
if (nearestTree != null) {
|
||||
this.target = nearestTree;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetBeforeMoving(final CSimulation simulation) {
|
||||
|
||||
@ -152,4 +205,20 @@ public class CBehaviorHarvest extends CAbstractRangedBehavior implements Ability
|
||||
return this.abilityHarvest.getGoldCapacity();
|
||||
}
|
||||
|
||||
private void dropResources() {
|
||||
if (this.abilityHarvest.getCarriedResourceType() != null) {
|
||||
switch (this.abilityHarvest.getCarriedResourceType()) {
|
||||
case FOOD:
|
||||
throw new IllegalStateException("Unit used Harvest skill to carry FOOD resource!");
|
||||
case GOLD:
|
||||
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.GOLD);
|
||||
break;
|
||||
case LUMBER:
|
||||
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.LUMBER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.abilityHarvest.setCarriedResources(null, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.CWidget;
|
||||
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;
|
||||
@ -22,7 +23,7 @@ public class CBehaviorReturnResources extends CAbstractRangedBehavior implements
|
||||
private CSimulation simulation;
|
||||
|
||||
public CBehaviorReturnResources(final CUnit unit, final CAbilityHarvest abilityHarvest) {
|
||||
super(unit, true);
|
||||
super(unit);
|
||||
this.abilityHarvest = abilityHarvest;
|
||||
}
|
||||
|
||||
@ -32,7 +33,7 @@ public class CBehaviorReturnResources extends CAbstractRangedBehavior implements
|
||||
// TODO it is unconventional not to return self here
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
}
|
||||
innerReset(nearestDropoffPoint);
|
||||
innerReset(nearestDropoffPoint, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -65,22 +66,44 @@ public class CBehaviorReturnResources extends CAbstractRangedBehavior implements
|
||||
final CAbilityReturnResources abilityReturnResources = (CAbilityReturnResources) ability;
|
||||
if (abilityReturnResources.accepts(this.abilityHarvest.getCarriedResourceType())) {
|
||||
final CPlayer player = this.simulation.getPlayer(this.unit.getPlayerIndex());
|
||||
CWidget nextTarget = null;
|
||||
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);
|
||||
if ((this.abilityHarvest.getLastHarvestTarget() != null) && this.abilityHarvest
|
||||
.getLastHarvestTarget().visit(AbilityTargetStillAliveVisitor.INSTANCE)) {
|
||||
nextTarget = this.abilityHarvest.getLastHarvestTarget();
|
||||
}
|
||||
else {
|
||||
nextTarget = findNearestMine(this.unit, this.simulation);
|
||||
}
|
||||
break;
|
||||
case LUMBER:
|
||||
player.setLumber(player.getLumber() + this.abilityHarvest.getCarriedResourceAmount());
|
||||
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.LUMBER);
|
||||
if (this.abilityHarvest.getLastHarvestTarget() != null) {
|
||||
if (this.abilityHarvest.getLastHarvestTarget()
|
||||
.visit(AbilityTargetStillAliveVisitor.INSTANCE)) {
|
||||
nextTarget = this.abilityHarvest.getLastHarvestTarget();
|
||||
}
|
||||
else {
|
||||
nextTarget = findNearestTree(this.unit, this.abilityHarvest, this.simulation,
|
||||
this.abilityHarvest.getLastHarvestTarget());
|
||||
}
|
||||
}
|
||||
else {
|
||||
nextTarget = findNearestTree(this.unit, this.abilityHarvest, this.simulation, this.unit);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.simulation.unitGainResourceEvent(this.unit, this.abilityHarvest.getCarriedResourceType(),
|
||||
this.abilityHarvest.getCarriedResourceAmount());
|
||||
this.abilityHarvest.setCarriedResources(null, 0);
|
||||
final CUnit nearestMine = findNearestMine(this.unit, this.simulation);
|
||||
if (nearestMine != null) {
|
||||
return this.abilityHarvest.getBehaviorHarvest().reset(nearestMine);
|
||||
if (nextTarget != null) {
|
||||
return this.abilityHarvest.getBehaviorHarvest().reset(nextTarget);
|
||||
}
|
||||
return this.unit.pollNextOrderBehavior(this.simulation);
|
||||
}
|
||||
@ -102,18 +125,17 @@ public class CBehaviorReturnResources extends CAbstractRangedBehavior implements
|
||||
|
||||
@Override
|
||||
protected boolean checkTargetStillValid(final CSimulation simulation) {
|
||||
final boolean aliveCheck = this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
|
||||
if (!aliveCheck) {
|
||||
return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
|
||||
final CUnit nearestDropoff = findNearestDropoffPoint(simulation);
|
||||
if (nearestDropoff == null) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (nearestDropoff != null) {
|
||||
this.target = nearestDropoff;
|
||||
return true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return this.unit.pollNextOrderBehavior(simulation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,6 +198,24 @@ public class CBehaviorReturnResources extends CAbstractRangedBehavior implements
|
||||
return nearestMine;
|
||||
}
|
||||
|
||||
public static CDestructable findNearestTree(final CUnit worker, final CAbilityHarvest abilityHarvest,
|
||||
final CSimulation simulation, final CWidget toObject) {
|
||||
CDestructable nearestMine = null;
|
||||
double nearestMineDistance = Float.MAX_VALUE;
|
||||
for (final CDestructable unit : simulation.getDestructables()) {
|
||||
if (unit.canBeTargetedBy(simulation, worker, abilityHarvest.getTreeAttack().getTargetsAllowed())) {
|
||||
// TODO maybe use distance squared, problem is that we're using this
|
||||
// inefficient more complex distance function on unit
|
||||
final double distance = unit.distanceSquaredNoCollision(toObject);
|
||||
if (distance < nearestMineDistance) {
|
||||
nearestMineDistance = distance;
|
||||
nearestMine = unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestMine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(final CSimulation game) {
|
||||
|
||||
|
@ -198,5 +198,6 @@ public abstract class CUnitAttack {
|
||||
return this.maxDamage;
|
||||
}
|
||||
|
||||
public abstract void launch(CSimulation simulation, CUnit unit, AbilityTarget target, float damage);
|
||||
public abstract void launch(CSimulation simulation, CUnit unit, AbilityTarget target, float damage,
|
||||
CUnitAttackListener attackListener);
|
||||
}
|
||||
|
@ -34,11 +34,14 @@ public class CUnitAttackInstant extends CUnitAttack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage) {
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage,
|
||||
final CUnitAttackListener attackListener) {
|
||||
attackListener.onLaunch();
|
||||
final CWidget widget = target.visit(AbilityTargetWidgetVisitor.INSTANCE);
|
||||
if (widget != null) {
|
||||
simulation.createInstantAttackEffect(unit, this, widget);
|
||||
widget.damage(simulation, unit, getAttackType(), getWeaponSound(), damage);
|
||||
attackListener.onHit(target, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks;
|
||||
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
|
||||
|
||||
public interface CUnitAttackListener {
|
||||
void onLaunch();
|
||||
|
||||
void onHit(AbilityTarget target, float damage);
|
||||
}
|
@ -65,16 +65,20 @@ public class CUnitAttackMissile extends CUnitAttack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage) {
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage,
|
||||
final CUnitAttackListener attackListener) {
|
||||
attackListener.onLaunch();
|
||||
simulation.createProjectile(unit, unit.getX(), unit.getY(), (float) Math.toRadians(unit.getFacing()), this,
|
||||
target, damage, 0);
|
||||
target, damage, 0, attackListener);
|
||||
}
|
||||
|
||||
public void doDamage(final CSimulation cSimulation, final CUnit source, final AbilityTarget target,
|
||||
final float damage, final float x, final float y, final int bounceIndex) {
|
||||
final float damage, final float x, final float y, final int bounceIndex,
|
||||
final CUnitAttackListener attackListener) {
|
||||
final CWidget widget = target.visit(AbilityTargetWidgetVisitor.INSTANCE);
|
||||
if (widget != null) {
|
||||
widget.damage(cSimulation, source, getAttackType(), getWeaponSound(), damage);
|
||||
attackListener.onHit(target, damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,14 +54,15 @@ public class CUnitAttackMissileBounce extends CUnitAttackMissile {
|
||||
|
||||
@Override
|
||||
public void doDamage(final CSimulation cSimulation, final CUnit source, final AbilityTarget target,
|
||||
final float damage, final float x, final float y, final int bounceIndex) {
|
||||
super.doDamage(cSimulation, source, target, damage, x, y, bounceIndex);
|
||||
final float damage, final float x, final float y, final int bounceIndex,
|
||||
final CUnitAttackListener attackListener) {
|
||||
super.doDamage(cSimulation, source, target, damage, x, y, bounceIndex, attackListener);
|
||||
final CWidget widget = target.visit(AbilityTargetWidgetVisitor.INSTANCE);
|
||||
if (widget != null) {
|
||||
final int nextBounceIndex = bounceIndex + 1;
|
||||
if (nextBounceIndex != this.maximumNumberOfTargets) {
|
||||
BounceMissileConsumer.INSTANCE.nextBounce(cSimulation, source, widget, this, x, y, damage,
|
||||
nextBounceIndex);
|
||||
nextBounceIndex, attackListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,11 +78,12 @@ public class CUnitAttackMissileBounce extends CUnitAttackMissile {
|
||||
private float y;
|
||||
private float damage;
|
||||
private int bounceIndex;
|
||||
private CUnitAttackListener attackListener;
|
||||
private boolean launched = false;
|
||||
|
||||
public void nextBounce(final CSimulation simulation, final CUnit source, final CWidget target,
|
||||
final CUnitAttackMissileBounce attack, final float x, final float y, final float damage,
|
||||
final int bounceIndex) {
|
||||
final int bounceIndex, final CUnitAttackListener attackListener) {
|
||||
this.simulation = simulation;
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
@ -90,6 +92,7 @@ public class CUnitAttackMissileBounce extends CUnitAttackMissile {
|
||||
this.y = y;
|
||||
this.damage = damage;
|
||||
this.bounceIndex = bounceIndex;
|
||||
this.attackListener = attackListener;
|
||||
this.launched = false;
|
||||
final float doubleMaxArea = attack.areaOfEffectFullDamage
|
||||
+ (this.simulation.getGameplayConstants().getCloseEnoughRange() * 2);
|
||||
@ -112,7 +115,7 @@ public class CUnitAttackMissileBounce extends CUnitAttackMissile {
|
||||
final float dy = enumUnit.getY() - this.y;
|
||||
final float angle = (float) Math.atan2(dy, dx);
|
||||
this.simulation.createProjectile(this.source, this.x, this.y, angle, this.attack, enumUnit,
|
||||
this.damage * (1.0f - this.attack.damageLossFactor), this.bounceIndex);
|
||||
this.damage * (1.0f - this.attack.damageLossFactor), this.bounceIndex, this.attackListener);
|
||||
this.launched = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -94,10 +94,12 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
|
||||
|
||||
@Override
|
||||
public void doDamage(final CSimulation cSimulation, final CUnit source, final AbilityTarget target,
|
||||
final float damage, final float x, final float y, final int bounceIndex) {
|
||||
SplashDamageConsumer.INSTANCE.doDamage(cSimulation, source, target, this, x, y, damage);
|
||||
final float damage, final float x, final float y, final int bounceIndex,
|
||||
final CUnitAttackListener attackListener) {
|
||||
SplashDamageConsumer.INSTANCE.doDamage(cSimulation, source, target, this, x, y, damage, attackListener);
|
||||
if ((getWeaponType() != CWeaponType.ARTILLERY) && !SplashDamageConsumer.INSTANCE.hitTarget) {
|
||||
super.doDamage(cSimulation, source, target, damage * this.damageFactorSmall, x, y, bounceIndex);
|
||||
super.doDamage(cSimulation, source, target, damage * this.damageFactorSmall, x, y, bounceIndex,
|
||||
attackListener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,10 +113,12 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
|
||||
private float x;
|
||||
private float y;
|
||||
private float damage;
|
||||
private CUnitAttackListener attackListener;
|
||||
private boolean hitTarget;
|
||||
|
||||
public void doDamage(final CSimulation simulation, final CUnit source, final AbilityTarget target,
|
||||
final CUnitAttackMissileSplash attack, final float x, final float y, final float damage) {
|
||||
final CUnitAttackMissileSplash attack, final float x, final float y, final float damage,
|
||||
final CUnitAttackListener attackListener) {
|
||||
this.simulation = simulation;
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
@ -122,6 +126,7 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.damage = damage;
|
||||
this.attackListener = attackListener;
|
||||
this.hitTarget = false;
|
||||
final float doubleMaxArea = (attack.areaOfEffectSmallDamage) * 2;
|
||||
final float maxArea = doubleMaxArea / 2;
|
||||
@ -136,14 +141,17 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
|
||||
if (distance <= (this.attack.areaOfEffectFullDamage)) {
|
||||
enumUnit.damage(this.simulation, this.source, this.attack.getAttackType(),
|
||||
this.attack.getWeaponSound(), this.damage);
|
||||
this.attackListener.onHit(enumUnit, this.damage);
|
||||
}
|
||||
else if (distance <= (this.attack.areaOfEffectMediumDamage)) {
|
||||
enumUnit.damage(this.simulation, this.source, this.attack.getAttackType(),
|
||||
this.attack.getWeaponSound(), this.damage * this.attack.damageFactorMedium);
|
||||
this.attackListener.onHit(enumUnit, this.damage);
|
||||
}
|
||||
else if (distance <= (this.attack.areaOfEffectSmallDamage)) {
|
||||
enumUnit.damage(this.simulation, this.source, this.attack.getAttackType(),
|
||||
this.attack.getWeaponSound(), this.damage * this.attack.damageFactorSmall);
|
||||
this.attackListener.onHit(enumUnit, this.damage);
|
||||
}
|
||||
if (enumUnit == this.target) {
|
||||
this.hitTarget = true;
|
||||
|
@ -24,10 +24,13 @@ public class CUnitAttackNormal extends CUnitAttack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage) {
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage,
|
||||
final CUnitAttackListener attackListener) {
|
||||
attackListener.onLaunch();
|
||||
final CWidget widget = target.visit(AbilityTargetWidgetVisitor.INSTANCE);
|
||||
if (widget != null) {
|
||||
widget.damage(simulation, unit, getAttackType(), getWeaponSound(), damage);
|
||||
attackListener.onHit(target, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ 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.targeting.AbilityTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CWeaponType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
|
||||
|
||||
public class CAttackProjectile {
|
||||
@ -19,9 +20,11 @@ public class CAttackProjectile {
|
||||
private final float damage;
|
||||
private final CUnitAttackMissile unitAttack;
|
||||
private final int bounceIndex;
|
||||
private final CUnitAttackListener attackListener;
|
||||
|
||||
public CAttackProjectile(final float x, final float y, final float speed, final AbilityTarget target,
|
||||
final CUnit source, final float damage, final CUnitAttackMissile unitAttack, final int bounceIndex) {
|
||||
final CUnit source, final float damage, final CUnitAttackMissile unitAttack, final int bounceIndex,
|
||||
final CUnitAttackListener attackListener) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.speed = speed;
|
||||
@ -30,6 +33,7 @@ public class CAttackProjectile {
|
||||
this.damage = damage;
|
||||
this.unitAttack = unitAttack;
|
||||
this.bounceIndex = bounceIndex;
|
||||
this.attackListener = attackListener;
|
||||
this.initialTargetX = target.getX();
|
||||
this.initialTargetY = target.getY();
|
||||
}
|
||||
@ -60,7 +64,7 @@ public class CAttackProjectile {
|
||||
|
||||
if (done && !this.done) {
|
||||
this.unitAttack.doDamage(cSimulation, this.source, this.target, this.damage, this.x, this.y,
|
||||
this.bounceIndex);
|
||||
this.bounceIndex, this.attackListener);
|
||||
this.done = true;
|
||||
}
|
||||
return this.done;
|
||||
|
@ -9,12 +9,14 @@ 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.AbilityTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
|
||||
|
||||
public interface SimulationRenderController {
|
||||
CAttackProjectile createAttackProjectile(CSimulation simulation, float launchX, float launchY, float launchFacing,
|
||||
CUnit source, CUnitAttackMissile attack, AbilityTarget target, float damage, int bounceIndex);
|
||||
CUnit source, CUnitAttackMissile attack, AbilityTarget target, float damage, int bounceIndex,
|
||||
CUnitAttackListener attackListener);
|
||||
|
||||
CUnit createUnit(CSimulation simulation, final War3ID typeId, final int playerIndex, final float x, final float y,
|
||||
final float facing);
|
||||
@ -42,4 +44,6 @@ public interface SimulationRenderController {
|
||||
void spawnUnitReadySound(CUnit trainedUnit);
|
||||
|
||||
void unitRepositioned(CUnit cUnit);
|
||||
|
||||
void spawnGainResourceTextTag(CUnit gainingUnit, ResourceType resourceType, int amount);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
@ -65,6 +66,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.TextTag;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraPreset;
|
||||
@ -252,6 +254,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private MdxModel waypointModel;
|
||||
private final List<MdxComplexInstance> waypointModelInstances = new ArrayList<>();
|
||||
private List<RenderUnit> selectedUnits;
|
||||
private BitmapFont textTagFont;
|
||||
|
||||
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport,
|
||||
final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final Scene portraitScene,
|
||||
@ -634,9 +637,14 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
War3MapViewer.mdx(this.rootFrame.getSkinField("WaypointIndicator")), this.war3MapViewer.mapPathSolver,
|
||||
this.war3MapViewer.solverParams);
|
||||
|
||||
final FreeTypeFontParameter fontParam = new FreeTypeFontParameter();
|
||||
fontParam.size = (int) GameUI.convertY(this.uiViewport, 0.012f);
|
||||
this.textTagFont = this.fontGenerator.generateFont(fontParam);
|
||||
|
||||
this.rootFrame.positionBounds(this.rootFrame, this.uiViewport);
|
||||
|
||||
selectUnit(null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -834,6 +842,14 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.meleeUIMinimap.render(batch, this.war3MapViewer.units);
|
||||
this.timeIndicator.setFrameByRatio(this.war3MapViewer.simulation.getGameTimeOfDay()
|
||||
/ this.war3MapViewer.simulation.getGameplayConstants().getGameDayHours());
|
||||
for (final TextTag textTag : this.war3MapViewer.textTags) {
|
||||
this.war3MapViewer.worldScene.camera.worldToScreen(screenCoordsVector, textTag.getPosition());
|
||||
final Vector2 unprojected = this.uiViewport.unproject(screenCoordsVector);
|
||||
this.textTagFont.setColor(textTag.getColor());
|
||||
glyphLayout.setText(this.textTagFont, textTag.getText());
|
||||
this.textTagFont.draw(batch, textTag.getText(), unprojected.x - (glyphLayout.width / 2),
|
||||
(unprojected.y - (glyphLayout.height / 2)));
|
||||
}
|
||||
}
|
||||
|
||||
public void portraitTalk() {
|
||||
|
Loading…
Reference in New Issue
Block a user