2022-07-29 18:22:39 +00:00
|
|
|
/**
|
|
|
|
* This file defines a class representing the player Build.
|
|
|
|
*
|
|
|
|
* Keeps track of equipment list, equip order, skillpoint assignment (initial),
|
|
|
|
* Aggregates item stats into a statMap to be used in damage calculation.
|
|
|
|
*/
|
2021-03-31 06:44:56 +00:00
|
|
|
|
2022-07-10 21:57:02 +00:00
|
|
|
const classDefenseMultipliers = new Map([ ["relik",0.50], ["bow",0.60], ["wand", 0.80], ["dagger", 1.0], ["spear",1.0], ["sword", 1.10]]);
|
2021-01-10 10:02:23 +00:00
|
|
|
|
2022-07-07 23:13:26 +00:00
|
|
|
/*
|
|
|
|
* Class that represents a wynn player's build.
|
2021-01-17 21:01:20 +00:00
|
|
|
*/
|
2021-01-07 00:02:10 +00:00
|
|
|
class Build{
|
|
|
|
|
2021-01-17 21:01:20 +00:00
|
|
|
/**
|
|
|
|
* @description Construct a build.
|
|
|
|
* @param {Number} level : Level of the player.
|
2022-07-29 18:22:39 +00:00
|
|
|
* @param {String[]} items: List of equipment names that make up the build.
|
|
|
|
* In order: Helmet, Chestplate, Leggings, Boots, Ring1, Ring2, Brace, Neck, Tomes [x7].
|
|
|
|
* @param {Item} weapon: Weapon that this build is using.
|
2021-01-09 08:52:58 +00:00
|
|
|
*/
|
2022-06-23 10:42:18 +00:00
|
|
|
constructor(level, items, weapon){
|
2021-01-17 21:01:20 +00:00
|
|
|
|
|
|
|
if (level < 1) { //Should these be constants?
|
2021-01-07 00:02:10 +00:00
|
|
|
this.level = 1;
|
2021-01-17 21:01:20 +00:00
|
|
|
} else if (level > 106) {
|
2021-01-07 00:02:10 +00:00
|
|
|
this.level = 106;
|
2021-01-17 21:01:20 +00:00
|
|
|
} else if (level <= 106 && level >= 1) {
|
2021-01-07 00:02:10 +00:00
|
|
|
this.level = level;
|
2021-01-17 21:01:20 +00:00
|
|
|
} else if (typeof level === "string") {
|
|
|
|
this.level = level;
|
|
|
|
} else {
|
|
|
|
errors.push("Level is not a string or number.");
|
2021-01-07 00:02:10 +00:00
|
|
|
}
|
2021-01-17 21:01:20 +00:00
|
|
|
document.getElementById("level-choice").value = this.level;
|
|
|
|
|
2021-01-07 06:41:41 +00:00
|
|
|
this.availableSkillpoints = levelToSkillPoints(this.level);
|
2022-06-19 07:42:49 +00:00
|
|
|
this.equipment = items;
|
|
|
|
this.weapon = weapon;
|
2022-06-23 10:42:18 +00:00
|
|
|
this.items = this.equipment.concat([this.weapon]);
|
2022-06-19 16:49:04 +00:00
|
|
|
|
|
|
|
// calc skillpoints requires statmaps only
|
2022-06-23 10:42:18 +00:00
|
|
|
let result = calculate_skillpoints(this.equipment.map((x) => x.statMap), this.weapon.statMap);
|
2022-07-31 12:41:23 +00:00
|
|
|
this.equip_order = result[0].slice();
|
2022-07-30 00:06:54 +00:00
|
|
|
for (let i = 0; i < this.equip_order.length; i++) {
|
2022-07-31 12:41:23 +00:00
|
|
|
if (this.equip_order[i].get("category") === "tome" || this.equip_order[i].get("fixID") === true) {
|
|
|
|
this.equip_order.splice(i, 1);
|
|
|
|
i--;
|
2022-07-30 00:06:54 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-27 10:04:12 +00:00
|
|
|
// How many skillpoints the player had to assign (5 number)
|
2021-01-07 06:41:41 +00:00
|
|
|
this.base_skillpoints = result[1];
|
2021-07-27 10:04:12 +00:00
|
|
|
// How many skillpoints the build ended up with (5 number)
|
2021-01-07 06:41:41 +00:00
|
|
|
this.total_skillpoints = result[2];
|
2021-07-27 10:04:12 +00:00
|
|
|
// How many skillpoints assigned (1 number, sum of base_skillpoints)
|
2021-01-07 06:41:41 +00:00
|
|
|
this.assigned_skillpoints = result[3];
|
2021-01-10 04:29:07 +00:00
|
|
|
this.activeSetCounts = result[4];
|
2021-01-14 03:17:01 +00:00
|
|
|
|
2021-01-08 04:31:29 +00:00
|
|
|
this.initBuildStats();
|
2021-01-07 00:02:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*Returns build in string format
|
2021-01-07 06:41:41 +00:00
|
|
|
*/
|
2021-01-07 00:02:10 +00:00
|
|
|
toString(){
|
2022-06-23 10:42:18 +00:00
|
|
|
return [this.equipment,this.weapon].flat();
|
2021-01-07 00:02:10 +00:00
|
|
|
}
|
|
|
|
|
2021-01-08 05:36:57 +00:00
|
|
|
/* Get all stats for this build. Stores in this.statMap.
|
2021-01-07 21:32:36 +00:00
|
|
|
@pre The build itself should be valid. No checking of validity of pieces is done here.
|
|
|
|
*/
|
2021-01-08 04:31:29 +00:00
|
|
|
initBuildStats(){
|
|
|
|
|
2022-06-26 11:08:54 +00:00
|
|
|
let staticIDs = ["hp", "eDef", "tDef", "wDef", "fDef", "aDef", "str", "dex", "int", "def", "agi", "damMobs", "defMobs"];
|
2021-01-08 04:31:29 +00:00
|
|
|
|
2022-06-24 10:35:03 +00:00
|
|
|
let must_ids = [
|
|
|
|
"eMdPct","eMdRaw","eSdPct","eSdRaw","eDamPct","eDamRaw","eDamAddMin","eDamAddMax",
|
|
|
|
"tMdPct","tMdRaw","tSdPct","tSdRaw","tDamPct","tDamRaw","tDamAddMin","tDamAddMax",
|
|
|
|
"wMdPct","wMdRaw","wSdPct","wSdRaw","wDamPct","wDamRaw","wDamAddMin","wDamAddMax",
|
|
|
|
"fMdPct","fMdRaw","fSdPct","fSdRaw","fDamPct","fDamRaw","fDamAddMin","fDamAddMax",
|
|
|
|
"aMdPct","aMdRaw","aSdPct","aSdRaw","aDamPct","aDamRaw","aDamAddMin","aDamAddMax",
|
|
|
|
"nMdPct","nMdRaw","nSdPct","nSdRaw","nDamPct","nDamRaw","nDamAddMin","nDamAddMax", // neutral which is now an element
|
|
|
|
"mdPct","mdRaw","sdPct","sdRaw","damPct","damRaw","damAddMin","damAddMax", // These are the old ids. Become proportional.
|
|
|
|
"rMdPct","rMdRaw","rSdPct","rSdRaw","rDamPct","rDamRaw","rDamAddMin","rDamAddMax" // rainbow (the "element" of all minus neutral). rSdRaw is rainraw
|
|
|
|
]
|
|
|
|
|
2021-01-07 21:32:36 +00:00
|
|
|
//Create a map of this build's stats
|
|
|
|
let statMap = new Map();
|
2021-01-08 04:31:29 +00:00
|
|
|
|
|
|
|
for (const staticID of staticIDs) {
|
|
|
|
statMap.set(staticID, 0);
|
2021-01-07 21:32:36 +00:00
|
|
|
}
|
2022-06-24 10:35:03 +00:00
|
|
|
for (const staticID of must_ids) {
|
|
|
|
statMap.set(staticID, 0);
|
|
|
|
}
|
2021-01-30 08:50:25 +00:00
|
|
|
statMap.set("hp", levelToHPBase(this.level));
|
2021-01-14 06:58:32 +00:00
|
|
|
|
2021-01-30 12:03:40 +00:00
|
|
|
let major_ids = new Set();
|
2021-01-09 00:56:07 +00:00
|
|
|
for (const item of this.items){
|
2022-06-19 16:49:04 +00:00
|
|
|
const item_stats = item.statMap;
|
|
|
|
for (let [id, value] of item_stats.get("maxRolls")) {
|
2021-07-07 03:36:12 +00:00
|
|
|
if (staticIDs.includes(id)) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-08 04:31:29 +00:00
|
|
|
statMap.set(id,(statMap.get(id) || 0)+value);
|
|
|
|
}
|
|
|
|
for (const staticID of staticIDs) {
|
2022-06-19 16:49:04 +00:00
|
|
|
if (item_stats.get(staticID)) {
|
2022-06-23 09:23:56 +00:00
|
|
|
statMap.set(staticID, statMap.get(staticID) + item_stats.get(staticID));
|
2021-01-10 13:18:53 +00:00
|
|
|
}
|
2021-01-07 21:32:36 +00:00
|
|
|
}
|
2022-06-19 16:49:04 +00:00
|
|
|
if (item_stats.get("majorIds")) {
|
|
|
|
for (const major_id of item_stats.get("majorIds")) {
|
2021-07-23 07:47:13 +00:00
|
|
|
major_ids.add(major_id);
|
|
|
|
}
|
2021-01-30 12:03:40 +00:00
|
|
|
}
|
2021-01-07 21:32:36 +00:00
|
|
|
}
|
2022-07-08 05:28:46 +00:00
|
|
|
statMap.set('damMult', new Map());
|
|
|
|
statMap.set('defMult', new Map());
|
|
|
|
statMap.get('damMult').set('tome', statMap.get('damMobs'))
|
|
|
|
statMap.get('defMult').set('tome', statMap.get('defMobs'))
|
2021-01-30 12:03:40 +00:00
|
|
|
statMap.set("activeMajorIDs", major_ids);
|
2021-01-10 04:29:07 +00:00
|
|
|
for (const [setName, count] of this.activeSetCounts) {
|
2022-06-19 16:49:04 +00:00
|
|
|
const bonus = sets.get(setName).bonuses[count-1];
|
2021-01-10 03:40:15 +00:00
|
|
|
for (const id in bonus) {
|
2021-01-10 04:29:07 +00:00
|
|
|
if (skp_order.includes(id)) {
|
|
|
|
// pass. Don't include skillpoints in ids
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
statMap.set(id,(statMap.get(id) || 0)+bonus[id]);
|
|
|
|
}
|
2021-01-10 03:40:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-18 14:18:14 +00:00
|
|
|
statMap.set("poisonPct", 100);
|
2022-07-12 16:38:28 +00:00
|
|
|
statMap.set("critDamPct", 100);
|
2022-07-19 05:23:16 +00:00
|
|
|
statMap.set("healPct", 100);
|
2021-01-07 06:41:41 +00:00
|
|
|
|
2021-01-08 04:31:29 +00:00
|
|
|
// The stuff relevant for damage calculation!!! @ferricles
|
2022-06-19 16:49:04 +00:00
|
|
|
statMap.set("atkSpd", this.weapon.statMap.get("atkSpd"));
|
2021-01-14 06:58:32 +00:00
|
|
|
|
2021-01-08 04:31:29 +00:00
|
|
|
this.statMap = statMap;
|
2021-01-18 14:18:14 +00:00
|
|
|
}
|
2021-01-07 00:02:10 +00:00
|
|
|
}
|