mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Update campaign menu behaviors and make some progress on untested common j apis
This commit is contained in:
parent
b5ab73fb47
commit
f1bcb4ae54
@ -53,7 +53,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
|
||||
|
||||
public class WarsmashGdxMapScreen implements InputProcessor, Screen {
|
||||
public static final boolean ENABLE_AUDIO = true;
|
||||
private static final boolean ENABLE_MUSIC = true;
|
||||
private static final boolean ENABLE_MUSIC = false;
|
||||
private final War3MapViewer viewer;
|
||||
private final Rectangle tempRect = new Rectangle();
|
||||
|
||||
|
@ -52,7 +52,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI;
|
||||
|
||||
public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleModelScreen {
|
||||
private static final boolean ENABLE_AUDIO = true;
|
||||
private static final boolean ENABLE_MUSIC = true;
|
||||
private static final boolean ENABLE_MUSIC = false;
|
||||
private DataSource codebase;
|
||||
private MdxViewer viewer;
|
||||
private MdxModel model;
|
||||
|
@ -294,7 +294,8 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
this.fontParam.size = 128;
|
||||
}
|
||||
final BitmapFont frameFont = this.fontGenerator.generateFont(this.fontParam);
|
||||
final StringFrame stringFrame = new StringFrame(name, parent, color, justifyH, justifyV, frameFont, name);
|
||||
final StringFrame stringFrame = new StringFrame(name, parent, color, justifyH, justifyV, frameFont, name, null,
|
||||
null);
|
||||
this.nameToFrame.put(name, stringFrame);
|
||||
add(stringFrame);
|
||||
return stringFrame;
|
||||
@ -400,6 +401,28 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
fontColorDefinition.getZ(), fontColorDefinition.getW());
|
||||
}
|
||||
|
||||
Color fontHighlightColor;
|
||||
final Vector4Definition fontHighlightColorDefinition = frameDefinition.getVector4("FontHighlightColor");
|
||||
if (fontHighlightColorDefinition == null) {
|
||||
fontHighlightColor = null;
|
||||
}
|
||||
else {
|
||||
fontHighlightColor = new Color(fontHighlightColorDefinition.getX(),
|
||||
fontHighlightColorDefinition.getY(), fontHighlightColorDefinition.getZ(),
|
||||
fontHighlightColorDefinition.getW());
|
||||
}
|
||||
|
||||
Color fontDisabledColor;
|
||||
final Vector4Definition fontDisabledColorDefinition = frameDefinition.getVector4("FontDisabledColor");
|
||||
if (fontDisabledColorDefinition == null) {
|
||||
fontDisabledColor = null;
|
||||
}
|
||||
else {
|
||||
fontDisabledColor = new Color(fontDisabledColorDefinition.getX(),
|
||||
fontDisabledColorDefinition.getY(), fontDisabledColorDefinition.getZ(),
|
||||
fontDisabledColorDefinition.getW());
|
||||
}
|
||||
|
||||
Color fontShadowColor;
|
||||
final Vector4Definition fontShadowColorDefinition = frameDefinition.getVector4("FontShadowColor");
|
||||
if (fontShadowColorDefinition == null) {
|
||||
@ -428,7 +451,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
textString = text;
|
||||
}
|
||||
final StringFrame stringFrame = new StringFrame(frameDefinition.getName(), parent, fontColor, justifyH,
|
||||
justifyV, frameFont, textString);
|
||||
justifyV, frameFont, textString, fontHighlightColor, fontDisabledColor);
|
||||
if (fontShadowColor != null) {
|
||||
final Vector2Definition shadowOffset = frameDefinition.getVector2("FontShadowOffset");
|
||||
stringFrame.setFontShadowColor(fontShadowColor);
|
||||
@ -850,7 +873,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
textString = text;
|
||||
}
|
||||
final StringFrame stringFrame = new StringFrame(frameDefinition.getName(), parent, fontColor, justifyH,
|
||||
justifyV, frameFont, textString);
|
||||
justifyV, frameFont, textString, null, null);
|
||||
inflatedFrame = stringFrame;
|
||||
break;
|
||||
case Texture:
|
||||
|
@ -23,7 +23,7 @@ public abstract class AbstractRenderableFrame implements UIFrame {
|
||||
private static final FramePoint[] TOP_ANCHOR_PRIORITY = { FramePoint.TOP, FramePoint.TOPLEFT, FramePoint.TOPRIGHT };
|
||||
private static final FramePoint[] BOTTOM_ANCHOR_PRIORITY = { FramePoint.BOTTOM, FramePoint.BOTTOMLEFT,
|
||||
FramePoint.BOTTOMRIGHT };
|
||||
private static final boolean DEBUG_LOG = true;
|
||||
private static final boolean DEBUG_LOG = false;
|
||||
protected String name;
|
||||
protected UIFrame parent;
|
||||
protected boolean visible = true;
|
||||
|
@ -54,6 +54,10 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setHighlightOnMouseOver(final boolean highlightOnMouseOver) {
|
||||
this.highlightOnMouseOver = highlightOnMouseOver;
|
||||
}
|
||||
@ -112,12 +116,20 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
if (this.highlightOnMouseOver) {
|
||||
this.mouseOver = true;
|
||||
onMouseEnter();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onMouseEnter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
this.mouseOver = false;
|
||||
onMouseExit();
|
||||
}
|
||||
|
||||
protected void onMouseExit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.etheller.warsmash.parsers.fdf.frames;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
@ -32,4 +33,45 @@ public class GlueTextButtonFrame extends GlueButtonFrame {
|
||||
this.buttonText.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(final boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
if (this.buttonText instanceof StringFrame) {
|
||||
final StringFrame stringButtonText = (StringFrame) this.buttonText;
|
||||
final Color fontColor = enabled ? stringButtonText.getFontOriginalColor()
|
||||
: stringButtonText.getFontDisabledColor();
|
||||
if (fontColor != null) {
|
||||
stringButtonText.setColor(fontColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMouseEnter() {
|
||||
super.onMouseEnter();
|
||||
if (isEnabled()) {
|
||||
if (this.buttonText instanceof StringFrame) {
|
||||
final StringFrame stringFrame = (StringFrame) this.buttonText;
|
||||
final Color fontHighlightColor = stringFrame.getFontHighlightColor();
|
||||
if (fontHighlightColor != null) {
|
||||
stringFrame.setColor(fontHighlightColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMouseExit() {
|
||||
super.onMouseExit();
|
||||
if (isEnabled()) {
|
||||
if (this.buttonText instanceof StringFrame) {
|
||||
final StringFrame stringFrame = (StringFrame) this.buttonText;
|
||||
final Color fontOriginalColor = stringFrame.getFontOriginalColor();
|
||||
if (fontOriginalColor != null) {
|
||||
stringFrame.setColor(fontOriginalColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ public class SingleStringFrame extends AbstractRenderableFrame {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public void setFontShadowColor(final Color fontShadowColor) {
|
||||
this.fontShadowColor = fontShadowColor;
|
||||
}
|
||||
|
@ -30,15 +30,22 @@ public class StringFrame extends AbstractRenderableFrame {
|
||||
private float predictedViewportHeight;
|
||||
|
||||
static ShapeRenderer shapeRenderer = new ShapeRenderer();
|
||||
private final Color fontHighlightColor;
|
||||
private final Color fontDisabledColor;
|
||||
private final Color fontColor;
|
||||
|
||||
public StringFrame(final String name, final UIFrame parent, final Color color, final TextJustify justifyH,
|
||||
final TextJustify justifyV, final BitmapFont frameFont, final String text) {
|
||||
final TextJustify justifyV, final BitmapFont frameFont, final String text, final Color fontHighlightColor,
|
||||
final Color fontDisabledColor) {
|
||||
super(name, parent);
|
||||
this.fontColor = color;
|
||||
this.color = color;
|
||||
this.justifyH = justifyH;
|
||||
this.justifyV = justifyV;
|
||||
this.frameFont = frameFont;
|
||||
this.text = text;
|
||||
this.fontHighlightColor = fontHighlightColor;
|
||||
this.fontDisabledColor = fontDisabledColor;
|
||||
this.internalFramesContainer = new SimpleFrame(null, this);
|
||||
}
|
||||
|
||||
@ -55,16 +62,30 @@ public class StringFrame extends AbstractRenderableFrame {
|
||||
}
|
||||
|
||||
public void setColor(final Color color) {
|
||||
this.color = color;
|
||||
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||
if (internalFrame.getColor() == this.color) {
|
||||
internalFrame.setColor(color);
|
||||
}
|
||||
}
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public Color getFontOriginalColor() {
|
||||
return this.fontColor;
|
||||
}
|
||||
|
||||
public Color getFontDisabledColor() {
|
||||
return this.fontDisabledColor;
|
||||
}
|
||||
|
||||
public Color getFontHighlightColor() {
|
||||
return this.fontHighlightColor;
|
||||
}
|
||||
|
||||
public void setFontShadowColor(final Color fontShadowColor) {
|
||||
this.fontShadowColor = fontShadowColor;
|
||||
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
||||
package com.etheller.warsmash.parsers.jass.scope;
|
||||
|
||||
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
|
||||
|
||||
public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
private final CUnit triggeringUnit;
|
||||
private final CUnit filterUnit;
|
||||
private final CUnit enumUnit;
|
||||
private final CPlayerJass filterPlayer;
|
||||
private final CPlayerJass enumPlayer;
|
||||
|
||||
public CommonTriggerExecutionScope(final TriggerExecutionScope parentScope, final CUnit triggeringUnit,
|
||||
final CUnit filterUnit, final CUnit enumUnit, final CPlayerJass filterPlayer,
|
||||
final CPlayerJass enumPlayer) {
|
||||
super(parentScope.getTriggeringTrigger());
|
||||
this.triggeringUnit = triggeringUnit;
|
||||
this.filterUnit = filterUnit;
|
||||
this.enumUnit = enumUnit;
|
||||
this.filterPlayer = filterPlayer;
|
||||
this.enumPlayer = enumPlayer;
|
||||
}
|
||||
|
||||
public CUnit getEnumUnit() {
|
||||
return this.enumUnit;
|
||||
}
|
||||
|
||||
public CUnit getTriggeringUnit() {
|
||||
return this.triggeringUnit;
|
||||
}
|
||||
|
||||
public CUnit getFilterUnit() {
|
||||
return this.filterUnit;
|
||||
}
|
||||
|
||||
public CPlayerJass getFilterPlayer() {
|
||||
return this.filterPlayer;
|
||||
}
|
||||
|
||||
public CPlayerJass getEnumPlayer() {
|
||||
return this.enumPlayer;
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
|
||||
final CUnit filterUnit) {
|
||||
return new CommonTriggerExecutionScope(parentScope, null, filterUnit, null, null, null);
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CUnit enumUnit) {
|
||||
return new CommonTriggerExecutionScope(parentScope, null, null, enumUnit, null, null);
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
|
||||
final CPlayerJass filterPlayer) {
|
||||
return new CommonTriggerExecutionScope(parentScope, null, null, null, filterPlayer, null);
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope,
|
||||
final CPlayerJass enumPlayer) {
|
||||
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, enumPlayer);
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,8 @@ public class Quadtree<T> {
|
||||
}
|
||||
|
||||
public void add(final T object, final Rectangle bounds) {
|
||||
add(new Node<T>(object, bounds), 0);
|
||||
final Node<T> node = new Node<T>(object, bounds);
|
||||
add(node, 0);
|
||||
}
|
||||
|
||||
public void remove(final T object, final Rectangle bounds) {
|
||||
|
@ -6,7 +6,7 @@ public class WarsmashConstants {
|
||||
* With version, we use 0 for RoC, 1 for TFT emulation, and probably 2+ or
|
||||
* whatever for custom mods and other stuff
|
||||
*/
|
||||
public static int GAME_VERSION = 0;
|
||||
public static int GAME_VERSION = 1;
|
||||
public static final int REPLACEABLE_TEXTURE_LIMIT = 64;
|
||||
public static final float SIMULATION_STEP_TIME = 1 / 20f;
|
||||
public static final int PORT_NUMBER = 6115;
|
||||
|
@ -97,7 +97,7 @@ public class BatchGroup extends GenericGroup {
|
||||
final float[] geosetColor = instance.geosetColors[geosetIndex];
|
||||
final float layerAlpha = instance.layerAlphas[layerIndex];
|
||||
|
||||
if ((geosetColor[3] > 0) && (layerAlpha > 0)) {
|
||||
if ((geosetColor[3] > 0.01) && (layerAlpha > 0.01)) {
|
||||
// BELOW: I updated it to "Math.max(0," because MDL and MDX parser for PRSCMOD
|
||||
// menu screen behaved differently,
|
||||
// the MDL case was getting "no data" for default value when unanimated, and "no
|
||||
|
@ -167,7 +167,7 @@ public final class SdSequence<TYPE> {
|
||||
}
|
||||
|
||||
public int getValue(final TYPE out, final long frame) {
|
||||
final int l = this.frames.length;
|
||||
final int length = this.frames.length;
|
||||
|
||||
if (this.constant || (frame < this.start)) {
|
||||
this.sd.copy(out, this.values[0]);
|
||||
@ -175,34 +175,34 @@ public final class SdSequence<TYPE> {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
int startFrame = -1;
|
||||
int endFrame = -1;
|
||||
final int l1 = l - 1;
|
||||
if ((frame < this.frames[0]) || (frame >= this.frames[l1])) {
|
||||
startFrame = l1;
|
||||
endFrame = 0;
|
||||
int startFrameIndex = -1;
|
||||
int endFrameIndex = -1;
|
||||
final int lengthLessOne = length - 1;
|
||||
if ((frame < this.frames[0]) || (frame >= this.frames[lengthLessOne])) {
|
||||
startFrameIndex = lengthLessOne;
|
||||
endFrameIndex = 0;
|
||||
}
|
||||
else {
|
||||
for (int i = 1; i < l; i++) {
|
||||
for (int i = 1; i < length; i++) {
|
||||
if (this.frames[i] > frame) {
|
||||
startFrame = i - 1;
|
||||
endFrame = i;
|
||||
startFrameIndex = i - 1;
|
||||
endFrameIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
long start = this.frames[startFrame];
|
||||
final long end = this.frames[endFrame];
|
||||
long timeBetweenFrames = end - start;
|
||||
long startFrame = this.frames[startFrameIndex];
|
||||
final long endFrame = this.frames[endFrameIndex];
|
||||
long timeBetweenFrames = endFrame - startFrame;
|
||||
if (timeBetweenFrames < 0) {
|
||||
timeBetweenFrames += (this.end - this.start);
|
||||
if (frame < start) {
|
||||
start = end;
|
||||
if (frame < startFrame) {
|
||||
startFrame = endFrame;
|
||||
}
|
||||
}
|
||||
final float t = ((timeBetweenFrames) == 0 ? 0 : ((frame - start) / (float) (timeBetweenFrames)));
|
||||
this.sd.interpolate(out, this.values, this.inTans, this.outTans, startFrame, endFrame, t);
|
||||
return startFrame;
|
||||
final float t = ((timeBetweenFrames) == 0 ? 0 : ((frame - startFrame) / (float) (timeBetweenFrames)));
|
||||
this.sd.interpolate(out, this.values, this.inTans, this.outTans, startFrameIndex, endFrameIndex, t);
|
||||
return startFrameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -939,11 +939,10 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
final RenderDestructable renderDestructable = new RenderDestructable(this, model, row, doodad, type,
|
||||
maxPitch, maxRoll, doodad.getLife(), destructableShadow, simulationDestructable);
|
||||
if (row.readSLKTagBoolean("walkable")) {
|
||||
final float angle = doodad.getAngle();
|
||||
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());
|
||||
final Rectangle renderDestructableBounds = getRotatedBoundingBox(x, y, angle, boundingBox);
|
||||
System.out.println("ROTATED BOUNDS TO: " + renderDestructableBounds);
|
||||
this.walkableObjectsTree.add((MdxComplexInstance) renderDestructable.instance,
|
||||
renderDestructableBounds);
|
||||
renderDestructable.walkableBounds = renderDestructableBounds;
|
||||
@ -1020,6 +1019,39 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
this.anyReady = true;
|
||||
}
|
||||
|
||||
private Rectangle getRotatedBoundingBox(final float x, final float y, final float angle,
|
||||
final BoundingBox boundingBox) {
|
||||
final float x1 = boundingBox.min.x;
|
||||
final float y1 = boundingBox.min.y;
|
||||
final float x2 = boundingBox.min.x + boundingBox.getWidth();
|
||||
final float y2 = boundingBox.min.y;
|
||||
final float x3 = boundingBox.min.x + boundingBox.getWidth();
|
||||
final float y3 = boundingBox.min.y + boundingBox.getHeight();
|
||||
final float x4 = boundingBox.min.x;
|
||||
final float y4 = boundingBox.min.y + boundingBox.getHeight();
|
||||
final float angle1 = (float) StrictMath.atan2(y1, x1) + angle;
|
||||
final float len1 = (float) StrictMath.sqrt((x1 * x1) + (y1 * y1));
|
||||
final float angle2 = (float) StrictMath.atan2(y2, x2) + angle;
|
||||
final float len2 = (float) StrictMath.sqrt((x2 * x2) + (y2 * y2));
|
||||
final float angle3 = (float) StrictMath.atan2(y3, x3) + angle;
|
||||
final float len3 = (float) StrictMath.sqrt((x3 * x3) + (y3 * y3));
|
||||
final float angle4 = (float) StrictMath.atan2(y4, x4) + angle;
|
||||
final float len4 = (float) StrictMath.sqrt((x4 * x4) + (y4 * y4));
|
||||
final double x1prime = StrictMath.cos(angle1) * len1;
|
||||
final double x2prime = StrictMath.cos(angle2) * len2;
|
||||
final double x3prime = StrictMath.cos(angle3) * len3;
|
||||
final double x4prime = StrictMath.cos(angle4) * len4;
|
||||
final double y1prime = StrictMath.sin(angle1) * len1;
|
||||
final double y2prime = StrictMath.sin(angle2) * len2;
|
||||
final double y3prime = StrictMath.sin(angle3) * len3;
|
||||
final double y4prime = StrictMath.sin(angle4) * len4;
|
||||
final float minX = (float) StrictMath.min(StrictMath.min(x1prime, x2prime), StrictMath.min(x3prime, x4prime));
|
||||
final float minY = (float) StrictMath.min(StrictMath.min(y1prime, y2prime), StrictMath.min(y3prime, y4prime));
|
||||
final float maxX = (float) StrictMath.max(StrictMath.max(x1prime, x2prime), StrictMath.max(x3prime, x4prime));
|
||||
final float maxY = (float) StrictMath.max(StrictMath.max(y1prime, y2prime), StrictMath.max(y3prime, y4prime));
|
||||
return new Rectangle(x + minX, y + minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
|
||||
private void applyModificationFile(final MappedData doodadsData2, final MappedData doodadMetaData2,
|
||||
final MutableObjectData destructibles, final WorldEditorDataType dataType) {
|
||||
// TODO condense ported MappedData from Ghostwolf and MutableObjectData from
|
||||
@ -1732,6 +1764,16 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
return mdxPath;
|
||||
}
|
||||
|
||||
public static String mdl(String mdxPath) {
|
||||
if (mdxPath.toLowerCase().endsWith(".mdx")) {
|
||||
mdxPath = mdxPath.substring(0, mdxPath.length() - 4);
|
||||
}
|
||||
if (!mdxPath.toLowerCase().endsWith(".mdl")) {
|
||||
mdxPath += ".mdl";
|
||||
}
|
||||
return mdxPath;
|
||||
}
|
||||
|
||||
public String blp(String iconPath) {
|
||||
final int lastDotIndex = iconPath.lastIndexOf('.');
|
||||
if (lastDotIndex != -1) {
|
||||
|
@ -37,6 +37,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindin
|
||||
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.CRace;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionManager;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
|
||||
@ -70,6 +71,7 @@ public class CSimulation implements CPlayerAPI {
|
||||
private final Map<Integer, CAbility> handleIdToAbility = new HashMap<>();
|
||||
private final LinkedList<CTimer> activeTimers = new LinkedList<>();
|
||||
private transient CommandErrorListener commandErrorListener;
|
||||
private final CRegionManager regionManager;
|
||||
|
||||
public CSimulation(final War3MapConfig config, final DataTable miscData, final MutableObjectData parsedUnitData,
|
||||
final MutableObjectData parsedItemData, final MutableObjectData parsedDestructableData,
|
||||
@ -92,6 +94,7 @@ public class CSimulation implements CPlayerAPI {
|
||||
this.newProjectiles = new ArrayList<>();
|
||||
this.handleIdAllocator = new HandleIdAllocator();
|
||||
this.worldCollision = new CWorldCollision(entireMapBounds, this.gameplayConstants.getMaxCollisionRadius());
|
||||
this.regionManager = new CRegionManager(entireMapBounds, pathingGrid);
|
||||
this.pathfindingProcessors = new CPathfindingProcessor[WarsmashConstants.MAX_PLAYERS];
|
||||
this.playerHeroes = new ArrayList[WarsmashConstants.MAX_PLAYERS];
|
||||
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
|
||||
@ -293,6 +296,10 @@ public class CSimulation implements CPlayerAPI {
|
||||
return this.worldCollision;
|
||||
}
|
||||
|
||||
public CRegionManager getRegionManager() {
|
||||
return this.regionManager;
|
||||
}
|
||||
|
||||
public CGameplayConstants getGameplayConstants() {
|
||||
return this.gameplayConstants;
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
@ -37,15 +39,21 @@ 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.attacks.CUnitAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrder;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderNoTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderTargetPoint;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.COrderTargetWidget;
|
||||
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.CPlayer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegion;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionEnumFunction;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionManager;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver;
|
||||
|
||||
public class CUnit extends CWidget {
|
||||
private static RegionCheckerImpl regionCheckerImpl = new RegionCheckerImpl();
|
||||
|
||||
private War3ID typeId;
|
||||
private float facing; // degrees
|
||||
private float mana;
|
||||
@ -111,6 +119,8 @@ public class CUnit extends CWidget {
|
||||
private int foodUsed;
|
||||
|
||||
private List<CUnitAttack> unitSpecificAttacks;
|
||||
private transient Set<CRegion> containingRegions = new LinkedHashSet<>();
|
||||
private transient Set<CRegion> priorContainingRegions = new LinkedHashSet<>();
|
||||
|
||||
public CUnit(final int handleId, final int playerIndex, final float x, final float y, final float life,
|
||||
final War3ID typeId, final float facing, final float mana, final int maximumLife, final int maximumMana,
|
||||
@ -474,6 +484,74 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean order(final CSimulation simulation, final int orderId, final AbilityTarget target) {
|
||||
if (orderId == OrderIds.stop) {
|
||||
order(simulation, new COrderNoTarget(0, orderId, false), false);
|
||||
return true;
|
||||
}
|
||||
for (final CAbility ability : this.abilities) {
|
||||
final BooleanAbilityActivationReceiver activationReceiver = BooleanAbilityActivationReceiver.INSTANCE;
|
||||
ability.checkCanUse(simulation, this, orderId, activationReceiver);
|
||||
if (activationReceiver.isOk()) {
|
||||
if (target == null) {
|
||||
final BooleanAbilityTargetCheckReceiver<Void> booleanTargetReceiver = BooleanAbilityTargetCheckReceiver
|
||||
.<Void>getInstance().reset();
|
||||
ability.checkCanTargetNoTarget(simulation, this, orderId, booleanTargetReceiver);
|
||||
if (booleanTargetReceiver.isTargetable()) {
|
||||
order(simulation, new COrderNoTarget(ability.getHandleId(), orderId, false), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final boolean targetable = target.visit(new AbilityTargetVisitor<Boolean>() {
|
||||
@Override
|
||||
public Boolean accept(final AbilityPointTarget target) {
|
||||
final BooleanAbilityTargetCheckReceiver<AbilityPointTarget> booleanTargetReceiver = BooleanAbilityTargetCheckReceiver
|
||||
.<AbilityPointTarget>getInstance().reset();
|
||||
ability.checkCanTarget(simulation, CUnit.this, orderId, target, booleanTargetReceiver);
|
||||
final boolean pointTargetable = booleanTargetReceiver.isTargetable();
|
||||
if (pointTargetable) {
|
||||
order(simulation, new COrderTargetPoint(ability.getHandleId(), orderId, target, false),
|
||||
false);
|
||||
}
|
||||
return pointTargetable;
|
||||
}
|
||||
|
||||
public Boolean acceptWidget(final CWidget target) {
|
||||
final BooleanAbilityTargetCheckReceiver<CWidget> booleanTargetReceiver = BooleanAbilityTargetCheckReceiver
|
||||
.<CWidget>getInstance().reset();
|
||||
ability.checkCanTarget(simulation, CUnit.this, orderId, target, booleanTargetReceiver);
|
||||
final boolean widgetTargetable = booleanTargetReceiver.isTargetable();
|
||||
if (widgetTargetable) {
|
||||
order(simulation,
|
||||
new COrderTargetWidget(ability.getHandleId(), orderId, target.getHandleId(), false),
|
||||
false);
|
||||
}
|
||||
return widgetTargetable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean accept(final CUnit target) {
|
||||
return acceptWidget(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean accept(final CDestructable target) {
|
||||
return acceptWidget(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean accept(final CItem target) {
|
||||
return acceptWidget(target);
|
||||
}
|
||||
});
|
||||
if (targetable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private CBehavior beginOrder(final CSimulation game, final COrder order) {
|
||||
this.lastStartedOrder = order;
|
||||
CBehavior nextBehavior;
|
||||
@ -550,20 +628,22 @@ public class CUnit extends CWidget {
|
||||
return this.collisionRectangle;
|
||||
}
|
||||
|
||||
public void setX(final float newX, final CWorldCollision collision) {
|
||||
public void setX(final float newX, final CWorldCollision collision, final CRegionManager regionManager) {
|
||||
final float prevX = getX();
|
||||
if (!this.unitType.isBuilding()) {
|
||||
setX(newX);
|
||||
collision.translate(this, newX - prevX, 0);
|
||||
}
|
||||
checkRegionEvents(regionManager);
|
||||
}
|
||||
|
||||
public void setY(final float newY, final CWorldCollision collision) {
|
||||
public void setY(final float newY, final CWorldCollision collision, final CRegionManager regionManager) {
|
||||
final float prevY = getY();
|
||||
if (!this.unitType.isBuilding()) {
|
||||
setY(newY);
|
||||
collision.translate(this, 0, newY - prevY);
|
||||
}
|
||||
checkRegionEvents(regionManager);
|
||||
}
|
||||
|
||||
public void setPointAndCheckUnstuck(final float newX, final float newY, final CSimulation game) {
|
||||
@ -602,11 +682,12 @@ public class CUnit extends CWidget {
|
||||
checkX -= (int) Math.cos(angle);
|
||||
checkY -= (int) Math.sin(angle);
|
||||
}
|
||||
setPoint(outputX, outputY, collision);
|
||||
setPoint(outputX, outputY, collision, game.getRegionManager());
|
||||
game.unitRepositioned(this);
|
||||
}
|
||||
|
||||
public void setPoint(final float newX, final float newY, final CWorldCollision collision) {
|
||||
public void setPoint(final float newX, final float newY, final CWorldCollision collision,
|
||||
final CRegionManager regionManager) {
|
||||
final float prevX = getX();
|
||||
final float prevY = getY();
|
||||
setX(newX);
|
||||
@ -614,6 +695,29 @@ public class CUnit extends CWidget {
|
||||
if (!this.unitType.isBuilding()) {
|
||||
collision.translate(this, newX - prevX, newY - prevY);
|
||||
}
|
||||
checkRegionEvents(regionManager);
|
||||
}
|
||||
|
||||
private void checkRegionEvents(final CRegionManager regionManager) {
|
||||
final Set<CRegion> temp = this.containingRegions;
|
||||
this.containingRegions = this.priorContainingRegions;
|
||||
this.priorContainingRegions = temp;
|
||||
this.containingRegions.clear();
|
||||
regionManager.checkRegions(this.collisionRectangle == null ? tempRect.set(this.getX(), this.getY(), 0, 0)
|
||||
: this.collisionRectangle, regionCheckerImpl.reset(this));
|
||||
for (final CRegion region : this.priorContainingRegions) {
|
||||
if (!this.containingRegions.contains(region)) {
|
||||
onLeaveRegion(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onEnterRegion(final CRegion region) {
|
||||
|
||||
}
|
||||
|
||||
private void onLeaveRegion(final CRegion region) {
|
||||
|
||||
}
|
||||
|
||||
public EnumSet<CUnitClassification> getClassifications() {
|
||||
@ -1428,4 +1532,28 @@ public class CUnit extends CWidget {
|
||||
game.unitDropItemEvent(this, droppedItem);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInRegion(final CRegion region) {
|
||||
return this.containingRegions.contains(region);
|
||||
}
|
||||
|
||||
private static final class RegionCheckerImpl implements CRegionEnumFunction {
|
||||
private CUnit unit;
|
||||
|
||||
public RegionCheckerImpl reset(final CUnit unit) {
|
||||
this.unit = unit;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean call(final CRegion region) {
|
||||
if (this.unit.containingRegions.add(region)) {
|
||||
if (!this.unit.priorContainingRegions.contains(region)) {
|
||||
this.unit.onEnterRegion(region);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +225,9 @@ public class CWorldCollision {
|
||||
return false;
|
||||
}
|
||||
if (this.done) {
|
||||
// This check is because we may use the intersector for multiple intersect
|
||||
// calls, see "enumUnitsInRect" and how it uses this intersector first on the
|
||||
// ground unit layer, then the flying unit layer, without recycling
|
||||
return true;
|
||||
}
|
||||
if (this.intersectedUnits.add(intersectingObject)) {
|
||||
|
@ -240,7 +240,7 @@ public class CBehaviorMove implements CBehavior {
|
||||
// / 16)
|
||||
// * 16
|
||||
&& !worldCollision.intersectsAnythingOtherThan(tempRect, this.unit, movementType))) {
|
||||
this.unit.setPoint(nextX, nextY, worldCollision);
|
||||
this.unit.setPoint(nextX, nextY, worldCollision, simulation.getRegionManager());
|
||||
if (done) {
|
||||
// if we're making headway along the path then it's OK to start thinking fast
|
||||
// again
|
||||
|
@ -95,7 +95,7 @@ public class CBehaviorUndeadBuild extends CAbstractRangedBehavior {
|
||||
final float delta = (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY));
|
||||
this.unit.setPoint(this.target.getX() + ((deltaX / delta) * unitTypeToCreate.getCollisionSize()),
|
||||
this.target.getY() + ((deltaY / delta) * unitTypeToCreate.getCollisionSize()),
|
||||
simulation.getWorldCollision());
|
||||
simulation.getWorldCollision(), simulation.getRegionManager());
|
||||
simulation.unitRepositioned(this.unit);
|
||||
simulation.unitConstructedEvent(this.unit, constructedStructure);
|
||||
this.doneTick = simulation.getGameTurnTick() + delayAnimationTicks;
|
||||
|
@ -15,6 +15,8 @@ public interface CPlayerJass {
|
||||
|
||||
void setAlliance(int otherPlayerIndex, CAllianceType whichAllianceSetting, boolean value);
|
||||
|
||||
boolean hasAlliance(int otherPlayerIndex, CAllianceType allianceType);
|
||||
|
||||
void setTaxRate(int otherPlayerIndex, CPlayerState whichResource, int rate);
|
||||
|
||||
void setRacePref(CRacePreference whichRacePreference);
|
||||
|
@ -0,0 +1,125 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.region;
|
||||
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
|
||||
public class CRegion {
|
||||
private Rectangle currentBounds;
|
||||
private boolean complexRegion;
|
||||
|
||||
public void addRect(final Rectangle rect, final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
this.currentBounds = new Rectangle(rect);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
else {
|
||||
if (!this.complexRegion) {
|
||||
convertToComplexRegionAndAddRect(rect, regionManager);
|
||||
}
|
||||
else {
|
||||
complexRegionAddRect(rect, regionManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearRect(final Rectangle rect, final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
return;
|
||||
}
|
||||
if (this.complexRegion) {
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
regionManager.removeComplexRegionCells(this, rect);
|
||||
regionManager.computeNewMinimumComplexRegionBounds(this, this.currentBounds);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
else {
|
||||
this.complexRegion = true;
|
||||
regionManager.addComplexRegionCells(this, this.currentBounds);
|
||||
regionManager.removeComplexRegionCells(this, rect);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
return;
|
||||
}
|
||||
if (this.complexRegion) {
|
||||
regionManager.removeComplexRegionCells(this, this.currentBounds);
|
||||
}
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
|
||||
public void addCell(final float x, final float y, final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
this.complexRegion = true;
|
||||
this.currentBounds = new Rectangle(x, y, 0, 0);
|
||||
regionManager.addComplexRegionCell(this, x, y, this.currentBounds);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
else {
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
if (!this.complexRegion) {
|
||||
regionManager.addComplexRegionCells(this, this.currentBounds);
|
||||
this.complexRegion = true;
|
||||
}
|
||||
regionManager.addComplexRegionCell(this, x, y, this.currentBounds);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCell(final float x, final float y, final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
if (!this.complexRegion) {
|
||||
regionManager.addComplexRegionCells(this, this.currentBounds);
|
||||
this.complexRegion = true;
|
||||
}
|
||||
regionManager.clearComplexRegionCell(this, x, y, this.currentBounds);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
}
|
||||
|
||||
private void complexRegionAddRect(final Rectangle rect, final CRegionManager regionManager) {
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
regionManager.addComplexRegionCells(this, rect);
|
||||
this.currentBounds = this.currentBounds.merge(rect);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
|
||||
private void convertToComplexRegionAndAddRect(final Rectangle rect, final CRegionManager regionManager) {
|
||||
regionManager.removeRectForRegion(this, this.currentBounds);
|
||||
this.complexRegion = true;
|
||||
regionManager.addComplexRegionCells(this, this.currentBounds);
|
||||
regionManager.addComplexRegionCells(this, rect);
|
||||
this.currentBounds = this.currentBounds.merge(rect);
|
||||
regionManager.addRectForRegion(this, this.currentBounds);
|
||||
}
|
||||
|
||||
public Rectangle getCurrentBounds() {
|
||||
return this.currentBounds;
|
||||
}
|
||||
|
||||
public void setCurrentBounds(final Rectangle currentBounds) {
|
||||
this.currentBounds = currentBounds;
|
||||
}
|
||||
|
||||
public boolean isComplexRegion() {
|
||||
return this.complexRegion;
|
||||
}
|
||||
|
||||
public void setComplexRegion(final boolean complexRegion) {
|
||||
this.complexRegion = complexRegion;
|
||||
}
|
||||
|
||||
public boolean contains(final float x, final float y, final CRegionManager regionManager) {
|
||||
if (this.currentBounds == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.complexRegion) {
|
||||
return regionManager.isPointInComplexRegion(this, x, y);
|
||||
}
|
||||
return this.currentBounds.contains(x, y);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.region;
|
||||
|
||||
public interface CRegionEnumFunction {
|
||||
/**
|
||||
* Operates on a region, returning true if we should stop execution.
|
||||
*
|
||||
* @param region
|
||||
* @return
|
||||
*/
|
||||
boolean call(CRegion region);
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.region;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.etheller.warsmash.util.Quadtree;
|
||||
import com.etheller.warsmash.util.QuadtreeIntersector;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
|
||||
|
||||
public class CRegionManager {
|
||||
private static Rectangle tempRect = new Rectangle();
|
||||
private final Quadtree<CRegion> regionTree;
|
||||
private final RegionChecker regionChecker = new RegionChecker();
|
||||
private final List<CRegion>[][] cellRegions;
|
||||
private final PathingGrid pathingGrid;
|
||||
|
||||
public CRegionManager(final Rectangle entireMapBounds, final PathingGrid pathingGrid) {
|
||||
this.regionTree = new Quadtree<>(entireMapBounds);
|
||||
this.cellRegions = new List[pathingGrid.getHeight()][pathingGrid.getWidth()];
|
||||
this.pathingGrid = pathingGrid;
|
||||
}
|
||||
|
||||
public void addRectForRegion(final CRegion region, final Rectangle rect) {
|
||||
this.regionTree.add(region, rect);
|
||||
}
|
||||
|
||||
public void removeRectForRegion(final CRegion region, final Rectangle rect) {
|
||||
this.regionTree.remove(region, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls back on the enum function for every region that touches the given area.
|
||||
* Sometimes, for performance, this algorithm is designed to call the enum
|
||||
* function twice for the same region, because our expected use case is to store
|
||||
* the regions in a set that guarantees uniqueness anyway (see CUnit and/or
|
||||
* other uses of this method).
|
||||
*/
|
||||
public void checkRegions(final Rectangle area, final CRegionEnumFunction enumFunction) {
|
||||
this.regionTree.intersect(area, this.regionChecker.reset(enumFunction));
|
||||
if (this.regionChecker.includesComplex) {
|
||||
final int minX = this.pathingGrid.getCellX(area.x);
|
||||
final int minY = this.pathingGrid.getCellY(area.y);
|
||||
final int maxX = this.pathingGrid.getCellX(area.x + area.width);
|
||||
final int maxY = this.pathingGrid.getCellY(area.y + area.height);
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
final List<CRegion> cellRegionsAtPoint = this.cellRegions[y][x];
|
||||
if (cellRegionsAtPoint != null) {
|
||||
for (final CRegion region : cellRegionsAtPoint) {
|
||||
if (enumFunction.call(region)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RegionChecker implements QuadtreeIntersector<CRegion> {
|
||||
private CRegionEnumFunction delegate;
|
||||
private boolean includesComplex = false;
|
||||
|
||||
public RegionChecker reset(final CRegionEnumFunction delegate) {
|
||||
this.delegate = delegate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onIntersect(final CRegion intersectingObject) {
|
||||
if (intersectingObject.isComplexRegion()) {
|
||||
this.includesComplex = true;
|
||||
// handle this type of region differently
|
||||
return false;
|
||||
}
|
||||
return this.delegate.call(intersectingObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addComplexRegionCells(final CRegion region, final Rectangle currentBounds) {
|
||||
final int minX = this.pathingGrid.getCellX(currentBounds.x);
|
||||
final int minY = this.pathingGrid.getCellY(currentBounds.y);
|
||||
final int maxX = this.pathingGrid.getCellX(currentBounds.x + currentBounds.width);
|
||||
final int maxY = this.pathingGrid.getCellY(currentBounds.y + currentBounds.height);
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
List<CRegion> list = this.cellRegions[y][x];
|
||||
if (list == null) {
|
||||
this.cellRegions[y][x] = list = new ArrayList<>();
|
||||
}
|
||||
list.add(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeComplexRegionCells(final CRegion region, final Rectangle currentBounds) {
|
||||
final int minX = this.pathingGrid.getCellX(currentBounds.x);
|
||||
final int minY = this.pathingGrid.getCellY(currentBounds.y);
|
||||
final int maxX = this.pathingGrid.getCellX(currentBounds.x + currentBounds.width);
|
||||
final int maxY = this.pathingGrid.getCellY(currentBounds.y + currentBounds.height);
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
final List<CRegion> list = this.cellRegions[y][x];
|
||||
if (list != null) {
|
||||
list.remove(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void computeNewMinimumComplexRegionBounds(final CRegion region, final Rectangle complexRegionBounds) {
|
||||
final int minX = this.pathingGrid.getCellX(complexRegionBounds.x);
|
||||
final int minY = this.pathingGrid.getCellY(complexRegionBounds.y);
|
||||
final int maxX = this.pathingGrid.getCellX(complexRegionBounds.x + complexRegionBounds.width);
|
||||
final int maxY = this.pathingGrid.getCellY(complexRegionBounds.y + complexRegionBounds.height);
|
||||
float newMinX = this.pathingGrid.getWorldX(this.pathingGrid.getWidth() - 1);
|
||||
float newMaxX = this.pathingGrid.getWorldX(0);
|
||||
float newMinY = this.pathingGrid.getWorldY(this.pathingGrid.getHeight() - 1);
|
||||
float newMaxY = this.pathingGrid.getWorldY(0);
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
final List<CRegion> list = this.cellRegions[y][x];
|
||||
if (list != null) {
|
||||
if (list.contains(region)) {
|
||||
final float worldX = this.pathingGrid.getWorldX(x);
|
||||
final float worldY = this.pathingGrid.getWorldY(y);
|
||||
final float wMinX = worldX - 16f;
|
||||
final float wMinY = worldY - 16f;
|
||||
final float wMaxX = worldX + 15f;
|
||||
final float wMaxY = worldY + 15f;
|
||||
if (wMinX < newMinX) {
|
||||
newMinX = wMinX;
|
||||
}
|
||||
if (wMinY < newMinY) {
|
||||
newMinY = wMinY;
|
||||
}
|
||||
if (wMaxX > newMaxX) {
|
||||
newMaxX = wMaxX;
|
||||
}
|
||||
if (wMaxY > newMaxY) {
|
||||
newMaxY = wMaxY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
complexRegionBounds.set(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
|
||||
}
|
||||
|
||||
public void addComplexRegionCell(final CRegion region, final float x, final float y,
|
||||
final Rectangle boundsToUpdate) {
|
||||
final int cellX = this.pathingGrid.getCellX(x);
|
||||
final int cellY = this.pathingGrid.getCellY(y);
|
||||
List<CRegion> list = this.cellRegions[cellY][cellX];
|
||||
if (list == null) {
|
||||
this.cellRegions[cellY][cellX] = list = new ArrayList<>();
|
||||
}
|
||||
list.add(region);
|
||||
final float worldX = this.pathingGrid.getWorldX(cellX);
|
||||
final float worldY = this.pathingGrid.getWorldY(cellY);
|
||||
final float wMinX = worldX - 16f;
|
||||
final float wMinY = worldY - 16f;
|
||||
boundsToUpdate.merge(tempRect.set(wMinX, wMinY, 31f, 31f));
|
||||
}
|
||||
|
||||
public void clearComplexRegionCell(final CRegion region, final float x, final float y,
|
||||
final Rectangle boundsToUpdate) {
|
||||
final int cellX = this.pathingGrid.getCellX(x);
|
||||
final int cellY = this.pathingGrid.getCellY(y);
|
||||
final List<CRegion> list = this.cellRegions[cellY][cellX];
|
||||
if (list != null) {
|
||||
list.remove(region);
|
||||
}
|
||||
computeNewMinimumComplexRegionBounds(region, boundsToUpdate);
|
||||
}
|
||||
|
||||
public boolean isPointInComplexRegion(final CRegion region, final float x, final float y) {
|
||||
final int cellX = this.pathingGrid.getCellX(x);
|
||||
final int cellY = this.pathingGrid.getCellY(y);
|
||||
final List<CRegion> list = this.cellRegions[cellY][cellX];
|
||||
if (list != null) {
|
||||
return list.contains(region);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -295,6 +295,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private SimpleButtonFrame alliesButton;
|
||||
private SimpleButtonFrame chatButton;
|
||||
private final Runnable exitGameRunnable;
|
||||
private SimpleFrame smashEscMenu;
|
||||
|
||||
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene,
|
||||
final Scene portraitScene, final CameraPreset[] cameraPresets, final CameraRates cameraRates,
|
||||
@ -448,12 +449,14 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.chatButton = (SimpleButtonFrame) this.rootFrame.getFrameByName("UpperButtonBarChatButton", 0);
|
||||
this.chatButton.setEnabled(false);
|
||||
|
||||
final UIFrame escMenuBackdrop = this.rootFrame.createFrame("EscMenuBackdrop", this.rootFrame, 0, 0);
|
||||
this.smashEscMenu = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashEscMenu", this.rootFrame, 0);
|
||||
this.smashEscMenu.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, GameUI.convertY(this.uiViewport, -0.05f)));
|
||||
final UIFrame escMenuBackdrop = this.rootFrame.createFrame("EscMenuBackdrop", this.smashEscMenu, 0, 0);
|
||||
escMenuBackdrop.setVisible(false);
|
||||
escMenuBackdrop.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, GameUI.convertY(this.uiViewport, -0.05f)));
|
||||
final UIFrame escMenuMainPanel = this.rootFrame.createFrame("EscMenuMainPanel", this.rootFrame, 0, 0);
|
||||
final UIFrame escMenuMainPanel = this.rootFrame.createFrame("EscMenuMainPanel", this.smashEscMenu, 0, 0);
|
||||
escMenuMainPanel.setVisible(false);
|
||||
escMenuMainPanel.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, GameUI.convertY(this.uiViewport, -0.05f)));
|
||||
this.smashEscMenu.add(escMenuBackdrop);
|
||||
this.smashEscMenu.add(escMenuMainPanel);
|
||||
|
||||
final UIFrame escMenuInnerMainPanel = this.rootFrame.getFrameByName("MainPanel", 0);
|
||||
final GlueTextButtonFrame pauseButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("PauseButton", 0);
|
||||
@ -504,6 +507,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
public void run() {
|
||||
escMenuBackdrop.setVisible(true);
|
||||
escMenuMainPanel.setVisible(true);
|
||||
MeleeUI.this.smashEscMenu.setVisible(true);
|
||||
escMenuInnerMainPanel.setVisible(true);
|
||||
updateEscMenuCurrentPanel(escMenuBackdrop, escMenuMainPanel, escMenuInnerMainPanel);
|
||||
}
|
||||
@ -513,6 +517,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
public void run() {
|
||||
escMenuBackdrop.setVisible(false);
|
||||
escMenuMainPanel.setVisible(false);
|
||||
MeleeUI.this.smashEscMenu.setVisible(false);
|
||||
escMenuInnerMainPanel.setVisible(false);
|
||||
}
|
||||
});
|
||||
@ -924,12 +929,12 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
|
||||
private void updateEscMenuCurrentPanel(final UIFrame escMenuBackdrop, final UIFrame escMenuMainPanel,
|
||||
final UIFrame escMenuInnerMainPanel) {
|
||||
escMenuMainPanel.setHeight(escMenuInnerMainPanel.getAssignedHeight());
|
||||
escMenuMainPanel.setWidth(escMenuInnerMainPanel.getAssignedWidth());
|
||||
escMenuBackdrop.setHeight(escMenuInnerMainPanel.getAssignedHeight());
|
||||
this.smashEscMenu.setWidth(escMenuInnerMainPanel.getAssignedWidth());
|
||||
this.smashEscMenu.setHeight(escMenuInnerMainPanel.getAssignedHeight());
|
||||
escMenuBackdrop.setWidth(escMenuInnerMainPanel.getAssignedWidth());
|
||||
escMenuMainPanel.positionBounds(MeleeUI.this.rootFrame, MeleeUI.this.uiViewport);
|
||||
escMenuBackdrop.positionBounds(MeleeUI.this.rootFrame, MeleeUI.this.uiViewport);
|
||||
escMenuBackdrop.setHeight(escMenuInnerMainPanel.getAssignedHeight());
|
||||
this.smashEscMenu.positionBounds(this.rootFrame, this.uiViewport);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,13 +166,24 @@ public class MenuUI {
|
||||
this.heightRatioCorrection = getMinWorldHeight() / 1200f;
|
||||
|
||||
this.campaignStrings = new DataTable(StringBundle.EMPTY);
|
||||
try (InputStream campaignStringStream = dataSource.getResourceAsStream(
|
||||
"UI\\CampaignStrings" + (WarsmashConstants.GAME_VERSION == 1 ? "_exp" : "") + ".txt")) {
|
||||
final String campaignStringPath = "UI\\CampaignStrings" + (WarsmashConstants.GAME_VERSION == 1 ? "_exp" : "")
|
||||
+ ".txt";
|
||||
if (dataSource.has(campaignStringPath)) {
|
||||
try (InputStream campaignStringStream = dataSource.getResourceAsStream(campaignStringPath)) {
|
||||
this.campaignStrings.readTXT(campaignStringStream, true);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try (InputStream campaignStringStream = dataSource.getResourceAsStream("UI\\CampaignInfoClassic.txt")) {
|
||||
this.campaignStrings.readTXT(campaignStringStream, true);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
this.profileManager = PlayerProfileManager.loadFromGdx();
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ public class CampaignMenuUI extends SimpleFrame {
|
||||
super.innerPositionBounds(gameUI, viewport);
|
||||
final float myHeight = this.renderBounds.height;
|
||||
final int buttonCount = this.buttonUIs.size();
|
||||
System.out.println("myheight / count is " + myHeight + "/" + buttonCount);
|
||||
final float buttonSpacing = Math.min(myHeight / buttonCount, GameUI.convertY(this.uiViewport, 0.056f));
|
||||
final float buttonsHeight = buttonSpacing * buttonCount;
|
||||
final float expectedHeight = Math.min(buttonsHeight, myHeight);
|
||||
@ -65,12 +64,10 @@ public class CampaignMenuUI extends SimpleFrame {
|
||||
UIFrame lastButton = null;
|
||||
for (final CampaignButtonUI campaignButtonUI : this.buttonUIs) {
|
||||
if (lastButton == null) {
|
||||
System.out.println("offsetting from this " + getName() + " by " + yOffset);
|
||||
campaignButtonUI.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, 0, -yOffset));
|
||||
campaignButtonUI.addSetPoint(new SetPoint(FramePoint.TOPRIGHT, this, FramePoint.TOPRIGHT, 0, -yOffset));
|
||||
}
|
||||
else {
|
||||
System.out.println("offsetting from bs " + lastButton.getName() + " by " + buttonSpacing);
|
||||
campaignButtonUI.addSetPoint(
|
||||
new SetPoint(FramePoint.TOPLEFT, lastButton, FramePoint.TOPLEFT, 0, -buttonSpacing));
|
||||
campaignButtonUI.addSetPoint(
|
||||
|
Loading…
Reference in New Issue
Block a user