From bf16b4f698f5b26049b0db055ae5ba8998fb4779 Mon Sep 17 00:00:00 2001 From: Retera Date: Fri, 4 Sep 2020 08:29:37 -0400 Subject: [PATCH] Damage and armor UI and attack animation fixes --- core/assets/warsmash.ini | 14 +- .../etheller/warsmash/WarsmashGdxMapGame.java | 195 +- .../etheller/warsmash/parsers/fdf/GameUI.java | 203 +- .../fdf/frames/AbstractRenderableFrame.java | 68 +- .../parsers/fdf/frames/AbstractUIFrame.java | 6 +- .../warsmash/parsers/fdf/frames/SetPoint.java | 40 + .../parsers/fdf/frames/SpriteFrame.java | 52 + .../parsers/fdf/frames/StringFrame.java | 72 + .../parsers/fdf/frames/TextureFrame.java | 40 +- .../warsmash/parsers/fdf/frames/UIFrame.java | 14 +- .../etheller/warsmash/parsers/jass/Jass2.java | 111 +- .../warsmash/parsers/mdlx/AnimatedObject.java | 6 +- .../warsmash/util/FastNumberFormat.java | 24 + .../handlers/mdx/MdxComplexInstance.java | 7 +- .../warsmash/viewer5/handlers/w3x/Doodad.java | 41 +- .../viewer5/handlers/w3x/TerrainDoodad.java | 20 +- .../viewer5/handlers/w3x/War3MapViewer.java | 72 +- .../w3x/environment/RenderCorner.java | 1 + .../handlers/w3x/environment/Terrain.java | 29 +- .../rendersim/OrientationInterpolation.java | 61 + .../handlers/w3x/rendersim/ParseBogus.java | 49 + .../handlers/w3x/rendersim/ParseBogus2.java | 60 + .../handlers/w3x/rendersim/ParseBogus3.java | 19 + .../handlers/w3x/rendersim/ParseBogus4.java | 80 + .../w3x/rendersim/RenderAttackProjectile.java | 5 +- .../handlers/w3x/rendersim/RenderUnit.java | 168 +- .../w3x/simulation/CDestructable.java | 4 + .../w3x/simulation/CGameplayConstants.java | 21 + .../handlers/w3x/simulation/CItem.java | 4 + .../handlers/w3x/simulation/COrder.java | 10 - .../handlers/w3x/simulation/CSimulation.java | 16 +- .../handlers/w3x/simulation/CUnit.java | 43 +- .../simulation/CUnitAnimationListener.java | 16 + .../w3x/simulation/CUnitClassification.java | 67 + .../handlers/w3x/simulation/CUnitType.java | 59 +- .../handlers/w3x/simulation/CWidget.java | 2 + .../simulation/abilities/CAbilityAttack.java | 2 +- .../w3x/simulation/combat/CAttackType.java | 31 + .../w3x/simulation/combat/CDefenseType.java | 27 + .../w3x/simulation/combat/CRegenType.java | 13 + .../w3x/simulation/combat/CTargetType.java | 139 ++ .../w3x/simulation/combat/CUpgradeClass.java | 13 + .../w3x/simulation/combat/CWeaponType.java | 16 + .../w3x/simulation/combat/CodeKeyType.java | 7 + .../combat/attacks/CUnitAttack.java | 198 ++ .../combat/attacks/CUnitAttackInstant.java | 31 + .../combat/attacks/CUnitAttackMissile.java | 62 + .../attacks/CUnitAttackMissileBounce.java | 43 + .../attacks/CUnitAttackMissileLine.java | 43 + .../attacks/CUnitAttackMissileSplash.java | 85 + .../combat/attacks/CUnitAttackNormal.java | 21 + .../projectile/CAttackProjectile.java | 2 +- .../w3x/simulation/data/CUnitData.java | 240 +- .../w3x/simulation/orders/CAttackOrder.java | 46 +- .../simulation/orders/CDoNothingOrder.java | 6 - .../w3x/simulation/orders/CMoveOrder.java | 23 +- .../simulation/util/ProjectileCreator.java | 2 +- .../viewer5/handlers/w3x/ui/MeleeUI.java | 372 ++++ .../warsmash/desktop/DesktopLauncher.java | 10 +- .../fdf/datamodel/FrameDefinition.java | 18 + .../fields/visitor/GetFontFieldVisitor.java | 57 + .../visitor/GetTextJustifyFieldVisitor.java | 57 + jassparser/.gitignore | 1 + jassparser/antlr-src/Jass.g4 | 2 +- .../warsmash/jassparser/JassBaseVisitor.java | 317 --- .../warsmash/jassparser/JassLexer.java | 224 -- .../warsmash/jassparser/JassParser.java | 1969 ----------------- .../warsmash/jassparser/JassVisitor.java | 302 --- resources/Scripts/common.jui | 31 + resources/Scripts/melee.jui | 40 +- resources/UI/FrameDef/SmashFrameDef.toc | 2 + .../UI/FrameDef/SmashUI/SmashConsoleUI.fdf | 81 + .../FrameDef/SmashUI/TimeOfDayIndicator.fdf | 6 + .../UI/FrameDef/SmashUI/UnitPortrait.fdf | 44 + resources/UI/FrameDef/UI/SimpleInfoPanel.fdf | 447 ++++ 75 files changed, 3638 insertions(+), 3091 deletions(-) create mode 100644 core/src/com/etheller/warsmash/parsers/fdf/frames/SetPoint.java create mode 100644 core/src/com/etheller/warsmash/parsers/fdf/frames/SpriteFrame.java create mode 100644 core/src/com/etheller/warsmash/parsers/fdf/frames/StringFrame.java create mode 100644 core/src/com/etheller/warsmash/util/FastNumberFormat.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/OrientationInterpolation.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus2.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus3.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus4.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CGameplayConstants.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitAnimationListener.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitClassification.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CDefenseType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CRegenType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CTargetType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CUpgradeClass.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CWeaponType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CodeKeyType.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttack.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackInstant.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissile.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileBounce.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileLine.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileSplash.java create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackNormal.java rename core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/{ => combat}/projectile/CAttackProjectile.java (95%) create mode 100644 core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java create mode 100644 fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetFontFieldVisitor.java create mode 100644 fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetTextJustifyFieldVisitor.java create mode 100644 jassparser/.gitignore delete mode 100644 jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassBaseVisitor.java delete mode 100644 jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassLexer.java delete mode 100644 jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassParser.java delete mode 100644 jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassVisitor.java create mode 100644 resources/UI/FrameDef/SmashFrameDef.toc create mode 100644 resources/UI/FrameDef/SmashUI/SmashConsoleUI.fdf create mode 100644 resources/UI/FrameDef/SmashUI/TimeOfDayIndicator.fdf create mode 100644 resources/UI/FrameDef/SmashUI/UnitPortrait.fdf create mode 100644 resources/UI/FrameDef/UI/SimpleInfoPanel.fdf diff --git a/core/assets/warsmash.ini b/core/assets/warsmash.ini index 88e3a85..276c5ba 100644 --- a/core/assets/warsmash.ini +++ b/core/assets/warsmash.ini @@ -1,13 +1,15 @@ [DataSources] -Count=4 +Count=5 Type00=Folder -Path00="E:\Backups\Warcraft\Data\127" +Path00="E:\Backups\Warcraft III 1.30 but dead\War3mod.mpq" Type01=Folder -Path01="..\..\resources" +Path01="E:\Backups\Warcraft\Data\127" Type02=Folder -Path02="E:\Backups\Warsmash\Data" +Path02="..\..\resources" Type03=Folder -Path03="." +Path03="E:\Backups\Warsmash\Data" +Type04=Folder +Path04="." [Map] -FilePath="RuinedGround.w3x" \ No newline at end of file +FilePath="PitchRoll.w3x" \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/WarsmashGdxMapGame.java b/core/src/com/etheller/warsmash/WarsmashGdxMapGame.java index 9ae08f2..db4ca3d 100644 --- a/core/src/com/etheller/warsmash/WarsmashGdxMapGame.java +++ b/core/src/com/etheller/warsmash/WarsmashGdxMapGame.java @@ -38,7 +38,6 @@ import com.etheller.warsmash.datasources.DataSourceDescriptor; import com.etheller.warsmash.datasources.FolderDataSourceDescriptor; import com.etheller.warsmash.datasources.MpqDataSourceDescriptor; import com.etheller.warsmash.parsers.fdf.GameUI; -import com.etheller.warsmash.parsers.jass.Jass2; import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener; import com.etheller.warsmash.units.DataTable; import com.etheller.warsmash.units.Element; @@ -52,15 +51,19 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance; import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; import com.etheller.warsmash.viewer5.handlers.mdx.ReplaceableIds; import com.etheller.warsmash.viewer5.handlers.tga.TgaFile; -import com.etheller.warsmash.viewer5.handlers.w3x.StandSequence; import com.etheller.warsmash.viewer5.handlers.w3x.UnitSoundset.UnitAckSound; import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.CommandCardIcon; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityStop; +import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI; public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProvider, InputProcessor { + private static final float HORIZONTAL_MAXIMUM = (float) Math.toRadians(56); + private static final float HORIZONTAL_MINIMUM = (float) -Math.toRadians(56); + private static final double HORIZONTAL_ANGLE_INCREMENT = Math.PI / 60; + private static final Vector3 clickLocationTemp = new Vector3(); private static final Vector2 clickLocationTemp2 = new Vector2(); private DataSource codebase; @@ -68,10 +71,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv private CameraManager cameraManager; private final Rectangle tempRect = new Rectangle(); - private CameraManager portraitCameraManager; - private final float[] cameraPositionTemp = new float[3]; - private final float[] cameraTargetTemp = new float[3]; - // libGDX stuff private OrthographicCamera uiCamera; private BitmapFont font; @@ -82,8 +81,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv private GlyphLayout glyphLayout; private Texture consoleUITexture; - private final Vector2 projectionTemp1 = new Vector2(); - private final Vector2 projectionTemp2 = new Vector2(); private RenderUnit selectedUnit; private int selectedSoundCount = 0; @@ -165,17 +162,11 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1); // TODO remove white background Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST); - this.portraitScene = this.viewer.addSimpleScene(); - this.portraitCameraManager = new CameraManager(); - this.portraitCameraManager.setupCamera(this.portraitScene); - this.uiScene = this.viewer.addSimpleScene(); this.uiScene.alpha = true; // this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\MainMenu\\MainMenu3D_exp\\MainMenu3D_exp.mdx", - this.portraitScene.camera.viewport(new Rectangle(100, 0, 6400, 48)); - // libGDX stuff final float w = Gdx.graphics.getWidth(); final float h = Gdx.graphics.getHeight(); @@ -196,7 +187,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.font24 = fontGenerator.generateFont(fontParam); fontParam.size = 20; this.font20 = fontGenerator.generateFont(fontParam); - fontGenerator.dispose(); this.glyphLayout = new GlyphLayout(); // Constructs a new OrthographicCamera, using the given viewport width and @@ -209,8 +199,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.uiCamera.position.set(this.uiCamera.viewportWidth / 2f, this.uiCamera.viewportHeight / 2f, 0); this.uiCamera.update(); - positionPortrait(); - this.batch = new SpriteBatch(); // this.consoleUITexture = new Texture(new DataSourceFileHandle(this.viewer.dataSource, "AlphaUi.png")); @@ -273,12 +261,22 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.shapeRenderer = new ShapeRenderer(); this.talentTreeWindow = new Rectangle(100, 300, 1400, 800); - Jass2.loadJUI(this.codebase, this.uiViewport, new RootFrameListener() { - @Override - public void onCreate(final GameUI rootFrame) { - WarsmashGdxMapGame.this.gameUI = rootFrame; - } - }, "Scripts\\common.jui", "Scripts\\melee.jui"); +// Jass2.loadJUI(this.codebase, this.uiViewport, fontGenerator, this.uiScene, this.viewer, +// new RootFrameListener() { +// @Override +// public void onCreate(final GameUI rootFrame) { +// WarsmashGdxMapGame.this.gameUI = rootFrame; +// } +// }, "Scripts\\common.jui", "Scripts\\melee.jui"); + + this.meleeUI = new MeleeUI(this.codebase, this.uiViewport, fontGenerator, this.uiScene, this.viewer, + new RootFrameListener() { + @Override + public void onCreate(final GameUI rootFrame) { + } + }); + this.meleeUI.main(); + fontGenerator.dispose(); } @Override @@ -292,7 +290,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.viewer.terrain.getGroundHeight(this.cameraManager.target.x, this.cameraManager.target.y), this.viewer.terrain.getWaterHeight(this.cameraManager.target.x, this.cameraManager.target.y)) - 256; this.cameraManager.updateCamera(); - this.portraitCameraManager.updateCamera(); + this.meleeUI.updatePortrait(); this.viewer.updateAndRender(); // gl.glDrawElements(GL20.GL_TRIANGLES, this.elements, GL20.GL_UNSIGNED_SHORT, this.faceOffset); @@ -301,12 +299,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv // this.font.draw(this.batch, Integer.toString(Gdx.graphics.getFramesPerSecond()), 0, 0); // this.batch.end(); - if ((this.portraitCameraManager.modelInstance != null) - && (this.portraitCameraManager.modelInstance.sequenceEnded - || (this.portraitCameraManager.modelInstance.sequence == -1))) { - StandSequence.randomPortraitSequence(this.portraitCameraManager.modelInstance); - } - Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST); Gdx.gl30.glDisable(GL30.GL_CULL_FACE); @@ -317,7 +309,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.uiViewport.apply(); this.batch.setProjectionMatrix(this.uiCamera.combined); this.batch.begin(); - this.gameUI.render(this.batch); + this.meleeUI.render(this.batch, this.font20, this.glyphLayout); this.font.setColor(Color.YELLOW); final String fpsString = "FPS: " + Gdx.graphics.getFramesPerSecond(); this.glyphLayout.setText(this.font, fpsString); @@ -428,25 +420,12 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.uiScene.camera.viewport(this.tempRect); this.uiScene.camera.ortho(0f, 0.8f, 0f, 0.6f, -1f, 1); - positionPortrait(); + this.meleeUI.resize(); } - private void positionPortrait() { - this.projectionTemp1.x = 422; - this.projectionTemp1.y = 57; - this.projectionTemp2.x = 422 + 167; - this.projectionTemp2.y = 57 + 170; - this.uiViewport.project(this.projectionTemp1); - this.uiViewport.project(this.projectionTemp2); - - this.tempRect.x = this.projectionTemp1.x; - this.tempRect.y = this.projectionTemp1.y; - this.tempRect.width = this.projectionTemp2.x - this.projectionTemp1.x; - this.tempRect.height = this.projectionTemp2.y - this.projectionTemp1.y; - this.portraitScene.camera.viewport(this.tempRect); - } - - class CameraManager { + public static class CameraManager { + private final float[] cameraPositionTemp = new float[3]; + private final float[] cameraTargetTemp = new float[3]; public com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera; private MdxComplexInstance modelInstance; private CanvasProvider canvas; @@ -456,6 +435,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv private float zoomFactor; private float horizontalAngle; private float verticalAngle; + private float verticalAngleAcceleration; private float distance; private Vector3 position; private Vector3 target; @@ -463,17 +443,19 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv private Vector3 vecHeap; private Quaternion quatHeap; private Quaternion quatHeap2; + private boolean insertDown; + private boolean deleteDown; // An orbit camera setup example. // Left mouse button controls the orbit itself. // The right mouse button allows to move the camera and the point it's looking // at on the XY plane. // Scrolling zooms in and out. - private void setupCamera(final Scene scene) { + public void setupCamera(final Scene scene) { this.canvas = scene.viewer.canvas; this.camera = scene.camera; this.moveSpeed = 2; - this.rotationSpeed = (float) (Math.PI / 180); + this.rotationSpeed = (float) HORIZONTAL_ANGLE_INCREMENT; this.zoomFactor = 0.1f; this.horizontalAngle = 0;// (float) (Math.PI / 2); this.verticalAngle = (float) Math.toRadians(34); @@ -490,10 +472,45 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv // cameraUpdate(); } - private void updateCamera() { + public void updateCamera() { this.quatHeap.idt(); this.quatHeap.setFromAxisRad(0, 0, 1, this.horizontalAngle); + if (this.insertDown && !this.deleteDown) { + this.horizontalAngle -= HORIZONTAL_ANGLE_INCREMENT; + if (this.horizontalAngle < HORIZONTAL_MINIMUM) { + this.horizontalAngle = HORIZONTAL_MINIMUM; + } + } + else if (this.deleteDown && !this.insertDown) { + this.horizontalAngle += HORIZONTAL_ANGLE_INCREMENT; + if (this.horizontalAngle > HORIZONTAL_MAXIMUM) { + this.horizontalAngle = HORIZONTAL_MAXIMUM; + } + } + else { + if (Math.abs(this.horizontalAngle) < HORIZONTAL_ANGLE_INCREMENT) { + this.horizontalAngle = 0; + } + else { + this.horizontalAngle -= HORIZONTAL_ANGLE_INCREMENT * Math.signum(this.horizontalAngle); + } + } + this.quatHeap2.idt(); + this.verticalAngle += this.verticalAngleAcceleration; + this.verticalAngleAcceleration *= 0.975f; + if (this.verticalAngle > ((Math.PI / 2) - Math.toRadians(17))) { + this.verticalAngle = (float) ((Math.PI / 2) - Math.toRadians(17)); + if (this.verticalAngleAcceleration > 0) { + this.verticalAngleAcceleration = 0; + } + } + if (this.verticalAngle < (float) Math.toRadians(34)) { + this.verticalAngle = (float) Math.toRadians(34); + if (this.verticalAngleAcceleration < 0) { + this.verticalAngleAcceleration = 0; + } + } this.quatHeap2.setFromAxisRad(1, 0, 0, this.verticalAngle); this.quatHeap.mul(this.quatHeap2); @@ -502,18 +519,16 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.position.scl(this.distance); this.position = this.position.add(this.target); if (this.modelCamera != null) { - this.modelCamera.getPositionTranslation(WarsmashGdxMapGame.this.cameraPositionTemp, - this.modelInstance.sequence, this.modelInstance.frame, this.modelInstance.counter); - this.modelCamera.getTargetTranslation(WarsmashGdxMapGame.this.cameraTargetTemp, - this.modelInstance.sequence, this.modelInstance.frame, this.modelInstance.counter); + this.modelCamera.getPositionTranslation(this.cameraPositionTemp, this.modelInstance.sequence, + this.modelInstance.frame, this.modelInstance.counter); + this.modelCamera.getTargetTranslation(this.cameraTargetTemp, this.modelInstance.sequence, + this.modelInstance.frame, this.modelInstance.counter); this.position.set(this.modelCamera.position); this.target.set(this.modelCamera.targetPosition); - this.position.add(WarsmashGdxMapGame.this.cameraPositionTemp[0], - WarsmashGdxMapGame.this.cameraPositionTemp[1], WarsmashGdxMapGame.this.cameraPositionTemp[2]); - this.target.add(WarsmashGdxMapGame.this.cameraTargetTemp[0], - WarsmashGdxMapGame.this.cameraTargetTemp[1], WarsmashGdxMapGame.this.cameraTargetTemp[2]); + this.position.add(this.cameraPositionTemp[0], this.cameraPositionTemp[1], this.cameraPositionTemp[2]); + this.target.add(this.cameraTargetTemp[0], this.cameraTargetTemp[1], this.cameraTargetTemp[2]); this.camera.perspective(this.modelCamera.fieldOfView * 0.75f, this.camera.getAspect(), this.modelCamera.nearClippingPlane, this.modelCamera.farClippingPlane); } @@ -524,6 +539,16 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv this.camera.moveToAndFace(this.position, this.target, this.worldUp); } + public void setModelInstance(final MdxComplexInstance modelInstance, final MdxModel portraitModel) { + this.modelInstance = modelInstance; + if (modelInstance == null) { + this.modelCamera = null; + } + else if ((portraitModel != null) && (portraitModel.getCameras().size() > 0)) { + this.modelCamera = portraitModel.getCameras().get(0); + } + } + // private void cameraUpdate() { // // } @@ -531,11 +556,10 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv private final float cameraSpeed = 4096.0f; // per second private final Vector2 cameraVelocity = new Vector2(); - private Scene portraitScene; private Texture minimapTexture; private Rectangle talentTreeWindow; - private GameUI gameUI; private Scene uiScene; + private MeleeUI meleeUI; @Override public boolean keyDown(final int keycode) { @@ -551,6 +575,12 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv else if (keycode == Input.Keys.UP) { this.cameraVelocity.y = this.cameraSpeed; } + else if (keycode == Input.Keys.INSERT) { + this.cameraManager.insertDown = true; + } + else if (keycode == Input.Keys.FORWARD_DEL) { + this.cameraManager.deleteDown = true; + } return true; } @@ -568,6 +598,12 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv else if (keycode == Input.Keys.UP) { this.cameraVelocity.y = 0; } + else if (keycode == Input.Keys.INSERT) { + this.cameraManager.insertDown = false; + } + else if (keycode == Input.Keys.FORWARD_DEL) { + this.cameraManager.deleteDown = false; + } return true; } @@ -613,7 +649,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv if ((rayPickUnit != null) && (this.selectedUnit != null) && (rayPickUnit.playerIndex != this.selectedUnit.playerIndex)) { if (this.viewer.orderSmart(rayPickUnit)) { - StandSequence.randomPortraitTalkSequence(this.portraitCameraManager.modelInstance); + this.meleeUI.portraitTalk(); this.selectedSoundCount = 0; } } @@ -626,7 +662,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv System.out.println(x + "," + y); this.viewer.terrain.logRomp(x, y); if (this.viewer.orderSmart(clickLocationTemp.x, clickLocationTemp.y)) { - StandSequence.randomPortraitTalkSequence(this.portraitCameraManager.modelInstance); + this.meleeUI.portraitTalk(); this.selectedSoundCount = 0; } } @@ -662,32 +698,15 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv } } if (selectionChanged) { - final MdxModel portraitModel = unit.portraitModel; - if (portraitModel != null) { - if (this.portraitCameraManager.modelInstance != null) { - this.portraitScene.removeInstance(this.portraitCameraManager.modelInstance); - } - this.portraitCameraManager.modelInstance = (MdxComplexInstance) portraitModel.addInstance(); - this.portraitCameraManager.modelInstance.setSequenceLoopMode(1); - this.portraitCameraManager.modelInstance.setScene(this.portraitScene); - this.portraitCameraManager.modelInstance.setVertexColor(unit.instance.vertexColor); - if (portraitModel.getCameras().size() > 0) { - this.portraitCameraManager.modelCamera = portraitModel.getCameras().get(0); - } - this.portraitCameraManager.modelInstance.setTeamColor(unit.playerIndex); - } + this.meleeUI.selectUnit(unit); } if (playedNewSound) { - StandSequence.randomPortraitTalkSequence(this.portraitCameraManager.modelInstance); + this.meleeUI.portraitTalk(); } } else { this.selectedUnit = null; - if (this.portraitCameraManager.modelInstance != null) { - this.portraitScene.removeInstance(this.portraitCameraManager.modelInstance); - } - this.portraitCameraManager.modelInstance = null; - this.portraitCameraManager.modelCamera = null; + this.meleeUI.selectUnit(null); } } return false; @@ -710,12 +729,12 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv @Override public boolean scrolled(final int amount) { - this.cameraManager.verticalAngle -= amount / 10.f; - if (this.cameraManager.verticalAngle > (Math.PI / 2)) { - this.cameraManager.verticalAngle = (float) Math.PI / 2; + this.cameraManager.verticalAngleAcceleration -= amount / 100.f; + if (this.cameraManager.verticalAngleAcceleration > (Math.PI / 128)) { + this.cameraManager.verticalAngleAcceleration = (float) (Math.PI / 128); } - if (this.cameraManager.verticalAngle < (float) Math.toRadians(34)) { - this.cameraManager.verticalAngle = (float) Math.toRadians(34); + if (this.cameraManager.verticalAngleAcceleration < (-Math.PI / 128)) { + this.cameraManager.verticalAngleAcceleration = -(float) (Math.PI / 128); } return true; } diff --git a/core/src/com/etheller/warsmash/parsers/fdf/GameUI.java b/core/src/com/etheller/warsmash/parsers/fdf/GameUI.java index 64c4989..fbf8f2f 100644 --- a/core/src/com/etheller/warsmash/parsers/fdf/GameUI.java +++ b/core/src/com/etheller/warsmash/parsers/fdf/GameUI.java @@ -7,43 +7,66 @@ import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter; +import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; import com.etheller.warsmash.datasources.DataSource; import com.etheller.warsmash.fdfparser.FDFParser; import com.etheller.warsmash.fdfparser.FrameDefinitionVisitor; import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition; +import com.etheller.warsmash.parsers.fdf.datamodel.FontDefinition; import com.etheller.warsmash.parsers.fdf.datamodel.FrameClass; import com.etheller.warsmash.parsers.fdf.datamodel.FrameDefinition; import com.etheller.warsmash.parsers.fdf.datamodel.FrameTemplateEnvironment; +import com.etheller.warsmash.parsers.fdf.datamodel.SetPointDefinition; +import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify; import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition; import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame; +import com.etheller.warsmash.parsers.fdf.frames.SetPoint; import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame; +import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame; +import com.etheller.warsmash.parsers.fdf.frames.StringFrame; import com.etheller.warsmash.parsers.fdf.frames.TextureFrame; import com.etheller.warsmash.parsers.fdf.frames.UIFrame; import com.etheller.warsmash.units.DataTable; import com.etheller.warsmash.units.Element; import com.etheller.warsmash.util.ImageUtils; import com.etheller.warsmash.util.StringBundle; +import com.etheller.warsmash.viewer5.Scene; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; +import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; public final class GameUI extends AbstractUIFrame implements UIFrame { - private final DataSource dataSource; private final Element skin; private final Viewport viewport; + private final Scene uiScene; + private final War3MapViewer modelViewer; private final FrameTemplateEnvironment templates; private final Map pathToTexture = new HashMap<>(); private final boolean autoPosition = false; + private final FreeTypeFontGenerator fontGenerator; + private final FreeTypeFontParameter fontParam; + private final Map nameToFrame = new HashMap<>(); + private final Viewport fdfCoordinateResolutionDummyViewport; - public GameUI(final DataSource dataSource, final Element skin, final Viewport viewport) { + public GameUI(final DataSource dataSource, final Element skin, final Viewport viewport, + final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final War3MapViewer modelViewer) { super("GameUI", null); this.dataSource = dataSource; this.skin = skin; this.viewport = viewport; + this.uiScene = uiScene; + this.modelViewer = modelViewer; this.renderBounds.set(0, 0, viewport.getWorldWidth(), viewport.getWorldHeight()); this.templates = new FrameTemplateEnvironment(); - + this.fontGenerator = fontGenerator; + this.fontParam = new FreeTypeFontParameter(); + this.fdfCoordinateResolutionDummyViewport = new FitViewport(0.8f, 0.6f); } public static Element loadSkin(final DataSource dataSource, final String skin) { @@ -67,6 +90,27 @@ public final class GameUI extends AbstractUIFrame implements UIFrame { return userSkin; } + public static Element loadSkin(final DataSource dataSource, final int skinIndex) { + final DataTable skinsTable = new DataTable(StringBundle.EMPTY); + try (InputStream stream = dataSource.getResourceAsStream("UI\\war3skins.txt")) { + skinsTable.readTXT(stream, true); + } + catch (final IOException e) { + throw new RuntimeException(e); + } + final Element main = skinsTable.get("Main"); + final String skinsField = main.getField("Skins"); + final String[] skins = skinsField.split(","); + final Element defaultSkin = skinsTable.get("Default"); + final Element userSkin = skinsTable.get(skins[skinIndex]); + for (final String key : defaultSkin.keySet()) { + if (!userSkin.hasField(key)) { + userSkin.setField(key, defaultSkin.getField(key)); + } + } + return userSkin; + } + public void loadTOCFile(final String tocFilePath) throws IOException { final DataSourceFDFParserBuilder dataSourceFDFParserBuilder = new DataSourceFDFParserBuilder(this.dataSource); final FrameDefinitionVisitor fdfVisitor = new FrameDefinitionVisitor(this.templates, @@ -85,14 +129,20 @@ public final class GameUI extends AbstractUIFrame implements UIFrame { } } - public UIFrame createFrame(final String name, final UIFrame owner, final int priority, final int createContext) { - throw new UnsupportedOperationException("Not yet implemented"); + public String getSkinField(String file) { + if ((file != null) && this.skin.hasField(file)) { + file = this.skin.getField(file); + } + else { + throw new IllegalStateException("Decorated file name lookup not available: " + file); + } + return file; } - public UIFrame createSimpleFrame(final String name, final UIFrame owner, final int createContext) { + public UIFrame createFrame(final String name, final UIFrame owner, final int priority, final int createContext) { final FrameDefinition frameDefinition = this.templates.getFrame(name); if (frameDefinition.getFrameClass() == FrameClass.Frame) { - if ("SIMPLEFRAME".equals(frameDefinition.getFrameType())) { + if ("SPRITE".equals(frameDefinition.getFrameType())) { final UIFrame inflated = inflate(frameDefinition, owner, null); if (this.autoPosition) { inflated.positionBounds(this.viewport); @@ -101,67 +151,150 @@ public final class GameUI extends AbstractUIFrame implements UIFrame { return inflated; } } + throw new UnsupportedOperationException("Not yet implemented"); + } + + public UIFrame createSimpleFrame(final String name, final UIFrame owner, final int createContext) { + final FrameDefinition frameDefinition = this.templates.getFrame(name); + if (frameDefinition.getFrameClass() == FrameClass.Frame) { + final UIFrame inflated = inflate(frameDefinition, owner, null); + if (this.autoPosition) { + inflated.positionBounds(this.viewport); + } + add(inflated); + return inflated; + } return null; } public UIFrame inflate(final FrameDefinition frameDefinition, final UIFrame parent, final FrameDefinition parentDefinitionIfAvailable) { UIFrame inflatedFrame = null; + BitmapFont frameFont = null; + Viewport viewport2 = this.viewport; switch (frameDefinition.getFrameClass()) { case Frame: if ("SIMPLEFRAME".equals(frameDefinition.getFrameType())) { final SimpleFrame simpleFrame = new SimpleFrame(frameDefinition.getName(), parent); + // TODO: we should not need to put ourselves in this map 2x + this.nameToFrame.put(frameDefinition.getName(), simpleFrame); for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) { simpleFrame.add(inflate(childDefinition, simpleFrame, frameDefinition)); } inflatedFrame = simpleFrame; } + else if ("SPRITE".equals(frameDefinition.getFrameType())) { + final SpriteFrame spriteFrame = new SpriteFrame(frameDefinition.getName(), parent, this.uiScene); + String backgroundArt = frameDefinition.getString("BackgroundArt"); + if (frameDefinition.has("DecorateFileNames") || ((parentDefinitionIfAvailable != null) + && parentDefinitionIfAvailable.has("DecorateFileNames"))) { + if (this.skin.hasField(backgroundArt)) { + backgroundArt = this.skin.getField(backgroundArt); + } + else { + throw new IllegalStateException("Decorated file name lookup not available: " + backgroundArt); + } + } + if (backgroundArt.toLowerCase().endsWith(".mdl") || backgroundArt.toLowerCase().endsWith(".mdx")) { + backgroundArt = backgroundArt.substring(0, backgroundArt.length() - 4); + } + backgroundArt += ".mdx"; + final MdxModel model = (MdxModel) this.modelViewer.load(backgroundArt, this.modelViewer.mapPathSolver, + this.modelViewer.solverParams); + spriteFrame.setModel(model); + spriteFrame.setSequence(0); + viewport2 = this.fdfCoordinateResolutionDummyViewport; + inflatedFrame = spriteFrame; + } break; case Layer: // NOT HANDLED YET break; case String: - break; - case Texture: - String file = frameDefinition.getString("File"); - if (frameDefinition.has("DecorateFileNames") || ((parentDefinitionIfAvailable != null) - && parentDefinitionIfAvailable.has("DecorateFileNames"))) { - if (this.skin.hasField(file)) { - file = this.skin.getField(file); - } - else { - throw new IllegalStateException("Decorated file name lookup not available: " + file); - } + final Float textLength = frameDefinition.getFloat("TextLength"); + TextJustify justifyH = frameDefinition.getTextJustify("FontJustificationH"); + if (justifyH == null) { + justifyH = TextJustify.CENTER; } - final Texture texture = loadTexture(file); - final Vector4Definition texCoord = frameDefinition.getVector4("TexCoord"); - final TextureRegion texRegion; - if (texCoord != null) { - texRegion = new TextureRegion(texture, texCoord.getX(), texCoord.getZ(), texCoord.getY(), - texCoord.getW()); + TextJustify justifyV = frameDefinition.getTextJustify("FontJustificationV"); + if (justifyV == null) { + justifyV = TextJustify.MIDDLE; + } + + Color fontColor; + final Vector4Definition fontColorDefinition = frameDefinition.getVector4("FontColor"); + if (fontColorDefinition == null) { + fontColor = Color.WHITE; } else { - texRegion = new TextureRegion(texture); + fontColor = new Color(fontColorDefinition.getX(), fontColorDefinition.getY(), + fontColorDefinition.getZ(), fontColorDefinition.getW()); } - final TextureFrame textureFrame = new TextureFrame(frameDefinition.getName(), parent, texRegion); + final FontDefinition font = frameDefinition.getFont("Font"); + this.fontParam.size = (int) convertY(viewport2, font.getFontSize()); + if (this.fontParam.size == 0) { + this.fontParam.size = 24; + } + frameFont = this.fontGenerator.generateFont(this.fontParam); + final StringFrame stringFrame = new StringFrame(frameDefinition.getName(), parent, fontColor, justifyH, + justifyV, frameFont); + inflatedFrame = stringFrame; + String text = frameDefinition.getString("Text"); + if (text != null) { + final String decoratedString = this.templates.getDecoratedString(text); + if (decoratedString != text) { + text = decoratedString; + } + stringFrame.setText(text); + } + break; + case Texture: + final String file = frameDefinition.getString("File"); + final boolean decorateFileNames = frameDefinition.has("DecorateFileNames") + || ((parentDefinitionIfAvailable != null) && parentDefinitionIfAvailable.has("DecorateFileNames")); + final Vector4Definition texCoord = frameDefinition.getVector4("TexCoord"); + final TextureFrame textureFrame = new TextureFrame(frameDefinition.getName(), parent, decorateFileNames, + texCoord); + textureFrame.setTexture(file, this); inflatedFrame = textureFrame; break; default: break; } if (inflatedFrame != null) { - final Float width = frameDefinition.getFloat("Width"); + if (frameDefinition.has("SetAllPoints")) { + inflatedFrame.setSetAllPoints(true); + } + Float width = frameDefinition.getFloat("Width"); if (width != null) { - inflatedFrame.setWidth(convertX(this.viewport, width)); + inflatedFrame.setWidth(convertX(viewport2, width)); + } + else { + width = frameDefinition.getFloat("TextLength"); + if (width != null) { + if (frameFont != null) { + inflatedFrame.setWidth(convertX(viewport2, width * frameFont.getSpaceWidth())); + } + } } final Float height = frameDefinition.getFloat("Height"); if (height != null) { - inflatedFrame.setHeight(convertY(this.viewport, height)); + inflatedFrame.setHeight(convertY(viewport2, height)); + } + else if (frameDefinition.getFont("Font") != null) { + inflatedFrame.setHeight(convertY(viewport2, frameDefinition.getFont("Font").getFontSize())); } for (final AnchorDefinition anchor : frameDefinition.getAnchors()) { - inflatedFrame.addAnchor(new AnchorDefinition(anchor.getMyPoint(), - convertX(this.viewport, anchor.getX()), convertY(this.viewport, anchor.getY()))); + inflatedFrame.addAnchor(new AnchorDefinition(anchor.getMyPoint(), convertX(viewport2, anchor.getX()), + convertY(viewport2, anchor.getY()))); } + for (final SetPointDefinition setPointDefinition : frameDefinition.getSetPoints()) { + inflatedFrame.addSetPoint(new SetPoint(setPointDefinition.getMyPoint(), + getFrameByName(setPointDefinition.getOther(), 0 /* TODO: createContext */), + setPointDefinition.getOtherPoint(), convertX(viewport2, setPointDefinition.getX()), + convertY(viewport2, setPointDefinition.getY()))); + } + this.nameToFrame.put(frameDefinition.getName(), inflatedFrame); } else { // TODO in production throw some kind of exception here @@ -174,6 +307,10 @@ public final class GameUI extends AbstractUIFrame implements UIFrame { throw new UnsupportedOperationException("Not yet implemented"); } + public UIFrame getFrameByName(final String name, final int createContext) { + return this.nameToFrame.get(name); + } + public static float convertX(final Viewport viewport, final float fdfX) { return (fdfX / 0.8f) * viewport.getWorldWidth(); } @@ -182,7 +319,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame { return (fdfY / 0.6f) * viewport.getWorldHeight(); } - private Texture loadTexture(String path) { + public Texture loadTexture(String path) { if (!path.contains(".")) { path = path + ".blp"; } diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractRenderableFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractRenderableFrame.java index 65e1aae..46af7b3 100644 --- a/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractRenderableFrame.java +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractRenderableFrame.java @@ -3,28 +3,41 @@ package com.etheller.warsmash.parsers.fdf.frames; import java.util.ArrayList; import java.util.List; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.viewport.Viewport; import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition; import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint; public abstract class AbstractRenderableFrame implements UIFrame { + private static final boolean DEBUG_LOG = true; protected String name; protected UIFrame parent; - protected boolean visible; + protected boolean visible = true; protected int level; protected final Rectangle renderBounds = new Rectangle(0, 0, 0, 0); // in libgdx rendering space protected List anchors = new ArrayList<>(); + protected List setPoints = new ArrayList<>(); + private boolean setAllPoints; public AbstractRenderableFrame(final String name, final UIFrame parent) { this.name = name; this.parent = parent; } + @Override + public void setSetAllPoints(final boolean setAllPoints) { + this.setAllPoints = setAllPoints; + } + + @Override public void setWidth(final float width) { this.renderBounds.width = width; } + @Override public void setHeight(final float height) { this.renderBounds.height = height; } @@ -133,6 +146,7 @@ public abstract class AbstractRenderableFrame implements UIFrame { } } + @Override public void setFramePointX(final FramePoint framePoint, final float x) { if (this.renderBounds.width == 0) { this.renderBounds.x = x; @@ -192,6 +206,7 @@ public abstract class AbstractRenderableFrame implements UIFrame { } } + @Override public void setFramePointY(final FramePoint framePoint, final float y) { if (this.renderBounds.height == 0) { this.renderBounds.y = y; @@ -235,6 +250,11 @@ public abstract class AbstractRenderableFrame implements UIFrame { this.anchors.add(anchorDefinition); } + @Override + public void addSetPoint(final SetPoint setPointDefinition) { + this.setPoints.add(setPointDefinition); + } + @Override public void positionBounds(final Viewport viewport) { if (this.parent == null) { @@ -244,7 +264,7 @@ public abstract class AbstractRenderableFrame implements UIFrame { if ("ResourceBarFrame".equals(this.name)) { System.out.println("doing resource bar"); } - if (this.anchors.isEmpty()) { + if (this.anchors.isEmpty() && this.setPoints.isEmpty()) { this.renderBounds.x = this.parent.getFramePointX(FramePoint.LEFT); this.renderBounds.y = this.parent.getFramePointY(FramePoint.BOTTOM); } @@ -254,19 +274,35 @@ public abstract class AbstractRenderableFrame implements UIFrame { final float parentPointY = this.parent.getFramePointY(anchor.getMyPoint()); setFramePointX(anchor.getMyPoint(), parentPointX + anchor.getX()); setFramePointY(anchor.getMyPoint(), parentPointY + anchor.getY()); - System.out.println(getClass().getSimpleName() + ":" + this.name + " anchoring to: " + anchor); + if (DEBUG_LOG) { + System.out.println(getClass().getSimpleName() + ":" + this.name + " anchoring to: " + anchor); + } + } + for (final SetPoint setPoint : this.setPoints) { + final UIFrame other = setPoint.getOther(); + if (other == null) { + continue; + } + final float parentPointX = other.getFramePointX(setPoint.getOtherPoint()); + final float parentPointY = other.getFramePointY(setPoint.getOtherPoint()); + setFramePointX(setPoint.getMyPoint(), parentPointX + setPoint.getX()); + setFramePointY(setPoint.getMyPoint(), parentPointY + setPoint.getY()); } } - if (this.renderBounds.width == 0) { - this.renderBounds.width = this.parent.getFramePointX(FramePoint.RIGHT) - - this.parent.getFramePointX(FramePoint.LEFT); + if (this.setAllPoints) { + if (this.renderBounds.width == 0) { + this.renderBounds.width = this.parent.getFramePointX(FramePoint.RIGHT) + - this.parent.getFramePointX(FramePoint.LEFT); + } + if (this.renderBounds.height == 0) { + this.renderBounds.height = this.parent.getFramePointY(FramePoint.TOP) + - this.parent.getFramePointY(FramePoint.BOTTOM); + } } - if (this.renderBounds.height == 0) { - this.renderBounds.height = this.parent.getFramePointY(FramePoint.TOP) - - this.parent.getFramePointY(FramePoint.BOTTOM); + if (DEBUG_LOG) { + System.out.println( + getClass().getSimpleName() + ":" + this.name + " finishing position bounds: " + this.renderBounds); } - System.out.println( - getClass().getSimpleName() + ":" + this.name + " finishing position bounds: " + this.renderBounds); innerPositionBounds(viewport); } @@ -280,6 +316,7 @@ public abstract class AbstractRenderableFrame implements UIFrame { return this.level; } + @Override public void setVisible(final boolean visible) { this.visible = visible; } @@ -288,4 +325,13 @@ public abstract class AbstractRenderableFrame implements UIFrame { this.level = level; } + @Override + public final void render(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) { + if (this.visible) { + internalRender(batch, baseFont, glyphLayout); + } + } + + protected abstract void internalRender(SpriteBatch batch, BitmapFont baseFont, GlyphLayout glyphLayout); + } diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractUIFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractUIFrame.java index a203fdb..eb2889d 100644 --- a/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractUIFrame.java +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/AbstractUIFrame.java @@ -3,6 +3,8 @@ package com.etheller.warsmash.parsers.fdf.frames; import java.util.ArrayList; import java.util.List; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.utils.viewport.Viewport; @@ -21,9 +23,9 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements } @Override - public void render(final SpriteBatch batch) { + protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) { for (final UIFrame childFrame : this.childFrames) { - childFrame.render(batch); + childFrame.render(batch, baseFont, glyphLayout); } } diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/SetPoint.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/SetPoint.java new file mode 100644 index 0000000..0c54c20 --- /dev/null +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/SetPoint.java @@ -0,0 +1,40 @@ +package com.etheller.warsmash.parsers.fdf.frames; + +import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint; + +public class SetPoint { + private final FramePoint myPoint; + private final UIFrame other; + private final FramePoint otherPoint; + private final float x; + private final float y; + + public SetPoint(final FramePoint myPoint, final UIFrame other, final FramePoint otherPoint, final float x, + final float y) { + this.myPoint = myPoint; + this.other = other; + this.otherPoint = otherPoint; + this.x = x; + this.y = y; + } + + public FramePoint getMyPoint() { + return this.myPoint; + } + + public UIFrame getOther() { + return this.other; + } + + public FramePoint getOtherPoint() { + return this.otherPoint; + } + + public float getX() { + return this.x; + } + + public float getY() { + return this.y; + } +} diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/SpriteFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/SpriteFrame.java new file mode 100644 index 0000000..1cfbd53 --- /dev/null +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/SpriteFrame.java @@ -0,0 +1,52 @@ +package com.etheller.warsmash.parsers.fdf.frames; + +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.etheller.warsmash.viewer5.Scene; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; + +public class SpriteFrame extends AbstractRenderableFrame { + + private final Scene scene; + private MdxComplexInstance instance; + + public SpriteFrame(final String name, final UIFrame parent, final Scene scene) { + super(name, parent); + this.scene = scene; + } + + public void setModel(final MdxModel model) { + if (this.instance != null) { + this.scene.removeInstance(this.instance); + } + if (model != null) { + this.instance = (MdxComplexInstance) model.addInstance(); + this.instance.setSequenceLoopMode(1); + this.instance.setScene(this.scene); + this.instance.setLocation(this.renderBounds.x, this.renderBounds.y, 0); + } + else { + this.instance = null; + } + } + + @Override + protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) { + + } + + @Override + protected void innerPositionBounds(final Viewport viewport) { + + } + + public void setSequence(final int index) { + if (this.instance != null) { + this.instance.setSequence(index); + } + } + +} diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/StringFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/StringFrame.java new file mode 100644 index 0000000..92fa4a6 --- /dev/null +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/StringFrame.java @@ -0,0 +1,72 @@ +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; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify; + +public class StringFrame extends AbstractRenderableFrame { + private Color color; + private String text = "Default string"; + private final TextJustify justifyH; + private final TextJustify justifyV; + private final BitmapFont frameFont; + + public StringFrame(final String name, final UIFrame parent, final Color color, final TextJustify justifyH, + final TextJustify justifyV, final BitmapFont frameFont) { + super(name, parent); + this.color = color; + this.justifyH = justifyH; + this.justifyV = justifyV; + this.frameFont = frameFont; + this.text = name; + } + + public void setText(final String text) { + this.text = text; + } + + public void setColor(final Color color) { + this.color = color; + } + + @Override + protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) { + this.frameFont.setColor(this.color); + glyphLayout.setText(this.frameFont, this.text); + final float x; + switch (this.justifyH) { + case CENTER: + x = this.renderBounds.x + ((this.renderBounds.width - glyphLayout.width) / 2); + break; + case RIGHT: + x = (this.renderBounds.x + this.renderBounds.width) - glyphLayout.width; + break; + case LEFT: + default: + x = this.renderBounds.x; + break; + } + final float y; + switch (this.justifyV) { + case MIDDLE: + y = this.renderBounds.y + ((this.renderBounds.height + this.frameFont.getLineHeight()) / 2); + break; + case TOP: + y = (this.renderBounds.y + this.renderBounds.height); + break; + case BOTTOM: + default: + y = this.renderBounds.y + this.frameFont.getLineHeight(); + break; + } + this.frameFont.draw(batch, this.text, x, y); + } + + @Override + protected void innerPositionBounds(final Viewport viewport) { + } + +} diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/TextureFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/TextureFrame.java index 65b291b..da90653 100644 --- a/core/src/com/etheller/warsmash/parsers/fdf/frames/TextureFrame.java +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/TextureFrame.java @@ -1,19 +1,28 @@ package com.etheller.warsmash.parsers.fdf.frames; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.viewport.Viewport; +import com.etheller.warsmash.parsers.fdf.GameUI; +import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition; public class TextureFrame extends AbstractRenderableFrame { - private final TextureRegion texture; + private TextureRegion texture; + private final boolean decorateFileNames; + private final Vector4Definition texCoord; - public TextureFrame(final String name, final UIFrame parent, final TextureRegion texture) { + public TextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames, + final Vector4Definition texCoord) { super(name, parent); - this.texture = texture; + this.decorateFileNames = decorateFileNames; + this.texCoord = texCoord; } @Override - public void render(final SpriteBatch batch) { + protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) { batch.draw(this.texture, this.renderBounds.x, this.renderBounds.y, this.renderBounds.width, this.renderBounds.height); } @@ -22,4 +31,27 @@ public class TextureFrame extends AbstractRenderableFrame { protected void innerPositionBounds(final Viewport viewport) { } + public void setTexture(String file, final GameUI gameUI) { + if (this.decorateFileNames) { + file = gameUI.getSkinField(file); + } + final Texture texture = gameUI.loadTexture(file); + setTexture(texture); + } + + public void setTexture(final Texture texture) { + final TextureRegion texRegion; + if (this.texCoord != null) { + texRegion = new TextureRegion(texture, this.texCoord.getX(), this.texCoord.getZ(), this.texCoord.getY(), + this.texCoord.getW()); + } + else { + texRegion = new TextureRegion(texture); + } + this.texture = texRegion; + } + + public void setTexture(final TextureRegion texture) { + this.texture = texture; + } } diff --git a/core/src/com/etheller/warsmash/parsers/fdf/frames/UIFrame.java b/core/src/com/etheller/warsmash/parsers/fdf/frames/UIFrame.java index 8f20224..0615caa 100644 --- a/core/src/com/etheller/warsmash/parsers/fdf/frames/UIFrame.java +++ b/core/src/com/etheller/warsmash/parsers/fdf/frames/UIFrame.java @@ -1,22 +1,34 @@ package com.etheller.warsmash.parsers.fdf.frames; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.utils.viewport.Viewport; import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition; import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint; public interface UIFrame { - public void render(SpriteBatch batch); + public void render(SpriteBatch batch, BitmapFont baseFont, GlyphLayout glyphLayout); public float getFramePointX(FramePoint framePoint); public float getFramePointY(FramePoint framePoint); + void setFramePointX(final FramePoint framePoint, final float x); + + void setFramePointY(final FramePoint framePoint, final float y); + void positionBounds(final Viewport viewport); void addAnchor(final AnchorDefinition anchorDefinition); + void addSetPoint(SetPoint setPointDefinition); + void setWidth(final float width); void setHeight(final float height); + + void setSetAllPoints(boolean setAllPoints); + + void setVisible(boolean visible); } diff --git a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java index 95e853f..e19a5a0 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java +++ b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java @@ -9,6 +9,8 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.Recognizer; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; import com.badlogic.gdx.utils.viewport.Viewport; import com.etheller.interpreter.JassLexer; import com.etheller.interpreter.JassParser; @@ -20,6 +22,7 @@ import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression; import com.etheller.interpreter.ast.value.BooleanJassValue; import com.etheller.interpreter.ast.value.HandleJassType; import com.etheller.interpreter.ast.value.HandleJassValue; +import com.etheller.interpreter.ast.value.IntegerJassValue; import com.etheller.interpreter.ast.value.JassValue; import com.etheller.interpreter.ast.value.StringJassValue; import com.etheller.interpreter.ast.value.visitor.IntegerJassValueVisitor; @@ -32,6 +35,8 @@ import com.etheller.warsmash.datasources.DataSource; import com.etheller.warsmash.parsers.fdf.GameUI; import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition; import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint; +import com.etheller.warsmash.parsers.fdf.frames.SetPoint; +import com.etheller.warsmash.parsers.fdf.frames.StringFrame; import com.etheller.warsmash.parsers.fdf.frames.UIFrame; import com.etheller.warsmash.parsers.jass.triggers.BoolExprAnd; import com.etheller.warsmash.parsers.jass.triggers.BoolExprCondition; @@ -41,16 +46,19 @@ import com.etheller.warsmash.parsers.jass.triggers.BoolExprOr; import com.etheller.warsmash.parsers.jass.triggers.TriggerAction; import com.etheller.warsmash.parsers.jass.triggers.TriggerCondition; import com.etheller.warsmash.units.Element; +import com.etheller.warsmash.viewer5.Scene; +import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; public class Jass2 { public static final boolean REPORT_SYNTAX_ERRORS = true; public static JUIEnvironment loadJUI(final DataSource dataSource, final Viewport uiViewport, + final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener, final String... files) { final JassProgramVisitor jassProgramVisitor = new JassProgramVisitor(); - final JUIEnvironment environment = new JUIEnvironment(jassProgramVisitor, dataSource, uiViewport, - rootFrameListener); + final JUIEnvironment environment = new JUIEnvironment(jassProgramVisitor, dataSource, uiViewport, fontGenerator, + uiScene, war3MapViewer, rootFrameListener); for (final String jassFile : files) { try { JassLexer lexer; @@ -95,7 +103,8 @@ public class Jass2 { private Element skin; public JUIEnvironment(final JassProgramVisitor jassProgramVisitor, final DataSource dataSource, - final Viewport uiViewport, final RootFrameListener rootFrameListener) { + final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator, final Scene uiScene, + final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener) { final GlobalScope globals = jassProgramVisitor.getGlobals(); final HandleJassType frameHandleType = globals.registerHandleType("framehandle"); final HandleJassType framePointType = globals.registerHandleType("framepointtype"); @@ -128,7 +137,8 @@ public class Jass2 { final TriggerExecutionScope triggerScope) { final String skinArg = arguments.get(0).visit(StringJassValueVisitor.getInstance()); final Element skin = GameUI.loadSkin(dataSource, skinArg); - final GameUI gameUI = new GameUI(dataSource, skin, uiViewport); + final GameUI gameUI = new GameUI(dataSource, skin, uiViewport, fontGenerator, uiScene, + war3MapViewer); JUIEnvironment.this.gameUI = gameUI; JUIEnvironment.this.skin = skin; rootFrameListener.onCreate(gameUI); @@ -163,7 +173,33 @@ public class Jass2 { return new HandleJassValue(frameHandleType, simpleFrame); } }); - jassProgramVisitor.getJassNativeManager().createNative("FrameSetAbsPoint", new JassFunction() { + jassProgramVisitor.getJassNativeManager().createNative("CreateFrame", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final String templateName = arguments.get(0).visit(StringJassValueVisitor.getInstance()); + final UIFrame ownerFrame = arguments.get(1).visit(ObjectJassValueVisitor.getInstance()); + final int priority = arguments.get(2).visit(IntegerJassValueVisitor.getInstance()); + final int createContext = arguments.get(3).visit(IntegerJassValueVisitor.getInstance()); + + final UIFrame simpleFrame = JUIEnvironment.this.gameUI.createFrame(templateName, ownerFrame, + priority, createContext); + + return new HandleJassValue(frameHandleType, simpleFrame); + } + }); + jassProgramVisitor.getJassNativeManager().createNative("GetFrameByName", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final String templateName = arguments.get(0).visit(StringJassValueVisitor.getInstance()); + final int createContext = arguments.get(1).visit(IntegerJassValueVisitor.getInstance()); + + final UIFrame simpleFrame = JUIEnvironment.this.gameUI.getFrameByName(templateName, createContext); + return new HandleJassValue(frameHandleType, simpleFrame); + } + }); + jassProgramVisitor.getJassNativeManager().createNative("FrameSetAnchor", new JassFunction() { @Override public JassValue call(final List arguments, final GlobalScope globalScope, final TriggerExecutionScope triggerScope) { @@ -178,6 +214,71 @@ public class Jass2 { return null; } }); + jassProgramVisitor.getJassNativeManager().createNative("FrameSetAbsPoint", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final UIFrame frame = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + final FramePoint framePoint = arguments.get(1) + .visit(ObjectJassValueVisitor.getInstance()); + final double x = arguments.get(2).visit(RealJassValueVisitor.getInstance()); + final double y = arguments.get(3).visit(RealJassValueVisitor.getInstance()); + + frame.setFramePointX(framePoint, GameUI.convertX(uiViewport, (float) x)); + frame.setFramePointY(framePoint, GameUI.convertY(uiViewport, (float) y)); + return null; + } + }); + jassProgramVisitor.getJassNativeManager().createNative("FrameSetPoint", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final UIFrame frame = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + final FramePoint framePoint = arguments.get(1) + .visit(ObjectJassValueVisitor.getInstance()); + final UIFrame otherFrame = arguments.get(2).visit(ObjectJassValueVisitor.getInstance()); + final FramePoint otherPoint = arguments.get(3) + .visit(ObjectJassValueVisitor.getInstance()); + final double x = arguments.get(2).visit(RealJassValueVisitor.getInstance()); + final double y = arguments.get(3).visit(RealJassValueVisitor.getInstance()); + + frame.addSetPoint(new SetPoint(framePoint, otherFrame, otherPoint, + GameUI.convertX(uiViewport, (float) x), GameUI.convertY(uiViewport, (float) y))); + return null; + } + }); + jassProgramVisitor.getJassNativeManager().createNative("FrameSetText", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final StringFrame frame = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + final String text = arguments.get(1).visit(StringJassValueVisitor.getInstance()); + + frame.setText(text); + return null; + } + }); + jassProgramVisitor.getJassNativeManager().createNative("FrameSetTextColor", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final StringFrame frame = arguments.get(0).visit(ObjectJassValueVisitor.getInstance()); + final int colorInt = arguments.get(1).visit(IntegerJassValueVisitor.getInstance()); + frame.setColor(new Color(colorInt)); + return null; + } + }); + jassProgramVisitor.getJassNativeManager().createNative("ConvertColor", new JassFunction() { + @Override + public JassValue call(final List arguments, final GlobalScope globalScope, + final TriggerExecutionScope triggerScope) { + final int a = arguments.get(0).visit(IntegerJassValueVisitor.getInstance()); + final int r = arguments.get(1).visit(IntegerJassValueVisitor.getInstance()); + final int g = arguments.get(2).visit(IntegerJassValueVisitor.getInstance()); + final int b = arguments.get(3).visit(IntegerJassValueVisitor.getInstance()); + return new IntegerJassValue(a | (b << 8) | (g << 16) | (r << 24)); + } + }); jassProgramVisitor.getJassNativeManager().createNative("FramePositionBounds", new JassFunction() { @Override public JassValue call(final List arguments, final GlobalScope globalScope, diff --git a/core/src/com/etheller/warsmash/parsers/mdlx/AnimatedObject.java b/core/src/com/etheller/warsmash/parsers/mdlx/AnimatedObject.java index e665208..8d93db5 100644 --- a/core/src/com/etheller/warsmash/parsers/mdlx/AnimatedObject.java +++ b/core/src/com/etheller/warsmash/parsers/mdlx/AnimatedObject.java @@ -25,7 +25,11 @@ public abstract class AnimatedObject implements Chunk, MdlxBlock { public void readTimelines(final LittleEndianDataInputStream stream, long size) throws IOException { while (size > 0) { final War3ID name = new War3ID(Integer.reverseBytes(stream.readInt())); - final Timeline timeline = AnimationMap.ID_TO_TAG.get(name).getImplementation().createTimeline(); + final AnimationMap animationMap = AnimationMap.ID_TO_TAG.get(name); + if (animationMap == null) { + throw new IllegalStateException("Unable to parse: '" + name + "'"); + } + final Timeline timeline = animationMap.getImplementation().createTimeline(); timeline.readMdx(stream, name); diff --git a/core/src/com/etheller/warsmash/util/FastNumberFormat.java b/core/src/com/etheller/warsmash/util/FastNumberFormat.java new file mode 100644 index 0000000..8741b4d --- /dev/null +++ b/core/src/com/etheller/warsmash/util/FastNumberFormat.java @@ -0,0 +1,24 @@ +package com.etheller.warsmash.util; + +public class FastNumberFormat { + private static final StringBuilder RECYCLE_STRING_BUILDER = new StringBuilder(); + + public static String formatWholeNumber(final float value) { + int intValue = (int) value; + RECYCLE_STRING_BUILDER.setLength(0); + do { + RECYCLE_STRING_BUILDER.append(intValue % 10); + intValue /= 10; + } + while (intValue > 0); + final int len = RECYCLE_STRING_BUILDER.length(); + final int halfLength = len / 2; + for (int i = 0; i < halfLength; i++) { + final char swapCharA = RECYCLE_STRING_BUILDER.charAt(i); + final char swapCharB = RECYCLE_STRING_BUILDER.charAt(len - 1 - i); + RECYCLE_STRING_BUILDER.setCharAt(len - 1 - i, swapCharA); + RECYCLE_STRING_BUILDER.setCharAt(i, swapCharB); + } + return RECYCLE_STRING_BUILDER.toString(); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java b/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java index fb80449..ded730c 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/mdx/MdxComplexInstance.java @@ -63,6 +63,7 @@ public class MdxComplexInstance extends ModelInstance { public FloatBuffer worldMatricesCopyHeap; public DataTexture boneTexture; public Texture[] replaceableTextures = new Texture[WarsmashConstants.REPLACEABLE_TEXTURE_LIMIT]; + private float animationSpeed = 1.0f; public MdxComplexInstance(final MdxModel model) { super(model); @@ -522,7 +523,7 @@ public class MdxComplexInstance extends ModelInstance { if (sequenceId != -1) { final Sequence sequence = model.sequences.get(sequenceId); final long[] interval = sequence.getInterval(); - final int frameTime = (int) (dt * 1000); + final int frameTime = (int) (dt * 1000 * this.animationSpeed); this.frame += frameTime; this.counter += frameTime; @@ -713,4 +714,8 @@ public class MdxComplexInstance extends ModelInstance { } return false; } + + public void setAnimationSpeed(final float speedRatio) { + this.animationSpeed = speedRatio; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/Doodad.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/Doodad.java index d39df24..f969f0c 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/Doodad.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/Doodad.java @@ -9,13 +9,19 @@ import com.etheller.warsmash.viewer5.ModelInstance; import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; public class Doodad { + private static final int SAMPLE_RADIUS = 4; private static final War3ID TEX_FILE = War3ID.fromString("btxf"); private static final War3ID TEX_ID = War3ID.fromString("btxi"); public final ModelInstance instance; private final MutableGameObject row; + private final float maxPitch; + private final float maxRoll; public Doodad(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) { + this.maxPitch = maxPitch; + this.maxRoll = maxRoll; final boolean isSimple = row.readSLKTagBoolean("lightweight"); ModelInstance instance; @@ -27,7 +33,38 @@ public class Doodad { } instance.move(doodad.getLocation()); - instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, doodad.getAngle())); + // TODO: the following pitch/roll system is a heuristic, and we probably want to + // revisit it later. + // Specifically, I was pretty convinced that whichever is applied first + // (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 + // (instead of measuring down from an imaginary flat ground plane, as we do + // currently). + final float facingRadians = doodad.getAngle(); + float pitch, roll; + final float x = doodad.getLocation()[0]; + final float y = doodad.getLocation()[1]; + final float pitchSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(facingRadians)); + final float pitchSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(facingRadians)); + final float pitchSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(facingRadians)); + final float pitchSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(facingRadians)); + final float pitchSampleGroundHeight1 = map.terrain.getGroundHeight(pitchSampleBackwardX, pitchSampleBackwardY); + final float pitchSampleGorundHeight2 = map.terrain.getGroundHeight(pitchSampleForwardX, pitchSampleForwardY); + pitch = Math.min(maxPitch, + (float) Math.atan2(pitchSampleGorundHeight2 - pitchSampleGroundHeight1, SAMPLE_RADIUS * 2)); + final double leftOfFacingAngle = facingRadians + (Math.PI / 2); + final float rollSampleForwardX = x + (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle)); + final float rollSampleForwardY = y + (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle)); + final float rollSampleBackwardX = x - (SAMPLE_RADIUS * (float) Math.cos(leftOfFacingAngle)); + final float rollSampleBackwardY = y - (SAMPLE_RADIUS * (float) Math.sin(leftOfFacingAngle)); + final float rollSampleGroundHeight1 = map.terrain.getGroundHeight(rollSampleBackwardX, rollSampleBackwardY); + final float rollSampleGroundHeight2 = map.terrain.getGroundHeight(rollSampleForwardX, rollSampleForwardY); + roll = Math.min(maxRoll, + (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_Y, -pitch)); + instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_X, roll)); +// instance.rotate(new Quaternion().setEulerAnglesRad(facingRadians, 0, 0)); instance.scale(doodad.getScale()); if (type == WorldEditorDataType.DOODADS) { final float defScale = row.readSLKTagFloat("defScale"); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/TerrainDoodad.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/TerrainDoodad.java index 9db6c47..eda3fc4 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/TerrainDoodad.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/TerrainDoodad.java @@ -1,23 +1,31 @@ package com.etheller.warsmash.viewer5.handlers.w3x; +import java.awt.image.BufferedImage; + import com.badlogic.gdx.math.Quaternion; import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject; import com.etheller.warsmash.util.RenderMathUtils; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance; import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; -import com.etheller.warsmash.viewer5.handlers.mdx.MdxSimpleInstance; public class TerrainDoodad { private static final float[] locationHeap = new float[3]; - public final MdxSimpleInstance instance; + public final MdxComplexInstance instance; private final MutableGameObject row; public TerrainDoodad(final War3MapViewer map, final MdxModel model, final MutableGameObject row, - final com.etheller.warsmash.parsers.w3x.doo.TerrainDoodad doodad) { + final com.etheller.warsmash.parsers.w3x.doo.TerrainDoodad doodad, final BufferedImage pathingTextureImage) { final float[] centerOffset = map.terrain.centerOffset; - final MdxSimpleInstance instance = (MdxSimpleInstance) model.addInstance(1); + final MdxComplexInstance instance = (MdxComplexInstance) model.addInstance(0); - locationHeap[0] = (doodad.getLocation()[0] * 128) + centerOffset[0] + 128; - locationHeap[1] = (doodad.getLocation()[1] * 128) + centerOffset[1] + 128; + final int textureWidth = pathingTextureImage.getWidth(); + final int textureHeight = pathingTextureImage.getHeight(); + final int textureWidthTerrainCells = textureWidth / 4; + final int textureHeightTerrainCells = textureHeight / 4; + final int minCellX = ((int) doodad.getLocation()[0]); + final int minCellY = ((int) doodad.getLocation()[1]); + locationHeap[0] = ((minCellX * 128) + (textureWidthTerrainCells * 64) + centerOffset[0]); + locationHeap[1] = ((minCellY * 128) + (textureHeightTerrainCells * 64) + centerOffset[1]); instance.move(locationHeap); instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java index b12ee51..7b9a16b 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java @@ -69,11 +69,12 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderItem; import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitClassification; 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.CAbilityAttack; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.projectile.CAttackProjectile; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile; 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.PointAbilityTargetCheckReceiver; @@ -143,6 +144,7 @@ public class War3MapViewer extends ModelViewer { public List selected = new ArrayList<>(); private DataTable unitAckSoundsTable; private DataTable miscData; + private DataTable unitGlobalStrings; private MdxComplexInstance confirmationInstance; public CSimulation simulation; private float updateTime; @@ -231,6 +233,20 @@ public class War3MapViewer extends ModelViewer { try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("UI\\MiscData.txt")) { this.miscData.readTXT(miscDataTxtStream, true); } + try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("Units\\MiscData.txt")) { + this.miscData.readTXT(miscDataTxtStream, true); + } + this.unitGlobalStrings = new DataTable(worldEditStrings); + try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("Units\\UnitGlobalStrings.txt")) { + this.unitGlobalStrings.readTXT(miscDataTxtStream, true); + } + final Element categories = this.unitGlobalStrings.get("Categories"); + for (final CUnitClassification unitClassification : CUnitClassification.values()) { + if (unitClassification.getLocaleKey() != null) { + final String displayName = categories.getField(unitClassification.getLocaleKey()); + unitClassification.setDisplayName(displayName); + } + } this.selectionCircleSizes.clear(); final Element selectionCircleData = this.miscData.get("SelectionCircle"); final int selectionCircleNumSizes = selectionCircleData.getFieldValue("NumSizes"); @@ -335,7 +351,7 @@ public class War3MapViewer extends ModelViewer { } final Warcraft3MapObjectData modifications = this.mapMpq.readModifications(); - this.simulation = new CSimulation(modifications.getUnits(), modifications.getAbilities(), + this.simulation = new CSimulation(this.miscData, modifications.getUnits(), modifications.getAbilities(), new ProjectileCreator() { @Override public CAttackProjectile create(final CSimulation simulation, final CUnit source, @@ -443,6 +459,8 @@ public class War3MapViewer extends ModelViewer { fileVar += ".mdx"; + final float maxPitch = row.readSLKTagFloat("maxPitch"); + final float maxRoll = row.readSLKTagFloat("maxRoll"); if (type == WorldEditorDataType.DESTRUCTIBLES) { final String shadowString = row.readSLKTag("shadow"); if ((shadowString != null) && (shadowString.length() > 0) && !"_".equals(shadowString)) { @@ -490,14 +508,18 @@ public class War3MapViewer extends ModelViewer { model = (MdxModel) this.load(fileVar, this.mapPathSolver, this.solverParams); } - this.doodads.add(new Doodad(this, model, row, doodad, type)); + this.doodads.add(new Doodad(this, model, row, doodad, type, maxPitch, maxRoll)); } } // Cliff/Terrain doodads. for (final com.etheller.warsmash.parsers.w3x.doo.TerrainDoodad doodad : doo.getTerrainDoodads()) { final MutableGameObject row = modifications.getDoodads().get(doodad.getId()); - String file = "UI\\Feedback\\WaypointFlags\\WaypointFlag.mdx";// row.readSLKTag("file"); + String file = row.readSLKTag("file");// + if ("".equals(file)) { + final String blaBla = row.readSLKTag("file"); + System.out.println("bla"); + } if (file.toLowerCase().endsWith(".mdl")) { file = file.substring(0, file.length() - 4); } @@ -506,7 +528,47 @@ public class War3MapViewer extends ModelViewer { } final MdxModel model = (MdxModel) this.load(file, this.mapPathSolver, this.solverParams); - this.terrainDoodads.add(new TerrainDoodad(this, model, row, doodad)); + final String pathingTexture = row.readSLKTag("pathTex"); + BufferedImage pathingTextureImage; + if ((pathingTexture != null) && (pathingTexture.length() > 0) && !"_".equals(pathingTexture)) { + + pathingTextureImage = this.filePathToPathingMap.get(pathingTexture.toLowerCase()); + if (pathingTextureImage == null) { + if (this.mapMpq.has(pathingTexture)) { + try { + pathingTextureImage = TgaFile.readTGA(pathingTexture, + this.mapMpq.getResourceAsStream(pathingTexture)); + this.filePathToPathingMap.put(pathingTexture.toLowerCase(), pathingTextureImage); + } + catch (final Exception exc) { + exc.printStackTrace(); + } + } + } + } + else { + pathingTextureImage = null; + } + if (pathingTextureImage != null) { + // blit out terrain cells under this TerrainDoodad + final int textureWidth = pathingTextureImage.getWidth(); + final int textureHeight = pathingTextureImage.getHeight(); + final int textureWidthTerrainCells = textureWidth / 4; + final int textureHeightTerrainCells = textureHeight / 4; + final int minCellX = ((int) doodad.getLocation()[0]); + final int minCellY = ((int) doodad.getLocation()[1]); + final int maxCellX = (minCellX + textureWidthTerrainCells) - 1; + final int maxCellY = (minCellY + textureHeightTerrainCells) - 1; + for (int j = minCellY; j <= maxCellY; j++) { + for (int i = minCellX; i <= maxCellX; i++) { + this.terrain.removeTerrainCellWithoutFlush(i, j); + } + } + this.terrain.flushRemovedTerrainCells(); + } + + System.out.println("Loading terrain doodad: " + file); + this.terrainDoodads.add(new TerrainDoodad(this, model, row, doodad, pathingTextureImage)); } this.doodadsReady = true; diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/RenderCorner.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/RenderCorner.java index f974f84..421385e 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/RenderCorner.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/RenderCorner.java @@ -7,6 +7,7 @@ public class RenderCorner extends Corner { public boolean romp; public float rampAdjust; public float depth; + public boolean hideCliff; public RenderCorner(final Corner corner) { super(corner); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java index 0634a34..c353fe4 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/environment/Terrain.java @@ -544,7 +544,7 @@ public class Terrain { final RenderCorner topLeft = this.corners[i][j + 1]; final RenderCorner topRight = this.corners[i + 1][j + 1]; - if (bottomLeft.cliff) { + if (bottomLeft.cliff && !bottomLeft.hideCliff) { final int base = Math.min(Math.min(bottomLeft.getLayerHeight(), bottomRight.getLayerHeight()), Math.min(topLeft.getLayerHeight(), topRight.getLayerHeight())); @@ -672,6 +672,33 @@ public class Terrain { uploadGroundTexture(); } + public void removeTerrainCell(final int i, final int j) { + this.groundTextureList[(((j * (this.columns - 1)) + i) * 4) + 3] |= 0b1000000000000000; + this.corners[i][j].hideCliff = true; + uploadGroundTexture(); + try { + updateCliffMeshes(new Rectangle(i - 1, j - 1, 1, 1)); // TODO does this work? + } + catch (final IOException e) { + throw new RuntimeException(e); + } + } + + public void removeTerrainCellWithoutFlush(final int i, final int j) { + this.groundTextureList[(((j * (this.columns - 1)) + i) * 4) + 3] |= 0b1000000000000000; + this.corners[i][j].hideCliff = true; + } + + public void flushRemovedTerrainCells() { + uploadGroundTexture(); + try { + updateCliffMeshes(new Rectangle(0, 0, this.columns - 1, this.rows - 1)); + } + catch (final IOException e) { + throw new RuntimeException(e); + } + } + private void uploadGroundTexture() { if (this.groundTextureData != -1) { Gdx.gl30.glBindTexture(GL30.GL_TEXTURE_2D, this.groundTextureData); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/OrientationInterpolation.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/OrientationInterpolation.java new file mode 100644 index 0000000..e761e7c --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/OrientationInterpolation.java @@ -0,0 +1,61 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; + +/** + * We observe this table during gameplay but I haven't found it anywhere in the + * data yet. So, I'm making my own. + */ +public enum OrientationInterpolation { + OI0(0.07f, 0.2f, 999f), + OI1(0.03f, 0.1f, 0.04f), + OI2(0.015f, 1.0f, 999), + OI3(0.005f, 0.1f, 0.0043f), + OI4(0.04f, 0.15f, 0.01f), + OI5(0.05f, 0.18f, 0.015f), + OI6(0.1f, 0.3f, 0.1f), + OI7(0.003f, 0.08f, 0.0027f), + OI8(0.001f, 0.05f, 0.001f); + + public static OrientationInterpolation[] VALUES = values(); + + private float startingAcceleration; + private float maxVelocity; + private float endingNegativeAcceleration; + private float endingAccelCutoff; + private float startingAccelCutoff; + + private OrientationInterpolation(final float startingAcceleration, final float maxVelocity, + final float endingNegativeAcceleration) { + this.startingAcceleration = startingAcceleration; + this.maxVelocity = maxVelocity; + this.endingNegativeAcceleration = endingNegativeAcceleration; + this.endingAccelCutoff = endingAccelCutoff(maxVelocity, endingNegativeAcceleration); + this.startingAccelCutoff = endingAccelCutoff(maxVelocity, startingAcceleration); + } + + public float getStartingAcceleration() { + return this.startingAcceleration; + } + + public float getMaxVelocity() { + return this.maxVelocity; + } + + public float getEndingNegativeAcceleration() { + return this.endingNegativeAcceleration; + } + + public float getEndingAccelCutoff() { + return this.endingAccelCutoff; + } + + public float getStartingAccelCutoff() { + return this.startingAccelCutoff; + } + + private static float endingAccelCutoff(final float maxVelocity, final float endingAccel) { + final float endingAccelFinishingTime = maxVelocity / endingAccel; + final float endingDistanceRequired = (maxVelocity * endingAccelFinishingTime) + - ((endingAccel / 2) * (endingAccelFinishingTime * endingAccelFinishingTime)); + return endingDistanceRequired; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus.java new file mode 100644 index 0000000..1a764b4 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus.java @@ -0,0 +1,49 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + +public class ParseBogus { + + public static void main(final String[] args) { + final File bogusDataFile = new File("E:\\Games\\Warcraft III Patch 1.22\\Logs\\MyReteraTest.pre"); + final float[][] cubeIndexToData = new float[9][44]; + try { + final List allLines = Files.readAllLines(bogusDataFile.toPath()); + for (final String line : allLines) { + final int cubeStringIndex = line.indexOf("Cube"); + if (cubeStringIndex != -1) { + final int colonStringIndex = line.indexOf(':'); + final int cubeIndex = Integer.parseInt(line.substring(cubeStringIndex + 4, colonStringIndex)); + final int dataIndex = Integer.parseInt(line.substring(line.indexOf('"') + 1, cubeStringIndex)); + final float value = Float.parseFloat(line.substring(colonStringIndex + 1, line.indexOf(".txt"))); + cubeIndexToData[cubeIndex][dataIndex] = value; + } + } + } + catch (final IOException e) { + e.printStackTrace(); + } + final boolean[] spun = new boolean[9]; + for (int j = 0; j < cubeIndexToData[0].length; j++) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < cubeIndexToData.length; i++) { + if (sb.length() > 0) { + sb.append(','); + } + float value = cubeIndexToData[i][j]; + if (value > 280) { + spun[i] = true; + } + else if ((value < 100) && spun[i]) { + value += 360; + } + sb.append(Math.toRadians(value)); + } + System.out.println(sb); + } + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus2.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus2.java new file mode 100644 index 0000000..da2e022 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus2.java @@ -0,0 +1,60 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + +public class ParseBogus2 { + + private static final int _383 = 280; + + public static void main(final String[] args) { + final float[][] cubeIndexToData = new float[9][_383]; + for (int fileIdx = 0; fileIdx < _383; fileIdx++) { + final File bogusDataFile = new File( + "E:\\Games\\Warcraft III Patch 1.22\\Logs\\MyReteraTest" + (fileIdx + 1) + ".pre"); + try { + final List allLines = Files.readAllLines(bogusDataFile.toPath()); + for (final String line : allLines) { + final int cubeStringIndex = line.indexOf("Cube"); + if (cubeStringIndex != -1) { + final int colonStringIndex = line.indexOf(':'); + final int cubeIndex = Integer.parseInt(line.substring(cubeStringIndex + 4, colonStringIndex)); + final int dataIndex = Integer.parseInt(line.substring(line.indexOf('"') + 1, cubeStringIndex)); + final float value = Float + .parseFloat(line.substring(colonStringIndex + 1, line.indexOf(".txt"))); + cubeIndexToData[cubeIndex][dataIndex] = value; + } + } + } + catch (final IOException e) { + e.printStackTrace(); + } + } + final boolean[] spun = new boolean[9]; + for (int j = 0; j < cubeIndexToData[0].length; j++) { + if ((j % 3) == 0) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < cubeIndexToData.length; i++) { + if (sb.length() > 0) { + sb.append(','); + } + float value = cubeIndexToData[i][j]; +// if (value > 280) { +// spun[i] = true; +// } +// else if ((value < 100) && spun[i]) { +// value += 360; +// } + if ((j / 3) < 32) { + value += 360; + } + sb.append(Math.toRadians(value)); + } + System.out.println(sb); + } + } + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus3.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus3.java new file mode 100644 index 0000000..f239eec --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus3.java @@ -0,0 +1,19 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; + +public class ParseBogus3 { + public static float endingAccelCutoff(final float maxVelocity, final float endingAccel) { + final float endingAccelFinishingTime = maxVelocity / endingAccel; + final float endingDistanceRequired = (maxVelocity * endingAccelFinishingTime) + - ((endingAccel / 2) * (endingAccelFinishingTime * endingAccelFinishingTime)); + return endingDistanceRequired; + } + + public static void main(final String[] args) { + System.out.println(endingAccelCutoff(0.1f, 0.04f)); + + for (final OrientationInterpolation oi : OrientationInterpolation.values()) { + System.out.println(oi + ": " + oi.getStartingAcceleration() + "," + oi.getMaxVelocity() + "," + + oi.getEndingNegativeAcceleration() + "->" + oi.getEndingAccelCutoff()); + } + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus4.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus4.java new file mode 100644 index 0000000..054e481 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/ParseBogus4.java @@ -0,0 +1,80 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; + +import java.util.Arrays; + +public class ParseBogus4 { + + public static void main(final String[] args) { + + final OrientationInterpolation[] interpolations = OrientationInterpolation.values(); + final float[] velocities = new float[interpolations.length]; + final float[] signs = new float[interpolations.length]; + Arrays.fill(signs, -1); + signs[1] = signs[6] = 1; + final float[] angles = new float[interpolations.length]; + Arrays.fill(angles, (float) ((3 * Math.PI) / 2)); + final boolean[] spun = new boolean[interpolations.length]; + + for (int j = 0; j < 140; j++) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < interpolations.length; i++) { + float simulationFacing = 90; + if (simulationFacing < 0) { + simulationFacing += 360; + } + float renderFacing = (float) Math.toDegrees(angles[i]); + if (renderFacing < 0) { + renderFacing += 360; + } + float facingDelta = simulationFacing - renderFacing; + if (facingDelta < -180) { + facingDelta = 360 + facingDelta; + } + if (facingDelta > 180) { + facingDelta = -360 + facingDelta; + } + final float absoluteFacingDelta = Math.abs(facingDelta); + + final float absoluteFacingDeltaRadians = (float) Math.toRadians(absoluteFacingDelta); + float acceleration; + final boolean endPhase = (absoluteFacingDeltaRadians <= interpolations[i].getEndingAccelCutoff()) + && ((velocities[i] * signs[i]) > 0); + if (endPhase) { + acceleration = -interpolations[i].getEndingNegativeAcceleration() * signs[i]; + if (((velocities[i] + acceleration) * signs[i]) <= 0.001) { + velocities[i] = absoluteFacingDeltaRadians * signs[i] * 0.25f; + } + else { + velocities[i] = velocities[i] + acceleration; + } + } + else { + acceleration = interpolations[i].getStartingAcceleration() * signs[i]; + velocities[i] = velocities[i] + acceleration; + } + if ((velocities[i] * signs[i]) > interpolations[i].getMaxVelocity()) { + velocities[i] = interpolations[i].getMaxVelocity() * signs[i]; + } + + float angleToAdd = (float) (/* Math.signum(facingDelta) **/ Math + .toDegrees(velocities[i]) /* * deltaTime */); + if (absoluteFacingDelta < Math.abs(angleToAdd)) { + angleToAdd = facingDelta; + } + double newDegreesAngle = (((Math.toDegrees(angles[i]) + angleToAdd) % 360) + 360) % 360; + if (newDegreesAngle > 280) { + spun[i] = true; + } + else if ((newDegreesAngle < 100) && spun[i]) { + newDegreesAngle += 360; + } + angles[i] = (float) Math.toRadians(newDegreesAngle); + if (sb.length() > 0) { + sb.append(','); + } + sb.append(angles[i]); + } + System.out.println(sb.toString()); + } + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderAttackProjectile.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderAttackProjectile.java index a2557bd..4293f71 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderAttackProjectile.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderAttackProjectile.java @@ -10,7 +10,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; import com.etheller.warsmash.viewer5.handlers.w3x.IndexedSequence; import com.etheller.warsmash.viewer5.handlers.w3x.StandSequence; import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.projectile.CAttackProjectile; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile; public class RenderAttackProjectile { private static final Quaternion pitchHeap = new Quaternion(); @@ -45,7 +45,8 @@ public class RenderAttackProjectile { final float d2DToTarget = (float) StrictMath.sqrt((dxToTarget * dxToTarget) + (dyToTarget * dyToTarget)); final float startingDistance = d2DToTarget + this.totalTravelDistance; this.targetHeight = (war3MapViewer.terrain.getGroundHeight(targetX, targetY) - + this.simulationProjectile.getTarget().getFlyHeight()); + + this.simulationProjectile.getTarget().getFlyHeight() + + this.simulationProjectile.getTarget().getImpactZ()); this.arcPeakHeight = arc * startingDistance; this.yaw = (float) StrictMath.atan2(dyToTarget, dxToTarget); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderUnit.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderUnit.java index 74458f3..318f948 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderUnit.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderUnit.java @@ -2,11 +2,12 @@ package com.etheller.warsmash.viewer5.handlers.w3x.rendersim; import java.util.ArrayList; import java.util.EnumSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Quaternion; -import com.etheller.warsmash.parsers.mdlx.Sequence; import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject; import com.etheller.warsmash.util.ImageUtils; import com.etheller.warsmash.util.RenderMathUtils; @@ -15,15 +16,15 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance; import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; -import com.etheller.warsmash.viewer5.handlers.w3x.IndexedSequence; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag; import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover; import com.etheller.warsmash.viewer5.handlers.w3x.StandSequence; import com.etheller.warsmash.viewer5.handlers.w3x.UnitSoundset; import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder; 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.abilities.CAbility; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityHoldPosition; @@ -32,13 +33,13 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityP import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityStop; public class RenderUnit { - private static final double GLOBAL_TURN_RATE = Math.toDegrees(7f); private static final Quaternion tempQuat = new Quaternion(); private static final War3ID RED = War3ID.fromString("uclr"); private static final War3ID GREEN = War3ID.fromString("uclg"); private static final War3ID BLUE = War3ID.fromString("uclb"); private static final War3ID MODEL_SCALE = War3ID.fromString("usca"); private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh"); + private static final War3ID ORIENTATION_INTERPOLATION = War3ID.fromString("uori"); private static final float[] heapZ = new float[3]; public final MdxComplexInstance instance; public final MutableGameObject row; @@ -48,8 +49,6 @@ public class RenderUnit { public final MdxModel portraitModel; public int playerIndex; private final CUnit simulationUnit; - private COrder lastOrder; - private AnimationTokens.PrimaryTag lastOrderAnimation; public SplatMover shadow; public SplatMover selectionCircle; private final List commandCardIcons = new ArrayList<>(); @@ -60,10 +59,11 @@ public class RenderUnit { private boolean swimming; - private boolean alreadyPlayedDeath = false; + private final boolean alreadyPlayedDeath = false; - private final EnumSet secondaryAnimationTags = EnumSet - .noneOf(AnimationTokens.SecondaryTag.class); + private final UnitAnimationListenerImpl unitAnimationListenerImpl; + private OrientationInterpolation orientationInterpolation; + private float currentTurnVelocity = 0; public RenderUnit(final War3MapViewer map, final MdxModel model, final MutableGameObject row, final com.etheller.warsmash.parsers.w3x.unitsdoo.Unit unit, final UnitSoundset soundset, @@ -82,9 +82,11 @@ public class RenderUnit { this.y = simulationUnit.getY(); instance.rotate(tempQuat.setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, angle)); instance.scale(unit.getScale()); - this.playerIndex = unit.getPlayer(); + this.playerIndex = unit.getPlayer() & 0xFFFF; instance.setTeamColor(this.playerIndex); instance.setScene(map.worldScene); + this.unitAnimationListenerImpl = new UnitAnimationListenerImpl(instance); + simulationUnit.setUnitAnimationListener(this.unitAnimationListenerImpl); if (row != null) { heapZ[2] = simulationUnit.getFlyHeight(); @@ -104,6 +106,12 @@ public class RenderUnit { instance.uniformScale(row.getFieldAsFloat(scale, 0)); this.selectionScale = row.getFieldAsFloat(War3MapViewer.UNIT_SELECT_SCALE, 0); + int orientationInterpolationOrdinal = row.getFieldAsInteger(ORIENTATION_INTERPOLATION, 0); + if ((orientationInterpolationOrdinal < 0) + || (orientationInterpolationOrdinal >= OrientationInterpolation.VALUES.length)) { + orientationInterpolationOrdinal = 0; + } + this.orientationInterpolation = OrientationInterpolation.VALUES[orientationInterpolationOrdinal]; } this.instance = instance; @@ -179,14 +187,11 @@ public class RenderUnit { else { groundHeight = map.terrain.getGroundHeight(x, y); } - boolean changedAnimationTags = false; if (swimming && !this.swimming) { - this.secondaryAnimationTags.add(AnimationTokens.SecondaryTag.SWIM); - changedAnimationTags = true; + this.unitAnimationListenerImpl.addSecondaryTag(AnimationTokens.SecondaryTag.SWIM); } else if (!swimming && this.swimming) { - this.secondaryAnimationTags.remove(AnimationTokens.SecondaryTag.SWIM); - changedAnimationTags = true; + this.unitAnimationListenerImpl.removeSecondaryTag(AnimationTokens.SecondaryTag.SWIM); } this.swimming = swimming; this.location[2] = this.simulationUnit.getFlyHeight() + groundHeight; @@ -207,52 +212,41 @@ public class RenderUnit { facingDelta = -360 + facingDelta; } final float absoluteFacingDelta = Math.abs(facingDelta); - float angleToAdd = (float) (Math.signum(facingDelta) * GLOBAL_TURN_RATE * deltaTime); + final float turningSign = Math.signum(facingDelta); + + final float absoluteFacingDeltaRadians = (float) Math.toRadians(absoluteFacingDelta); + float acceleration; + final boolean endPhase = (absoluteFacingDeltaRadians <= this.orientationInterpolation.getEndingAccelCutoff()) + && ((this.currentTurnVelocity * turningSign) > 0); + if (endPhase) { + this.currentTurnVelocity = (1 + - ((this.orientationInterpolation.getEndingAccelCutoff() - absoluteFacingDeltaRadians) + / this.orientationInterpolation.getEndingAccelCutoff())) + * (this.orientationInterpolation.getMaxVelocity()) * turningSign; + } + else { + acceleration = this.orientationInterpolation.getStartingAcceleration() * turningSign; + this.currentTurnVelocity = this.currentTurnVelocity + acceleration; + } + if ((this.currentTurnVelocity * turningSign) > this.orientationInterpolation.getMaxVelocity()) { + this.currentTurnVelocity = this.orientationInterpolation.getMaxVelocity() * turningSign; + } + float angleToAdd = (float) ((Math.toDegrees(this.currentTurnVelocity) * deltaTime) / 0.03f); + if (absoluteFacingDelta < Math.abs(angleToAdd)) { angleToAdd = facingDelta; + this.currentTurnVelocity = 0.0f; } this.facing = (((this.facing + angleToAdd) % 360) + 360) % 360; this.instance.setLocalRotation(tempQuat.setFromAxis(RenderMathUtils.VEC3_UNIT_Z, this.facing)); map.worldScene.instanceMoved(this.instance, this.location[0], this.location[1]); - final MdxComplexInstance mdxComplexInstance = this.instance; - final COrder currentOrder = this.simulationUnit.getCurrentOrder(); - if (this.simulationUnit.getLife() <= 0) { - final MdxModel model = (MdxModel) mdxComplexInstance.model; - final List sequences = model.getSequences(); - IndexedSequence sequence = StandSequence.selectSequence("death", sequences); - if (!this.alreadyPlayedDeath && (sequence != null) && (mdxComplexInstance.sequence != sequence.index)) { - mdxComplexInstance.setSequence(sequence.index); - this.alreadyPlayedDeath = true; - } - else if (mdxComplexInstance.sequenceEnded && this.alreadyPlayedDeath) { - sequence = StandSequence.selectSequence("dissipate", sequences); - if ((sequence != null) && (mdxComplexInstance.sequence != sequence.index)) { - mdxComplexInstance.setSequence(sequence.index); - } - } - } - else if (mdxComplexInstance.sequenceEnded || (mdxComplexInstance.sequence == -1) - || (currentOrder != this.lastOrder) - || ((currentOrder != null) && (currentOrder.getAnimationName() != null) - && !currentOrder.getAnimationName().equals(this.lastOrderAnimation)) - || changedAnimationTags) { - if (this.simulationUnit.getCurrentOrder() != null) { - final AnimationTokens.PrimaryTag animationName = this.simulationUnit.getCurrentOrder() - .getAnimationName(); - StandSequence.randomSequence(mdxComplexInstance, animationName, this.secondaryAnimationTags); - this.lastOrderAnimation = animationName; - } - else { - StandSequence.randomSequence(mdxComplexInstance, PrimaryTag.STAND, this.secondaryAnimationTags); - } - } - this.lastOrder = currentOrder; if (this.shadow != null) { this.shadow.move(dx, dy, map.terrain.centerOffset); } if (this.selectionCircle != null) { this.selectionCircle.move(dx, dy, map.terrain.centerOffset); } + this.unitAnimationListenerImpl.update(); } public CUnit getSimulationUnit() { @@ -262,4 +256,80 @@ public class RenderUnit { public List getCommandCardIcons() { return this.commandCardIcons; } + + private static final class UnitAnimationListenerImpl implements CUnitAnimationListener { + private final MdxComplexInstance instance; + private final EnumSet secondaryAnimationTags = EnumSet + .noneOf(AnimationTokens.SecondaryTag.class); + private final EnumSet recycleSet = EnumSet + .noneOf(AnimationTokens.SecondaryTag.class); + private PrimaryTag currentAnimation; + private EnumSet currentAnimationSecondaryTags; + private float currentSpeedRatio; + private final Queue animationQueue = new LinkedList<>(); + + public UnitAnimationListenerImpl(final MdxComplexInstance instance) { + this.instance = instance; + } + + public void addSecondaryTag(final AnimationTokens.SecondaryTag tag) { + this.secondaryAnimationTags.add(tag); + playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio); + } + + public void removeSecondaryTag(final AnimationTokens.SecondaryTag tag) { + this.secondaryAnimationTags.remove(tag); + playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio); + } + + @Override + public void playAnimation(final boolean force, final PrimaryTag animationName, + final EnumSet secondaryAnimationTags, final float speedRatio) { + this.animationQueue.clear(); + if (force || (animationName != this.currentAnimation)) { + this.currentAnimation = animationName; + this.currentAnimationSecondaryTags = secondaryAnimationTags; + this.currentSpeedRatio = speedRatio; + this.recycleSet.clear(); + this.recycleSet.addAll(this.secondaryAnimationTags); + this.recycleSet.addAll(secondaryAnimationTags); + this.instance.setAnimationSpeed(speedRatio); + StandSequence.randomSequence(this.instance, animationName, this.recycleSet); + } + } + + @Override + public void queueAnimation(final PrimaryTag animationName, final EnumSet secondaryAnimationTags) { + this.animationQueue.add(new QueuedAnimation(animationName, secondaryAnimationTags)); + } + + public void update() { + if (this.instance.sequenceEnded || (this.instance.sequence == -1)) { + // animation done + if ((this.instance.sequence != -1) && (((MdxModel) this.instance.model).getSequences() + .get(this.instance.sequence).getFlags() == 0)) { + // animation is a looping animation + playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, + this.currentSpeedRatio); + } + else { + final QueuedAnimation nextAnimation = this.animationQueue.poll(); + if (nextAnimation != null) { + playAnimation(true, nextAnimation.animationName, nextAnimation.secondaryAnimationTags, 1.0f); + } + } + } + } + + } + + private static final class QueuedAnimation { + private final PrimaryTag animationName; + private final EnumSet secondaryAnimationTags; + + public QueuedAnimation(final PrimaryTag animationName, final EnumSet secondaryAnimationTags) { + this.animationName = animationName; + this.secondaryAnimationTags = secondaryAnimationTags; + } + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CDestructable.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CDestructable.java index 754f81d..f221c03 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CDestructable.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CDestructable.java @@ -11,4 +11,8 @@ public class CDestructable extends CWidget { return 0; } + @Override + public float getImpactZ() { + return 0; // TODO maybe from DestructableType + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CGameplayConstants.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CGameplayConstants.java new file mode 100644 index 0000000..3567cc6 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CGameplayConstants.java @@ -0,0 +1,21 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation; + +import com.etheller.warsmash.units.DataTable; +import com.etheller.warsmash.units.Element; + +/** + * Stores some gameplay constants at runtime in a java object (symbol table) to + * maybe be faster than a map. + */ +public class CGameplayConstants { + private final float attackHalfAngle; + + public CGameplayConstants(final DataTable parsedDataTable) { + final Element miscData = parsedDataTable.get("Misc"); + this.attackHalfAngle = (miscData.getFieldFloatValue("AttackHalfAngle")); // TODO use + } + + public float getAttackHalfAngle() { + return this.attackHalfAngle; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CItem.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CItem.java index 73de42b..81b69b9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CItem.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CItem.java @@ -16,4 +16,8 @@ public class CItem extends CWidget { return 0; } + @Override + public float getImpactZ() { + return 0; // TODO probably from ItemType + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/COrder.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/COrder.java index 591f036..b7821a1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/COrder.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/COrder.java @@ -1,7 +1,5 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation; -import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; - public interface COrder { /** * Executes one step of game simulation of the current order, returning true if @@ -20,12 +18,4 @@ public interface COrder { * @return */ int getOrderId(); - - /** - * Gets the animation name used for visuals. Calling this function should not - * impact the game state of the CSimulation in any way. - * - * @return - */ - AnimationTokens.PrimaryTag getAnimationName(); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java index 0b3f0cc..61ca42c 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java @@ -6,13 +6,14 @@ import java.util.Iterator; import java.util.List; import com.badlogic.gdx.math.Rectangle; +import com.etheller.warsmash.units.DataTable; import com.etheller.warsmash.units.manager.MutableObjectData; import com.etheller.warsmash.util.War3ID; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CAbilityData; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CUnitData; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.projectile.CAttackProjectile; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ProjectileCreator; public class CSimulation { @@ -21,14 +22,17 @@ public class CSimulation { private final List units; private final List projectiles; private final HandleIdAllocator handleIdAllocator; - private final ProjectileCreator projectileCreator; + private transient final ProjectileCreator projectileCreator; private int gameTurnTick = 0; private final PathingGrid pathingGrid; private final CWorldCollision worldCollision; private final CPathfindingProcessor pathfindingProcessor; + private final CGameplayConstants gameplayConstants; - public CSimulation(final MutableObjectData parsedUnitData, final MutableObjectData parsedAbilityData, - final ProjectileCreator projectileCreator, final PathingGrid pathingGrid, final Rectangle entireMapBounds) { + public CSimulation(final DataTable miscData, final MutableObjectData parsedUnitData, + final MutableObjectData parsedAbilityData, final ProjectileCreator projectileCreator, + final PathingGrid pathingGrid, final Rectangle entireMapBounds) { + this.gameplayConstants = new CGameplayConstants(miscData); this.projectileCreator = projectileCreator; this.pathingGrid = pathingGrid; this.unitData = new CUnitData(parsedUnitData); @@ -101,4 +105,8 @@ public class CSimulation { public CWorldCollision getWorldCollision() { return this.worldCollision; } + + public CGameplayConstants getGameplayConstants() { + return this.gameplayConstants; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java index b67c0e9..36f83b0 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java @@ -1,13 +1,17 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation; import java.util.ArrayList; +import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; import com.badlogic.gdx.math.Rectangle; import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; 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.CWeaponType; public class CUnit extends CWidget { private War3ID typeId; @@ -16,6 +20,7 @@ public class CUnit extends CWidget { private int maximumLife; private int maximumMana; private int speed; + private final int defense; private int cooldownEndTime = 0; private float flyHeight; private int playerIndex; @@ -28,9 +33,13 @@ public class CUnit extends CWidget { private Rectangle collisionRectangle; + private final EnumSet classifications = EnumSet.noneOf(CUnitClassification.class); + + private transient CUnitAnimationListener unitAnimationListener; + 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, - final int speed, final CUnitType unitType) { + final int speed, final int defense, final CUnitType unitType) { super(handleId, x, y, life); this.typeId = typeId; this.facing = facing; @@ -38,8 +47,19 @@ public class CUnit extends CWidget { this.maximumLife = maximumLife; this.maximumMana = maximumMana; this.speed = speed; + this.defense = defense; this.flyHeight = unitType.getDefaultFlyingHeight(); this.unitType = unitType; + this.classifications.addAll(unitType.getClassifications()); + } + + public void setUnitAnimationListener(final CUnitAnimationListener unitAnimationListener) { + this.unitAnimationListener = unitAnimationListener; + this.unitAnimationListener.playAnimation(true, PrimaryTag.STAND, CUnitAnimationListener.EMPTY, 1.0f); + } + + public CUnitAnimationListener getUnitAnimationListener() { + return this.unitAnimationListener; } public void add(final CSimulation simulation, final CAbility ability) { @@ -110,6 +130,10 @@ public class CUnit extends CWidget { // item from order queue this.currentOrder = this.orderQueue.poll(); } + if (this.currentOrder == null) { + // maybe order "stop" here + this.unitAnimationListener.playAnimation(true, PrimaryTag.STAND, CUnitAnimationListener.EMPTY, 1.0f); + } } } @@ -193,4 +217,21 @@ public class CUnit extends CWidget { } } + public EnumSet getClassifications() { + return this.classifications; + } + + public int getDefense() { + return this.defense; + } + + public void damage(final CUnit source, final CAttackType attackType, final CWeaponType weaponType, + final int damage) { + + } + + @Override + public float getImpactZ() { + return this.unitType.getImpactZ(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitAnimationListener.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitAnimationListener.java new file mode 100644 index 0000000..db7f9d0 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitAnimationListener.java @@ -0,0 +1,16 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation; + +import java.util.EnumSet; + +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag; + +public interface CUnitAnimationListener { + EnumSet EMPTY = EnumSet.noneOf(SecondaryTag.class); + EnumSet READY = EnumSet.of(SecondaryTag.READY); + + void playAnimation(boolean force, final PrimaryTag animationName, + final EnumSet secondaryAnimationTags, float speedRatio); + + void queueAnimation(final PrimaryTag animationName, final EnumSet secondaryAnimationTags); +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitClassification.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitClassification.java new file mode 100644 index 0000000..d603983 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitClassification.java @@ -0,0 +1,67 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation; + +import java.util.HashMap; +import java.util.Map; + +/** + * We think in the original WC3 sourcecode, these are probably referred to as + * "Unit Types", but the community turn of phrase "Unit Type" has come to refer + * to what WC3 sourcecode calls "Unit Class", hence this is now named "Unit + * Classification" instead of "Unit Type" or "Unit Class" to disambiguate. This + * is consistent with the World Editor naming: "Stats - Unit Classification". + */ +public enum CUnitClassification { + GIANT("giant", "GiantClass"), + UNDEAD("undead", "UndeadClass"), + SUMMONED("summoned"), + MECHANICAL("mechanical", "MechanicalClass"), + PEON("peon"), + SAPPER("sapper"), + TOWNHALL("townhall"), + TREE("tree"), + WARD("ward"), + ANCIENT("ancient"), + STANDON("standon"), + NEURAL("neutral"), + TAUREN("tauren", "TaurenClass"); + private static final Map UNIT_EDITOR_KEY_TO_CLASSIFICATION = new HashMap<>(); + static { + for (final CUnitClassification unitClassification : values()) { + UNIT_EDITOR_KEY_TO_CLASSIFICATION.put(unitClassification.getUnitDataKey(), unitClassification); + } + } + + private String localeKey; + private String unitDataKey; + private String displayName; + + private CUnitClassification(final String unitDataKey, final String localeKey) { + this.unitDataKey = unitDataKey; + this.localeKey = localeKey; + } + + private CUnitClassification(final String unitDataKey) { + this.unitDataKey = unitDataKey; + this.localeKey = null; + } + + public String getUnitDataKey() { + return this.unitDataKey; + } + + public String getLocaleKey() { + return this.localeKey; + } + + public String getDisplayName() { + return this.displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + public static CUnitClassification parseUnitClassification(final String unitEditorKey) { + return UNIT_EDITOR_KEY_TO_CLASSIFICATION.get(unitEditorKey.toLowerCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java index b175af5..7970023 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java @@ -1,24 +1,51 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation; +import java.util.EnumSet; +import java.util.List; + import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack; /** * The quick (symbol table instead of map) lookup for unit type values that we * probably cannot change per unit instance. */ public class CUnitType { + private final String name; private final boolean building; private final PathingGrid.MovementType movementType; private final float defaultFlyingHeight; private final float collisionSize; + private final EnumSet classifications; + private final List attacks; + private final String armorType; // used for audio + private final boolean raise; + private final boolean decay; + private final CDefenseType defenseType; + private final float impactZ; - public CUnitType(final boolean isBldg, final MovementType movementType, final float defaultFlyingHeight, - final float collisionSize) { + public CUnitType(final String name, final boolean isBldg, final MovementType movementType, + final float defaultFlyingHeight, final float collisionSize, + final EnumSet classifications, final List attacks, final String armorType, + final boolean raise, final boolean decay, final CDefenseType defenseType, final float impactZ) { + this.name = name; this.building = isBldg; this.movementType = movementType; this.defaultFlyingHeight = defaultFlyingHeight; this.collisionSize = collisionSize; + this.classifications = classifications; + this.attacks = attacks; + this.armorType = armorType; + this.raise = raise; + this.decay = decay; + this.defenseType = defenseType; + this.impactZ = impactZ; + } + + public String getName() { + return this.name; } public float getDefaultFlyingHeight() { @@ -36,4 +63,32 @@ public class CUnitType { public boolean isBuilding() { return this.building; } + + public EnumSet getClassifications() { + return this.classifications; + } + + public List getAttacks() { + return this.attacks; + } + + public boolean isRaise() { + return this.raise; + } + + public boolean isDecay() { + return this.decay; + } + + public String getArmorType() { + return this.armorType; + } + + public CDefenseType getDefenseType() { + return this.defenseType; + } + + public float getImpactZ() { + return this.impactZ; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java index 3250aca..38dd2f9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java @@ -47,4 +47,6 @@ public abstract class CWidget { public abstract float getFlyHeight(); + public abstract float getImpactZ(); + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java index 3968632..8cc10d2 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityAttack.java @@ -47,7 +47,7 @@ public class CAbilityAttack implements CAbility { @Override public void onOrder(final CSimulation game, final CUnit caster, final CWidget target, final boolean queue) { - caster.order(new CAttackOrder(caster, target), queue); + caster.order(new CAttackOrder(caster, caster.getUnitType().getAttacks().get(0), target), queue); } @Override diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java new file mode 100644 index 0000000..13c6c68 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java @@ -0,0 +1,31 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public enum CAttackType implements CodeKeyType { + UNKNOWN, + NORMAL, + PIERCE, + SIEGE, + SPELLS, + CHAOS, + MAGIC, + HERO; + + private String codeKey; + + private CAttackType() { + String name = name(); + if (name.equals("SPELLS")) { + name = "MAGIC"; + } + this.codeKey = name.charAt(0) + name.substring(1).toLowerCase(); + } + + @Override + public String getCodeKey() { + return this.codeKey; + } + + public static CAttackType parseAttackType(final String attackTypeString) { + return valueOf(attackTypeString.toUpperCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CDefenseType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CDefenseType.java new file mode 100644 index 0000000..b23382b --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CDefenseType.java @@ -0,0 +1,27 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public enum CDefenseType implements CodeKeyType { + NONE, + NORMAL, + SMALL, + MEDIUM, + LARGE, + FORT, + HERO, + DIVINE; + + private String codeKey; + + private CDefenseType() { + this.codeKey = name().charAt(0) + name().substring(1).toLowerCase(); + } + + @Override + public String getCodeKey() { + return this.codeKey; + } + + public static CDefenseType parseDefenseType(final String typeString) { + return valueOf(typeString.toUpperCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CRegenType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CRegenType.java new file mode 100644 index 0000000..b303272 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CRegenType.java @@ -0,0 +1,13 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public enum CRegenType { + NONE, + ALWAYS, + BLIGHT, + DAY, + NIGHT; + + public static CRegenType parseRegenType(final String typeString) { + return valueOf(typeString.toUpperCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CTargetType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CTargetType.java new file mode 100644 index 0000000..5fb484a --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CTargetType.java @@ -0,0 +1,139 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +import java.util.EnumSet; + +public enum CTargetType { + AIR, + ALIVE, + ALLIES, + DEAD, + DEBRIS, + ENEMIES, + GROUND, + HERO, + INVULNERABLE, + ITEM, + MECHANICAL, + NEUTRAL, + NONE, + NONHERO, + NONSAPPER, + NOTSELF, + ORGANIC, + PLAYERUNITS, + SAPPER, + SELF, + STRUCTURE, + TERRAIN, + TREE, + VULNERABLE, + WALL, + WARD, + ANCIENT, + NONANCIENT, + FRIEND, + BRIDGE, + DECORATION; + + public static CTargetType parseTargetType(final String targetTypeString) { + if (targetTypeString == null) { + return null; + } + switch (targetTypeString.toLowerCase()) { + case "air": + return AIR; + case "alive": + case "aliv": + return ALIVE; + case "allies": + case "alli": + case "ally": + return ALLIES; + case "dead": + return DEAD; + case "debris": + case "debr": + return DEBRIS; + case "enemies": + case "enem": + case "enemy": + return ENEMIES; + case "ground": + case "grou": + return GROUND; + case "hero": + return HERO; + case "invulnerable": + case "invu": + return INVULNERABLE; + case "item": + return ITEM; + case "mechanical": + case "mech": + return MECHANICAL; + case "neutral": + case "neut": + return NEUTRAL; + case "none": + return NONE; + case "nonhero": + case "nonh": + return NONHERO; + case "nonsapper": + return NONSAPPER; + case "notself": + case "nots": + return NOTSELF; + case "organic": + case "orga": + return ORGANIC; + case "player": + case "play": + return PLAYERUNITS; + case "sapper": + return SAPPER; + case "self": + return SELF; + case "structure": + case "stru": + return STRUCTURE; + case "terrain": + case "terr": + return TERRAIN; + case "tree": + return TREE; + case "vulnerable": + case "vuln": + return VULNERABLE; + case "wall": + return WALL; + case "ward": + return WARD; + case "ancient": + return ANCIENT; + case "nonancient": + return NONANCIENT; + case "friend": + case "frie": + return FRIEND; + case "bridge": + return BRIDGE; + case "decoration": + case "deco": + return DECORATION; + default: + return null; + } + } + + public static EnumSet parseTargetTypeSet(final String targetTypeString) { + final EnumSet types = EnumSet.noneOf(CTargetType.class); + for (final String type : targetTypeString.split(",")) { + final CTargetType parsedType = parseTargetType(type); + if (parsedType != null) { + types.add(parsedType); + } + } + return types; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CUpgradeClass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CUpgradeClass.java new file mode 100644 index 0000000..3112bf6 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CUpgradeClass.java @@ -0,0 +1,13 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public enum CUpgradeClass { + ARMOR, + ARTILLERY, + MELEE, + RANGED, + CASTER; + + public static CUpgradeClass parseUpgradeClass(final String upgradeClassString) { + return valueOf(upgradeClassString.toUpperCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CWeaponType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CWeaponType.java new file mode 100644 index 0000000..6a9d634 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CWeaponType.java @@ -0,0 +1,16 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public enum CWeaponType { + NORMAL, + INSTANT, + ARTILLERY, + ALINE, + MISSILE, + MSPLASH, + MBOUNCE, + MLINE; + + public static CWeaponType parseWeaponType(final String weaponTypeString) { + return valueOf(weaponTypeString.toUpperCase()); + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CodeKeyType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CodeKeyType.java new file mode 100644 index 0000000..d727a02 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CodeKeyType.java @@ -0,0 +1,7 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat; + +public interface CodeKeyType { + String getCodeKey(); + + int ordinal(); +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttack.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttack.java new file mode 100644 index 0000000..d72530a --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttack.java @@ -0,0 +1,198 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +/** + * The base class for unit-data-based combat attacks. + * + * I really wanted to split this out into sub classes based on weapon type, but + * I came to realize the Ballista in RoC probably had the spill distance effect + * & area of effect both after it upgrades Impaling Bolt, and this would point + * out that the behaviors were not mutually exclusive. + * + * Then I reviewed it and decided that in RoC, the Impaling Bolts upgrade did + * not interact with the damage spill combat settings from the UnitWeapons.slk, + * because many of those settings did not exist. So I will attempt to emulate + * these attacks as best as possible. + */ +public class CUnitAttack { + private float animationBackswingPoint; + private float animationDamagePoint; + private CAttackType attackType; + private float cooldownTime; + private int damageBase; + private int damageDice; + private int damageSidesPerDie; + private int damageUpgradeAmount; + private int range; + private float rangeMotionBuffer; + private boolean showUI; + private EnumSet targetsAllowed; + private String weaponSound; + private CWeaponType weaponType; + + // calculate + private int minDamage; + private int maxDamage; + + public CUnitAttack(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType) { + this.animationBackswingPoint = animationBackswingPoint; + this.animationDamagePoint = animationDamagePoint; + this.attackType = attackType; + this.cooldownTime = cooldownTime; + this.damageBase = damageBase; + this.damageDice = damageDice; + this.damageSidesPerDie = damageSidesPerDie; + this.damageUpgradeAmount = damageUpgradeAmount; + this.range = range; + this.rangeMotionBuffer = rangeMotionBuffer; + this.showUI = showUI; + this.targetsAllowed = targetsAllowed; + this.weaponSound = weaponSound; + this.weaponType = weaponType; + computeDerivedFields(); + } + + private void computeDerivedFields() { + this.minDamage = this.damageBase + this.damageDice; + this.maxDamage = this.damageBase + (this.damageDice * this.damageSidesPerDie); + if (this.minDamage < 0) { + this.minDamage = 0; + } + if (this.maxDamage < 0) { + this.maxDamage = 0; + } + } + + public float getAnimationBackswingPoint() { + return this.animationBackswingPoint; + } + + public float getAnimationDamagePoint() { + return this.animationDamagePoint; + } + + public CAttackType getAttackType() { + return this.attackType; + } + + public float getCooldownTime() { + return this.cooldownTime; + } + + public int getDamageBase() { + return this.damageBase; + } + + public int getDamageDice() { + return this.damageDice; + } + + public int getDamageSidesPerDie() { + return this.damageSidesPerDie; + } + + public int getDamageUpgradeAmount() { + return this.damageUpgradeAmount; + } + + public int getRange() { + return this.range; + } + + public float getRangeMotionBuffer() { + return this.rangeMotionBuffer; + } + + public boolean isShowUI() { + return this.showUI; + } + + public EnumSet getTargetsAllowed() { + return this.targetsAllowed; + } + + public String getWeaponSound() { + return this.weaponSound; + } + + public CWeaponType getWeaponType() { + return this.weaponType; + } + + public void setAnimationBackswingPoint(final float animationBackswingPoint) { + this.animationBackswingPoint = animationBackswingPoint; + } + + public void setAnimationDamagePoint(final float animationDamagePoint) { + this.animationDamagePoint = animationDamagePoint; + } + + public void setAttackType(final CAttackType attackType) { + this.attackType = attackType; + } + + public void setCooldownTime(final float cooldownTime) { + this.cooldownTime = cooldownTime; + } + + public void setDamageBase(final int damageBase) { + this.damageBase = damageBase; + computeDerivedFields(); + } + + public void setDamageDice(final int damageDice) { + this.damageDice = damageDice; + computeDerivedFields(); + } + + public void setDamageSidesPerDie(final int damageSidesPerDie) { + this.damageSidesPerDie = damageSidesPerDie; + computeDerivedFields(); + } + + public void setDamageUpgradeAmount(final int damageUpgradeAmount) { + this.damageUpgradeAmount = damageUpgradeAmount; + } + + public void setRange(final int range) { + this.range = range; + } + + public void setRangeMotionBuffer(final float rangeMotionBuffer) { + this.rangeMotionBuffer = rangeMotionBuffer; + } + + public void setShowUI(final boolean showUI) { + this.showUI = showUI; + } + + public void setTargetsAllowed(final EnumSet targetsAllowed) { + this.targetsAllowed = targetsAllowed; + } + + public void setWeaponSound(final String weaponSound) { + this.weaponSound = weaponSound; + } + + public void setWeaponType(final CWeaponType weaponType) { + this.weaponType = weaponType; + } + + public int getMinDamage() { + return this.minDamage; + } + + public int getMaxDamage() { + return this.maxDamage; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackInstant.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackInstant.java new file mode 100644 index 0000000..8e9ab2e --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackInstant.java @@ -0,0 +1,31 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackInstant extends CUnitAttack { + private String projectileArt; + + public CUnitAttackInstant(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType, final String projectileArt) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType); + this.projectileArt = projectileArt; + } + + public String getProjectileArt() { + return this.projectileArt; + } + + public void setProjectileArt(final String projectileArt) { + this.projectileArt = projectileArt; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissile.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissile.java new file mode 100644 index 0000000..9397295 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissile.java @@ -0,0 +1,62 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackMissile extends CUnitAttack { + private float projectileArc; + private String projectileArt; + private boolean projectileHomingEnabled; + private int projectileSpeed; + + public CUnitAttackMissile(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType, final float projectileArc, final String projectileArt, + final boolean projectileHomingEnabled, final int projectileSpeed) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType); + this.projectileArc = projectileArc; + this.projectileArt = projectileArt; + this.projectileHomingEnabled = projectileHomingEnabled; + this.projectileSpeed = projectileSpeed; + } + + public float getProjectileArc() { + return this.projectileArc; + } + + public String getProjectileArt() { + return this.projectileArt; + } + + public boolean isProjectileHomingEnabled() { + return this.projectileHomingEnabled; + } + + public int getProjectileSpeed() { + return this.projectileSpeed; + } + + public void setProjectileArc(final float projectileArc) { + this.projectileArc = projectileArc; + } + + public void setProjectileArt(final String projectileArt) { + this.projectileArt = projectileArt; + } + + public void setProjectileHomingEnabled(final boolean projectileHomingEnabled) { + this.projectileHomingEnabled = projectileHomingEnabled; + } + + public void setProjectileSpeed(final int projectileSpeed) { + this.projectileSpeed = projectileSpeed; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileBounce.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileBounce.java new file mode 100644 index 0000000..474ca3f --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileBounce.java @@ -0,0 +1,43 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackMissileBounce extends CUnitAttackMissile { + private float damageLossFactor; + private int maximumNumberOfTargets; + + public CUnitAttackMissileBounce(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType, final float projectileArc, final String projectileArt, + final boolean projectileHomingEnabled, final int projectileSpeed, final float damageLossFactor, + final int maximumNumberOfTargets) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed); + this.damageLossFactor = damageLossFactor; + this.maximumNumberOfTargets = maximumNumberOfTargets; + } + + public float getDamageLossFactor() { + return this.damageLossFactor; + } + + public int getMaximumNumberOfTargets() { + return this.maximumNumberOfTargets; + } + + public void setDamageLossFactor(final float damageLossFactor) { + this.damageLossFactor = damageLossFactor; + } + + public void setMaximumNumberOfTargets(final int maximumNumberOfTargets) { + this.maximumNumberOfTargets = maximumNumberOfTargets; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileLine.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileLine.java new file mode 100644 index 0000000..6d4dbeb --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileLine.java @@ -0,0 +1,43 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackMissileLine extends CUnitAttackMissile { + private float damageSpillDistance; + private float damageSpillRadius; + + public CUnitAttackMissileLine(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType, final float projectileArc, final String projectileArt, + final boolean projectileHomingEnabled, final int projectileSpeed, final float damageSpillDistance, + final float damageSpillRadius) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed); + this.damageSpillDistance = damageSpillDistance; + this.damageSpillRadius = damageSpillRadius; + } + + public float getDamageSpillDistance() { + return this.damageSpillDistance; + } + + public float getDamageSpillRadius() { + return this.damageSpillRadius; + } + + public void setDamageSpillDistance(final float damageSpillDistance) { + this.damageSpillDistance = damageSpillDistance; + } + + public void setDamageSpillRadius(final float damageSpillRadius) { + this.damageSpillRadius = damageSpillRadius; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileSplash.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileSplash.java new file mode 100644 index 0000000..a9e636e --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackMissileSplash.java @@ -0,0 +1,85 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackMissileSplash extends CUnitAttackMissile { + private int areaOfEffectFullDamage; + private int areaOfEffectMediumDamage; + private int areaOfEffectSmallDamage; + private EnumSet areaOfEffectTargets; + private float damageFactorMedium; + private float damageFactorSmall; + + public CUnitAttackMissileSplash(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType, final float projectileArc, final String projectileArt, + final boolean projectileHomingEnabled, final int projectileSpeed, final int areaOfEffectFullDamage, + final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage, + final EnumSet areaOfEffectTargets, final float damageFactorMedium, + final float damageFactorSmall) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType, projectileArc, projectileArt, projectileHomingEnabled, projectileSpeed); + this.areaOfEffectFullDamage = areaOfEffectFullDamage; + this.areaOfEffectMediumDamage = areaOfEffectMediumDamage; + this.areaOfEffectSmallDamage = areaOfEffectSmallDamage; + this.areaOfEffectTargets = areaOfEffectTargets; + this.damageFactorMedium = damageFactorMedium; + this.damageFactorSmall = damageFactorSmall; + } + + public int getAreaOfEffectFullDamage() { + return this.areaOfEffectFullDamage; + } + + public int getAreaOfEffectMediumDamage() { + return this.areaOfEffectMediumDamage; + } + + public int getAreaOfEffectSmallDamage() { + return this.areaOfEffectSmallDamage; + } + + public EnumSet getAreaOfEffectTargets() { + return this.areaOfEffectTargets; + } + + public float getDamageFactorMedium() { + return this.damageFactorMedium; + } + + public float getDamageFactorSmall() { + return this.damageFactorSmall; + } + + public void setAreaOfEffectFullDamage(final int areaOfEffectFullDamage) { + this.areaOfEffectFullDamage = areaOfEffectFullDamage; + } + + public void setAreaOfEffectMediumDamage(final int areaOfEffectMediumDamage) { + this.areaOfEffectMediumDamage = areaOfEffectMediumDamage; + } + + public void setAreaOfEffectSmallDamage(final int areaOfEffectSmallDamage) { + this.areaOfEffectSmallDamage = areaOfEffectSmallDamage; + } + + public void setAreaOfEffectTargets(final EnumSet areaOfEffectTargets) { + this.areaOfEffectTargets = areaOfEffectTargets; + } + + public void setDamageFactorMedium(final float damageFactorMedium) { + this.damageFactorMedium = damageFactorMedium; + } + + public void setDamageFactorSmall(final float damageFactorSmall) { + this.damageFactorSmall = damageFactorSmall; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackNormal.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackNormal.java new file mode 100644 index 0000000..9dca88c --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/attacks/CUnitAttackNormal.java @@ -0,0 +1,21 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks; + +import java.util.EnumSet; + +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.CWeaponType; + +public class CUnitAttackNormal extends CUnitAttack { + + public CUnitAttackNormal(final float animationBackswingPoint, final float animationDamagePoint, + final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice, + final int damageSidesPerDie, final int damageUpgradeAmount, final int range, final float rangeMotionBuffer, + final boolean showUI, final EnumSet targetsAllowed, final String weaponSound, + final CWeaponType weaponType) { + super(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, damageBase, damageDice, + damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound, + weaponType); + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/projectile/CAttackProjectile.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/projectile/CAttackProjectile.java similarity index 95% rename from core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/projectile/CAttackProjectile.java rename to core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/projectile/CAttackProjectile.java index 4246f3c..99d1b71 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/projectile/CAttackProjectile.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/projectile/CAttackProjectile.java @@ -1,4 +1,4 @@ -package com.etheller.warsmash.viewer5.handlers.w3x.simulation.projectile; +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile; import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java index 435e083..ed7bc48 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java @@ -1,6 +1,9 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data; +import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.etheller.warsmash.units.manager.MutableObjectData; @@ -9,12 +12,24 @@ import com.etheller.warsmash.util.War3ID; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitClassification; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityHoldPosition; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityPatrol; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityStop; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; +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.CUnitAttackInstant; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissile; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissileBounce; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissileLine; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissileSplash; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackNormal; public class CUnitData { private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi"); @@ -28,24 +43,76 @@ public class CUnitData { 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_Z = War3ID.fromString("ulpz"); + private static final War3ID ATTACKS_ENABLED = War3ID.fromString("uaen"); + 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_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_QUARTER_DMG = War3ID.fromString("ua1q"); + 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_COOLDOWN = War3ID.fromString("ua1c"); 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_QUARTER = War3ID.fromString("uqd1"); + 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_SIDES_PER_DIE = War3ID.fromString("ua1s"); - private static final War3ID ATTACK1_PROJECTILE_SPEED = War3ID.fromString("ua1z"); - private static final War3ID ATTACK1_MISSILE_ART = War3ID.fromString("ua1m"); + 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_UPGRADE_AMT = War3ID.fromString("udu1"); + 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_COOLDOWN = War3ID.fromString("ua1c"); + 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_SPEED = War3ID.fromString("ua1z"); + 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_SHOW_UI = War3ID.fromString("uwu1"); + 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_TYPE = War3ID.fromString("ua1w"); + + 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_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_QUARTER_DMG = War3ID.fromString("ua2q"); + 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_COOLDOWN = War3ID.fromString("ua2c"); 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_QUARTER = War3ID.fromString("uqd2"); + 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_SIDES_PER_DIE = War3ID.fromString("ua2s"); - private static final War3ID ATTACK2_PROJECTILE_SPEED = War3ID.fromString("ua2z"); - private static final War3ID ATTACK2_MISSILE_ART = War3ID.fromString("ua2m"); + 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_UPGRADE_AMT = War3ID.fromString("udu2"); + 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_COOLDOWN = War3ID.fromString("ua2c"); + 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_SPEED = War3ID.fromString("ua2z"); + 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_SHOW_UI = War3ID.fromString("uwu2"); + 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_TYPE = War3ID.fromString("ua2w"); + + private static final War3ID PROJECTILE_IMPACT_Z = War3ID.fromString("uimz"); + + private static final War3ID DEATH_TYPE = War3ID.fromString("udea"); + private static final War3ID ARMOR_TYPE = War3ID.fromString("uarm"); + private static final War3ID DEFENSE = War3ID.fromString("udef"); + private static final War3ID DEFENSE_TYPE = War3ID.fromString("udty"); private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh"); private static final War3ID MOVE_TYPE = War3ID.fromString("umvt"); private static final War3ID COLLISION_SIZE = War3ID.fromString("ucol"); + private static final War3ID CLASSIFICATION = War3ID.fromString("utyp"); private final MutableObjectData unitData; private final Map unitIdToUnitType = new HashMap<>(); @@ -65,8 +132,113 @@ public class CUnitData { final float collisionSize = unitType.getFieldAsFloat(COLLISION_SIZE, 0); final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0); final PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp); + final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0); + final String unitName = unitType.getFieldAsString(NAME, 0); + final EnumSet classifications = EnumSet.noneOf(CUnitClassification.class); + if (classificationString != null) { + final String[] classificationValues = classificationString.split(","); + for (final String unitEditorKey : classificationValues) { + final CUnitClassification unitClassification = CUnitClassification + .parseUnitClassification(unitEditorKey); + if (unitClassification != null) { + classifications.add(unitClassification); + } + } + } + final List attacks = new ArrayList<>(); + final int attacksEnabled = unitType.getFieldAsInteger(ATTACKS_ENABLED, 0); + if ((attacksEnabled & 0x1) != 0) { + // attack one + final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK1_BACKSWING_POINT, 0); + final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK1_DAMAGE_POINT, 0); + final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_FULL_DMG, 0); + final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_HALF_DMG, 0); + final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_QUARTER_DMG, 0); + final EnumSet areaOfEffectTargets = CTargetType + .parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_AREA_OF_EFFECT_TARGETS, 0)); + final CAttackType attackType = CAttackType + .parseAttackType(unitType.getFieldAsString(ATTACK1_ATTACK_TYPE, 0)); + final float cooldownTime = unitType.getFieldAsFloat(ATTACK1_COOLDOWN, 0); + final int damageBase = unitType.getFieldAsInteger(ATTACK1_DMG_BASE, 0); + final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_HALF, 0); + final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_QUARTER, 0); + final float damageLossFactor = unitType.getFieldAsFloat(ATTACK1_DAMAGE_LOSS_FACTOR, 0); + final int damageDice = unitType.getFieldAsInteger(ATTACK1_DMG_DICE, 0); + final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0); + final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_DIST, 0); + final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_RADIUS, 0); + final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK1_DMG_UPGRADE_AMT, 0); + final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK1_TARGET_COUNT, 0); + final float projectileArc = unitType.getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0); + final String projectileArt = unitType.getFieldAsString(ATTACK1_MISSILE_ART, 0); + final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK1_PROJECTILE_HOMING_ENABLED, 0); + final int projectileSpeed = unitType.getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0); + final int range = unitType.getFieldAsInteger(ATTACK1_RANGE, 0); + final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK1_RANGE_MOTION_BUFFER, 0); + final boolean showUI = unitType.getFieldAsBoolean(ATTACK1_SHOW_UI, 0); + final EnumSet targetsAllowed = CTargetType + .parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_TARGETS_ALLOWED, 0)); + final String weaponSound = unitType.getFieldAsString(ATTACK1_WEAPON_SOUND, 0); + final CWeaponType weaponType = CWeaponType + .parseWeaponType(unitType.getFieldAsString(ATTACK1_WEAPON_TYPE, 0)); + attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage, + areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType, cooldownTime, + damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice, damageSidesPerDie, + damageSpillDistance, damageSpillRadius, damageUpgradeAmount, maximumNumberOfTargets, projectileArc, + projectileArt, projectileHomingEnabled, projectileSpeed, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType)); + } + if ((attacksEnabled & 0x2) != 0) { + // attack two + 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); + final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_HALF_DMG, 0); + final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_QUARTER_DMG, 0); + final EnumSet areaOfEffectTargets = CTargetType + .parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_AREA_OF_EFFECT_TARGETS, 0)); + final CAttackType attackType = CAttackType + .parseAttackType(unitType.getFieldAsString(ATTACK2_ATTACK_TYPE, 0)); + final float cooldownTime = unitType.getFieldAsFloat(ATTACK2_COOLDOWN, 0); + final int damageBase = unitType.getFieldAsInteger(ATTACK2_DMG_BASE, 0); + final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_HALF, 0); + final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_QUARTER, 0); + final float damageLossFactor = unitType.getFieldAsFloat(ATTACK2_DAMAGE_LOSS_FACTOR, 0); + final int damageDice = unitType.getFieldAsInteger(ATTACK2_DMG_DICE, 0); + final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0); + final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_DIST, 0); + final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_RADIUS, 0); + final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK2_DMG_UPGRADE_AMT, 0); + final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK2_TARGET_COUNT, 0); + final float projectileArc = unitType.getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0); + final String projectileArt = unitType.getFieldAsString(ATTACK2_MISSILE_ART, 0); + final boolean projectileHomingEnabled = unitType.getFieldAsBoolean(ATTACK2_PROJECTILE_HOMING_ENABLED, 0); + final int projectileSpeed = unitType.getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0); + final int range = unitType.getFieldAsInteger(ATTACK2_RANGE, 0); + final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK2_RANGE_MOTION_BUFFER, 0); + final boolean showUI = unitType.getFieldAsBoolean(ATTACK2_SHOW_UI, 0); + final EnumSet targetsAllowed = CTargetType + .parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_TARGETS_ALLOWED, 0)); + final String weaponSound = unitType.getFieldAsString(ATTACK2_WEAPON_SOUND, 0); + final CWeaponType weaponType = CWeaponType + .parseWeaponType(unitType.getFieldAsString(ATTACK2_WEAPON_TYPE, 0)); + attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage, + areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType, cooldownTime, + damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor, damageDice, damageSidesPerDie, + damageSpillDistance, damageSpillRadius, damageUpgradeAmount, maximumNumberOfTargets, projectileArc, + projectileArt, projectileHomingEnabled, projectileSpeed, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType)); + } + final int deathType = unitType.getFieldAsInteger(DEATH_TYPE, 0); + final boolean raise = (deathType & 0x1) != 0; + final boolean decay = (deathType & 0x2) != 0; + final String armorType = unitType.getFieldAsString(ARMOR_TYPE, 0); + final int defense = unitType.getFieldAsInteger(DEFENSE, 0); + final float impactZ = unitType.getFieldAsFloat(PROJECTILE_IMPACT_Z, 0); + final CDefenseType defenseType = CDefenseType.parseDefenseType(unitType.getFieldAsString(DEFENSE_TYPE, 0)); final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum, - speed, new CUnitType(isBldg, movementType, moveHeight, collisionSize)); + speed, defense, new CUnitType(unitName, isBldg, movementType, moveHeight, collisionSize, + classifications, attacks, armorType, raise, decay, defenseType, impactZ)); if (speed > 0) { unit.add(simulation, CAbilityMove.INSTANCE); unit.add(simulation, CAbilityPatrol.INSTANCE); @@ -81,6 +253,60 @@ public class CUnitData { return unit; } + private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint, + final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage, + final EnumSet areaOfEffectTargets, final CAttackType attackType, final float cooldownTime, + final int damageBase, final float damageFactorMedium, final float damageFactorSmall, + final float damageLossFactor, final int damageDice, final int damageSidesPerDie, + final float damageSpillDistance, final float damageSpillRadius, final int damageUpgradeAmount, + final int maximumNumberOfTargets, final float projectileArc, final String projectileArt, + final boolean projectileHomingEnabled, final int projectileSpeed, final int range, + final float rangeMotionBuffer, final boolean showUI, final EnumSet targetsAllowed, + final String weaponSound, final CWeaponType weaponType) { + final CUnitAttack attack; + switch (weaponType) { + case MISSILE: + attack = new CUnitAttackMissile(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, + damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled, + projectileSpeed); + break; + case MBOUNCE: + attack = new CUnitAttackMissileBounce(animationBackswingPoint, animationDamagePoint, attackType, + cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, + rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, + projectileHomingEnabled, projectileSpeed, damageLossFactor, maximumNumberOfTargets); + break; + case MSPLASH: + case ARTILLERY: + attack = new CUnitAttackMissileSplash(animationBackswingPoint, animationDamagePoint, attackType, + cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, + rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, + projectileHomingEnabled, projectileSpeed, areaOfEffectFullDamage, areaOfEffectMediumDamage, + areaOfEffectSmallDamage, areaOfEffectTargets, damageFactorMedium, damageFactorSmall); + break; + case MLINE: + case ALINE: + attack = new CUnitAttackMissileLine(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, + damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled, + projectileSpeed, damageSpillDistance, damageSpillRadius); + break; + case INSTANT: + attack = new CUnitAttackInstant(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, + damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType, projectileArt); + break; + default: + case NORMAL: + attack = new CUnitAttackNormal(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime, + damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI, + targetsAllowed, weaponSound, weaponType); + break; + } + return attack; + } + public float getPropulsionWindow(final War3ID unitTypeId) { return this.unitData.get(unitTypeId).getFieldAsFloat(PROPULSION_WINDOW, 0); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CAttackOrder.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CAttackOrder.java index ea9e5e9..0987753 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CAttackOrder.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CAttackOrder.java @@ -1,20 +1,25 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders; import com.etheller.warsmash.util.WarsmashConstants; -import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; 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.CUnitAnimationListener; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack; public class CAttackOrder implements COrder { private final CUnit unit; private boolean wasWithinPropWindow = false; + private final CUnitAttack unitAttack; private final CWidget target; + private int backswingLaunchTime; - public CAttackOrder(final CUnit unit, final CWidget target) { + public CAttackOrder(final CUnit unit, final CUnitAttack unitAttack, final CWidget target) { this.unit = unit; + this.unitAttack = unitAttack; this.target = target; } @@ -31,9 +36,8 @@ public class CAttackOrder implements COrder { } float facing = this.unit.getFacing(); float delta = goalAngle - facing; - final float propulsionWindow = simulation.getUnitData().getPropulsionWindow(this.unit.getTypeId()); + final float propulsionWindow = simulation.getGameplayConstants().getAttackHalfAngle(); final float turnRate = simulation.getUnitData().getTurnRate(this.unit.getTypeId()); - final int speed = this.unit.getSpeed(); if (delta < -180) { delta = 360 + delta; @@ -65,11 +69,30 @@ public class CAttackOrder implements COrder { final int cooldownEndTime = this.unit.getCooldownEndTime(); final int currentTurnTick = simulation.getGameTurnTick(); - if (currentTurnTick >= cooldownEndTime) { - final float a1Cooldown = simulation.getUnitData().getA1Cooldown(this.unit.getTypeId()); - final int a1CooldownSteps = (int) (a1Cooldown / WarsmashConstants.SIMULATION_STEP_TIME); - this.unit.setCooldownEndTime(currentTurnTick + a1CooldownSteps); - simulation.createProjectile(this.unit, 0, this.target); + if (this.wasWithinPropWindow) { + if (this.backswingLaunchTime != 0) { + if (currentTurnTick >= this.backswingLaunchTime) { + simulation.createProjectile(this.unit, 0, this.target); + this.backswingLaunchTime = 0; + } + } + else if (currentTurnTick >= cooldownEndTime) { + final float cooldownTime = this.unitAttack.getCooldownTime(); + final float animationBackswingPoint = this.unitAttack.getAnimationBackswingPoint(); + final int a1CooldownSteps = (int) (cooldownTime / WarsmashConstants.SIMULATION_STEP_TIME); + final int a1BackswingSteps = (int) (animationBackswingPoint / WarsmashConstants.SIMULATION_STEP_TIME); + final int a1DamagePointSteps = (int) (this.unitAttack.getAnimationDamagePoint() + / WarsmashConstants.SIMULATION_STEP_TIME); + this.unit.setCooldownEndTime(currentTurnTick + a1CooldownSteps); + this.backswingLaunchTime = currentTurnTick + a1DamagePointSteps; + this.unit.getUnitAnimationListener().playAnimation(true, PrimaryTag.ATTACK, + CUnitAnimationListener.EMPTY, 1.0f); + this.unit.getUnitAnimationListener().queueAnimation(PrimaryTag.STAND, CUnitAnimationListener.READY); + } + } + else { + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, CUnitAnimationListener.READY, + 1.0f); } return false; @@ -80,9 +103,4 @@ public class CAttackOrder implements COrder { return CAbilityAttack.ORDER_ID; } - @Override - public AnimationTokens.PrimaryTag getAnimationName() { - return AnimationTokens.PrimaryTag.ATTACK; - } - } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CDoNothingOrder.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CDoNothingOrder.java index a7f1b23..9067fa7 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CDoNothingOrder.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CDoNothingOrder.java @@ -1,6 +1,5 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders; -import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.COrder; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; @@ -21,9 +20,4 @@ public class CDoNothingOrder implements COrder { return this.orderId; } - @Override - public AnimationTokens.PrimaryTag getAnimationName() { - return AnimationTokens.PrimaryTag.STAND; - } - } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CMoveOrder.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CMoveOrder.java index b51a412..1516005 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CMoveOrder.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/orders/CMoveOrder.java @@ -6,12 +6,13 @@ import java.util.List; import com.badlogic.gdx.math.Rectangle; import com.etheller.warsmash.util.WarsmashConstants; -import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.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.CUnitAnimationListener; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWorldCollision; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CPathfindingProcessor; @@ -207,6 +208,10 @@ public class CMoveOrder implements COrder { } absDelta = Math.abs(delta); if (absDelta >= propulsionWindow) { + if (this.wasWithinPropWindow) { + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, + CUnitAnimationListener.EMPTY, 1.0f); + } this.wasWithinPropWindow = false; return false; } @@ -224,6 +229,10 @@ public class CMoveOrder implements COrder { this.path.add(this.target); } } + if (!this.wasWithinPropWindow) { + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.WALK, + CUnitAnimationListener.EMPTY, 1.0f); + } this.wasWithinPropWindow = true; } while (continueDistance > 0); @@ -231,6 +240,10 @@ public class CMoveOrder implements COrder { else { // If this happens, the unit is facing the wrong way, and has to turn before // moving. + if (this.wasWithinPropWindow) { + this.unit.getUnitAnimationListener().playAnimation(false, PrimaryTag.STAND, + CUnitAnimationListener.EMPTY, 1.0f); + } this.wasWithinPropWindow = false; } @@ -242,12 +255,4 @@ public class CMoveOrder implements COrder { return CAbilityMove.ORDER_ID; } - @Override - public AnimationTokens.PrimaryTag getAnimationName() { - if (!this.wasWithinPropWindow) { - return AnimationTokens.PrimaryTag.STAND; - } - return AnimationTokens.PrimaryTag.WALK; - } - } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/ProjectileCreator.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/ProjectileCreator.java index 1f182c9..be22c6a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/ProjectileCreator.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/ProjectileCreator.java @@ -3,7 +3,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget; -import com.etheller.warsmash.viewer5.handlers.w3x.simulation.projectile.CAttackProjectile; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.projectile.CAttackProjectile; public interface ProjectileCreator { CAttackProjectile create(CSimulation simulation, CUnit source, int attackIndex, CWidget target); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java new file mode 100644 index 0000000..96bd077 --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java @@ -0,0 +1,372 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.ui; + +import java.io.IOException; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.etheller.warsmash.WarsmashGdxMapGame; +import com.etheller.warsmash.datasources.DataSource; +import com.etheller.warsmash.parsers.fdf.GameUI; +import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition; +import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint; +import com.etheller.warsmash.parsers.fdf.frames.SetPoint; +import com.etheller.warsmash.parsers.fdf.frames.StringFrame; +import com.etheller.warsmash.parsers.fdf.frames.TextureFrame; +import com.etheller.warsmash.parsers.fdf.frames.UIFrame; +import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener; +import com.etheller.warsmash.util.FastNumberFormat; +import com.etheller.warsmash.viewer5.Scene; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance; +import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel; +import com.etheller.warsmash.viewer5.handlers.w3x.StandSequence; +import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer; +import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitClassification; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CodeKeyType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack; + +public class MeleeUI { + private final DataSource dataSource; + private final Viewport uiViewport; + private final FreeTypeFontGenerator fontGenerator; + private final Scene uiScene; + private final War3MapViewer war3MapViewer; + private final RootFrameListener rootFrameListener; + private GameUI rootFrame; + private UIFrame consoleUI; + private UIFrame resourceBar; + private UIFrame timeIndicator; + private UIFrame unitPortrait; + private StringFrame unitLifeText; + private StringFrame unitManaText; + private Portrait portrait; + private final Rectangle tempRect = new Rectangle(); + private final Vector2 projectionTemp1 = new Vector2(); + private final Vector2 projectionTemp2 = new Vector2(); + private UIFrame simpleInfoPanelUnitDetail; + private StringFrame simpleNameValue; + private StringFrame simpleClassValue; + private StringFrame simpleBuildingActionLabel; + private UIFrame attack1Icon; + private TextureFrame attack1IconBackdrop; + private StringFrame attack1InfoPanelIconValue; + private StringFrame attack1InfoPanelIconLevel; + private UIFrame attack2Icon; + private TextureFrame attack2IconBackdrop; + private StringFrame attack2InfoPanelIconValue; + private StringFrame attack2InfoPanelIconLevel; + private UIFrame armorIcon; + private TextureFrame armorIconBackdrop; + private StringFrame armorInfoPanelIconValue; + private StringFrame armorInfoPanelIconLevel; + private InfoPanelIconBackdrops damageBackdrops; + private InfoPanelIconBackdrops defenseBackdrops; + + public MeleeUI(final DataSource dataSource, final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator, + final Scene uiScene, final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener) { + this.dataSource = dataSource; + this.uiViewport = uiViewport; + this.fontGenerator = fontGenerator; + this.uiScene = uiScene; + this.war3MapViewer = war3MapViewer; + this.rootFrameListener = rootFrameListener; + + } + + /** + * Called "main" because this was originally written in JASS so that maps could + * override it, and I may convert it back to the JASS at some point. + */ + public void main() { + // ================================= + // Load skins and templates + // ================================= + this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, 1), this.uiViewport, + this.fontGenerator, this.uiScene, this.war3MapViewer); + try { + this.rootFrame.loadTOCFile("UI\\FrameDef\\FrameDef.toc"); + } + catch (final IOException exc) { + throw new IllegalStateException("Unable to load FrameDef.toc", exc); + } + try { + this.rootFrame.loadTOCFile("UI\\FrameDef\\SmashFrameDef.toc"); + } + catch (final IOException exc) { + throw new IllegalStateException("Unable to load SmashFrameDef.toc", exc); + } + this.damageBackdrops = new InfoPanelIconBackdrops(CAttackType.values(), this.rootFrame, "Damage", "Neutral"); + this.defenseBackdrops = new InfoPanelIconBackdrops(CDefenseType.values(), this.rootFrame, "Armor", "Neutral"); + + // ================================= + // Load major UI components + // ================================= + // Console UI is the background with the racial theme + this.consoleUI = this.rootFrame.createSimpleFrame("ConsoleUI", this.rootFrame, 0); + this.consoleUI.setSetAllPoints(true); + + // Resource bar is a 3 part bar with Gold, Lumber, and Food. + // Its template does not specify where to put it, so we must + // put it in the "TOPRIGHT" corner. + this.resourceBar = this.rootFrame.createSimpleFrame("ResourceBarFrame", this.consoleUI, 0); + this.resourceBar.addSetPoint(new SetPoint(FramePoint.TOPRIGHT, this.consoleUI, FramePoint.TOPRIGHT, 0, 0)); + + // Create the Time Indicator (clock) + this.timeIndicator = this.rootFrame.createFrame("TimeOfDayIndicator", this.rootFrame, 0, 0); + + // Create the unit portrait stuff + this.portrait = new Portrait(this.war3MapViewer); + positionPortrait(); + this.unitPortrait = this.rootFrame.createSimpleFrame("UnitPortrait", this.consoleUI, 0); + this.unitLifeText = (StringFrame) this.rootFrame.getFrameByName("UnitPortraitHitPointText", 0); + this.unitManaText = (StringFrame) this.rootFrame.getFrameByName("UnitPortraitManaPointText", 0); + + this.simpleInfoPanelUnitDetail = this.rootFrame.createSimpleFrame("SimpleInfoPanelUnitDetail", this.consoleUI, + 0); + this.simpleInfoPanelUnitDetail + .addAnchor(new AnchorDefinition(FramePoint.BOTTOM, 0, GameUI.convertY(this.uiViewport, 0.0f))); + this.simpleInfoPanelUnitDetail.setWidth(GameUI.convertY(this.uiViewport, 0.180f)); + this.simpleInfoPanelUnitDetail.setHeight(GameUI.convertY(this.uiViewport, 0.105f)); + this.simpleNameValue = (StringFrame) this.rootFrame.getFrameByName("SimpleNameValue", 0); + this.simpleClassValue = (StringFrame) this.rootFrame.getFrameByName("SimpleClassValue", 0); + this.simpleBuildingActionLabel = (StringFrame) this.rootFrame.getFrameByName("SimpleBuildingActionLabel", 0); + + this.attack1Icon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconDamage", this.simpleInfoPanelUnitDetail, + 0); + this.attack1Icon.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, + FramePoint.TOPLEFT, 0, GameUI.convertY(this.uiViewport, -0.030125f))); + this.attack1IconBackdrop = (TextureFrame) this.rootFrame.getFrameByName("InfoPanelIconBackdrop", 0); + this.attack1InfoPanelIconValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconValue", 0); + this.attack1InfoPanelIconLevel = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconLevel", 0); + + this.attack2Icon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconDamage", this.simpleInfoPanelUnitDetail, + 1); + this.attack2Icon + .addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT, + GameUI.convertX(this.uiViewport, 0.1f), GameUI.convertY(this.uiViewport, -0.030125f))); + this.attack2IconBackdrop = (TextureFrame) this.rootFrame.getFrameByName("InfoPanelIconBackdrop", 1); + this.attack2InfoPanelIconValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconValue", 1); + this.attack2InfoPanelIconLevel = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconLevel", 1); + + this.armorIcon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconArmor", this.simpleInfoPanelUnitDetail, + 1); + this.armorIcon.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT, + GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.06025f))); + this.armorIconBackdrop = (TextureFrame) this.rootFrame.getFrameByName("InfoPanelIconBackdrop", 0); + this.armorInfoPanelIconValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconValue", 0); + this.armorInfoPanelIconLevel = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconLevel", 0); + + this.rootFrame.positionBounds(this.uiViewport); + selectUnit(null); + } + + public void updatePortrait() { + this.portrait.update(); + } + + public void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) { + this.rootFrame.render(batch, font20, glyphLayout); + } + + public void portraitTalk() { + this.portrait.talk(); + } + + private static final class Portrait { + private MdxComplexInstance modelInstance; + private final WarsmashGdxMapGame.CameraManager portraitCameraManager; + private final Scene portraitScene; + + public Portrait(final War3MapViewer war3MapViewer) { + this.portraitScene = war3MapViewer.addSimpleScene(); + this.portraitCameraManager = new WarsmashGdxMapGame.CameraManager(); + this.portraitCameraManager.setupCamera(this.portraitScene); + this.portraitScene.camera.viewport(new Rectangle(100, 0, 6400, 48)); + } + + public void update() { + this.portraitCameraManager.updateCamera(); + if ((this.modelInstance != null) + && (this.modelInstance.sequenceEnded || (this.modelInstance.sequence == -1))) { + StandSequence.randomPortraitSequence(this.modelInstance); + } + } + + public void talk() { + StandSequence.randomPortraitTalkSequence(this.modelInstance); + } + + public void setSelectedUnit(final RenderUnit unit) { + if (unit == null) { + if (this.modelInstance != null) { + this.portraitScene.removeInstance(this.modelInstance); + } + this.modelInstance = null; + this.portraitCameraManager.setModelInstance(null, null); + } + else { + final MdxModel portraitModel = unit.portraitModel; + if (portraitModel != null) { + if (this.modelInstance != null) { + this.portraitScene.removeInstance(this.modelInstance); + } + this.modelInstance = (MdxComplexInstance) portraitModel.addInstance(); + this.portraitCameraManager.setModelInstance(this.modelInstance, portraitModel); + this.modelInstance.setSequenceLoopMode(1); + this.modelInstance.setScene(this.portraitScene); + this.modelInstance.setVertexColor(unit.instance.vertexColor); + this.modelInstance.setTeamColor(unit.playerIndex); + } + } + } + } + + public void selectUnit(final RenderUnit unit) { + this.portrait.setSelectedUnit(unit); + if (unit == null) { + this.simpleNameValue.setText(""); + this.unitLifeText.setText(""); + this.unitManaText.setText(""); + this.simpleClassValue.setText(""); + this.simpleBuildingActionLabel.setText(""); + this.attack1Icon.setVisible(false); + this.attack2Icon.setVisible(false); + this.attack1InfoPanelIconLevel.setText(""); + this.attack2InfoPanelIconLevel.setText(""); + this.armorIcon.setVisible(false); + this.armorInfoPanelIconLevel.setText(""); + } + else { + this.simpleNameValue.setText(unit.getSimulationUnit().getUnitType().getName()); + String classText = null; + for (final CUnitClassification classification : unit.getSimulationUnit().getClassifications()) { + if (classification.getDisplayName() != null) { + classText = classification.getDisplayName(); + } + } + if (classText != null) { + this.simpleClassValue.setText(classText); + } + else { + this.simpleClassValue.setText(""); + } + this.unitLifeText.setText(FastNumberFormat.formatWholeNumber(unit.getSimulationUnit().getLife()) + " / " + + unit.getSimulationUnit().getMaximumLife()); + final int maximumMana = unit.getSimulationUnit().getMaximumMana(); + if (maximumMana > 0) { + this.unitManaText.setText( + FastNumberFormat.formatWholeNumber(unit.getSimulationUnit().getMana()) + " / " + maximumMana); + } + else { + this.unitManaText.setText(""); + } + this.simpleBuildingActionLabel.setText(""); + + if (unit.getSimulationUnit().getUnitType().getAttacks().size() > 0) { + final CUnitAttack attackOne = unit.getSimulationUnit().getUnitType().getAttacks().get(0); + this.attack1Icon.setVisible(attackOne.isShowUI()); + this.attack1IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackOne.getAttackType())); + this.attack1InfoPanelIconValue.setText(attackOne.getMinDamage() + " - " + attackOne.getMaxDamage()); + if (unit.getSimulationUnit().getUnitType().getAttacks().size() > 1) { + final CUnitAttack attackTwo = unit.getSimulationUnit().getUnitType().getAttacks().get(1); + this.attack2Icon.setVisible(attackTwo.isShowUI()); + this.attack2IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackTwo.getAttackType())); + this.attack2InfoPanelIconValue.setText(attackTwo.getMinDamage() + " - " + attackTwo.getMaxDamage()); + } + else { + this.attack2Icon.setVisible(false); + } + } + else { + this.attack1Icon.setVisible(false); + this.attack2Icon.setVisible(false); + } + + this.armorIcon.setVisible(true); + this.armorIconBackdrop.setTexture( + this.defenseBackdrops.getTexture(unit.getSimulationUnit().getUnitType().getDefenseType())); + this.armorInfoPanelIconValue.setText(Integer.toString(unit.getSimulationUnit().getDefense())); + } + } + + public void resize() { + positionPortrait(); + } + + public void positionPortrait() { + this.projectionTemp1.x = 422; + this.projectionTemp1.y = 57; + this.projectionTemp2.x = 422 + 167; + this.projectionTemp2.y = 57 + 170; + this.uiViewport.project(this.projectionTemp1); + this.uiViewport.project(this.projectionTemp2); + + this.tempRect.x = this.projectionTemp1.x; + this.tempRect.y = this.projectionTemp1.y; + this.tempRect.width = this.projectionTemp2.x - this.projectionTemp1.x; + this.tempRect.height = this.projectionTemp2.y - this.projectionTemp1.y; + this.portrait.portraitScene.camera.viewport(this.tempRect); + } + + private static final class InfoPanelIconBackdrops { + private final Texture[] damageBackdropTextures; + + public InfoPanelIconBackdrops(final CodeKeyType[] attackTypes, final GameUI gameUI, final String prefix, + final String suffix) { + this.damageBackdropTextures = new Texture[attackTypes.length]; + for (int index = 0; index < attackTypes.length; index++) { + final CodeKeyType attackType = attackTypes[index]; + String skinLookupKey = "InfoPanelIcon" + prefix + attackType.getCodeKey() + suffix; + try { + this.damageBackdropTextures[index] = gameUI.loadTexture(gameUI.getSkinField(skinLookupKey)); + } + catch (final Exception exc) { + skinLookupKey = "InfoPanelIcon" + prefix + attackType.getCodeKey(); + this.damageBackdropTextures[index] = gameUI.loadTexture(gameUI.getSkinField(skinLookupKey)); + } + } + } + + public Texture getTexture(final CodeKeyType attackType) { + if (attackType != null) { + final int ordinal = attackType.ordinal(); + if ((ordinal >= 0) && (ordinal < this.damageBackdropTextures.length)) { + return this.damageBackdropTextures[ordinal]; + } + } + return this.damageBackdropTextures[0]; + } + + private static String getSuffix(final CAttackType attackType) { + switch (attackType) { + case CHAOS: + return "Chaos"; + case HERO: + return "Hero"; + case MAGIC: + return "Magic"; + case NORMAL: + return "Normal"; + case PIERCE: + return "Pierce"; + case SIEGE: + return "Siege"; + case SPELLS: + return "Magic"; + case UNKNOWN: + return "Unknown"; + default: + throw new IllegalArgumentException("Unknown attack type: " + attackType); + } + + } + } +} diff --git a/desktop/src/com/etheller/warsmash/desktop/DesktopLauncher.java b/desktop/src/com/etheller/warsmash/desktop/DesktopLauncher.java index f6538ff..2c7fba2 100644 --- a/desktop/src/com/etheller/warsmash/desktop/DesktopLauncher.java +++ b/desktop/src/com/etheller/warsmash/desktop/DesktopLauncher.java @@ -84,10 +84,12 @@ public class DesktopLauncher { config.gles30ContextMajorVersion = 3; config.gles30ContextMinorVersion = 3; config.samples = 16; - config.fullscreen = true; - final DisplayMode desktopDisplayMode = LwjglApplicationConfiguration.getDesktopDisplayMode(); - config.width = desktopDisplayMode.width; - config.height = desktopDisplayMode.height; + config.fullscreen = false; + if (config.fullscreen) { + final DisplayMode desktopDisplayMode = LwjglApplicationConfiguration.getDesktopDisplayMode(); + config.width = desktopDisplayMode.width; + config.height = desktopDisplayMode.height; + } new LwjglApplication(new WarsmashGdxMapGame(warsmashIni), config); } } diff --git a/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/FrameDefinition.java b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/FrameDefinition.java index b4f58c5..b655c6d 100644 --- a/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/FrameDefinition.java +++ b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/FrameDefinition.java @@ -9,7 +9,9 @@ import java.util.Set; import com.etheller.warsmash.parsers.fdf.datamodel.fields.FrameDefinitionField; import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetFloatFieldVisitor; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetFontFieldVisitor; import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetStringFieldVisitor; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetTextJustifyFieldVisitor; import com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor.GetVector4FieldVisitor; /** @@ -123,4 +125,20 @@ public class FrameDefinition { } return null; } + + public FontDefinition getFont(final String id) { + final FrameDefinitionField frameDefinitionField = this.nameToField.get(id); + if (frameDefinitionField != null) { + return frameDefinitionField.visit(GetFontFieldVisitor.INSTANCE); + } + return null; + } + + public TextJustify getTextJustify(final String id) { + final FrameDefinitionField frameDefinitionField = this.nameToField.get(id); + if (frameDefinitionField != null) { + return frameDefinitionField.visit(GetTextJustifyFieldVisitor.INSTANCE); + } + return null; + } } diff --git a/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetFontFieldVisitor.java b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetFontFieldVisitor.java new file mode 100644 index 0000000..44f9ece --- /dev/null +++ b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetFontFieldVisitor.java @@ -0,0 +1,57 @@ +package com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor; + +import com.etheller.warsmash.parsers.fdf.datamodel.FontDefinition; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FloatFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FontFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FrameDefinitionFieldVisitor; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.StringFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.StringPairFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.TextJustifyFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector2FrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector3FrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector4FrameDefinitionField; + +public class GetFontFieldVisitor implements FrameDefinitionFieldVisitor { + public static GetFontFieldVisitor INSTANCE = new GetFontFieldVisitor(); + + @Override + public FontDefinition accept(final StringFrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final StringPairFrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final FloatFrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final Vector3FrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final Vector4FrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final Vector2FrameDefinitionField field) { + return null; + } + + @Override + public FontDefinition accept(final FontFrameDefinitionField field) { + return field.getValue(); + } + + @Override + public FontDefinition accept(final TextJustifyFrameDefinitionField field) { + return null; + } + +} diff --git a/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetTextJustifyFieldVisitor.java b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetTextJustifyFieldVisitor.java new file mode 100644 index 0000000..bb45533 --- /dev/null +++ b/fdfparser/src/com/etheller/warsmash/parsers/fdf/datamodel/fields/visitor/GetTextJustifyFieldVisitor.java @@ -0,0 +1,57 @@ +package com.etheller.warsmash.parsers.fdf.datamodel.fields.visitor; + +import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FloatFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FontFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.FrameDefinitionFieldVisitor; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.StringFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.StringPairFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.TextJustifyFrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector2FrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector3FrameDefinitionField; +import com.etheller.warsmash.parsers.fdf.datamodel.fields.Vector4FrameDefinitionField; + +public class GetTextJustifyFieldVisitor implements FrameDefinitionFieldVisitor { + public static GetTextJustifyFieldVisitor INSTANCE = new GetTextJustifyFieldVisitor(); + + @Override + public TextJustify accept(final StringFrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final StringPairFrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final FloatFrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final Vector3FrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final Vector4FrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final Vector2FrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final FontFrameDefinitionField field) { + return null; + } + + @Override + public TextJustify accept(final TextJustifyFrameDefinitionField field) { + return field.getValue(); + } + +} diff --git a/jassparser/.gitignore b/jassparser/.gitignore new file mode 100644 index 0000000..84c048a --- /dev/null +++ b/jassparser/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/jassparser/antlr-src/Jass.g4 b/jassparser/antlr-src/Jass.g4 index 6db646c..cab4935 100644 --- a/jassparser/antlr-src/Jass.g4 +++ b/jassparser/antlr-src/Jass.g4 @@ -19,7 +19,7 @@ program : typeDefinition : TYPE ID EXTENDS ID newlines - ; + ; type : ID # BasicType diff --git a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassBaseVisitor.java b/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassBaseVisitor.java deleted file mode 100644 index 90b541a..0000000 --- a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassBaseVisitor.java +++ /dev/null @@ -1,317 +0,0 @@ -// Generated from Jass.g4 by ANTLR 4.7 - - package com.etheller.interpreter; - -import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; - -/** - * This class provides an empty implementation of {@link JassVisitor}, - * which can be extended to create a visitor which only needs to handle a subset - * of the available methods. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -public class JassBaseVisitor extends AbstractParseTreeVisitor implements JassVisitor { - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitProgram(JassParser.ProgramContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTypeDefinition(JassParser.TypeDefinitionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitBasicType(JassParser.BasicTypeContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitArrayType(JassParser.ArrayTypeContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNothingType(JassParser.NothingTypeContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitBasicGlobal(JassParser.BasicGlobalContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitDefinitionGlobal(JassParser.DefinitionGlobalContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitAssignTail(JassParser.AssignTailContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitReferenceExpression(JassParser.ReferenceExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitStringLiteralExpression(JassParser.StringLiteralExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitIntegerLiteralExpression(JassParser.IntegerLiteralExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFunctionReferenceExpression(JassParser.FunctionReferenceExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNullExpression(JassParser.NullExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTrueExpression(JassParser.TrueExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFalseExpression(JassParser.FalseExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitArrayReferenceExpression(JassParser.ArrayReferenceExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFunctionCallExpression(JassParser.FunctionCallExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitParentheticalExpression(JassParser.ParentheticalExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNotExpression(JassParser.NotExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFunctionExpression(JassParser.FunctionExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSingleArgument(JassParser.SingleArgumentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitListArgument(JassParser.ListArgumentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitCallStatement(JassParser.CallStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSetStatement(JassParser.SetStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitArrayedAssignmentStatement(JassParser.ArrayedAssignmentStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitReturnStatement(JassParser.ReturnStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitIfStatement(JassParser.IfStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSimpleIfStatement(JassParser.SimpleIfStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitIfElseStatement(JassParser.IfElseStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitIfElseIfStatement(JassParser.IfElseIfStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitParam(JassParser.ParamContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSingleParameter(JassParser.SingleParameterContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitListParameter(JassParser.ListParameterContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNothingParameter(JassParser.NothingParameterContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitGlobalsBlock(JassParser.GlobalsBlockContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTypeDefinitionBlock(JassParser.TypeDefinitionBlockContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNativeBlock(JassParser.NativeBlockContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitBlock(JassParser.BlockContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFunctionBlock(JassParser.FunctionBlockContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitStatements(JassParser.StatementsContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNewlines(JassParser.NewlinesContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNewlines_opt(JassParser.Newlines_optContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitPnewlines(JassParser.PnewlinesContext ctx) { return visitChildren(ctx); } -} \ No newline at end of file diff --git a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassLexer.java b/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassLexer.java deleted file mode 100644 index 9f02f08..0000000 --- a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassLexer.java +++ /dev/null @@ -1,224 +0,0 @@ -// Generated from Jass.g4 by ANTLR 4.7 - - package com.etheller.interpreter; - -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) -public class JassLexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, EQUALS=6, GLOBALS=7, ENDGLOBALS=8, - NATIVE=9, FUNCTION=10, TAKES=11, RETURNS=12, ENDFUNCTION=13, NOTHING=14, - CALL=15, SET=16, RETURN=17, ARRAY=18, TYPE=19, EXTENDS=20, IF=21, THEN=22, - ELSE=23, ENDIF=24, ELSEIF=25, CONSTANT=26, STRING_LITERAL=27, INTEGER=28, - NULL=29, TRUE=30, FALSE=31, NOT=32, ID=33, WS=34, NEWLINE=35; - public static String[] channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" - }; - - public static String[] modeNames = { - "DEFAULT_MODE" - }; - - public static final String[] ruleNames = { - "T__0", "T__1", "T__2", "T__3", "T__4", "EQUALS", "GLOBALS", "ENDGLOBALS", - "NATIVE", "FUNCTION", "TAKES", "RETURNS", "ENDFUNCTION", "NOTHING", "CALL", - "SET", "RETURN", "ARRAY", "TYPE", "EXTENDS", "IF", "THEN", "ELSE", "ENDIF", - "ELSEIF", "CONSTANT", "STRING_LITERAL", "INTEGER", "NULL", "TRUE", "FALSE", - "NOT", "ID", "WS", "NEWLINE" - }; - - private static final String[] _LITERAL_NAMES = { - null, "'['", "']'", "'('", "')'", "','", "'='", "'globals'", "'endglobals'", - "'native'", "'function'", "'takes'", "'returns'", "'endfunction'", "'nothing'", - "'call'", "'set'", "'return'", "'array'", "'type'", "'extends'", "'if'", - "'then'", "'else'", "'endif'", "'elseif'", "'constant'", null, null, "'null'", - "'true'", "'false'", "'not'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, "EQUALS", "GLOBALS", "ENDGLOBALS", - "NATIVE", "FUNCTION", "TAKES", "RETURNS", "ENDFUNCTION", "NOTHING", "CALL", - "SET", "RETURN", "ARRAY", "TYPE", "EXTENDS", "IF", "THEN", "ELSE", "ENDIF", - "ELSEIF", "CONSTANT", "STRING_LITERAL", "INTEGER", "NULL", "TRUE", "FALSE", - "NOT", "ID", "WS", "NEWLINE" - }; - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - - public JassLexer(CharStream input) { - super(input); - _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @Override - public String getGrammarFileName() { return "Jass.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public String[] getChannelNames() { return channelNames; } - - @Override - public String[] getModeNames() { return modeNames; } - - @Override - public ATN getATN() { return _ATN; } - - public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2%\u0139\b\1\4\2\t"+ - "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ - "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ - "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ - "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ - "\t!\4\"\t\"\4#\t#\4$\t$\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3"+ - "\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t"+ - "\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+ - "\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16"+ - "\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17"+ - "\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21"+ - "\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24"+ - "\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26"+ - "\3\26\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31"+ - "\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33"+ - "\3\33\3\33\3\33\3\33\3\33\3\34\3\34\7\34\u00e3\n\34\f\34\16\34\u00e6\13"+ - "\34\3\34\3\34\3\35\3\35\3\35\7\35\u00ed\n\35\f\35\16\35\u00f0\13\35\5"+ - "\35\u00f2\n\35\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3 \3"+ - " \3 \3 \3 \3 \3!\3!\3!\3!\3\"\3\"\7\"\u010a\n\"\f\"\16\"\u010d\13\"\3"+ - "#\6#\u0110\n#\r#\16#\u0111\3#\3#\3$\3$\3$\3$\7$\u011a\n$\f$\16$\u011d"+ - "\13$\3$\3$\3$\3$\3$\3$\7$\u0125\n$\f$\16$\u0128\13$\3$\3$\3$\3$\3$\7$"+ - "\u012f\n$\f$\16$\u0132\13$\3$\3$\3$\3$\5$\u0138\n$\6\u00e4\u011b\u0126"+ - "\u0130\2%\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33"+ - "\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67"+ - "\359\36;\37= ?!A\"C#E$G%\3\2\t\3\2\62\62\3\2\63;\3\2\62;\5\2C\\aac|\6"+ - "\2\62;C\\aac|\4\2\13\13\"\"\4\2\f\f\17\17\2\u0144\2\3\3\2\2\2\2\5\3\2"+ - "\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+ - "\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2"+ - "\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3"+ - "\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3"+ - "\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3"+ - "\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\3I\3\2\2\2\5K\3\2\2"+ - "\2\7M\3\2\2\2\tO\3\2\2\2\13Q\3\2\2\2\rS\3\2\2\2\17U\3\2\2\2\21]\3\2\2"+ - "\2\23h\3\2\2\2\25o\3\2\2\2\27x\3\2\2\2\31~\3\2\2\2\33\u0086\3\2\2\2\35"+ - "\u0092\3\2\2\2\37\u009a\3\2\2\2!\u009f\3\2\2\2#\u00a3\3\2\2\2%\u00aa\3"+ - "\2\2\2\'\u00b0\3\2\2\2)\u00b5\3\2\2\2+\u00bd\3\2\2\2-\u00c0\3\2\2\2/\u00c5"+ - "\3\2\2\2\61\u00ca\3\2\2\2\63\u00d0\3\2\2\2\65\u00d7\3\2\2\2\67\u00e0\3"+ - "\2\2\29\u00f1\3\2\2\2;\u00f3\3\2\2\2=\u00f8\3\2\2\2?\u00fd\3\2\2\2A\u0103"+ - "\3\2\2\2C\u0107\3\2\2\2E\u010f\3\2\2\2G\u0137\3\2\2\2IJ\7]\2\2J\4\3\2"+ - "\2\2KL\7_\2\2L\6\3\2\2\2MN\7*\2\2N\b\3\2\2\2OP\7+\2\2P\n\3\2\2\2QR\7."+ - "\2\2R\f\3\2\2\2ST\7?\2\2T\16\3\2\2\2UV\7i\2\2VW\7n\2\2WX\7q\2\2XY\7d\2"+ - "\2YZ\7c\2\2Z[\7n\2\2[\\\7u\2\2\\\20\3\2\2\2]^\7g\2\2^_\7p\2\2_`\7f\2\2"+ - "`a\7i\2\2ab\7n\2\2bc\7q\2\2cd\7d\2\2de\7c\2\2ef\7n\2\2fg\7u\2\2g\22\3"+ - "\2\2\2hi\7p\2\2ij\7c\2\2jk\7v\2\2kl\7k\2\2lm\7x\2\2mn\7g\2\2n\24\3\2\2"+ - "\2op\7h\2\2pq\7w\2\2qr\7p\2\2rs\7e\2\2st\7v\2\2tu\7k\2\2uv\7q\2\2vw\7"+ - "p\2\2w\26\3\2\2\2xy\7v\2\2yz\7c\2\2z{\7m\2\2{|\7g\2\2|}\7u\2\2}\30\3\2"+ - "\2\2~\177\7t\2\2\177\u0080\7g\2\2\u0080\u0081\7v\2\2\u0081\u0082\7w\2"+ - "\2\u0082\u0083\7t\2\2\u0083\u0084\7p\2\2\u0084\u0085\7u\2\2\u0085\32\3"+ - "\2\2\2\u0086\u0087\7g\2\2\u0087\u0088\7p\2\2\u0088\u0089\7f\2\2\u0089"+ - "\u008a\7h\2\2\u008a\u008b\7w\2\2\u008b\u008c\7p\2\2\u008c\u008d\7e\2\2"+ - "\u008d\u008e\7v\2\2\u008e\u008f\7k\2\2\u008f\u0090\7q\2\2\u0090\u0091"+ - "\7p\2\2\u0091\34\3\2\2\2\u0092\u0093\7p\2\2\u0093\u0094\7q\2\2\u0094\u0095"+ - "\7v\2\2\u0095\u0096\7j\2\2\u0096\u0097\7k\2\2\u0097\u0098\7p\2\2\u0098"+ - "\u0099\7i\2\2\u0099\36\3\2\2\2\u009a\u009b\7e\2\2\u009b\u009c\7c\2\2\u009c"+ - "\u009d\7n\2\2\u009d\u009e\7n\2\2\u009e \3\2\2\2\u009f\u00a0\7u\2\2\u00a0"+ - "\u00a1\7g\2\2\u00a1\u00a2\7v\2\2\u00a2\"\3\2\2\2\u00a3\u00a4\7t\2\2\u00a4"+ - "\u00a5\7g\2\2\u00a5\u00a6\7v\2\2\u00a6\u00a7\7w\2\2\u00a7\u00a8\7t\2\2"+ - "\u00a8\u00a9\7p\2\2\u00a9$\3\2\2\2\u00aa\u00ab\7c\2\2\u00ab\u00ac\7t\2"+ - "\2\u00ac\u00ad\7t\2\2\u00ad\u00ae\7c\2\2\u00ae\u00af\7{\2\2\u00af&\3\2"+ - "\2\2\u00b0\u00b1\7v\2\2\u00b1\u00b2\7{\2\2\u00b2\u00b3\7r\2\2\u00b3\u00b4"+ - "\7g\2\2\u00b4(\3\2\2\2\u00b5\u00b6\7g\2\2\u00b6\u00b7\7z\2\2\u00b7\u00b8"+ - "\7v\2\2\u00b8\u00b9\7g\2\2\u00b9\u00ba\7p\2\2\u00ba\u00bb\7f\2\2\u00bb"+ - "\u00bc\7u\2\2\u00bc*\3\2\2\2\u00bd\u00be\7k\2\2\u00be\u00bf\7h\2\2\u00bf"+ - ",\3\2\2\2\u00c0\u00c1\7v\2\2\u00c1\u00c2\7j\2\2\u00c2\u00c3\7g\2\2\u00c3"+ - "\u00c4\7p\2\2\u00c4.\3\2\2\2\u00c5\u00c6\7g\2\2\u00c6\u00c7\7n\2\2\u00c7"+ - "\u00c8\7u\2\2\u00c8\u00c9\7g\2\2\u00c9\60\3\2\2\2\u00ca\u00cb\7g\2\2\u00cb"+ - "\u00cc\7p\2\2\u00cc\u00cd\7f\2\2\u00cd\u00ce\7k\2\2\u00ce\u00cf\7h\2\2"+ - "\u00cf\62\3\2\2\2\u00d0\u00d1\7g\2\2\u00d1\u00d2\7n\2\2\u00d2\u00d3\7"+ - "u\2\2\u00d3\u00d4\7g\2\2\u00d4\u00d5\7k\2\2\u00d5\u00d6\7h\2\2\u00d6\64"+ - "\3\2\2\2\u00d7\u00d8\7e\2\2\u00d8\u00d9\7q\2\2\u00d9\u00da\7p\2\2\u00da"+ - "\u00db\7u\2\2\u00db\u00dc\7v\2\2\u00dc\u00dd\7c\2\2\u00dd\u00de\7p\2\2"+ - "\u00de\u00df\7v\2\2\u00df\66\3\2\2\2\u00e0\u00e4\7$\2\2\u00e1\u00e3\13"+ - "\2\2\2\u00e2\u00e1\3\2\2\2\u00e3\u00e6\3\2\2\2\u00e4\u00e5\3\2\2\2\u00e4"+ - "\u00e2\3\2\2\2\u00e5\u00e7\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e7\u00e8\7$"+ - "\2\2\u00e88\3\2\2\2\u00e9\u00f2\t\2\2\2\u00ea\u00ee\t\3\2\2\u00eb\u00ed"+ - "\t\4\2\2\u00ec\u00eb\3\2\2\2\u00ed\u00f0\3\2\2\2\u00ee\u00ec\3\2\2\2\u00ee"+ - "\u00ef\3\2\2\2\u00ef\u00f2\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f1\u00e9\3\2"+ - "\2\2\u00f1\u00ea\3\2\2\2\u00f2:\3\2\2\2\u00f3\u00f4\7p\2\2\u00f4\u00f5"+ - "\7w\2\2\u00f5\u00f6\7n\2\2\u00f6\u00f7\7n\2\2\u00f7<\3\2\2\2\u00f8\u00f9"+ - "\7v\2\2\u00f9\u00fa\7t\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7g\2\2\u00fc"+ - ">\3\2\2\2\u00fd\u00fe\7h\2\2\u00fe\u00ff\7c\2\2\u00ff\u0100\7n\2\2\u0100"+ - "\u0101\7u\2\2\u0101\u0102\7g\2\2\u0102@\3\2\2\2\u0103\u0104\7p\2\2\u0104"+ - "\u0105\7q\2\2\u0105\u0106\7v\2\2\u0106B\3\2\2\2\u0107\u010b\t\5\2\2\u0108"+ - "\u010a\t\6\2\2\u0109\u0108\3\2\2\2\u010a\u010d\3\2\2\2\u010b\u0109\3\2"+ - "\2\2\u010b\u010c\3\2\2\2\u010cD\3\2\2\2\u010d\u010b\3\2\2\2\u010e\u0110"+ - "\t\7\2\2\u010f\u010e\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u010f\3\2\2\2\u0111"+ - "\u0112\3\2\2\2\u0112\u0113\3\2\2\2\u0113\u0114\b#\2\2\u0114F\3\2\2\2\u0115"+ - "\u0116\7\61\2\2\u0116\u0117\7\61\2\2\u0117\u011b\3\2\2\2\u0118\u011a\13"+ - "\2\2\2\u0119\u0118\3\2\2\2\u011a\u011d\3\2\2\2\u011b\u011c\3\2\2\2\u011b"+ - "\u0119\3\2\2\2\u011c\u011e\3\2\2\2\u011d\u011b\3\2\2\2\u011e\u011f\7\17"+ - "\2\2\u011f\u0138\7\f\2\2\u0120\u0121\7\61\2\2\u0121\u0122\7\61\2\2\u0122"+ - "\u0126\3\2\2\2\u0123\u0125\13\2\2\2\u0124\u0123\3\2\2\2\u0125\u0128\3"+ - "\2\2\2\u0126\u0127\3\2\2\2\u0126\u0124\3\2\2\2\u0127\u0129\3\2\2\2\u0128"+ - "\u0126\3\2\2\2\u0129\u0138\7\f\2\2\u012a\u012b\7\61\2\2\u012b\u012c\7"+ - "\61\2\2\u012c\u0130\3\2\2\2\u012d\u012f\13\2\2\2\u012e\u012d\3\2\2\2\u012f"+ - "\u0132\3\2\2\2\u0130\u0131\3\2\2\2\u0130\u012e\3\2\2\2\u0131\u0133\3\2"+ - "\2\2\u0132\u0130\3\2\2\2\u0133\u0138\7\17\2\2\u0134\u0135\7\17\2\2\u0135"+ - "\u0138\7\f\2\2\u0136\u0138\t\b\2\2\u0137\u0115\3\2\2\2\u0137\u0120\3\2"+ - "\2\2\u0137\u012a\3\2\2\2\u0137\u0134\3\2\2\2\u0137\u0136\3\2\2\2\u0138"+ - "H\3\2\2\2\f\2\u00e4\u00ee\u00f1\u010b\u0111\u011b\u0126\u0130\u0137\3"+ - "\b\2\2"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassParser.java b/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassParser.java deleted file mode 100644 index 886a399..0000000 --- a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassParser.java +++ /dev/null @@ -1,1969 +0,0 @@ -// Generated from Jass.g4 by ANTLR 4.7 - - package com.etheller.interpreter; - -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.misc.*; -import org.antlr.v4.runtime.tree.*; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) -public class JassParser extends Parser { - static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, EQUALS=6, GLOBALS=7, ENDGLOBALS=8, - NATIVE=9, FUNCTION=10, TAKES=11, RETURNS=12, ENDFUNCTION=13, NOTHING=14, - CALL=15, SET=16, RETURN=17, ARRAY=18, TYPE=19, EXTENDS=20, IF=21, THEN=22, - ELSE=23, ENDIF=24, ELSEIF=25, CONSTANT=26, STRING_LITERAL=27, INTEGER=28, - NULL=29, TRUE=30, FALSE=31, NOT=32, ID=33, WS=34, NEWLINE=35; - public static final int - RULE_program = 0, RULE_typeDefinition = 1, RULE_type = 2, RULE_global = 3, - RULE_assignTail = 4, RULE_expression = 5, RULE_functionExpression = 6, - RULE_argsList = 7, RULE_statement = 8, RULE_ifStatementPartial = 9, RULE_param = 10, - RULE_paramList = 11, RULE_globalsBlock = 12, RULE_typeDefinitionBlock = 13, - RULE_nativeBlock = 14, RULE_block = 15, RULE_functionBlock = 16, RULE_statements = 17, - RULE_newlines = 18, RULE_newlines_opt = 19, RULE_pnewlines = 20; - public static final String[] ruleNames = { - "program", "typeDefinition", "type", "global", "assignTail", "expression", - "functionExpression", "argsList", "statement", "ifStatementPartial", "param", - "paramList", "globalsBlock", "typeDefinitionBlock", "nativeBlock", "block", - "functionBlock", "statements", "newlines", "newlines_opt", "pnewlines" - }; - - private static final String[] _LITERAL_NAMES = { - null, "'['", "']'", "'('", "')'", "','", "'='", "'globals'", "'endglobals'", - "'native'", "'function'", "'takes'", "'returns'", "'endfunction'", "'nothing'", - "'call'", "'set'", "'return'", "'array'", "'type'", "'extends'", "'if'", - "'then'", "'else'", "'endif'", "'elseif'", "'constant'", null, null, "'null'", - "'true'", "'false'", "'not'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, "EQUALS", "GLOBALS", "ENDGLOBALS", - "NATIVE", "FUNCTION", "TAKES", "RETURNS", "ENDFUNCTION", "NOTHING", "CALL", - "SET", "RETURN", "ARRAY", "TYPE", "EXTENDS", "IF", "THEN", "ELSE", "ENDIF", - "ELSEIF", "CONSTANT", "STRING_LITERAL", "INTEGER", "NULL", "TRUE", "FALSE", - "NOT", "ID", "WS", "NEWLINE" - }; - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - @Override - public String getGrammarFileName() { return "Jass.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public ATN getATN() { return _ATN; } - - public JassParser(TokenStream input) { - super(input); - _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - public static class ProgramContext extends ParserRuleContext { - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public Newlines_optContext newlines_opt() { - return getRuleContext(Newlines_optContext.class,0); - } - public TypeDefinitionBlockContext typeDefinitionBlock() { - return getRuleContext(TypeDefinitionBlockContext.class,0); - } - public List block() { - return getRuleContexts(BlockContext.class); - } - public BlockContext block(int i) { - return getRuleContext(BlockContext.class,i); - } - public List functionBlock() { - return getRuleContexts(FunctionBlockContext.class); - } - public FunctionBlockContext functionBlock(int i) { - return getRuleContext(FunctionBlockContext.class,i); - } - public ProgramContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_program; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitProgram(this); - else return visitor.visitChildren(this); - } - } - - public final ProgramContext program() throws RecognitionException { - ProgramContext _localctx = new ProgramContext(_ctx, getState()); - enterRule(_localctx, 0, RULE_program); - int _la; - try { - setState(57); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(42); - newlines(); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(43); - newlines_opt(); - setState(44); - typeDefinitionBlock(); - setState(48); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << GLOBALS) | (1L << NATIVE) | (1L << CONSTANT))) != 0)) { - { - { - setState(45); - block(); - } - } - setState(50); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(54); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==FUNCTION) { - { - { - setState(51); - functionBlock(); - } - } - setState(56); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class TypeDefinitionContext extends ParserRuleContext { - public TerminalNode TYPE() { return getToken(JassParser.TYPE, 0); } - public List ID() { return getTokens(JassParser.ID); } - public TerminalNode ID(int i) { - return getToken(JassParser.ID, i); - } - public TerminalNode EXTENDS() { return getToken(JassParser.EXTENDS, 0); } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public TypeDefinitionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_typeDefinition; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitTypeDefinition(this); - else return visitor.visitChildren(this); - } - } - - public final TypeDefinitionContext typeDefinition() throws RecognitionException { - TypeDefinitionContext _localctx = new TypeDefinitionContext(_ctx, getState()); - enterRule(_localctx, 2, RULE_typeDefinition); - try { - enterOuterAlt(_localctx, 1); - { - setState(59); - match(TYPE); - setState(60); - match(ID); - setState(61); - match(EXTENDS); - setState(62); - match(ID); - setState(63); - newlines(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class TypeContext extends ParserRuleContext { - public TypeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_type; } - - public TypeContext() { } - public void copyFrom(TypeContext ctx) { - super.copyFrom(ctx); - } - } - public static class ArrayTypeContext extends TypeContext { - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public TerminalNode ARRAY() { return getToken(JassParser.ARRAY, 0); } - public ArrayTypeContext(TypeContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitArrayType(this); - else return visitor.visitChildren(this); - } - } - public static class BasicTypeContext extends TypeContext { - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public BasicTypeContext(TypeContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitBasicType(this); - else return visitor.visitChildren(this); - } - } - public static class NothingTypeContext extends TypeContext { - public TerminalNode NOTHING() { return getToken(JassParser.NOTHING, 0); } - public NothingTypeContext(TypeContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNothingType(this); - else return visitor.visitChildren(this); - } - } - - public final TypeContext type() throws RecognitionException { - TypeContext _localctx = new TypeContext(_ctx, getState()); - enterRule(_localctx, 4, RULE_type); - try { - setState(69); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) { - case 1: - _localctx = new BasicTypeContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(65); - match(ID); - } - break; - case 2: - _localctx = new ArrayTypeContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(66); - match(ID); - setState(67); - match(ARRAY); - } - break; - case 3: - _localctx = new NothingTypeContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(68); - match(NOTHING); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class GlobalContext extends ParserRuleContext { - public GlobalContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_global; } - - public GlobalContext() { } - public void copyFrom(GlobalContext ctx) { - super.copyFrom(ctx); - } - } - public static class DefinitionGlobalContext extends GlobalContext { - public TypeContext type() { - return getRuleContext(TypeContext.class,0); - } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public AssignTailContext assignTail() { - return getRuleContext(AssignTailContext.class,0); - } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public TerminalNode CONSTANT() { return getToken(JassParser.CONSTANT, 0); } - public DefinitionGlobalContext(GlobalContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitDefinitionGlobal(this); - else return visitor.visitChildren(this); - } - } - public static class BasicGlobalContext extends GlobalContext { - public TypeContext type() { - return getRuleContext(TypeContext.class,0); - } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public TerminalNode CONSTANT() { return getToken(JassParser.CONSTANT, 0); } - public BasicGlobalContext(GlobalContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitBasicGlobal(this); - else return visitor.visitChildren(this); - } - } - - public final GlobalContext global() throws RecognitionException { - GlobalContext _localctx = new GlobalContext(_ctx, getState()); - enterRule(_localctx, 6, RULE_global); - int _la; - try { - setState(86); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { - case 1: - _localctx = new BasicGlobalContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(72); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==CONSTANT) { - { - setState(71); - match(CONSTANT); - } - } - - setState(74); - type(); - setState(75); - match(ID); - setState(76); - newlines(); - } - break; - case 2: - _localctx = new DefinitionGlobalContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(79); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==CONSTANT) { - { - setState(78); - match(CONSTANT); - } - } - - setState(81); - type(); - setState(82); - match(ID); - setState(83); - assignTail(); - setState(84); - newlines(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class AssignTailContext extends ParserRuleContext { - public TerminalNode EQUALS() { return getToken(JassParser.EQUALS, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public AssignTailContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_assignTail; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitAssignTail(this); - else return visitor.visitChildren(this); - } - } - - public final AssignTailContext assignTail() throws RecognitionException { - AssignTailContext _localctx = new AssignTailContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_assignTail); - try { - enterOuterAlt(_localctx, 1); - { - setState(88); - match(EQUALS); - setState(89); - expression(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ExpressionContext extends ParserRuleContext { - public ExpressionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_expression; } - - public ExpressionContext() { } - public void copyFrom(ExpressionContext ctx) { - super.copyFrom(ctx); - } - } - public static class TrueExpressionContext extends ExpressionContext { - public TerminalNode TRUE() { return getToken(JassParser.TRUE, 0); } - public TrueExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitTrueExpression(this); - else return visitor.visitChildren(this); - } - } - public static class ParentheticalExpressionContext extends ExpressionContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public ParentheticalExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitParentheticalExpression(this); - else return visitor.visitChildren(this); - } - } - public static class StringLiteralExpressionContext extends ExpressionContext { - public TerminalNode STRING_LITERAL() { return getToken(JassParser.STRING_LITERAL, 0); } - public StringLiteralExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitStringLiteralExpression(this); - else return visitor.visitChildren(this); - } - } - public static class IntegerLiteralExpressionContext extends ExpressionContext { - public TerminalNode INTEGER() { return getToken(JassParser.INTEGER, 0); } - public IntegerLiteralExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitIntegerLiteralExpression(this); - else return visitor.visitChildren(this); - } - } - public static class ReferenceExpressionContext extends ExpressionContext { - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public ReferenceExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitReferenceExpression(this); - else return visitor.visitChildren(this); - } - } - public static class FunctionReferenceExpressionContext extends ExpressionContext { - public TerminalNode FUNCTION() { return getToken(JassParser.FUNCTION, 0); } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public FunctionReferenceExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitFunctionReferenceExpression(this); - else return visitor.visitChildren(this); - } - } - public static class NotExpressionContext extends ExpressionContext { - public TerminalNode NOT() { return getToken(JassParser.NOT, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public NotExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNotExpression(this); - else return visitor.visitChildren(this); - } - } - public static class ArrayReferenceExpressionContext extends ExpressionContext { - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public ArrayReferenceExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitArrayReferenceExpression(this); - else return visitor.visitChildren(this); - } - } - public static class FunctionCallExpressionContext extends ExpressionContext { - public FunctionExpressionContext functionExpression() { - return getRuleContext(FunctionExpressionContext.class,0); - } - public FunctionCallExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitFunctionCallExpression(this); - else return visitor.visitChildren(this); - } - } - public static class NullExpressionContext extends ExpressionContext { - public TerminalNode NULL() { return getToken(JassParser.NULL, 0); } - public NullExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNullExpression(this); - else return visitor.visitChildren(this); - } - } - public static class FalseExpressionContext extends ExpressionContext { - public TerminalNode FALSE() { return getToken(JassParser.FALSE, 0); } - public FalseExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitFalseExpression(this); - else return visitor.visitChildren(this); - } - } - - public final ExpressionContext expression() throws RecognitionException { - ExpressionContext _localctx = new ExpressionContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_expression); - try { - setState(111); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { - case 1: - _localctx = new ReferenceExpressionContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(91); - match(ID); - } - break; - case 2: - _localctx = new StringLiteralExpressionContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(92); - match(STRING_LITERAL); - } - break; - case 3: - _localctx = new IntegerLiteralExpressionContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(93); - match(INTEGER); - } - break; - case 4: - _localctx = new FunctionReferenceExpressionContext(_localctx); - enterOuterAlt(_localctx, 4); - { - setState(94); - match(FUNCTION); - setState(95); - match(ID); - } - break; - case 5: - _localctx = new NullExpressionContext(_localctx); - enterOuterAlt(_localctx, 5); - { - setState(96); - match(NULL); - } - break; - case 6: - _localctx = new TrueExpressionContext(_localctx); - enterOuterAlt(_localctx, 6); - { - setState(97); - match(TRUE); - } - break; - case 7: - _localctx = new FalseExpressionContext(_localctx); - enterOuterAlt(_localctx, 7); - { - setState(98); - match(FALSE); - } - break; - case 8: - _localctx = new ArrayReferenceExpressionContext(_localctx); - enterOuterAlt(_localctx, 8); - { - setState(99); - match(ID); - setState(100); - match(T__0); - setState(101); - expression(); - setState(102); - match(T__1); - } - break; - case 9: - _localctx = new FunctionCallExpressionContext(_localctx); - enterOuterAlt(_localctx, 9); - { - setState(104); - functionExpression(); - } - break; - case 10: - _localctx = new ParentheticalExpressionContext(_localctx); - enterOuterAlt(_localctx, 10); - { - setState(105); - match(T__2); - setState(106); - expression(); - setState(107); - match(T__3); - } - break; - case 11: - _localctx = new NotExpressionContext(_localctx); - enterOuterAlt(_localctx, 11); - { - setState(109); - match(NOT); - setState(110); - expression(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class FunctionExpressionContext extends ParserRuleContext { - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public ArgsListContext argsList() { - return getRuleContext(ArgsListContext.class,0); - } - public FunctionExpressionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_functionExpression; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitFunctionExpression(this); - else return visitor.visitChildren(this); - } - } - - public final FunctionExpressionContext functionExpression() throws RecognitionException { - FunctionExpressionContext _localctx = new FunctionExpressionContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_functionExpression); - try { - setState(121); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(113); - match(ID); - setState(114); - match(T__2); - setState(115); - argsList(); - setState(116); - match(T__3); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(118); - match(ID); - setState(119); - match(T__2); - setState(120); - match(T__3); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ArgsListContext extends ParserRuleContext { - public ArgsListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_argsList; } - - public ArgsListContext() { } - public void copyFrom(ArgsListContext ctx) { - super.copyFrom(ctx); - } - } - public static class SingleArgumentContext extends ArgsListContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public SingleArgumentContext(ArgsListContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitSingleArgument(this); - else return visitor.visitChildren(this); - } - } - public static class ListArgumentContext extends ArgsListContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public ArgsListContext argsList() { - return getRuleContext(ArgsListContext.class,0); - } - public ListArgumentContext(ArgsListContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitListArgument(this); - else return visitor.visitChildren(this); - } - } - - public final ArgsListContext argsList() throws RecognitionException { - ArgsListContext _localctx = new ArgsListContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_argsList); - try { - setState(128); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) { - case 1: - _localctx = new SingleArgumentContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(123); - expression(); - } - break; - case 2: - _localctx = new ListArgumentContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(124); - expression(); - setState(125); - match(T__4); - setState(126); - argsList(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class StatementContext extends ParserRuleContext { - public StatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_statement; } - - public StatementContext() { } - public void copyFrom(StatementContext ctx) { - super.copyFrom(ctx); - } - } - public static class ArrayedAssignmentStatementContext extends StatementContext { - public TerminalNode SET() { return getToken(JassParser.SET, 0); } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public List expression() { - return getRuleContexts(ExpressionContext.class); - } - public ExpressionContext expression(int i) { - return getRuleContext(ExpressionContext.class,i); - } - public TerminalNode EQUALS() { return getToken(JassParser.EQUALS, 0); } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public ArrayedAssignmentStatementContext(StatementContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitArrayedAssignmentStatement(this); - else return visitor.visitChildren(this); - } - } - public static class IfStatementContext extends StatementContext { - public TerminalNode IF() { return getToken(JassParser.IF, 0); } - public IfStatementPartialContext ifStatementPartial() { - return getRuleContext(IfStatementPartialContext.class,0); - } - public IfStatementContext(StatementContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitIfStatement(this); - else return visitor.visitChildren(this); - } - } - public static class ReturnStatementContext extends StatementContext { - public TerminalNode RETURN() { return getToken(JassParser.RETURN, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public ReturnStatementContext(StatementContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitReturnStatement(this); - else return visitor.visitChildren(this); - } - } - public static class CallStatementContext extends StatementContext { - public TerminalNode CALL() { return getToken(JassParser.CALL, 0); } - public FunctionExpressionContext functionExpression() { - return getRuleContext(FunctionExpressionContext.class,0); - } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public CallStatementContext(StatementContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitCallStatement(this); - else return visitor.visitChildren(this); - } - } - public static class SetStatementContext extends StatementContext { - public TerminalNode SET() { return getToken(JassParser.SET, 0); } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public TerminalNode EQUALS() { return getToken(JassParser.EQUALS, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public SetStatementContext(StatementContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitSetStatement(this); - else return visitor.visitChildren(this); - } - } - - public final StatementContext statement() throws RecognitionException { - StatementContext _localctx = new StatementContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_statement); - try { - setState(155); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { - case 1: - _localctx = new CallStatementContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(130); - match(CALL); - setState(131); - functionExpression(); - setState(132); - newlines(); - } - break; - case 2: - _localctx = new SetStatementContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(134); - match(SET); - setState(135); - match(ID); - setState(136); - match(EQUALS); - setState(137); - expression(); - setState(138); - newlines(); - } - break; - case 3: - _localctx = new ArrayedAssignmentStatementContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(140); - match(SET); - setState(141); - match(ID); - setState(142); - match(T__0); - setState(143); - expression(); - setState(144); - match(T__1); - setState(145); - match(EQUALS); - setState(146); - expression(); - setState(147); - newlines(); - } - break; - case 4: - _localctx = new ReturnStatementContext(_localctx); - enterOuterAlt(_localctx, 4); - { - setState(149); - match(RETURN); - setState(150); - expression(); - setState(151); - newlines(); - } - break; - case 5: - _localctx = new IfStatementContext(_localctx); - enterOuterAlt(_localctx, 5); - { - setState(153); - match(IF); - setState(154); - ifStatementPartial(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class IfStatementPartialContext extends ParserRuleContext { - public IfStatementPartialContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_ifStatementPartial; } - - public IfStatementPartialContext() { } - public void copyFrom(IfStatementPartialContext ctx) { - super.copyFrom(ctx); - } - } - public static class IfElseIfStatementContext extends IfStatementPartialContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode THEN() { return getToken(JassParser.THEN, 0); } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public TerminalNode ELSEIF() { return getToken(JassParser.ELSEIF, 0); } - public IfStatementPartialContext ifStatementPartial() { - return getRuleContext(IfStatementPartialContext.class,0); - } - public IfElseIfStatementContext(IfStatementPartialContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitIfElseIfStatement(this); - else return visitor.visitChildren(this); - } - } - public static class IfElseStatementContext extends IfStatementPartialContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode THEN() { return getToken(JassParser.THEN, 0); } - public List newlines() { - return getRuleContexts(NewlinesContext.class); - } - public NewlinesContext newlines(int i) { - return getRuleContext(NewlinesContext.class,i); - } - public List statements() { - return getRuleContexts(StatementsContext.class); - } - public StatementsContext statements(int i) { - return getRuleContext(StatementsContext.class,i); - } - public TerminalNode ELSE() { return getToken(JassParser.ELSE, 0); } - public TerminalNode ENDIF() { return getToken(JassParser.ENDIF, 0); } - public IfElseStatementContext(IfStatementPartialContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitIfElseStatement(this); - else return visitor.visitChildren(this); - } - } - public static class SimpleIfStatementContext extends IfStatementPartialContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode THEN() { return getToken(JassParser.THEN, 0); } - public List newlines() { - return getRuleContexts(NewlinesContext.class); - } - public NewlinesContext newlines(int i) { - return getRuleContext(NewlinesContext.class,i); - } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public TerminalNode ENDIF() { return getToken(JassParser.ENDIF, 0); } - public SimpleIfStatementContext(IfStatementPartialContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitSimpleIfStatement(this); - else return visitor.visitChildren(this); - } - } - - public final IfStatementPartialContext ifStatementPartial() throws RecognitionException { - IfStatementPartialContext _localctx = new IfStatementPartialContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_ifStatementPartial); - try { - setState(181); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { - case 1: - _localctx = new SimpleIfStatementContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(157); - expression(); - setState(158); - match(THEN); - setState(159); - newlines(); - setState(160); - statements(); - setState(161); - match(ENDIF); - setState(162); - newlines(); - } - break; - case 2: - _localctx = new IfElseStatementContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(164); - expression(); - setState(165); - match(THEN); - setState(166); - newlines(); - setState(167); - statements(); - setState(168); - match(ELSE); - setState(169); - newlines(); - setState(170); - statements(); - setState(171); - match(ENDIF); - setState(172); - newlines(); - } - break; - case 3: - _localctx = new IfElseIfStatementContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(174); - expression(); - setState(175); - match(THEN); - setState(176); - newlines(); - setState(177); - statements(); - setState(178); - match(ELSEIF); - setState(179); - ifStatementPartial(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ParamContext extends ParserRuleContext { - public TypeContext type() { - return getRuleContext(TypeContext.class,0); - } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public ParamContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_param; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitParam(this); - else return visitor.visitChildren(this); - } - } - - public final ParamContext param() throws RecognitionException { - ParamContext _localctx = new ParamContext(_ctx, getState()); - enterRule(_localctx, 20, RULE_param); - try { - enterOuterAlt(_localctx, 1); - { - setState(183); - type(); - setState(184); - match(ID); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ParamListContext extends ParserRuleContext { - public ParamListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_paramList; } - - public ParamListContext() { } - public void copyFrom(ParamListContext ctx) { - super.copyFrom(ctx); - } - } - public static class NothingParameterContext extends ParamListContext { - public TerminalNode NOTHING() { return getToken(JassParser.NOTHING, 0); } - public NothingParameterContext(ParamListContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNothingParameter(this); - else return visitor.visitChildren(this); - } - } - public static class SingleParameterContext extends ParamListContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); - } - public SingleParameterContext(ParamListContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitSingleParameter(this); - else return visitor.visitChildren(this); - } - } - public static class ListParameterContext extends ParamListContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); - } - public ParamListContext paramList() { - return getRuleContext(ParamListContext.class,0); - } - public ListParameterContext(ParamListContext ctx) { copyFrom(ctx); } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitListParameter(this); - else return visitor.visitChildren(this); - } - } - - public final ParamListContext paramList() throws RecognitionException { - ParamListContext _localctx = new ParamListContext(_ctx, getState()); - enterRule(_localctx, 22, RULE_paramList); - try { - setState(192); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { - case 1: - _localctx = new SingleParameterContext(_localctx); - enterOuterAlt(_localctx, 1); - { - setState(186); - param(); - } - break; - case 2: - _localctx = new ListParameterContext(_localctx); - enterOuterAlt(_localctx, 2); - { - setState(187); - param(); - setState(188); - match(T__4); - setState(189); - paramList(); - } - break; - case 3: - _localctx = new NothingParameterContext(_localctx); - enterOuterAlt(_localctx, 3); - { - setState(191); - match(NOTHING); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class GlobalsBlockContext extends ParserRuleContext { - public TerminalNode GLOBALS() { return getToken(JassParser.GLOBALS, 0); } - public List newlines() { - return getRuleContexts(NewlinesContext.class); - } - public NewlinesContext newlines(int i) { - return getRuleContext(NewlinesContext.class,i); - } - public TerminalNode ENDGLOBALS() { return getToken(JassParser.ENDGLOBALS, 0); } - public List global() { - return getRuleContexts(GlobalContext.class); - } - public GlobalContext global(int i) { - return getRuleContext(GlobalContext.class,i); - } - public GlobalsBlockContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_globalsBlock; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitGlobalsBlock(this); - else return visitor.visitChildren(this); - } - } - - public final GlobalsBlockContext globalsBlock() throws RecognitionException { - GlobalsBlockContext _localctx = new GlobalsBlockContext(_ctx, getState()); - enterRule(_localctx, 24, RULE_globalsBlock); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(194); - match(GLOBALS); - setState(195); - newlines(); - setState(199); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << NOTHING) | (1L << CONSTANT) | (1L << ID))) != 0)) { - { - { - setState(196); - global(); - } - } - setState(201); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(202); - match(ENDGLOBALS); - setState(203); - newlines(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class TypeDefinitionBlockContext extends ParserRuleContext { - public List typeDefinition() { - return getRuleContexts(TypeDefinitionContext.class); - } - public TypeDefinitionContext typeDefinition(int i) { - return getRuleContext(TypeDefinitionContext.class,i); - } - public TypeDefinitionBlockContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_typeDefinitionBlock; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitTypeDefinitionBlock(this); - else return visitor.visitChildren(this); - } - } - - public final TypeDefinitionBlockContext typeDefinitionBlock() throws RecognitionException { - TypeDefinitionBlockContext _localctx = new TypeDefinitionBlockContext(_ctx, getState()); - enterRule(_localctx, 26, RULE_typeDefinitionBlock); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(208); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==TYPE) { - { - { - setState(205); - typeDefinition(); - } - } - setState(210); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class NativeBlockContext extends ParserRuleContext { - public TerminalNode NATIVE() { return getToken(JassParser.NATIVE, 0); } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public TerminalNode TAKES() { return getToken(JassParser.TAKES, 0); } - public ParamListContext paramList() { - return getRuleContext(ParamListContext.class,0); - } - public TerminalNode RETURNS() { return getToken(JassParser.RETURNS, 0); } - public TypeContext type() { - return getRuleContext(TypeContext.class,0); - } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public TerminalNode CONSTANT() { return getToken(JassParser.CONSTANT, 0); } - public NativeBlockContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_nativeBlock; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNativeBlock(this); - else return visitor.visitChildren(this); - } - } - - public final NativeBlockContext nativeBlock() throws RecognitionException { - NativeBlockContext _localctx = new NativeBlockContext(_ctx, getState()); - enterRule(_localctx, 28, RULE_nativeBlock); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(212); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==CONSTANT) { - { - setState(211); - match(CONSTANT); - } - } - - setState(214); - match(NATIVE); - setState(215); - match(ID); - setState(216); - match(TAKES); - setState(217); - paramList(); - setState(218); - match(RETURNS); - setState(219); - type(); - setState(220); - newlines(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class BlockContext extends ParserRuleContext { - public GlobalsBlockContext globalsBlock() { - return getRuleContext(GlobalsBlockContext.class,0); - } - public NativeBlockContext nativeBlock() { - return getRuleContext(NativeBlockContext.class,0); - } - public BlockContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_block; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitBlock(this); - else return visitor.visitChildren(this); - } - } - - public final BlockContext block() throws RecognitionException { - BlockContext _localctx = new BlockContext(_ctx, getState()); - enterRule(_localctx, 30, RULE_block); - try { - setState(224); - _errHandler.sync(this); - switch (_input.LA(1)) { - case GLOBALS: - enterOuterAlt(_localctx, 1); - { - setState(222); - globalsBlock(); - } - break; - case NATIVE: - case CONSTANT: - enterOuterAlt(_localctx, 2); - { - setState(223); - nativeBlock(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class FunctionBlockContext extends ParserRuleContext { - public TerminalNode FUNCTION() { return getToken(JassParser.FUNCTION, 0); } - public TerminalNode ID() { return getToken(JassParser.ID, 0); } - public TerminalNode TAKES() { return getToken(JassParser.TAKES, 0); } - public ParamListContext paramList() { - return getRuleContext(ParamListContext.class,0); - } - public TerminalNode RETURNS() { return getToken(JassParser.RETURNS, 0); } - public TypeContext type() { - return getRuleContext(TypeContext.class,0); - } - public List newlines() { - return getRuleContexts(NewlinesContext.class); - } - public NewlinesContext newlines(int i) { - return getRuleContext(NewlinesContext.class,i); - } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public TerminalNode ENDFUNCTION() { return getToken(JassParser.ENDFUNCTION, 0); } - public FunctionBlockContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_functionBlock; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitFunctionBlock(this); - else return visitor.visitChildren(this); - } - } - - public final FunctionBlockContext functionBlock() throws RecognitionException { - FunctionBlockContext _localctx = new FunctionBlockContext(_ctx, getState()); - enterRule(_localctx, 32, RULE_functionBlock); - try { - enterOuterAlt(_localctx, 1); - { - setState(226); - match(FUNCTION); - setState(227); - match(ID); - setState(228); - match(TAKES); - setState(229); - paramList(); - setState(230); - match(RETURNS); - setState(231); - type(); - setState(232); - newlines(); - setState(233); - statements(); - setState(234); - match(ENDFUNCTION); - setState(235); - newlines(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class StatementsContext extends ParserRuleContext { - public List statement() { - return getRuleContexts(StatementContext.class); - } - public StatementContext statement(int i) { - return getRuleContext(StatementContext.class,i); - } - public StatementsContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_statements; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitStatements(this); - else return visitor.visitChildren(this); - } - } - - public final StatementsContext statements() throws RecognitionException { - StatementsContext _localctx = new StatementsContext(_ctx, getState()); - enterRule(_localctx, 34, RULE_statements); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(240); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << CALL) | (1L << SET) | (1L << RETURN) | (1L << IF))) != 0)) { - { - { - setState(237); - statement(); - } - } - setState(242); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class NewlinesContext extends ParserRuleContext { - public PnewlinesContext pnewlines() { - return getRuleContext(PnewlinesContext.class,0); - } - public TerminalNode EOF() { return getToken(JassParser.EOF, 0); } - public NewlinesContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_newlines; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNewlines(this); - else return visitor.visitChildren(this); - } - } - - public final NewlinesContext newlines() throws RecognitionException { - NewlinesContext _localctx = new NewlinesContext(_ctx, getState()); - enterRule(_localctx, 36, RULE_newlines); - try { - setState(245); - _errHandler.sync(this); - switch (_input.LA(1)) { - case NEWLINE: - enterOuterAlt(_localctx, 1); - { - setState(243); - pnewlines(); - } - break; - case EOF: - enterOuterAlt(_localctx, 2); - { - setState(244); - match(EOF); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class Newlines_optContext extends ParserRuleContext { - public PnewlinesContext pnewlines() { - return getRuleContext(PnewlinesContext.class,0); - } - public TerminalNode EOF() { return getToken(JassParser.EOF, 0); } - public Newlines_optContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_newlines_opt; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitNewlines_opt(this); - else return visitor.visitChildren(this); - } - } - - public final Newlines_optContext newlines_opt() throws RecognitionException { - Newlines_optContext _localctx = new Newlines_optContext(_ctx, getState()); - enterRule(_localctx, 38, RULE_newlines_opt); - try { - setState(250); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(247); - pnewlines(); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(248); - match(EOF); - } - break; - case 3: - enterOuterAlt(_localctx, 3); - { - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class PnewlinesContext extends ParserRuleContext { - public TerminalNode NEWLINE() { return getToken(JassParser.NEWLINE, 0); } - public NewlinesContext newlines() { - return getRuleContext(NewlinesContext.class,0); - } - public PnewlinesContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_pnewlines; } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof JassVisitor ) return ((JassVisitor)visitor).visitPnewlines(this); - else return visitor.visitChildren(this); - } - } - - public final PnewlinesContext pnewlines() throws RecognitionException { - PnewlinesContext _localctx = new PnewlinesContext(_ctx, getState()); - enterRule(_localctx, 40, RULE_pnewlines); - try { - setState(255); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(252); - match(NEWLINE); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(253); - match(NEWLINE); - setState(254); - newlines(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3%\u0104\4\2\t\2\4"+ - "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ - "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ - "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\3\2\3\2\3\2\3\2\7\2\61\n\2\f"+ - "\2\16\2\64\13\2\3\2\7\2\67\n\2\f\2\16\2:\13\2\5\2<\n\2\3\3\3\3\3\3\3\3"+ - "\3\3\3\3\3\4\3\4\3\4\3\4\5\4H\n\4\3\5\5\5K\n\5\3\5\3\5\3\5\3\5\3\5\5\5"+ - "R\n\5\3\5\3\5\3\5\3\5\3\5\5\5Y\n\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7"+ - "\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7r\n\7\3\b"+ - "\3\b\3\b\3\b\3\b\3\b\3\b\3\b\5\b|\n\b\3\t\3\t\3\t\3\t\3\t\5\t\u0083\n"+ - "\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\5\n\u009e\n\n\3\13\3\13\3\13\3\13\3\13"+ - "\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+ - "\3\13\3\13\3\13\3\13\3\13\5\13\u00b8\n\13\3\f\3\f\3\f\3\r\3\r\3\r\3\r"+ - "\3\r\3\r\5\r\u00c3\n\r\3\16\3\16\3\16\7\16\u00c8\n\16\f\16\16\16\u00cb"+ - "\13\16\3\16\3\16\3\16\3\17\7\17\u00d1\n\17\f\17\16\17\u00d4\13\17\3\20"+ - "\5\20\u00d7\n\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\5\21"+ - "\u00e3\n\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23"+ - "\7\23\u00f1\n\23\f\23\16\23\u00f4\13\23\3\24\3\24\5\24\u00f8\n\24\3\25"+ - "\3\25\3\25\5\25\u00fd\n\25\3\26\3\26\3\26\5\26\u0102\n\26\3\26\2\2\27"+ - "\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*\2\2\2\u0113\2;\3\2\2\2"+ - "\4=\3\2\2\2\6G\3\2\2\2\bX\3\2\2\2\nZ\3\2\2\2\fq\3\2\2\2\16{\3\2\2\2\20"+ - "\u0082\3\2\2\2\22\u009d\3\2\2\2\24\u00b7\3\2\2\2\26\u00b9\3\2\2\2\30\u00c2"+ - "\3\2\2\2\32\u00c4\3\2\2\2\34\u00d2\3\2\2\2\36\u00d6\3\2\2\2 \u00e2\3\2"+ - "\2\2\"\u00e4\3\2\2\2$\u00f2\3\2\2\2&\u00f7\3\2\2\2(\u00fc\3\2\2\2*\u0101"+ - "\3\2\2\2,<\5&\24\2-.\5(\25\2.\62\5\34\17\2/\61\5 \21\2\60/\3\2\2\2\61"+ - "\64\3\2\2\2\62\60\3\2\2\2\62\63\3\2\2\2\638\3\2\2\2\64\62\3\2\2\2\65\67"+ - "\5\"\22\2\66\65\3\2\2\2\67:\3\2\2\28\66\3\2\2\289\3\2\2\29<\3\2\2\2:8"+ - "\3\2\2\2;,\3\2\2\2;-\3\2\2\2<\3\3\2\2\2=>\7\25\2\2>?\7#\2\2?@\7\26\2\2"+ - "@A\7#\2\2AB\5&\24\2B\5\3\2\2\2CH\7#\2\2DE\7#\2\2EH\7\24\2\2FH\7\20\2\2"+ - "GC\3\2\2\2GD\3\2\2\2GF\3\2\2\2H\7\3\2\2\2IK\7\34\2\2JI\3\2\2\2JK\3\2\2"+ - "\2KL\3\2\2\2LM\5\6\4\2MN\7#\2\2NO\5&\24\2OY\3\2\2\2PR\7\34\2\2QP\3\2\2"+ - "\2QR\3\2\2\2RS\3\2\2\2ST\5\6\4\2TU\7#\2\2UV\5\n\6\2VW\5&\24\2WY\3\2\2"+ - "\2XJ\3\2\2\2XQ\3\2\2\2Y\t\3\2\2\2Z[\7\b\2\2[\\\5\f\7\2\\\13\3\2\2\2]r"+ - "\7#\2\2^r\7\35\2\2_r\7\36\2\2`a\7\f\2\2ar\7#\2\2br\7\37\2\2cr\7 \2\2d"+ - "r\7!\2\2ef\7#\2\2fg\7\3\2\2gh\5\f\7\2hi\7\4\2\2ir\3\2\2\2jr\5\16\b\2k"+ - "l\7\5\2\2lm\5\f\7\2mn\7\6\2\2nr\3\2\2\2op\7\"\2\2pr\5\f\7\2q]\3\2\2\2"+ - "q^\3\2\2\2q_\3\2\2\2q`\3\2\2\2qb\3\2\2\2qc\3\2\2\2qd\3\2\2\2qe\3\2\2\2"+ - "qj\3\2\2\2qk\3\2\2\2qo\3\2\2\2r\r\3\2\2\2st\7#\2\2tu\7\5\2\2uv\5\20\t"+ - "\2vw\7\6\2\2w|\3\2\2\2xy\7#\2\2yz\7\5\2\2z|\7\6\2\2{s\3\2\2\2{x\3\2\2"+ - "\2|\17\3\2\2\2}\u0083\5\f\7\2~\177\5\f\7\2\177\u0080\7\7\2\2\u0080\u0081"+ - "\5\20\t\2\u0081\u0083\3\2\2\2\u0082}\3\2\2\2\u0082~\3\2\2\2\u0083\21\3"+ - "\2\2\2\u0084\u0085\7\21\2\2\u0085\u0086\5\16\b\2\u0086\u0087\5&\24\2\u0087"+ - "\u009e\3\2\2\2\u0088\u0089\7\22\2\2\u0089\u008a\7#\2\2\u008a\u008b\7\b"+ - "\2\2\u008b\u008c\5\f\7\2\u008c\u008d\5&\24\2\u008d\u009e\3\2\2\2\u008e"+ - "\u008f\7\22\2\2\u008f\u0090\7#\2\2\u0090\u0091\7\3\2\2\u0091\u0092\5\f"+ - "\7\2\u0092\u0093\7\4\2\2\u0093\u0094\7\b\2\2\u0094\u0095\5\f\7\2\u0095"+ - "\u0096\5&\24\2\u0096\u009e\3\2\2\2\u0097\u0098\7\23\2\2\u0098\u0099\5"+ - "\f\7\2\u0099\u009a\5&\24\2\u009a\u009e\3\2\2\2\u009b\u009c\7\27\2\2\u009c"+ - "\u009e\5\24\13\2\u009d\u0084\3\2\2\2\u009d\u0088\3\2\2\2\u009d\u008e\3"+ - "\2\2\2\u009d\u0097\3\2\2\2\u009d\u009b\3\2\2\2\u009e\23\3\2\2\2\u009f"+ - "\u00a0\5\f\7\2\u00a0\u00a1\7\30\2\2\u00a1\u00a2\5&\24\2\u00a2\u00a3\5"+ - "$\23\2\u00a3\u00a4\7\32\2\2\u00a4\u00a5\5&\24\2\u00a5\u00b8\3\2\2\2\u00a6"+ - "\u00a7\5\f\7\2\u00a7\u00a8\7\30\2\2\u00a8\u00a9\5&\24\2\u00a9\u00aa\5"+ - "$\23\2\u00aa\u00ab\7\31\2\2\u00ab\u00ac\5&\24\2\u00ac\u00ad\5$\23\2\u00ad"+ - "\u00ae\7\32\2\2\u00ae\u00af\5&\24\2\u00af\u00b8\3\2\2\2\u00b0\u00b1\5"+ - "\f\7\2\u00b1\u00b2\7\30\2\2\u00b2\u00b3\5&\24\2\u00b3\u00b4\5$\23\2\u00b4"+ - "\u00b5\7\33\2\2\u00b5\u00b6\5\24\13\2\u00b6\u00b8\3\2\2\2\u00b7\u009f"+ - "\3\2\2\2\u00b7\u00a6\3\2\2\2\u00b7\u00b0\3\2\2\2\u00b8\25\3\2\2\2\u00b9"+ - "\u00ba\5\6\4\2\u00ba\u00bb\7#\2\2\u00bb\27\3\2\2\2\u00bc\u00c3\5\26\f"+ - "\2\u00bd\u00be\5\26\f\2\u00be\u00bf\7\7\2\2\u00bf\u00c0\5\30\r\2\u00c0"+ - "\u00c3\3\2\2\2\u00c1\u00c3\7\20\2\2\u00c2\u00bc\3\2\2\2\u00c2\u00bd\3"+ - "\2\2\2\u00c2\u00c1\3\2\2\2\u00c3\31\3\2\2\2\u00c4\u00c5\7\t\2\2\u00c5"+ - "\u00c9\5&\24\2\u00c6\u00c8\5\b\5\2\u00c7\u00c6\3\2\2\2\u00c8\u00cb\3\2"+ - "\2\2\u00c9\u00c7\3\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00cc\3\2\2\2\u00cb"+ - "\u00c9\3\2\2\2\u00cc\u00cd\7\n\2\2\u00cd\u00ce\5&\24\2\u00ce\33\3\2\2"+ - "\2\u00cf\u00d1\5\4\3\2\u00d0\u00cf\3\2\2\2\u00d1\u00d4\3\2\2\2\u00d2\u00d0"+ - "\3\2\2\2\u00d2\u00d3\3\2\2\2\u00d3\35\3\2\2\2\u00d4\u00d2\3\2\2\2\u00d5"+ - "\u00d7\7\34\2\2\u00d6\u00d5\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u00d8\3"+ - "\2\2\2\u00d8\u00d9\7\13\2\2\u00d9\u00da\7#\2\2\u00da\u00db\7\r\2\2\u00db"+ - "\u00dc\5\30\r\2\u00dc\u00dd\7\16\2\2\u00dd\u00de\5\6\4\2\u00de\u00df\5"+ - "&\24\2\u00df\37\3\2\2\2\u00e0\u00e3\5\32\16\2\u00e1\u00e3\5\36\20\2\u00e2"+ - "\u00e0\3\2\2\2\u00e2\u00e1\3\2\2\2\u00e3!\3\2\2\2\u00e4\u00e5\7\f\2\2"+ - "\u00e5\u00e6\7#\2\2\u00e6\u00e7\7\r\2\2\u00e7\u00e8\5\30\r\2\u00e8\u00e9"+ - "\7\16\2\2\u00e9\u00ea\5\6\4\2\u00ea\u00eb\5&\24\2\u00eb\u00ec\5$\23\2"+ - "\u00ec\u00ed\7\17\2\2\u00ed\u00ee\5&\24\2\u00ee#\3\2\2\2\u00ef\u00f1\5"+ - "\22\n\2\u00f0\u00ef\3\2\2\2\u00f1\u00f4\3\2\2\2\u00f2\u00f0\3\2\2\2\u00f2"+ - "\u00f3\3\2\2\2\u00f3%\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f5\u00f8\5*\26\2"+ - "\u00f6\u00f8\7\2\2\3\u00f7\u00f5\3\2\2\2\u00f7\u00f6\3\2\2\2\u00f8\'\3"+ - "\2\2\2\u00f9\u00fd\5*\26\2\u00fa\u00fd\7\2\2\3\u00fb\u00fd\3\2\2\2\u00fc"+ - "\u00f9\3\2\2\2\u00fc\u00fa\3\2\2\2\u00fc\u00fb\3\2\2\2\u00fd)\3\2\2\2"+ - "\u00fe\u0102\7%\2\2\u00ff\u0100\7%\2\2\u0100\u0102\5&\24\2\u0101\u00fe"+ - "\3\2\2\2\u0101\u00ff\3\2\2\2\u0102+\3\2\2\2\27\628;GJQXq{\u0082\u009d"+ - "\u00b7\u00c2\u00c9\u00d2\u00d6\u00e2\u00f2\u00f7\u00fc\u0101"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassVisitor.java b/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassVisitor.java deleted file mode 100644 index ce63888..0000000 --- a/jassparser/build/generated-src/com/etheller/warsmash/jassparser/JassVisitor.java +++ /dev/null @@ -1,302 +0,0 @@ -// Generated from Jass.g4 by ANTLR 4.7 - - package com.etheller.interpreter; - -import org.antlr.v4.runtime.tree.ParseTreeVisitor; - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by {@link JassParser}. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -public interface JassVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by {@link JassParser#program}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitProgram(JassParser.ProgramContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#typeDefinition}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTypeDefinition(JassParser.TypeDefinitionContext ctx); - /** - * Visit a parse tree produced by the {@code BasicType} - * labeled alternative in {@link JassParser#type}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitBasicType(JassParser.BasicTypeContext ctx); - /** - * Visit a parse tree produced by the {@code ArrayType} - * labeled alternative in {@link JassParser#type}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitArrayType(JassParser.ArrayTypeContext ctx); - /** - * Visit a parse tree produced by the {@code NothingType} - * labeled alternative in {@link JassParser#type}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNothingType(JassParser.NothingTypeContext ctx); - /** - * Visit a parse tree produced by the {@code BasicGlobal} - * labeled alternative in {@link JassParser#global}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitBasicGlobal(JassParser.BasicGlobalContext ctx); - /** - * Visit a parse tree produced by the {@code DefinitionGlobal} - * labeled alternative in {@link JassParser#global}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitDefinitionGlobal(JassParser.DefinitionGlobalContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#assignTail}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitAssignTail(JassParser.AssignTailContext ctx); - /** - * Visit a parse tree produced by the {@code ReferenceExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitReferenceExpression(JassParser.ReferenceExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code StringLiteralExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitStringLiteralExpression(JassParser.StringLiteralExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code IntegerLiteralExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitIntegerLiteralExpression(JassParser.IntegerLiteralExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code FunctionReferenceExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFunctionReferenceExpression(JassParser.FunctionReferenceExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code NullExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNullExpression(JassParser.NullExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code TrueExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTrueExpression(JassParser.TrueExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code FalseExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFalseExpression(JassParser.FalseExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code ArrayReferenceExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitArrayReferenceExpression(JassParser.ArrayReferenceExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code FunctionCallExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFunctionCallExpression(JassParser.FunctionCallExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code ParentheticalExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitParentheticalExpression(JassParser.ParentheticalExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code NotExpression} - * labeled alternative in {@link JassParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNotExpression(JassParser.NotExpressionContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#functionExpression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFunctionExpression(JassParser.FunctionExpressionContext ctx); - /** - * Visit a parse tree produced by the {@code SingleArgument} - * labeled alternative in {@link JassParser#argsList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSingleArgument(JassParser.SingleArgumentContext ctx); - /** - * Visit a parse tree produced by the {@code ListArgument} - * labeled alternative in {@link JassParser#argsList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitListArgument(JassParser.ListArgumentContext ctx); - /** - * Visit a parse tree produced by the {@code CallStatement} - * labeled alternative in {@link JassParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitCallStatement(JassParser.CallStatementContext ctx); - /** - * Visit a parse tree produced by the {@code SetStatement} - * labeled alternative in {@link JassParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSetStatement(JassParser.SetStatementContext ctx); - /** - * Visit a parse tree produced by the {@code ArrayedAssignmentStatement} - * labeled alternative in {@link JassParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitArrayedAssignmentStatement(JassParser.ArrayedAssignmentStatementContext ctx); - /** - * Visit a parse tree produced by the {@code ReturnStatement} - * labeled alternative in {@link JassParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitReturnStatement(JassParser.ReturnStatementContext ctx); - /** - * Visit a parse tree produced by the {@code IfStatement} - * labeled alternative in {@link JassParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitIfStatement(JassParser.IfStatementContext ctx); - /** - * Visit a parse tree produced by the {@code SimpleIfStatement} - * labeled alternative in {@link JassParser#ifStatementPartial}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSimpleIfStatement(JassParser.SimpleIfStatementContext ctx); - /** - * Visit a parse tree produced by the {@code IfElseStatement} - * labeled alternative in {@link JassParser#ifStatementPartial}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitIfElseStatement(JassParser.IfElseStatementContext ctx); - /** - * Visit a parse tree produced by the {@code IfElseIfStatement} - * labeled alternative in {@link JassParser#ifStatementPartial}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitIfElseIfStatement(JassParser.IfElseIfStatementContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#param}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitParam(JassParser.ParamContext ctx); - /** - * Visit a parse tree produced by the {@code SingleParameter} - * labeled alternative in {@link JassParser#paramList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSingleParameter(JassParser.SingleParameterContext ctx); - /** - * Visit a parse tree produced by the {@code ListParameter} - * labeled alternative in {@link JassParser#paramList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitListParameter(JassParser.ListParameterContext ctx); - /** - * Visit a parse tree produced by the {@code NothingParameter} - * labeled alternative in {@link JassParser#paramList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNothingParameter(JassParser.NothingParameterContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#globalsBlock}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitGlobalsBlock(JassParser.GlobalsBlockContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#typeDefinitionBlock}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTypeDefinitionBlock(JassParser.TypeDefinitionBlockContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#nativeBlock}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNativeBlock(JassParser.NativeBlockContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#block}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitBlock(JassParser.BlockContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#functionBlock}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFunctionBlock(JassParser.FunctionBlockContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#statements}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitStatements(JassParser.StatementsContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#newlines}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNewlines(JassParser.NewlinesContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#newlines_opt}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNewlines_opt(JassParser.Newlines_optContext ctx); - /** - * Visit a parse tree produced by {@link JassParser#pnewlines}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitPnewlines(JassParser.PnewlinesContext ctx); -} \ No newline at end of file diff --git a/resources/Scripts/common.jui b/resources/Scripts/common.jui index 37012a3..34f4ec7 100644 --- a/resources/Scripts/common.jui +++ b/resources/Scripts/common.jui @@ -80,10 +80,28 @@ native LoadTOCFile takes string TOCFile returns fra // that. native CreateSimpleFrame takes string name, framehandle owner, integer createContext returns framehandle +// Spawn a FRAME element that was defined in an FDF +// template onto the screen. The "name" field must +// match the name of a template to spawn, loaded with LoadTOCFile. +// As noted on CreateSimpleFrame, for now createContext is pointless. +// Likewise for priority -- until it fixed. +native CreateFrame takes string name, framehandle owner, integer priority, integer createContext returns framehandle + + // Set the absolute point (often called Anchor) for the frame handle. // See FDF template files for examples +native FrameSetAnchor takes framehandle frame, framepointtype point, real x, real y returns nothing + +// Tasyen said: "takes one point of a Frame unbound that point and places it to a specific coordinates on the screen." native FrameSetAbsPoint takes framehandle frame, framepointtype point, real x, real y returns nothing +// Set the relative point (called SetPoint in FDF templates) for the frame handle. +// See FDF template files for examples +// Tasyen said: places a point of FrameA relative to a point of FrameB. When FrameB moves FrameA's point will keep this rule and moves with it. +// Note for Project Warsmash: "When FrameB moves..." might not be true... call FramePositionBounds() for now +native FrameSetPoint takes framehandle frame, framepointtype point, framehandle relative, framepointtype relativePoint, real x, real y returns nothing + + // Created for Warsmash engine, not a part of 1.31 UI apis, // and at some point it might be removed. Basically // this function will apply Anchors and SetPoints assigned @@ -98,6 +116,19 @@ native FramePositionBounds takes framehandle frame returns // when the "Human" skin was loaded with CreateRootFrame native SkinGetField takes string field returns string +// Sets the text value on a String Frame, currently it crashes otherwise +native FrameSetText takes framehandle frame, string text returns nothing + +// Sets the text color on a String Frame, currently it crashes otherwise +native FrameSetTextColor takes framehandle frame, integer color returns nothing + +native ConvertColor takes integer a, integer r, integer g, integer b returns integer + + +// Gets a previously created Frame using its name ( from an FDF template file that was +// previously spawned ). See previous notes about createContext. Mostly pointless? +native GetFrameByName takes string name, integer createContext returns framehandle + //============================================================================ // Native trigger interface // diff --git a/resources/Scripts/melee.jui b/resources/Scripts/melee.jui index 2186536..9d3c9a4 100644 --- a/resources/Scripts/melee.jui +++ b/resources/Scripts/melee.jui @@ -6,6 +6,15 @@ globals framehandle ROOT_FRAME framehandle CONSOLE_UI framehandle RESOURCE_BAR + framehandle RESOURCE_BAR_GOLD_TEXT + framehandle RESOURCE_BAR_LUMBER_TEXT + framehandle RESOURCE_BAR_SUPPLY_TEXT + framehandle RESOURCE_BAR_UPKEEP_TEXT + framehandle TIME_INDICATOR + framehandle SIMPLE_INFO_PANEL_UNIT_DETAIL + framehandle UNIT_PORTRAIT + framehandle UNIT_LIFE_TEXT + framehandle UNIT_MANA_TEXT endglobals @@ -17,6 +26,9 @@ function main takes nothing returns nothing if not LoadTOCFile("UI\\FrameDef\\FrameDef.toc") then call LogError("Unable to load FrameDef.toc") endif + if not LoadTOCFile("UI\\FrameDef\\SmashFrameDef.toc") then + call LogError("Unable to load SmashFrameDef.toc") + endif // ================================= // Load major UI components // ================================= @@ -26,7 +38,33 @@ function main takes nothing returns nothing // Its template does not specify where to put it, so we must // put it in the "TOPRIGHT" corner. set RESOURCE_BAR = CreateSimpleFrame("ResourceBarFrame", CONSOLE_UI, 0) - call FrameSetAbsPoint(RESOURCE_BAR, FRAMEPOINT_TOPRIGHT, 0, 0) + call FrameSetPoint(RESOURCE_BAR, FRAMEPOINT_TOPRIGHT, CONSOLE_UI, FRAMEPOINT_TOPRIGHT, 0, 0) + + // Create the Time Indicator (clock) + set TIME_INDICATOR = CreateFrame("TimeOfDayIndicator", ROOT_FRAME, 0, 0) + + // Create the unit portrait stuff (for now this doesn't actually create the 3D, only HP/mana) + set UNIT_PORTRAIT = CreateSimpleFrame("UnitPortrait", CONSOLE_UI, 0) + set UNIT_LIFE_TEXT = GetFrameByName("UnitPortraitHitPointText", 0) + set UNIT_MANA_TEXT = GetFrameByName("UnitPortraitManaPointText", 0) + + // Set default values + call FrameSetText(UNIT_LIFE_TEXT, "706 / 725") + call FrameSetText(UNIT_MANA_TEXT, "405 / 405") + + + // Retrieve inflated sub-frames and store references + set RESOURCE_BAR_GOLD_TEXT = GetFrameByName("ResourceBarGoldText", 0) + set RESOURCE_BAR_LUMBER_TEXT = GetFrameByName("ResourceBarLumberText", 0) + set RESOURCE_BAR_SUPPLY_TEXT = GetFrameByName("ResourceBarSupplyText", 0) + set RESOURCE_BAR_UPKEEP_TEXT = GetFrameByName("ResourceBarUpkeepText", 0) + + // Set default values + call FrameSetText(RESOURCE_BAR_GOLD_TEXT, "500") + call FrameSetText(RESOURCE_BAR_LUMBER_TEXT, "150") + call FrameSetText(RESOURCE_BAR_SUPPLY_TEXT, "5/10") + call FrameSetText(RESOURCE_BAR_UPKEEP_TEXT, "No Upkeep") + call FrameSetTextColor(RESOURCE_BAR_UPKEEP_TEXT, ConvertColor(255, 0, 255, 0)) // Assemble the UI and resolve the location of every component that // has Anchors and SetPoints (maybe in future version this call diff --git a/resources/UI/FrameDef/SmashFrameDef.toc b/resources/UI/FrameDef/SmashFrameDef.toc new file mode 100644 index 0000000..a67d6b6 --- /dev/null +++ b/resources/UI/FrameDef/SmashFrameDef.toc @@ -0,0 +1,2 @@ +UI\FrameDef\SmashUI\TimeOfDayIndicator.fdf +UI\FrameDef\SmashUI\UnitPortrait.fdf diff --git a/resources/UI/FrameDef/SmashUI/SmashConsoleUI.fdf b/resources/UI/FrameDef/SmashUI/SmashConsoleUI.fdf new file mode 100644 index 0000000..9ba9949 --- /dev/null +++ b/resources/UI/FrameDef/SmashUI/SmashConsoleUI.fdf @@ -0,0 +1,81 @@ +// I had to override this because the Blizzard version is missing the "ConsoleTexture01Top" names. +Frame "SIMPLEFRAME" "ConsoleUI" { + DecorateFileNames, + + // The top of the UI console + Texture "ConsoleTexture01Top" { + File "ConsoleTexture01", + Width 0.256, + Height 0.032, + TexCoord 0, 1, 0, 0.125, + AlphaMode "ALPHAKEY", + Anchor TOPLEFT,0,0, + } + Texture "ConsoleTexture02Top" { + File "ConsoleTexture02", + Width 0.087, + Height 0.032, + TexCoord 0, 0.33984375, 0, 0.125, + AlphaMode "ALPHAKEY", + Anchor TOPLEFT,0.256, 0, + } + Texture "ConsoleTexture02Top" { + File "ConsoleTexture02", + Width 0.053, + Height 0.032, + TexCoord 0.79296875, 1, 0, 0.125, + AlphaMode "ALPHAKEY", + Anchor TOPRIGHT,-0.288, 0, + } + Texture "ConsoleTexture03Top" { + File "ConsoleTexture03", + Width 0.256, + Height 0.032, + TexCoord 0, 1, 0, 0.125, + AlphaMode "ALPHAKEY", + Anchor TOPRIGHT,-0.032, 0, + } + Texture "ConsoleTexture04Top" { + File "ConsoleTexture04", + Width 0.032, + Height 0.032, + TexCoord 0, 1, 0, 0.125, + AlphaMode "ALPHAKEY", + Anchor TOPRIGHT,0,0, + } + + // The bottom of the UI console + Texture "ConsoleTexture01Bottom" { + File "ConsoleTexture01", + Width 0.256, + Height 0.176, + TexCoord 0, 1, 0.3125, 1, + AlphaMode "ALPHAKEY", + Anchor BOTTOMLEFT,0,0, + } + Texture "ConsoleTexture02Bottom" { + File "ConsoleTexture02", + Width 0.256, + Height 0.15, + TexCoord 0, 1, 0.4140625, 1, + AlphaMode "ALPHAKEY", + Anchor BOTTOMLEFT,0.256,0, + } + Texture "ConsoleTexture03Bottom" { + File "ConsoleTexture03", + Width 0.256, + Height 0.176, + TexCoord 0, 1, 0.3125, 1, + AlphaMode "ALPHAKEY", + Anchor BOTTOMRIGHT,-0.032,0.0, + } + Texture "ConsoleTexture04Bottom" { + File "ConsoleTexture04", + Width 0.032, + Height 0.176, + TexCoord 0, 1, 0.3125, 1, + AlphaMode "ALPHAKEY", + Anchor BOTTOMRIGHT,0,0, + } + +} diff --git a/resources/UI/FrameDef/SmashUI/TimeOfDayIndicator.fdf b/resources/UI/FrameDef/SmashUI/TimeOfDayIndicator.fdf new file mode 100644 index 0000000..9480e6e --- /dev/null +++ b/resources/UI/FrameDef/SmashUI/TimeOfDayIndicator.fdf @@ -0,0 +1,6 @@ + +Frame "SPRITE" "TimeOfDayIndicator" { + DecorateFileNames, + BackgroundArt "TimeOfDayIndicator", + SetPoint BOTTOMLEFT,"ConsoleUI",BOTTOMLEFT,0,0, +} \ No newline at end of file diff --git a/resources/UI/FrameDef/SmashUI/UnitPortrait.fdf b/resources/UI/FrameDef/SmashUI/UnitPortrait.fdf new file mode 100644 index 0000000..ce7f91b --- /dev/null +++ b/resources/UI/FrameDef/SmashUI/UnitPortrait.fdf @@ -0,0 +1,44 @@ +/* + * UnitPortrait.fdf + * --------------------- + * Right now the actual 3d portrait is hardcoded like the + * original game, eventually that should be a config file + * like this so that a map can override it. + */ + +String "UnitPortraitTextTemplate" { + Font "MasterFont",0.011, + Height 0.01640625, + TextLength 20, +} + +Frame "SIMPLEFRAME" "UnitPortrait" { + DecorateFileNames, + SetPoint BOTTOMLEFT,"ConsoleUI",BOTTOMLEFT,0.211,0, + Width 0.0835, + Height 0.114, + + Frame "SIMPLEFRAME" "UnitPortraitModel" { + DecorateFileNames, + SetPoint BOTTOM,"UnitPortrait",BOTTOM,0,0.0285, + Width 0.0835, + Height 0.085, + + //Texture { + //File "IdlePeon", + // AlphaMode "ALPHAKEY", + //} + } + + String "UnitPortraitHitPointText" INHERITS "UnitPortraitTextTemplate" { + Anchor BOTTOM, 0, 0.0115, + FontJustificationH JUSTIFYCENTER, + FontColor 0.0 1.0 0.0 1.0, + } + + String "UnitPortraitManaPointText" INHERITS "UnitPortraitTextTemplate" { + Anchor BOTTOM, 0, -0.0030, + FontJustificationH JUSTIFYCENTER, + FontColor 1.0 1.0 1.0 1.0, + } +} \ No newline at end of file diff --git a/resources/UI/FrameDef/UI/SimpleInfoPanel.fdf b/resources/UI/FrameDef/UI/SimpleInfoPanel.fdf new file mode 100644 index 0000000..de6fa8d --- /dev/null +++ b/resources/UI/FrameDef/UI/SimpleInfoPanel.fdf @@ -0,0 +1,447 @@ + +// --- TEXT ----------------------------------------------------------------------- + + +String "SimpleInfoPanelTitleTextTemplate" { + FontColor 1.0 1.0 1.0 1.0, + FontShadowColor 0.0 0.0 0.0 0.9, + FontShadowOffset 0.002 -0.002, + Font "InfoPanelTextFont",0.013, +} +String "SimpleInfoPanelTitleTextDisabledTemplate" INHERITS "SimpleInfoPanelTitleTextTemplate" { + FontColor 0.2 0.2 0.2 1.0, +} + +String "SimpleInfoPanelDescriptionTextTemplate" { + FontColor 0.99 0.827 0.0705 1.0, + FontShadowColor 0.0 0.0 0.0 0.9, + FontShadowOffset 0.001 -0.001, + Font "InfoPanelTextFont",0.01, +} +String "SimpleInfoPanelDescriptionHighlightTextTemplate" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + FontColor 1.0 1.0 1.0 1.0, +} +String "SimpleInfoPanelDescriptionDisabledTextTemplate" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + FontColor 0.2 0.2 0.2 1.0, +} + +String "SimpleInfoPanelLabelTextTemplate" { + FontJustificationH JUSTIFYLEFT, + FontJustificationV JUSTIFYTOP, + FontColor 0.99 0.827 0.0705 1.0, + FontShadowColor 0.0 0.0 0.0 0.9, + FontShadowOffset 0.001 -0.001, + Font "InfoPanelTextFont",0.0085, +} +String "SimpleInfoPanelLabelHighlightTextTemplate" INHERITS "SimpleInfoPanelLabelTextTemplate" { + FontColor 1.0 1.0 1.0 1.0, +} +String "SimpleInfoPanelLabelDisabledTextTemplate" INHERITS "SimpleInfoPanelLabelTextTemplate" { + FontColor 0.2 0.2 0.2 1.0, +} + +String "SimpleInfoPanelValueTextTemplate" INHERITS "SimpleInfoPanelLabelTextTemplate" { + FontColor 1.0 1.0 1.0 1.0, +} + +String "SimpleInfoPanelAttributeTextTemplate" { + FontColor 1.0 1.0 1.0 1.0, + FontShadowColor 0.0 0.0 0.0 0.9, + FontShadowOffset 0.001 -0.001, + Font "InfoPanelTextFont",0.009, +} +String "SimpleInfoPanelAttributeDisabledTextTemplate" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + FontColor 0.2 0.2 0.2 1.0, +} + +Texture "InfoPanelIconTemplate" { + Width 0.032, + Height 0.032, + Anchor TOPLEFT, 0.004, -0.001, +} + +Texture "ResourceIconTemplate" { + Width 0.014, + Height 0.014, +} + +String "ResourceTextTemplate" INHERITS "SimpleInfoPanelValueTextTemplate" { + Font "InfoPanelTextFont", 0.0085, +} + +// -- FRAMES ---------------------------------------------------------------- + +Frame "SIMPLEFRAME" "SimpleInfoPanelUnitDetail" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + // --- unit name frame -------------------------------------------------- + String "SimpleNameValue" INHERITS "SimpleInfoPanelTitleTextTemplate" { + Anchor TOP,0,0, + } + + // --- hero level bar --------------------------------------------------- + Frame "SIMPLESTATUSBAR" "SimpleHeroLevelBar" { + UseActiveContext, + SetPoint TOP, "SimpleNameValue", BOTTOM, 0.0, -0.0015, + Height 0.015625, + } + + // --- timed life bar ---------------------------------------------------- + Frame "SIMPLESTATUSBAR" "SimpleProgressIndicator" { + UseActiveContext, + SetPoint TOP, "SimpleNameValue", BOTTOM, 0.0, -0.0015, + Height 0.015625, + } + + // --- building build queue panel ------------------------------------------------- + Frame "SIMPLESTATUSBAR" "SimpleBuildTimeIndicator" { + UseActiveContext, + SetPoint TOPLEFT, "SimpleInfoPanelUnitDetail", TOPLEFT, 0.061250, -0.038125, + } + + String "SimpleBuildingActionLabel" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + SetPoint CENTER, "SimpleInfoPanelUnitDetail", TOPLEFT, 0.11375, -0.029875, + Text "Retarded text", + } + + // --- unit stats panel ------------------------------------------------- + // This is required to make sure the class text appears above the status bars. + Frame "SIMPLEFRAME" "SimpleUnitStatsPanel" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + // --- class ------------------------------------------------------------ + String "SimpleClassValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOP, "SimpleNameValue", BOTTOM, 0.0, -0.0055, + FontJustificationH JUSTIFYCENTER, + } + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelCargoDetail" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + // --- unit name frame -------------------------------------------------- + String "SimpleHoldNameValue" INHERITS "SimpleInfoPanelTitleTextTemplate" { + Anchor TOP,0,0, + } + + String "SimpleHoldDescriptionValue" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + SetPoint TOP, "SimpleHoldNameValue", BOTTOM, 0.0, -0.007, + Width 0.188, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelBuildingDetail" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + String "SimpleBuildingNameValue" INHERITS "SimpleInfoPanelTitleTextTemplate" { + Anchor TOP,0,0, + } + + String "SimpleBuildingDescriptionValue" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + SetPoint TOP, "SimpleBuildingNameValue", BOTTOM, 0.0, -0.007, + Width 0.188, + } + + // --- building build queue panel ------------------------------------------------- + Frame "SIMPLESTATUSBAR" "SimpleBuildTimeIndicator" { + UseActiveContext, + SetPoint TOPLEFT, "SimpleInfoPanelBuildingDetail", TOPLEFT, 0.061250, -0.038125, + } + + String "SimpleBuildingActionLabel" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + SetPoint CENTER, "SimpleInfoPanelBuildingDetail", TOPLEFT, 0.11375, -0.029875, + Text "Retarded text", + } + + Layer "ARTWORK" { + Texture "SimpleBuildQueueBackdrop" { + SetPoint BOTTOMLEFT, "SimpleInfoPanelBuildingDetail", BOTTOMLEFT, 0.0, 0.0, + SetPoint BOTTOMRIGHT, "SimpleInfoPanelBuildingDetail", BOTTOMRIGHT, 0.0, 0.0, + Height 0.1, + File "BuildQueueBackdrop", + } + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelItemDetail" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + // --- item name frame -------------------------------------------------- + String "SimpleItemNameValue" INHERITS "SimpleInfoPanelTitleTextTemplate" { + Anchor TOP,0,0, + } + + // --- item description frame ------------------------------------------- + String "SimpleItemDescriptionValue" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + Width 0.188, + SetPoint TOP, "SimpleItemNameValue", BOTTOM, 0.0, -0.008, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelDestructableDetail" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + + // --- destructable name frame -------------------------------------------------- + String "SimpleDestructableNameValue" INHERITS "SimpleInfoPanelTitleTextTemplate" { + Anchor TOP,0,0, + } + + // --- destructable description frame ------------------------------------------- + //String "SimpleDestructableDescriptionValue" INHERITS "SimpleInfoPanelDescriptionTextTemplate" { + // Width 0.188, + // SetPoint TOP, "SimpleDestructableNameValue", BOTTOM, 0.0, -0.008, + //} +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconDamage" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.03125, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconBackdrop" INHERITS "InfoPanelIconTemplate" { + File "HeroStrengthIcon", + } + + // --- icon # ----------------------------------------------------------- + String "InfoPanelIconLevel" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + SetPoint CENTER, "InfoPanelIconBackdrop", BOTTOMRIGHT, -0.007625, 0.006875, + } + + // --- label ------------------------------------------------------------ + String "InfoPanelIconLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconBackdrop", TOPRIGHT, 0.0, -0.003, + Text "COLON_DAMAGE", + } + + // --- value ------------------------------------------------------------ + String "InfoPanelIconValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconLabel", BOTTOMLEFT, 0.005, -0.003, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconArmor" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.03125, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconBackdrop" INHERITS "InfoPanelIconTemplate" { + File "HeroStrengthIcon", + } + + // --- icon # ----------------------------------------------------------- + String "InfoPanelIconLevel" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + SetPoint CENTER, "InfoPanelIconBackdrop", BOTTOMRIGHT, -0.007625, 0.006875, + } + + // --- label ------------------------------------------------------------ + String "InfoPanelIconLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconBackdrop", TOPRIGHT, 0.0, -0.003, + Text "COLON_ARMOR", + } + + // --- value ------------------------------------------------------------ + String "InfoPanelIconValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconLabel", BOTTOMLEFT, 0.005, -0.003, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconRank" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.03125, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconBackdrop" INHERITS "InfoPanelIconTemplate" { + File "HeroStrengthIcon", + } + + // --- icon # ----------------------------------------------------------- + String "InfoPanelIconLevel" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + SetPoint CENTER, "InfoPanelIconBackdrop", BOTTOMRIGHT, -0.007625, 0.006875, + } + + // --- label ------------------------------------------------------------ + String "InfoPanelIconLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconBackdrop", TOPRIGHT, 0.0, -0.003, + Text "COLON_RANK", + } + + // --- value ------------------------------------------------------------ + String "InfoPanelIconValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconLabel", BOTTOMLEFT, 0.005, -0.003, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconFood" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.03125, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconBackdrop" INHERITS "InfoPanelIconTemplate" { + File "InfoPanelIconFood", + } + + // --- icon # ----------------------------------------------------------- + String "InfoPanelIconLevel" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + SetPoint CENTER, "InfoPanelIconBackdrop", BOTTOMRIGHT, -0.007625, 0.006875, + } + + // --- label ------------------------------------------------------------ + String "InfoPanelIconLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconBackdrop", TOPRIGHT, 0.0, -0.003, + Text "COLON_FOOD", + } + + // --- value ------------------------------------------------------------ + String "InfoPanelIconValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconLabel", BOTTOMLEFT, 0.005, -0.003, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconGold" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.03125, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconBackdrop" INHERITS "InfoPanelIconTemplate" { + File "InfoPanelIconGold", + } + + // --- icon # ----------------------------------------------------------- + String "InfoPanelIconLevel" INHERITS "SimpleInfoPanelAttributeTextTemplate" { + SetPoint CENTER, "InfoPanelIconBackdrop", BOTTOMRIGHT, -0.007625, 0.006875, + } + + // --- label ------------------------------------------------------------ + String "InfoPanelIconLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconBackdrop", TOPRIGHT, 0.0, -0.003, + Text "COLON_GOLD", + } + + // --- value ------------------------------------------------------------ + String "InfoPanelIconValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconLabel", BOTTOMLEFT, 0.005, -0.003, + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconHero" { + UseActiveContext, + SetAllPoints, + DecorateFileNames, + Height 0.0625, + + // --- icon ------------------------------------------------------------- + Texture "InfoPanelIconHeroIcon" INHERITS "InfoPanelIconTemplate" { + File "HeroStrengthIcon", + Anchor LEFT, 0.004, 0.0, + } + + Frame "SIMPLEFRAME" "SimpleInfoPanelIconHeroText" { + UseActiveContext, + DecorateFileNames, + SetPoint LEFT, "InfoPanelIconHeroIcon", RIGHT, 0.0, 0.0, + SetPoint RIGHT, "SimpleInfoPanelIconHero", RIGHT, 0.0, 0.0, + SetPoint TOP, "SimpleInfoPanelIconHero", TOP, 0.0, 0.0, + SetPoint BOTTOM, "SimpleInfoPanelIconHero", BOTTOM, 0.0, 0.0, + + // --- strength --------------------------------------------------------- + String "InfoPanelIconHeroStrengthLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + Anchor TOPLEFT, 0.0, -0.003, + Text "COLON_STRENGTH", + } + + String "InfoPanelIconHeroStrengthValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconHeroStrengthLabel", BOTTOMLEFT, 0.005, 0.0, + } + + // --- agility ---------------------------------------------------------- + String "InfoPanelIconHeroAgilityLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconHeroStrengthValue", BOTTOMLEFT, -0.005, -0.004, + Text "COLON_AGILITY", + } + + String "InfoPanelIconHeroAgilityValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconHeroAgilityLabel", BOTTOMLEFT, 0.005, 0.0, + } + + // --- intellect -------------------------------------------------------- + String "InfoPanelIconHeroIntellectLabel" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconHeroAgilityValue", BOTTOMLEFT, -0.005, -0.004, + Text "COLON_INTELLECT", + } + + String "InfoPanelIconHeroIntellectValue" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconHeroIntellectLabel", BOTTOMLEFT, 0.005, 0.0, + } + } +} + +Frame "SIMPLEFRAME" "SimpleInfoPanelIconAlly" { + UseActiveContext, + DecorateFileNames, + Height 0.0625, + + // --- title ------------------------------------------------------------ + String "InfoPanelIconAllyTitle" INHERITS "SimpleInfoPanelLabelTextTemplate" { + SetPoint TOPLEFT, "SimpleInfoPanelIconAlly", TOPLEFT, 0.0, 0.0, + Text "ALLY_RESOURCES", + } + + // --- gold ------------------------------------------------------------- + Texture "InfoPanelIconAllyGoldIcon" INHERITS "ResourceIconTemplate" { + SetPoint TOPLEFT, "SimpleInfoPanelIconAlly", TOPLEFT, 0.0, -0.009, + File "GoldIcon", + } + + String "InfoPanelIconAllyGoldValue" INHERITS "ResourceTextTemplate" { + SetPoint LEFT, "InfoPanelIconAllyGoldIcon", RIGHT, 0.005, 0.0, + } + + // --- wood ------------------------------------------------------------- + Texture "InfoPanelIconAllyWoodIcon" INHERITS "ResourceIconTemplate" { + SetPoint TOPLEFT, "InfoPanelIconAllyGoldIcon", BOTTOMLEFT, 0.0, 0.0, + File "LumberIcon", + } + + String "InfoPanelIconAllyWoodValue" INHERITS "ResourceTextTemplate" { + SetPoint LEFT, "InfoPanelIconAllyWoodIcon", RIGHT, 0.005, 0.0, + } + + // --- food ------------------------------------------------------------- + Texture "InfoPanelIconAllyFoodIcon" INHERITS "ResourceIconTemplate" { + SetPoint TOPLEFT, "InfoPanelIconAllyWoodIcon", BOTTOMLEFT, 0.0, 0.0, + File "SupplyIcon", + } + + String "InfoPanelIconAllyFoodValue" INHERITS "ResourceTextTemplate" { + SetPoint LEFT, "InfoPanelIconAllyFoodIcon", RIGHT, 0.005, 0.0, + } + + // --- upkeep ----------------------------------------------------------- + String "InfoPanelIconAllyUpkeep" INHERITS "SimpleInfoPanelValueTextTemplate" { + SetPoint TOPLEFT, "InfoPanelIconAllyFoodValue", BOTTOMLEFT, 0.0, -0.005, + Text "Upkeep", + } +} \ No newline at end of file