mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Fun with some menu button support and hero stats and levels
This commit is contained in:
parent
27ee234574
commit
22e07de19a
@ -1,26 +1,53 @@
|
||||
[DataSources]
|
||||
Count=5
|
||||
Type00=Folder
|
||||
Path00="D:\Games\Warcraft III CASC 1.31\war3.w3mod"
|
||||
Type01=Folder
|
||||
Path01="D:\Games\Warcraft III CASC 1.31\war3.w3mod\_locales\enus.w3mod"
|
||||
Type02=Folder
|
||||
Path02="..\..\resources"
|
||||
Type03=Folder
|
||||
Path03="D:\Backups\Warsmash\Data"
|
||||
Count=8
|
||||
Type00=MPQ
|
||||
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
|
||||
Type01=MPQ
|
||||
Path01="D:\Games\Warcraft III Patch 1.22\War3x.mpq"
|
||||
Type02=MPQ
|
||||
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
|
||||
Type03=MPQ
|
||||
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
|
||||
Type04=Folder
|
||||
Path04="."
|
||||
Path04="..\..\resources"
|
||||
Type05=Folder
|
||||
Path05="D:\Backups\Warsmash\Data"
|
||||
Type06=Folder
|
||||
Path06="D:\Games\Warcraft III Patch 1.22\Maps"
|
||||
Type07=Folder
|
||||
Path07="."
|
||||
|
||||
[Map]
|
||||
//FilePath="CombatUnitTests.w3x"
|
||||
//FilePath="PitchRoll.w3x"
|
||||
//FilePath="ReforgedGeorgeVacation.w3x"
|
||||
//FilePath="PeonStartingBase_Simple.w3x"
|
||||
FilePath="PeonStartingBase_Scythe.w3x"
|
||||
//FilePath="MyStromguarde.w3m"
|
||||
//FilePath="ColdArrows.w3m"
|
||||
//FilePath="DungeonGoldMine.w3m"
|
||||
//FilePath="PlayerPeasants.w3m"
|
||||
//FilePath="FireLord.w3x"
|
||||
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||
//FilePath="PrivateDontShare/Cult 8.w3x"
|
||||
//FilePath="PhoenixAttack.w3x"
|
||||
//FilePath="LightEnvironmentTest.w3x"
|
||||
//FilePath="TorchLight2.w3x"
|
||||
//FilePath="OrcAssault.w3x"
|
||||
//FilePath="PeonStartingBase.w3x"
|
||||
//FilePath="PhoenixAttack.w3x"
|
||||
//FilePath="OperationReforged.w3x"
|
||||
//FilePath="AzerothRoleplay1.909t03DecoratedV2.w3x"
|
||||
//FilePath="American Colo EX 1.0 unpro.w3x"
|
||||
FilePath="TheSheepAttack.w3x"
|
||||
//FilePath="FrostyVsFarm.w3m"
|
||||
//FilePath="ModelTest.w3x"
|
||||
//FilePath="SpinningSample.w3x"
|
||||
//FilePath="Maps\Campaign\Prologue02.w3m"
|
||||
//FilePath="Pathing.w3x"
|
||||
//FilePath="ItemFacing.w3x"
|
||||
//FilePath=SomeParticleTests.w3x
|
||||
//FilePath="PeonMiningMultiHall.w3x"
|
||||
//FilePath="QuadtreeBugs.w3x"
|
||||
//FilePath="test2.w3x"
|
||||
//FilePath="FarseerHoldPositionTest.w3x"
|
||||
//FilePath="Ramps.w3m"
|
||||
//FilePath="V1\Farm.w3x"
|
||||
//FilePath="PenguinWorld.w3x"
|
||||
//FilePath="Maps\FrozenThrone\Campaign\UndeadX09.w3x"
|
||||
//FilePath="LavellaLagoon.w3x"
|
||||
//FilePath="WiceOrc.w3x"
|
||||
//FilePath="NorthrendPathingDoodle.w3x"
|
||||
//FilePath="Maps\Campaign\Prologue01.w3m"
|
||||
|
@ -1,51 +0,0 @@
|
||||
[DataSources]
|
||||
Count=8
|
||||
Type00=MPQ
|
||||
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
|
||||
Type01=MPQ
|
||||
Path01="D:\Games\Warcraft III Patch 1.22\War3x.mpq"
|
||||
Type02=MPQ
|
||||
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
|
||||
Type03=MPQ
|
||||
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
|
||||
Type04=Folder
|
||||
Path04="..\..\resources"
|
||||
Type05=Folder
|
||||
Path05="D:\Backups\Warsmash\Data"
|
||||
Type06=Folder
|
||||
Path06="D:\Games\Warcraft III Patch 1.22\Maps"
|
||||
Type07=Folder
|
||||
Path07="."
|
||||
|
||||
[Map]
|
||||
//FilePath="CombatUnitTests.w3x"
|
||||
//FilePath="PitchRoll.w3x"
|
||||
//FilePath="PeonStartingBase_Simple.w3x"
|
||||
//FilePath="MyStromguarde.w3m"
|
||||
//FilePath="ColdArrows.w3m"
|
||||
//FilePath="DungeonGoldMine.w3m"
|
||||
//FilePath="PlayerPeasants.w3m"
|
||||
//FilePath="FireLord.w3x"
|
||||
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||
//FilePath="PhoenixAttack.w3x"
|
||||
//FilePath="LightEnvironmentTest.w3x"
|
||||
//FilePath="TorchLight2.w3x"
|
||||
//FilePath="OrcAssault.w3x"
|
||||
//FilePath="FrostyVsFarm.w3m"
|
||||
//FilePath="ModelTest.w3x"
|
||||
//FilePath="SpinningSample.w3x"
|
||||
//FilePath="Maps\Campaign\Prologue02.w3m"
|
||||
//FilePath="Pathing.w3x"
|
||||
//FilePath="ItemFacing.w3x"
|
||||
//FilePath=SomeParticleTests.w3x
|
||||
//FilePath="PeonMiningMultiHall.w3x"
|
||||
//FilePath="QuadtreeBugs.w3x"
|
||||
//FilePath="test2.w3x"
|
||||
//FilePath="FarseerHoldPositionTest.w3x"
|
||||
//FilePath="Ramps.w3m"
|
||||
//FilePath="V1\Farm.w3x"
|
||||
//FilePath="PenguinWorld.w3x"
|
||||
//FilePath="Maps\FrozenThrone\Campaign\UndeadX09.w3x"
|
||||
//FilePath="LavellaLagoon.w3x"
|
||||
//FilePath="WiceOrc.w3x"
|
||||
FilePath="TheSheepAttack.w3x"
|
26
core/assets/warsmash131.ini
Normal file
26
core/assets/warsmash131.ini
Normal file
@ -0,0 +1,26 @@
|
||||
[DataSources]
|
||||
Count=5
|
||||
Type00=Folder
|
||||
Path00="D:\Games\Warcraft III CASC 1.31\war3.w3mod"
|
||||
Type01=Folder
|
||||
Path01="D:\Games\Warcraft III CASC 1.31\war3.w3mod\_locales\enus.w3mod"
|
||||
Type02=Folder
|
||||
Path02="..\..\resources"
|
||||
Type03=Folder
|
||||
Path03="D:\Backups\Warsmash\Data"
|
||||
Type04=Folder
|
||||
Path04="."
|
||||
|
||||
[Map]
|
||||
//FilePath="PitchRoll.w3x"
|
||||
//FilePath="ReforgedGeorgeVacation.w3x"
|
||||
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||
//FilePath="PrivateDontShare/Cult 8.w3x"
|
||||
//FilePath="TorchLight2.w3x"
|
||||
//FilePath="OrcAssault.w3x"
|
||||
//FilePath="PeonStartingBase.w3x"
|
||||
//FilePath="PhoenixAttack.w3x"
|
||||
//FilePath="OperationReforged.w3x"
|
||||
//FilePath="AzerothRoleplay1.909t03DecoratedV2.w3x"
|
||||
//FilePath="American Colo EX 1.0 unpro.w3x"
|
||||
FilePath="TheSheepAttack.w3x"
|
@ -4,23 +4,23 @@
|
||||
[DataSources]
|
||||
Count=9
|
||||
Type00=MPQ
|
||||
Path00="E:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3.mpq"
|
||||
Path00="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3.mpq"
|
||||
Type01=MPQ
|
||||
Path01="E:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3x.mpq"
|
||||
Path01="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3x.mpq"
|
||||
Type02=MPQ
|
||||
Path02="E:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3xlocal.mpq"
|
||||
Path02="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3xlocal.mpq"
|
||||
Type03=MPQ
|
||||
Path03="E:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3patch.mpq"
|
||||
Path03="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3patch.mpq"
|
||||
Type04=MPQ
|
||||
Path04="E:\Games\Warcraft III Project Revolution\PRSCMOD\Revolution.mpq"
|
||||
Path04="D:\Games\Warcraft III Project Revolution\PRSCMOD\Revolution.mpq"
|
||||
Type05=MPQ
|
||||
Path05="E:\Games\Warcraft III Project Revolution\PRSCMOD\Sound.mpq"
|
||||
Path05="D:\Games\Warcraft III Project Revolution\PRSCMOD\Sound.mpq"
|
||||
Type06=Folder
|
||||
Path06="E:\Games\Warcraft III Project Revolution\ProjectRevolusmash"
|
||||
Path06="D:\Games\Warcraft III Project Revolution\ProjectRevolusmash"
|
||||
Type07=Folder
|
||||
Path07="..\..\resources"
|
||||
Type08=Folder
|
||||
Path08="E:\Games\Warcraft III Project Revolution\PRSCMOD\PR-Maps"
|
||||
Path08="D:\Games\Warcraft III Project Revolution\PRSCMOD\PR-Maps"
|
||||
|
||||
[Map]
|
||||
FilePath="ProjectRevolusmash.w3x"
|
@ -2,7 +2,7 @@
|
||||
Count=5
|
||||
Type00=CASC
|
||||
Path00="C:\Program Files\Warcraft III"
|
||||
Prefixes00=war3.w3mod,war3.w3mod\_deprecated.w3mod,war3.w3mod\_locales\enus.w3mod
|
||||
Prefixes00=war3.w3mod,war3.w3mod\_deprecated.w3mod,war3.w3mod\_locales\enus.w3mod,war3.w3mod\_hd.w3mod,war3.w3mod\_hd.w3mod\_locales\enus.w3mod
|
||||
Type01=Folder
|
||||
Path01="..\..\resources"
|
||||
Type02=Folder
|
||||
|
22
core/assets/warsmashTTOR.ini
Normal file
22
core/assets/warsmashTTOR.ini
Normal file
@ -0,0 +1,22 @@
|
||||
// This is the Warsmash INI file for Project Revolution
|
||||
// PRSCMOD
|
||||
|
||||
[DataSources]
|
||||
Count=7
|
||||
Type00=MPQ
|
||||
Path00="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3.mpq"
|
||||
Type01=MPQ
|
||||
Path01="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3x.mpq"
|
||||
Type02=MPQ
|
||||
Path02="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3xlocal.mpq"
|
||||
Type03=MPQ
|
||||
Path03="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3patch_TTOR.mpq"
|
||||
Type04=Folder
|
||||
Path04="D:\Games\Warcraft III Project Revolution\ProjectRevolusmash"
|
||||
Type05=Folder
|
||||
Path05="..\..\resources"
|
||||
Type06=Folder
|
||||
Path06="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\Maps"
|
||||
|
||||
[Map]
|
||||
FilePath="(2)BootyBay.w3m"
|
22
core/assets/warsmashUF.ini
Normal file
22
core/assets/warsmashUF.ini
Normal file
@ -0,0 +1,22 @@
|
||||
// This is the Warsmash INI file for Project Revolution
|
||||
// PRSCMOD
|
||||
|
||||
[DataSources]
|
||||
Count=7
|
||||
Type00=MPQ
|
||||
Path00="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\war3.mpq"
|
||||
Type01=MPQ
|
||||
Path01="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3x.mpq"
|
||||
Type02=MPQ
|
||||
Path02="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3xlocal.mpq"
|
||||
Type03=MPQ
|
||||
Path03="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\war3patch.mpq"
|
||||
Type04=MPQ
|
||||
Path04="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3Mod.mpq"
|
||||
Type05=Folder
|
||||
Path05="..\..\resources"
|
||||
Type06=Folder
|
||||
Path06="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\Maps"
|
||||
|
||||
[Map]
|
||||
FilePath="Maps\Campaign\Prologue01.w3m"
|
@ -1,7 +1,15 @@
|
||||
package com.etheller.warsmash;
|
||||
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
|
||||
public class TestMain {
|
||||
public static void main(final String[] args) {
|
||||
if (true) {
|
||||
System.out.println(War3ID.fromString("hwat").getValue());
|
||||
System.out.println(Integer.toHexString(War3ID.fromString("hwat").getValue()));
|
||||
System.out.println(new War3ID(0x68776174));
|
||||
return;
|
||||
}
|
||||
// System.out.println(Integer.parseInt("4294967295"));
|
||||
for (int i = 1; i <= 30; i++) {
|
||||
// System.out.println(a(i));
|
||||
|
@ -62,7 +62,7 @@ public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvide
|
||||
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||
System.err.println("Renderer: " + renderer);
|
||||
|
||||
this.codebase = WarsmashGdxMapGame.parseDataSources(this.warsmashIni);
|
||||
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||
this.viewer = new MdxViewer(this.codebase, this);
|
||||
|
||||
this.viewer.addHandler(new MdxHandler());
|
||||
|
@ -9,20 +9,16 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.InputProcessor;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.audio.Music;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.GL30;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
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.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
@ -56,7 +52,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnit
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.SettableCommandErrorListener;
|
||||
|
||||
public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProvider, InputProcessor {
|
||||
public class WarsmashGdxMapScreen implements CanvasProvider, InputProcessor, Screen {
|
||||
private static final boolean ENABLE_AUDIO = true;
|
||||
private static final boolean ENABLE_MUSIC = false;
|
||||
private DataSource codebase;
|
||||
@ -65,8 +61,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
|
||||
// libGDX stuff
|
||||
private OrthographicCamera uiCamera;
|
||||
private BitmapFont font;
|
||||
private BitmapFont font20;
|
||||
private SpriteBatch batch;
|
||||
private ExtendViewport uiViewport;
|
||||
private GlyphLayout glyphLayout;
|
||||
@ -80,10 +74,13 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
|
||||
private Scene uiScene;
|
||||
private MeleeUI meleeUI;
|
||||
private FreeTypeFontGenerator fontGenerator;
|
||||
|
||||
public WarsmashGdxMapGame(final DataTable warsmashIni) {
|
||||
private Music currentMusic;
|
||||
private final String fileToLoad;
|
||||
|
||||
public WarsmashGdxMapScreen(final DataTable warsmashIni, final String fileToLoad) {
|
||||
this.warsmashIni = warsmashIni;
|
||||
this.fileToLoad = fileToLoad;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -92,7 +89,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
* @see com.badlogic.gdx.ApplicationAdapter#create()
|
||||
*/
|
||||
@Override
|
||||
public void create() {
|
||||
public void show() {
|
||||
|
||||
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
@ -115,7 +112,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
this.viewer.enableAudio();
|
||||
}
|
||||
try {
|
||||
this.viewer.loadMap(this.warsmashIni.get("Map").getField("FilePath"), 0);
|
||||
this.viewer.loadMap(this.fileToLoad, 0);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -155,13 +152,6 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
final int width = Gdx.graphics.getWidth();
|
||||
final int height = Gdx.graphics.getHeight();
|
||||
|
||||
this.fontGenerator = new FreeTypeFontGenerator(
|
||||
new DataSourceFileHandle(this.viewer.dataSource, "fonts\\FRIZQT__.TTF"));
|
||||
final FreeTypeFontParameter fontParam = new FreeTypeFontParameter();
|
||||
fontParam.size = 32;
|
||||
this.font = this.fontGenerator.generateFont(fontParam);
|
||||
fontParam.size = 20;
|
||||
this.font20 = this.fontGenerator.generateFont(fontParam);
|
||||
this.glyphLayout = new GlyphLayout();
|
||||
|
||||
// Constructs a new OrthographicCamera, using the given viewport width and
|
||||
@ -207,24 +197,25 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
cameraRatesElement.getFieldFloatValue("FOV"), cameraRatesElement.getFieldFloatValue("Rotation"),
|
||||
cameraRatesElement.getFieldFloatValue("Distance"), cameraRatesElement.getFieldFloatValue("Forward"),
|
||||
cameraRatesElement.getFieldFloatValue("Strafe"));
|
||||
this.meleeUI = new MeleeUI(this.viewer.mapMpq, this.uiViewport, this.fontGenerator, this.uiScene, portraitScene,
|
||||
cameraPresets, cameraRates, this.viewer, new RootFrameListener() {
|
||||
this.meleeUI = new MeleeUI(this.viewer.mapMpq, this.uiViewport, this.uiScene, portraitScene, cameraPresets,
|
||||
cameraRates, this.viewer, new RootFrameListener() {
|
||||
@Override
|
||||
public void onCreate(final GameUI rootFrame) {
|
||||
WarsmashGdxMapGame.this.viewer.setGameUI(rootFrame);
|
||||
WarsmashGdxMapScreen.this.viewer.setGameUI(rootFrame);
|
||||
|
||||
if (ENABLE_MUSIC) {
|
||||
final String musicField = rootFrame.getSkinField("Music_V1");
|
||||
final String[] musics = musicField.split(";");
|
||||
String musicPath = musics[(int) (Math.random() * musics.length)];
|
||||
if (true) {
|
||||
if (false) {
|
||||
musicPath = "Sound\\Music\\mp3Music\\PH1.mp3";
|
||||
}
|
||||
final Music music = Gdx.audio.newMusic(
|
||||
new DataSourceFileHandle(WarsmashGdxMapGame.this.viewer.dataSource, musicPath));
|
||||
new DataSourceFileHandle(WarsmashGdxMapScreen.this.viewer.dataSource, musicPath));
|
||||
music.setVolume(0.2f);
|
||||
music.setLooping(true);
|
||||
music.play();
|
||||
WarsmashGdxMapScreen.this.currentMusic = music;
|
||||
}
|
||||
}
|
||||
}, new CPlayerUnitOrderExecutor(this.viewer.simulation, commandErrorListener));
|
||||
@ -292,7 +283,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
public void render(final float delta) {
|
||||
this.uiCamera.update();
|
||||
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||
final float deltaTime = Gdx.graphics.getDeltaTime();
|
||||
@ -322,12 +313,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
this.uiViewport.apply();
|
||||
this.batch.setProjectionMatrix(this.uiCamera.combined);
|
||||
this.batch.begin();
|
||||
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);
|
||||
this.font.draw(this.batch, fpsString, (this.uiViewport.getMinWorldWidth() - this.glyphLayout.width) / 2,
|
||||
1100 * this.meleeUI.getHeightRatioCorrection());
|
||||
this.meleeUI.render(this.batch, this.glyphLayout);
|
||||
this.batch.end();
|
||||
|
||||
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||
@ -336,7 +322,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
this.fontGenerator.dispose();
|
||||
this.meleeUI.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -351,7 +337,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
|
||||
@Override
|
||||
public void resize(final int width, final int height) {
|
||||
super.resize(width, height);
|
||||
// super.resize(width, height);
|
||||
|
||||
this.uiViewport.update(width, height);
|
||||
this.uiCamera.position.set(this.uiViewport.getMinWorldWidth() / 2, this.uiViewport.getMinWorldHeight() / 2, 0);
|
||||
@ -529,4 +515,19 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if (this.currentMusic != null) {
|
||||
this.currentMusic.stop();
|
||||
}
|
||||
}
|
||||
}
|
@ -5,20 +5,16 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.InputProcessor;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.audio.Music;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.GL30;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
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.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
@ -30,6 +26,7 @@ import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||
import com.etheller.warsmash.units.DataTable;
|
||||
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||
import com.etheller.warsmash.util.ImageUtils;
|
||||
import com.etheller.warsmash.util.WarsmashConstants;
|
||||
import com.etheller.warsmash.viewer5.Camera;
|
||||
import com.etheller.warsmash.viewer5.CanvasProvider;
|
||||
import com.etheller.warsmash.viewer5.Model;
|
||||
@ -50,7 +47,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI;
|
||||
|
||||
public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements CanvasProvider, InputProcessor {
|
||||
public class WarsmashGdxMenuScreen implements CanvasProvider, InputProcessor, Screen {
|
||||
private static final boolean ENABLE_AUDIO = true;
|
||||
private static final boolean ENABLE_MUSIC = true;
|
||||
private DataSource codebase;
|
||||
@ -61,8 +58,6 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
|
||||
// libGDX stuff
|
||||
private OrthographicCamera uiCamera;
|
||||
private BitmapFont font;
|
||||
private BitmapFont font20;
|
||||
private SpriteBatch batch;
|
||||
private ExtendViewport uiViewport;
|
||||
private GlyphLayout glyphLayout;
|
||||
@ -71,14 +66,16 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
private Scene uiScene;
|
||||
private Texture solidGreenTexture;
|
||||
private MenuUI menuUI;
|
||||
private final WarsmashGdxMultiScreenGame game;
|
||||
private Music currentMusic;
|
||||
|
||||
public WarsmashGdxMenuTestGame(final DataTable warsmashIni) {
|
||||
public WarsmashGdxMenuScreen(final DataTable warsmashIni, final WarsmashGdxMultiScreenGame game) {
|
||||
this.warsmashIni = warsmashIni;
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
|
||||
public void show() {
|
||||
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||
@ -91,7 +88,7 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||
System.err.println("Renderer: " + renderer);
|
||||
|
||||
this.codebase = WarsmashGdxMapGame.parseDataSources(this.warsmashIni);
|
||||
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||
this.viewer = new MdxViewer(this.codebase, this);
|
||||
|
||||
this.viewer.addHandler(new MdxHandler());
|
||||
@ -108,13 +105,6 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
final int width = Gdx.graphics.getWidth();
|
||||
final int height = Gdx.graphics.getHeight();
|
||||
|
||||
final FreeTypeFontGenerator fontGenerator = new FreeTypeFontGenerator(
|
||||
new DataSourceFileHandle(this.viewer.dataSource, "fonts\\FRIZQT__.TTF"));
|
||||
final FreeTypeFontParameter fontParam = new FreeTypeFontParameter();
|
||||
fontParam.size = 32;
|
||||
this.font = fontGenerator.generateFont(fontParam);
|
||||
fontParam.size = 20;
|
||||
this.font20 = fontGenerator.generateFont(fontParam);
|
||||
this.glyphLayout = new GlyphLayout();
|
||||
|
||||
// Constructs a new OrthographicCamera, using the given viewport width and
|
||||
@ -184,27 +174,30 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
System.out.println("Loaded");
|
||||
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1);
|
||||
|
||||
this.menuUI = new MenuUI(this.viewer.dataSource, this.uiViewport, fontGenerator, this.uiScene, this.viewer,
|
||||
new RootFrameListener() {
|
||||
this.menuUI = new MenuUI(this.viewer.dataSource, this.uiViewport, this.uiScene, this.viewer, this.game,
|
||||
this.warsmashIni, new RootFrameListener() {
|
||||
@Override
|
||||
public void onCreate(final GameUI rootFrame) {
|
||||
// WarsmashGdxMapGame.this.viewer.setGameUI(rootFrame);
|
||||
|
||||
if (ENABLE_MUSIC) {
|
||||
final String musicField = rootFrame.getSkinField("GlueMusic_V1");
|
||||
final String musicField = rootFrame
|
||||
.getSkinField("GlueMusic_V" + WarsmashConstants.GAME_VERSION);
|
||||
final String[] musics = musicField.split(";");
|
||||
final String musicPath = musics[(int) (Math.random() * musics.length)];
|
||||
final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(
|
||||
WarsmashGdxMenuTestGame.this.viewer.dataSource, musicPath));
|
||||
final Music music = Gdx.audio.newMusic(
|
||||
new DataSourceFileHandle(WarsmashGdxMenuScreen.this.viewer.dataSource, musicPath));
|
||||
music.setVolume(0.2f);
|
||||
music.setLooping(true);
|
||||
music.play();
|
||||
WarsmashGdxMenuScreen.this.currentMusic = music;
|
||||
}
|
||||
|
||||
singleModelScene(scene,
|
||||
War3MapViewer.mdx(rootFrame.getSkinField("GlueSpriteLayerBackground_V1")), "Stand");
|
||||
WarsmashGdxMenuTestGame.this.modelCamera = WarsmashGdxMenuTestGame.this.mainModel.cameras
|
||||
.get(0);
|
||||
War3MapViewer.mdx(rootFrame
|
||||
.getSkinField("GlueSpriteLayerBackground_V" + WarsmashConstants.GAME_VERSION)),
|
||||
"Stand");
|
||||
WarsmashGdxMenuScreen.this.modelCamera = WarsmashGdxMenuScreen.this.mainModel.cameras.get(0);
|
||||
}
|
||||
});
|
||||
|
||||
@ -213,7 +206,6 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
libgdxContentInstance.setLocation(0f, 0f, -0.5f);
|
||||
libgdxContentInstance.setScene(this.uiScene);
|
||||
this.menuUI.main();
|
||||
fontGenerator.dispose();
|
||||
|
||||
updateUIScene();
|
||||
|
||||
@ -487,7 +479,7 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
private final boolean firstFrame = true;
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
public void render(final float delta) {
|
||||
|
||||
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||
final float deltaTime = Gdx.graphics.getDeltaTime();
|
||||
@ -507,6 +499,7 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
this.menuUI.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -525,7 +518,7 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
this.tempRect.height = height;
|
||||
this.cameraManager.camera.viewport(this.tempRect);
|
||||
|
||||
super.resize(width, height);
|
||||
// super.resize(width, height);
|
||||
|
||||
this.uiViewport.update(width, height);
|
||||
this.uiCamera.position.set(this.uiViewport.getMinWorldWidth() / 2, this.uiViewport.getMinWorldHeight() / 2, 0);
|
||||
@ -595,20 +588,16 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
this.quatHeap.transform(this.position);
|
||||
this.position.scl(this.distance);
|
||||
this.position = this.position.add(this.target);
|
||||
if (WarsmashGdxMenuTestGame.this.modelCamera != null) {
|
||||
WarsmashGdxMenuTestGame.this.modelCamera.getPositionTranslation(
|
||||
WarsmashGdxMenuTestGame.this.cameraPositionTemp,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.sequence,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.frame,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.counter);
|
||||
WarsmashGdxMenuTestGame.this.modelCamera.getTargetTranslation(
|
||||
WarsmashGdxMenuTestGame.this.cameraTargetTemp,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.sequence,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.frame,
|
||||
WarsmashGdxMenuTestGame.this.mainInstance.counter);
|
||||
if (WarsmashGdxMenuScreen.this.modelCamera != null) {
|
||||
WarsmashGdxMenuScreen.this.modelCamera.getPositionTranslation(
|
||||
WarsmashGdxMenuScreen.this.cameraPositionTemp, WarsmashGdxMenuScreen.this.mainInstance.sequence,
|
||||
WarsmashGdxMenuScreen.this.mainInstance.frame, WarsmashGdxMenuScreen.this.mainInstance.counter);
|
||||
WarsmashGdxMenuScreen.this.modelCamera.getTargetTranslation(WarsmashGdxMenuScreen.this.cameraTargetTemp,
|
||||
WarsmashGdxMenuScreen.this.mainInstance.sequence, WarsmashGdxMenuScreen.this.mainInstance.frame,
|
||||
WarsmashGdxMenuScreen.this.mainInstance.counter);
|
||||
|
||||
this.position.set(WarsmashGdxMenuTestGame.this.modelCamera.position);
|
||||
this.target.set(WarsmashGdxMenuTestGame.this.modelCamera.targetPosition);
|
||||
this.position.set(WarsmashGdxMenuScreen.this.modelCamera.position);
|
||||
this.target.set(WarsmashGdxMenuScreen.this.modelCamera.targetPosition);
|
||||
// this.vecHeap2.set(this.target);
|
||||
// this.vecHeap2.sub(this.position);
|
||||
// this.vecHeap.set(this.vecHeap2);
|
||||
@ -618,16 +607,15 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
// this.vecHeap.scl(this.camera.rect.height / 2f);
|
||||
// this.position.add(this.vecHeap);
|
||||
|
||||
this.position.add(WarsmashGdxMenuTestGame.this.cameraPositionTemp[0],
|
||||
WarsmashGdxMenuTestGame.this.cameraPositionTemp[1],
|
||||
WarsmashGdxMenuTestGame.this.cameraPositionTemp[2]);
|
||||
this.target.add(WarsmashGdxMenuTestGame.this.cameraTargetTemp[0],
|
||||
WarsmashGdxMenuTestGame.this.cameraTargetTemp[1],
|
||||
WarsmashGdxMenuTestGame.this.cameraTargetTemp[2]);
|
||||
this.camera.perspective(WarsmashGdxMenuTestGame.this.modelCamera.fieldOfView * 0.75f,
|
||||
this.position.add(WarsmashGdxMenuScreen.this.cameraPositionTemp[0],
|
||||
WarsmashGdxMenuScreen.this.cameraPositionTemp[1],
|
||||
WarsmashGdxMenuScreen.this.cameraPositionTemp[2]);
|
||||
this.target.add(WarsmashGdxMenuScreen.this.cameraTargetTemp[0],
|
||||
WarsmashGdxMenuScreen.this.cameraTargetTemp[1], WarsmashGdxMenuScreen.this.cameraTargetTemp[2]);
|
||||
this.camera.perspective(WarsmashGdxMenuScreen.this.modelCamera.fieldOfView * 0.75f,
|
||||
Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight(),
|
||||
WarsmashGdxMenuTestGame.this.modelCamera.nearClippingPlane,
|
||||
WarsmashGdxMenuTestGame.this.modelCamera.farClippingPlane);
|
||||
WarsmashGdxMenuScreen.this.modelCamera.nearClippingPlane,
|
||||
WarsmashGdxMenuScreen.this.modelCamera.farClippingPlane);
|
||||
}
|
||||
else {
|
||||
this.camera.perspective(70, this.camera.getAspect(), 100, 5000);
|
||||
@ -665,25 +653,39 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
|
||||
@Override
|
||||
public boolean touchDown(final int screenX, final int screenY, final int pointer, final int button) {
|
||||
// TODO Auto-generated method stub
|
||||
final float worldScreenY = getHeight() - screenY;
|
||||
|
||||
if (this.menuUI.touchDown(screenX, screenY, worldScreenY, button)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchUp(final int screenX, final int screenY, final int pointer, final int button) {
|
||||
// TODO Auto-generated method stub
|
||||
final float worldScreenY = getHeight() - screenY;
|
||||
|
||||
if (this.menuUI.touchUp(screenX, screenY, worldScreenY, button)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
|
||||
// TODO Auto-generated method stub
|
||||
final float worldScreenY = getHeight() - screenY;
|
||||
if (this.menuUI.touchDragged(screenX, screenY, worldScreenY, pointer)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseMoved(final int screenX, final int screenY) {
|
||||
// TODO Auto-generated method stub
|
||||
final float worldScreenY = getHeight() - screenY;
|
||||
if (this.menuUI.mouseMoved(screenX, screenY, worldScreenY)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -706,14 +708,7 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
this.uiViewport.apply();
|
||||
this.batch.setProjectionMatrix(this.uiCamera.combined);
|
||||
this.batch.begin();
|
||||
this.menuUI.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);
|
||||
if (false) {
|
||||
this.font.draw(this.batch, fpsString, (this.uiViewport.getMinWorldWidth() - this.glyphLayout.width) / 2,
|
||||
1100 * this.menuUI.getHeightRatioCorrection());
|
||||
}
|
||||
this.menuUI.render(this.batch, this.glyphLayout);
|
||||
this.batch.end();
|
||||
|
||||
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||
@ -804,4 +799,20 @@ public class WarsmashGdxMenuTestGame extends ApplicationAdapter implements Canva
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if (this.currentMusic != null) {
|
||||
this.currentMusic.stop();
|
||||
}
|
||||
this.menuUI.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.etheller.warsmash;
|
||||
|
||||
import com.badlogic.gdx.Game;
|
||||
|
||||
public class WarsmashGdxMultiScreenGame extends Game {
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
}
|
||||
|
||||
}
|
@ -59,7 +59,7 @@ public class WarsmashPreviewApplication extends ApplicationAdapter implements Ca
|
||||
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||
System.err.println("Renderer: " + renderer);
|
||||
|
||||
this.codebase = WarsmashGdxMapGame.parseDataSources(this.warsmashIni);
|
||||
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||
this.viewer = new MdxViewer(this.codebase, this);
|
||||
|
||||
this.mdxHandler = new MdxHandler();
|
||||
|
@ -0,0 +1,44 @@
|
||||
package com.etheller.warsmash.parsers.fdf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.etheller.warsmash.datasources.DataSource;
|
||||
import com.etheller.warsmash.units.Element;
|
||||
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||
|
||||
public class DynamicFontGeneratorHolder {
|
||||
private final DataSource dataSource;
|
||||
private final Element skin;
|
||||
private final Map<String, FreeTypeFontGenerator> fontNameToGenerator;
|
||||
|
||||
public DynamicFontGeneratorHolder(final DataSource dataSource, final Element skin) {
|
||||
this.dataSource = dataSource;
|
||||
this.skin = skin;
|
||||
this.fontNameToGenerator = new HashMap<>();
|
||||
}
|
||||
|
||||
public FreeTypeFontGenerator getFontGenerator(final String font) {
|
||||
FreeTypeFontGenerator fontGenerator = this.fontNameToGenerator.get(font);
|
||||
if (fontGenerator == null) {
|
||||
final String fontName = this.skin.getField(font);
|
||||
if (fontName == null) {
|
||||
throw new IllegalStateException("No such font: " + font);
|
||||
}
|
||||
if (!this.dataSource.has(fontName)) {
|
||||
throw new IllegalStateException("No such font file: " + fontName + " (for \"" + font + "\")");
|
||||
}
|
||||
fontGenerator = new FreeTypeFontGenerator(new DataSourceFileHandle(this.dataSource, fontName));
|
||||
this.fontNameToGenerator.put(font, fontGenerator);
|
||||
}
|
||||
return fontGenerator;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
for (final FreeTypeFontGenerator generator : this.fontNameToGenerator.values()) {
|
||||
generator.dispose();
|
||||
}
|
||||
this.fontNameToGenerator.clear();
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ 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.BackdropCornerFlags;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.ControlStyle;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FontDefinition;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FrameClass;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FrameDefinition;
|
||||
@ -34,6 +35,8 @@ import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.BackdropFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.FilterModeTextureFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleStatusBarFrame;
|
||||
@ -52,6 +55,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
|
||||
|
||||
public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
private static final boolean PIN_FAIL_IS_FATAL = false;
|
||||
private final DataSource dataSource;
|
||||
private final Element skin;
|
||||
private final Viewport viewport;
|
||||
@ -69,10 +73,12 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
private final Element errorStrings;
|
||||
private final GlyphLayout glyphLayout;
|
||||
private final WTS mapStrings;
|
||||
private final BitmapFont font;
|
||||
private final BitmapFont font20;
|
||||
private final DynamicFontGeneratorHolder dynamicFontGeneratorHolder;
|
||||
|
||||
public GameUI(final DataSource dataSource, final Element skin, final Viewport viewport,
|
||||
final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final AbstractMdxModelViewer modelViewer,
|
||||
final int racialCommandIndex, final WTS mapStrings) {
|
||||
public GameUI(final DataSource dataSource, final Element skin, final Viewport viewport, final Scene uiScene,
|
||||
final AbstractMdxModelViewer modelViewer, final int racialCommandIndex, final WTS mapStrings) {
|
||||
super("GameUI", null);
|
||||
this.dataSource = dataSource;
|
||||
this.skin = skin;
|
||||
@ -88,7 +94,14 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
this.renderBounds.set(0, 0, viewport.getWorldWidth(), viewport.getWorldHeight());
|
||||
}
|
||||
this.templates = new FrameTemplateEnvironment();
|
||||
this.fontGenerator = fontGenerator;
|
||||
|
||||
this.dynamicFontGeneratorHolder = new DynamicFontGeneratorHolder(this.modelViewer.dataSource, skin);
|
||||
this.fontGenerator = this.dynamicFontGeneratorHolder.getFontGenerator("MasterFont");
|
||||
final FreeTypeFontParameter fontParam = new FreeTypeFontParameter();
|
||||
fontParam.size = 32;
|
||||
this.font = this.fontGenerator.generateFont(fontParam);
|
||||
fontParam.size = 20;
|
||||
this.font20 = this.fontGenerator.generateFont(fontParam);
|
||||
this.fontParam = new FreeTypeFontParameter();
|
||||
this.fdfCoordinateResolutionDummyViewport = new FitViewport(0.8f, 0.6f);
|
||||
this.skinData = new DataTable(modelViewer.getWorldEditStrings());
|
||||
@ -393,7 +406,8 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
if (this.fontParam.size == 0) {
|
||||
this.fontParam.size = 24;
|
||||
}
|
||||
frameFont = this.fontGenerator.generateFont(this.fontParam);
|
||||
frameFont = this.dynamicFontGeneratorHolder.getFontGenerator(font.getFontName())
|
||||
.generateFont(this.fontParam);
|
||||
String textString = frameDefinition.getName();
|
||||
String text = frameDefinition.getString("Text");
|
||||
if (text != null) {
|
||||
@ -415,41 +429,116 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
}
|
||||
else if ("GLUETEXTBUTTON".equals(frameDefinition.getFrameType())) {
|
||||
// ButtonText & ControlBackdrop
|
||||
final SimpleFrame simpleFrame = new SimpleFrame(frameDefinition.getName(), parent);
|
||||
final GlueTextButtonFrame glueButtonFrame = new GlueTextButtonFrame(frameDefinition.getName(), parent);
|
||||
// TODO: we should not need to put ourselves in this map 2x, but we do
|
||||
// since there are nested inflate calls happening before the general case
|
||||
// mapping
|
||||
this.nameToFrame.put(frameDefinition.getName(), simpleFrame);
|
||||
final String buttonTextKey = frameDefinition.getString("ButtonText");
|
||||
this.nameToFrame.put(frameDefinition.getName(), glueButtonFrame);
|
||||
final String controlBackdropKey = frameDefinition.getString("ControlBackdrop");
|
||||
final String controlPushedBackdropKey = frameDefinition.getString("ControlPushedBackdrop");
|
||||
final String controlDisabledBackdropKey = frameDefinition.getString("ControlDisabledBackdrop");
|
||||
final String controlMouseOverHighlightKey = frameDefinition.getString("ControlMouseOverHighlight");
|
||||
final String buttonTextKey = frameDefinition.getString("ButtonText");
|
||||
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
|
||||
if (childDefinition.getName().equals(buttonTextKey)
|
||||
|| childDefinition.getName().equals(controlBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, simpleFrame, frameDefinition,
|
||||
if (childDefinition.getName().equals(controlBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
simpleFrame.add(inflatedChild);
|
||||
glueButtonFrame.setControlBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlPushedBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlPushedBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlDisabledBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlDisabledBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlMouseOverHighlightKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlMouseOverHighlight(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(buttonTextKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setButtonText(inflatedChild);
|
||||
}
|
||||
}
|
||||
inflatedFrame = simpleFrame;
|
||||
final EnumSet<ControlStyle> controlStyle = ControlStyle
|
||||
.parseControlStyle(frameDefinition.getString("ControlStyle"));
|
||||
if (controlStyle.contains(ControlStyle.AUTOTRACK)
|
||||
&& controlStyle.contains(ControlStyle.HIGHLIGHTONMOUSEOVER)) {
|
||||
glueButtonFrame.setHighlightOnMouseOver(true);
|
||||
}
|
||||
inflatedFrame = glueButtonFrame;
|
||||
}
|
||||
else if ("GLUEBUTTON".equals(frameDefinition.getFrameType())) {
|
||||
// ButtonText & ControlBackdrop
|
||||
final SimpleFrame simpleFrame = new SimpleFrame(frameDefinition.getName(), parent);
|
||||
final GlueButtonFrame glueButtonFrame = new GlueButtonFrame(frameDefinition.getName(), parent);
|
||||
// TODO: we should not need to put ourselves in this map 2x, but we do
|
||||
// since there are nested inflate calls happening before the general case
|
||||
// mapping
|
||||
this.nameToFrame.put(frameDefinition.getName(), simpleFrame);
|
||||
this.nameToFrame.put(frameDefinition.getName(), glueButtonFrame);
|
||||
final String controlBackdropKey = frameDefinition.getString("ControlBackdrop");
|
||||
final String controlPushedBackdropKey = frameDefinition.getString("ControlPushedBackdrop");
|
||||
final String controlDisabledBackdropKey = frameDefinition.getString("ControlDisabledBackdrop");
|
||||
final String controlMouseOverHighlightKey = frameDefinition.getString("ControlMouseOverHighlight");
|
||||
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
|
||||
if (childDefinition.getName().equals(controlBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, simpleFrame, frameDefinition,
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
simpleFrame.add(inflatedChild);
|
||||
glueButtonFrame.setControlBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlPushedBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlPushedBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlDisabledBackdropKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlDisabledBackdrop(inflatedChild);
|
||||
}
|
||||
else if (childDefinition.getName().equals(controlMouseOverHighlightKey)) {
|
||||
final UIFrame inflatedChild = inflate(childDefinition, glueButtonFrame, frameDefinition,
|
||||
inDecorateFileNames || childDefinition.has("DecorateFileNames"));
|
||||
inflatedChild.setSetAllPoints(true);
|
||||
glueButtonFrame.setControlMouseOverHighlight(inflatedChild);
|
||||
}
|
||||
}
|
||||
inflatedFrame = simpleFrame;
|
||||
final EnumSet<ControlStyle> controlStyle = ControlStyle
|
||||
.parseControlStyle(frameDefinition.getString("ControlStyle"));
|
||||
if (controlStyle.contains(ControlStyle.AUTOTRACK)
|
||||
&& controlStyle.contains(ControlStyle.HIGHLIGHTONMOUSEOVER)) {
|
||||
glueButtonFrame.setHighlightOnMouseOver(true);
|
||||
}
|
||||
inflatedFrame = glueButtonFrame;
|
||||
}
|
||||
else if ("HIGHLIGHT".equals(frameDefinition.getFrameType())) {
|
||||
final String highlightType = frameDefinition.getString("HighlightType");
|
||||
if (!"FILETEXTURE".equals(highlightType)) {
|
||||
throw new IllegalStateException(
|
||||
"Our engine does not know how to handle a non-FILETEXTURE highlight");
|
||||
}
|
||||
final String highlightAlphaFile = frameDefinition.getString("HighlightAlphaFile");
|
||||
final String highlightAlphaMode = frameDefinition.getString("HighlightAlphaMode");
|
||||
final FilterModeTextureFrame textureFrame = new FilterModeTextureFrame(frameDefinition.getName(),
|
||||
parent, false, null);
|
||||
textureFrame.setTexture(highlightAlphaFile, this);
|
||||
if ("ADD".equals(highlightAlphaMode)) {
|
||||
textureFrame.setFilterMode(FilterMode.ADDALPHA);
|
||||
}
|
||||
return textureFrame;
|
||||
}
|
||||
else if ("BACKDROP".equals(frameDefinition.getFrameType())) {
|
||||
final boolean tileBackground = frameDefinition.has("BackdropTileBackground");
|
||||
@ -480,10 +569,10 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
String edgeFileString = frameDefinition.getString("BackdropEdgeFile");
|
||||
System.out.println(frameDefinition.getName() + " wants edge file: " + edgeFileString);
|
||||
if (decorateFileNames && (edgeFileString != null)) {
|
||||
edgeFileString = getSkinField(edgeFileString);
|
||||
edgeFileString = trySkinField(edgeFileString);
|
||||
}
|
||||
if (decorateFileNames && (edgeFileString != null)) {
|
||||
backgroundString = getSkinField(backgroundString);
|
||||
backgroundString = trySkinField(backgroundString);
|
||||
}
|
||||
final Texture background = backgroundString == null ? null : loadTexture(backgroundString);
|
||||
final Texture edgeFile = edgeFileString == null ? null : loadTexture(edgeFileString);
|
||||
@ -534,7 +623,8 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
if (this.fontParam.size == 0) {
|
||||
this.fontParam.size = 24;
|
||||
}
|
||||
frameFont = this.fontGenerator.generateFont(this.fontParam);
|
||||
frameFont = this.dynamicFontGeneratorHolder.getFontGenerator(font.getFontName())
|
||||
.generateFont(this.fontParam);
|
||||
String textString = frameDefinition.getName();
|
||||
String text = frameDefinition.getString("Text");
|
||||
if (text != null) {
|
||||
@ -591,12 +681,18 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
final UIFrame otherFrameByName = getFrameByName(setPointDefinition.getOther(),
|
||||
0 /* TODO: createContext */);
|
||||
if (otherFrameByName == null) {
|
||||
throw new IllegalStateException("Failing to pin " + frameDefinition.getName() + " to "
|
||||
System.err.println("Failing to pin " + frameDefinition.getName() + " to "
|
||||
+ setPointDefinition.getOther() + " because it was null!");
|
||||
if (PIN_FAIL_IS_FATAL) {
|
||||
throw new IllegalStateException("Failing to pin " + frameDefinition.getName() + " to "
|
||||
+ setPointDefinition.getOther() + " because it was null!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
inflatedFrame.addSetPoint(new SetPoint(setPointDefinition.getMyPoint(), otherFrameByName,
|
||||
setPointDefinition.getOtherPoint(), convertX(this.viewport, setPointDefinition.getX()),
|
||||
convertY(this.viewport, setPointDefinition.getY())));
|
||||
}
|
||||
inflatedFrame.addSetPoint(new SetPoint(setPointDefinition.getMyPoint(), otherFrameByName,
|
||||
setPointDefinition.getOtherPoint(), convertX(this.viewport, setPointDefinition.getX()),
|
||||
convertY(this.viewport, setPointDefinition.getY())));
|
||||
}
|
||||
this.nameToFrame.put(frameDefinition.getName(), inflatedFrame);
|
||||
}
|
||||
@ -659,9 +755,13 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
}
|
||||
|
||||
public Texture loadTexture(String path) {
|
||||
if (!path.contains(".")) {
|
||||
final int lastDotIndex = path.lastIndexOf('.');
|
||||
if (lastDotIndex == -1) {
|
||||
path = path + ".blp";
|
||||
}
|
||||
else {
|
||||
path = path.substring(0, lastDotIndex) + ".blp";
|
||||
}
|
||||
Texture texture = this.pathToTexture.get(path);
|
||||
if (texture == null) {
|
||||
try {
|
||||
@ -714,4 +814,20 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
|
||||
public void setText(final StringFrame stringFrame, final String text) {
|
||||
stringFrame.setText(text, this, this.viewport);
|
||||
}
|
||||
|
||||
public BitmapFont getFont() {
|
||||
return this.font;
|
||||
}
|
||||
|
||||
public BitmapFont getFont20() {
|
||||
return this.font20;
|
||||
}
|
||||
|
||||
public FreeTypeFontGenerator getFontGenerator() {
|
||||
return this.fontGenerator;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
this.dynamicFontGeneratorHolder.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -314,9 +314,9 @@ public abstract class AbstractRenderableFrame implements UIFrame {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void render(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
public final void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
||||
if (this.visible) {
|
||||
internalRender(batch, baseFont, glyphLayout);
|
||||
internalRender(batch, font20, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,12 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements
|
||||
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.touchDown(screenX, screenY, button);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
if (isVisible()) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.touchDown(screenX, screenY, button);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
@ -57,10 +59,12 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements
|
||||
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.touchUp(screenX, screenY, button);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
if (isVisible()) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.touchUp(screenX, screenY, button);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
@ -68,10 +72,12 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
if (isVisible()) {
|
||||
for (final UIFrame childFrame : this.childFrames) {
|
||||
final UIFrame clickedChild = childFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||
if (clickedChild != null) {
|
||||
return clickedChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
|
@ -0,0 +1,151 @@
|
||||
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.GameUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||
|
||||
public class GlueButtonFrame extends AbstractRenderableFrame implements ClickableFrame {
|
||||
private UIFrame controlBackdrop;
|
||||
private UIFrame controlPushedBackdrop;
|
||||
private UIFrame controlDisabledBackdrop;
|
||||
private UIFrame controlMouseOverHighlight;
|
||||
|
||||
private boolean enabled = true;
|
||||
private boolean highlightOnMouseOver;
|
||||
private boolean mouseOver = false;
|
||||
|
||||
private UIFrame activeChild;
|
||||
|
||||
private Runnable onClick;
|
||||
|
||||
public GlueButtonFrame(final String name, final UIFrame parent) {
|
||||
super(name, parent);
|
||||
}
|
||||
|
||||
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||
this.controlBackdrop = controlBackdrop;
|
||||
}
|
||||
|
||||
public void setControlPushedBackdrop(final UIFrame controlPushedBackdrop) {
|
||||
this.controlPushedBackdrop = controlPushedBackdrop;
|
||||
}
|
||||
|
||||
public void setControlDisabledBackdrop(final UIFrame controlDisabledBackdrop) {
|
||||
this.controlDisabledBackdrop = controlDisabledBackdrop;
|
||||
}
|
||||
|
||||
public void setControlMouseOverHighlight(final UIFrame controlMouseOverHighlight) {
|
||||
this.controlMouseOverHighlight = controlMouseOverHighlight;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
if (this.enabled) {
|
||||
this.activeChild = this.controlBackdrop;
|
||||
}
|
||||
else {
|
||||
this.activeChild = this.controlDisabledBackdrop;
|
||||
}
|
||||
}
|
||||
|
||||
public void setHighlightOnMouseOver(final boolean highlightOnMouseOver) {
|
||||
this.highlightOnMouseOver = highlightOnMouseOver;
|
||||
}
|
||||
|
||||
public void setOnClick(final Runnable onClick) {
|
||||
this.onClick = onClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
if (this.controlBackdrop != null) {
|
||||
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.controlPushedBackdrop != null) {
|
||||
this.controlPushedBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.controlDisabledBackdrop != null) {
|
||||
this.controlDisabledBackdrop.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.controlMouseOverHighlight != null) {
|
||||
this.controlMouseOverHighlight.positionBounds(gameUI, viewport);
|
||||
}
|
||||
if (this.enabled) {
|
||||
this.activeChild = this.controlBackdrop;
|
||||
}
|
||||
else {
|
||||
this.activeChild = this.controlDisabledBackdrop;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
if (this.activeChild != null) {
|
||||
this.activeChild.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
if (this.mouseOver) {
|
||||
this.controlMouseOverHighlight.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||
if (this.enabled) {
|
||||
this.activeChild = this.controlPushedBackdrop;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||
if (this.enabled) {
|
||||
this.activeChild = this.controlBackdrop;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
if (this.highlightOnMouseOver) {
|
||||
this.mouseOver = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
this.mouseOver = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final int button) {
|
||||
if (this.onClick != null) {
|
||||
this.onClick.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.touchUp(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.touchDown(screenX, screenY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||
return this;
|
||||
}
|
||||
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
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.GameUI;
|
||||
|
||||
public class GlueTextButtonFrame extends GlueButtonFrame {
|
||||
private UIFrame buttonText;
|
||||
|
||||
public GlueTextButtonFrame(final String name, final UIFrame parent) {
|
||||
super(name, parent);
|
||||
}
|
||||
|
||||
public void setButtonText(final UIFrame buttonText) {
|
||||
this.buttonText = buttonText;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
super.innerPositionBounds(gameUI, viewport);
|
||||
if (this.buttonText != null) {
|
||||
this.buttonText.positionBounds(gameUI, viewport);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||
super.internalRender(batch, baseFont, glyphLayout);
|
||||
if (this.buttonText != null) {
|
||||
this.buttonText.render(batch, baseFont, glyphLayout);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.etheller.warsmash.parsers.fdf.frames;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
@ -13,6 +14,7 @@ public class TextureFrame extends AbstractRenderableFrame {
|
||||
private TextureRegion texture;
|
||||
private final boolean decorateFileNames;
|
||||
private final Vector4Definition texCoord;
|
||||
private Color color;
|
||||
|
||||
public TextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||
final Vector4Definition texCoord) {
|
||||
@ -26,14 +28,24 @@ public class TextureFrame extends AbstractRenderableFrame {
|
||||
if (this.texture == null) {
|
||||
return;
|
||||
}
|
||||
if (this.color != null) {
|
||||
batch.setColor(this.color);
|
||||
}
|
||||
batch.draw(this.texture, this.renderBounds.x, this.renderBounds.y, this.renderBounds.width,
|
||||
this.renderBounds.height);
|
||||
if (this.color != null) {
|
||||
batch.setColor(1f, 1f, 1f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||
}
|
||||
|
||||
public void setColor(final Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public void setTexture(String file, final GameUI gameUI) {
|
||||
if (this.decorateFileNames) {
|
||||
file = gameUI.getSkinField(file);
|
||||
|
@ -10,7 +10,6 @@ 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;
|
||||
@ -52,13 +51,12 @@ 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) {
|
||||
public static JUIEnvironment loadJUI(final DataSource dataSource, final Viewport uiViewport, 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, fontGenerator,
|
||||
uiScene, war3MapViewer, rootFrameListener);
|
||||
final JUIEnvironment environment = new JUIEnvironment(jassProgramVisitor, dataSource, uiViewport, uiScene,
|
||||
war3MapViewer, rootFrameListener);
|
||||
for (final String jassFile : files) {
|
||||
try {
|
||||
JassLexer lexer;
|
||||
@ -103,8 +101,8 @@ public class Jass2 {
|
||||
private Element skin;
|
||||
|
||||
public JUIEnvironment(final JassProgramVisitor jassProgramVisitor, final DataSource dataSource,
|
||||
final Viewport uiViewport, final FreeTypeFontGenerator fontGenerator, final Scene uiScene,
|
||||
final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener) {
|
||||
final Viewport uiViewport, 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");
|
||||
@ -137,8 +135,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, fontGenerator, uiScene,
|
||||
war3MapViewer, 0, war3MapViewer.getAllObjectData().getWts());
|
||||
final GameUI gameUI = new GameUI(dataSource, skin, uiViewport, uiScene, war3MapViewer, 0,
|
||||
war3MapViewer.getAllObjectData().getWts());
|
||||
JUIEnvironment.this.gameUI = gameUI;
|
||||
JUIEnvironment.this.skin = skin;
|
||||
rootFrameListener.onCreate(gameUI);
|
||||
|
@ -98,7 +98,7 @@ public final class ImageUtils {
|
||||
}
|
||||
|
||||
public boolean isNeedsSRGBFix() {
|
||||
return false;
|
||||
return this.needsSRGBFix;
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,9 +217,6 @@ public final class ImageUtils {
|
||||
* @return Resulting sRGB image.
|
||||
*/
|
||||
public static BufferedImage forceBufferedImagesRGB(final BufferedImage in) {
|
||||
if (true) {
|
||||
return in;
|
||||
}
|
||||
// Resolve input ColorSpace.
|
||||
final ColorSpace inCS = in.getColorModel().getColorSpace();
|
||||
final ColorSpace sRGBCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
|
@ -1,7 +1,12 @@
|
||||
package com.etheller.warsmash.util;
|
||||
|
||||
public class WarsmashConstants {
|
||||
public static final int MAX_PLAYERS = 28;
|
||||
public static final int MAX_PLAYERS = 16;
|
||||
/*
|
||||
* With version, we use 0 for RoC, 1 for TFT emulation, and probably 2+ or
|
||||
* whatever for custom mods and other stuff
|
||||
*/
|
||||
public static int GAME_VERSION = 0;
|
||||
public static final int REPLACEABLE_TEXTURE_LIMIT = 64;
|
||||
public static final float SIMULATION_STEP_TIME = 1 / 20f;
|
||||
public static final int PORT_NUMBER = 6115;
|
||||
@ -14,4 +19,8 @@ public class WarsmashConstants {
|
||||
// High - 1.5f
|
||||
public static final float MODEL_DETAIL_PARTICLE_FACTOR = 1.5f;
|
||||
public static final float MODEL_DETAIL_PARTICLE_FACTOR_INVERSE = 1f / MODEL_DETAIL_PARTICLE_FACTOR;
|
||||
|
||||
// I know this default string is from somewhere, maybe a language file? Didn't
|
||||
// find it yet so I used this
|
||||
public static final String DEFAULT_STRING = "Default string";
|
||||
}
|
||||
|
@ -11,11 +11,12 @@ public class AudioBufferSource {
|
||||
this.panner = panner;
|
||||
}
|
||||
|
||||
public void start(final int value, final float volume, final float pitch) {
|
||||
public void start(final int value, final float volume, final float pitch, final boolean looping) {
|
||||
if (this.buffer != null) {
|
||||
if (!this.panner.listener.is3DSupported() || this.panner.isWithinListenerDistance()) {
|
||||
Extensions.audio.play(this.buffer, volume, pitch, this.panner.x, this.panner.y, this.panner.z,
|
||||
this.panner.listener.is3DSupported(), this.panner.maxDistance, this.panner.refDistance);
|
||||
this.panner.listener.is3DSupported(), this.panner.maxDistance, this.panner.refDistance,
|
||||
looping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,8 +91,7 @@ public abstract class RawOpenGLTextureResource extends Texture {
|
||||
final GL20 gl = this.viewer.gl;
|
||||
}
|
||||
|
||||
public void update(final BufferedImage image, boolean sRGBFix) {
|
||||
sRGBFix = false;
|
||||
public void update(final BufferedImage image, final boolean sRGBFix) {
|
||||
final GL20 gl = this.viewer.gl;
|
||||
|
||||
final int imageWidth = image.getWidth();
|
||||
|
@ -12,6 +12,7 @@ public abstract class SkeletalNode extends GenericNode {
|
||||
protected static final Vector3 billboardAxisHeap = new Vector3();
|
||||
protected static final Quaternion rotationHeap = new Quaternion();
|
||||
protected static final Quaternion rotationHeap2 = new Quaternion();
|
||||
protected static final Quaternion rotationHeap3 = new Quaternion();
|
||||
protected static final Vector3 scalingHeap = new Vector3();
|
||||
protected static final Vector3 blendLocationHeap = new Vector3();
|
||||
protected static final Vector3 blendHeap = new Vector3();
|
||||
@ -133,10 +134,33 @@ public abstract class SkeletalNode extends GenericNode {
|
||||
computedRotation = rotationHeap;
|
||||
cameraRayHeap.set(camera.billboardedVectors[6]);
|
||||
computedRotation.set(this.parent.inverseWorldRotation);
|
||||
|
||||
// Compute local rotation
|
||||
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {
|
||||
rotationHeap2.set(this.localRotation).slerp(this.localBlendRotation, blendTimeRatio);
|
||||
}
|
||||
else {
|
||||
rotationHeap2.set(this.localRotation);
|
||||
}
|
||||
// Inverse that local rotation
|
||||
rotationHeap2.x = -rotationHeap2.x;
|
||||
rotationHeap2.y = -rotationHeap2.y;
|
||||
rotationHeap2.z = -rotationHeap2.z;
|
||||
rotationHeap3.set(computedRotation);
|
||||
RenderMathUtils.mul(computedRotation, rotationHeap2, rotationHeap3);
|
||||
|
||||
computedRotation.transform(cameraRayHeap);
|
||||
|
||||
billboardAxisHeap.set(0, 1, 0);
|
||||
final float angle = (float) Math.atan2(cameraRayHeap.z, -cameraRayHeap.x);
|
||||
computedRotation.setFromAxisRad(billboardAxisHeap, angle);
|
||||
|
||||
// Inverse that local rotation back to what it was
|
||||
rotationHeap2.x = -rotationHeap2.x;
|
||||
rotationHeap2.y = -rotationHeap2.y;
|
||||
rotationHeap2.z = -rotationHeap2.z;
|
||||
rotationHeap3.set(computedRotation);
|
||||
RenderMathUtils.mul(computedRotation, rotationHeap2, rotationHeap3);
|
||||
}
|
||||
else if (this.billboardedZ) {
|
||||
final Camera camera = scene.camera;
|
||||
|
@ -9,5 +9,5 @@ public interface AudioExtension {
|
||||
float getDuration(Sound sound);
|
||||
|
||||
void play(Sound buffer, final float volume, final float pitch, final float x, final float y, final float z,
|
||||
final boolean is3DSound, float maxDistance, float refDistance);
|
||||
final boolean is3DSound, float maxDistance, float refDistance, boolean looping);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public class AttachmentInstance implements UpdatableObject {
|
||||
internalInstance.dontInheritScaling = false;
|
||||
internalInstance.hide();
|
||||
internalInstance.setParent(instance.nodes[attachment.objectId]);
|
||||
internalInstance.setAnimationSpeed(instance.getAnimationSpeed());
|
||||
|
||||
this.instance = instance;
|
||||
this.attachment = attachment;
|
||||
|
@ -48,7 +48,8 @@ public class EventObjectSnd extends EmittedObject<MdxComplexInstance, EventObjec
|
||||
// Make a sound.
|
||||
source.start(0, emitterObject.volume,
|
||||
(emitterObject.pitch + ((float) Math.random() * emitterObject.pitchVariance * 2))
|
||||
- emitterObject.pitchVariance);
|
||||
- emitterObject.pitchVariance,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -778,6 +778,15 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
|
||||
public void setAnimationSpeed(final float speedRatio) {
|
||||
this.animationSpeed = speedRatio;
|
||||
for (final AttachmentInstance attachmentInstance : this.attachments) {
|
||||
if (attachmentInstance.internalInstance != null) {
|
||||
attachmentInstance.internalInstance.setAnimationSpeed(speedRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float getAnimationSpeed() {
|
||||
return this.animationSpeed;
|
||||
}
|
||||
|
||||
public void setBlendTime(final float blendTime) {
|
||||
@ -796,6 +805,11 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
+ ((currentlyPlayingSequence.getInterval()[1] - currentlyPlayingSequence.getInterval()[0])
|
||||
* ratioOfAnimationCompleted);
|
||||
this.frame = (int) this.floatingFrame;
|
||||
for (final AttachmentInstance attachmentInstance : this.attachments) {
|
||||
if (attachmentInstance.internalInstance != null) {
|
||||
attachmentInstance.internalInstance.setFrameByRatio(ratioOfAnimationCompleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public class TextTag {
|
||||
private float screenCoordsZHeight;
|
||||
private final String text;
|
||||
private final Color color;
|
||||
private int lifetime = 0;
|
||||
private float lifetime = 0;
|
||||
|
||||
public TextTag(final Vector3 position, final String text, final Color color) {
|
||||
this.position = position;
|
||||
@ -17,16 +17,20 @@ public class TextTag {
|
||||
position.z += 64f;
|
||||
}
|
||||
|
||||
public boolean update() {
|
||||
this.screenCoordsZHeight += 1.0f;
|
||||
this.lifetime++;
|
||||
return this.lifetime > 196;
|
||||
public boolean update(final float deltaTime) {
|
||||
this.screenCoordsZHeight += 60.0f * deltaTime;
|
||||
this.lifetime += deltaTime;
|
||||
return this.lifetime > 3.5f;
|
||||
}
|
||||
|
||||
public Vector3 getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public float getRemainingLife() {
|
||||
return 3.5f - this.lifetime;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import com.etheller.warsmash.viewer5.gl.Extensions;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
|
||||
|
||||
public final class UnitSound {
|
||||
private static final UnitSound SILENT = new UnitSound(0, 0, 0, 0, 0, 0);
|
||||
private static final UnitSound SILENT = new UnitSound(0, 0, 0, 0, 0, 0, false);
|
||||
|
||||
private final List<Sound> sounds = new ArrayList<>();
|
||||
private final float volume;
|
||||
@ -26,6 +26,7 @@ public final class UnitSound {
|
||||
private final float minDistance;
|
||||
private final float maxDistance;
|
||||
private final float distanceCutoff;
|
||||
private final boolean looping;
|
||||
|
||||
private Sound lastPlayedSound;
|
||||
|
||||
@ -49,7 +50,15 @@ public final class UnitSound {
|
||||
final float minDistance = row.getFieldFloatValue("MinDistance");
|
||||
final float maxDistance = row.getFieldFloatValue("MaxDistance");
|
||||
final float distanceCutoff = row.getFieldFloatValue("DistanceCutoff");
|
||||
final UnitSound sound = new UnitSound(volume, pitch, pitchVariance, minDistance, maxDistance, distanceCutoff);
|
||||
final String[] flags = row.getField("Flags").split(",");
|
||||
boolean looping = false;
|
||||
for (final String flag : flags) {
|
||||
if ("LOOPING".equals(flag)) {
|
||||
looping = true;
|
||||
}
|
||||
}
|
||||
final UnitSound sound = new UnitSound(volume, pitch, pitchVariance, minDistance, maxDistance, distanceCutoff,
|
||||
looping);
|
||||
for (final String fileName : fileNames.split(",")) {
|
||||
String filePath = directoryBase + fileName;
|
||||
final int lastDotIndex = filePath.lastIndexOf('.');
|
||||
@ -64,13 +73,14 @@ public final class UnitSound {
|
||||
}
|
||||
|
||||
public UnitSound(final float volume, final float pitch, final float pitchVariation, final float minDistance,
|
||||
final float maxDistance, final float distanceCutoff) {
|
||||
final float maxDistance, final float distanceCutoff, final boolean looping) {
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
this.pitchVariance = pitchVariation;
|
||||
this.minDistance = minDistance;
|
||||
this.maxDistance = maxDistance;
|
||||
this.distanceCutoff = distanceCutoff;
|
||||
this.looping = looping;
|
||||
}
|
||||
|
||||
public boolean playUnitResponse(final AudioContext audioContext, final RenderUnit unit) {
|
||||
@ -116,7 +126,7 @@ public final class UnitSound {
|
||||
|
||||
// Make a sound.
|
||||
source.start(0, this.volume,
|
||||
(this.pitch + ((float) Math.random() * this.pitchVariance * 2)) - this.pitchVariance);
|
||||
(this.pitch + ((float) Math.random() * this.pitchVariance * 2)) - this.pitchVariance, this.looping);
|
||||
this.lastPlayedSound = source.buffer;
|
||||
return true;
|
||||
}
|
||||
@ -124,4 +134,10 @@ public final class UnitSound {
|
||||
public int getSoundCount() {
|
||||
return this.sounds.size();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (final Sound sound : this.sounds) {
|
||||
sound.stop();
|
||||
}
|
||||
}
|
||||
}
|
@ -67,9 +67,11 @@ import com.etheller.warsmash.viewer5.Texture;
|
||||
import com.etheller.warsmash.viewer5.WorldScene;
|
||||
import com.etheller.warsmash.viewer5.gl.WebGL;
|
||||
import com.etheller.warsmash.viewer5.handlers.AbstractMdxModelViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.Attachment;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxNode;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
||||
import com.etheller.warsmash.viewer5.handlers.tga.TgaFile;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
|
||||
@ -87,6 +89,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnitTypeData;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderWidget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||
@ -107,6 +110,7 @@ import mpq.MPQArchive;
|
||||
import mpq.MPQException;
|
||||
|
||||
public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
private static final War3ID ABILITY_HERO_RAWCODE = War3ID.fromString("AHer");
|
||||
private static final Color PLACEHOLDER_LUMBER_COLOR = new Color(0.0f, 200f / 255f, 80f / 255f, 1.0f);
|
||||
private static final Color PLACEHOLDER_GOLD_COLOR = new Color(1.0f, 220f / 255f, 0f, 1.0f);
|
||||
private static final War3ID UNIT_FILE = War3ID.fromString("umdl");
|
||||
@ -636,6 +640,42 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnGainLevelEffect(final CUnit source) {
|
||||
final AbilityUI heroUI = War3MapViewer.this.abilityDataUI.getUI(ABILITY_HERO_RAWCODE);
|
||||
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(source);
|
||||
final String heroLevelUpArt = heroUI.getCasterArt(0);
|
||||
final MdxModel heroLevelUpModel = loadModel(heroLevelUpArt);
|
||||
if (heroLevelUpModel != null) {
|
||||
final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel
|
||||
.addInstance();
|
||||
modelInstance.setTeamColor(source.getPlayerIndex());
|
||||
|
||||
final MdxModel model = (MdxModel) renderUnit.instance.model;
|
||||
int index = -1;
|
||||
for (int i = 0; i < model.attachments.size(); i++) {
|
||||
final Attachment attachment = model.attachments.get(i);
|
||||
if (attachment.getName().startsWith("origin ref")) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index != -1) {
|
||||
final MdxNode attachment = renderUnit.instance.getAttachment(index);
|
||||
modelInstance.setParent(attachment);
|
||||
}
|
||||
else {
|
||||
modelInstance.setLocation(renderUnit.location);
|
||||
}
|
||||
|
||||
modelInstance.setScene(War3MapViewer.this.worldScene);
|
||||
SequenceUtils.randomBirthSequence(modelInstance);
|
||||
War3MapViewer.this.projectiles
|
||||
.add(new RenderAttackInstant(modelInstance, War3MapViewer.this,
|
||||
(float) Math.toRadians(renderUnit.getSimulationUnit().getFacing())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEffectOnUnit(final CUnit unit, final String effectPath) {
|
||||
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(unit);
|
||||
@ -1253,7 +1293,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
|
||||
final Iterator<TextTag> textTagIterator = this.textTags.iterator();
|
||||
while (textTagIterator.hasNext()) {
|
||||
if (textTagIterator.next().update()) {
|
||||
if (textTagIterator.next().update(Gdx.graphics.getDeltaTime())) {
|
||||
textTagIterator.remove();
|
||||
}
|
||||
}
|
||||
@ -1619,6 +1659,10 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
return mdxPath;
|
||||
}
|
||||
|
||||
public MdxModel loadModel(final String path) {
|
||||
return (MdxModel) load(mdx(path), PathSolver.DEFAULT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneLightManager createLightManager(final boolean simple) {
|
||||
if (simple) {
|
||||
@ -1637,7 +1681,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
public void setGameUI(final GameUI gameUI) {
|
||||
this.gameUI = gameUI;
|
||||
this.abilityDataUI = new AbilityDataUI(this.allObjectData.getAbilities(), this.allObjectData.getUnits(),
|
||||
this.allObjectData.getUpgrades(), gameUI);
|
||||
this.allObjectData.getUpgrades(), gameUI, this);
|
||||
}
|
||||
|
||||
public GameUI getGameUI() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -11,6 +12,7 @@ import com.etheller.warsmash.units.Element;
|
||||
import com.etheller.warsmash.units.manager.MutableObjectData;
|
||||
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
|
||||
public class AbilityDataUI {
|
||||
// Standard ability icon fields
|
||||
@ -30,6 +32,13 @@ public class AbilityDataUI {
|
||||
private static final War3ID ABILITY_RESEARCH_TIP = War3ID.fromString("aret");
|
||||
private static final War3ID ABILITY_RESEARCH_UBER_TIP = War3ID.fromString("arut");
|
||||
|
||||
private static final War3ID CASTER_ART = War3ID.fromString("acat");
|
||||
private static final War3ID TARGET_ART = War3ID.fromString("atat");
|
||||
private static final War3ID SPECIAL_ART = War3ID.fromString("asat");
|
||||
private static final War3ID EFFECT_ART = War3ID.fromString("aeat");
|
||||
private static final War3ID AREA_EFFECT_ART = War3ID.fromString("aaea");
|
||||
private static final War3ID MISSILE_ART = War3ID.fromString("amat");
|
||||
|
||||
private static final War3ID UNIT_ICON_NORMAL_X = War3ID.fromString("ubpx");
|
||||
private static final War3ID UNIT_ICON_NORMAL_Y = War3ID.fromString("ubpy");
|
||||
private static final War3ID UNIT_ICON_NORMAL = War3ID.fromString("uico");
|
||||
@ -43,7 +52,7 @@ public class AbilityDataUI {
|
||||
private static final War3ID UPGRADE_TIP = War3ID.fromString("gtp1");
|
||||
private static final War3ID UPGRADE_UBER_TIP = War3ID.fromString("gub1");
|
||||
|
||||
private final Map<War3ID, AbilityIconUI> rawcodeToUI = new HashMap<>();
|
||||
private final Map<War3ID, AbilityUI> rawcodeToUI = new HashMap<>();
|
||||
private final Map<War3ID, IconUI> rawcodeToUnitUI = new HashMap<>();
|
||||
private final Map<War3ID, List<IconUI>> rawcodeToUpgradeUI = new HashMap<>();
|
||||
private final IconUI moveUI;
|
||||
@ -62,9 +71,10 @@ public class AbilityDataUI {
|
||||
private final IconUI cancelBuildUI;
|
||||
private final IconUI cancelTrainUI;
|
||||
private final IconUI rallyUI;
|
||||
private final IconUI selectSkillUI;
|
||||
|
||||
public AbilityDataUI(final MutableObjectData abilityData, final MutableObjectData unitData,
|
||||
final MutableObjectData upgradeData, final GameUI gameUI) {
|
||||
final MutableObjectData upgradeData, final GameUI gameUI, final War3MapViewer viewer) {
|
||||
final String disabledPrefix = gameUI.getSkinField("CommandButtonDisabledArtPath");
|
||||
for (final War3ID alias : abilityData.keySet()) {
|
||||
final MutableGameObject abilityTypeData = abilityData.get(alias);
|
||||
@ -89,13 +99,23 @@ public class AbilityDataUI {
|
||||
final Texture iconNormalDisabled = gameUI.loadTexture(disable(iconNormalPath, disabledPrefix));
|
||||
final Texture iconTurnOff = gameUI.loadTexture(iconTurnOffPath);
|
||||
final Texture iconTurnOffDisabled = gameUI.loadTexture(disable(iconTurnOffPath, disabledPrefix));
|
||||
|
||||
final List<String> casterArt = Arrays.asList(abilityTypeData.getFieldAsString(CASTER_ART, 0).split(","));
|
||||
final List<String> targetArt = Arrays.asList(abilityTypeData.getFieldAsString(TARGET_ART, 0).split(","));
|
||||
final List<String> specialArt = Arrays.asList(abilityTypeData.getFieldAsString(SPECIAL_ART, 0).split(","));
|
||||
final List<String> effectArt = Arrays.asList(abilityTypeData.getFieldAsString(EFFECT_ART, 0).split(","));
|
||||
final List<String> areaEffectArt = Arrays
|
||||
.asList(abilityTypeData.getFieldAsString(AREA_EFFECT_ART, 0).split(","));
|
||||
final List<String> missileArt = Arrays.asList(abilityTypeData.getFieldAsString(MISSILE_ART, 0).split(","));
|
||||
|
||||
this.rawcodeToUI.put(alias,
|
||||
new AbilityIconUI(
|
||||
new AbilityUI(
|
||||
new IconUI(iconResearch, iconResearchDisabled, iconResearchX, iconResearchY,
|
||||
iconResearchTip, iconResearchUberTip),
|
||||
new IconUI(iconNormal, iconNormalDisabled, iconNormalX, iconNormalY, iconTip, iconUberTip),
|
||||
new IconUI(iconTurnOff, iconTurnOffDisabled, iconTurnOffX, iconTurnOffY, iconTurnOffTip,
|
||||
iconTurnOffUberTip)));
|
||||
iconTurnOffUberTip),
|
||||
casterArt, targetArt, specialArt, effectArt, areaEffectArt, missileArt));
|
||||
}
|
||||
for (final War3ID alias : unitData.keySet()) {
|
||||
final MutableGameObject abilityTypeData = unitData.get(alias);
|
||||
@ -143,6 +163,7 @@ public class AbilityDataUI {
|
||||
this.cancelBuildUI = createBuiltInIconUI(gameUI, "CmdCancelBuild", disabledPrefix);
|
||||
this.cancelTrainUI = createBuiltInIconUI(gameUI, "CmdCancelTrain", disabledPrefix);
|
||||
this.rallyUI = createBuiltInIconUI(gameUI, "CmdRally", disabledPrefix);
|
||||
this.selectSkillUI = createBuiltInIconUI(gameUI, "CmdSelectSkill", disabledPrefix);
|
||||
}
|
||||
|
||||
private IconUI createBuiltInIconUI(final GameUI gameUI, final String key, final String disabledPrefix) {
|
||||
@ -157,7 +178,7 @@ public class AbilityDataUI {
|
||||
return new IconUI(icon, iconDisabled, buttonPositionX, buttonPositionY, tip, uberTip);
|
||||
}
|
||||
|
||||
public AbilityIconUI getUI(final War3ID rawcode) {
|
||||
public AbilityUI getUI(final War3ID rawcode) {
|
||||
return this.rawcodeToUI.get(rawcode);
|
||||
}
|
||||
|
||||
@ -251,4 +272,8 @@ public class AbilityDataUI {
|
||||
return this.rallyUI;
|
||||
}
|
||||
|
||||
public IconUI getSelectSkillUI() {
|
||||
return this.selectSkillUI;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability;
|
||||
|
||||
public class AbilityIconUI {
|
||||
private final IconUI learnIconUI;
|
||||
private final IconUI onIconUI;
|
||||
private final IconUI offIconUI;
|
||||
|
||||
public AbilityIconUI(final IconUI learnIconUI, final IconUI onIconUI, final IconUI offIconUI) {
|
||||
this.learnIconUI = learnIconUI;
|
||||
this.onIconUI = onIconUI;
|
||||
this.offIconUI = offIconUI;
|
||||
}
|
||||
|
||||
public IconUI getLearnIconUI() {
|
||||
return this.learnIconUI;
|
||||
}
|
||||
|
||||
public IconUI getOnIconUI() {
|
||||
return this.onIconUI;
|
||||
}
|
||||
|
||||
public IconUI getOffIconUI() {
|
||||
return this.offIconUI;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AbilityUI {
|
||||
private final IconUI learnIconUI;
|
||||
private final IconUI onIconUI;
|
||||
private final IconUI offIconUI;
|
||||
private final List<String> casterArt;
|
||||
private final List<String> targetArt;
|
||||
private final List<String> specialArt;
|
||||
private final List<String> effectArt;
|
||||
private final List<String> areaEffectArt;
|
||||
private final List<String> missileArt;
|
||||
|
||||
public AbilityUI(final IconUI learnIconUI, final IconUI onIconUI, final IconUI offIconUI,
|
||||
final List<String> casterArt, final List<String> targetArt, final List<String> specialArt,
|
||||
final List<String> effectArt, final List<String> areaEffectArt, final List<String> missileArt) {
|
||||
this.learnIconUI = learnIconUI;
|
||||
this.onIconUI = onIconUI;
|
||||
this.offIconUI = offIconUI;
|
||||
this.casterArt = casterArt;
|
||||
this.targetArt = targetArt;
|
||||
this.specialArt = specialArt;
|
||||
this.effectArt = effectArt;
|
||||
this.areaEffectArt = areaEffectArt;
|
||||
this.missileArt = missileArt;
|
||||
}
|
||||
|
||||
public IconUI getLearnIconUI() {
|
||||
return this.learnIconUI;
|
||||
}
|
||||
|
||||
public IconUI getOnIconUI() {
|
||||
return this.onIconUI;
|
||||
}
|
||||
|
||||
public IconUI getOffIconUI() {
|
||||
return this.offIconUI;
|
||||
}
|
||||
|
||||
public String getCasterArt(final int index) {
|
||||
return tryGet(this.casterArt, index);
|
||||
}
|
||||
|
||||
public String getTargetArt(final int index) {
|
||||
return tryGet(this.targetArt, index);
|
||||
}
|
||||
|
||||
public String getSpecialArt(final int index) {
|
||||
return tryGet(this.specialArt, index);
|
||||
}
|
||||
|
||||
public String getEffectArt(final int index) {
|
||||
return tryGet(this.effectArt, index);
|
||||
}
|
||||
|
||||
public String getAreaEffectArt(final int index) {
|
||||
return tryGet(this.areaEffectArt, index);
|
||||
}
|
||||
|
||||
public String getMissileArt(final int index) {
|
||||
return tryGet(this.missileArt, index);
|
||||
}
|
||||
|
||||
private static String tryGet(final List<String> items, final int index) {
|
||||
if (index < items.size()) {
|
||||
return items.get(index);
|
||||
}
|
||||
return items.get(items.size() - 1);
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons;
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityIconUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityUI;
|
||||
|
||||
public class AbilityCommandButton implements CommandButton {
|
||||
private final AbilityIconUI abilityIconUI;
|
||||
private final AbilityUI abilityIconUI;
|
||||
private final int orderId;
|
||||
|
||||
public AbilityCommandButton(final AbilityIconUI abilityIconUI, final int orderId) {
|
||||
public AbilityCommandButton(final AbilityUI abilityIconUI, final int orderId) {
|
||||
this.abilityIconUI = abilityIconUI;
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityIconUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||
@ -24,6 +24,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||
@ -63,7 +64,7 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
||||
addCommandButton(ability, this.abilityDataUI.getAttackUI(), ability.getHandleId(), OrderIds.attack, 0,
|
||||
false, false);
|
||||
boolean attackGroundEnabled = false;
|
||||
for (final CUnitAttack attack : this.unit.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : this.unit.getAttacks()) {
|
||||
if (attack.getWeaponType().isAttackGroundSupported()) {
|
||||
attackGroundEnabled = true;
|
||||
break;
|
||||
@ -100,8 +101,13 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
||||
@Override
|
||||
public Void accept(final CAbilityGeneric ability) {
|
||||
if ((this.menuBaseOrderId == 0) && ability.isIconShowing()) {
|
||||
addCommandButton(ability, this.abilityDataUI.getUI(ability.getRawcode()).getOnIconUI(),
|
||||
ability.getHandleId(), 0, 0, false, false);
|
||||
final AbilityUI abilityUI = this.abilityDataUI.getUI(ability.getRawcode());
|
||||
if (abilityUI != null) {
|
||||
addCommandButton(ability, abilityUI.getOnIconUI(), ability.getHandleId(), 0, 0, false, false);
|
||||
}
|
||||
else {
|
||||
addCommandButton(ability, this.abilityDataUI.getStopUI(), ability.getHandleId(), 0, 0, false, false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -109,7 +115,7 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
||||
@Override
|
||||
public Void accept(final GenericSingleIconActiveAbility ability) {
|
||||
if ((this.menuBaseOrderId == 0) && ability.isIconShowing()) {
|
||||
final AbilityIconUI ui = this.abilityDataUI.getUI(ability.getAlias());
|
||||
final AbilityUI ui = this.abilityDataUI.getUI(ability.getAlias());
|
||||
addCommandButton(ability, ability.isToggleOn() ? ui.getOffIconUI() : ui.getOnIconUI(),
|
||||
ability.getHandleId(), ability.getBaseOrderId(), 0, false, false);
|
||||
}
|
||||
@ -329,4 +335,10 @@ public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void
|
||||
return this.requirementsTextBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void accept(final CAbilityHero ability) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,44 @@ public class CGameplayConstants {
|
||||
private final float buildingAngle;
|
||||
private final float rootAngle;
|
||||
|
||||
private final float defenseArmor;
|
||||
|
||||
private final int heroExpRange;
|
||||
|
||||
private final int maxHeroLevel;
|
||||
private final int maxUnitLevel;
|
||||
private final int[] needHeroXp;
|
||||
private final int[] needHeroXpSum;
|
||||
private final int[] grantHeroXp;
|
||||
private final int[] grantNormalXp;
|
||||
private final int[] heroFactorXp;
|
||||
private final float summonedKillFactor;
|
||||
private final float strAttackBonus;
|
||||
private final float strHitPointBonus;
|
||||
private final float strRegenBonus;
|
||||
private final float intManaBonus;
|
||||
private final float intRegenBonus;
|
||||
private final float agiDefenseBonus;
|
||||
private final float agiDefenseBase;
|
||||
private final int agiMoveBonus;
|
||||
private final float agiAttackSpeedBonus;
|
||||
|
||||
private final int needHeroXPFormulaA;
|
||||
private final int needHeroXPFormulaB;
|
||||
private final int needHeroXPFormulaC;
|
||||
private final int grantHeroXPFormulaA;
|
||||
private final int grantHeroXPFormulaB;
|
||||
private final int grantHeroXPFormulaC;
|
||||
private final int grantNormalXPFormulaA;
|
||||
private final int grantNormalXPFormulaB;
|
||||
private final int grantNormalXPFormulaC;
|
||||
|
||||
private final int heroAbilityLevelSkip;
|
||||
|
||||
private final boolean globalExperience;
|
||||
private final boolean maxLevelHeroesDrainExp;
|
||||
private final boolean buildingKillsGiveExp;
|
||||
|
||||
public CGameplayConstants(final DataTable parsedDataTable) {
|
||||
final Element miscData = parsedDataTable.get("Misc");
|
||||
// TODO use radians for half angle
|
||||
@ -67,6 +105,56 @@ public class CGameplayConstants {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.defenseArmor = miscData.getFieldFloatValue("DefenseArmor");
|
||||
|
||||
this.globalExperience = miscData.getFieldValue("GlobalExperience") != 0;
|
||||
this.maxLevelHeroesDrainExp = miscData.getFieldValue("MaxLevelHeroesDrainExp") != 0;
|
||||
this.buildingKillsGiveExp = miscData.getFieldValue("BuildingKillsGiveExp") != 0;
|
||||
|
||||
this.heroExpRange = miscData.getFieldValue("HeroExpRange");
|
||||
|
||||
this.maxHeroLevel = miscData.getFieldValue("MaxHeroLevel");
|
||||
this.maxUnitLevel = miscData.getFieldValue("MaxUnitLevel");
|
||||
|
||||
this.needHeroXPFormulaA = miscData.getFieldValue("NeedHeroXPFormulaA");
|
||||
this.needHeroXPFormulaB = miscData.getFieldValue("NeedHeroXPFormulaB");
|
||||
this.needHeroXPFormulaC = miscData.getFieldValue("NeedHeroXPFormulaC");
|
||||
this.grantHeroXPFormulaA = miscData.getFieldValue("GrantHeroXPFormulaA");
|
||||
this.grantHeroXPFormulaB = miscData.getFieldValue("GrantHeroXPFormulaB");
|
||||
this.grantHeroXPFormulaC = miscData.getFieldValue("GrantHeroXPFormulaC");
|
||||
this.grantNormalXPFormulaA = miscData.getFieldValue("GrantNormalXPFormulaA");
|
||||
this.grantNormalXPFormulaB = miscData.getFieldValue("GrantNormalXPFormulaB");
|
||||
this.grantNormalXPFormulaC = miscData.getFieldValue("GrantNormalXPFormulaC");
|
||||
|
||||
this.needHeroXp = parseTable(miscData.getField("NeedHeroXP"), this.needHeroXPFormulaA, this.needHeroXPFormulaB,
|
||||
this.needHeroXPFormulaC, this.maxHeroLevel);
|
||||
this.needHeroXpSum = new int[this.needHeroXp.length];
|
||||
for (int i = 0; i < this.needHeroXpSum.length; i++) {
|
||||
if (i == 0) {
|
||||
this.needHeroXpSum[i] = this.needHeroXp[i];
|
||||
}
|
||||
else {
|
||||
this.needHeroXpSum[i] = this.needHeroXp[i] + this.needHeroXpSum[i - 1];
|
||||
}
|
||||
}
|
||||
this.grantHeroXp = parseTable(miscData.getField("GrantHeroXP"), this.grantHeroXPFormulaA,
|
||||
this.grantHeroXPFormulaB, this.grantHeroXPFormulaC, this.maxHeroLevel);
|
||||
this.grantNormalXp = parseTable(miscData.getField("GrantNormalXP"), this.grantNormalXPFormulaA,
|
||||
this.grantNormalXPFormulaB, this.grantNormalXPFormulaC, this.maxUnitLevel);
|
||||
this.heroFactorXp = parseIntArray(miscData.getField("HeroFactorXP"));
|
||||
this.summonedKillFactor = miscData.getFieldFloatValue("SummonedKillFactor");
|
||||
this.strAttackBonus = miscData.getFieldFloatValue("StrAttackBonus");
|
||||
this.strHitPointBonus = miscData.getFieldFloatValue("StrHitPointBonus");
|
||||
this.strRegenBonus = miscData.getFieldFloatValue("StrRegenBonus");
|
||||
this.intManaBonus = miscData.getFieldFloatValue("IntManaBonus");
|
||||
this.intRegenBonus = miscData.getFieldFloatValue("IntRegenBonus");
|
||||
this.agiDefenseBonus = miscData.getFieldFloatValue("AgiDefenseBonus");
|
||||
this.agiDefenseBase = miscData.getFieldFloatValue("AgiDefenseBase");
|
||||
this.agiMoveBonus = miscData.getFieldValue("AgiMoveBonus");
|
||||
this.agiAttackSpeedBonus = miscData.getFieldFloatValue("AgiAttackSpeedBonus");
|
||||
|
||||
this.heroAbilityLevelSkip = miscData.getFieldValue("HeroAbilityLevelSkip");
|
||||
}
|
||||
|
||||
public float getAttackHalfAngle() {
|
||||
@ -124,4 +212,134 @@ public class CGameplayConstants {
|
||||
public float getRootAngle() {
|
||||
return this.rootAngle;
|
||||
}
|
||||
|
||||
public float getDefenseArmor() {
|
||||
return this.defenseArmor;
|
||||
}
|
||||
|
||||
public boolean isGlobalExperience() {
|
||||
return this.globalExperience;
|
||||
}
|
||||
|
||||
public boolean isMaxLevelHeroesDrainExp() {
|
||||
return this.maxLevelHeroesDrainExp;
|
||||
}
|
||||
|
||||
public boolean isBuildingKillsGiveExp() {
|
||||
return this.buildingKillsGiveExp;
|
||||
}
|
||||
|
||||
public int getHeroAbilityLevelSkip() {
|
||||
return this.heroAbilityLevelSkip;
|
||||
}
|
||||
|
||||
public int getHeroExpRange() {
|
||||
return this.heroExpRange;
|
||||
}
|
||||
|
||||
public int getMaxHeroLevel() {
|
||||
return this.maxHeroLevel;
|
||||
}
|
||||
|
||||
public int getMaxUnitLevel() {
|
||||
return this.maxUnitLevel;
|
||||
}
|
||||
|
||||
public float getSummonedKillFactor() {
|
||||
return this.summonedKillFactor;
|
||||
}
|
||||
|
||||
public float getStrAttackBonus() {
|
||||
return this.strAttackBonus;
|
||||
}
|
||||
|
||||
public float getStrHitPointBonus() {
|
||||
return this.strHitPointBonus;
|
||||
}
|
||||
|
||||
public float getStrRegenBonus() {
|
||||
return this.strRegenBonus;
|
||||
}
|
||||
|
||||
public float getIntManaBonus() {
|
||||
return this.intManaBonus;
|
||||
}
|
||||
|
||||
public float getIntRegenBonus() {
|
||||
return this.intRegenBonus;
|
||||
}
|
||||
|
||||
public float getAgiDefenseBonus() {
|
||||
return this.agiDefenseBonus;
|
||||
}
|
||||
|
||||
public float getAgiDefenseBase() {
|
||||
return this.agiDefenseBase;
|
||||
}
|
||||
|
||||
public int getAgiMoveBonus() {
|
||||
return this.agiMoveBonus;
|
||||
}
|
||||
|
||||
public float getAgiAttackSpeedBonus() {
|
||||
return this.agiAttackSpeedBonus;
|
||||
}
|
||||
|
||||
public float getHeroFactorXp(final int level) {
|
||||
return getTableValue(this.heroFactorXp, level) / 100f;
|
||||
}
|
||||
|
||||
public int getNeedHeroXP(final int level) {
|
||||
return getTableValue(this.needHeroXp, level);
|
||||
}
|
||||
|
||||
public int getNeedHeroXPSum(final int level) {
|
||||
return getTableValue(this.needHeroXpSum, level);
|
||||
}
|
||||
|
||||
public int getGrantHeroXP(final int level) {
|
||||
return getTableValue(this.grantHeroXp, level);
|
||||
}
|
||||
|
||||
public int getGrantNormalXP(final int level) {
|
||||
return getTableValue(this.grantNormalXp, level);
|
||||
}
|
||||
|
||||
private static int getTableValue(final int[] table, int level) {
|
||||
if (level <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (level > table.length) {
|
||||
level = table.length;
|
||||
}
|
||||
return table[level - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* This incorporates the function "f(x)" documented both on
|
||||
* http://classic.battle.net/war3/basics/heroes.shtml and also on MiscGame.txt.
|
||||
*/
|
||||
private static int[] parseTable(final String txt, final int formulaA, final int formulaB, final int formulaC,
|
||||
final int tableSize) {
|
||||
final String[] splitTxt = txt.split(",");
|
||||
final int[] result = new int[tableSize];
|
||||
for (int i = 0; i < tableSize; i++) {
|
||||
if (i < splitTxt.length) {
|
||||
result[i] = Integer.parseInt(splitTxt[i]);
|
||||
}
|
||||
else {
|
||||
result[i] = (formulaA * result[i - 1]) + (formulaB * i) + formulaC;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] parseIntArray(final String txt) {
|
||||
final String[] splitTxt = txt.split(",");
|
||||
final int[] result = new int[splitTxt.length];
|
||||
for (int i = 0; i < splitTxt.length; i++) {
|
||||
result[i] = Integer.parseInt(splitTxt[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
|
||||
|
||||
public class CItemType {
|
||||
|
||||
}
|
@ -52,6 +52,7 @@ public class CSimulation {
|
||||
private final PathingGrid pathingGrid;
|
||||
private final CWorldCollision worldCollision;
|
||||
private final CPathfindingProcessor[] pathfindingProcessors;
|
||||
private final List<CUnit>[] playerHeroes;
|
||||
private final CGameplayConstants gameplayConstants;
|
||||
private final Random seededRandom;
|
||||
private float currentGameDayTimeElapsed;
|
||||
@ -69,7 +70,8 @@ public class CSimulation {
|
||||
this.simulationRenderController = simulationRenderController;
|
||||
this.pathingGrid = pathingGrid;
|
||||
this.abilityData = new CAbilityData(parsedAbilityData);
|
||||
this.unitData = new CUnitData(parsedUnitData, this.abilityData, this.simulationRenderController);
|
||||
this.unitData = new CUnitData(this.gameplayConstants, parsedUnitData, this.abilityData,
|
||||
this.simulationRenderController);
|
||||
this.destructableData = new CDestructableData(parsedDestructableData, simulationRenderController);
|
||||
this.units = new ArrayList<>();
|
||||
this.newUnits = new ArrayList<>();
|
||||
@ -79,8 +81,10 @@ public class CSimulation {
|
||||
this.handleIdAllocator = new HandleIdAllocator();
|
||||
this.worldCollision = new CWorldCollision(entireMapBounds, this.gameplayConstants.getMaxCollisionRadius());
|
||||
this.pathfindingProcessors = new CPathfindingProcessor[WarsmashConstants.MAX_PLAYERS];
|
||||
for (int i = 0; i < this.pathfindingProcessors.length; i++) {
|
||||
this.playerHeroes = new ArrayList[WarsmashConstants.MAX_PLAYERS];
|
||||
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
|
||||
this.pathfindingProcessors[i] = new CPathfindingProcessor(pathingGrid, this.worldCollision);
|
||||
this.playerHeroes[i] = new ArrayList<>();
|
||||
}
|
||||
this.seededRandom = seededRandom;
|
||||
this.players = new ArrayList<>();
|
||||
@ -211,6 +215,7 @@ public class CSimulation {
|
||||
}
|
||||
this.handleIdToUnit.remove(unit.getHandleId());
|
||||
this.simulationRenderController.removeUnit(unit);
|
||||
this.playerHeroes[unit.getPlayerIndex()].remove(unit);
|
||||
}
|
||||
}
|
||||
finishAddingNewUnits();
|
||||
@ -304,6 +309,18 @@ public class CSimulation {
|
||||
this.simulationRenderController.spawnGainResourceTextTag(unit, resourceType, amount);
|
||||
}
|
||||
|
||||
public void unitGainLevelEvent(final CUnit unit) {
|
||||
this.simulationRenderController.spawnGainLevelEffect(unit);
|
||||
}
|
||||
|
||||
public void heroCreateEvent(final CUnit hero) {
|
||||
this.playerHeroes[hero.getPlayerIndex()].add(hero);
|
||||
}
|
||||
|
||||
public List<CUnit> getPlayerHeroes(final int playerIndex) {
|
||||
return this.playerHeroes[playerIndex];
|
||||
}
|
||||
|
||||
public void unitsLoaded() {
|
||||
// called on startup after the system loads the map's units layer, but not any
|
||||
// custom scripts yet
|
||||
@ -331,4 +348,5 @@ public class CSimulation {
|
||||
public void createEffectOnUnit(final CUnit unit, final String effectPath) {
|
||||
this.simulationRenderController.spawnEffectOnUnit(unit, effectPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitStateListener.
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
|
||||
@ -51,7 +52,13 @@ public class CUnit extends CWidget {
|
||||
private int maximumLife;
|
||||
private int maximumMana;
|
||||
private int speed;
|
||||
private final int defense;
|
||||
private int agilityDefenseBonus;
|
||||
private int permanentDefenseBonus;
|
||||
private int temporaryDefenseBonus;
|
||||
|
||||
private int currentDefenseDisplay;
|
||||
private int currentDefense;
|
||||
|
||||
private int cooldownEndTime = 0;
|
||||
private float flyHeight;
|
||||
private int playerIndex;
|
||||
@ -103,10 +110,11 @@ public class CUnit extends CWidget {
|
||||
private int foodMade;
|
||||
private int foodUsed;
|
||||
|
||||
private List<CUnitAttack> unitSpecificAttacks;
|
||||
|
||||
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 int defense, final CUnitType unitType,
|
||||
final RemovablePathingMapInstance pathingInstance) {
|
||||
final int speed, final CUnitType unitType, final RemovablePathingMapInstance pathingInstance) {
|
||||
super(handleId, x, y, life);
|
||||
this.playerIndex = playerIndex;
|
||||
this.typeId = typeId;
|
||||
@ -115,7 +123,6 @@ public class CUnit extends CWidget {
|
||||
this.maximumLife = maximumLife;
|
||||
this.maximumMana = maximumMana;
|
||||
this.speed = speed;
|
||||
this.defense = defense;
|
||||
this.pathingInstance = pathingInstance;
|
||||
this.flyHeight = unitType.getDefaultFlyingHeight();
|
||||
this.unitType = unitType;
|
||||
@ -126,6 +133,34 @@ public class CUnit extends CWidget {
|
||||
this.currentBehavior = this.defaultBehavior;
|
||||
}
|
||||
|
||||
private void computeDerivedFields() {
|
||||
this.currentDefenseDisplay = this.unitType.getDefense() + this.agilityDefenseBonus + this.permanentDefenseBonus;
|
||||
this.currentDefense = this.currentDefenseDisplay + this.temporaryDefenseBonus;
|
||||
}
|
||||
|
||||
public void setAgilityDefenseBonus(final int agilityDefenseBonus) {
|
||||
this.agilityDefenseBonus = agilityDefenseBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public void setPermanentDefenseBonus(final int permanentDefenseBonus) {
|
||||
this.permanentDefenseBonus = permanentDefenseBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public void setTemporaryDefenseBonus(final int temporaryDefenseBonus) {
|
||||
this.temporaryDefenseBonus = temporaryDefenseBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public int getTemporaryDefenseBonus() {
|
||||
return this.temporaryDefenseBonus;
|
||||
}
|
||||
|
||||
public int getCurrentDefenseDisplay() {
|
||||
return this.currentDefenseDisplay;
|
||||
}
|
||||
|
||||
public void setUnitAnimationListener(final CUnitAnimationListener unitAnimationListener) {
|
||||
this.unitAnimationListener = unitAnimationListener;
|
||||
this.unitAnimationListener.playAnimation(true, PrimaryTag.STAND, SequenceUtils.EMPTY, 1.0f, true);
|
||||
@ -365,8 +400,7 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
|
||||
public boolean autoAcquireAttackTargets(final CSimulation game, final boolean disableMove) {
|
||||
if (!this.unitType.getAttacks().isEmpty()
|
||||
&& !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
|
||||
if (!this.getAttacks().isEmpty() && !this.unitType.getClassifications().contains(CUnitClassification.PEON)) {
|
||||
if (this.collisionRectangle != null) {
|
||||
tempRect.set(this.collisionRectangle);
|
||||
}
|
||||
@ -587,7 +621,7 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
|
||||
public int getDefense() {
|
||||
return this.defense;
|
||||
return this.currentDefense;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -647,11 +681,13 @@ public class CUnit extends CWidget {
|
||||
final float damageRatioFromArmorClass = simulation.getGameplayConstants().getDamageRatioAgainst(attackType,
|
||||
this.unitType.getDefenseType());
|
||||
final float damageRatioFromDefense;
|
||||
if (this.defense >= 0) {
|
||||
damageRatioFromDefense = 1f - (float) (((this.defense) * 0.06) / (1 + (0.06 * this.defense)));
|
||||
final int defense = this.currentDefense;
|
||||
if (defense >= 0) {
|
||||
damageRatioFromDefense = 1f - (((defense) * simulation.getGameplayConstants().getDefenseArmor())
|
||||
/ (1 + (simulation.getGameplayConstants().getDefenseArmor() * defense)));
|
||||
}
|
||||
else {
|
||||
damageRatioFromDefense = 2f - (float) StrictMath.pow(0.94, -this.defense);
|
||||
damageRatioFromDefense = 2f - (float) StrictMath.pow(0.94, -defense);
|
||||
}
|
||||
final float trueDamage = damageRatioFromArmorClass * damageRatioFromDefense * damage;
|
||||
this.life -= trueDamage;
|
||||
@ -660,14 +696,14 @@ public class CUnit extends CWidget {
|
||||
simulation.unitDamageEvent(this, weaponType, this.unitType.getArmorType());
|
||||
if (!this.invulnerable && isDead()) {
|
||||
if (!wasDead) {
|
||||
kill(simulation);
|
||||
kill(simulation, source);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((this.currentBehavior == null) || (this.currentBehavior == this.defaultBehavior)) {
|
||||
if (!simulation.getPlayer(getPlayerIndex()).hasAlliance(source.getPlayerIndex(),
|
||||
CAllianceType.PASSIVE)) {
|
||||
for (final CUnitAttack attack : this.unitType.getAttacks()) {
|
||||
for (final CUnitAttack attack : this.getAttacks()) {
|
||||
if (source.canBeTargetedBy(simulation, this, attack.getTargetsAllowed())) {
|
||||
this.currentBehavior = getAttackBehavior().reset(OrderIds.attack, attack, source, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
@ -680,7 +716,7 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
}
|
||||
|
||||
private void kill(final CSimulation simulation) {
|
||||
private void kill(final CSimulation simulation, final CUnit source) {
|
||||
if (this.currentBehavior != null) {
|
||||
this.currentBehavior.end(simulation, true);
|
||||
}
|
||||
@ -704,6 +740,55 @@ public class CUnit extends CWidget {
|
||||
if (this.foodUsed != 0) {
|
||||
player.setUnitFoodUsed(this, 0);
|
||||
}
|
||||
|
||||
// Award hero experience
|
||||
if (source != null) {
|
||||
final CPlayer sourcePlayer = simulation.getPlayer(source.getPlayerIndex());
|
||||
if (!sourcePlayer.hasAlliance(this.playerIndex, CAllianceType.PASSIVE)) {
|
||||
final CGameplayConstants gameplayConstants = simulation.getGameplayConstants();
|
||||
if (gameplayConstants.isBuildingKillsGiveExp() || !source.getUnitType().isBuilding()) {
|
||||
final CUnit killedUnit = this;
|
||||
final CAbilityHero killedUnitHeroData = getHeroData();
|
||||
final boolean killedUnitIsAHero = killedUnitHeroData != null;
|
||||
int availableAwardXp;
|
||||
if (killedUnitIsAHero) {
|
||||
availableAwardXp = gameplayConstants.getGrantHeroXP(killedUnitHeroData.getHeroLevel());
|
||||
}
|
||||
else {
|
||||
availableAwardXp = gameplayConstants.getGrantNormalXP(this.unitType.getLevel());
|
||||
}
|
||||
final List<CUnit> xpReceivingHeroes = new ArrayList<>();
|
||||
final int heroExpRange = gameplayConstants.getHeroExpRange();
|
||||
simulation.getWorldCollision().enumUnitsInRect(new Rectangle(this.getX() - heroExpRange,
|
||||
this.getY() - heroExpRange, heroExpRange * 2, heroExpRange * 2), new CUnitEnumFunction() {
|
||||
@Override
|
||||
public boolean call(final CUnit unit) {
|
||||
if ((unit.distance(killedUnit) <= heroExpRange)
|
||||
&& sourcePlayer.hasAlliance(unit.getPlayerIndex(), CAllianceType.SHARED_XP)
|
||||
&& (unit.getHeroData() != null)) {
|
||||
xpReceivingHeroes.add(unit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (xpReceivingHeroes.isEmpty()) {
|
||||
if (gameplayConstants.isGlobalExperience()) {
|
||||
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
|
||||
if (sourcePlayer.hasAlliance(i, CAllianceType.SHARED_XP)) {
|
||||
xpReceivingHeroes.addAll(simulation.getPlayerHeroes(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final CUnit receivingHero : xpReceivingHeroes) {
|
||||
final CAbilityHero heroData = receivingHero.getHeroData();
|
||||
heroData.addXp(simulation, receivingHero,
|
||||
(int) (availableAwardXp * (1f / xpReceivingHeroes.size())
|
||||
* gameplayConstants.getHeroFactorXp(heroData.getHeroLevel())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canReach(final AbilityTarget target, final float range) {
|
||||
@ -881,7 +966,7 @@ public class CUnit extends CWidget {
|
||||
public boolean call(final CUnit unit) {
|
||||
if (!this.game.getPlayer(this.source.getPlayerIndex()).hasAlliance(unit.getPlayerIndex(),
|
||||
CAllianceType.PASSIVE)) {
|
||||
for (final CUnitAttack attack : this.source.unitType.getAttacks()) {
|
||||
for (final CUnitAttack attack : this.source.getAttacks()) {
|
||||
if (this.source.canReach(unit, this.source.acquisitionRange)
|
||||
&& unit.canBeTargetedBy(this.game, this.source, attack.getTargetsAllowed())
|
||||
&& (this.source.distance(unit) >= this.source.getUnitType().getMinimumAttackRange())) {
|
||||
@ -1020,7 +1105,7 @@ public class CUnit extends CWidget {
|
||||
final boolean wasDead = isDead();
|
||||
super.setLife(simulation, life);
|
||||
if (isDead() && !wasDead) {
|
||||
kill(simulation);
|
||||
kill(simulation, null);
|
||||
}
|
||||
this.stateNotifier.lifeChanged();
|
||||
}
|
||||
@ -1138,6 +1223,10 @@ public class CUnit extends CWidget {
|
||||
this.stateNotifier.rallyPointChanged();
|
||||
}
|
||||
|
||||
public void internalPublishHeroStatsChanged() {
|
||||
this.stateNotifier.heroStatsChanged();
|
||||
}
|
||||
|
||||
public AbilityTarget getRallyPoint() {
|
||||
return this.rallyPoint;
|
||||
}
|
||||
@ -1275,4 +1364,28 @@ public class CUnit extends CWidget {
|
||||
public COrder getCurrentOrder() {
|
||||
return this.lastStartedOrder;
|
||||
}
|
||||
|
||||
public CAbilityHero getHeroData() {
|
||||
for (final CAbility ability : this.abilities) {
|
||||
if (ability instanceof CAbilityHero) {
|
||||
return (CAbilityHero) ability;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setUnitSpecificAttacks(final List<CUnitAttack> unitSpecificAttacks) {
|
||||
this.unitSpecificAttacks = unitSpecificAttacks;
|
||||
}
|
||||
|
||||
public List<CUnitAttack> getUnitSpecificAttacks() {
|
||||
return this.unitSpecificAttacks;
|
||||
}
|
||||
|
||||
public List<CUnitAttack> getAttacks() {
|
||||
if (this.unitSpecificAttacks != null) {
|
||||
return this.unitSpecificAttacks;
|
||||
}
|
||||
return this.unitType.getAttacks();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ public interface CUnitStateListener {
|
||||
|
||||
void waypointsChanged();
|
||||
|
||||
void heroStatsChanged();
|
||||
|
||||
public static final class CUnitStateNotifier extends SubscriberSetNotifier<CUnitStateListener>
|
||||
implements CUnitStateListener {
|
||||
@Override
|
||||
@ -49,5 +51,12 @@ public interface CUnitStateListener {
|
||||
listener.waypointsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void heroStatsChanged() {
|
||||
for (final CUnitStateListener listener : set) {
|
||||
listener.heroStatsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import java.util.List;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
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.abilities.hero.CPrimaryAttribute;
|
||||
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.attacks.CUnitAttack;
|
||||
@ -58,6 +59,18 @@ public class CUnitType {
|
||||
private final float propWindow;
|
||||
private final float turnRate;
|
||||
private final List<CUnitTypeRequirement> requirements;
|
||||
private final int level;
|
||||
private final boolean hero;
|
||||
private final int startingStrength;
|
||||
private final float strengthPerLevel;
|
||||
private final int startingAgility;
|
||||
private final float agilityPerLevel;
|
||||
private final int startingIntelligence;
|
||||
private final float intelligencePerLevel;
|
||||
private final CPrimaryAttribute primaryAttribute;
|
||||
private final List<War3ID> heroAbilityList;
|
||||
private final List<String> heroProperNames;
|
||||
private final int properNamesCount;
|
||||
|
||||
public CUnitType(final String name, final int life, final int manaInitial, final int manaMaximum, final int speed,
|
||||
final int defense, final String abilityList, final boolean isBldg, final MovementType movementType,
|
||||
@ -70,7 +83,10 @@ public class CUnitType {
|
||||
final int goldCost, final int lumberCost, final int foodUsed, final int foodMade, final int buildTime,
|
||||
final EnumSet<CBuildingPathingType> preventedPathingTypes,
|
||||
final EnumSet<CBuildingPathingType> requiredPathingTypes, final float propWindow, final float turnRate,
|
||||
final List<CUnitTypeRequirement> requirements) {
|
||||
final List<CUnitTypeRequirement> requirements, final int level, final boolean hero, final int strength,
|
||||
final float strengthPerLevel, final int agility, final float agilityPerLevel, final int intelligence,
|
||||
final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute,
|
||||
final List<War3ID> heroAbilityList, final List<String> heroProperNames, final int properNamesCount) {
|
||||
this.name = name;
|
||||
this.life = life;
|
||||
this.manaInitial = manaInitial;
|
||||
@ -108,6 +124,18 @@ public class CUnitType {
|
||||
this.propWindow = propWindow;
|
||||
this.turnRate = turnRate;
|
||||
this.requirements = requirements;
|
||||
this.level = level;
|
||||
this.hero = hero;
|
||||
this.startingStrength = strength;
|
||||
this.strengthPerLevel = strengthPerLevel;
|
||||
this.startingAgility = agility;
|
||||
this.agilityPerLevel = agilityPerLevel;
|
||||
this.startingIntelligence = intelligence;
|
||||
this.intelligencePerLevel = intelligencePerLevel;
|
||||
this.primaryAttribute = primaryAttribute;
|
||||
this.heroAbilityList = heroAbilityList;
|
||||
this.heroProperNames = heroProperNames;
|
||||
this.properNamesCount = properNamesCount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -257,4 +285,52 @@ public class CUnitType {
|
||||
public List<CUnitTypeRequirement> getRequirements() {
|
||||
return this.requirements;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
public boolean isHero() {
|
||||
return this.hero;
|
||||
}
|
||||
|
||||
public int getStartingStrength() {
|
||||
return this.startingStrength;
|
||||
}
|
||||
|
||||
public float getStrengthPerLevel() {
|
||||
return this.strengthPerLevel;
|
||||
}
|
||||
|
||||
public int getStartingAgility() {
|
||||
return this.startingAgility;
|
||||
}
|
||||
|
||||
public float getAgilityPerLevel() {
|
||||
return this.agilityPerLevel;
|
||||
}
|
||||
|
||||
public int getStartingIntelligence() {
|
||||
return this.startingIntelligence;
|
||||
}
|
||||
|
||||
public float getIntelligencePerLevel() {
|
||||
return this.intelligencePerLevel;
|
||||
}
|
||||
|
||||
public CPrimaryAttribute getPrimaryAttribute() {
|
||||
return this.primaryAttribute;
|
||||
}
|
||||
|
||||
public List<War3ID> getHeroAbilityList() {
|
||||
return this.heroAbilityList;
|
||||
}
|
||||
|
||||
public List<String> getHeroProperNames() {
|
||||
return this.heroProperNames;
|
||||
}
|
||||
|
||||
public int getProperNamesCount() {
|
||||
return this.properNamesCount;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
}
|
||||
if ((orderId == OrderIds.smart) || (orderId == OrderIds.attack)) {
|
||||
boolean canTarget = false;
|
||||
for (final CUnitAttack attack : unit.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : unit.getAttacks()) {
|
||||
if (target.canBeTargetedBy(game, unit, attack.getTargetsAllowed())) {
|
||||
canTarget = true;
|
||||
break;
|
||||
@ -77,7 +77,7 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
break;
|
||||
case OrderIds.attackground:
|
||||
boolean allowAttackGround = false;
|
||||
for (final CUnitAttack attack : unit.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : unit.getAttacks()) {
|
||||
if (attack.getWeaponType().isAttackGroundSupported()) {
|
||||
allowAttackGround = true;
|
||||
break;
|
||||
@ -118,7 +118,7 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
@Override
|
||||
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : caster.getAttacks()) {
|
||||
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attack, attack, target, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
@ -142,7 +142,7 @@ public class CAbilityAttack extends AbstractCAbility {
|
||||
return caster.getMoveBehavior().reset(OrderIds.attack, point);
|
||||
case OrderIds.attackground:
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : caster.getAttacks()) {
|
||||
if (attack.getWeaponType().isAttackGroundSupported()) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.attackground, attack, point, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
|
@ -10,6 +10,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
|
||||
|
||||
@ -51,4 +52,6 @@ public interface CAbilityVisitor<T> {
|
||||
T accept(CAbilityRally ability);
|
||||
|
||||
T accept(GenericNoIconAbility ability);
|
||||
|
||||
T accept(CAbilityHero ability);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public class CAbilityColdArrows extends AbstractCAbility {
|
||||
@Override
|
||||
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
|
||||
CBehavior behavior = null;
|
||||
for (final CUnitAttack attack : caster.getUnitType().getAttacks()) {
|
||||
for (final CUnitAttack attack : caster.getAttacks()) {
|
||||
if (target.canBeTargetedBy(game, caster, attack.getTargetsAllowed())) {
|
||||
behavior = caster.getAttackBehavior().reset(OrderIds.coldarrowstarg, attack, target, false,
|
||||
CBehaviorAttackListener.DO_NOTHING);
|
||||
|
@ -53,7 +53,7 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
|
||||
this.behaviorHarvest = new CBehaviorHarvest(unit, this);
|
||||
this.behaviorReturnResources = new CBehaviorReturnResources(unit, this);
|
||||
|
||||
final List<CUnitAttack> unitAttacks = unit.getUnitType().getAttacks();
|
||||
final List<CUnitAttack> unitAttacks = unit.getAttacks();
|
||||
CUnitAttack bestFitTreeAttack = null;
|
||||
for (final CUnitAttack attack : unitAttacks) {
|
||||
if (attack.getTargetsAllowed().contains(CTargetType.TREE)) {
|
||||
|
@ -1,5 +1,275 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero;
|
||||
|
||||
public class CAbilityHero {
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.util.WarsmashConstants;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CGameplayConstants;
|
||||
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.CUnitType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
|
||||
|
||||
public class CAbilityHero extends AbstractCAbility {
|
||||
private final List<War3ID> skillsAvailable;
|
||||
private int xp;
|
||||
private int heroLevel;
|
||||
private int skillPoints;
|
||||
|
||||
private HeroStatValue strength;
|
||||
private HeroStatValue agility;
|
||||
private HeroStatValue intelligence;
|
||||
private String properName;
|
||||
|
||||
public CAbilityHero(final int handleId, final List<War3ID> skillsAvailable) {
|
||||
super(handleId);
|
||||
this.skillsAvailable = skillsAvailable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdd(final CSimulation game, final CUnit unit) {
|
||||
this.heroLevel = 1;
|
||||
this.xp = 0;
|
||||
final CUnitType unitType = unit.getUnitType();
|
||||
this.strength = new HeroStatValue(unitType.getStartingStrength(), unitType.getStrengthPerLevel());
|
||||
this.agility = new HeroStatValue(unitType.getStartingAgility(), unitType.getAgilityPerLevel());
|
||||
this.intelligence = new HeroStatValue(unitType.getStartingIntelligence(), unitType.getIntelligencePerLevel());
|
||||
calculateDerivatedFields(game, unit);
|
||||
|
||||
final int nameIndex = game.getSeededRandom().nextInt(unitType.getProperNamesCount());
|
||||
|
||||
String properName;
|
||||
final List<String> heroProperNames = unitType.getHeroProperNames();
|
||||
if (heroProperNames.size() > 0) {
|
||||
if (nameIndex < heroProperNames.size()) {
|
||||
properName = heroProperNames.get(nameIndex);
|
||||
}
|
||||
else {
|
||||
properName = heroProperNames.get(heroProperNames.size() - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
properName = WarsmashConstants.DEFAULT_STRING;
|
||||
}
|
||||
this.properName = properName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(final CSimulation game, final CUnit unit) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(final CSimulation game, final CUnit unit) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
|
||||
final AbilityPointTarget point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
|
||||
final AbilityTargetCheckReceiver<CWidget> receiver) {
|
||||
receiver.orderIdNotAccepted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
|
||||
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
|
||||
receiver.orderIdNotAccepted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
|
||||
final AbilityTargetCheckReceiver<Void> receiver) {
|
||||
receiver.orderIdNotAccepted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(final CAbilityVisitor<T> visitor) {
|
||||
return visitor.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
|
||||
final AbilityActivationReceiver receiver) {
|
||||
receiver.useOk();
|
||||
}
|
||||
|
||||
public int getSkillPoints() {
|
||||
return this.skillPoints;
|
||||
}
|
||||
|
||||
public void setSkillPoints(final int skillPoints) {
|
||||
this.skillPoints = skillPoints;
|
||||
}
|
||||
|
||||
public int getXp() {
|
||||
return this.xp;
|
||||
}
|
||||
|
||||
public void setXp(final int xp) {
|
||||
this.xp = xp;
|
||||
}
|
||||
|
||||
public int getHeroLevel() {
|
||||
return this.heroLevel;
|
||||
}
|
||||
|
||||
public void setHeroLevel(final int level) {
|
||||
this.heroLevel = level;
|
||||
}
|
||||
|
||||
public HeroStatValue getStrength() {
|
||||
return this.strength;
|
||||
}
|
||||
|
||||
public HeroStatValue getAgility() {
|
||||
return this.agility;
|
||||
}
|
||||
|
||||
public HeroStatValue getIntelligence() {
|
||||
return this.intelligence;
|
||||
}
|
||||
|
||||
public String getProperName() {
|
||||
return this.properName;
|
||||
}
|
||||
|
||||
public void addXp(final CSimulation simulation, final CUnit unit, final int xp) {
|
||||
this.xp += xp;
|
||||
final CGameplayConstants gameplayConstants = simulation.getGameplayConstants();
|
||||
while ((this.heroLevel < gameplayConstants.getMaxHeroLevel())
|
||||
&& (this.xp >= gameplayConstants.getNeedHeroXPSum(this.heroLevel))) {
|
||||
this.heroLevel++;
|
||||
this.skillPoints++;
|
||||
calculateDerivatedFields(simulation, unit);
|
||||
simulation.unitGainLevelEvent(unit);
|
||||
}
|
||||
unit.internalPublishHeroStatsChanged();
|
||||
}
|
||||
|
||||
private HeroStatValue getStat(final CPrimaryAttribute attribute) {
|
||||
switch (attribute) {
|
||||
case AGILITY:
|
||||
return this.agility;
|
||||
case INTELLIGENCE:
|
||||
return this.intelligence;
|
||||
default:
|
||||
case STRENGTH:
|
||||
return this.strength;
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateDerivatedFields(final CSimulation game, final CUnit unit) {
|
||||
final CGameplayConstants gameplayConstants = game.getGameplayConstants();
|
||||
final int prevStrength = this.strength.getCurrent();
|
||||
final int prevAgility = this.agility.getCurrent();
|
||||
final int prevIntelligence = this.intelligence.getCurrent();
|
||||
this.strength.calculate(this.heroLevel);
|
||||
this.agility.calculate(this.heroLevel);
|
||||
this.intelligence.calculate(this.heroLevel);
|
||||
final int deltaStrength = this.strength.getCurrent() - prevStrength;
|
||||
final int deltaIntelligence = this.intelligence.getCurrent() - prevIntelligence;
|
||||
final int currentAgility = this.agility.getCurrent();
|
||||
final int deltaAgility = currentAgility - prevAgility;
|
||||
|
||||
final int primaryAttribute = getStat(unit.getUnitType().getPrimaryAttribute()).getCurrent();
|
||||
for (final CUnitAttack attack : unit.getUnitSpecificAttacks()) {
|
||||
attack.setPrimaryAttributeDamageBonus((int) (primaryAttribute * gameplayConstants.getStrAttackBonus()));
|
||||
}
|
||||
|
||||
final float hitPointIncrease = gameplayConstants.getStrHitPointBonus() * deltaStrength;
|
||||
final int oldMaximumLife = unit.getMaximumLife();
|
||||
final float oldLife = unit.getLife();
|
||||
final int newMaximumLife = Math.round(oldMaximumLife + hitPointIncrease);
|
||||
final float newLife = (oldLife * (newMaximumLife)) / oldMaximumLife;
|
||||
unit.setMaximumLife(newMaximumLife);
|
||||
unit.setLife(game, newLife);
|
||||
|
||||
final float manaPointIncrease = gameplayConstants.getIntManaBonus() * deltaIntelligence;
|
||||
final int oldMaximumMana = unit.getMaximumMana();
|
||||
final float oldMana = unit.getMana();
|
||||
final int newMaximumMana = Math.round(oldMaximumMana + manaPointIncrease);
|
||||
final float newMana = (oldMana * (newMaximumMana)) / oldMaximumMana;
|
||||
unit.setMaximumMana(newMaximumMana);
|
||||
unit.setMana(newMana);
|
||||
|
||||
final int agilityDefenseBonus = Math.round(
|
||||
gameplayConstants.getAgiDefenseBase() + (gameplayConstants.getAgiDefenseBonus() * currentAgility));
|
||||
unit.setAgilityDefenseBonus(agilityDefenseBonus);
|
||||
}
|
||||
|
||||
public static final class HeroStatValue {
|
||||
private final float perLevelFactor;
|
||||
private int base;
|
||||
private int bonus;
|
||||
private int currentBase;
|
||||
private int current;
|
||||
|
||||
private HeroStatValue(final int base, final float perLevelFactor) {
|
||||
this.base = base;
|
||||
this.perLevelFactor = perLevelFactor;
|
||||
}
|
||||
|
||||
public void calculate(final int level) {
|
||||
this.currentBase = this.base + (int) ((level - 1) * this.perLevelFactor);
|
||||
this.current = this.currentBase + this.bonus;
|
||||
}
|
||||
|
||||
public void setBase(final int base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public void setBonus(final int bonus) {
|
||||
this.bonus = bonus;
|
||||
}
|
||||
|
||||
public int getCurrent() {
|
||||
return this.current;
|
||||
}
|
||||
|
||||
public String getDisplayText() {
|
||||
String text = Integer.toString(this.currentBase);
|
||||
if (this.bonus != 0) {
|
||||
if (this.bonus > 0) {
|
||||
text += "|cFF00FF00 (+" + this.bonus + ")";
|
||||
}
|
||||
else {
|
||||
text += "|cFFFF0000 (+" + this.bonus + ")";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero;
|
||||
|
||||
public enum CPrimaryAttribute {
|
||||
STRENGTH,
|
||||
INTELLIGENCE,
|
||||
AGILITY;
|
||||
|
||||
public static CPrimaryAttribute parsePrimaryAttribute(final String targetTypeString) {
|
||||
if (targetTypeString == null) {
|
||||
return STRENGTH;
|
||||
}
|
||||
switch (targetTypeString.toUpperCase()) {
|
||||
case "STR":
|
||||
return STRENGTH;
|
||||
case "INT":
|
||||
return INTELLIGENCE;
|
||||
case "AGI":
|
||||
return AGILITY;
|
||||
default:
|
||||
return STRENGTH;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
|
||||
|
||||
@ -125,4 +126,11 @@ public class AbilityDisableWhileUnderConstructionVisitor implements CAbilityVisi
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void accept(final CAbilityHero ability) {
|
||||
ability.setDisabled(true);
|
||||
ability.setIconShowing(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,6 +41,12 @@ public abstract class CUnitAttack {
|
||||
// calculate
|
||||
private int minDamage;
|
||||
private int maxDamage;
|
||||
private int minDamageDisplay;
|
||||
private int maxDamageDisplay;
|
||||
|
||||
private int primaryAttributeDamageBonus;
|
||||
private int permanentDamageBonus;
|
||||
private int temporaryDamageBonus;
|
||||
|
||||
public CUnitAttack(final float animationBackswingPoint, final float animationDamagePoint,
|
||||
final CAttackType attackType, final float cooldownTime, final int damageBase, final int damageDice,
|
||||
@ -64,15 +70,42 @@ public abstract class CUnitAttack {
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public CUnitAttack(final CUnitAttack other) {
|
||||
this.animationBackswingPoint = other.animationBackswingPoint;
|
||||
this.animationDamagePoint = other.animationDamagePoint;
|
||||
this.attackType = other.attackType;
|
||||
this.cooldownTime = other.cooldownTime;
|
||||
this.damageBase = other.damageBase;
|
||||
this.damageDice = other.damageDice;
|
||||
this.damageSidesPerDie = other.damageSidesPerDie;
|
||||
this.damageUpgradeAmount = other.damageUpgradeAmount;
|
||||
this.range = other.range;
|
||||
this.rangeMotionBuffer = other.rangeMotionBuffer;
|
||||
this.showUI = other.showUI;
|
||||
this.targetsAllowed = other.targetsAllowed;
|
||||
this.weaponSound = other.weaponSound;
|
||||
this.weaponType = other.weaponType;
|
||||
|
||||
this.primaryAttributeDamageBonus = other.primaryAttributeDamageBonus;
|
||||
this.permanentDamageBonus = other.permanentDamageBonus;
|
||||
this.temporaryDamageBonus = other.temporaryDamageBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public abstract CUnitAttack copy();
|
||||
|
||||
private void computeDerivedFields() {
|
||||
this.minDamage = this.damageBase + this.damageDice;
|
||||
this.maxDamage = this.damageBase + (this.damageDice * this.damageSidesPerDie);
|
||||
if (this.minDamage < 0) {
|
||||
this.minDamage = 0;
|
||||
final int baseDamage = this.damageBase + this.primaryAttributeDamageBonus + this.permanentDamageBonus;
|
||||
this.minDamageDisplay = baseDamage + this.damageDice;
|
||||
this.maxDamageDisplay = baseDamage + (this.damageDice * this.damageSidesPerDie);
|
||||
if (this.minDamageDisplay < 0) {
|
||||
this.minDamageDisplay = 0;
|
||||
}
|
||||
if (this.maxDamage < 0) {
|
||||
this.maxDamage = 0;
|
||||
if (this.maxDamageDisplay < 0) {
|
||||
this.maxDamageDisplay = 0;
|
||||
}
|
||||
this.minDamage = this.minDamageDisplay + this.temporaryDamageBonus;
|
||||
this.maxDamage = this.maxDamageDisplay + this.temporaryDamageBonus;
|
||||
}
|
||||
|
||||
public float getAnimationBackswingPoint() {
|
||||
@ -198,6 +231,41 @@ public abstract class CUnitAttack {
|
||||
return this.maxDamage;
|
||||
}
|
||||
|
||||
public int getMinDamageDisplay() {
|
||||
return this.minDamageDisplay;
|
||||
}
|
||||
|
||||
public int getMaxDamageDisplay() {
|
||||
return this.maxDamageDisplay;
|
||||
}
|
||||
|
||||
public void setPrimaryAttributeDamageBonus(final int primaryAttributeDamageBonus) {
|
||||
this.primaryAttributeDamageBonus = primaryAttributeDamageBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public void setPermanentDamageBonus(final int permanentDamageBonus) {
|
||||
this.permanentDamageBonus = permanentDamageBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public void setTemporaryDamageBonus(final int temporaryDamageBonus) {
|
||||
this.temporaryDamageBonus = temporaryDamageBonus;
|
||||
computeDerivedFields();
|
||||
}
|
||||
|
||||
public int getPrimaryAttributeDamageBonus() {
|
||||
return this.primaryAttributeDamageBonus;
|
||||
}
|
||||
|
||||
public int getPermanentDamageBonus() {
|
||||
return this.permanentDamageBonus;
|
||||
}
|
||||
|
||||
public int getTemporaryDamageBonus() {
|
||||
return this.temporaryDamageBonus;
|
||||
}
|
||||
|
||||
public abstract void launch(CSimulation simulation, CUnit unit, AbilityTarget target, float damage,
|
||||
CUnitAttackListener attackListener);
|
||||
}
|
||||
|
@ -25,6 +25,14 @@ public class CUnitAttackInstant extends CUnitAttack {
|
||||
this.projectileArt = projectileArt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackInstant(getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType(),
|
||||
this.projectileArt);
|
||||
}
|
||||
|
||||
public String getProjectileArt() {
|
||||
return this.projectileArt;
|
||||
}
|
||||
|
@ -32,6 +32,14 @@ public class CUnitAttackMissile extends CUnitAttack {
|
||||
this.projectileSpeed = projectileSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackMissile(this.getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType(),
|
||||
this.projectileArc, this.projectileArt, this.projectileHomingEnabled, this.projectileSpeed);
|
||||
}
|
||||
|
||||
public float getProjectileArc() {
|
||||
return this.projectileArc;
|
||||
}
|
||||
|
@ -36,6 +36,16 @@ public class CUnitAttackMissileBounce extends CUnitAttackMissile {
|
||||
this.areaOfEffectTargets = areaOfEffectTargets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackMissileBounce(getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType(),
|
||||
getProjectileArc(), getProjectileArt(), isProjectileHomingEnabled(), getProjectileSpeed(),
|
||||
this.damageLossFactor, this.maximumNumberOfTargets, this.areaOfEffectFullDamage,
|
||||
this.areaOfEffectTargets);
|
||||
}
|
||||
|
||||
public float getDamageLossFactor() {
|
||||
return this.damageLossFactor;
|
||||
}
|
||||
|
@ -24,6 +24,15 @@ public class CUnitAttackMissileLine extends CUnitAttackMissile {
|
||||
this.damageSpillRadius = damageSpillRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackMissileLine(getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType(),
|
||||
getProjectileArc(), getProjectileArt(), isProjectileHomingEnabled(), getProjectileSpeed(),
|
||||
this.damageSpillDistance, this.damageSpillRadius);
|
||||
}
|
||||
|
||||
public float getDamageSpillDistance() {
|
||||
return this.damageSpillDistance;
|
||||
}
|
||||
|
@ -39,6 +39,16 @@ public class CUnitAttackMissileSplash extends CUnitAttackMissile {
|
||||
this.damageFactorSmall = damageFactorSmall;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackMissileSplash(getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType(),
|
||||
getProjectileArc(), getProjectileArt(), isProjectileHomingEnabled(), getProjectileSpeed(),
|
||||
this.areaOfEffectFullDamage, this.areaOfEffectMediumDamage, this.areaOfEffectSmallDamage,
|
||||
this.areaOfEffectTargets, this.damageFactorMedium, this.damageFactorSmall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRange() {
|
||||
return super.getRange();
|
||||
|
@ -23,6 +23,13 @@ public class CUnitAttackNormal extends CUnitAttack {
|
||||
weaponType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUnitAttack copy() {
|
||||
return new CUnitAttackNormal(getAnimationBackswingPoint(), getAnimationDamagePoint(), getAttackType(),
|
||||
getCooldownTime(), getDamageBase(), getDamageDice(), getDamageSidesPerDie(), getDamageUpgradeAmount(),
|
||||
getRange(), getRangeMotionBuffer(), isShowUI(), getTargetsAllowed(), getWeaponSound(), getWeaponType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(final CSimulation simulation, final CUnit unit, final AbilityTarget target, final float damage,
|
||||
final CUnitAttackListener attackListener) {
|
||||
|
@ -40,6 +40,9 @@ public class CAbilityData {
|
||||
CAbilityType<?> abilityType = this.aliasToAbilityType.get(alias);
|
||||
if (abilityType == null) {
|
||||
final MutableGameObject mutableGameObject = this.abilityData.get(alias);
|
||||
if (mutableGameObject == null) {
|
||||
return null;
|
||||
}
|
||||
final War3ID code = mutableGameObject.getCode();
|
||||
final CAbilityTypeDefinition abilityTypeDefinition = this.codeToAbilityTypeDefinition.get(code);
|
||||
if (abilityTypeDefinition != null) {
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data;
|
||||
|
||||
import com.etheller.warsmash.units.manager.MutableObjectData;
|
||||
|
||||
public class CItemData {
|
||||
public CItemData(final MutableObjectData itemData) {
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -13,6 +14,7 @@ import com.etheller.warsmash.util.War3ID;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.RemovablePathingMapInstance;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CGameplayConstants;
|
||||
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;
|
||||
@ -28,6 +30,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CPrimaryAttribute;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
|
||||
@ -53,6 +57,8 @@ public class CUnitData {
|
||||
private static final War3ID TURN_RATE = War3ID.fromString("umvr");
|
||||
private static final War3ID IS_BLDG = War3ID.fromString("ubdg");
|
||||
private static final War3ID NAME = War3ID.fromString("unam");
|
||||
private static final War3ID PROPER_NAMES = War3ID.fromString("upro");
|
||||
private static final War3ID PROPER_NAMES_COUNT = War3ID.fromString("upru");
|
||||
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");
|
||||
@ -133,6 +139,7 @@ public class CUnitData {
|
||||
private static final War3ID TARGETED_AS = War3ID.fromString("utar");
|
||||
|
||||
private static final War3ID ABILITIES_NORMAL = War3ID.fromString("uabi");
|
||||
private static final War3ID ABILITIES_HERO = War3ID.fromString("uhab");
|
||||
|
||||
private static final War3ID STRUCTURES_BUILT = War3ID.fromString("ubui");
|
||||
private static final War3ID UNITS_TRAINED = War3ID.fromString("utra");
|
||||
@ -151,13 +158,25 @@ public class CUnitData {
|
||||
private static final War3ID REQUIRE_PLACE = War3ID.fromString("upar");
|
||||
private static final War3ID PREVENT_PLACE = War3ID.fromString("upap");
|
||||
|
||||
private static final War3ID UNIT_LEVEL = War3ID.fromString("ulev");
|
||||
|
||||
private static final War3ID STR = War3ID.fromString("ustr");
|
||||
private static final War3ID STR_PLUS = War3ID.fromString("ustp");
|
||||
private static final War3ID AGI = War3ID.fromString("uagi");
|
||||
private static final War3ID AGI_PLUS = War3ID.fromString("uagp");
|
||||
private static final War3ID INT = War3ID.fromString("uint");
|
||||
private static final War3ID INT_PLUS = War3ID.fromString("uinp");
|
||||
private static final War3ID PRIMARY_ATTRIBUTE = War3ID.fromString("upra");
|
||||
|
||||
private final CGameplayConstants gameplayConstants;
|
||||
private final MutableObjectData unitData;
|
||||
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
|
||||
private final CAbilityData abilityData;
|
||||
private final SimulationRenderController simulationRenderController;
|
||||
|
||||
public CUnitData(final MutableObjectData unitData, final CAbilityData abilityData,
|
||||
final SimulationRenderController simulationRenderController) {
|
||||
public CUnitData(final CGameplayConstants gameplayConstants, final MutableObjectData unitData,
|
||||
final CAbilityData abilityData, final SimulationRenderController simulationRenderController) {
|
||||
this.gameplayConstants = gameplayConstants;
|
||||
this.unitData = unitData;
|
||||
this.abilityData = abilityData;
|
||||
this.simulationRenderController = simulationRenderController;
|
||||
@ -174,14 +193,20 @@ public class CUnitData {
|
||||
final int manaInitial = unitTypeInstance.getManaInitial();
|
||||
final int manaMaximum = unitTypeInstance.getManaMaximum();
|
||||
final int speed = unitTypeInstance.getSpeed();
|
||||
final int defense = unitTypeInstance.getDefense();
|
||||
|
||||
final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum,
|
||||
speed, defense, unitTypeInstance, pathingInstance);
|
||||
speed, unitTypeInstance, pathingInstance);
|
||||
if (speed > 0) {
|
||||
unit.add(simulation, new CAbilityMove(handleIdAllocator.createId()));
|
||||
}
|
||||
if (!unitTypeInstance.getAttacks().isEmpty()) {
|
||||
if (unitTypeInstance.isHero()) {
|
||||
final List<CUnitAttack> heroAttacks = new ArrayList<>();
|
||||
for (final CUnitAttack attack : unitTypeInstance.getAttacks()) {
|
||||
heroAttacks.add(attack.copy());
|
||||
}
|
||||
unit.setUnitSpecificAttacks(heroAttacks);
|
||||
}
|
||||
if (!unit.getAttacks().isEmpty()) {
|
||||
unit.add(simulation, new CAbilityAttack(handleIdAllocator.createId()));
|
||||
}
|
||||
final List<War3ID> structuresBuilt = unitTypeInstance.getStructuresBuilt();
|
||||
@ -218,6 +243,12 @@ public class CUnitData {
|
||||
if (!unitsTrained.isEmpty()) {
|
||||
unit.add(simulation, new CAbilityRally(handleIdAllocator.createId()));
|
||||
}
|
||||
if (unitTypeInstance.isHero()) {
|
||||
final List<War3ID> heroAbilityList = unitTypeInstance.getHeroAbilityList();
|
||||
unit.add(simulation, new CAbilityHero(handleIdAllocator.createId(), heroAbilityList));
|
||||
// reset initial mana after the value is adjusted for hero data
|
||||
unit.setMana(manaInitial);
|
||||
}
|
||||
for (final String ability : unitTypeInstance.getAbilityList().split(",")) {
|
||||
if ((ability.length() > 0) && !"_".equals(ability)) {
|
||||
final CAbility createAbility = this.abilityData.createAbility(ability, handleIdAllocator.createId());
|
||||
@ -239,6 +270,8 @@ public class CUnitData {
|
||||
final int speed = unitType.getFieldAsInteger(MOVEMENT_SPEED_BASE, 0);
|
||||
final int defense = unitType.getFieldAsInteger(DEFENSE, 0);
|
||||
final String abilityList = unitType.getFieldAsString(ABILITIES_NORMAL, 0);
|
||||
final String heroAbilityListString = unitType.getFieldAsString(ABILITIES_HERO, 0);
|
||||
final int unitLevel = unitType.getFieldAsInteger(UNIT_LEVEL, 0);
|
||||
|
||||
final float moveHeight = unitType.getFieldAsFloat(MOVE_HEIGHT, 0);
|
||||
final String movetp = unitType.getFieldAsString(MOVE_TYPE, 0);
|
||||
@ -246,6 +279,22 @@ public class CUnitData {
|
||||
final float propWindow = unitType.getFieldAsFloat(PROPULSION_WINDOW, 0);
|
||||
final float turnRate = unitType.getFieldAsFloat(TURN_RATE, 0);
|
||||
|
||||
final float strPlus = unitType.getFieldAsFloat(STR_PLUS, 0);
|
||||
final float agiPlus = unitType.getFieldAsFloat(AGI_PLUS, 0);
|
||||
final float intPlus = unitType.getFieldAsFloat(INT_PLUS, 0);
|
||||
|
||||
final int strength = unitType.getFieldAsInteger(STR, 0);
|
||||
final int agility = unitType.getFieldAsInteger(AGI, 0);
|
||||
final int intelligence = unitType.getFieldAsInteger(INT, 0);
|
||||
if (typeId.toString().equals("Hjai")) {
|
||||
System.out.println("bp");
|
||||
}
|
||||
final CPrimaryAttribute primaryAttribute = CPrimaryAttribute
|
||||
.parsePrimaryAttribute(unitType.getFieldAsString(PRIMARY_ATTRIBUTE, 0));
|
||||
|
||||
final String properNames = unitType.getFieldAsString(PROPER_NAMES, 0);
|
||||
final int properNamesCount = unitType.getFieldAsInteger(PROPER_NAMES_COUNT, 0);
|
||||
|
||||
final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0);
|
||||
PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp);
|
||||
if (movementType == null) {
|
||||
@ -424,6 +473,14 @@ public class CUnitData {
|
||||
}
|
||||
}
|
||||
|
||||
final String[] heroAbilityListStringItems = heroAbilityListString.split(",");
|
||||
final List<War3ID> heroAbilityList = new ArrayList<>();
|
||||
for (final String heroAbilityItem : heroAbilityListStringItems) {
|
||||
if (heroAbilityItem.length() == 4) {
|
||||
heroAbilityList.add(War3ID.fromString(heroAbilityItem));
|
||||
}
|
||||
}
|
||||
|
||||
final String requirementsString = unitType.getFieldAsString(REQUIRES, 0);
|
||||
final String requirementsLevelsString = unitType.getFieldAsString(REQUIRES_AMOUNT, 0);
|
||||
final String[] requirementsStringItems = requirementsString.split(",");
|
||||
@ -466,17 +523,38 @@ public class CUnitData {
|
||||
final String raceString = unitType.getFieldAsString(UNIT_RACE, 0);
|
||||
final CUnitRace unitRace = CUnitRace.parseRace(raceString);
|
||||
|
||||
final boolean hero = Character.isUpperCase(typeId.charAt(0));
|
||||
|
||||
final List<String> heroProperNames = Arrays.asList(properNames.split(","));
|
||||
|
||||
unitTypeInstance = new CUnitType(unitName, life, manaInitial, manaMaximum, speed, defense, abilityList,
|
||||
isBldg, movementType, moveHeight, collisionSize, classifications, attacks, armorType, raise, decay,
|
||||
defenseType, impactZ, buildingPathingPixelMap, deathTime, targetedAs, acquisitionRange,
|
||||
minimumAttackRange, structuresBuilt, unitsTrained, researchesAvailable, unitRace, goldCost,
|
||||
lumberCost, foodUsed, foodMade, buildTime, preventedPathingTypes, requiredPathingTypes, propWindow,
|
||||
turnRate, requirements);
|
||||
turnRate, requirements, unitLevel, hero, strength, strPlus, agility, agiPlus, intelligence, intPlus,
|
||||
primaryAttribute, heroAbilityList, heroProperNames, properNamesCount);
|
||||
this.unitIdToUnitType.put(typeId, unitTypeInstance);
|
||||
}
|
||||
return unitTypeInstance;
|
||||
}
|
||||
|
||||
private static int[] populateHeroStatTable(final int maxHeroLevel, final float statPerLevel) {
|
||||
final int[] table = new int[maxHeroLevel];
|
||||
float sumBonusAtLevel = 0f;
|
||||
for (int i = 0; i < table.length; i++) {
|
||||
final float newSumBonusAtLevel = sumBonusAtLevel + statPerLevel;
|
||||
if (i == 0) {
|
||||
table[i] = (int) newSumBonusAtLevel;
|
||||
}
|
||||
else {
|
||||
table[i] = (int) newSumBonusAtLevel - table[i - 1];
|
||||
}
|
||||
sumBonusAtLevel = newSumBonusAtLevel;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint,
|
||||
final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage,
|
||||
final EnumSet<CTargetType> areaOfEffectTargets, final CAttackType attackType, final float cooldownTime,
|
||||
|
@ -41,6 +41,8 @@ public interface SimulationRenderController {
|
||||
|
||||
void spawnBuildingDeathEffect(CUnit cUnit);
|
||||
|
||||
void spawnGainLevelEffect(CUnit cUnit);
|
||||
|
||||
void spawnUnitReadySound(CUnit trainedUnit);
|
||||
|
||||
void unitRepositioned(CUnit cUnit);
|
||||
|
@ -176,6 +176,14 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
|
||||
positionBounds(gameUI, uiViewport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
|
@ -21,7 +21,6 @@ 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.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
@ -82,6 +81,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataU
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CGameplayConstants;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CPlayerStateListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||
@ -108,6 +108,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAb
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CPrimaryAttribute;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
|
||||
@ -154,7 +156,6 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private static final AbilityPointTarget clickLocationTemp2 = new AbilityPointTarget();
|
||||
private final DataSource dataSource;
|
||||
private final ExtendViewport uiViewport;
|
||||
private final FreeTypeFontGenerator fontGenerator;
|
||||
private final Scene uiScene;
|
||||
private final Scene portraitScene;
|
||||
private final GameCameraManager cameraManager;
|
||||
@ -189,6 +190,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private StringFrame simpleClassValue;
|
||||
private StringFrame simpleBuildingActionLabel;
|
||||
private SimpleStatusBarFrame simpleBuildTimeIndicator;
|
||||
private SimpleStatusBarFrame simpleHeroLevelBar;
|
||||
|
||||
private UIFrame simpleInfoPanelBuildingDetail;
|
||||
private StringFrame simpleBuildingNameValue;
|
||||
@ -213,6 +215,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private InfoPanelIconBackdrops damageBackdrops;
|
||||
private InfoPanelIconBackdrops defenseBackdrops;
|
||||
|
||||
private UIFrame heroInfoPanel;
|
||||
|
||||
private final CommandCardIcon[][] commandCard = new CommandCardIcon[COMMAND_CARD_HEIGHT][COMMAND_CARD_WIDTH];
|
||||
|
||||
private RenderUnit selectedUnit;
|
||||
@ -264,14 +268,18 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
private BitmapFont textTagFont;
|
||||
private SetPoint uberTipNoResourcesSetPoint;
|
||||
private SetPoint uberTipWithResourcesSetPoint;
|
||||
private TextureFrame primaryAttributeIcon;
|
||||
private StringFrame strengthValue;
|
||||
private StringFrame agilityValue;
|
||||
private StringFrame intelligenceValue;
|
||||
private SimpleFrame smashHeroInfoPanelWrapper;
|
||||
|
||||
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport,
|
||||
final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final Scene portraitScene,
|
||||
final CameraPreset[] cameraPresets, final CameraRates cameraRates, final War3MapViewer war3MapViewer,
|
||||
final RootFrameListener rootFrameListener, final CPlayerUnitOrderListener unitOrderListener) {
|
||||
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene,
|
||||
final Scene portraitScene, final CameraPreset[] cameraPresets, final CameraRates cameraRates,
|
||||
final War3MapViewer war3MapViewer, final RootFrameListener rootFrameListener,
|
||||
final CPlayerUnitOrderListener unitOrderListener) {
|
||||
this.dataSource = dataSource;
|
||||
this.uiViewport = uiViewport;
|
||||
this.fontGenerator = fontGenerator;
|
||||
this.uiScene = uiScene;
|
||||
this.portraitScene = portraitScene;
|
||||
this.war3MapViewer = war3MapViewer;
|
||||
@ -333,41 +341,40 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
// Load skins and templates
|
||||
// =================================
|
||||
final CRace race = this.localPlayer.getRace();
|
||||
final int racialSkinIndex;
|
||||
final String racialSkinKey;
|
||||
int racialCommandIndex;
|
||||
if (race == null) {
|
||||
racialSkinIndex = 1;
|
||||
racialSkinKey = "Human";
|
||||
racialCommandIndex = 0;
|
||||
}
|
||||
else {
|
||||
switch (race) {
|
||||
case HUMAN:
|
||||
racialSkinIndex = 1;
|
||||
racialSkinKey = "Human";
|
||||
racialCommandIndex = 0;
|
||||
break;
|
||||
case ORC:
|
||||
racialSkinIndex = 0;
|
||||
racialSkinKey = "Orc";
|
||||
racialCommandIndex = 1;
|
||||
break;
|
||||
case NIGHTELF:
|
||||
racialSkinIndex = 2;
|
||||
racialSkinKey = "NightElf";
|
||||
racialCommandIndex = 3;
|
||||
break;
|
||||
case UNDEAD:
|
||||
racialSkinIndex = 3;
|
||||
racialSkinKey = "Undead";
|
||||
racialCommandIndex = 2;
|
||||
break;
|
||||
case DEMON:
|
||||
case OTHER:
|
||||
default:
|
||||
racialSkinIndex = -1;
|
||||
racialSkinKey = "Human";
|
||||
racialCommandIndex = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, racialSkinIndex), this.uiViewport,
|
||||
this.fontGenerator, this.uiScene, this.war3MapViewer, racialCommandIndex,
|
||||
this.war3MapViewer.getAllObjectData().getWts());
|
||||
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, racialSkinKey), this.uiViewport,
|
||||
this.uiScene, this.war3MapViewer, racialCommandIndex, this.war3MapViewer.getAllObjectData().getWts());
|
||||
this.rootFrameListener.onCreate(this.rootFrame);
|
||||
try {
|
||||
this.rootFrame.loadTOCFile("UI\\FrameDef\\FrameDef.toc");
|
||||
@ -418,7 +425,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.unitManaText = (StringFrame) this.rootFrame.getFrameByName("UnitPortraitManaPointText", 0);
|
||||
|
||||
final float infoPanelUnitDetailWidth = GameUI.convertY(this.uiViewport, 0.180f);
|
||||
final float infoPanelUnitDetailHeight = GameUI.convertY(this.uiViewport, 0.110f);
|
||||
final float infoPanelUnitDetailHeight = GameUI.convertY(this.uiViewport, 0.112f);
|
||||
this.smashSimpleInfoPanel = this.rootFrame.createSimpleFrame("SmashSimpleInfoPanel", this.rootFrame, 0);
|
||||
this.smashSimpleInfoPanel
|
||||
.addAnchor(new AnchorDefinition(FramePoint.BOTTOM, 0, GameUI.convertY(this.uiViewport, 0.0f)));
|
||||
@ -442,6 +449,14 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.simpleBuildTimeIndicator.setWidth(buildTimeIndicatorWidth);
|
||||
this.simpleBuildTimeIndicator.setHeight(buildTimeIndicatorHeight);
|
||||
|
||||
this.simpleHeroLevelBar = (SimpleStatusBarFrame) this.rootFrame.getFrameByName("SimpleHeroLevelBar", 0);
|
||||
final TextureFrame simpleHeroLevelBarBar = this.simpleHeroLevelBar.getBarFrame();
|
||||
simpleHeroLevelBarBar.setTexture("SimpleXpBarConsole", this.rootFrame);
|
||||
simpleHeroLevelBarBar.setColor(new Color(138f / 255f, 0, 131f / 255f, 1f));
|
||||
final TextureFrame simpleHeroLevelBarBorder = this.simpleHeroLevelBar.getBorderFrame();
|
||||
simpleHeroLevelBarBorder.setTexture("SimpleXpBarBorder", this.rootFrame);
|
||||
this.simpleHeroLevelBar.setWidth(infoPanelUnitDetailWidth);
|
||||
|
||||
// Create Simple Info Panel Building Detail
|
||||
this.simpleInfoPanelBuildingDetail = this.rootFrame.createSimpleFrame("SimpleInfoPanelBuildingDetail",
|
||||
this.smashSimpleInfoPanel, 0);
|
||||
@ -515,7 +530,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.smashAttack1IconWrapper = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashSimpleInfoPanelIconDamage",
|
||||
this.simpleInfoPanelUnitDetail, 0);
|
||||
this.smashAttack1IconWrapper.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail,
|
||||
FramePoint.TOPLEFT, 0, GameUI.convertY(this.uiViewport, -0.030125f)));
|
||||
FramePoint.TOPLEFT, 0, GameUI.convertY(this.uiViewport, -0.032f)));
|
||||
this.smashAttack1IconWrapper.setWidth(GameUI.convertX(this.uiViewport, 0.1f));
|
||||
this.smashAttack1IconWrapper.setHeight(GameUI.convertY(this.uiViewport, 0.030125f));
|
||||
this.attack1Icon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconDamage", this.smashAttack1IconWrapper,
|
||||
@ -528,7 +543,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.simpleInfoPanelUnitDetail, 0);
|
||||
this.smashAttack2IconWrapper
|
||||
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
|
||||
GameUI.convertX(this.uiViewport, 0.1f), GameUI.convertY(this.uiViewport, -0.030125f)));
|
||||
GameUI.convertX(this.uiViewport, 0.1f), GameUI.convertY(this.uiViewport, -0.03125f)));
|
||||
this.smashAttack2IconWrapper.setWidth(GameUI.convertX(this.uiViewport, 0.1f));
|
||||
this.smashAttack2IconWrapper.setHeight(GameUI.convertY(this.uiViewport, 0.030125f));
|
||||
this.attack2Icon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconDamage", this.smashAttack2IconWrapper,
|
||||
@ -540,7 +555,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.smashArmorIconWrapper = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashSimpleInfoPanelIconArmor",
|
||||
this.simpleInfoPanelUnitDetail, 0);
|
||||
this.smashArmorIconWrapper.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail,
|
||||
FramePoint.TOPLEFT, GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.06025f)));
|
||||
FramePoint.TOPLEFT, GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.0625f)));
|
||||
this.smashArmorIconWrapper.setWidth(GameUI.convertX(this.uiViewport, 0.1f));
|
||||
this.smashArmorIconWrapper.setHeight(GameUI.convertY(this.uiViewport, 0.030125f));
|
||||
this.armorIcon = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconArmor", this.smashArmorIconWrapper, 0);
|
||||
@ -548,6 +563,19 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.armorInfoPanelIconValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconValue", 0);
|
||||
this.armorInfoPanelIconLevel = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconLevel", 0);
|
||||
|
||||
this.smashHeroInfoPanelWrapper = (SimpleFrame) this.rootFrame.createSimpleFrame("SmashSimpleInfoPanelIconHero",
|
||||
this.simpleInfoPanelUnitDetail, 0);
|
||||
this.smashHeroInfoPanelWrapper.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail,
|
||||
FramePoint.TOPLEFT, GameUI.convertX(this.uiViewport, 0.1f), GameUI.convertY(this.uiViewport, -0.029f)));
|
||||
this.smashHeroInfoPanelWrapper.setWidth(GameUI.convertX(this.uiViewport, 0.1f));
|
||||
this.smashHeroInfoPanelWrapper.setHeight(GameUI.convertY(this.uiViewport, 0.0625f));
|
||||
this.heroInfoPanel = this.rootFrame.createSimpleFrame("SimpleInfoPanelIconHero", this.smashHeroInfoPanelWrapper,
|
||||
0);
|
||||
this.primaryAttributeIcon = (TextureFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroIcon", 0);
|
||||
this.strengthValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroStrengthValue", 0);
|
||||
this.agilityValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroAgilityValue", 0);
|
||||
this.intelligenceValue = (StringFrame) this.rootFrame.getFrameByName("InfoPanelIconHeroIntellectValue", 0);
|
||||
|
||||
this.inventoryCover = this.rootFrame.createSimpleFrame("SmashConsoleInventoryCover", this.rootFrame, 0);
|
||||
|
||||
final Element fontHeights = this.war3MapViewer.miscData.get("FontHeights");
|
||||
@ -676,7 +704,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
|
||||
final FreeTypeFontParameter fontParam = new FreeTypeFontParameter();
|
||||
fontParam.size = (int) GameUI.convertY(this.uiViewport, 0.012f);
|
||||
this.textTagFont = this.fontGenerator.generateFont(fontParam);
|
||||
this.textTagFont = this.rootFrame.getFontGenerator().generateFont(fontParam);
|
||||
|
||||
this.rootFrame.positionBounds(this.rootFrame, this.uiViewport);
|
||||
|
||||
@ -876,10 +904,16 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
}
|
||||
}
|
||||
|
||||
public void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
||||
this.rootFrame.render(batch, font20, glyphLayout);
|
||||
public void render(final SpriteBatch batch, final GlyphLayout glyphLayout) {
|
||||
final BitmapFont font = this.rootFrame.getFont();
|
||||
font.setColor(Color.YELLOW);
|
||||
final String fpsString = "FPS: " + Gdx.graphics.getFramesPerSecond();
|
||||
glyphLayout.setText(font, fpsString);
|
||||
font.draw(batch, fpsString, (this.uiViewport.getMinWorldWidth() - glyphLayout.width) / 2,
|
||||
1100 * this.heightRatioCorrection);
|
||||
this.rootFrame.render(batch, this.rootFrame.getFont20(), glyphLayout);
|
||||
if (this.selectedUnit != null) {
|
||||
font20.setColor(Color.WHITE);
|
||||
this.rootFrame.getFont20().setColor(Color.WHITE);
|
||||
|
||||
}
|
||||
|
||||
@ -891,7 +925,10 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
if (this.war3MapViewer.worldScene.camera.rect.contains(screenCoordsVector.x,
|
||||
(Gdx.graphics.getHeight() - screenCoordsVector.y) + textTag.getScreenCoordsZHeight())) {
|
||||
final Vector2 unprojected = this.uiViewport.unproject(screenCoordsVector);
|
||||
this.textTagFont.setColor(textTag.getColor());
|
||||
final float remainingLife = textTag.getRemainingLife();
|
||||
final float alpha = (remainingLife > 1.0f ? 1.0f : remainingLife);
|
||||
this.textTagFont.setColor(textTag.getColor().r, textTag.getColor().g, textTag.getColor().b,
|
||||
textTag.getColor().a * alpha);
|
||||
glyphLayout.setText(this.textTagFont, textTag.getText());
|
||||
this.textTagFont.draw(batch, textTag.getText(), unprojected.x - (glyphLayout.width / 2),
|
||||
(unprojected.y - (glyphLayout.height / 2)) + textTag.getScreenCoordsZHeight());
|
||||
@ -917,8 +954,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
public Void accept(final CAbilityAttack ability) {
|
||||
if (MeleeUI.this.activeCommandOrderId == OrderIds.attackground) {
|
||||
float radius = 0;
|
||||
for (final CUnitAttack attack : MeleeUI.this.activeCommandUnit.getSimulationUnit().getUnitType()
|
||||
.getAttacks()) {
|
||||
for (final CUnitAttack attack : MeleeUI.this.activeCommandUnit.getSimulationUnit().getAttacks()) {
|
||||
if (attack.getWeaponType().isAttackGroundSupported()) {
|
||||
if (attack instanceof CUnitAttackMissileSplash) {
|
||||
final int areaOfEffectSmallDamage = ((CUnitAttackMissileSplash) attack)
|
||||
@ -1020,6 +1056,12 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void accept(final CAbilityHero ability) {
|
||||
handleTargetCursor(ability);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleTargetCursor(final CAbility ability) {
|
||||
if (MeleeUI.this.cursorModelInstance != null) {
|
||||
MeleeUI.this.cursorModelInstance.detach();
|
||||
@ -1333,6 +1375,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.armorIcon.setVisible(false);
|
||||
this.rootFrame.setText(this.armorInfoPanelIconLevel, "");
|
||||
this.simpleBuildTimeIndicator.setVisible(false);
|
||||
this.simpleHeroLevelBar.setVisible(false);
|
||||
this.simpleBuildingBuildTimeIndicator.setVisible(false);
|
||||
this.simpleInfoPanelBuildingDetail.setVisible(false);
|
||||
this.simpleInfoPanelUnitDetail.setVisible(false);
|
||||
@ -1340,6 +1383,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
queueIconFrame.setVisible(false);
|
||||
}
|
||||
this.selectWorkerInsideFrame.setVisible(false);
|
||||
this.heroInfoPanel.setVisible(false);
|
||||
this.rallyPointInstance.hide();
|
||||
this.rallyPointInstance.detach();
|
||||
repositionWaypointFlags(null);
|
||||
@ -1491,6 +1535,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
|
||||
this.simpleBuildingBuildTimeIndicator.setVisible(true);
|
||||
this.simpleBuildTimeIndicator.setVisible(false);
|
||||
this.simpleHeroLevelBar.setVisible(false);
|
||||
if (simulationUnit.getBuildQueueTypes()[0] == QueueItemType.UNIT) {
|
||||
this.rootFrame.setText(this.simpleBuildingBuildingActionLabel,
|
||||
this.rootFrame.getTemplates().getDecoratedString("TRAINING"));
|
||||
@ -1502,6 +1547,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.attack1Icon.setVisible(false);
|
||||
this.attack2Icon.setVisible(false);
|
||||
this.armorIcon.setVisible(false);
|
||||
this.heroInfoPanel.setVisible(false);
|
||||
this.selectWorkerInsideFrame.setVisible(false);
|
||||
}
|
||||
else {
|
||||
@ -1510,41 +1556,35 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
}
|
||||
this.simpleInfoPanelBuildingDetail.setVisible(false);
|
||||
this.simpleInfoPanelUnitDetail.setVisible(true);
|
||||
this.rootFrame.setText(this.simpleNameValue, simulationUnit.getUnitType().getName());
|
||||
String classText = null;
|
||||
for (final CUnitClassification classification : simulationUnit.getClassifications()) {
|
||||
if ((classification == CUnitClassification.MECHANICAL) && simulationUnit.getUnitType().isBuilding()) {
|
||||
// buildings dont display MECHANICAL
|
||||
continue;
|
||||
}
|
||||
if (classification.getDisplayName() != null) {
|
||||
classText = classification.getDisplayName();
|
||||
}
|
||||
}
|
||||
if (classText != null) {
|
||||
this.rootFrame.setText(this.simpleClassValue, classText);
|
||||
}
|
||||
else {
|
||||
this.rootFrame.setText(this.simpleClassValue, "");
|
||||
}
|
||||
final String unitTypeName = simulationUnit.getUnitType().getName();
|
||||
|
||||
final boolean anyAttacks = simulationUnit.getUnitType().getAttacks().size() > 0;
|
||||
final boolean anyAttacks = simulationUnit.getAttacks().size() > 0;
|
||||
final boolean constructing = simulationUnit.isConstructing();
|
||||
final UIFrame localArmorIcon = this.armorIcon;
|
||||
final TextureFrame localArmorIconBackdrop = this.armorIconBackdrop;
|
||||
final StringFrame localArmorInfoPanelIconValue = this.armorInfoPanelIconValue;
|
||||
if (anyAttacks && !constructing) {
|
||||
final CUnitAttack attackOne = simulationUnit.getUnitType().getAttacks().get(0);
|
||||
final CUnitAttack attackOne = simulationUnit.getAttacks().get(0);
|
||||
this.attack1Icon.setVisible(attackOne.isShowUI());
|
||||
this.attack1IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackOne.getAttackType()));
|
||||
this.rootFrame.setText(this.attack1InfoPanelIconValue,
|
||||
attackOne.getMinDamage() + " - " + attackOne.getMaxDamage());
|
||||
if (simulationUnit.getUnitType().getAttacks().size() > 1) {
|
||||
final CUnitAttack attackTwo = simulationUnit.getUnitType().getAttacks().get(1);
|
||||
String attackOneDmgText = attackOne.getMinDamageDisplay() + " - " + attackOne.getMaxDamageDisplay();
|
||||
final int attackOneTemporaryDamageBonus = attackOne.getTemporaryDamageBonus();
|
||||
if (attackOneTemporaryDamageBonus != 0) {
|
||||
attackOneDmgText += (attackOneTemporaryDamageBonus > 0 ? "|cFF00FF00 (+" : "|cFFFF0000 (+")
|
||||
+ attackOneTemporaryDamageBonus + ")";
|
||||
}
|
||||
this.rootFrame.setText(this.attack1InfoPanelIconValue, attackOneDmgText);
|
||||
if (simulationUnit.getAttacks().size() > 1) {
|
||||
final CUnitAttack attackTwo = simulationUnit.getAttacks().get(1);
|
||||
this.attack2Icon.setVisible(attackTwo.isShowUI());
|
||||
this.attack2IconBackdrop.setTexture(this.damageBackdrops.getTexture(attackTwo.getAttackType()));
|
||||
this.rootFrame.setText(this.attack2InfoPanelIconValue,
|
||||
attackTwo.getMinDamage() + " - " + attackTwo.getMaxDamage());
|
||||
String attackTwoDmgText = attackTwo.getMinDamage() + " - " + attackTwo.getMaxDamage();
|
||||
final int attackTwoTemporaryDamageBonus = attackTwo.getTemporaryDamageBonus();
|
||||
if (attackTwoTemporaryDamageBonus != 0) {
|
||||
attackTwoDmgText += (attackTwoTemporaryDamageBonus > 0 ? "|cFF00FF00 (+" : "|cFFFF0000 (+")
|
||||
+ attackTwoTemporaryDamageBonus + ")";
|
||||
}
|
||||
this.rootFrame.setText(this.attack2InfoPanelIconValue, attackTwoDmgText);
|
||||
}
|
||||
else {
|
||||
this.attack2Icon.setVisible(false);
|
||||
@ -1552,7 +1592,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
|
||||
this.smashArmorIconWrapper.addSetPoint(
|
||||
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
|
||||
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.06025f)));
|
||||
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.0625f)));
|
||||
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
|
||||
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
@ -1562,11 +1602,67 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
|
||||
this.smashArmorIconWrapper.addSetPoint(
|
||||
new SetPoint(FramePoint.TOPLEFT, this.simpleInfoPanelUnitDetail, FramePoint.TOPLEFT,
|
||||
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.030125f)));
|
||||
GameUI.convertX(this.uiViewport, 0f), GameUI.convertY(this.uiViewport, -0.032f)));
|
||||
this.smashArmorIconWrapper.positionBounds(this.rootFrame, this.uiViewport);
|
||||
this.armorIcon.positionBounds(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
|
||||
final CAbilityHero heroData = simulationUnit.getHeroData();
|
||||
final boolean hero = heroData != null;
|
||||
this.heroInfoPanel.setVisible(hero);
|
||||
if (hero) {
|
||||
final CPrimaryAttribute primaryAttribute = simulationUnit.getUnitType().getPrimaryAttribute();
|
||||
String iconKey;
|
||||
switch (primaryAttribute) {
|
||||
case AGILITY:
|
||||
iconKey = "InfoPanelIconHeroIconAGI";
|
||||
break;
|
||||
case INTELLIGENCE:
|
||||
iconKey = "InfoPanelIconHeroIconINT";
|
||||
break;
|
||||
default:
|
||||
case STRENGTH:
|
||||
iconKey = "InfoPanelIconHeroIconSTR";
|
||||
break;
|
||||
}
|
||||
this.primaryAttributeIcon.setTexture(iconKey, this.rootFrame);
|
||||
|
||||
this.rootFrame.setText(this.strengthValue, heroData.getStrength().getDisplayText());
|
||||
this.rootFrame.setText(this.agilityValue, heroData.getAgility().getDisplayText());
|
||||
this.rootFrame.setText(this.intelligenceValue, heroData.getIntelligence().getDisplayText());
|
||||
final String infopanelLevelClass = this.rootFrame.getTemplates()
|
||||
.getDecoratedString("INFOPANEL_LEVEL_CLASS").replace("%u", "%d"); // :(
|
||||
final int heroLevel = heroData.getHeroLevel();
|
||||
this.rootFrame.setText(this.simpleClassValue,
|
||||
String.format(infopanelLevelClass, heroLevel, unitTypeName));
|
||||
this.rootFrame.setText(this.simpleNameValue, heroData.getProperName());
|
||||
this.simpleHeroLevelBar.setVisible(true);
|
||||
final CGameplayConstants gameplayConstants = this.war3MapViewer.simulation.getGameplayConstants();
|
||||
this.simpleHeroLevelBar.setValue((heroData.getXp() - gameplayConstants.getNeedHeroXPSum(heroLevel - 1))
|
||||
/ (float) gameplayConstants.getNeedHeroXP(heroLevel));
|
||||
}
|
||||
else {
|
||||
this.rootFrame.setText(this.simpleNameValue, unitTypeName);
|
||||
String classText = null;
|
||||
for (final CUnitClassification classification : simulationUnit.getClassifications()) {
|
||||
if ((classification == CUnitClassification.MECHANICAL)
|
||||
&& simulationUnit.getUnitType().isBuilding()) {
|
||||
// buildings dont display MECHANICAL
|
||||
continue;
|
||||
}
|
||||
if (classification.getDisplayName() != null) {
|
||||
classText = classification.getDisplayName();
|
||||
}
|
||||
}
|
||||
if (classText != null) {
|
||||
this.rootFrame.setText(this.simpleClassValue, classText);
|
||||
}
|
||||
else {
|
||||
this.rootFrame.setText(this.simpleClassValue, "");
|
||||
}
|
||||
this.simpleHeroLevelBar.setVisible(false);
|
||||
}
|
||||
|
||||
localArmorIcon.setVisible(!constructing);
|
||||
this.simpleBuildTimeIndicator.setVisible(constructing);
|
||||
this.simpleBuildingBuildTimeIndicator.setVisible(false);
|
||||
@ -1574,13 +1670,13 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.rootFrame.setText(this.simpleBuildingActionLabel,
|
||||
this.rootFrame.getTemplates().getDecoratedString("CONSTRUCTING"));
|
||||
this.queueIconFrames[0].setVisible(true);
|
||||
this.queueIconFrames[0].setTexture(this.war3MapViewer.getAbilityDataUI()
|
||||
.getUnitUI(this.selectedUnit.getSimulationUnit().getTypeId()).getIcon());
|
||||
this.queueIconFrames[0].setTexture(
|
||||
this.war3MapViewer.getAbilityDataUI().getUnitUI(simulationUnit.getTypeId()).getIcon());
|
||||
|
||||
if (this.selectedUnit.getSimulationUnit().getWorkerInside() != null) {
|
||||
if (simulationUnit.getWorkerInside() != null) {
|
||||
this.selectWorkerInsideFrame.setVisible(true);
|
||||
this.selectWorkerInsideFrame.setTexture(this.war3MapViewer.getAbilityDataUI()
|
||||
.getUnitUI(this.selectedUnit.getSimulationUnit().getWorkerInside().getTypeId()).getIcon());
|
||||
.getUnitUI(simulationUnit.getWorkerInside().getTypeId()).getIcon());
|
||||
}
|
||||
else {
|
||||
this.selectWorkerInsideFrame.setVisible(false);
|
||||
@ -1596,7 +1692,18 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
throw new RuntimeException(simulationUnit.getUnitType().getDefenseType() + " can't find texture!");
|
||||
}
|
||||
localArmorIconBackdrop.setTexture(defenseTexture);
|
||||
this.rootFrame.setText(localArmorInfoPanelIconValue, Integer.toString(simulationUnit.getDefense()));
|
||||
|
||||
String defenseDisplayString = Integer.toString(simulationUnit.getCurrentDefenseDisplay());
|
||||
final int temporaryDefenseBonus = simulationUnit.getTemporaryDefenseBonus();
|
||||
if (temporaryDefenseBonus != 0) {
|
||||
if (temporaryDefenseBonus > 0) {
|
||||
defenseDisplayString += "|cFF00FF00 (+" + temporaryDefenseBonus + ")";
|
||||
}
|
||||
else {
|
||||
defenseDisplayString += "|cFFFF0000 (+" + temporaryDefenseBonus + ")";
|
||||
}
|
||||
}
|
||||
this.rootFrame.setText(localArmorInfoPanelIconValue, defenseDisplayString);
|
||||
}
|
||||
clearAndRepopulateCommandCard();
|
||||
}
|
||||
@ -1753,6 +1860,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void heroStatsChanged() {
|
||||
reloadSelectedUnitUI(this.selectedUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueChanged() {
|
||||
reloadSelectedUnitUI(this.selectedUnit);
|
||||
@ -2191,4 +2303,10 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
this.unitOrderListener.unitCancelTrainingItem(simulationUnit.getHandleId(), index);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (this.rootFrame != null) {
|
||||
this.rootFrame.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,37 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
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.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||
import com.etheller.warsmash.WarsmashGdxMapScreen;
|
||||
import com.etheller.warsmash.WarsmashGdxMenuScreen;
|
||||
import com.etheller.warsmash.WarsmashGdxMultiScreenGame;
|
||||
import com.etheller.warsmash.datasources.DataSource;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||
import com.etheller.warsmash.units.DataTable;
|
||||
import com.etheller.warsmash.units.custom.WTS;
|
||||
import com.etheller.warsmash.util.WarsmashConstants;
|
||||
import com.etheller.warsmash.util.WorldEditStrings;
|
||||
import com.etheller.warsmash.viewer5.Scene;
|
||||
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.sound.KeyedSounds;
|
||||
|
||||
public class MenuUI {
|
||||
private static final Vector2 screenCoordsVector = new Vector2();
|
||||
@ -25,7 +39,6 @@ public class MenuUI {
|
||||
private final DataSource dataSource;
|
||||
private final Scene uiScene;
|
||||
private final ExtendViewport uiViewport;
|
||||
private final FreeTypeFontGenerator fontGenerator;
|
||||
private final MdxViewer viewer;
|
||||
private final RootFrameListener rootFrameListener;
|
||||
private final float widthRatioCorrection;
|
||||
@ -33,20 +46,61 @@ public class MenuUI {
|
||||
private GameUI rootFrame;
|
||||
private SpriteFrame cursorFrame;
|
||||
|
||||
private ClickableFrame mouseDownUIFrame;
|
||||
private ClickableFrame mouseOverUIFrame;
|
||||
|
||||
private UIFrame mainMenuFrame;
|
||||
|
||||
private SpriteFrame glueSpriteLayerTopRight;
|
||||
|
||||
private SpriteFrame glueSpriteLayerTopLeft;
|
||||
|
||||
public MenuUI(final DataSource dataSource, final ExtendViewport uiViewport,
|
||||
final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final MdxViewer viewer,
|
||||
private WorldEditStrings worldEditStrings;
|
||||
|
||||
private DataTable uiSoundsTable;
|
||||
|
||||
private KeyedSounds uiSounds;
|
||||
|
||||
private GlueTextButtonFrame singlePlayerButton;
|
||||
private GlueTextButtonFrame battleNetButton;
|
||||
private GlueTextButtonFrame localAreaNetworkButton;
|
||||
private GlueTextButtonFrame optionsButton;
|
||||
private GlueTextButtonFrame creditsButton;
|
||||
private GlueButtonFrame realmButton;
|
||||
private GlueTextButtonFrame exitButton;
|
||||
|
||||
private final boolean quitting = false;
|
||||
|
||||
private MenuState menuState;
|
||||
|
||||
private UIFrame singlePlayerMenu;
|
||||
|
||||
private UIFrame profilePanel;
|
||||
|
||||
private GlueButtonFrame profileButton;
|
||||
private GlueTextButtonFrame campaignButton;
|
||||
private GlueTextButtonFrame loadSavedButton;
|
||||
private GlueTextButtonFrame viewReplayButton;
|
||||
private GlueTextButtonFrame customCampaignButton;
|
||||
private GlueTextButtonFrame skirmishButton;
|
||||
private GlueTextButtonFrame cancelButton;
|
||||
private GlueButtonFrame editionButton;
|
||||
|
||||
private final WarsmashGdxMultiScreenGame screenManager;
|
||||
|
||||
private final DataTable warsmashIni;
|
||||
|
||||
private UnitSound glueScreenLoop;
|
||||
|
||||
public MenuUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene,
|
||||
final MdxViewer viewer, final WarsmashGdxMultiScreenGame screenManager, final DataTable warsmashIni,
|
||||
final RootFrameListener rootFrameListener) {
|
||||
this.dataSource = dataSource;
|
||||
this.uiViewport = uiViewport;
|
||||
this.fontGenerator = fontGenerator;
|
||||
this.uiScene = uiScene;
|
||||
this.viewer = viewer;
|
||||
this.screenManager = screenManager;
|
||||
this.warsmashIni = warsmashIni;
|
||||
this.rootFrameListener = rootFrameListener;
|
||||
|
||||
this.widthRatioCorrection = this.uiViewport.getMinWorldWidth() / 1600f;
|
||||
@ -65,8 +119,9 @@ public class MenuUI {
|
||||
// =================================
|
||||
// Load skins and templates
|
||||
// =================================
|
||||
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, 1), this.uiViewport,
|
||||
this.fontGenerator, this.uiScene, this.viewer, 0, WTS.DO_NOTHING);
|
||||
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, WarsmashConstants.GAME_VERSION),
|
||||
this.uiViewport, this.uiScene, this.viewer, 0, WTS.DO_NOTHING);
|
||||
|
||||
this.rootFrameListener.onCreate(this.rootFrame);
|
||||
try {
|
||||
this.rootFrame.loadTOCFile("UI\\FrameDef\\FrameDef.toc");
|
||||
@ -80,23 +135,31 @@ public class MenuUI {
|
||||
catch (final IOException exc) {
|
||||
throw new IllegalStateException("Unable to load SmashFrameDef.toc", exc);
|
||||
}
|
||||
|
||||
// Create main menu
|
||||
this.mainMenuFrame = this.rootFrame.createFrame("MainMenuFrame", this.rootFrame, 0, 0);
|
||||
this.mainMenuFrame.setVisible(false);
|
||||
|
||||
final SpriteFrame warcraftIIILogo = (SpriteFrame) this.rootFrame.getFrameByName("WarCraftIIILogo", 0);
|
||||
this.rootFrame.setSpriteFrameModel(warcraftIIILogo, this.rootFrame.getSkinField("MainMenuLogo_V1"));
|
||||
this.rootFrame.setSpriteFrameModel(warcraftIIILogo,
|
||||
this.rootFrame.getSkinField("MainMenuLogo_V" + WarsmashConstants.GAME_VERSION));
|
||||
warcraftIIILogo.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this.mainMenuFrame, FramePoint.TOPLEFT,
|
||||
GameUI.convertX(this.uiViewport, 0.13f), GameUI.convertY(this.uiViewport, -0.08f)));
|
||||
this.rootFrame.getFrameByName("RealmSelect", 0).setVisible(false);
|
||||
|
||||
this.glueSpriteLayerTopRight = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
||||
"SmashGlueSpriteLayerTopRight", this.rootFrame, "", 0);
|
||||
this.glueSpriteLayerTopRight.setSetAllPoints(true);
|
||||
final String topRightModel = this.rootFrame.getSkinField("GlueSpriteLayerTopRight_V1");
|
||||
final String topRightModel = this.rootFrame
|
||||
.getSkinField("GlueSpriteLayerTopRight_V" + WarsmashConstants.GAME_VERSION);
|
||||
this.rootFrame.setSpriteFrameModel(this.glueSpriteLayerTopRight, topRightModel);
|
||||
this.glueSpriteLayerTopRight.setSequence("MainMenu Birth");
|
||||
|
||||
this.glueSpriteLayerTopLeft = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE",
|
||||
"SmashGlueSpriteLayerTopLeft", this.rootFrame, "", 0);
|
||||
this.glueSpriteLayerTopLeft.setSetAllPoints(true);
|
||||
final String topLeftModel = this.rootFrame.getSkinField("GlueSpriteLayerTopLeft_V1");
|
||||
final String topLeftModel = this.rootFrame
|
||||
.getSkinField("GlueSpriteLayerTopLeft_V" + WarsmashConstants.GAME_VERSION);
|
||||
this.rootFrame.setSpriteFrameModel(this.glueSpriteLayerTopLeft, topLeftModel);
|
||||
this.glueSpriteLayerTopLeft.setSequence("MainMenu Birth");
|
||||
|
||||
@ -107,15 +170,126 @@ public class MenuUI {
|
||||
this.cursorFrame.setZDepth(-1.0f);
|
||||
Gdx.input.setCursorCatched(true);
|
||||
|
||||
// Create single player
|
||||
this.singlePlayerMenu = this.rootFrame.createFrame("SinglePlayerMenu", this.rootFrame, 0, 0);
|
||||
this.singlePlayerMenu.setVisible(false);
|
||||
|
||||
this.profilePanel = this.rootFrame.getFrameByName("ProfilePanel", 0);
|
||||
this.profilePanel.setVisible(false);
|
||||
|
||||
// position all
|
||||
this.rootFrame.positionBounds(this.rootFrame, this.uiViewport);
|
||||
|
||||
// Main Menu
|
||||
this.singlePlayerButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("SinglePlayerButton", 0);
|
||||
this.battleNetButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("BattleNetButton", 0);
|
||||
this.realmButton = (GlueButtonFrame) this.rootFrame.getFrameByName("RealmButton", 0);
|
||||
this.localAreaNetworkButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("LocalAreaNetworkButton", 0);
|
||||
this.optionsButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("OptionsButton", 0);
|
||||
this.creditsButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("CreditsButton", 0);
|
||||
this.exitButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("ExitButton", 0);
|
||||
this.editionButton = (GlueButtonFrame) this.rootFrame.getFrameByName("EditionButton", 0);
|
||||
|
||||
if (this.editionButton != null) {
|
||||
this.editionButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WarsmashConstants.GAME_VERSION = (WarsmashConstants.GAME_VERSION == 1 ? 0 : 1);
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("MainMenu Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("MainMenu Death");
|
||||
MenuUI.this.mainMenuFrame.setVisible(false);
|
||||
MenuUI.this.menuState = MenuState.RESTARTING;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.battleNetButton.setEnabled(false);
|
||||
this.realmButton.setEnabled(false);
|
||||
this.localAreaNetworkButton.setEnabled(false);
|
||||
this.optionsButton.setEnabled(false);
|
||||
this.creditsButton.setEnabled(false);
|
||||
|
||||
this.exitButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("MainMenu Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("MainMenu Death");
|
||||
MenuUI.this.mainMenuFrame.setVisible(false);
|
||||
MenuUI.this.menuState = MenuState.QUITTING;
|
||||
}
|
||||
});
|
||||
|
||||
this.singlePlayerButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("MainMenu Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("MainMenu Death");
|
||||
MenuUI.this.mainMenuFrame.setVisible(false);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_SINGLE_PLAYER;
|
||||
}
|
||||
});
|
||||
|
||||
// Single Player
|
||||
this.profileButton = (GlueButtonFrame) this.rootFrame.getFrameByName("ProfileButton", 0);
|
||||
this.campaignButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("CampaignButton", 0);
|
||||
this.loadSavedButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("LoadSavedButton", 0);
|
||||
this.viewReplayButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("ViewReplayButton", 0);
|
||||
this.customCampaignButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("CustomCampaignButton", 0);
|
||||
this.skirmishButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("SkirmishButton", 0);
|
||||
|
||||
this.cancelButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("CancelButton", 0);
|
||||
|
||||
final StringFrame profileNameText = (StringFrame) this.rootFrame.getFrameByName("ProfileNameText", 0);
|
||||
this.rootFrame.setText(profileNameText, "WorldEdit");
|
||||
|
||||
this.profileButton.setEnabled(false);
|
||||
this.loadSavedButton.setEnabled(false);
|
||||
this.viewReplayButton.setEnabled(false);
|
||||
this.customCampaignButton.setEnabled(false);
|
||||
this.skirmishButton.setEnabled(false);
|
||||
|
||||
this.campaignButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("SinglePlayer Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("SinglePlayer Death");
|
||||
MenuUI.this.singlePlayerMenu.setVisible(false);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_CAMPAIGN;
|
||||
}
|
||||
});
|
||||
|
||||
this.cancelButton.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MenuUI.this.glueSpriteLayerTopLeft.setSequence("SinglePlayer Death");
|
||||
MenuUI.this.glueSpriteLayerTopRight.setSequence("SinglePlayer Death");
|
||||
MenuUI.this.singlePlayerMenu.setVisible(false);
|
||||
MenuUI.this.menuState = MenuState.GOING_TO_MAIN_MENU;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
this.menuState = MenuState.MAIN_MENU;
|
||||
|
||||
loadSounds();
|
||||
|
||||
final String glueLoopField = this.rootFrame.getSkinField("GlueScreenLoop_V" + WarsmashConstants.GAME_VERSION);
|
||||
this.glueScreenLoop = this.uiSounds.getSound(glueLoopField);
|
||||
this.glueScreenLoop.play(this.uiScene.audioContext, 0f, 0f, 0f);
|
||||
}
|
||||
|
||||
public void resize() {
|
||||
|
||||
}
|
||||
|
||||
public void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
||||
public void render(final SpriteBatch batch, final GlyphLayout glyphLayout) {
|
||||
final BitmapFont font = this.rootFrame.getFont();
|
||||
final BitmapFont font20 = this.rootFrame.getFont20();
|
||||
font.setColor(Color.YELLOW);
|
||||
final String fpsString = "FPS: " + Gdx.graphics.getFramesPerSecond();
|
||||
glyphLayout.setText(font, fpsString);
|
||||
font.draw(batch, fpsString, (this.uiViewport.getMinWorldWidth() - glyphLayout.width) / 2,
|
||||
1100 * this.heightRatioCorrection);
|
||||
this.rootFrame.render(batch, font20, glyphLayout);
|
||||
}
|
||||
|
||||
@ -143,7 +317,140 @@ public class MenuUI {
|
||||
this.cursorFrame.setSequence("Normal");
|
||||
|
||||
if (this.glueSpriteLayerTopRight.isSequenceEnded()) {
|
||||
this.glueSpriteLayerTopRight.setSequence("MainMenu Stand");
|
||||
switch (this.menuState) {
|
||||
case GOING_TO_MAIN_MENU:
|
||||
this.glueSpriteLayerTopLeft.setSequence("MainMenu Birth");
|
||||
this.glueSpriteLayerTopRight.setSequence("MainMenu Birth");
|
||||
this.menuState = MenuState.MAIN_MENU;
|
||||
break;
|
||||
case MAIN_MENU:
|
||||
this.mainMenuFrame.setVisible(true);
|
||||
this.glueSpriteLayerTopLeft.setSequence("MainMenu Stand");
|
||||
this.glueSpriteLayerTopRight.setSequence("MainMenu Stand");
|
||||
break;
|
||||
case GOING_TO_SINGLE_PLAYER:
|
||||
this.glueSpriteLayerTopLeft.setSequence("SinglePlayer Birth");
|
||||
this.glueSpriteLayerTopRight.setSequence("SinglePlayer Birth");
|
||||
this.menuState = MenuState.SINGLE_PLAYER;
|
||||
break;
|
||||
case SINGLE_PLAYER:
|
||||
this.singlePlayerMenu.setVisible(true);
|
||||
this.glueSpriteLayerTopLeft.setSequence("SinglePlayer Stand");
|
||||
this.glueSpriteLayerTopRight.setSequence("SinglePlayer Stand");
|
||||
break;
|
||||
case GOING_TO_CAMPAIGN:
|
||||
MenuUI.this.screenManager.setScreen(new WarsmashGdxMapScreen(MenuUI.this.warsmashIni,
|
||||
this.warsmashIni.get("Map").getField("FilePath")));
|
||||
break;
|
||||
case QUITTING:
|
||||
Gdx.app.exit();
|
||||
break;
|
||||
case RESTARTING:
|
||||
MenuUI.this.screenManager
|
||||
.setScreen(new WarsmashGdxMenuScreen(MenuUI.this.warsmashIni, this.screenManager));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean touchDown(final int screenX, final int screenY, final float worldScreenY, final int button) {
|
||||
screenCoordsVector.set(screenX, screenY);
|
||||
this.uiViewport.unproject(screenCoordsVector);
|
||||
final UIFrame clickedUIFrame = this.rootFrame.touchDown(screenCoordsVector.x, screenCoordsVector.y, button);
|
||||
if (clickedUIFrame != null) {
|
||||
if (clickedUIFrame instanceof ClickableFrame) {
|
||||
this.mouseDownUIFrame = (ClickableFrame) clickedUIFrame;
|
||||
this.mouseDownUIFrame.mouseDown(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean touchUp(final int screenX, final int screenY, final float worldScreenY, final int button) {
|
||||
screenCoordsVector.set(screenX, screenY);
|
||||
this.uiViewport.unproject(screenCoordsVector);
|
||||
final UIFrame clickedUIFrame = this.rootFrame.touchUp(screenCoordsVector.x, screenCoordsVector.y, button);
|
||||
if (this.mouseDownUIFrame != null) {
|
||||
if (clickedUIFrame == this.mouseDownUIFrame) {
|
||||
this.mouseDownUIFrame.onClick(button);
|
||||
this.uiSounds.getSound("GlueScreenClick").play(this.uiScene.audioContext, 0, 0, 0);
|
||||
}
|
||||
this.mouseDownUIFrame.mouseUp(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
this.mouseDownUIFrame = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean touchDragged(final int screenX, final int screenY, final float worldScreenY, final int pointer) {
|
||||
mouseMoved(screenX, screenY, worldScreenY);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mouseMoved(final int screenX, final int screenY, final float worldScreenY) {
|
||||
screenCoordsVector.set(screenX, screenY);
|
||||
this.uiViewport.unproject(screenCoordsVector);
|
||||
final UIFrame mousedUIFrame = this.rootFrame.getFrameChildUnderMouse(screenCoordsVector.x,
|
||||
screenCoordsVector.y);
|
||||
if (mousedUIFrame != this.mouseOverUIFrame) {
|
||||
if (this.mouseOverUIFrame != null) {
|
||||
this.mouseOverUIFrame.mouseExit(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
if (mousedUIFrame instanceof ClickableFrame) {
|
||||
this.mouseOverUIFrame = (ClickableFrame) mousedUIFrame;
|
||||
if (this.mouseOverUIFrame != null) {
|
||||
this.mouseOverUIFrame.mouseEnter(this.rootFrame, this.uiViewport);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.mouseOverUIFrame = null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void loadSounds() {
|
||||
this.worldEditStrings = new WorldEditStrings(this.dataSource);
|
||||
this.uiSoundsTable = new DataTable(this.worldEditStrings);
|
||||
try {
|
||||
try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("UI\\SoundInfo\\UISounds.slk")) {
|
||||
this.uiSoundsTable.readSLK(miscDataTxtStream);
|
||||
}
|
||||
try (InputStream miscDataTxtStream = this.dataSource
|
||||
.getResourceAsStream("UI\\SoundInfo\\AmbienceSounds.slk")) {
|
||||
this.uiSoundsTable.readSLK(miscDataTxtStream);
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.uiSounds = new KeyedSounds(this.uiSoundsTable, this.dataSource);
|
||||
}
|
||||
|
||||
public KeyedSounds getUiSounds() {
|
||||
return this.uiSounds;
|
||||
}
|
||||
|
||||
private static enum MenuState {
|
||||
GOING_TO_MAIN_MENU,
|
||||
MAIN_MENU,
|
||||
GOING_TO_SINGLE_PLAYER,
|
||||
SINGLE_PLAYER,
|
||||
GOING_TO_CAMPAIGN,
|
||||
CAMPAIGN,
|
||||
QUITTING,
|
||||
RESTARTING;
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
this.glueScreenLoop.stop();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (this.rootFrame != null) {
|
||||
this.rootFrame.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,14 @@ public class QueueIcon extends AbstractRenderableFrame implements ClickableActio
|
||||
positionBounds(gameUI, uiViewport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||
|
@ -2,13 +2,15 @@ package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
|
||||
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
|
||||
public interface ClickableActionFrame extends UIFrame {
|
||||
public interface ClickableActionFrame extends ClickableFrame {
|
||||
@Override
|
||||
void mouseDown(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
@Override
|
||||
void mouseUp(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
@Override
|
||||
void onClick(int button);
|
||||
|
||||
String getToolTip();
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
|
||||
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
|
||||
public interface ClickableFrame extends UIFrame {
|
||||
void mouseDown(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
void mouseUp(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
void mouseEnter(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
void mouseExit(final GameUI gameUI, final Viewport uiViewport);
|
||||
|
||||
void onClick(int button);
|
||||
}
|
@ -8,10 +8,10 @@ import com.hiveworkshop.rms.util.BinaryWriter;
|
||||
|
||||
public class MdlxTexture implements MdlxBlock {
|
||||
public enum WrapMode {
|
||||
REPEAT_BOTH(true, true),
|
||||
REPEAT_BOTH(false, false),
|
||||
WRAP_WIDTH(true, false),
|
||||
WRAP_HEIGHT(false, true),
|
||||
WRAP_BOTH(false, false);
|
||||
WRAP_BOTH(true, true);
|
||||
|
||||
private final boolean wrapWidth;
|
||||
private final boolean wrapHeight;
|
||||
|
@ -134,7 +134,13 @@ public class Flac {
|
||||
}
|
||||
|
||||
// Start writing WAV output file
|
||||
final int bytesPerSample = streamInfo.sampleDepth / 8;
|
||||
int bytesPerSample = streamInfo.sampleDepth / 8;
|
||||
final boolean needsDownscaleForLibgdx = bytesPerSample >= 3;
|
||||
int downsampleBytes = 0;
|
||||
if (needsDownscaleForLibgdx) {
|
||||
downsampleBytes = bytesPerSample - 2;
|
||||
bytesPerSample = 2;
|
||||
}
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(baos))) {
|
||||
// Header chunk
|
||||
@ -151,14 +157,17 @@ public class Flac {
|
||||
writeLittleInt32(out, streamInfo.sampleRate);
|
||||
writeLittleInt32(out, streamInfo.sampleRate * streamInfo.numChannels * bytesPerSample);
|
||||
writeLittleInt16(out, streamInfo.numChannels * bytesPerSample);
|
||||
writeLittleInt16(out, streamInfo.sampleDepth);
|
||||
writeLittleInt16(out, needsDownscaleForLibgdx ? 16 : streamInfo.sampleDepth);
|
||||
|
||||
// Audio data chunk ("data")
|
||||
out.writeInt(0x64617461); // "data"
|
||||
writeLittleInt32(out, sampleDataLen);
|
||||
for (int i = 0; i < samples[0].length; i++) {
|
||||
for (int j = 0; j < samples.length; j++) {
|
||||
final int val = samples[j][i];
|
||||
int val = samples[j][i];
|
||||
for (int k = 0; k < downsampleBytes; k++) {
|
||||
val = val >>> 8;
|
||||
}
|
||||
if (bytesPerSample == 1) {
|
||||
out.write(val + 128); // Convert to unsigned, as per WAV PCM conventions
|
||||
}
|
||||
|
@ -226,8 +226,8 @@ public class OpenALSound implements Sound {
|
||||
}
|
||||
|
||||
public long play(final float volume, final float pitch, final float x, final float y, final float z,
|
||||
final boolean is3DSound, final float maxDistance, final float refDistance) {
|
||||
final long id = play();
|
||||
final boolean is3DSound, final float maxDistance, final float refDistance, final boolean looping) {
|
||||
final long id = looping ? loop() : play();
|
||||
setPitch(id, pitch);
|
||||
setVolume(id, volume);
|
||||
setPosition(id, x, y, z, is3DSound, maxDistance, refDistance);
|
||||
|
@ -15,12 +15,15 @@ import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Graphics.DisplayMode;
|
||||
import com.badlogic.gdx.audio.Sound;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglNativesLoader;
|
||||
import com.etheller.warsmash.WarsmashGdxMapGame;
|
||||
import com.etheller.warsmash.WarsmashGdxMapScreen;
|
||||
import com.etheller.warsmash.WarsmashGdxMenuScreen;
|
||||
import com.etheller.warsmash.WarsmashGdxMultiScreenGame;
|
||||
import com.etheller.warsmash.audio.OpenALSound;
|
||||
import com.etheller.warsmash.units.DataTable;
|
||||
import com.etheller.warsmash.util.StringBundle;
|
||||
@ -40,21 +43,40 @@ public class DesktopLauncher {
|
||||
config.gles30ContextMajorVersion = 3;
|
||||
config.gles30ContextMinorVersion = 3;
|
||||
// config.samples = 16;
|
||||
// config.vSyncEnabled = false;
|
||||
// config.foregroundFPS = 0;
|
||||
// config.backgroundFPS = 0;
|
||||
config.vSyncEnabled = false;
|
||||
config.foregroundFPS = 0;
|
||||
config.backgroundFPS = 0;
|
||||
final DisplayMode desktopDisplayMode = LwjglApplicationConfiguration.getDesktopDisplayMode();
|
||||
config.width = desktopDisplayMode.width;
|
||||
config.height = desktopDisplayMode.height;
|
||||
if ((arg.length > 0) && "-windowed".equals(arg[0])) {
|
||||
config.fullscreen = false;
|
||||
}
|
||||
else {
|
||||
config.fullscreen = true;
|
||||
String fileToLoad = null;
|
||||
config.fullscreen = true;
|
||||
for (int argIndex = 0; argIndex < arg.length; argIndex++) {
|
||||
if ("-windowed".equals(arg[argIndex])) {
|
||||
config.fullscreen = false;
|
||||
}
|
||||
else if ((arg.length > (argIndex + 1)) && "-loadfile".equals(arg[argIndex])) {
|
||||
argIndex++;
|
||||
fileToLoad = arg[argIndex];
|
||||
}
|
||||
}
|
||||
loadExtensions();
|
||||
final DataTable warsmashIni = loadWarsmashIni();
|
||||
new LwjglApplication(new WarsmashGdxMapGame(warsmashIni), config);
|
||||
final WarsmashGdxMultiScreenGame warsmashGdxMultiScreenGame = new WarsmashGdxMultiScreenGame();
|
||||
new LwjglApplication(warsmashGdxMultiScreenGame, config);
|
||||
final String finalFileToLoad = fileToLoad;
|
||||
Gdx.app.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (finalFileToLoad != null) {
|
||||
warsmashGdxMultiScreenGame.setScreen(new WarsmashGdxMapScreen(warsmashIni, finalFileToLoad));
|
||||
}
|
||||
else {
|
||||
warsmashGdxMultiScreenGame
|
||||
.setScreen(new WarsmashGdxMenuScreen(warsmashIni, warsmashGdxMultiScreenGame));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static DataTable loadWarsmashIni() {
|
||||
@ -123,8 +145,9 @@ public class DesktopLauncher {
|
||||
|
||||
@Override
|
||||
public void play(final Sound buffer, final float volume, final float pitch, final float x, final float y,
|
||||
final float z, final boolean is3dSound, final float maxDistance, final float refDistance) {
|
||||
((OpenALSound) buffer).play(volume, pitch, x, y, z, is3dSound, maxDistance, refDistance);
|
||||
final float z, final boolean is3dSound, final float maxDistance, final float refDistance,
|
||||
final boolean looping) {
|
||||
((OpenALSound) buffer).play(volume, pitch, x, y, z, is3dSound, maxDistance, refDistance, looping);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,7 +6,7 @@ import javax.swing.JFrame;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.WindowConstants;
|
||||
|
||||
import com.etheller.warsmash.WarsmashGdxMapGame;
|
||||
import com.etheller.warsmash.WarsmashGdxMapScreen;
|
||||
import com.etheller.warsmash.datasources.DataSource;
|
||||
import com.etheller.warsmash.desktop.DesktopLauncher;
|
||||
import com.etheller.warsmash.parsers.w3x.War3Map;
|
||||
@ -16,7 +16,7 @@ import com.etheller.warsmash.units.DataTable;
|
||||
public class TerrainView {
|
||||
public static void main(final String[] args) {
|
||||
final DataTable warsmashIni = DesktopLauncher.loadWarsmashIni();
|
||||
final DataSource dataSources = WarsmashGdxMapGame.parseDataSources(warsmashIni);
|
||||
final DataSource dataSources = WarsmashGdxMapScreen.parseDataSources(warsmashIni);
|
||||
final War3Map war3Map = new War3Map(dataSources, warsmashIni.get("Map").getField("FilePath"));
|
||||
try {
|
||||
final War3MapW3e environmentFile = war3Map.readEnvironment();
|
||||
|
@ -135,16 +135,19 @@ public class FrameDefinitionFieldVisitor extends FDFBaseVisitor<Void> {
|
||||
|
||||
@Override
|
||||
public Void visitFontElement(final FontElementContext ctx) {
|
||||
this.frameDefinition.set(ctx.ID().getText(),
|
||||
new FontFrameDefinitionField(new FontDefinition(ctx.STRING_LITERAL(0).getText(),
|
||||
Float.parseFloat(ctx.FLOAT().getText()), ctx.STRING_LITERAL(1).getText())));
|
||||
String text = ctx.STRING_LITERAL(0).getText();
|
||||
text = text.substring(1, text.length() - 1);
|
||||
this.frameDefinition.set(ctx.ID().getText(), new FontFrameDefinitionField(
|
||||
new FontDefinition(text, Float.parseFloat(ctx.FLOAT().getText()), ctx.STRING_LITERAL(1).getText())));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSimpleFontElement(final SimpleFontElementContext ctx) {
|
||||
this.frameDefinition.set(ctx.ID().getText(), new FontFrameDefinitionField(
|
||||
new FontDefinition(ctx.STRING_LITERAL().getText(), Float.parseFloat(ctx.FLOAT().getText()), null)));
|
||||
String text = ctx.STRING_LITERAL().getText();
|
||||
text = text.substring(1, text.length() - 1);
|
||||
this.frameDefinition.set(ctx.ID().getText(),
|
||||
new FontFrameDefinitionField(new FontDefinition(text, Float.parseFloat(ctx.FLOAT().getText()), null)));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,19 @@
|
||||
package com.etheller.warsmash.parsers.fdf.datamodel;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum ControlStyle {
|
||||
AUTOTRACK,
|
||||
HIGHLIGHTONFOCUS,
|
||||
HIGHLIGHTONMOUSEOVER;
|
||||
|
||||
public static EnumSet<ControlStyle> parseControlStyle(final String controlStyles) {
|
||||
final EnumSet<ControlStyle> set = EnumSet.noneOf(ControlStyle.class);
|
||||
for (final String flag : controlStyles.split("\\|")) {
|
||||
if (!"".equals(flag)) {
|
||||
set.add(ControlStyle.valueOf(flag));
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
@ -1,447 +0,0 @@
|
||||
|
||||
// --- 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",
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user