mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Merge and some fixes, includes click drag ui test
This commit is contained in:
commit
5b7db285e2
@ -18,7 +18,7 @@ Path06="."
|
|||||||
[Map]
|
[Map]
|
||||||
//FilePath="CombatUnitTests.w3x"
|
//FilePath="CombatUnitTests.w3x"
|
||||||
//FilePath="PitchRoll.w3x"
|
//FilePath="PitchRoll.w3x"
|
||||||
//FilePath="PeonStartingBase.w3x"
|
FilePath="PeonStartingBase.w3x"
|
||||||
//FilePath="DungeonGoldMine.w3m"
|
//FilePath="DungeonGoldMine.w3m"
|
||||||
//FilePath="PlayerPeasants.w3m"
|
//FilePath="PlayerPeasants.w3m"
|
||||||
//FilePath="FireLord.w3x"
|
//FilePath="FireLord.w3x"
|
||||||
@ -29,4 +29,4 @@ Path06="."
|
|||||||
//FilePath="OrcAssault.w3x"
|
//FilePath="OrcAssault.w3x"
|
||||||
//FilePath="FrostyVsFarm.w3m"
|
//FilePath="FrostyVsFarm.w3m"
|
||||||
//FilePath="ModelTest.w3x"
|
//FilePath="ModelTest.w3x"
|
||||||
FilePath="SpinningSample.w3x"
|
//FilePath="SpinningSample.w3x"
|
@ -134,7 +134,10 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Element cameraData = this.viewer.miscData.get("Camera");
|
final Element cameraData = this.viewer.miscData.get("Camera");
|
||||||
final Element cameraListenerData = this.viewer.miscData.get("Listener");
|
Element cameraListenerData = this.viewer.miscData.get("Listener");
|
||||||
|
if (cameraListenerData == null) {
|
||||||
|
cameraListenerData = new Element("Listener", new DataTable(null));
|
||||||
|
}
|
||||||
final CameraPreset[] cameraPresets = new CameraPreset[6];
|
final CameraPreset[] cameraPresets = new CameraPreset[6];
|
||||||
for (int i = 0; i < cameraPresets.length; i++) {
|
for (int i = 0; i < cameraPresets.length; i++) {
|
||||||
cameraPresets[i] = new CameraPreset(cameraData.getFieldFloatValue("AOA", i),
|
cameraPresets[i] = new CameraPreset(cameraData.getFieldFloatValue("AOA", i),
|
||||||
@ -353,6 +356,9 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyTyped(final char character) {
|
public boolean keyTyped(final char character) {
|
||||||
|
if (character == '1') {
|
||||||
|
Gdx.input.setCursorCatched(!Gdx.input.isCursorCatched());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +379,10 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
|
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
|
||||||
|
final float worldScreenY = getHeight() - screenY;
|
||||||
|
if (this.meleeUI.touchDragged(screenX, screenY, worldScreenY, pointer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,14 @@ import com.etheller.warsmash.parsers.fdf.datamodel.SetPointDefinition;
|
|||||||
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||||
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.frames.FilterModeTextureFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
|
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||||
|
import com.etheller.warsmash.parsers.mdlx.Layer.FilterMode;
|
||||||
import com.etheller.warsmash.units.DataTable;
|
import com.etheller.warsmash.units.DataTable;
|
||||||
import com.etheller.warsmash.units.Element;
|
import com.etheller.warsmash.units.Element;
|
||||||
import com.etheller.warsmash.util.ImageUtils;
|
import com.etheller.warsmash.util.ImageUtils;
|
||||||
@ -211,6 +213,16 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
|||||||
return textureFrame;
|
return textureFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextureFrame createTextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||||
|
final Vector4Definition texCoord, final FilterMode filterMode) {
|
||||||
|
final FilterModeTextureFrame textureFrame = new FilterModeTextureFrame(name, parent, decorateFileNames,
|
||||||
|
texCoord);
|
||||||
|
textureFrame.setFilterMode(filterMode);
|
||||||
|
this.nameToFrame.put(name, textureFrame);
|
||||||
|
add(textureFrame);
|
||||||
|
return textureFrame;
|
||||||
|
}
|
||||||
|
|
||||||
public StringFrame createStringFrame(final String name, final UIFrame parent, final Color color,
|
public StringFrame createStringFrame(final String name, final UIFrame parent, final Color color,
|
||||||
final TextJustify justifyH, final TextJustify justifyV, final float fdfFontSize) {
|
final TextJustify justifyH, final TextJustify justifyV, final float fdfFontSize) {
|
||||||
this.fontParam.size = (int) convertY(this.viewport, fdfFontSize);
|
this.fontParam.size = (int) convertY(this.viewport, fdfFontSize);
|
||||||
|
@ -25,6 +25,9 @@ public class StringFrame extends AbstractRenderableFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setText(final String text) {
|
public void setText(final String text) {
|
||||||
|
if (text == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +63,12 @@ public class TextureFrame extends AbstractRenderableFrame {
|
|||||||
public void setTexture(final TextureRegion texture) {
|
public void setTexture(final TextureRegion texture) {
|
||||||
this.texture = texture;
|
this.texture = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,43 @@ public class Quadtree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean intersect(float x, float y, final QuadtreeIntersector<T> intersector) {
|
||||||
|
if (this.leaf) {
|
||||||
|
for (int i = 0; i < this.nodes.size; i++) {
|
||||||
|
final Node<T> node = this.nodes.get(i);
|
||||||
|
if (node.bounds.contains(x, y)) {
|
||||||
|
if (intersector.onIntersect(node.object)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.northeast.bounds.contains(x, y)) {
|
||||||
|
if (this.northeast.intersect(x, y, intersector)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.northwest.bounds.contains(x, y)) {
|
||||||
|
if (this.northwest.intersect(x, y, intersector)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.southwest.bounds.contains(x, y)) {
|
||||||
|
if (this.southwest.intersect(x, y, intersector)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.southeast.bounds.contains(x, y)) {
|
||||||
|
if (this.southeast.intersect(x, y, intersector)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void add(final Node<T> node, final int depth) {
|
private void add(final Node<T> node, final int depth) {
|
||||||
if (this.leaf) {
|
if (this.leaf) {
|
||||||
if ((this.nodes.size >= SPLIT_THRESHOLD) && (depth < MAX_DEPTH)) {
|
if ((this.nodes.size >= SPLIT_THRESHOLD) && (depth < MAX_DEPTH)) {
|
||||||
|
@ -31,4 +31,8 @@ public class Bounds {
|
|||||||
public boolean intersectRayFast(final Ray ray) {
|
public boolean intersectRayFast(final Ray ray) {
|
||||||
return Intersector.intersectRayBoundsFast(ray, this.boundingBox);
|
return Intersector.intersectRayBoundsFast(ray, this.boundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BoundingBox getBoundingBox() {
|
||||||
|
return boundingBox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,343 +22,328 @@ import com.etheller.warsmash.viewer5.Texture;
|
|||||||
import com.etheller.warsmash.viewer5.handlers.EmitterObject;
|
import com.etheller.warsmash.viewer5.handlers.EmitterObject;
|
||||||
|
|
||||||
public class EventObjectEmitterObject extends GenericObject implements EmitterObject {
|
public class EventObjectEmitterObject extends GenericObject implements EmitterObject {
|
||||||
private static final class LoadGenericSoundCallback implements LoadGenericCallback {
|
private static final class LoadGenericSoundCallback implements LoadGenericCallback {
|
||||||
private final String filename;
|
private final String filename;
|
||||||
|
|
||||||
public LoadGenericSoundCallback(final String filename) {
|
public LoadGenericSoundCallback(final String filename) {
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object call(final InputStream data) {
|
public Object call(final InputStream data) {
|
||||||
final FileHandle temp = new FileHandle(this.filename) {
|
final FileHandle temp = new FileHandle(this.filename) {
|
||||||
@Override
|
@Override
|
||||||
public InputStream read() {
|
public InputStream read() {
|
||||||
return data;
|
return data;
|
||||||
};
|
}
|
||||||
};
|
|
||||||
if (data != null) {
|
|
||||||
return Gdx.audio.newSound(temp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
System.err.println("Warning: missing sound file: " + this.filename);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final LoadGenericCallback mappedDataCallback = new LoadGenericCallback() {
|
;
|
||||||
|
};
|
||||||
|
if (data != null) {
|
||||||
|
return Gdx.audio.newSound(temp);
|
||||||
|
} else {
|
||||||
|
System.err.println("Warning: missing sound file: " + this.filename);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private static final LoadGenericCallback mappedDataCallback = new LoadGenericCallback() {
|
||||||
public Object call(final InputStream data) {
|
|
||||||
final StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(data, "utf-8"))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
stringBuilder.append(line);
|
|
||||||
stringBuilder.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (final UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
catch (final IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return new MappedData(stringBuilder.toString());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private int geometryEmitterType = -1;
|
@Override
|
||||||
public final String type;
|
public Object call(final InputStream data) {
|
||||||
private final String id;
|
final StringBuilder stringBuilder = new StringBuilder();
|
||||||
public final long[] keyFrames;
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(data, "utf-8"))) {
|
||||||
private long globalSequence = -1;
|
String line;
|
||||||
private final long[] defval = { 1 };
|
while ((line = reader.readLine()) != null) {
|
||||||
public MdxModel internalModel;
|
stringBuilder.append(line);
|
||||||
public Texture internalTexture;
|
stringBuilder.append("\n");
|
||||||
public float[][] colors;
|
}
|
||||||
public float[] intervalTimes;
|
} catch (final UnsupportedEncodingException e) {
|
||||||
public float scale;
|
throw new RuntimeException(e);
|
||||||
public int columns;
|
} catch (final IOException e) {
|
||||||
public int rows;
|
throw new RuntimeException(e);
|
||||||
public float lifeSpan;
|
}
|
||||||
public int blendSrc;
|
return new MappedData(stringBuilder.toString());
|
||||||
public int blendDst;
|
}
|
||||||
public float[][] intervals;
|
};
|
||||||
public float distanceCutoff;
|
|
||||||
private float maxDistance;
|
|
||||||
public float minDistance;
|
|
||||||
private float pitch;
|
|
||||||
private float pitchVariance;
|
|
||||||
private float volume;
|
|
||||||
public List<Sound> decodedBuffers = new ArrayList<>();
|
|
||||||
/**
|
|
||||||
* If this is an SPL/UBR emitter object, ok will be set to true if the tables
|
|
||||||
* are loaded.
|
|
||||||
*
|
|
||||||
* This is because, like the other geometry emitters, it is fine to use them
|
|
||||||
* even if the textures don't load.
|
|
||||||
*
|
|
||||||
* The particles will simply be black.
|
|
||||||
*/
|
|
||||||
private boolean ok = false;
|
|
||||||
|
|
||||||
public EventObjectEmitterObject(final MdxModel model,
|
private int geometryEmitterType = -1;
|
||||||
final com.etheller.warsmash.parsers.mdlx.EventObject eventObject, final int index) {
|
public final String type;
|
||||||
super(model, eventObject, index);
|
private final String id;
|
||||||
|
public final long[] keyFrames;
|
||||||
|
private long globalSequence = -1;
|
||||||
|
private final long[] defval = {1};
|
||||||
|
public MdxModel internalModel;
|
||||||
|
public Texture internalTexture;
|
||||||
|
public float[][] colors;
|
||||||
|
public float[] intervalTimes;
|
||||||
|
public float scale;
|
||||||
|
public int columns;
|
||||||
|
public int rows;
|
||||||
|
public float lifeSpan;
|
||||||
|
public int blendSrc;
|
||||||
|
public int blendDst;
|
||||||
|
public float[][] intervals;
|
||||||
|
public float distanceCutoff;
|
||||||
|
private float maxDistance;
|
||||||
|
public float minDistance;
|
||||||
|
private float pitch;
|
||||||
|
private float pitchVariance;
|
||||||
|
private float volume;
|
||||||
|
public List<Sound> decodedBuffers = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* If this is an SPL/UBR emitter object, ok will be set to true if the tables
|
||||||
|
* are loaded.
|
||||||
|
* <p>
|
||||||
|
* This is because, like the other geometry emitters, it is fine to use them
|
||||||
|
* even if the textures don't load.
|
||||||
|
* <p>
|
||||||
|
* The particles will simply be black.
|
||||||
|
*/
|
||||||
|
private boolean ok = false;
|
||||||
|
|
||||||
final ModelViewer viewer = model.viewer;
|
public EventObjectEmitterObject(final MdxModel model,
|
||||||
final String name = eventObject.getName();
|
final com.etheller.warsmash.parsers.mdlx.EventObject eventObject, final int index) {
|
||||||
String type = name.substring(0, 3);
|
super(model, eventObject, index);
|
||||||
final String id = name.substring(4);
|
|
||||||
|
|
||||||
// Same thing
|
final ModelViewer viewer = model.viewer;
|
||||||
if ("FPT".equals(type)) {
|
final String name = eventObject.getName();
|
||||||
type = "SPL";
|
String type = name.substring(0, 3);
|
||||||
}
|
final String id = name.substring(4);
|
||||||
|
|
||||||
if ("SPL".equals(type)) {
|
// Same thing
|
||||||
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPLAT;
|
if ("FPT".equals(type)) {
|
||||||
}
|
type = "SPL";
|
||||||
else if ("UBR".equals(type)) {
|
}
|
||||||
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_UBERSPLAT;
|
|
||||||
}
|
|
||||||
else if ("SPN".equals(type)) {
|
|
||||||
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPN;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.type = type;
|
if ("SPL".equals(type)) {
|
||||||
this.id = id;
|
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPLAT;
|
||||||
this.keyFrames = eventObject.getKeyFrames();
|
} else if ("UBR".equals(type)) {
|
||||||
|
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_UBERSPLAT;
|
||||||
|
} else if ("SPN".equals(type)) {
|
||||||
|
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPN;
|
||||||
|
}
|
||||||
|
|
||||||
final int globalSequenceId = eventObject.getGlobalSequenceId();
|
this.type = type;
|
||||||
if (globalSequenceId != -1) {
|
this.id = id;
|
||||||
this.globalSequence = model.getGlobalSequences().get(globalSequenceId);
|
this.keyFrames = eventObject.getKeyFrames();
|
||||||
}
|
|
||||||
|
|
||||||
final List<GenericResource> tables = new ArrayList<>();
|
final int globalSequenceId = eventObject.getGlobalSequenceId();
|
||||||
final PathSolver pathSolver = model.pathSolver;
|
if (globalSequenceId != -1) {
|
||||||
final Object solverParams = model.solverParams;
|
this.globalSequence = model.getGlobalSequences().get(globalSequenceId);
|
||||||
|
}
|
||||||
|
|
||||||
if ("SPN".equals(type)) {
|
final List<GenericResource> tables = new ArrayList<>();
|
||||||
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SpawnData.slk", solverParams).finalSrc,
|
final PathSolver pathSolver = model.pathSolver;
|
||||||
FetchDataTypeName.SLK, mappedDataCallback));
|
final Object solverParams = model.solverParams;
|
||||||
}
|
|
||||||
else if ("SPL".equals(type)) {
|
|
||||||
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SplatData.slk", solverParams).finalSrc,
|
|
||||||
FetchDataTypeName.SLK, mappedDataCallback));
|
|
||||||
}
|
|
||||||
else if ("UBR".equals(type)) {
|
|
||||||
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\UberSplatData.slk", solverParams).finalSrc,
|
|
||||||
FetchDataTypeName.SLK, mappedDataCallback));
|
|
||||||
}
|
|
||||||
else if ("SND".equals(type)) {
|
|
||||||
if (!model.reforged) {
|
|
||||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimLookups.slk", solverParams).finalSrc,
|
|
||||||
FetchDataTypeName.SLK, mappedDataCallback));
|
|
||||||
}
|
|
||||||
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
|
|
||||||
FetchDataTypeName.SLK, mappedDataCallback));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Units\Critters\BlackStagMale\BlackStagMale.mdx has an event object named
|
|
||||||
// "Point01".
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO I am scrapping some async stuff with promises here from the JS and
|
if ("SPN".equals(type)) {
|
||||||
// calling load
|
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SpawnData.slk", solverParams).finalSrc,
|
||||||
this.load(tables);
|
FetchDataTypeName.SLK, mappedDataCallback));
|
||||||
}
|
} else if ("SPL".equals(type)) {
|
||||||
|
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SplatData.slk", solverParams).finalSrc,
|
||||||
|
FetchDataTypeName.SLK, mappedDataCallback));
|
||||||
|
} else if ("UBR".equals(type)) {
|
||||||
|
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\UberSplatData.slk", solverParams).finalSrc,
|
||||||
|
FetchDataTypeName.SLK, mappedDataCallback));
|
||||||
|
} else if ("SND".equals(type)) {
|
||||||
|
if (!model.reforged) {
|
||||||
|
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimLookups.slk", solverParams).finalSrc,
|
||||||
|
FetchDataTypeName.SLK, mappedDataCallback));
|
||||||
|
}
|
||||||
|
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
|
||||||
|
FetchDataTypeName.SLK, mappedDataCallback));
|
||||||
|
} else {
|
||||||
|
// Units\Critters\BlackStagMale\BlackStagMale.mdx has an event object named
|
||||||
|
// "Point01".
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private float getFloat(final MappedDataRow row, final String name) {
|
// TODO I am scrapping some async stuff with promises here from the JS and
|
||||||
final Float x = (Float) row.get(name);
|
// calling load
|
||||||
if (x == null) {
|
this.load(tables);
|
||||||
return Float.NaN;
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
return x.floatValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getInt(final MappedDataRow row, final String name) {
|
private float getFloat(final MappedDataRow row, final String name) {
|
||||||
return getInt(row, name, Integer.MIN_VALUE);
|
final Float x = (Float) row.get(name);
|
||||||
}
|
if (x == null) {
|
||||||
|
return Float.NaN;
|
||||||
|
} else {
|
||||||
|
return x.floatValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int getInt(final MappedDataRow row, final String name, final int defaultValue) {
|
private int getInt(final MappedDataRow row, final String name) {
|
||||||
final Number x = (Number) row.get(name);
|
return getInt(row, name, Integer.MIN_VALUE);
|
||||||
if (x == null) {
|
}
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return x.intValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void load(final List<GenericResource> tables) {
|
private int getInt(final MappedDataRow row, final String name, final int defaultValue) {
|
||||||
final MappedData firstTable = (MappedData) tables.get(0).data;
|
final Number x = (Number) row.get(name);
|
||||||
final MappedDataRow row = firstTable.getRow(this.id.trim());
|
if (x == null) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return x.intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (row != null) {
|
private void load(final List<GenericResource> tables) {
|
||||||
final MdxModel model = this.model;
|
final MappedData firstTable = (MappedData) tables.get(0).data;
|
||||||
final ModelViewer viewer = model.viewer;
|
if (firstTable == null) {
|
||||||
final PathSolver pathSolver = model.pathSolver;
|
return;
|
||||||
|
}
|
||||||
|
final MappedDataRow row = firstTable.getRow(this.id.trim());
|
||||||
|
|
||||||
if ("SPN".equals(this.type)) {
|
if (row != null) {
|
||||||
this.internalModel = (MdxModel) viewer.load(((String) row.get("Model")).replace(".mdl", ".mdx"),
|
final MdxModel model = this.model;
|
||||||
pathSolver, model.solverParams);
|
final ModelViewer viewer = model.viewer;
|
||||||
|
final PathSolver pathSolver = model.pathSolver;
|
||||||
|
|
||||||
if (this.internalModel != null) {
|
if ("SPN".equals(this.type)) {
|
||||||
// TODO javascript async code removed here
|
this.internalModel = (MdxModel) viewer.load(((String) row.get("Model")).replace(".mdl", ".mdx"),
|
||||||
|
pathSolver, model.solverParams);
|
||||||
|
|
||||||
|
if (this.internalModel != null) {
|
||||||
|
// TODO javascript async code removed here
|
||||||
// this.internalModel.whenLoaded((model) => this.ok = model.ok)
|
// this.internalModel.whenLoaded((model) => this.ok = model.ok)
|
||||||
this.ok = this.internalModel.ok;
|
this.ok = this.internalModel.ok;
|
||||||
}
|
}
|
||||||
}
|
} else if ("SPL".equals(this.type) || "UBR".equals(this.type)) {
|
||||||
else if ("SPL".equals(this.type) || "UBR".equals(this.type)) {
|
final String texturesExt = model.reforged ? ".dds" : ".blp";
|
||||||
final String texturesExt = model.reforged ? ".dds" : ".blp";
|
|
||||||
|
|
||||||
this.internalTexture = (Texture) viewer.load(
|
this.internalTexture = (Texture) viewer.load(
|
||||||
"ReplaceableTextures\\Splats\\" + row.get("file") + texturesExt, pathSolver,
|
"ReplaceableTextures\\Splats\\" + row.get("file") + texturesExt, pathSolver,
|
||||||
model.solverParams);
|
model.solverParams);
|
||||||
|
|
||||||
this.scale = getFloat(row, "Scale");
|
this.scale = getFloat(row, "Scale");
|
||||||
this.colors = new float[][] {
|
this.colors = new float[][]{
|
||||||
{ getFloat(row, "StartR"), getFloat(row, "StartG"), getFloat(row, "StartB"),
|
{getFloat(row, "StartR"), getFloat(row, "StartG"), getFloat(row, "StartB"),
|
||||||
getFloat(row, "StartA") },
|
getFloat(row, "StartA")},
|
||||||
{ getFloat(row, "MiddleR"), getFloat(row, "MiddleG"), getFloat(row, "MiddleB"),
|
{getFloat(row, "MiddleR"), getFloat(row, "MiddleG"), getFloat(row, "MiddleB"),
|
||||||
getFloat(row, "MiddleA") },
|
getFloat(row, "MiddleA")},
|
||||||
{ getFloat(row, "EndR"), getFloat(row, "EndG"), getFloat(row, "EndB"),
|
{getFloat(row, "EndR"), getFloat(row, "EndG"), getFloat(row, "EndB"),
|
||||||
getFloat(row, "EndA") } };
|
getFloat(row, "EndA")}};
|
||||||
|
|
||||||
if ("SPL".equals(this.type)) {
|
if ("SPL".equals(this.type)) {
|
||||||
this.columns = getInt(row, "Columns");
|
this.columns = getInt(row, "Columns");
|
||||||
this.rows = getInt(row, "Rows");
|
this.rows = getInt(row, "Rows");
|
||||||
this.lifeSpan = getFloat(row, "Lifespan") + getFloat(row, "Decay");
|
this.lifeSpan = getFloat(row, "Lifespan") + getFloat(row, "Decay");
|
||||||
this.intervalTimes = new float[] { getFloat(row, "Lifespan"), getFloat(row, "Decay") };
|
this.intervalTimes = new float[]{getFloat(row, "Lifespan"), getFloat(row, "Decay")};
|
||||||
this.intervals = new float[][] {
|
this.intervals = new float[][]{
|
||||||
{ getFloat(row, "UVLifespanStart"), getFloat(row, "UVLifespanEnd"),
|
{getFloat(row, "UVLifespanStart"), getFloat(row, "UVLifespanEnd"),
|
||||||
getFloat(row, "LifespanRepeat") },
|
getFloat(row, "LifespanRepeat")},
|
||||||
{ getFloat(row, "UVDecayStart"), getFloat(row, "UVDecayEnd"),
|
{getFloat(row, "UVDecayStart"), getFloat(row, "UVDecayEnd"),
|
||||||
getFloat(row, "DecayRepeat") }, };
|
getFloat(row, "DecayRepeat")},};
|
||||||
}
|
} else {
|
||||||
else {
|
this.columns = 1;
|
||||||
this.columns = 1;
|
this.rows = 1;
|
||||||
this.rows = 1;
|
this.lifeSpan = getFloat(row, "BirthTime") + getFloat(row, "PauseTime") + getFloat(row, "Decay");
|
||||||
this.lifeSpan = getFloat(row, "BirthTime") + getFloat(row, "PauseTime") + getFloat(row, "Decay");
|
this.intervalTimes = new float[]{getFloat(row, "BirthTime"), getFloat(row, "PauseTime"),
|
||||||
this.intervalTimes = new float[] { getFloat(row, "BirthTime"), getFloat(row, "PauseTime"),
|
getFloat(row, "Decay")};
|
||||||
getFloat(row, "Decay") };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final int[] blendModes = FilterMode
|
final int[] blendModes = FilterMode
|
||||||
.emitterFilterMode(com.etheller.warsmash.parsers.mdlx.ParticleEmitter2.FilterMode
|
.emitterFilterMode(com.etheller.warsmash.parsers.mdlx.ParticleEmitter2.FilterMode
|
||||||
.fromId(getInt(row, "BlendMode")));
|
.fromId(getInt(row, "BlendMode")));
|
||||||
|
|
||||||
this.blendSrc = blendModes[0];
|
this.blendSrc = blendModes[0];
|
||||||
this.blendDst = blendModes[1];
|
this.blendDst = blendModes[1];
|
||||||
|
|
||||||
this.ok = true;
|
this.ok = true;
|
||||||
}
|
} else if ("SND".equals(this.type)) {
|
||||||
else if ("SND".equals(this.type)) {
|
// Only load sounds if audio is enabled.
|
||||||
// Only load sounds if audio is enabled.
|
// This is mostly to save on bandwidth and loading time, especially when loading
|
||||||
// This is mostly to save on bandwidth and loading time, especially when loading
|
// full maps.
|
||||||
// full maps.
|
if (viewer.audioEnabled) {
|
||||||
if (viewer.audioEnabled) {
|
final MappedData animSounds = (MappedData) tables.get(1).data;
|
||||||
final MappedData animSounds = (MappedData) tables.get(1).data;
|
|
||||||
|
|
||||||
final MappedDataRow animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
|
final MappedDataRow animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
|
||||||
|
|
||||||
if (animSoundsRow != null) {
|
if (animSoundsRow != null) {
|
||||||
this.distanceCutoff = getFloat(animSoundsRow, "DistanceCutoff");
|
this.distanceCutoff = getFloat(animSoundsRow, "DistanceCutoff");
|
||||||
this.maxDistance = getFloat(animSoundsRow, "MaxDistance");
|
this.maxDistance = getFloat(animSoundsRow, "MaxDistance");
|
||||||
this.minDistance = getFloat(animSoundsRow, "MinDistance");
|
this.minDistance = getFloat(animSoundsRow, "MinDistance");
|
||||||
this.pitch = getFloat(animSoundsRow, "Pitch");
|
this.pitch = getFloat(animSoundsRow, "Pitch");
|
||||||
this.pitchVariance = getFloat(animSoundsRow, "PitchVariance");
|
this.pitchVariance = getFloat(animSoundsRow, "PitchVariance");
|
||||||
this.volume = getFloat(animSoundsRow, "Volume");
|
this.volume = getFloat(animSoundsRow, "Volume");
|
||||||
|
|
||||||
final String[] fileNames = ((String) animSoundsRow.get("FileNames")).split(",");
|
final String[] fileNames = ((String) animSoundsRow.get("FileNames")).split(",");
|
||||||
final GenericResource[] resources = new GenericResource[fileNames.length];
|
final GenericResource[] resources = new GenericResource[fileNames.length];
|
||||||
for (int i = 0; i < fileNames.length; i++) {
|
for (int i = 0; i < fileNames.length; i++) {
|
||||||
final String path = ((String) animSoundsRow.get("DirectoryBase")) + fileNames[i];
|
final String path = ((String) animSoundsRow.get("DirectoryBase")) + fileNames[i];
|
||||||
try {
|
try {
|
||||||
final String pathString = pathSolver.solve(path, model.solverParams).finalSrc;
|
final String pathString = pathSolver.solve(path, model.solverParams).finalSrc;
|
||||||
final GenericResource genericResource = viewer.loadGeneric(pathString,
|
final GenericResource genericResource = viewer.loadGeneric(pathString,
|
||||||
FetchDataTypeName.ARRAY_BUFFER, new LoadGenericSoundCallback(pathString));
|
FetchDataTypeName.ARRAY_BUFFER, new LoadGenericSoundCallback(pathString));
|
||||||
if (genericResource == null) {
|
if (genericResource == null) {
|
||||||
System.err.println("Null sound: " + fileNames[i]);
|
System.err.println("Null sound: " + fileNames[i]);
|
||||||
}
|
}
|
||||||
resources[i] = genericResource;
|
resources[i] = genericResource;
|
||||||
}
|
} catch (final Exception exc) {
|
||||||
catch (final Exception exc) {
|
System.err.println("Failed to load sound: " + path);
|
||||||
System.err.println("Failed to load sound: " + path);
|
exc.printStackTrace();
|
||||||
exc.printStackTrace();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO JS async removed
|
// TODO JS async removed
|
||||||
for (final GenericResource resource : resources) {
|
for (final GenericResource resource : resources) {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
this.decodedBuffers.add((Sound) resource.data);
|
this.decodedBuffers.add((Sound) resource.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ok = true;
|
this.ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
System.err.println("Unknown event object type: " + this.type + this.id);
|
||||||
System.err.println("Unknown event object type: " + this.type + this.id);
|
}
|
||||||
}
|
} else {
|
||||||
}
|
System.err.println("Unknown event object ID: " + this.type + this.id);
|
||||||
else {
|
}
|
||||||
System.err.println("Unknown event object ID: " + this.type + this.id);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue(final long[] out, final MdxComplexInstance instance) {
|
public int getValue(final long[] out, final MdxComplexInstance instance) {
|
||||||
if (this.globalSequence != -1) {
|
if (this.globalSequence != -1) {
|
||||||
|
|
||||||
return this.getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
|
return this.getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
|
||||||
}
|
} else if (instance.sequence != -1) {
|
||||||
else if (instance.sequence != -1) {
|
final long[] interval = this.model.getSequences().get(instance.sequence).getInterval();
|
||||||
final long[] interval = this.model.getSequences().get(instance.sequence).getInterval();
|
|
||||||
|
|
||||||
return this.getValueAtTime(out, instance.frame, interval[0], interval[1]);
|
return this.getValueAtTime(out, instance.frame, interval[0], interval[1]);
|
||||||
}
|
} else {
|
||||||
else {
|
out[0] = this.defval[0];
|
||||||
out[0] = this.defval[0];
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getValueAtTime(final long[] out, final long frame, final long start, final long end) {
|
public int getValueAtTime(final long[] out, final long frame, final long start, final long end) {
|
||||||
if ((frame >= start) && (frame <= end)) {
|
if ((frame >= start) && (frame <= end)) {
|
||||||
for (int i = this.keyFrames.length - 1; i > -1; i--) {
|
for (int i = this.keyFrames.length - 1; i > -1; i--) {
|
||||||
if (this.keyFrames[i] < start) {
|
if (this.keyFrames[i] < start) {
|
||||||
out[0] = 0;
|
out[0] = 0;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
} else if (this.keyFrames[i] <= frame) {
|
||||||
else if (this.keyFrames[i] <= frame) {
|
out[0] = 1;
|
||||||
out[0] = 1;
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out[0] = 0;
|
out[0] = 0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean ok() {
|
public boolean ok() {
|
||||||
return this.ok;
|
return this.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getGeometryEmitterType() {
|
public int getGeometryEmitterType() {
|
||||||
return this.geometryEmitterType;
|
return this.geometryEmitterType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -32,14 +32,14 @@ public class MdxHandler extends ModelHandler {
|
|||||||
Shaders.extendedShadowMap = viewer.webGL.createShaderProgram(
|
Shaders.extendedShadowMap = viewer.webGL.createShaderProgram(
|
||||||
"#define EXTENDED_BONES\r\n" + MdxShaders.vsComplex, MdxShaders.fsComplexShadowMap);
|
"#define EXTENDED_BONES\r\n" + MdxShaders.vsComplex, MdxShaders.fsComplexShadowMap);
|
||||||
Shaders.particles = viewer.webGL.createShaderProgram(MdxShaders.vsParticles, MdxShaders.fsParticles);
|
Shaders.particles = viewer.webGL.createShaderProgram(MdxShaders.vsParticles, MdxShaders.fsParticles);
|
||||||
Shaders.simple = viewer.webGL.createShaderProgram(MdxShaders.vsSimple, MdxShaders.fsSimple);
|
//Shaders.simple = viewer.webGL.createShaderProgram(MdxShaders.vsSimple, MdxShaders.fsSimple);
|
||||||
// Shaders.hd = viewer.webGL.createShaderProgram(MdxShaders.vsHd, MdxShaders.fsHd);
|
// Shaders.hd = viewer.webGL.createShaderProgram(MdxShaders.vsHd, MdxShaders.fsHd);
|
||||||
// TODO HD reforged
|
// TODO HD reforged
|
||||||
|
|
||||||
// If a shader failed to compile, don't allow the handler to be registered, and
|
// If a shader failed to compile, don't allow the handler to be registered, and
|
||||||
// send an error instead.
|
// send an error instead.
|
||||||
return Shaders.complex.isCompiled() && Shaders.extended.isCompiled() && Shaders.particles.isCompiled()
|
return Shaders.complex.isCompiled() && Shaders.extended.isCompiled() && Shaders.particles.isCompiled()
|
||||||
&& Shaders.simple.isCompiled() /* && Shaders.hd.isCompiled() */;
|
/* && Shaders.simple.isCompiled() && Shaders.hd.isCompiled() */;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,6 +152,9 @@ public final class SdSequence<TYPE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TYPE[] fixTimelineArray(final Timeline<TYPE> timeline, final TYPE[] values) {
|
private TYPE[] fixTimelineArray(final Timeline<TYPE> timeline, final TYPE[] values) {
|
||||||
|
if(values == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (timeline.getName().equals(AnimationMap.KLAC.getWar3id())
|
if (timeline.getName().equals(AnimationMap.KLAC.getWar3id())
|
||||||
|| timeline.getName().equals(AnimationMap.KLBC.getWar3id())) {
|
|| timeline.getName().equals(AnimationMap.KLBC.getWar3id())) {
|
||||||
final float[][] flippedColorData = new float[values.length][3];
|
final float[][] flippedColorData = new float[values.length][3];
|
||||||
|
@ -2,25 +2,38 @@ package com.etheller.warsmash.viewer5.handlers.w3x;
|
|||||||
|
|
||||||
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
||||||
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||||
|
|
||||||
public class RenderDestructable extends RenderDoodad {
|
public class RenderDestructable extends RenderDoodad {
|
||||||
|
private static final War3ID TEX_FILE = War3ID.fromString("btxf");
|
||||||
|
private static final War3ID TEX_ID = War3ID.fromString("btxi");
|
||||||
|
|
||||||
private final float life;
|
private final float life;
|
||||||
|
|
||||||
public RenderDestructable(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
|
public RenderDestructable(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
|
||||||
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type,
|
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type,
|
||||||
final float maxPitch, final float maxRoll, final float life) {
|
final float maxPitch, final float maxRoll, final float life) {
|
||||||
super(map, model, row, doodad, type, maxPitch, maxRoll);
|
super(map, model, row, doodad, type, maxPitch, maxRoll);
|
||||||
this.life = life;
|
this.life = life;
|
||||||
}
|
String replaceableTextureFile = row.getFieldAsString(TEX_FILE, 0);
|
||||||
|
final int replaceableTextureId = row.getFieldAsInteger(TEX_ID, 0);
|
||||||
|
if ((replaceableTextureFile != null) && (replaceableTextureFile.length() > 1)) {
|
||||||
|
int dotIndex = replaceableTextureFile.lastIndexOf('.');
|
||||||
|
if (dotIndex != -1) {
|
||||||
|
replaceableTextureFile = replaceableTextureFile.substring(0, dotIndex);
|
||||||
|
}
|
||||||
|
replaceableTextureFile += ".blp";
|
||||||
|
instance.setReplaceableTexture(replaceableTextureId, replaceableTextureFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PrimaryTag getAnimation() {
|
public PrimaryTag getAnimation() {
|
||||||
if (this.life <= 0) {
|
if (this.life <= 0) {
|
||||||
return PrimaryTag.DEATH;
|
return PrimaryTag.DEATH;
|
||||||
}
|
}
|
||||||
return super.getAnimation();
|
return super.getAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,86 +12,72 @@ import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||||
|
|
||||||
public class RenderDoodad {
|
public class RenderDoodad {
|
||||||
private static final int SAMPLE_RADIUS = 4;
|
private static final int SAMPLE_RADIUS = 4;
|
||||||
private static final War3ID TEX_FILE = War3ID.fromString("btxf");
|
public final ModelInstance instance;
|
||||||
private static final War3ID TEX_ID = War3ID.fromString("btxi");
|
private final MutableGameObject row;
|
||||||
public final ModelInstance instance;
|
private final float maxPitch;
|
||||||
private final MutableGameObject row;
|
private final float maxRoll;
|
||||||
private final float maxPitch;
|
|
||||||
private final float maxRoll;
|
|
||||||
|
|
||||||
public RenderDoodad(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
|
public RenderDoodad(final War3MapViewer map, final MdxModel model, final MutableGameObject row,
|
||||||
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type,
|
final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad, final WorldEditorDataType type,
|
||||||
final float maxPitch, final float maxRoll) {
|
final float maxPitch, final float maxRoll) {
|
||||||
this.maxPitch = maxPitch;
|
this.maxPitch = maxPitch;
|
||||||
this.maxRoll = maxRoll;
|
this.maxRoll = maxRoll;
|
||||||
final boolean isSimple = row.readSLKTagBoolean("lightweight");
|
final boolean isSimple = row.readSLKTagBoolean("lightweight");
|
||||||
ModelInstance instance;
|
ModelInstance instance;
|
||||||
|
|
||||||
if (isSimple && false) {
|
if (isSimple && false) {
|
||||||
instance = model.addInstance(1);
|
instance = model.addInstance(1);
|
||||||
}
|
} else {
|
||||||
else {
|
instance = model.addInstance();
|
||||||
instance = model.addInstance();
|
((MdxComplexInstance) instance).setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
|
||||||
((MdxComplexInstance) instance).setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
instance.move(doodad.getLocation());
|
instance.move(doodad.getLocation());
|
||||||
// TODO: the following pitch/roll system is a heuristic, and we probably want to
|
// TODO: the following pitch/roll system is a heuristic, and we probably want to
|
||||||
// revisit it later.
|
// revisit it later.
|
||||||
// Specifically, I was pretty convinced that whichever is applied first
|
// Specifically, I was pretty convinced that whichever is applied first
|
||||||
// (pitch/roll) should be used to do a projection onto the already-tilted plane
|
// (pitch/roll) should be used to do a projection onto the already-tilted plane
|
||||||
// to find the angle used for the other of the two
|
// to find the angle used for the other of the two
|
||||||
// (instead of measuring down from an imaginary flat ground plane, as we do
|
// (instead of measuring down from an imaginary flat ground plane, as we do
|
||||||
// currently).
|
// currently).
|
||||||
final float facingRadians = doodad.getAngle();
|
final float facingRadians = doodad.getAngle();
|
||||||
float pitch, roll;
|
float pitch, roll;
|
||||||
final float x = doodad.getLocation()[0];
|
final float x = doodad.getLocation()[0];
|
||||||
final float y = doodad.getLocation()[1];
|
final float y = doodad.getLocation()[1];
|
||||||
final float pitchSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(facingRadians));
|
final float pitchSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(facingRadians));
|
||||||
final float pitchSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(facingRadians));
|
final float pitchSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(facingRadians));
|
||||||
final float pitchSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(facingRadians));
|
final float pitchSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(facingRadians));
|
||||||
final float pitchSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(facingRadians));
|
final float pitchSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(facingRadians));
|
||||||
final float pitchSampleGroundHeight1 = map.terrain.getGroundHeight(pitchSampleBackwardX, pitchSampleBackwardY);
|
final float pitchSampleGroundHeight1 = map.terrain.getGroundHeight(pitchSampleBackwardX, pitchSampleBackwardY);
|
||||||
final float pitchSampleGorundHeight2 = map.terrain.getGroundHeight(pitchSampleForwardX, pitchSampleForwardY);
|
final float pitchSampleGorundHeight2 = map.terrain.getGroundHeight(pitchSampleForwardX, pitchSampleForwardY);
|
||||||
pitch = Math.max(-maxPitch, Math.min(maxPitch,
|
pitch = Math.max(-maxPitch, Math.min(maxPitch,
|
||||||
(float) Math.atan2(pitchSampleGorundHeight2 - pitchSampleGroundHeight1, SAMPLE_RADIUS * 2)));
|
(float) Math.atan2(pitchSampleGorundHeight2 - pitchSampleGroundHeight1, SAMPLE_RADIUS * 2)));
|
||||||
final double leftOfFacingAngle = facingRadians + (Math.PI / 2);
|
final double leftOfFacingAngle = facingRadians + (Math.PI / 2);
|
||||||
final float rollSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle));
|
final float rollSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle));
|
||||||
final float rollSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle));
|
final float rollSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle));
|
||||||
final float rollSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle));
|
final float rollSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle));
|
||||||
final float rollSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle));
|
final float rollSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle));
|
||||||
final float rollSampleGroundHeight1 = map.terrain.getGroundHeight(rollSampleBackwardX, rollSampleBackwardY);
|
final float rollSampleGroundHeight1 = map.terrain.getGroundHeight(rollSampleBackwardX, rollSampleBackwardY);
|
||||||
final float rollSampleGroundHeight2 = map.terrain.getGroundHeight(rollSampleForwardX, rollSampleForwardY);
|
final float rollSampleGroundHeight2 = map.terrain.getGroundHeight(rollSampleForwardX, rollSampleForwardY);
|
||||||
roll = Math.max(-maxRoll, Math.min(maxRoll,
|
roll = Math.max(-maxRoll, Math.min(maxRoll,
|
||||||
(float) Math.atan2(rollSampleGroundHeight2 - rollSampleGroundHeight1, SAMPLE_RADIUS * 2)));
|
(float) Math.atan2(rollSampleGroundHeight2 - rollSampleGroundHeight1, SAMPLE_RADIUS * 2)));
|
||||||
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, facingRadians));
|
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, facingRadians));
|
||||||
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Y, -pitch));
|
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Y, -pitch));
|
||||||
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_X, roll));
|
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_X, roll));
|
||||||
// instance.rotate(new Quaternion().setEulerAnglesRad(facingRadians, 0, 0));
|
// instance.rotate(new Quaternion().setEulerAnglesRad(facingRadians, 0, 0));
|
||||||
instance.scale(doodad.getScale());
|
instance.scale(doodad.getScale());
|
||||||
if (type == WorldEditorDataType.DOODADS) {
|
if (type == WorldEditorDataType.DOODADS) {
|
||||||
final float defScale = row.readSLKTagFloat("defScale");
|
final float defScale = row.readSLKTagFloat("defScale");
|
||||||
instance.uniformScale(defScale);
|
instance.uniformScale(defScale);
|
||||||
}
|
}
|
||||||
if (type == WorldEditorDataType.DESTRUCTIBLES) {
|
instance.setScene(map.worldScene);
|
||||||
// TODO destructables need to be their own type, game simulation, etc
|
|
||||||
String replaceableTextureFile = row.getFieldAsString(TEX_FILE, 0);
|
|
||||||
final int replaceableTextureId = row.getFieldAsInteger(TEX_ID, 0);
|
|
||||||
if ((replaceableTextureFile != null) && (replaceableTextureFile.length() > 1)) {
|
|
||||||
if (!replaceableTextureFile.toLowerCase().endsWith(".blp")) {
|
|
||||||
replaceableTextureFile += ".blp";
|
|
||||||
}
|
|
||||||
instance.setReplaceableTexture(replaceableTextureId, replaceableTextureFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instance.setScene(map.worldScene);
|
|
||||||
|
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.row = row;
|
this.row = row;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimaryTag getAnimation() {
|
public PrimaryTag getAnimation() {
|
||||||
return PrimaryTag.STAND;
|
return PrimaryTag.STAND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.math.Rectangle;
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.math.Vector3;
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.badlogic.gdx.math.collision.BoundingBox;
|
||||||
import com.badlogic.gdx.math.collision.Ray;
|
import com.badlogic.gdx.math.collision.Ray;
|
||||||
import com.etheller.warsmash.common.FetchDataTypeName;
|
import com.etheller.warsmash.common.FetchDataTypeName;
|
||||||
import com.etheller.warsmash.common.LoadGenericCallback;
|
import com.etheller.warsmash.common.LoadGenericCallback;
|
||||||
@ -48,6 +49,8 @@ import com.etheller.warsmash.units.manager.MutableObjectData;
|
|||||||
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
||||||
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
||||||
import com.etheller.warsmash.util.MappedData;
|
import com.etheller.warsmash.util.MappedData;
|
||||||
|
import com.etheller.warsmash.util.Quadtree;
|
||||||
|
import com.etheller.warsmash.util.QuadtreeIntersector;
|
||||||
import com.etheller.warsmash.util.RenderMathUtils;
|
import com.etheller.warsmash.util.RenderMathUtils;
|
||||||
import com.etheller.warsmash.util.War3ID;
|
import com.etheller.warsmash.util.War3ID;
|
||||||
import com.etheller.warsmash.util.WarsmashConstants;
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
@ -85,12 +88,14 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitFilterFunction
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackInstant;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile;
|
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.combat.projectile.CAttackProjectile;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CWidgetAbilityTargetCheckReceiver;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CWidgetAbilityTargetCheckReceiver;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.PointAbilityTargetCheckReceiver;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
||||||
|
|
||||||
import mpq.MPQArchive;
|
import mpq.MPQArchive;
|
||||||
@ -117,10 +122,11 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
private static final War3ID sloc = War3ID.fromString("sloc");
|
private static final War3ID sloc = War3ID.fromString("sloc");
|
||||||
private static final LoadGenericCallback stringDataCallback = new StringDataCallbackImplementation();
|
private static final LoadGenericCallback stringDataCallback = new StringDataCallbackImplementation();
|
||||||
private static final float[] rayHeap = new float[6];
|
private static final float[] rayHeap = new float[6];
|
||||||
private static final Ray gdxRayHeap = new Ray();
|
public static final Ray gdxRayHeap = new Ray();
|
||||||
private static final Vector2 mousePosHeap = new Vector2();
|
private static final Vector2 mousePosHeap = new Vector2();
|
||||||
private static final Vector3 normalHeap = new Vector3();
|
private static final Vector3 normalHeap = new Vector3();
|
||||||
private static final Vector3 intersectionHeap = new Vector3();
|
public static final Vector3 intersectionHeap = new Vector3();
|
||||||
|
private static final Rectangle rectangleHeap = new Rectangle();
|
||||||
public static final StreamDataCallbackImplementation streamDataCallback = new StreamDataCallbackImplementation();
|
public static final StreamDataCallbackImplementation streamDataCallback = new StreamDataCallbackImplementation();
|
||||||
|
|
||||||
public PathSolver wc3PathSolver = PathSolver.DEFAULT;
|
public PathSolver wc3PathSolver = PathSolver.DEFAULT;
|
||||||
@ -185,6 +191,11 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
private GameUI gameUI;
|
private GameUI gameUI;
|
||||||
private Vector3 lightDirection;
|
private Vector3 lightDirection;
|
||||||
|
|
||||||
|
private Quadtree<MdxComplexInstance> walkableObjectsTree;
|
||||||
|
private final QuadtreeIntersectorFindsWalkableRenderHeight walkablesIntersector = new QuadtreeIntersectorFindsWalkableRenderHeight();
|
||||||
|
private final QuadtreeIntersectorFindsHitPoint walkablesIntersectionFinder = new QuadtreeIntersectorFindsHitPoint();
|
||||||
|
private final QuadtreeIntersectorFindsHighestWalkable intersectorFindsHighestWalkable = new QuadtreeIntersectorFindsHighestWalkable();
|
||||||
|
|
||||||
public War3MapViewer(final DataSource dataSource, final CanvasProvider canvas) {
|
public War3MapViewer(final DataSource dataSource, final CanvasProvider canvas) {
|
||||||
super(dataSource, canvas);
|
super(dataSource, canvas);
|
||||||
this.gameDataSource = dataSource;
|
this.gameDataSource = dataSource;
|
||||||
@ -501,10 +512,9 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
War3MapViewer.this.units.remove(renderUnit);
|
War3MapViewer.this.units.remove(renderUnit);
|
||||||
War3MapViewer.this.worldScene.removeInstance(renderUnit.instance);
|
War3MapViewer.this.worldScene.removeInstance(renderUnit.instance);
|
||||||
}
|
}
|
||||||
}, this.terrain.pathingGrid,
|
}, this.terrain.pathingGrid, this.terrain.getEntireMap(), this.seededRandom, w3iFile.getPlayers());
|
||||||
new Rectangle(centerOffset[0], centerOffset[1], (mapSize[0] * 128f) - 128, (mapSize[1] * 128f) - 128),
|
|
||||||
this.seededRandom, w3iFile.getPlayers());
|
|
||||||
|
|
||||||
|
this.walkableObjectsTree = new Quadtree<>(this.terrain.getEntireMap());
|
||||||
if (this.doodadsAndDestructiblesLoaded) {
|
if (this.doodadsAndDestructiblesLoaded) {
|
||||||
this.loadDoodadsAndDestructibles(this.allObjectData);
|
this.loadDoodadsAndDestructibles(this.allObjectData);
|
||||||
}
|
}
|
||||||
@ -632,8 +642,20 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == WorldEditorDataType.DESTRUCTIBLES) {
|
if (type == WorldEditorDataType.DESTRUCTIBLES) {
|
||||||
this.doodads.add(new RenderDestructable(this, model, row, doodad, type, maxPitch, maxRoll,
|
final RenderDestructable renderDestructable = new RenderDestructable(this, model, row, doodad, type,
|
||||||
doodad.getLife()));
|
maxPitch, maxRoll, doodad.getLife());
|
||||||
|
if (row.readSLKTagBoolean("walkable")) {
|
||||||
|
final float x = doodad.getLocation()[0];
|
||||||
|
final float y = doodad.getLocation()[1];
|
||||||
|
final BoundingBox boundingBox = model.bounds.getBoundingBox();
|
||||||
|
final float minX = boundingBox.min.x + x;
|
||||||
|
final float minY = boundingBox.min.y + y;
|
||||||
|
final Rectangle renderDestructableBounds = new Rectangle(minX, minY, boundingBox.getWidth(),
|
||||||
|
boundingBox.getHeight());
|
||||||
|
this.walkableObjectsTree.add((MdxComplexInstance) renderDestructable.instance,
|
||||||
|
renderDestructableBounds);
|
||||||
|
}
|
||||||
|
this.doodads.add(renderDestructable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.doodads.add(new RenderDoodad(this, model, row, doodad, type, maxPitch, maxRoll));
|
this.doodads.add(new RenderDoodad(this, model, row, doodad, type, maxPitch, maxRoll));
|
||||||
@ -884,7 +906,7 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.items.add(new RenderItem(this, model, row, unit, soundset, portraitModel)); // TODO store
|
this.items.add(new RenderItem(this, model, row, unit, soundset, portraitModel)); // TODO store
|
||||||
// somewhere
|
// somewhere
|
||||||
if (unitShadowSplat != null) {
|
if (unitShadowSplat != null) {
|
||||||
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
|
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
|
||||||
@Override
|
@Override
|
||||||
@ -1080,6 +1102,15 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
gdxRayHeap.direction.nor();// needed for libgdx
|
gdxRayHeap.direction.nor();// needed for libgdx
|
||||||
RenderMathUtils.intersectRayTriangles(gdxRayHeap, this.terrain.softwareGroundMesh.vertices,
|
RenderMathUtils.intersectRayTriangles(gdxRayHeap, this.terrain.softwareGroundMesh.vertices,
|
||||||
this.terrain.softwareGroundMesh.indices, 3, out);
|
this.terrain.softwareGroundMesh.indices, 3, out);
|
||||||
|
rectangleHeap.set(Math.min(out.x, gdxRayHeap.origin.x), Math.min(out.y, gdxRayHeap.origin.y),
|
||||||
|
Math.abs(out.x - gdxRayHeap.origin.x), Math.abs(out.y - gdxRayHeap.origin.y));
|
||||||
|
this.walkableObjectsTree.intersect(rectangleHeap, this.walkablesIntersectionFinder.reset(gdxRayHeap));
|
||||||
|
if (this.walkablesIntersectionFinder.found) {
|
||||||
|
out.set(this.walkablesIntersectionFinder.intersection);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.z = Math.max(getWalkableRenderHeight(out.x, out.y), this.terrain.getGroundHeight(out.x, out.y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showConfirmation(final Vector3 position, final float red, final float green, final float blue) {
|
public void showConfirmation(final Vector3 position, final float red, final float green, final float blue) {
|
||||||
@ -1105,9 +1136,11 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
final MdxComplexInstance instance = unit.instance;
|
final MdxComplexInstance instance = unit.instance;
|
||||||
if (instance.isVisible(this.worldScene.camera)
|
if (instance.isVisible(this.worldScene.camera)
|
||||||
&& instance.intersectRayWithCollision(gdxRayHeap, intersectionHeap,
|
&& instance.intersectRayWithCollision(gdxRayHeap, intersectionHeap,
|
||||||
unit.getSimulationUnit().getUnitType().isBuilding())
|
unit.getSimulationUnit().getUnitType().isBuilding(), false)
|
||||||
&& !unit.getSimulationUnit().isDead()) {
|
&& !unit.getSimulationUnit().isDead()) {
|
||||||
entity = unit;
|
if ((entity == null) || (entity.instance.depth > instance.depth)) {
|
||||||
|
entity = unit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<RenderUnit> sel;
|
List<RenderUnit> sel;
|
||||||
@ -1148,7 +1181,7 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
for (final RenderUnit unit : this.units) {
|
for (final RenderUnit unit : this.units) {
|
||||||
final MdxComplexInstance instance = unit.instance;
|
final MdxComplexInstance instance = unit.instance;
|
||||||
if (instance.isVisible(this.worldScene.camera) && instance.intersectRayWithCollision(gdxRayHeap,
|
if (instance.isVisible(this.worldScene.camera) && instance.intersectRayWithCollision(gdxRayHeap,
|
||||||
intersectionHeap, unit.getSimulationUnit().getUnitType().isBuilding())) {
|
intersectionHeap, unit.getSimulationUnit().getUnitType().isBuilding(), false)) {
|
||||||
if (filter.call(unit.getSimulationUnit())) {
|
if (filter.call(unit.getSimulationUnit())) {
|
||||||
if ((entity == null) || (entity.instance.depth > instance.depth)) {
|
if ((entity == null) || (entity.instance.depth > instance.depth)) {
|
||||||
entity = unit;
|
entity = unit;
|
||||||
@ -1242,6 +1275,41 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
return (numElements < 0) ? 1 : (numElements >= MAXIMUM_ACCEPTED) ? MAXIMUM_ACCEPTED : numElements + 1;
|
return (numElements < 0) ? 1 : (numElements >= MAXIMUM_ACCEPTED) ? MAXIMUM_ACCEPTED : numElements + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean orderSmart(final float x, final float y) {
|
||||||
|
mousePosHeap.x = x;
|
||||||
|
mousePosHeap.y = y;
|
||||||
|
boolean ordered = false;
|
||||||
|
for (final RenderUnit unit : this.selected) {
|
||||||
|
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
|
||||||
|
if (ability instanceof CAbilityMove) {
|
||||||
|
ability.checkCanUse(this.simulation, unit.getSimulationUnit(), OrderIds.smart,
|
||||||
|
BooleanAbilityActivationReceiver.INSTANCE);
|
||||||
|
if (BooleanAbilityActivationReceiver.INSTANCE.isOk()) {
|
||||||
|
ability.checkCanTarget(this.simulation, unit.getSimulationUnit(), OrderIds.smart, mousePosHeap,
|
||||||
|
PointAbilityTargetCheckReceiver.INSTANCE);
|
||||||
|
final Vector2 target = PointAbilityTargetCheckReceiver.INSTANCE.getTarget();
|
||||||
|
if (target != null) {
|
||||||
|
ability.onOrder(this.simulation, unit.getSimulationUnit(), OrderIds.smart, mousePosHeap,
|
||||||
|
false);
|
||||||
|
ordered = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("Target not valid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("Ability not ok to use.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("Ability not move.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return ordered;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean orderSmart(final RenderUnit target) {
|
public boolean orderSmart(final RenderUnit target) {
|
||||||
boolean ordered = false;
|
boolean ordered = false;
|
||||||
for (final RenderUnit unit : this.selected) {
|
for (final RenderUnit unit : this.selected) {
|
||||||
@ -1348,4 +1416,82 @@ public class War3MapViewer extends ModelViewer {
|
|||||||
public AbilityDataUI getAbilityDataUI() {
|
public AbilityDataUI getAbilityDataUI() {
|
||||||
return this.abilityDataUI;
|
return this.abilityDataUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getWalkableRenderHeight(final float x, final float y) {
|
||||||
|
this.walkableObjectsTree.intersect(x, y, this.walkablesIntersector.reset(x, y));
|
||||||
|
return this.walkablesIntersector.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MdxComplexInstance getHighestWalkableUnder(final float x, final float y) {
|
||||||
|
this.walkableObjectsTree.intersect(x, y, this.intersectorFindsHighestWalkable.reset(x, y));
|
||||||
|
return this.intersectorFindsHighestWalkable.highestInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class QuadtreeIntersectorFindsWalkableRenderHeight
|
||||||
|
implements QuadtreeIntersector<MdxComplexInstance> {
|
||||||
|
private float z;
|
||||||
|
private final Ray ray = new Ray();
|
||||||
|
private final Vector3 intersection = new Vector3();
|
||||||
|
|
||||||
|
private QuadtreeIntersectorFindsWalkableRenderHeight reset(final float x, final float y) {
|
||||||
|
this.z = -Float.MAX_VALUE;
|
||||||
|
this.ray.set(x, y, 4096, 0, 0, -8192);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onIntersect(final MdxComplexInstance intersectingObject) {
|
||||||
|
if (intersectingObject.intersectRayWithCollision(this.ray, this.intersection, true, true)) {
|
||||||
|
this.z = Math.max(this.z, this.intersection.z);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class QuadtreeIntersectorFindsHighestWalkable
|
||||||
|
implements QuadtreeIntersector<MdxComplexInstance> {
|
||||||
|
private float z;
|
||||||
|
private final Ray ray = new Ray();
|
||||||
|
private final Vector3 intersection = new Vector3();
|
||||||
|
private MdxComplexInstance highestInstance;
|
||||||
|
|
||||||
|
private QuadtreeIntersectorFindsHighestWalkable reset(final float x, final float y) {
|
||||||
|
this.z = -Float.MAX_VALUE;
|
||||||
|
this.ray.set(x, y, 4096, 0, 0, -8192);
|
||||||
|
this.highestInstance = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onIntersect(final MdxComplexInstance intersectingObject) {
|
||||||
|
if (intersectingObject.intersectRayWithCollision(this.ray, this.intersection, true, true)) {
|
||||||
|
if (this.intersection.z > this.z) {
|
||||||
|
this.z = this.intersection.z;
|
||||||
|
this.highestInstance = intersectingObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class QuadtreeIntersectorFindsHitPoint implements QuadtreeIntersector<MdxComplexInstance> {
|
||||||
|
private Ray ray;
|
||||||
|
private final Vector3 intersection = new Vector3();
|
||||||
|
private boolean found;
|
||||||
|
|
||||||
|
private QuadtreeIntersectorFindsHitPoint reset(final Ray ray) {
|
||||||
|
this.ray = ray;
|
||||||
|
this.found = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onIntersect(final MdxComplexInstance intersectingObject) {
|
||||||
|
if (intersectingObject.intersectRayWithCollision(this.ray, this.intersection, true, true)) {
|
||||||
|
this.found = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,6 +411,7 @@ public class Terrain {
|
|||||||
this.shaderMapBoundsRectangle = new Rectangle(this.shaderMapBounds[0], this.shaderMapBounds[1],
|
this.shaderMapBoundsRectangle = new Rectangle(this.shaderMapBounds[0], this.shaderMapBounds[1],
|
||||||
this.shaderMapBounds[2] - this.shaderMapBounds[0], this.shaderMapBounds[3] - this.shaderMapBounds[1]);
|
this.shaderMapBounds[2] - this.shaderMapBounds[0], this.shaderMapBounds[3] - this.shaderMapBounds[1]);
|
||||||
this.mapSize = w3eFile.getMapSize();
|
this.mapSize = w3eFile.getMapSize();
|
||||||
|
this.entireMapRectangle = new Rectangle(centerOffset[0], centerOffset[1], (mapSize[0] * 128f) - 128, (mapSize[1] * 128f) - 128);
|
||||||
this.softwareGroundMesh = new SoftwareGroundMesh(this.groundHeights, this.groundCornerHeights,
|
this.softwareGroundMesh = new SoftwareGroundMesh(this.groundHeights, this.groundCornerHeights,
|
||||||
this.centerOffset, width, height);
|
this.centerOffset, width, height);
|
||||||
|
|
||||||
@ -1019,15 +1020,14 @@ public class Terrain {
|
|||||||
gl.glUniform1i(6, (int) this.waterIndex);
|
gl.glUniform1i(6, (int) this.waterIndex);
|
||||||
gl.glUniform1f(this.waterShader.getUniformLocation("centerOffsetX"), this.centerOffset[0]);
|
gl.glUniform1f(this.waterShader.getUniformLocation("centerOffsetX"), this.centerOffset[0]);
|
||||||
gl.glUniform1f(this.waterShader.getUniformLocation("centerOffsetY"), this.centerOffset[1]);
|
gl.glUniform1f(this.waterShader.getUniformLocation("centerOffsetY"), this.centerOffset[1]);
|
||||||
gl.glUniform4fv(9, 1, this.shaderMapBounds, 0);
|
gl.glUniform4fv(11, 1, this.shaderMapBounds, 0);
|
||||||
|
|
||||||
final W3xSceneLightManager lightManager = (W3xSceneLightManager) this.viewer.worldScene.getLightManager();
|
final W3xSceneLightManager lightManager = (W3xSceneLightManager) this.viewer.worldScene.getLightManager();
|
||||||
final DataTexture unitLightsTexture = lightManager.getTerrainLightsTexture();
|
final DataTexture terrainLightsTexture = lightManager.getTerrainLightsTexture();
|
||||||
|
|
||||||
unitLightsTexture.bind(21);
|
terrainLightsTexture.bind(3);
|
||||||
gl.glUniform1i(this.waterShader.getUniformLocation("lightTexture"), 21);
|
gl.glUniform1f(9, lightManager.getTerrainLightCount());
|
||||||
gl.glUniform1f(this.waterShader.getUniformLocation("lightCount"), lightManager.getTerrainLightCount());
|
gl.glUniform1f(10, terrainLightsTexture.getHeight());
|
||||||
gl.glUniform1f(this.waterShader.getUniformLocation("lightCountHeight"), unitLightsTexture.getHeight());
|
|
||||||
|
|
||||||
gl.glActiveTexture(GL30.GL_TEXTURE0);
|
gl.glActiveTexture(GL30.GL_TEXTURE0);
|
||||||
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.waterHeight);
|
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.waterHeight);
|
||||||
@ -1035,7 +1035,7 @@ public class Terrain {
|
|||||||
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.groundCornerHeight);
|
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.groundCornerHeight);
|
||||||
gl.glActiveTexture(GL30.GL_TEXTURE2);
|
gl.glActiveTexture(GL30.GL_TEXTURE2);
|
||||||
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.waterExists);
|
gl.glBindTexture(GL30.GL_TEXTURE_2D, this.waterExists);
|
||||||
gl.glActiveTexture(GL30.GL_TEXTURE3);
|
gl.glActiveTexture(GL30.GL_TEXTURE4);
|
||||||
gl.glBindTexture(GL30.GL_TEXTURE_2D_ARRAY, this.waterTextureArray);
|
gl.glBindTexture(GL30.GL_TEXTURE_2D_ARRAY, this.waterTextureArray);
|
||||||
|
|
||||||
gl.glBindBuffer(GL30.GL_ARRAY_BUFFER, Shapes.INSTANCE.vertexBuffer);
|
gl.glBindBuffer(GL30.GL_ARRAY_BUFFER, Shapes.INSTANCE.vertexBuffer);
|
||||||
@ -1239,6 +1239,7 @@ public class Terrain {
|
|||||||
private final WaveBuilder waveBuilder;
|
private final WaveBuilder waveBuilder;
|
||||||
public PathingGrid pathingGrid;
|
public PathingGrid pathingGrid;
|
||||||
private final Rectangle shaderMapBoundsRectangle;
|
private final Rectangle shaderMapBoundsRectangle;
|
||||||
|
private final Rectangle entireMapRectangle;
|
||||||
|
|
||||||
private static final class UnloadedTexture {
|
private static final class UnloadedTexture {
|
||||||
private final int width;
|
private final int width;
|
||||||
@ -1399,4 +1400,8 @@ public class Terrain {
|
|||||||
public Rectangle getPlayableMapArea() {
|
public Rectangle getPlayableMapArea() {
|
||||||
return this.shaderMapBoundsRectangle;
|
return this.shaderMapBoundsRectangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rectangle getEntireMap() {
|
||||||
|
return entireMapRectangle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,9 +428,9 @@ public class TerrainShaders {
|
|||||||
"layout (location = 3) uniform vec4 deep_color_min;\r\n" + //
|
"layout (location = 3) uniform vec4 deep_color_min;\r\n" + //
|
||||||
"layout (location = 4) uniform vec4 deep_color_max;\r\n" + //
|
"layout (location = 4) uniform vec4 deep_color_max;\r\n" + //
|
||||||
"layout (location = 5) uniform float water_offset;\r\n" + //
|
"layout (location = 5) uniform float water_offset;\r\n" + //
|
||||||
"layout (location = 10) uniform sampler2D lightTexture;\r\n" + //
|
"layout (binding = 3) uniform sampler2D lightTexture;\r\n" + //
|
||||||
"layout (location = 11) uniform float lightCount;\r\n" + //
|
"layout (location = 9) uniform float lightCount;\r\n" + //
|
||||||
"layout (location = 12) uniform float lightTextureHeight;\r\n" + //
|
"layout (location = 10) uniform float lightTextureHeight;\r\n" + //
|
||||||
"\r\n" + //
|
"\r\n" + //
|
||||||
"out vec2 UV;\r\n" + //
|
"out vec2 UV;\r\n" + //
|
||||||
"out vec4 Color;\r\n" + //
|
"out vec4 Color;\r\n" + //
|
||||||
@ -477,12 +477,12 @@ public class TerrainShaders {
|
|||||||
|
|
||||||
public static final String frag = "#version 450 core\r\n" + //
|
public static final String frag = "#version 450 core\r\n" + //
|
||||||
"\r\n" + //
|
"\r\n" + //
|
||||||
"layout (binding = 3) uniform sampler2DArray water_textures;\r\n" + //
|
"layout (binding = 4) uniform sampler2DArray water_textures;\r\n" + //
|
||||||
"layout (binding = 2) uniform sampler2D water_exists_texture;\r\n" + //
|
"layout (binding = 2) uniform sampler2D water_exists_texture;\r\n" + //
|
||||||
"\r\n" + //
|
"\r\n" + //
|
||||||
"\r\n" + //
|
"\r\n" + //
|
||||||
"layout (location = 6) uniform int current_texture;\r\n" + //
|
"layout (location = 6) uniform int current_texture;\r\n" + //
|
||||||
"layout (location = 9) uniform vec4 mapBounds;\r\n" + //
|
"layout (location = 11) uniform vec4 mapBounds;\r\n" + //
|
||||||
"\r\n" + //
|
"\r\n" + //
|
||||||
"in vec2 UV;\r\n" + //
|
"in vec2 UV;\r\n" + //
|
||||||
"in vec4 Color;\r\n" + //
|
"in vec4 Color;\r\n" + //
|
||||||
|
@ -24,6 +24,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.Moveme
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
|
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandCardPopulatingAbilityVisitor;
|
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandCardPopulatingAbilityVisitor;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitAnimationListener;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitAnimationListener;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
||||||
@ -131,10 +132,11 @@ public class RenderUnit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void populateCommandCard(final CommandButtonListener commandButtonListener,
|
public void populateCommandCard(final CSimulation game, final CommandButtonListener commandButtonListener,
|
||||||
final AbilityDataUI abilityDataUI) {
|
final AbilityDataUI abilityDataUI) {
|
||||||
for (final CAbility ability : this.simulationUnit.getAbilities()) {
|
for (final CAbility ability : this.simulationUnit.getAbilities()) {
|
||||||
ability.visit(CommandCardPopulatingAbilityVisitor.INSTANCE.reset(commandButtonListener, abilityDataUI));
|
ability.visit(CommandCardPopulatingAbilityVisitor.INSTANCE.reset(game, this.simulationUnit,
|
||||||
|
commandButtonListener, abilityDataUI));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,15 +168,43 @@ public class RenderUnit {
|
|||||||
final float groundHeight;
|
final float groundHeight;
|
||||||
final MovementType movementType = this.simulationUnit.getUnitType().getMovementType();
|
final MovementType movementType = this.simulationUnit.getUnitType().getMovementType();
|
||||||
final short terrainPathing = map.terrain.pathingGrid.getPathing(x, y);
|
final short terrainPathing = map.terrain.pathingGrid.getPathing(x, y);
|
||||||
final boolean swimming = (movementType == MovementType.AMPHIBIOUS)
|
boolean swimming = (movementType == MovementType.AMPHIBIOUS)
|
||||||
&& PathingGrid.isPathingFlag(terrainPathing, PathingGrid.PathingType.SWIMMABLE)
|
&& PathingGrid.isPathingFlag(terrainPathing, PathingGrid.PathingType.SWIMMABLE)
|
||||||
&& !PathingGrid.isPathingFlag(terrainPathing, PathingGrid.PathingType.WALKABLE);
|
&& !PathingGrid.isPathingFlag(terrainPathing, PathingGrid.PathingType.WALKABLE);
|
||||||
if ((swimming) || (movementType == MovementType.FLOAT) || (movementType == MovementType.FLY)
|
final float groundHeightTerrain = map.terrain.getGroundHeight(x, y);
|
||||||
|| (movementType == MovementType.HOVER)) {
|
float groundHeightTerrainAndWater;
|
||||||
groundHeight = Math.max(map.terrain.getGroundHeight(x, y), map.terrain.getWaterHeight(x, y));
|
MdxComplexInstance currentWalkableUnder;
|
||||||
|
final boolean standingOnWater = (swimming) || (movementType == MovementType.FLOAT)
|
||||||
|
|| (movementType == MovementType.FLY) || (movementType == MovementType.HOVER);
|
||||||
|
if (standingOnWater) {
|
||||||
|
groundHeightTerrainAndWater = Math.max(groundHeightTerrain, map.terrain.getWaterHeight(x, y));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
groundHeight = map.terrain.getGroundHeight(x, y);
|
// land units will have their feet pass under the surface of the water
|
||||||
|
groundHeightTerrainAndWater = groundHeightTerrain;
|
||||||
|
}
|
||||||
|
if (movementType == MovementType.FLOAT) {
|
||||||
|
// boats cant go on bridges
|
||||||
|
groundHeight = groundHeightTerrainAndWater;
|
||||||
|
currentWalkableUnder = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentWalkableUnder = map.getHighestWalkableUnder(x, y);
|
||||||
|
if (currentWalkableUnder != null) {
|
||||||
|
System.out.println("WALKABLE UNDER");
|
||||||
|
}
|
||||||
|
War3MapViewer.gdxRayHeap.set(x, y, 4096, 0, 0, -8192);
|
||||||
|
if ((currentWalkableUnder != null)
|
||||||
|
&& currentWalkableUnder.intersectRayWithCollision(War3MapViewer.gdxRayHeap,
|
||||||
|
War3MapViewer.intersectionHeap, true, true)
|
||||||
|
&& (War3MapViewer.intersectionHeap.z > groundHeightTerrainAndWater)) {
|
||||||
|
groundHeight = War3MapViewer.intersectionHeap.z;
|
||||||
|
swimming = false; // Naga Royal Guard should slither across a bridge, not swim in rock
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
groundHeight = groundHeightTerrainAndWater;
|
||||||
|
currentWalkableUnder = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (swimming && !this.swimming) {
|
if (swimming && !this.swimming) {
|
||||||
this.unitAnimationListenerImpl.addSecondaryTag(AnimationTokens.SecondaryTag.SWIM);
|
this.unitAnimationListenerImpl.addSecondaryTag(AnimationTokens.SecondaryTag.SWIM);
|
||||||
@ -263,17 +293,49 @@ public class RenderUnit {
|
|||||||
final float pitchSampleForwardY = y + (sampleRadius * (float) Math.sin(facingRadians));
|
final float pitchSampleForwardY = y + (sampleRadius * (float) Math.sin(facingRadians));
|
||||||
final float pitchSampleBackwardX = x - (sampleRadius * (float) Math.cos(facingRadians));
|
final float pitchSampleBackwardX = x - (sampleRadius * (float) Math.cos(facingRadians));
|
||||||
final float pitchSampleBackwardY = y - (sampleRadius * (float) Math.sin(facingRadians));
|
final float pitchSampleBackwardY = y - (sampleRadius * (float) Math.sin(facingRadians));
|
||||||
final float pitchSampleGroundHeight1 = map.terrain.getGroundHeight(pitchSampleBackwardX, pitchSampleBackwardY);
|
|
||||||
final float pitchSampleGorundHeight2 = map.terrain.getGroundHeight(pitchSampleForwardX, pitchSampleForwardY);
|
|
||||||
pitch = Math.max(-maxPitch, Math.min(maxPitch,
|
|
||||||
(float) Math.atan2(pitchSampleGorundHeight2 - pitchSampleGroundHeight1, sampleRadius * 2)));
|
|
||||||
final double leftOfFacingAngle = facingRadians + (Math.PI / 2);
|
final double leftOfFacingAngle = facingRadians + (Math.PI / 2);
|
||||||
final float rollSampleForwardX = x + (sampleRadius * (float) Math.cos(leftOfFacingAngle));
|
final float rollSampleForwardX = x + (sampleRadius * (float) Math.cos(leftOfFacingAngle));
|
||||||
final float rollSampleForwardY = y + (sampleRadius * (float) Math.sin(leftOfFacingAngle));
|
final float rollSampleForwardY = y + (sampleRadius * (float) Math.sin(leftOfFacingAngle));
|
||||||
final float rollSampleBackwardX = x - (sampleRadius * (float) Math.cos(leftOfFacingAngle));
|
final float rollSampleBackwardX = x - (sampleRadius * (float) Math.cos(leftOfFacingAngle));
|
||||||
final float rollSampleBackwardY = y - (sampleRadius * (float) Math.sin(leftOfFacingAngle));
|
final float rollSampleBackwardY = y - (sampleRadius * (float) Math.sin(leftOfFacingAngle));
|
||||||
final float rollSampleGroundHeight1 = map.terrain.getGroundHeight(rollSampleBackwardX, rollSampleBackwardY);
|
final float pitchSampleGroundHeight1;
|
||||||
final float rollSampleGroundHeight2 = map.terrain.getGroundHeight(rollSampleForwardX, rollSampleForwardY);
|
final float pitchSampleGroundHeight2;
|
||||||
|
final float rollSampleGroundHeight1;
|
||||||
|
final float rollSampleGroundHeight2;
|
||||||
|
if (currentWalkableUnder != null) {
|
||||||
|
pitchSampleGroundHeight1 = getGroundHeightSample(groundHeight, currentWalkableUnder, pitchSampleBackwardX,
|
||||||
|
pitchSampleBackwardY);
|
||||||
|
pitchSampleGroundHeight2 = getGroundHeightSample(groundHeight, currentWalkableUnder, pitchSampleForwardX,
|
||||||
|
pitchSampleForwardY);
|
||||||
|
rollSampleGroundHeight1 = getGroundHeightSample(groundHeight, currentWalkableUnder, rollSampleBackwardX,
|
||||||
|
rollSampleBackwardY);
|
||||||
|
rollSampleGroundHeight2 = getGroundHeightSample(groundHeight, currentWalkableUnder, rollSampleForwardX,
|
||||||
|
rollSampleForwardY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final float pitchGroundHeight1 = map.terrain.getGroundHeight(pitchSampleBackwardX, pitchSampleBackwardY);
|
||||||
|
final float pitchGroundHeight2 = map.terrain.getGroundHeight(pitchSampleForwardX, pitchSampleForwardY);
|
||||||
|
final float rollGroundHeight1 = map.terrain.getGroundHeight(rollSampleBackwardX, rollSampleBackwardY);
|
||||||
|
final float rollGroundHeight2 = map.terrain.getGroundHeight(rollSampleForwardX, rollSampleForwardY);
|
||||||
|
if (standingOnWater) {
|
||||||
|
pitchSampleGroundHeight1 = Math.max(pitchGroundHeight1,
|
||||||
|
map.terrain.getWaterHeight(pitchSampleBackwardX, pitchSampleBackwardY));
|
||||||
|
pitchSampleGroundHeight2 = Math.max(pitchGroundHeight2,
|
||||||
|
map.terrain.getWaterHeight(pitchSampleForwardX, pitchSampleForwardY));
|
||||||
|
rollSampleGroundHeight1 = Math.max(rollGroundHeight1,
|
||||||
|
map.terrain.getWaterHeight(rollSampleBackwardX, rollSampleBackwardY));
|
||||||
|
rollSampleGroundHeight2 = Math.max(rollGroundHeight2,
|
||||||
|
map.terrain.getWaterHeight(rollSampleForwardX, rollSampleForwardY));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pitchSampleGroundHeight1 = pitchGroundHeight1;
|
||||||
|
pitchSampleGroundHeight2 = pitchGroundHeight2;
|
||||||
|
rollSampleGroundHeight1 = rollGroundHeight1;
|
||||||
|
rollSampleGroundHeight2 = rollGroundHeight2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pitch = Math.max(-maxPitch, Math.min(maxPitch,
|
||||||
|
(float) Math.atan2(pitchSampleGroundHeight2 - pitchSampleGroundHeight1, sampleRadius * 2)));
|
||||||
roll = Math.max(-maxRoll, Math.min(maxRoll,
|
roll = Math.max(-maxRoll, Math.min(maxRoll,
|
||||||
(float) Math.atan2(rollSampleGroundHeight2 - rollSampleGroundHeight1, sampleRadius * 2)));
|
(float) Math.atan2(rollSampleGroundHeight2 - rollSampleGroundHeight1, sampleRadius * 2)));
|
||||||
this.instance.rotate(tempQuat.setFromAxisRad(RenderMathUtils.VEC3_UNIT_Y, -pitch));
|
this.instance.rotate(tempQuat.setFromAxisRad(RenderMathUtils.VEC3_UNIT_Y, -pitch));
|
||||||
@ -289,6 +351,21 @@ public class RenderUnit {
|
|||||||
this.unitAnimationListenerImpl.update();
|
this.unitAnimationListenerImpl.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float getGroundHeightSample(final float groundHeight, final MdxComplexInstance currentWalkableUnder,
|
||||||
|
final float sampleX, final float sampleY) {
|
||||||
|
final float sampleGroundHeight;
|
||||||
|
War3MapViewer.gdxRayHeap.origin.x = sampleX;
|
||||||
|
War3MapViewer.gdxRayHeap.origin.y = sampleY;
|
||||||
|
if (currentWalkableUnder.intersectRayWithCollision(War3MapViewer.gdxRayHeap, War3MapViewer.intersectionHeap,
|
||||||
|
true, true)) {
|
||||||
|
sampleGroundHeight = War3MapViewer.intersectionHeap.z;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sampleGroundHeight = groundHeight;
|
||||||
|
}
|
||||||
|
return sampleGroundHeight;
|
||||||
|
}
|
||||||
|
|
||||||
public CUnit getSimulationUnit() {
|
public CUnit getSimulationUnit() {
|
||||||
return this.simulationUnit;
|
return this.simulationUnit;
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,6 @@ public interface CommandButtonListener {
|
|||||||
// int getButtonPositionY();
|
// int getButtonPositionY();
|
||||||
//
|
//
|
||||||
// int getOrderId();
|
// int getOrderId();
|
||||||
void commandButton(int buttonPositionX, int buttonPositionY, Texture icon, int abilityHandleId, int orderId);
|
void commandButton(int buttonPositionX, int buttonPositionY, Texture icon, int abilityHandleId, int orderId,
|
||||||
|
boolean active);
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,29 @@ package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons;
|
|||||||
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
|
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
|
||||||
|
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.CAbility;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
|
||||||
|
|
||||||
public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void> {
|
public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void> {
|
||||||
public static final CommandCardPopulatingAbilityVisitor INSTANCE = new CommandCardPopulatingAbilityVisitor();
|
public static final CommandCardPopulatingAbilityVisitor INSTANCE = new CommandCardPopulatingAbilityVisitor();
|
||||||
|
|
||||||
|
private CSimulation game;
|
||||||
|
private CUnit unit;
|
||||||
|
|
||||||
private CommandButtonListener commandButtonListener;
|
private CommandButtonListener commandButtonListener;
|
||||||
private AbilityDataUI abilityDataUI;
|
private AbilityDataUI abilityDataUI;
|
||||||
private boolean hasStop;
|
private boolean hasStop;
|
||||||
|
|
||||||
public CommandCardPopulatingAbilityVisitor reset(final CommandButtonListener commandButtonListener,
|
public CommandCardPopulatingAbilityVisitor reset(final CSimulation game, final CUnit unit,
|
||||||
final AbilityDataUI abilityDataUI) {
|
final CommandButtonListener commandButtonListener, final AbilityDataUI abilityDataUI) {
|
||||||
|
this.game = game;
|
||||||
|
this.unit = unit;
|
||||||
this.commandButtonListener = commandButtonListener;
|
this.commandButtonListener = commandButtonListener;
|
||||||
this.abilityDataUI = abilityDataUI;
|
this.abilityDataUI = abilityDataUI;
|
||||||
this.hasStop = false;
|
this.hasStop = false;
|
||||||
@ -24,28 +33,41 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void accept(final CAbilityAttack ability) {
|
public Void accept(final CAbilityAttack ability) {
|
||||||
addCommandButton(this.abilityDataUI.getAttackUI(), ability.getHandleId(), OrderIds.attack);
|
addCommandButton(ability, this.abilityDataUI.getAttackUI(), ability.getHandleId(), OrderIds.attack);
|
||||||
if (!this.hasStop) {
|
if (!this.hasStop) {
|
||||||
this.hasStop = true;
|
this.hasStop = true;
|
||||||
addCommandButton(this.abilityDataUI.getStopUI(), -1, OrderIds.stop);
|
addCommandButton(null, this.abilityDataUI.getStopUI(), -1, OrderIds.stop);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void accept(final CAbilityMove ability) {
|
public Void accept(final CAbilityMove ability) {
|
||||||
addCommandButton(this.abilityDataUI.getMoveUI(), ability.getHandleId(), OrderIds.move);
|
addCommandButton(ability, this.abilityDataUI.getMoveUI(), ability.getHandleId(), OrderIds.move);
|
||||||
addCommandButton(this.abilityDataUI.getHoldPosUI(), ability.getHandleId(), OrderIds.holdposition);
|
addCommandButton(ability, this.abilityDataUI.getHoldPosUI(), ability.getHandleId(), OrderIds.holdposition);
|
||||||
addCommandButton(this.abilityDataUI.getPatrolUI(), ability.getHandleId(), OrderIds.patrol);
|
addCommandButton(ability, this.abilityDataUI.getPatrolUI(), ability.getHandleId(), OrderIds.patrol);
|
||||||
if (!this.hasStop) {
|
if (!this.hasStop) {
|
||||||
this.hasStop = true;
|
this.hasStop = true;
|
||||||
addCommandButton(this.abilityDataUI.getStopUI(), -1, OrderIds.stop);
|
addCommandButton(null, this.abilityDataUI.getStopUI(), -1, OrderIds.stop);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCommandButton(final IconUI iconUI, final int handleId, final int orderId) {
|
private void addCommandButton(final CAbility ability, final IconUI iconUI, final int handleId, final int orderId) {
|
||||||
|
final boolean active;
|
||||||
|
if (this.unit.getCurrentOrder() == null) {
|
||||||
|
active = (orderId == OrderIds.stop);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ability == null) {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ability.checkCanUse(this.game, this.unit, orderId, BooleanAbilityActivationReceiver.INSTANCE);
|
||||||
|
active = BooleanAbilityActivationReceiver.INSTANCE.isOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
this.commandButtonListener.commandButton(iconUI.getButtonPositionX(), iconUI.getButtonPositionY(),
|
this.commandButtonListener.commandButton(iconUI.getButtonPositionX(), iconUI.getButtonPositionY(),
|
||||||
iconUI.getIcon(), handleId, orderId);
|
iconUI.getIcon(), handleId, orderId, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CAttackOrder;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehaviorAttack;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehavior;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
|
||||||
@ -37,8 +38,8 @@ public class CUnit extends CWidget {
|
|||||||
|
|
||||||
private final List<CAbility> abilities = new ArrayList<>();
|
private final List<CAbility> abilities = new ArrayList<>();
|
||||||
|
|
||||||
private COrder currentOrder;
|
private CBehavior currentOrder;
|
||||||
private final Queue<COrder> orderQueue = new LinkedList<>();
|
private final Queue<CBehavior> orderQueue = new LinkedList<>();
|
||||||
private final CUnitType unitType;
|
private final CUnitType unitType;
|
||||||
|
|
||||||
private Rectangle collisionRectangle;
|
private Rectangle collisionRectangle;
|
||||||
@ -189,6 +190,7 @@ public class CUnit extends CWidget {
|
|||||||
// remove current order, because it's completed, polling next
|
// remove current order, because it's completed, polling next
|
||||||
// item from order queue
|
// item from order queue
|
||||||
this.currentOrder = this.orderQueue.poll();
|
this.currentOrder = this.orderQueue.poll();
|
||||||
|
this.stateNotifier.ordersChanged();
|
||||||
}
|
}
|
||||||
if (this.currentOrder == null) {
|
if (this.currentOrder == null) {
|
||||||
// maybe order "stop" here
|
// maybe order "stop" here
|
||||||
@ -222,7 +224,7 @@ public class CUnit extends CWidget {
|
|||||||
return game.getGameplayConstants().getBoneDecayTime();
|
return game.getGameplayConstants().getBoneDecayTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void order(final COrder order, final boolean queue) {
|
public void order(final CBehavior order, final boolean queue) {
|
||||||
if (isDead()) {
|
if (isDead()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -231,10 +233,12 @@ public class CUnit extends CWidget {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.currentOrder = order;
|
this.currentOrder = order;
|
||||||
|
this.orderQueue.clear();
|
||||||
}
|
}
|
||||||
|
this.stateNotifier.ordersChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public COrder getCurrentOrder() {
|
public CBehavior getCurrentOrder() {
|
||||||
return this.currentOrder;
|
return this.currentOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +394,7 @@ public class CUnit extends CWidget {
|
|||||||
CAllianceType.PASSIVE)) {
|
CAllianceType.PASSIVE)) {
|
||||||
for (final CUnitAttack attack : this.unitType.getAttacks()) {
|
for (final CUnitAttack attack : this.unitType.getAttacks()) {
|
||||||
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
|
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
|
||||||
this.order(new CAttackOrder(this, attack, OrderIds.attack, source), false);
|
this.order(new CBehaviorAttack(this, attack, OrderIds.attack, source), false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,6 +525,10 @@ public class CUnit extends CWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("No targeting because " + targetsAllowed + " does not contain all of "
|
||||||
|
+ this.unitType.getTargetedAs());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +558,7 @@ public class CUnit extends CWidget {
|
|||||||
if (this.source.canReach(unit, this.source.acquisitionRange)
|
if (this.source.canReach(unit, this.source.acquisitionRange)
|
||||||
&& unit.canBeTargetedBy(this.game, this.source, attack.getTargetsAllowed())
|
&& unit.canBeTargetedBy(this.game, this.source, attack.getTargetsAllowed())
|
||||||
&& (this.source.distance(unit) >= this.source.getUnitType().getMinimumAttackRange())) {
|
&& (this.source.distance(unit) >= this.source.getUnitType().getMinimumAttackRange())) {
|
||||||
this.source.order(new CAttackOrder(this.source, attack, OrderIds.attack, unit), false);
|
this.source.order(new CBehaviorAttack(this.source, attack, OrderIds.attack, unit), false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import com.etheller.warsmash.util.SubscriberSetNotifier;
|
|||||||
public interface CUnitStateListener {
|
public interface CUnitStateListener {
|
||||||
void lifeChanged(); // hp (current) changes
|
void lifeChanged(); // hp (current) changes
|
||||||
|
|
||||||
|
void ordersChanged();
|
||||||
|
|
||||||
public static final class CUnitStateNotifier extends SubscriberSetNotifier<CUnitStateListener>
|
public static final class CUnitStateNotifier extends SubscriberSetNotifier<CUnitStateListener>
|
||||||
implements CUnitStateListener {
|
implements CUnitStateListener {
|
||||||
@Override
|
@Override
|
||||||
@ -13,5 +15,12 @@ public interface CUnitStateListener {
|
|||||||
listener.lifeChanged();
|
listener.lifeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ordersChanged() {
|
||||||
|
for (final CUnitStateListener listener : set) {
|
||||||
|
listener.ordersChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,4 +17,5 @@ public interface CAbility extends CAbilityView {
|
|||||||
void onOrder(CSimulation game, CUnit caster, int orderId, Vector2 point, boolean queue);
|
void onOrder(CSimulation game, CUnit caster, int orderId, Vector2 point, boolean queue);
|
||||||
|
|
||||||
void onOrderNoTarget(CSimulation game, CUnit caster, int orderId, boolean queue);
|
void onOrderNoTarget(CSimulation game, CUnit caster, int orderId, boolean queue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
|
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder;
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
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.CUnit;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.StringsToExternalizeLater;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.StringsToExternalizeLater;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CWeaponType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CAttackOrder;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehavior;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CMoveOrder;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehaviorAttack;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehaviorMove;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CAllianceType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
|
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;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver.TargetType;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver.TargetType;
|
||||||
@ -30,6 +32,15 @@ public class CAbilityAttack implements CAbility {
|
|||||||
@Override
|
@Override
|
||||||
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
|
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
|
||||||
final AbilityTargetCheckReceiver<CWidget> receiver) {
|
final AbilityTargetCheckReceiver<CWidget> receiver) {
|
||||||
|
if (orderId == OrderIds.smart) {
|
||||||
|
if (target instanceof CUnit) {
|
||||||
|
if (game.getPlayer(unit.getPlayerIndex()).hasAlliance(((CUnit) target).getPlayerIndex(),
|
||||||
|
CAllianceType.PASSIVE)) {
|
||||||
|
receiver.orderIdNotAccepted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((orderId == OrderIds.smart) || (orderId == OrderIds.attack)) {
|
if ((orderId == OrderIds.smart) || (orderId == OrderIds.attack)) {
|
||||||
boolean canTarget = false;
|
boolean canTarget = false;
|
||||||
for (final CUnitAttack attack : unit.getUnitType().getAttacks()) {
|
for (final CUnitAttack attack : unit.getUnitType().getAttacks()) {
|
||||||
@ -54,7 +65,30 @@ public class CAbilityAttack implements CAbility {
|
|||||||
@Override
|
@Override
|
||||||
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final Vector2 target,
|
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final Vector2 target,
|
||||||
final AbilityTargetCheckReceiver<Vector2> receiver) {
|
final AbilityTargetCheckReceiver<Vector2> receiver) {
|
||||||
receiver.mustTargetType(TargetType.UNIT);
|
switch (orderId) {
|
||||||
|
case OrderIds.attack:
|
||||||
|
receiver.targetOk(target);
|
||||||
|
break;
|
||||||
|
case OrderIds.attackground:
|
||||||
|
boolean allowAttackGround = false;
|
||||||
|
for (final CUnitAttack attack : unit.getUnitType().getAttacks()) {
|
||||||
|
if ((attack.getWeaponType() == CWeaponType.ARTILLERY)
|
||||||
|
|| (attack.getWeaponType() == CWeaponType.ALINE)) {
|
||||||
|
allowAttackGround = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowAttackGround) {
|
||||||
|
receiver.targetOk(target);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
receiver.orderIdNotAccepted();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
receiver.orderIdNotAccepted();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,15 +108,15 @@ public class CAbilityAttack implements CAbility {
|
|||||||
@Override
|
@Override
|
||||||
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final CWidget target,
|
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final CWidget target,
|
||||||
final boolean queue) {
|
final boolean queue) {
|
||||||
COrder order = null;
|
CBehavior order = null;
|
||||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||||
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
||||||
order = new CAttackOrder(caster, attack, orderId, target);
|
order = new CBehaviorAttack(caster, attack, orderId, target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (order == null) {
|
if (order == null) {
|
||||||
order = new CMoveOrder(caster, orderId, target.getX(), target.getY());
|
order = new CBehaviorMove(caster, orderId, target.getX(), target.getY());
|
||||||
}
|
}
|
||||||
caster.order(order, queue);
|
caster.order(order, queue);
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ 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.CUnit;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.StringsToExternalizeLater;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.StringsToExternalizeLater;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CMoveOrder;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehaviorMove;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CPatrolOrder;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.CBehaviorPatrol;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
|
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.AbilityActivationReceiver;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
|
||||||
@ -85,13 +85,13 @@ public class CAbilityMove implements CAbility {
|
|||||||
@Override
|
@Override
|
||||||
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final CWidget target,
|
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final CWidget target,
|
||||||
final boolean queue) {
|
final boolean queue) {
|
||||||
caster.order(new CPatrolOrder(caster, orderId, (CUnit) target), queue);
|
caster.order(new CBehaviorPatrol(caster, orderId, (CUnit) target), queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final Vector2 target,
|
public void onOrder(final CSimulation game, final CUnit caster, final int orderId, final Vector2 target,
|
||||||
final boolean queue) {
|
final boolean queue) {
|
||||||
caster.order(new CMoveOrder(caster, orderId, target.x, target.y), queue);
|
caster.order(new CBehaviorMove(caster, orderId, target.x, target.y), queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,388 +32,396 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUni
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
||||||
|
|
||||||
public class CUnitData {
|
public class CUnitData {
|
||||||
private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi");
|
private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi");
|
||||||
private static final War3ID MANA_MAXIMUM = War3ID.fromString("umpm");
|
private static final War3ID MANA_MAXIMUM = War3ID.fromString("umpm");
|
||||||
private static final War3ID HIT_POINT_MAXIMUM = War3ID.fromString("uhpm");
|
private static final War3ID HIT_POINT_MAXIMUM = War3ID.fromString("uhpm");
|
||||||
private static final War3ID MOVEMENT_SPEED_BASE = War3ID.fromString("umvs");
|
private static final War3ID MOVEMENT_SPEED_BASE = War3ID.fromString("umvs");
|
||||||
private static final War3ID PROPULSION_WINDOW = War3ID.fromString("uprw");
|
private static final War3ID PROPULSION_WINDOW = War3ID.fromString("uprw");
|
||||||
private static final War3ID TURN_RATE = War3ID.fromString("umvr");
|
private static final War3ID TURN_RATE = War3ID.fromString("umvr");
|
||||||
private static final War3ID IS_BLDG = War3ID.fromString("ubdg");
|
private static final War3ID IS_BLDG = War3ID.fromString("ubdg");
|
||||||
private static final War3ID NAME = War3ID.fromString("unam");
|
private static final War3ID NAME = War3ID.fromString("unam");
|
||||||
private static final War3ID PROJECTILE_LAUNCH_X = War3ID.fromString("ulpx");
|
private static final War3ID PROJECTILE_LAUNCH_X = War3ID.fromString("ulpx");
|
||||||
private static final War3ID PROJECTILE_LAUNCH_Y = War3ID.fromString("ulpy");
|
private static final War3ID PROJECTILE_LAUNCH_Y = War3ID.fromString("ulpy");
|
||||||
private static final War3ID PROJECTILE_LAUNCH_Z = War3ID.fromString("ulpz");
|
private static final War3ID PROJECTILE_LAUNCH_Z = War3ID.fromString("ulpz");
|
||||||
private static final War3ID ATTACKS_ENABLED = War3ID.fromString("uaen");
|
private static final War3ID ATTACKS_ENABLED = War3ID.fromString("uaen");
|
||||||
private static final War3ID ATTACK1_BACKSWING_POINT = War3ID.fromString("ubs1");
|
private static final War3ID ATTACK1_BACKSWING_POINT = War3ID.fromString("ubs1");
|
||||||
private static final War3ID ATTACK1_DAMAGE_POINT = War3ID.fromString("udp1");
|
private static final War3ID ATTACK1_DAMAGE_POINT = War3ID.fromString("udp1");
|
||||||
private static final War3ID ATTACK1_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua1f");
|
private static final War3ID ATTACK1_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua1f");
|
||||||
private static final War3ID ATTACK1_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua1h");
|
private static final War3ID ATTACK1_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua1h");
|
||||||
private static final War3ID ATTACK1_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua1q");
|
private static final War3ID ATTACK1_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua1q");
|
||||||
private static final War3ID ATTACK1_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua1p");
|
private static final War3ID ATTACK1_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua1p");
|
||||||
private static final War3ID ATTACK1_ATTACK_TYPE = War3ID.fromString("ua1t");
|
private static final War3ID ATTACK1_ATTACK_TYPE = War3ID.fromString("ua1t");
|
||||||
private static final War3ID ATTACK1_COOLDOWN = War3ID.fromString("ua1c");
|
private static final War3ID ATTACK1_COOLDOWN = War3ID.fromString("ua1c");
|
||||||
private static final War3ID ATTACK1_DMG_BASE = War3ID.fromString("ua1b");
|
private static final War3ID ATTACK1_DMG_BASE = War3ID.fromString("ua1b");
|
||||||
private static final War3ID ATTACK1_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd1");
|
private static final War3ID ATTACK1_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd1");
|
||||||
private static final War3ID ATTACK1_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd1");
|
private static final War3ID ATTACK1_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd1");
|
||||||
private static final War3ID ATTACK1_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl1");
|
private static final War3ID ATTACK1_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl1");
|
||||||
private static final War3ID ATTACK1_DMG_DICE = War3ID.fromString("ua1d");
|
private static final War3ID ATTACK1_DMG_DICE = War3ID.fromString("ua1d");
|
||||||
private static final War3ID ATTACK1_DMG_SIDES_PER_DIE = War3ID.fromString("ua1s");
|
private static final War3ID ATTACK1_DMG_SIDES_PER_DIE = War3ID.fromString("ua1s");
|
||||||
private static final War3ID ATTACK1_DMG_SPILL_DIST = War3ID.fromString("usd1");
|
private static final War3ID ATTACK1_DMG_SPILL_DIST = War3ID.fromString("usd1");
|
||||||
private static final War3ID ATTACK1_DMG_SPILL_RADIUS = War3ID.fromString("usr1");
|
private static final War3ID ATTACK1_DMG_SPILL_RADIUS = War3ID.fromString("usr1");
|
||||||
private static final War3ID ATTACK1_DMG_UPGRADE_AMT = War3ID.fromString("udu1");
|
private static final War3ID ATTACK1_DMG_UPGRADE_AMT = War3ID.fromString("udu1");
|
||||||
private static final War3ID ATTACK1_TARGET_COUNT = War3ID.fromString("utc1");
|
private static final War3ID ATTACK1_TARGET_COUNT = War3ID.fromString("utc1");
|
||||||
private static final War3ID ATTACK1_PROJECTILE_ARC = War3ID.fromString("uma1");
|
private static final War3ID ATTACK1_PROJECTILE_ARC = War3ID.fromString("uma1");
|
||||||
private static final War3ID ATTACK1_MISSILE_ART = War3ID.fromString("ua1m");
|
private static final War3ID ATTACK1_MISSILE_ART = War3ID.fromString("ua1m");
|
||||||
private static final War3ID ATTACK1_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh1");
|
private static final War3ID ATTACK1_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh1");
|
||||||
private static final War3ID ATTACK1_PROJECTILE_SPEED = War3ID.fromString("ua1z");
|
private static final War3ID ATTACK1_PROJECTILE_SPEED = War3ID.fromString("ua1z");
|
||||||
private static final War3ID ATTACK1_RANGE = War3ID.fromString("ua1r");
|
private static final War3ID ATTACK1_RANGE = War3ID.fromString("ua1r");
|
||||||
private static final War3ID ATTACK1_RANGE_MOTION_BUFFER = War3ID.fromString("urb1");
|
private static final War3ID ATTACK1_RANGE_MOTION_BUFFER = War3ID.fromString("urb1");
|
||||||
private static final War3ID ATTACK1_SHOW_UI = War3ID.fromString("uwu1");
|
private static final War3ID ATTACK1_SHOW_UI = War3ID.fromString("uwu1");
|
||||||
private static final War3ID ATTACK1_TARGETS_ALLOWED = War3ID.fromString("ua1g");
|
private static final War3ID ATTACK1_TARGETS_ALLOWED = War3ID.fromString("ua1g");
|
||||||
private static final War3ID ATTACK1_WEAPON_SOUND = War3ID.fromString("ucs1");
|
private static final War3ID ATTACK1_WEAPON_SOUND = War3ID.fromString("ucs1");
|
||||||
private static final War3ID ATTACK1_WEAPON_TYPE = War3ID.fromString("ua1w");
|
private static final War3ID ATTACK1_WEAPON_TYPE = War3ID.fromString("ua1w");
|
||||||
|
|
||||||
private static final War3ID ATTACK2_BACKSWING_POINT = War3ID.fromString("ubs2");
|
private static final War3ID ATTACK2_BACKSWING_POINT = War3ID.fromString("ubs2");
|
||||||
private static final War3ID ATTACK2_DAMAGE_POINT = War3ID.fromString("udp2");
|
private static final War3ID ATTACK2_DAMAGE_POINT = War3ID.fromString("udp2");
|
||||||
private static final War3ID ATTACK2_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua2f");
|
private static final War3ID ATTACK2_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua2f");
|
||||||
private static final War3ID ATTACK2_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua2h");
|
private static final War3ID ATTACK2_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua2h");
|
||||||
private static final War3ID ATTACK2_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua2q");
|
private static final War3ID ATTACK2_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua2q");
|
||||||
private static final War3ID ATTACK2_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua2p");
|
private static final War3ID ATTACK2_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua2p");
|
||||||
private static final War3ID ATTACK2_ATTACK_TYPE = War3ID.fromString("ua2t");
|
private static final War3ID ATTACK2_ATTACK_TYPE = War3ID.fromString("ua2t");
|
||||||
private static final War3ID ATTACK2_COOLDOWN = War3ID.fromString("ua2c");
|
private static final War3ID ATTACK2_COOLDOWN = War3ID.fromString("ua2c");
|
||||||
private static final War3ID ATTACK2_DMG_BASE = War3ID.fromString("ua2b");
|
private static final War3ID ATTACK2_DMG_BASE = War3ID.fromString("ua2b");
|
||||||
private static final War3ID ATTACK2_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd2");
|
private static final War3ID ATTACK2_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd2");
|
||||||
private static final War3ID ATTACK2_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd2");
|
private static final War3ID ATTACK2_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd2");
|
||||||
private static final War3ID ATTACK2_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl2");
|
private static final War3ID ATTACK2_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl2");
|
||||||
private static final War3ID ATTACK2_DMG_DICE = War3ID.fromString("ua2d");
|
private static final War3ID ATTACK2_DMG_DICE = War3ID.fromString("ua2d");
|
||||||
private static final War3ID ATTACK2_DMG_SIDES_PER_DIE = War3ID.fromString("ua2s");
|
private static final War3ID ATTACK2_DMG_SIDES_PER_DIE = War3ID.fromString("ua2s");
|
||||||
private static final War3ID ATTACK2_DMG_SPILL_DIST = War3ID.fromString("usd2");
|
private static final War3ID ATTACK2_DMG_SPILL_DIST = War3ID.fromString("usd2");
|
||||||
private static final War3ID ATTACK2_DMG_SPILL_RADIUS = War3ID.fromString("usr2");
|
private static final War3ID ATTACK2_DMG_SPILL_RADIUS = War3ID.fromString("usr2");
|
||||||
private static final War3ID ATTACK2_DMG_UPGRADE_AMT = War3ID.fromString("udu2");
|
private static final War3ID ATTACK2_DMG_UPGRADE_AMT = War3ID.fromString("udu2");
|
||||||
private static final War3ID ATTACK2_TARGET_COUNT = War3ID.fromString("utc2");
|
private static final War3ID ATTACK2_TARGET_COUNT = War3ID.fromString("utc2");
|
||||||
private static final War3ID ATTACK2_PROJECTILE_ARC = War3ID.fromString("uma2");
|
private static final War3ID ATTACK2_PROJECTILE_ARC = War3ID.fromString("uma2");
|
||||||
private static final War3ID ATTACK2_MISSILE_ART = War3ID.fromString("ua2m");
|
private static final War3ID ATTACK2_MISSILE_ART = War3ID.fromString("ua2m");
|
||||||
private static final War3ID ATTACK2_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh2");
|
private static final War3ID ATTACK2_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh2");
|
||||||
private static final War3ID ATTACK2_PROJECTILE_SPEED = War3ID.fromString("ua2z");
|
private static final War3ID ATTACK2_PROJECTILE_SPEED = War3ID.fromString("ua2z");
|
||||||
private static final War3ID ATTACK2_RANGE = War3ID.fromString("ua2r");
|
private static final War3ID ATTACK2_RANGE = War3ID.fromString("ua2r");
|
||||||
private static final War3ID ATTACK2_RANGE_MOTION_BUFFER = War3ID.fromString("urb2");
|
private static final War3ID ATTACK2_RANGE_MOTION_BUFFER = War3ID.fromString("urb2");
|
||||||
private static final War3ID ATTACK2_SHOW_UI = War3ID.fromString("uwu2");
|
private static final War3ID ATTACK2_SHOW_UI = War3ID.fromString("uwu2");
|
||||||
private static final War3ID ATTACK2_TARGETS_ALLOWED = War3ID.fromString("ua2g");
|
private static final War3ID ATTACK2_TARGETS_ALLOWED = War3ID.fromString("ua2g");
|
||||||
private static final War3ID ATTACK2_WEAPON_SOUND = War3ID.fromString("ucs2");
|
private static final War3ID ATTACK2_WEAPON_SOUND = War3ID.fromString("ucs2");
|
||||||
private static final War3ID ATTACK2_WEAPON_TYPE = War3ID.fromString("ua2w");
|
private static final War3ID ATTACK2_WEAPON_TYPE = War3ID.fromString("ua2w");
|
||||||
|
|
||||||
private static final War3ID ACQUISITION_RANGE = War3ID.fromString("uacq");
|
private static final War3ID ACQUISITION_RANGE = War3ID.fromString("uacq");
|
||||||
private static final War3ID MINIMUM_ATTACK_RANGE = War3ID.fromString("uamn");
|
private static final War3ID MINIMUM_ATTACK_RANGE = War3ID.fromString("uamn");
|
||||||
|
|
||||||
private static final War3ID PROJECTILE_IMPACT_Z = War3ID.fromString("uimz");
|
private static final War3ID PROJECTILE_IMPACT_Z = War3ID.fromString("uimz");
|
||||||
|
|
||||||
private static final War3ID DEATH_TYPE = War3ID.fromString("udea");
|
private static final War3ID DEATH_TYPE = War3ID.fromString("udea");
|
||||||
private static final War3ID ARMOR_TYPE = War3ID.fromString("uarm");
|
private static final War3ID ARMOR_TYPE = War3ID.fromString("uarm");
|
||||||
|
|
||||||
private static final War3ID DEFENSE = War3ID.fromString("udef");
|
private static final War3ID DEFENSE = War3ID.fromString("udef");
|
||||||
private static final War3ID DEFENSE_TYPE = War3ID.fromString("udty");
|
private static final War3ID DEFENSE_TYPE = War3ID.fromString("udty");
|
||||||
private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh");
|
private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh");
|
||||||
private static final War3ID MOVE_TYPE = War3ID.fromString("umvt");
|
private static final War3ID MOVE_TYPE = War3ID.fromString("umvt");
|
||||||
private static final War3ID COLLISION_SIZE = War3ID.fromString("ucol");
|
private static final War3ID COLLISION_SIZE = War3ID.fromString("ucol");
|
||||||
private static final War3ID CLASSIFICATION = War3ID.fromString("utyp");
|
private static final War3ID CLASSIFICATION = War3ID.fromString("utyp");
|
||||||
private static final War3ID DEATH_TIME = War3ID.fromString("udtm");
|
private static final War3ID DEATH_TIME = War3ID.fromString("udtm");
|
||||||
private static final War3ID TARGETED_AS = War3ID.fromString("utar");
|
private static final War3ID TARGETED_AS = War3ID.fromString("utar");
|
||||||
private final MutableObjectData unitData;
|
private final MutableObjectData unitData;
|
||||||
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
|
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
|
||||||
|
|
||||||
public CUnitData(final MutableObjectData unitData) {
|
public CUnitData(final MutableObjectData unitData) {
|
||||||
this.unitData = unitData;
|
this.unitData = unitData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CUnit create(final CSimulation simulation, final int playerIndex, final War3ID typeId, final float x,
|
public CUnit create(final CSimulation simulation, final int playerIndex, final War3ID typeId, final float x,
|
||||||
final float y, final float facing, final BufferedImage buildingPathingPixelMap,
|
final float y, final float facing, final BufferedImage buildingPathingPixelMap,
|
||||||
final SimulationRenderController simulationRenderController, final HandleIdAllocator handleIdAllocator) {
|
final SimulationRenderController simulationRenderController, final HandleIdAllocator handleIdAllocator) {
|
||||||
final MutableGameObject unitType = this.unitData.get(typeId);
|
final MutableGameObject unitType = this.unitData.get(typeId);
|
||||||
final int handleId = handleIdAllocator.createId();
|
final int handleId = handleIdAllocator.createId();
|
||||||
final int life = unitType.getFieldAsInteger(HIT_POINT_MAXIMUM, 0);
|
final int life = unitType.getFieldAsInteger(HIT_POINT_MAXIMUM, 0);
|
||||||
final int manaInitial = unitType.getFieldAsInteger(MANA_INITIAL_AMOUNT, 0);
|
final int manaInitial = unitType.getFieldAsInteger(MANA_INITIAL_AMOUNT, 0);
|
||||||
final int manaMaximum = unitType.getFieldAsInteger(MANA_MAXIMUM, 0);
|
final int manaMaximum = unitType.getFieldAsInteger(MANA_MAXIMUM, 0);
|
||||||
final int speed = unitType.getFieldAsInteger(MOVEMENT_SPEED_BASE, 0);
|
final int speed = unitType.getFieldAsInteger(MOVEMENT_SPEED_BASE, 0);
|
||||||
final int defense = unitType.getFieldAsInteger(DEFENSE, 0);
|
final int defense = unitType.getFieldAsInteger(DEFENSE, 0);
|
||||||
|
|
||||||
final CUnitType unitTypeInstance = getUnitTypeInstance(typeId, buildingPathingPixelMap, unitType);
|
final CUnitType unitTypeInstance = getUnitTypeInstance(typeId, buildingPathingPixelMap, unitType);
|
||||||
|
|
||||||
final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum,
|
final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum,
|
||||||
speed, defense, unitTypeInstance);
|
speed, defense, unitTypeInstance);
|
||||||
if (speed > 0) {
|
if (speed > 0) {
|
||||||
unit.add(simulation, new CAbilityMove(handleIdAllocator.createId()));
|
unit.add(simulation, new CAbilityMove(handleIdAllocator.createId()));
|
||||||
}
|
}
|
||||||
if (!unitTypeInstance.getAttacks().isEmpty()) {
|
if (!unitTypeInstance.getAttacks().isEmpty()) {
|
||||||
unit.add(simulation, new CAbilityAttack(handleIdAllocator.createId()));
|
unit.add(simulation, new CAbilityAttack(handleIdAllocator.createId()));
|
||||||
}
|
}
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage buildingPathingPixelMap,
|
private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage buildingPathingPixelMap,
|
||||||
final MutableGameObject unitType) {
|
final MutableGameObject unitType) {
|
||||||
CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId);
|
CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId);
|
||||||
if (unitTypeInstance == null) {
|
if (unitTypeInstance == null) {
|
||||||
final float moveHeight = unitType.getFieldAsFloat(MOVE_HEIGHT, 0);
|
final float moveHeight = unitType.getFieldAsFloat(MOVE_HEIGHT, 0);
|
||||||
final String movetp = unitType.getFieldAsString(MOVE_TYPE, 0);
|
final String movetp = unitType.getFieldAsString(MOVE_TYPE, 0);
|
||||||
final float collisionSize = unitType.getFieldAsFloat(COLLISION_SIZE, 0);
|
final float collisionSize = unitType.getFieldAsFloat(COLLISION_SIZE, 0);
|
||||||
final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0);
|
final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0);
|
||||||
final PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp);
|
final PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp);
|
||||||
final String unitName = unitType.getFieldAsString(NAME, 0);
|
final String unitName = unitType.getFieldAsString(NAME, 0);
|
||||||
final float acquisitionRange = unitType.getFieldAsFloat(ACQUISITION_RANGE, 0);
|
final float acquisitionRange = unitType.getFieldAsFloat(ACQUISITION_RANGE, 0);
|
||||||
final float minimumAttackRange = unitType.getFieldAsFloat(MINIMUM_ATTACK_RANGE, 0);
|
final float minimumAttackRange = unitType.getFieldAsFloat(MINIMUM_ATTACK_RANGE, 0);
|
||||||
final EnumSet<CTargetType> targetedAs = CTargetType
|
final EnumSet<CTargetType> targetedAs = CTargetType
|
||||||
.parseTargetTypeSet(unitType.getFieldAsString(TARGETED_AS, 0));
|
.parseTargetTypeSet(unitType.getFieldAsString(TARGETED_AS, 0));
|
||||||
final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0);
|
final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0);
|
||||||
final EnumSet<CUnitClassification> classifications = EnumSet.noneOf(CUnitClassification.class);
|
final EnumSet<CUnitClassification> classifications = EnumSet.noneOf(CUnitClassification.class);
|
||||||
if (classificationString != null) {
|
if (classificationString != null) {
|
||||||
final String[] classificationValues = classificationString.split(",");
|
final String[] classificationValues = classificationString.split(",");
|
||||||
for (final String unitEditorKey : classificationValues) {
|
for (final String unitEditorKey : classificationValues) {
|
||||||
final CUnitClassification unitClassification = CUnitClassification
|
final CUnitClassification unitClassification = CUnitClassification
|
||||||
.parseUnitClassification(unitEditorKey);
|
.parseUnitClassification(unitEditorKey);
|
||||||
if (unitClassification != null) {
|
if (unitClassification != null) {
|
||||||
classifications.add(unitClassification);
|
classifications.add(unitClassification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final List<CUnitAttack> attacks = new ArrayList<>();
|
final List<CUnitAttack> attacks = new ArrayList<>();
|
||||||
final int attacksEnabled = unitType.getFieldAsInteger(ATTACKS_ENABLED, 0);
|
final int attacksEnabled = unitType.getFieldAsInteger(ATTACKS_ENABLED, 0);
|
||||||
if ((attacksEnabled & 0x1) != 0) {
|
if ((attacksEnabled & 0x1) != 0) {
|
||||||
// attack one
|
try {
|
||||||
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK1_BACKSWING_POINT, 0);
|
// attack one
|
||||||
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK1_DAMAGE_POINT, 0);
|
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK1_BACKSWING_POINT, 0);
|
||||||
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_FULL_DMG, 0);
|
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK1_DAMAGE_POINT, 0);
|
||||||
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_HALF_DMG, 0);
|
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_FULL_DMG, 0);
|
||||||
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_QUARTER_DMG, 0);
|
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_HALF_DMG, 0);
|
||||||
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
|
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_QUARTER_DMG, 0);
|
||||||
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_AREA_OF_EFFECT_TARGETS, 0));
|
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
|
||||||
final CAttackType attackType = CAttackType
|
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_AREA_OF_EFFECT_TARGETS, 0));
|
||||||
.parseAttackType(unitType.getFieldAsString(ATTACK1_ATTACK_TYPE, 0));
|
final CAttackType attackType = CAttackType
|
||||||
final float cooldownTime = unitType.getFieldAsFloat(ATTACK1_COOLDOWN, 0);
|
.parseAttackType(unitType.getFieldAsString(ATTACK1_ATTACK_TYPE, 0));
|
||||||
final int damageBase = unitType.getFieldAsInteger(ATTACK1_DMG_BASE, 0);
|
final float cooldownTime = unitType.getFieldAsFloat(ATTACK1_COOLDOWN, 0);
|
||||||
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_HALF, 0);
|
final int damageBase = unitType.getFieldAsInteger(ATTACK1_DMG_BASE, 0);
|
||||||
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_QUARTER, 0);
|
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_HALF, 0);
|
||||||
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK1_DAMAGE_LOSS_FACTOR, 0);
|
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_QUARTER, 0);
|
||||||
final int damageDice = unitType.getFieldAsInteger(ATTACK1_DMG_DICE, 0);
|
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK1_DAMAGE_LOSS_FACTOR, 0);
|
||||||
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0);
|
final int damageDice = unitType.getFieldAsInteger(ATTACK1_DMG_DICE, 0);
|
||||||
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_DIST, 0);
|
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0);
|
||||||
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_RADIUS, 0);
|
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_DIST, 0);
|
||||||
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK1_DMG_UPGRADE_AMT, 0);
|
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_RADIUS, 0);
|
||||||
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK1_TARGET_COUNT, 0);
|
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK1_DMG_UPGRADE_AMT, 0);
|
||||||
final float projectileArc = unitType.getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
|
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK1_TARGET_COUNT, 0);
|
||||||
final String projectileArt = unitType.getFieldAsString(ATTACK1_MISSILE_ART, 0);
|
final float projectileArc = unitType.getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
|
||||||
final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK1_PROJECTILE_HOMING_ENABLED,
|
final String projectileArt = unitType.getFieldAsString(ATTACK1_MISSILE_ART, 0);
|
||||||
0);
|
final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK1_PROJECTILE_HOMING_ENABLED,
|
||||||
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
|
0);
|
||||||
final int range = unitType.getFieldAsInteger(ATTACK1_RANGE, 0);
|
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
|
||||||
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK1_RANGE_MOTION_BUFFER, 0);
|
final int range = unitType.getFieldAsInteger(ATTACK1_RANGE, 0);
|
||||||
final boolean showUI = unitType.getFieldAsBoolean(ATTACK1_SHOW_UI, 0);
|
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK1_RANGE_MOTION_BUFFER, 0);
|
||||||
final EnumSet<CTargetType> targetsAllowed = CTargetType
|
final boolean showUI = unitType.getFieldAsBoolean(ATTACK1_SHOW_UI, 0);
|
||||||
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_TARGETS_ALLOWED, 0));
|
final EnumSet<CTargetType> targetsAllowed = CTargetType
|
||||||
final String weaponSound = unitType.getFieldAsString(ATTACK1_WEAPON_SOUND, 0);
|
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_TARGETS_ALLOWED, 0));
|
||||||
final CWeaponType weaponType = CWeaponType
|
final String weaponSound = unitType.getFieldAsString(ATTACK1_WEAPON_SOUND, 0);
|
||||||
.parseWeaponType(unitType.getFieldAsString(ATTACK1_WEAPON_TYPE, 0));
|
final CWeaponType weaponType = CWeaponType
|
||||||
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
|
.parseWeaponType(unitType.getFieldAsString(ATTACK1_WEAPON_TYPE, 0));
|
||||||
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
|
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
|
||||||
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice,
|
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
|
||||||
damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
|
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice,
|
||||||
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed,
|
damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
|
||||||
range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType));
|
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed,
|
||||||
}
|
range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType));
|
||||||
if ((attacksEnabled & 0x2) != 0) {
|
} catch (Exception exc) {
|
||||||
// attack two
|
System.err.println("Attack 1 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
|
||||||
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK2_BACKSWING_POINT, 0);
|
}
|
||||||
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK2_DAMAGE_POINT, 0);
|
}
|
||||||
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_FULL_DMG, 0);
|
if ((attacksEnabled & 0x2) != 0) {
|
||||||
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_HALF_DMG, 0);
|
try {
|
||||||
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_QUARTER_DMG, 0);
|
// attack two
|
||||||
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
|
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK2_BACKSWING_POINT, 0);
|
||||||
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_AREA_OF_EFFECT_TARGETS, 0));
|
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK2_DAMAGE_POINT, 0);
|
||||||
final CAttackType attackType = CAttackType
|
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_FULL_DMG, 0);
|
||||||
.parseAttackType(unitType.getFieldAsString(ATTACK2_ATTACK_TYPE, 0));
|
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_HALF_DMG, 0);
|
||||||
final float cooldownTime = unitType.getFieldAsFloat(ATTACK2_COOLDOWN, 0);
|
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_QUARTER_DMG, 0);
|
||||||
final int damageBase = unitType.getFieldAsInteger(ATTACK2_DMG_BASE, 0);
|
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
|
||||||
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_HALF, 0);
|
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_AREA_OF_EFFECT_TARGETS, 0));
|
||||||
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_QUARTER, 0);
|
final CAttackType attackType = CAttackType
|
||||||
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK2_DAMAGE_LOSS_FACTOR, 0);
|
.parseAttackType(unitType.getFieldAsString(ATTACK2_ATTACK_TYPE, 0));
|
||||||
final int damageDice = unitType.getFieldAsInteger(ATTACK2_DMG_DICE, 0);
|
final float cooldownTime = unitType.getFieldAsFloat(ATTACK2_COOLDOWN, 0);
|
||||||
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0);
|
final int damageBase = unitType.getFieldAsInteger(ATTACK2_DMG_BASE, 0);
|
||||||
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_DIST, 0);
|
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_HALF, 0);
|
||||||
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_RADIUS, 0);
|
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_QUARTER, 0);
|
||||||
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK2_DMG_UPGRADE_AMT, 0);
|
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK2_DAMAGE_LOSS_FACTOR, 0);
|
||||||
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK2_TARGET_COUNT, 0);
|
final int damageDice = unitType.getFieldAsInteger(ATTACK2_DMG_DICE, 0);
|
||||||
final float projectileArc = unitType.getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
|
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0);
|
||||||
final String projectileArt = unitType.getFieldAsString(ATTACK2_MISSILE_ART, 0);
|
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_DIST, 0);
|
||||||
final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK2_PROJECTILE_HOMING_ENABLED,
|
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_RADIUS, 0);
|
||||||
0);
|
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK2_DMG_UPGRADE_AMT, 0);
|
||||||
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
|
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK2_TARGET_COUNT, 0);
|
||||||
final int range = unitType.getFieldAsInteger(ATTACK2_RANGE, 0);
|
final float projectileArc = unitType.getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
|
||||||
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK2_RANGE_MOTION_BUFFER, 0);
|
final String projectileArt = unitType.getFieldAsString(ATTACK2_MISSILE_ART, 0);
|
||||||
final boolean showUI = unitType.getFieldAsBoolean(ATTACK2_SHOW_UI, 0);
|
final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK2_PROJECTILE_HOMING_ENABLED,
|
||||||
final EnumSet<CTargetType> targetsAllowed = CTargetType
|
0);
|
||||||
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_TARGETS_ALLOWED, 0));
|
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
|
||||||
final String weaponSound = unitType.getFieldAsString(ATTACK2_WEAPON_SOUND, 0);
|
final int range = unitType.getFieldAsInteger(ATTACK2_RANGE, 0);
|
||||||
final CWeaponType weaponType = CWeaponType
|
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK2_RANGE_MOTION_BUFFER, 0);
|
||||||
.parseWeaponType(unitType.getFieldAsString(ATTACK2_WEAPON_TYPE, 0));
|
final boolean showUI = unitType.getFieldAsBoolean(ATTACK2_SHOW_UI, 0);
|
||||||
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
|
final EnumSet<CTargetType> targetsAllowed = CTargetType
|
||||||
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
|
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_TARGETS_ALLOWED, 0));
|
||||||
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice,
|
final String weaponSound = unitType.getFieldAsString(ATTACK2_WEAPON_SOUND, 0);
|
||||||
damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
|
final CWeaponType weaponType = CWeaponType
|
||||||
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed,
|
.parseWeaponType(unitType.getFieldAsString(ATTACK2_WEAPON_TYPE, 0));
|
||||||
range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType));
|
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
|
||||||
}
|
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
|
||||||
final int deathType = unitType.getFieldAsInteger(DEATH_TYPE, 0);
|
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice,
|
||||||
final boolean raise = (deathType & 0x1) != 0;
|
damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
|
||||||
final boolean decay = (deathType & 0x2) != 0;
|
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed,
|
||||||
final String armorType = unitType.getFieldAsString(ARMOR_TYPE, 0);
|
range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType));
|
||||||
final float impactZ = unitType.getFieldAsFloat(PROJECTILE_IMPACT_Z, 0);
|
} catch (Exception exc) {
|
||||||
final CDefenseType defenseType = CDefenseType.parseDefenseType(unitType.getFieldAsString(DEFENSE_TYPE, 0));
|
System.err.println("Attack 2 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
|
||||||
final float deathTime = unitType.getFieldAsFloat(DEATH_TIME, 0);
|
}
|
||||||
unitTypeInstance = new CUnitType(unitName, isBldg, movementType, moveHeight, collisionSize, classifications,
|
}
|
||||||
attacks, armorType, raise, decay, defenseType, impactZ, buildingPathingPixelMap, deathTime,
|
final int deathType = unitType.getFieldAsInteger(DEATH_TYPE, 0);
|
||||||
targetedAs, acquisitionRange, minimumAttackRange);
|
final boolean raise = (deathType & 0x1) != 0;
|
||||||
this.unitIdToUnitType.put(typeId, unitTypeInstance);
|
final boolean decay = (deathType & 0x2) != 0;
|
||||||
}
|
final String armorType = unitType.getFieldAsString(ARMOR_TYPE, 0);
|
||||||
return unitTypeInstance;
|
final float impactZ = unitType.getFieldAsFloat(PROJECTILE_IMPACT_Z, 0);
|
||||||
}
|
final CDefenseType defenseType = CDefenseType.parseDefenseType(unitType.getFieldAsString(DEFENSE_TYPE, 0));
|
||||||
|
final float deathTime = unitType.getFieldAsFloat(DEATH_TIME, 0);
|
||||||
|
unitTypeInstance = new CUnitType(unitName, isBldg, movementType, moveHeight, collisionSize, classifications,
|
||||||
|
attacks, armorType, raise, decay, defenseType, impactZ, buildingPathingPixelMap, deathTime,
|
||||||
|
targetedAs, acquisitionRange, minimumAttackRange);
|
||||||
|
this.unitIdToUnitType.put(typeId, unitTypeInstance);
|
||||||
|
}
|
||||||
|
return unitTypeInstance;
|
||||||
|
}
|
||||||
|
|
||||||
private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint,
|
private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint,
|
||||||
final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage,
|
final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage,
|
||||||
final EnumSet<CTargetType> areaOfEffectTargets, final CAttackType attackType, final float cooldownTime,
|
final EnumSet<CTargetType> areaOfEffectTargets, final CAttackType attackType, final float cooldownTime,
|
||||||
final int damageBase, final float damageFactorMedium, final float damageFactorSmall,
|
final int damageBase, final float damageFactorMedium, final float damageFactorSmall,
|
||||||
final float damageLossFactor, final int damageDice, final int damageSidesPerDie,
|
final float damageLossFactor, final int damageDice, final int damageSidesPerDie,
|
||||||
final float damageSpillDistance, final float damageSpillRadius, final int damageUpgradeAmount,
|
final float damageSpillDistance, final float damageSpillRadius, final int damageUpgradeAmount,
|
||||||
final int maximumNumberOfTargets, final float projectileArc, final String projectileArt,
|
final int maximumNumberOfTargets, final float projectileArc, final String projectileArt,
|
||||||
final boolean projectileHomingEnabled, final int projectileSpeed, final int range,
|
final boolean projectileHomingEnabled, final int projectileSpeed, final int range,
|
||||||
final float rangeMotionBuffer, final boolean showUI, final EnumSet<CTargetType> targetsAllowed,
|
final float rangeMotionBuffer, final boolean showUI, final EnumSet<CTargetType> targetsAllowed,
|
||||||
final String weaponSound, final CWeaponType weaponType) {
|
final String weaponSound, final CWeaponType weaponType) {
|
||||||
final CUnitAttack attack;
|
final CUnitAttack attack;
|
||||||
switch (weaponType) {
|
switch (weaponType) {
|
||||||
case MISSILE:
|
case MISSILE:
|
||||||
attack = new CUnitAttackMissile(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
attack = new CUnitAttackMissile(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
||||||
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
||||||
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
|
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
|
||||||
projectileSpeed);
|
projectileSpeed);
|
||||||
break;
|
break;
|
||||||
case MBOUNCE:
|
case MBOUNCE:
|
||||||
attack = new CUnitAttackMissileBounce(animationBackswingPoint, animationDamagePoint, attackType,
|
attack = new CUnitAttackMissileBounce(animationBackswingPoint, animationDamagePoint, attackType,
|
||||||
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
|
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
|
||||||
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
|
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
|
||||||
projectileHomingEnabled, projectileSpeed, damageLossFactor, maximumNumberOfTargets,
|
projectileHomingEnabled, projectileSpeed, damageLossFactor, maximumNumberOfTargets,
|
||||||
areaOfEffectFullDamage, areaOfEffectTargets);
|
areaOfEffectFullDamage, areaOfEffectTargets);
|
||||||
break;
|
break;
|
||||||
case MSPLASH:
|
case MSPLASH:
|
||||||
case ARTILLERY:
|
case ARTILLERY:
|
||||||
attack = new CUnitAttackMissileSplash(animationBackswingPoint, animationDamagePoint, attackType,
|
attack = new CUnitAttackMissileSplash(animationBackswingPoint, animationDamagePoint, attackType,
|
||||||
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
|
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
|
||||||
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
|
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
|
||||||
projectileHomingEnabled, projectileSpeed, areaOfEffectFullDamage, areaOfEffectMediumDamage,
|
projectileHomingEnabled, projectileSpeed, areaOfEffectFullDamage, areaOfEffectMediumDamage,
|
||||||
areaOfEffectSmallDamage, areaOfEffectTargets, damageFactorMedium, damageFactorSmall);
|
areaOfEffectSmallDamage, areaOfEffectTargets, damageFactorMedium, damageFactorSmall);
|
||||||
break;
|
break;
|
||||||
case MLINE:
|
case MLINE:
|
||||||
case ALINE:
|
case ALINE:
|
||||||
attack = new CUnitAttackMissileLine(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
attack = new CUnitAttackMissileLine(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
||||||
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
||||||
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
|
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
|
||||||
projectileSpeed, damageSpillDistance, damageSpillRadius);
|
projectileSpeed, damageSpillDistance, damageSpillRadius);
|
||||||
break;
|
break;
|
||||||
case INSTANT:
|
case INSTANT:
|
||||||
attack = new CUnitAttackInstant(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
attack = new CUnitAttackInstant(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
||||||
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
||||||
targetsAllowed, weaponSound, weaponType, projectileArt);
|
targetsAllowed, weaponSound, weaponType, projectileArt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
attack = new CUnitAttackNormal(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
attack = new CUnitAttackNormal(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
|
||||||
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
|
||||||
targetsAllowed, weaponSound, weaponType);
|
targetsAllowed, weaponSound, weaponType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return attack;
|
return attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getPropulsionWindow(final War3ID unitTypeId) {
|
public float getPropulsionWindow(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(PROPULSION_WINDOW, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(PROPULSION_WINDOW, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getTurnRate(final War3ID unitTypeId) {
|
public float getTurnRate(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(TURN_RATE, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(TURN_RATE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBuilding(final War3ID unitTypeId) {
|
public boolean isBuilding(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsBoolean(IS_BLDG, 0);
|
return this.unitData.get(unitTypeId).getFieldAsBoolean(IS_BLDG, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(final War3ID unitTypeId) {
|
public String getName(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getName();
|
return this.unitData.get(unitTypeId).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA1MinDamage(final War3ID unitTypeId) {
|
public int getA1MinDamage(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
|
||||||
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0);
|
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA1MaxDamage(final War3ID unitTypeId) {
|
public int getA1MaxDamage(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
|
||||||
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0)
|
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0)
|
||||||
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0));
|
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA2MinDamage(final War3ID unitTypeId) {
|
public int getA2MinDamage(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
|
||||||
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0);
|
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA2MaxDamage(final War3ID unitTypeId) {
|
public int getA2MaxDamage(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
|
||||||
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0)
|
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0)
|
||||||
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0));
|
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefense(final War3ID unitTypeId) {
|
public int getDefense(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(DEFENSE, 0);
|
return this.unitData.get(unitTypeId).getFieldAsInteger(DEFENSE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA1ProjectileSpeed(final War3ID unitTypeId) {
|
public int getA1ProjectileSpeed(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getA1ProjectileArc(final War3ID unitTypeId) {
|
public float getA1ProjectileArc(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getA2ProjectileSpeed(final War3ID unitTypeId) {
|
public int getA2ProjectileSpeed(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
|
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getA2ProjectileArc(final War3ID unitTypeId) {
|
public float getA2ProjectileArc(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getA1MissileArt(final War3ID unitTypeId) {
|
public String getA1MissileArt(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK1_MISSILE_ART, 0);
|
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK1_MISSILE_ART, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getA2MissileArt(final War3ID unitTypeId) {
|
public String getA2MissileArt(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK2_MISSILE_ART, 0);
|
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK2_MISSILE_ART, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getA1Cooldown(final War3ID unitTypeId) {
|
public float getA1Cooldown(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_COOLDOWN, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_COOLDOWN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getA2Cooldown(final War3ID unitTypeId) {
|
public float getA2Cooldown(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_COOLDOWN, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_COOLDOWN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getProjectileLaunchX(final War3ID unitTypeId) {
|
public float getProjectileLaunchX(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_X, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_X, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getProjectileLaunchY(final War3ID unitTypeId) {
|
public float getProjectileLaunchY(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Y, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getProjectileLaunchZ(final War3ID unitTypeId) {
|
public float getProjectileLaunchZ(final War3ID unitTypeId) {
|
||||||
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Z, 0);
|
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Z, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
|
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
||||||
|
|
||||||
public interface COrder {
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||||
|
|
||||||
|
public interface CBehavior {
|
||||||
/**
|
/**
|
||||||
* Executes one step of game simulation of the current order, returning true if
|
* Executes one step of game simulation of the current order, returning true if
|
||||||
* the order has completed. Many orders may wrap the move order and spend a
|
* the order has completed. Many orders may wrap the move order and spend a
|
@ -3,13 +3,12 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
|||||||
import com.etheller.warsmash.util.WarsmashConstants;
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder;
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
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.CUnit;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||||
|
|
||||||
public class CAttackOrder implements COrder {
|
public class CBehaviorAttack implements CBehavior {
|
||||||
private final CUnit unit;
|
private final CUnit unit;
|
||||||
private final int orderId;
|
private final int orderId;
|
||||||
private boolean wasWithinPropWindow = false;
|
private boolean wasWithinPropWindow = false;
|
||||||
@ -17,11 +16,11 @@ public class CAttackOrder implements COrder {
|
|||||||
private final CWidget target;
|
private final CWidget target;
|
||||||
private int damagePointLaunchTime;
|
private int damagePointLaunchTime;
|
||||||
private int backSwingTime;
|
private int backSwingTime;
|
||||||
private COrder moveOrder;
|
private CBehavior moveOrder;
|
||||||
private int thisOrderCooldownEndTime;
|
private int thisOrderCooldownEndTime;
|
||||||
private boolean wasInRange = false;
|
private boolean wasInRange = false;
|
||||||
|
|
||||||
public CAttackOrder(final CUnit unit, final CUnitAttack unitAttack, final int orderId, final CWidget target) {
|
public CBehaviorAttack(final CUnit unit, final CUnitAttack unitAttack, final int orderId, final CWidget target) {
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.unitAttack = unitAttack;
|
this.unitAttack = unitAttack;
|
||||||
this.orderId = orderId;
|
this.orderId = orderId;
|
||||||
@ -32,10 +31,10 @@ public class CAttackOrder implements COrder {
|
|||||||
private void createMoveOrder(final CUnit unit, final CWidget target) {
|
private void createMoveOrder(final CUnit unit, final CWidget target) {
|
||||||
if (!unit.isMovementDisabled()) { // TODO: Check mobility instead
|
if (!unit.isMovementDisabled()) { // TODO: Check mobility instead
|
||||||
if ((target instanceof CUnit) && !(((CUnit) target).getUnitType().isBuilding())) {
|
if ((target instanceof CUnit) && !(((CUnit) target).getUnitType().isBuilding())) {
|
||||||
this.moveOrder = new CMoveOrder(unit, this.orderId, (CUnit) target);
|
this.moveOrder = new CBehaviorMove(unit, this.orderId, (CUnit) target);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.moveOrder = new CMoveOrder(unit, this.orderId, target.getX(), target.getY());
|
this.moveOrder = new CBehaviorMove(unit, this.orderId, target.getX(), target.getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -50,7 +49,7 @@ public class CAttackOrder implements COrder {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
float range = this.unitAttack.getRange();
|
float range = this.unitAttack.getRange();
|
||||||
if ((this.target instanceof CUnit) && (((CUnit) this.target).getCurrentOrder() instanceof CMoveOrder)
|
if ((this.target instanceof CUnit) && (((CUnit) this.target).getCurrentOrder() instanceof CBehaviorMove)
|
||||||
&& (this.damagePointLaunchTime != 0 /*
|
&& (this.damagePointLaunchTime != 0 /*
|
||||||
* only apply range motion buffer if they were already in range and
|
* only apply range motion buffer if they were already in range and
|
||||||
* attacked
|
* attacked
|
||||||
@ -138,7 +137,6 @@ public class CAttackOrder implements COrder {
|
|||||||
else {
|
else {
|
||||||
damage = simulation.getSeededRandom().nextInt(maxDamage - minDamage) + minDamage;
|
damage = simulation.getSeededRandom().nextInt(maxDamage - minDamage) + minDamage;
|
||||||
}
|
}
|
||||||
System.out.println(damage + " from " + minDamage + " to " + maxDamage);
|
|
||||||
this.unitAttack.launch(simulation, this.unit, this.target, damage);
|
this.unitAttack.launch(simulation, this.unit, this.target, damage);
|
||||||
this.damagePointLaunchTime = 0;
|
this.damagePointLaunchTime = 0;
|
||||||
}
|
}
|
@ -10,13 +10,12 @@ import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
|||||||
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
|
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
|
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder;
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
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.CUnit;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWorldCollision;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWorldCollision;
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor;
|
||||||
|
|
||||||
public class CMoveOrder implements COrder {
|
public class CBehaviorMove implements CBehavior {
|
||||||
private static final Rectangle tempRect = new Rectangle();
|
private static final Rectangle tempRect = new Rectangle();
|
||||||
private final CUnit unit;
|
private final CUnit unit;
|
||||||
private final int orderId;
|
private final int orderId;
|
||||||
@ -27,7 +26,7 @@ public class CMoveOrder implements COrder {
|
|||||||
private int searchCycles = 0;
|
private int searchCycles = 0;
|
||||||
private CUnit followUnit;
|
private CUnit followUnit;
|
||||||
|
|
||||||
public CMoveOrder(final CUnit unit, final int orderId, final float targetX, final float targetY) {
|
public CBehaviorMove(final CUnit unit, final int orderId, final float targetX, final float targetY) {
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.orderId = orderId;
|
this.orderId = orderId;
|
||||||
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
|
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
|
||||||
@ -36,7 +35,7 @@ public class CMoveOrder implements COrder {
|
|||||||
this.target = new Point2D.Float(targetX, targetY);
|
this.target = new Point2D.Float(targetX, targetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CMoveOrder(final CUnit unit, final int orderId, final CUnit followUnit) {
|
public CBehaviorMove(final CUnit unit, final int orderId, final CUnit followUnit) {
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.orderId = orderId;
|
this.orderId = orderId;
|
||||||
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
|
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
|
@ -0,0 +1,96 @@
|
|||||||
|
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class CBehaviorPatrol implements CBehavior {
|
||||||
|
private final CUnit unit;
|
||||||
|
private final int orderId;
|
||||||
|
private final CWidget target;
|
||||||
|
private CBehavior moveOrder;
|
||||||
|
|
||||||
|
public CBehaviorPatrol(final CUnit unit, final int orderId, final CUnit target) {
|
||||||
|
this.unit = unit;
|
||||||
|
this.orderId = orderId;
|
||||||
|
this.target = target;
|
||||||
|
createMoveOrder(unit, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMoveOrder(final CUnit unit, final CUnit target) {
|
||||||
|
if (!unit.isMovementDisabled()) { // TODO: Check mobility instead
|
||||||
|
if ((target instanceof CUnit) && !(target.getUnitType().isBuilding())) {
|
||||||
|
this.moveOrder = new CBehaviorMove(unit, this.orderId, target);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.moveOrder = new CBehaviorMove(unit, this.orderId, target.getX(), target.getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.moveOrder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(final CSimulation simulation) {
|
||||||
|
if (this.target.isDead()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final float range = this.unit.getAcquisitionRange();
|
||||||
|
if (!this.unit.canReach(this.target, range)) {
|
||||||
|
if (this.moveOrder == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this.moveOrder.update(simulation)) {
|
||||||
|
return true; // we just cant reach them
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.unit.isMovementDisabled()) {
|
||||||
|
final float prevX = this.unit.getX();
|
||||||
|
final float prevY = this.unit.getY();
|
||||||
|
final float deltaY = this.target.getY() - prevY;
|
||||||
|
final float deltaX = this.target.getX() - prevX;
|
||||||
|
final double goalAngleRad = Math.atan2(deltaY, deltaX);
|
||||||
|
float goalAngle = (float) Math.toDegrees(goalAngleRad);
|
||||||
|
if (goalAngle < 0) {
|
||||||
|
goalAngle += 360;
|
||||||
|
}
|
||||||
|
float facing = this.unit.getFacing();
|
||||||
|
float delta = goalAngle - facing;
|
||||||
|
final float turnRate = simulation.getUnitData().getTurnRate(this.unit.getTypeId());
|
||||||
|
|
||||||
|
if (delta < -180) {
|
||||||
|
delta = 360 + delta;
|
||||||
|
}
|
||||||
|
if (delta > 180) {
|
||||||
|
delta = -360 + delta;
|
||||||
|
}
|
||||||
|
final float absDelta = Math.abs(delta);
|
||||||
|
|
||||||
|
if ((absDelta <= 1.0) && (absDelta != 0)) {
|
||||||
|
this.unit.setFacing(goalAngle);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float angleToAdd = Math.signum(delta) * (float) Math.toDegrees(turnRate);
|
||||||
|
if (absDelta < Math.abs(angleToAdd)) {
|
||||||
|
angleToAdd = delta;
|
||||||
|
}
|
||||||
|
facing += angleToAdd;
|
||||||
|
this.unit.setFacing(facing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, SequenceUtils.EMPTY, 1.0f, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrderId() {
|
||||||
|
return this.orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,11 @@
|
|||||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
||||||
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder;
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||||
|
|
||||||
public class CDoNothingOrder implements COrder {
|
public class CBehaviorStop implements CBehavior {
|
||||||
private final int orderId;
|
private final int orderId;
|
||||||
|
|
||||||
public CDoNothingOrder(final int orderId) {
|
public CBehaviorStop(final int orderId) {
|
||||||
this.orderId = orderId;
|
this.orderId = orderId;
|
||||||
}
|
}
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders;
|
|
||||||
|
|
||||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class CPatrolOrder implements COrder {
|
|
||||||
private final CUnit unit;
|
|
||||||
private final int orderId;
|
|
||||||
private final CWidget target;
|
|
||||||
private COrder moveOrder;
|
|
||||||
|
|
||||||
public CPatrolOrder(final CUnit unit, final int orderId, final CUnit target) {
|
|
||||||
this.unit = unit;
|
|
||||||
this.orderId = orderId;
|
|
||||||
this.target = target;
|
|
||||||
createMoveOrder(unit, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createMoveOrder(final CUnit unit, final CUnit target) {
|
|
||||||
if (!unit.isMovementDisabled()) { // TODO: Check mobility instead
|
|
||||||
if ((target instanceof CUnit) && !(target.getUnitType().isBuilding())) {
|
|
||||||
this.moveOrder = new CMoveOrder(unit, this.orderId, target);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.moveOrder = new CMoveOrder(unit, this.orderId, target.getX(), target.getY());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.moveOrder = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean update(final CSimulation simulation) {
|
|
||||||
if (this.target.isDead()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final float range = this.unit.getAcquisitionRange();
|
|
||||||
if (!this.unit.canReach(this.target, range)) {
|
|
||||||
if (this.moveOrder == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (this.moveOrder.update(simulation)) {
|
|
||||||
return true; // we just cant reach them
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOrderId() {
|
|
||||||
return this.orderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -177,7 +177,8 @@ public class CPathfindingProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!openSet.isEmpty()) {
|
int searchIterations = 0;
|
||||||
|
while (!openSet.isEmpty() && searchIterations < 150000) {
|
||||||
Node current = openSet.poll();
|
Node current = openSet.poll();
|
||||||
if (isGoal(current)) {
|
if (isGoal(current)) {
|
||||||
final LinkedList<Point2D.Float> totalPath = new LinkedList<>();
|
final LinkedList<Point2D.Float> totalPath = new LinkedList<>();
|
||||||
@ -259,6 +260,7 @@ public class CPathfindingProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
searchIterations++;
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class CPlayerUnitOrderExecutor implements CPlayerUnitOrderListener {
|
|||||||
if (this.abilityActivationReceiver.isUseOk()) {
|
if (this.abilityActivationReceiver.isUseOk()) {
|
||||||
final StringMsgTargetCheckReceiver<Void> targetReceiver = this.<Void>targetCheckReceiver();
|
final StringMsgTargetCheckReceiver<Void> targetReceiver = this.<Void>targetCheckReceiver();
|
||||||
ability.checkCanTargetNoTarget(this.game, unit, orderId, targetReceiver);
|
ability.checkCanTargetNoTarget(this.game, unit, orderId, targetReceiver);
|
||||||
if (targetReceiver.getTarget() != null) {
|
if (targetReceiver.getMessage() == null) {
|
||||||
ability.onOrderNoTarget(this.game, unit, orderId, queue);
|
ability.onOrderNoTarget(this.game, unit, orderId, queue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandL
|
|||||||
public class CommandCardIcon extends AbstractRenderableFrame {
|
public class CommandCardIcon extends AbstractRenderableFrame {
|
||||||
|
|
||||||
private TextureFrame iconFrame;
|
private TextureFrame iconFrame;
|
||||||
|
private TextureFrame activeHighlightFrame;
|
||||||
private SpriteFrame cooldownFrame;
|
private SpriteFrame cooldownFrame;
|
||||||
private SpriteFrame autocastFrame;
|
private SpriteFrame autocastFrame;
|
||||||
private CommandButton commandButton;
|
private CommandButton commandButton;
|
||||||
@ -30,8 +31,10 @@ public class CommandCardIcon extends AbstractRenderableFrame {
|
|||||||
this.commandCardCommandListener = commandCardCommandListener;
|
this.commandCardCommandListener = commandCardCommandListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(final TextureFrame iconFrame, final SpriteFrame cooldownFrame, final SpriteFrame autocastFrame) {
|
public void set(final TextureFrame iconFrame, final TextureFrame activeHighlightFrame,
|
||||||
|
final SpriteFrame cooldownFrame, final SpriteFrame autocastFrame) {
|
||||||
this.iconFrame = iconFrame;
|
this.iconFrame = iconFrame;
|
||||||
|
this.activeHighlightFrame = activeHighlightFrame;
|
||||||
this.cooldownFrame = cooldownFrame;
|
this.cooldownFrame = cooldownFrame;
|
||||||
this.autocastFrame = autocastFrame;
|
this.autocastFrame = autocastFrame;
|
||||||
}
|
}
|
||||||
@ -40,6 +43,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
|
|||||||
this.commandButton = commandButton;
|
this.commandButton = commandButton;
|
||||||
if (commandButton == null) {
|
if (commandButton == null) {
|
||||||
this.iconFrame.setVisible(false);
|
this.iconFrame.setVisible(false);
|
||||||
|
this.activeHighlightFrame.setVisible(false);
|
||||||
this.cooldownFrame.setVisible(false);
|
this.cooldownFrame.setVisible(false);
|
||||||
this.autocastFrame.setVisible(false);
|
this.autocastFrame.setVisible(false);
|
||||||
}
|
}
|
||||||
@ -64,8 +68,10 @@ public class CommandCardIcon extends AbstractRenderableFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId) {
|
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId,
|
||||||
|
final boolean active) {
|
||||||
this.iconFrame.setVisible(true);
|
this.iconFrame.setVisible(true);
|
||||||
|
this.activeHighlightFrame.setVisible(active);
|
||||||
this.cooldownFrame.setVisible(false);
|
this.cooldownFrame.setVisible(false);
|
||||||
this.autocastFrame.setVisible(false);
|
this.autocastFrame.setVisible(false);
|
||||||
this.iconFrame.setTexture(texture);
|
this.iconFrame.setTexture(texture);
|
||||||
@ -76,6 +82,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
|
|||||||
@Override
|
@Override
|
||||||
protected void innerPositionBounds(final Viewport viewport) {
|
protected void innerPositionBounds(final Viewport viewport) {
|
||||||
this.iconFrame.positionBounds(viewport);
|
this.iconFrame.positionBounds(viewport);
|
||||||
|
this.activeHighlightFrame.positionBounds(viewport);
|
||||||
this.cooldownFrame.positionBounds(viewport);
|
this.cooldownFrame.positionBounds(viewport);
|
||||||
this.autocastFrame.positionBounds(viewport);
|
this.autocastFrame.positionBounds(viewport);
|
||||||
}
|
}
|
||||||
@ -83,6 +90,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
|
|||||||
@Override
|
@Override
|
||||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
this.iconFrame.render(batch, baseFont, glyphLayout);
|
this.iconFrame.render(batch, baseFont, glyphLayout);
|
||||||
|
this.activeHighlightFrame.render(batch, baseFont, glyphLayout);
|
||||||
this.cooldownFrame.render(batch, baseFont, glyphLayout);
|
this.cooldownFrame.render(batch, baseFont, glyphLayout);
|
||||||
this.autocastFrame.render(batch, baseFont, glyphLayout);
|
this.autocastFrame.render(batch, baseFont, glyphLayout);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
|||||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
|
||||||
import com.badlogic.gdx.math.Rectangle;
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.math.Vector3;
|
import com.badlogic.gdx.math.Vector3;
|
||||||
@ -28,6 +30,7 @@ import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
|||||||
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
|
||||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||||
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||||
|
import com.etheller.warsmash.parsers.mdlx.Layer.FilterMode;
|
||||||
import com.etheller.warsmash.util.FastNumberFormat;
|
import com.etheller.warsmash.util.FastNumberFormat;
|
||||||
import com.etheller.warsmash.util.ImageUtils;
|
import com.etheller.warsmash.util.ImageUtils;
|
||||||
import com.etheller.warsmash.util.WarsmashConstants;
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
@ -135,6 +138,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
private int selectedSoundCount = 0;
|
private int selectedSoundCount = 0;
|
||||||
private final ActiveCommandUnitTargetFilter activeCommandUnitTargetFilter;
|
private final ActiveCommandUnitTargetFilter activeCommandUnitTargetFilter;
|
||||||
|
|
||||||
|
private UIFrame clickUI = null;
|
||||||
|
|
||||||
public MeleeUI(final DataSource dataSource, final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator,
|
public MeleeUI(final DataSource dataSource, final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator,
|
||||||
final Scene uiScene, final Scene portraitScene, final CameraPreset[] cameraPresets,
|
final Scene uiScene, final Scene portraitScene, final CameraPreset[] cameraPresets,
|
||||||
final CameraRates cameraRates, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener,
|
final CameraRates cameraRates, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener,
|
||||||
@ -305,6 +310,9 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
this.rootFrame.add(commandCardIcon);
|
this.rootFrame.add(commandCardIcon);
|
||||||
final TextureFrame iconFrame = this.rootFrame.createTextureFrame(
|
final TextureFrame iconFrame = this.rootFrame.createTextureFrame(
|
||||||
"SmashCommandButton_" + (commandButtonIndex) + "_Icon", this.rootFrame, false, null);
|
"SmashCommandButton_" + (commandButtonIndex) + "_Icon", this.rootFrame, false, null);
|
||||||
|
final TextureFrame activeHighlightFrame = this.rootFrame.createTextureFrame(
|
||||||
|
"SmashCommandButton_" + (commandButtonIndex) + "_ActiveHighlight", this.rootFrame, true, null,
|
||||||
|
FilterMode.ADDALPHA);
|
||||||
final SpriteFrame cooldownFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
final SpriteFrame cooldownFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
||||||
"SmashCommandButton_" + (commandButtonIndex) + "_Cooldown", this.rootFrame, "", 0);
|
"SmashCommandButton_" + (commandButtonIndex) + "_Cooldown", this.rootFrame, "", 0);
|
||||||
final SpriteFrame autocastFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
final SpriteFrame autocastFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
||||||
@ -318,6 +326,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
iconFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
iconFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
||||||
iconFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
|
iconFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
|
||||||
iconFrame.setTexture(ImageUtils.DEFAULT_ICON_PATH, this.rootFrame);
|
iconFrame.setTexture(ImageUtils.DEFAULT_ICON_PATH, this.rootFrame);
|
||||||
|
activeHighlightFrame
|
||||||
|
.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
|
||||||
|
activeHighlightFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
||||||
|
activeHighlightFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
|
||||||
|
activeHighlightFrame.setTexture("CommandButtonActiveHighlight", this.rootFrame);
|
||||||
cooldownFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
|
cooldownFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
|
||||||
this.rootFrame.setSpriteFrameModel(cooldownFrame, this.rootFrame.getSkinField("CommandButtonCooldown"));
|
this.rootFrame.setSpriteFrameModel(cooldownFrame, this.rootFrame.getSkinField("CommandButtonCooldown"));
|
||||||
cooldownFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
cooldownFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
||||||
@ -326,7 +339,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
this.rootFrame.setSpriteFrameModel(autocastFrame, this.rootFrame.getSkinField("CommandButtonAutocast"));
|
this.rootFrame.setSpriteFrameModel(autocastFrame, this.rootFrame.getSkinField("CommandButtonAutocast"));
|
||||||
autocastFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
autocastFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
|
||||||
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
|
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
|
||||||
commandCardIcon.set(iconFrame, cooldownFrame, autocastFrame);
|
commandCardIcon.set(iconFrame, activeHighlightFrame, cooldownFrame, autocastFrame);
|
||||||
this.commandCard[j][i] = commandCardIcon;
|
this.commandCard[j][i] = commandCardIcon;
|
||||||
commandCardIcon.setCommandButton(null);
|
commandCardIcon.setCommandButton(null);
|
||||||
commandButtonIndex++;
|
commandButtonIndex++;
|
||||||
@ -408,7 +421,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
|
|
||||||
mouseX = Math.max(minX, Math.min(maxX, mouseX));
|
mouseX = Math.max(minX, Math.min(maxX, mouseX));
|
||||||
mouseY = Math.max(minY, Math.min(maxY, mouseY));
|
mouseY = Math.max(minY, Math.min(maxY, mouseY));
|
||||||
Gdx.input.setCursorPosition(mouseX, mouseY);
|
// Gdx.input.setCursorPosition(mouseX, mouseY);
|
||||||
|
|
||||||
screenCoordsVector.set(mouseX, mouseY);
|
screenCoordsVector.set(mouseX, mouseY);
|
||||||
this.uiViewport.unproject(screenCoordsVector);
|
this.uiViewport.unproject(screenCoordsVector);
|
||||||
@ -456,6 +469,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
this.cameraManager.updateCamera();
|
this.cameraManager.updateCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ShapeRenderer shapeRenderer = new ShapeRenderer();
|
||||||
|
|
||||||
public void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
public void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
||||||
this.rootFrame.render(batch, font20, glyphLayout);
|
this.rootFrame.render(batch, font20, glyphLayout);
|
||||||
if (this.selectedUnit != null) {
|
if (this.selectedUnit != null) {
|
||||||
@ -466,6 +481,18 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
this.meleeUIMinimap.render(batch, this.war3MapViewer.units);
|
this.meleeUIMinimap.render(batch, this.war3MapViewer.units);
|
||||||
this.timeIndicator.setFrameByRatio(this.war3MapViewer.simulation.getGameTimeOfDay()
|
this.timeIndicator.setFrameByRatio(this.war3MapViewer.simulation.getGameTimeOfDay()
|
||||||
/ this.war3MapViewer.simulation.getGameplayConstants().getGameDayHours());
|
/ this.war3MapViewer.simulation.getGameplayConstants().getGameDayHours());
|
||||||
|
|
||||||
|
if (this.clickUI != null) {
|
||||||
|
batch.end();
|
||||||
|
this.shapeRenderer.setProjectionMatrix(this.uiViewport.getCamera().combined);
|
||||||
|
this.shapeRenderer.begin(ShapeType.Line);
|
||||||
|
this.shapeRenderer.rect(this.clickUI.getFramePointX(FramePoint.LEFT),
|
||||||
|
this.clickUI.getFramePointY(FramePoint.BOTTOM),
|
||||||
|
this.clickUI.getFramePointX(FramePoint.RIGHT) - this.clickUI.getFramePointX(FramePoint.LEFT),
|
||||||
|
this.clickUI.getFramePointY(FramePoint.TOP) - this.clickUI.getFramePointY(FramePoint.BOTTOM));
|
||||||
|
this.shapeRenderer.end();
|
||||||
|
batch.begin();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void portraitTalk() {
|
public void portraitTalk() {
|
||||||
@ -477,8 +504,9 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
public boolean call(final CUnit unit) {
|
public boolean call(final CUnit unit) {
|
||||||
final BooleanAbilityTargetCheckReceiver<CWidget> targetReceiver = BooleanAbilityTargetCheckReceiver
|
final BooleanAbilityTargetCheckReceiver<CWidget> targetReceiver = BooleanAbilityTargetCheckReceiver
|
||||||
.<CWidget>getInstance();
|
.<CWidget>getInstance();
|
||||||
MeleeUI.this.activeCommand.checkCanTarget(MeleeUI.this.war3MapViewer.simulation, unit,
|
MeleeUI.this.activeCommand.checkCanTarget(MeleeUI.this.war3MapViewer.simulation,
|
||||||
MeleeUI.this.activeCommandOrderId, unit, targetReceiver);
|
MeleeUI.this.activeCommandUnit.getSimulationUnit(), MeleeUI.this.activeCommandOrderId, unit,
|
||||||
|
targetReceiver);
|
||||||
return targetReceiver.isTargetable();
|
return targetReceiver.isTargetable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,11 +569,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
this.portrait.setSelectedUnit(unit);
|
this.portrait.setSelectedUnit(unit);
|
||||||
this.selectedUnit = unit;
|
this.selectedUnit = unit;
|
||||||
for (int j = 0; j < COMMAND_CARD_HEIGHT; j++) {
|
clearCommandCard();
|
||||||
for (int i = 0; i < COMMAND_CARD_WIDTH; i++) {
|
|
||||||
this.commandCard[j][i].setCommandButton(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unit == null) {
|
if (unit == null) {
|
||||||
this.simpleNameValue.setText("");
|
this.simpleNameValue.setText("");
|
||||||
this.unitLifeText.setText("");
|
this.unitLifeText.setText("");
|
||||||
@ -633,16 +657,24 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
localArmorIconBackdrop.setTexture(defenseTexture);
|
localArmorIconBackdrop.setTexture(defenseTexture);
|
||||||
localArmorInfoPanelIconValue.setText(Integer.toString(unit.getSimulationUnit().getDefense()));
|
localArmorInfoPanelIconValue.setText(Integer.toString(unit.getSimulationUnit().getDefense()));
|
||||||
unit.populateCommandCard(this, this.war3MapViewer.getAbilityDataUI());
|
unit.populateCommandCard(this.war3MapViewer.simulation, this, this.war3MapViewer.getAbilityDataUI());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearCommandCard() {
|
||||||
|
for (int j = 0; j < COMMAND_CARD_HEIGHT; j++) {
|
||||||
|
for (int i = 0; i < COMMAND_CARD_WIDTH; i++) {
|
||||||
|
this.commandCard[j][i].setCommandButton(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commandButton(final int buttonPositionX, final int buttonPositionY, final Texture icon,
|
public void commandButton(final int buttonPositionX, final int buttonPositionY, final Texture icon,
|
||||||
final int abilityHandleId, final int orderId) {
|
final int abilityHandleId, final int orderId, final boolean active) {
|
||||||
final int x = Math.max(0, Math.min(COMMAND_CARD_WIDTH - 1, buttonPositionX));
|
final int x = Math.max(0, Math.min(COMMAND_CARD_WIDTH - 1, buttonPositionX));
|
||||||
final int y = Math.max(0, Math.min(COMMAND_CARD_HEIGHT - 1, buttonPositionY));
|
final int y = Math.max(0, Math.min(COMMAND_CARD_HEIGHT - 1, buttonPositionY));
|
||||||
this.commandCard[y][x].setCommandButtonData(icon, abilityHandleId, orderId);
|
this.commandCard[y][x].setCommandButtonData(icon, abilityHandleId, orderId, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resize(final Rectangle viewport) {
|
public void resize(final Rectangle viewport) {
|
||||||
@ -732,6 +764,13 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ordersChanged() {
|
||||||
|
clearCommandCard();
|
||||||
|
this.selectedUnit.populateCommandCard(this.war3MapViewer.simulation, this,
|
||||||
|
this.war3MapViewer.getAbilityDataUI());
|
||||||
|
}
|
||||||
|
|
||||||
public RenderUnit getSelectedUnit() {
|
public RenderUnit getSelectedUnit() {
|
||||||
return this.selectedUnit;
|
return this.selectedUnit;
|
||||||
}
|
}
|
||||||
@ -748,6 +787,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
this.cameraManager.scrolled(amount);
|
this.cameraManager.scrolled(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float lastX, lastY;
|
||||||
|
|
||||||
public boolean touchDown(final int screenX, final int screenY, final float worldScreenY, final int button) {
|
public boolean touchDown(final int screenX, final int screenY, final float worldScreenY, final int button) {
|
||||||
screenCoordsVector.set(screenX, screenY);
|
screenCoordsVector.set(screenX, screenY);
|
||||||
this.uiViewport.unproject(screenCoordsVector);
|
this.uiViewport.unproject(screenCoordsVector);
|
||||||
@ -756,6 +797,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
screenCoordsVector.y);
|
screenCoordsVector.y);
|
||||||
this.cameraManager.target.x = worldPoint.x;
|
this.cameraManager.target.x = worldPoint.x;
|
||||||
this.cameraManager.target.y = worldPoint.y;
|
this.cameraManager.target.y = worldPoint.y;
|
||||||
|
this.lastX = screenCoordsVector.x;
|
||||||
|
this.lastY = screenCoordsVector.y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
final UIFrame clickedUIFrame = this.rootFrame.touchDown(screenCoordsVector.x, screenCoordsVector.y, button);
|
final UIFrame clickedUIFrame = this.rootFrame.touchDown(screenCoordsVector.x, screenCoordsVector.y, button);
|
||||||
@ -790,6 +833,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.war3MapViewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
|
this.war3MapViewer.getClickLocation(clickLocationTemp, screenX, (int) worldScreenY);
|
||||||
|
clickLocationTemp2.set(clickLocationTemp.x, clickLocationTemp.y);
|
||||||
|
|
||||||
this.activeCommand.checkCanTarget(this.war3MapViewer.simulation,
|
this.activeCommand.checkCanTarget(this.war3MapViewer.simulation,
|
||||||
this.activeCommandUnit.getSimulationUnit(), this.activeCommandOrderId,
|
this.activeCommandUnit.getSimulationUnit(), this.activeCommandOrderId,
|
||||||
clickLocationTemp2, PointAbilityTargetCheckReceiver.INSTANCE);
|
clickLocationTemp2, PointAbilityTargetCheckReceiver.INSTANCE);
|
||||||
@ -822,10 +867,9 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (button == Input.Buttons.RIGHT) {
|
if (button == Input.Buttons.RIGHT) {
|
||||||
final RenderUnit rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY);
|
|
||||||
if (getSelectedUnit() != null) {
|
if (getSelectedUnit() != null) {
|
||||||
if ((rayPickUnit != null) && (rayPickUnit.playerIndex != getSelectedUnit().playerIndex)
|
final RenderUnit rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY);
|
||||||
&& !rayPickUnit.getSimulationUnit().isDead()) {
|
if ((rayPickUnit != null) && !rayPickUnit.getSimulationUnit().isDead()) {
|
||||||
boolean ordered = false;
|
boolean ordered = false;
|
||||||
for (final RenderUnit unit : this.war3MapViewer.selected) {
|
for (final RenderUnit unit : this.war3MapViewer.selected) {
|
||||||
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
|
for (final CAbility ability : unit.getSimulationUnit().getAbilities()) {
|
||||||
@ -929,10 +973,34 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.clickUI = clickedUIFrame;
|
||||||
|
this.lastX = screenCoordsVector.x;
|
||||||
|
this.lastY = screenCoordsVector.y;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isShiftDown() {
|
private static boolean isShiftDown() {
|
||||||
return Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT);
|
return Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Input.Keys.SHIFT_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean touchDragged(final int screenX, final int screenY, final float worldScreenY, final int pointer) {
|
||||||
|
screenCoordsVector.set(screenX, screenY);
|
||||||
|
this.uiViewport.unproject(screenCoordsVector);
|
||||||
|
final float dx = screenCoordsVector.x - this.lastX;
|
||||||
|
final float dy = screenCoordsVector.y - this.lastY;
|
||||||
|
|
||||||
|
if (this.meleeUIMinimap.containsMouse(screenCoordsVector.x, screenCoordsVector.y)) {
|
||||||
|
this.meleeUIMinimap.touchDragged(screenX, screenY, worldScreenY, pointer, dx, dy);
|
||||||
|
}
|
||||||
|
else if (this.clickUI != null) {
|
||||||
|
this.clickUI.setFramePointX(FramePoint.LEFT, this.clickUI.getFramePointX(FramePoint.LEFT) + dx);
|
||||||
|
this.clickUI.setFramePointY(FramePoint.BOTTOM, this.clickUI.getFramePointY(FramePoint.BOTTOM) + dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastX = screenCoordsVector.x;
|
||||||
|
this.lastY = screenCoordsVector.y;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,4 +59,12 @@ public class MeleeUIMinimap {
|
|||||||
public boolean containsMouse(final float x, final float y) {
|
public boolean containsMouse(final float x, final float y) {
|
||||||
return this.minimapFilledArea.contains(x, y);
|
return this.minimapFilledArea.contains(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void touchDragged(final int screenX, final int screenY, final float worldScreenY, final int pointer,
|
||||||
|
final float dx, final float dy) {
|
||||||
|
this.minimapFilledArea.x += dx;
|
||||||
|
this.minimapFilledArea.y += dy;
|
||||||
|
this.minimap.x += dx;
|
||||||
|
this.minimap.y += dy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import com.etheller.warsmash.viewer5.gl.SoundLengthExtension;
|
|||||||
import com.etheller.warsmash.viewer5.gl.WireframeExtension;
|
import com.etheller.warsmash.viewer5.gl.WireframeExtension;
|
||||||
|
|
||||||
public class DesktopLauncher {
|
public class DesktopLauncher {
|
||||||
public static void main(final String[] arg) {
|
public static void main(String[] arg) {
|
||||||
Extensions.angleInstancedArrays = new ANGLEInstancedArrays() {
|
Extensions.angleInstancedArrays = new ANGLEInstancedArrays() {
|
||||||
@Override
|
@Override
|
||||||
public void glVertexAttribDivisorANGLE(final int index, final int divisor) {
|
public void glVertexAttribDivisorANGLE(final int index, final int divisor) {
|
||||||
@ -83,10 +83,11 @@ public class DesktopLauncher {
|
|||||||
config.useGL30 = true;
|
config.useGL30 = true;
|
||||||
config.gles30ContextMajorVersion = 3;
|
config.gles30ContextMajorVersion = 3;
|
||||||
config.gles30ContextMinorVersion = 3;
|
config.gles30ContextMinorVersion = 3;
|
||||||
config.samples = 16;
|
//config.samples = 16;
|
||||||
// config.vSyncEnabled = false;
|
// config.vSyncEnabled = false;
|
||||||
// config.foregroundFPS = 0;
|
// config.foregroundFPS = 0;
|
||||||
// config.backgroundFPS = 0;
|
// config.backgroundFPS = 0;
|
||||||
|
arg = new String[]{"-windowed"};
|
||||||
if ((arg.length > 0) && "-windowed".equals(arg[0])) {
|
if ((arg.length > 0) && "-windowed".equals(arg[0])) {
|
||||||
config.fullscreen = false;
|
config.fullscreen = false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user