feat(character/pvp): add pvp page
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "azerothcore-armory",
|
"name": "azerothcore-armory",
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "azerothcore-armory",
|
"name": "azerothcore-armory",
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supercharge/promise-pool": "^2.1.0",
|
"@supercharge/promise-pool": "^2.1.0",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "azerothcore-armory",
|
"name": "azerothcore-armory",
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p tsconfig.json",
|
"build": "tsc -p tsconfig.json",
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ export class Armory {
|
||||||
app.get("/character/:realm/:name/talents", this.wrapRoute(charsController.talents.bind(charsController)));
|
app.get("/character/:realm/:name/talents", this.wrapRoute(charsController.talents.bind(charsController)));
|
||||||
app.get("/character/:realm/:name/achievements", this.wrapRoute(charsController.achievements.bind(charsController)));
|
app.get("/character/:realm/:name/achievements", this.wrapRoute(charsController.achievements.bind(charsController)));
|
||||||
app.get("/character/:realm/:character/achievements/data", this.wrapRoute(charsController.achievementsData.bind(charsController)));
|
app.get("/character/:realm/:character/achievements/data", this.wrapRoute(charsController.achievementsData.bind(charsController)));
|
||||||
|
app.get("/character/:realm/:name/pvp", this.wrapRoute(charsController.pvp.bind(charsController)));
|
||||||
|
|
||||||
const guildsController = new GuildController(this);
|
const guildsController = new GuildController(this);
|
||||||
app.get("/guild/:realm/:name", this.wrapRoute(guildsController.guild.bind(guildsController)));
|
app.get("/guild/:realm/:name", this.wrapRoute(guildsController.guild.bind(guildsController)));
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,14 @@ export enum EFaction {
|
||||||
Alliance = 1,
|
Alliance = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IEmblem {
|
||||||
|
icon: string;
|
||||||
|
iconColor: string;
|
||||||
|
border: string;
|
||||||
|
borderColor: string;
|
||||||
|
background: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class Utils {
|
export class Utils {
|
||||||
public static raceNames = {
|
public static raceNames = {
|
||||||
1: "human",
|
1: "human",
|
||||||
|
|
@ -32,4 +40,15 @@ export class Utils {
|
||||||
public static getFactionFromRaceId(race: number): EFaction {
|
public static getFactionFromRaceId(race: number): EFaction {
|
||||||
return [1, 3, 4, 7, 11].includes(race) ? EFaction.Alliance : EFaction.Horde;
|
return [1, 3, 4, 7, 11].includes(race) ? EFaction.Alliance : EFaction.Horde;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static makeEmblemObject(obj: any, padWithZeroes: boolean = true): IEmblem {
|
||||||
|
const padLength = padWithZeroes ? 2 : 0;
|
||||||
|
return {
|
||||||
|
icon: obj.emblemStyle.toString().padStart(padLength, "0"),
|
||||||
|
iconColor: obj.emblemColor.toString().padStart(padLength, "0"),
|
||||||
|
border: obj.borderStyle.toString().padStart(padLength, "0"),
|
||||||
|
borderColor: obj.borderColor.toString().padStart(padLength, "0"),
|
||||||
|
background: obj.background.toString().padStart(padLength, "0"),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,9 +178,9 @@ export class CharacterController {
|
||||||
const mounts = await this.getMounts(realmName, charData.guid);
|
const mounts = await this.getMounts(realmName, charData.guid);
|
||||||
|
|
||||||
res.render("character.hbs", {
|
res.render("character.hbs", {
|
||||||
title: `Armory - ${charName}`,
|
title: `Armory - ${charData.name}`,
|
||||||
...this.makeSharedDataObject(realm, charData),
|
...this.makeSharedDataObject(realm, charData),
|
||||||
data: JSON.stringify({
|
data: {
|
||||||
race: charData.race,
|
race: charData.race,
|
||||||
gender: charData.gender,
|
gender: charData.gender,
|
||||||
class: charData.class,
|
class: charData.class,
|
||||||
|
|
@ -189,7 +189,7 @@ export class CharacterController {
|
||||||
customizationOptions: customization,
|
customizationOptions: customization,
|
||||||
equipment,
|
equipment,
|
||||||
mounts,
|
mounts,
|
||||||
}),
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.armory.gc();
|
this.armory.gc();
|
||||||
|
|
@ -212,13 +212,13 @@ export class CharacterController {
|
||||||
}
|
}
|
||||||
|
|
||||||
res.render("character-talents.hbs", {
|
res.render("character-talents.hbs", {
|
||||||
title: `Armory - ${charName} - Talents`,
|
title: `Armory - ${charData.name} - Talents`,
|
||||||
...this.makeSharedDataObject(realm, charData),
|
...this.makeSharedDataObject(realm, charData),
|
||||||
data: JSON.stringify({
|
data: {
|
||||||
talents: await this.getTalents(realm.name, charData.guid),
|
talents: await this.getTalents(realm.name, charData.guid),
|
||||||
trees: await this.getTalentTrees(charData.class),
|
trees: await this.getTalentTrees(charData.class),
|
||||||
glyphs: await this.getGlyphs(realm.name, charData.guid),
|
glyphs: await this.getGlyphs(realm.name, charData.guid),
|
||||||
}),
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ export class CharacterController {
|
||||||
}
|
}
|
||||||
|
|
||||||
res.render("character-achievements.hbs", {
|
res.render("character-achievements.hbs", {
|
||||||
title: `Armory - ${charName} - Achievements`,
|
title: `Armory - ${charData.name} - Achievements`,
|
||||||
...this.makeSharedDataObject(realm, charData),
|
...this.makeSharedDataObject(realm, charData),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -266,6 +266,31 @@ export class CharacterController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async pvp(req: express.Request, res: express.Response, next: express.NextFunction): Promise<void> {
|
||||||
|
const realmName = req.params.realm;
|
||||||
|
const charName = req.params.name;
|
||||||
|
|
||||||
|
const realm = this.armory.getRealm(realmName);
|
||||||
|
if (realm === undefined) {
|
||||||
|
// Could not find realm
|
||||||
|
return next(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const charData = await this.getCharacterData(realm, charName);
|
||||||
|
if (charData === null) {
|
||||||
|
// Could not find character
|
||||||
|
return next(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.render("character-pvp.hbs", {
|
||||||
|
title: `Armory - ${charData.name} - PvP`,
|
||||||
|
...this.makeSharedDataObject(realm, charData),
|
||||||
|
faction: Utils.getFactionFromRaceId(charData.race),
|
||||||
|
kills: await this.getPvpKills(realm.name, charData.guid),
|
||||||
|
arenaTeams: await this.getArenaTeams(realm.name, charData.guid),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private makeSharedDataObject(realm: IRealmConfig, charData: ICharacterData) {
|
private makeSharedDataObject(realm: IRealmConfig, charData: ICharacterData) {
|
||||||
return {
|
return {
|
||||||
realm: realm.name,
|
realm: realm.name,
|
||||||
|
|
@ -770,4 +795,44 @@ export class CharacterController {
|
||||||
earned,
|
earned,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getPvpKills(realm: string, charGuid: number): Promise<{ total: number, today: number, yesterday: number }> {
|
||||||
|
const [rows, fields] = await this.armory.getCharactersDb(realm).query({
|
||||||
|
sql: `
|
||||||
|
SELECT totalKills, todayKills, yesterdayKills
|
||||||
|
FROM characters
|
||||||
|
WHERE guid = ?
|
||||||
|
`,
|
||||||
|
values: [charGuid],
|
||||||
|
timeout: this.armory.config.dbQueryTimeout,
|
||||||
|
});
|
||||||
|
const row = rows[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: row.totalKills,
|
||||||
|
today: row.todayKills,
|
||||||
|
yesterday: row.yesterdayKills,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getArenaTeams(realm: string, charGuid: number): Promise<any[]> {
|
||||||
|
const [rows, fields] = await this.armory.getCharactersDb(realm).query({
|
||||||
|
sql: `
|
||||||
|
SELECT
|
||||||
|
arena_team.arenaTeamId AS id, arena_team.name, arena_team.type, arena_team.rating, arena_team.seasonWins, arena_team.seasonGames,
|
||||||
|
arena_team.backgroundColor AS background, arena_team.emblemStyle, arena_team.emblemColor, arena_team.borderStyle, arena_team.borderColor
|
||||||
|
FROM arena_team_member
|
||||||
|
LEFT JOIN arena_team ON arena_team_member.arenaTeamId = arena_team.arenaTeamId
|
||||||
|
WHERE guid = ?
|
||||||
|
ORDER BY arena_team.type ASC
|
||||||
|
`,
|
||||||
|
values: [charGuid],
|
||||||
|
timeout: this.armory.config.dbQueryTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (rows as RowDataPacket[]).map(row => {
|
||||||
|
row.emblem = Utils.makeEmblemObject(row, false);
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,13 +133,7 @@ export class GuildController {
|
||||||
name: guild.name,
|
name: guild.name,
|
||||||
leader: leader.name,
|
leader: leader.name,
|
||||||
faction: Utils.getFactionFromRaceId(leader.race),
|
faction: Utils.getFactionFromRaceId(leader.race),
|
||||||
emblem: {
|
emblem: Utils.makeEmblemObject(guild),
|
||||||
icon: guild.emblemStyle.toString().padStart(2, "0"),
|
|
||||||
iconColor: guild.emblemColor.toString().padStart(2, "0"),
|
|
||||||
border: guild.borderStyle.toString().padStart(2, "0"),
|
|
||||||
borderColor: guild.borderColor.toString().padStart(2, "0"),
|
|
||||||
background: guild.background.toString().padStart(2, "0"),
|
|
||||||
},
|
|
||||||
membersCount,
|
membersCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,18 @@ require("source-map-support").install();
|
||||||
const baseUrl = "https://wow.zamimg.com/modelviewer/live";
|
const baseUrl = "https://wow.zamimg.com/modelviewer/live";
|
||||||
|
|
||||||
class Stopwatch {
|
class Stopwatch {
|
||||||
private startTime: Date;
|
private startTime: number;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(): void {
|
public start(): void {
|
||||||
this.startTime = new Date();
|
this.startTime = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop(text?: string): void {
|
public stop(text?: string): void {
|
||||||
const dt = Date.now() - this.startTime.getTime();
|
const dt = Date.now() - this.startTime;
|
||||||
const txt = text ?? "Done in {time}";
|
const txt = text ?? "Done in {time}";
|
||||||
console.log(txt.replace("{time}", prettyMs(dt)));
|
console.log(txt.replace("{time}", prettyMs(dt)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
static/character-pvp.hbs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/character-pvp.css">
|
||||||
|
{{> emblems}}
|
||||||
|
|
||||||
|
{{> character-header }}
|
||||||
|
|
||||||
|
<div class="columns is-multiline">
|
||||||
|
<div class="column has-text-centered is-size-5 is-full-touch is-one-quarter-desktop">
|
||||||
|
{{#eq faction 1}}
|
||||||
|
<img class="faction" src="/img/PlusManz-Alliance.png">
|
||||||
|
{{else}}
|
||||||
|
<img class="faction" src="/img/PlusManz-Horde.png">
|
||||||
|
{{/eq}}
|
||||||
|
|
||||||
|
<div>Total Kills: {{kills.total}}</div>
|
||||||
|
<div>Kills Today: {{kills.today}}</div>
|
||||||
|
<div>Kills Yesterday: {{kills.yesterday}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#each arenaTeams}}
|
||||||
|
<div class="column is-full-touch is-one-quarter-desktop">
|
||||||
|
<div class="box arena-team" data-team-id="{{this.id}}">
|
||||||
|
<div class="info has-text-centered">
|
||||||
|
<div class="is-size-4">{{this.name}}</div>
|
||||||
|
<div class="is-size-5">{{this.type}}v{{this.type}} Team</div>
|
||||||
|
<div>Rating: {{this.rating}}</div>
|
||||||
|
<div>{{this.seasonWins}} W / {{subtract this.seasonGames this.seasonWins}} L</div>
|
||||||
|
</div>
|
||||||
|
<div class="emblem-container">
|
||||||
|
<div class="arena-emblem">
|
||||||
|
<canvas width="74" height="128"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
{{#each arenaTeams}}
|
||||||
|
createArenaEmblem({{this.type}}, {{{JSONstringify this.emblem}}}, $(".arena-team[data-team-id={{this.id}}] .arena-emblem")[0]);
|
||||||
|
{{/each}}
|
||||||
|
</script>
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
const talentsData = JSON.parse(`{{{data}}}`);
|
const talentsData = {{{JSONstringify data}}};
|
||||||
|
|
||||||
for (let spec = 0; spec < 2; ++spec) {
|
for (let spec = 0; spec < 2; ++spec) {
|
||||||
const $spec = $(`#talents-spec-${spec}`);
|
const $spec = $(`#talents-spec-${spec}`);
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
debug: () => { },
|
debug: () => { },
|
||||||
};
|
};
|
||||||
|
|
||||||
const charData = JSON.parse(`{{{data}}}`);
|
const charData = {{{JSONstringify data}}};
|
||||||
const races = {
|
const races = {
|
||||||
1: "human",
|
1: "human",
|
||||||
2: "orc",
|
2: "orc",
|
||||||
|
|
|
||||||
9
static/css/character-pvp.css
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
.arena-team {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arena-team .info {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
26
static/css/emblems.css
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
.guild-emblem .images,
|
||||||
|
.arena-emblem .images {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-emblem {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 128px;
|
||||||
|
height: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-emblem canvas {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
clip-path: circle(50% at 50% 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.arena-emblem {
|
||||||
|
width: 74px;
|
||||||
|
height: 128px;
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#guild-header .emblem {
|
#guild-header .emblem-container {
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,26 +21,8 @@
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#emblem-images {
|
.guild-emblem {
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#emblem {
|
|
||||||
background: url("/img/guild-emblems/circle.png") no-repeat center;
|
background: url("/img/guild-emblems/circle.png") no-repeat center;
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 128px;
|
|
||||||
width: 128px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#emblem canvas {
|
|
||||||
height: 96px;
|
|
||||||
width: 96px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.circle {
|
|
||||||
clip-path: circle(50% at 50% 50%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#members_processing {
|
#members_processing {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/css/guild.css">
|
<link rel="stylesheet" type="text/css" href="/css/guild.css">
|
||||||
{{> datatables}}
|
{{> datatables}}
|
||||||
|
{{> emblems}}
|
||||||
|
|
||||||
<a href="/">Back to Armory</a>
|
<a href="/">Back to Armory</a>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<div id="guild-header">
|
<div id="guild-header">
|
||||||
<div class="emblem">
|
<div class="emblem-container">
|
||||||
<div id="emblem" class="shape-outer circle">
|
<div class="guild-emblem circle">
|
||||||
<canvas class="shape-inner circle" width="128" height="96"></canvas>
|
<div class="images"></div>
|
||||||
|
<canvas class="circle" width="128" height="96"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -36,14 +38,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<div id="emblem-images">
|
|
||||||
<img id="emblem-bg-upper" src="/img/guild-emblems/Background_{{emblem.background}}_TU_U.PNG">
|
|
||||||
<img id="emblem-bg-lower" src="/img/guild-emblems/Background_{{emblem.background}}_TL_U.PNG">
|
|
||||||
<img id="emblem-icon-upper" src="/img/guild-emblems/Emblem_{{emblem.icon}}_{{emblem.iconColor}}_TU_U.PNG">
|
|
||||||
<img id="emblem-icon-lower" src="/img/guild-emblems/Emblem_{{emblem.icon}}_{{emblem.iconColor}}_TL_U.PNG">
|
|
||||||
<img id="emblem-border-upper" src="/img/guild-emblems/Border_{{emblem.border}}_{{emblem.borderColor}}_TU_U.PNG">
|
|
||||||
<img id="emblem-border-lower" src="/img/guild-emblems/Border_{{emblem.border}}_{{emblem.borderColor}}_TL_U.PNG">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table id="members" class="stripe hover row-border">
|
<table id="members" class="stripe hover row-border">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
@ -60,59 +54,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
function createEmblem() {
|
createGuildEmblem({{{JSONstringify emblem}}}, $(".emblem-container .guild-emblem")[0]);
|
||||||
const canvas = $("#emblem canvas")[0];
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
|
|
||||||
const mask = $("#emblem-mask")[0];
|
|
||||||
const bgUpper = $("#emblem-bg-upper")[0];
|
|
||||||
const bgLower = $("#emblem-bg-lower")[0];
|
|
||||||
const iconUpper = $("#emblem-icon-upper")[0];
|
|
||||||
const iconLower = $("#emblem-icon-lower")[0];
|
|
||||||
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(0, 0);
|
|
||||||
ctx.lineTo(26, 0);
|
|
||||||
ctx.lineTo(64, 28);
|
|
||||||
ctx.lineTo(102, 0);
|
|
||||||
ctx.lineTo(128, 0);
|
|
||||||
ctx.lineTo(128, 96);
|
|
||||||
ctx.lineTo(0, 96);
|
|
||||||
ctx.closePath();
|
|
||||||
ctx.clip();
|
|
||||||
drawEmblemLayer(canvas, ctx, "bg");
|
|
||||||
drawEmblemLayer(canvas, ctx, "icon");
|
|
||||||
drawEmblemLayer(canvas, ctx, "border");
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawEmblemLayer(canvas, ctx, layer) {
|
|
||||||
const upper = $(`#emblem-${layer}-upper`)[0];
|
|
||||||
const lower = $(`#emblem-${layer}-lower`)[0];
|
|
||||||
|
|
||||||
const w = upper.width / 2;
|
|
||||||
const uh = upper.height;
|
|
||||||
const lh = lower.height;
|
|
||||||
|
|
||||||
ctx.drawImage(upper, 0, 0, w, uh, w, 0, w, uh);
|
|
||||||
ctx.drawImage(lower, 0, 0, w, lh, w, upper.height, w, lh);
|
|
||||||
ctx.save();
|
|
||||||
ctx.scale(-1, 1);
|
|
||||||
ctx.drawImage(upper, 0, 0, w, uh, 0, 0, -w, uh);
|
|
||||||
ctx.drawImage(lower, 0, 0, w, lh, 0, upper.height, -w, lh);
|
|
||||||
ctx.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
const emblemLoadPromises = $("#emblem-images img").map((idx, img) => {
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
if (img.complete) {
|
|
||||||
res();
|
|
||||||
} else {
|
|
||||||
img.addEventListener("load", res);
|
|
||||||
img.addEventListener("error", rej);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Promise.all(emblemLoadPromises).then(createEmblem);
|
|
||||||
|
|
||||||
dt = $("#members").DataTable({
|
dt = $("#members").DataTable({
|
||||||
processing: true,
|
processing: true,
|
||||||
|
|
|
||||||
BIN
static/img/arena-banners/PVP-Banner-2-Border-1.PNG
Normal file
|
After Width: | Height: | Size: 256 B |
BIN
static/img/arena-banners/PVP-Banner-2-Border-2.PNG
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
static/img/arena-banners/PVP-Banner-2-Border-3.PNG
Normal file
|
After Width: | Height: | Size: 6 KiB |
BIN
static/img/arena-banners/PVP-Banner-2-Border-4.PNG
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
static/img/arena-banners/PVP-Banner-2-Border-5.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-2-Border-6.PNG
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
static/img/arena-banners/PVP-Banner-2-Crop.PNG
Normal file
|
After Width: | Height: | Size: 7 KiB |
BIN
static/img/arena-banners/PVP-Banner-2.PNG
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Border-1.PNG
Normal file
|
After Width: | Height: | Size: 256 B |
BIN
static/img/arena-banners/PVP-Banner-3-Border-2.PNG
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Border-3.PNG
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Border-4.PNG
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Border-5.PNG
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Border-6.PNG
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
static/img/arena-banners/PVP-Banner-3-Crop.PNG
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
static/img/arena-banners/PVP-Banner-3.PNG
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Border-1.PNG
Normal file
|
After Width: | Height: | Size: 256 B |
BIN
static/img/arena-banners/PVP-Banner-5-Border-2.PNG
Normal file
|
After Width: | Height: | Size: 6 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Border-3.PNG
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Border-4.PNG
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Border-5.PNG
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Border-6.PNG
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
static/img/arena-banners/PVP-Banner-5-Crop.PNG
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
static/img/arena-banners/PVP-Banner-5.PNG
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-1.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-10.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-100.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-101.PNG
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-102.PNG
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-11.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-12.PNG
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-13.PNG
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-14.PNG
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-15.PNG
Normal file
|
After Width: | Height: | Size: 6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-16.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-17.PNG
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-18.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-19.PNG
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-2.PNG
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-20.PNG
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-21.PNG
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-22.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-23.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-24.PNG
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-25.PNG
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-26.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-27.PNG
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-28.PNG
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-29.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-3.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-30.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-31.PNG
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-32.PNG
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-33.PNG
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-34.PNG
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-35.PNG
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-36.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-37.PNG
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-38.PNG
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-39.PNG
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-4.PNG
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-40.PNG
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-41.PNG
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-42.PNG
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-43.PNG
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-44.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-45.PNG
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-46.PNG
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-47.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-48.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-49.PNG
Normal file
|
After Width: | Height: | Size: 9 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-5.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-50.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-51.PNG
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-52.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-53.PNG
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-54.PNG
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-55.PNG
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-56.PNG
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-57.PNG
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-58.PNG
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-59.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-6.PNG
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-60.PNG
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-61.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/img/arena-banners/PVP-Banner-Emblem-62.PNG
Normal file
|
After Width: | Height: | Size: 9.2 KiB |