Inventory system for basic item pickup and drop but no item behaviors yet

This commit is contained in:
Retera 2021-03-16 01:03:24 -04:00
parent 876b26e42f
commit 5e3150124a
65 changed files with 2414 additions and 223 deletions

View File

@ -127,4 +127,11 @@ public class SpriteFrame extends AbstractRenderableFrame {
return this.instance.sequenceEnded;
}
public void setReplaceableId(final int replaceableId, final String blpPath) {
if (this.instance != null) {
this.instance.setReplaceableTexture(replaceableId, blpPath);
}
}
}

View File

@ -48,18 +48,30 @@ public class StringFrame extends AbstractRenderableFrame {
public void setColor(final Color color) {
this.color = color;
for (final SingleStringFrame internalFrame : this.internalFrames) {
internalFrame.setColor(color);
}
}
public void setFontShadowColor(final Color fontShadowColor) {
this.fontShadowColor = fontShadowColor;
for (final SingleStringFrame internalFrame : this.internalFrames) {
internalFrame.setFontShadowColor(fontShadowColor);
}
}
public void setFontShadowOffsetX(final float fontShadowOffsetX) {
this.fontShadowOffsetX = fontShadowOffsetX;
for (final SingleStringFrame internalFrame : this.internalFrames) {
internalFrame.setFontShadowOffsetX(fontShadowOffsetX);
}
}
public void setFontShadowOffsetY(final float fontShadowOffsetY) {
this.fontShadowOffsetY = fontShadowOffsetY;
for (final SingleStringFrame internalFrame : this.internalFrames) {
internalFrame.setFontShadowOffsetY(fontShadowOffsetY);
}
}
@Override
@ -414,6 +426,9 @@ public class StringFrame extends AbstractRenderableFrame {
public void setAlpha(final float alpha) {
this.alpha = alpha;
for (final SingleStringFrame internalFrame : this.internalFrames) {
internalFrame.setAlpha(alpha);
}
}

View File

@ -6,7 +6,7 @@ public class WarsmashConstants {
* With version, we use 0 for RoC, 1 for TFT emulation, and probably 2+ or
* whatever for custom mods and other stuff
*/
public static int GAME_VERSION = 0;
public static int GAME_VERSION = 1;
public static final int REPLACEABLE_TEXTURE_LIMIT = 64;
public static final float SIMULATION_STEP_TIME = 1 / 20f;
public static final int PORT_NUMBER = 6115;

View File

@ -39,7 +39,7 @@ public class EmitterGroup extends GenericGroup {
viewer.webGL.useShaderProgram(shader);
shader.setUniformMatrix("u_mvp", mvp);
shader.setUniformf("u_texture", 0);
shader.setUniformi("u_texture", 0);
final int a_position = shader.getAttributeLocation("a_position");
instancedArrays.glVertexAttribDivisorANGLE(a_position, 0);

View File

@ -433,7 +433,7 @@ public class GeometryEmitterFuncs {
buffer.bindAndUpdate(size);
shader.setUniformi("u_emitter", emitterType);
shader.setUniformf("u_emitter", emitterType);
shader.setVertexAttribute("a_p0", 3, GL20.GL_FLOAT, false, BYTES_PER_OBJECT, BYTE_OFFSET_P0);
shader.setVertexAttribute("a_p1", 3, GL20.GL_FLOAT, false, BYTES_PER_OBJECT, BYTE_OFFSET_P1);

View File

@ -6,6 +6,8 @@ import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
@ -510,6 +512,11 @@ public class MdxComplexInstance extends ModelInstance {
for (final GenericGroup group : model.opaqueGroups) {
group.render(this, mvp);
}
final int glGetError = Gdx.gl.glGetError();
if (glGetError != GL20.GL_NO_ERROR) {
throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Opaque)");
}
}
@Override
@ -521,6 +528,11 @@ public class MdxComplexInstance extends ModelInstance {
for (final GenericGroup group : model.translucentGroups) {
group.render(this, this.scene.camera.viewProjectionMatrix);
final int glGetError = Gdx.gl.glGetError();
if (glGetError != GL20.GL_NO_ERROR) {
throw new IllegalStateException("GL ERROR: " + glGetError + " ON " + model.name + " (Translucent)");
}
}
}

View File

@ -20,7 +20,7 @@ public class TextTag {
public boolean update(final float deltaTime) {
this.screenCoordsZHeight += 60.0f * deltaTime;
this.lifetime += deltaTime;
return this.lifetime > 3.5f;
return this.lifetime > 2.5f;
}
public Vector3 getPosition() {
@ -28,7 +28,7 @@ public class TextTag {
}
public float getRemainingLife() {
return 3.5f - this.lifetime;
return 2.5f - this.lifetime;
}
public Color getColor() {

View File

@ -24,6 +24,7 @@ import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
@ -91,6 +92,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityUI;
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.CUnitClassification;
@ -130,6 +132,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
private static final War3ID DESTRUCTABLE_PATHING_DEATH = War3ID.fromString("bptd");
private static final War3ID ELEVATION_SAMPLE_RADIUS = War3ID.fromString("uerd");
private static final War3ID MAX_PITCH = War3ID.fromString("umxp");
private static final War3ID ALLOW_CUSTOM_TEAM_COLOR = War3ID.fromString("utcc");
private static final War3ID TEAM_COLOR = War3ID.fromString("utco");
private static final War3ID MAX_ROLL = War3ID.fromString("umxr");
private static final War3ID sloc = War3ID.fromString("sloc");
private static final LoadGenericCallback stringDataCallback = new StringDataCallbackImplementation();
@ -160,7 +164,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public MappedData unitMetaData = new MappedData();
public List<RenderWidget> widgets = new ArrayList<>();
public List<RenderUnit> units = new ArrayList<>();
public List<RenderItem> items = new ArrayList<>();
public List<RenderEffect> projectiles = new ArrayList<>();
public boolean unitsReady;
public War3Map mapMpq;
@ -199,6 +202,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
private final Map<CUnit, RenderUnit> unitToRenderPeer = new HashMap<>();
private final Map<CDestructable, RenderDestructable> destructableToRenderPeer = new HashMap<>();
private final Map<CItem, RenderItem> itemToRenderPeer = new HashMap<>();
private final Map<War3ID, RenderUnitTypeData> unitIdToTypeData = new HashMap<>();
private GameUI gameUI;
private Vector3 lightDirection;
@ -451,7 +455,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
this.confirmationInstance.setScene(this.worldScene);
this.allObjectData = this.mapMpq.readModifications();
this.simulation = new CSimulation(this.miscData, this.allObjectData.getUnits(),
this.simulation = new CSimulation(this.miscData, this.allObjectData.getUnits(), this.allObjectData.getItems(),
this.allObjectData.getDestructibles(), this.allObjectData.getAbilities(),
new SimulationRenderController() {
private final Map<String, UnitSound> keyToCombatSound = new HashMap<>();
@ -541,10 +545,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void spawnDamageSound(final CWidget damagedDestructable, final String weaponSound,
final String armorType) {
RenderWidget damagedWidget = War3MapViewer.this.unitToRenderPeer.get(damagedDestructable);
if (damagedWidget == null) {
damagedWidget = War3MapViewer.this.destructableToRenderPeer.get(damagedDestructable);
}
final RenderWidget damagedWidget = getRenderPeer(damagedDestructable);
if (damagedWidget == null) {
return;
}
@ -621,7 +622,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public CUnit createUnit(final CSimulation simulation, final War3ID typeId, final int playerIndex,
final float x, final float y, final float facing) {
return createNewUnit(War3MapViewer.this.allObjectData, typeId, x, y, 0f, playerIndex,
(float) Math.toRadians(facing));
playerIndex, (float) Math.toRadians(facing));
}
@Override
@ -724,6 +725,26 @@ public class War3MapViewer extends AbstractMdxModelViewer {
break;
}
}
@Override
public void spawnUIUnitGetItemSound(final CUnit cUnit, final CItem item) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(cUnit);
if (localPlayerIndex == renderPeer.getSimulationUnit().getPlayerIndex()) {
War3MapViewer.this.uiSounds.getSound("ItemGet").play(
War3MapViewer.this.worldScene.audioContext, renderPeer.getX(), renderPeer.getY(),
renderPeer.getZ());
}
}
@Override
public void spawnUIUnitDropItemSound(final CUnit cUnit, final CItem item) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(cUnit);
if (localPlayerIndex == renderPeer.getSimulationUnit().getPlayerIndex()) {
War3MapViewer.this.uiSounds.getSound("ItemDrop").play(
War3MapViewer.this.worldScene.audioContext, renderPeer.getX(), renderPeer.getY(),
renderPeer.getZ());
}
}
}, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, w3iFile.getPlayers(),
this.commandErrorListener);
@ -983,10 +1004,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final float unitY = unit.getLocation()[1];
final float unitZ = unit.getLocation()[2];
final int playerIndex = unit.getPlayer();
final int customTeamColor = unit.getCustomTeamColor();
final float unitAngle = unit.getAngle();
final CUnit unitCreated = createNewUnit(modifications, unitId, unitX, unitY, unitZ, playerIndex,
unitAngle);
customTeamColor, unitAngle);
if (unit.getGoldAmount() != 0) {
unitCreated.setGold(unit.getGoldAmount());
}
@ -1001,7 +1023,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
private CUnit createNewUnit(final Warcraft3MapObjectData modifications, final War3ID unitId, float unitX,
float unitY, final float unitZ, final int playerIndex, final float unitAngle) {
float unitY, final float unitZ, final int playerIndex, int customTeamColor, final float unitAngle) {
UnitSoundset soundset = null;
MutableGameObject row = null;
String path = null;
@ -1174,7 +1196,15 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final CUnit simulationUnit = this.simulation.createUnit(row.getAlias(), playerIndex, unitX, unitY,
angle, buildingPathingPixelMap, pathingInstance);
final RenderUnitTypeData typeData = getUnitTypeData(unitId, row);
final RenderUnit renderUnit = new RenderUnit(this, model, row, unitX, unitY, unitZ, playerIndex,
if (!typeData.isAllowCustomTeamColor() || (customTeamColor == -1)) {
if (typeData.getTeamColor() != -1) {
customTeamColor = typeData.getTeamColor();
}
else {
customTeamColor = playerIndex;
}
}
final RenderUnit renderUnit = new RenderUnit(this, model, row, unitX, unitY, unitZ, customTeamColor,
soundset, portraitModel, simulationUnit, typeData, specialArtModel, buildingShadowInstance,
this.selectionCircleScaleFactor);
this.unitToRenderPeer.put(simulationUnit, renderUnit);
@ -1205,19 +1235,22 @@ public class War3MapViewer extends AbstractMdxModelViewer {
return simulationUnit;
}
else {
this.items
.add(new RenderItem(this, model, row, unitX, unitY, unitZ, unitAngle, soundset, portraitModel)); // TODO
// store
// somewhere
final CItem simulationItem = this.simulation.createItem(row.getAlias(), unitX, unitY);
final RenderItem renderItem = new RenderItem(this, model, row, unitX, unitY, unitZ, unitAngle, soundset,
portraitModel, simulationItem);
this.widgets.add(renderItem);
this.itemToRenderPeer.put(simulationItem, renderItem);
if (unitShadowSplat != null) {
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
@Override
public void accept(final SplatMover t) {
renderItem.shadow = t;
}
});
}
if (unitShadowSplatDynamicIngame != null) {
renderItem.shadow = unitShadowSplatDynamicIngame;
}
}
}
@ -1278,7 +1311,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
RenderUnitTypeData unitTypeData = this.unitIdToTypeData.get(key);
if (unitTypeData == null) {
unitTypeData = new RenderUnitTypeData(row.getFieldAsFloat(MAX_PITCH, 0), row.getFieldAsFloat(MAX_ROLL, 0),
row.getFieldAsFloat(ELEVATION_SAMPLE_RADIUS, 0));
row.getFieldAsFloat(ELEVATION_SAMPLE_RADIUS, 0), row.getFieldAsBoolean(ALLOW_CUSTOM_TEAM_COLOR, 0),
row.getFieldAsInteger(TEAM_COLOR, 0));
this.unitIdToTypeData.put(key, unitTypeData);
}
return unitTypeData;
@ -1287,13 +1321,14 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void update() {
if (this.anyReady) {
this.terrain.update();
final float deltaTime = Gdx.graphics.getDeltaTime();
this.terrain.update(deltaTime);
super.update();
final Iterator<TextTag> textTagIterator = this.textTags.iterator();
while (textTagIterator.hasNext()) {
if (textTagIterator.next().update(Gdx.graphics.getDeltaTime())) {
if (textTagIterator.next().update(deltaTime)) {
textTagIterator.remove();
}
}
@ -1307,13 +1342,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
projectileIterator.remove();
}
}
for (final RenderItem item : this.items) {
final MdxComplexInstance instance = item.instance;
final MdxComplexInstance mdxComplexInstance = instance;
if (mdxComplexInstance.sequenceEnded || (mdxComplexInstance.sequence == -1)) {
SequenceUtils.randomStandSequence(mdxComplexInstance);
}
}
for (final RenderDoodad item : this.doodads) {
final ModelInstance instance = item.instance;
if (instance instanceof MdxComplexInstance) {
@ -1373,6 +1401,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
scene.renderTranslucent();
}
}
final int glGetError = Gdx.gl.glGetError();
if (glGetError != GL20.GL_NO_ERROR) {
throw new IllegalStateException("GL ERROR: " + glGetError);
}
}
}
@ -1492,11 +1525,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
else {
sel = Arrays.asList(entity);
}
this.doSelectUnit(sel);
}
else {
sel = Collections.emptyList();
}
this.doSelectUnit(sel);
return sel;
}
@ -1659,6 +1692,17 @@ public class War3MapViewer extends AbstractMdxModelViewer {
return mdxPath;
}
public String blp(String iconPath) {
final int lastDotIndex = iconPath.lastIndexOf('.');
if (lastDotIndex != -1) {
iconPath = iconPath.substring(0, lastDotIndex);
}
if (!iconPath.toLowerCase().endsWith(".blp")) {
iconPath += ".blp";
}
return iconPath;
}
public MdxModel loadModel(final String path) {
return (MdxModel) load(mdx(path), PathSolver.DEFAULT, null);
}
@ -1681,7 +1725,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public void setGameUI(final GameUI gameUI) {
this.gameUI = gameUI;
this.abilityDataUI = new AbilityDataUI(this.allObjectData.getAbilities(), this.allObjectData.getUnits(),
this.allObjectData.getUpgrades(), gameUI, this);
this.allObjectData.getItems(), this.allObjectData.getUpgrades(), gameUI, this);
}
public GameUI getGameUI() {
@ -1722,6 +1766,21 @@ public class War3MapViewer extends AbstractMdxModelViewer {
return this.destructableToRenderPeer.get(dest);
}
public RenderItem getRenderPeer(final CItem item) {
return this.itemToRenderPeer.get(item);
}
private RenderWidget getRenderPeer(final CWidget damagedDestructable) {
RenderWidget damagedWidget = War3MapViewer.this.unitToRenderPeer.get(damagedDestructable);
if (damagedWidget == null) {
damagedWidget = War3MapViewer.this.destructableToRenderPeer.get(damagedDestructable);
}
if (damagedWidget == null) {
damagedWidget = War3MapViewer.this.itemToRenderPeer.get(damagedDestructable);
}
return damagedWidget;
}
private static final class QuadtreeIntersectorFindsWalkableRenderHeight
implements QuadtreeIntersector<MdxComplexInstance> {
private float z;
@ -1793,4 +1852,5 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public void add(final TextTag textTag) {
this.textTags.add(textTag);
}
}

View File

@ -83,7 +83,7 @@ public class PathingGrid {
data |= PathingFlags.UNFLYABLE;
}
if (((rgb & 0xFF0000) >>> 16) > 127) {
data |= PathingFlags.UNWALKABLE;
data |= PathingFlags.UNWALKABLE | PathingFlags.UNSWIMABLE;
}
this.dynamicPathingOverlay[(yy * this.pathingGridSizes[0]) + xx] |= data;
}
@ -188,8 +188,7 @@ public class PathingGrid {
public RemovablePathingMapInstance createRemovablePathingOverlayTexture(final float positionX,
final float positionY, final int rotationInput, final BufferedImage pathingTextureTga) {
return new RemovablePathingMapInstance(positionX,
positionY, rotationInput, pathingTextureTga);
return new RemovablePathingMapInstance(positionX, positionY, rotationInput, pathingTextureTga);
}
public int getWidth() {

View File

@ -188,7 +188,7 @@ public class Terrain {
if (waterInfo != null) {
this.waterHeightOffset = waterInfo.getFieldFloatValue("height");
this.waterTextureCount = waterInfo.getFieldValue("numTex");
this.waterIncreasePerFrame = waterInfo.getFieldValue("texRate") / 60f;
this.waterIncreasePerFrame = waterInfo.getFieldValue("texRate");
}
else {
this.waterHeightOffset = 0;
@ -896,8 +896,8 @@ public class Terrain {
}
}
public void update() {
this.waterIndex += this.waterIncreasePerFrame;
public void update(final float deltaTime) {
this.waterIndex += this.waterIncreasePerFrame * deltaTime;
if (this.waterIndex >= this.waterTextureCount) {
this.waterIndex = 0;

View File

@ -6,25 +6,35 @@ 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.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSoundset;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
public class RenderItem {
public class RenderItem implements RenderWidget {
private static final War3ID ITEM_MODEL_SCALE = War3ID.fromString("isca");
private static final War3ID ITEM_RED = War3ID.fromString("iclr");
private static final War3ID ITEM_GREEN = War3ID.fromString("iclg");
private static final War3ID ITEM_BLUE = War3ID.fromString("iclb");
private final CItem simulationItem;
public final MdxComplexInstance instance;
public final MutableGameObject row;
public final float[] location = new float[3];
public float radius;
public UnitSoundset soundset;
public final MdxModel portraitModel;
public SplatMover shadow;
public SplatMover selectionCircle;
private boolean hidden;
private boolean dead;
public RenderItem(final War3MapViewer map, final MdxModel model, final MutableGameObject row, final float x,
final float y, final float z, final float angle, final UnitSoundset soundset,
final MdxModel portraitModel) {
final float y, final float z, final float angle, final UnitSoundset soundset, final MdxModel portraitModel,
final CItem simulationItem) {
this.portraitModel = portraitModel;
this.simulationItem = simulationItem;
final MdxComplexInstance instance = (MdxComplexInstance) model.addInstance();
this.location[0] = x;
@ -55,4 +65,115 @@ public class RenderItem {
this.row = row;
this.soundset = soundset;
}
@Override
public MdxComplexInstance getInstance() {
return this.instance;
}
@Override
public CWidget getSimulationWidget() {
return this.simulationItem;
}
@Override
public void updateAnimations(final War3MapViewer map) {
final boolean hidden = this.simulationItem.isHidden();
if (hidden != this.hidden) {
this.hidden = hidden;
if (hidden) {
this.instance.hide();
if (this.shadow != null) {
this.shadow.hide();
}
}
else {
this.instance.show();
if (this.shadow != null) {
this.shadow.show(map.terrain.centerOffset);
}
}
}
final boolean dead = this.simulationItem.isDead();
final MdxComplexInstance mdxComplexInstance = this.instance;
if (dead) {
if (!this.dead) {
this.dead = dead;
SequenceUtils.randomDeathSequence(mdxComplexInstance);
}
}
else if (mdxComplexInstance.sequenceEnded || (mdxComplexInstance.sequence == -1)) {
SequenceUtils.randomStandSequence(mdxComplexInstance);
}
final float prevX = this.location[0];
final float prevY = this.location[1];
final float simulationX = this.simulationItem.getX();
final float simulationY = this.simulationItem.getY();
final float simDx = simulationX - this.location[0];
final float simDy = simulationY - this.location[1];
this.location[0] = simulationX;
this.location[1] = simulationY;
final float dx = this.location[0] - prevX;
final float dy = this.location[1] - prevY;
final float groundHeight;
// land units will have their feet pass under the surface of the water, so items
// here are in the same place
final float groundHeightTerrainAndWater = map.terrain.getGroundHeight(this.location[0], this.location[1]);
MdxComplexInstance currentWalkableUnder;
currentWalkableUnder = map.getHighestWalkableUnder(this.location[0], this.location[1]);
War3MapViewer.gdxRayHeap.set(this.location[0], this.location[1], 4096, 0, 0, -8192);
if ((currentWalkableUnder != null)
&& currentWalkableUnder.intersectRayWithCollision(War3MapViewer.gdxRayHeap,
War3MapViewer.intersectionHeap, true, true)
&& (War3MapViewer.intersectionHeap.z > groundHeightTerrainAndWater)) {
groundHeight = War3MapViewer.intersectionHeap.z;
}
else {
groundHeight = groundHeightTerrainAndWater;
currentWalkableUnder = null;
}
this.location[2] = this.simulationItem.getFlyHeight() + groundHeight;
this.instance.moveTo(this.location);
if (this.shadow != null) {
this.shadow.move(dx, dy, map.terrain.centerOffset);
this.shadow.setHeightAbsolute(currentWalkableUnder != null, groundHeight + map.imageWalkableZOffset);
}
}
@Override
public boolean isIntersectedOnMeshAlways() {
return false;
}
@Override
public float getSelectionScale() {
return 1.0f;
}
@Override
public float getX() {
return this.location[0];
}
@Override
public float getY() {
return this.location[1];
}
@Override
public float getZ() {
return this.location[2];
}
@Override
public void unassignSelectionCircle() {
this.selectionCircle = null;
}
@Override
public void assignSelectionCircle(final SplatMover t) {
this.selectionCircle = t;
}
}

View File

@ -4,11 +4,16 @@ public class RenderUnitTypeData {
private final float maxPitch;
private final float maxRoll;
private final float sampleRadius;
private final boolean allowCustomTeamColor;
private final int teamColor;
public RenderUnitTypeData(final float maxPitch, final float maxRoll, final float sampleRadius) {
public RenderUnitTypeData(final float maxPitch, final float maxRoll, final float sampleRadius,
final boolean allowCustomTeamColor, final int teamColor) {
this.maxPitch = maxPitch;
this.maxRoll = maxRoll;
this.sampleRadius = sampleRadius;
this.allowCustomTeamColor = allowCustomTeamColor;
this.teamColor = teamColor;
}
public float getMaxPitch() {
@ -22,4 +27,12 @@ public class RenderUnitTypeData {
public float getElevationSampleRadius() {
return this.sampleRadius;
}
public boolean isAllowCustomTeamColor() {
return this.allowCustomTeamColor;
}
public int getTeamColor() {
return this.teamColor;
}
}

View File

@ -45,6 +45,13 @@ public class AbilityDataUI {
private static final War3ID UNIT_TIP = War3ID.fromString("utip");
private static final War3ID UNIT_UBER_TIP = War3ID.fromString("utub");
private static final War3ID ITEM_ICON_NORMAL_X = War3ID.fromString("ubpx");
private static final War3ID ITEM_ICON_NORMAL_Y = War3ID.fromString("ubpy");
private static final War3ID ITEM_ICON_NORMAL = War3ID.fromString("iico");
private static final War3ID ITEM_TIP = War3ID.fromString("utip");
private static final War3ID ITEM_UBER_TIP = War3ID.fromString("utub");
private static final War3ID ITEM_DESCRIPTION = War3ID.fromString("ides");
private static final War3ID UPGRADE_ICON_NORMAL_X = War3ID.fromString("gbpx");
private static final War3ID UPGRADE_ICON_NORMAL_Y = War3ID.fromString("gbpy");
private static final War3ID UPGRADE_ICON_NORMAL = War3ID.fromString("gar1");
@ -54,6 +61,7 @@ public class AbilityDataUI {
private final Map<War3ID, AbilityUI> rawcodeToUI = new HashMap<>();
private final Map<War3ID, IconUI> rawcodeToUnitUI = new HashMap<>();
private final Map<War3ID, ItemUI> rawcodeToItemUI = new HashMap<>();
private final Map<War3ID, List<IconUI>> rawcodeToUpgradeUI = new HashMap<>();
private final IconUI moveUI;
private final IconUI stopUI;
@ -74,7 +82,8 @@ public class AbilityDataUI {
private final IconUI selectSkillUI;
public AbilityDataUI(final MutableObjectData abilityData, final MutableObjectData unitData,
final MutableObjectData upgradeData, final GameUI gameUI, final War3MapViewer viewer) {
final MutableObjectData itemData, final MutableObjectData upgradeData, final GameUI gameUI,
final War3MapViewer viewer) {
final String disabledPrefix = gameUI.getSkinField("CommandButtonDisabledArtPath");
for (final War3ID alias : abilityData.keySet()) {
final MutableGameObject abilityTypeData = abilityData.get(alias);
@ -129,6 +138,21 @@ public class AbilityDataUI {
this.rawcodeToUnitUI.put(alias,
new IconUI(iconNormal, iconNormalDisabled, iconNormalX, iconNormalY, iconTip, iconUberTip));
}
for (final War3ID alias : itemData.keySet()) {
final MutableGameObject abilityTypeData = itemData.get(alias);
final String iconNormalPath = gameUI.trySkinField(abilityTypeData.getFieldAsString(ITEM_ICON_NORMAL, 0));
final int iconNormalX = abilityTypeData.getFieldAsInteger(ITEM_ICON_NORMAL_X, 0);
final int iconNormalY = abilityTypeData.getFieldAsInteger(ITEM_ICON_NORMAL_Y, 0);
final String iconTip = abilityTypeData.getFieldAsString(ITEM_TIP, 0);
final String iconUberTip = abilityTypeData.getFieldAsString(ITEM_UBER_TIP, 0);
final String iconDescription = abilityTypeData.getFieldAsString(ITEM_DESCRIPTION, 0);
final Texture iconNormal = gameUI.loadTexture(iconNormalPath);
final Texture iconNormalDisabled = gameUI.loadTexture(disable(iconNormalPath, disabledPrefix));
this.rawcodeToItemUI.put(alias,
new ItemUI(
new IconUI(iconNormal, iconNormalDisabled, iconNormalX, iconNormalY, iconTip, iconUberTip),
abilityTypeData.getName(), iconDescription, iconNormalPath));
}
for (final War3ID alias : upgradeData.keySet()) {
final MutableGameObject upgradeTypeData = upgradeData.get(alias);
final int upgradeLevels = upgradeTypeData.getFieldAsInteger(UPGRADE_LEVELS, 0);
@ -186,6 +210,10 @@ public class AbilityDataUI {
return this.rawcodeToUnitUI.get(rawcode);
}
public ItemUI getItemUI(final War3ID rawcode) {
return this.rawcodeToItemUI.get(rawcode);
}
public IconUI getUpgradeUI(final War3ID rawcode, final int level) {
final List<IconUI> upgradeUI = this.rawcodeToUpgradeUI.get(rawcode);
if (upgradeUI != null) {

View File

@ -0,0 +1,32 @@
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability;
public class ItemUI {
private final IconUI iconUI;
private final String name;
private final String description;
private final String itemIconPathForDragging;
public ItemUI(final IconUI iconUI, final String name, final String description,
final String itemIconPathForDragging) {
this.iconUI = iconUI;
this.name = name;
this.description = description;
this.itemIconPathForDragging = itemIconPathForDragging;
}
public IconUI getIconUI() {
return this.iconUI;
}
public String getName() {
return this.name;
}
public String getDescription() {
return this.description;
}
public String getItemIconPathForDragging() {
return this.itemIconPathForDragging;
}
}

View File

@ -65,6 +65,17 @@ public class CGameplayConstants {
private final boolean maxLevelHeroesDrainExp;
private final boolean buildingKillsGiveExp;
private final float dropItemRange;
private final float giveItemRange;
private final float pickupItemRange;
private final float pawnItemRange;
private final float pawnItemRate;
private final float followRange;
private final float structureFollowRange;
private final float followItemRange;
private final float spellCastRangeBuffer;
public CGameplayConstants(final DataTable parsedDataTable) {
final Element miscData = parsedDataTable.get("Misc");
// TODO use radians for half angle
@ -155,6 +166,18 @@ public class CGameplayConstants {
this.agiAttackSpeedBonus = miscData.getFieldFloatValue("AgiAttackSpeedBonus");
this.heroAbilityLevelSkip = miscData.getFieldValue("HeroAbilityLevelSkip");
this.dropItemRange = miscData.getFieldFloatValue("DropItemRange");
this.giveItemRange = miscData.getFieldFloatValue("GiveItemRange");
this.pickupItemRange = miscData.getFieldFloatValue("PickupItemRange");
this.pawnItemRange = miscData.getFieldFloatValue("PawnItemRange");
this.pawnItemRate = miscData.getFieldFloatValue("PawnItemRate");
this.followRange = miscData.getFieldFloatValue("FollowRange");
this.structureFollowRange = miscData.getFieldFloatValue("StructureFollowRange");
this.followItemRange = miscData.getFieldFloatValue("FollowItemRange");
this.spellCastRangeBuffer = miscData.getFieldFloatValue("SpellCastRangeBuffer");
}
public float getAttackHalfAngle() {
@ -305,6 +328,26 @@ public class CGameplayConstants {
return getTableValue(this.grantNormalXp, level);
}
public float getDropItemRange() {
return this.dropItemRange;
}
public float getPickupItemRange() {
return this.pickupItemRange;
}
public float getGiveItemRange() {
return this.giveItemRange;
}
public float getPawnItemRange() {
return this.pawnItemRange;
}
public float getPawnItemRate() {
return this.pawnItemRate;
}
private static int getTableValue(final int[] table, int level) {
if (level <= 0) {
return 0;

View File

@ -3,17 +3,22 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
import java.util.EnumSet;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
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;
public class CItem extends CWidget {
private final War3ID typeId;
private final CItemType itemType;
private boolean hidden;
private final War3ID itemType;
public CItem(final int handleId, final float x, final float y, final float life, final War3ID itemType) {
public CItem(final int handleId, final float x, final float y, final float life, final War3ID typeId,
final CItemType itemTypeInstance) {
super(handleId, x, y, life);
this.itemType = itemType;
this.typeId = typeId;
this.itemType = itemTypeInstance;
}
@Override
@ -30,6 +35,7 @@ public class CItem extends CWidget {
public void damage(final CSimulation simulation, final CUnit source, final CAttackType attackType,
final String weaponType, final float damage) {
this.life -= damage;
simulation.itemDamageEvent(this, weaponType, this.itemType.getArmorType());
}
@Override
@ -38,8 +44,60 @@ public class CItem extends CWidget {
return targetsAllowed.contains(CTargetType.ITEM);
}
public void setX(final float x, final CWorldCollision collision) {
super.setX(x);
}
public void setY(final float y, final CWorldCollision collision) {
super.setY(y);
}
@Override
public <T> T visit(final AbilityTargetVisitor<T> visitor) {
return visitor.accept(this);
}
public War3ID getTypeId() {
return this.typeId;
}
public CItemType getItemType() {
return this.itemType;
}
public void setHidden(final boolean hidden) {
this.hidden = hidden;
}
public boolean isHidden() {
return this.hidden;
}
public void setPointAndCheckUnstuck(final float newX, final float newY, final CSimulation game) {
final CWorldCollision collision = game.getWorldCollision();
final PathingGrid pathingGrid = game.getPathingGrid();
;
float outputX = newX, outputY = newY;
int checkX = 0;
int checkY = 0;
float collisionSize;
tempRect.setSize(16, 16);
collisionSize = 16;
for (int i = 0; i < 300; i++) {
final float centerX = newX + (checkX * 64);
final float centerY = newY + (checkY * 64);
tempRect.setCenter(centerX, centerY);
if (pathingGrid.isPathable(centerX, centerY, MovementType.FOOT, collisionSize)) {
outputX = centerX;
outputY = centerY;
break;
}
final double angle = ((((int) Math.floor(Math.sqrt((4 * i) + 1))) % 4) * Math.PI) / 2;
checkX -= (int) Math.cos(angle);
checkY -= (int) Math.sin(angle);
}
setX(outputX);
setY(outputY);
}
}

View File

@ -1,5 +1,156 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
public class CItemType {
private final List<War3ID> abilityList;
private final War3ID cooldownGroup;
private final boolean ignoreCooldown;
private final int numberOfCharges;
private final boolean activelyUsed;
private final boolean perishable;
private final boolean useAutomaticallyWhenAcquired;
private final int goldCost;
private final int lumberCost;
private final int stockMax;
private final int stockReplenishInterval;
private final int stockStartDelay;
private final int hitPoints;
private final String armorType;
private final int level;
private final int levelUnclassified;
private final int priority;
private final boolean sellable;
private final boolean pawnable;
private final boolean droppedWhenCarrierDies;
private final boolean canBeDropped;
private final boolean validTargetForTransformation;
private final boolean includeAsRandomChoice;
public CItemType(final List<War3ID> abilityList, final War3ID cooldownGroup, final boolean ignoreCooldown,
final int numberOfCharges, final boolean activelyUsed, final boolean perishable,
final boolean useAutomaticallyWhenAcquired, final int goldCost, final int lumberCost, final int stockMax,
final int stockReplenishInterval, final int stockStartDelay, final int hitPoints, final String armorType,
final int level, final int levelUnclassified, final int priority, final boolean sellable,
final boolean pawnable, final boolean droppedWhenCarrierDies, final boolean canBeDropped,
final boolean validTargetForTransformation, final boolean includeAsRandomChoice) {
this.abilityList = abilityList;
this.cooldownGroup = cooldownGroup;
this.ignoreCooldown = ignoreCooldown;
this.numberOfCharges = numberOfCharges;
this.activelyUsed = activelyUsed;
this.perishable = perishable;
this.useAutomaticallyWhenAcquired = useAutomaticallyWhenAcquired;
this.goldCost = goldCost;
this.lumberCost = lumberCost;
this.stockMax = stockMax;
this.stockReplenishInterval = stockReplenishInterval;
this.stockStartDelay = stockStartDelay;
this.hitPoints = hitPoints;
this.armorType = armorType;
this.level = level;
this.levelUnclassified = levelUnclassified;
this.priority = priority;
this.sellable = sellable;
this.pawnable = pawnable;
this.droppedWhenCarrierDies = droppedWhenCarrierDies;
this.canBeDropped = canBeDropped;
this.validTargetForTransformation = validTargetForTransformation;
this.includeAsRandomChoice = includeAsRandomChoice;
}
public List<War3ID> getAbilityList() {
return this.abilityList;
}
public War3ID getCooldownGroup() {
return this.cooldownGroup;
}
public boolean isIgnoreCooldown() {
return this.ignoreCooldown;
}
public int getNumberOfCharges() {
return this.numberOfCharges;
}
public boolean isActivelyUsed() {
return this.activelyUsed;
}
public boolean isPerishable() {
return this.perishable;
}
public boolean isUseAutomaticallyWhenAcquired() {
return this.useAutomaticallyWhenAcquired;
}
public int getGoldCost() {
return this.goldCost;
}
public int getLumberCost() {
return this.lumberCost;
}
public int getStockMax() {
return this.stockMax;
}
public int getStockReplenishInterval() {
return this.stockReplenishInterval;
}
public int getStockStartDelay() {
return this.stockStartDelay;
}
public int getHitPoints() {
return this.hitPoints;
}
public String getArmorType() {
return this.armorType;
}
public int getLevel() {
return this.level;
}
public int getLevelUnclassified() {
return this.levelUnclassified;
}
public int getPriority() {
return this.priority;
}
public boolean isSellable() {
return this.sellable;
}
public boolean isPawnable() {
return this.pawnable;
}
public boolean isDroppedWhenCarrierDies() {
return this.droppedWhenCarrierDies;
}
public boolean isCanBeDropped() {
return this.canBeDropped;
}
public boolean isValidTargetForTransformation() {
return this.validTargetForTransformation;
}
public boolean isIncludeAsRandomChoice() {
return this.includeAsRandomChoice;
}
}

View File

@ -26,6 +26,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUni
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CAbilityData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CDestructableData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CItemData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CUnitData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
@ -40,9 +41,11 @@ public class CSimulation {
private final CAbilityData abilityData;
private final CUnitData unitData;
private final CDestructableData destructableData;
private final CItemData itemData;
private final List<CUnit> units;
private final List<CUnit> newUnits;
private final List<CDestructable> destructables;
private final List<CItem> items;
private final List<CPlayer> players;
private final List<CAttackProjectile> projectiles;
private final List<CAttackProjectile> newProjectiles;
@ -58,14 +61,15 @@ public class CSimulation {
private float currentGameDayTimeElapsed;
private final Map<Integer, CUnit> handleIdToUnit = new HashMap<>();
private final Map<Integer, CDestructable> handleIdToDestructable = new HashMap<>();
private final Map<Integer, CItem> handleIdToItem = new HashMap<>();
private final Map<Integer, CAbility> handleIdToAbility = new HashMap<>();
private transient CommandErrorListener commandErrorListener;
public CSimulation(final DataTable miscData, final MutableObjectData parsedUnitData,
final MutableObjectData parsedDestructableData, final MutableObjectData parsedAbilityData,
final SimulationRenderController simulationRenderController, final PathingGrid pathingGrid,
final Rectangle entireMapBounds, final Random seededRandom, final List<Player> playerInfos,
final CommandErrorListener commandErrorListener) {
final MutableObjectData parsedItemData, final MutableObjectData parsedDestructableData,
final MutableObjectData parsedAbilityData, final SimulationRenderController simulationRenderController,
final PathingGrid pathingGrid, final Rectangle entireMapBounds, final Random seededRandom,
final List<Player> playerInfos, final CommandErrorListener commandErrorListener) {
this.gameplayConstants = new CGameplayConstants(miscData);
this.simulationRenderController = simulationRenderController;
this.pathingGrid = pathingGrid;
@ -73,9 +77,11 @@ public class CSimulation {
this.unitData = new CUnitData(this.gameplayConstants, parsedUnitData, this.abilityData,
this.simulationRenderController);
this.destructableData = new CDestructableData(parsedDestructableData, simulationRenderController);
this.itemData = new CItemData(parsedItemData);
this.units = new ArrayList<>();
this.newUnits = new ArrayList<>();
this.destructables = new ArrayList<>();
this.items = new ArrayList<>();
this.projectiles = new ArrayList<>();
this.newProjectiles = new ArrayList<>();
this.handleIdAllocator = new HandleIdAllocator();
@ -155,6 +161,13 @@ public class CSimulation {
return dest;
}
public CItem createItem(final War3ID alias, final float unitX, final float unitY) {
final CItem item = this.itemData.create(this, alias, unitX, unitY, this.handleIdAllocator.createId());
this.handleIdToItem.put(item.getHandleId(), item);
this.items.add(item);
return item;
}
public CUnit createUnit(final War3ID typeId, final int playerIndex, final float x, final float y,
final float facing) {
return this.simulationRenderController.createUnit(this, typeId, playerIndex, x, y, facing);
@ -271,6 +284,10 @@ public class CSimulation {
this.simulationRenderController.spawnDamageSound(damagedDestructable, weaponSound, armorType);
}
public void itemDamageEvent(final CItem damageItem, final String weaponSound, final String armorType) {
this.simulationRenderController.spawnDamageSound(damageItem, weaponSound, armorType);
}
public void unitConstructedEvent(final CUnit constructingUnit, final CUnit constructedStructure) {
this.simulationRenderController.spawnUnitConstructionSound(constructingUnit, constructedStructure);
}
@ -279,7 +296,7 @@ public class CSimulation {
return this.players.get(index);
}
public CommandErrorListener getCommandErrorListener() {
public CommandErrorListener getCommandErrorListener(final int playerIndex) {
return this.commandErrorListener;
}
@ -317,6 +334,14 @@ public class CSimulation {
this.playerHeroes[hero.getPlayerIndex()].add(hero);
}
public void unitPickUpItemEvent(final CUnit cUnit, final CItem item) {
this.simulationRenderController.spawnUIUnitGetItemSound(cUnit, item);
}
public void unitDropItemEvent(final CUnit cUnit, final CItem item) {
this.simulationRenderController.spawnUIUnitDropItemSound(cUnit, item);
}
public List<CUnit> getPlayerHeroes(final int playerIndex) {
return this.playerHeroes[playerIndex];
}
@ -342,6 +367,10 @@ public class CSimulation {
if (destructable != null) {
return destructable;
}
final CItem item = this.handleIdToItem.get(handleId);
if (item != null) {
return item;
}
return null;
}

View File

@ -20,6 +20,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
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;
@ -45,7 +46,6 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbility
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver;
public class CUnit extends CWidget {
private static final Rectangle tempRect = new Rectangle();
private War3ID typeId;
private float facing; // degrees
private float mana;
@ -436,7 +436,7 @@ public class CUnit extends CWidget {
if (ability != null) {
// Allow the ability to response to the order without actually placing itself in
// the queue, nor modifying (interrupting) the queue.
if (!ability.checkBeforeQueue(game, this, order.getOrderId())) {
if (!ability.checkBeforeQueue(game, this, order.getOrderId(), order.getTarget(game))) {
this.stateNotifier.ordersChanged();
return;
}
@ -629,9 +629,15 @@ public class CUnit extends CWidget {
return this.unitType.getImpactZ();
}
public double angleTo(final AbilityTarget target) {
final double dx = target.getX() - getX();
final double dy = target.getY() - getY();
return StrictMath.atan2(dy, dx);
}
public double distance(final AbilityTarget target) {
double dx = Math.abs(target.getX() - getX());
double dy = Math.abs(target.getY() - getY());
double dx = StrictMath.abs(target.getX() - getX());
double dy = StrictMath.abs(target.getY() - getY());
final float thisCollisionSize = this.unitType.getCollisionSize();
float targetCollisionSize;
if (target instanceof CUnit) {
@ -701,17 +707,28 @@ public class CUnit extends CWidget {
}
else {
if ((this.currentBehavior == null) || (this.currentBehavior == this.defaultBehavior)) {
if (!simulation.getPlayer(getPlayerIndex()).hasAlliance(source.getPlayerIndex(),
CAllianceType.PASSIVE)) {
boolean foundMatchingReturnFireAttack = false;
if (!simulation.getPlayer(getPlayerIndex()).hasAlliance(source.getPlayerIndex(), CAllianceType.PASSIVE)
&& !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
for (final CUnitAttack attack : this.getAttacks()) {
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
this.currentBehavior = getAttackBehavior().reset(OrderIds.attack, attack, source, false,
CBehaviorAttackListener.DO_NOTHING);
this.currentBehavior.begin(simulation);
foundMatchingReturnFireAttack = true;
break;
}
}
}
if (!foundMatchingReturnFireAttack && this.unitType.isCanFlee() && !isMovementDisabled()
&& (this.moveBehavior != null)) {
final double angleTo = source.angleTo(this);
final int distanceToFlee = getSpeed();
this.currentBehavior = this.moveBehavior.reset(OrderIds.move,
new AbilityPointTarget((float) (getX() + (distanceToFlee * StrictMath.cos(angleTo))),
(float) (getY() + (distanceToFlee * StrictMath.sin(angleTo)))));
this.currentBehavior.begin(simulation);
}
}
}
}
@ -1194,7 +1211,7 @@ public class CUnit extends CWidget {
}
else {
this.queuedUnitFoodPaid = false;
game.getCommandErrorListener().showNoFoodError();
game.getCommandErrorListener(this.playerIndex).showNoFoodError();
}
}
}
@ -1374,6 +1391,15 @@ public class CUnit extends CWidget {
return null;
}
public CAbilityInventory getInventoryData() {
for (final CAbility ability : this.abilities) {
if (ability instanceof CAbilityInventory) {
return (CAbilityInventory) ability;
}
}
return null;
}
public void setUnitSpecificAttacks(final List<CUnitAttack> unitSpecificAttacks) {
this.unitSpecificAttacks = unitSpecificAttacks;
}
@ -1388,4 +1414,18 @@ public class CUnit extends CWidget {
}
return this.unitType.getAttacks();
}
public void onPickUpItem(final CSimulation game, final CItem item, final boolean playUserUISounds) {
this.stateNotifier.inventoryChanged();
if (playUserUISounds) {
game.unitPickUpItemEvent(this, item);
}
}
public void onDropItem(final CSimulation game, final CItem droppedItem, final boolean playUserUISounds) {
this.stateNotifier.inventoryChanged();
if (playUserUISounds) {
game.unitDropItemEvent(this, droppedItem);
}
}
}

View File

@ -15,6 +15,8 @@ public interface CUnitStateListener {
void heroStatsChanged();
void inventoryChanged();
public static final class CUnitStateNotifier extends SubscriberSetNotifier<CUnitStateListener>
implements CUnitStateListener {
@Override
@ -58,5 +60,12 @@ public interface CUnitStateListener {
listener.heroStatsChanged();
}
}
@Override
public void inventoryChanged() {
for (final CUnitStateListener listener : set) {
listener.inventoryChanged();
}
}
}
}

View File

@ -71,6 +71,7 @@ public class CUnitType {
private final List<War3ID> heroAbilityList;
private final List<String> heroProperNames;
private final int properNamesCount;
private final boolean canFlee;
public CUnitType(final String name, final int life, final int manaInitial, final int manaMaximum, final int speed,
final int defense, final String abilityList, final boolean isBldg, final MovementType movementType,
@ -86,7 +87,8 @@ public class CUnitType {
final List<CUnitTypeRequirement> requirements, final int level, final boolean hero, final int strength,
final float strengthPerLevel, final int agility, final float agilityPerLevel, final int intelligence,
final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute,
final List<War3ID> heroAbilityList, final List<String> heroProperNames, final int properNamesCount) {
final List<War3ID> heroAbilityList, final List<String> heroProperNames, final int properNamesCount,
final boolean canFlee) {
this.name = name;
this.life = life;
this.manaInitial = manaInitial;
@ -136,6 +138,7 @@ public class CUnitType {
this.heroAbilityList = heroAbilityList;
this.heroProperNames = heroProperNames;
this.properNamesCount = properNamesCount;
this.canFlee = canFlee;
}
public String getName() {
@ -333,4 +336,8 @@ public class CUnitType {
public int getProperNamesCount() {
return this.properNamesCount;
}
public boolean isCanFlee() {
return this.canFlee;
}
}

View File

@ -2,11 +2,13 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
import java.util.EnumSet;
import com.badlogic.gdx.math.Rectangle;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public abstract class CWidget implements AbilityTarget {
protected static final Rectangle tempRect = new Rectangle();
private final int handleId;
private float x;
private float y;

View File

@ -4,6 +4,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.CWidget;
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.behaviors.CBehavior;
public interface CAbility extends CAbilityView {
@ -18,7 +19,7 @@ public interface CAbility extends CAbilityView {
void onCancelFromQueue(CSimulation game, CUnit unit, int orderId);
/* return false to not do anything, such as for toggling autocast */
boolean checkBeforeQueue(CSimulation game, CUnit caster, int orderId);
boolean checkBeforeQueue(CSimulation game, CUnit caster, int orderId, AbilityTarget target);
CBehavior begin(CSimulation game, CUnit caster, int orderId, CWidget target);

View File

@ -4,6 +4,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.CWidget;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
@ -64,7 +65,7 @@ public class CAbilityAttack extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -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.CWidget;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
@ -66,7 +67,7 @@ public class CAbilityGeneric extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return false;
}

View File

@ -4,6 +4,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.CWidget;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorFollow;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorHoldPosition;
@ -91,7 +92,7 @@ public class CAbilityMove extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -14,6 +14,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.menu.CAbilityMenu;
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.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
@ -107,7 +108,7 @@ public abstract class AbstractCAbilityBuild extends AbstractCAbility implements
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -6,6 +6,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
@ -33,7 +34,7 @@ public class CAbilityBuildInProgress extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
final CPlayer player = game.getPlayer(caster.getPlayerIndex());
player.refundFor(caster.getUnitType());
caster.setLife(game, 0);

View File

@ -7,6 +7,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorAttackListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
@ -91,7 +92,7 @@ public class CAbilityColdArrows extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
switch (orderId) {
case OrderIds.coldarrows:
case OrderIds.uncoldarrows:

View File

@ -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.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
public abstract class AbstractGenericNoIconAbility extends AbstractCAbility implements GenericNoIconAbility {
private final War3ID alias;
@ -15,7 +16,8 @@ public abstract class AbstractGenericNoIconAbility extends AbstractCAbility impl
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId,
final AbilityTarget target) {
return true;
}

View File

@ -7,6 +7,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
@ -20,7 +21,7 @@ public abstract class AbstractGenericSingleIconActiveAbility extends AbstractCAb
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -12,6 +12,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
@ -77,7 +78,7 @@ public class CAbilityHero extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -0,0 +1,240 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItemType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.inventory.CBehaviorDropItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.inventory.CBehaviorGetItem;
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;
public class CAbilityInventory extends AbstractGenericNoIconAbility {
private final boolean canDropItems;
private final boolean canGetItems;
private final boolean canUseItems;
private final boolean dropItemsOnDeath;
private final CItem[] itemsHeld;
private CBehaviorGetItem behaviorGetItem;
private CBehaviorDropItem behaviorDropItem;
public CAbilityInventory(final int handleId, final War3ID alias, final boolean canDropItems,
final boolean canGetItems, final boolean canUseItems, final boolean dropItemsOnDeath,
final int itemCapacity) {
super(handleId, alias);
this.canDropItems = canDropItems;
this.canGetItems = canGetItems;
this.canUseItems = canUseItems;
this.dropItemsOnDeath = dropItemsOnDeath;
this.itemsHeld = new CItem[itemCapacity];
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorGetItem = new CBehaviorGetItem(unit, this);
this.behaviorDropItem = new CBehaviorDropItem(unit, this);
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId,
final AbilityTarget target) {
if ((orderId >= OrderIds.itemdrag00) && (orderId <= OrderIds.itemdrag05)) {
for (int i = 0; i < this.itemsHeld.length; i++) {
if (this.itemsHeld[i] == target) {
final CItem temp = this.itemsHeld[i];
final int dragDropDestinationIndex = orderId - OrderIds.itemdrag00;
this.itemsHeld[i] = this.itemsHeld[dragDropDestinationIndex];
this.itemsHeld[dragDropDestinationIndex] = temp;
return false;
}
}
}
return super.checkBeforeQueue(game, caster, orderId, target);
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
public int getItemCapacity() {
return this.itemsHeld.length;
}
public CItem getItemInSlot(final int slotIndex) {
if ((slotIndex < 0) || (slotIndex >= this.itemsHeld.length)) {
return null;
}
return this.itemsHeld[slotIndex];
}
public boolean isDropItemsOnDeath() {
return this.dropItemsOnDeath;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return this.behaviorGetItem.reset((CItem) target);
}
public CBehavior beginDropItem(final CSimulation game, final CUnit caster, final int orderId,
final CItem itemToDrop, final AbilityPointTarget target) {
return this.behaviorDropItem.reset(itemToDrop, target);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
// TODO Auto-generated method stub
return null;
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
final AbilityTargetCheckReceiver<CWidget> receiver) {
if (((orderId == OrderIds.getitem) || (orderId == OrderIds.smart)) && !target.isDead()) {
if (target instanceof CItem) {
final CItem targetItem = (CItem) target;
if (!targetItem.isHidden()) {
receiver.targetOk(target);
}
else {
receiver.orderIdNotAccepted();
}
}
else {
receiver.orderIdNotAccepted();
}
}
else {
if ((orderId >= OrderIds.itemdrag00) && (orderId <= OrderIds.itemdrag05)) {
if (target instanceof CItem) {
final int slot = getSlot((CItem) target);
if (slot != -1) {
receiver.targetOk(target);
}
else {
receiver.orderIdNotAccepted();
}
}
else {
receiver.orderIdNotAccepted();
}
}
receiver.orderIdNotAccepted();
}
}
public int getSlot(final CItem target) {
int slot = -1;
for (int i = 0; i < this.itemsHeld.length; i++) {
if (this.itemsHeld[i] == target) {
slot = i;
}
}
return slot;
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
if (orderId == OrderIds.dropitem) {
receiver.orderIdNotAccepted();
}
}
@Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.useOk();
}
/**
* Attempts to give the hero the specified item, returning the item slot to
* which the item is added or -1 if no available slot is found
*
* @param item
* @return
*/
public int giveItem(final CSimulation simulation, final CUnit hero, final CItem item,
final boolean playUserUISounds) {
if ((item != null) && !item.isDead() && !item.isHidden()) {
final CItemType itemType = item.getItemType();
if (itemType.isUseAutomaticallyWhenAcquired()) {
if (itemType.isActivelyUsed()) {
item.setLife(simulation, 0);
// TODO when we give unit ability here, then use ability
}
}
else {
for (int i = 0; i < this.itemsHeld.length; i++) {
if (this.itemsHeld[i] == null) {
this.itemsHeld[i] = item;
item.setHidden(true);
hero.onPickUpItem(simulation, item, true);
return i;
}
}
if (playUserUISounds) {
simulation.getCommandErrorListener(hero.getPlayerIndex()).showInventoryFullError();
}
}
}
return -1;
}
public void dropItem(final CSimulation simulation, final CUnit hero, final int slotIndex, final float x,
final float y, final boolean playUserUISounds) {
final CItem droppedItem = this.itemsHeld[slotIndex];
hero.onDropItem(simulation, droppedItem, true);
this.itemsHeld[slotIndex] = null;
droppedItem.setHidden(false);
droppedItem.setPointAndCheckUnstuck(x, y, simulation);
}
public void dropItem(final CSimulation simulation, final CUnit hero, final CItem itemToDrop, final float x,
final float y, final boolean playUserUISounds) {
boolean foundItem = false;
for (int i = 0; i < this.itemsHeld.length; i++) {
if (this.itemsHeld[i] == itemToDrop) {
this.itemsHeld[i] = null;
foundItem = true;
}
}
if (foundItem) {
hero.onDropItem(simulation, itemToDrop, true);
itemToDrop.setHidden(false);
itemToDrop.setPointAndCheckUnstuck(x, y, simulation);
}
}
}

View File

@ -13,6 +13,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
@ -115,7 +116,7 @@ public final class CAbilityQueue extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -6,6 +6,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
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.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
@ -72,7 +73,7 @@ public class CAbilityRally extends AbstractCAbility {
}
@Override
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) {
return true;
}

View File

@ -0,0 +1,30 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting;
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.CUnit;
public class AbilityTargetItemVisitor implements AbilityTargetVisitor<CItem> {
public static final AbilityTargetItemVisitor INSTANCE = new AbilityTargetItemVisitor();
@Override
public CItem accept(final AbilityPointTarget target) {
return null;
}
@Override
public CItem accept(final CUnit target) {
return null;
}
@Override
public CItem accept(final CDestructable target) {
return null;
}
@Override
public CItem accept(final CItem target) {
return target;
}
}

View File

@ -24,7 +24,7 @@ public class AbilityTargetStillAliveVisitor implements AbilityTargetVisitor<Bool
@Override
public Boolean accept(final CItem target) {
return !target.isDead();
return !target.isDead() && !target.isHidden();
}
}

View File

@ -0,0 +1,42 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl;
import java.util.EnumSet;
import java.util.List;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeInventoryLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionInventory extends AbstractCAbilityTypeDefinition<CAbilityTypeInventoryLevelData>
implements CAbilityTypeDefinition {
protected static final War3ID ITEM_CAPACITY = War3ID.fromString("inv1");
protected static final War3ID DROP_ITEMS_ON_DEATH = War3ID.fromString("inv2");
protected static final War3ID CAN_USE_ITEMS = War3ID.fromString("inv3");
protected static final War3ID CAN_GET_ITEMS = War3ID.fromString("inv4");
protected static final War3ID CAN_DROP_ITEMS = War3ID.fromString("inv5");
@Override
protected CAbilityTypeInventoryLevelData createLevelData(final MutableGameObject abilityEditorData,
final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
final int itemCapacity = abilityEditorData.getFieldAsInteger(ITEM_CAPACITY, level);
final boolean dropItemsOnDeath = abilityEditorData.getFieldAsBoolean(DROP_ITEMS_ON_DEATH, level);
final boolean canUseItems = abilityEditorData.getFieldAsBoolean(CAN_USE_ITEMS, level);
final boolean canGetItems = abilityEditorData.getFieldAsBoolean(CAN_GET_ITEMS, level);
final boolean canDropItems = abilityEditorData.getFieldAsBoolean(CAN_DROP_ITEMS, level);
return new CAbilityTypeInventoryLevelData(targetsAllowedAtLevel, canDropItems, canGetItems, canUseItems,
dropItemsOnDeath, itemCapacity);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeInventoryLevelData> levelData) {
return new CAbilityTypeInventory(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,24 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
public class CAbilityTypeInventory extends CAbilityType<CAbilityTypeInventoryLevelData> {
public CAbilityTypeInventory(final War3ID alias, final War3ID code,
final List<CAbilityTypeInventoryLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeInventoryLevelData levelData = getLevelData(0);
return new CAbilityInventory(handleId, getAlias(), levelData.isCanDropItems(), levelData.isCanGetItems(),
levelData.isCanUseItems(), levelData.isDropItemsOnDeath(), levelData.getItemCapacity());
}
}

View File

@ -0,0 +1,47 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeInventoryLevelData extends CAbilityTypeLevelData {
private final boolean canDropItems;
private final boolean canGetItems;
private final boolean canUseItems;
private final boolean dropItemsOnDeath;
private final int itemCapacity;
public CAbilityTypeInventoryLevelData(final EnumSet<CTargetType> targetsAllowed, final boolean canDropItems,
final boolean canGetItems, final boolean canUseItems, final boolean dropItemsOnDeath,
final int itemCapacity) {
super(targetsAllowed);
this.canDropItems = canDropItems;
this.canGetItems = canGetItems;
this.canUseItems = canUseItems;
this.dropItemsOnDeath = dropItemsOnDeath;
this.itemCapacity = itemCapacity;
}
public boolean isCanDropItems() {
return this.canDropItems;
}
public boolean isCanGetItems() {
return this.canGetItems;
}
public boolean isCanUseItems() {
return this.canUseItems;
}
public boolean isDropItemsOnDeath() {
return this.dropItemsOnDeath;
}
public int getItemCapacity() {
return this.itemCapacity;
}
}

View File

@ -61,9 +61,10 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
buildLocationObstructed = true;
}
}
final int playerIndex = this.unit.getPlayerIndex();
if (!buildLocationObstructed) {
final CUnit constructedStructure = simulation.createUnit(this.orderId, this.unit.getPlayerIndex(),
this.target.getX(), this.target.getY(), simulation.getGameplayConstants().getBuildingAngle());
final CUnit constructedStructure = simulation.createUnit(this.orderId, playerIndex, this.target.getX(),
this.target.getY(), simulation.getGameplayConstants().getBuildingAngle());
constructedStructure.setConstructing(true);
constructedStructure.setWorkerInside(this.unit);
constructedStructure.setLife(simulation,
@ -80,9 +81,9 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
simulation.unitConstructedEvent(this.unit, constructedStructure);
}
else {
final CPlayer player = simulation.getPlayer(this.unit.getPlayerIndex());
final CPlayer player = simulation.getPlayer(playerIndex);
refund(player, unitTypeToCreate);
simulation.getCommandErrorListener().showCantPlaceError();
simulation.getCommandErrorListener(playerIndex).showCantPlaceError();
}
}
return this.unit.pollNextOrderBehavior(simulation);

View File

@ -77,9 +77,10 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior {
buildLocationObstructed = true;
}
}
final int playerIndex = this.unit.getPlayerIndex();
if (!buildLocationObstructed) {
final CUnit constructedStructure = simulation.createUnit(this.orderId, this.unit.getPlayerIndex(),
this.target.getX(), this.target.getY(), simulation.getGameplayConstants().getBuildingAngle());
final CUnit constructedStructure = simulation.createUnit(this.orderId, playerIndex, this.target.getX(),
this.target.getY(), simulation.getGameplayConstants().getBuildingAngle());
constructedStructure.setConstructing(true);
constructedStructure.setLife(simulation,
constructedStructure.getMaximumLife() * WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE);
@ -100,9 +101,9 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior {
this.doneTick = simulation.getGameTurnTick() + delayAnimationTicks;
}
else {
final CPlayer player = simulation.getPlayer(this.unit.getPlayerIndex());
final CPlayer player = simulation.getPlayer(playerIndex);
refund(player, unitTypeToCreate);
simulation.getCommandErrorListener().showCantPlaceError();
simulation.getCommandErrorListener(playerIndex).showCantPlaceError();
return this.unit.pollNextOrderBehavior(simulation);
}
}

View File

@ -0,0 +1,71 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.inventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CBehaviorDropItem extends CAbstractRangedBehavior {
private final CAbilityInventory inventory;
private CItem targetItem;
public CBehaviorDropItem(final CUnit unit, final CAbilityInventory inventory) {
super(unit);
this.inventory = inventory;
}
public CBehaviorDropItem reset(final CItem targetItem, final AbilityPointTarget targetPoint) {
innerReset(targetPoint);
this.targetItem = targetItem;
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
return this.unit.canReach(this.target, simulation.getGameplayConstants().getDropItemRange());
}
@Override
public void endMove(final CSimulation game, final boolean interrupted) {
}
@Override
public void begin(final CSimulation game) {
}
@Override
public void end(final CSimulation game, final boolean interrupted) {
}
@Override
public int getHighlightOrderId() {
return OrderIds.dropitem;
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinRange) {
this.inventory.dropItem(simulation, this.unit, this.targetItem, this.target.getX(), this.target.getY(), true);
return this.unit.pollNextOrderBehavior(simulation);
}
@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);
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
}

View File

@ -0,0 +1,70 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.inventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetItemVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CBehaviorGetItem extends CAbstractRangedBehavior {
private final CAbilityInventory inventory;
public CBehaviorGetItem(final CUnit unit, final CAbilityInventory inventory) {
super(unit);
this.inventory = inventory;
}
public CBehaviorGetItem reset(final CItem targetItem) {
innerReset(targetItem);
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
return this.unit.canReach(this.target, simulation.getGameplayConstants().getPickupItemRange());
}
@Override
public void endMove(final CSimulation game, final boolean interrupted) {
}
@Override
public void begin(final CSimulation game) {
}
@Override
public void end(final CSimulation game, final boolean interrupted) {
}
@Override
public int getHighlightOrderId() {
return OrderIds.getitem;
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinRange) {
final CItem targetItem = this.target.visit(AbilityTargetItemVisitor.INSTANCE);
this.inventory.giveItem(simulation, this.unit, targetItem, true);
return this.unit.pollNextOrderBehavior(simulation);
}
@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);
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
}

View File

@ -14,6 +14,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.def
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionReturnResources;
public class CAbilityData {
@ -34,6 +35,7 @@ public class CAbilityData {
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Artn"), new CAbilityTypeDefinitionReturnResources());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Ahar"), new CAbilityTypeDefinitionHarvest());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("ANcl"), new CAbilityTypeDefinitionChannelTest());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("AInv"), new CAbilityTypeDefinitionInventory());
}
public CAbilityType<?> getAbilityType(final War3ID alias) {

View File

@ -1,8 +1,117 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.etheller.warsmash.units.manager.MutableObjectData;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItemType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
public class CItemData {
private static final War3ID ABILITY_LIST = War3ID.fromString("iabi");
private static final War3ID COOLDOWN_GROUP = War3ID.fromString("icid");
private static final War3ID IGNORE_COOLDOWN = War3ID.fromString("iicd");
private static final War3ID NUMBER_OF_CHARGES = War3ID.fromString("iuse");
private static final War3ID ACTIVELY_USED = War3ID.fromString("iusa");
private static final War3ID PERISHABLE = War3ID.fromString("iper");
private static final War3ID USE_AUTOMATICALLY_WHEN_ACQUIRED = War3ID.fromString("ipow");
private static final War3ID GOLD_COST = War3ID.fromString("igol");
private static final War3ID LUMBER_COST = War3ID.fromString("ilum");
private static final War3ID STOCK_MAX = War3ID.fromString("isto");
private static final War3ID STOCK_REPLENISH_INTERVAL = War3ID.fromString("istr");
private static final War3ID STOCK_START_DELAY = War3ID.fromString("isst");
private static final War3ID HIT_POINTS = War3ID.fromString("ihtp");
private static final War3ID ARMOR_TYPE = War3ID.fromString("iarm");
private static final War3ID LEVEL = War3ID.fromString("ilev");
private static final War3ID LEVEL_UNCLASSIFIED = War3ID.fromString("ilvo");
private static final War3ID PRIORITY = War3ID.fromString("ipri");
private static final War3ID SELLABLE = War3ID.fromString("isel");
private static final War3ID PAWNABLE = War3ID.fromString("ipaw");
private static final War3ID DROPPED_WHEN_CARRIER_DIES = War3ID.fromString("idrp");
private static final War3ID CAN_BE_DROPPED = War3ID.fromString("idro");
private static final War3ID VALID_TARGET_FOR_TRANSFORMATION = War3ID.fromString("imor");
private static final War3ID INCLUDE_AS_RANDOM_CHOICE = War3ID.fromString("iprn");
private final Map<War3ID, CItemType> itemIdToItemType = new HashMap<>();
private final MutableObjectData itemData;
public CItemData(final MutableObjectData itemData) {
this.itemData = itemData;
}
public CItem create(final CSimulation simulation, final War3ID typeId, final float x, final float y,
final int handleId) {
final MutableGameObject itemType = this.itemData.get(typeId);
final CItemType itemTypeInstance = getItemTypeInstance(typeId, itemType);
return new CItem(handleId, x, y, itemTypeInstance.getHitPoints(), typeId, itemTypeInstance);
}
private CItemType getItemTypeInstance(final War3ID typeId, final MutableGameObject itemType) {
CItemType itemTypeInstance = this.itemIdToItemType.get(typeId);
if (itemTypeInstance == null) {
final String abilityListString = itemType.getFieldAsString(ABILITY_LIST, 0);
final String[] abilityListStringItems = abilityListString.split(",");
final List<War3ID> abilityList = new ArrayList<>();
for (final String abilityListStringItem : abilityListStringItems) {
if (abilityListStringItem.length() == 4) {
abilityList.add(War3ID.fromString(abilityListStringItem));
}
}
final War3ID cooldownGroup;
final String cooldownGroupString = itemType.getFieldAsString(COOLDOWN_GROUP, 0);
if ((cooldownGroupString != null) && (cooldownGroupString.length() == 4)) {
cooldownGroup = War3ID.fromString(cooldownGroupString);
}
else {
cooldownGroup = null;
}
final boolean ignoreCooldown = itemType.getFieldAsBoolean(IGNORE_COOLDOWN, 0);
final int numberOfCharges = itemType.getFieldAsInteger(NUMBER_OF_CHARGES, 0);
final boolean activelyUsed = itemType.getFieldAsBoolean(ACTIVELY_USED, 0);
final boolean perishable = itemType.getFieldAsBoolean(PERISHABLE, 0);
final boolean useAutomaticallyWhenAcquired = itemType.getFieldAsBoolean(USE_AUTOMATICALLY_WHEN_ACQUIRED, 0);
final int goldCost = itemType.getFieldAsInteger(GOLD_COST, 0);
final int lumberCost = itemType.getFieldAsInteger(LUMBER_COST, 0);
final int stockMax = itemType.getFieldAsInteger(STOCK_MAX, 0);
final int stockReplenishInterval = itemType.getFieldAsInteger(STOCK_REPLENISH_INTERVAL, 0);
final int stockStartDelay = itemType.getFieldAsInteger(STOCK_START_DELAY, 0);
final int hitPoints = itemType.getFieldAsInteger(HIT_POINTS, 0);
final String armorType = itemType.getFieldAsString(ARMOR_TYPE, 0);
final int level = itemType.getFieldAsInteger(LEVEL, 0);
final int levelUnclassified = itemType.getFieldAsInteger(LEVEL_UNCLASSIFIED, 0);
final int priority = itemType.getFieldAsInteger(PRIORITY, 0);
final boolean sellable = itemType.getFieldAsBoolean(SELLABLE, 0);
final boolean pawnable = itemType.getFieldAsBoolean(PAWNABLE, 0);
final boolean droppedWhenCarrierDies = itemType.getFieldAsBoolean(DROPPED_WHEN_CARRIER_DIES, 0);
final boolean canBeDropped = itemType.getFieldAsBoolean(CAN_BE_DROPPED, 0);
final boolean validTargetForTransformation = itemType.getFieldAsBoolean(VALID_TARGET_FOR_TRANSFORMATION, 0);
final boolean includeAsRandomChoice = itemType.getFieldAsBoolean(INCLUDE_AS_RANDOM_CHOICE, 0);
itemTypeInstance = new CItemType(abilityList, cooldownGroup, ignoreCooldown, numberOfCharges, activelyUsed,
perishable, useAutomaticallyWhenAcquired, goldCost, lumberCost, stockMax, stockReplenishInterval,
stockStartDelay, hitPoints, armorType, level, levelUnclassified, priority, sellable, pawnable,
droppedWhenCarrierDies, canBeDropped, validTargetForTransformation, includeAsRandomChoice);
this.itemIdToItemType.put(typeId, itemTypeInstance);
}
return itemTypeInstance;
}
}

View File

@ -168,6 +168,8 @@ public class CUnitData {
private static final War3ID INT_PLUS = War3ID.fromString("uinp");
private static final War3ID PRIMARY_ATTRIBUTE = War3ID.fromString("upra");
private static final War3ID CAN_FLEE = War3ID.fromString("ufle");
private final CGameplayConstants gameplayConstants;
private final MutableObjectData unitData;
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
@ -279,6 +281,8 @@ public class CUnitData {
final float propWindow = unitType.getFieldAsFloat(PROPULSION_WINDOW, 0);
final float turnRate = unitType.getFieldAsFloat(TURN_RATE, 0);
final boolean canFlee = unitType.getFieldAsBoolean(CAN_FLEE, 0);
final float strPlus = unitType.getFieldAsFloat(STR_PLUS, 0);
final float agiPlus = unitType.getFieldAsFloat(AGI_PLUS, 0);
final float intPlus = unitType.getFieldAsFloat(INT_PLUS, 0);
@ -533,7 +537,7 @@ public class CUnitData {
minimumAttackRange, structuresBuilt, unitsTrained, researchesAvailable, unitRace, goldCost,
lumberCost, foodUsed, foodMade, buildTime, preventedPathingTypes, requiredPathingTypes, propWindow,
turnRate, requirements, unitLevel, hero, strength, strPlus, agility, agiPlus, intelligence, intPlus,
primaryAttribute, heroAbilityList, heroProperNames, properNamesCount);
primaryAttribute, heroAbilityList, heroProperNames, properNamesCount, canFlee);
this.unitIdToUnitType.put(typeId, unitTypeInstance);
}
return unitTypeInstance;

View File

@ -0,0 +1,111 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.StringMsgTargetCheckReceiver;
public class COrderDropItemAtPoint implements COrder {
private final int abilityHandleId;
private final int orderId;
private final int itemHandleId;
private final AbilityPointTarget target;
private final boolean queued;
public COrderDropItemAtPoint(final int abilityHandleId, final int orderId, final int itemHandleId,
final AbilityPointTarget target, final boolean queued) {
this.abilityHandleId = abilityHandleId;
this.orderId = orderId;
this.itemHandleId = itemHandleId;
this.target = target;
this.queued = queued;
}
@Override
public int getAbilityHandleId() {
return this.abilityHandleId;
}
@Override
public int getOrderId() {
return this.orderId;
}
@Override
public AbilityPointTarget getTarget(final CSimulation game) {
return this.target;
}
@Override
public boolean isQueued() {
return this.queued;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster) {
final CAbilityInventory ability = (CAbilityInventory) game.getAbility(this.abilityHandleId);
ability.checkCanUse(game, caster, this.orderId, this.abilityActivationReceiver.reset());
if (this.abilityActivationReceiver.isUseOk()) {
final StringMsgTargetCheckReceiver<AbilityPointTarget> targetReceiver = (StringMsgTargetCheckReceiver<AbilityPointTarget>) targetCheckReceiver;
final CItem itemToDrop = (CItem) game.getWidget(this.itemHandleId);
return ability.beginDropItem(game, caster, this.orderId, itemToDrop, this.target);
}
else {
game.getCommandErrorListener(caster.getPlayerIndex())
.showCommandError(this.abilityActivationReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + this.abilityHandleId;
result = (prime * result) + this.itemHandleId;
result = (prime * result) + this.orderId;
result = (prime * result) + (this.queued ? 1231 : 1237);
result = (prime * result) + ((this.target == null) ? 0 : this.target.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final COrderDropItemAtPoint other = (COrderDropItemAtPoint) obj;
if (this.abilityHandleId != other.abilityHandleId) {
return false;
}
if (this.itemHandleId != other.itemHandleId) {
return false;
}
if (this.orderId != other.orderId) {
return false;
}
if (this.queued != other.queued) {
return false;
}
if (this.target == null) {
if (other.target != null) {
return false;
}
}
else if (!this.target.equals(other.target)) {
return false;
}
return true;
}
}

View File

@ -44,12 +44,13 @@ public class COrderNoTarget implements COrder {
return ability.beginNoTarget(game, caster, this.orderId);
}
else {
game.getCommandErrorListener().showCommandError(targetReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex()).showCommandError(targetReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}
else {
game.getCommandErrorListener().showCommandError(this.abilityActivationReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex())
.showCommandError(this.abilityActivationReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}

View File

@ -52,12 +52,13 @@ public class COrderTargetPoint implements COrder {
return ability.begin(game, caster, this.orderId, this.target);
}
else {
game.getCommandErrorListener().showCommandError(targetReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex()).showCommandError(targetReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}
else {
game.getCommandErrorListener().showCommandError(this.abilityActivationReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex())
.showCommandError(this.abilityActivationReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}

View File

@ -55,12 +55,13 @@ public class COrderTargetWidget implements COrder {
return ability.begin(game, caster, this.orderId, targetReceiver.getTarget());
}
else {
game.getCommandErrorListener().showCommandError(targetReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex()).showCommandError(targetReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}
else {
game.getCommandErrorListener().showCommandError(this.abilityActivationReceiver.getMessage());
game.getCommandErrorListener(caster.getPlayerIndex())
.showCommandError(this.abilityActivationReceiver.getMessage());
return caster.pollNextOrderBehavior(game);
}
}

View File

@ -4,6 +4,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.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorHoldPosition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderDropItemAtPoint;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderNoTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderTargetPoint;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderTargetWidget;
@ -26,6 +27,14 @@ public class CPlayerUnitOrderExecutor implements CPlayerUnitOrderListener {
unit.order(this.game, new COrderTargetWidget(abilityHandleId, orderId, targetHandleId, queue), queue);
}
@Override
public void issueDropItemAtPointOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final int targetHandleId, final float x, final float y, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
unit.order(this.game, new COrderDropItemAtPoint(abilityHandleId, orderId, targetHandleId,
new AbilityPointTarget(x, y), queue), queue);
}
@Override
public void issuePointOrder(final int unitHandleId, final int abilityHandleId, final int orderId, final float x,
final float y, final boolean queue) {

View File

@ -5,8 +5,9 @@ public interface CPlayerUnitOrderListener {
void 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);
// Below: used for "DROP ITEM AT POINT"
void issueDropItemAtPointOrder(int unitHandleId, int abilityHandleId, int orderId, int targetHandleId, float x,
float y, final boolean queue);
void issueImmediateOrder(int unitHandleId, int abilityHandleId, int orderId, boolean queue);

View File

@ -4,6 +4,7 @@ import java.awt.image.BufferedImage;
import com.etheller.warsmash.util.War3ID;
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;
@ -50,4 +51,8 @@ public interface SimulationRenderController {
void spawnGainResourceTextTag(CUnit gainingUnit, ResourceType resourceType, int amount);
void spawnEffectOnUnit(CUnit unit, String effectPath);
void spawnUIUnitGetItemSound(CUnit cUnit, CItem item);
void spawnUIUnitDropItemSound(CUnit cUnit, CItem item);
}

View File

@ -12,7 +12,6 @@ import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
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.ClickableActionFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandListener;
@ -22,7 +21,8 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
private TextureFrame activeHighlightFrame;
private SpriteFrame cooldownFrame;
private SpriteFrame autocastFrame;
private CommandButton commandButton;
private float defaultWidth;
private float defaultHeight;
private int abilityHandleId;
private int orderId;
private int autoCastOrderId;
@ -49,33 +49,16 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
this.autocastFrame = autocastFrame;
}
public void setCommandButton(final CommandButton commandButton) {
this.commandButton = commandButton;
if (commandButton == null) {
this.iconFrame.setVisible(false);
public void clear() {
this.iconFrame.setVisible(false);
if (this.activeHighlightFrame != null) {
this.activeHighlightFrame.setVisible(false);
this.cooldownFrame.setVisible(false);
}
this.cooldownFrame.setVisible(false);
if (this.autocastFrame != null) {
this.autocastFrame.setVisible(false);
setVisible(false);
}
else {
if (commandButton.isEnabled()) {
this.iconFrame.setTexture(commandButton.getIcon());
}
else {
this.iconFrame.setTexture(commandButton.getDisabledIcon());
}
if (commandButton.getCooldownRemaining() <= 0) {
this.cooldownFrame.setVisible(false);
}
else {
this.cooldownFrame.setVisible(true);
this.cooldownFrame.setSequence(PrimaryTag.STAND);
this.cooldownFrame.setAnimationSpeed(commandButton.getCooldown());
this.cooldownFrame
.setFrameByRatio(1 - (commandButton.getCooldownRemaining() / commandButton.getCooldown()));
}
}
setVisible(false);
}
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId,
@ -84,19 +67,23 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
this.menuButton = menuButton;
setVisible(true);
this.iconFrame.setVisible(true);
this.activeHighlightFrame.setVisible(active);
if (this.activeHighlightFrame != null) {
this.activeHighlightFrame.setVisible(active);
}
this.cooldownFrame.setVisible(false);
this.autocastFrame.setVisible(autoCastOrderId != 0);
if (autoCastOrderId != 0) {
if (this.autoCastActive != autoCastActive) {
if (autoCastActive) {
this.autocastFrame.setSequence(PrimaryTag.STAND);
}
else {
this.autocastFrame.setSequence(-1);
if (this.autocastFrame != null) {
this.autocastFrame.setVisible(autoCastOrderId != 0);
if (autoCastOrderId != 0) {
if (this.autoCastActive != autoCastActive) {
if (autoCastActive) {
this.autocastFrame.setSequence(PrimaryTag.STAND);
}
else {
this.autocastFrame.setSequence(-1);
}
}
this.autoCastActive = autoCastActive;
}
this.autoCastActive = autoCastActive;
}
this.iconFrame.setTexture(texture);
this.abilityHandleId = abilityHandleId;
@ -112,23 +99,32 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
this.iconFrame.positionBounds(gameUI, viewport);
this.activeHighlightFrame.positionBounds(gameUI, viewport);
if (this.activeHighlightFrame != null) {
this.activeHighlightFrame.positionBounds(gameUI, viewport);
}
this.cooldownFrame.positionBounds(gameUI, viewport);
this.autocastFrame.positionBounds(gameUI, viewport);
if (this.autocastFrame != null) {
this.autocastFrame.positionBounds(gameUI, viewport);
}
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
this.iconFrame.render(batch, baseFont, glyphLayout);
this.activeHighlightFrame.render(batch, baseFont, glyphLayout);
if (this.activeHighlightFrame != null) {
this.activeHighlightFrame.render(batch, baseFont, glyphLayout);
}
this.cooldownFrame.render(batch, baseFont, glyphLayout);
this.autocastFrame.render(batch, baseFont, glyphLayout);
if (this.autocastFrame != null) {
this.autocastFrame.render(batch, baseFont, glyphLayout);
}
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
if ((this.orderId != 0) || this.menuButton) {
if (((button == Input.Buttons.LEFT) && (this.orderId != 0))
|| ((button == Input.Buttons.RIGHT) && (this.autoCastOrderId != 0)) || this.menuButton) {
return this;
}
}
@ -154,28 +150,40 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
this.commandCardCommandListener.openMenu(this.orderId);
}
else {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.orderId, false);
this.commandCardCommandListener.onClick(this.abilityHandleId, this.orderId, false);
}
}
else if (button == Input.Buttons.RIGHT) {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.autoCastOrderId, true);
this.commandCardCommandListener.onClick(this.abilityHandleId, this.autoCastOrderId, true);
}
}
@Override
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
this.iconFrame.setWidth(GameUI.convertX(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH));
this.iconFrame.setHeight(GameUI.convertY(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH));
this.iconFrame.setWidth(this.defaultWidth * 0.95f);
this.iconFrame.setHeight(this.defaultHeight * 0.95f);
positionBounds(gameUI, uiViewport);
}
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
this.iconFrame.setWidth(GameUI.convertX(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_WIDTH));
this.iconFrame.setHeight(GameUI.convertY(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_WIDTH));
this.iconFrame.setWidth(this.defaultWidth);
this.iconFrame.setHeight(this.defaultHeight);
positionBounds(gameUI, uiViewport);
}
@Override
public void setWidth(final float width) {
this.defaultWidth = width;
super.setWidth(width);
}
@Override
public void setHeight(final float height) {
this.defaultHeight = height;
super.setHeight(height);
}
@Override
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
}

View File

@ -79,10 +79,12 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.ItemUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CGameplayConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItemType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit.QueueItemType;
@ -110,6 +112,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.G
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CPrimaryAttribute;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
@ -147,9 +150,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
- WORLD_FRAME_MESSAGE_FADEOUT_MILLIS;
private static final String BUILDING_PATHING_PREVIEW_KEY = "buildingPathingPreview";
public static final float DEFAULT_COMMAND_CARD_ICON_WIDTH = 0.039f;
public static final float DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH = 0.037f;
public static final float DEFAULT_INVENTORY_ICON_WIDTH = 0.03125f;
private static final int COMMAND_CARD_WIDTH = 4;
private static final int COMMAND_CARD_HEIGHT = 3;
private static final int INVENTORY_WIDTH = 2;
private static final int INVENTORY_HEIGHT = 3;
private static final Vector2 screenCoordsVector = new Vector2();
private static final Vector3 clickLocationTemp = new Vector3();
@ -217,6 +222,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private UIFrame heroInfoPanel;
private SimpleFrame inventoryBarFrame;
private StringFrame inventoryTitleFrame;
private final CommandCardIcon[][] inventoryIcons = new CommandCardIcon[INVENTORY_HEIGHT][INVENTORY_WIDTH];
private Texture consoleInventoryNoCapacityTexture;
private final CommandCardIcon[][] commandCard = new CommandCardIcon[COMMAND_CARD_HEIGHT][COMMAND_CARD_WIDTH];
private RenderUnit selectedUnit;
@ -274,6 +284,10 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private StringFrame intelligenceValue;
private SimpleFrame smashHeroInfoPanelWrapper;
private final StringBuilder recycleStringBuilder = new StringBuilder();
private CItem draggingItem;
private final ItemCommandCardCommandListener itemCommandCardCommandListener;
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene,
final Scene portraitScene, final CameraPreset[] cameraPresets, final CameraRates cameraRates,
final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener,
@ -303,6 +317,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.cursorTargetSetupVisitor = new CursorTargetSetupVisitor();
this.localPlayer.addStateListener(this);
this.itemCommandCardCommandListener = new ItemCommandCardCommandListener();
}
private MeleeUIMinimap createMinimap(final War3MapViewer war3MapViewer) {
@ -576,6 +592,57 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.agilityValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroAgilityValue", 0);
this.intelligenceValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroIntellectValue", 0);
this.inventoryBarFrame = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashSimpleInventoryBar",
this.rootFrame, 0);
this.inventoryBarFrame.setWidth(GameUI.convertX(this.uiViewport, 0.064f));
this.inventoryBarFrame.setHeight(GameUI.convertY(this.uiViewport, 0.115f));
this.inventoryBarFrame.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, this.consoleUI, FramePoint.BOTTOMLEFT,
GameUI.convertX(this.uiViewport, 0.496f), GameUI.convertY(this.uiViewport, 0.0f)));
int commandButtonIndex = 0;
for (int j = 0; j < INVENTORY_HEIGHT; j++) {
for (int i = 0; i < INVENTORY_WIDTH; i++) {
final CommandCardIcon commandCardIcon = new CommandCardIcon(
"SmashInventoryButton_" + commandButtonIndex, this.inventoryBarFrame,
this.itemCommandCardCommandListener);
this.inventoryBarFrame.add(commandCardIcon);
final TextureFrame iconFrame = new TextureFrame(
"SmashInventoryButton_" + (commandButtonIndex) + "_Icon", this.rootFrame, false, null);
final SpriteFrame cooldownFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
"SmashInventoryButton_" + (commandButtonIndex) + "_Cooldown", this.rootFrame, "", 0);
commandCardIcon.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.inventoryBarFrame,
FramePoint.TOPRIGHT, GameUI.convertX(this.uiViewport, 0.0187f + (0.04f * i)),
GameUI.convertY(this.uiViewport, -0.0021f - (0.03815f * j))));
commandCardIcon.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_INVENTORY_ICON_WIDTH));
commandCardIcon.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_INVENTORY_ICON_WIDTH));
iconFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
iconFrame.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_INVENTORY_ICON_WIDTH));
iconFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_INVENTORY_ICON_WIDTH));
iconFrame.setTexture(ImageUtils.DEFAULT_ICON_PATH, this.rootFrame);
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, DEFAULT_INVENTORY_ICON_WIDTH));
cooldownFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_INVENTORY_ICON_WIDTH));
commandCardIcon.set(iconFrame, null, cooldownFrame, null);
this.inventoryIcons[j][i] = commandCardIcon;
commandCardIcon.clear();
commandButtonIndex++;
}
}
this.inventoryTitleFrame = this.rootFrame.createStringFrame("SmashInventoryText", this.inventoryBarFrame,
new Color(0xFCDE12FF), TextJustify.LEFT, TextJustify.MIDDLE, 0.0109f);
this.rootFrame.setText(this.inventoryTitleFrame, this.rootFrame.getTemplates().getDecoratedString("INVENTORY"));
this.inventoryTitleFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.inventoryBarFrame, FramePoint.TOPRIGHT,
GameUI.convertX(this.uiViewport, 0.029f), GameUI.convertY(this.uiViewport, 0.0165625f)));
this.inventoryTitleFrame.setWidth(GameUI.convertX(this.uiViewport, 0.076875f));
this.inventoryTitleFrame.setHeight(GameUI.convertX(this.uiViewport, 0.01125f));
this.inventoryTitleFrame.setFontShadowColor(new Color(0f, 0f, 0f, 0.9f));
this.inventoryTitleFrame.setFontShadowOffsetX(GameUI.convertX(this.uiViewport, 0.001f));
this.inventoryTitleFrame.setFontShadowOffsetY(GameUI.convertY(this.uiViewport, -0.001f));
this.consoleInventoryNoCapacityTexture = ImageUtils.getAnyExtensionTexture(this.dataSource,
this.rootFrame.getSkinField("ConsoleInventoryNoCapacity"));
this.inventoryCover = this.rootFrame.createSimpleFrame("SmashConsoleInventoryCover", this.rootFrame, 0);
final Element fontHeights = this.war3MapViewer.miscData.get("FontHeights");
@ -592,7 +659,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.errorMessageFrame.setFontShadowOffsetY(GameUI.convertY(this.uiViewport, -0.001f));
this.errorMessageFrame.setVisible(false);
int commandButtonIndex = 0;
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,
@ -631,7 +698,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
commandCardIcon.set(iconFrame, activeHighlightFrame, cooldownFrame, autocastFrame);
this.commandCard[j][i] = commandCardIcon;
commandCardIcon.setCommandButton(null);
commandCardIcon.clear();
commandButtonIndex++;
}
}
@ -713,7 +780,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
@Override
public void startUsingAbility(final int abilityHandleId, final int orderId, final boolean rightClick) {
public void onClick(final int abilityHandleId, final int orderId, final boolean rightClick) {
// TODO not O(N)
if (this.selectedUnit == null) {
return;
@ -776,8 +843,9 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
public void showCommandError(final String message) {
this.rootFrame.setText(this.errorMessageFrame, message);
this.errorMessageFrame.setVisible(true);
this.lastErrorMessageExpireTime = TimeUtils.millis() + WORLD_FRAME_MESSAGE_EXPIRE_MILLIS;
this.lastErrorMessageFadeTime = TimeUtils.millis() + WORLD_FRAME_MESSAGE_FADEOUT_MILLIS;
final long millis = TimeUtils.millis();
this.lastErrorMessageExpireTime = millis + WORLD_FRAME_MESSAGE_EXPIRE_MILLIS;
this.lastErrorMessageFadeTime = millis + WORLD_FRAME_MESSAGE_FADEOUT_MILLIS;
this.errorMessageFrame.setAlpha(1.0f);
}
@ -795,6 +863,13 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
.play(this.uiScene.audioContext, 0, 0, 0);
}
@Override
public void showInventoryFullError() {
showCommandError(this.rootFrame.getErrorString("InventoryFull"));
this.war3MapViewer.getUiSounds().getSound(this.rootFrame.getSkinField("InventoryFullSound"))
.play(this.uiScene.audioContext, 0, 0, 0);
}
public void update(final float deltaTime) {
this.portrait.update();
@ -824,7 +899,12 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.cursorFrame.setFramePointY(FramePoint.BOTTOM, screenCoordsVector.y);
if (this.activeCommand != null) {
this.activeCommand.visit(this.cursorTargetSetupVisitor.reset(baseMouseX, baseMouseY));
if (this.draggingItem != null) {
this.cursorFrame.setSequence("HoldItem");
}
else {
this.activeCommand.visit(this.cursorTargetSetupVisitor.reset(baseMouseX, baseMouseY));
}
}
else {
if (this.cursorModelInstance != null) {
@ -1349,6 +1429,52 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
}
public void setDraggingItem(final CItem itemInSlot) {
this.draggingItem = itemInSlot;
if (itemInSlot != null) {
final String iconPath = this.war3MapViewer.getAbilityDataUI().getItemUI(itemInSlot.getTypeId())
.getItemIconPathForDragging();
this.cursorFrame.setReplaceableId(21, this.war3MapViewer.blp(iconPath));
int index = 0;
final CAbilityInventory inventory = this.selectedUnit.getSimulationUnit().getInventoryData();
for (int i = 0; i < INVENTORY_HEIGHT; i++) {
for (int j = 0; j < INVENTORY_WIDTH; j++) {
final CommandCardIcon inventoryIcon = this.inventoryIcons[i][j];
final CItem item = inventory.getItemInSlot(index);
if (item == null) {
if (index < inventory.getItemCapacity()) {
inventoryIcon.setCommandButtonData(null, 0, 0, index + 1, true, false, false, null, null, 0,
0, 0);
}
}
index++;
}
}
}
else {
if (this.selectedUnit != null) {
final CAbilityInventory inventory = this.selectedUnit.getSimulationUnit().getInventoryData();
if (inventory != null) {
int index = 0;
for (int i = 0; i < INVENTORY_HEIGHT; i++) {
for (int j = 0; j < INVENTORY_WIDTH; j++) {
final CommandCardIcon inventoryIcon = this.inventoryIcons[i][j];
final CItem item = inventory.getItemInSlot(index);
if (item == null) {
if (index < inventory.getItemCapacity()) {
inventoryIcon.clear();
}
}
index++;
}
}
}
}
}
}
public void selectUnit(RenderUnit unit) {
this.subMenuOrderIdStack.clear();
if ((unit != null) && unit.getSimulationUnit().isDead()) {
@ -1359,6 +1485,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
this.portrait.setSelectedUnit(unit);
this.selectedUnit = unit;
setDraggingItem(null);
if (unit == null) {
clearCommandCard();
this.rootFrame.setText(this.simpleNameValue, "");
@ -1386,6 +1513,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.heroInfoPanel.setVisible(false);
this.rallyPointInstance.hide();
this.rallyPointInstance.detach();
this.inventoryCover.setVisible(true);
this.inventoryBarFrame.setVisible(false);
repositionWaypointFlags(null);
}
else {
@ -1518,12 +1647,16 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
final IconUI upgradeUI = this.war3MapViewer.getAbilityDataUI()
.getUpgradeUI(simulationUnit.getBuildQueue()[i], 0);
this.queueIconFrames[i].setTexture(upgradeUI.getIcon());
this.queueIconFrames[i].setToolTip(upgradeUI.getToolTip());
this.queueIconFrames[i].setUberTip(upgradeUI.getUberTip());
break;
case UNIT:
default:
final IconUI unitUI = this.war3MapViewer.getAbilityDataUI()
.getUnitUI(simulationUnit.getBuildQueue()[i]);
this.queueIconFrames[i].setTexture(unitUI.getIcon());
this.queueIconFrames[i].setToolTip(unitUI.getToolTip());
this.queueIconFrames[i].setUberTip(unitUI.getUberTip());
break;
}
}
@ -1662,6 +1795,59 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
this.simpleHeroLevelBar.setVisible(false);
}
final CAbilityInventory inventory = simulationUnit.getInventoryData();
this.inventoryCover.setVisible(inventory == null);
if (inventory != null) {
this.inventoryBarFrame.setVisible(true);
int index = 0;
for (int i = 0; i < INVENTORY_HEIGHT; i++) {
for (int j = 0; j < INVENTORY_WIDTH; j++) {
final CommandCardIcon inventoryIcon = this.inventoryIcons[i][j];
final CItem item = inventory.getItemInSlot(index);
if (item != null) {
final ItemUI itemUI = this.war3MapViewer.getAbilityDataUI().getItemUI(item.getTypeId());
final IconUI iconUI = itemUI.getIconUI();
final CItemType itemType = item.getItemType();
// TODO: below we set menu=false, this is bad, item should be based on item abil
final boolean activelyUsed = itemType.isActivelyUsed();
final boolean pawnable = itemType.isPawnable();
final String uberTip = iconUI.getUberTip();
this.recycleStringBuilder.setLength(0);
if (pawnable) {
this.recycleStringBuilder
.append(this.rootFrame.getTemplates().getDecoratedString("ITEM_PAWN_TOOLTIP"));
this.recycleStringBuilder.append("|n");
}
if (activelyUsed) {
this.recycleStringBuilder
.append(this.rootFrame.getTemplates().getDecoratedString("ITEM_USE_TOOLTIP"));
this.recycleStringBuilder.append("|n");
}
this.recycleStringBuilder.append(uberTip);
inventoryIcon.setCommandButtonData(iconUI.getIcon(), 0,
activelyUsed ? itemType.getCooldownGroup().getValue() : 0, index + 1, activelyUsed,
false, false, itemUI.getName(), this.recycleStringBuilder.toString(),
itemType.getGoldCost(), itemType.getLumberCost(), 0);
}
else {
if (index >= inventory.getItemCapacity()) {
inventoryIcon.setCommandButtonData(this.consoleInventoryNoCapacityTexture, 0, 0, 0,
false, false, false, null, null, 0, 0, 0);
}
else {
if (this.draggingItem != null) {
inventoryIcon.setCommandButtonData(null, 0, 0, index + 1, true, false, false, null,
null, 0, 0, 0);
}
else {
inventoryIcon.clear();
}
}
}
index++;
}
}
}
localArmorIcon.setVisible(!constructing);
this.simpleBuildTimeIndicator.setVisible(constructing);
@ -1711,7 +1897,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private void clearCommandCard() {
for (int j = 0; j < COMMAND_CARD_HEIGHT; j++) {
for (int i = 0; i < COMMAND_CARD_WIDTH; i++) {
this.commandCard[j][i].setCommandButton(null);
this.commandCard[j][i].clear();
}
}
}
@ -1865,6 +2051,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
reloadSelectedUnitUI(this.selectedUnit);
}
@Override
public void inventoryChanged() {
reloadSelectedUnitUI(this.selectedUnit);
}
@Override
public void queueChanged() {
reloadSelectedUnitUI(this.selectedUnit);
@ -1874,7 +2065,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
clearCommandCard();
final AbilityDataUI abilityDataUI = this.war3MapViewer.getAbilityDataUI();
final int menuOrderId = getSubMenuOrderId();
if (this.activeCommand != null) {
if ((this.activeCommand != null) && (this.draggingItem == null)) {
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(), 0,
menuOrderId, 0, false, false, true, cancelUI.getToolTip(), cancelUI.getUberTip(), 0, 0, 0);
@ -1932,6 +2123,9 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
if (this.draggingItem != null) {
setDraggingItem(null);
}
clearAndRepopulateCommandCard();
}
else {
@ -1966,44 +2160,65 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.war3MapViewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
clickLocationTemp2.set(clickLocationTemp.x, clickLocationTemp.y);
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.activeCommandOrderId == OrderIds.attack)) {
this.war3MapViewer.showConfirmation(clickLocationTemp, 1, 0, 0);
}
else {
this.war3MapViewer.showConfirmation(clickLocationTemp, 0, 1, 0);
}
this.unitOrderListener.issuePointOrder(
if (this.draggingItem != null) {
this.war3MapViewer.showConfirmation(clickLocationTemp, 0, 1, 0);
this.unitOrderListener.issueDropItemAtPointOrder(
this.activeCommandUnit.getSimulationUnit().getHandleId(),
this.activeCommand.getHandleId(), this.activeCommandOrderId, clickLocationTemp2.x,
clickLocationTemp2.y, shiftDown);
this.activeCommand.getHandleId(), this.activeCommandOrderId,
this.draggingItem.getHandleId(), clickLocationTemp2.x, clickLocationTemp2.y,
shiftDown);
if (getSelectedUnit().soundset.yes
.playUnitResponse(this.war3MapViewer.worldScene.audioContext, getSelectedUnit())) {
portraitTalk();
}
this.selectedSoundCount = 0;
if (this.activeCommand instanceof AbstractCAbilityBuild) {
this.war3MapViewer.getUiSounds().getSound("PlaceBuildingDefault")
.play(this.uiScene.audioContext, 0, 0, 0);
}
else if (this.activeCommand instanceof CAbilityRally) {
this.war3MapViewer.getUiSounds().getSound("RallyPointPlace")
.play(this.uiScene.audioContext, 0, 0, 0);
}
if (!shiftDown) {
this.subMenuOrderIdStack.clear();
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
clearAndRepopulateCommandCard();
}
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
setDraggingItem(null);
clearAndRepopulateCommandCard();
}
else {
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.activeCommandOrderId == OrderIds.attack)) {
this.war3MapViewer.showConfirmation(clickLocationTemp, 1, 0, 0);
}
else {
this.war3MapViewer.showConfirmation(clickLocationTemp, 0, 1, 0);
}
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 (this.activeCommand instanceof AbstractCAbilityBuild) {
this.war3MapViewer.getUiSounds().getSound("PlaceBuildingDefault")
.play(this.uiScene.audioContext, 0, 0, 0);
}
else if (this.activeCommand instanceof CAbilityRally) {
this.war3MapViewer.getUiSounds().getSound("RallyPointPlace")
.play(this.uiScene.audioContext, 0, 0, 0);
}
if (!shiftDown) {
this.subMenuOrderIdStack.clear();
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
clearAndRepopulateCommandCard();
}
}
}
}
}
}
@ -2224,45 +2439,51 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
final int lumberCost = this.mouseOverUIFrame.getToolTipLumberCost();
final int foodCost = this.mouseOverUIFrame.getToolTipFoodCost();
final String toolTip = this.mouseOverUIFrame.getToolTip();
this.rootFrame.setText(this.tooltipUberTipText, this.mouseOverUIFrame.getUberTip());
int resourceIndex = 0;
if (goldCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipGoldIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(goldCost));
resourceIndex++;
}
if (lumberCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipLumberIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(lumberCost));
resourceIndex++;
}
if (foodCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipSupplyIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(foodCost));
resourceIndex++;
}
for (int i = resourceIndex; i < this.tooltipResourceFrames.length; i++) {
this.tooltipResourceFrames[i].setVisible(false);
}
float resourcesHeight;
if (resourceIndex != 0) {
this.tooltipUberTipText.addSetPoint(this.uberTipWithResourcesSetPoint);
resourcesHeight = 0.014f;
final String uberTip = this.mouseOverUIFrame.getUberTip();
if ((toolTip == null) || (uberTip == null)) {
this.tooltipFrame.setVisible(false);
}
else {
this.tooltipUberTipText.addSetPoint(this.uberTipNoResourcesSetPoint);
resourcesHeight = 0.004f;
this.rootFrame.setText(this.tooltipUberTipText, uberTip);
int resourceIndex = 0;
if (goldCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipGoldIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(goldCost));
resourceIndex++;
}
if (lumberCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipLumberIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(lumberCost));
resourceIndex++;
}
if (foodCost != 0) {
this.tooltipResourceFrames[resourceIndex].setVisible(true);
this.tooltipResourceIconFrames[resourceIndex].setTexture("ToolTipSupplyIcon", this.rootFrame);
this.rootFrame.setText(this.tooltipResourceTextFrames[resourceIndex], Integer.toString(foodCost));
resourceIndex++;
}
for (int i = resourceIndex; i < this.tooltipResourceFrames.length; i++) {
this.tooltipResourceFrames[i].setVisible(false);
}
float resourcesHeight;
if (resourceIndex != 0) {
this.tooltipUberTipText.addSetPoint(this.uberTipWithResourcesSetPoint);
resourcesHeight = 0.014f;
}
else {
this.tooltipUberTipText.addSetPoint(this.uberTipNoResourcesSetPoint);
resourcesHeight = 0.004f;
}
this.rootFrame.setText(this.tooltipText, toolTip);
final float predictedViewportHeight = this.tooltipText.getPredictedViewportHeight()
+ GameUI.convertY(this.uiViewport, resourcesHeight)
+ this.tooltipUberTipText.getPredictedViewportHeight() + GameUI.convertY(this.uiViewport, 0.003f);
this.tooltipFrame.setHeight(predictedViewportHeight);
this.tooltipFrame.positionBounds(this.rootFrame, this.uiViewport);
this.tooltipFrame.setVisible(true);
}
this.rootFrame.setText(this.tooltipText, toolTip);
final float predictedViewportHeight = this.tooltipText.getPredictedViewportHeight()
+ GameUI.convertY(this.uiViewport, resourcesHeight)
+ this.tooltipUberTipText.getPredictedViewportHeight() + GameUI.convertY(this.uiViewport, 0.003f);
this.tooltipFrame.setHeight(predictedViewportHeight);
this.tooltipFrame.positionBounds(this.rootFrame, this.uiViewport);
this.tooltipFrame.setVisible(true);
}
public float getHeightRatioCorrection() {
@ -2309,4 +2530,39 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.rootFrame.dispose();
}
}
private class ItemCommandCardCommandListener implements CommandCardCommandListener {
@Override
public void onClick(final int abilityHandleId, final int orderId, final boolean rightClick) {
if (rightClick) {
final RenderUnit selectedUnit2 = MeleeUI.this.selectedUnit;
final CUnit simulationUnit = selectedUnit2.getSimulationUnit();
final CAbilityInventory inventoryData = simulationUnit.getInventoryData();
final int slot = orderId - 1;
final CItem itemInSlot = inventoryData.getItemInSlot(slot);
if (MeleeUI.this.draggingItem != null) {
final CUnit activeCmdSimUnit = MeleeUI.this.activeCommandUnit.getSimulationUnit();
MeleeUI.this.unitOrderListener.issueTargetOrder(activeCmdSimUnit.getHandleId(),
activeCmdSimUnit.getInventoryData().getHandleId(), OrderIds.itemdrag00 + slot,
MeleeUI.this.draggingItem.getHandleId(), false);
setDraggingItem(null);
MeleeUI.this.activeCommand = null;
MeleeUI.this.activeCommandUnit = null;
}
else {
if (itemInSlot != null) {
setDraggingItem(itemInSlot);
MeleeUI.this.activeCommand = inventoryData;
MeleeUI.this.activeCommandUnit = selectedUnit2;
}
}
}
}
@Override
public void openMenu(final int orderId) {
MeleeUI.this.openMenu(orderId);
}
}
}

View File

@ -34,7 +34,7 @@ public class MeleeUIMinimap {
batch.draw(this.minimapTexture, this.minimap.x, this.minimap.y, this.minimap.width, this.minimap.height);
for (final RenderUnit unit : units) {
final Texture minimapIcon = this.teamColors[unit.playerIndex];
final Texture minimapIcon = this.teamColors[unit.getSimulationUnit().getPlayerIndex()];
batch.draw(minimapIcon,
this.minimapFilledArea.x
+ (((unit.location[0] - this.playableMapArea.getX()) / (this.playableMapArea.getWidth()))

View File

@ -20,6 +20,9 @@ public class QueueIcon extends AbstractRenderableFrame implements ClickableActio
private float defaultHeight;
private final int queueIconIndexId;
private String toolTip;
private String uberTip;
public QueueIcon(final String name, final UIFrame parent, final QueueIconListener clickListener,
final int queueIconIndexId) {
super(name, parent);
@ -113,14 +116,22 @@ public class QueueIcon extends AbstractRenderableFrame implements ClickableActio
return null;
}
public void setToolTip(final String toolTip) {
this.toolTip = toolTip;
}
public void setUberTip(final String uberTip) {
this.uberTip = uberTip;
}
@Override
public String getToolTip() {
return "QueueIcon " + this.queueIconIndexId;
return this.toolTip;
}
@Override
public String getUberTip() {
return "The |cffffcc00QueueIcon|r is a hardcoded Warsmash engine component that is not yet loading its |cffffaa88description|r.";
return this.uberTip;
}
@Override

View File

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

View File

@ -6,4 +6,6 @@ public interface CommandErrorListener {
void showCantPlaceError();
void showNoFoodError();
void showInventoryFullError();
}

View File

@ -18,6 +18,11 @@ public class SettableCommandErrorListener implements CommandErrorListener {
this.delegate.showNoFoodError();
}
@Override
public void showInventoryFullError() {
this.delegate.showInventoryFullError();
}
public void setDelegate(final CommandErrorListener delegate) {
this.delegate = delegate;
}

View File

@ -393,7 +393,7 @@ public class MdlxModel {
break;
case MdlUtils.TOKEN_TEXTURE_ANIMS:
loadNumberedObjectBlock(this.textureAnimations, MdlxBlockDescriptor.TEXTURE_ANIMATION,
MdlUtils.TOKEN_TEXTURE_ANIM, stream);
MdlUtils.TOKEN_TVERTEX_ANIM, stream);
break;
case MdlUtils.TOKEN_GEOSET:
loadObject(this.geosets, MdlxBlockDescriptor.GEOSET, stream);

View File

@ -42,7 +42,7 @@ public class MdlxTextureAnimation extends MdlxAnimatedObject {
@Override
public void writeMdl(final MdlTokenOutputStream stream, final int version) {
stream.startBlock(MdlUtils.TOKEN_TVERTEX_ANIM_SPACE);
stream.startBlock(MdlUtils.TOKEN_TVERTEX_ANIM);
writeTimeline(stream, AnimationMap.KTAT);
writeTimeline(stream, AnimationMap.KTAR);
writeTimeline(stream, AnimationMap.KTAS);

View File

@ -29,7 +29,7 @@ public class MdlUtils {
public static final String TOKEN_WRAP_HEIGHT = "WrapHeight";
public static final String TOKEN_BITMAP = "Bitmap";
public static final String TOKEN_TVERTEX_ANIM_SPACE = "TVertexAnim";
public static final String TOKEN_TVERTEX_ANIM = "TVertexAnim";
public static final String TOKEN_DONT_INTERP = "DontInterp";
public static final String TOKEN_LINEAR = "Linear";
@ -177,7 +177,6 @@ public class MdlUtils {
public static final String TOKEN_TEXTURES = "Textures";
public static final String TOKEN_MATERIALS = "Materials";
public static final String TOKEN_TEXTURE_ANIMS = "TextureAnims";
public static final String TOKEN_TEXTURE_ANIM = "TextureAnim";
public static final String TOKEN_PIVOT_POINTS = "PivotPoints";
public static final String TOKEN_ATTACHMENT = "Attachment";
@ -198,7 +197,7 @@ public class MdlUtils {
// > 800
public static final String TOKEN_EMISSIVE_GAIN = "EmissiveGain";
public static final String TOKEN_FRESNEL_COLOR = "FresnelColor";
public static final String TOKEN_FRESNEL_COLOR = "FresnelColor";
public static final String TOKEN_FRESNEL_OPACITY = "FresnelOpacity";
public static final String TOKEN_FRESNEL_TEAM_COLOR = "FresnelTeamColor";
}

View File

@ -0,0 +1,501 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.lwjgl;
import java.awt.Canvas;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.HashMap;
import java.util.Map;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.Display;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.ApplicationLogger;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.SharedLibraryLoader;
import com.etheller.warsmash.audio.OpenALAudio;
/**
* An OpenGL surface on an AWT Canvas, allowing OpenGL to be embedded in a Swing
* application. This uses {@link Display#setParent(Canvas)}, which is preferred
* over {@link AWTGLCanvas} but is limited to a single LwjglCanvas in an
* application. All OpenGL calls are done on the EDT. Note that you may need to
* call {@link #stop()} or a Swing application may deadlock on System.exit due
* to how LWJGL and/or Swing deal with shutdown hooks.
*
* @author Nathan Sweet
*/
public class LwjglCanvas implements Application {
static boolean isWindows = System.getProperty("os.name").contains("Windows");
LwjglGraphics graphics;
OpenALAudio audio;
LwjglFiles files;
LwjglInput input;
LwjglNet net;
ApplicationListener listener;
Canvas canvas;
final Array<Runnable> runnables = new Array();
final Array<Runnable> executedRunnables = new Array();
final Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
boolean running = true;
int logLevel = LOG_INFO;
ApplicationLogger applicationLogger;
Cursor cursor;
public LwjglCanvas(final ApplicationListener listener) {
final LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
initialize(listener, config);
}
public LwjglCanvas(final ApplicationListener listener, final LwjglApplicationConfiguration config) {
initialize(listener, config);
}
private void initialize(final ApplicationListener listener, final LwjglApplicationConfiguration config) {
LwjglNativesLoader.load();
setApplicationLogger(new LwjglApplicationLogger());
this.canvas = new Canvas() {
private final Dimension minSize = new Dimension(1, 1);
@Override
public final void addNotify() {
super.addNotify();
if (SharedLibraryLoader.isMac) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
create();
}
});
}
else {
create();
}
}
@Override
public final void removeNotify() {
stop();
super.removeNotify();
}
@Override
public Dimension getMinimumSize() {
return this.minSize;
}
};
this.canvas.setSize(1, 1);
this.canvas.setIgnoreRepaint(true);
this.graphics = new LwjglGraphics(this.canvas, config) {
@Override
public void setTitle(final String title) {
super.setTitle(title);
LwjglCanvas.this.setTitle(title);
}
public boolean setWindowedMode(final int width, final int height, final boolean fullscreen) {
if (!super.setWindowedMode(width, height)) {
return false;
}
if (!fullscreen) {
LwjglCanvas.this.setDisplayMode(width, height);
}
return true;
}
@Override
public boolean setFullscreenMode(final DisplayMode displayMode) {
if (!super.setFullscreenMode(displayMode)) {
return false;
}
LwjglCanvas.this.setDisplayMode(displayMode.width, displayMode.height);
return true;
}
};
this.graphics.setVSync(config.vSyncEnabled);
if (!LwjglApplicationConfiguration.disableAudio) {
this.audio = new OpenALAudio();
}
this.files = new LwjglFiles();
this.input = new LwjglInput();
this.net = new LwjglNet();
this.listener = listener;
Gdx.app = this;
Gdx.graphics = this.graphics;
Gdx.audio = this.audio;
Gdx.files = this.files;
Gdx.input = this.input;
Gdx.net = this.net;
}
protected void setDisplayMode(final int width, final int height) {
}
protected void setTitle(final String title) {
}
@Override
public ApplicationListener getApplicationListener() {
return this.listener;
}
public Canvas getCanvas() {
return this.canvas;
}
@Override
public Audio getAudio() {
return this.audio;
}
@Override
public Files getFiles() {
return this.files;
}
@Override
public Graphics getGraphics() {
return this.graphics;
}
@Override
public Input getInput() {
return this.input;
}
@Override
public Net getNet() {
return this.net;
}
@Override
public ApplicationType getType() {
return ApplicationType.Desktop;
}
@Override
public int getVersion() {
return 0;
}
void create() {
try {
this.graphics.setupDisplay();
this.listener.create();
this.listener.resize(Math.max(1, this.graphics.getWidth()), Math.max(1, this.graphics.getHeight()));
start();
}
catch (final Exception ex) {
stopped();
exception(ex);
return;
}
EventQueue.invokeLater(new Runnable() {
int lastWidth = Math.max(1, LwjglCanvas.this.graphics.getWidth());
int lastHeight = Math.max(1, LwjglCanvas.this.graphics.getHeight());
@Override
public void run() {
if (!LwjglCanvas.this.running || Display.isCloseRequested()) {
LwjglCanvas.this.running = false;
stopped();
return;
}
try {
Display.processMessages();
if ((LwjglCanvas.this.cursor != null) || !isWindows) {
LwjglCanvas.this.canvas.setCursor(LwjglCanvas.this.cursor);
}
boolean shouldRender = false;
final int width = Math.max(1, LwjglCanvas.this.graphics.getWidth());
final int height = Math.max(1, LwjglCanvas.this.graphics.getHeight());
if ((this.lastWidth != width) || (this.lastHeight != height)) {
this.lastWidth = width;
this.lastHeight = height;
Gdx.gl.glViewport(0, 0, this.lastWidth, this.lastHeight);
resize(width, height);
LwjglCanvas.this.listener.resize(width, height);
shouldRender = true;
}
if (executeRunnables()) {
shouldRender = true;
}
// If one of the runnables set running to false, for example after an exit().
if (!LwjglCanvas.this.running) {
return;
}
LwjglCanvas.this.input.update();
shouldRender |= LwjglCanvas.this.graphics.shouldRender();
LwjglCanvas.this.input.processEvents();
if (LwjglCanvas.this.audio != null) {
LwjglCanvas.this.audio.update();
}
if (shouldRender) {
LwjglCanvas.this.graphics.updateTime();
LwjglCanvas.this.graphics.frameId++;
LwjglCanvas.this.listener.render();
Display.update(false);
}
Display.sync(getFrameRate());
}
catch (final Throwable ex) {
exception(ex);
}
EventQueue.invokeLater(this);
}
});
}
public boolean executeRunnables() {
synchronized (this.runnables) {
for (int i = this.runnables.size - 1; i >= 0; i--) {
this.executedRunnables.addAll(this.runnables.get(i));
}
this.runnables.clear();
}
if (this.executedRunnables.size == 0) {
return false;
}
do {
this.executedRunnables.pop().run();
}
while (this.executedRunnables.size > 0);
return true;
}
protected int getFrameRate() {
int frameRate = Display.isActive() ? this.graphics.config.foregroundFPS : this.graphics.config.backgroundFPS;
if (frameRate == -1) {
frameRate = 10;
}
if (frameRate == 0) {
frameRate = this.graphics.config.backgroundFPS;
}
if (frameRate == 0) {
frameRate = 30;
}
return frameRate;
}
protected void exception(final Throwable ex) {
ex.printStackTrace();
stop();
}
/**
* Called after {@link ApplicationListener} create and resize, but before the
* game loop iteration.
*/
protected void start() {
}
/** Called when the canvas size changes. */
protected void resize(final int width, final int height) {
}
/** Called when the game loop has stopped. */
protected void stopped() {
}
public void stop() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (!LwjglCanvas.this.running) {
return;
}
LwjglCanvas.this.running = false;
final Array<LifecycleListener> listeners = LwjglCanvas.this.lifecycleListeners;
synchronized (listeners) {
for (final LifecycleListener listener : listeners) {
listener.pause();
listener.dispose();
}
}
LwjglCanvas.this.listener.pause();
LwjglCanvas.this.listener.dispose();
try {
Display.destroy();
if (LwjglCanvas.this.audio != null) {
LwjglCanvas.this.audio.dispose();
}
}
catch (final Throwable ignored) {
}
}
});
}
@Override
public long getJavaHeap() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
@Override
public long getNativeHeap() {
return getJavaHeap();
}
Map<String, Preferences> preferences = new HashMap<String, Preferences>();
@Override
public Preferences getPreferences(final String name) {
if (this.preferences.containsKey(name)) {
return this.preferences.get(name);
}
else {
final Preferences prefs = new LwjglPreferences(name, ".prefs/");
this.preferences.put(name, prefs);
return prefs;
}
}
@Override
public Clipboard getClipboard() {
return new LwjglClipboard();
}
@Override
public void postRunnable(final Runnable runnable) {
synchronized (this.runnables) {
this.runnables.add(runnable);
Gdx.graphics.requestRendering();
}
}
@Override
public void debug(final String tag, final String message) {
if (this.logLevel >= LOG_DEBUG) {
getApplicationLogger().debug(tag, message);
}
}
@Override
public void debug(final String tag, final String message, final Throwable exception) {
if (this.logLevel >= LOG_DEBUG) {
getApplicationLogger().debug(tag, message, exception);
}
}
@Override
public void log(final String tag, final String message) {
if (this.logLevel >= LOG_INFO) {
getApplicationLogger().log(tag, message);
}
}
@Override
public void log(final String tag, final String message, final Throwable exception) {
if (this.logLevel >= LOG_INFO) {
getApplicationLogger().log(tag, message, exception);
}
}
@Override
public void error(final String tag, final String message) {
if (this.logLevel >= LOG_ERROR) {
getApplicationLogger().error(tag, message);
}
}
@Override
public void error(final String tag, final String message, final Throwable exception) {
if (this.logLevel >= LOG_ERROR) {
getApplicationLogger().error(tag, message, exception);
}
}
@Override
public void setLogLevel(final int logLevel) {
this.logLevel = logLevel;
}
@Override
public int getLogLevel() {
return this.logLevel;
}
@Override
public void setApplicationLogger(final ApplicationLogger applicationLogger) {
this.applicationLogger = applicationLogger;
}
@Override
public ApplicationLogger getApplicationLogger() {
return this.applicationLogger;
}
@Override
public void exit() {
postRunnable(new Runnable() {
@Override
public void run() {
LwjglCanvas.this.listener.pause();
LwjglCanvas.this.listener.dispose();
if (LwjglCanvas.this.audio != null) {
LwjglCanvas.this.audio.dispose();
}
System.exit(-1);
}
});
}
/** @param cursor May be null. */
public void setCursor(final Cursor cursor) {
this.cursor = cursor;
}
@Override
public void addLifecycleListener(final LifecycleListener listener) {
synchronized (this.lifecycleListeners) {
this.lifecycleListeners.add(listener);
}
}
@Override
public void removeLifecycleListener(final LifecycleListener listener) {
synchronized (this.lifecycleListeners) {
this.lifecycleListeners.removeValue(listener, true);
}
}
}