Cargo hold, some fixes, WIP lobby setup

This commit is contained in:
Retera 2022-04-29 13:27:16 -04:00
parent 6c4eee02e2
commit ed8134b5a4
57 changed files with 2080 additions and 249 deletions

View File

@ -7,7 +7,7 @@ import java.nio.file.Files;
public class CodeCounter {
public static void main(final String[] args) {
final int sourceLines = countFile(new File("src/com"));
final int sourceLines = countFile(new File("src/com/etheller"));
System.out.println(sourceLines);
}

View File

@ -2602,10 +2602,16 @@ public class Jass2 {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final CUnit whichUnit = nullable(arguments, 0, ObjectJassValueVisitor.getInstance());
final CUnitState whichUnitState = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
final float value = arguments.get(2).visit(RealJassValueVisitor.getInstance()).floatValue();
whichUnit.setUnitState(CommonEnvironment.this.simulation, whichUnitState, value);
if (whichUnit != null) {
whichUnit.setUnitState(CommonEnvironment.this.simulation, whichUnitState, value);
}
else {
System.err.println("got SetUnitState(null," + whichUnitState + "," + value
+ ") call (skipping because unit is null)");
}
return null;
}
});
@ -2976,8 +2982,11 @@ public class Jass2 {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final int lowBound = arguments.get(0).visit(IntegerJassValueVisitor.getInstance());
int lowBound = arguments.get(0).visit(IntegerJassValueVisitor.getInstance());
final int highBound = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
if (lowBound > highBound) {
lowBound = highBound;
}
return new IntegerJassValue(
CommonEnvironment.this.simulation.getSeededRandom().nextInt((highBound - lowBound) + 1)
+ lowBound);
@ -4800,7 +4809,7 @@ public class Jass2 {
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CPlayerJass player = arguments.get(0).visit(ObjectJassValueVisitor.<CPlayerJass>getInstance());
return BooleanJassValue.of(player.isSelectable());
return BooleanJassValue.of(player.isRaceSelectable());
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerController", new JassFunction() {
@ -5495,8 +5504,20 @@ public class Jass2 {
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final String s = arguments.get(0).visit(StringJassValueVisitor.getInstance());
final int start = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final int end = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
int start = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
int end = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
if (start > s.length()) {
start = s.length();
}
if (start < 0) {
start = 0;
}
if (end > s.length()) {
end = s.length();
}
if (end < start) {
end = start;
}
return new StringJassValue(s.substring(start, end));
}
});

View File

@ -23,7 +23,27 @@ public class Force {
ParseUtils.writeWithNullTerminator(stream, this.name);
}
public long getFlags() {
return this.flags;
}
public long getPlayerMasks() {
return this.playerMasks;
}
public String getName() {
return this.name;
}
public int getByteLength() {
return 9 + this.name.length();
}
public static final class Flag {
public static final int ALLIED = 0x0001;
public static final int ALLIED_VICTORY = 0x0002;
public static final int SHARE_VISION = 0x0008;
public static final int SHARE_UNIT_CONTROL = 0x0010;
public static final int SHARE_ADV_UNIT_CONTROL = 0x0020;
}
}

View File

@ -466,4 +466,8 @@ public class War3MapW3i {
public int getGameVersionMinor() {
return this.gameVersionMinor;
}
public boolean hasFlag(final int mapFlag) {
return (this.flags & mapFlag) != 0;
}
}

View File

@ -0,0 +1,19 @@
package com.etheller.warsmash.parsers.w3x.w3i;
public class War3MapW3iFlags {
// definitions for these are based on what was found online located at:
// wc3maps.com/InsideTheW3M.html
public static final int HIDE_MINIMAP_IN_PREVIEW_SCREENS = 0x0001;
public static final int MODIFY_ALLY_PRIORITIES = 0x0002;
public static final int MELEE_MAP = 0x0004;
public static final int PLAYABLE_MAP_SIZE_LARGE_AND_NEVER_REDUCED_TO_MEDIUM = 0x0008; // ? not sure
public static final int MASKED_AREAS_ARE_PARTIALLY_VISIBLE = 0x0010;
public static final int FIXED_PLAYER_SETTINGS_FOR_CUSTOM_FORCES = 0x0020;
public static final int USE_CUSTOM_FORCES = 0x0040;
public static final int USE_CUSTOM_TECHTREE = 0x0080;
public static final int USE_CUSTOM_ABILITIES = 0x0100;
public static final int USE_CUSTOM_UPGRADES = 0x0200;
public static final int MAP_PROPERTIES_MENU_OPENED_AT_LEAST_ONCE_SINCE_MAP_CREATED = 0x0400;
public static final int SHOW_WATER_WAVES_ON_CLIFF_SHORES = 0x0800;
public static final int SHOW_WATER_WAVES_ON_ROLLING_SHORES = 0x1000;
}

View File

@ -802,6 +802,9 @@ public final class MutableObjectData {
final Change matchingChange = getMatchingChange(field, level);
if (matchingChange != null) {
if (matchingChange.getVartype() != War3ObjectDataChangeset.VAR_TYPE_INT) {
if (matchingChange.getVartype() == War3ObjectDataChangeset.VAR_TYPE_UNREAL) {
return (int) matchingChange.getRealval();
}
throw new IllegalStateException(
"Requested integer value of '" + field + "' from '" + this.parentWC3Object.getId()
+ "', but this field was not an int! vartype=" + matchingChange.getVartype());
@ -909,12 +912,7 @@ public final class MutableObjectData {
}
public enum WorldEditorDataType {
UNITS("w3u"),
ITEM("w3t"),
DESTRUCTIBLES("w3b"),
DOODADS("w3d"),
ABILITIES("w3a"),
BUFFS_EFFECTS("w3h"),
UNITS("w3u"), ITEM("w3t"), DESTRUCTIBLES("w3b"), DOODADS("w3d"), ABILITIES("w3a"), BUFFS_EFFECTS("w3h"),
UPGRADES("w3q");
private String extension;

View File

@ -8,7 +8,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

@ -656,7 +656,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
// RenderUnit class:
final String originalRequiredAnimationNames = War3MapViewer.this.allObjectData.getUnits()
.get(unit.getTypeId()).getFieldAsString(RenderUnit.ANIM_PROPS, 0);
TokenLoop: for (final String animationName : originalRequiredAnimationNames.split(",")) {
TokenLoop:
for (final String animationName : originalRequiredAnimationNames.split(",")) {
final String upperCaseToken = animationName.toUpperCase();
for (final SecondaryTag secondaryTag : SecondaryTag.values()) {
if (upperCaseToken.equals(secondaryTag.name())) {
@ -668,7 +669,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
// TODO this should be behind some auto lookup so it isn't copied from
// RenderUnit class:
final String requiredAnimationNames = upgrade.getFieldAsString(RenderUnit.ANIM_PROPS, 0);
TokenLoop: for (final String animationName : requiredAnimationNames.split(",")) {
TokenLoop:
for (final String animationName : requiredAnimationNames.split(",")) {
final String upperCaseToken = animationName.toUpperCase();
for (final SecondaryTag secondaryTag : SecondaryTag.values()) {
if (upperCaseToken.equals(secondaryTag.name())) {
@ -687,7 +689,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
// TODO this should be behind some auto lookup so it isn't copied from
// RenderUnit class:
final String requiredAnimationNames = upgrade.getFieldAsString(RenderUnit.ANIM_PROPS, 0);
TokenLoop: for (final String animationName : requiredAnimationNames.split(",")) {
TokenLoop:
for (final String animationName : requiredAnimationNames.split(",")) {
final String upperCaseToken = animationName.toUpperCase();
for (final SecondaryTag secondaryTag : SecondaryTag.values()) {
if (upperCaseToken.equals(secondaryTag.name())) {
@ -699,7 +702,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final String originalRequiredAnimationNames = War3MapViewer.this.allObjectData.getUnits()
.get(unit.getTypeId()).getFieldAsString(RenderUnit.ANIM_PROPS, 0);
TokenLoop: for (final String animationName : originalRequiredAnimationNames.split(",")) {
TokenLoop:
for (final String animationName : originalRequiredAnimationNames.split(",")) {
final String upperCaseToken = animationName.toUpperCase();
for (final SecondaryTag secondaryTag : SecondaryTag.values()) {
if (upperCaseToken.equals(secondaryTag.name())) {
@ -942,9 +946,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void spawnUnitReadySound(final CUnit trainedUnit) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(trainedUnit);
renderPeer.soundset.ready.playUnitResponse(War3MapViewer.this.worldScene.audioContext,
renderPeer);
if (trainedUnit.getPlayerIndex() == War3MapViewer.this.localPlayerIndex) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(trainedUnit);
renderPeer.soundset.ready.playUnitResponse(War3MapViewer.this.worldScene.audioContext,
renderPeer);
}
}
@Override
@ -953,6 +959,69 @@ public class War3MapViewer extends AbstractMdxModelViewer {
renderPeer.repositioned(War3MapViewer.this);
}
@Override
public void unitUpdatedType(final CUnit simulationUnit, final War3ID typeId) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(simulationUnit);
final MutableGameObject row = War3MapViewer.this.allObjectData.getUnits().get(typeId);
final String path = getUnitModelPath(row);
final String unitSpecialArtPath = row.getFieldAsString(UNIT_SPECIAL, 0);
MdxModel specialArtModel;
if ((unitSpecialArtPath != null) && !unitSpecialArtPath.isEmpty()) {
try {
specialArtModel = loadModelMdx(unitSpecialArtPath);
}
catch (final Exception exc) {
exc.printStackTrace();
specialArtModel = null;
}
}
else {
specialArtModel = null;
}
final MdxModel model = loadModelMdx(path);
MdxModel portraitModel;
final String portraitPath = path.substring(0, path.length() - 4) + "_portrait.mdx";
if (War3MapViewer.this.dataSource.has(portraitPath)) {
portraitModel = loadModelMdx(portraitPath);
}
else {
portraitModel = model;
}
final float angle = (float) Math.toDegrees(simulationUnit.getFacing());
final RenderUnitTypeData typeData = getUnitTypeData(typeId, row);
final int customTeamColor = War3MapViewer.this.simulation
.getPlayer(simulationUnit.getPlayerIndex()).getColor();
final float unitX = simulationUnit.getX();
final float unitY = simulationUnit.getY();
final float unitZ = Math.max(getWalkableRenderHeight(unitX, unitY),
War3MapViewer.this.terrain.getGroundHeight(unitX, unitY))
+ simulationUnit.getFlyHeight();
UnitSoundset soundset = null;
BuildingShadow buildingShadowInstance = null;
final String buildingShadow = row.getFieldAsString(BUILDING_SHADOW, 0);
if ((buildingShadow != null) && !"_".equals(buildingShadow)) {
buildingShadowInstance = War3MapViewer.this.terrain.addShadow(buildingShadow, unitX, unitY);
}
final String soundName = row.getFieldAsString(UNIT_SOUNDSET, 0);
UnitSoundset unitSoundset = War3MapViewer.this.soundsetNameToSoundset.get(soundName);
if (unitSoundset == null) {
unitSoundset = new UnitSoundset(War3MapViewer.this.dataSource,
War3MapViewer.this.unitAckSoundsTable, soundName);
War3MapViewer.this.soundsetNameToSoundset.put(soundName, unitSoundset);
}
soundset = unitSoundset;
renderPeer.resetRenderUnit(War3MapViewer.this, model, row, unitX, unitY, unitZ,
localPlayerIndex, soundset, portraitModel, simulationUnit, typeData, specialArtModel,
buildingShadowInstance, War3MapViewer.this.selectionCircleScaleFactor,
typeData.getAnimationWalkSpeed(), typeData.getAnimationRunSpeed(),
typeData.getScalingValue());
}
@Override
public void spawnGainResourceTextTag(final CUnit gainingUnit, final ResourceType resourceType,
final int amount) {

View File

@ -589,6 +589,7 @@ public class Terrain {
int bottomLeftCliffTex = bottomLeft.getCliffTexture();
if (bottomLeftCliffTex == 15) {
boolean foundTexture = false;
final int topLeftCliffTex = topLeft.getCliffTexture();
if (topLeftCliffTex == 15) {
final int topRightCliffTex = topRight.getCliffTexture();
@ -599,14 +600,20 @@ public class Terrain {
}
else {
bottomLeftCliffTex = bottomRightCliffTex;
foundTexture = true;
}
}
else {
bottomLeftCliffTex = topRightCliffTex;
foundTexture = true;
}
}
else {
bottomLeftCliffTex = topLeftCliffTex;
foundTexture = true;
}
if (foundTexture) {
bottomLeft.setCliffTexture(bottomLeftCliffTex);
}
}
if (!(facingDown && (j == 0)) && !(!facingDown && (j >= (this.rows - 2)))

View File

@ -6,6 +6,7 @@ import java.util.Map;
import com.badlogic.gdx.math.Quaternion;
import com.etheller.warsmash.parsers.w3x.w3e.War3MapW3e;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3iFlags;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.Element;
import com.etheller.warsmash.util.RenderMathUtils;
@ -48,8 +49,8 @@ public class WaveBuilder {
final char tileset = this.w3eFile.getTileset();
final Element waterRow = this.waterTable.get(tileset + "Sha");
final long wavesCliff = (this.w3iFile.getFlags() & 0x0800);
final long wavesRolling = (this.w3iFile.getFlags() & 0x1000);
final long wavesCliff = (this.w3iFile.getFlags() & War3MapW3iFlags.SHOW_WATER_WAVES_ON_CLIFF_SHORES);
final long wavesRolling = (this.w3iFile.getFlags() & War3MapW3iFlags.SHOW_WATER_WAVES_ON_ROLLING_SHORES);
final String shoreline = waterRow.getField("shoreDir") + "\\" + waterRow.getField("shoreSFile") + "\\"
+ waterRow.getField("shoreSFile") + "0.mdx";

View File

@ -40,12 +40,12 @@ public class RenderUnit implements RenderWidget {
private static final War3ID BUILD_SOUND_LABEL = War3ID.fromString("ubsl");
private static final War3ID UNIT_SELECT_HEIGHT = War3ID.fromString("uslz");
private static final float[] heapZ = new float[3];
public final MdxComplexInstance instance;
public final MutableGameObject row;
public MdxComplexInstance instance;
public MutableGameObject row;
public final float[] location = new float[3];
public float selectionScale;
public UnitSoundset soundset;
public final MdxModel portraitModel;
public MdxModel portraitModel;
public int playerIndex;
private final CUnit simulationUnit;
public SplatMover shadow;
@ -60,14 +60,14 @@ public class RenderUnit implements RenderWidget {
private boolean dead = false;
private final UnitAnimationListenerImpl unitAnimationListenerImpl;
private UnitAnimationListenerImpl unitAnimationListenerImpl;
private OrientationInterpolation orientationInterpolation;
private float currentTurnVelocity = 0;
public long lastUnitResponseEndTimeMillis;
private boolean corpse;
private boolean boneCorpse;
private final RenderUnitTypeData typeData;
public final MdxModel specialArtModel;
private RenderUnitTypeData typeData;
public MdxModel specialArtModel;
public SplatMover uberSplat;
private float selectionHeight;
private RenderUnit preferredSelectionReplacement;
@ -77,11 +77,28 @@ public class RenderUnit implements RenderWidget {
final MdxModel portraitModel, final CUnit simulationUnit, final RenderUnitTypeData typeData,
final MdxModel specialArtModel, final BuildingShadow buildingShadow, final float selectionCircleScaleFactor,
final float animationWalkSpeed, final float animationRunSpeed, final float scalingValue) {
this.portraitModel = portraitModel;
this.simulationUnit = simulationUnit;
resetRenderUnit(map, model, row, x, y, z, playerIndex, soundset, portraitModel, simulationUnit, typeData,
specialArtModel, buildingShadow, selectionCircleScaleFactor, animationWalkSpeed, animationRunSpeed,
scalingValue);
}
public void resetRenderUnit(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
final float x, final float y, final float z, final int playerIndex, final UnitSoundset soundset,
final MdxModel portraitModel, final CUnit simulationUnit, final RenderUnitTypeData typeData,
final MdxModel specialArtModel, final BuildingShadow buildingShadow, final float selectionCircleScaleFactor,
final float animationWalkSpeed, final float animationRunSpeed, final float scalingValue) {
this.portraitModel = portraitModel;
this.typeData = typeData;
this.specialArtModel = specialArtModel;
if (this.buildingShadowInstance != null) {
this.buildingShadowInstance.remove();
}
this.buildingShadowInstance = buildingShadow;
if (this.instance != null) {
this.instance.detach();
}
final MdxComplexInstance instance = (MdxComplexInstance) model.addInstance();
this.location[0] = x;
@ -98,7 +115,8 @@ public class RenderUnit implements RenderWidget {
this.unitAnimationListenerImpl = new UnitAnimationListenerImpl(instance, animationWalkSpeed, animationRunSpeed);
simulationUnit.setUnitAnimationListener(this.unitAnimationListenerImpl);
final String requiredAnimationNames = row.getFieldAsString(ANIM_PROPS, 0);
TokenLoop: for (final String animationName : requiredAnimationNames.split(",")) {
TokenLoop:
for (final String animationName : requiredAnimationNames.split(",")) {
final String upperCaseToken = animationName.toUpperCase();
for (final SecondaryTag secondaryTag : SecondaryTag.values()) {
if (upperCaseToken.equals(secondaryTag.name())) {
@ -139,7 +157,6 @@ public class RenderUnit implements RenderWidget {
this.instance = instance;
this.row = row;
this.soundset = soundset;
}
public void populateCommandCard(final CSimulation game, final GameUI gameUI,

View File

@ -676,4 +676,8 @@ public class CSimulation implements CPlayerAPI {
this.simulationRenderController.setBlight(x, y, radius, blighted);
}
public void unitUpdatedType(final CUnit unit, final War3ID typeId) {
this.simulationRenderController.unitUpdatedType(unit, typeId);
}
}

View File

@ -24,6 +24,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.GetAbilityByRawcodeVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
@ -288,6 +289,7 @@ public class CUnit extends CWidget {
}
public void setTypeId(final CSimulation game, final War3ID typeId) {
game.getWorldCollision().removeUnit(this);
this.typeId = typeId;
final float lifeRatio = this.maximumLife == 0 ? 1 : (this.life / this.maximumLife);
final float manaRatio = this.maximumMana == 0 ? Float.NaN : (this.mana / this.maximumMana);
@ -304,6 +306,7 @@ public class CUnit extends CWidget {
this.lifeRegen = this.unitType.getLifeRegen();
this.manaRegen = this.unitType.getManaRegen();
this.flyHeight = this.unitType.getDefaultFlyingHeight();
this.speed = this.unitType.getSpeed();
this.classifications.clear();
this.classifications.addAll(this.unitType.getClassifications());
this.acquisitionRange = this.unitType.getDefaultAcquisitionRange();
@ -315,6 +318,8 @@ public class CUnit extends CWidget {
game.getUnitData().addDefaultAbilitiesToUnit(game, game.getHandleIdAllocator(), this.unitType, false, -1,
this.speed, this);
computeDerivedFields();
game.getWorldCollision().addUnit(this);
game.unitUpdatedType(this, typeId);
}
public void setFacing(final float facing) {
@ -661,12 +666,12 @@ public class CUnit extends CWidget {
}
public boolean autoAcquireAttackTargets(final CSimulation game, final boolean disableMove) {
if (!this.getAttacks().isEmpty() && !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
if (!getAttacks().isEmpty() && !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
if (this.collisionRectangle != null) {
tempRect.set(this.collisionRectangle);
}
else {
tempRect.set(this.getX(), this.getY(), 0, 0);
tempRect.set(getX(), getY(), 0, 0);
}
final float halfSize = this.acquisitionRange;
tempRect.x -= halfSize;
@ -681,7 +686,7 @@ public class CUnit extends CWidget {
}
public float getEndingDecayTime(final CSimulation game) {
if (this.isBuilding()) {
if (isBuilding()) {
return game.getGameplayConstants().getStructureDecayTime();
}
if (this.unitType.isHero()) {
@ -884,7 +889,7 @@ public class CUnit extends CWidget {
public void setX(final float newX, final CWorldCollision collision, final CRegionManager regionManager) {
final float prevX = getX();
if (!this.isBuilding()) {
if (!isBuilding()) {
setX(newX);
collision.translate(this, newX - prevX, 0);
}
@ -893,7 +898,7 @@ public class CUnit extends CWidget {
public void setY(final float newY, final CWorldCollision collision, final CRegionManager regionManager) {
final float prevY = getY();
if (!this.isBuilding()) {
if (!isBuilding()) {
setY(newY);
collision.translate(this, 0, newY - prevY);
}
@ -946,7 +951,7 @@ public class CUnit extends CWidget {
final float prevY = getY();
setX(newX);
setY(newY);
if (!this.isBuilding()) {
if (!isBuilding()) {
collision.translate(this, newX - prevX, newY - prevY);
}
checkRegionEvents(regionManager);
@ -957,8 +962,9 @@ public class CUnit extends CWidget {
this.containingRegions = this.priorContainingRegions;
this.priorContainingRegions = temp;
this.containingRegions.clear();
regionManager.checkRegions(this.collisionRectangle == null ? tempRect.set(this.getX(), this.getY(), 0, 0)
: this.collisionRectangle, regionCheckerImpl.reset(this, regionManager));
regionManager.checkRegions(
this.collisionRectangle == null ? tempRect.set(getX(), getY(), 0, 0) : this.collisionRectangle,
regionCheckerImpl.reset(this, regionManager));
for (final CRegion region : this.priorContainingRegions) {
if (!this.containingRegions.contains(region)) {
regionManager.onUnitLeaveRegion(this, region);
@ -1067,7 +1073,7 @@ public class CUnit extends CWidget {
boolean foundMatchingReturnFireAttack = false;
if (!simulation.getPlayer(getPlayerIndex()).hasAlliance(source.getPlayerIndex(), CAllianceType.PASSIVE)
&& !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
for (final CUnitAttack attack : this.getAttacks()) {
for (final CUnitAttack attack : getAttacks()) {
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
this.currentBehavior = getAttackBehavior().reset(OrderIds.attack, attack, source, false,
CBehaviorAttackListener.DO_NOTHING);
@ -1143,8 +1149,8 @@ public class CUnit extends CWidget {
}
final List<CUnit> xpReceivingHeroes = new ArrayList<>();
final int heroExpRange = gameplayConstants.getHeroExpRange();
simulation.getWorldCollision().enumUnitsInRect(new Rectangle(this.getX() - heroExpRange,
this.getY() - heroExpRange, heroExpRange * 2, heroExpRange * 2), new CUnitEnumFunction() {
simulation.getWorldCollision().enumUnitsInRect(new Rectangle(getX() - heroExpRange,
getY() - heroExpRange, heroExpRange * 2, heroExpRange * 2), new CUnitEnumFunction() {
@Override
public boolean call(final CUnit unit) {
if ((unit.distance(killedUnit) <= heroExpRange)
@ -1720,9 +1726,7 @@ public class CUnit extends CWidget {
}
public static enum QueueItemType {
UNIT,
RESEARCH,
HERO_REVIVE;
UNIT, RESEARCH, HERO_REVIVE;
}
public void setRallyPoint(final AbilityTarget target) {
@ -1905,6 +1909,15 @@ public class CUnit extends CWidget {
return null;
}
public CAbilityCargoHold getCargoData() {
for (final CAbility ability : this.abilities) {
if (ability instanceof CAbilityCargoHold) {
return (CAbilityCargoHold) ability;
}
}
return null;
}
public void setUnitSpecificAttacks(final List<CUnitAttack> unitSpecificAttacks) {
this.unitSpecificAttacks = unitSpecificAttacks;
}
@ -1992,8 +2005,7 @@ public class CUnit extends CWidget {
}
private static enum StateListenerUpdateType {
ADD,
REMOVE;
ADD, REMOVE;
}
private static final class StateListenerUpdate {

View File

@ -0,0 +1,126 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
public class CAbilityCargoHold extends AbstractGenericNoIconAbility {
private int cargoCapacity;
private final List<CUnit> cargoUnits;
private float duration;
private EnumSet<CTargetType> targetsAllowed;
public CAbilityCargoHold(final int handleId, final War3ID alias, final int cargoCapacity, final float duration,
final EnumSet<CTargetType> targetsAllowed) {
super(handleId, alias);
this.cargoCapacity = cargoCapacity;
this.cargoUnits = new ArrayList<>();
this.duration = duration;
this.targetsAllowed = targetsAllowed;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return null;
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.notAnActiveAbility();
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
public int getCargoCapacity() {
return this.cargoCapacity;
}
public float getDuration() {
return this.duration;
}
public List<CUnit> getCargoUnits() {
return this.cargoUnits;
}
public EnumSet<CTargetType> getTargetsAllowed() {
return this.targetsAllowed;
}
public void addUnit(final CUnit target) {
this.cargoUnits.add(target);
}
public void setCargoCapacity(final int cargoCapacity) {
this.cargoCapacity = cargoCapacity;
}
public void setDuration(final float duration) {
this.duration = duration;
}
public void setTargetsAllowed(final EnumSet<CTargetType> targetsAllowed) {
this.targetsAllowed = targetsAllowed;
}
}

View File

@ -0,0 +1,108 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericSingleIconNoSmartActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.cargohold.CBehaviorDrop;
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 CAbilityDrop extends AbstractGenericSingleIconNoSmartActiveAbility {
private float castRange;
private CBehaviorDrop behaviorDrop;
public CAbilityDrop(final int handleId, final War3ID alias, final float castRange) {
super(handleId, alias);
this.castRange = castRange;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorDrop = new CBehaviorDrop(unit, this);
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public int getBaseOrderId() {
return OrderIds.unloadall;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return this.behaviorDrop.reset(point);
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return null;
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.useOk();
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
@Override
public boolean isToggleOn() {
return false;
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
if (!unit.isMovementDisabled() || unit.canReach(target, this.castRange)) {
receiver.targetOk(target);
}
else {
receiver.targetOutsideRange();
}
}
@Override
protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
public float getCastRange() {
return this.castRange;
}
public void setCastRange(final float castRange) {
this.castRange = castRange;
}
}

View File

@ -0,0 +1,91 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold;
import java.util.ArrayList;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
public class CAbilityDropInstant extends AbstractGenericNoIconAbility {
private final int cargoCapacity;
private final List<CUnit> cargoUnits;
public CAbilityDropInstant(final int handleId, final War3ID alias, final int cargoCapacity) {
super(handleId, alias);
this.cargoCapacity = cargoCapacity;
this.cargoUnits = new ArrayList<>();
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return null;
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.notAnActiveAbility();
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
public int getCargoCapacity() {
return this.cargoCapacity;
}
}

View File

@ -0,0 +1,126 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericSingleIconActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.cargohold.CBehaviorLoad;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver.TargetType;
public class CAbilityLoad extends AbstractGenericSingleIconActiveAbility {
private float castRange;
private CBehaviorLoad behaviorLoad;
public CAbilityLoad(final int handleId, final War3ID alias, final float castRange) {
super(handleId, alias);
this.castRange = castRange;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorLoad = new CBehaviorLoad(unit, this);
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public int getBaseOrderId() {
return OrderIds.load;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return this.behaviorLoad.reset(target);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return null;
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.useOk();
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
@Override
public void onDeath(final CSimulation game, final CUnit cUnit) {
}
@Override
public boolean isToggleOn() {
return false;
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
if ((target instanceof CUnit) && target.canBeTargetedBy(game, unit, unit.getCargoData().getTargetsAllowed())) {
if (!unit.isMovementDisabled() || unit.canReach(target, this.castRange)) {
receiver.targetOk(target);
}
else {
receiver.targetOutsideRange();
}
}
else {
receiver.mustTargetType(TargetType.UNIT);
}
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
public float getCastRange() {
return this.castRange;
}
public void setCastRange(final float castRange) {
this.castRange = castRange;
}
@Override
protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
innerCheckCanTarget(game, unit, orderId, target, receiver);
}
@Override
protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
}

View File

@ -0,0 +1,39 @@
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.CAbilityTypeCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeCargoHoldLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionCargoHold extends AbstractCAbilityTypeDefinition<CAbilityTypeCargoHoldLevelData>
implements CAbilityTypeDefinition {
protected static final War3ID CARGO_CAPACITY = War3ID.fromString("Car1");
@Override
protected CAbilityTypeCargoHoldLevelData createLevelData(final MutableGameObject abilityEditorData,
final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final int cargoCapacity = abilityEditorData.getFieldAsInteger(CARGO_CAPACITY, level);
final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level);
final float duration = abilityEditorData.getFieldAsFloat(DURATION, level);
// final int goldCost = abilityEditorData.getFieldAsInteger(GOLD_COST, level);
// final int lumberCost = abilityEditorData.getFieldAsInteger(LUMBER_COST, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
return new CAbilityTypeCargoHoldLevelData(targetsAllowedAtLevel, cargoCapacity, duration);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeCargoHoldLevelData> levelData) {
return new CAbilityTypeCargoHold(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,32 @@
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.CAbilityTypeDrop;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeDropLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionDrop extends AbstractCAbilityTypeDefinition<CAbilityTypeDropLevelData>
implements CAbilityTypeDefinition {
@Override
protected CAbilityTypeDropLevelData createLevelData(final MutableGameObject abilityEditorData, final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
return new CAbilityTypeDropLevelData(targetsAllowedAtLevel, castRange);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeDropLevelData> levelData) {
return new CAbilityTypeDrop(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,32 @@
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.CAbilityTypeLoad;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeLoadLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionLoad extends AbstractCAbilityTypeDefinition<CAbilityTypeLoadLevelData>
implements CAbilityTypeDefinition {
@Override
protected CAbilityTypeLoadLevelData createLevelData(final MutableGameObject abilityEditorData, final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
return new CAbilityTypeLoadLevelData(targetsAllowedAtLevel, castRange);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeLoadLevelData> levelData) {
return new CAbilityTypeLoad(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,38 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
public class CAbilityTypeCargoHold extends CAbilityType<CAbilityTypeCargoHoldLevelData> {
public CAbilityTypeCargoHold(final War3ID alias, final War3ID code,
final List<CAbilityTypeCargoHoldLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeCargoHoldLevelData levelData = getLevelData(0);
return new CAbilityCargoHold(handleId, getAlias(), levelData.getCargoCapcity(), levelData.getDuration(),
levelData.getTargetsAllowed());
}
@Override
public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) {
final CAbilityTypeCargoHoldLevelData levelData = getLevelData(level - 1);
final CAbilityCargoHold heroAbility = ((CAbilityCargoHold) existingAbility);
heroAbility.setDuration(levelData.getDuration());
heroAbility.setCargoCapacity(levelData.getCargoCapcity());
heroAbility.setTargetsAllowed(levelData.getTargetsAllowed());
heroAbility.setLevel(level);
}
}

View File

@ -0,0 +1,27 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeCargoHoldLevelData extends CAbilityTypeLevelData {
private final int cargoCapcity;
private final float duration;
public CAbilityTypeCargoHoldLevelData(final EnumSet<CTargetType> targetsAllowed, final int cargoCapcity,
final float duration) {
super(targetsAllowed);
this.cargoCapcity = cargoCapcity;
this.duration = duration;
}
public int getCargoCapcity() {
return this.cargoCapcity;
}
public float getDuration() {
return this.duration;
}
}

View File

@ -0,0 +1,34 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityDrop;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
public class CAbilityTypeDrop extends CAbilityType<CAbilityTypeDropLevelData> {
public CAbilityTypeDrop(final War3ID alias, final War3ID code, final List<CAbilityTypeDropLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeDropLevelData levelData = getLevelData(0);
return new CAbilityDrop(handleId, getAlias(), levelData.getCastRange());
}
@Override
public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) {
final CAbilityTypeDropLevelData levelData = getLevelData(level - 1);
final CAbilityDrop heroAbility = ((CAbilityDrop) existingAbility);
heroAbility.setCastRange(levelData.getCastRange());
heroAbility.setLevel(level);
}
}

View File

@ -0,0 +1,20 @@
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 CAbilityTypeDropLevelData extends CAbilityTypeLevelData {
private final float castRange;
public CAbilityTypeDropLevelData(final EnumSet<CTargetType> targetsAllowed, final float castRange) {
super(targetsAllowed);
this.castRange = castRange;
}
public float getCastRange() {
return this.castRange;
}
}

View File

@ -0,0 +1,34 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityLoad;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.CLevelingAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
public class CAbilityTypeLoad extends CAbilityType<CAbilityTypeLoadLevelData> {
public CAbilityTypeLoad(final War3ID alias, final War3ID code, final List<CAbilityTypeLoadLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeLoadLevelData levelData = getLevelData(0);
return new CAbilityLoad(handleId, getAlias(), levelData.getCastRange());
}
@Override
public void setLevel(final CSimulation game, final CLevelingAbility existingAbility, final int level) {
final CAbilityTypeLoadLevelData levelData = getLevelData(level - 1);
final CAbilityLoad heroAbility = ((CAbilityLoad) existingAbility);
heroAbility.setCastRange(levelData.getCastRange());
heroAbility.setLevel(level);
}
}

View File

@ -0,0 +1,20 @@
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 CAbilityTypeLoadLevelData extends CAbilityTypeLevelData {
private final float castRange;
public CAbilityTypeLoadLevelData(final EnumSet<CTargetType> targetsAllowed, final float castRange) {
super(targetsAllowed);
this.castRange = castRange;
}
public float getCastRange() {
return this.castRange;
}
}

View File

@ -35,8 +35,14 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
@Override
public boolean isWithinRange(final CSimulation simulation) {
final CUnitType unitType = simulation.getUnitData().getUnitType(this.orderId);
return this.unit.canReachToPathing(0, simulation.getGameplayConstants().getBuildingAngle(),
unitType.getBuildingPathingPixelMap(), this.target.getX(), this.target.getY());
final BufferedImage buildingPathingPixelMap = unitType.getBuildingPathingPixelMap();
if (buildingPathingPixelMap != null) {
return this.unit.canReachToPathing(0, simulation.getGameplayConstants().getBuildingAngle(),
buildingPathingPixelMap, this.target.getX(), this.target.getY());
}
else {
return this.unit.canReach(this.target.getX(), this.target.getY(), 0);
}
}
@Override

View File

@ -0,0 +1,84 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.cargohold;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityDrop;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CBehaviorDrop extends CAbstractRangedBehavior {
private final CAbilityDrop ability;
private int lastDropTick = 0;
public CBehaviorDrop(final CUnit unit, final CAbilityDrop ability) {
super(unit);
this.ability = ability;
}
public CBehaviorDrop reset(final AbilityPointTarget target) {
innerReset(target, false);
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
final float castRange = this.ability.getCastRange();
return this.unit.canReach(this.target, castRange);
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinFacingWindow) {
final int gameTurnTick = simulation.getGameTurnTick();
final int deltaTicks = gameTurnTick - this.lastDropTick;
final CAbilityCargoHold cargoData = this.unit.getCargoData();
if (cargoData.getCargoUnits().isEmpty()) {
return this.unit.pollNextOrderBehavior(simulation);
}
// TODO i do a nonstandard Math.ceil() here to make this one feel a bit slower
final float durationTicks = (int) Math.ceil(cargoData.getDuration() / WarsmashConstants.SIMULATION_STEP_TIME);
if (deltaTicks >= durationTicks) {
simulation.unitSoundEffectEvent(this.unit, cargoData.getAlias());
final CUnit firstUnit = cargoData.getCargoUnits().remove(0);
firstUnit.setPointAndCheckUnstuck(this.target.getX(), this.target.getY(), simulation);
firstUnit.setHidden(false);
firstUnit.setPaused(false);
this.lastDropTick = gameTurnTick;
}
return this;
}
@Override
protected CBehavior updateOnInvalidTarget(final CSimulation simulation) {
return this.unit.pollNextOrderBehavior(simulation);
}
@Override
protected boolean checkTargetStillValid(final CSimulation simulation) {
return true;
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
@Override
public void begin(final CSimulation game) {
}
@Override
public void end(final CSimulation game, final boolean interrupted) {
}
@Override
public void endMove(final CSimulation game, final boolean interrupted) {
}
@Override
public int getHighlightOrderId() {
return OrderIds.unloadall;
}
}

View File

@ -0,0 +1,76 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.cargohold;
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.cargohold.CAbilityCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityLoad;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveAndTargetableVisitor;
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 CBehaviorLoad extends CAbstractRangedBehavior {
private final CAbilityLoad ability;
private final AbilityTargetStillAliveAndTargetableVisitor stillAliveVisitor;
public CBehaviorLoad(final CUnit unit, final CAbilityLoad ability) {
super(unit);
this.ability = ability;
this.stillAliveVisitor = new AbilityTargetStillAliveAndTargetableVisitor();
}
public CBehaviorLoad reset(final CWidget target) {
innerReset(target, false);
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
final float castRange = this.ability.getCastRange();
return this.unit.canReach(this.target, castRange);
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinFacingWindow) {
final CAbilityCargoHold cargoData = this.unit.getCargoData();
simulation.unitSoundEffectEvent(this.unit, cargoData.getAlias());
final CUnit targetUnit = (CUnit) this.target;
cargoData.addUnit(targetUnit);
targetUnit.setHidden(true);
targetUnit.setPaused(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(
this.stillAliveVisitor.reset(simulation, this.unit, this.unit.getCargoData().getTargetsAllowed()));
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
@Override
public void begin(final CSimulation game) {
}
@Override
public void end(final CSimulation game, final boolean interrupted) {
}
@Override
public void endMove(final CSimulation game, final boolean interrupted) {
}
@Override
public int getHighlightOrderId() {
return OrderIds.load;
}
}

View File

@ -24,7 +24,7 @@ public abstract class CBasePlayer implements CPlayerJass {
private final EnumMap<CPlayerState, Integer>[] taxRates;
private boolean onScoreScreen;
private boolean raceSelectable;
private CMapControl mapControl = CMapControl.NEUTRAL;
private CMapControl mapControl = CMapControl.NONE;
private CPlayerSlotState slotState = CPlayerSlotState.EMPTY;
private AIDifficulty aiDifficulty = null;
@ -167,7 +167,7 @@ public abstract class CBasePlayer implements CPlayerJass {
}
@Override
public boolean isSelectable() {
public boolean isRaceSelectable() {
return this.raceSelectable;
}

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
import java.util.EnumMap;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapFlag;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapPlacement;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CGameSpeed;
@ -26,11 +27,16 @@ public class War3MapConfig implements CPlayerAPI {
private CGameType gameTypeSelected;
public War3MapConfig(final int maxPlayers) {
// TODO should this be WarsmashConstants.MAX_PLAYERS instead of local
// constructor arg?
this.startLocations = new War3MapConfigStartLoc[maxPlayers];
this.players = new CBasePlayer[maxPlayers];
for (int i = 0; i < maxPlayers; i++) {
this.startLocations[i] = new War3MapConfigStartLoc();
this.players[i] = new War3MapConfigPlayer(i);
if (i >= (maxPlayers - 4)) {
this.players[i].setController(CMapControl.NEUTRAL);
}
}
}

View File

@ -14,10 +14,12 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.def
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionAcolyteHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionBlight;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionBlightedGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionCarrionSwarmDummy;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionChannelTest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionCoupleInstant;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionDrop;
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.CAbilityTypeDefinitionHarvestLumber;
@ -31,6 +33,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.def
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemLifeBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemPermanentStatGain;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemStatBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionLoad;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionWispHarvest;
@ -82,6 +85,9 @@ public class CAbilityData {
this.codeToAbilityTypeDefinition.put(War3ID.fromString("AIde"), new CAbilityTypeDefinitionItemDefenseBonus());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("AImi"), new CAbilityTypeDefinitionItemLifeBonus());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("AIml"), new CAbilityTypeDefinitionItemLifeBonus());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Acar"), new CAbilityTypeDefinitionCargoHold());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Aloa"), new CAbilityTypeDefinitionLoad());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Adro"), new CAbilityTypeDefinitionDrop());
}
public CAbilityType<?> getAbilityType(final War3ID alias) {

View File

@ -44,7 +44,7 @@ public interface CPlayerJass {
int getColor();
boolean isSelectable();
boolean isRaceSelectable();
CMapControl getController();

View File

@ -87,4 +87,6 @@ public interface SimulationRenderController {
void setBlight(float x, float y, float radius, boolean blighted);
void createSpellEffectFacing(War3ID alias, float harvestStandX, float harvestStandY, float angle);
void unitUpdatedType(CUnit unit, War3ID typeId);
}

View File

@ -0,0 +1,210 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.frames.AbstractRenderableFrame;
import com.etheller.warsmash.parsers.fdf.frames.SimpleStatusBarFrame;
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableActionFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.MultiSelectionIconListener;
public class CargoHoldUnitIcon extends AbstractRenderableFrame implements ClickableActionFrame {
public static final float HP_BAR_HEIGHT_RATIO = 0.175f;
public static final float HP_BAR_SPACING_RATIO = 0.02f;
private TextureFrame iconFrame;
private final MultiSelectionIconListener clickListener;
private float defaultWidth;
private float defaultHeight;
private final int queueIconIndexId;
private String toolTip;
private String uberTip;
private boolean focused;
private SimpleStatusBarFrame hpBarFrame;
public CargoHoldUnitIcon(final String name, final UIFrame parent, final MultiSelectionIconListener clickListener,
final int queueIconIndexId) {
super(name, parent);
this.clickListener = clickListener;
this.queueIconIndexId = queueIconIndexId;
}
public void set(final TextureFrame iconFrame, final SimpleStatusBarFrame hpBarFrame) {
this.iconFrame = iconFrame;
this.hpBarFrame = hpBarFrame;
setVisible(true);
}
public void clear() {
setVisible(false);
}
public void setTexture(final Texture texture) {
this.iconFrame.setTexture(texture);
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
this.iconFrame.positionBounds(gameUI, viewport);
this.hpBarFrame.positionBounds(gameUI, viewport);
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
this.iconFrame.render(batch, baseFont, glyphLayout);
this.hpBarFrame.render(batch, baseFont, glyphLayout);
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
return this;
}
return super.touchDown(screenX, screenY, button);
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
return this;
}
return super.touchUp(screenX, screenY, button);
}
@Override
public void onClick(final int button) {
this.clickListener.multiSelectIconClicked(this.queueIconIndexId);
}
@Override
public void mouseDragged(final GameUI rootFrame, final Viewport uiViewport, final float x, final float y) {
}
@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);
}
private void innerSetDimensions(final float newWidth, final float newHeight) {
this.iconFrame.setWidth(newWidth);
this.iconFrame.setHeight(newHeight);
this.hpBarFrame.setWidth(newWidth * 1.05f);
this.hpBarFrame.setHeight(newHeight * HP_BAR_HEIGHT_RATIO);
}
public void showUnFocused(final GameUI gameUI, final Viewport uiViewport) {
final float newWidth = this.defaultWidth * 0.75f;
final float newHeight = this.defaultHeight * 0.75f;
innerSetDimensions(newWidth, newHeight);
positionBounds(gameUI, uiViewport);
this.focused = false;
}
public void showFocused(final GameUI gameUI, final Viewport uiViewport) {
innerSetDimensions(this.defaultWidth, this.defaultHeight);
positionBounds(gameUI, uiViewport);
this.focused = true;
}
public void showMousePressed(final GameUI gameUI, final Viewport uiViewport) {
final float ratio = this.focused ? 0.95f : 0.70f;
final float newWidth = this.defaultWidth * ratio;
final float newHeight = this.defaultHeight * ratio;
innerSetDimensions(newWidth, newHeight);
positionBounds(gameUI, uiViewport);
}
@Override
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
this.clickListener.multiSelectIconPress(this.queueIconIndexId);
showMousePressed(gameUI, uiViewport);
}
public void showMouseReleased(final GameUI gameUI, final Viewport uiViewport) {
final float ratio = this.focused ? 1.00f : 0.75f;
final float newWidth = this.defaultWidth * ratio;
final float newHeight = this.defaultHeight * ratio;
innerSetDimensions(newWidth, newHeight);
positionBounds(gameUI, uiViewport);
}
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
this.clickListener.multiSelectIconRelease(this.queueIconIndexId);
showMouseReleased(gameUI, uiViewport);
}
@Override
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
return this;
}
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 this.toolTip;
}
@Override
public String getUberTip() {
return this.uberTip;
}
@Override
public int getToolTipFoodCost() {
return 0;
}
@Override
public int getToolTipGoldCost() {
return 0;
}
@Override
public int getToolTipLumberCost() {
return 0;
}
@Override
public int getToolTipManaCost() {
return 0;
}
public void setLifeRatioRemaining(final float lifeRatioRemaining) {
this.hpBarFrame.getBarFrame().setColor(Math.min(1.0f, 2.0f - (lifeRatioRemaining * 2)),
Math.min(1.0f, lifeRatioRemaining * 2), 0, 1.0f);
this.hpBarFrame.setValue(lifeRatioRemaining);
}
}

View File

@ -130,6 +130,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.cargohold.CAbilityCargoHold;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
@ -246,6 +247,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private QueueIcon selectWorkerInsideFrame;
private final UIFrame[] selectedUnitHighlightBackdrop = new UIFrame[WarsmashConstants.MAX_SELECTION_SIZE];
private final MultiSelectionIcon[] selectedUnitFrames = new MultiSelectionIcon[WarsmashConstants.MAX_SELECTION_SIZE];
private final UIFrame[] cargoBackdrop = new UIFrame[WarsmashConstants.MAX_SELECTION_SIZE];
private final MultiSelectionIcon[] cargoUnitFrames = new MultiSelectionIcon[WarsmashConstants.MAX_SELECTION_SIZE];
private UIFrame attack1Icon;
private TextureFrame attack1IconBackdrop;
@ -358,6 +361,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private long lastUnitClickTime = 0;
private RenderWidget lastClickUnit;
private MultiSelectionIconListener multiSelectClickListener;
private MultiSelectionIconListener cargoClickListener;
private float frontQueueIconWidth;
private int draggingMouseButton;
private Music[] currentMusics;
@ -770,23 +774,58 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
final int halfSelectionMaxSize = this.selectedUnitFrames.length / 2;
for (int i = 0; i < this.selectedUnitFrames.length; i++) {
final FilterModeTextureFrame selectedSubgroupHighlightBackdrop = new FilterModeTextureFrame(
"SmashMultiSelectUnitIconHighlightBackdrop", this.smashSimpleInfoPanel, true,
new Vector4Definition(0, 1, 0, 1));
selectedSubgroupHighlightBackdrop.setFilterMode(FilterMode.ADDITIVE);
this.selectedUnitHighlightBackdrop[i] = selectedSubgroupHighlightBackdrop;
selectedSubgroupHighlightBackdrop.setTexture("SelectedSubgroupHighlight", this.rootFrame);
selectedSubgroupHighlightBackdrop.setWidth(this.frontQueueIconWidth * 1.37f);
selectedSubgroupHighlightBackdrop.setHeight(this.frontQueueIconWidth * 1.75f);
selectedSubgroupHighlightBackdrop.setColor(1.0f, 1.0f, 0.0f, 1.0f);
this.rootFrame.add(selectedSubgroupHighlightBackdrop);
selectedSubgroupHighlightBackdrop
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.smashSimpleInfoPanel, FramePoint.TOPLEFT,
((-this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * .10f)
+ (this.frontQueueIconWidth * 1.10f * (i % halfSelectionMaxSize)),
(((this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * -.75f))
- (this.frontQueueIconWidth * 1.5f * (i / halfSelectionMaxSize))));
{
final FilterModeTextureFrame selectedSubgroupHighlightBackdrop = new FilterModeTextureFrame(
"SmashMultiSelectUnitIconHighlightBackdrop", this.smashSimpleInfoPanel, true,
new Vector4Definition(0, 1, 0, 1));
selectedSubgroupHighlightBackdrop.setFilterMode(FilterMode.ADDITIVE);
this.selectedUnitHighlightBackdrop[i] = selectedSubgroupHighlightBackdrop;
selectedSubgroupHighlightBackdrop.setTexture("SelectedSubgroupHighlight", this.rootFrame);
selectedSubgroupHighlightBackdrop.setWidth(this.frontQueueIconWidth * 1.37f);
selectedSubgroupHighlightBackdrop.setHeight(this.frontQueueIconWidth * 1.75f);
selectedSubgroupHighlightBackdrop.setColor(1.0f, 1.0f, 0.0f, 1.0f);
this.rootFrame.add(selectedSubgroupHighlightBackdrop);
selectedSubgroupHighlightBackdrop
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.smashSimpleInfoPanel, FramePoint.TOPLEFT,
((-this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * .10f)
+ (this.frontQueueIconWidth * 1.10f * (i % halfSelectionMaxSize)),
(((this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * -.75f))
- (this.frontQueueIconWidth * 1.5f * (i / halfSelectionMaxSize))));
}
{
final TextureFrame cargoBackdrop = new TextureFrame("SmashCargoBackdrop", this.smashSimpleInfoPanel,
true, new Vector4Definition(0, 1, 0, 1));
cargoBackdrop.setVisible(false);
this.cargoBackdrop[i] = cargoBackdrop;
cargoBackdrop.setTexture("CargoBackdrop", this.rootFrame);
cargoBackdrop.setWidth(this.frontQueueIconWidth * 1.37f);
cargoBackdrop.setHeight(this.frontQueueIconWidth * 1.75f);
cargoBackdrop.setColor(1.0f, 1.0f, 0.0f, 1.0f);
this.rootFrame.add(cargoBackdrop);
cargoBackdrop
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.smashSimpleInfoPanel, FramePoint.TOPLEFT,
((-this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * .10f)
+ (this.frontQueueIconWidth * 1.10f * (i % halfSelectionMaxSize)),
(((this.frontQueueIconWidth * .37f) / 2) + (this.frontQueueIconWidth * -.75f))
- (this.frontQueueIconWidth * 1.5f * (i / halfSelectionMaxSize))));
}
}
this.cargoClickListener = new MultiSelectionIconListener() {
@Override
public void multiSelectIconRelease(final int index) {
}
@Override
public void multiSelectIconPress(final int index) {
}
@Override
public void multiSelectIconClicked(final int index) {
}
};
this.multiSelectClickListener = new MultiSelectionIconListener() {
@Override
public void multiSelectIconClicked(final int index) {
@ -856,6 +895,49 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.selectedUnitFrames[i].setVisible(false);
}
for (int i = 0; i < this.cargoUnitFrames.length; i++) {
this.cargoUnitFrames[i] = new MultiSelectionIcon("SmashMultiSelectUnitIcon", this.smashSimpleInfoPanel,
this.cargoClickListener, i);
this.cargoUnitFrames[i].setVisible(false);
final TextureFrame cargoUnitIconFrameBackdrop = new TextureFrame("SmashCargoUnitIconBackdrop",
this.cargoUnitFrames[i], false, new Vector4Definition(0, 1, 0, 1));
final SimpleStatusBarFrame hpBarFrame = new SimpleStatusBarFrame(
"SmashMultiSelectHpBar" + this.hpBarFrameIndex, this.rootFrame, true, true, 3.0f);
hpBarFrame.getBarFrame().setTexture("SimpleHpBarConsole", this.rootFrame);
hpBarFrame.getBorderFrame().setTexture("Textures\\Black32.blp", this.rootFrame);
hpBarFrame.setWidth(this.frontQueueIconWidth);
hpBarFrame.setHeight(this.frontQueueIconWidth * MultiSelectionIcon.HP_BAR_HEIGHT_RATIO);
hpBarFrame.addSetPoint(new SetPoint(FramePoint.TOP, cargoUnitIconFrameBackdrop, FramePoint.BOTTOM, 0,
-this.frontQueueIconWidth * MultiSelectionIcon.HP_BAR_SPACING_RATIO));
final SimpleStatusBarFrame manaBarFrame = new SimpleStatusBarFrame(
"SmashMultiSelectManaBar" + this.hpBarFrameIndex, this.rootFrame, true, true, 3.0f);
manaBarFrame.getBarFrame().setTexture("SimpleManaBarConsole", this.rootFrame);
manaBarFrame.getBorderFrame().setTexture("Textures\\Black32.blp", this.rootFrame);
manaBarFrame.setWidth(this.frontQueueIconWidth);
manaBarFrame.setHeight(this.frontQueueIconWidth * MultiSelectionIcon.HP_BAR_HEIGHT_RATIO);
manaBarFrame.addSetPoint(new SetPoint(FramePoint.TOP, hpBarFrame, FramePoint.BOTTOM, 0,
-this.frontQueueIconWidth * MultiSelectionIcon.HP_BAR_SPACING_RATIO));
manaBarFrame.getBarFrame().setColor(0f, 0f, 1f, 1f);
this.cargoUnitFrames[i].set(cargoUnitIconFrameBackdrop, hpBarFrame, manaBarFrame);
cargoUnitIconFrameBackdrop
.addSetPoint(new SetPoint(FramePoint.CENTER, this.cargoUnitFrames[i], FramePoint.CENTER, 0, 0));
this.cargoUnitFrames[i]
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.smashSimpleInfoPanel, FramePoint.TOPLEFT,
(this.frontQueueIconWidth * .10f)
+ (this.frontQueueIconWidth * 1.10f * (i % halfSelectionMaxSize)),
(this.frontQueueIconWidth * -.75f)
- (this.frontQueueIconWidth * 1.5f * (i / halfSelectionMaxSize))));
this.cargoUnitFrames[i].setWidth(this.frontQueueIconWidth);
this.cargoUnitFrames[i].setHeight(this.frontQueueIconWidth);
cargoUnitIconFrameBackdrop.setWidth(this.frontQueueIconWidth);
cargoUnitIconFrameBackdrop.setHeight(this.frontQueueIconWidth);
this.rootFrame.add(this.cargoUnitFrames[i]);
this.cargoUnitFrames[i].setVisible(false);
}
this.smashAttack1IconWrapper = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashSimpleInfoPanelIconDamage",
this.simpleInfoPanelUnitDetail, 0);
@ -2529,167 +2611,174 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.selectWorkerInsideFrame.setVisible(false);
}
else {
for (final QueueIcon queueIconFrame : this.queueIconFrames) {
queueIconFrame.setVisible(false);
}
this.simpleInfoPanelBuildingDetail.setVisible(false);
this.simpleInfoPanelUnitDetail.setVisible(!multiSelect);
final String unitTypeName = simulationUnit.getUnitType().getName();
final CAbilityCargoHold cargoData = simulationUnit.getCargoData();
if (cargoData != null) {
final boolean anyAttacks = simulationUnit.getAttacks().size() > 0;
final boolean constructing = simulationUnit.isConstructingOrUpgrading();
final UIFrame localArmorIcon = this.armorIcon;
final TextureFrame localArmorIconBackdrop = this.armorIconBackdrop;
final StringFrame localArmorInfoPanelIconValue = this.armorInfoPanelIconValue;
if (anyAttacks && !constructing) {
final CUnitAttack attackOne = simulationUnit.getAttacks().get(0);
this.attack1Icon.setVisible(attackOne.isShowUI());
this.attack1IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackOne.getAttackType()));
String attackOneDmgText = attackOne.getMinDamageDisplay() + " - " + attackOne.getMaxDamageDisplay();
final int attackOneTemporaryDamageBonus = attackOne.getTotalTemporaryDamageBonus();
if (attackOneTemporaryDamageBonus != 0) {
attackOneDmgText += (attackOneTemporaryDamageBonus > 0 ? "|cFF00FF00 +" : "|cFFFF0000 ")
+ attackOneTemporaryDamageBonus + "";
}
else {
for (final QueueIcon queueIconFrame : this.queueIconFrames) {
queueIconFrame.setVisible(false);
}
this.rootFrame.setText(this.attack1InfoPanelIconValue, attackOneDmgText);
if (simulationUnit.getAttacks().size() > 1) {
final CUnitAttack attackTwo = simulationUnit.getAttacks().get(1);
this.attack2Icon.setVisible(attackTwo.isShowUI());
this.attack2IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackTwo.getAttackType()));
String attackTwoDmgText = attackTwo.getMinDamage() + " - " + attackTwo.getMaxDamage();
final int attackTwoTemporaryDamageBonus = attackTwo.getTotalTemporaryDamageBonus();
if (attackTwoTemporaryDamageBonus != 0) {
attackTwoDmgText += (attackTwoTemporaryDamageBonus > 0 ? "|cFF00FF00 +" : "|cFFFF0000 ")
+ attackTwoTemporaryDamageBonus + "";
this.simpleInfoPanelBuildingDetail.setVisible(false);
this.simpleInfoPanelUnitDetail.setVisible(!multiSelect);
final String unitTypeName = simulationUnit.getUnitType().getName();
final boolean anyAttacks = simulationUnit.getAttacks().size() > 0;
final boolean constructing = simulationUnit.isConstructingOrUpgrading();
final UIFrame localArmorIcon = this.armorIcon;
final TextureFrame localArmorIconBackdrop = this.armorIconBackdrop;
final StringFrame localArmorInfoPanelIconValue = this.armorInfoPanelIconValue;
if (anyAttacks && !constructing) {
final CUnitAttack attackOne = simulationUnit.getAttacks().get(0);
this.attack1Icon.setVisible(attackOne.isShowUI());
this.attack1IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackOne.getAttackType()));
String attackOneDmgText = attackOne.getMinDamageDisplay() + " - " + attackOne.getMaxDamageDisplay();
final int attackOneTemporaryDamageBonus = attackOne.getTotalTemporaryDamageBonus();
if (attackOneTemporaryDamageBonus != 0) {
attackOneDmgText += (attackOneTemporaryDamageBonus > 0 ? "|cFF00FF00 +" : "|cFFFF0000 ")
+ attackOneTemporaryDamageBonus + "";
}
this.rootFrame.setText(this.attack2InfoPanelIconValue, attackTwoDmgText);
}
else {
this.attack2Icon.setVisible(false);
}
this.smashArmorIconWrapper.addSetPoint(
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.0705f)));
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
}
else {
this.attack1Icon.setVisible(false);
this.attack2Icon.setVisible(false);
this.smashArmorIconWrapper.addSetPoint(
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.040f)));
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
}
final CAbilityHero heroData = simulationUnit.getHeroData();
final boolean hero = heroData != null;
this.heroInfoPanel.setVisible(hero);
if (hero) {
final CPrimaryAttribute primaryAttribute = simulationUnit.getUnitType().getPrimaryAttribute();
String iconKey;
switch (primaryAttribute) {
case AGILITY:
iconKey = "InfoPanelIconHeroIconAGI";
break;
case INTELLIGENCE:
iconKey = "InfoPanelIconHeroIconINT";
break;
default:
case STRENGTH:
iconKey = "InfoPanelIconHeroIconSTR";
break;
}
this.primaryAttributeIcon.setTexture(iconKey, this.rootFrame);
this.rootFrame.setText(this.strengthValue, heroData.getStrength().getDisplayText());
this.rootFrame.setText(this.agilityValue, heroData.getAgility().getDisplayText());
this.rootFrame.setText(this.intelligenceValue, heroData.getIntelligence().getDisplayText());
final String infopanelLevelClass = this.rootFrame.getTemplates()
.getDecoratedString("INFOPANEL_LEVEL_CLASS").replace("%u", "%d"); // :(
final int heroLevel = heroData.getHeroLevel();
this.simpleClassValue.setVisible(true);
this.rootFrame.setText(this.simpleClassValue,
String.format(infopanelLevelClass, heroLevel, unitTypeName));
this.rootFrame.setText(this.simpleNameValue, heroData.getProperName());
this.simpleHeroLevelBar.setVisible(true);
final CGameplayConstants gameplayConstants = this.war3MapViewer.simulation.getGameplayConstants();
this.simpleHeroLevelBar.setValue((heroData.getXp() - gameplayConstants.getNeedHeroXPSum(heroLevel - 1))
/ (float) gameplayConstants.getNeedHeroXP(heroLevel));
}
else {
this.simpleClassValue.setVisible(!simulationUnit.isBuilding());
this.rootFrame.setText(this.simpleNameValue, unitTypeName);
String classText = null;
for (final CUnitClassification classification : simulationUnit.getClassifications()) {
if (classification.getDisplayName() != null) {
classText = classification.getDisplayName();
}
}
if (classText != null) {
this.rootFrame.setText(this.simpleClassValue, classText);
}
else {
this.rootFrame.setText(this.simpleClassValue, "");
}
this.simpleHeroLevelBar.setVisible(false);
}
localArmorIcon.setVisible(!constructing);
this.simpleBuildTimeIndicator.setVisible(constructing);
this.simpleBuildingBuildTimeIndicator.setVisible(false);
if (constructing) {
War3ID constructingTypeId = simulationUnit.getTypeId();
if (simulationUnit.isUpgrading()) {
constructingTypeId = simulationUnit.getUpgradeIdType();
}
this.rootFrame.setText(this.simpleBuildingActionLabel,
this.rootFrame.getTemplates().getDecoratedString("CONSTRUCTING"));
this.queueIconFrames[0].setVisible(true);
this.queueIconFrames[0]
.setTexture(this.war3MapViewer.getAbilityDataUI().getUnitUI(constructingTypeId).getIcon());
if (simulationUnit.getWorkerInside() != null) {
this.selectWorkerInsideFrame.setVisible(true);
this.selectWorkerInsideFrame.setTexture(this.war3MapViewer.getAbilityDataUI()
.getUnitUI(simulationUnit.getWorkerInside().getTypeId()).getIcon());
}
else {
this.selectWorkerInsideFrame.setVisible(false);
}
}
else {
this.rootFrame.setText(this.simpleBuildingActionLabel, "");
this.selectWorkerInsideFrame.setVisible(false);
}
final Texture defenseTexture = this.defenseBackdrops
.getTexture(simulationUnit.getUnitType().getDefenseType());
if (defenseTexture == null) {
throw new RuntimeException(simulationUnit.getUnitType().getDefenseType() + " can't find texture!");
}
localArmorIconBackdrop.setTexture(defenseTexture);
String defenseDisplayString;
if (simulationUnit.isInvulnerable()) {
defenseDisplayString = this.rootFrame.getTemplates().getDecoratedString("INVULNERABLE");
}
else {
defenseDisplayString = Integer.toString(simulationUnit.getCurrentDefenseDisplay());
final float temporaryDefenseBonus = simulationUnit.getTotalTemporaryDefenseBonus();
if (temporaryDefenseBonus != 0) {
if (temporaryDefenseBonus > 0) {
defenseDisplayString += "|cFF00FF00 +" + String.format("%.1f", temporaryDefenseBonus) + "";
this.rootFrame.setText(this.attack1InfoPanelIconValue, attackOneDmgText);
if (simulationUnit.getAttacks().size() > 1) {
final CUnitAttack attackTwo = simulationUnit.getAttacks().get(1);
this.attack2Icon.setVisible(attackTwo.isShowUI());
this.attack2IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackTwo.getAttackType()));
String attackTwoDmgText = attackTwo.getMinDamage() + " - " + attackTwo.getMaxDamage();
final int attackTwoTemporaryDamageBonus = attackTwo.getTotalTemporaryDamageBonus();
if (attackTwoTemporaryDamageBonus != 0) {
attackTwoDmgText += (attackTwoTemporaryDamageBonus > 0 ? "|cFF00FF00 +" : "|cFFFF0000 ")
+ attackTwoTemporaryDamageBonus + "";
}
this.rootFrame.setText(this.attack2InfoPanelIconValue, attackTwoDmgText);
}
else {
defenseDisplayString += "|cFFFF0000 " + String.format("%.1f", temporaryDefenseBonus) + "";
this.attack2Icon.setVisible(false);
}
this.smashArmorIconWrapper.addSetPoint(
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.0705f)));
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
}
else {
this.attack1Icon.setVisible(false);
this.attack2Icon.setVisible(false);
this.smashArmorIconWrapper.addSetPoint(
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.040f)));
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
}
final CAbilityHero heroData = simulationUnit.getHeroData();
final boolean hero = heroData != null;
this.heroInfoPanel.setVisible(hero);
if (hero) {
final CPrimaryAttribute primaryAttribute = simulationUnit.getUnitType().getPrimaryAttribute();
String iconKey;
switch (primaryAttribute) {
case AGILITY:
iconKey = "InfoPanelIconHeroIconAGI";
break;
case INTELLIGENCE:
iconKey = "InfoPanelIconHeroIconINT";
break;
default:
case STRENGTH:
iconKey = "InfoPanelIconHeroIconSTR";
break;
}
this.primaryAttributeIcon.setTexture(iconKey, this.rootFrame);
this.rootFrame.setText(this.strengthValue, heroData.getStrength().getDisplayText());
this.rootFrame.setText(this.agilityValue, heroData.getAgility().getDisplayText());
this.rootFrame.setText(this.intelligenceValue, heroData.getIntelligence().getDisplayText());
final String infopanelLevelClass = this.rootFrame.getTemplates()
.getDecoratedString("INFOPANEL_LEVEL_CLASS").replace("%u", "%d"); // :(
final int heroLevel = heroData.getHeroLevel();
this.simpleClassValue.setVisible(true);
this.rootFrame.setText(this.simpleClassValue,
String.format(infopanelLevelClass, heroLevel, unitTypeName));
this.rootFrame.setText(this.simpleNameValue, heroData.getProperName());
this.simpleHeroLevelBar.setVisible(true);
final CGameplayConstants gameplayConstants = this.war3MapViewer.simulation.getGameplayConstants();
this.simpleHeroLevelBar
.setValue((heroData.getXp() - gameplayConstants.getNeedHeroXPSum(heroLevel - 1))
/ (float) gameplayConstants.getNeedHeroXP(heroLevel));
}
else {
this.simpleClassValue.setVisible(!simulationUnit.isBuilding());
this.rootFrame.setText(this.simpleNameValue, unitTypeName);
String classText = null;
for (final CUnitClassification classification : simulationUnit.getClassifications()) {
if (classification.getDisplayName() != null) {
classText = classification.getDisplayName();
}
}
if (classText != null) {
this.rootFrame.setText(this.simpleClassValue, classText);
}
else {
this.rootFrame.setText(this.simpleClassValue, "");
}
this.simpleHeroLevelBar.setVisible(false);
}
localArmorIcon.setVisible(!constructing);
this.simpleBuildTimeIndicator.setVisible(constructing);
this.simpleBuildingBuildTimeIndicator.setVisible(false);
if (constructing) {
War3ID constructingTypeId = simulationUnit.getTypeId();
if (simulationUnit.isUpgrading()) {
constructingTypeId = simulationUnit.getUpgradeIdType();
}
this.rootFrame.setText(this.simpleBuildingActionLabel,
this.rootFrame.getTemplates().getDecoratedString("CONSTRUCTING"));
this.queueIconFrames[0].setVisible(true);
this.queueIconFrames[0]
.setTexture(this.war3MapViewer.getAbilityDataUI().getUnitUI(constructingTypeId).getIcon());
if (simulationUnit.getWorkerInside() != null) {
this.selectWorkerInsideFrame.setVisible(true);
this.selectWorkerInsideFrame.setTexture(this.war3MapViewer.getAbilityDataUI()
.getUnitUI(simulationUnit.getWorkerInside().getTypeId()).getIcon());
}
else {
this.selectWorkerInsideFrame.setVisible(false);
}
}
else {
this.rootFrame.setText(this.simpleBuildingActionLabel, "");
this.selectWorkerInsideFrame.setVisible(false);
}
final Texture defenseTexture = this.defenseBackdrops
.getTexture(simulationUnit.getUnitType().getDefenseType());
if (defenseTexture == null) {
throw new RuntimeException(simulationUnit.getUnitType().getDefenseType() + " can't find texture!");
}
localArmorIconBackdrop.setTexture(defenseTexture);
String defenseDisplayString;
if (simulationUnit.isInvulnerable()) {
defenseDisplayString = this.rootFrame.getTemplates().getDecoratedString("INVULNERABLE");
}
else {
defenseDisplayString = Integer.toString(simulationUnit.getCurrentDefenseDisplay());
final float temporaryDefenseBonus = simulationUnit.getTotalTemporaryDefenseBonus();
if (temporaryDefenseBonus != 0) {
if (temporaryDefenseBonus > 0) {
defenseDisplayString += "|cFF00FF00 +" + String.format("%.1f", temporaryDefenseBonus) + "";
}
else {
defenseDisplayString += "|cFFFF0000 " + String.format("%.1f", temporaryDefenseBonus) + "";
}
}
}
this.rootFrame.setText(localArmorInfoPanelIconValue, defenseDisplayString);
}
this.rootFrame.setText(localArmorInfoPanelIconValue, defenseDisplayString);
}
final CAbilityInventory inventory = simulationUnit.getInventoryData();
this.inventoryCover.setVisible(inventory == null);

View File

@ -835,7 +835,7 @@ public class MenuUI {
MenuUI.this.skirmishMapInfoPane.setMap(MenuUI.this.rootFrame, MenuUI.this.uiViewport, map,
mapInfo, war3MapConfig);
teamSetupPane.setMap(map, MenuUI.this.rootFrame, MenuUI.this.uiViewport, war3MapConfig,
mapInfo.getPlayers().size());
mapInfo.getPlayers().size(), mapInfo);
MenuUI.this.currentMapConfig = war3MapConfig;
}
catch (final IOException e) {

View File

@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.frames.BackdropFrame;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
@ -13,11 +14,15 @@ import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.parsers.w3x.War3Map;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3iFlags;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.Element;
import com.etheller.warsmash.units.StandardObjectData;
import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
public class MapInfoPane {
private final UIFrame mapInfoPaneFrame;
@ -29,13 +34,14 @@ public class MapInfoPane {
private final StringFrame mapSizeValue;
private final StringFrame mapDescValue;
private final StringFrame mapTilesetValue;
private final BackdropFrame maxPlayersIcon;
public MapInfoPane(final GameUI rootFrame, final Viewport uiViewport, final SimpleFrame container) {
this.mapInfoPaneFrame = rootFrame.createFrame("MapInfoPane", container, 0, 0);
this.mapInfoPaneFrame.setSetAllPoints(true);
container.add(this.mapInfoPaneFrame);
final UIFrame maxPlayersIcon = rootFrame.getFrameByName("MaxPlayersIcon", 0);
this.maxPlayersIcon = (BackdropFrame) rootFrame.getFrameByName("MaxPlayersIcon", 0);
this.maxPlayersValue = (StringFrame) rootFrame.getFrameByName("MaxPlayersValue", 0);
this.suggestedPlayersValue = (StringFrame) rootFrame.getFrameByName("SuggestedPlayersValue", 0);
this.mapSizeValue = (StringFrame) rootFrame.getFrameByName("MapSizeValue", 0);
@ -57,9 +63,10 @@ public class MapInfoPane {
// TODO there might be some kind of layout manager system that is supposed to do
// the below anchoring automatically but I don't have that atm
maxPlayersIcon.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.mapInfoPaneFrame, FramePoint.TOPLEFT, 0, 0));
this.maxPlayersIcon
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.mapInfoPaneFrame, FramePoint.TOPLEFT, 0, 0));
minimapImageFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, maxPlayersIcon, FramePoint.BOTTOMLEFT, 0,
minimapImageFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.maxPlayersIcon, FramePoint.BOTTOMLEFT, 0,
GameUI.convertY(uiViewport, -0.01f)));
suggestedPlayersLabel.addSetPoint(new SetPoint(FramePoint.TOPLEFT, minimapImageFrame, FramePoint.BOTTOMLEFT, 0,
GameUI.convertY(uiViewport, -0.01f)));
@ -80,10 +87,23 @@ public class MapInfoPane {
public void setMap(final GameUI rootFrame, final Viewport uiViewport, final War3Map map, final War3MapW3i mapInfo,
final War3MapConfig war3MapConfig) throws IOException {
rootFrame.setText(this.mapNameValue, rootFrame.getTrigStr(war3MapConfig.getMapName()));
rootFrame.setText(this.maxPlayersValue, Integer.toString(mapInfo.getPlayers().size()));
int usedPlayerCount = 0;
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer player = war3MapConfig.getPlayer(i);
if (player.getController() == CMapControl.USER) {
usedPlayerCount++;
}
}
rootFrame.setText(this.maxPlayersValue, Integer.toString(usedPlayerCount));
rootFrame.setText(this.suggestedPlayersValue, rootFrame.getTrigStr(mapInfo.getRecommendedPlayers()));
rootFrame.setText(this.mapDescValue, rootFrame.getTrigStr(war3MapConfig.getMapDescription()));
rootFrame.setText(this.mapSizeValue, rootFrame.getTrigStr(Integer.toString(mapInfo.getPlayableSize()[0])));
if (mapInfo.hasFlag(War3MapW3iFlags.MELEE_MAP)) {
this.maxPlayersIcon.setBackground(rootFrame.loadTexture("ui\\widgets\\glues\\icon-file-melee.blp"));
}
else {
this.maxPlayersIcon.setBackground(rootFrame.loadTexture("ui\\widgets\\glues\\icon-file-ums.blp"));
}
final StandardObjectData standardObjectData = new StandardObjectData(map);
final DataTable worldEditData = standardObjectData.getWorldEditData();
@ -93,11 +113,16 @@ public class MapInfoPane {
rootFrame.setText(this.mapTilesetValue, rootFrame.getTrigStr(tileSetNameString));
Texture minimapTexture;
try {
minimapTexture = ImageUtils.getAnyExtensionTexture(map, "war3mapPreview.blp");
if (mapInfo.hasFlag(War3MapW3iFlags.HIDE_MINIMAP_IN_PREVIEW_SCREENS)) {
minimapTexture = ImageUtils.getAnyExtensionTexture(map, "ui\\widgets\\glues\\minimap-unknown.blp");
}
catch (final Exception exc) {
minimapTexture = ImageUtils.getAnyExtensionTexture(map, "war3mapMap.blp");
else {
try {
minimapTexture = ImageUtils.getAnyExtensionTexture(map, "war3mapPreview.blp");
}
catch (final Exception exc) {
minimapTexture = ImageUtils.getAnyExtensionTexture(map, "war3mapMap.blp");
}
}
this.minimapImageTextureFrame.setTexture(minimapTexture);

View File

@ -133,6 +133,9 @@ public class PlayerSlotPane {
setTextFromRacePreference(rootFrame, player);
}
});
this.raceMenu.setEnabled(player.isRaceSelectable());
this.teamButtonFrame.setEnabled(player.isRaceSelectable());
this.colorButtonFrame.setEnabled(player.isRaceSelectable());
}
public void setNameMenuTextByPlayer(final GameUI rootFrame, final CPlayerJass player,

View File

@ -7,12 +7,18 @@ import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.parsers.w3x.w3i.Force;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3iFlags;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
public class TeamSetupPane {
private final List<PlayerSlotPane> playerSlots = new ArrayList<>();
@ -23,29 +29,66 @@ public class TeamSetupPane {
}
public void setMap(final DataSource dataSource, final GameUI rootFrame, final Viewport uiViewport,
final War3MapConfig config, final int playerCount) {
final War3MapConfig config, final int playerCount, final War3MapW3i mapInfo) {
for (final PlayerSlotPane playerSlotPane : this.playerSlots) {
this.container.remove(playerSlotPane.getPlayerSlotFrame());
}
this.playerSlots.clear();
int usedSlots = 0;
for (int i = 0; (i < WarsmashConstants.MAX_PLAYERS) && (usedSlots < playerCount); i++) {
final CBasePlayer player = config.getPlayer(i);
if (player.getSlotState() == CPlayerSlotState.EMPTY) {
continue;
if (mapInfo.hasFlag(War3MapW3iFlags.FIXED_PLAYER_SETTINGS_FOR_CUSTOM_FORCES)) {
UIFrame lastFrame = null;
int forceIndex = 0;
for (final Force force : mapInfo.getForces()) {
final StringFrame forceLabelString = rootFrame.createStringFrame(
"SmashForce" + forceIndex + "NameLabel", rootFrame, null, TextJustify.LEFT, TextJustify.MIDDLE,
0.01f);
rootFrame.setText(forceLabelString, rootFrame.getTrigStr(force.getName()));
for (int i = 0; (i < WarsmashConstants.MAX_PLAYERS) && (usedSlots < playerCount); i++) {
final CBasePlayer player = config.getPlayer(i);
if (player.getController() == CMapControl.NONE) {
continue;
}
final int playerMaskBit = 1 << i;
final boolean forceContainsPlayer = (force.getPlayerMasks() & playerMaskBit) != 0;
if (forceContainsPlayer) {
final PlayerSlotPane playerSlotPane = new PlayerSlotPane(rootFrame, uiViewport, this.container,
i);
this.playerSlots.add(playerSlotPane);
if (lastFrame == null) {
playerSlotPane.getPlayerSlotFrame().addSetPoint(
new SetPoint(FramePoint.TOPLEFT, this.container, FramePoint.TOPLEFT, 0, 0));
}
else {
playerSlotPane.getPlayerSlotFrame().addSetPoint(
new SetPoint(FramePoint.TOPLEFT, lastFrame, FramePoint.BOTTOMLEFT, 0, 0));
}
lastFrame = playerSlotPane.getPlayerSlotFrame();
playerSlotPane.setForPlayer(dataSource, rootFrame, uiViewport, player);
usedSlots++;
}
}
forceIndex++;
}
final PlayerSlotPane playerSlotPane = new PlayerSlotPane(rootFrame, uiViewport, this.container, i);
this.playerSlots.add(playerSlotPane);
if (usedSlots == 0) {
playerSlotPane.getPlayerSlotFrame()
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.container, FramePoint.TOPLEFT, 0, 0));
}
else {
for (int i = 0; (i < WarsmashConstants.MAX_PLAYERS) && (usedSlots < playerCount); i++) {
final CBasePlayer player = config.getPlayer(i);
if (player.getController() == CMapControl.NONE) {
continue;
}
final PlayerSlotPane playerSlotPane = new PlayerSlotPane(rootFrame, uiViewport, this.container, i);
this.playerSlots.add(playerSlotPane);
if (usedSlots == 0) {
playerSlotPane.getPlayerSlotFrame()
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.container, FramePoint.TOPLEFT, 0, 0));
}
else {
playerSlotPane.getPlayerSlotFrame().addSetPoint(new SetPoint(FramePoint.TOPLEFT,
this.playerSlots.get(usedSlots - 1).getPlayerSlotFrame(), FramePoint.BOTTOMLEFT, 0, 0));
}
playerSlotPane.setForPlayer(dataSource, rootFrame, uiViewport, player);
usedSlots++;
}
else {
playerSlotPane.getPlayerSlotFrame().addSetPoint(new SetPoint(FramePoint.TOPLEFT,
this.playerSlots.get(usedSlots - 1).getPlayerSlotFrame(), FramePoint.BOTTOMLEFT, 0, 0));
}
playerSlotPane.setForPlayer(dataSource, rootFrame, uiViewport, player);
usedSlots++;
}
this.container.positionBounds(rootFrame, uiViewport);
}

View File

@ -8,8 +8,11 @@ import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.util.CHandle;
public class Trigger {
public class Trigger implements CHandle {
private static int STUPID_STATIC_TRIGGER_COUNT_DELETE_THIS_LATER = 452354453;
private final int handleId = STUPID_STATIC_TRIGGER_COUNT_DELETE_THIS_LATER++;
private final List<TriggerBooleanExpression> conditions = new ArrayList<>();
private final List<JassFunction> actions = new ArrayList<>();
private int evalCount;
@ -109,4 +112,9 @@ public class Trigger {
return this.waitOnSleeps;
}
@Override
public int getHandleId() {
return this.handleId;
}
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public class LobbyConstants {
public static final int MAX_PLAYERS = 24;
}

View File

@ -0,0 +1,17 @@
package net.warsmash.uberserver.lobby;
public interface LobbyListener {
void addUserPlayer(int slotIndex, String playerName);
void moveUserPlayer(String playerName, int oldSlotIndex, int newSlotIndex);
void setUserSlotSetting(int slotIndex, UserSlotSetting userSlotSetting);
void setRace(int slotIndex, LobbyRace race);
void setTeam(int slotIndex, int teamIndex);
void setColor(int slotIndex, int colorIndex);
void setHandicap(int slotIndex, int handicapIndex);
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public enum LobbyRace {
RANDOM, HUMAN, ORC, NIGHTELF, UNDEAD;
}

View File

@ -0,0 +1,14 @@
package net.warsmash.uberserver.lobby;
public interface LobbySetupListener {
void beginLobby(LobbyType lobbyType, boolean fixedPlayerSettings, int forcesCount);
void addForce(String name);
// NOTE: below, pass null for lobbyRace if you want it to be specially
// selectable
void addSlot(int playerIndex, LobbySlotType slotType, LobbyRace lobbyRace, int forceIndex);
LobbyListener endLobby();
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public enum LobbySlotType {
USER, COMPUTER;
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public interface LobbyStateView {
void getSnapshot(LobbyListener lobbyListener);
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public enum LobbyType {
MELEE, CUSTOM_FORCES;
}

View File

@ -0,0 +1,5 @@
package net.warsmash.uberserver.lobby;
public enum UserSlotSetting {
OPEN, CLOSED, USER, COMPUTER_EASY, COMPUTER_NORMAL, COMPUTER_INSANE;
}

View File

@ -0,0 +1,10 @@
package net.warsmash.uberserver.lobby.state;
import net.warsmash.uberserver.lobby.LobbyRace;
public class CustomForcesLobbySlot {
private int playerIndex;
private LobbyRace race;
private int colorIndex;
private int handicapIndex;
}

View File

@ -0,0 +1,13 @@
package net.warsmash.uberserver.lobby.state;
import net.warsmash.uberserver.lobby.LobbyRace;
import net.warsmash.uberserver.lobby.LobbySlotType;
public class FixedCustomForcesLobbySlot {
private int playerIndex;
private LobbySlotType slotType;
private LobbyRace race;
private boolean raceSelectable;
private int colorIndex;
private int handicapIndex;
}

View File

@ -0,0 +1,9 @@
package net.warsmash.uberserver.lobby.state;
public class LobbyActionException extends RuntimeException {
public LobbyActionException(final String message) {
super(message);
// TODO Auto-generated constructor stub
}
}

View File

@ -0,0 +1,81 @@
package net.warsmash.uberserver.lobby.state;
import net.warsmash.uberserver.lobby.LobbyRace;
import net.warsmash.uberserver.lobby.LobbySlotType;
public class LobbyPlayerSlot {
private boolean used;
private LobbySlotType slotType;
private LobbyRace race;
private boolean raceSelectable;
private int teamIndex;
private int colorIndex;
private int handicapIndex;
public LobbyPlayerSlot(final boolean used, final LobbySlotType slotType, final LobbyRace race,
final boolean raceSelectable, final int teamIndex, final int colorIndex, final int handicapIndex) {
this.used = used;
this.slotType = slotType;
this.race = race;
this.raceSelectable = raceSelectable;
this.teamIndex = teamIndex;
this.colorIndex = colorIndex;
this.handicapIndex = handicapIndex;
}
public boolean isUsed() {
return this.used;
}
public void setUsed(final boolean used) {
this.used = used;
}
public LobbySlotType getSlotType() {
return this.slotType;
}
public void setSlotType(final LobbySlotType slotType) {
this.slotType = slotType;
}
public LobbyRace getRace() {
return this.race;
}
public void setRace(final LobbyRace race) {
this.race = race;
}
public boolean isRaceSelectable() {
return this.raceSelectable;
}
public void setRaceSelectable(final boolean raceSelectable) {
this.raceSelectable = raceSelectable;
}
public int getTeamIndex() {
return this.teamIndex;
}
public void setTeamIndex(final int teamIndex) {
this.teamIndex = teamIndex;
}
public int getColorIndex() {
return this.colorIndex;
}
public void setColorIndex(final int colorIndex) {
this.colorIndex = colorIndex;
}
public int getHandicapIndex() {
return this.handicapIndex;
}
public void setHandicapIndex(final int handicapIndex) {
this.handicapIndex = handicapIndex;
}
}

View File

@ -0,0 +1,104 @@
package net.warsmash.uberserver.lobby.state;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.warsmash.uberserver.lobby.LobbyListener;
import net.warsmash.uberserver.lobby.LobbyRace;
import net.warsmash.uberserver.lobby.LobbySlotType;
import net.warsmash.uberserver.lobby.LobbyStateView;
import net.warsmash.uberserver.lobby.LobbyType;
import net.warsmash.uberserver.lobby.UserSlotSetting;
public class LobbyStateImpl implements LobbyListener, LobbyStateView {
private final LobbyType lobbyType;
private final boolean fixedPlayerSettings;
private final LobbyPlayerSlot[] playerSlots;
private final String[] forceNames;
private final UserSlotSetting[] userSlotSettings;
private final List<LobbyUserPlayer> userPlayers;
public LobbyStateImpl(final LobbyType lobbyType, final boolean fixedPlayerSettings,
final LobbyPlayerSlot[] playerSlots, final String[] forceNames) {
this.lobbyType = lobbyType;
this.fixedPlayerSettings = fixedPlayerSettings;
this.playerSlots = playerSlots;
this.forceNames = forceNames;
this.userSlotSettings = new UserSlotSetting[playerSlots.length];
this.userPlayers = new ArrayList<>();
Arrays.fill(this.userSlotSettings, UserSlotSetting.OPEN);
}
@Override
public void addUserPlayer(final int slotIndex, final String playerName) {
for (final LobbyUserPlayer lobbyUserPlayer : this.userPlayers) {
if (lobbyUserPlayer.getSlotIndex() == slotIndex) {
throw new LobbyActionException("addUserPlayer(" + slotIndex + "," + playerName
+ ") would conflict with " + lobbyUserPlayer.getName() + " who is already in that slot!");
}
}
this.userPlayers.add(new LobbyUserPlayer(slotIndex, playerName));
this.userSlotSettings[slotIndex] = null;
}
@Override
public void moveUserPlayer(final String playerName, final int oldSlotIndex, final int newSlotIndex) {
if (this.lobbyType == LobbyType.MELEE) {
throw new LobbyActionException("Cannot move user player in " + this.lobbyType);
}
for (final LobbyUserPlayer lobbyUserPlayer : this.userPlayers) {
if (lobbyUserPlayer.getName().equals(playerName) && (lobbyUserPlayer.getSlotIndex() == oldSlotIndex)) {
this.userSlotSettings[oldSlotIndex] = UserSlotSetting.OPEN;
lobbyUserPlayer.setSlotIndex(newSlotIndex);
this.userSlotSettings[newSlotIndex] = null;
}
}
}
@Override
public void setUserSlotSetting(final int slotIndex, final UserSlotSetting userSlotSetting) {
if (this.playerSlots[slotIndex].getSlotType() != LobbySlotType.USER) {
throw new LobbyActionException("Cannot change slot setting for player " + slotIndex);
}
this.userSlotSettings[slotIndex] = userSlotSetting;
}
@Override
public void setRace(final int slotIndex, final LobbyRace race) {
if (this.playerSlots[slotIndex].isRaceSelectable()) {
this.playerSlots[slotIndex].setRace(race);
}
else {
throw new LobbyActionException("Cannot set race for player " + slotIndex);
}
}
@Override
public void setTeam(final int slotIndex, final int teamIndex) {
if (this.lobbyType != LobbyType.MELEE) {
throw new LobbyActionException("Cannot set team in " + this.lobbyType);
}
}
@Override
public void setColor(final int slotIndex, final int colorIndex) {
if (this.fixedPlayerSettings) {
throw new LobbyActionException("Cannot set player color in a fixed player settings lobby");
}
this.playerSlots[slotIndex].setColorIndex(colorIndex);
}
@Override
public void setHandicap(final int slotIndex, final int handicapIndex) {
this.playerSlots[slotIndex].setHandicapIndex(handicapIndex);
}
@Override
public void getSnapshot(final LobbyListener lobbyListener) {
for (int i = 0; i < this.playerSlots.length; i++) {
final LobbyPlayerSlot lobbyPlayerSlot = this.playerSlots[i];
}
}
}

View File

@ -0,0 +1,63 @@
package net.warsmash.uberserver.lobby.state;
import net.warsmash.uberserver.lobby.LobbyConstants;
import net.warsmash.uberserver.lobby.LobbyListener;
import net.warsmash.uberserver.lobby.LobbyRace;
import net.warsmash.uberserver.lobby.LobbySetupListener;
import net.warsmash.uberserver.lobby.LobbySlotType;
import net.warsmash.uberserver.lobby.LobbyType;
public class LobbyStateImplBuilder implements LobbySetupListener {
private LobbyType lobbyType;
private boolean fixedPlayerSettings;
private LobbyPlayerSlot[] playerSlots;
private String[] forceNames;
private int nextForceNameIndex;
@Override
public void beginLobby(final LobbyType lobbyType, final boolean fixedPlayerSettings, final int forcesCount) {
this.lobbyType = lobbyType;
this.fixedPlayerSettings = fixedPlayerSettings;
this.playerSlots = new LobbyPlayerSlot[LobbyConstants.MAX_PLAYERS];
this.forceNames = new String[forcesCount];
this.nextForceNameIndex = 0;
}
@Override
public void addForce(final String name) {
this.forceNames[this.nextForceNameIndex++] = name;
}
@Override
public void addSlot(final int playerIndex, final LobbySlotType slotType, LobbyRace lobbyRace,
final int forceIndex) {
final LobbyPlayerSlot lobbyPlayerSlot = this.playerSlots[playerIndex];
lobbyPlayerSlot.setUsed(true);
lobbyPlayerSlot.setColorIndex(playerIndex);
lobbyPlayerSlot.setHandicapIndex(0); // 100%
if (this.lobbyType == LobbyType.MELEE) {
lobbyPlayerSlot.setSlotType(LobbySlotType.USER);
lobbyPlayerSlot.setRace(LobbyRace.RANDOM);
lobbyPlayerSlot.setRaceSelectable(true);
lobbyPlayerSlot.setTeamIndex(playerIndex);
}
else {
boolean raceSelectable = !this.fixedPlayerSettings;
if (lobbyRace == null) {
lobbyRace = LobbyRace.RANDOM;
raceSelectable = true;
}
lobbyPlayerSlot.setRace(lobbyRace);
lobbyPlayerSlot.setSlotType(slotType);
lobbyPlayerSlot.setRaceSelectable(raceSelectable);
lobbyPlayerSlot.setTeamIndex(forceIndex);
}
}
@Override
public LobbyListener endLobby() {
return new LobbyStateImpl(this.lobbyType, this.fixedPlayerSettings, this.playerSlots, this.forceNames);
}
}

View File

@ -0,0 +1,23 @@
package net.warsmash.uberserver.lobby.state;
public class LobbyUserPlayer {
private int slotIndex;
private final String name;
public LobbyUserPlayer(final int slotIndex, final String name) {
this.slotIndex = slotIndex;
this.name = name;
}
public int getSlotIndex() {
return this.slotIndex;
}
public void setSlotIndex(final int slotIndex) {
this.slotIndex = slotIndex;
}
public String getName() {
return this.name;
}
}

View File

@ -0,0 +1,10 @@
package net.warsmash.uberserver.lobby.state;
import net.warsmash.uberserver.lobby.LobbyRace;
import net.warsmash.uberserver.lobby.LobbySlotType;
public class MeleeLobbySlot {
private int playerIndex;
private LobbySlotType slotType;
private LobbyRace race;
}