/*
* This file is part of the Haven & Hearth game client.
* Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and
* Björn Johannessen <johannessen.bjorn@gmail.com>
*
* Redistribution and/or modification of this file is subject to the
* terms of the GNU Lesser General Public License, version 3, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Other parts of this source tree adhere to other copying
* rights. Please see the file `COPYING' in the root directory of the
* source tree for details.
*
* A copy the GNU Lesser General Public License is distributed along
* with the source tree of which this file is a part in the file
* `doc/LPGL-3'. If it is missing for any reason, please see the Free
* Software Foundation's website at <http://www.fsf.org/>, or write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package haven;
import static haven.Inventory.invsq;
import static haven.Inventory.isqsz;
import haven.res.lib.HomeTrackerFX;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.ender.timer.TimerController;
public class GameUI extends ConsoleHost implements Console.Directory {
public final String chrid;
private static final int fkeys[] = {KeyEvent.VK_F1, KeyEvent.VK_F2, KeyEvent.VK_F3, KeyEvent.VK_F4,
KeyEvent.VK_F5, KeyEvent.VK_F6, KeyEvent.VK_F7, KeyEvent.VK_F8,
KeyEvent.VK_F9, KeyEvent.VK_F10, KeyEvent.VK_F11, KeyEvent.VK_F12};
private static final int nkeys[] = {KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4,
KeyEvent.VK_5, KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8,
KeyEvent.VK_9, KeyEvent.VK_0, KeyEvent.VK_MINUS, KeyEvent.VK_EQUALS};
public final long plid;
public final EquipProxyWdg equipProxy;
public MenuGrid menu;
public CraftWnd craftwnd;
public Tempers tm;
public Gobble gobble;
public MapView map;
public LocalMiniMap mmap;
public Fightview fv;
public static final Text.Foundry errfoundry = new Text.Foundry(new java.awt.Font("SansSerif", java.awt.Font.BOLD, 14), new Color(192, 0, 0));
private Text lasterr;
private long errtime;
private InvWindow invwnd;
private Window equwnd, makewnd;
public Inventory maininv;
public WeightWdg weightwdg;
public MainMenu mainmenu;
public BuddyWnd buddies;
public CharWnd chrwdg;
public Polity polity;
public HelpWnd help;
public OptWnd opts;
public Collection<GItem> hand = new LinkedList<GItem>();
private WItem vhand;
public ChatUI chat;
public FilterWnd filter = new FilterWnd(this);
public ChatUI.Channel syslog;
private HomeTrackerFX.HTrackWdg hrtptr;
public int prog = -1;
private boolean afk = false;
@SuppressWarnings("unchecked")
public Indir<Resource>[] belt = new Indir[144];
public Indir<Resource> lblk, dblk;
// Belt beltwdg;
public String polowner;
public int weight;
public abstract class Belt extends Widget {
public Belt(Coord c, Coord sz, Widget parent) {
super(c, sz, parent);
}
public void keyact(final int slot) {
if(map != null) {
Coord mvc = map.rootxlate(ui.mc);
if(mvc.isect(Coord.z, map.sz)) {
map.delay(map.new Hittest(mvc) {
protected void hit(Coord pc, Coord mc, MapView.ClickInfo inf) {
if(inf == null)
GameUI.this.wdgmsg("belt", slot, 1, ui.modflags(), mc);
else
GameUI.this.wdgmsg("belt", slot, 1, ui.modflags(), mc, (int)inf.gob.id, inf.gob.rc);
}
protected void nohit(Coord pc) {
GameUI.this.wdgmsg("belt", slot, 1, ui.modflags());
}
});
}
}
}
}
@RName("gameui")
public static class $_ implements Factory {
public Widget create(Coord c, Widget parent, Object[] args) {
String chrid = (String)args[0];
int plid = (Integer)args[1];
return(new GameUI(parent, chrid, plid));
}
}
public GameUI(Widget parent, String chrid, long plid) {
super(Coord.z, parent.sz, parent);
ui.gui = this;
this.chrid = chrid;
this.plid = plid;
setcanfocus(true);
setfocusctl(true);
menu = new MenuGrid(Coord.z, this);
new SeasonImg(new Coord(2,2), Avaview.dasz, this);
new Bufflist(new Coord(80, 40), this);
equipProxy = new EquipProxyWdg(new Coord(80, 2), new int[]{6, 7, 9, 14, 5, 4}, this);
tm = new Tempers(Coord.z, this);
chat = new ChatUI(Coord.z, 0, this);
syslog = new ChatUI.Log(chat, "System");
ui.cons.out = new java.io.PrintWriter(new java.io.Writer() {
StringBuilder buf = new StringBuilder();
public void write(char[] src, int off, int len) {
buf.append(src, off, len);
int p;
while((p = buf.indexOf("\n")) >= 0) {
syslog.append(buf.substring(0, p), Color.WHITE);
buf.delete(0, p + 1);
}
}
public void close() {}
public void flush() {}
});
opts = new OptWnd(sz.sub(200, 200).div(2), this);
opts.hide();
TimerController.init(Config.server);
makemenu();
resize(sz);
}
public static class MenuButton extends IButton {
private final int gkey;
private long flash;
private Tex glowmask;
MenuButton(Coord c, Widget parent, String base, int gkey, String tooltip) {
super(c, parent, Resource.loadimg("gfx/hud/" + base + "up"), Resource.loadimg("gfx/hud/" + base + "down"));
this.tooltip = Text.render(tooltip);
this.gkey = (char)gkey;
}
public void click() {}
protected void toggle(){
BufferedImage sel = up;
BufferedImage img = down;
hover = up = img;
down = sel;
}
public boolean globtype(char key, KeyEvent ev) {
if((gkey != -1) && (key == gkey)) {
click();
return(true);
}
return(super.globtype(key, ev));
}
public void draw(GOut g) {
super.draw(g);
if(flash > 0) {
if(glowmask == null)
glowmask = new TexI(PUtils.glowmask(PUtils.glowmask(up.getRaster()), 10, new Color(192, 255, 64)));
g = g.reclipl(new Coord(-10, -10), g.sz.add(20, 20));
double ph = (System.currentTimeMillis() - flash) / 1000.0;
g.chcolor(255, 255, 255, (int)(128 * ((Math.cos(ph * Math.PI * 2) * -0.5) + 0.5)));
g.image(glowmask, Coord.z);
g.chcolor();
}
}
public void flash(boolean f) {
if(f) {
if(flash == 0)
flash = System.currentTimeMillis();
} else {
flash = 0;
}
}
}
public static class MenuButtonT extends MenuButton{
MenuButtonT(Coord c, Widget parent, String base, int gkey, String tooltip) {
super(c, parent, base, gkey, tooltip);
hover = down;
}
@Override
protected void toggle() {
BufferedImage img = up;
up = hover;
hover = img;
down = img;
}
}
static class Hidewnd extends Window {
Hidewnd(Coord c, Coord sz, Widget parent, String cap) {
super(c, sz, parent, cap);
}
public void wdgmsg(Widget sender, String msg, Object... args) {
if((sender == this) && msg.equals("close")) {
this.hide();
return;
}
super.wdgmsg(sender, msg, args);
}
}
public static class InvWindow extends Hidewnd {
private final Map<Inventory, String> names = new HashMap<Inventory, String>();
private Label[] labels = new Label[0];
private final GameUI wui;
private final Label wlbl;
@RName("invwnd")
public static class $_ implements Factory {
public Widget create(Coord c, Widget parent, Object[] args) {
String cap = (String)args[0];
return(new InvWindow(c, new Coord(100, 100), parent, cap, null));
}
}
public InvWindow(Coord c, Coord sz, Widget parent, String cap, GameUI wui) {
super(c, sz, parent, cap);
if((this.wui = wui) != null) {
wlbl = new Label(Coord.z, this, "");
updweight();
} else {
wlbl = null;
}
}
private void updweight() {
int weight = wui.weight;
int cap = 25000;
Glob.CAttr ca = ui.sess.glob.cattr.get("carry");
if(ca != null)
cap = ca.comp;
wlbl.settext(String.format("Carrying %.2f/%.2f kg", weight / 1000.0, cap / 1000.0));
wlbl.setcolor((weight > cap)?Color.RED:Color.WHITE);
}
private void repack() {
for(Label lbl : labels) {
if(lbl != null)
lbl.destroy();
}
int mw = 0;
for(Inventory inv : names.keySet())
mw = Math.max(mw, inv.sz.x);
List<String> cn = new ArrayList<String>();
for(String nm : names.values()) {
if(!cn.contains(nm))
cn.add(nm);
}
Collections.sort(cn);
Label[] nl = new Label[cn.size()];
int n = 0, y = 0;
for(String nm : cn) {
if(!nm.equals("")) {
nl[n] = new Label(new Coord(0, y), this, nm);
y = nl[n].c.y + nl[n].sz.y + 5;
}
int x = 0;
int mh = 0;
for(Map.Entry<Inventory, String> e : names.entrySet()) {
if(e.getValue().equals(nm)) {
Inventory inv = e.getKey();
if((x > 0) && ((x + inv.sz.x) > mw)) {
x = 0;
y += mh + 5;
mh = 0;
}
inv.c = new Coord(x, y);
mh = Math.max(mh, inv.sz.y);
x += inv.sz.x + 5;
}
}
y += mh + 5;
n++;
}
if(wlbl != null)
wlbl.c = new Coord(0, y);
this.labels = nl;
pack();
}
public Widget makechild(String type, Object[] pargs, Object[] cargs) {
String nm;
if(pargs.length > 0)
nm = (String)pargs[0];
else
nm = "";
Inventory inv = (Inventory)gettype(type).create(Coord.z, this, cargs);
names.put(inv, nm);
repack();
return(inv);
}
public void cdestroy(Widget w) {
if((w instanceof Inventory) && names.containsKey(w)) {
Inventory inv = (Inventory)w;
names.remove(inv);
repack();
}
}
public void cresize(Widget w) {
if((w instanceof Inventory) && names.containsKey(w))
repack();
}
}
private void updhand() {
if((hand.isEmpty() && (vhand != null)) || ((vhand != null) && !hand.contains(vhand.item))) {
ui.destroy(vhand);
vhand = null;
}
if(!hand.isEmpty() && (vhand == null)) {
GItem fi = hand.iterator().next();
vhand = new ItemDrag(new Coord(15, 15), this, fi);
}
}
public Widget makechild(String type, Object[] pargs, Object[] cargs) {
String place = ((String)pargs[0]).intern();
if(place == "mapview") {
Coord cc = (Coord)cargs[0];
map = new MapView(Coord.z, sz, this, cc, plid);
map.lower();
if(mmap != null){
ui.destroy(mmap);
}
mmap = new LocalMiniMap(new Coord(0, sz.y - 125), new Coord(125, 125), this, map);
return(map);
} else if(place == "fight") {
fv = (Fightview)gettype(type).create(new Coord(sz.x - Fightview.width, 0), this, cargs);
return(fv);
} else if(place == "inv") {
String nm = (pargs.length > 1)?((String)pargs[1]):null;
if(invwnd == null) {
invwnd = new InvWindow(new Coord(100, 100), Coord.z, this, "Inventory", this);
invwnd.hide();
}
if(nm == null) {
Inventory inv = (Inventory)invwnd.makechild(type, new Object[0], cargs);
maininv = inv;
weightwdg = new WeightWdg(new Coord(10, 100), this);
return(inv);
} else {
return(invwnd.makechild(type, new Object[] {nm}, cargs));
}
} else if(place == "equ") {
equwnd = new Hidewnd(new Coord(400, 10), Coord.z, this, "Equipment");
Widget equ = gettype(type).create(Coord.z, equwnd, cargs);
equwnd.pack();
equwnd.hide();
return(equ);
} else if(place == "hand") {
GItem g = (GItem)gettype(type).create((Coord)pargs[1], this, cargs);
hand.add(g);
updhand();
return(g);
} else if(place == "craft") {
final Widget[] mk = {null};
showCraftWnd();
if(craftwnd != null){
mk[0] = gettype(type).create(new Coord(215, 250), craftwnd, cargs);
craftwnd.setMakewindow(mk[0]);
return (mk[0]);
} else {
makewnd = new Window(new Coord(350, 100), Coord.z, this, "Crafting") {
public void wdgmsg(Widget sender, String msg, Object... args) {
if((sender == this) && msg.equals("close")) {
mk[0].wdgmsg("close");
return;
}
super.wdgmsg(sender, msg, args);
}
public void cdestroy(Widget w) {
if(w == mk[0]) {
ui.destroy(this);
makewnd = null;
}
}
};
mk[0] = gettype(type).create(Coord.z, makewnd, cargs);
makewnd.pack();
return (mk[0]);
}
} else if(place == "buddy") {
buddies = (BuddyWnd)gettype(type).create(new Coord(187, 50), this, cargs);
buddies.hide();
return(buddies);
} else if(place == "pol") {
polity = (Polity)gettype(type).create(new Coord(500, 50), this, cargs);
polity.hide();
return(polity);
} else if(place == "chr") {
chrwdg = (CharWnd)gettype(type).create(new Coord(100, 50), this, cargs);
chrwdg.hide();
fixattrview(chrwdg);
return(chrwdg);
} else if(place == "chat") {
return(chat.makechild(type, new Object[] {}, cargs));
} else if(place == "party") {
return(gettype(type).create(new Coord(2, 80), this, cargs));
} else if(place == "misc") {
if(type.contains("ui/hrtptr")){
hrtptr = new HomeTrackerFX.HTrackWdg(this, gettype(type).create((Coord)pargs[1], this, cargs));
return hrtptr;
}
return(gettype(type).create((Coord)pargs[1], this, cargs));
} else {
throw(new UI.UIException("Illegal gameui child", type, pargs));
}
}
public Equipory getEquipory(){
if(equwnd != null){
for(Widget wdg = equwnd.child; wdg != null; wdg = wdg.next){
if(wdg instanceof Equipory){
return (Equipory) wdg;
}
}
}
return null;
}
public void cdestroy(Widget w) {
if((w instanceof GItem) && hand.contains(w)) {
hand.remove(w);
updhand();
} else if(w == polity) {
polity = null;
} else if(w == chrwdg) {
chrwdg = null;
attrview.destroy();
}
}
public void destroy() {
super.destroy();
OptWnd2.close();
TimerPanel.close();
DarknessWnd.close();
FlatnessTool.close();
WikiBrowser.close();
}
private Widget attrview;
private void fixattrview(final CharWnd cw) {
final IBox box = new IBox(Window.fbox.ctl, Tex.empty, Window.fbox.cbl, Tex.empty,
Window.fbox.bl, Tex.empty, Window.fbox.bt, Window.fbox.bb);
CharWnd.Attr a = (CharWnd.Attr)cw.attrwdgs.child;
final Coord moff = new Coord(20, 0);
attrview = new Widget(Coord.z, new Coord(a.expsz.x, cw.attrwdgs.sz.y).add(moff).add(10, Window.cbtni[0].getHeight() + 10).add(box.bisz()), this) {
boolean act = false;
Label la;
int cmod = 0;
{
Widget cbtn = new IButton(Coord.z, this, Window.cbtni[0], Window.cbtni[1], Window.cbtni[2]) {
public void click() {
act(false);
}
};
cbtn.c = new Coord(sz.x - cbtn.sz.x, box.bt.sz().y);
int y = cbtn.c.y + cbtn.sz.y;
cbtn = new IButton(Coord.z, this, Window.rbtni[0], Window.rbtni[1], Window.rbtni[2]) {
public void click() {
togglecw();
}
};
cbtn.c = new Coord(sz.x - Window.cbtni[0].getWidth() - cbtn.sz.x - 2, box.bt.sz().y);
la = new Label(box.btloff(), this, "LA: ");
Coord ctl = box.btloff().add(5, 5);
for(CharWnd.Attr a = (CharWnd.Attr)cw.attrwdgs.child; a != null; a = (CharWnd.Attr)a.next) {
final CharWnd.Attr ca = a;
new Widget(ctl.add(0, y), a.expsz.add(moff), this) {
public void draw(GOut g) {
g.image(ca.res.layer(Resource.imgc).tex(), Coord.z);
ca.drawmeter(g, moff, ca.expsz);
}
@Override
public boolean mousedown(Coord c, int button) {
boolean res = ca.mousedown(c.add(ca.expc), button);
ui.grabmouse(this);
return res;
}
@Override
public boolean mouseup(Coord c, int button) {
ui.grabmouse(null);
return ca.mouseup(c.add(ca.expc), button);
}
};
y += 20;
}
}
public void draw(GOut g) {
if(cmod != cw.tmexp){
cmod = cw.tmexp;
la.settext(String.format("LA: %d", cmod));
}
if((fv != null) && !fv.lsrel.isEmpty())
return;
g.chcolor(0, 0, 0, 128);
g.frect(box.btloff(), sz.sub(box.bisz()));
g.chcolor();
super.draw(g);
box.draw(g, Coord.z, sz);
}
public void presize() {
c = new Coord(GameUI.this.sz.x - sz.x, (menu.c.y - sz.y) / 2);
}
public boolean show(boolean show) {
return(super.show(show && act));
}
private void act(boolean act) {
Utils.setprefb("attrview", this.act = act);
show(act);
}
{
cw.addtwdg(new IButton(Coord.z, cw, Window.rbtni[0], Window.rbtni[1], Window.rbtni[2]) {
public void click() {
act(true);
cw.hide();
}
});
presize();
act(Utils.getprefb("attrview", false));
}
};
}
private void togglecw() {
if(chrwdg != null) {
if(chrwdg.show(!chrwdg.visible)) {
chrwdg.raise();
fitwdg(chrwdg);
setfocus(chrwdg);
}
attrview.show(!chrwdg.visible);
}
}
static Text.Furnace progf = new PUtils.BlurFurn(new Text.Foundry(new java.awt.Font("serif", java.awt.Font.BOLD, 24)).aa(true), 2, 1, new Color(0, 16, 16));
Text progt = null;
public void draw(GOut g) {
// boolean beltp = !chat.expanded;
// beltwdg.show(beltp);
super.draw(g);
if(prog >= 0) {
String progs = String.format("%d%%", prog);
if((progt == null) || !progs.equals(progt.text))
progt = progf.render(progs);
g.aimage(progt.tex(), new Coord(sz.x / 2, (sz.y * 4) / 10), 0.5, 0.5);
}
int by = sz.y;
if(chat.expanded)
by = Math.min(by, chat.c.y);
// if(beltwdg.visible)
// by = Math.min(by, beltwdg.c.y);
int bx = mainmenu.sz.x + 10;
if(cmdline != null) {
drawcmd(g, new Coord(bx, by -= 20));
} else if(lasterr != null) {
if((System.currentTimeMillis() - errtime) > 3000) {
lasterr = null;
} else {
g.chcolor(0, 0, 0, 192);
g.frect(new Coord(bx - 2, by - 22), lasterr.sz().add(4, 4));
g.chcolor();
g.image(lasterr.tex(), new Coord(bx, by -= 20));
}
}
if(!chat.expanded) {
chat.drawsmall(g, new Coord(bx, by), 50);
}
}
public void tick(double dt) {
super.tick(dt);
if(!afk && (System.currentTimeMillis() - ui.lastevent > 300000)) {
afk = true;
wdgmsg("afk");
} else if(afk && (System.currentTimeMillis() - ui.lastevent < 300000)) {
afk = false;
}
dwalkupd();
}
public void uimsg(String msg, Object... args) {
if(msg == "err") {
String err = (String)args[0];
error(err);
} else if(msg == "prog") {
if(args.length > 0)
prog = (Integer)args[0];
else
prog = -1;
} else if(msg == "setbelt") {
int slot = (Integer)args[0];
if(args.length < 2) {
belt[slot] = null;
} else {
belt[slot] = ui.sess.getres((Integer)args[1]);
}
} else if(msg == "ins") {
tm.updinsanity((Integer)args[0]);
} else if(msg == "stm") {
int[] n = new int[4];
for(int i = 0; i < 4; i++)
n[i] = (Integer)args[i];
tm.upds(n);
} else if(msg == "htm") {
int[] n = new int[4];
for(int i = 0; i < 4; i++)
n[i] = (Integer)args[i];
tm.updh(n);
} else if(msg == "gavail") {
tm.gavail = (Integer)args[0] != 0;
} else if(msg == "gobble") {
boolean g = (Integer)args[0] != 0;
if(g && (gobble == null)) {
tm.hide();
gobble = new Gobble(Coord.z, this);
resize(sz);
} else if(!g && (gobble != null)) {
ui.destroy(gobble);
gobble = null;
tm.show();
}
} else if(msg == "gtm") {
int[] n = new int[4];
for(int i = 0; i < 4; i++)
n[i] = (Integer)args[i];
gobble.updt(n);
} else if(msg == "glvlup") {
gobble.lvlup((Integer)args[0]);
} else if(msg == "glvls") {
gobble.lcount((Integer)args[0], (Color)args[1]);
} else if(msg == "gtypemod") {
gobble.typemod(ui.sess.getres((Integer)args[0]), ((Integer)args[1]) / 100.0);
} else if(msg == "polowner") {
String o = (String)args[0];
boolean n = ((Integer)args[1]) != 0;
if(o.length() == 0)
o = null;
else
o = o.intern();
if(o != polowner) {
if(map != null) {
if(o == null) {
if(polowner != null)
map.setpoltext("Leaving " + polowner);
} else {
map.setpoltext("Entering " + o);
}
}
polowner = o;
}
} else if(msg == "dblk") {
int id = (Integer)args[0];
dblk = (id < 0)?null:(ui.sess.getres(id));
} else if(msg == "lblk") {
int id = (Integer)args[0];
lblk = (id < 0)?null:(ui.sess.getres(id));
} else if(msg == "showhelp") {
Indir<Resource> res = ui.sess.getres((Integer)args[0]);
if(help == null)
help = new HelpWnd(sz.div(2).sub(150, 200), this, res);
else
help.res = res;
} else if(msg == "weight") {
weight = (Integer)args[0];
if(invwnd != null)
invwnd.updweight();
if(weightwdg != null){
weightwdg.update(weight);
}
} else {
super.uimsg(msg, args);
}
}
@Override
public void wdgmsg(String msg, Object... args) {
super.wdgmsg(msg, args);
if(msg.equals("belt")){
checkBelt(args);
}
}
private void checkBelt(Object... args) {
int index = (Integer) args[0];
Indir<Resource> indir = belt[index];
if(indir != null) {
Resource res = indir.get();
if (menu.isCrafting(res)) {
showCraftWnd();
}
if (craftwnd != null) {
craftwnd.select(res, true);
}
}
}
public void wdgmsg(Widget sender, String msg, Object... args) {
if(sender == menu) {
wdgmsg(msg, args);
return;
} else if((sender == buddies) && (msg == "close")) {
buddies.hide();
} else if((sender == polity) && (msg == "close")) {
polity.hide();
} else if((sender == chrwdg) && (msg == "close")) {
chrwdg.hide();
} else if((sender == help) && (msg == "close")) {
ui.destroy(help);
help = null;
return;
}
super.wdgmsg(sender, msg, args);
}
private void fitwdg(Widget wdg) {
if(wdg.c.x < 0)
wdg.c.x = 0;
if(wdg.c.y < 0)
wdg.c.y = 0;
if(wdg.c.x + wdg.sz.x > sz.x)
wdg.c.x = sz.x - wdg.sz.x;
if(wdg.c.y + wdg.sz.y > sz.y)
wdg.c.y = sz.y - wdg.sz.y;
}
/* Directional walking. Apparently AWT send repeated keyup/keydown
* events on key autorepeat (:-/), so hysteresis elimination of
* some kind is necessary. This variant waits 100 ms before
* accepting a keyup event. */
private boolean dwalking = false;
private Coord dwalkang = new Coord();
private long dwalkhys;
private float dwalkbase;
private boolean[] dkeys = {false, false, false, false};
private void dwalkupd() {
Coord a = new Coord();
if(dkeys[0]) a = a.add(1, 0);
if(dkeys[1]) a = a.add(0, 1);
if(dkeys[2]) a = a.add(-1, 0);
if(dkeys[3]) a = a.add(0, -1);
long now = System.currentTimeMillis();
if(!a.equals(dwalkang) && (now > dwalkhys)) {
if((a.x == 0) && (a.y == 0)) {
wdgmsg("dwalk");
} else {
float da = dwalkbase + (float)a.angle(Coord.z);
wdgmsg("dwalk", (int)((da / (Math.PI * 2)) * 1000));
}
dwalkang = a;
}
}
private int dwalkkey(char key) {
if(key == 'W')
return(0);
else if(key == 'D')
return(1);
else if(key == 'S')
return(2);
else if(key == 'A')
return(3);
throw(new Error());
}
private void dwalkdown(char key, KeyEvent ev) {
if(!dwalking) {
dwalking = true;
dwalkbase = -map.camera.angle();
ui.grabkeys(this);
}
int k = dwalkkey(key);
dkeys[k] = true;
dwalkhys = ev.getWhen();
}
private void dwalkup(char key, KeyEvent ev) {
int k = dwalkkey(key);
dkeys[k] = false;
dwalkhys = ev.getWhen() + 100;
if(!dkeys[0] && !dkeys[1] && !dkeys[2] && !dkeys[3]) {
dwalking = false;
ui.grabkeys(null);
}
}
private static final Tex menubg = Resource.loadtex("gfx/hud/menubg");
private static final Tex menubgfull = Resource.loadtex("gfx/hud/menubgfull");
public class MainMenu extends Widget {
public final MenuButton invb, equb, chrb, budb, polb, optb;
public final MenuButton clab, towb, warb, ptrb, chatb;
public boolean hpv = true, pv = hpv && !Config.hptr;
boolean full = true;
public Widget[] tohide = {
invb = new MenuButton(new Coord(4, 8), this, "inv", 9, "Inventory (Tab)") {
int seq = 0;
public void click() {
if((invwnd != null) && invwnd.show(!invwnd.visible)) {
invwnd.raise();
fitwdg(invwnd);
}
}
public void tick(double dt) {
if(maininv != null) {
if(invwnd.visible) {
seq = maininv.newseq;
flash(false);
} else if(maininv.newseq != seq) {
flash(true);
}
}
}
},
equb = new MenuButton(new Coord(62, 8), this, "equ", 5, "Equipment (Ctrl+E)") {
public void click() {
if((equwnd != null) && equwnd.show(!equwnd.visible)) {
equwnd.raise();
fitwdg(equwnd);
}
}
},
chrb = new MenuButton(new Coord(120, 8), this, "chr", 20, "Studying (Ctrl+T)") {
public void click() {
togglecw();
}
public void tick(double dt) {
if((chrwdg != null) && chrwdg.skavail)
flash(true);
else
flash(false);
}
},
budb = new MenuButton(new Coord(4, 66), this, "bud", 2, "Buddy List (Ctrl+B)") {
public void click() {
if((buddies != null) && buddies.show(!buddies.visible)) {
buddies.raise();
fitwdg(buddies);
setfocus(buddies);
}
}
},
polb = new MenuButton(new Coord(62, 66), this, "pol", 16, "Town (Ctrl+P)") {
final Tex gray = Resource.loadtex("gfx/hud/polgray");
public void draw(GOut g) {
if(polity == null)
g.image(gray, Coord.z);
else
super.draw(g);
}
public void click() {
if((polity != null) && polity.show(!polity.visible)) {
polity.raise();
fitwdg(polity);
setfocus(polity);
}
}
},
optb = new MenuButton(new Coord(120, 66), this, "opt", 15, "Options (Ctrl+O)") {
public void click() {
OptWnd2.toggle();
// if(opts.show(!opts.visible)) {
// opts.raise();
// fitwdg(opts);
// setfocus(opts);
// }
}
}
};
public IButton cash;
public IButton manual;
public MainMenu(Coord c, Coord sz, Widget parent) {
super(c, sz, parent);
int y = sz.y - 21;
int x = 6;
clab = new MenuButtonT(new Coord(x, y), this, "cla", -1, "Display personal claims") {
public void click() {
if(!map.visol(0))
map.enol(0, 1);
else
map.disol(0, 1);
toggle();
}
};
x+=18;
towb = new MenuButtonT(new Coord(x, y), this, "tow", -1, "Display town claims") {
public void click() {
if(!map.visol(2))
map.enol(2, 3);
else
map.disol(2, 3);
toggle();
}
};
x+=18;
warb = new MenuButtonT(new Coord(x, y), this, "war", -1, "Display waste claims") {
public void click() {
if(!map.visol(4))
map.enol(4);
else
map.disol(4);
toggle();
}
};
x+=18;
ptrb = new MenuButton(new Coord(x, y), this, "ptr", -1, "Display homstead pointer") {
public void click() {
hpv = !hpv;
pv = hpv && !Config.hptr;
}
};
x+=18;
new MenuButton(new Coord(x, y), this, "height", -1, "Display heightmap") {
{
hover = down;
down = Resource.loadimg("gfx/hud/heighthl");
}
public void click() {
mmap.toggleHeight();
toggle();
}
@Override
protected void toggle() {
BufferedImage img = up;
up = hover;
hover = down;
down = img;
}
};
x+=18;
chatb = new MenuButton(new Coord(x, y), this, "chat", 3, "Chat (Ctrl+C)") {
public void click() {
chat.toggle();
}
};
new MenuButton(new Coord(this.sz.x - 22, y), this, "gear", -1, "Menu") {
{
recthit = true;
hover = Resource.loadimg("gfx/hud/gearhl");
}
public void click() {
mainmenu.toggle();
toggle();
}
@Override
protected void toggle() {
BufferedImage img = up;
up = down;
down = img;
}
};
}
@Override
public void draw(GOut g) {
g.image(full?menubgfull:menubg, Coord.z);
super.draw(g);
}
public void toggle() {
full = !full;
for (Widget w: tohide){
w.visible = full;
}
if(cash != null){
cash.visible = full;
cash.presize();
}
if(manual != null){
manual.visible = full;
manual.presize();
}
}
}
public void showCraftWnd() {
showCraftWnd(false);
}
public void showCraftWnd(boolean force) {
if(craftwnd == null && (force || Config.autoopen_craftwnd)){
new CraftWnd(Coord.z, this);
}
}
public void toggleCraftWnd() {
if(craftwnd == null) {
showCraftWnd(true);
} else {
craftwnd.wdgmsg(craftwnd, "close");
}
}
public void toggleFilterWnd() {
filter.show(!filter.visible);
}
private void makemenu() {
mainmenu = new MainMenu(new Coord(0, sz.y - menubg.sz().y), menubg.sz(), this);
new Widget(Coord.z, isqsz.add(Window.swbox.bisz()), this) {
private final Tex none = Resource.loadtex("gfx/hud/blknone");
private Tex mono;
private Indir<Resource> monores;
{
tooltip = Text.render("Toggle maneuver (Ctrl+S)");
}
public void draw(GOut g) {
try {
if(lblk != null) {
g.image(lblk.get().layer(Resource.imgc).tex(), Window.swbox.btloff());
} else if(dblk != null) {
if(monores != dblk) {
if(mono != null) mono.dispose();
mono = new TexI(PUtils.monochromize(dblk.get().layer(Resource.imgc).img, new Color(128, 128, 128)));
monores = dblk;
}
g.image(mono, Window.swbox.btloff());
} else {
g.image(none, Window.swbox.btloff());
}
} catch(Loading e) {
}
g.chcolor(133, 92, 62, 255);
Window.swbox.draw(g, Coord.z, sz);
g.chcolor();
}
public void presize() {
this.c = menu.c.add(menu.sz.x, 0).sub(this.sz);
}
public boolean globtype(char key, KeyEvent ev) {
if(key == 19) {
act("blk");
return(true);
}
return(super.globtype(key, ev));
}
public boolean mousedown(Coord c, int btn) {
act("blk");
return(true);
}
}.presize();
if((Config.storeurl != null) && (WebBrowser.self != null)) {
IButton cash = new IButton(Coord.z, this, Resource.loadimg("gfx/hud/cashu"), Resource.loadimg("gfx/hud/cashd"), Resource.loadimg("gfx/hud/cashh")) {
{
tooltip = Text.render("Salem Store");
}
private String encode(String in) {
StringBuilder buf = new StringBuilder();
byte[] enc;
try {
enc = in.getBytes("utf-8");
} catch(java.io.UnsupportedEncodingException e) {
/* ¦] */
throw(new Error(e));
}
for(byte c : enc) {
if(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
((c >= '0') && (c <= '9')) || (c == '.')) {
buf.append((char)c);
} else {
buf.append("%" + Utils.num2hex((c & 0xf0) >> 4) + Utils.num2hex(c & 0x0f));
}
}
return(buf.toString());
}
public void click() {
URL base = Config.storeurl;
try {
WebBrowser.self.show(new URL(base.getProtocol(), base.getHost(), base.getPort(), base.getFile() + "?userid=" + encode(ui.sess.username)));
} catch(java.net.MalformedURLException e) {
throw(new RuntimeException(e));
} catch(WebBrowser.BrowserException e) {
error("Could not launch web browser.");
}
}
public void presize() {
c = new Coord(90, (mainmenu.c.y - sz.y));
}
public Object tooltip(Coord c, Widget prev) {
if(checkhit(c))
return(super.tooltip(c, prev));
return(null);
}
};
cash.presize();
mainmenu.cash = cash;
}
if((Config.manualurl != null) && (WebBrowser.self != null)) {
mainmenu.manual = new IButton(Coord.z, this, Resource.loadimg("gfx/hud/manu"), Resource.loadimg("gfx/hud/mand"), Resource.loadimg("gfx/hud/manh")) {
{
tooltip = Text.render("Open Manual");
}
public void click() {
URL base = Config.manualurl;
try {
WebBrowser.self.show(base);
} catch(WebBrowser.BrowserException e) {
error("Could not launch web browser.");
}
}
public void presize() {
this.c = mainmenu.c.sub(0, this.sz.y);
}
public Object tooltip(Coord c, Widget prev) {
if(checkhit(c))
return(super.tooltip(c, prev));
return(null);
}
};
mainmenu.manual.presize();
}
mainmenu.toggle();
}
public boolean globtype(char key, KeyEvent ev) {
char ukey = Character.toUpperCase(key);
if(key == ':') {
entercmd();
return(true);
} else if((Config.screenurl != null) && (ukey == 'S') && ((ev.getModifiersEx() & (KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0)) {
Screenshooter.take(this, Config.screenurl);
return(true);
} else if((ukey == 'W') || (ukey == 'A') || (ukey == 'S') || (ukey == 'D')) {
dwalkdown(ukey, ev);
return(true);
}
return(super.globtype(key, ev));
}
public boolean keydown(KeyEvent ev) {
char ukey = Character.toUpperCase(ev.getKeyChar());
if(dwalking && ((ukey == 'W') || (ukey == 'A') || (ukey == 'S') || (ukey == 'D'))) {
dwalkdown(ukey, ev);
return(true);
}
return(super.keydown(ev));
}
public boolean keyup(KeyEvent ev) {
char ukey = Character.toUpperCase(ev.getKeyChar());
if(dwalking && ((ukey == 'W') || (ukey == 'A') || (ukey == 'S') || (ukey == 'D'))) {
dwalkup(ukey, ev);
return(true);
}
return(super.keyup(ev));
}
public boolean mousedown(Coord c, int button) {
return(super.mousedown(c, button));
}
public void resize(Coord sz) {
this.sz = sz;
menu.c = sz.sub(menu.sz);
tm.c = new Coord((sz.x - tm.sz.x) / 2, 0);
chat.move(new Coord(mainmenu.sz.x, sz.y));
chat.resize(sz.x - chat.c.x - menu.sz.x);
if(gobble != null)
gobble.c = new Coord((sz.x - gobble.sz.x) / 2, 0);
if(map != null)
map.resize(sz);
if(fv != null)
fv.c = new Coord(sz.x - Fightview.width, 0);
mainmenu.c = new Coord(0, sz.y - mainmenu.sz.y);
// beltwdg.c = new Coord(mainmenu.sz.x + 10, sz.y - beltwdg.sz.y);
super.resize(sz);
}
public void presize() {
resize(parent.sz);
}
public void error(String msg) {
message(msg, MsgType.ERROR);
}
private static final Resource errsfx = Resource.load("sfx/error");
public void message(String msg, MsgType type) {
message(msg, getMsgColor(type));
}
public void message(String msg, Color msgColor) {
errtime = System.currentTimeMillis();
lasterr = errfoundry.render(msg, msgColor);
syslog.append(msg, msgColor);
Audio.play(errsfx);
}
public static Color getMsgColor(MsgType type)
{
switch (type){
case INFO:
return Color.CYAN;
case GOOD:
return Color.GREEN;
case BAD:
return Color.RED;
case ERROR:
return Color.RED;
}
return Color.WHITE;
}
public static enum MsgType{
INFO, GOOD, BAD, ERROR
}
public void act(String... args) {
wdgmsg("act", (Object[])args);
}
public void act(int mods, Coord mc, Gob gob, String... args) {
int n = args.length;
Object[] al = new Object[n];
System.arraycopy(args, 0, al, 0, n);
if(mc != null) {
al = Utils.extend(al, al.length + 2);
al[n++] = mods;
al[n++] = mc;
if(gob != null) {
al = Utils.extend(al, al.length + 2);
al[n++] = (int)gob.id;
al[n++] = gob.rc;
}
}
wdgmsg("act", al);
}
public class FKeyBelt extends Belt implements DTarget, DropTarget {
public final int beltkeys[] = {KeyEvent.VK_F1, KeyEvent.VK_F2, KeyEvent.VK_F3, KeyEvent.VK_F4,
KeyEvent.VK_F5, KeyEvent.VK_F6, KeyEvent.VK_F7, KeyEvent.VK_F8,
KeyEvent.VK_F9, KeyEvent.VK_F10, KeyEvent.VK_F11, KeyEvent.VK_F12};
public int curbelt = 0;
public FKeyBelt(Coord c, Widget parent) {
super(c, Inventory.invsz(new Coord(12, 1)), parent);
}
private Coord beltc(int i) {
return(Inventory.sqoff(new Coord(i, 0)));
}
private int beltslot(Coord c) {
for(int i = 0; i < 12; i++) {
if(c.isect(beltc(i), isqsz))
return(i + (curbelt * 12));
}
return(-1);
}
public void draw(GOut g) {
invsq(g, Coord.z, new Coord(12, 1));
for(int i = 0; i < 12; i++) {
int slot = i + (curbelt * 12);
Coord c = beltc(i);
try {
Indir<Resource> ir = belt[slot];
if(ir != null)
g.image(ir.get().layer(Resource.imgc).tex(), c);
} catch(Loading e) {}
g.chcolor(156, 180, 158, 255);
FastText.aprintf(g, c.add(isqsz), 1, 1, "F%d", i + 1);
g.chcolor();
}
}
public boolean mousedown(Coord c, int button) {
int slot = beltslot(c);
if(slot != -1) {
if(button == 1)
GameUI.this.wdgmsg("belt", slot, 1, ui.modflags());
if(button == 3)
GameUI.this.wdgmsg("setbelt", slot, 1);
return(true);
}
return(false);
}
public boolean globtype(char key, KeyEvent ev) {
if(key != 0)
return(false);
boolean M = (ev.getModifiersEx() & (KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0;
for(int i = 0; i < beltkeys.length; i++) {
if(ev.getKeyCode() == beltkeys[i]) {
if(M) {
curbelt = i;
return(true);
} else {
keyact(i + (curbelt * 12));
return(true);
}
}
}
return(false);
}
public boolean drop(Coord c, Coord ul) {
int slot = beltslot(c);
if(slot != -1) {
GameUI.this.wdgmsg("setbelt", slot, 0);
return(true);
}
return(false);
}
public boolean iteminteract(Coord c, Coord ul) {return(false);}
public boolean dropthing(Coord c, Object thing) {
int slot = beltslot(c);
if(slot != -1) {
if(thing instanceof Resource) {
Resource res = (Resource)thing;
if(res.layer(Resource.action) != null) {
GameUI.this.wdgmsg("setbelt", slot, res.name);
return(true);
}
}
}
return(false);
}
}
public class NKeyBelt extends Belt implements DTarget, DropTarget {
public int curbelt = 0;
public NKeyBelt(Coord c, Widget parent) {
super(c, Inventory.invsz(new Coord(10, 1)), parent);
}
private Coord beltc(int i) {
return(Inventory.sqoff(new Coord(i, 0)));
}
private int beltslot(Coord c) {
for(int i = 0; i < 10; i++) {
if(c.isect(beltc(i), isqsz))
return(i + (curbelt * 12));
}
return(-1);
}
public void draw(GOut g) {
invsq(g, Coord.z, new Coord(10, 1));
for(int i = 0; i < 10; i++) {
int slot = i + (curbelt * 12);
Coord c = beltc(i);
try {
Indir<Resource> ir = belt[slot];
if(ir != null)
g.image(ir.get().layer(Resource.imgc).tex(), c);
} catch(Loading e) {}
g.chcolor(156, 180, 158, 255);
FastText.aprintf(g, c.add(isqsz), 1, 1, "%d", (i + 1) % 10);
g.chcolor();
}
}
public boolean mousedown(Coord c, int button) {
int slot = beltslot(c);
if(slot != -1) {
if(button == 1)
GameUI.this.wdgmsg("belt", slot, 1, ui.modflags());
if(button == 3)
GameUI.this.wdgmsg("setbelt", slot, 1);
return(true);
}
return(false);
}
public boolean globtype(char key, KeyEvent ev) {
if(key != 0)
return(false);
int c = ev.getKeyChar();
if((c < KeyEvent.VK_0) || (c > KeyEvent.VK_9))
return(false);
int i = Utils.floormod(c - KeyEvent.VK_0 - 1, 10);
boolean M = (ev.getModifiersEx() & (KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0;
if(M) {
curbelt = i;
} else {
keyact(i + (curbelt * 12));
}
return(true);
}
public boolean drop(Coord c, Coord ul) {
int slot = beltslot(c);
if(slot != -1) {
GameUI.this.wdgmsg("setbelt", slot, 0);
return(true);
}
return(false);
}
public boolean iteminteract(Coord c, Coord ul) {return(false);}
public boolean dropthing(Coord c, Object thing) {
int slot = beltslot(c);
if(slot != -1) {
if(thing instanceof Resource) {
Resource res = (Resource)thing;
if(res.layer(Resource.action) != null) {
GameUI.this.wdgmsg("setbelt", slot, res.name);
return(true);
}
}
}
return(false);
}
}
{
new ToolBeltWdg(this, "F-Belt", 0, fkeys);
new ToolBeltWdg(this, "NumericBelt", 6, nkeys);
// String val = Utils.getpref("belttype", "n");
// if(val.equals("n")) {
// beltwdg = new NKeyBelt();
// } else if(val.equals("f")) {
// beltwdg = new FKeyBelt();
// } else {
// beltwdg = new NKeyBelt();
// }
}
private Map<String, Console.Command> cmdmap = new TreeMap<String, Console.Command>();
{
cmdmap.put("afk", new Console.Command() {
public void run(Console cons, String[] args) {
afk = true;
wdgmsg("afk");
}
});
cmdmap.put("act", new Console.Command() {
public void run(Console cons, String[] args) {
Object[] ad = new Object[args.length - 1];
System.arraycopy(args, 1, ad, 0, ad.length);
wdgmsg("act", ad);
}
});
/*cmdmap.put("belt", new Console.Command() {
public void run(Console cons, String[] args) {
if(args[1].equals("f")) {
beltwdg.destroy();
beltwdg = new FKeyBelt(Coord.z, GameUI.this);
Utils.setpref("belttype", "f");
resize(sz);
} else if(args[1].equals("n")) {
beltwdg.destroy();
beltwdg = new NKeyBelt(Coord.z, GameUI.this);
Utils.setpref("belttype", "n");
resize(sz);
}
}
});*/
cmdmap.put("tool", new Console.Command() {
public void run(Console cons, String[] args) {
gettype(args[1]).create(new Coord(200, 200), GameUI.this, new Object[0]);
}
});
cmdmap.put("flatness", new Console.Command(){
public void run(Console cons, String[] args){
FlatnessTool.instance(GameUI.this.ui);
}
});
}
public Map<String, Console.Command> findcmds() {
return(cmdmap);
}
}