Begin transition into entity3 package along with new Animation class

This commit is contained in:
Collin Smith
2019-01-25 17:01:35 -08:00
parent 8cea13273e
commit e6e10705c5
29 changed files with 1833 additions and 415 deletions

View File

@ -174,6 +174,12 @@ project(":core") {
compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
compile group: 'com.jcraft', name: 'jzlib', version: '1.1.3'
}
dependencies {
testCompile 'junit:junit:4.12'
testCompile "com.badlogicgames.gdx:gdx-backend-headless:1.9.9"
testCompile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
}
}
project(":server") {

View File

@ -4,6 +4,7 @@ sourceCompatibility = 1.7
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceSets.main.java.srcDirs = [ "src/" ]
sourceSets.test.java.srcDirs = [ "test/" ]
eclipse.project {

View File

@ -31,7 +31,7 @@ public class Char {
public String armType;
public float angle;
public Animation.COFAnimation animation;
public Animation animation;
public Char(CharClass charClass) {
this.charClass = charClass;
@ -115,7 +115,7 @@ public class Char {
// FIXME: dispose/unload old animation layer
//if (animation != null) animation.dispose();
Animation oldAnim = animation;
animation = new Animation.COFAnimation(cof);
animation = Animation.newAnimation(cof);
if (oldAnim != null) animation.setDirection(oldAnim.getDirection());
String helm = "cap";

View File

@ -2,8 +2,6 @@ package gdx.diablo.codec;
import com.google.common.base.Preconditions;
import android.support.annotation.Nullable;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
@ -12,9 +10,9 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Affine2;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import gdx.diablo.BlendMode;
@ -22,64 +20,108 @@ import gdx.diablo.Diablo;
import gdx.diablo.codec.util.BBox;
import gdx.diablo.graphics.PaletteIndexedBatch;
public abstract class Animation extends BaseDrawable {
public class Animation extends BaseDrawable {
private static final String TAG = "Animation";
private static final int NUM_LAYERS = 16;
private static final float FRAMES_PER_SECOND = 25f;
private static final float FRAME_DURATION = 1 / FRAMES_PER_SECOND;
final Bits dirs;
private final int numDirections;
private final int numFrames;
private static final Color SHADOW_TINT = new Color(0, 0, 0, 0.5f);
private static final Affine2 SHADOW_TRANSFORM = new Affine2();
private int numDirections;
private int numFrames;
private int direction;
private int frame;
private boolean looping;
private float frameDuration;
private float elapsedTime;
private Layer layers[];
private COF cof;
private boolean drawShadow;
//private Bits cache[];
private final CopyOnWriteArraySet<AnimationListener> ANIMATION_LISTENERS;
private final Set<AnimationListener> ANIMATION_LISTENERS;
public Animation(int directions, int framesPerDir) {
this(directions, framesPerDir, 0, new Bits());
}
public Animation(int directions, int framesPerDir, int d) {
this(directions, framesPerDir, d, new Bits());
Animation() {
this(0, 0, new Layer[NUM_LAYERS]);
}
public Animation(int directions, int framesPerDir, int d, Bits dirs) {
Animation(int directions, int framesPerDir) {
this(directions, framesPerDir, new Layer[NUM_LAYERS]);
}
Animation(int directions, int framesPerDir, Layer[] layers) {
numDirections = directions;
numFrames = framesPerDir;
this.dirs = dirs;
this.layers = layers;
looping = true;
drawShadow = false;
frameDuration = FRAME_DURATION;
ANIMATION_LISTENERS = new CopyOnWriteArraySet<>();
dirs.set(d);
}
public static Animation newAnimation(Layer layer) {
return new AnimationImpl(layer);
public static Animation newAnimation(DC dc) {
return Animation.builder().layer(dc).build();
}
public static Animation newAnimation(DC anim) {
return new AnimationImpl(anim);
public static Animation newAnimation(COF cof) {
Animation animation = new Animation();
animation.reset(cof);
return animation;
}
public static Animation newAnimation(DC anim, int d) {
return new AnimationImpl(anim, d);
public boolean reset(COF cof) {
if (this.cof != cof) {
this.cof = cof;
numDirections = cof.getNumDirections();
numFrames = cof.getNumFramesPerDir();
drawShadow = true;
setFrameDelta(cof.getAnimRate());
if (direction >= numDirections) direction = 0;
if (frame >= numFrames) {
frame = 0;
elapsedTime = 0;
}
return true;
}
return false;
}
protected void loadAll() {
for (int d = dirs.nextSetBit(0); d >= 0; d = dirs.nextSetBit(d + 1)) {
load(d);
public static Builder builder() {
return new Builder();
}
//protected void loadAll() {
// for (int d = dirs.nextSetBit(0); d >= 0; d = dirs.nextSetBit(d + 1)) {
// load(d);
// }
//}
protected void load(int d) {
for (Layer l : layers) if (l != null) l.load(d);
}
public Animation setLayer(int component, DC dc) {
layers[component] = dc != null ? new Layer(dc).load(direction) : null;
return this;
}
public Layer getLayer(int component) {
return layers[component];
}
public void setShadow(boolean b) {
if (b != drawShadow) {
drawShadow = b;
}
}
protected abstract void load(int d);
public int getNumDirections() {
return numDirections;
}
@ -95,7 +137,7 @@ public abstract class Animation extends BaseDrawable {
public void setDirection(int d) {
if (d != direction) {
Preconditions.checkArgument(0 <= d && d < numDirections, "Invalid direction: " + d);
if (!dirs.get(d)) load(d);
load(d);
direction = d;
}
}
@ -152,13 +194,121 @@ public abstract class Animation extends BaseDrawable {
if (frame == numFrames - 1) notifyAnimationFinished();
}
public void drawDebug(ShapeRenderer shapes, float x, float y) {
if (cof == null) {
boolean reset = !shapes.isDrawing();
if (reset) {
shapes.begin(ShapeRenderer.ShapeType.Line);
} else {
shapes.set(ShapeRenderer.ShapeType.Line);
}
shapes.setColor(Color.RED);
shapes.line(x, y, x + 50, y);
shapes.setColor(Color.GREEN);
shapes.line(x, y, x, y + 50);
shapes.setColor(Color.BLUE);
shapes.line(x, y, x + 15, y - 20);
BBox box = getBox();
shapes.setColor(layers[0].DEBUG_COLOR);
shapes.rect(x + box.xMin, y - box.yMax, box.width, box.height);
if (reset) {
shapes.end();
}
} else {
int d = DC.Direction.toReadDir(direction, cof.getNumDirections());
int f = frame;
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers[component];
if (layer != null) layer.drawDebug(shapes, d, f, x, y);
}
}
}
public void draw(Batch batch, float x, float y) {
draw(batch, x, y, getMinWidth(), getMinHeight());
}
public abstract void drawDebug(ShapeRenderer shapes, float x, float y);
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
draw((PaletteIndexedBatch) batch, x, y);
}
public abstract BBox getBox();
public void draw(PaletteIndexedBatch batch, float x, float y) {
if (cof == null) {
if (drawShadow) {
for (Layer layer : layers) {
if (layer == null) continue;
drawShadow(batch, layer, x, y);
}
batch.resetBlendMode();
}
for (Layer layer : layers) {
if (layer == null) continue;
drawLayer(batch, layer, x, y);
}
batch.resetBlendMode();
batch.resetColormap();
} else {
int d = DC.Direction.toReadDir(direction, cof.getNumDirections());
int f = frame;
if (drawShadow) {
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers[component];
if (layer != null) {
COF.Layer cofLayer = cof.getComponent(component);
if (cofLayer.shadow == 0x1) {
drawShadow(batch, layer, x, y);
}
}
}
batch.resetBlendMode();
}
// TODO: Layer blend modes should correspond with the cof trans levels
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers[component];
if (layer != null) drawLayer(batch, layer, x, y);
}
batch.resetBlendMode();
batch.resetColormap();
}
}
public void drawShadow(PaletteIndexedBatch batch, Layer layer, float x, float y) {
int d = direction;
int f = frame;
DC dc = layer.dc;
BBox box = dc.getBox(d, f);
SHADOW_TRANSFORM.idt();
SHADOW_TRANSFORM.preTranslate(box.xMin, -(box.yMax / 2));
SHADOW_TRANSFORM.preShear(-1.0f, 0);
SHADOW_TRANSFORM.preTranslate(x, y);
SHADOW_TRANSFORM.scale(1, 0.5f);
if (layer.regions[d] == null) layer.load(d);
TextureRegion region = layer.regions[d][f];
batch.setBlendMode(BlendMode.TINT_BLACKS, SHADOW_TINT);
batch.draw(region, region.getRegionWidth(), region.getRegionHeight(), SHADOW_TRANSFORM);
}
public void drawLayer(PaletteIndexedBatch batch, Layer layer, float x, float y) {
layer.draw(batch, direction, frame, x, y);
}
public BBox getBox() {
return cof == null
? layers[0].dc.getDirection(direction).box
: cof.box;
}
@Override
public float getMinWidth() {
@ -170,10 +320,6 @@ public abstract class Animation extends BaseDrawable {
return getBox().height;
}
public CompositeAnimation composite() {
throw new UnsupportedOperationException();
}
private void notifyAnimationFinished() {
for (AnimationListener l : ANIMATION_LISTENERS) {
l.onFinished(this);
@ -185,11 +331,11 @@ public abstract class Animation extends BaseDrawable {
return ANIMATION_LISTENERS.add(l);
}
public boolean removeAnimationListener(@Nullable Object o) {
public boolean removeAnimationListener(Object o) {
return o != null && ANIMATION_LISTENERS.remove(o);
}
public boolean containsAnimationListener(@Nullable Object o) {
public boolean containsAnimationListener(Object o) {
return o != null && ANIMATION_LISTENERS.contains(o);
}
@ -198,35 +344,27 @@ public abstract class Animation extends BaseDrawable {
}
public static class Layer {
public static Layer from(DC anim) {
return new Layer(anim);
}
private final Color DEBUG_COLOR = new Color(MathUtils.random(), MathUtils.random(), MathUtils.random(), 1);
public static Layer from(DC anim, int blendMode) {
return new Layer(anim, blendMode);
}
final DC base;
final DC dc;
final TextureRegion regions[][];
final int numDirections;
final int numFrames;
int blendMode;
int blendMode;
Index transform;
int transformColor;
int transformColor;
private final Color DEBUG_COLOR = new Color(MathUtils.random(), MathUtils.random(), MathUtils.random(), 1);
Layer(DC anim) {
this(anim, BlendMode.ID);
Layer(DC dc) {
this(dc, BlendMode.ID);
}
Layer(DC anim, int blendMode) {
Layer(DC dc, int blendMode) {
this.dc = dc;
this.blendMode = blendMode;
numDirections = anim.getNumDirections();
numFrames = anim.getNumFramesPerDir();
base = anim;
numDirections = dc.getNumDirections();
numFrames = dc.getNumFramesPerDir();
regions = new TextureRegion[numDirections][];
transform = null;
transformColor = 0;
@ -242,10 +380,10 @@ public abstract class Animation extends BaseDrawable {
protected Layer load(int d) {
if (regions[d] != null) return this;
base.loadDirection(d);
dc.loadDirection(d);
regions[d] = new TextureRegion[numFrames];
for (int f = 0; f < numFrames; f++) {
regions[d][f] = base.getTexture(d, f);
regions[d][f] = dc.getTexture(d, f);
}
return this;
@ -256,7 +394,7 @@ public abstract class Animation extends BaseDrawable {
}
public void setTransform(Index colormap, int id) {
//if ( colormap != null) System.out.println("----> " + colormap + "; " + id);
//if (colormap != null) System.out.println("----> " + colormap + "; " + id);
transform = colormap;
transformColor = colormap == null ? 0 : id;
}
@ -269,28 +407,8 @@ public abstract class Animation extends BaseDrawable {
}
}
/*
public void setTransform(byte packedTransform) {
if ((packedTransform & 0xFF) == 0xFF) {
transform = 0;
transformColor = 0;
} else {
transform = packedTransform >>> 4;
transformColor = packedTransform & 0xF;
}
}
public void setTransform(int transform) {
this.transform = transform;
}
public void setTransformColor(int colorId) {
this.transformColor = colorId;
}
*/
protected void draw(Batch batch, int d, int f, float x, float y) {
BBox box = base.getBox(d, f);
BBox box = dc.getBox(d, f);
x += box.xMin;
y -= box.yMax;
if (regions[d] == null) load(d);
@ -315,7 +433,7 @@ public abstract class Animation extends BaseDrawable {
shapeRenderer.setColor(Color.BLUE);
shapeRenderer.line(x, y, x + 20, y - 10);
BBox box = base.getDirection(d).box;
BBox box = dc.getDirection(d).box;
shapeRenderer.setColor(DEBUG_COLOR);
shapeRenderer.rect(x + box.xMin, y - box.yMax, box.width, box.height);
@ -325,260 +443,26 @@ public abstract class Animation extends BaseDrawable {
}
}
public static class AnimationImpl extends Animation {
final Layer layer;
public static class Builder {
int size = 0;
Layer layers[] = new Layer[NUM_LAYERS];
AnimationImpl(DC base) {
super(base.getNumDirections(), base.getNumFramesPerDir());
layer = new Layer(base);
loadAll();
public Builder layer(DC dc) {
return layer(new Layer(dc));
}
AnimationImpl(DC base, int d) {
super(base.getNumDirections(), base.getNumFramesPerDir(), d);
layer = new Layer(base);
loadAll();
public Builder layer(DC dc, int blendMode) {
return layer(new Layer(dc, blendMode));
}
AnimationImpl(Layer layer) {
super(layer.numDirections, layer.numFrames);
this.layer = layer;
loadAll();
}
@Override
public CompositeAnimation composite() {
return new CompositeAnimation(this);
}
@Override
protected void load(int d) {
layer.load(d);
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
layer.draw(batch, getDirection(), getFrame(), x, y);
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
layer.drawDebug(shapes, getDirection(), getFrame(), x, y);
}
@Override
public BBox getBox() {
return layer.base.getDirection(getDirection()).box;
}
}
public static class CompositeAnimation extends Animation {
private static final Color SHADOW_TINT = new Color(0, 0, 0, 0.5f);
private static final Affine2 SHADOW_TRANSFORM = new Affine2();
static final int DEFAULT_LAYERS = 4;
final Array<Layer> layers;
public CompositeAnimation(Animation anim) {
super(anim.numDirections, anim.numFrames, anim.direction, anim.dirs);
layers = new Array<>(DEFAULT_LAYERS);
if (anim instanceof AnimationImpl) {
AnimationImpl impl = (AnimationImpl) anim;
layers.add(impl.layer);
} else if (anim instanceof CompositeAnimation) {
CompositeAnimation impl = (CompositeAnimation) anim;
layers.addAll(impl.layers);
} else {
throw new UnsupportedOperationException();
}
}
public CompositeAnimation(Layer base) {
super(base.numFrames, base.numDirections);
layers = new Array<>(DEFAULT_LAYERS);
addLayer(base);
}
public CompositeAnimation(Layer... layers) {
super(layers[0].numDirections, layers[0].numFrames);
this.layers = new Array<>(layers);
}
public CompositeAnimation(DC... anims) {
super(anims[0].getNumDirections(), anims[0].getNumFramesPerDir());
this.layers = new Array<>(anims.length);
for (DC anim : anims) addLayer(Layer.from(anim));
}
public CompositeAnimation(int directions, int framesPerDir, int numLayers) {
super(directions, framesPerDir);
layers = new Array<>(numLayers);
for (int i = 0; i < numLayers; i++) {
layers.add(null);
}
}
@Override
protected void load(int d) {
for (Layer l : layers) if (l != null) l.load(d);
}
public CompositeAnimation addAll(Layer[] layers) {
for (Layer layer : layers) addLayer(layer);
public Builder layer(Layer layer) {
layers[size++] = layer;
return this;
}
public CompositeAnimation addLayer(Layer layer) {
return addLayer(layer, layer.blendMode);
}
public CompositeAnimation addLayer(Layer layer, int blendMode) {
layer.blendMode = blendMode;
layers.add(layer.loadAll(dirs));
return this;
}
public CompositeAnimation setLayer(int layer, DC anim) {
layers.set(layer, new Layer(anim).loadAll(dirs));
return this;
}
public Layer getLayer(int i) {
return layers.get(i);
}
public void drawShadow(Batch batch, Layer layer, float x, float y) {
int d = getDirection();
int f = getFrame();
DC base = layer.base;
BBox box = base.getBox(d, f);
SHADOW_TRANSFORM.idt();
SHADOW_TRANSFORM.preTranslate(box.xMin, -(box.yMax / 2));
SHADOW_TRANSFORM.preShear(-1.0f, 0);
SHADOW_TRANSFORM.preTranslate(x, y);
SHADOW_TRANSFORM.scale(1, 0.5f);
if (layer.regions[d] == null) layer.load(d);
TextureRegion region = layer.regions[d][f];
((PaletteIndexedBatch) batch).setBlendMode(BlendMode.TINT_BLACKS, SHADOW_TINT);
batch.draw(region, region.getRegionWidth(), region.getRegionHeight(), SHADOW_TRANSFORM);
}
public void drawLayer(Batch batch, Layer layer, float x, float y) {
layer.draw(batch, getDirection(), getFrame(), x, y);
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
for (int i = 0; i < layers.size; i++) {
Layer layer = layers.get(i);
if (layer == null) {
continue;
}
drawLayer(batch, layer, x, y);
}
((PaletteIndexedBatch) batch).resetBlendMode();
((PaletteIndexedBatch) batch).resetColormap();
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
boolean reset = !shapes.isDrawing();
if (reset) {
shapes.begin(ShapeRenderer.ShapeType.Line);
} else {
shapes.set(ShapeRenderer.ShapeType.Line);
}
shapes.setColor(Color.RED);
shapes.line(x, y, x + 50, y);
shapes.setColor(Color.GREEN);
shapes.line(x, y, x, y + 50);
shapes.setColor(Color.BLUE);
shapes.line(x, y, x + 15, y - 20);
BBox box = getBox();
shapes.setColor(layers.first().DEBUG_COLOR);
shapes.rect(x + box.xMin, y - box.yMax, box.width, box.height);
if (reset) {
shapes.end();
}
}
@Override
public BBox getBox() {
return layers.first().base.getDirection(super.direction).box;
}
}
public static class COFAnimation extends CompositeAnimation {
final COF cof;
boolean drawShadow = true;
public COFAnimation(COF cof) {
// TODO: 15 needs to be a variable
super(cof.getNumDirections(), cof.getNumFramesPerDir(), 15);
this.cof = cof;
setFrameDelta(cof.getAnimRate());
}
public COF getCOF() {
return cof;
}
public void setShadow(boolean b) {
if (b != drawShadow) {
drawShadow = b;
}
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
int d = DC.Direction.toReadDir(getDirection(), cof.getNumDirections());
int f = getFrame();
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) {
COF.Layer cofLayer = cof.getComponent(component);
if (drawShadow && cofLayer.shadow == 0x1) {
drawShadow(batch, layer, x, y);
}
}
}
((PaletteIndexedBatch) batch).resetBlendMode();
// TODO: Layer blend modes should correspond with the cof trans levels
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) drawLayer(batch, layer, x, y);
}
((PaletteIndexedBatch) batch).resetBlendMode();
((PaletteIndexedBatch) batch).resetColormap();
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
int d = DC.Direction.toReadDir(getDirection(), cof.getNumDirections());
int f = getFrame();
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) layer.drawDebug(shapes, d, f, x, y);
}
}
@Override
public BBox getBox() {
return cof.box;
public Animation build() {
Layer first = layers[0];
return new Animation(first.numDirections, first.numFrames, layers);
}
}
}

View File

@ -0,0 +1,584 @@
package gdx.diablo.codec;
import com.google.common.base.Preconditions;
import android.support.annotation.Nullable;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Affine2;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import java.util.concurrent.CopyOnWriteArraySet;
import gdx.diablo.BlendMode;
import gdx.diablo.Diablo;
import gdx.diablo.codec.util.BBox;
import gdx.diablo.graphics.PaletteIndexedBatch;
public abstract class Animation extends BaseDrawable {
private static final String TAG = "Animation";
private static final float FRAMES_PER_SECOND = 25f;
private static final float FRAME_DURATION = 1 / FRAMES_PER_SECOND;
final Bits dirs;
private final int numDirections;
private final int numFrames;
private int direction;
private int frame;
private boolean looping;
private float frameDuration;
private float elapsedTime;
private final CopyOnWriteArraySet<AnimationListener> ANIMATION_LISTENERS;
public Animation(int directions, int framesPerDir) {
this(directions, framesPerDir, 0, new Bits());
}
public Animation(int directions, int framesPerDir, int d) {
this(directions, framesPerDir, d, new Bits());
}
public Animation(int directions, int framesPerDir, int d, Bits dirs) {
numDirections = directions;
numFrames = framesPerDir;
this.dirs = dirs;
looping = true;
frameDuration = FRAME_DURATION;
ANIMATION_LISTENERS = new CopyOnWriteArraySet<>();
dirs.set(d);
}
public static Animation newAnimation(Layer layer) {
return new AnimationImpl(layer);
}
public static Animation newAnimation(DC anim) {
return new AnimationImpl(anim);
}
public static Animation newAnimation(DC anim, int d) {
return new AnimationImpl(anim, d);
}
protected void loadAll() {
for (int d = dirs.nextSetBit(0); d >= 0; d = dirs.nextSetBit(d + 1)) {
load(d);
}
}
protected abstract void load(int d);
public int getNumDirections() {
return numDirections;
}
public int getNumFramesPerDir() {
return numFrames;
}
public int getDirection() {
return direction;
}
public void setDirection(int d) {
if (d != direction) {
Preconditions.checkArgument(0 <= d && d < numDirections, "Invalid direction: " + d);
if (!dirs.get(d)) load(d);
direction = d;
}
}
public int getFrame() {
return frame;
}
public void setFrame(int f) {
if (f != frame) {
Preconditions.checkArgument(0 <= f && f < numFrames, "Invalid frame: " + f);
frame = f;
elapsedTime = frameDuration * frame;
if (frame == numFrames - 1) notifyAnimationFinished();
}
}
public boolean isLooping() {
return looping;
}
public void setLooping(boolean b) {
looping = b;
}
public float getFrameDuration() {
return frameDuration;
}
public void setFrameDuration(float f) {
frameDuration = f;
elapsedTime = frameDuration * frame;
}
public void setFrameDelta(int delta) {
setFrameDuration(256f / (delta * FRAMES_PER_SECOND));
}
public int getKeyFrameIndex(float stateTime) {
if (numFrames == 1) return 0;
int frameNumber = (int) (stateTime / frameDuration);
return looping
? frameNumber % numFrames
: Math.min(numFrames - 1, frameNumber);
}
public void act() {
act(Gdx.graphics.getDeltaTime());
}
public void act(float delta) {
elapsedTime += delta;
frame = getKeyFrameIndex(elapsedTime);
if (frame == numFrames - 1) notifyAnimationFinished();
}
public void draw(Batch batch, float x, float y) {
draw(batch, x, y, getMinWidth(), getMinHeight());
}
public abstract void drawDebug(ShapeRenderer shapes, float x, float y);
public abstract BBox getBox();
@Override
public float getMinWidth() {
return getBox().width;
}
@Override
public float getMinHeight() {
return getBox().height;
}
public CompositeAnimation composite() {
throw new UnsupportedOperationException();
}
private void notifyAnimationFinished() {
for (AnimationListener l : ANIMATION_LISTENERS) {
l.onFinished(this);
}
}
public boolean addAnimationListener(AnimationListener l) {
Preconditions.checkArgument(l != null, "l cannot be null");
return ANIMATION_LISTENERS.add(l);
}
public boolean removeAnimationListener(@Nullable Object o) {
return o != null && ANIMATION_LISTENERS.remove(o);
}
public boolean containsAnimationListener(@Nullable Object o) {
return o != null && ANIMATION_LISTENERS.contains(o);
}
public interface AnimationListener {
void onFinished(Animation animation);
}
public static class Layer {
public static Layer from(DC anim) {
return new Layer(anim);
}
public static Layer from(DC anim, int blendMode) {
return new Layer(anim, blendMode);
}
final DC base;
final TextureRegion regions[][];
final int numDirections;
final int numFrames;
int blendMode;
Index transform;
int transformColor;
private final Color DEBUG_COLOR = new Color(MathUtils.random(), MathUtils.random(), MathUtils.random(), 1);
Layer(DC anim) {
this(anim, BlendMode.ID);
}
Layer(DC anim, int blendMode) {
this.blendMode = blendMode;
numDirections = anim.getNumDirections();
numFrames = anim.getNumFramesPerDir();
base = anim;
regions = new TextureRegion[numDirections][];
transform = null;
transformColor = 0;
}
protected Layer loadAll(Bits dirs) {
for (int d = dirs.nextSetBit(0); d >= 0; d = dirs.nextSetBit(d + 1)) {
load(d);
}
return this;
}
protected Layer load(int d) {
if (regions[d] != null) return this;
base.loadDirection(d);
regions[d] = new TextureRegion[numFrames];
for (int f = 0; f < numFrames; f++) {
regions[d][f] = base.getTexture(d, f);
}
return this;
}
public void setBlendMode(int blendMode) {
this.blendMode = blendMode;
}
public void setTransform(Index colormap, int id) {
//if ( colormap != null) System.out.println("----> " + colormap + "; " + id);
transform = colormap;
transformColor = colormap == null ? 0 : id;
}
public void setTransform(byte packedTransform) {
if ((packedTransform & 0xFF) == 0xFF) {
setTransform(null, 0);
} else {
setTransform(Diablo.colormaps.get(packedTransform >>> 5), packedTransform & 0x1F);
}
}
/*
public void setTransform(byte packedTransform) {
if ((packedTransform & 0xFF) == 0xFF) {
transform = 0;
transformColor = 0;
} else {
transform = packedTransform >>> 4;
transformColor = packedTransform & 0xF;
}
}
public void setTransform(int transform) {
this.transform = transform;
}
public void setTransformColor(int colorId) {
this.transformColor = colorId;
}
*/
protected void draw(Batch batch, int d, int f, float x, float y) {
BBox box = base.getBox(d, f);
x += box.xMin;
y -= box.yMax;
if (regions[d] == null) load(d);
PaletteIndexedBatch b = (PaletteIndexedBatch) batch;
b.setBlendMode(blendMode);
b.setColormap(transform, transformColor);
b.draw(regions[d][f], x, y);
}
protected void drawDebug(ShapeRenderer shapeRenderer, int d, int f, float x, float y) {
boolean reset = !shapeRenderer.isDrawing();
if (reset) {
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
} else {
shapeRenderer.set(ShapeRenderer.ShapeType.Line);
}
shapeRenderer.setColor(Color.RED);
shapeRenderer.line(x, y, x + 40, y);
shapeRenderer.setColor(Color.GREEN);
shapeRenderer.line(x, y, x, y + 20);
shapeRenderer.setColor(Color.BLUE);
shapeRenderer.line(x, y, x + 20, y - 10);
BBox box = base.getDirection(d).box;
shapeRenderer.setColor(DEBUG_COLOR);
shapeRenderer.rect(x + box.xMin, y - box.yMax, box.width, box.height);
if (reset) {
shapeRenderer.end();
}
}
}
public static class AnimationImpl extends Animation {
final Layer layer;
AnimationImpl(DC base) {
super(base.getNumDirections(), base.getNumFramesPerDir());
layer = new Layer(base);
loadAll();
}
AnimationImpl(DC base, int d) {
super(base.getNumDirections(), base.getNumFramesPerDir(), d);
layer = new Layer(base);
loadAll();
}
AnimationImpl(Layer layer) {
super(layer.numDirections, layer.numFrames);
this.layer = layer;
loadAll();
}
@Override
public CompositeAnimation composite() {
return new CompositeAnimation(this);
}
@Override
protected void load(int d) {
layer.load(d);
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
layer.draw(batch, getDirection(), getFrame(), x, y);
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
layer.drawDebug(shapes, getDirection(), getFrame(), x, y);
}
@Override
public BBox getBox() {
return layer.base.getDirection(getDirection()).box;
}
}
public static class CompositeAnimation extends Animation {
private static final Color SHADOW_TINT = new Color(0, 0, 0, 0.5f);
private static final Affine2 SHADOW_TRANSFORM = new Affine2();
static final int DEFAULT_LAYERS = 4;
final Array<Layer> layers;
public CompositeAnimation(Animation anim) {
super(anim.numDirections, anim.numFrames, anim.direction, anim.dirs);
layers = new Array<>(DEFAULT_LAYERS);
if (anim instanceof AnimationImpl) {
AnimationImpl impl = (AnimationImpl) anim;
layers.add(impl.layer);
} else if (anim instanceof CompositeAnimation) {
CompositeAnimation impl = (CompositeAnimation) anim;
layers.addAll(impl.layers);
} else {
throw new UnsupportedOperationException();
}
}
public CompositeAnimation(Layer base) {
super(base.numFrames, base.numDirections);
layers = new Array<>(DEFAULT_LAYERS);
addLayer(base);
}
public CompositeAnimation(Layer... layers) {
super(layers[0].numDirections, layers[0].numFrames);
this.layers = new Array<>(layers);
}
public CompositeAnimation(DC... anims) {
super(anims[0].getNumDirections(), anims[0].getNumFramesPerDir());
this.layers = new Array<>(anims.length);
for (DC anim : anims) addLayer(Layer.from(anim));
}
public CompositeAnimation(int directions, int framesPerDir, int numLayers) {
super(directions, framesPerDir);
layers = new Array<>(numLayers);
for (int i = 0; i < numLayers; i++) {
layers.add(null);
}
}
@Override
protected void load(int d) {
for (Layer l : layers) if (l != null) l.load(d);
}
public CompositeAnimation addAll(Layer[] layers) {
for (Layer layer : layers) addLayer(layer);
return this;
}
public CompositeAnimation addLayer(Layer layer) {
return addLayer(layer, layer.blendMode);
}
public CompositeAnimation addLayer(Layer layer, int blendMode) {
layer.blendMode = blendMode;
layers.add(layer.loadAll(dirs));
return this;
}
public CompositeAnimation setLayer(int layer, DC anim) {
layers.set(layer, new Layer(anim).loadAll(dirs));
return this;
}
public Layer getLayer(int i) {
return layers.get(i);
}
public void drawShadow(Batch batch, Layer layer, float x, float y) {
int d = getDirection();
int f = getFrame();
DC base = layer.base;
BBox box = base.getBox(d, f);
SHADOW_TRANSFORM.idt();
SHADOW_TRANSFORM.preTranslate(box.xMin, -(box.yMax / 2));
SHADOW_TRANSFORM.preShear(-1.0f, 0);
SHADOW_TRANSFORM.preTranslate(x, y);
SHADOW_TRANSFORM.scale(1, 0.5f);
if (layer.regions[d] == null) layer.load(d);
TextureRegion region = layer.regions[d][f];
((PaletteIndexedBatch) batch).setBlendMode(BlendMode.TINT_BLACKS, SHADOW_TINT);
batch.draw(region, region.getRegionWidth(), region.getRegionHeight(), SHADOW_TRANSFORM);
}
public void drawLayer(Batch batch, Layer layer, float x, float y) {
layer.draw(batch, getDirection(), getFrame(), x, y);
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
for (int i = 0; i < layers.size; i++) {
Layer layer = layers.get(i);
if (layer == null) {
continue;
}
drawLayer(batch, layer, x, y);
}
((PaletteIndexedBatch) batch).resetBlendMode();
((PaletteIndexedBatch) batch).resetColormap();
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
boolean reset = !shapes.isDrawing();
if (reset) {
shapes.begin(ShapeRenderer.ShapeType.Line);
} else {
shapes.set(ShapeRenderer.ShapeType.Line);
}
shapes.setColor(Color.RED);
shapes.line(x, y, x + 50, y);
shapes.setColor(Color.GREEN);
shapes.line(x, y, x, y + 50);
shapes.setColor(Color.BLUE);
shapes.line(x, y, x + 15, y - 20);
BBox box = getBox();
shapes.setColor(layers.first().DEBUG_COLOR);
shapes.rect(x + box.xMin, y - box.yMax, box.width, box.height);
if (reset) {
shapes.end();
}
}
@Override
public BBox getBox() {
return layers.first().base.getDirection(super.direction).box;
}
}
public static class COFAnimation extends CompositeAnimation {
final COF cof;
boolean drawShadow = true;
public COFAnimation(COF cof) {
// TODO: 15 needs to be a variable
super(cof.getNumDirections(), cof.getNumFramesPerDir(), 15);
this.cof = cof;
setFrameDelta(cof.getAnimRate());
}
public COF getCOF() {
return cof;
}
public void setShadow(boolean b) {
if (b != drawShadow) {
drawShadow = b;
}
}
@Override
public void draw(Batch batch, float x, float y, float width, float height) {
int d = DC.Direction.toReadDir(getDirection(), cof.getNumDirections());
int f = getFrame();
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) {
COF.Layer cofLayer = cof.getComponent(component);
if (drawShadow && cofLayer.shadow == 0x1) {
drawShadow(batch, layer, x, y);
}
}
}
((PaletteIndexedBatch) batch).resetBlendMode();
// TODO: Layer blend modes should correspond with the cof trans levels
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) drawLayer(batch, layer, x, y);
}
((PaletteIndexedBatch) batch).resetBlendMode();
((PaletteIndexedBatch) batch).resetColormap();
}
@Override
public void drawDebug(ShapeRenderer shapes, float x, float y) {
int d = DC.Direction.toReadDir(getDirection(), cof.getNumDirections());
int f = getFrame();
for (int l = 0; l < cof.getNumLayers(); l++) {
int component = cof.getLayerOrder(d, f, l);
Layer layer = layers.get(component);
if (layer != null) layer.drawDebug(shapes, d, f, x, y);
}
}
@Override
public BBox getBox() {
return cof.box;
}
}
}

View File

@ -30,7 +30,7 @@ import gdx.diablo.util.DebugUtils;
public class D2S {
private static final String TAG = "D2S";
private static final boolean DEBUG = true;
private static final boolean DEBUG = !true;
private static final boolean DEBUG_HEADER = DEBUG && true;
private static final boolean DEBUG_QUESTS = DEBUG && true;
private static final boolean DEBUG_WAYPOINTS = DEBUG && true;

View File

@ -1,6 +1,14 @@
package gdx.diablo.codec.excel;
public class PlrType extends Excel<PlrType.Entry>{
public class PlrType extends Excel<PlrType.Entry> {
public static final int AM = 0;
public static final int SO = 1;
public static final int NE = 2;
public static final int PA = 3;
public static final int BA = 4;
public static final int DZ = 5;
public static final int AS = 6;
public static class Entry extends Excel.Entry {
@Override
public String toString() {

View File

@ -60,7 +60,7 @@ public class Player {
boolean dirty;
String cofId;
Animation.COFAnimation anim;
Animation anim;
EnumMap<BodyLoc, Item> equipped;
Array<Item> inventory;
@ -335,7 +335,7 @@ public class Player {
//if (animation != null) animation.dispose();
Animation oldAnim = anim;
anim = new Animation.COFAnimation(cof);
anim = Animation.newAnimation(cof);
// TODO: This might be a problem
anim.setDirection(oldAnim != null ? oldAnim.getDirection() : getDirection());

View File

@ -0,0 +1,46 @@
package gdx.diablo.entity3;
import com.badlogic.gdx.Gdx;
public enum Component {
HD,
TR,
LG,
RA,
LA,
RH,
LH,
SH,
S1,
S2,
S3,
S4,
S5,
S6,
S7,
S8;
public static Component valueOf(int i) {
switch (i) {
case 0x0: return HD;
case 0x1: return TR;
case 0x2: return LG;
case 0x3: return RA;
case 0x4: return LA;
case 0x5: return RH;
case 0x6: return LH;
case 0x7: return SH;
case 0x8: return S1;
case 0x9: return S2;
case 0xA: return S3;
case 0xB: return S4;
case 0xC: return S5;
case 0xD: return S6;
case 0xE: return S7;
case 0xF: return S8;
default:
Gdx.app.error("Component", "Unknown component: " + i);
return null;
}
}
}

View File

@ -0,0 +1,293 @@
package gdx.diablo.entity3;
import android.support.annotation.CallSuper;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.MathUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import java.util.Arrays;
import gdx.diablo.Diablo;
import gdx.diablo.codec.Animation;
import gdx.diablo.codec.COF;
import gdx.diablo.codec.COFD2;
import gdx.diablo.codec.DCC;
import gdx.diablo.entity.Direction;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.item.Item;
import gdx.diablo.map.DT1.Tile;
public class Entity {
private static final String TAG = "Entity";
private static final boolean DEBUG = true;
private static final boolean DEBUG_COMPONENTS = DEBUG && true;
private static final boolean DEBUG_DIRTY = DEBUG && true;
private static final boolean DEBUG_ASSETS = DEBUG && true;
private static final boolean DEBUG_WCLASS = DEBUG && true;
protected enum EntType {
OBJECT,
MONSTER,
CHARS;
public final String PATH = "data\\global\\" + name() + "\\";
}
public static final class Dirty {
public static final int NONE = 0;
public static final int HD = 1 << 0;
public static final int TR = 1 << 1;
public static final int LG = 1 << 2;
public static final int RA = 1 << 3;
public static final int LA = 1 << 4;
public static final int RH = 1 << 5;
public static final int LH = 1 << 6;
public static final int SH = 1 << 7;
public static final int S1 = 1 << 8;
public static final int S2 = 1 << 9;
public static final int S3 = 1 << 10;
public static final int S4 = 1 << 11;
public static final int S5 = 1 << 12;
public static final int S6 = 1 << 13;
public static final int S7 = 1 << 14;
public static final int S8 = 1 << 15;
public static String toString(int bits) {
StringBuilder builder = new StringBuilder();
if (bits == NONE) {
builder.append("NONE");
} else {
if ((bits & HD) == HD) builder.append("HD").append("|");
if ((bits & TR) == TR) builder.append("TR").append("|");
if ((bits & LG) == LG) builder.append("LG").append("|");
if ((bits & RA) == RA) builder.append("RA").append("|");
if ((bits & LA) == LA) builder.append("LA").append("|");
if ((bits & RH) == RH) builder.append("RH").append("|");
if ((bits & LH) == LH) builder.append("LH").append("|");
if ((bits & SH) == SH) builder.append("SH").append("|");
if ((bits & S1) == S1) builder.append("S1").append("|");
if ((bits & S2) == S2) builder.append("S2").append("|");
if ((bits & S3) == S3) builder.append("S3").append("|");
if ((bits & S4) == S4) builder.append("S4").append("|");
if ((bits & S5) == S5) builder.append("S5").append("|");
if ((bits & S6) == S6) builder.append("S6").append("|");
if ((bits & S7) == S7) builder.append("S7").append("|");
if ((bits & S8) == S8) builder.append("S8").append("|");
if (builder.length() > 0) builder.setLength(builder.length() - 1);
}
return builder.toString();
}
}
private final int ALL_DIRTY = 0x0000FFFF;
protected static final String DEFAULT_LAYER = "LIT";
private static final String[] DEFAULT_LAYERS;
static {
DEFAULT_LAYERS = new String[16];
Arrays.fill(DEFAULT_LAYERS, DEFAULT_LAYER);
}
GridPoint2 origin = new GridPoint2();
float angle = MathUtils.PI * 3 / 2;
int dirty;
String type;
String mode;
String code;
String layers[];
String weaponClass;
EntType entType;
Animation animation;
Entity(String type) {
this(type, EntType.OBJECT);
}
Entity(String type, EntType entType) {
this.type = type;
this.entType = entType;
mode = code = "NU";
weaponClass = "HTH";
layers = DEFAULT_LAYERS;
invalidate();
}
public void setMode(String mode) {
setMode(mode, mode);
}
public void setMode(String mode, String code) {
if (!this.mode.equals(mode)) {
this.mode = mode;
invalidate();
}
this.code = code;
}
public void setWeaponClass(String wclass) {
if (!weaponClass.equals(wclass)) {
if (DEBUG_WCLASS) Gdx.app.debug(TAG, "wclass: " + weaponClass + " -> " + wclass);
weaponClass = wclass;
invalidate();
}
}
public void setArmType(Component component, String armType) {
if (layers == DEFAULT_LAYERS) {
if (!armType.equalsIgnoreCase(DEFAULT_LAYER)) {
layers = ArrayUtils.clone(DEFAULT_LAYERS);
} else {
return;
}
}
int ordinal = component.ordinal();
if (layers[ordinal].equalsIgnoreCase(armType)) {
return;
}
if (DEBUG_COMPONENTS) Gdx.app.debug(TAG, "layer " + ordinal + " " + layers[ordinal] + " -> " + armType);
layers[ordinal] = armType;
dirty |= (1 << ordinal);
}
protected Item getItem(Component component) {
return null;
}
public final void invalidate() {
dirty = ALL_DIRTY;
}
public final void validate() {
if (dirty == 0) {
return;
}
update();
}
@CallSuper
protected void update() {
String path = type + mode + weaponClass;
Gdx.app.log(TAG, path);
COF cof = getCOFs().lookup(path);
Gdx.app.log(TAG, ObjectUtils.toString(cof));
boolean changed;
if (animation == null) {
animation = Animation.newAnimation(cof);
changed = true;
} else {
changed = animation.reset(cof);
}
if (changed) {
dirty = ALL_DIRTY;
animation.setDirection(getDirection());
}
if (DEBUG_DIRTY) Gdx.app.debug(TAG, "dirty layers: " + Dirty.toString(dirty));
for (int l = 0; l < cof.getNumLayers(); l++) {
COF.Layer layer = cof.getLayer(l);
if (((1 << layer.component) & dirty) == 0) {
continue;
}
final int c = layer.component;
final Component comp = Component.valueOf(c);
if (comp == null) continue;
String component = comp.name();
String armType = layers[c];
String weaponClass = layer.weaponClass;
path = entType.PATH + type + "\\" + component + "\\" + type + component + armType + mode + weaponClass + ".dcc";
if (armType.isEmpty()) {
animation.setLayer(c, null);
continue;
}
Gdx.app.log(TAG, path);
if (DEBUG_ASSETS) {
AssetDescriptor<DCC> descriptor = new AssetDescriptor<>(path, DCC.class);
Diablo.assets.load(descriptor);
Diablo.assets.finishLoadingAsset(descriptor);
DCC dcc = Diablo.assets.get(descriptor);
animation.setLayer(c, dcc);
}
Item item = getItem(comp);
if (item != null) {
animation.getLayer(layer.component).setTransform(item.charColormap, item.charColorIndex);
}
}
dirty = 0;
}
protected COFD2 getCOFs() {
return Diablo.cofs.active;
}
public void drawDebug(ShapeRenderer shapes) {
float x = +(origin.x * Tile.SUBTILE_WIDTH50) - (origin.y * Tile.SUBTILE_WIDTH50);
float y = -(origin.x * Tile.SUBTILE_HEIGHT50) - (origin.y * Tile.SUBTILE_HEIGHT50);
final float R = 32;
shapes.setColor(Color.RED);
shapes.line(x, y, x + MathUtils.cos(angle) * R, y + MathUtils.sin(angle) * R);
float rounded = Direction.radiansToDirection16Radians(angle);
shapes.setColor(Color.GREEN);
shapes.line(x, y, x + MathUtils.cos(rounded) * R * 0.5f, y + MathUtils.sin(rounded) * R * 0.5f);
}
public void draw(Batch batch) {
draw((PaletteIndexedBatch) batch);
}
public void draw(PaletteIndexedBatch batch) {
validate();
animation.act();
float x = +(origin.x * Tile.SUBTILE_WIDTH50) - (origin.y * Tile.SUBTILE_WIDTH50);
float y = -(origin.x * Tile.SUBTILE_HEIGHT50) - (origin.y * Tile.SUBTILE_HEIGHT50);
animation.draw(batch, x, y);
}
public void setAngle(float rad) {
if (angle != rad) {
angle = rad;
if (animation != null) animation.setDirection(getDirection());
}
}
public int getDirection() {
return Direction.radiansToDirection(angle, 16);
}
public GridPoint2 origin() {
return origin;
}
public void move() {
if (!mode.equalsIgnoreCase("WL")
&& !mode.equalsIgnoreCase("RN")
&& !mode.equalsIgnoreCase("TW")) {
return;
}
int x = Direction.getOffX(angle);
int y = Direction.getOffY(angle);
origin.add(x, y);
}
}

View File

@ -0,0 +1,326 @@
package gdx.diablo.entity3;
import com.google.common.base.Preconditions;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import org.apache.commons.lang3.ObjectUtils;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import gdx.diablo.CharClass;
import gdx.diablo.Diablo;
import gdx.diablo.codec.COFD2;
import gdx.diablo.codec.D2S;
import gdx.diablo.codec.excel.Armor;
import gdx.diablo.codec.excel.Weapons;
import gdx.diablo.item.BodyLoc;
import gdx.diablo.item.Item;
public class Player extends Entity {
private static final String TAG = "Player";
private static final boolean DEBUG = true;
private static final boolean DEBUG_WCLASS = DEBUG && !true;
public enum Slot {
HEAD, NECK, TORS, RARM, LARM, RRIN, LRIN, BELT, FEET, GLOV;
public BodyLoc toBodyLoc(boolean alternate) {
return toBodyLoc(this, alternate);
}
public static BodyLoc toBodyLoc(Slot slot, boolean alternate) {
switch (slot) {
case HEAD: return BodyLoc.HEAD;
case NECK: return BodyLoc.NECK;
case TORS: return BodyLoc.TORS;
case RARM: return alternate ? BodyLoc.RARM2 : BodyLoc.RARM;
case LARM: return alternate ? BodyLoc.LARM2 : BodyLoc.LARM;
case RRIN: return BodyLoc.RRIN;
case LRIN: return BodyLoc.LRIN;
case BELT: return BodyLoc.BELT;
case FEET: return BodyLoc.FEET;
case GLOV: return BodyLoc.GLOV;
default:
throw new GdxRuntimeException("Invalid slot: " + slot);
}
}
}
D2S d2s;
boolean alternate;
EnumMap<BodyLoc, Item> equipped = new EnumMap<>(BodyLoc.class);
Array<Item> inventory = new Array<>();
final Set<SlotListener> SLOT_LISTENERS = new CopyOnWriteArraySet<>();
public Stats stats;
public Player(String name, CharClass clazz) {
super(null);
throw new UnsupportedOperationException();
}
public Player(D2S d2s) {
super(Diablo.files.PlrType.get(d2s.charClass).Token, EntType.CHARS);
this.d2s = d2s;
this.stats = new Stats();
equipped.putAll(d2s.items.equipped);
inventory.addAll(d2s.items.inventory);
for (Map.Entry<BodyLoc, Item> entry : equipped.entrySet()) {
entry.getValue().load();
//if (DEBUG_EQUIPPED) Gdx.app.debug(TAG, entry.getKey() + ": " + entry.getValue());
}
for (Item item : inventory) {
item.load();
//if (DEBUG_INVENTORY) Gdx.app.debug(TAG, item.gridX + "," + item.gridY + ": " + item);
}
}
public Item getSlot(Slot slot) {
BodyLoc loc = slot.toBodyLoc(alternate);
return getSlot(loc);
}
public Item getSlot(BodyLoc loc) {
return equipped.get(loc);
}
public Item setSlot(Slot slot, Item item) {
Preconditions.checkState(item == null || getSlot(slot) == null, "Slot must be empty first!");
BodyLoc loc = slot.toBodyLoc(alternate);
return setSlot(loc, item);
}
public Item setSlot(BodyLoc loc, Item item) {
Item oldItem = equipped.put(loc, item);
//invalidate();
//setArmType(slot, item.base.alternateGfx);
int components = loc.components();
if (components > 0) dirty |= components;
updateWeaponClass();
notifySlotChanged(loc, oldItem, item);
return oldItem;
}
@Override
protected Item getItem(Component component) {
switch (component) {
case HD: return getSlot(Slot.HEAD);
case TR:
case RA:
case LA:
case S1:
case S2: return getSlot(Slot.TORS);
// TODO: Shield/weapons?
default: return super.getItem(component);
}
}
public boolean isAlternate() {
return alternate;
}
public void setAlternate(boolean b) {
if (alternate != b) {
alternate = b;
updateWeaponClass();
}
}
@Override
protected COFD2 getCOFs() {
return Diablo.cofs.chars_cof;
}
public void update() {
updateWeaponClass();
Item head = getSlot(Slot.HEAD);
setArmType(Component.HD, head != null ? head.base.alternateGfx : "LIT");
Item body = getSlot(Slot.TORS);
if (body != null) {
Armor.Entry armor = body.getBase();
setArmType(Component.TR, Diablo.files.ArmType.get(armor.Torso).Token);
setArmType(Component.LG, Diablo.files.ArmType.get(armor.Legs ).Token);
setArmType(Component.RA, Diablo.files.ArmType.get(armor.rArm ).Token);
setArmType(Component.LA, Diablo.files.ArmType.get(armor.lArm ).Token);
setArmType(Component.S1, Diablo.files.ArmType.get(armor.lSPad).Token);
setArmType(Component.S2, Diablo.files.ArmType.get(armor.rSPad).Token);
} else {
setArmType(Component.TR, DEFAULT_LAYER);
setArmType(Component.LG, DEFAULT_LAYER);
setArmType(Component.RA, DEFAULT_LAYER);
setArmType(Component.LA, DEFAULT_LAYER);
setArmType(Component.S1, DEFAULT_LAYER);
setArmType(Component.S2, DEFAULT_LAYER);
}
super.update();
}
private void updateWeaponClass() {
Item RH = null, LH = null, SH = null;
Item rArm = getSlot(Slot.RARM);
if (rArm != null) {
if (rArm.type.is("weap")) {
RH = rArm;
} else if (rArm.type.is("shld")) {
SH = rArm;
}
}
Item lArm = getSlot(Slot.LARM);
if (lArm != null) {
if (lArm.type.is("weap")) {
LH = lArm;
} else if (lArm.type.is("shld")) {
SH = lArm;
}
}
if (DEBUG_WCLASS) {
Gdx.app.debug(TAG, "RH = " + RH);
Gdx.app.debug(TAG, "LH = " + LH);
Gdx.app.debug(TAG, "SH = " + SH);
}
if (LH != null && RH != null) {
Weapons.Entry LHEntry = LH.getBase();
Weapons.Entry RHEntry = RH.getBase();
if ( LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1hs")) {
setWeaponClass("1SS"); // Left Swing Right Swing
} else if (LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1ht")) {
setWeaponClass("1ST"); // Left Swing Right Thrust
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1hs")) {
setWeaponClass("1JS"); // Left Jab Right Swing
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1ht")) {
setWeaponClass("1JT"); // Left Jab Right Thrust
} else if (LH.type.is("miss") || RH.type.is("miss")) {
setWeaponClass(LH.type.is("miss") ? LHEntry.wclass : RHEntry.wclass);
} else if (LH.type.is("h2h") || RH.type.is("h2h")) {
setWeaponClass("HT2"); // Two Hand-to-Hand
} else {
setWeaponClass("HTH");
Gdx.app.error(TAG, String.format(
"Unknown weapon combination: LH=%s RH=%s", LHEntry.wclass, RHEntry.wclass));
}
} else if (LH != null || RH != null) {
RH = ObjectUtils.firstNonNull(RH, LH);
LH = null;
if (RH.type.is("bow")) {
LH = RH;
RH = null;
Weapons.Entry LHEntry = LH.getBase();
setWeaponClass(LHEntry.wclass);
} else if (RH.type.is("weap")) { // make sure weap and not e.g. misl, might not be required
Weapons.Entry RHEntry = RH.getBase();
setWeaponClass(RHEntry.wclass);
} else {
setWeaponClass("HTH");
}
} else {
setWeaponClass("HTH");
}
if (RH != null) setArmType(Component.RH, RH.base.alternateGfx);
if (LH != null) setArmType(Component.LH, LH.base.alternateGfx);
if (SH != null) setArmType(Component.SH, SH.base.alternateGfx);
else setArmType(Component.SH, "");
}
private void notifySlotChanged(BodyLoc bodyLoc, Item oldItem, Item item) {
for (SlotListener l : SLOT_LISTENERS) l.onChanged(this, bodyLoc, oldItem, item);
}
public boolean addSlotListener(SlotListener l) {
boolean added = SLOT_LISTENERS.add(l);
return added;
}
public boolean containsSlotListener(Object o) {
return o != null && SLOT_LISTENERS.contains(o);
}
public boolean removeSlotListener(Object o) {
return o != null && SLOT_LISTENERS.remove(o);
}
public boolean clearSlotListeners() {
boolean empty = SLOT_LISTENERS.isEmpty();
SLOT_LISTENERS.clear();
return !empty;
}
public interface SlotListener {
void onChanged(Player player, BodyLoc bodyLoc, Item oldItem, Item item);
}
public Array<Item> getInventory() {
return inventory;
}
public class Stats {
public int getClassId() {
return d2s.charClass;
}
public CharClass getCharClass() {
return CharClass.get(d2s.charClass);
}
public String getName() {
return d2s.name;
}
public int getLevel() {
return d2s.stats.level;
}
public long getExperience() {
return d2s.stats.xp;
}
public int getStrength() {
return d2s.stats.strength;
}
public int getDexterity() {
return d2s.stats.dexterity;
}
public int getVitality() {
return d2s.stats.vitality;
}
public int getEnergy() {
return d2s.stats.energy;
}
public int getFireResistance() {
return 0;
}
public int getColdResistance() {
return 0;
}
public int getLightningResistance() {
return 0;
}
public int getPoisonResistance() {
return 0;
}
}
}

View File

@ -2,20 +2,22 @@ package gdx.diablo.item;
import com.badlogic.gdx.Gdx;
import static gdx.diablo.entity3.Entity.Dirty.*;
public enum BodyLoc {
NONE,
HEAD,
HEAD(HD),
NECK,
TORS,
RARM,
LARM,
TORS(TR|LG|LA|RA|S1|S2),
RARM(RH|LH|SH),
LARM(RH|LH|SH),
RRIN,
LRIN,
BELT,
FEET,
FEET(LG),
GLOV,
RARM2,
LARM2;
RARM2(RH|LH|SH),
LARM2(RH|LH|SH);
public static BodyLoc valueOf(int i) {
switch (i) {
@ -37,4 +39,18 @@ public enum BodyLoc {
return null;
}
}
final int components;
BodyLoc() {
this.components = -1;
}
BodyLoc(int components) {
this.components = components;
}
public int components() {
return components;
}
}

View File

@ -16,7 +16,7 @@ import java.text.NumberFormat;
import gdx.diablo.Cvars;
import gdx.diablo.Diablo;
import gdx.diablo.codec.DC6;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.loader.DC6Loader;
import gdx.diablo.screen.GameScreen;
import gdx.diablo.widget.Button;
@ -58,7 +58,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
Player player = gameScreen.player;
Label name = new Label(player.getName(), Diablo.fonts.font16);
Label name = new Label(player.stats.getName(), Diablo.fonts.font16);
name.setPosition(12, getHeight() - 24);
name.setSize(168, 13);
name.setAlignment(Align.center);
@ -68,17 +68,17 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
level.setPosition(12, getHeight() - 65);
level.setSize(42, 33);
level.add(new Label(4057, Diablo.fonts.ReallyTheLastSucker)).row();
level.add(new Label(Integer.toString(player.getLevel()), Diablo.fonts.font16)).growY().row();
level.add(new Label(Integer.toString(player.stats.getLevel()), Diablo.fonts.font16)).growY().row();
addActor(level);
Table exp = new Table();
exp.setPosition(66, getHeight() - 65);
exp.setSize(114, 33);
exp.add(new Label(4058, Diablo.fonts.ReallyTheLastSucker)).row();
exp.add(new Label(NumberFormat.getInstance(Cvars.Client.Locale.get()).format(player.getExperience()), Diablo.fonts.font16)).growY().row();
exp.add(new Label(NumberFormat.getInstance(Cvars.Client.Locale.get()).format(player.stats.getExperience()), Diablo.fonts.font16)).growY().row();
addActor(exp);
Label clazz = new Label(player.getCharClass().name, Diablo.fonts.font16);
Label clazz = new Label(player.stats.getCharClass().name, Diablo.fonts.font16);
clazz.setPosition(194, getHeight() - 24);
clazz.setSize(114, 13);
clazz.setAlignment(Align.center);
@ -97,7 +97,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
strLabel.setAlignment(Align.center);
addActor(strLabel);
Label str = new Label(Integer.toString(player.getStrength()), Diablo.fonts.font16);
Label str = new Label(Integer.toString(player.stats.getStrength()), Diablo.fonts.font16);
str.setPosition(78, getHeight() - 100);
str.setSize(36, 16);
str.setAlignment(Align.center);
@ -109,7 +109,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
dexLabel.setAlignment(Align.center);
addActor(dexLabel);
Label dex = new Label(Integer.toString(player.getDexterity()), Diablo.fonts.font16);
Label dex = new Label(Integer.toString(player.stats.getDexterity()), Diablo.fonts.font16);
dex.setPosition(78, getHeight() - 162);
dex.setSize(36, 16);
dex.setAlignment(Align.center);
@ -121,7 +121,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
vitLabel.setAlignment(Align.center);
addActor(vitLabel);
Label vit = new Label(Integer.toString(player.getVitality()), Diablo.fonts.font16);
Label vit = new Label(Integer.toString(player.stats.getVitality()), Diablo.fonts.font16);
vit.setPosition(78, getHeight() - 248);
vit.setSize(36, 16);
vit.setAlignment(Align.center);
@ -133,7 +133,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
eneLabel.setAlignment(Align.center);
addActor(eneLabel);
Label ene = new Label(Integer.toString(player.getEnergy()), Diablo.fonts.font16);
Label ene = new Label(Integer.toString(player.stats.getEnergy()), Diablo.fonts.font16);
ene.setPosition(78, getHeight() - 310);
ene.setSize(36, 16);
ene.setAlignment(Align.center);
@ -145,7 +145,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
fireResLabel.setAlignment(Align.center);
addActor(fireResLabel);
Label fireRes = new Label(Integer.toString(player.getFireResistance()), Diablo.fonts.font16);
Label fireRes = new Label(Integer.toString(player.stats.getFireResistance()), Diablo.fonts.font16);
fireRes.setPosition(273, getHeight() - 349);
fireRes.setSize(36, 16);
fireRes.setAlignment(Align.center);
@ -157,7 +157,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
coldResLabel.setAlignment(Align.center);
addActor(coldResLabel);
Label coldRes = new Label(Integer.toString(player.getColdResistance()), Diablo.fonts.font16);
Label coldRes = new Label(Integer.toString(player.stats.getColdResistance()), Diablo.fonts.font16);
coldRes.setPosition(273, getHeight() - 373);
coldRes.setSize(36, 16);
coldRes.setAlignment(Align.center);
@ -169,7 +169,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
lightningResLabel.setAlignment(Align.center);
addActor(lightningResLabel);
Label lightningRes = new Label(Integer.toString(player.getLightningResistance()), Diablo.fonts.font16);
Label lightningRes = new Label(Integer.toString(player.stats.getLightningResistance()), Diablo.fonts.font16);
lightningRes.setPosition(273, getHeight() - 397);
lightningRes.setSize(36, 16);
lightningRes.setAlignment(Align.center);
@ -181,7 +181,7 @@ public class CharacterPanel extends WidgetGroup implements Disposable {
poisonResLabel.setAlignment(Align.center);
addActor(poisonResLabel);
Label poisonRes = new Label(Integer.toString(player.getPoisonResistance()), Diablo.fonts.font16);
Label poisonRes = new Label(Integer.toString(player.stats.getPoisonResistance()), Diablo.fonts.font16);
poisonRes.setPosition(273, getHeight() - 421);
poisonRes.setSize(36, 16);
poisonRes.setAlignment(Align.center);

View File

@ -22,7 +22,7 @@ import gdx.diablo.codec.DC6;
import gdx.diablo.codec.excel.BodyLocs;
import gdx.diablo.codec.excel.Inventory;
import gdx.diablo.codec.util.BBox;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.item.BodyLoc;
import gdx.diablo.item.Item;
@ -99,7 +99,7 @@ public class InventoryPanel extends WidgetGroup implements Disposable {
});
addActor(btnExit);
inventory = Diablo.files.inventory.getClass(gameScreen.player.getClassId());
inventory = Diablo.files.inventory.getClass(gameScreen.player.stats.getClassId());
Diablo.assets.load(inv_armorDescriptor);
Diablo.assets.load(inv_beltDescriptor);
@ -207,7 +207,7 @@ public class InventoryPanel extends WidgetGroup implements Disposable {
for (int i = BodyLocs.HEAD; i < BodyLocs.NUM_LOCS; i++) {
if (bodyParts[i] == null) continue;
bodyParts[i].slot = i;
bodyParts[i].item = gameScreen.player.getBodyLoc(BodyLoc.valueOf(i));
bodyParts[i].item = gameScreen.player.getSlot(BodyLoc.valueOf(i));
bodyParts[i].setBodyPart(Diablo.files.bodylocs.get(i).Code);
}
@ -312,11 +312,11 @@ public class InventoryPanel extends WidgetGroup implements Disposable {
Diablo.cursor.setItem(item);
item = cursor;
//gameScreen.player.setSlot(slot, item);
gameScreen.player.setSlot(BodyLoc.valueOf(slot), item);
} else {
Diablo.cursor.setItem(item);
item = null;
//gameScreen.player.setSlot(slot, null);
gameScreen.player.setSlot(BodyLoc.valueOf(slot), null);
}
}
});

View File

@ -26,7 +26,7 @@ import gdx.diablo.CharClass;
import gdx.diablo.Diablo;
import gdx.diablo.codec.Animation;
import gdx.diablo.codec.DC6;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.loader.DC6Loader;
import gdx.diablo.widget.CharButton;

View File

@ -24,11 +24,10 @@ import com.badlogic.gdx.utils.Timer;
import gdx.diablo.Diablo;
import gdx.diablo.Keys;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.key.MappedKey;
import gdx.diablo.key.MappedKeyStateAdapter;
import gdx.diablo.map.DT1.Tile;
import gdx.diablo.map.Map;
import gdx.diablo.map.MapLoader;
import gdx.diablo.map.MapRenderer;
@ -246,9 +245,10 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
//int spx = + (character.x * Tile.SUBTILE_WIDTH50) - (character.y * Tile.SUBTILE_WIDTH50);
//int spy = - (character.x * Tile.SUBTILE_HEIGHT50) - (character.y * Tile.SUBTILE_HEIGHT50);
//character.draw(b, spx, spy);
int spx = + (player.getOrigin().x * Tile.SUBTILE_WIDTH50) - (player.getOrigin().y * Tile.SUBTILE_WIDTH50);
int spy = - (player.getOrigin().x * Tile.SUBTILE_HEIGHT50) - (player.getOrigin().y * Tile.SUBTILE_HEIGHT50);
player.draw(b, spx, spy);
//int spx = + (player.getOrigin().x * Tile.SUBTILE_WIDTH50) - (player.getOrigin().y * Tile.SUBTILE_WIDTH50);
//int spy = - (player.getOrigin().x * Tile.SUBTILE_HEIGHT50) - (player.getOrigin().y * Tile.SUBTILE_HEIGHT50);
//player.draw(b, spx, spy);
player.draw(b);
b.end();
b.setProjectionMatrix(Diablo.viewport.getCamera().combined);
@ -256,7 +256,8 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
Diablo.shapes.setProjectionMatrix(camera.combined);
Diablo.shapes.begin(ShapeRenderer.ShapeType.Line);
mapRenderer.renderDebug(Diablo.shapes);
player.drawDebug(Diablo.shapes, spx, spy);
//player.drawDebug(Diablo.shapes, spx, spy);
player.drawDebug(Diablo.shapes);
Diablo.shapes.end();
stage.act();
@ -283,7 +284,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
//character.x = origin.x;
//character.y = origin.y;
player.getOrigin().set(origin);
player.origin().set(origin);
Gdx.app.debug(TAG, player.toString());
Keys.Esc.addStateListener(mappedKeyStateListener);
@ -298,7 +299,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
@Override
public void run() {
player.move();
mapRenderer.setPosition(player.getOrigin());
mapRenderer.setPosition(player.origin());
}
}, 0, 1 / 25f);
}

View File

@ -85,17 +85,19 @@ public class LoginScreen extends ScreenAdapter {
if (D2logoLeft == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackLeftDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireLeftDescriptor);
D2logoLeft = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackLeftDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY));
D2logoLeft = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackLeftDescriptor))
.layer(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY)
.build();
}
if (D2logoRight == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackRightDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireRightDescriptor);
D2logoRight = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackRightDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY));
D2logoRight = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackRightDescriptor))
.layer(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY)
.build();
}
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle() {{

View File

@ -75,17 +75,19 @@ public class MenuScreen extends ScreenAdapter {
if (D2logoLeft == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackLeftDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireLeftDescriptor);
D2logoLeft = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackLeftDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY));
D2logoLeft = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackLeftDescriptor))
.layer(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY)
.build();
}
if (D2logoRight == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackRightDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireRightDescriptor);
D2logoRight = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackRightDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY));
D2logoRight = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackRightDescriptor))
.layer(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY)
.build();
}
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle() {{

View File

@ -70,17 +70,19 @@ public class MultiplayerScreen extends ScreenAdapter {
if (D2logoLeft == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackLeftDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireLeftDescriptor);
D2logoLeft = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackLeftDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY));
D2logoLeft = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackLeftDescriptor))
.layer(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY)
.build();
}
if (D2logoRight == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackRightDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireRightDescriptor);
D2logoRight = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackRightDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY));
D2logoRight = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackRightDescriptor))
.layer(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY)
.build();
}
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle() {{

View File

@ -17,7 +17,7 @@ import com.badlogic.gdx.utils.Array;
import gdx.diablo.Diablo;
import gdx.diablo.codec.D2S;
import gdx.diablo.codec.DC6;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.loader.DC6Loader;
import gdx.diablo.widget.SelectButton;
@ -60,8 +60,7 @@ public class SelectCharacterScreen extends ScreenAdapter {
Diablo.client.popScreen();
} else if (actor == btnOK) {
assert selected != null;
Diablo.client.clearAndSet(new LoadingScreen(new GameScreen(new Player(selected.getD2S()
))));
Diablo.client.clearAndSet(new LoadingScreen(new GameScreen(new Player(selected.getD2S()))));
} else if (actor == btnCreateNewCharacter) {
Diablo.client.pushScreen(new CreateCharacterScreen());
}

View File

@ -27,8 +27,8 @@ public class SplashScreen extends ScreenAdapter {
final AssetDescriptor<DC6> D2logoFireLeftDescriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\D2logoFireLeft.DC6", DC6.class);
final AssetDescriptor<DC6> D2logoBlackRightDescriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\D2logoBlackRight.DC6", DC6.class);
final AssetDescriptor<DC6> D2logoFireRightDescriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\D2logoFireRight.DC6", DC6.class);
Animation.CompositeAnimation D2logoLeft;
Animation.CompositeAnimation D2logoRight;
Animation D2logoLeft;
Animation D2logoRight;
GlyphLayout pressContinueGlyphs;
@ -57,15 +57,17 @@ public class SplashScreen extends ScreenAdapter {
Diablo.assets.finishLoadingAsset(D2logoBlackLeftDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireLeftDescriptor);
D2logoLeft = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackLeftDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY));
D2logoLeft = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackLeftDescriptor))
.layer(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY)
.build();
Diablo.assets.finishLoadingAsset(D2logoBlackRightDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireRightDescriptor);
D2logoRight = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackRightDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY));
D2logoRight = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackRightDescriptor))
.layer(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY)
.build();
String press_to_continue;
// TODO: Update message for controllers press_any_button

View File

@ -85,17 +85,19 @@ public class TCPIPScreen extends ScreenAdapter {
if (D2logoLeft == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackLeftDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireLeftDescriptor);
D2logoLeft = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackLeftDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY));
D2logoLeft = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackLeftDescriptor))
.layer(Diablo.assets.get(D2logoFireLeftDescriptor), BlendMode.LUMINOSITY)
.build();
}
if (D2logoRight == null) {
Diablo.assets.finishLoadingAsset(D2logoBlackRightDescriptor);
Diablo.assets.finishLoadingAsset(D2logoFireRightDescriptor);
D2logoRight = new Animation.CompositeAnimation(
Animation.Layer.from(Diablo.assets.get(D2logoBlackRightDescriptor)),
Animation.Layer.from(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY));
D2logoRight = Animation.builder()
.layer(Diablo.assets.get(D2logoBlackRightDescriptor))
.layer(Diablo.assets.get(D2logoFireRightDescriptor), BlendMode.LUMINOSITY)
.build();
}
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle() {{

View File

@ -0,0 +1,139 @@
package gdx.diablo.widget;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.net.HttpRequestBuilder;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import gdx.diablo.Diablo;
import gdx.diablo.codec.DC6;
import gdx.diablo.loader.DC6Loader;
public class BNetConnectDialog extends Dialog {
final AssetDescriptor<DC6> PopUp_340x224Descriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\PopUp_340x224.dc6", DC6.class, DC6Loader.DC6Parameters.COMBINE);
final AssetDescriptor<DC6> MediumButtonBlankDescriptor = new AssetDescriptor<>("data\\global\\ui\\FrontEnd\\MediumButtonBlank.dc6", DC6.class, DC6Loader.DC6Parameters.COMBINE);
Label status;
public BNetConnectDialog() {
Diablo.assets.load(PopUp_340x224Descriptor);
Diablo.assets.load(MediumButtonBlankDescriptor);
setDebug(true, true);
}
public void create() {
Diablo.assets.finishLoadingAsset(PopUp_340x224Descriptor);
TextureRegion PopUp_340x224 = Diablo.assets.get(PopUp_340x224Descriptor).getTexture();
setBackground(new TextureRegionDrawable(PopUp_340x224));
getContentTable().add(new Table() {{
add(new Label(5171, Diablo.fonts.font30) {{
setWrap(true);
setAlignment(Align.center);
}}).width(220).row();
add(status = new Label("", Diablo.fonts.font24)).growY().row();
add(new Label("*", Diablo.fonts.font24)).row();
setWidth(220);
pad(10);
}}).growY();
Table buttonTable = getButtonTable();
Button btnCancel = new TextButton(5134, new TextButton.TextButtonStyle() {{
Diablo.assets.finishLoadingAsset(MediumButtonBlankDescriptor);
DC6 MediumButtonBlank = Diablo.assets.get(MediumButtonBlankDescriptor);
up = new TextureRegionDrawable(MediumButtonBlank.getTexture(0));
down = new TextureRegionDrawable(MediumButtonBlank.getTexture(1));
font = Diablo.fonts.fontexocet10;
}});
btnCancel.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
hide(null);
}
});
buttonTable.add(btnCancel);
buttonTable.padBottom(10);
}
@Override
public com.badlogic.gdx.scenes.scene2d.ui.Dialog show(Stage stage, Action action) {
setPosition(
Diablo.VIRTUAL_WIDTH_CENTER - 340 / 2,
Diablo.VIRTUAL_HEIGHT_CENTER - 224 / 2);
return super.show(stage, action);
}
@Override
public void hide(Action action) {
super.hide(action);
}
@Override
public void dispose() {
Diablo.assets.unload(PopUp_340x224Descriptor.fileName);
Diablo.assets.unload(MediumButtonBlankDescriptor.fileName);
}
public void connect(Stage stage) {
show(stage, null);
queryGateway();
findServer();
accessAccount();
checkVersion();
}
private void queryGateway() {
status.setText(5172);
findServer();
}
private void findServer() {
status.setText(5173);
Net.HttpRequest request = new HttpRequestBuilder()
.newRequest()
.method(Net.HttpMethods.GET)
.url("http://hydra:6112/find-server")
.build();
Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
@Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
accessAccount();
}
@Override
public void failed(Throwable t) {
BNetConnectDialog.this.failed(t.getMessage());
}
@Override
public void cancelled() {
BNetConnectDialog.this.failed("cancelled");
}
});
}
private void accessAccount() {
status.setText(5174);
checkVersion();
}
private void checkVersion() {
status.setText(5175);
connected();
}
protected void connected() {
}
protected void failed(String message) {
}
}

View File

@ -189,12 +189,13 @@ public class CharButton extends Widget implements Disposable {
state = State.FW;
if (fw == null) {
Diablo.assets.finishLoadingAsset(fwDesc);
fw = Animation.newAnimation(Diablo.assets.get(fwDesc));
Animation.Builder builder = Animation.builder()
.layer(Diablo.assets.get(fwDesc));
if (charClass.fws) {
Diablo.assets.finishLoadingAsset(fwsDesc);
Animation.Layer composite = Animation.Layer.from(Diablo.assets.get(fwsDesc));
fw = fw.composite().addLayer(composite, charClass.blendSpecial);
builder.layer(Diablo.assets.get(fwsDesc), charClass.blendSpecial);
}
fw = builder.build();
fw.setLooping(false);
fw.addAnimationListener(new Animation.AnimationListener() {
@Override
@ -202,12 +203,13 @@ public class CharButton extends Widget implements Disposable {
state = State.NU3;
if (nu3 == null) {
Diablo.assets.finishLoadingAsset(nu3Desc);
nu3 = Animation.newAnimation(Diablo.assets.get(nu3Desc));
Animation.Builder builder = Animation.builder()
.layer(Diablo.assets.get(nu3Desc));
if (charClass.nu3s) {
Diablo.assets.finishLoadingAsset(nu3sDesc);
Animation.Layer composite = Animation.Layer.from(Diablo.assets.get(nu3sDesc));
nu3 = nu3.composite().addLayer(composite, charClass.blendSpecial);
builder.layer(Diablo.assets.get(nu3sDesc), charClass.blendSpecial);
}
nu3 = builder.build();
}
setActive(nu3);
}
@ -227,12 +229,13 @@ public class CharButton extends Widget implements Disposable {
state = State.BW;
if (bw == null) {
Diablo.assets.finishLoadingAsset(bwDesc);
bw = Animation.newAnimation(Diablo.assets.get(bwDesc));
Animation.Builder builder = Animation.builder()
.layer(Diablo.assets.get(bwDesc));
if (charClass.bws) {
Diablo.assets.finishLoadingAsset(bwsDesc);
Animation.Layer composite = Animation.Layer.from(Diablo.assets.get(bwsDesc));
bw = bw.composite().addLayer(composite, charClass.blendSpecial);
builder.layer(Diablo.assets.get(bwsDesc), charClass.blendSpecial);
}
bw = builder.build();
bw.setLooping(false);
bw.addAnimationListener(new Animation.AnimationListener() {
@Override

View File

@ -22,7 +22,7 @@ public class CharacterPreview extends Widget implements Disposable {
D2S d2s;
AssetDescriptor[] assets;
Animation.COFAnimation anim;
Animation anim;
public CharacterPreview() {}
@ -56,7 +56,7 @@ public class CharacterPreview extends Widget implements Disposable {
}
//System.out.println(Arrays.toString(armorClasses));
anim = new Animation.COFAnimation(cof);
anim = Animation.newAnimation(cof);
anim.setDirection(Direction.DOWN);
anim.setShadow(false);
if (assets == null) assets = new AssetDescriptor[COF.Component.NUM_COMPONENTS];

View File

@ -0,0 +1,16 @@
package gdx.diablo.widget;
import com.badlogic.gdx.utils.Disposable;
import gdx.diablo.Diablo;
public class Dialog extends com.badlogic.gdx.scenes.scene2d.ui.Dialog implements Disposable {
public Dialog() {
super("", new WindowStyle() {{
titleFont = Diablo.fonts.font16;
}});
}
@Override
public void dispose() {}
}

View File

@ -20,7 +20,7 @@ import gdx.diablo.BlendMode;
import gdx.diablo.Diablo;
import gdx.diablo.codec.excel.Inventory;
import gdx.diablo.codec.excel.ItemEntry;
import gdx.diablo.entity.Player;
import gdx.diablo.entity3.Player;
import gdx.diablo.graphics.PaletteIndexedBatch;
import gdx.diablo.item.Item;

View File

@ -0,0 +1,86 @@
package gdx.diablo.entity3;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.backends.headless.HeadlessApplication;
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicBoolean;
import gdx.diablo.COFs;
import gdx.diablo.Diablo;
import gdx.diablo.Files;
import gdx.diablo.codec.D2S;
import gdx.diablo.codec.StringTBLs;
import gdx.diablo.mpq.MPQFileHandleResolver;
public class EntityTest {
@BeforeClass
public static void setUp() throws Exception {
final AtomicBoolean block = new AtomicBoolean(true);
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
new HeadlessApplication(new ApplicationAdapter() {
@Override
public void create() {
Gdx.app.setLogLevel(Application.LOG_DEBUG);
MPQFileHandleResolver resolver = Diablo.mpqs = new MPQFileHandleResolver();
resolver.add(Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II\\patch_d2.mpq"));
resolver.add(Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II\\d2exp.mpq"));
resolver.add(Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II\\d2data.mpq"));
Diablo.assets = new AssetManager(resolver);
Diablo.cofs = new COFs(Diablo.assets);
Diablo.files = new Files(Diablo.assets);
Diablo.string = new StringTBLs(resolver);
block.set(false);
}
@Override
public void dispose() {
Diablo.assets.dispose();
}
}, config);
while (block.get());
}
@AfterClass
public static void tearDown() throws Exception {
Gdx.app.exit();
}
@Test
public void validateStatic() {
Entity entity = new Entity("AF");
entity.setMode("NU");
entity.setWeaponClass("HTH");
entity.validate();
}
@Test
public void validateMonster() {
Entity entity = new Entity("BH", Entity.EntType.MONSTER);
entity.setMode("NU");
entity.setWeaponClass("HTH");
entity.validate();
}
@Test
public void validatePlayer() {
D2S d2s = D2S.loadFromFile(Gdx.files.local("test/Tirant.d2s"));
Player entity = new Player(d2s);
entity.setMode("TN");
entity.setWeaponClass("1hs");
entity.validate();
entity.setSlot(Player.Slot.HEAD, null);
entity.validate();
entity.setMode("RN");
entity.validate();
}
}

View File

@ -42,7 +42,7 @@ public class Tester1101 extends ApplicationAdapter {
Gdx.app.setLogLevel(Application.LOG_DEBUG);
MPQ d2data = MPQ.loadFromFile(Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II\\d2data.mpq"));
COF cof = COF.loadFromStream(d2data.read("data\\global\\objects\\TO\\COF\\toonhth.cof"));
animation = new Animation.COFAnimation(cof);
animation = Animation.newAnimation(cof);
palette = Palette.loadFromStream(d2data.read(Palettes.ACT1)).render();