Added SpellsQuickPanel

Added SpellsQuickPanel
Added HotkeyButton assigned to MappedKey
Added Skill1-16 Keys
Button now has a customizable disabled and highlight state
Hacked together a couple skills for testing purposes
Added animation overlay support (will expand in future)
Added Entity.cast(int)
ControlPanel left and right skill corresponds and changes based on active skill
Mapped key now allows primary key as NOT_MAPPED
Added Map from string to mode index
Added Animation clamp function to play animation until over or stop at last frame
Added additional fields to excel Skills
Added excel Overlay
This commit is contained in:
Collin Smith 2019-03-19 03:03:25 -07:00
parent 3acd1ab0c5
commit c3fcfc4f05
16 changed files with 495 additions and 61 deletions

View File

@ -33,6 +33,8 @@ public class Colors {
public Color c12 = C12.cpy();
public Color highlight = new Color(0.15f, 0.15f, 0.12f, 0);
public Color darken = new Color(0.40f, 0.40f, 0.40f, 0);
public Color darkenR = new Color(1.00f, 0.20f, 0.20f, 0);
public Color invBlue = new Color(0.1f, 0.1f, 0.5f, 0.3f);
public Color invGreen = new Color(0.1f, 0.5f, 0.1f, 0.3f);

View File

@ -29,6 +29,7 @@ import com.riiablo.codec.excel.MonStats2;
import com.riiablo.codec.excel.Obj;
import com.riiablo.codec.excel.ObjMode;
import com.riiablo.codec.excel.Objects;
import com.riiablo.codec.excel.Overlay;
import com.riiablo.codec.excel.PlrMode;
import com.riiablo.codec.excel.PlrType;
import com.riiablo.codec.excel.QualityItems;
@ -70,6 +71,7 @@ public class Files {
public final MonStats2 monstats2;
public final Objects objects;
public final ObjMode ObjMode;
public final Overlay Overlay;
public final PlrMode PlrMode;
public final PlrType PlrType;
public final QualityItems QualityItems;
@ -115,6 +117,7 @@ public class Files {
Runes = load(assets, Runes.class);
objects = load(assets, Objects.class);
ObjMode = load(assets, ObjMode.class);
Overlay = load(assets, Overlay.class, Excel.EXPANSION);
PlrMode = load(assets, PlrMode.class);
PlrType = load(assets, PlrType.class);
QualityItems = load(assets, QualityItems.class);

View File

@ -3,13 +3,12 @@ package com.riiablo;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.Field;
import com.riiablo.key.KeyMapper;
import com.riiablo.key.MappedKey;
import java.util.ArrayList;
import java.util.Collection;
import com.riiablo.key.KeyMapper;
import com.riiablo.key.MappedKey;
public class Keys {
public static Collection<Throwable> addTo(KeyMapper keyMapper) {
return addTo(keyMapper, Keys.class, new ArrayList<Throwable>(0));
@ -39,8 +38,29 @@ public class Keys {
public static final MappedKey Esc = new MappedKey("Esc", "esc", Input.Keys.ESCAPE, Input.Keys.BACK);
public static final MappedKey Inventory = new MappedKey("Inventory", "inventory", Input.Keys.I, Input.Keys.B);
public static final MappedKey Character = new MappedKey("Character", "character", Input.Keys.C, Input.Keys.A);
public static final MappedKey Spells = new MappedKey("Spells", "spells", Input.Keys.S, Input.Keys.T);
public static final MappedKey Stash = new MappedKey("Stash", "stash", Input.Keys.NUMPAD_1);
public static final MappedKey SwapWeapons = new MappedKey("SwapWeapons", "swap", Input.Keys.W);
public static final MappedKey Enter = new MappedKey("Enter", "enter", Input.Keys.ENTER);
public static final MappedKey Skill1 = new MappedKey("Skill 1", "skill1", Input.Keys.F1);
public static final MappedKey Skill2 = new MappedKey("Skill 2", "skill2", Input.Keys.F2);
public static final MappedKey Skill3 = new MappedKey("Skill 3", "skill3", Input.Keys.F3);
public static final MappedKey Skill4 = new MappedKey("Skill 4", "skill4", Input.Keys.F4);
public static final MappedKey Skill5 = new MappedKey("Skill 5", "skill5", Input.Keys.F5);
public static final MappedKey Skill6 = new MappedKey("Skill 6", "skill6", Input.Keys.F6);
public static final MappedKey Skill7 = new MappedKey("Skill 7", "skill7", Input.Keys.F7);
public static final MappedKey Skill8 = new MappedKey("Skill 8", "skill8", Input.Keys.F8);
public static final MappedKey Skill9 = new MappedKey("Skill 9", "skill9", MappedKey.NOT_MAPPED);
public static final MappedKey Skill10 = new MappedKey("Skill 10", "skill10", MappedKey.NOT_MAPPED);
public static final MappedKey Skill11 = new MappedKey("Skill 11", "skill11", MappedKey.NOT_MAPPED);
public static final MappedKey Skill12 = new MappedKey("Skill 12", "skill12", MappedKey.NOT_MAPPED);
public static final MappedKey Skill13 = new MappedKey("Skill 13", "skill13", MappedKey.NOT_MAPPED);
public static final MappedKey Skill14 = new MappedKey("Skill 14", "skill14", MappedKey.NOT_MAPPED);
public static final MappedKey Skill15 = new MappedKey("Skill 15", "skill15", MappedKey.NOT_MAPPED);
public static final MappedKey Skill16 = new MappedKey("Skill 16", "skill16", MappedKey.NOT_MAPPED);
public static final MappedKey Skill[] = new MappedKey[] {
Skill1, Skill2, Skill3, Skill4, Skill5, Skill6, Skill7, Skill8,
Skill9, Skill10, Skill11, Skill12, Skill13, Skill14, Skill15, Skill16
};
}

View File

@ -23,8 +23,8 @@ public class Animation extends BaseDrawable {
private static final int DEBUG_MODE = 1; // 0=off, 1=box, 2=layer box
private static final int NUM_LAYERS = COF.Component.NUM_COMPONENTS;
private static final float FRAMES_PER_SECOND = 25f;
private static final float FRAME_DURATION = 1 / FRAMES_PER_SECOND;
public static final float FRAMES_PER_SECOND = 25f;
public static final float FRAME_DURATION = 1 / FRAMES_PER_SECOND;
private static final Color SHADOW_TINT = Riiablo.colors.modal75;
private static final Affine2 SHADOW_TRANSFORM = new Affine2();
@ -36,6 +36,7 @@ public class Animation extends BaseDrawable {
private int direction;
private int frame;
private boolean looping;
private boolean clamp;
private float frameDuration;
private float elapsedTime;
private Layer layers[];
@ -59,23 +60,28 @@ public class Animation extends BaseDrawable {
numFrames = framesPerDir;
this.layers = layers;
looping = true;
clamp = true;
frameDuration = FRAME_DURATION;
box = new BBox();
animationListeners = EMPTY_MAP;
}
public static Animation newAnimation(com.riiablo.codec.DC dc) {
public static Animation newAnimation(DC dc) {
return Animation.builder().layer(dc).build();
}
public static Animation newAnimation(com.riiablo.codec.COF cof) {
public static Animation newAnimation(COF cof) {
Animation animation = new Animation();
animation.reset(cof);
return animation;
}
public boolean reset(com.riiablo.codec.COF cof) {
public COF getCOF() {
return cof;
}
public boolean reset(COF cof) {
if (this.cof != cof) {
this.cof = cof;
numDirections = cof.getNumDirections();
@ -83,10 +89,10 @@ public class Animation extends BaseDrawable {
setFrameDelta(cof.getAnimRate());
if (direction >= numDirections) direction = 0;
if (frame >= numFrames) {
//if (frame >= numFrames) {
frame = 0;
elapsedTime = 0;
}
//}
return true;
}
@ -108,17 +114,17 @@ public class Animation extends BaseDrawable {
for (Layer l : layers) if (l != null) l.load(d);
}
public Animation setLayer(int component, com.riiablo.codec.DC dc) {
public Animation setLayer(int component, DC dc) {
return setLayer(component, dc, true);
}
public Animation setLayer(int component, com.riiablo.codec.DC dc, boolean updateBox) {
public Animation setLayer(int component, DC dc, boolean updateBox) {
layers[component] = dc != null ? new Layer(dc).load(direction) : null;
if (updateBox) updateBox();
return this;
}
public Layer setLayer(com.riiablo.codec.COF.Layer cofLayer, com.riiablo.codec.DC dc, boolean updateBox) {
public Layer setLayer(COF.Layer cofLayer, DC dc, boolean updateBox) {
setLayer(cofLayer.component, dc, updateBox);
Layer layer = layers[cofLayer.component];
if (layer != null && cofLayer.overrideTransLvl != 0) {
@ -186,7 +192,7 @@ public class Animation extends BaseDrawable {
Preconditions.checkArgument(0 <= f && f < numFrames, "Invalid frame: " + f);
frame = f;
elapsedTime = frameDuration * frame;
if (frame == numFrames - 1) notifyAnimationFinished();
//if (frame == numFrames - 1) notifyAnimationFinished();
}
}
@ -202,6 +208,14 @@ public class Animation extends BaseDrawable {
looping = b;
}
public boolean isClamped() {
return clamp;
}
public void setClamp(boolean b) {
clamp = b;
}
public boolean isHighlighted() {
return highlighted;
}
@ -271,7 +285,7 @@ public class Animation extends BaseDrawable {
int frameNumber = (int) (stateTime / frameDuration);
return looping
? frameNumber % numFrames
: Math.min(numFrames - 1, frameNumber);
: Math.min(clamp ? numFrames - 1 : numFrames, frameNumber);
}
public void act() {
@ -305,8 +319,8 @@ public class Animation extends BaseDrawable {
shapes.setColor(Color.GREEN);
shapes.rect(x + box.xMin, y - box.yMax, box.width, box.height);
if (reset) shapes.end();
} else if (DEBUG_MODE == 2) {
int d = com.riiablo.codec.DC.Direction.toReadDir(direction, cof.getNumDirections());
} else if (DEBUG_MODE == 2 && frame < numFrames) {
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);
@ -326,15 +340,15 @@ public class Animation extends BaseDrawable {
}
public void draw(PaletteIndexedBatch batch, float x, float y) {
if (cof == null) {
if (cof == null && frame < numFrames) {
for (Layer layer : layers) {
if (layer == null) continue;
drawLayer(batch, layer, x, y);
}
batch.resetBlendMode();
batch.resetColormap();
} else {
int d = com.riiablo.codec.DC.Direction.toReadDir(direction, cof.getNumDirections());
} else if (frame < numFrames) {
int d = DC.Direction.toReadDir(direction, cof.getNumDirections());
int f = frame;
// TODO: Layer blend modes should correspond with the cof trans levels
for (int l = 0; l < cof.getNumLayers(); l++) {
@ -360,8 +374,8 @@ public class Animation extends BaseDrawable {
if (layer == null) continue;
drawShadow(batch, layer, x, y);
}
} else {
int d = com.riiablo.codec.DC.Direction.toReadDir(direction, cof.getNumDirections());
} else if (frame < numFrames) {
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);
@ -378,6 +392,10 @@ public class Animation extends BaseDrawable {
}
public void drawShadow(PaletteIndexedBatch batch, Layer layer, float x, float y) {
if (frame >= numFrames) {
return;
}
int d = direction;
int f = frame;
@ -407,8 +425,8 @@ public class Animation extends BaseDrawable {
if (layer == null) break;
box.max(layer.dc.getBox(direction));
}
} else {
int d = com.riiablo.codec.DC.Direction.toReadDir(direction, cof.getNumDirections());
} else if (frame < numFrames) {
int d = DC.Direction.toReadDir(direction, cof.getNumDirections());
int f = frame;
box.reset();
for (int l = 0; l < cof.getNumLayers(); l++) {
@ -493,11 +511,11 @@ public class Animation extends BaseDrawable {
Index transform;
int transformColor;
Layer(com.riiablo.codec.DC dc) {
Layer(DC dc) {
this(dc, BlendMode.ID);
}
Layer(com.riiablo.codec.DC dc, int blendMode) {
Layer(DC dc, int blendMode) {
this.dc = dc;
this.blendMode = blendMode;
tint = Color.WHITE;
@ -590,7 +608,7 @@ public class Animation extends BaseDrawable {
int size = 0;
Layer layers[] = new Layer[NUM_LAYERS];
public Builder layer(com.riiablo.codec.DC dc) {
public Builder layer(DC dc) {
return layer(new Layer(dc));
}

View File

@ -0,0 +1,40 @@
package com.riiablo.codec.excel;
public class Overlay extends Excel<Overlay.Entry> {
public static class Entry extends Excel.Entry {
@Override
public String toString() {
return overlay;
}
@Key
@Column
public String overlay;
@Column public String Filename;
@Column public int version;
@Column public int Frames;
@Column public String Character;
@Column public boolean PreDraw;
@Column(format = "1ofN")
public int _1ofN;
@Column public int Dir;
@Column public boolean Open;
@Column public boolean Beta;
@Column public int Xoffset;
@Column public int Yoffset;
@Column public int Height1;
@Column public int Height2;
@Column public int Height3;
@Column public int Height4;
@Column public int AnimRate;
@Column public int LoopWaitTime;
@Column public int Trans;
@Column public int InitRadius;
@Column public int Radius;
@Column public int Red;
@Column public int Green;
@Column public int Blue;
@Column public int NumDirections;
@Column public boolean LocalBlood;
}
}

View File

@ -28,5 +28,7 @@ public class Skills extends Excel<Skills.Entry> {
@Column public int lvlmana;
@Column(startIndex = 1, endIndex = 9)
public int Param[];
@Column public boolean leftskill;
@Column public boolean passive;
}
}

View File

@ -16,6 +16,8 @@ import com.riiablo.codec.Animation;
import com.riiablo.codec.COF;
import com.riiablo.codec.COFD2;
import com.riiablo.codec.DCC;
import com.riiablo.codec.excel.Overlay;
import com.riiablo.codec.excel.Skills;
import com.riiablo.codec.util.BBox;
import com.riiablo.graphics.PaletteIndexedBatch;
import com.riiablo.map.DS1;
@ -32,15 +34,16 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import gdx.diablo.BlendMode;
import gdx.diablo.Diablo;
public abstract class Entity {
public abstract class Entity implements Animation.AnimationListener {
private static final String TAG = "Entity";
private static final boolean DEBUG = true;
private static final boolean DEBUG_STATE = DEBUG && true;
private static final boolean DEBUG_DIRTY = DEBUG && true;
private static final boolean DEBUG_COF = DEBUG && true;
private static final boolean DEBUG_STATE = DEBUG && !true;
private static final boolean DEBUG_DIRTY = DEBUG && !true;
private static final boolean DEBUG_COF = DEBUG && !true;
private static final boolean DEBUG_TARGET = DEBUG && true;
private static final boolean DEBUG_PATH = DEBUG && !true;
@ -99,11 +102,14 @@ public abstract class Entity {
public final String MODE[];
public final String COMP[];
private ObjectIntMap<String> MODES;
private ObjectIntMap<String> COMPS;
Type(String path, String[] modes, String[] comps) {
PATH = "data\\global\\" + path;
MODE = modes;
MODES = new ObjectIntMap<>();
for (int i = 0; i < modes.length; i++) MODES.put(modes[i].toLowerCase(), i);
COMP = comps;
COMPS = new ObjectIntMap<>();
for (int i = 0; i < comps.length; i++) COMPS.put(comps[i].toLowerCase(), i);
@ -113,6 +119,10 @@ public abstract class Entity {
return Riiablo.cofs.active;
}
public byte getMode(String mode) {
return (byte) MODES.get(mode.toLowerCase(), -1);
}
public int getComponent(String comp) {
return COMPS.get(comp.toLowerCase(), -1);
}
@ -232,6 +242,9 @@ public abstract class Entity {
float walkSpeed = 6;
float runSpeed = 9;
Overlay.Entry overlayEntry;
Animation overlay;
private static final Vector2 tmpVec2 = new Vector2();
public static Entity create(Map map, Map.Zone zone, DS1 ds1, DS1.Object object) {
@ -390,6 +403,7 @@ public abstract class Entity {
private boolean updateAnimation(COF cof) {
if (animation == null) {
animation = Animation.newAnimation(cof);
animation.addAnimationListener(-1, this);
updateDirection();
return true;
} else {
@ -397,6 +411,16 @@ public abstract class Entity {
}
}
@Override
public void onTrigger(Animation animation, int frame) {
switch (frame) {
case -1: onAnimationFinished(animation); break;
default: // do nothing
}
}
protected void onAnimationFinished(Animation animation) {}
public String getCOF() {
return cof;
}
@ -406,6 +430,7 @@ public abstract class Entity {
}
public void act(float delta) {
if (overlay != null) overlay.act(delta);
if (animation != null) animation.act(delta);
}
@ -413,12 +438,14 @@ public abstract class Entity {
validate();
float x = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
float y = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
if (overlayEntry != null && overlayEntry.PreDraw) overlay.draw(batch, x, y);
animation.draw(batch, x, y);
if (overlayEntry != null && !overlayEntry.PreDraw) overlay.draw(batch, x, y);
label.setPosition(x, y + getLabelOffset() + label.getHeight() / 2, Align.center);
if (nextMode >= 0 && animation.isFinished()) {
setMode(nextMode);
nextMode = -1;
}
//if (animation.isFinished() && nextMode >= 0) {
// setMode(nextMode);
// nextMode = -1;
//}
}
public void drawShadow(PaletteIndexedBatch batch) {
@ -523,6 +550,13 @@ public abstract class Entity {
angle(MathUtils.atan2(tmpVec2.y, tmpVec2.x));
}
public void lookAt(float x, float y) {
float x2 = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
float y2 = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
tmpVec2.set(x, y).sub(x2, y2);
angle(MathUtils.atan2(tmpVec2.y, tmpVec2.x));
}
public int direction() {
int numDirs = animation.getNumDirections();
return Direction.radiansToDirection(angle, numDirs);
@ -565,9 +599,11 @@ public abstract class Entity {
}
}
public void animate(byte transition, byte mode) {
public boolean sequence(byte transition, byte mode) {
boolean changed = this.mode != transition;
setMode(transition);
nextMode = mode;
return changed;
}
public Vector2 target() {
@ -648,11 +684,16 @@ public abstract class Entity {
}
public void update(float delta) {
if (animation != null && animation.isFinished() && nextMode >= 0) {
setMode(nextMode);
nextMode = -1;
}
if (target.isZero()) return;
if (position.epsilonEquals(target)) {
if (!targets.hasNext()) {
path.clear();
if (mode == (running ? getRunMode() : getWalkMode())) setMode(getNeutralMode());
if (isMoving(mode)) setMode(getNeutralMode());
return;
}
}
@ -677,4 +718,46 @@ public abstract class Entity {
}
}
}
public boolean isCasting(byte mode) {
return false;
}
public boolean isMoving(byte mode) {
return false;
}
public boolean isCastable(byte mode) {
return false;
}
public boolean cast(final int spell) {
if (!isCastable(mode)) return false;
setPath(null, null);
//if (mode == getNeutralMode()) return;
//animating = true;
final Skills.Entry skill = Riiablo.files.skills.get(spell);
byte tm = mode;
boolean changed = sequence(type.getMode(skill.anim), getNeutralMode());
if (!changed) return false;
System.out.println("cast " + type.MODE[tm] + "->" + type.MODE[mode]);
Riiablo.audio.play(skill.stsound, true);
if (!skill.castoverlay.isEmpty()) {
overlayEntry = Riiablo.files.Overlay.get(skill.castoverlay);
AssetDescriptor<DCC> descriptor = new AssetDescriptor<>("data\\global\\overlays\\" + overlayEntry.Filename + ".dcc", DCC.class);
Riiablo.assets.load(descriptor);
Riiablo.assets.finishLoadingAsset(descriptor);
DCC dcc = Riiablo.assets.get(descriptor);
overlay = Animation.builder()
.layer(dcc, overlayEntry.Trans == 3 ? BlendMode.LUMINOSITY : BlendMode.ID)
.build();
overlay.setLooping(false);
overlay.setClamp(false);
//overlay.setFrameDuration(1f / overlayEntry.AnimRate);
}
return true;
}
}

View File

@ -90,9 +90,9 @@ public class Object extends Entity {
}
@Override
public void animate(byte transition, byte mode) {
public boolean sequence(byte transition, byte mode) {
assert !base.CycleAnim[transition];
super.animate(transition, mode);
return super.sequence(transition, mode);
}
@Override
@ -158,7 +158,7 @@ public class Object extends Entity {
break;
case 23: // waypoint
if (mode == MODE_NU) {
animate(MODE_OP, MODE_ON);
sequence(MODE_OP, MODE_ON);
Riiablo.audio.play("object_waypoint_open", true);
}
break;

View File

@ -52,6 +52,10 @@ public class Player extends Entity {
//public static final byte MODE_GH = 18;
//public static final byte MODE_GH = 19;
private static final int MOVING_MODES = (1 << MODE_WL) | (1 << MODE_RN) | (1 << MODE_TW);
private static final int CASTING_MODES = (1 << MODE_SC);
private static final int CASTABLE_MODES = (1 << MODE_NU) | (1 << MODE_TN) | MOVING_MODES;
private static final String[] TOKENS = {"AM", "SO", "NE", "PA", "BA", "DZ", "AI"};
public static String getToken(int type) {
@ -87,6 +91,7 @@ public class Player extends Entity {
boolean ignoreUpdate;
public Stats stats;
public Skills skills;
public int[] skillBar;
public Map map;
public Map.Zone curZone;
public final CharacterClass charClass;
@ -100,12 +105,14 @@ public class Player extends Entity {
this(name, characterClass.id);
stats = new StatsImpl(name, characterClass.id);
skills = new SkillsImpl();
skillBar = new int[16];
}
public Player(D2S d2s) {
this(d2s.name, d2s.charClass);
stats = new D2SStats(d2s);
skills = new D2SSkills(d2s);
skillBar = d2s.skillBar;
loadEquipped(d2s.items.equipped);
loadInventory(d2s.items.inventory);
}
@ -359,6 +366,21 @@ public class Player extends Entity {
}
}
@Override
public boolean isCasting(byte mode) {
return (CASTING_MODES & (1 << mode)) != 0;
}
@Override
public boolean isCastable(byte mode) {
return (CASTABLE_MODES & (1 << mode)) != 0;
}
@Override
public boolean isMoving(byte mode) {
return (MOVING_MODES & (1 << mode)) != 0;
}
private void notifySlotChanged(BodyLoc bodyLoc, Item oldItem, Item item) {
for (SlotListener l : SLOT_LISTENERS) l.onChanged(this, bodyLoc, oldItem, item);
}

View File

@ -53,6 +53,10 @@ public class MappedKey implements Iterable<Integer> {
private final Set<AssignmentListener> ASSIGNMENT_LISTENERS = new CopyOnWriteArraySet<>();
private final Set<StateListener> STATE_LISTENERS = new CopyOnWriteArraySet<>();
public MappedKey(String name, String alias) {
this(name, alias, NOT_MAPPED, NOT_MAPPED);
}
public MappedKey(String name, String alias, @Keycode int primary) {
this(name, alias, primary, NOT_MAPPED);
}
@ -60,8 +64,9 @@ public class MappedKey implements Iterable<Integer> {
public MappedKey(String name, String alias, @Keycode int primary, @Keycode int secondary) {
Preconditions.checkArgument(!name.isEmpty(), "name cannot be empty");
Preconditions.checkArgument(!alias.isEmpty(), "alias cannot be empty");
Preconditions.checkArgument(primary != NOT_MAPPED, "primary key mapping must be mapped");
Preconditions.checkArgument(primary != secondary, "key mappings must be unique");
//Preconditions.checkArgument(primary != NOT_MAPPED, "primary key mapping must be mapped");
//Preconditions.checkArgument(primary != secondary, "key mappings must be unique");
Preconditions.checkArgument(primary == NOT_MAPPED || primary != secondary, "key mappings must be unique");
NAME = name;
ALIAS = alias;

View File

@ -555,6 +555,10 @@ public class Map implements Disposable {
return null;
}
public Zone getZone(Vector2 pos) {
return getZone(Map.round(pos.x), Map.round(pos.y));
}
Zone addZone(Levels.Entry level, int diff, LvlPrest.Entry preset, int ds1) {
assert preset.LevelId != 0 : "presets should have an assigned level id";
Zone zone = addZone(level, diff, level.SizeX[diff], level.SizeY[diff]);

View File

@ -21,6 +21,7 @@ import com.riiablo.Riiablo;
import com.riiablo.codec.DC6;
import com.riiablo.screen.GameScreen;
import com.riiablo.widget.Button;
import com.riiablo.widget.HotkeyButton;
public class ControlPanel extends Table implements Disposable {
private static final String TAG = "ControlPanel";
@ -39,11 +40,11 @@ public class ControlPanel extends Table implements Disposable {
final AssetDescriptor<DC6> SkilliconDescriptor = new AssetDescriptor<>("data\\global\\ui\\SPELLS\\Skillicon.DC6", DC6.class);
DC6 Skillicon;
Button leftSkill, rightSkill;
HotkeyButton leftSkill, rightSkill;
GameScreen gameScreen;
public ControlPanel(GameScreen gameScreen) {
public ControlPanel(final GameScreen gameScreen) {
this.gameScreen = gameScreen;
Riiablo.assets.load(hlthmanaDescriptor);
Riiablo.assets.finishLoadingAsset(hlthmanaDescriptor);
@ -66,14 +67,20 @@ public class ControlPanel extends Table implements Disposable {
manaWidget = new ManaWidget(ctrlpnl.getTexture(numFrames - 2));
if (!DEBUG_MOBILE && Gdx.app.getType() == Application.ApplicationType.Desktop) {
leftSkill = new Button(new Button.ButtonStyle() {{
up = new TextureRegionDrawable(Skillicon.getTexture(0));
down = new TextureRegionDrawable(Skillicon.getTexture(1));
}});
rightSkill = new Button(new Button.ButtonStyle() {{
up = new TextureRegionDrawable(Skillicon.getTexture(0));
down = new TextureRegionDrawable(Skillicon.getTexture(1));
}});
leftSkill = new HotkeyButton(Skillicon, 0);
leftSkill.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
gameScreen.spellsQuickPanelL.setVisible(!gameScreen.spellsQuickPanelL.isVisible());
}
});
rightSkill = new HotkeyButton(Skillicon, 0);
rightSkill.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
gameScreen.spellsQuickPanelR.setVisible(!gameScreen.spellsQuickPanelR.isVisible());
}
});
int width = 0;
int height = Integer.MIN_VALUE;
@ -108,6 +115,14 @@ public class ControlPanel extends Table implements Disposable {
//setDebug(true, true);
}
public HotkeyButton getLeftSkill() {
return leftSkill;
}
public HotkeyButton getRightSkill() {
return rightSkill;
}
@Override
public void dispose() {
Riiablo.assets.unload(ctrlpnlDescriptor.fileName);

View File

@ -0,0 +1,127 @@
package com.riiablo.panel;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectMap;
import com.riiablo.CharacterClass;
import com.riiablo.Keys;
import com.riiablo.Riiablo;
import com.riiablo.codec.DC6;
import com.riiablo.codec.excel.SkillDesc;
import com.riiablo.codec.excel.Skills;
import com.riiablo.entity.Player;
import com.riiablo.key.MappedKey;
import com.riiablo.key.MappedKeyStateAdapter;
import com.riiablo.screen.GameScreen;
import com.riiablo.widget.HotkeyButton;
import org.apache.commons.lang3.ArrayUtils;
public class SpellsQuickPanel extends Table implements Disposable {
final AssetDescriptor<DC6> SkilliconDescriptor = new AssetDescriptor<>("data\\global\\ui\\SPELLS\\Skillicon.DC6", DC6.class);
DC6 Skillicon;
final AssetDescriptor<DC6> CharSkilliconDescriptor;
DC6 CharSkillicon;
GameScreen gameScreen;
ObjectMap<MappedKey, HotkeyButton> keyMappings;
MappedKeyStateAdapter mappedKeyListener;
public SpellsQuickPanel(final GameScreen gameScreen, final boolean leftSkills) {
this.gameScreen = gameScreen;
Riiablo.assets.load(SkilliconDescriptor);
Riiablo.assets.finishLoadingAsset(SkilliconDescriptor);
Skillicon = Riiablo.assets.get(SkilliconDescriptor);
Player player = gameScreen.player;
CharacterClass charClass = player.charClass;
CharSkilliconDescriptor = new AssetDescriptor<>("data\\global\\ui\\SPELLS\\" + charClass.spellIcons + ".DC6", DC6.class);
Riiablo.assets.load(CharSkilliconDescriptor);
Riiablo.assets.finishLoadingAsset(CharSkilliconDescriptor);
CharSkillicon = Riiablo.assets.get(CharSkilliconDescriptor);
keyMappings = new ObjectMap<>(31);
Table top = new Table() {{
add(new HotkeyButton(Skillicon, 14));
add(new HotkeyButton(Skillicon, 18));
pack();
}};
Table[] tables = new Table[5];
for (int i = charClass.firstSpell; i < charClass.lastSpell; i++) {
if (player.skills.getLevel(i) <= 0) continue;
final Skills.Entry skill = Riiablo.files.skills.get(i);
if (leftSkills && !skill.leftskill) continue;
if (skill.passive) continue;
final SkillDesc.Entry desc = Riiablo.files.skilldesc.get(skill.skilldesc);
Table table = tables[desc.ListRow];
if (table == null) table = tables[desc.ListRow] = new Table();
final HotkeyButton button = new HotkeyButton(CharSkillicon, desc.IconCel);
int index = ArrayUtils.indexOf(player.skillBar, i);
if (index != ArrayUtils.INDEX_NOT_FOUND) {
MappedKey mapping = Keys.Skill[index];
button.map(mapping);
keyMappings.put(mapping, button);
}
button.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
ControlPanel controlPanel = gameScreen.controlPanel;
if (leftSkills) {
controlPanel.getLeftSkill().copy(button);
} else {
controlPanel.getRightSkill().copy(button);
}
}
});
table.add(button);
}
Table bottom = new Table() {{
add(new HotkeyButton(Skillicon, 4));
add(new HotkeyButton(Skillicon, 6));
add(new HotkeyButton(Skillicon, 2));
pack();
}};
add(top).align(leftSkills ? Align.left : Align.right).row();
for (int i = tables.length - 1; i >= 0; i--) {
if (tables[i] != null) {
add(tables[i]).align(leftSkills ? Align.left : Align.right).row();
}
}
add(bottom).align(leftSkills ? Align.left : Align.right).row();
pack();
//setDebug(true, true);
mappedKeyListener = new MappedKeyStateAdapter() {
@Override
public void onPressed(MappedKey key, int keycode) {
HotkeyButton button = keyMappings.get(key);
if (button == null) return;
// TODO: Assign
ControlPanel controlPanel = gameScreen.controlPanel;
if (leftSkills) {
controlPanel.getLeftSkill().copy(button);
} else {
controlPanel.getRightSkill().copy(button);
}
}
};
for (MappedKey Skill : Keys.Skill) Skill.addStateListener(mappedKeyListener);
}
@Override
public void dispose() {
for (MappedKey Skill : Keys.Skill) Skill.removeStateListener(mappedKeyListener);
Riiablo.assets.unload(SkilliconDescriptor.fileName);
Riiablo.assets.unload(CharSkilliconDescriptor.fileName);
}
}

View File

@ -55,6 +55,7 @@ import com.riiablo.panel.InventoryPanel;
import com.riiablo.panel.MobileControls;
import com.riiablo.panel.MobilePanel;
import com.riiablo.panel.SpellsPanel;
import com.riiablo.panel.SpellsQuickPanel;
import com.riiablo.panel.StashPanel;
import com.riiablo.server.Connect;
import com.riiablo.server.ConnectResponse;
@ -93,13 +94,15 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
Actor left;
Actor right;
ControlPanel controlPanel;
public ControlPanel controlPanel;
MobilePanel mobilePanel;
MobileControls mobileControls;
public InventoryPanel inventoryPanel;
public CharacterPanel characterPanel;
public SpellsPanel spellsPanel;
public StashPanel stashPanel;
public SpellsQuickPanel spellsQuickPanelL;
public SpellsQuickPanel spellsQuickPanelR;
MappedKeyStateAdapter mappedKeyStateListener;
Stage stage;
@ -232,6 +235,14 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
0,
stage.getHeight() - stashPanel.getHeight());
spellsQuickPanelL = new SpellsQuickPanel(this, true);
spellsQuickPanelL.setPosition(0, 100, Align.bottomLeft);
spellsQuickPanelL.setVisible(false);
spellsQuickPanelR = new SpellsQuickPanel(this, false);
spellsQuickPanelR.setPosition(stage.getWidth(), 100, Align.bottomRight);
spellsQuickPanelR.setVisible(false);
//stage.setDebugAll(true);
if (mobilePanel != null) stage.addActor(mobilePanel);
if (mobileControls != null) stage.addActor(mobileControls);
@ -243,6 +254,8 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
stage.addActor(spellsPanel);
stage.addActor(characterPanel);
stage.addActor(stashPanel);
stage.addActor(spellsQuickPanelL);
stage.addActor(spellsQuickPanelR);
controlPanel.toFront();
if (mobilePanel != null) mobilePanel.toFront();
output.toFront();
@ -493,6 +506,22 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
} else {*/
mapListener.update();
//}
if (Gdx.input.isKeyPressed(Input.Keys.F1) || Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
mapRenderer.unproject(tmpVec2.set(Gdx.input.getX(), Gdx.input.getY()));
player.lookAt(tmpVec2.x, tmpVec2.y);
boolean cast = player.cast(54);
if (cast) {
GridPoint2 dst = mapRenderer.coords(tmpVec2.x, tmpVec2.y);
player.position().set(dst.x, dst.y);
player.target().setZero();
player.setPath(null, null);
}
} else if (Gdx.input.isKeyPressed(Input.Keys.F2)) {
mapRenderer.unproject(tmpVec2.set(Gdx.input.getX(), Gdx.input.getY()));
player.lookAt(tmpVec2.x, tmpVec2.y);
boolean cast = player.cast(36);
}
}
else if (DEBUG_HIT) Gdx.app.debug(TAG, hit.toString());
}
@ -781,6 +810,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
}
private void displayEntry() {
if (curZone == null) return;
if (enteringImage == null) {
enteringImage = new DCWrapper();
enteringImage.setScaling(Scaling.none);
@ -795,8 +825,7 @@ public class GameScreen extends ScreenAdapter implements LoadingScreen.Loadable
Riiablo.assets.load(entryDescriptor);
Riiablo.assets.finishLoadingAsset(entryDescriptor);
enteringImage.setDrawable(Riiablo.assets.get(entryDescriptor));
enteringImage.setPosition(stage.getWidth() / 2, stage.getHeight() * 0.75f, Align.center);
System.out.println(enteringImage.getWidth() + ", " + enteringImage.getHeight());
enteringImage.setPosition(stage.getWidth() / 2, stage.getHeight() * 0.8f, Align.center);
enteringImage.clearActions();
enteringImage.addAction(Actions.sequence(
Actions.show(),

View File

@ -17,6 +17,12 @@ public class Button extends com.badlogic.gdx.scenes.scene2d.ui.Button implements
private static final AssetDescriptor<Sound> buttonDescriptor = new AssetDescriptor<>("data\\global\\sfx\\cursor\\button.wav", Sound.class);
int disabledBlendMode = BlendMode.DARKEN;
Color disabledColor = Riiablo.colors.darken;
int highlightedBlendMode = BlendMode.BRIGHTEN;
Color highlightedColor = Riiablo.colors.highlight;
@Override
public void setStyle(com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle style) {
super.setStyle(style);
@ -47,6 +53,16 @@ public class Button extends com.badlogic.gdx.scenes.scene2d.ui.Button implements
});
}
public void setDisabledBlendMode(int blendMode, Color color) {
disabledBlendMode = blendMode;
disabledColor = color;
}
public void setHighlightedBlendMode(int blendMode, Color color) {
highlightedBlendMode = blendMode;
highlightedColor = color;
}
@Override
public void dispose() {
Riiablo.assets.unload(buttonDescriptor.fileName);
@ -63,15 +79,19 @@ public class Button extends com.badlogic.gdx.scenes.scene2d.ui.Button implements
// FIXME: super.draw(Batch,float) sets color and applies to batch, circumventing my own color -- workaround is to set actor's color
public void draw(PaletteIndexedBatch batch, float parentAlpha) {
final boolean over = isOver() && !isDisabled();
if (isDisabled()) {
setColor(Riiablo.colors.trans50);
final boolean disabled = isDisabled();
final boolean over = isOver();
if (disabled) {
setColor(disabledColor);
batch.setBlendMode(disabledBlendMode);
} else if (over) {
setColor(highlightedColor);
batch.setBlendMode(highlightedBlendMode);
} else {
setColor(over ? Riiablo.colors.highlight : Color.WHITE);
setColor(Color.WHITE);
}
if (over) batch.setBlendMode(BlendMode.BRIGHTEN);
super.draw(batch, parentAlpha);
if (over) batch.resetBlendMode();
if (disabled || over) batch.resetBlendMode();
}
public static class ButtonStyle extends com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle {

View File

@ -0,0 +1,44 @@
package com.riiablo.widget;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.riiablo.Riiablo;
import com.riiablo.codec.DC;
import com.riiablo.graphics.BlendMode;
import com.riiablo.key.MappedKey;
public class HotkeyButton extends Button {
MappedKey mapping;
Label label;
public HotkeyButton(final DC dc, final int index) {
super(new ButtonStyle() {{
up = new TextureRegionDrawable(dc.getTexture(index));
down = new TextureRegionDrawable(dc.getTexture(index + 1));
disabled = up;
pressedOffsetX = pressedOffsetY = -2;
}});
add(label = new Label("", Riiablo.fonts.font16, Riiablo.colors.gold));
align(Align.topRight);
pad(2);
pack();
setDisabledBlendMode(BlendMode.DARKEN, Riiablo.colors.darkenR);
}
public void map(MappedKey mapping) {
this.mapping = mapping;
label.setText(Input.Keys.toString(mapping.getPrimaryAssignment()));
}
public MappedKey getMapping() {
return mapping;
}
public void copy(HotkeyButton other) {
setStyle(other.getStyle());
label.setText(other.label.getText());
}
}