Make UI icons clickable

This commit is contained in:
Retera 2020-10-24 01:10:37 -04:00
parent e919f35904
commit 2173c993bc
18 changed files with 728 additions and 156 deletions

View File

@ -10,7 +10,6 @@ import java.util.List;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
@ -26,8 +25,6 @@ import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFont
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
import com.etheller.warsmash.datasources.DataSource;
@ -50,17 +47,15 @@ import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.TextureMapper;
import com.etheller.warsmash.viewer5.handlers.ModelHandler;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
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;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnitOrderExecutor;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProvider, InputProcessor {
private static final boolean ENABLE_MUSIC = false;
private static final Vector3 clickLocationTemp = new Vector3();
private static final Vector2 clickLocationTemp2 = new Vector2();
private DataSource codebase;
private War3MapViewer viewer;
private final Rectangle tempRect = new Rectangle();
@ -73,8 +68,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
private ExtendViewport uiViewport;
private GlyphLayout glyphLayout;
private int selectedSoundCount = 0;
private Texture solidGreenTexture;
private ShapeRenderer shapeRenderer;
@ -227,7 +220,12 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
music.play();
}
}
});
}, new CPlayerUnitOrderExecutor(this.viewer.simulation, new CommandErrorListener() {
@Override
public void showCommandError(final String message) {
WarsmashGdxMapGame.this.meleeUI.showCommandError(message);
}
}));
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
this.viewer.mapPathSolver, "").addInstance();
libgdxContentInstance.setScene(this.uiScene);
@ -361,85 +359,10 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
@Override
public boolean touchDown(final int screenX, final int screenY, final int pointer, final int button) {
final float worldScreenY = getHeight() - screenY;
System.out.println(screenX + "," + screenY);
clickLocationTemp2.x = screenX;
clickLocationTemp2.y = screenY;
this.uiViewport.unproject(clickLocationTemp2);
if (this.meleeUI.touchDown(clickLocationTemp2.x, clickLocationTemp2.y, button)) {
if (this.meleeUI.touchDown(screenX, screenY, worldScreenY, button)) {
return false;
}
if (button == Input.Buttons.RIGHT) {
final RenderUnit rayPickUnit = this.viewer.rayPickUnit(screenX, worldScreenY);
if (this.meleeUI.getSelectedUnit() != null) {
if ((rayPickUnit != null) && (rayPickUnit.playerIndex != this.meleeUI.getSelectedUnit().playerIndex)
&& !rayPickUnit.getSimulationUnit().isDead()) {
if (this.viewer.orderSmart(rayPickUnit)) {
if (this.meleeUI.getSelectedUnit().soundset.yesAttack.playUnitResponse(
this.viewer.worldScene.audioContext, this.meleeUI.getSelectedUnit())) {
this.meleeUI.portraitTalk();
}
this.selectedSoundCount = 0;
}
}
else {
this.viewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
System.out.println(clickLocationTemp);
this.viewer.showConfirmation(clickLocationTemp, 0, 1, 0);
final int x = (int) ((clickLocationTemp.x - this.viewer.terrain.centerOffset[0]) / 128);
final int y = (int) ((clickLocationTemp.y - this.viewer.terrain.centerOffset[1]) / 128);
System.out.println(x + "," + y);
this.viewer.terrain.logRomp(x, y);
if (this.viewer.orderSmart(clickLocationTemp.x, clickLocationTemp.y)) {
if (this.meleeUI.getSelectedUnit().soundset.yes.playUnitResponse(
this.viewer.worldScene.audioContext, this.meleeUI.getSelectedUnit())) {
this.meleeUI.portraitTalk();
}
this.selectedSoundCount = 0;
}
}
}
}
else {
final List<RenderUnit> selectedUnits = this.viewer.selectUnit(screenX, worldScreenY, false);
if (!selectedUnits.isEmpty()) {
final RenderUnit unit = selectedUnits.get(0);
final boolean selectionChanged = this.meleeUI.getSelectedUnit() != unit;
boolean playedNewSound = false;
if (selectionChanged) {
this.selectedSoundCount = 0;
}
if (unit.soundset != null) {
UnitSound ackSoundToPlay = unit.soundset.what;
final int pissedSoundCount = unit.soundset.pissed.getSoundCount();
int soundIndex;
if ((this.selectedSoundCount >= 3) && (pissedSoundCount > 0)) {
soundIndex = this.selectedSoundCount - 3;
ackSoundToPlay = unit.soundset.pissed;
}
else {
soundIndex = (int) (Math.random() * ackSoundToPlay.getSoundCount());
}
if (ackSoundToPlay.playUnitResponse(this.viewer.worldScene.audioContext, unit, soundIndex)) {
this.selectedSoundCount++;
if ((this.selectedSoundCount - 3) >= pissedSoundCount) {
this.selectedSoundCount = 0;
}
playedNewSound = true;
}
}
if (selectionChanged) {
this.meleeUI.selectUnit(unit);
}
if (playedNewSound) {
this.meleeUI.portraitTalk();
}
}
else {
this.meleeUI.selectUnit(null);
}
}
return false;
}

View File

@ -211,6 +211,19 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
return textureFrame;
}
public StringFrame createStringFrame(final String name, final UIFrame parent, final Color color,
final TextJustify justifyH, final TextJustify justifyV, final float fdfFontSize) {
this.fontParam.size = (int) convertY(this.viewport, fdfFontSize);
if (this.fontParam.size == 0) {
this.fontParam.size = 24;
}
final BitmapFont frameFont = this.fontGenerator.generateFont(this.fontParam);
final StringFrame stringFrame = new StringFrame(name, parent, color, justifyH, justifyV, frameFont);
this.nameToFrame.put(name, stringFrame);
add(stringFrame);
return stringFrame;
}
public UIFrame inflate(final FrameDefinition frameDefinition, final UIFrame parent,
final FrameDefinition parentDefinitionIfAvailable) {
UIFrame inflatedFrame = null;

View File

@ -81,17 +81,16 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataU
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.CUnitClassification;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitFilterFunction;
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.CAbilityAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
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.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CWidgetAbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.PointAbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
import mpq.MPQArchive;
@ -1135,6 +1134,10 @@ public class War3MapViewer extends ModelViewer {
}
public RenderUnit rayPickUnit(final float x, final float y) {
return rayPickUnit(x, y, CUnitFilterFunction.ACCEPT_ALL);
}
public RenderUnit rayPickUnit(final float x, final float y, final CUnitFilterFunction filter) {
final float[] ray = rayHeap;
mousePosHeap.set(x, y);
this.worldScene.camera.screenToWorldRay(ray, mousePosHeap);
@ -1146,7 +1149,11 @@ public class War3MapViewer extends ModelViewer {
final MdxComplexInstance instance = unit.instance;
if (instance.isVisible(this.worldScene.camera) && instance.intersectRayWithCollision(gdxRayHeap,
intersectionHeap, unit.getSimulationUnit().getUnitType().isBuilding())) {
entity = unit;
if (filter.call(unit.getSimulationUnit())) {
if ((entity == null) || (entity.instance.depth > instance.depth)) {
entity = unit;
}
}
}
}
return entity;
@ -1235,41 +1242,6 @@ public class War3MapViewer extends ModelViewer {
return (numElements < 0) ? 1 : (numElements >= MAXIMUM_ACCEPTED) ? MAXIMUM_ACCEPTED : numElements + 1;
}
public boolean orderSmart(final float x, final float y) {
mousePosHeap.x = x;
mousePosHeap.y = y;
boolean ordered = false;
for (final RenderUnit unit : this.selected) {
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
if (ability instanceof CAbilityMove) {
ability.checkCanUse(this.simulation, unit.getSimulationUnit(), OrderIds.smart,
BooleanAbilityActivationReceiver.INSTANCE);
if (BooleanAbilityActivationReceiver.INSTANCE.isOk()) {
ability.checkCanTarget(this.simulation, unit.getSimulationUnit(), OrderIds.smart, mousePosHeap,
PointAbilityTargetCheckReceiver.INSTANCE);
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (target != null) {
ability.onOrder(this.simulation, unit.getSimulationUnit(), OrderIds.smart, mousePosHeap,
false);
ordered = true;
}
else {
System.err.println("Target not valid.");
}
}
else {
System.err.println("Ability not ok to use.");
}
}
else {
System.err.println("Ability not move.");
}
}
}
return ordered;
}
public boolean orderSmart(final RenderUnit target) {
boolean ordered = false;
for (final RenderUnit unit : this.selected) {

View File

@ -34,5 +34,5 @@ public interface CommandButtonListener {
// int getButtonPositionY();
//
// int getOrderId();
void commandButton(int buttonPositionX, int buttonPositionY, Texture icon, int orderId);
void commandButton(int buttonPositionX, int buttonPositionY, Texture icon, int abilityHandleId, int orderId);
}

View File

@ -46,6 +46,6 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
private void addCommandButton(final IconUI iconUI, final int handleId, final int orderId) {
this.commandButtonListener.commandButton(iconUI.getButtonPositionX(), iconUI.getButtonPositionY(),
iconUI.getIcon(), orderId);
iconUI.getIcon(), handleId, orderId);
}
}

View File

@ -3,8 +3,10 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.badlogic.gdx.math.Rectangle;
@ -14,6 +16,7 @@ import com.etheller.warsmash.units.manager.MutableObjectData;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
@ -42,6 +45,8 @@ public class CSimulation {
private final CGameplayConstants gameplayConstants;
private final Random seededRandom;
private float currentGameDayTimeElapsed;
private final Map<Integer, CUnit> handleIdToUnit = new HashMap<>();
private final Map<Integer, CAbility> handleIdToAbility = new HashMap<>();
public CSimulation(final DataTable miscData, final MutableObjectData parsedUnitData,
final MutableObjectData parsedAbilityData, final SimulationRenderController simulationRenderController,
@ -106,10 +111,22 @@ public class CSimulation {
final CUnit unit = this.unitData.create(this, playerIndex, typeId, x, y, facing, buildingPathingPixelMap,
this.simulationRenderController, this.handleIdAllocator);
this.units.add(unit);
this.handleIdToUnit.put(unit.getHandleId(), unit);
for (final CAbility ability : unit.getAbilities()) {
this.handleIdToAbility.put(ability.getHandleId(), ability);
}
this.worldCollision.addUnit(unit);
return unit;
}
public CUnit getUnit(final int handleId) {
return this.handleIdToUnit.get(handleId);
}
public CAbility getAbility(final int handleId) {
return this.handleIdToAbility.get(handleId);
}
public CAttackProjectile createProjectile(final CUnit source, final float launchX, final float launchY,
final float launchFacing, final CUnitAttackMissile attack, final CWidget target, final float damage,
final int bounceIndex) {
@ -142,6 +159,10 @@ public class CSimulation {
final CUnit unit = unitIterator.next();
if (unit.update(this)) {
unitIterator.remove();
for (final CAbility ability : unit.getAbilities()) {
this.handleIdToAbility.remove(ability.getHandleId());
}
this.handleIdToUnit.remove(unit.getHandleId());
this.simulationRenderController.removeUnit(unit);
}
}

View File

@ -0,0 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
public interface CUnitFilterFunction {
boolean call(CUnit unit);
CUnitFilterFunction ACCEPT_ALL = new CUnitFilterFunction() {
@Override
public boolean call(final CUnit unit) {
return true;
}
};
}

View File

@ -1,9 +0,0 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public interface CPlayerController {
boolean issueTargetOrder(int unitHandleId, int orderId, int targetHandleId);
boolean issuePointOrder(int unitHandleId, int orderId, float x, float y);
boolean issueImmediateOrder(int unitHandleId, int orderId);
}

View File

@ -0,0 +1,101 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import com.badlogic.gdx.math.Vector2;
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.util.StringMsgAbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.StringMsgTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
public class CPlayerUnitOrderExecutor implements CPlayerUnitOrderListener {
private final CSimulation game;
private final CommandErrorListener errorListener;
private final StringMsgTargetCheckReceiver<?> targetCheckReceiver = new StringMsgTargetCheckReceiver<>();
private final StringMsgAbilityActivationReceiver abilityActivationReceiver = new StringMsgAbilityActivationReceiver();
private <T> StringMsgTargetCheckReceiver<T> targetCheckReceiver() {
return (StringMsgTargetCheckReceiver<T>) this.targetCheckReceiver.reset();
}
public CPlayerUnitOrderExecutor(final CSimulation game, final CommandErrorListener errorListener) {
this.game = game;
this.errorListener = errorListener;
}
@Override
public boolean issueTargetOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final int targetHandleId, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
final CAbility ability = this.game.getAbility(abilityHandleId);
ability.checkCanUse(this.game, unit, orderId, this.abilityActivationReceiver.reset());
if (this.abilityActivationReceiver.isUseOk()) {
final CUnit target = this.game.getUnit(targetHandleId);
final StringMsgTargetCheckReceiver<CWidget> targetReceiver = this.<CWidget>targetCheckReceiver();
ability.checkCanTarget(this.game, unit, orderId, target, targetReceiver);
if (targetReceiver.getTarget() != null) {
ability.onOrder(this.game, unit, orderId, target, queue);
return true;
}
else {
this.errorListener.showCommandError(targetReceiver.getMessage());
return false;
}
}
else {
this.errorListener.showCommandError(this.abilityActivationReceiver.getMessage());
return false;
}
}
@Override
public boolean issuePointOrder(final int unitHandleId, final int abilityHandleId, final int orderId, final float x,
final float y, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
final CAbility ability = this.game.getAbility(abilityHandleId);
ability.checkCanUse(this.game, unit, orderId, this.abilityActivationReceiver.reset());
if (this.abilityActivationReceiver.isUseOk()) {
final Vector2 target = new Vector2(x, y);
final StringMsgTargetCheckReceiver<Vector2> targetReceiver = this.<Vector2>targetCheckReceiver();
ability.checkCanTarget(this.game, unit, orderId, target, targetReceiver);
if (targetReceiver.getTarget() != null) {
ability.onOrder(this.game, unit, orderId, target, queue);
return true;
}
else {
this.errorListener.showCommandError(targetReceiver.getMessage());
return false;
}
}
else {
this.errorListener.showCommandError(this.abilityActivationReceiver.getMessage());
return false;
}
}
@Override
public boolean issueImmediateOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
final CAbility ability = this.game.getAbility(abilityHandleId);
ability.checkCanUse(this.game, unit, orderId, this.abilityActivationReceiver.reset());
if (this.abilityActivationReceiver.isUseOk()) {
final StringMsgTargetCheckReceiver<Void> targetReceiver = this.<Void>targetCheckReceiver();
ability.checkCanTargetNoTarget(this.game, unit, orderId, targetReceiver);
if (targetReceiver.getTarget() != null) {
ability.onOrderNoTarget(this.game, unit, orderId, queue);
return true;
}
else {
this.errorListener.showCommandError(targetReceiver.getMessage());
return false;
}
}
else {
this.errorListener.showCommandError(this.abilityActivationReceiver.getMessage());
return false;
}
}
}

View File

@ -0,0 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public interface CPlayerUnitOrderListener {
boolean issueTargetOrder(int unitHandleId, int abilityHandleId, int orderId, int targetHandleId, boolean queue);
boolean issuePointOrder(int unitHandleId, int abilityHandleId, int orderId, float x, float y, boolean queue);
// Below: used for "DROP ITEM AT POINT" ????
// boolean issueTargetAndPointOrder(int unitHandleId, int orderId, int targetHandleId, float x, float y);
boolean issueImmediateOrder(int unitHandleId, int abilityHandleId, int orderId, boolean queue);
}

View File

@ -0,0 +1,66 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
public final class BooleanAbilityTargetCheckReceiver<TARGET_TYPE> implements AbilityTargetCheckReceiver<TARGET_TYPE> {
private static final BooleanAbilityTargetCheckReceiver<?> INSTANCE = new BooleanAbilityTargetCheckReceiver<>();
public static <T> BooleanAbilityTargetCheckReceiver<T> getInstance() {
return (BooleanAbilityTargetCheckReceiver<T>) INSTANCE;
}
private boolean targetable = false;
public boolean isTargetable() {
return this.targetable;
}
public BooleanAbilityTargetCheckReceiver<TARGET_TYPE> reset() {
this.targetable = false;
return this;
}
@Override
public void targetOk(final TARGET_TYPE target) {
this.targetable = true;
}
@Override
public void mustTargetTeamType(final TeamType correctType) {
this.targetable = false;
}
@Override
public void mustTargetType(final TargetType correctType) {
this.targetable = false;
}
@Override
public void targetOutsideRange(final double howMuch) {
this.targetable = false;
}
@Override
public void notAnActiveAbility() {
this.targetable = false;
}
@Override
public void targetNotVisible() {
this.targetable = false;
}
@Override
public void targetTooComplicated() {
this.targetable = false;
}
@Override
public void targetNotInPlayableMap() {
this.targetable = false;
}
@Override
public void orderIdNotAccepted() {
this.targetable = false;
}
}

View File

@ -0,0 +1,57 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
public class StringMsgAbilityActivationReceiver implements AbilityActivationReceiver {
private static final StringMsgAbilityActivationReceiver INSTANCE = new StringMsgAbilityActivationReceiver();
public static StringMsgAbilityActivationReceiver getInstance() {
return INSTANCE;
}
private String message;
private boolean useOk = false;
public StringMsgAbilityActivationReceiver reset() {
this.message = null;
this.useOk = false;
return this;
}
public String getMessage() {
return this.message;
}
public boolean isUseOk() {
return this.useOk;
}
@Override
public void useOk() {
this.useOk = true;
}
@Override
public void notEnoughResources(final ResourceType resource, final int amount) {
this.message = "NOTEXTERN: Requires " + amount + " " + resource.name().toLowerCase() + ".";
}
@Override
public void notAnActiveAbility() {
this.message = "NOTEXTERN: Not an active ability.";
}
@Override
public void missingRequirement(final String name) {
this.message = "NOTEXTERN: Requires " + name;
}
@Override
public void cargoCapacityUnavailable() {
this.message = "NOTEXTERN: Cargo capacity unavailable.";
}
@Override
public void casterMovementDisabled() {
this.message = "NOTEXTERN: Caster movement disabled.";
}
}

View File

@ -0,0 +1,96 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
public final class StringMsgTargetCheckReceiver<TARGET_TYPE> implements AbilityTargetCheckReceiver<TARGET_TYPE> {
private static final StringMsgTargetCheckReceiver<?> INSTANCE = new StringMsgTargetCheckReceiver<>();
public static <T> StringMsgTargetCheckReceiver<T> getInstance() {
return (StringMsgTargetCheckReceiver<T>) INSTANCE;
}
private TARGET_TYPE target;
private String message;
public TARGET_TYPE getTarget() {
return this.target;
}
public String getMessage() {
return this.message;
}
public StringMsgTargetCheckReceiver<TARGET_TYPE> reset() {
this.target = null;
this.message = null;
return this;
}
@Override
public void targetOk(final TARGET_TYPE target) {
this.target = target;
}
@Override
public void mustTargetTeamType(final TeamType correctType) {
switch (correctType) {
case ALLIED:
this.message = "NOTEXTERN: Must target an allied unit.";
break;
case ENEMY:
this.message = "NOTEXTERN: Must target an enemy unit.";
break;
case PLAYER_UNITS:
this.message = "NOTEXTERN: Unable to target a unit you do not control.";
break;
default:
this.message = "NOTEXTERN: Must target team type: " + correctType;
}
}
@Override
public void mustTargetType(final TargetType correctType) {
switch (correctType) {
case POINT:
this.message = "NOTEXTERN: Must target a point.";
break;
case UNIT:
this.message = "NOTEXTERN: Must target a unit.";
break;
case UNIT_OR_POINT:
this.message = "NOTEXTERN: Must target a unit or point.";
break;
default:
this.message = "NOTEXTERN: Must target type: " + correctType;
}
}
@Override
public void targetOutsideRange(final double howMuch) {
this.message = "NOTEXTERN: Target is outside range.";
}
@Override
public void notAnActiveAbility() {
this.message = "NOTEXTERN: Not an active ability.";
}
@Override
public void targetNotVisible() {
this.message = "NOTEXTERN: Target is not visible.";
}
@Override
public void targetTooComplicated() {
this.message = "NOTEXTERN: Target is too complicated.";
}
@Override
public void targetNotInPlayableMap() {
this.message = "NOTEXTERN: Target is not within the designed combat area.";
}
@Override
public void orderIdNotAccepted() {
this.message = "NOTEXTERN: OrderID not accepted.";
}
}

View File

@ -1,5 +1,6 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
@ -11,6 +12,7 @@ import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButton;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandListener;
public class CommandCardIcon extends AbstractRenderableFrame {
@ -18,9 +20,14 @@ public class CommandCardIcon extends AbstractRenderableFrame {
private SpriteFrame cooldownFrame;
private SpriteFrame autocastFrame;
private CommandButton commandButton;
private int abilityHandleId;
private int orderId;
private final CommandCardCommandListener commandCardCommandListener;
public CommandCardIcon(final String name, final UIFrame parent) {
public CommandCardIcon(final String name, final UIFrame parent,
final CommandCardCommandListener commandCardCommandListener) {
super(name, parent);
this.commandCardCommandListener = commandCardCommandListener;
}
public void set(final TextureFrame iconFrame, final SpriteFrame cooldownFrame, final SpriteFrame autocastFrame) {
@ -57,11 +64,13 @@ public class CommandCardIcon extends AbstractRenderableFrame {
}
}
public void setCommandButtonData(final Texture texture, final int orderId) {
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId) {
this.iconFrame.setVisible(true);
this.cooldownFrame.setVisible(false);
this.autocastFrame.setVisible(false);
this.iconFrame.setTexture(texture);
this.abilityHandleId = abilityHandleId;
this.orderId = orderId;
}
@Override
@ -81,6 +90,12 @@ public class CommandCardIcon extends AbstractRenderableFrame {
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (this.renderBounds.contains(screenX, screenY)) {
if (button == Input.Buttons.LEFT) {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.orderId);
}
else if (button == Input.Buttons.RIGHT) {
this.commandCardCommandListener.toggleAutoCastAbility(this.abilityHandleId);
}
return this;
}
return null;

View File

@ -1,10 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
@ -13,11 +15,13 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
@ -34,6 +38,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.ReplaceableIds;
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
import com.etheller.warsmash.viewer5.handlers.tga.TgaFile;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
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;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
@ -41,18 +46,34 @@ import com.etheller.warsmash.viewer5.handlers.w3x.camera.GameCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.PortraitCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitClassification;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitFilterFunction;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitStateListener;
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.CAbilityAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityView;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CodeKeyType;
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.CPlayerUnitOrderListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CWidgetAbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.PointAbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.StringMsgAbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandListener;
public class MeleeUI implements CUnitStateListener, CommandButtonListener {
public class MeleeUI implements CUnitStateListener, CommandButtonListener, CommandCardCommandListener {
private static final int COMMAND_CARD_WIDTH = 4;
private static final int COMMAND_CARD_HEIGHT = 3;
private static final Vector2 screenCoordsVector = new Vector2();
private static final Vector3 clickLocationTemp = new Vector3();
private static final Vector2 clickLocationTemp2 = new Vector2();
private final DataSource dataSource;
private final Viewport uiViewport;
private final FreeTypeFontGenerator fontGenerator;
@ -104,11 +125,20 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
private UIFrame inventoryCover;
private SpriteFrame cursorFrame;
private MeleeUIMinimap meleeUIMinimap;
private final CPlayerUnitOrderListener unitOrderListener;
private StringFrame errorMessageFrame;
private CAbilityView activeCommand;
private int activeCommandOrderId;
private RenderUnit activeCommandUnit;
private int selectedSoundCount = 0;
private final ActiveCommandUnitTargetFilter activeCommandUnitTargetFilter;
public MeleeUI(final DataSource dataSource, final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator,
final Scene uiScene, final Scene portraitScene, final CameraPreset[] cameraPresets,
final CameraRates cameraRates, final War3MapViewer war3MapViewer,
final RootFrameListener rootFrameListener) {
final CameraRates cameraRates, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener,
final CPlayerUnitOrderListener unitOrderListener) {
this.dataSource = dataSource;
this.uiViewport = uiViewport;
this.fontGenerator = fontGenerator;
@ -116,6 +146,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.portraitScene = portraitScene;
this.war3MapViewer = war3MapViewer;
this.rootFrameListener = rootFrameListener;
this.unitOrderListener = unitOrderListener;
this.cameraManager = new GameCameraManager(cameraPresets, cameraRates);
@ -127,6 +158,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.activeButtonTexture = ImageUtils.getBLPTexture(war3MapViewer.mapMpq,
"UI\\Widgets\\Console\\Human\\CommandButton\\human-activebutton.blp");
this.activeCommandUnitTargetFilter = new ActiveCommandUnitTargetFilter();
}
@ -170,7 +202,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
// =================================
// Load skins and templates
// =================================
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, 3), this.uiViewport,
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, 0), this.uiViewport,
this.fontGenerator, this.uiScene, this.war3MapViewer);
this.rootFrameListener.onCreate(this.rootFrame);
try {
@ -259,11 +291,17 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.inventoryCover = this.rootFrame.createSimpleFrame("SmashConsoleInventoryCover", this.rootFrame, 0);
this.errorMessageFrame = this.rootFrame.createStringFrame("SmashErrorMessageFrame", this.consoleUI,
new Color(0xFFFFCC00), TextJustify.LEFT, TextJustify.MIDDLE, 0.014f);
this.errorMessageFrame.addAnchor(new AnchorDefinition(FramePoint.BOTTOMLEFT,
GameUI.convertX(this.uiViewport, 0.275f), GameUI.convertY(this.uiViewport, 0.275f)));
this.errorMessageFrame.setWidth(GameUI.convertX(this.uiViewport, 0.25f));
int commandButtonIndex = 0;
for (int j = 0; j < COMMAND_CARD_HEIGHT; j++) {
for (int i = 0; i < COMMAND_CARD_WIDTH; i++) {
final CommandCardIcon commandCardIcon = new CommandCardIcon("SmashCommandButton_" + commandButtonIndex,
this.rootFrame);
this.rootFrame, this);
this.rootFrame.add(commandCardIcon);
final TextureFrame iconFrame = this.rootFrame.createTextureFrame(
"SmashCommandButton_" + (commandButtonIndex) + "_Icon", this.rootFrame, false, null);
@ -271,17 +309,20 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
"SmashCommandButton_" + (commandButtonIndex) + "_Cooldown", this.rootFrame, "", 0);
final SpriteFrame autocastFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
"SmashCommandButton_" + (commandButtonIndex) + "_Autocast", this.rootFrame, "", 0);
iconFrame.addAnchor(new AnchorDefinition(FramePoint.BOTTOMLEFT,
commandCardIcon.addAnchor(new AnchorDefinition(FramePoint.BOTTOMLEFT,
GameUI.convertX(this.uiViewport, 0.6175f + (0.0434f * i)),
GameUI.convertY(this.uiViewport, 0.095f - (0.044f * j))));
commandCardIcon.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
commandCardIcon.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
iconFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
iconFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
iconFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
iconFrame.setTexture(ImageUtils.DEFAULT_ICON_PATH, this.rootFrame);
cooldownFrame.addSetPoint(new SetPoint(FramePoint.CENTER, iconFrame, FramePoint.CENTER, 0, 0));
cooldownFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
this.rootFrame.setSpriteFrameModel(cooldownFrame, this.rootFrame.getSkinField("CommandButtonCooldown"));
cooldownFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
cooldownFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
autocastFrame.addSetPoint(new SetPoint(FramePoint.CENTER, iconFrame, FramePoint.CENTER, 0, 0));
autocastFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
this.rootFrame.setSpriteFrameModel(autocastFrame, this.rootFrame.getSkinField("CommandButtonAutocast"));
autocastFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
@ -305,6 +346,51 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
selectUnit(null);
}
@Override
public void startUsingAbility(final int abilityHandleId, final int orderId) {
// TODO not O(N)
CAbilityView abilityToUse = null;
for (final CAbility ability : this.selectedUnit.getSimulationUnit().getAbilities()) {
if (ability.getHandleId() == abilityHandleId) {
abilityToUse = ability;
break;
}
}
if (abilityToUse != null) {
final StringMsgAbilityActivationReceiver stringMsgActivationReceiver = StringMsgAbilityActivationReceiver
.getInstance().reset();
abilityToUse.checkCanUse(this.war3MapViewer.simulation, this.selectedUnit.getSimulationUnit(), orderId,
stringMsgActivationReceiver);
if (!stringMsgActivationReceiver.isUseOk()) {
showCommandError(stringMsgActivationReceiver.getMessage());
}
else {
final BooleanAbilityTargetCheckReceiver<Void> noTargetReceiver = BooleanAbilityTargetCheckReceiver
.<Void>getInstance().reset();
abilityToUse.checkCanTargetNoTarget(this.war3MapViewer.simulation,
this.selectedUnit.getSimulationUnit(), orderId, noTargetReceiver);
if (noTargetReceiver.isTargetable()) {
this.unitOrderListener.issueImmediateOrder(this.selectedUnit.getSimulationUnit().getHandleId(),
abilityHandleId, orderId, isShiftDown());
}
else {
this.activeCommand = abilityToUse;
this.activeCommandOrderId = orderId;
this.activeCommandUnit = this.selectedUnit;
}
}
}
}
public void showCommandError(final String message) {
this.errorMessageFrame.setText(message);
}
@Override
public void toggleAutoCastAbility(final int abilityHandleId) {
}
public void update(final float deltaTime) {
this.portrait.update();
@ -329,7 +415,10 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.cursorFrame.setFramePointX(FramePoint.LEFT, screenCoordsVector.x);
this.cursorFrame.setFramePointY(FramePoint.BOTTOM, screenCoordsVector.y);
if (down) {
if (this.activeCommand != null) {
this.cursorFrame.setSequence("Target");
}
else if (down) {
if (left) {
this.cursorFrame.setSequence("Scroll Down Left");
}
@ -383,6 +472,17 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.portrait.talk();
}
private final class ActiveCommandUnitTargetFilter implements CUnitFilterFunction {
@Override
public boolean call(final CUnit unit) {
final BooleanAbilityTargetCheckReceiver<CWidget> targetReceiver = BooleanAbilityTargetCheckReceiver
.<CWidget>getInstance();
MeleeUI.this.activeCommand.checkCanTarget(MeleeUI.this.war3MapViewer.simulation, unit,
MeleeUI.this.activeCommandOrderId, unit, targetReceiver);
return targetReceiver.isTargetable();
}
}
private static final class Portrait {
private MdxComplexInstance modelInstance;
private final PortraitCameraManager portraitCameraManager;
@ -539,11 +639,10 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
@Override
public void commandButton(final int buttonPositionX, final int buttonPositionY, final Texture icon,
final int orderId) {
final int abilityHandleId, final int orderId) {
final int x = Math.max(0, Math.min(COMMAND_CARD_WIDTH - 1, buttonPositionX));
final int y = Math.max(0, Math.min(COMMAND_CARD_HEIGHT - 1, buttonPositionY));
this.commandCard[y][x].setCommandButtonData(icon, orderId);
this.commandCard[y][x].setCommandButtonData(icon, abilityHandleId, orderId);
}
public void resize(final Rectangle viewport) {
@ -649,17 +748,191 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener {
this.cameraManager.scrolled(amount);
}
public boolean touchDown(final float screenX, final float screenY, final int button) {
if (this.meleeUIMinimap.containsMouse(screenX, screenY)) {
final Vector2 worldPoint = this.meleeUIMinimap.getWorldPointFromScreen(screenX, screenY);
public boolean touchDown(final int screenX, final int screenY, final float worldScreenY, final int button) {
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
if (this.meleeUIMinimap.containsMouse(screenCoordsVector.x, screenCoordsVector.y)) {
final Vector2 worldPoint = this.meleeUIMinimap.getWorldPointFromScreen(screenCoordsVector.x,
screenCoordsVector.y);
this.cameraManager.target.x = worldPoint.x;
this.cameraManager.target.y = worldPoint.y;
return true;
}
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
this.rootFrame.touchDown(GameUI.unconvertX(this.uiViewport, screenCoordsVector.x),
GameUI.unconvertY(this.uiViewport, screenCoordsVector.y), button);
final UIFrame clickedUIFrame = this.rootFrame.touchDown(screenCoordsVector.x, screenCoordsVector.y, button);
if (clickedUIFrame == null) {
// try to interact with world
if (this.activeCommand != null) {
if (button == Input.Buttons.RIGHT) {
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
}
else {
final RenderUnit rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY,
this.activeCommandUnitTargetFilter);
final boolean shiftDown = isShiftDown();
if (rayPickUnit != null) {
if (this.unitOrderListener.issueTargetOrder(
this.activeCommandUnit.getSimulationUnit().getHandleId(),
this.activeCommand.getHandleId(), this.activeCommandOrderId,
rayPickUnit.getSimulationUnit().getHandleId(), shiftDown)) {
if (getSelectedUnit().soundset.yesAttack
.playUnitResponse(this.war3MapViewer.worldScene.audioContext, getSelectedUnit())) {
portraitTalk();
}
this.selectedSoundCount = 0;
if (!shiftDown) {
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
}
}
}
else {
this.war3MapViewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
this.activeCommand.checkCanTarget(this.war3MapViewer.simulation,
this.activeCommandUnit.getSimulationUnit(), this.activeCommandOrderId,
clickLocationTemp2, PointAbilityTargetCheckReceiver.INSTANCE);
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (target != null) {
if (this.activeCommand instanceof CAbilityAttack) {
this.war3MapViewer.showConfirmation(clickLocationTemp, 1, 0, 0);
}
else {
this.war3MapViewer.showConfirmation(clickLocationTemp, 0, 1, 0);
}
if (this.unitOrderListener.issuePointOrder(
this.activeCommandUnit.getSimulationUnit().getHandleId(),
this.activeCommand.getHandleId(), this.activeCommandOrderId, clickLocationTemp2.x,
clickLocationTemp2.y, shiftDown)) {
if (getSelectedUnit().soundset.yes.playUnitResponse(
this.war3MapViewer.worldScene.audioContext, getSelectedUnit())) {
portraitTalk();
}
this.selectedSoundCount = 0;
if (!shiftDown) {
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
}
}
}
}
}
}
else {
if (button == Input.Buttons.RIGHT) {
final RenderUnit rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY);
if (getSelectedUnit() != null) {
if ((rayPickUnit != null) && (rayPickUnit.playerIndex != getSelectedUnit().playerIndex)
&& !rayPickUnit.getSimulationUnit().isDead()) {
boolean ordered = false;
for (final RenderUnit unit : this.war3MapViewer.selected) {
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
ability.checkCanTarget(this.war3MapViewer.simulation, unit.getSimulationUnit(),
OrderIds.smart, rayPickUnit.getSimulationUnit(),
CWidgetAbilityTargetCheckReceiver.INSTANCE);
final CWidget targetWidget = CWidgetAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (targetWidget != null) {
this.unitOrderListener.issueTargetOrder(unit.getSimulationUnit().getHandleId(),
ability.getHandleId(), OrderIds.smart, targetWidget.getHandleId(),
isShiftDown());
ordered = true;
}
}
}
if (ordered) {
if (getSelectedUnit().soundset.yesAttack.playUnitResponse(
this.war3MapViewer.worldScene.audioContext, getSelectedUnit())) {
portraitTalk();
}
this.selectedSoundCount = 0;
}
}
else {
this.war3MapViewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
this.war3MapViewer.showConfirmation(clickLocationTemp, 0, 1, 0);
clickLocationTemp2.set(clickLocationTemp.x, clickLocationTemp.y);
boolean ordered = false;
for (final RenderUnit unit : this.war3MapViewer.selected) {
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
ability.checkCanUse(this.war3MapViewer.simulation, unit.getSimulationUnit(),
OrderIds.smart, BooleanAbilityActivationReceiver.INSTANCE);
if (BooleanAbilityActivationReceiver.INSTANCE.isOk()) {
ability.checkCanTarget(this.war3MapViewer.simulation, unit.getSimulationUnit(),
OrderIds.smart, clickLocationTemp2,
PointAbilityTargetCheckReceiver.INSTANCE);
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (target != null) {
this.unitOrderListener.issuePointOrder(
unit.getSimulationUnit().getHandleId(), ability.getHandleId(),
OrderIds.smart, clickLocationTemp2.x, clickLocationTemp2.y,
isShiftDown());
ordered = true;
}
}
}
}
if (ordered) {
if (getSelectedUnit().soundset.yes.playUnitResponse(
this.war3MapViewer.worldScene.audioContext, getSelectedUnit())) {
portraitTalk();
}
this.selectedSoundCount = 0;
}
}
}
}
else {
final List<RenderUnit> selectedUnits = this.war3MapViewer.selectUnit(screenX, worldScreenY, false);
if (!selectedUnits.isEmpty()) {
final RenderUnit unit = selectedUnits.get(0);
final boolean selectionChanged = getSelectedUnit() != unit;
boolean playedNewSound = false;
if (selectionChanged) {
this.selectedSoundCount = 0;
}
if (unit.soundset != null) {
UnitSound ackSoundToPlay = unit.soundset.what;
final int pissedSoundCount = unit.soundset.pissed.getSoundCount();
int soundIndex;
if ((this.selectedSoundCount >= 3) && (pissedSoundCount > 0)) {
soundIndex = this.selectedSoundCount - 3;
ackSoundToPlay = unit.soundset.pissed;
}
else {
soundIndex = (int) (Math.random() * ackSoundToPlay.getSoundCount());
}
if (ackSoundToPlay.playUnitResponse(this.war3MapViewer.worldScene.audioContext, unit,
soundIndex)) {
this.selectedSoundCount++;
if ((this.selectedSoundCount - 3) >= pissedSoundCount) {
this.selectedSoundCount = 0;
}
playedNewSound = true;
}
}
if (selectionChanged) {
selectUnit(unit);
}
if (playedNewSound) {
portraitTalk();
}
}
else {
selectUnit(null);
}
}
}
}
return false;
}
private static boolean isShiftDown() {
return Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT);
}
}

View File

@ -0,0 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
public interface ActiveCommand {
boolean finish(CSimulation simulation, CUnit selectedUnit, float mouseScreenX, float mouseScreenY);
}

View File

@ -0,0 +1,7 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
public interface CommandCardCommandListener {
void startUsingAbility(int abilityHandleId, int orderId);
void toggleAutoCastAbility(int abilityHandleId);
}

View File

@ -0,0 +1,5 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
public interface CommandErrorListener {
void showCommandError(String message);
}