Update with some beginning on a jass API that does not run and is not usable yet

This commit is contained in:
Retera 2021-03-20 14:54:38 -04:00
parent 5e3150124a
commit 55bdfcb9fc
65 changed files with 3208 additions and 197 deletions

View File

@ -35,6 +35,7 @@ import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.Element;
import com.etheller.warsmash.util.DataSourceFileHandle;
import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.CanvasProvider;
import com.etheller.warsmash.viewer5.Model;
import com.etheller.warsmash.viewer5.ModelInstance;
@ -48,6 +49,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraPreset;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnitOrderExecutor;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.SettableCommandErrorListener;
@ -105,7 +107,8 @@ public class WarsmashGdxMapScreen implements CanvasProvider, InputProcessor, Scr
final SettableCommandErrorListener commandErrorListener = new SettableCommandErrorListener();
this.codebase = parseDataSources(this.warsmashIni);
this.viewer = new War3MapViewer(this.codebase, this, commandErrorListener);
this.viewer = new War3MapViewer(this.codebase, this, commandErrorListener,
new War3MapConfig(WarsmashConstants.MAX_PLAYERS));
if (ENABLE_AUDIO) {
this.viewer.worldScene.enableAudio();
@ -218,7 +221,8 @@ public class WarsmashGdxMapScreen implements CanvasProvider, InputProcessor, Scr
WarsmashGdxMapScreen.this.currentMusic = music;
}
}
}, new CPlayerUnitOrderExecutor(this.viewer.simulation, commandErrorListener));
}, new CPlayerUnitOrderExecutor(this.viewer.simulation, this.viewer.getLocalPlayerIndex(),
commandErrorListener));
commandErrorListener.setDelegate(this.meleeUI);
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
this.viewer.mapPathSolver, "").addInstance();

View File

@ -187,7 +187,7 @@ public class WarsmashGdxMenuScreen implements CanvasProvider, InputProcessor, Sc
final String musicPath = musics[(int) (Math.random() * musics.length)];
final Music music = Gdx.audio.newMusic(
new DataSourceFileHandle(WarsmashGdxMenuScreen.this.viewer.dataSource, musicPath));
music.setVolume(0.2f);
// music.setVolume(0.2f);
music.setLooping(true);
music.play();
WarsmashGdxMenuScreen.this.currentMusic = music;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
package com.etheller.warsmash.parsers.jass;
import java.util.Scanner;
public class Tmpgen {
public static void main(final String[] args) {
// final HandleJassType eventType = globals.registerHandleType("event");
final Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
if (line.startsWith("type ")) {
final String[] splitLine = line.split("\\s+");
System.out.println("final HandleJassType " + splitLine[1] + "Type = globals.registerHandleType(\""
+ splitLine[1] + "\");");
}
}
}
}

View File

@ -0,0 +1,29 @@
package com.etheller.warsmash.parsers.jass;
import java.util.Scanner;
public class Tmpgen2 {
public static void main(final String[] args) {
// final HandleJassType eventType = globals.registerHandleType("event");
final Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
final String[] splitLine = line.trim().split("\\s+");
if (line.trim().startsWith("//")) {
System.out.println(line);
}
else {
if (splitLine.length > 3) {
System.out.println(splitLine[2] + ",");
}
else {
System.out.println();
}
}
}
}
}

View File

@ -6,7 +6,7 @@ public class WarsmashConstants {
* With version, we use 0 for RoC, 1 for TFT emulation, and probably 2+ or
* whatever for custom mods and other stuff
*/
public static int GAME_VERSION = 1;
public static int GAME_VERSION = 0;
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

@ -6,7 +6,7 @@ import java.util.List;
import com.etheller.warsmash.viewer5.handlers.ModelHandler;
public abstract class Model<HANDLER extends ModelHandler> extends HandlerResource<HANDLER> {
public Bounds bounds;
public final Bounds bounds;
public List<ModelInstance> preloadedInstances;
public Model(final HANDLER handler, final ModelViewer viewer, final String extension, final PathSolver pathSolver,

View File

@ -13,6 +13,7 @@ import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.Ray;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Bounds;
import com.etheller.warsmash.viewer5.GenericNode;
import com.etheller.warsmash.viewer5.ModelInstance;
import com.etheller.warsmash.viewer5.Node;
@ -748,8 +749,23 @@ public class MdxComplexInstance extends ModelInstance {
throw new UnsupportedOperationException("NOT API");
}
public Bounds getBounds() {
if (this.sequence == -1) {
return this.model.bounds;
}
else {
final Bounds sequenceBounds = ((MdxModel) this.model).sequences.get(this.sequence).getBounds();
if (sequenceBounds.r == 0) {
return this.model.bounds;
}
else {
return sequenceBounds;
}
}
}
public void intersectRayBounds(final Ray ray, final Vector3 intersection) {
this.model.bounds.intersectRay(ray, intersection);
getBounds().intersectRay(ray, intersection);
}
/**

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.viewer5.handlers.mdx;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.Bounds;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
@ -10,12 +11,16 @@ import com.hiveworkshop.rms.parsers.mdlx.MdlxSequence;
public class Sequence {
private final MdlxSequence sequence;
private final Bounds bounds;
private final EnumSet<AnimationTokens.PrimaryTag> primaryTags = EnumSet.noneOf(AnimationTokens.PrimaryTag.class);
private final EnumSet<AnimationTokens.SecondaryTag> secondaryTags = EnumSet
.noneOf(AnimationTokens.SecondaryTag.class);
public Sequence(final MdlxSequence sequence) {
this.sequence = sequence;
this.bounds = new Bounds();
final MdlxExtent sequenceExtent = sequence.getExtent();
this.bounds.fromExtents(sequenceExtent.getMin(), sequenceExtent.getMax(), sequenceExtent.getBoundsRadius());
populateTags();
}
@ -64,6 +69,10 @@ public class Sequence {
return this.sequence.getSyncPoint();
}
public Bounds getBounds() {
return this.bounds;
}
public MdlxExtent getExtent() {
return this.sequence.getExtent();
}

View File

@ -42,6 +42,7 @@ import com.etheller.warsmash.parsers.w3x.doo.War3MapDoo;
import com.etheller.warsmash.parsers.w3x.objectdata.Warcraft3MapObjectData;
import com.etheller.warsmash.parsers.w3x.unitsdoo.War3MapUnitsDoo;
import com.etheller.warsmash.parsers.w3x.w3e.War3MapW3e;
import com.etheller.warsmash.parsers.w3x.w3i.Player;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
import com.etheller.warsmash.parsers.w3x.wpm.War3MapWpm;
import com.etheller.warsmash.units.DataTable;
@ -103,6 +104,10 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUni
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRacePreference;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
@ -144,6 +149,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public static final Vector3 intersectionHeap = new Vector3();
private static final Rectangle rectangleHeap = new Rectangle();
public static final StreamDataCallbackImplementation streamDataCallback = new StreamDataCallbackImplementation();
private static final boolean ENABLE_WORLDEDIT_AS_GAMEPLAY_DATA_HACK = true;
public WorldScene worldScene;
public boolean anyReady;
@ -218,8 +224,10 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public final List<TextTag> textTags = new ArrayList<>();
private final War3MapConfig mapConfig;
public War3MapViewer(final DataSource dataSource, final CanvasProvider canvas,
final CommandErrorListener errorListener) {
final CommandErrorListener errorListener, final War3MapConfig mapConfig) {
super(dataSource, canvas);
this.gameDataSource = dataSource;
@ -236,6 +244,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
this.commandErrorListener = errorListener;
this.mapConfig = mapConfig;
}
public void loadSLKs(final WorldEditStrings worldEditStrings) throws IOException {
@ -387,6 +396,17 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final War3MapW3i w3iFile = this.mapMpq.readMapInformation();
if (ENABLE_WORLDEDIT_AS_GAMEPLAY_DATA_HACK) {
int playerIndex = 0;
for (final Player player : w3iFile.getPlayers()) {
final CBasePlayer cfgPlayer = this.mapConfig.getPlayer(playerIndex);
cfgPlayer.setName(player.getName());
cfgPlayer.setRacePref(CRacePreference.VALUES[player.getRace()]);
cfgPlayer.setController(CMapControl.VALUES[player.getType()]);
playerIndex++;
}
}
tileset = w3iFile.getTileset();
DataSource tilesetSource;
@ -455,8 +475,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
this.confirmationInstance.setScene(this.worldScene);
this.allObjectData = this.mapMpq.readModifications();
this.simulation = new CSimulation(this.miscData, this.allObjectData.getUnits(), this.allObjectData.getItems(),
this.allObjectData.getDestructibles(), this.allObjectData.getAbilities(),
this.simulation = new CSimulation(this.mapConfig, this.miscData, this.allObjectData.getUnits(),
this.allObjectData.getItems(), this.allObjectData.getDestructibles(), this.allObjectData.getAbilities(),
new SimulationRenderController() {
private final Map<String, UnitSound> keyToCombatSound = new HashMap<>();
@ -745,8 +765,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
renderPeer.getZ());
}
}
}, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, w3iFile.getPlayers(),
this.commandErrorListener);
}, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, this.commandErrorListener);
this.walkableObjectsTree = new Quadtree<>(this.terrain.getEntireMap());
if (this.doodadsAndDestructiblesLoaded) {
@ -1853,4 +1872,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
this.textTags.add(textTag);
}
public War3MapConfig getMapConfig() {
return this.mapConfig;
}
}

View File

@ -348,6 +348,22 @@ public class CGameplayConstants {
return this.pawnItemRate;
}
public float getFollowRange() {
return this.followRange;
}
public float getStructureFollowRange() {
return this.structureFollowRange;
}
public float getFollowItemRange() {
return this.followItemRange;
}
public float getSpellCastRangeBuffer() {
return this.spellCastRangeBuffer;
}
private static int getTableValue(final int[] table, int level) {
if (level <= 0) {
return 0;

View File

@ -5,12 +5,13 @@ import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import com.badlogic.gdx.math.Rectangle;
import com.etheller.warsmash.parsers.w3x.w3i.Player;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.manager.MutableObjectData;
import com.etheller.warsmash.util.War3ID;
@ -24,20 +25,24 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUni
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CPlayerAPI;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfig;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.War3MapConfigStartLoc;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CAbilityData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CDestructableData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CItemData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CUnitData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
public class CSimulation {
public class CSimulation implements CPlayerAPI {
private final CAbilityData abilityData;
private final CUnitData unitData;
private final CDestructableData destructableData;
@ -63,13 +68,14 @@ public class CSimulation {
private final Map<Integer, CDestructable> handleIdToDestructable = new HashMap<>();
private final Map<Integer, CItem> handleIdToItem = new HashMap<>();
private final Map<Integer, CAbility> handleIdToAbility = new HashMap<>();
private final LinkedList<CTimer> activeTimers = new LinkedList<>();
private transient CommandErrorListener commandErrorListener;
public CSimulation(final DataTable miscData, final MutableObjectData parsedUnitData,
public CSimulation(final War3MapConfig config, final DataTable miscData, final MutableObjectData parsedUnitData,
final MutableObjectData parsedItemData, final MutableObjectData parsedDestructableData,
final MutableObjectData parsedAbilityData, final SimulationRenderController simulationRenderController,
final PathingGrid pathingGrid, final Rectangle entireMapBounds, final Random seededRandom,
final List<Player> playerInfos, final CommandErrorListener commandErrorListener) {
final CommandErrorListener commandErrorListener) {
this.gameplayConstants = new CGameplayConstants(miscData);
this.simulationRenderController = simulationRenderController;
this.pathingGrid = pathingGrid;
@ -94,27 +100,19 @@ public class CSimulation {
}
this.seededRandom = seededRandom;
this.players = new ArrayList<>();
for (int i = 0; i < (WarsmashConstants.MAX_PLAYERS - 4); i++) {
CPlayer newPlayer;
if (i < playerInfos.size()) {
final Player playerInfo = playerInfos.get(i);
newPlayer = new CPlayer(playerInfo.getId(), CMapControl.values()[playerInfo.getType()],
playerInfo.getName(), CRace.parseRace(playerInfo.getRace()), playerInfo.getStartLocation());
}
else {
newPlayer = new CPlayer(i, CMapControl.NONE, "Default string", CRace.OTHER, new float[] { 0, 0 });
}
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer configPlayer = config.getPlayer(i);
final War3MapConfigStartLoc startLoc = config.getStartLoc(configPlayer.getStartLocationIndex());
final CPlayer newPlayer = new CPlayer(CRace.OTHER, new float[] { startLoc.getX(), startLoc.getY() },
configPlayer);
this.players.add(newPlayer);
}
this.players.add(new CPlayer(this.players.size(), CMapControl.NEUTRAL,
miscData.getLocalizedString("WESTRING_PLAYER_NA"), CRace.OTHER, new float[] { 0, 0 }));
this.players.add(new CPlayer(this.players.size(), CMapControl.NEUTRAL,
miscData.getLocalizedString("WESTRING_PLAYER_NV"), CRace.OTHER, new float[] { 0, 0 }));
this.players.add(new CPlayer(this.players.size(), CMapControl.NEUTRAL,
miscData.getLocalizedString("WESTRING_PLAYER_NE"), CRace.OTHER, new float[] { 0, 0 }));
final CPlayer neutralPassive = new CPlayer(this.players.size(), CMapControl.NEUTRAL,
miscData.getLocalizedString("WESTRING_PLAYER_NP"), CRace.OTHER, new float[] { 0, 0 });
this.players.add(neutralPassive);
this.players.get(this.players.size() - 4).setName(miscData.getLocalizedString("WESTRING_PLAYER_NA"));
this.players.get(this.players.size() - 3).setName(miscData.getLocalizedString("WESTRING_PLAYER_NV"));
this.players.get(this.players.size() - 2).setName(miscData.getLocalizedString("WESTRING_PLAYER_NE"));
final CPlayer neutralPassive = this.players.get(this.players.size() - 1);
neutralPassive.setName(miscData.getLocalizedString("WESTRING_PLAYER_NP"));
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CPlayer cPlayer = this.players.get(i);
cPlayer.setAlliance(neutralPassive, CAllianceType.PASSIVE, true);
@ -133,6 +131,14 @@ public class CSimulation {
return this.abilityData;
}
public CDestructableData getDestructableData() {
return this.destructableData;
}
public CItemData getItemData() {
return this.itemData;
}
public List<CUnit> getUnits() {
return this.units;
}
@ -141,6 +147,22 @@ public class CSimulation {
return this.destructables;
}
public void registerTimer(final CTimer timer) {
final ListIterator<CTimer> listIterator = this.activeTimers.listIterator();
while (listIterator.hasNext()) {
final CTimer nextTimer = listIterator.next();
if (nextTimer.getEngineFireTick() > timer.getEngineFireTick()) {
listIterator.previous();
listIterator.add(timer);
}
}
this.activeTimers.add(timer);
}
public void unregisterTimer(final CTimer time) {
this.activeTimers.remove(time);
}
public CUnit createUnit(final War3ID typeId, final int playerIndex, final float x, final float y,
final float facing, final BufferedImage buildingPathingPixelMap,
final RemovablePathingMapInstance pathingInstance) {
@ -247,6 +269,10 @@ public class CSimulation {
this.gameTurnTick++;
this.currentGameDayTimeElapsed = (this.currentGameDayTimeElapsed + WarsmashConstants.SIMULATION_STEP_TIME)
% this.gameplayConstants.getGameDayLength();
while (!this.activeTimers.isEmpty() && (this.activeTimers.peek().getEngineFireTick() <= this.gameTurnTick)) {
this.activeTimers.pop().fire(this);
}
}
private void finishAddingNewUnits() {
@ -292,6 +318,7 @@ public class CSimulation {
this.simulationRenderController.spawnUnitConstructionSound(constructingUnit, constructedStructure);
}
@Override
public CPlayer getPlayer(final int index) {
return this.players.get(index);
}

View File

@ -721,7 +721,7 @@ public class CUnit extends CWidget {
}
}
if (!foundMatchingReturnFireAttack && this.unitType.isCanFlee() && !isMovementDisabled()
&& (this.moveBehavior != null)) {
&& (this.moveBehavior != null) && (this.playerIndex != source.getPlayerIndex())) {
final double angleTo = source.angleTo(this);
final int distanceToFlee = getSpeed();
this.currentBehavior = this.moveBehavior.reset(OrderIds.move,

View File

@ -20,6 +20,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CBuildingPa
*/
public class CUnitType {
private final String name;
private final String legacyName;
private final War3ID typeId;
private final int life;
private final int manaInitial;
private final int manaMaximum;
@ -73,15 +75,16 @@ public class CUnitType {
private final int properNamesCount;
private final boolean canFlee;
public CUnitType(final String name, final int life, final int manaInitial, final int manaMaximum, final int speed,
final int defense, final String abilityList, final boolean isBldg, final MovementType movementType,
final float defaultFlyingHeight, final float collisionSize,
final EnumSet<CUnitClassification> classifications, final List<CUnitAttack> attacks, final String armorType,
final boolean raise, final boolean decay, final CDefenseType defenseType, final float impactZ,
final BufferedImage buildingPathingPixelMap, final float deathTime, final EnumSet<CTargetType> targetedAs,
final float defaultAcquisitionRange, final float minimumAttackRange, final List<War3ID> structuresBuilt,
final List<War3ID> unitsTrained, final List<War3ID> researchesAvailable, final CUnitRace unitRace,
final int goldCost, final int lumberCost, final int foodUsed, final int foodMade, final int buildTime,
public CUnitType(final String name, final String legacyName, final War3ID typeId, final int life,
final int manaInitial, final int manaMaximum, final int speed, final int defense, final String abilityList,
final boolean isBldg, final MovementType movementType, final float defaultFlyingHeight,
final float collisionSize, final EnumSet<CUnitClassification> classifications,
final List<CUnitAttack> attacks, final String armorType, final boolean raise, final boolean decay,
final CDefenseType defenseType, final float impactZ, final BufferedImage buildingPathingPixelMap,
final float deathTime, final EnumSet<CTargetType> targetedAs, final float defaultAcquisitionRange,
final float minimumAttackRange, final List<War3ID> structuresBuilt, final List<War3ID> unitsTrained,
final List<War3ID> researchesAvailable, final CUnitRace unitRace, final int goldCost, final int lumberCost,
final int foodUsed, final int foodMade, final int buildTime,
final EnumSet<CBuildingPathingType> preventedPathingTypes,
final EnumSet<CBuildingPathingType> requiredPathingTypes, final float propWindow, final float turnRate,
final List<CUnitTypeRequirement> requirements, final int level, final boolean hero, final int strength,
@ -90,6 +93,8 @@ public class CUnitType {
final List<War3ID> heroAbilityList, final List<String> heroProperNames, final int properNamesCount,
final boolean canFlee) {
this.name = name;
this.legacyName = legacyName;
this.typeId = typeId;
this.life = life;
this.manaInitial = manaInitial;
this.manaMaximum = manaMaximum;
@ -145,6 +150,14 @@ public class CUnitType {
return this.name;
}
public String getLegacyName() {
return this.legacyName;
}
public War3ID getTypeId() {
return this.typeId;
}
public int getLife() {
return this.life;
}

View File

@ -0,0 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.ai;
public enum AIDifficulty {
NEWBIE,
NORMAL,
INSANE;
public static AIDifficulty[] VALUES = values();
}

View File

@ -0,0 +1,185 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
import java.util.EnumMap;
import java.util.EnumSet;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CMapControl;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerState;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRacePreference;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
public class CBasePlayer implements CPlayerJass {
private final int id;
private String name;
private int team;
private int startLocationIndex;
private int forcedStartLocationIndex = -1;
private int color;
private final EnumSet<CRacePreference> racePrefs;
private final EnumSet<CAllianceType>[] alliances;
private final EnumMap<CPlayerState, Integer>[] taxRates;
private boolean onScoreScreen;
private boolean raceSelectable;
private CMapControl mapControl = CMapControl.NEUTRAL;
private CPlayerSlotState slotState = CPlayerSlotState.EMPTY;
public CBasePlayer(final CBasePlayer other) {
this.id = other.id;
this.name = other.name;
this.team = other.team;
this.startLocationIndex = other.startLocationIndex;
this.forcedStartLocationIndex = other.forcedStartLocationIndex;
this.color = other.color;
this.racePrefs = other.racePrefs;
this.alliances = other.alliances;
this.taxRates = other.taxRates;
this.onScoreScreen = other.onScoreScreen;
this.raceSelectable = other.raceSelectable;
this.mapControl = other.mapControl;
this.slotState = other.slotState;
}
public CBasePlayer(final int id) {
this.id = id;
this.alliances = new EnumSet[WarsmashConstants.MAX_PLAYERS];
this.taxRates = new EnumMap[WarsmashConstants.MAX_PLAYERS];
this.racePrefs = EnumSet.noneOf(CRacePreference.class);
for (int i = 0; i < this.alliances.length; i++) {
if (i == id) {
// player is fully allied with self
this.alliances[i] = EnumSet.allOf(CAllianceType.class);
}
else {
this.alliances[i] = EnumSet.noneOf(CAllianceType.class);
}
this.taxRates[i] = new EnumMap<>(CPlayerState.class);
}
}
public int getId() {
return this.id;
}
@Override
public void setName(final String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void setOnScoreScreen(final boolean onScoreScreen) {
this.onScoreScreen = onScoreScreen;
}
public boolean isOnScoreScreen() {
return this.onScoreScreen;
}
@Override
public void setRaceSelectable(final boolean raceSelectable) {
this.raceSelectable = raceSelectable;
}
@Override
public void setTeam(final int team) {
this.team = team;
}
@Override
public int getTeam() {
return this.team;
}
@Override
public int getStartLocationIndex() {
return this.startLocationIndex;
}
@Override
public void setStartLocationIndex(final int startLocationIndex) {
this.startLocationIndex = startLocationIndex;
}
@Override
public void setColor(final int color) {
this.color = color;
}
@Override
public int getColor() {
return this.color;
}
@Override
public boolean isRacePrefSet(final CRacePreference racePref) {
return this.racePrefs.contains(racePref);
}
@Override
public void setRacePref(final CRacePreference racePref) {
this.racePrefs.add(racePref);
}
@Override
public void setAlliance(final int otherPlayerIndex, final CAllianceType allianceType, final boolean value) {
final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayerIndex];
if (value) {
alliancesWithOtherPlayer.add(allianceType);
}
else {
alliancesWithOtherPlayer.remove(allianceType);
}
}
public boolean hasAlliance(final int otherPlayerIndex, final CAllianceType allianceType) {
final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayerIndex];
return alliancesWithOtherPlayer.contains(allianceType);
}
@Override
public void forceStartLocation(final int startLocIndex) {
this.forcedStartLocationIndex = startLocIndex;
}
@Override
public void setTaxRate(final int otherPlayerIndex, final CPlayerState whichResource, final int rate) {
this.taxRates[otherPlayerIndex].put(whichResource, rate);
}
@Override
public void setController(final CMapControl mapControl) {
this.mapControl = mapControl;
}
@Override
public boolean isSelectable() {
return this.raceSelectable;
}
@Override
public CMapControl getController() {
return this.mapControl;
}
@Override
public CPlayerSlotState getSlotState() {
return this.slotState;
}
@Override
public int getTaxRate(final int otherPlayerIndex, final CPlayerState whichResource) {
final Integer taxRate = this.taxRates[otherPlayerIndex].get(whichResource);
if (taxRate == null) {
return 0;
}
return taxRate;
}
}

View File

@ -0,0 +1,5 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
public interface CPlayerAPI {
CBasePlayer getPlayer(int index);
}

View File

@ -0,0 +1,153 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
import java.util.EnumMap;
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;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CGameType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CMapDensity;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CMapDifficulty;
public class War3MapConfig implements CPlayerAPI {
private String mapName;
private String mapDescription;
private int teamCount;
private int playerCount;
private final War3MapConfigStartLoc[] startLocations;
private final CBasePlayer[] players;
private final EnumMap<CGameType, Boolean> gameTypeToSupported = new EnumMap<>(CGameType.class);
private final EnumMap<CMapFlag, Boolean> mapFlagToEnabled = new EnumMap<>(CMapFlag.class);
private CMapPlacement placement;
private CGameSpeed gameSpeed;
private CMapDifficulty gameDifficulty;
private CMapDensity resourceDensity;
private CMapDensity creatureDensity;
private CGameType gameTypeSelected;
public War3MapConfig(final int maxPlayers) {
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 CBasePlayer(i);
}
}
public void setMapName(final String mapName) {
this.mapName = mapName;
}
public void setMapDescription(final String mapDescription) {
this.mapDescription = mapDescription;
}
public String getMapName() {
return this.mapName;
}
public String getMapDescription() {
return this.mapDescription;
}
public void setTeamCount(final int teamCount) {
this.teamCount = teamCount;
}
public void setPlayerCount(final int playerCount) {
this.playerCount = playerCount;
}
public void defineStartLocation(final int whichStartLoc, final float x, final float y) {
final War3MapConfigStartLoc startLoc = this.startLocations[whichStartLoc];
startLoc.setX(x);
startLoc.setY(y);
}
public War3MapConfigStartLoc getStartLoc(final int whichStartLoc) {
return this.startLocations[whichStartLoc];
}
public void setGameTypeSupported(final CGameType gameType, final boolean supported) {
this.gameTypeToSupported.put(gameType, supported);
}
public void setMapFlag(final CMapFlag mapFlag, final boolean set) {
this.mapFlagToEnabled.put(mapFlag, set);
}
public void setPlacement(final CMapPlacement placement) {
this.placement = placement;
}
public void setGameSpeed(final CGameSpeed gameSpeed) {
this.gameSpeed = gameSpeed;
}
public void setGameDifficulty(final CMapDifficulty gameDifficulty) {
this.gameDifficulty = gameDifficulty;
}
public void setResourceDensity(final CMapDensity resourceDensity) {
this.resourceDensity = resourceDensity;
}
public void setCreatureDensity(final CMapDensity creatureDensity) {
this.creatureDensity = creatureDensity;
}
public int getTeamCount() {
return this.teamCount;
}
public int getPlayerCount() {
return this.playerCount;
}
public boolean isGameTypeSupported(final CGameType gameType) {
final Boolean supported = this.gameTypeToSupported.get(gameType);
return (supported != null) && supported;
}
public CGameType getGameTypeSelected() {
return this.gameTypeSelected;
}
public boolean isMapFlagSet(final CMapFlag mapFlag) {
final Boolean flag = this.mapFlagToEnabled.get(mapFlag);
return (flag != null) && flag;
}
public CMapPlacement getPlacement() {
return this.placement;
}
public CGameSpeed getGameSpeed() {
return this.gameSpeed;
}
public CMapDifficulty getGameDifficulty() {
return this.gameDifficulty;
}
public CMapDensity getResourceDensity() {
return this.resourceDensity;
}
public CMapDensity getCreatureDensity() {
return this.creatureDensity;
}
public float getStartLocationX(final int startLocIndex) {
return this.startLocations[startLocIndex].getX();
}
public float getStartLocationY(final int startLocIndex) {
return this.startLocations[startLocIndex].getY();
}
@Override
public CBasePlayer getPlayer(final int index) {
return this.players[index];
}
}

View File

@ -0,0 +1,44 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.config;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CStartLocPrio;
public class War3MapConfigStartLoc {
private float x;
private float y;
private int[] otherStartIndices;
private CStartLocPrio[] otherStartLocPriorities;
public void setX(final float x) {
this.x = x;
}
public void setY(final float y) {
this.y = y;
}
public float getX() {
return this.x;
}
public float getY() {
return this.y;
}
public int[] getOtherStartIndices() {
return this.otherStartIndices;
}
public CStartLocPrio[] getOtherStartLocPriorities() {
return this.otherStartLocPriorities;
}
public void setStartLocPrioCount(final int startLocPrioCount) {
this.otherStartIndices = new int[startLocPrioCount];
this.otherStartLocPriorities = new CStartLocPrio[startLocPrioCount];
}
public void setStartLocPrio(final int prioSlotIndex, final int otherStartLocIndex, final CStartLocPrio priority) {
this.otherStartIndices[prioSlotIndex] = otherStartLocIndex;
this.otherStartLocPriorities[prioSlotIndex] = priority;
}
}

View File

@ -58,6 +58,14 @@ public class CItemData {
return new CItem(handleId, x, y, itemTypeInstance.getHitPoints(), typeId, itemTypeInstance);
}
public CItemType getItemType(final War3ID typeId) {
final MutableGameObject itemType = this.itemData.get(typeId);
if (itemType == null) {
return null;
}
return getItemTypeInstance(typeId, itemType);
}
private CItemType getItemTypeInstance(final War3ID typeId, final MutableGameObject itemType) {
CItemType itemTypeInstance = this.itemIdToItemType.get(typeId);
if (itemTypeInstance == null) {

View File

@ -173,6 +173,7 @@ public class CUnitData {
private final CGameplayConstants gameplayConstants;
private final MutableObjectData unitData;
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
private final Map<String, War3ID> jassLegacyNameToUnitId = new HashMap<>();
private final CAbilityData abilityData;
private final SimulationRenderController simulationRenderController;
@ -266,6 +267,7 @@ public class CUnitData {
final MutableGameObject unitType) {
CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId);
if (unitTypeInstance == null) {
final String legacyName = getLegacyName(unitType);
final int life = unitType.getFieldAsInteger(HIT_POINT_MAXIMUM, 0);
final int manaInitial = unitType.getFieldAsInteger(MANA_INITIAL_AMOUNT, 0);
final int manaMaximum = unitType.getFieldAsInteger(MANA_MAXIMUM, 0);
@ -531,18 +533,33 @@ public class CUnitData {
final List<String> heroProperNames = Arrays.asList(properNames.split(","));
unitTypeInstance = new CUnitType(unitName, life, manaInitial, manaMaximum, speed, defense, abilityList,
isBldg, movementType, moveHeight, collisionSize, classifications, attacks, armorType, raise, decay,
defenseType, impactZ, buildingPathingPixelMap, deathTime, targetedAs, acquisitionRange,
minimumAttackRange, structuresBuilt, unitsTrained, researchesAvailable, unitRace, goldCost,
lumberCost, foodUsed, foodMade, buildTime, preventedPathingTypes, requiredPathingTypes, propWindow,
turnRate, requirements, unitLevel, hero, strength, strPlus, agility, agiPlus, intelligence, intPlus,
primaryAttribute, heroAbilityList, heroProperNames, properNamesCount, canFlee);
unitTypeInstance = new CUnitType(unitName, legacyName, typeId, life, manaInitial, manaMaximum, speed,
defense, abilityList, isBldg, movementType, moveHeight, collisionSize, classifications, attacks,
armorType, raise, decay, defenseType, impactZ, buildingPathingPixelMap, deathTime, targetedAs,
acquisitionRange, minimumAttackRange, structuresBuilt, unitsTrained, researchesAvailable, unitRace,
goldCost, lumberCost, foodUsed, foodMade, buildTime, preventedPathingTypes, requiredPathingTypes,
propWindow, turnRate, requirements, unitLevel, hero, strength, strPlus, agility, agiPlus,
intelligence, intPlus, primaryAttribute, heroAbilityList, heroProperNames, properNamesCount,
canFlee);
this.unitIdToUnitType.put(typeId, unitTypeInstance);
this.jassLegacyNameToUnitId.put(legacyName, typeId);
}
return unitTypeInstance;
}
private String getLegacyName(final MutableGameObject unitType) {
String legacyName;
if (unitType.isCustom()) {
legacyName = "custom_" + unitType.getAlias();
}
else {
// ?? this might be correct here, not sure, legacy name is mostly only used
// for spawning hidden units in campaign secrets
legacyName = unitType.readSLKTag("name");
}
return legacyName;
}
private static int[] populateHeroStatTable(final int maxHeroLevel, final float statPerLevel) {
final int[] table = new int[maxHeroLevel];
float sumBonusAtLevel = 0f;
@ -713,4 +730,22 @@ public class CUnitData {
.getBuildingPathingPixelMap(rawcode);
return getUnitTypeInstance(rawcode, buildingPathingPixelMap, unitType);
}
public CUnitType getUnitTypeByJassLegacyName(final String jassLegacyName) {
final War3ID typeId = this.jassLegacyNameToUnitId.get(jassLegacyName);
if (typeId == null) {
// VERY inefficient, but this is a crazy system anyway, they should not be using
// this!
System.err.println(
"We are doing a highly inefficient lookup for a non-cached unit type based on its legacy string ID that I am pretty sure is not used by modding community: "
+ jassLegacyName);
for (final War3ID key : this.unitData.keySet()) {
final MutableGameObject mutableGameObject = this.unitData.get(key);
if (jassLegacyName.equals(getLegacyName(mutableGameObject))) {
return getUnitType(mutableGameObject.getAlias());
}
}
}
return getUnitType(typeId);
}
}

View File

@ -0,0 +1,15 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.item;
public enum CItemTypeJass {
PERMANENT,
CHARGED,
POWERUP,
ARTIFACT,
PURCHASABLE,
CAMPAIGN,
MISCELLANEOUS,
UNKNOWN,
ANY;
public static CItemTypeJass[] VALUES = values();
}

View File

@ -0,0 +1,38 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class OrderIdUtils {
private static Map<Integer, String> orderIdToString = new HashMap<>();
private static Map<String, Integer> stringToOrderId = new HashMap<>();
static {
for (final Field field : OrderIds.class.getDeclaredFields()) {
final String name = field.getName();
try {
final Object value = field.get(null);
if (value instanceof Integer) {
final Integer orderId = (Integer) value;
orderIdToString.put(orderId, name);
stringToOrderId.put(name, orderId);
}
}
catch (final IllegalArgumentException e) {
e.printStackTrace();
}
catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}
public static int getOrderId(final String orderIdString) {
return stringToOrderId.get(orderIdString);
}
public static String getStringFromOrderId(final Integer orderId) {
return orderIdToString.get(orderId);
}
}

View File

@ -11,4 +11,6 @@ public enum CAllianceType {
SHARED_ADVANCED_CONTROL,
RESCUABLE,
SHARED_VISION_FORCED;
public static CAllianceType[] VALUES = values();
}

View File

@ -7,4 +7,6 @@ public enum CMapControl {
NEUTRAL,
CREEP,
NONE;
public static CMapControl[] VALUES = values();
}

View File

@ -0,0 +1,44 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CMapFlag {
MAP_FOG_HIDE_TERRAIN,
MAP_FOG_MAP_EXPLORED,
MAP_FOG_ALWAYS_VISIBLE,
MAP_USE_HANDICAPS,
MAP_OBSERVERS,
MAP_OBSERVERS_ON_DEATH,
MAP_FIXED_COLORS,
MAP_LOCK_RESOURCE_TRADING,
MAP_RESOURCE_TRADING_ALLIES_ONLY,
MAP_LOCK_ALLIANCE_CHANGES,
MAP_ALLIANCE_CHANGES_HIDDEN,
MAP_CHEATS,
MAP_CHEATS_HIDDEN,
MAP_LOCK_SPEED,
MAP_LOCK_RANDOM_SEED,
MAP_SHARED_ADVANCED_CONTROL,
MAP_RANDOM_HERO,
MAP_RANDOM_RACES,
MAP_RELOADED;
public static CMapFlag[] VALUES = values();
public static CMapFlag getById(final int id) {
for (final CMapFlag type : VALUES) {
if ((type.getId()) == id) {
return type;
}
}
return null;
}
public int getId() {
return 1 << ordinal();
}
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CMapPlacement {
RANDOM,
FIXED,
USE_MAP_SETTINGS,
TEAMS_TOGETHER;
public static CMapPlacement[] VALUES = values();
}

View File

@ -1,29 +1,22 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener.CPlayerStateNotifier;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.config.CBasePlayer;
public class CPlayer {
private final int id;
private int colorIndex;
private final CMapControl controlType;
private String name;
public class CPlayer extends CBasePlayer {
private final CRace race;
private final float[] startLocation;
private final EnumSet<CRacePreference> racePrefs;
private int gold = 500;
private int lumber = 150;
private int foodCap;
private int foodUsed;
private final EnumSet<CAllianceType>[] alliances = new EnumSet[WarsmashConstants.MAX_PLAYERS];
private final Map<War3ID, Integer> rawcodeToTechtreeUnlocked = new HashMap<>();
// if you use triggers for this then the transient tag here becomes really
@ -31,73 +24,20 @@ public class CPlayer {
// which fields shouldn't be persisted if we do game state save later
private transient CPlayerStateNotifier stateNotifier = new CPlayerStateNotifier();
public CPlayer(final int id, final CMapControl controlType, final String name, final CRace race,
final float[] startLocation) {
this.id = id;
this.colorIndex = id;
this.controlType = controlType;
this.name = name;
public CPlayer(final CRace race, final float[] startLocation, final CBasePlayer configPlayer) {
super(configPlayer);
this.race = race;
this.startLocation = startLocation;
this.racePrefs = EnumSet.noneOf(CRacePreference.class);
for (int i = 0; i < this.alliances.length; i++) {
if (i == this.id) {
// player is fully allied with self
this.alliances[i] = EnumSet.allOf(CAllianceType.class);
}
else {
this.alliances[i] = EnumSet.noneOf(CAllianceType.class);
}
}
}
public int getId() {
return this.id;
}
public int getColorIndex() {
return this.colorIndex;
}
public CMapControl getControlType() {
return this.controlType;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
public void setAlliance(final CPlayer other, final CAllianceType alliance, final boolean flag) {
setAlliance(other.getId(), alliance, flag);
}
public CRace getRace() {
return this.race;
}
public boolean isRacePrefSet(final CRacePreference racePref) {
return this.racePrefs.contains(racePref);
}
public void setAlliance(final CPlayer otherPlayer, final CAllianceType allianceType, final boolean value) {
final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayer.getId()];
if (value) {
alliancesWithOtherPlayer.add(allianceType);
}
else {
alliancesWithOtherPlayer.remove(allianceType);
}
}
public boolean hasAlliance(final CPlayer otherPlayer, final CAllianceType allianceType) {
return hasAlliance(otherPlayer.getId(), allianceType);
}
public boolean hasAlliance(final int otherPlayerIndex, final CAllianceType allianceType) {
final EnumSet<CAllianceType> alliancesWithOtherPlayer = this.alliances[otherPlayerIndex];
return alliancesWithOtherPlayer.contains(allianceType);
}
public int getGold() {
return this.gold;
}
@ -138,10 +78,6 @@ public class CPlayer {
this.stateNotifier.foodChanged();
}
public void setColorIndex(final int colorIndex) {
this.colorIndex = colorIndex;
}
public int getTechtreeUnlocked(final War3ID rawcode) {
final Integer techtreeUnlocked = this.rawcodeToTechtreeUnlocked.get(rawcode);
if (techtreeUnlocked == null) {

View File

@ -0,0 +1,25 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerColor {
RED,
BLUE,
CYAN,
PURPLE,
YELLOW,
ORANGE,
GREEN,
PINK,
LIGHT_GRAY,
LIGHT_BLUE,
AQUA,
BROWN;
public static CPlayerColor[] VALUES = values();
public static CPlayerColor getColorByIndex(final int index) {
if ((index >= 0) && (index < VALUES.length)) {
return VALUES[index];
}
return null;
}
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerGameResult {
VICTORY,
DEFEAT,
TIE,
NEUTRAL;
public static CPlayerGameResult[] VALUES = values();
}

View File

@ -0,0 +1,47 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
public interface CPlayerJass {
int getId();
void setTeam(int team);
void setStartLocationIndex(int startLocIndex);
void forceStartLocation(int startLocIndex);
void setColor(int colorIndex);
void setAlliance(int otherPlayerIndex, CAllianceType whichAllianceSetting, boolean value);
void setTaxRate(int otherPlayerIndex, CPlayerState whichResource, int rate);
void setRacePref(CRacePreference whichRacePreference);
void setRaceSelectable(boolean selectable);
void setController(CMapControl mapControl);
void setName(String name);
void setOnScoreScreen(boolean flag);
int getTeam();
int getStartLocationIndex();
int getColor();
boolean isSelectable();
CMapControl getController();
CPlayerSlotState getSlotState();
int getTaxRate(int otherPlayerIndex, CPlayerState whichResource);
boolean isRacePrefSet(CRacePreference pref);
String getName();
}

View File

@ -0,0 +1,31 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerScore {
UNITS_TRAINED,
UNITS_KILLED,
STRUCT_BUILT,
STRUCT_RAZED,
TECH_PERCENT,
FOOD_MAXPROD,
FOOD_MAXUSED,
HEROES_KILLED,
ITEMS_GAINED,
MERCS_HIRED,
GOLD_MINED_TOTAL,
GOLD_MINED_UPKEEP,
GOLD_LOST_UPKEEP,
GOLD_LOST_TAX,
GOLD_GIVEN,
GOLD_RECEIVED,
LUMBER_TOTAL,
LUMBER_LOST_UPKEEP,
LUMBER_LOST_TAX,
LUMBER_GIVEN,
LUMBER_RECEIVED,
UNIT_TOTAL,
HERO_TOTAL,
RESOURCE_TOTAL,
TOTAL;
public static CPlayerScore[] VALUES = values();
}

View File

@ -0,0 +1,42 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerState {
// current resource levels
//
RESOURCE_GOLD,
RESOURCE_LUMBER,
RESOURCE_HERO_TOKENS,
RESOURCE_FOOD_CAP,
RESOURCE_FOOD_USED,
FOOD_CAP_CEILING,
GIVES_BOUNTY,
ALLIED_VICTORY,
PLACED,
OBSERVER_ON_DEATH,
OBSERVER,
UNFOLLOWABLE,
// taxation rate for each resource
//
GOLD_UPKEEP_RATE,
LUMBER_UPKEEP_RATE,
// cumulative resources collected by the player during the mission
//
GOLD_GATHERED,
LUMBER_GATHERED,
UNKNOWN_STATE_17,
UNKNOWN_STATE_18,
UNKNOWN_STATE_19,
UNKNOWN_STATE_20,
UNKNOWN_STATE_21,
UNKNOWN_STATE_22,
UNKNOWN_STATE_23,
UNKNOWN_STATE_24,
NO_CREEP_SLEEP;
public static CPlayerState[] VALUES = values();
}

View File

@ -13,10 +13,13 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListene
public class CPlayerUnitOrderExecutor implements CPlayerUnitOrderListener {
private final CSimulation game;
private final int playerIndex;
private final CommandErrorListener errorListener;
public CPlayerUnitOrderExecutor(final CSimulation game, final CommandErrorListener errorListener) {
public CPlayerUnitOrderExecutor(final CSimulation game, final int playerIndex,
final CommandErrorListener errorListener) {
this.game = game;
this.playerIndex = playerIndex;
this.errorListener = errorListener;
}
@ -24,50 +27,60 @@ public class CPlayerUnitOrderExecutor implements CPlayerUnitOrderListener {
public void issueTargetOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final int targetHandleId, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
unit.order(this.game, new COrderTargetWidget(abilityHandleId, orderId, targetHandleId, queue), queue);
if (this.playerIndex == unit.getPlayerIndex()) {
unit.order(this.game, new COrderTargetWidget(abilityHandleId, orderId, targetHandleId, queue), queue);
}
}
@Override
public void issueDropItemAtPointOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final int targetHandleId, final float x, final float y, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
unit.order(this.game, new COrderDropItemAtPoint(abilityHandleId, orderId, targetHandleId,
new AbilityPointTarget(x, y), queue), queue);
if (this.playerIndex == unit.getPlayerIndex()) {
unit.order(this.game, new COrderDropItemAtPoint(abilityHandleId, orderId, targetHandleId,
new AbilityPointTarget(x, y), queue), queue);
}
}
@Override
public void issuePointOrder(final int unitHandleId, final int abilityHandleId, final int orderId, final float x,
final float y, final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
unit.order(this.game, new COrderTargetPoint(abilityHandleId, orderId, new AbilityPointTarget(x, y), queue),
queue);
if (this.playerIndex == unit.getPlayerIndex()) {
unit.order(this.game, new COrderTargetPoint(abilityHandleId, orderId, new AbilityPointTarget(x, y), queue),
queue);
}
}
@Override
public void issueImmediateOrder(final int unitHandleId, final int abilityHandleId, final int orderId,
final boolean queue) {
final CUnit unit = this.game.getUnit(unitHandleId);
if (abilityHandleId == 0) {
if (orderId == OrderIds.stop) {
unit.order(this.game, null, queue);
}
else if (orderId == OrderIds.holdposition) {
unit.order(this.game, null, queue);
final CBehaviorHoldPosition holdPositionBehavior = unit.getHoldPositionBehavior();
if (holdPositionBehavior != null) {
unit.setDefaultBehavior(holdPositionBehavior);
if (this.playerIndex == unit.getPlayerIndex()) {
if (abilityHandleId == 0) {
if (orderId == OrderIds.stop) {
unit.order(this.game, null, queue);
}
else if (orderId == OrderIds.holdposition) {
unit.order(this.game, null, queue);
final CBehaviorHoldPosition holdPositionBehavior = unit.getHoldPositionBehavior();
if (holdPositionBehavior != null) {
unit.setDefaultBehavior(holdPositionBehavior);
}
}
}
}
else {
unit.order(this.game, new COrderNoTarget(abilityHandleId, orderId, queue), queue);
else {
unit.order(this.game, new COrderNoTarget(abilityHandleId, orderId, queue), queue);
}
}
}
@Override
public void unitCancelTrainingItem(final int unitHandleId, final int cancelIndex) {
final CUnit unit = this.game.getUnit(unitHandleId);
unit.cancelBuildQueueItem(this.game, cancelIndex);
if (this.playerIndex == unit.getPlayerIndex()) {
unit.cancelBuildQueueItem(this.game, cancelIndex);
}
}
}

View File

@ -14,6 +14,8 @@ public enum CRace {
this.id = id;
}
public static CRace[] VALUES = values();
public int getId() {
return this.id;
}

View File

@ -8,4 +8,19 @@ public enum CRacePreference {
DEMON,
RANDOM,
USER_SELECTABLE;
public static CRacePreference[] VALUES = values();
public static CRacePreference getById(final int id) {
for (final CRacePreference type : VALUES) {
if ((type.getId()) == id) {
return type;
}
}
return null;
}
public int getId() {
return 1 << ordinal();
}
}

View File

@ -0,0 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CStartLocPrio {
LOW,
HIGH,
NOT;
public static CStartLocPrio[] VALUES = values();
}

View File

@ -0,0 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.state;
public enum CGameState {
DIVINE_INTERVENTION,
DISCONNECTED,
TIME_OF_DAY;
public static CGameState[] VALUES = values();
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.state;
public enum CUnitState {
LIFE,
MAX_LIFE,
MANA,
MAX_MANA;
public static CUnitState[] VALUES = values();
}

View File

@ -0,0 +1,89 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
public abstract class CTimer {
private int engineFireTick;
private int scheduleTick;
private float timeoutTime;
private float remainingTimeAfterPause;
private boolean running = false;
private boolean repeats;
public void setTimeoutTime(final float timeoutTime) {
this.timeoutTime = timeoutTime;
}
public boolean isRepeats() {
return this.repeats;
}
public boolean isRunning() {
return this.running;
}
public float getTimeoutTime() {
return this.timeoutTime;
}
/**
* @param simulation
*/
public void start(final CSimulation simulation) {
this.running = true;
final int currentTick = simulation.getGameTurnTick();
this.scheduleTick = currentTick;
innerStart(this.timeoutTime, simulation, currentTick);
}
private void innerStart(final float timeoutTime, final CSimulation simulation, final int currentTick) {
final int ticks = (int) (timeoutTime / WarsmashConstants.SIMULATION_STEP_TIME);
this.engineFireTick = currentTick + ticks;
simulation.registerTimer(this);
}
public void pause(final CSimulation simulation) {
this.remainingTimeAfterPause = getRemaining(simulation);
simulation.unregisterTimer(this);
}
public void resume(final CSimulation simulation) {
if (this.remainingTimeAfterPause == 0) {
start(simulation);
}
final int currentTick = simulation.getGameTurnTick();
innerStart(this.remainingTimeAfterPause, simulation, currentTick);
this.remainingTimeAfterPause = 0;
}
public float getElapsed(final CSimulation simulation) {
final int currentTick = simulation.getGameTurnTick();
final int elapsedTicks = currentTick - this.scheduleTick;
return Math.max(elapsedTicks * WarsmashConstants.SIMULATION_STEP_TIME, this.timeoutTime);
}
public float getRemaining(final CSimulation simulation) {
return this.timeoutTime - getElapsed(simulation);
}
public void setRepeats(final boolean repeats) {
this.repeats = repeats;
}
public int getEngineFireTick() {
return this.engineFireTick;
}
public abstract void onFire();
public void fire(final CSimulation simulation) {
// its implied that we will have "unregisterTimer" happen automatically
// before this is called
this.running = false;
if (this.repeats) {
start(simulation);
}
}
}

View File

@ -0,0 +1,25 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers;
import java.util.Collections;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
public class CTimerJass extends CTimer {
private JassFunction handlerFunc;
private final GlobalScope jassGlobalScope;
public CTimerJass(final GlobalScope jassGlobalScope) {
this.jassGlobalScope = jassGlobalScope;
}
public void setHandlerFunc(final JassFunction handlerFunc) {
this.handlerFunc = handlerFunc;
}
@Override
public void onFire() {
this.handlerFunc.call(Collections.emptyList(), this.jassGlobalScope, TriggerExecutionScope.EMPTY);
}
}

View File

@ -0,0 +1,248 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger;
//===================================================
//Game, Player and Unit Events
//
//When an event causes a trigger to fire these
//values allow the action code to determine which
//event was dispatched and therefore which set of
//native functions should be used to get information
//about the event.
//
//Do NOT change the order or value of these constants
//without insuring that the JASS_GAME_EVENTS_WAR3 enum
//is changed to match.
//
//===================================================
public enum JassGameEventsWar3 {
// ===================================================
// For use with TriggerRegisterGameEvent
// ===================================================
EVENT_GAME_VICTORY,
EVENT_GAME_END_LEVEL,
EVENT_GAME_VARIABLE_LIMIT,
EVENT_GAME_STATE_LIMIT,
EVENT_GAME_TIMER_EXPIRED,
EVENT_GAME_ENTER_REGION,
EVENT_GAME_LEAVE_REGION,
EVENT_GAME_TRACKABLE_HIT,
EVENT_GAME_TRACKABLE_TRACK,
EVENT_GAME_SHOW_SKILL,
EVENT_GAME_BUILD_SUBMENU,
// ===================================================
// For use with TriggerRegisterPlayerEvent
// ===================================================
EVENT_PLAYER_STATE_LIMIT,
EVENT_PLAYER_ALLIANCE_CHANGED,
EVENT_PLAYER_DEFEAT,
EVENT_PLAYER_VICTORY,
EVENT_PLAYER_LEAVE,
EVENT_PLAYER_CHAT,
EVENT_PLAYER_END_CINEMATIC,
// ===================================================
// For use with TriggerRegisterPlayerUnitEvent
// ===================================================
EVENT_PLAYER_UNIT_ATTACKED,
EVENT_PLAYER_UNIT_RESCUED,
EVENT_PLAYER_UNIT_DEATH,
EVENT_PLAYER_UNIT_DECAY,
EVENT_PLAYER_UNIT_DETECTED,
EVENT_PLAYER_UNIT_HIDDEN,
EVENT_PLAYER_UNIT_SELECTED,
EVENT_PLAYER_UNIT_DESELECTED,
EVENT_PLAYER_UNIT_CONSTRUCT_START,
EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL,
EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,
EVENT_PLAYER_UNIT_UPGRADE_START,
EVENT_PLAYER_UNIT_UPGRADE_CANCEL,
EVENT_PLAYER_UNIT_UPGRADE_FINISH,
EVENT_PLAYER_UNIT_TRAIN_START,
EVENT_PLAYER_UNIT_TRAIN_CANCEL,
EVENT_PLAYER_UNIT_TRAIN_FINISH,
EVENT_PLAYER_UNIT_RESEARCH_START,
EVENT_PLAYER_UNIT_RESEARCH_CANCEL,
EVENT_PLAYER_UNIT_RESEARCH_FINISH,
EVENT_PLAYER_UNIT_ISSUED_ORDER,
EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,
EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER,
EVENT_PLAYER_HERO_LEVEL,
EVENT_PLAYER_HERO_SKILL,
EVENT_PLAYER_HERO_REVIVABLE,
EVENT_PLAYER_HERO_REVIVE_START,
EVENT_PLAYER_HERO_REVIVE_CANCEL,
EVENT_PLAYER_HERO_REVIVE_FINISH,
EVENT_PLAYER_UNIT_SUMMON,
EVENT_PLAYER_UNIT_DROP_ITEM,
EVENT_PLAYER_UNIT_PICKUP_ITEM,
EVENT_PLAYER_UNIT_USE_ITEM,
EVENT_PLAYER_UNIT_LOADED,
// ===================================================
// For use with TriggerRegisterUnitEvent
// ===================================================
EVENT_UNIT_DAMAGED,
EVENT_UNIT_DEATH,
EVENT_UNIT_DECAY,
EVENT_UNIT_DETECTED,
EVENT_UNIT_HIDDEN,
EVENT_UNIT_SELECTED,
EVENT_UNIT_DESELECTED,
EVENT_UNIT_STATE_LIMIT,
// Events which may have a filter for the "other unit"
//
EVENT_UNIT_ACQUIRED_TARGET,
EVENT_UNIT_TARGET_IN_RANGE,
EVENT_UNIT_ATTACKED,
EVENT_UNIT_RESCUED,
EVENT_UNIT_CONSTRUCT_CANCEL,
EVENT_UNIT_CONSTRUCT_FINISH,
EVENT_UNIT_UPGRADE_START,
EVENT_UNIT_UPGRADE_CANCEL,
EVENT_UNIT_UPGRADE_FINISH,
// Events which involve the specified unit performing
// training of other units
//
EVENT_UNIT_TRAIN_START,
EVENT_UNIT_TRAIN_CANCEL,
EVENT_UNIT_TRAIN_FINISH,
EVENT_UNIT_RESEARCH_START,
EVENT_UNIT_RESEARCH_CANCEL,
EVENT_UNIT_RESEARCH_FINISH,
EVENT_UNIT_ISSUED_ORDER,
EVENT_UNIT_ISSUED_POINT_ORDER,
EVENT_UNIT_ISSUED_TARGET_ORDER,
EVENT_UNIT_HERO_LEVEL,
EVENT_UNIT_HERO_SKILL,
EVENT_UNIT_HERO_REVIVABLE,
EVENT_UNIT_HERO_REVIVE_START,
EVENT_UNIT_HERO_REVIVE_CANCEL,
EVENT_UNIT_HERO_REVIVE_FINISH,
EVENT_UNIT_SUMMON,
EVENT_UNIT_DROP_ITEM,
EVENT_UNIT_PICKUP_ITEM,
EVENT_UNIT_USE_ITEM,
EVENT_UNIT_LOADED,
EVENT_WIDGET_DEATH,
EVENT_DIALOG_BUTTON_CLICK,
EVENT_DIALOG_CLICK,
// ===================================================
// Frozen Throne Expansion Events
// Need to be added here to preserve compat
// ===================================================
// ===================================================
// For use with TriggerRegisterGameEvent
// ===================================================
EVENT_GAME_LOADED,
EVENT_GAME_TOURNAMENT_FINISH_SOON,
EVENT_GAME_TOURNAMENT_FINISH_NOW,
EVENT_GAME_SAVE,
EVENT_UNKNOWN_TFT_CODE_260,
// ===================================================
// For use with TriggerRegisterPlayerEvent
// ===================================================
EVENT_PLAYER_ARROW_LEFT_DOWN,
EVENT_PLAYER_ARROW_LEFT_UP,
EVENT_PLAYER_ARROW_RIGHT_DOWN,
EVENT_PLAYER_ARROW_RIGHT_UP,
EVENT_PLAYER_ARROW_DOWN_DOWN,
EVENT_PLAYER_ARROW_DOWN_UP,
EVENT_PLAYER_ARROW_UP_DOWN,
EVENT_PLAYER_ARROW_UP_UP,
// ===================================================
// For use with TriggerRegisterPlayerUnitEvent
// ===================================================
EVENT_PLAYER_UNIT_SELL,
EVENT_PLAYER_UNIT_CHANGE_OWNER,
EVENT_PLAYER_UNIT_SELL_ITEM,
EVENT_PLAYER_UNIT_SPELL_CHANNEL,
EVENT_PLAYER_UNIT_SPELL_CAST,
EVENT_PLAYER_UNIT_SPELL_EFFECT,
EVENT_PLAYER_UNIT_SPELL_FINISH,
EVENT_PLAYER_UNIT_SPELL_ENDCAST,
EVENT_PLAYER_UNIT_PAWN_ITEM,
EVENT_UNKNOWN_TFT_CODE_278,
EVENT_UNKNOWN_TFT_CODE_279,
EVENT_UNKNOWN_TFT_CODE_280,
EVENT_UNKNOWN_TFT_CODE_281,
EVENT_UNKNOWN_TFT_CODE_282,
EVENT_UNKNOWN_TFT_CODE_283,
EVENT_UNKNOWN_TFT_CODE_284,
EVENT_UNKNOWN_TFT_CODE_285,
// ===================================================
// For use with TriggerRegisterUnitEvent
// ===================================================
EVENT_UNIT_SELL,
EVENT_UNIT_CHANGE_OWNER,
EVENT_UNIT_SELL_ITEM,
EVENT_UNIT_SPELL_CHANNEL,
EVENT_UNIT_SPELL_CAST,
EVENT_UNIT_SPELL_EFFECT,
EVENT_UNIT_SPELL_FINISH,
EVENT_UNIT_SPELL_ENDCAST,
EVENT_UNIT_PAWN_ITEM,;
private static final int TFT_CUTOFF = EVENT_GAME_LOADED.ordinal();
public static JassGameEventsWar3[] VALUES;
static {
final JassGameEventsWar3[] localValuesArray = values();
final JassGameEventsWar3 endValue = localValuesArray[localValuesArray.length];
VALUES = new JassGameEventsWar3[endValue.getEventId() + 1];
for (final JassGameEventsWar3 event : localValuesArray) {
VALUES[event.getEventId()] = event;
}
}
public int getEventId() {
final int ordinal = ordinal();
if (ordinal >= TFT_CUTOFF) {
return (ordinal - TFT_CUTOFF) + 256;
}
return ordinal;
}
}

View File

@ -0,0 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
public enum CAttackTypeJass {
;
public static CAttackType[] VALUES = { CAttackType.SPELLS, CAttackType.NORMAL, CAttackType.PIERCE,
CAttackType.SIEGE, CAttackType.MAGIC, CAttackType.CHAOS, CAttackType.HERO };
}

View File

@ -0,0 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CBlendMode {
NONE,
KEYALPHA,
BLEND,
ADDITIVE,
MODULATE,
MODULATE_2X;
public static CBlendMode[] VALUES = values();
}

View File

@ -0,0 +1,13 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CCameraField {
TARGET_DISTANCE,
FARZ,
ANGLE_OF_ATTACK,
FIELD_OF_VIEW,
ROLL,
ROTATION,
ZOFFSET;
public static CCameraField[] VALUES = values();
}

View File

@ -0,0 +1,32 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CDamageType {
UNKNOWN,
UNKNOWN_CODE_1,
UNKNOWN_CODE_2,
UNKNOWN_CODE_3,
NORMAL,
ENHANCED,
UNKNOWN_CODE_6,
UNKNOWN_CODE_7,
FIRE,
COLD,
LIGHTNING,
POISON,
DISEASE,
DIVINE,
MAGIC,
SONIC,
ACID,
FORCE,
DEATH,
MIND,
PLANT,
DEFENSIVE,
DEMOLITION,
SLOW_POISON,
SPIRIT_LINK,
SHADOW_STRIKE;
public static CDamageType[] VALUES = values();
}

View File

@ -0,0 +1,13 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CEffectType {
EFFECT,
TARGET,
CASTER,
SPECIAL,
AREA_EFFECT,
MISSILE,
LIGHTNING;
public static CEffectType[] VALUES = values();
}

View File

@ -0,0 +1,22 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CFogState {
MASKED,
FOGGED,
VISIBLE;
public static CFogState[] VALUES = values();
public static CFogState getById(final int id) {
for (final CFogState type : VALUES) {
if ((type.getId()) == id) {
return type;
}
}
return null;
}
public int getId() {
return 1 << ordinal();
}
}

View File

@ -0,0 +1,11 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CGameSpeed {
SLOWEST,
SLOW,
NORMAL,
FAST,
FASTEST;
public static CGameSpeed[] VALUES = values();
}

View File

@ -0,0 +1,27 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CGameType {
MELEE,
FFA,
USE_MAP_SETTINGS,
BLIZ,
ONE_ON_ONE,
TWO_TEAM_PLAY,
THREE_TEAM_PLAY,
FOUR_TEAM_PLAY;
public static CGameType[] VALUES = values();
public static CGameType getById(final int id) {
for (final CGameType type : VALUES) {
if ((type.getId()) == id) {
return type;
}
}
return null;
}
public int getId() {
return 1 << ordinal();
}
}

View File

@ -0,0 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CLimitOp {
LESS_THAN,
LESS_THAN_OR_EQUAL,
EQUAL,
GREATER_THAN_OR_EQUAL,
GREATER_THAN,
NOT_EQUAL;
public static CLimitOp[] VALUES = values();
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CMapDensity {
NONE,
LIGHT,
MEDIUM,
HEAVY;
public static CMapDensity[] VALUES = values();
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CMapDifficulty {
EASY,
NORMAL,
HARD,
INSANE;
public static CMapDifficulty[] VALUES = values();
}

View File

@ -0,0 +1,14 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CPathingTypeJass {
ANY,
WALKABILITY,
FLYABILITY,
BUILDABILITY,
PEONHARVESTPATHING,
BLIGHTPATHING,
FLOATABILITY,
AMPHIBIOUSPATHING;
public static CPathingTypeJass[] VALUES = values();
}

View File

@ -0,0 +1,9 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CPlayerSlotState {
EMPTY,
PLAYING,
LEFT;
public static CPlayerSlotState[] VALUES = values();
}

View File

@ -0,0 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CRarityControl {
FREQUENT,
RARE;
public static CRarityControl[] VALUES = values();
}

View File

@ -0,0 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CSoundType {
EFFECT,
EFFECT_LOOPED;
public static CSoundType[] VALUES = values();
}

View File

@ -0,0 +1,14 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CSoundVolumeGroup {
UNITMOVEMENT,
UNITSOUNDS,
COMBAT,
SPELLS,
UI,
MUSIC,
AMBIENTSOUNDS,
FIRE;
public static CSoundVolumeGroup[] VALUES = values();
}

View File

@ -0,0 +1,10 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CTexMapFlags {
NONE,
WRAP_U,
WRAP_V,
WRAP_UV;
public static CTexMapFlags[] VALUES = values();
}

View File

@ -0,0 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CVersion {
REIGN_OF_CHAOS,
FROZEN_THRONE;
public static CVersion[] VALUES = values();
}

View File

@ -0,0 +1,40 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CWeaponSoundTypeJass {
WHOKNOWS(null),
METAL_LIGHT_CHOP("MetalLightChop"),
METAL_MEDIUM_CHOP("MetalMediumChop"),
METAL_HEAVY_CHOP("MetalHeavyChop"),
METAL_LIGHT_SLICE("MetalLightSlice"),
METAL_MEDIUM_SLICE("MetalMediumSlice"),
METAL_HEAVY_SLICE("MetalHeavySlice"),
METAL_MEDIUM_BASH("MetalMediumBash"),
METAL_HEAVY_BASH("MetalHeavyBash"),
METAL_MEDIUM_STAB("MetalMediumStab"),
METAL_HEAVY_STAB("MetalHeavyStab"),
WOOD_LIGHT_SLICE("WoodLightSlice"),
WOOD_MEDIUM_SLICE("WoodMediumSlice"),
WOOD_HEAVY_SLICE("WoodHeavySlice"),
WOOD_LIGHT_BASH("WoodLightBash"),
WOOD_MEDIUM_BASH("WoodMediumBash"),
WOOD_HEAVY_BASH("WoodHeavyBash"),
WOOD_LIGHT_STAB("WoodLightStab"),
WOOD_MEDIUM_STAB("WoodMediumStab"),
CLAW_LIGHT_SLICE("ClawLightSlice"),
CLAW_MEDIUM_SLICE("ClawMediumSlice"),
CLAW_HEAVY_SLICE("ClawHeavySlice"),
AXE_MEDIUM_CHOP("AxeMediumChop"),
ROCK_HEAVY_BASH("RockHeavyBash");
private final String soundKey;
CWeaponSoundTypeJass(final String soundKey) {
this.soundKey = soundKey;
}
public String getSoundKey() {
return this.soundKey;
}
public static CWeaponSoundTypeJass[] VALUES = values();
}

View File

@ -0,0 +1,39 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit;
public enum CUnitTypeJass {
HERO,
DEAD,
STRUCTURE,
FLYING,
GROUND,
ATTACKS_FLYING,
ATTACKS_GROUND,
MELEE_ATTACKER,
RANGED_ATTACKER,
GIANT,
SUMMONED,
STUNNED,
PLAGUED,
SNARED,
UNDEAD,
MECHANICAL,
PEON,
SAPPER,
TOWNHALL,
ANCIENT,
TAUREN,
POISONED,
POLYMORPHED,
SLEEPING,
RESISTANT,
ETHEREAL,
MAGIC_IMMUNE;
public static CUnitTypeJass[] VALUES = values();
}

View File

@ -1163,7 +1163,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
MeleeUI.this.cursorModelInstance = (MdxComplexInstance) model.addInstance();
// MeleeUI.this.cursorModelInstance.setVertexColor(new float[] { 1, 1, 1, 0.5f });
final int playerColorIndex = viewer.simulation
.getPlayer(MeleeUI.this.activeCommandUnit.getSimulationUnit().getPlayerIndex()).getColorIndex();
.getPlayer(MeleeUI.this.activeCommandUnit.getSimulationUnit().getPlayerIndex()).getColor();
MeleeUI.this.cursorModelInstance.setTeamColor(playerColorIndex);
MeleeUI.this.cursorModelInstance.rotate(RenderUnit.tempQuat.setFromAxis(RenderMathUtils.VEC3_UNIT_Z,
viewer.simulation.getGameplayConstants().getBuildingAngle()));
@ -1534,8 +1534,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private void repositionRallyPoint(final CUnit simulationUnit) {
final AbilityTarget rallyPoint = simulationUnit.getRallyPoint();
if (rallyPoint != null) {
this.rallyPointInstance.setTeamColor(
this.war3MapViewer.simulation.getPlayer(simulationUnit.getPlayerIndex()).getColorIndex());
this.rallyPointInstance
.setTeamColor(this.war3MapViewer.simulation.getPlayer(simulationUnit.getPlayerIndex()).getColor());
this.rallyPointInstance.show();
this.rallyPointInstance.detach();
rallyPoint.visit(this.rallyPositioningVisitor.reset(this.rallyPointInstance));
@ -1634,7 +1634,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
repositionRallyPoint(simulationUnit);
repositionWaypointFlags(simulationUnit);
if (simulationUnit.getBuildQueue()[0] != null) {
if ((simulationUnit.getBuildQueue()[0] != null)
&& (simulationUnit.getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex())) {
for (int i = 0; i < this.queueIconFrames.length; i++) {
final QueueItemType queueItemType = simulationUnit.getBuildQueueTypes()[i];
if (queueItemType == null) {
@ -2063,24 +2064,27 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private void clearAndRepopulateCommandCard() {
clearCommandCard();
final AbilityDataUI abilityDataUI = this.war3MapViewer.getAbilityDataUI();
final int menuOrderId = getSubMenuOrderId();
if ((this.activeCommand != null) && (this.draggingItem == null)) {
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(), 0,
menuOrderId, 0, false, false, true, cancelUI.getToolTip(), cancelUI.getUberTip(), 0, 0, 0);
}
else {
if (menuOrderId != 0) {
final int exitOrderId = this.subMenuOrderIdStack.size() > 1
? this.subMenuOrderIdStack.get(this.subMenuOrderIdStack.size() - 2)
: 0;
if (this.selectedUnit.getSimulationUnit().getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex()) {
final AbilityDataUI abilityDataUI = this.war3MapViewer.getAbilityDataUI();
final int menuOrderId = getSubMenuOrderId();
if ((this.activeCommand != null) && (this.draggingItem == null)) {
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(), 0,
exitOrderId, 0, false, false, true, cancelUI.getToolTip(), cancelUI.getUberTip(), 0, 0, 0);
menuOrderId, 0, false, false, true, cancelUI.getToolTip(), cancelUI.getUberTip(), 0, 0, 0);
}
else {
if (menuOrderId != 0) {
final int exitOrderId = this.subMenuOrderIdStack.size() > 1
? this.subMenuOrderIdStack.get(this.subMenuOrderIdStack.size() - 2)
: 0;
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(),
0, exitOrderId, 0, false, false, true, cancelUI.getToolTip(), cancelUI.getUberTip(), 0, 0,
0);
}
this.selectedUnit.populateCommandCard(this.war3MapViewer.simulation, this.rootFrame, this,
abilityDataUI, menuOrderId);
}
this.selectedUnit.populateCommandCard(this.war3MapViewer.simulation, this.rootFrame, this, abilityDataUI,
menuOrderId);
}
}
@ -2224,7 +2228,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
else {
if (button == Input.Buttons.RIGHT) {
if (getSelectedUnit() != null) {
if ((getSelectedUnit() != null) && (getSelectedUnit().getSimulationUnit()
.getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex())) {
final RenderWidget rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY);
if ((rayPickUnit != null) && !rayPickUnit.getSimulationWidget().isDead()) {
boolean ordered = false;
@ -2295,19 +2300,21 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
boolean ordered = false;
boolean rallied = false;
for (final RenderUnit unit : this.selectedUnits) {
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
ability.checkCanUse(this.war3MapViewer.simulation, unit.getSimulationUnit(), OrderIds.smart,
BooleanAbilityActivationReceiver.INSTANCE);
if (BooleanAbilityActivationReceiver.INSTANCE.isOk()) {
ability.checkCanTarget(this.war3MapViewer.simulation, unit.getSimulationUnit(), OrderIds.smart,
clickLocationTemp2, PointAbilityTargetCheckReceiver.INSTANCE);
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (target != null) {
this.unitOrderListener.issuePointOrder(unit.getSimulationUnit().getHandleId(),
ability.getHandleId(), OrderIds.smart, clickLocationTemp2.x, clickLocationTemp2.y,
isShiftDown());
rallied |= ability instanceof CAbilityRally;
ordered = true;
if (unit.getSimulationUnit().getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex()) {
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
ability.checkCanUse(this.war3MapViewer.simulation, unit.getSimulationUnit(), OrderIds.smart,
BooleanAbilityActivationReceiver.INSTANCE);
if (BooleanAbilityActivationReceiver.INSTANCE.isOk()) {
ability.checkCanTarget(this.war3MapViewer.simulation, unit.getSimulationUnit(), OrderIds.smart,
clickLocationTemp2, PointAbilityTargetCheckReceiver.INSTANCE);
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
if (target != null) {
this.unitOrderListener.issuePointOrder(unit.getSimulationUnit().getHandleId(),
ability.getHandleId(), OrderIds.smart, clickLocationTemp2.x, clickLocationTemp2.y,
isShiftDown());
rallied |= ability instanceof CAbilityRally;
ordered = true;
}
}
}
}
@ -2345,33 +2352,38 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
if (selectionChanged) {
this.selectedSoundCount = 0;
}
if (unit.soundset != null) {
UnitSound ackSoundToPlay = unit.soundset.what;
int soundIndex;
final int pissedSoundCount = unit.soundset.pissed.getSoundCount();
if (unit.getSimulationUnit().isConstructing()) {
ackSoundToPlay = this.war3MapViewer.getUiSounds()
.getSound(this.rootFrame.getSkinField("ConstructingBuilding"));
soundIndex = (int) (Math.random() * ackSoundToPlay.getSoundCount());
}
else {
if ((this.selectedSoundCount >= 3) && (pissedSoundCount > 0)) {
soundIndex = this.selectedSoundCount - 3;
ackSoundToPlay = unit.soundset.pissed;
}
else {
if (unit.getSimulationUnit().getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex()) {
if (unit.soundset != null) {
UnitSound ackSoundToPlay = unit.soundset.what;
int soundIndex;
final int pissedSoundCount = unit.soundset.pissed.getSoundCount();
if (unit.getSimulationUnit().isConstructing()) {
ackSoundToPlay = this.war3MapViewer.getUiSounds()
.getSound(this.rootFrame.getSkinField("ConstructingBuilding"));
soundIndex = (int) (Math.random() * ackSoundToPlay.getSoundCount());
}
}
if ((ackSoundToPlay != null) && ackSoundToPlay
.playUnitResponse(this.war3MapViewer.worldScene.audioContext, unit, soundIndex)) {
this.selectedSoundCount++;
if ((this.selectedSoundCount - 3) >= pissedSoundCount) {
this.selectedSoundCount = 0;
else {
if ((this.selectedSoundCount >= 3) && (pissedSoundCount > 0)) {
soundIndex = this.selectedSoundCount - 3;
ackSoundToPlay = unit.soundset.pissed;
}
else {
soundIndex = (int) (Math.random() * ackSoundToPlay.getSoundCount());
}
}
if ((ackSoundToPlay != null) && ackSoundToPlay
.playUnitResponse(this.war3MapViewer.worldScene.audioContext, unit, soundIndex)) {
this.selectedSoundCount++;
if ((this.selectedSoundCount - 3) >= pissedSoundCount) {
this.selectedSoundCount = 0;
}
playedNewSound = true;
}
playedNewSound = true;
}
}
else {
this.war3MapViewer.getUiSounds().getSound("InterfaceClick").play(this.uiScene.audioContext, 0, 0, 0);
}
if (selectionChanged) {
selectUnit(unit);
}

View File

@ -3,6 +3,8 @@ package com.etheller.interpreter.ast.scope;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
public class TriggerExecutionScope {
public static final TriggerExecutionScope EMPTY = new TriggerExecutionScope(null);
private final Trigger triggeringTrigger;
public TriggerExecutionScope(final Trigger triggeringTrigger) {

View File

@ -3,12 +3,18 @@ package com.etheller.interpreter.ast.value;
public class StringJassValue implements JassValue {
private final String value;
public static StringJassValue of(final String value) {
// later this could do that dumb thing jass does with making sure we dont create
// duplicate instances, maybe
return new StringJassValue(value);
}
public StringJassValue(final String value) {
this.value = value;
}
public String getValue() {
return value;
return this.value;
}
@Override