add html/jsonapi armor builder

- make decoration calculator use 1-slot decorations multiple times
This commit is contained in:
Bryce Allen
2015-04-29 02:16:01 -05:00
parent 784299dd53
commit 6329e7028b
11 changed files with 662 additions and 38 deletions

View File

@@ -7,9 +7,9 @@ import codecs
import _pathfix import _pathfix
from mhapi.db import MHDB from mhapi.db import MHDB
from mhapi.model import get_decoration_values
from mhapi.util import get_utf8_writer
def get_utf8_writer(writer):
return codecs.getwriter("utf8")(writer)
def parse_args(argv): def parse_args(argv):
parser = argparse.ArgumentParser(description= parser = argparse.ArgumentParser(description=
@@ -46,7 +46,7 @@ def find_armors(args):
ds = db.get_decorations_by_skills([sid]) ds = db.get_decorations_by_skills([sid])
for d in ds: for d in ds:
d.set_skills(db.get_item_skills(d.id)) d.set_skills(db.get_item_skills(d.id))
decoration_values = get_decoration_values(sid, ds) decoration_values = get_decoration_values(sid, ds)[1]
decorations[sid] = (ds, decoration_values) decorations[sid] = (ds, decoration_values)
print "%s[%s]:" % (skill_name, sid), ", ".join(d.name for d in ds), \ print "%s[%s]:" % (skill_name, sid), ", ".join(d.name for d in ds), \
decoration_values decoration_values
@@ -88,20 +88,6 @@ def find_armors(args):
print " ", a.one_line_skills_u(args.skills) print " ", a.one_line_skills_u(args.skills)
def get_decoration_values(skill_id, decorations):
# TODO: write script to compute this and shove innto skill_tree table
values = [0, 0, 0]
for d in decorations:
assert d.num_slots is not None
# some skills like Handicraft have multiple decorations with
# same number of slots - use the best one
new = d.skills[skill_id]
current = values[d.num_slots-1]
if new > current:
values[d.num_slots-1] = new
return values
if __name__ == '__main__': if __name__ == '__main__':
args = parse_args(None) args = parse_args(None)

View File

@@ -35,13 +35,21 @@ def file_path(path, model_object, use_name=False):
def write_list_file(path, model_list): def write_list_file(path, model_list):
list_path = os.path.join(path, "_list.json") list_path = os.path.join(path, "_list.json")
with open(list_path, "w") as f: with open(list_path, "w") as f:
json.dump([o.as_list_data() for o in model_list], f, indent=2) json.dump([o.as_list_data() for o in model_list],
f, cls=model.ModelJSONEncoder, indent=2)
def write_index_file(path, indexes): def write_index_file(path, indexes):
index_path = os.path.join(path, "_index.json") for key, data in indexes.iteritems():
index_path = os.path.join(path, "_index_%s.json" % key)
with open(index_path, "w") as f: with open(index_path, "w") as f:
json.dump(indexes, f, indent=2) json.dump(data, f, cls=model.ModelJSONEncoder, indent=2)
def write_all_file(path, all_data):
all_path = os.path.join(path, "_all.json")
with open(all_path, "w") as f:
json.dump(all_data, f, cls=model.ModelJSONEncoder, indent=2)
def monster_json(db, path): def monster_json(db, path):
@@ -63,6 +71,73 @@ def monster_json(db, path):
write_index_file(path, indexes) write_index_file(path, indexes)
def armor_json(db, path):
armors = db.get_armors()
mkdirs_p(path)
write_list_file(path, armors)
all_data = []
indexes = {}
for a in armors:
armor_path = file_path(path, a)
a.update_indexes(indexes)
skills = db.get_item_skills(a.id)
if not skills:
print "WARN: armor '%s' (%d) has no skills" % (a.name, a.id)
a.set_skills(skills)
all_data.append(a.as_data())
with open(armor_path, "w") as f:
a.json_dump(f)
write_index_file(path, indexes)
write_all_file(path, all_data)
def decoration_json(db, path):
decorations = db.get_decorations()
mkdirs_p(path)
write_list_file(path, decorations)
all_data = []
indexes = {}
for a in decorations:
decoration_path = file_path(path, a)
a.update_indexes(indexes)
skills = db.get_item_skills(a.id)
if not skills:
print "WARN: decoration '%s' (%d) has no skills" % (a.name, a.id)
a.set_skills(skills)
all_data.append(a.as_data())
with open(decoration_path, "w") as f:
a.json_dump(f)
write_index_file(path, indexes)
write_all_file(path, all_data)
def skilltree_json(db, path):
skill_trees = db.get_skill_trees()
mkdirs_p(path)
write_list_file(path, skill_trees)
all_data = {}
for st in skill_trees:
ds = db.get_decorations_by_skills([st.id])
for d in ds:
d.set_skills(db.get_item_skills(d.id))
st.set_decorations(ds)
skilltree_path = file_path(path, st)
all_data[st.name] = st
with open(skilltree_path, "w") as f:
st.json_dump(f)
write_all_file(path, all_data)
def weapon_json(db, path): def weapon_json(db, path):
weapons = db.get_weapons() weapons = db.get_weapons()
mkdirs_p(path) mkdirs_p(path)
@@ -104,7 +179,10 @@ def main():
items_json(db, os.path.join(outpath, "item")) items_json(db, os.path.join(outpath, "item"))
weapon_json(db, os.path.join(outpath, "weapon")) weapon_json(db, os.path.join(outpath, "weapon"))
monster_json(db, os.path.join(outpath, "monster")) monster_json(db, os.path.join(outpath, "monster"))
#quest_json armor_json(db, os.path.join(outpath, "armor"))
skilltree_json(db, os.path.join(outpath, "skilltree"))
decoration_json(db, os.path.join(outpath, "decoration"))
#quest_json(db, os.path.join(outpath, "quest"))
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -299,27 +299,31 @@ class MHDB(object):
def get_weapon_by_name(self, name): def get_weapon_by_name(self, name):
return self._query_one("weapon", """ return self._query_one("weapon", """
SELECT * FROM weapons SELECT items._id, items.name, items.buy, weapons.*
FROM weapons
LEFT JOIN items ON weapons._id = items._id LEFT JOIN items ON weapons._id = items._id
WHERE items.name=? WHERE items.name=?
""", (name,), model_cls=model.Weapon) """, (name,), model_cls=model.Weapon)
def get_armors(self): def get_armors(self):
return self._query_all("armors", """ return self._query_all("armors", """
SELECT * FROM armor SELECT items._id, items.name, items.buy, armor.*
FROM armor
LEFT JOIN items ON armor._id = items._id LEFT JOIN items ON armor._id = items._id
""", model_cls=model.Armor) """, model_cls=model.Armor)
def get_armor(self, armor_id): def get_armor(self, armor_id):
return self._query_one("armor", """ return self._query_one("armor", """
SELECT * FROM armor SELECT items._id, items.name, items.buy, armor.*
FROM armor
LEFT JOIN items ON armor._id = items._id LEFT JOIN items ON armor._id = items._id
WHERE armor._id=? WHERE armor._id=?
""", (armor_id,), model_cls=model.Armor) """, (armor_id,), model_cls=model.Armor)
def get_armor_by_name(self, name): def get_armor_by_name(self, name):
return self._query_one("armor", """ return self._query_one("armor", """
SELECT * FROM armor SELECT items._id, items.name, items.buy, armor.*
FROM armor
LEFT JOIN items ON armor._id = items._id LEFT JOIN items ON armor._id = items._id
WHERE items.name=? WHERE items.name=?
""", (name,), model_cls=model.Armor) """, (name,), model_cls=model.Armor)
@@ -335,7 +339,7 @@ class MHDB(object):
def get_decorations(self): def get_decorations(self):
return self._query_all("decorations", """ return self._query_all("decorations", """
SELECT * SELECT items._id, items.name, items.buy, decorations.*
FROM decorations FROM decorations
INNER JOIN items INNER JOIN items
ON items._id = decorations._id ON items._id = decorations._id
@@ -343,7 +347,7 @@ class MHDB(object):
def get_decoration(self, decoration_id): def get_decoration(self, decoration_id):
return self._query_one("decoration", """ return self._query_one("decoration", """
SELECT * SELECT items._id, items.name, items.buy, decorations.*
FROM decorations FROM decorations
INNER JOIN items INNER JOIN items
ON items._id = decorations._id ON items._id = decorations._id
@@ -352,13 +356,18 @@ class MHDB(object):
def get_decoration_by_name(self, name): def get_decoration_by_name(self, name):
return self._query_all("decoration", """ return self._query_all("decoration", """
SELECT * SELECT items._id, items.name, items.buy, decorations.*
FROM decorations FROM decorations
INNER JOIN items INNER JOIN items
ON items._id = decorations._id ON items._id = decorations._id
WHERE items.name = ? WHERE items.name = ?
""", (name,), model_cls=model.Decoration) """, (name,), model_cls=model.Decoration)
def get_skill_trees(self):
return self._query_all("skills", """
SELECT _id, name FROM skill_trees
""", model_cls=model.SkillTree)
def get_skill_tree_id(self, skill_tree_name): def get_skill_tree_id(self, skill_tree_name):
result = self._query_one("skill", """ result = self._query_one("skill", """
SELECT _id FROM skill_trees SELECT _id FROM skill_trees
@@ -372,7 +381,7 @@ class MHDB(object):
args = sorted(skill_tree_ids) args = sorted(skill_tree_ids)
placeholders = ", ".join(["?"] * len(skill_tree_ids)) placeholders = ", ".join(["?"] * len(skill_tree_ids))
return self._query_all("decorations", """ return self._query_all("decorations", """
SELECT items.*, decorations.* SELECT items._id, items.name, items.buy, decorations.*
FROM item_to_skill_tree FROM item_to_skill_tree
LEFT JOIN items LEFT JOIN items
ON items._id = item_to_skill_tree.item_id ON items._id = item_to_skill_tree.item_id
@@ -389,7 +398,7 @@ class MHDB(object):
placeholders = ", ".join(["?"] * len(skill_tree_ids)) placeholders = ", ".join(["?"] * len(skill_tree_ids))
args += [hunter_type] args += [hunter_type]
return self._query_all("decorations", """ return self._query_all("decorations", """
SELECT items.*, armor.* SELECT items._id, items.name, items.buy, armor.*
FROM item_to_skill_tree FROM item_to_skill_tree
LEFT JOIN items LEFT JOIN items
ON items._id = item_to_skill_tree.item_id ON items._id = item_to_skill_tree.item_id

View File

@@ -76,6 +76,9 @@ class RowModel(ModelBase):
self.update_index(key_field, value_fields, data[key_field]) self.update_index(key_field, value_fields, data[key_field])
def update_index(self, key_field, value_fields, data): def update_index(self, key_field, value_fields, data):
if isinstance(value_fields, str):
item = self[value_fields]
else:
item = dict((k, self[k]) for k in value_fields) item = dict((k, self[k]) for k in value_fields)
key_value = self[key_field] key_value = self[key_field]
if key_value not in data: if key_value not in data:
@@ -212,16 +215,29 @@ class ItemWithSkills(RowModel):
return self.skills.get(skill_id_or_name, 0) return self.skills.get(skill_id_or_name, 0)
def one_line_skills_u(self, skill_names=None): def one_line_skills_u(self, skill_names=None):
"""
Get comma separated list of skills on the item. If @skill_names
is passed, only include skills that are in that list.
"""
if skill_names is None: if skill_names is None:
skill_names = sorted(self.skill_names) skill_names = sorted(self.skill_names)
return ", ".join("%s %d" % (name, self.skills[name]) return ", ".join("%s %d" % (name, self.skills[name])
for name in skill_names for name in skill_names
if name in self.skills) if name in self.skills)
def as_data(self):
data = super(ItemWithSkills, self).as_data()
if self.skills is not None:
data["skills"] = dict((name, self.skills[name])
for name in self.skill_names)
#data["skills_by_id"] = dict((sid, self.skills[sid])
# for sid in self.skill_ids)
return data
class Armor(ItemWithSkills): class Armor(ItemWithSkills):
_indexes = { "name": ["id"], _indexes = { "name": "id",
"slot": ["id", "name"] } "slot": "name" }
_one_line_template = string.Template( _one_line_template = string.Template(
"$name ($slot) Def $defense-$max_defense Slot $num_slots" "$name ($slot) Def $defense-$max_defense Slot $num_slots"
@@ -236,9 +252,10 @@ class Armor(ItemWithSkills):
def skill(self, skill_id_or_name, decoration_values=()): def skill(self, skill_id_or_name, decoration_values=()):
""" """
decoration_values should be a list of points from the given decoration_values should be a list of points from the given
number of slots, e.g. [1, 3] means that one slot gets 1 point number of slots, e.g. [1, 3] or [1, 3, 0] means that one slot
and two slots get 3 points, [1, 0, 4] means that one slot gets 1 point, gets 1 point and two slots get 3 points, [1, 0, 4] means that
there is no two slot gem, and three slots gets 4 points. one slot gets 1 point, there is no two slot gem, and three slots
gets 4 points. If not passed, just returns native skill points.
""" """
assert self.skills is not None assert self.skills is not None
total = self.skills.get(skill_id_or_name, 0) total = self.skills.get(skill_id_or_name, 0)
@@ -249,7 +266,7 @@ class Armor(ItemWithSkills):
decoration_value = decoration_values[slots-1] decoration_value = decoration_values[slots-1]
if not decoration_value: if not decoration_value:
continue continue
if slots <= slots_left: while slots <= slots_left:
total += decoration_value total += decoration_value
slots_left -= slots slots_left -= slots
return total return total
@@ -263,6 +280,27 @@ class ItemSkill(RowModel):
pass pass
class SkillTree(RowModel):
def __init__(self, skill_tree_row):
super(SkillTree, self).__init__(skill_tree_row)
self.decoration_values = None
self.decoration_ids = None
def set_decorations(self, decorations):
if decorations is None:
self.decoration_values = None
else:
self.decoration_ids, self.decoration_values = \
get_decoration_values(self.id, decorations)
def as_data(self):
data = super(SkillTree, self).as_data()
if self.decoration_values is not None:
data["decoration_values"] = self.decoration_values
data["decoration_ids"] = self.decoration_ids
return data
class Weapon(RowModel): class Weapon(RowModel):
_list_fields = ["id", "wtype", "name"] _list_fields = ["id", "wtype", "name"]
_indexes = { "name": ["id"], _indexes = { "name": ["id"],
@@ -401,6 +439,22 @@ class MonsterDamage(ModelBase):
part_damage.breakable = True part_damage.breakable = True
def get_decoration_values(skill_id, decorations):
# TODO: write script to compute this and shove into skill_tree table
values = [0, 0, 0]
ids = [None, None, None]
for d in decorations:
assert d.num_slots is not None
# some skills like Handicraft have multiple decorations with
# same number of slots - use the best one
new = d.skills[skill_id]
current = values[d.num_slots-1]
if new > current:
values[d.num_slots-1] = new
ids[d.num_slots-1] = d.id
return (ids, values)
def _break_find(part, parts, breaks): def _break_find(part, parts, breaks):
# favor 'Tail Tip' over Tail for Basarios # favor 'Tail Tip' over Tail for Basarios
if part == "Tail" and "Tail Tip" in parts: if part == "Tail" and "Tail Tip" in parts:

View File

@@ -2,6 +2,8 @@
Shared utility classes and functions. Shared utility classes and functions.
""" """
import codecs
class EnumBase(object): class EnumBase(object):
_names = dict() _names = dict()
@@ -9,3 +11,7 @@ class EnumBase(object):
@classmethod @classmethod
def name(cls, enum_value): def name(cls, enum_value):
return cls._names[enum_value] return cls._names[enum_value]
def get_utf8_writer(writer):
return codecs.getwriter("utf8")(writer)

402
web/armor.html Normal file
View File

@@ -0,0 +1,402 @@
<html>
<head>
<title>Poogie Outfitters</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/ejs_production.js"></script>
<style>
label {
font-weight: bold;
}
body {
font-family: sans, sans-serif;
}
td.num {
text-align: right;
}
/*@media (max-width: 600) {*/
#flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
</style>
<script type="text/javascript">
var DATA_PATH = get_base_path() + "/jsonapi/";
var TYPES = ["Head", "Body", "Arms", "Waist", "Legs"];
var ELEMENTS = ["fire", "water", "thunder", "ice", "dragon"];
// dict mapping armor name to list containing id
var armor_ids = {};
// dict mapping skill name to object
var skill_trees = {};
// dict mapping type to armor name
var armors = {};
var decorations = { "Head": [], "Body": [], "Arms": [],
"Waist": [], "Legs": [] };
var slots_left = {};
$(document).ready(function(){
$.getJSON(DATA_PATH + "armor/_index_name.json",
function(data) {
armor_ids = data;
setup_autocomplete();
$.getJSON(DATA_PATH + "skilltree/_all.json",
function(data) {
skill_trees = data;
load_armors();
load_decorations();
// if nothing is loaded update won't be
// called, so force an update
update_skills();
});
});
$("#armor_table").on("click", "button.add_decoration",
function (evt) {
add_decoration_by_element(evt.target.id);
});
$("#armor_table").on("click", "button.remove_decoration",
function (evt) {
remove_decoration_by_element(evt.target.id);
});
// TODO: update skills
});
function load_armors() {
armors_saved = localStorage.getItem("armor_names");
if (armors_saved != null) {
armor_names = JSON.parse(armors_saved);
$.each(armor_names, function(type, name) {
if (name) {
$("#" + type).val(name);
set_armor(type, name);
}
});
}
}
function load_decorations() {
decorations_saved = localStorage.getItem("decoration_name_lists");
if (decorations_saved != null) {
dname_list = JSON.parse(decorations_saved);
$.each(dname_list, function(type, names) {
$.each(names, function(i, name) {
add_decoration(type, name);
});
});
}
}
function add_decoration_by_element(element_id) {
parts = element_id.split("_");
type = parts[0];
value = $("#" + type + "_decoration").val();
add_decoration(type, value);
}
function remove_decoration_by_element(element_id) {
parts = element_id.split("_");
type = parts[0];
index = parts[3];
remove_decoration(type, index);
}
function setup_decoration_autocomplete(type, max_slots) {
options = [];
$.each(skill_trees, function(skill_name, stree) {
$.each(stree["decoration_values"], function(i, points) {
nslots = i + 1;
if (nslots <= max_slots && points > 0) {
option_name = stree["name"] + " +" + points;
options.push(option_name);
}
});
});
$("#" + type + "_decoration").autocomplete({ source: options });
$("#" + type + "_decoration").keypress(function(e) {
if (e.which == 13) {
value = $("#" + type + "_decoration").val();
add_decoration(type, value);
}
});
}
function save_armors() {
var armor_names = {};
$.each(armors, function(type, armor) {
armor_names[type] = armor["name"];
});
localStorage.setItem("armor_names", JSON.stringify(armor_names));
}
function save_decorations() {
var decoration_name_lists = {};
$.each(decorations, function(type, dlist) {
$.each(dlist, function(i, d) {
if (! (type in decoration_name_lists)) {
decoration_name_lists[type] = [];
}
decoration_name_lists[type].push(d["display_name"]);
});
});
localStorage.setItem("decoration_name_lists",
JSON.stringify(decoration_name_lists));
}
function get_base_path() {
var path = document.location.pathname;
return path.substring(0, path.lastIndexOf('/'));
}
function setup_autocomplete() {
$.getJSON(DATA_PATH + "armor/_index_slot.json",
function(data) {
$.each(TYPES,
function(i, type) {
$("#" + type).autocomplete(
{ source: data[type],
change: function (event, ui) {
set_armor(this.id, ui.item["value"]);
}
}
);
$("#" + type).keypress(function(e) {
if (e.which == 13) {
set_armor(this.id, $("#" + this.id).val());
}
});
});
}
);
}
function add_decoration(type, value) {
parts = value.split(" +");
skill = parts[0]
points = parts[1]
slots = 0;
for (i=0; i < 3; i++) {
if (skill_trees[skill]["decoration_values"][i] == points) {
slots = i + 1;
break;
}
}
decoration_id = skill_trees[skill]["decoration_ids"][slots-1];
$.getJSON(DATA_PATH + "decoration/" + decoration_id + ".json",
function (data) {
if (! (type in decorations)) {
decorations[type] = []
}
data["display_name"] = value;
decorations[type].push(data);
slots_left[type] -= data["num_slots"];
save_decorations();
update_slots(type);
update_skills();
}
);
}
function remove_decoration(type, index) {
d = decorations[type][index];
slots_left[type] += d["num_slots"];
decorations[type].splice(index, 1);
save_decorations();
update_slots(type);
update_skills();
}
function set_armor(type, name, noupdate) {
armor_id = armor_ids[name][0];
$.getJSON(DATA_PATH + "armor/" + armor_id + ".json",
function(data) {
armors[type] = data;
if (noupdate == undefined) {
save_armors();
decorations[type] = [];
slots_left[type] = data["num_slots"];
var skill_names = Object.keys(data["skills"]);
skill_names.sort();
var slist = "";
$.each(skill_names, function(i, sname) {
if (i != 0) {
slist += ", ";
}
slist += sname + " " + data["skills"][sname];
});
$("#" + type + "_skills").html(slist);
update_slots(type);
update_skills();
}
}
);
}
function update_slots(type) {
var free_slots = slots_left[type];
var slots_html = new EJS(
{ url: "templates/decorations.ejs" }
).render({ decorations: decorations[type],
free_slots: free_slots,
type: type });
$("#" + type + "_slots").html(slots_html);
if (free_slots > 0) {
setup_decoration_autocomplete(type, free_slots);
}
}
function update_skills() {
// map of skill name to total
var skills = {};
// map of type to dict map of skill name to total including decoration
var tskills_by_type = {};
// map of type to dict map of skill name to total from decorations only
var dskills_by_type = {};
var element_resist = {};
var slots = 0;
var slots_free = 0;
$.each(armors, function(type, armor) {
dskills_by_type[type] = {};
tskills_by_type[type] = {};
$.each(armor["skills"], function(skill_name, skill_value) {
if (! (skill_name in skills)) {
skills[skill_name] = 0;
}
skills[skill_name] += skill_value;
if (! (skill_name in tskills_by_type[type])) {
tskills_by_type[type][skill_name] = 0;
}
tskills_by_type[type][skill_name] += skill_value;
})
$.each(decorations[type], function(i, decoration) {
$.each(decoration["skills"],
function(skill_name, skill_value) {
if (! (skill_name in skills)) {
skills[skill_name] = 0;
}
skills[skill_name] += skill_value;
if (! (skill_name in dskills_by_type[type])) {
dskills_by_type[type][skill_name] = 0;
}
dskills_by_type[type][skill_name] += skill_value;
if (! (skill_name in tskills_by_type[type])) {
tskills_by_type[type][skill_name] = 0;
}
tskills_by_type[type][skill_name] += skill_value;
}
);
})
$.each(ELEMENTS, function(i, element) {
key = element + "_res";
if (! (element in element_resist)) {
element_resist[element] = 0;
}
element_resist[element] += armor[key];
$("#" + type + "_" + element).html(armor[key]);
})
slots += armor["num_slots"];
slots_free += slots_left[type];
//$("#" + type + "_slots").html(armor["num_slots"]);
});
$("#Total_slots").html((slots - slots_free)
+ " used / " + slots + " slots");
var skill_names = Object.keys(skills);
skill_names.sort(function(a, b) {
sa = skills[a] ? skills[a] : 0;
sb = skills[b] ? skills[b] : 0;
return sb - sa;
});
var skills_table = new EJS(
{ url: "templates/skills.ejs" }
).render({ TYPES: TYPES,
skills: skills,
dskills_by_type: dskills_by_type,
tskills_by_type: tskills_by_type,
active_skills: skill_names,
armors: armors });
$("#skills_div").html(skills_table);
var resist_table = new EJS(
{ url: "templates/resistance.ejs" }
).render({ TYPES: TYPES,
ELEMENTS: ELEMENTS,
armors: armors,
element_resist: element_resist });
$("#resist_div").html(resist_table);
}
</script>
</head>
<body>
<table id="armor_table" cellpadding="2" cellspacing="2">
<tr>
<td><label for="Head">Head:</label></td>
<td><input id="Head" type="text" size="15" /></td>
<td id="Head_slots">&nbsp;</td>
<td id="Head_skills">&nbsp;</td>
</tr>
<tr>
<td><label for="Body">Body:</label></td>
<td><input id="Body" type="text" size="15" /></td>
<td id="Body_slots">&nbsp;</td>
<td id="Body_skills">&nbsp;</td>
</tr>
<tr>
<td><label for="Arms">Arms:</label></td>
<td><input id="Arms" type="text" size="15" /></td>
<td id="Arms_slots">&nbsp;</td>
<td id="Arms_skills">&nbsp;</td>
</tr>
<tr>
<td><label for="Waist">Waist:</label></td>
<td><input id="Waist" type="text" size="15" /></td>
<td id="Waist_slots">&nbsp;</td>
<td id="Waist_skills">&nbsp;</td>
</tr>
<tr>
<td><label for="Legs">Legs:</label></td>
<td><input id="Legs" type="text" size="15" /></td>
<td id="Legs_slots">&nbsp;</td>
<td id="Legs_skills">&nbsp;</td>
</tr>
<tr>
<th>&nbsp;</th>
<td>&nbsp;</td>
<td id="Total_slots">0</td>
<td>&nbsp;</td>
</tr>
</table>
<div id="flexbox">
<fieldset>
<legend>Skills</legend>
<div id="skills_div"></div>
</fieldset>
<fieldset>
<legend>Elemental Resistance</legend>
<div id="resist_div"></div>
</fieldset>
</div>
</body>
</body>

1
web/js/ejs_production.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
<table>
<% for(var i=0; i<decorations.length; i++) { %>
<tr>
<td><%= Array(decorations[i]["num_slots"] + 1).join("\u26ab") %></td>
<td><%= decorations[i]["display_name"] %>
<button id="<%= type %>_remove_decoration_<%= i %>"
class="remove_decoration">-</button></td>
</tr>
<% } %>
<% if (free_slots > 0) { %>
<tr>
<td><%= Array(free_slots + 1).join("\u26aa") %><%= Array(3- free_slots + 1).join("&nbsp;") %></td>
<td><input id="<%= type %>_decoration" type="text" size="12">
<button id="<%= type %>_add_decoration"
class="add_decoration">+</button></td>
</tr>
<% } %>
</table>

View File

@@ -0,0 +1,21 @@
<table id="resist_table" cellpadding="2" border="0">
<tr>
<th>&nbsp;</th>
<th>Total</th>
<th>Head</th>
<th>Body</th>
<th>Arms</th>
<th>Waist</th>
<th>Legs</th>
</tr>
<% for(var i=0; i<ELEMENTS.length; i++) { %>
<tr>
<th><%= ELEMENTS[i] %></th>
<td class="num"><%= element_resist[ELEMENTS[i]] %></td>
<% for(var j=0; j<TYPES.length; j++) { %>
<td class="num">
<%= armors[TYPES[j]]
? armors[TYPES[j]][ELEMENTS[i] + "_res"] : "&nbsp;" %></td>
<% } %>
<% } %>
</table>

25
web/templates/skills.ejs Normal file
View File

@@ -0,0 +1,25 @@
<table id="skills_table" cellpadding="2" border="0">
<tr>
<th>&nbsp;</th>
<th>Total</th>
<% for(var i=0; i<TYPES.length; i++) { %>
<td><%= TYPES[i] %></td>
<% } %>
</tr>
<% for(var i=0; i<active_skills.length; i++) { %>
<tr>
<td><%= active_skills[i] %></td>
<td class="num"><%= skills[active_skills[i]] %></td>
<% for(var j=0; j<TYPES.length; j++) { %>
<td class="num">
<%= (armors[TYPES[j]] && tskills_by_type[TYPES[j]][active_skills[i]])
? tskills_by_type[TYPES[j]][active_skills[i]]
: "&nbsp;" %>
<%= 0 && (armors[TYPES[j]] && dskills_by_type[TYPES[j]][active_skills[i]])
? " (" + dskills_by_type[TYPES[j]][active_skills[i]] + ")"
: "&nbsp;" %>
</td>
<% } %>
</tr>
<% } %>
</table>

View File

@@ -0,0 +1,24 @@
<table id="skills_table" cellpadding="2">
<tr>
<th>Skill</th>
<th>Total</th>
<% for(var i=0; i<TYPES.length; i++) { %>
<th><%= TYPES[i] %></th>
<% } %>
</tr>
<% for(var i=0; i<active_skills.length; i++) { %>
<tr>
<td><%= active_skills[i] %></td>
<td><%= skills[active_skills[i]] %></td>
<% for(var j=0; j<TYPES.length; j++) { %>
<td>
<%= (armors[TYPES[j]] && armors[TYPES[j]]["skills"][active_skills[i]])
? armors[TYPES[j]]["skills"][active_skills[i]] : "&nbsp;" %>
<%= (armors[TYPES[j]] && dskills_by_type[TYPES[j]][active_skills[i]])
? " (" + dskills_by_type[TYPES[j]][active_skills[i]] + ")"
: "&nbsp;" %>
</td>
<% } %>
</tr>
<% } %>
</table>