function drawSummaries() { for (var oHtml = $('
'), tree = 0; 3 > tree; tree++) oHtml.append($("
").addClass("tree-summary").addClass(treeNames[tree]).attr("data-idx", tree).text(treeNames[tree] + ": 0").css({ left: TREE_OFFSET * tree + 10, cursor: "pointer" })); return oHtml } function drawCalculator() { for (var $calculator = $('
'), tree = 0; 3 > tree; tree++) for (var index = 0; index < data[tree].length; index++) { drawButton(tree, index, $calculator); } var tip, maxDims = { width: $calculator.parent().width(), height: $calculator.parent().height() }; return $calculator.append($("
").addClass("j-tooltip").append($("")).append($("
").addClass("rank")).append($("
").addClass("req")).append($("

").addClass("tooltip-text").addClass("first")).append($("

").addClass("tooltip-text").addClass("second").append($("

").addClass("nextRank").text("下一层:")).append($("
").addClass("content")))), tip = $calculator.find(".j-tooltip"), $calculator.mousemove(function(event) { if (tip.is(":visible")) { var pos = $calculator.offset(), offsetX = 20, offsetY = 20; event.pageY - pos.top + tip.height() > maxDims.height && (offsetY = -tip.height() - 30), event.pageX - pos.left > tip.width() && (offsetX = -tip.width()), tip.css({ left: event.pageX - pos.left + offsetX, top: event.pageY - pos.top + offsetY }) } }), $calculator } function deltaMastery(tree, index, rank, deltaR) { if (isValidState(tree, index, rank, deltaR)) { var previous = masteryTierFull(tree, index); previous >= 0 && deltaR > 0 ? setState(tree, previous, state[tree][previous], -deltaR) : deltaR > 0 && masteryTierEmpty(tree, data[tree][index].tier) && data[tree][index].ranks > 1 && totalPoints + data[tree][index].ranks <= MAX_POINTS && (deltaR = data[tree][index].ranks), setState(tree, index, rank, deltaR) } } function drawButton(tree, index, $root) { var spritePos = masterySpritePos(tree, index), buttonPos = masteryButtonPosition(tree, index), status = 0 == data[tree][index].tier ? "available" : "unavailable", rank = 0, tier = data[tree][index].tier; $root.append($("
").addClass("button").addClass(status).css({ left: buttonPos.x + "px", top: buttonPos.y + "px", backgroundPosition: ("full" == status ? -2 : "available" == status ? -2 - BUTTON_SIZE : -2 - 2 * BUTTON_SIZE) + "px " + (spritePos - 1) + "px" }).append($("
").addClass("buttonFrame").css({ backgroundPosition: ("full" == status ? tier % 2 == 1 ? 1 == tier ? -76 : -38 * tier : -38 : "available" == status ? -38 : 0) + "px " + ("full" == status ? 3 == tier ? -38 : 5 == tier ? -76 : 0 : 0) + "px" })).append($("
").addClass("counter").addClass("counter-" + status).text("0/" + data[tree][index].ranks).css({ visibility: data[tree][index].tier % 2 == 0 ? "visible" : "hidden" })).mouseenter(function() { var $tooltip = $(this).parents(".j-calculator").find(".j-tooltip"), tooltipText = masteryTooltip(tree, index, rank); formatTooltip($tooltip.show(), tooltipText), $(this).data("hover", !0), $(this).parent().mousemove() }).mouseleave(function() { var $tooltip = $(this).parents(".j-calculator").find(".j-tooltip"); $tooltip.hide(), $tooltip.data("hover", !1) }).data("update", function() { rank = state[tree][index] || 0, rank > 0 ? status = "full" : (status = masteryPointReq(tree, index) <= treePoints(tree) ? "available" : "unavailable", totalPoints >= MAX_POINTS && (status = masteryTierFull(tree, index) >= 0 ? "available" : "unavailable")), $(this).hasClass(status) || $(this).removeClass(buttonClasses.join(" ")).addClass(status).css({ backgroundPosition: ("full" == status ? -2 : "available" == status ? -2 - BUTTON_SIZE : -2 - 2 * BUTTON_SIZE) + "px " + (spritePos - 2) + "px" }); var counter = $(this).find(".counter").text(rank + "/" + data[tree][index].ranks); counter.hasClass("counter-" + status) || counter.removeClass(counterClasses.join(" ")).addClass("counter-" + status), $(this).find(".buttonFrame").css({ backgroundPosition: ("full" == status ? tier % 2 == 1 ? 1 == tier ? -76 : -38 * tier : -38 : "available" == status ? -38 : 0) + "px " + ("full" == status ? 3 == tier ? -38 : 5 == tier ? -76 : 0 : 0) + "px" }), $(this).data("hover") && $(this).mouseover() })) } function customTooltip(tooltip, tooltipText) { tooltip.addClass("custom"), tooltip.children(":not(p.first)").hide(), tooltip.find("p.first").text(tooltipText) } function formatTooltip(tooltip, tooltipText) { tooltip.removeClass("custom"); var head = tooltip.find("strong").text(tooltipText.header).show(); head.hasClass(treeNames[tooltipText.tree]) || head.removeClass(treeNames.join(" ")).addClass(treeNames[tooltipText.tree]); var rank = tooltip.find(".rank").text(tooltipText.rank).show(); rank.hasClass(tooltipText.rankClass) || rank.removeClass(rankClasses.join(" ")).addClass(tooltipText.rankClass), tooltip.find(".req").text(tooltipText.req).show(), tooltip.find("p.first").html(tooltipText.body); var second = tooltip.find("p.second"); null == tooltipText.bodyNext ? second.hide() : second.show().find(".content").html(tooltipText.bodyNext) } function masteryTooltip(tree, index, rank) { var mastery = data[tree][index], showNext = !(1 > rank || rank >= mastery.ranks), text = { tree: tree, header: mastery.name, rank: "等级: " + rank + "/" + mastery.ranks, rankClass: rank == mastery.ranks ? rankClasses[2] : isValidState(tree, index, rank, 1) ? rankClasses[1] : rankClasses[0], req: masteryTooltipReq(tree, index), body: masteryTooltipBody(mastery, rank), bodyNext: showNext ? masteryTooltipBody(mastery, rank + 1) : null }; return text } function masteryTooltipBody(mastery, rank) { rank = Math.max(0, rank - 1); var desc = mastery.desc; return desc = desc.replace(/#/, mastery.rankInfo[rank]), desc = desc.replace(/\n/g, "
"), desc = desc.replace(/\|(.+?)\|/g, "$1"), mastery.rankInfo2 && (desc = desc.replace(/#/, mastery.rankInfo2[rank])), mastery.perLevel && (desc = desc.replace(/#/, Math.round(100 * mastery.perLevel[rank]) / 100)), mastery.perLevel2 && (desc = desc.replace(/#/, Math.round(100 * mastery.perLevel[rank]) / 100)), desc } function masteryTooltipReq(tree, index) { var missing = [], pointReq = masteryPointReq(tree, index); if (pointReq > treePoints(tree) && missing.push("需要" + pointReq + "点天赋投入" + treeNames[tree]), (state[tree][index] || 0) < data[tree][index].ranks) { var existing = masteryTierFull(tree, index); existing >= 0 && missing.push("选择这个将会移除在" + data[tree][existing].name + "的天赋点数。") } return missing.join("\n") } function masteryButtonPosition(tree, index) { var idx = data[tree][index].index - 1, ix = idx % 4, iy = data[tree][index].tier, x = 0, y = 0; x += TREE_OFFSET * tree; x += SPACING.margin_left; if((tree==0 || tree==1) && index >=2 && index <= 4){ }else{ if (iy % 2 == 1 && iy != 5 && iy != 1) x += SPACING.margin_keystone; // 偶数行的偏移 } y += SPACING.margin_top; x += ix * (BUTTON_SIZE + SPACING.spacing_x); //x 的最终偏移 单行第2个为2 * (54 + 13) 偶数为 1* (54+13) y += iy * (BUTTON_SIZE + SPACING.spacing_y); // y的最终偏移 为 (54+上边距) * 行数 var dwOffset = 10; if(tree==0){ if(index==2||index==7||index==12){x=20 + dwOffset;} if(index==3||index==8||index==13){x=61 + dwOffset;} if(index==4||index==9||index==14){x=100 + dwOffset;} if(index==0||index==5||index==10){x=39 + dwOffset;} if(index==1||index==6||index==11){x=83 + dwOffset;} } if(tree==1){ if(index==2||index==7||index==12){x=184 + dwOffset;} if(index==3||index==8||index==13){x=225 + dwOffset;} if(index==4||index==9||index==14){x=266 + dwOffset;} if(index==0||index==5||index==10){x=202 + dwOffset;} if(index==1||index==6||index==11){x=246 + dwOffset;} } if(tree==2){ if(index==2||index==7||index==12){x=352 + dwOffset;} if(index==3||index==8||index==13){x=393 + dwOffset;} if(index==4||index==9||index==14){x=434 + dwOffset;} if(index==0||index==5||index==10){x=371 + dwOffset;} if(index==1||index==6||index==11){x=415 + dwOffset;} } return {x: x, y: y}; } function masterySpritePos(tree, index) { return 0 - BUTTON_SIZE * (treeOffsets[tree] + index) } function masteryTier(tree, index) { return data[tree][index].tier } function masteryPointReq(tree, index) { return TIER_REQS[masteryTier(tree, index)] } function masteryTierFull(tree, index) { var tier = data[tree][index].tier; for (var i in data[tree]) if (i != index && data[tree][i].tier == tier && (state[tree][i] || 0) + (state[tree][index] || 0) >= data[tree][i].ranks) return i; return -1 } function masteryTierEmpty(tree, tier) { for (var i in data[tree]) if (data[tree][i].tier == tier && (state[tree][i] || 0) > 0) return !1; return !0 } function treePoints(tree, treeTier) { var points = 0; for (var i in state[tree])(!treeTier || treeTier > masteryTier(tree, i)) && (points += state[tree][i]); return points } function isValidState(tree, index, rank, mod) { var mastery = data[tree][index]; if (0 > rank + mod || rank + mod > mastery.ranks) return !1; if (mod > 0) { if (totalPoints + mod > MAX_POINTS) return masteryTierFull(tree, index) >= 0 ? !0 : !1; if (masteryPointReq(tree, index) > treePoints(tree) - rank) return !1 } if (0 > mod) { for (var i in state[tree]) if (i != index && state[tree][i] > 0 && masteryPointReq(tree, i) > treePoints(tree, masteryTier(tree, i)) - (masteryTier(tree, index) < masteryTier(tree, i))) return !1; for (var i in state[tree]) if (i != index && state[tree][i] > 0 && data[tree][i].parent == index) return !1 } return !0 } function setState(tree, index, rank, mod) { state[tree][index] = rank + mod, totalPoints += mod, updateButtons(), updateLabels() } function resetStates(quiet) { for (var tree = 0; 3 > tree; tree++) resetTree(tree); 1 != quiet && (updateButtons(), updateLabels()) } function resetTree(tree) { totalPoints -= treePoints(tree); for (var index in state[tree]) state[tree][index] = 0 } function updateButtons($dom) { $dom.find(".button").each(function() { $(this).data("update").call(this, 0) }) } function updateLabels($dom, $con) { for (var tree = 0; 3 > tree; tree++) { var points = treePoints(tree); $dom.find("div[data-idx=" + tree + "]").text(treeNames[tree] + ": " + points), $con.find(".meda" + (tree + 1)).html(points) } } function escapeHtml(str) { var entityMap = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/" }; return String(str).replace(/[&<>"'\/]/g, function(s) { return entityMap[s] }) } function exportMasteries() { var tree, str = "", bits = 0, collected = 0, jumpStart = -1, flush = function() { str += exportChars[(jumpStart > -1) << maxbits | bits], bits = 0, collected = 0, jumpStart = -1 }; for (tree = 0; 3 > tree; tree++) { for (var index = 0; index < data[tree].length; index++) { var space = bitfit(tree, index, maxbits - collected); if (1 > space && (flush(), space = bitfit(tree, index, maxbits)), !(jumpStart > -1) || state[tree][index] > 0) if (collected > 0 || [0, 1, 2, 3, 4].filter(function(a) { return space > a }).map(function(a) { return state[tree][index + a] || 0 }).some(function(a) { return a > 0 })) { jumpStart > -1 && (bits = index - jumpStart, flush()); var len = bitlen(tree, index); bits = bits << len | (state[tree][index] || 0), collected += len } else 0 > jumpStart && (collected > 0 && flush(), jumpStart = index) } jumpStart > -1 ? (bits = index - jumpStart, flush()) : collected > 0 && flush() } return str } function importMasteries(param, $list, $sum, $con, championsId) { var str = param.talent_link, title = param.talent_title; resetStates(true); for (var tree = 0, index = 0, i = 0; i < str.length; i++) { var cur = importChars[str.charAt(i)]; if (void 0 == cur) return; if (0 == (32 & cur)) for (var num = bitfit(tree, index, maxbits), sizes = [0, 1, 2, 3, 4].filter(function(a) { return num > a }).map(function(a) { return bitlen(tree, index + a) }), j = 0; j < sizes.length; j++, index++) { var shift = sizes.slice(j + 1).reduce(function(a, b) { return a + b }, 0), value = cur >> shift & (1 << sizes[j]) - 1; state[tree][index] = value, totalPoints += value } else { var dist = 31 & cur; index += dist } if (index >= data[tree].length && (tree++, index = 0, tree >= data.length)) break } var returnData = { talent_title: title, talent_data: state }, $apply = $con.find(".btn_apply"); $apply.attr("href", $apply.attr("href") + "?championsId=" + championsId + "&data=" + $.base64.btoa(encodeURIComponent(JSON.stringify(returnData)))); updateButtons($list); updateLabels($sum, $con) } for (var treeNames = ["凶猛", "诡诈", "坚决"], treeOffsets = [0, data[0].length, data[0].length + data[1].length], MAX_POINTS = 30, TIER_REQS = [0, 5, 6, 11, 12, 17], TREE_OFFSET = 166, SPACING = { margin_left: 32, margin_top: 10, margin_keystone: 26, spacing_x: 10, spacing_y: 12 }, BUTTON_SIZE = 28, state = [{}, {}, {}], totalPoints = 0, buttonClasses = ["unavailable", "available", "full"], rankClasses = ["num-unavailable", "num-available", "num-full"], counterClasses = ["counter-unavailable", "counter-available", "counter-full"], maxbits = 5, exportChars = "WvlgUCsA7pGZ3zSjakbP2x0mTB6htH8JuKMq1yrnwEQDLY5IVNXdcioe9fF4OR_-", bitlen = function(tree, index) { return void 0 == data[tree][index] ? 0 : Math.floor(data[tree][index].ranks / 2) + 1 }, bitfit = function(tree, index, bits) { for (var start = index;;) { var len = bitlen(tree, index); if (len > bits || 0 == len) return index - start; bits -= len, index++ } }, importChars = {}, i = 0; i < exportChars.length; i++) importChars[exportChars.charAt(i)] = i; Array.prototype.filter || (Array.prototype.filter = function(fun) { "use strict"; if (void 0 === this || null === this) throw new TypeError; var t = Object(this), len = t.length >>> 0; if ("function" != typeof fun) throw new TypeError; for (var res = [], thisArg = arguments.length >= 2 ? arguments[1] : void 0, i = 0; len > i; i++) if (i in t) { var val = t[i]; fun.call(thisArg, val, i, t) && res.push(val) } return res }), Array.prototype.map || (Array.prototype.map = function(callback, thisArg) { var T, A, k; if (null == this) throw new TypeError(" this is null or not defined"); var O = Object(this), len = O.length >>> 0; if ("function" != typeof callback) throw new TypeError(callback + " is not a function"); for (arguments.length > 1 && (T = thisArg), A = new Array(len), k = 0; len > k;) { var kValue, mappedValue; k in O && (kValue = O[k], mappedValue = callback.call(T, kValue, k, O), A[k] = mappedValue), k++ } return A }), Array.prototype.some || (Array.prototype.some = function(fun) { "use strict"; if (null == this) throw new TypeError("Array.prototype.some called on null or undefined"); if ("function" != typeof fun) throw new TypeError; for (var t = Object(this), len = t.length >>> 0, thisArg = arguments.length >= 2 ? arguments[1] : void 0, i = 0; len > i; i++) if (i in t && fun.call(thisArg, t[i], i, t)) return !0; return !1 }), Array.prototype.reduce || (Array.prototype.reduce = function(callback) { if (null == this) throw new TypeError("Array.prototype.reduce called on null or undefined"); if ("function" != typeof callback) throw new TypeError(callback + " is not a function"); var value, t = Object(this), len = t.length >>> 0, k = 0; if (2 == arguments.length) value = arguments[1]; else { for (; len > k && !(k in t);) k++; if (k >= len) throw new TypeError("Reduce of empty array with no initial value"); value = t[k++] } for (; len > k; k++) k in t && (value = callback(value, t[k], k, t)); return value });