/*
* 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 java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ender.CurioInfo;
public class Item extends Widget implements DTarget {
static Coord shoff = new Coord(1, 3);
static final Pattern patt = Pattern.compile("quality (\\d+) ", Pattern.CASE_INSENSITIVE);
static Map<Integer, Tex> qmap;
static Resource missing = Resource.load("gfx/invobjs/missing");
static Color outcol = new Color(0, 0, 0, 255);
static Color clrWater = new Color(24, 116, 205);
static Color clrWine = new Color(139, 71, 137);
static Color clrHoney = new Color(238, 173, 14);
boolean dm = false;
public int q, q2;
boolean hq;
Coord doff;
public String tooltip;
int num = -1;
Indir<Resource> res;
Tex sh;
public Color olcol = null;
Tex mask = null;
int meter = 0;
String curioStr = null;
public static int idCounter = 0; // new
public int id = 0; // new
static {
Widget.addtype("item", new WidgetFactory() {
public Widget create(Coord c, Widget parent, Object[] args) {
int res = (Integer) args[0];
int q = (Integer) args[1];
int num = -1;
String tooltip = null;
int ca = 3;
Coord drag = null;
if ((Integer) args[2] != 0)
drag = (Coord) args[ca++];
if (args.length > ca)
tooltip = (String) args[ca++];
if ((tooltip != null) && tooltip.equals(""))
tooltip = null;
if (args.length > ca)
num = (Integer) args[ca++];
Item item = new Item(c, res, q, parent, drag, num);
item.settip(tooltip);
return (item);
}
});
missing.loadwait();
qmap = new HashMap<Integer, Tex>();
}
public void settip(String t) {
tooltip = t;
q2 = -1;
if (tooltip != null) {
try {
Matcher m = patt.matcher(tooltip);
while (m.find()) {
q2 = Integer.parseInt(m.group(1));
}
} catch (IllegalStateException e) {
System.out.println(e.getMessage());
}
}
calcFEP();
calcCurio();
shorttip = longtip = null;
}
private void fixsize() {
if (res.get() != null) {
Tex tex = res.get().layer(Resource.imgc).tex();
sz = tex.sz().add(shoff);
} else {
sz = new Coord(30, 30);
}
}
public void draw(GOut g) {
final Resource ttres;
if (res.get() == null) {
sh = null;
sz = new Coord(30, 30);
g.image(missing.layer(Resource.imgc).tex(), Coord.z, sz);
ttres = missing;
} else {
Tex tex = res.get().layer(Resource.imgc).tex();
fixsize();
if (dm) {
g.chcolor(255, 255, 255, 128);
g.image(tex, Coord.z);
g.chcolor();
} else {
if(res.get().basename().equals("silkmoth") && tooltip != null && tooltip.contains("Female"))
g.chcolor(255, 124, 195, 255);
g.image(tex, Coord.z);
g.chcolor();
}
if (num >= 0) {
// g.chcolor(Color.WHITE);
// g.atext(Integer.toString(num), new Coord(0, 30), 0, 1);
g.aimage(getqtex(num), Coord.z, 0, 0);
}
if (meter > 0) {
double a = ((double) meter) / 100.0;
int r = (int) ((1 - a) * 255);
int gr = (int) (a * 255);
int b = 0;
g.chcolor(r, gr, b, 255);
// g.fellipse(sz.div(2), new Coord(15, 15), 90, (int)(90 + (360
// * a)));
g.frect(new Coord(sz.x - 5, (int) ((1 - a) * sz.y)), new Coord(5, (int) (a * sz.y)));
g.chcolor();
}
int tq = (q2 > 0) ? q2 : q;
if (Config.showq && (tq > 0)) {
tex = getqtex(tq);
g.aimage(tex, sz.sub(1, 1), 1, 1);
}
ttres = res.get();
}
if (olcol != null) {
Tex bg = ttres.layer(Resource.imgc).tex();
if ((mask == null) && (bg instanceof TexI)) {
mask = ((TexI) bg).mkmask();
}
if (mask != null) {
g.chcolor(olcol);
g.image(mask, Coord.z);
g.chcolor();
}
}
if (FEP == null) {
calcFEP();
}
if (curioStr == null) {
calcCurio();
}
if (ttres.name.lastIndexOf("waterflask") > 0) {
drawBar(g, 2, clrWater, 3);
} else if (ttres.name.lastIndexOf("glass-winef") > 0) {
drawBar(g, 0.2, clrWine, 3);
} else if (ttres.name.lastIndexOf("bottle-winef") > 0) {
drawBar(g, 0.6, clrWine, 3);
} else if (ttres.name.lastIndexOf("bottle-wine-weißbier") > 0) {
drawBar(g, 0.6, clrWine, 3);
} else if (ttres.name.lastIndexOf("tankardf") > 0) {
drawBar(g, 0.4, clrWine, 3);
} else if (ttres.name.lastIndexOf("waterskin") > 0) {
drawBar(g, 3, clrWater, 3);
} else if (ttres.name.lastIndexOf("bucket-") > 0 || ttres.name.lastIndexOf("waterflask-") > 0) {
Color clr;
if (ttres.name.lastIndexOf("water") > 0)
clr = clrWater;
else if (ttres.name.lastIndexOf("wine") > 0 || ttres.name.lastIndexOf("vinegar") > 0)
clr = clrWine;
else if (ttres.name.lastIndexOf("honey") > 0)
clr = clrHoney;
else
clr = Color.LIGHT_GRAY;
drawBar(g, 10, clr, 9);
}
}
private void drawBar(GOut g, double capacity, Color clr, int width) {
try {
String valStr = tooltip.substring(tooltip.indexOf('(') + 1, tooltip.indexOf('/'));
double val = Double.parseDouble(valStr);
int h = (int) (val / capacity * sz.y);
g.chcolor(clr);
int barH = h - shoff.y;
g.frect(new Coord(0, sz.y - h), new Coord(width, barH < 0 ? 0 : barH));
g.chcolor();
} catch (Exception e) {
} // fail silently.
}
static Tex getqtex(int q) {
synchronized (qmap) {
if (qmap.containsKey(q)) {
return qmap.get(q);
} else {
BufferedImage img = Text.render(Integer.toString(q)).img;
img = Utils.outline2(img, outcol, true);
Tex tex = new TexI(img);
qmap.put(q, tex);
return tex;
}
}
}
static Tex makesh(Resource res) {
BufferedImage img = res.layer(Resource.imgc).img;
Coord sz = Utils.imgsz(img);
BufferedImage sh = new BufferedImage(sz.x, sz.y, BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < sz.y; y++) {
for (int x = 0; x < sz.x; x++) {
long c = img.getRGB(x, y) & 0x00000000ffffffffL;
int a = (int) ((c & 0xff000000) >> 24);
sh.setRGB(x, y, (a / 2) << 24);
}
}
return (new TexI(sh));
}
public String name() {
Resource res = this.res.get();
if (res != null) {
if (res.layer(Resource.tooltip) != null) {
return res.layer(Resource.tooltip).t;
} else {
return (this.tooltip);
}
}
return null;
}
public String shorttip() {
if (this.tooltip != null)
return (this.tooltip);
Resource res = this.res.get();
if ((res != null) && (res.layer(Resource.tooltip) != null)) {
String tt = res.layer(Resource.tooltip).t;
if (tt != null) {
if (q > 0) {
tt = tt + ", quality " + q;
if (hq)
tt = tt + "+";
}
return (tt);
}
}
return (null);
}
long hoverstart;
Text shorttip = null, longtip = null;
public double qmult;
private String FEP = null;
public Object tooltip(Coord c, boolean again) {
long now = System.currentTimeMillis();
if (!again)
hoverstart = now;
Resource res = this.res.get();
Resource.Pagina pg = (res != null) ? res.layer(Resource.pagina) : null;
if (((now - hoverstart) < 500) || (pg == null)) {
if (shorttip == null) {
String tt = shorttip();
if (tt != null) {
tt = RichText.Parser.quote(tt);
if (meter > 0) {
tt = tt + " (" + meter + "%)";
}
if (FEP != null) {
tt += FEP;
}
if (curioStr != null) {
tt += curioStr;
}
shorttip = RichText.render(tt, 200);
}
}
return (shorttip);
} else {
if ((longtip == null) && (res != null)) {
String tip = shorttip();
if (tip == null)
return (null);
String tt = RichText.Parser.quote(tip);
if (meter > 0) {
tt = tt + " (" + meter + "%)";
}
if (FEP != null) {
tt += FEP;
}
if (curioStr != null) {
tt += curioStr;
}
if (pg != null)
tt += "\n\n" + pg.text;
longtip = RichText.render(tt, 200);
}
return (longtip);
}
}
private void resettt() {
shorttip = null;
longtip = null;
}
private void decq(int q) {
if (q < 0) {
this.q = q;
hq = false;
} else {
int fl = (q & 0xff000000) >> 24;
this.q = (q & 0xffffff);
hq = ((fl & 1) != 0);
}
}
public Item(Coord c, Indir<Resource> res, int q, Widget parent, Coord drag, int num) {
super(c, Coord.z, parent);
this.res = res;
idCounter++; // new
id = idCounter; // new
decq(q);
fixsize();
this.num = num;
if (drag == null) {
dm = false;
} else {
dm = true;
doff = drag;
ui.grabmouse(this);
this.c = ui.mc.add(doff.inv());
}
qmult = Math.sqrt((float) q / 10);
calcFEP();
calcCurio();
}
private void calcFEP() {
Map<String, Float> fep;
String name = name();
if (name == null) {
return;
}
if (name.equals("Ring of Brodgar")) {
if (res.get().name.equals("gfx/invobjs/bread-brodgar")) {
name = "Ring of Brodgar (Baking)";
}
if (res.get().name.equals("gfx/invobjs/feast-rob")) {
name = "Ring of Brodgar (Seafood)";
}
}
name = name.toLowerCase();
boolean isItem = false;
if ((fep = Config.FEPMap.get(name)) != null) {
if (fep.containsKey("isItem")) {
isItem = true;
}
FEP = "\n";
for (String key : fep.keySet()) {
float val = (float) (fep.get(key) * qmult);
if (key.equals("isItem")) {
continue;
}
if (isItem) {
val = (float) Math.floor(val);
FEP += String.format("%s:%.0f ", key, val);
} else {
FEP += String.format("%s:%.1f ", key, val);
}
}
shorttip = longtip = null;
}
}
public int getLP() {
String name = name();
if (name == null) {
return 0;
}
name = name.toLowerCase();
CurioInfo curio;
if ((curio = Config.curios.get(name)) != null) {
return (int) (curio.LP * qmult * ui.sess.glob.cattr.get("expmod").comp / 100);
}
return 0;
}
private void calcCurio() {
String name = name();
if (name == null) {
return;
}
name = name.toLowerCase();
CurioInfo curio;
if ((curio = Config.curios.get(name)) != null) {
int LP = (int) (curio.LP * qmult * ui.sess.glob.cattr.get("expmod").comp / 100);
int time = curio.time * (100 - meter) / 100;
int h = time / 60;
int m = time % 60;
curioStr = String.format("\nLP: %d, Weight: %d\nStudy time: %dh %2dm", LP, curio.weight, h, m);
shorttip = longtip = null;
}
}
public Item(Coord c, int res, int q, Widget parent, Coord drag, int num) {
this(c, parent.ui.sess.getres(res), q, parent, drag, num);
}
public Item(Coord c, Indir<Resource> res, int q, Widget parent, Coord drag) {
this(c, res, q, parent, drag, -1);
}
public Item(Coord c, int res, int q, Widget parent, Coord drag) {
this(c, parent.ui.sess.getres(res), q, parent, drag);
}
public boolean dropon(Widget w, Coord c) {
for (Widget wdg = w.lchild; wdg != null; wdg = wdg.prev) {
if (wdg == this)
continue;
Coord cc = w.xlate(wdg.c, true);
if (c.isect(cc, (wdg.hsz == null) ? wdg.sz : wdg.hsz)) {
if (dropon(wdg, c.add(cc.inv())))
return (true);
}
}
if (w instanceof DTarget) {
if (((DTarget) w).drop(c, c.add(doff.inv())))
return (true);
}
if (w instanceof DTarget2) {
if (((DTarget2) w).drop(c, c.add(doff.inv()), this))
return (true);
}
return (false);
}
public boolean interact(Widget w, Coord c) {
for (Widget wdg = w.lchild; wdg != null; wdg = wdg.prev) {
if (wdg == this)
continue;
Coord cc = w.xlate(wdg.c, true);
if (c.isect(cc, (wdg.hsz == null) ? wdg.sz : wdg.hsz)) {
if (interact(wdg, c.add(cc.inv())))
return (true);
}
}
if (w instanceof DTarget) {
if (((DTarget) w).iteminteract(c, c.add(doff.inv())))
return (true);
}
return (false);
}
public void chres(Indir<Resource> res, int q) {
this.res = res;
sh = null;
decq(q);
}
public void uimsg(String name, Object... args) {
if (name == "num") {
num = (Integer) args[0];
} else if (name == "chres") {
chres(ui.sess.getres((Integer) args[0]), (Integer) args[1]);
resettt();
} else if (name == "color") {
olcol = (Color) args[0];
} else if (name == "tt") {
if ((args.length > 0) && (((String) args[0]).length() > 0))
settip((String) args[0]);
else
settip(null);
resettt();
} else if (name == "meter") {
meter = (Integer) args[0];
shorttip = null;
longtip = null;
calcCurio();
}
}
public String GetResName() { // new
if (this.res.get() != null) {
return ((Resource) this.res.get()).name;
}
return "";
}
void sortedSkoop() { // new
String name = GetResName();
if (parent instanceof Inventory)
((Inventory) parent).skoopItems(name);
}
public boolean mousedown(Coord c, int button) {
if (button == 3 && ui.modflags() == 4) { // new
sortedSkoop();
return (true);
}
if (!dm) {
if (button == 1) {
if (ui.modshift)
if (ui.modmeta)
wdgmsg("transfer-same", name(), false);
else
wdgmsg("transfer", c);
else if (ui.modctrl)
if (ui.modmeta)
wdgmsg("drop-same", name(), false);
else
wdgmsg("drop", c);
else
wdgmsg("take", c);
return (true);
} else if (button == 3) {
if (ui.modmeta) {
if (ui.modshift) {
wdgmsg("transfer-same", name(), true);
} else if (ui.modctrl) {
wdgmsg("drop-same", name(), true);
}
} else {
wdgmsg("iact", c);
}
return (true);
}
} else {
if (button == 1) {
dropon(parent, c.add(this.c));
} else if (button == 3) {
interact(parent, c.add(this.c));
}
return (true);
}
return (false);
}
public void mousemove(Coord c) {
if (dm)
this.c = this.c.add(c.add(doff.inv()));
}
public boolean drop(Coord cc, Coord ul) {
return (false);
}
public boolean iteminteract(Coord cc, Coord ul) {
wdgmsg("itemact", ui.modflags());
return (true);
}
public ItemType getItemType(Item itm) {
String resname = itm.res.get().name;
int idx = resname.lastIndexOf("/");
resname = resname.substring(idx + 1);
if (!Config.itemTypes.containsKey(resname))
return ItemType.NOT_IMPLEMENTED;
return Config.itemTypes.get(resname);
}
}