Преглед изворни кода

Merge branch 'master' into 'release'

Master

See merge request Isleward/isleward!456
tags/v0.4.3
Big Bad Waffle пре 4 година
родитељ
комит
88f2e24755
90 измењених фајлова са 2036 додато и 707 уклоњено
  1. +6
    -16
      src/client/css/colors.less
  2. +11
    -9
      src/client/css/main.less
  3. +59
    -4
      src/client/js/config.js
  4. +13
    -6
      src/client/js/main.js
  5. +14
    -0
      src/client/js/misc/tosAcceptanceValid.js
  6. +16
    -33
      src/client/js/objects/objects.js
  7. +36
    -6
      src/client/js/sound/sound.js
  8. +25
    -0
      src/client/js/system/browserStorage.js
  9. +76
    -44
      src/client/ui/factory.js
  10. +81
    -0
      src/client/ui/shared/renderItem.js
  11. +11
    -2
      src/client/ui/templates/characters/characters.js
  12. +2
    -2
      src/client/ui/templates/createCharacter/createCharacter.js
  13. +3
    -3
      src/client/ui/templates/createCharacter/styles.less
  14. +16
    -11
      src/client/ui/templates/death/styles.less
  15. +1
    -0
      src/client/ui/templates/equipment/styles.less
  16. +16
    -2
      src/client/ui/templates/events/events.js
  17. +4
    -6
      src/client/ui/templates/events/styles.less
  18. +47
    -55
      src/client/ui/templates/inventory/inventory.js
  19. +173
    -34
      src/client/ui/templates/inventory/styles.less
  20. +1
    -1
      src/client/ui/templates/login/login.js
  21. +1
    -1
      src/client/ui/templates/login/styles.less
  22. +2
    -2
      src/client/ui/templates/login/template.html
  23. +112
    -0
      src/client/ui/templates/mainMenu/mainMenu.js
  24. +49
    -0
      src/client/ui/templates/mainMenu/styles.less
  25. +8
    -0
      src/client/ui/templates/mainMenu/template.html
  26. +1
    -1
      src/client/ui/templates/menu/menu.js
  27. +1
    -1
      src/client/ui/templates/menu/styles.less
  28. +1
    -1
      src/client/ui/templates/menu/template.html
  29. +88
    -37
      src/client/ui/templates/messages/messages.js
  30. +66
    -41
      src/client/ui/templates/messages/styles.less
  31. +4
    -1
      src/client/ui/templates/middleHud/styles.less
  32. +7
    -4
      src/client/ui/templates/online/styles.less
  33. +135
    -47
      src/client/ui/templates/options/options.js
  34. +70
    -32
      src/client/ui/templates/options/styles.less
  35. +43
    -7
      src/client/ui/templates/options/template.html
  36. +7
    -5
      src/client/ui/templates/passives/input.js
  37. +11
    -13
      src/client/ui/templates/passives/passives.js
  38. +20
    -2
      src/client/ui/templates/quests/quests.js
  39. +11
    -5
      src/client/ui/templates/quests/styles.less
  40. +5
    -7
      src/client/ui/templates/reputation/reputation.js
  41. +30
    -12
      src/client/ui/templates/reputation/styles.less
  42. +59
    -50
      src/client/ui/templates/smithing/styles.less
  43. +4
    -3
      src/client/ui/templates/spells/styles.less
  44. +10
    -27
      src/client/ui/templates/stash/stash.js
  45. +7
    -2
      src/client/ui/templates/stash/styles.less
  46. +33
    -2
      src/client/ui/templates/target/target.js
  47. +78
    -0
      src/client/ui/templates/terms/styles.less
  48. +9
    -0
      src/client/ui/templates/terms/template.html
  49. +43
    -0
      src/client/ui/templates/terms/terms.js
  50. +6
    -41
      src/client/ui/templates/trade/trade.js
  51. +33
    -18
      src/client/ui/templates/workbench/styles.less
  52. +15
    -3
      src/client/ui/uiBase.js
  53. +29
    -4
      src/server/components/extensions/socialCommands.js
  54. +17
    -8
      src/server/components/inventory.js
  55. +1
    -0
      src/server/components/passives.js
  56. +1
    -0
      src/server/components/player.js
  57. +3
    -1
      src/server/components/quests.js
  58. +13
    -0
      src/server/components/social/canChat.js
  59. +2
    -6
      src/server/components/social/chat.js
  60. +18
    -0
      src/server/components/social/rezone.js
  61. +21
    -19
      src/server/components/spellbook.js
  62. +13
    -4
      src/server/components/stash.js
  63. +17
    -5
      src/server/config/clientConfig.js
  64. +4
    -0
      src/server/config/effects/effectStunned.js
  65. +46
    -4
      src/server/config/maps/cave/map.json
  66. +13
    -1
      src/server/config/maps/fjolarok/zone.js
  67. +2
    -2
      src/server/config/maps/sewer/events/plagueOfRats.js
  68. +17
    -1
      src/server/config/maps/sewer/zone.js
  69. +5
    -0
      src/server/config/quests/questBuilder.js
  70. +2
    -2
      src/server/config/recipes/etching.js
  71. +8
    -0
      src/server/config/roles.js
  72. +1
    -1
      src/server/config/serverConfig.js
  73. +3
    -3
      src/server/config/spells/spellFireblast.js
  74. +18
    -0
      src/server/config/tos.js
  75. +2
    -0
      src/server/index.js
  76. +1
    -0
      src/server/items/enchanter.js
  77. +2
    -8
      src/server/mail/mailSqlite.js
  78. +25
    -0
      src/server/objects/objBase.js
  79. +14
    -0
      src/server/security/connections.js
  80. +4
    -3
      src/server/security/rest.js
  81. +14
    -29
      src/server/security/router.js
  82. +36
    -0
      src/server/security/routerConfig.js
  83. +2
    -0
      src/server/security/sheets.js
  84. +2
    -1
      src/server/security/sheetsConfig.js
  85. +37
    -0
      src/server/security/transactions.js
  86. +17
    -1
      src/server/server.js
  87. +30
    -0
      src/server/world/atlas.js
  88. +10
    -1
      src/server/world/instancer.js
  89. +3
    -3
      src/server/world/map/canPathFromPos.js
  90. +3
    -1
      src/server/world/worker.js

+ 6
- 16
src/client/css/colors.less Прегледај датотеку

@@ -1,59 +1,49 @@
@white: rgb(242, 245, 245);
@black: #2d2136;

@brown: rgb(107, 79, 76);

@darkGray: rgb(55, 48, 65);
@gray: rgb(60, 63, 76);
@lightGray: rgb(146, 147, 152);

@yellow: #ffeb38;
@purple: #a24eff;
@orange: #ff6942;

@red: #d43346;
@blue: #3fa7dd;
@green: #80f643;
@greenA: #80f643;
@greenB: #4ac441;
@greenC: #386646;

@blackA: #505360;
@blackB: #3c3f4c;
@blackC: #373041;
@blackD: #312136;

@brownC: #b15a30;
@brownD: #763b3b;

@redA: #ff4252;
@redB: #d43346;
@redC: #a82841;
@redD: #802343;
@orangeA: #ff6942;
@orangeB: #db5538;
@orangeC: #b34b3a;
@orangeD: #953f36;

@yellowB: #faac45;
@yellowC: #d07840;

@blueA: #48edff;
@blueB: #3fa7dd;
@blueC: #3a71ba;
@blueD: #42548d;

@tealB: #51fc9a;
@tealC: #44cb95;

@purpleA: #a24eff;
@purpleB: #7a3ad3;
@purpleC: #533399;
@purpleD: #393268;

@pinkA: #fc66f7;
@pinkB: #de43ae;

@grayB: #c0c3cf;
@grayC: #929398;
@grayD: #69696e;
@qualityCommon: @white;
@qualityMagic: @greenB;
@qualityRare: @blueB;
@qualityEpic: @purpleA;
@qualityLegendary: @orangeA;

+ 11
- 9
src/client/css/main.less Прегледај датотеку

@@ -38,10 +38,12 @@ body {

}

.mobile .right {
top: 0px;
right: 0px;
.mobile.ui-container > .right {
top: 10px;
right: 158px;
z-index: 2;
display: flex;
flex-direction: row-reverse;
}

* {
@@ -122,7 +124,7 @@ body {
.btnClose {
position: absolute;
background-color: @blackA;
color: @orange;
color: @orangeA;
cursor: pointer;
height: 31px;
width: 31px;
@@ -159,23 +161,23 @@ body {
}

.q0 {
color: @white;
color: @qualityCommon;
}

.q1 {
color: @greenB;
color: @qualityMagic;
}

.q2 {
color: @blueB;
color: @qualityRare;
}

.q3 {
color: @purpleA;
color: @qualityEpic;
}

.q4 {
color: @orange;
color: @qualityLegendary;
}

.color-red {


+ 59
- 4
src/client/js/config.js Прегледај датотеку

@@ -1,9 +1,64 @@
define([
'js/system/browserStorage'
], function (
browserStorage
) {
return {
showNames: false
const config = {
showNames: true,
showQuests: 'on',
showEvents: true,
playAudio: true,
qualityIndicators: 'off',
unusableIndicators: 'off',
rememberChatChannel: true
};

const valueChains = {
showQuests: ['on', 'minimal', 'off'],
qualityIndicators: ['border', 'bottom', 'background', 'off'],
unusableIndicators: ['off', 'border', 'top', 'background']
};

const getNextValue = key => {
const currentValue = config[key];
const chain = valueChains[key];
const currentIndex = chain.indexOf(currentValue);

const nextValue = chain[(currentIndex + 1) % chain.length];

return nextValue;
};

const getKeyName = key => {
return `opt_${key.toLowerCase()}`;
};

config.set = (key, value) => {
config[key] = value;

browserStorage.set(getKeyName(key), config[key]);
};

config.toggle = key => {
if (valueChains[key])
config[key] = getNextValue(key);
else
config[key] = !config[key];

browserStorage.set(getKeyName(key), config[key]);
};

const loadValue = key => {
const currentValue = browserStorage.get(getKeyName(key));

if (currentValue === '{unset}')
return;

const morphedValue = valueChains[key] ? currentValue : (currentValue === 'true');
config[key] = morphedValue;
};

Object.keys(config).forEach(key => loadValue(key) );

return config;
});

+ 13
- 6
src/client/js/main.js Прегледај датотеку

@@ -8,6 +8,8 @@ define([
'js/input',
'js/system/events',
'js/resources',
'js/sound/sound',
'js/system/globals',
'ui/templates/online/online',
'ui/templates/tooltips/tooltips'
], function (
@@ -19,7 +21,9 @@ define([
numbers,
input,
events,
resources
resources,
sound,
globals
) {
return {
hasFocus: true,
@@ -34,13 +38,14 @@ define([
onClientReady: function () {
client.request({
module: 'clientConfig',
method: 'getResourcesList',
callback: this.onGetResourceList.bind(this)
method: 'getClientConfig',
callback: this.onGetClientConfig.bind(this)
});
},

onGetResourceList: function (list) {
resources.init(list);
onGetClientConfig: function (config) {
globals.clientConfig = config;
resources.init(config.resourceList);

events.on('onResourcesLoaded', this.start.bind(this));
},
@@ -51,13 +56,15 @@ define([

$(window).on('contextmenu', this.onContextMenu.bind(this));

sound.init();

objects.init();
renderer.init();
input.init();

numbers.init();

uiFactory.init();
uiFactory.init(null, globals.clientConfig.uiList);
uiFactory.build('login', 'body');

this.update();


+ 14
- 0
src/client/js/misc/tosAcceptanceValid.js Прегледај датотеку

@@ -0,0 +1,14 @@
define([
'js/system/browserStorage',
'js/system/globals'
], function (
browserStorage,
globals
) {
return () => {
const acceptedVersion = browserStorage.get('tos_accepted_version');
const currentVersion = globals.clientConfig.tos.version;

return (acceptedVersion === currentVersion);
};
});

+ 16
- 33
src/client/js/objects/objects.js Прегледај датотеку

@@ -12,21 +12,14 @@ define([
config
) {
return {
showNames: true,

objects: [],

init: function () {
events.on('onKeyDown', this.onKeyDown.bind(this));
events.on('onGetObject', this.onGetObject.bind(this));
events.on('onRezone', this.onRezone.bind(this));
events.on('onChangeHoverTile', this.getLocation.bind(this));
events.on('onTilesVisible', this.onTilesVisible.bind(this));

//Get saved value for showNames, or use the value set above
let showNames = window.localStorage.getItem('iwd_opt_shownames');
this.showNames = showNames ? (showNames === 'true') : this.showNames;
config.showNames = this.showNames;
events.on('onToggleNameplates', this.onToggleNameplates.bind(this));
},

getLocation: function (x, y) {
@@ -282,7 +275,7 @@ define([
if (template.hidden !== null) {
sprite.visible = !template.hidden;
if (obj.nameSprite)
obj.nameSprite.visible = this.showNames;
obj.nameSprite.visible = config.showNames;
if ((obj.stats) && (obj.stats.hpSprite)) {
obj.stats.hpSprite.visible = !template.hidden;
obj.stats.hpSpriteInner.visible = !template.hidden;
@@ -305,7 +298,7 @@ define([
x: (obj.x * scale) + (scale / 2),
y: (obj.y * scale) + scale
});
obj.nameSprite.visible = this.showNames;
obj.nameSprite.visible = config.showNames;
}

if (obj.sprite) {
@@ -346,29 +339,6 @@ define([
}
},

onKeyDown: function (key) {
if (key === 'v') {
this.showNames = !this.showNames;

//Set new value in localStorage for showNames
window.localStorage.setItem('iwd_opt_shownames', this.showNames);
config.showNames = this.showNames;

let showNames = this.showNames;

let objects = this.objects;
let oLen = objects.length;
for (let i = 0; i < oLen; i++) {
let obj = objects[i];
let ns = obj.nameSprite;
if ((!ns) || (obj.dead) || ((obj.sprite) && (!obj.sprite.visible)))
continue;

ns.visible = showNames;
}
}
},

onTilesVisible: function (tiles, visible) {
let objects = this.objects;
let oLen = objects.length;
@@ -383,6 +353,19 @@ define([

o.setVisible(visible);
}
},

onToggleNameplates: function (show) {
let objects = this.objects;
let oLen = objects.length;
for (let i = 0; i < oLen; i++) {
let obj = objects[i];
let ns = obj.nameSprite;
if ((!ns) || (obj.dead) || ((obj.sprite) && (!obj.sprite.visible)))
continue;

ns.visible = show;
}
}
};
});

+ 36
- 6
src/client/js/sound/sound.js Прегледај датотеку

@@ -1,15 +1,23 @@
define([
'howler',
'js/misc/physics'
'js/misc/physics',
'js/system/events',
'js/config'
], function (
howler,
physics
physics,
events,
config
) {
return {
sounds: [],

init: function (zone) {
muted: false,

init: function () {
events.on('onToggleAudio', this.onToggleAudio.bind(this));

this.onToggleAudio(config.playAudio);
},

unload: function (zoneId) {
@@ -24,7 +32,7 @@ define([
},

update: function (x, y) {
this.sounds.forEach(function (s) {
this.sounds.forEach(s => {
let volume;

if (!s.w) {
@@ -67,9 +75,13 @@ define([
loop: true,
volume: 0
});

if (this.muted)
s.sound.mute(true);
}

s.sound.volume(volume * s.volume);
if (!this.muted)
s.sound.volume(volume * s.volume);
});
},

@@ -96,6 +108,24 @@ define([
};

this.sounds.push(sound);
},

onToggleAudio: function (isAudioOn) {
this.muted = !isAudioOn;

this.sounds.forEach(s => {
if (!s.sound)
return;

s.sound.mute(this.muted);
});

if (!window.player)
return;
const { player: { x, y } } = window;

this.update(x, y);
}
};
});

+ 25
- 0
src/client/js/system/browserStorage.js Прегледај датотеку

@@ -0,0 +1,25 @@
define([
'js/system/browserStorage'
], function (
browserStorage
) {
const getEntryName = key => {
return `iwd_${key.toLowerCase()}`;
};

return {
get: key => {
const keyName = getEntryName(key);

const { [keyName]: value = '{unset}' } = localStorage;

return value;
},

set: (key, value) => {
const keyName = getEntryName(key);

localStorage.setItem(keyName, value);
}
};
});

+ 76
- 44
src/client/ui/factory.js Прегледај датотеку

@@ -1,18 +1,62 @@
define([
'ui/uiBase',
'js/system/events'
'js/system/events',
'js/system/globals',
'js/misc/tosAcceptanceValid'
], function (
uiBase,
events
events,
globals,
tosAcceptanceValid
) {
const startupUis = [
'inventory',
'equipment',
'hud',
'target',
'menu',
'spells',
'messages',
'online',
'mainMenu',
'context',
'party',
'help',
'dialogue',
'buffs',
'tooltips',
'tooltipInfo',
'tooltipItem',
'announcements',
'quests',
'events',
'progressBar',
'stash',
'smithing',
'talk',
'trade',
'overlay',
'death',
'leaderboard',
'reputation',
'mail',
'wardrobe',
'passives',
'workbench',
'middleHud',
'options'
];

return {
uis: [],
root: '',

init: function (root) {
init: function (root, uiList = []) {
if (root)
this.root = root + '/';

startupUis.push(...uiList);

events.on('onEnterGame', this.onEnterGame.bind(this));
events.on('onUiKeyDown', this.onUiKeyDown.bind(this));
events.on('onResize', this.onResize.bind(this));
@@ -21,48 +65,23 @@ define([
onEnterGame: function () {
events.clearQueue();

[
'inventory',
'equipment',
'hud',
'target',
'menu',
'spells',
'messages',
'online',
'options',
'context',
'party',
'help',
'dialogue',
'buffs',
'tooltips',
'tooltipInfo',
'tooltipItem',
'announcements',
'quests',
'events',
'progressBar',
'stash',
'smithing',
'talk',
'trade',
'overlay',
'death',
'leaderboard',
'reputation',
'mail',
'wardrobe',
'passives',
'workbench',
'middleHud'
].forEach(function (u) {
this.build(u);
startupUis.forEach(function (u) {
if (u.path)
this.buildModUi(u);
else
this.build(u);
}, this);
},

buildModUi: function (config) {
const type = config.path.split('/').pop();

this.build(type, {
path: config.path
});
},

build: function (type, options) {
//Don't make doubles?
let className = 'ui' + type[0].toUpperCase() + type.substr(1);
let el = $('.' + className);
if (el.length > 0)
@@ -72,7 +91,13 @@ define([
},

getTemplate: function (type, options) {
require([this.root + 'ui/templates/' + type + '/' + type], this.onGetTemplate.bind(this, options));
let path = null;
if (options && options.path)
path = options.path + `\\${type}.js`;
else
path = this.root + 'ui/templates/' + type + '/' + type;

require([path], this.onGetTemplate.bind(this, options));
},

onGetTemplate: function (options, template) {
@@ -100,13 +125,14 @@ define([

onUiKeyDown: function (keyEvent) {
if (keyEvent.key === 'esc') {
this.uis.forEach(function (u) {
this.uis.forEach(u => {
if (!u.modal || !u.shown)
return;

keyEvent.consumed = true;
u.hide();
});
$('.uiOverlay').hide();
events.emit('onHideContextMenu');
} else if (['o', 'j', 'h', 'i'].indexOf(keyEvent.key) > -1)
@@ -131,7 +157,13 @@ define([
},

afterPreload: function () {
this.build('characters', {});
if (!globals.clientConfig.tos.required || tosAcceptanceValid()) {
this.build('characters');

return;
}

this.build('terms');
},

update: function () {


+ 81
- 0
src/client/ui/shared/renderItem.js Прегледај датотеку

@@ -0,0 +1,81 @@
const tplItem = `
<div class="item">
<div class="icon"></div>
<div class="quantity"></div>
</div>
`;

define([
], function (
) {
return (container, item) => {
let itemEl = null;

if (!item) {
itemEl = $(tplItem)
.appendTo(container)
.addClass('empty');

return itemEl;
}

itemEl = $(tplItem).appendTo(container);

let size = 64;
let offset = 0;

if (item.type === 'skin') {
offset = 4;
size = 8;
}

const imgX = (-item.sprite[0] * size) + offset;
const imgY = (-item.sprite[1] * size) + offset;

let spritesheet = item.spritesheet || '../../../images/items.png';
if (!item.spritesheet) {
if (item.material)
spritesheet = '../../../images/materials.png';
else if (item.quest)
spritesheet = '../../../images/questItems.png';
else if (item.type === 'consumable')
spritesheet = '../../../images/consumables.png';
else if (item.type === 'skin')
spritesheet = '../../../images/characters.png';
}

itemEl
.find('.icon')
.css('background', `url(${spritesheet}) ${imgX}px ${imgY}px`);

if (item.quantity > 1 || item.eq || item.active || item.has('quickSlot')) {
let elQuantity = itemEl.find('.quantity');
let txtQuantity = item.quantity;
if (!txtQuantity)
txtQuantity = item.has('quickSlot') ? 'QS' : 'EQ';

elQuantity.html(txtQuantity);

//If the item doesn't have a quantity and we reach this point
//it must mean that it's active, EQd or QSd
if (!item.quantity)
itemEl.addClass('eq');
} else if (item.isNew) {
itemEl.addClass('new');
itemEl.find('.quantity').html('NEW');
}

if (item.slot) {
const equipErrors = window.player.inventory.equipItemErrors(item);
if (equipErrors.length)
itemEl.addClass('no-equip');
}

if (item.has('quality'))
itemEl.addClass(`quality-${item.quality}`);

return itemEl;
};
});

+ 11
- 2
src/client/ui/templates/characters/characters.js Прегледај датотеку

@@ -28,6 +28,15 @@ define([
.on('mouseleave', this.onDeleteReset.bind(this));

this.getCharacters();

this.onEvent('onKeyDown', this.onKeyDown.bind(this));
},

onKeyDown: function (key) {
if (key !== 'enter' || this.el.hasClass('disabled'))
return;

this.onPlayClick();
},

onPlayClick: function () {
@@ -48,13 +57,13 @@ define([
},
onPlay: function () {
this.el.removeClass('disabled');
this.el.remove();
this.destroy();
events.emit('onEnterGame');
},

onNewClick: function () {
uiFactory.build('createCharacter', {});
this.el.remove();
this.destroy();
},

getCharacters: function () {


+ 2
- 2
src/client/ui/templates/createCharacter/createCharacter.js Прегледај датотеку

@@ -111,7 +111,7 @@ define([
back: function () {
this.clear();

this.el.remove();
this.destroy();

uiFactory.build('characters', {});
},
@@ -137,7 +137,7 @@ define([

if (!result) {
this.clear();
this.el.remove();
this.destroy();
events.emit('onEnterGame');
} else
this.el.find('.message').html(result);


+ 3
- 3
src/client/ui/templates/createCharacter/styles.less Прегледај датотеку

@@ -71,11 +71,11 @@
background-color: @grayD;

&:first-child {
margin-right: 15px;
margin-right: 10px;
}

&:last-child {
margin-left: 15px;
margin-left: 10px;
}

&:hover {
@@ -236,7 +236,7 @@
width: 45%;

.skinBox {
height: 70px;
height: 35px;
}

}


+ 16
- 11
src/client/ui/templates/death/styles.less Прегледај датотеку

@@ -2,7 +2,6 @@

.uiDeath {
display: none;

width: 400px;
background-color: @gray;
border: 4px solid @lightGray;
@@ -14,8 +13,9 @@

.inner {
display: inline-block;
color: @orange;
color: @orangeA;
}

}

.penalty {
@@ -25,17 +25,18 @@

.btn {
color: @white;
width: 100%;
height: 32px;
background-color: @blue;
margin: 16px 0px;
padding-top: 8px;
cursor: pointer;
&:hover {
width: 100%;
height: 32px;
background-color: @blue;
margin: 16px 0px;
padding-top: 8px;
cursor: pointer;
&:hover {
background-color: lighten(@blue, 15%);
color: @black;
}
}

}

&.permadeath {
@@ -47,12 +48,16 @@
.btn-logout {
display: block;
}

}

}

.buttons {
.btn-logout {
display: none;
}

}

}

+ 1
- 0
src/client/ui/templates/equipment/styles.less Прегледај датотеку

@@ -279,6 +279,7 @@
background-color: @blackC;
padding: 0px;
z-index: 2;
overflow-y: auto;

.slot {
float: left;


+ 16
- 2
src/client/ui/templates/events/events.js Прегледај датотеку

@@ -3,13 +3,15 @@ define([
'js/system/events',
'html!ui/templates/events/template',
'html!ui/templates/events/templateEvent',
'css!ui/templates/events/styles'
'css!ui/templates/events/styles',
'js/config'
], function (
client,
events,
tpl,
templateEvent,
styles
styles,
config
) {
return {
tpl: tpl,
@@ -30,6 +32,9 @@ define([
this.onEvent('onRemoveEvent', this.onRemoveEvent.bind(this));
this.onEvent('onUpdateEvent', this.onUpdateEvent.bind(this));
this.onEvent('onCompleteEvent', this.onCompleteEvent.bind(this));

this.onEvent('onToggleEventsVisibility', this.onToggleEventsVisibility.bind(this));
this.onToggleEventsVisibility(config.showEvents);
},

onRezone: function () {
@@ -112,6 +117,15 @@ define([
toggleButtons: function (e) {
this.el.toggleClass('active');
e.stopPropagation();
},

onToggleEventsVisibility: function (active) {
this.shown = active;

if (this.shown)
this.show();
else
this.hide();
}
};
});

+ 4
- 6
src/client/ui/templates/events/styles.less Прегледај датотеку

@@ -52,7 +52,7 @@

}

.btnClose {
.btnCollapse {
display: none;
}

@@ -60,11 +60,9 @@

.mobile .uiEvents {
background-color: fade(@darkGray, 90%);
margin-top: 0px;

&:not(.active) {
position: absolute;
top: 0px;
right: 232px;
width: @btnSize;
height: @btnSize;

@@ -95,11 +93,11 @@
display: block;
position: absolute;
right: calc(100% + 10px);
top: 50%;
transform: translateY(-50%);
top: 0px;
background-color: fade(@darkGray, 90%);
width: @btnSize;
height: @btnSize;
padding-top: 0px;

.icon {
width: 100%;


+ 47
- 55
src/client/ui/templates/inventory/inventory.js Прегледај датотеку

@@ -4,14 +4,18 @@ define([
'html!ui/templates/inventory/template',
'css!ui/templates/inventory/styles',
'html!ui/templates/inventory/templateItem',
'js/input'
'js/input',
'js/config',
'ui/shared/renderItem'
], function (
events,
client,
template,
styles,
tplItem,
input
input,
config,
renderItem
) {
return {
tpl: template,
@@ -33,6 +37,11 @@ define([
this.onEvent('onGetItems', this.onGetItems.bind(this));
this.onEvent('onDestroyItems', this.onDestroyItems.bind(this));
this.onEvent('onShowInventory', this.toggle.bind(this));
this.onEvent('onToggleQualityIndicators', this.onToggleQualityIndicators.bind(this));
this.onToggleQualityIndicators(config.qualityIndicators);

this.onEvent('onToggleUnusableIndicators', this.onToggleUnusableIndicators.bind(this));
this.onToggleUnusableIndicators(config.unusableIndicators);

this.onEvent('onKeyDown', this.onKeyDown.bind(this));
this.onEvent('onKeyUp', this.onKeyUp.bind(this));
@@ -71,8 +80,7 @@ define([
let item = items.find(f => (f.pos !== null && f.pos === i));

if (!item) {
itemEl = $(tplItem)
.appendTo(container);
itemEl = renderItem(container, null);

itemEl
.on('mouseup', this.onMouseDown.bind(this, null, null, false))
@@ -85,21 +93,7 @@ define([
} else
rendered.push(item);

let imgX = -item.sprite[0] * 64;
let imgY = -item.sprite[1] * 64;

itemEl = $(tplItem)
.appendTo(container);

let spritesheet = item.spritesheet || '../../../images/items.png';
if (!item.spritesheet) {
if (item.material)
spritesheet = '../../../images/materials.png';
else if (item.quest)
spritesheet = '../../../images/questItems.png';
else if (item.type === 'consumable')
spritesheet = '../../../images/consumables.png';
}
itemEl = renderItem(container, item);

let clickHandler = this.onMouseDown.bind(this, itemEl, item, true);
let moveHandler = this.onHover.bind(this, itemEl, item);
@@ -116,28 +110,26 @@ define([
.on('mousemove', moveHandler)
.on('mouseleave', this.hideTooltip.bind(this, itemEl, item))
.find('.icon')
.css('background', 'url(' + spritesheet + ') ' + imgX + 'px ' + imgY + 'px')
.on('contextmenu', this.showContext.bind(this, item));

if (item.quantity > 1 || item.eq || item.active || item.has('quickSlot')) {
let elQuantity = itemEl.find('.quantity');
let txtQuantity = item.quantity;
if (!txtQuantity)
txtQuantity = item.has('quickSlot') ? 'QS' : 'EQ';

elQuantity.html(txtQuantity);

//If the item doesn't have a quantity and we reach this point
//it must mean that it's active, EQd or QSd
if (!item.quantity)
itemEl.addClass('eq');
} else if (item.isNew) {
itemEl.addClass('new');
itemEl.find('.quantity').html('NEW');
}
}
},

onToggleQualityIndicators: function (state) {
const className = `quality-${state.toLowerCase()}`;

$('.ui-container')
.removeClass('quality-off quality-bottom quality-border quality-background')
.addClass(className);
},

onToggleUnusableIndicators: function (state) {
const className = `unusable-${state.toLowerCase()}`;

$('.ui-container')
.removeClass('unusable-off unusable-border unusable-top unusable-background')
.addClass(className);
},

onClick: function (item) {
let msg = {
item: item,
@@ -324,56 +316,56 @@ define([
if (item.active)
menuItems.activate.text = 'deactivate';

let config = [];
let ctxConfig = [];

if (item.ability)
config.push(menuItems.learn);
ctxConfig.push(menuItems.learn);
else if (item.type === 'mtx')
config.push(menuItems.activate);
ctxConfig.push(menuItems.activate);
else if (item.type === 'toy' || item.type === 'consumable' || item.useText || item.type === 'recipe') {
if (item.useText)
menuItems.use.text = item.useText;
config.push(menuItems.use);
ctxConfig.push(menuItems.use);
if (!item.has('quickSlot'))
config.push(menuItems.quickSlot);
ctxConfig.push(menuItems.quickSlot);
} else if (item.slot) {
config.push(menuItems.equip);
ctxConfig.push(menuItems.equip);
if (!item.eq)
config.push(menuItems.divider);
ctxConfig.push(menuItems.divider);

if (!item.eq) {
config.push(menuItems.augment);
config.push(menuItems.divider);
ctxConfig.push(menuItems.augment);
ctxConfig.push(menuItems.divider);
}
}

if ((!item.eq) && (!item.active)) {
if (!item.quest) {
if ((window.player.stash.active) && (!item.noStash))
config.push(menuItems.stash);
ctxConfig.push(menuItems.stash);

if (!item.noDrop)
config.push(menuItems.drop);
ctxConfig.push(menuItems.drop);

if ((!item.material) && (!item.noSalvage))
config.push(menuItems.salvage);
ctxConfig.push(menuItems.salvage);
}

if (!item.noDestroy)
config.push(menuItems.destroy);
ctxConfig.push(menuItems.destroy);
}

if (item.quantity > 1 && !item.quest)
config.push(menuItems.split);
ctxConfig.push(menuItems.split);

//if ((!item.noDrop) && (!item.quest))
// config.push(menuItems.mail);
if ((!item.noDrop) && (!item.quest))
ctxConfig.push(menuItems.mail);

if (isMobile)
this.hideTooltip(null, this.hoverItem);

if (config.length > 0)
events.emit('onContextMenu', config, e);
if (ctxConfig.length > 0)
events.emit('onContextMenu', ctxConfig, e);

e.preventDefault();
return false;


+ 173
- 34
src/client/ui/templates/inventory/styles.less Прегледај датотеку

@@ -1,6 +1,7 @@
@import "../../../css/colors.less";

.uiInventory, .uiStash {
.uiInventory,
.uiStash {
display: none;
z-index: 2;
width: 818px;
@@ -18,8 +19,9 @@
padding-top: 8px;
margin: auto;
}

}
position: relative;

.grid {
@@ -52,20 +54,18 @@
background-color: transparent;

.icon {
filter:
brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);

-moz-filter:
brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
-moz-filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
}

}

.quantity {
@@ -73,18 +73,14 @@
bottom: 3px;
position: absolute;
color: @white;
filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

-moz-filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
}

.icon {
@@ -99,30 +95,34 @@
.quantity {
color: @yellow;
}

}

&.new {
.quantity {
color: @green;
}

}

&:hover {
.icon {
filter: brightness(160%);

-moz-filter: brightness(160%);
}

}

}

}

.menu-bar {
background-color: @blackB;
width: 100%;
height: 41px;
padding: 5px 0px;
clear: both;
width: 100%;
height: 41px;
padding: 5px 0px;
clear: both;

.btn {
background-color: @blueC;
@@ -136,7 +136,9 @@
&.btnSortInv {
float: left;
}

}

}

.split-box {
@@ -168,6 +170,7 @@
padding-top: 8px;
margin: auto;
}

}

.bottom {
@@ -185,7 +188,9 @@
border: none;
}

input, .textbox, input:-webkit-autofill {
input,
.textbox,
input:-webkit-autofill {
color: @white;
-webkit-text-fill-color: @white;
background-color: @blackC;
@@ -210,14 +215,148 @@
&:hover {
background-color: @blackA;
}

}

&.btnSplit {
margin-top: 45px;
clear: both;
}

}

}
}

}

}

}

.ui-container.quality-border .grid .item:not(.empty),
.ui-container.quality-bottom .grid .item:not(.empty) {
&:before {
content: '';
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
box-sizing: border-box;
border-width: 5px;
border-style: solid;
}

&.quality-0:before {
border: none;
}

&.quality-1:before {
border-color: @greenC;
}

&.quality-2:before {
border-color: @blueD;
}

&.quality-3:before {
border-color: @purpleC;
}

&.quality-4:before {
border-color: @orangeD;
}

}

.ui-container.quality-bottom .grid .item:not(.empty) {
&:before {
border-width: 0px 0px 5px 0px;
}

}

.ui-container.quality-background .grid .item:not(.empty),&.unusable-background .grid .item.no-equip {
&:before {
content: '';
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}

.icon {
filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);

&:hover {
filter: brightness(160%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
}

}

&.quality-1:before {
background-color: @greenC;
}

&.quality-2:before {
background-color: @blueD;
}

&.quality-3:before {
background-color: @purpleC;
}

&.quality-4:before {
background-color: @orangeD;
}

&.no-equip:before {
background-color: @redD;
}

}

.ui-container.unusable-border .grid .item.no-equip,
.ui-container.unusable-top .grid .item.no-equip {
&:after {
content: '';
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
box-sizing: border-box;
border-width: 5px;
border-style: solid;
border-color: @redD;
pointer-events: none;
}

}

.ui-container.unusable-top .grid .item.no-equip {
&:after {
border-width: 5px 0px 0px 0px;
}

}

.ui-container.quality-border.unusable-border .grid .item.no-equip:not(.quality-0),
.ui-container.quality-border.unusable-top .grid .item.no-equip:not(.quality-0) {
&:after {
top: 5px;
left: 5px;
width: calc(100% - 10px);
height: calc(100% - 10px);
}

}

+ 1
- 1
src/client/ui/templates/login/login.js Прегледај датотеку

@@ -73,7 +73,7 @@ define([
uiFactory.preload();

$('.uiLoginExtra').remove();
this.el.remove();
this.destroy();
} else
this.el.find('.message').html(res);
},


+ 1
- 1
src/client/ui/templates/login/styles.less Прегледај датотеку

@@ -78,7 +78,7 @@
margin-top: 36px;
float: left;
text-align: center;
color: @orange;
color: @orangeA;
filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)


+ 2
- 2
src/client/ui/templates/login/template.html Прегледај датотеку

@@ -11,11 +11,11 @@
</div>
<div class="message"></div>
</div>
<div class="news" location="https://gitlab.com/Isleward/isleward/tags/v0.4.2">[ Latest Release Notes ]</div>
<div class="news" location="https://gitlab.com/Isleward/isleward/tags/v0.4.3">[ Latest Release Notes ]</div>
<div class="extra">
<div class="el btn btnPatreon" location="https://patreon.com/bigbadwaffle">Pledge on Patreon</div>
<div class="el btn btnPaypal" location="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BR2CC82WUAVEA">Donate on Paypal</div>
<div class="el btn btnWiki" location="http://wiki.isleward.com/Main_Page">Access the Wiki</div>
</div>
<div class="version" location="https://gitlab.com/Isleward/isleward/tags/v0.4.2">v0.4.2</div>
<div class="version" location="https://gitlab.com/Isleward/isleward/tags/v0.4.3">v0.4.3</div>
</div>

+ 112
- 0
src/client/ui/templates/mainMenu/mainMenu.js Прегледај датотеку

@@ -0,0 +1,112 @@
define([
'js/system/events',
'html!ui/templates/mainMenu/template',
'css!ui/templates/mainMenu/styles',
'js/rendering/renderer',
'ui/factory',
'js/objects/objects',
'js/system/client',
'js/sound/sound'
], function (
events,
template,
styles,
renderer,
factory,
objects,
client,
sound
) {
return {
tpl: template,
centered: true,

modal: true,

postRender: function () {
this.onEvent('onToggleMainMenu', this.toggle.bind(this));

this.el.find('.btnOptions').on('click', this.handler.bind(this, 'onToggleOptions'));
this.el.find('.btnCharSelect').on('click', this.charSelect.bind(this));
this.el.find('.btnLogOut').on('click', this.logOut.bind(this));
this.el.find('.btnContinue').on('click', this.toggle.bind(this));
this.el.find('.btnPatreon').on('click', this.patreon.bind(this));
this.el.find('.btnIssue').on('click', this.reportIssue.bind(this));

this.onEvent('onResize', this.onResize.bind(this));
},

handler: function (e) {
if (isMobile)
this.el.removeClass('active');

events.emit(e);

return false;
},
reportIssue: function () {
window.open('https://gitlab.com/Isleward/isleward/issues/new', '_blank');
},

patreon: function () {
window.open('https://patreon.com/bigbadwaffle', '_blank');
},

charSelect: function () {
this.el.addClass('disabled');

client.request({
module: 'cons',
method: 'unzone',
callback: this.onCharSelect.bind(this)
});
},

onCharSelect: function () {
renderer.clean();
objects.onRezone();
renderer.buildTitleScreen();
sound.unload();

events.emit('onShowCharacterSelect');
$('[class^="ui"]:not(.ui-container)').toArray().forEach(el => {
let ui = $(el).data('ui');
if (ui && ui.destroy)
ui.destroy();
});
factory.build('characters', {});
},

onResize: function () {
let isFullscreen = (window.innerHeight === screen.height);
if (isFullscreen)
this.el.find('.btnScreen').html('Windowed');
else
this.el.find('.btnScreen').html('Fullscreen');
},

toggle: function () {
this.onResize();

this.shown = !this.el.is(':visible');

if (this.shown) {
this.show();
events.emit('onShowOverlay', this.el);
} else {
this.hide();
events.emit('onHideOverlay', this.el);
}
},

logOut: function () {
window.location = window.location;
},

onKeyDown: function (key) {
if (key === 'esc')
this.toggle();
}
};
});

+ 49
- 0
src/client/ui/templates/mainMenu/styles.less Прегледај датотеку

@@ -0,0 +1,49 @@
@import "../../../css/colors.less";

.uiMainMenu {
display: none;

width: 400px;
background-color: @gray;
border: 4px solid @lightGray;
text-align: center;
padding: 0px 16px;

.btn {
color: @white;
width: 100%;
height: 32px;
background-color: @blue;
margin: 16px 0px;
padding-top: 8px;
cursor: pointer;

&.btnNames {
display: none;
}

&:hover {
background-color: lighten(@blue, 15%);
color: @black;
}
}

.btnIssue {
background-color: @red;

&:hover {
background-color: lighten(@red, 15%);
color: @black;
}
}
}

.mobile .uiMainMenu {
.btnScreen {
display: none;
}

.btnNames {
display: block;
}
}

+ 8
- 0
src/client/ui/templates/mainMenu/template.html Прегледај датотеку

@@ -0,0 +1,8 @@
<div class="uiMainMenu">
<div class="btn btnContinue">Continue</div>
<div class="btn btnOptions">Options</div>
<div class="btn btnCharSelect">Character Select</div>
<div class="btn btnLogOut">Log Out</div>
<div class="btn btnPatreon">Pledge on Patreon</div>
<div class="btn btnIssue">Report an Issue</div>
</div>

+ 1
- 1
src/client/ui/templates/menu/menu.js Прегледај датотеку

@@ -22,7 +22,7 @@ define([
this.find('.btnOnline').on('click', this.handler.bind(this, 'onShowOnline'));
this.find('.btnLeaderboard').on('click', this.handler.bind(this, 'onShowLeaderboard'));
this.find('.btnReputation').on('click', this.handler.bind(this, 'onShowReputation'));
this.find('.btnOptions').on('click', this.handler.bind(this, 'onToggleOptions'));
this.find('.btnMainMenu').on('click', this.handler.bind(this, 'onToggleMainMenu'));
this.find('.btnPassives').on('click', this.handler.bind(this, 'onShowPassives'));

this.onEvent('onGetPassivePoints', this.onGetPassivePoints.bind(this));


+ 1
- 1
src/client/ui/templates/menu/styles.less Прегледај датотеку

@@ -95,7 +95,7 @@
background: url('../../../images/uiIcons.png') -320px 0px;
}

&.btnOptions .icon {
&.btnMainMenu .icon {
background: url('../../../images/uiIcons.png') 0px -64px;
}
}


+ 1
- 1
src/client/ui/templates/menu/template.html Прегледај датотеку

@@ -24,7 +24,7 @@
<div class="btnHelp">
<div class="icon"></div>
</div>
<div class="btnOptions">
<div class="btnMainMenu">
<div class="icon"></div>
</div>
<div class="btn btnCollapse">


+ 88
- 37
src/client/ui/templates/messages/messages.js Прегледај датотеку

@@ -4,14 +4,16 @@ define([
'html!ui/templates/messages/tplTab',
'css!ui/templates/messages/styles',
'js/input',
'js/system/client'
'js/system/client',
'js/config'
], function (
events,
template,
tplTab,
styles,
input,
client
client,
config
) {
return {
tpl: template,
@@ -29,6 +31,8 @@ define([

blockedPlayers: [],

lastChannel: null,

postRender: function () {
this.onEvent('onGetMessages', this.onGetMessages.bind(this));
this.onEvent('onDoWhisper', this.onDoWhisper.bind(this));
@@ -36,6 +40,7 @@ define([
this.onEvent('onLeaveChannel', this.onLeaveChannel.bind(this));
this.onEvent('onGetCustomChatChannels', this.onGetCustomChatChannels.bind(this));
this.onEvent('onGetBlockedPlayers', this.onGetBlockedPlayers.bind(this));
this.onEvent('onToggleLastChannel', this.onToggleLastChannel.bind(this));

this
.find('.filter:not(.channel):not(.btn)')
@@ -91,37 +96,57 @@ define([
let container = $('<div class="keyboard"></div>')
.appendTo(this.el);

let controls = ['|', 'caps', 'space', 'backspace', 'enter'];

let keyboard = {
0: '1234567890|qwertyuiop|asdfghjkl|zxcvbnm',
1: '!@#$%^&*()|QWERTYUIOP|ASDFGHJKL|ZXCVBNM',
2: '!@#$%^&*()| {}[]\\|`-=_+;\':"|~,./<>?'
}[this.kbUpper].split('').concat(controls);

keyboard
.forEach(k => {
if (k === '|') {
$('<div class="newline"></div>')
.appendTo(container);

return;
}
0: 'qwertyuiop|asdfghjkl|zxcvbnm',
1: 'QWERTYUIOP|ASDFGHJKL|ZXCVBNM',
2: '1234567890|@#&*-+=()|_$"\';/'
}[this.kbUpper].split('');

//Hacky: Insert control characters in correct positions
//Backspace goes after 'm'
if (this.kbUpper === 0) {
keyboard.splice(keyboard.indexOf('z'), 0, 'caps');
keyboard.splice(keyboard.indexOf('m') + 1, 0, '<<');
} else if (this.kbUpper === 1) {
keyboard.splice(keyboard.indexOf('Z'), 0, 'caps');
keyboard.splice(keyboard.indexOf('M') + 1, 0, '<<');
} else if (this.kbUpper === 2)
keyboard.splice(keyboard.indexOf('/') + 1, 0, '<<');

keyboard.push(...['|', '123', ',', 'space', '.', 'send']);

let row = 0;
keyboard.forEach(k => {
if (k === '|') {
row++;

const postGapCount = row === 4 ? 0 : row - 1;
for (let i = 0; i < postGapCount; i++)
$('<div class="gap" />').appendTo(container);
$('<div class="newline" />').appendTo(container);
const preGapCount = row === 3 ? 0 : row;
for (let i = 0; i < preGapCount; i++)
$('<div class="gap" />').appendTo(container);

return;
}

let className = (k.match(/[a-z]/i) || k.length > 1) ? 'key' : 'key special';
if (k === ' ') {
k = '.';
className = 'key hidden';
}
let className = (k.length === 1) ? 'key' : 'key special';
if (k === ' ') {
k = '.';
className = 'key hidden';
}

className += ' ' + k;
className += ' ' + k;

let elKey = $(`<div class="${className}">${k}</div>`)
.appendTo(container);
let elKey = $(`<div class="${className}">${k}</div>`)
.appendTo(container);

if (!className.includes('hidden'))
elKey.on('click', this.clickKey.bind(this, k));
});
if (!className.includes('hidden'))
elKey.on('click', this.clickKey.bind(this, k));
});
},

clickKey: function (key) {
@@ -131,7 +156,12 @@ define([

const handler = {
caps: () => {
this.kbUpper = (this.kbUpper + 1) % 3;
this.kbUpper = (this.kbUpper + 1) % 2;
this.renderKeyboard();
},

123: () => {
this.kbUpper = (this.kbUpper === 2) ? 0 : 2;
this.renderKeyboard();
},

@@ -139,12 +169,12 @@ define([
this.clickKey(' ');
},

backspace: () => {
'<<': () => {
elInput.val(elInput.val().slice(0, -1));
this.find('.input').html(elInput.val());
},

enter: () => {
send: () => {
this.sendChat({
which: 13
});
@@ -223,9 +253,10 @@ define([
},

onKeyDown: function (key) {
if (key === 'enter')
if (key === 'enter') {
this.toggle(true);
else if (key === 'shift')
this.find('input').val(this.lastChannel || '');
} else if (key === 'shift')
this.showItemTooltip();
},

@@ -368,14 +399,14 @@ define([
}

let textbox = this.find('input');
let config = {
let msgConfig = {
success: true,
message: textbox.val()
};

events.emit('onBeforeChat', config);
events.emit('onBeforeChat', msgConfig);

let val = config.message
let val = msgConfig.message
.split('<')
.join('&lt;')
.split('>')
@@ -383,12 +414,27 @@ define([

textbox.blur();
if (!config.success)
if (!msgConfig.success)
return;

if (val.trim() === '')
return;

if (config.rememberChatChannel) {
const firstChar = val[0];
let lastChannel = null;
if ('@$'.includes(firstChar)) {
const firstSpace = val.indexOf(' ');
if (firstSpace === -1)
lastChannel = val + ' ';
else
lastChannel = val.substr(0, firstSpace) + ' ';
} else if (firstChar === '%')
lastChannel = '%';

this.lastChannel = lastChannel;
}

client.request({
cpn: 'social',
method: 'chat',
@@ -396,6 +442,11 @@ define([
message: val
}
});
},

onToggleLastChannel: function (isOn) {
if (!isOn)
this.lastChannel = null;
}
};
});

+ 66
- 41
src/client/ui/templates/messages/styles.less Прегледај датотеку

@@ -1,5 +1,4 @@
@import "../../../css/colors.less";

@pad: 8px;
@btnSize: 64px;

@@ -7,10 +6,8 @@
position: absolute;
left: 10px;
bottom: 10px;

width: 480px;
padding: @pad;

pointer-events: none;

.input {
@@ -28,6 +25,7 @@
&.time {
display: none;
}

}

.filters {
@@ -42,13 +40,16 @@
.list-message {
filter: none;
}

}

}

&.active {
.list-message {
opacity: 1 !important;
}

}

.filters {
@@ -79,8 +80,11 @@
background-color: @blackA;
color: @grayB;
}

}

}

}

.list {
@@ -93,18 +97,14 @@
width: 100%;
padding: 5px 10px;
color: white;
filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

-moz-filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
word-wrap: break-word;
line-height: 18px;

@@ -120,16 +120,17 @@
color: @greenB;
}

a, &.q2 {
a,
&.q2 {
color: @blueB;
}

&.q3 {
color: @purple;
color: @purpleA;
}

&.q4 {
color: @orange;
color: @orangeA;
}

&.color-green {
@@ -147,12 +148,25 @@
&.color-tealC {
color: @tealC;
}

}

&.rep .rep {
display: block;
}

&.chat .chat {
display: block;
}

&.info .info {
display: block;
}

&.loot .loot {
display: block;
}

&.rep .rep { display: block; }
&.chat .chat { display: block; }
&.info .info { display: block; }
&.loot .loot { display: block; }
}

.el {
@@ -168,27 +182,24 @@
background-color: transparent;
text-align: left;
padding: 5px 10px;

filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

-moz-filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
}

width: 100%;
color: @white;
}

}

.mobile .uiMessages {
padding: 10px 0px;
padding: 0px;
pointer-events: all;

.btnClose.active {
@@ -204,6 +215,8 @@

.filters {
margin-bottom: 0px;
flex-shrink: 0;
background-color: @darkGray;
}

.list {
@@ -223,12 +236,16 @@

.input {
display: block;
height: 26px;
flex-shrink: 0;
}

.el.textbox:not(.input) {
&.message, &.time {
&.message,
&.time {
display: none;
}

}

.keyboard {
@@ -238,7 +255,8 @@
background-color: @blackC;
justify-content: center;
align-items: center;
height: 292px;
height: 128px;
flex-shrink: 0;

.key {
flex: 1;
@@ -246,12 +264,9 @@
color: @white;
padding: 8px 10px;
text-align: center;
border-top: 2px solid #373041;
border-left: 1px solid #373041;
border-right: 1px solid #373041;

&.special {
color: @orange;
color: @orangeA;
}

&.hidden {
@@ -261,12 +276,20 @@
&.space {
flex: 5;
}

}

.newline {
width: 100%;
}

.gap {
width: 5%;
flex-shrink: 0;
}

}

}

&:not(.typing) {
@@ -292,5 +315,7 @@
> * {
display: none;
}

}

}

+ 4
- 1
src/client/ui/templates/middleHud/styles.less Прегледај датотеку

@@ -14,7 +14,7 @@
margin-left: calc(12px - 60px);
text-align: center;
position: absolute;
left: calc(50vw - 86px);
left: calc(50vw - 88px);
top: calc(50vh - 113px);
width: 64px;
height: 64px;
@@ -27,6 +27,7 @@
height: 100%;
background: url(../../../images/uiIcons.png) -448px -64px;
}

}

.casting {
@@ -51,5 +52,7 @@
text-align: center;
color: @black;
}

}

}

+ 7
- 4
src/client/ui/templates/online/styles.less Прегледај датотеку

@@ -6,7 +6,7 @@
border: 5px solid @blackB;
text-align: center;
width: 450px;
height: 400px;
height: 396px;

> .heading {
color: @blueA;
@@ -21,16 +21,17 @@
}

.bottom {
height: calc(100% - 35px);
height: calc(100% - 36px);
background-color: @blackC;
padding: 10px;
padding: 8px;

.list {
width: 100%;
height: 100%;
overflow-y: auto;
background-color: @darkGray;

display: flex;
flex-direction: column;

.heading {
height: 24px;
@@ -39,6 +40,7 @@
> div {
float: left;
padding: 4px;
height: 24px;
&:nth-child(1) {
width: 10%;
@@ -63,6 +65,7 @@
> div {
float: left;
padding: 4px;
height: 24px;
&:nth-child(1) {
width: 10%;


+ 135
- 47
src/client/ui/templates/options/options.js Прегледај датотеку

@@ -6,7 +6,8 @@ define([
'ui/factory',
'js/objects/objects',
'js/system/client',
'js/sound/sound'
'js/sound/sound',
'js/config'
], function (
events,
template,
@@ -15,95 +16,182 @@ define([
factory,
objects,
client,
sound
sound,
config
) {
return {
tpl: template,
centered: true,

modal: true,
hasClose: true,

postRender: function () {
this.onEvent('onToggleOptions', this.toggle.bind(this));

//Can only toggle fullscreen directly in a listener, not deferred the way jQuery does it
this.el.find('.btnScreen')[0].addEventListener('click', this.toggleScreen.bind(this));
this.el.find('.btnNames').on('click', events.emit.bind(events, 'onKeyDown', 'v'));
this.el.find('.btnCharSelect').on('click', this.charSelect.bind(this));
this.el.find('.btnLogOut').on('click', this.logOut.bind(this));
this.el.find('.btnContinue').on('click', this.toggle.bind(this));
this.el.find('.btnPatreon').on('click', this.patreon.bind(this));
this.el.find('.btnIssue').on('click', this.reportIssue.bind(this));
this.find('.item.screen .name')[0].addEventListener('click', this.toggleScreen.bind(this));
this.find('.item.nameplates .name').on('click', events.emit.bind(events, 'onUiKeyDown', { key: 'v' }));
this.find('.item.quests .name').on('click', this.toggleQuests.bind(this));
this.find('.item.events .name').on('click', this.toggleEvents.bind(this));
this.find('.item.quality .name').on('click', this.toggleQualityIndicators.bind(this));
this.find('.item.unusable .name').on('click', this.toggleUnusableIndicators.bind(this));
this.find('.item.audio .name').on('click', this.toggleAudio.bind(this));
this.find('.item.lastChannel .name').on('click', this.toggleLastChannel.bind(this));

this.onEvent('onResize', this.onResize.bind(this));
this.onEvent('onUiKeyDown', this.onKeyDown.bind(this));
this.onEvent('onToggleAudio', this.onToggleAudio.bind(this));
this.onEvent('onToggleNameplates', this.onToggleNameplates.bind(this));
this.onEvent('onToggleQualityIndicators', this.onToggleQualityIndicators.bind(this));
this.onEvent('onToggleUnusableIndicators', this.onToggleUnusableIndicators.bind(this));
this.onEvent('onToggleEventsVisibility', this.onToggleEventsVisibility.bind(this));
this.onEvent('onToggleQuestsVisibility', this.onToggleQuestsVisibility.bind(this));
this.onEvent('onToggleLastChannel', this.onToggleLastChannel.bind(this));
},
reportIssue: function () {
window.open('https://gitlab.com/Isleward/isleward/issues/new', '_blank');

toggleUnusableIndicators: function () {
config.toggle('unusableIndicators');

if (config.unusableIndicators === 'background' && config.qualityIndicators === 'background') {
config.toggle('qualityIndicators');
events.emit('onToggleQualityIndicators', config.qualityIndicators);
}

events.emit('onToggleUnusableIndicators', config.unusableIndicators);
},

patreon: function () {
window.open('https://patreon.com/bigbadwaffle', '_blank');
onToggleUnusableIndicators: function (state) {
const newValue = state[0].toUpperCase() + state.substr(1);

this.find('.item.unusable .value').html(newValue);
},

charSelect: function () {
this.el.addClass('disabled');
toggleQualityIndicators: function () {
config.toggle('qualityIndicators');

client.request({
module: 'cons',
method: 'unzone',
callback: this.onCharSelect.bind(this)
});
if (config.qualityIndicators === 'background' && config.unusableIndicators === 'background') {
config.toggle('unusableIndicators');
events.emit('onToggleUnusableIndicators', config.unusableIndicators);
}

events.emit('onToggleQualityIndicators', config.qualityIndicators);
},

onCharSelect: function () {
renderer.clean();
objects.onRezone();
renderer.buildTitleScreen();
sound.unload();
onToggleQualityIndicators: function (state) {
const newValue = state[0].toUpperCase() + state.substr(1);

events.emit('onShowCharacterSelect');
$('[class^="ui"]:not(.ui-container)').toArray().forEach(el => {
let ui = $(el).data('ui');
if (ui && ui.destroy)
ui.destroy();
});
factory.build('characters', {});
this.find('.item.quality .value').html(newValue);
},

toggleScreen: function () {
this.el.find('.btnScreen').html(renderer.toggleScreen());
const state = renderer.toggleScreen();
const newValue = (state === 'Windowed') ? 'Off' : 'On';

this.find('.item.screen .value').html(newValue);
},

toggleEvents: function () {
config.toggle('showEvents');

events.emit('onToggleEventsVisibility', config.showEvents);
},

toggleQuests: function () {
config.toggle('showQuests');

events.emit('onToggleQuestsVisibility', config.showQuests);
},

onToggleEventsVisibility: function (state) {
const newValue = state ? 'On' : 'Off';

this.find('.item.events .value').html(newValue);
},

onToggleQuestsVisibility: function (state) {
const newValue = state[0].toUpperCase() + state.substr(1);

this.find('.item.quests .value').html(newValue);
},

onResize: function () {
let isFullscreen = (window.innerHeight === screen.height);
if (isFullscreen)
this.el.find('.btnScreen').html('Windowed');
else
this.el.find('.btnScreen').html('Fullscreen');
const newValue = isFullscreen ? 'On' : 'Off';

this.find('.item.screen .value').html(newValue);
},

onToggleNameplates: function (state) {
const newValue = state ? 'On' : 'Off';

this.find('.item.nameplates .value').html(newValue);
},

toggleAudio: function () {
config.toggle('playAudio');

events.emit('onToggleAudio', config.playAudio);
},

onToggleAudio: function (isAudioOn) {
const newValue = isAudioOn ? 'On' : 'Off';

this.find('.item.audio .value').html(newValue);
},

toggleLastChannel: function () {
config.toggle('rememberChatChannel');

events.emit('onToggleLastChannel', config.rememberChatChannel);
},

onToggleLastChannel: function (state) {
const newValue = state ? 'On' : 'Off';

this.find('.item.lastChannel .value').html(newValue);
},

build: function () {
this.onToggleNameplates(config.showNames);
this.onToggleAudio(config.playAudio);
this.onToggleEventsVisibility(config.showEvents);
this.onToggleQuestsVisibility(config.showQuests);
this.onToggleQualityIndicators(config.qualityIndicators);
this.onToggleUnusableIndicators(config.unusableIndicators);
this.onToggleLastChannel(config.rememberChatChannel);
},

toggle: function () {
this.onResize();

this.shown = !this.el.is(':visible');

if (this.shown) {
if (!this.shown) {
this.show();
this.shown = true;
events.emit('onShowOverlay', this.el);

this.build();
} else {
this.hide();
events.emit('onHideOverlay', this.el);
this.shown = false;
}
},
onKeyDown: function (keyEvent) {
const { key } = keyEvent;
if (key === 'v') {
config.toggle('showNames');

logOut: function () {
window.location = window.location;
events.emit('onToggleNameplates', config.showNames);

const newValue = config.showNames ? 'On' : 'Off';
this.find('.item.nameplates .value').html(newValue);
}
},

onKeyDown: function (key) {
if (key === 'esc')
this.toggle();
afterHide: function () {
events.emit('onToggleMainMenu');
}
};
});

+ 70
- 32
src/client/ui/templates/options/styles.less Прегледај датотеку

@@ -2,48 +2,86 @@

.uiOptions {
display: none;

width: 400px;
background-color: @gray;
border: 4px solid @lightGray;
text-align: center;
padding: 0px 16px;

.btn {
color: @white;
width: 100%;
height: 32px;
background-color: @blue;
margin: 16px 0px;
padding-top: 8px;
cursor: pointer;

&.btnNames {
display: none;
}

&:hover {
background-color: lighten(@blue, 15%);
color: @black;
}
background-color: @blackC;
border: 5px solid @blackB;

> .heading {
color: @blueA;
width: 100%;
height: 36px;
background-color: @blackB;
position: relative;
text-align: center;

.heading-text {
padding-top: 8px;
margin: auto;
}

}

.btnIssue {
background-color: @red;
.bottom {
padding: 10px;

.list {
display: flex;
flex-direction: column;

.heading {
color: @grayC;
border-bottom: 2px solid @grayD;
margin: 0px 10px 5px 10px;
padding-bottom: 5px;

&:not(:first-child) {
margin: 10px 10px 5px 10px;
}

}

.item {
height: 30px;
display: flex;
justify-content: space-between;
align-items: center;

.name {
color: @blueB;
flex: 1;
height: 100%;
display: flex;
align-items: center;
padding: 0px 10px;
margin-right: 10px;
cursor: pointer;

&:hover {
color: @blueA;
background-color: @blackA;
}

}

.value {
color: @white;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10px;
}

}

&:hover {
background-color: lighten(@red, 15%);
color: @black;
}

}

}

.mobile .uiOptions {
.btnScreen {
.item.screen {
display: none;
}

.btnNames {
display: block;
}
}

+ 43
- 7
src/client/ui/templates/options/template.html Прегледај датотеку

@@ -1,9 +1,45 @@
<div class="uiOptions">
<div class="btn btnContinue">Continue</div>
<div class="btn btnScreen">Windowed</div>
<div class="btn btnCharSelect">Character Select</div>
<div class="btn btnNames">Toggle Nameplates</div>
<div class="btn btnLogOut">Log Out</div>
<div class="btn btnPatreon">Pledge on Patreon</div>
<div class="btn btnIssue">Report an Issue</div>
<div class="heading">
<div class="heading-text">Options</div>
</div>
<div class="bottom">
<div class="list">
<div class="heading game">Game</div>
<div class="item screen">
<div class="name">Fullscreen</div>
<div class="value">Off</div>
</div>
<div class="item audio">
<div class="name">Audio</div>
<div class="value">On</div>
</div>
<div class="heading hud">HUD</div>
<div class="item nameplates">
<div class="name">Nameplates</div>
<div class="value">On</div>
</div>
<div class="item quests">
<div class="name">Quests</div>
<div class="value">On</div>
</div>
<div class="item events">
<div class="name">Events</div>
<div class="value">On</div>
</div>
<div class="heading inventory">Inventory</div>
<div class="item quality">
<div class="name">Quality Indicators</div>
<div class="value">Off</div>
</div>
<div class="item unusable">
<div class="name">Unusable Indicators</div>
<div class="value">Off</div>
</div>
<div class="heading inventory">Chat</div>
<div class="item lastChannel">
<div class="name">Remember Last Chat Channel</div>
<div class="value">On</div>
</div>
</div>
</div>
</div>

+ 7
- 5
src/client/ui/templates/passives/input.js Прегледај датотеку

@@ -45,7 +45,9 @@ define([

enabled: true,

init: function (el) {
init: function (el, zoom) {
this.zoom = zoom;

el
.on('mousedown', this.events.mouse.mouseDown.bind(this))
.on('mouseup', this.events.mouse.mouseUp.bind(this))
@@ -197,7 +199,7 @@ define([

touch: {
touchStart: function (e) {
let pos = this.events.touch.convertTouchPos(e);
let pos = this.events.touch.convertTouchPos.call(this, e);

this.mouse.raw = {
clientX: pos.x,
@@ -215,7 +217,7 @@ define([
},

touchMove: function (e) {
let pos = this.events.touch.convertTouchPos(e);
let pos = this.events.touch.convertTouchPos.call(this, e);

this.mouse.raw = {
clientX: pos.x,
@@ -244,8 +246,8 @@ define([
convertTouchPos: function (e) {
let rect = e.target.getBoundingClientRect();
return {
x: e.targetTouches[0].pageX - rect.left,
y: e.targetTouches[0].pageY - rect.top
x: (e.targetTouches[0].pageX - rect.left) * this.zoom,
y: (e.targetTouches[0].pageY - rect.top) * this.zoom
};
}
}


+ 11
- 13
src/client/ui/templates/passives/passives.js Прегледај датотеку

@@ -1,3 +1,7 @@
let zoom = window.devicePixelRatio;
if (isMobile)
zoom /= 2;

define([
'js/system/events',
'js/system/client',
@@ -51,7 +55,7 @@ define([
handlerResize: null,

postRender: function () {
input.init(this.el);
input.init(this.el, zoom);

this.data.nodes = temp.nodes;
this.data.links = temp.links.map(l => {
@@ -74,8 +78,6 @@ define([
this.handlerResize = this.onResize.bind(this);
window.addEventListener('resize', this.handlerResize);

let zoom = window.devicePixelRatio;

this.canvas = this.find('.canvas')[0];
this.size.w = this.canvas.width = this.find('.bottom').width() * zoom;
this.size.h = this.canvas.height = this.find('.bottom').height() * zoom;
@@ -120,8 +122,6 @@ define([
if (isMobile || !this.shown)
return;
let zoom = window.devicePixelRatio;

this.size.w = this.canvas.width = this.find('.bottom').width() * zoom;
this.size.h = this.canvas.height = this.find('.bottom').height() * zoom;

@@ -357,8 +357,8 @@ define([
text = 'Starting node for ' + node.spiritStart + ' spirits';

let tooltipPos = {
x: input.mouse.raw.clientX + 15,
y: input.mouse.raw.clientY
x: (input.mouse.raw.clientX + 15) / zoom,
y: (input.mouse.raw.clientY) / zoom
};

events.emit('onShowTooltip', text, this.el[0], tooltipPos);
@@ -399,10 +399,9 @@ define([

this.events.onMouseMove.call(this, e);

let windowZoom = window.devicePixelRatio;
this.panOrigin = {
x: e.raw.clientX * windowZoom,
y: e.raw.clientY * windowZoom
x: e.raw.clientX * zoom,
y: e.raw.clientY * zoom
};
},

@@ -419,12 +418,11 @@ define([
};
}

let windowZoom = window.devicePixelRatio;
let zoomPanMultiplier = this.currentZoom;
let scrollSpeed = constants.scrollSpeed / zoomPanMultiplier;

const rawX = e.raw.clientX * windowZoom;
const rawY = e.raw.clientY * windowZoom;
const rawX = e.raw.clientX * zoom;
const rawY = e.raw.clientY * zoom;

this.pos.x += (this.panOrigin.x - rawX) * scrollSpeed;
this.pos.y += (this.panOrigin.y - rawY) * scrollSpeed;


+ 20
- 2
src/client/ui/templates/quests/quests.js Прегледај датотеку

@@ -3,13 +3,15 @@ define([
'js/system/events',
'html!ui/templates/quests/template',
'html!ui/templates/quests/templateQuest',
'css!ui/templates/quests/styles'
'css!ui/templates/quests/styles',
'js/config'
], function (
client,
events,
tpl,
templateQuest,
styles
styles,
config
) {
return {
tpl: tpl,
@@ -28,6 +30,9 @@ define([
this.onEvent('onObtainQuest', this.onObtainQuest.bind(this));
this.onEvent('onUpdateQuest', this.onUpdateQuest.bind(this));
this.onEvent('onCompleteQuest', this.onCompleteQuest.bind(this));
this.onEvent('onToggleQuestsVisibility', this.onToggleQuestsVisibility.bind(this));

this.onToggleQuestsVisibility(config.showQuests);
},

onRezone: function () {
@@ -118,6 +123,19 @@ define([
toggleButtons: function (e) {
this.el.toggleClass('active');
e.stopPropagation();
},

onToggleQuestsVisibility: function (state) {
this.shown = state !== 'off';

if (this.shown)
this.show();
else
this.hide();

this.el.removeClass('minimal');
if (state === 'minimal')
this.el.addClass('minimal');
}
};
});

+ 11
- 5
src/client/ui/templates/quests/styles.less Прегледај датотеку

@@ -97,17 +97,23 @@
display: none;
}

&.minimal {
.quest.disabled {
display: none;
}

}

}

.mobile .uiQuests {
background-color: fade(@darkGray, 90%);

&:not(.active) {
position: absolute;
top: 10px;
right: 158px;
width: @btnSize;
height: @btnSize;
margin-left: 10px;
position: relative;

&:after {
content: '';
@@ -136,11 +142,11 @@
display: block;
position: absolute;
right: calc(100% + 10px);
top: 50%;
transform: translateY(-50%);
top: 0px;
background-color: fade(@darkGray, 90%);
width: @btnSize;
height: @btnSize;
padding-top: 0px;

.icon {
width: 100%;


+ 5
- 7
src/client/ui/templates/reputation/reputation.js Прегледај датотеку

@@ -30,25 +30,23 @@ define([
this.find('.info .description').html('');
this.find('.bar-outer').hide();

if (list.length === 0)
if (!list.length)
this.find('.heading-bottom').html("you haven't discovered any factions yet");
else
this.find('.heading-bottom').html('select a faction to see more info');

let elList = this.find('.list').empty();

list.forEach(function (l) {
list.forEach(l => {
if (l.noGainRep)
return;

let html = '<div class="faction">' + l.name.toLowerCase() + '</div>';

let el = $(html)
.appendTo(elList);
let el = $(html).appendTo(elList);

el
.on('click', this.onSelectFaction.bind(this, el, l));
}, this);
el.on('click', this.onSelectFaction.bind(this, el, l));
});
},

onSelectFaction: function (el, faction) {


+ 30
- 12
src/client/ui/templates/reputation/styles.less Прегледај датотеку

@@ -17,9 +17,11 @@
padding-top: 8px;
margin: auto;
}

}

.list, .info {
.list,
.info {
background-color: fade(@blackC, 90%);
float: left;
height: calc(100% - 36px);
@@ -44,7 +46,9 @@
&:hover {
background-color: @grayC;
}

}

}

.info {
@@ -59,6 +63,7 @@
.heading-bottom {
margin: auto;
}

}

.description {
@@ -96,18 +101,31 @@
position: absolute;
left: 0px;
top: 5px;
filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

-moz-filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
}

}

}

.list:empty {
display: none;

+ .info {
width: 100%;
}

}

}

.mobile .uiReputation {
z-index: 2;
}

+ 59
- 50
src/client/ui/templates/smithing/styles.less Прегледај датотеку

@@ -16,6 +16,7 @@
padding-top: 8px;
margin: auto;
}

}

.bottom {
@@ -51,12 +52,14 @@
text-align: center;
}

&.item-picker, &.actionButton {
&.item-picker,
&.actionButton {
cursor: pointer;

&:hover {
background-color: @blackC;
}

}

&.item-picker {
@@ -67,15 +70,18 @@
height: 64px;
background: url('../../../images/uiIcons.png') -256px -64px;
}

}

&.actionButton {
padding: 8px;

.icon {
width: 64px;
height: 64px;
background: url('../../../images/uiIcons.png') -192px -64px;
}

}

.item {
@@ -91,21 +97,19 @@
bottom: 3px;
position: absolute;
color: @white;
filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

-moz-filter:
drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);
-moz-filter: drop-shadow(0px -2px 0px @blackD)
drop-shadow(0px 2px 0px @blackD)
drop-shadow(2px 0px 0px @blackD)
drop-shadow(-2px 0px 0px @blackD);

&.red {
color: @red;
}

}

.icon {
@@ -114,21 +118,20 @@
position: absolute;
left: 8px;
top: 8px;
filter:
brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);

-moz-filter:
brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
-moz-filter: brightness(100%)
drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
}

}

}

&:first-child {
@@ -142,36 +145,42 @@

.col-btn {
height: calc((100% - 10px) / 2);
width: 100%;
color: #f2f5f5;
text-align: center;
padding-top: 10px;
background-color: @blackB;
margin-bottom: 10px;
cursor: pointer;
&.selected {
color: @orange;
}
&:hover {
background-color: @blackA;
}
&.col-half {
width: calc((100% - 10px) / 2);
float: left;
&:nth-child(2n + 1) {
width: 100%;
color: #f2f5f5;
text-align: center;
padding-top: 10px;
background-color: @blackB;
margin-bottom: 10px;
cursor: pointer;
&.selected {
color: @orangeA;
}
&:hover {
background-color: @blackA;
}
&.col-half {
width: calc((100% - 10px) / 2);
float: left;
&:nth-child(2n + 1) {
margin-right: 10px;
}
}
}

&:not(.col-half) {
}

&:not(.col-half) {
clear: both;
}
}

}

}

}

}

}

+ 4
- 3
src/client/ui/templates/spells/styles.less Прегледај датотеку

@@ -81,8 +81,9 @@

.spell {
position: relative;
margin: 8px 0px 0px 0px;
margin: 10px 0px 0px 0px;
background-color: fade(#3a3b4a, 90%);
border: none;

.hotkey {
display: none;
@@ -90,9 +91,9 @@

&.active:before {
content: '';
width: 4px;
width: 5px;
height: 100%;
left: -4px;
left: -5px;
top: 0%;
background-color: @greenB;
position: absolute;


+ 10
- 27
src/client/ui/templates/stash/stash.js Прегледај датотеку

@@ -4,14 +4,16 @@ define([
'html!ui/templates/stash/template',
'css!ui/templates/stash/styles',
'html!ui/templates/inventory/templateItem',
'js/input'
'js/input',
'ui/shared/renderItem'
], function (
events,
client,
template,
styles,
tplItem,
input
input,
renderItem
) {
return {
tpl: template,
@@ -33,34 +35,24 @@ define([
},

build: function () {
this.el.removeClass('scrolls');
if (window.player.stash.maxItems > 50)
this.el.addClass('scrolls');

let container = this.el.find('.grid')
.empty();

let items = this.items;
let iLen = Math.max(items.length, 50);
let iLen = Math.max(items.length, window.player.stash.maxItems);

for (let i = 0; i < iLen; i++) {
let item = items[i];

let itemEl = $(tplItem)
.appendTo(container);
let itemEl = renderItem(container, item);

if (!item)
continue;

let imgX = -item.sprite[0] * 64;
let imgY = -item.sprite[1] * 64;

let spritesheet = item.spritesheet || '../../../images/items.png';
if (!item.spritesheet) {
if (item.material)
spritesheet = '../../../images/materials.png';
else if (item.quest)
spritesheet = '../../../images/questItems.png';
else if (item.type === 'consumable')
spritesheet = '../../../images/consumables.png';
}

let moveHandler = this.onHover.bind(this, itemEl, item);
let downHandler = () => {};
if (isMobile) {
@@ -74,16 +66,7 @@ define([
.on('mousemove', moveHandler)
.on('mouseleave', this.hideTooltip.bind(this, itemEl, item))
.find('.icon')
.css('background', 'url(' + spritesheet + ') ' + imgX + 'px ' + imgY + 'px')
.on('contextmenu', this.showContext.bind(this, item));

if (item.quantity)
itemEl.find('.quantity').html(item.quantity);

if (item.eq)
itemEl.addClass('eq');
if (item.isNew)
itemEl.addClass('new');
}
},



+ 7
- 2
src/client/ui/templates/stash/styles.less Прегледај датотеку

@@ -1,8 +1,13 @@
@import "../../../css/colors.less";

.uiStash {
.grid {
overflow-y: auto;
&.scrolls {
width: 834px;

.grid {
overflow-y: auto;
width: 825px;
}
}

.footer {


+ 33
- 2
src/client/ui/templates/target/target.js Прегледај датотеку

@@ -1,11 +1,13 @@
define([
'js/system/client',
'js/system/events',
'js/system/globals',
'html!ui/templates/target/template',
'css!ui/templates/target/styles'
], function (
client,
events,
globals,
template,
styles
) {
@@ -47,7 +49,7 @@ define([
// target.player (only the logged-in player has a player component)
if ((e.button !== 2) || (!target) || (!target.dialogue) || (target === window.player) || (target.prophecies)) {
if (target.prophecies) {
let inspectContext = [
const inspectContext = [
target.name,
'----------', {
text: 'inspect',
@@ -55,13 +57,20 @@ define([
}
];

globals.clientConfig.contextMenuActions.player.forEach(action => {
inspectContext.push({
text: action.text,
callback: this.onAction.bind(this, action, true)
});
});

events.emit('onContextMenu', inspectContext, e.event);
}

return;
}

let talkContext = [
const talkContext = [
target.name,
'----------', {
text: 'talk',
@@ -69,6 +78,13 @@ define([
}
];

globals.clientConfig.contextMenuActions.npc.forEach(action => {
talkContext.push({
text: action.text,
callback: this.onAction.bind(this, action, false)
});
});

events.emit('onContextMenu', talkContext, e.event);

e.event.preventDefault();
@@ -79,6 +95,21 @@ define([
window.player.dialogue.talk(this.target);
},

onAction: function (action, sendTargetServerId) {
const { threadModule, cpn, method, data = {} } = action;
if (method === 'performAction')
data.data.playerId = this.target.id;
else if (threadModule)
data.targetId = sendTargetServerId ? this.target.serverId : this.target.id;

client.request({
threadModule,
cpn,
method,
data
});
},

onInspect: function () {
client.request({
cpn: 'player',


+ 78
- 0
src/client/ui/templates/terms/styles.less Прегледај датотеку

@@ -0,0 +1,78 @@
@import "../../../css/colors.less";

.uiTerms {
display: none;
width: 562px;
height: 700px;
margin-top: -80px;
display: flex;
flex-direction: column;
align-items: center;

> * {
flex-shrink: 0;
}

.logo {
width: 562px;
height: 200px;
margin-bottom: 24px;
filter: drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
}

.heading {
color: @orangeA;
filter: drop-shadow(0px -4px 0px @blackD)
drop-shadow(0px 4px 0px @blackD)
drop-shadow(4px 0px 0px @blackD)
drop-shadow(-4px 0px 0px @blackD);
margin-bottom: 24px;
}

.content {
flex: 1;
width: 100%;
overflow-y: auto;
background-color: @blackC;
border: 5px solid @blackB;
padding: 10px;
color: @grayB;
text-align: justify;

.title {
color: @white;
}
}

.buttons {
width: 100%;
background-color: @blackC;
display: flex;
justify-content: space-between;
border-style: solid;
border-color: @blackB;
border-width: 0px 5px 5px 5px;
padding: 5px;

.btn {
background-color: @blueC;
color: @white;
height: 35px;
padding-left: 10px;
padding-right: 10px;

&:hover {
background-color: @blueB;
}
}
}

}

.mobile .uiTerms {
height: 80%;
margin-top: 0px;
}

+ 9
- 0
src/client/ui/templates/terms/template.html Прегледај датотеку

@@ -0,0 +1,9 @@
<div class="uiTerms">
<img class="logo" src="images/logo_0.png" alt="">
<div class="heading">Terms of Service</div>
<div class="content"></div>
<div class="buttons">
<div class="el btn btnDecline">Decline</div>
<div class="el btn btnAccept" title="Please scroll to the bottom to accept">Accept</div>
</div>
</div>

+ 43
- 0
src/client/ui/templates/terms/terms.js Прегледај датотеку

@@ -0,0 +1,43 @@
define([
'ui/factory',
'html!ui/templates/terms/template',
'css!ui/templates/terms/styles',
'js/system/globals',
'js/system/browserStorage'
], function (
uiFactory,
template,
styles,
globals,
browserStorage
) {
return {
tpl: template,
centered: true,

postRender: function () {
const { clientConfig: { tos: { content, version } } } = globals;
const morphedContent = content.split('\n').join('<br />');

const elHeading = this.find('.heading');
elHeading.html(`${elHeading.html()} (v${version})`);

this.find('.content').html(morphedContent);

this.find('.btnDecline').on('click', this.onDeclineClick.bind(this));
this.find('.btnAccept').on('click', this.onAcceptClick.bind(this, version));
},

onDeclineClick: function () {
browserStorage.set('tos_accepted_version', null);
window.location = window.location;
},

onAcceptClick: function (version) {
browserStorage.set('tos_accepted_version', version);
this.destroy();

uiFactory.build('characters');
}
};
});

+ 6
- 41
src/client/ui/templates/trade/trade.js Прегледај датотеку

@@ -3,13 +3,15 @@ define([
'js/system/client',
'html!ui/templates/trade/template',
'css!ui/templates/trade/styles',
'html!ui/templates/inventory/templateItem'
'html!ui/templates/inventory/templateItem',
'ui/shared/renderItem'
], function (
events,
client,
template,
styles,
tplItem
tplItem,
renderItem
) {
return {
tpl: template,
@@ -59,8 +61,7 @@ define([
}

if (!item) {
$(tplItem)
.appendTo(container)
renderItem(container, null)
.on('click', uiInventory.hideTooltip.bind(uiInventory));

continue;
@@ -68,35 +69,11 @@ define([

item = $.extend(true, {}, item);

let size = 64;
let offset = 0;

let itemEl = $(tplItem)
.appendTo(container);

let spritesheet = item.spritesheet || '../../../images/items.png';
if (!item.spritesheet) {
if (item.material)
spritesheet = '../../../images/materials.png';
else if (item.quest)
spritesheet = '../../../images/questItems.png';
else if (item.type === 'consumable')
spritesheet = '../../../images/consumables.png';
else if (item.type === 'skin')
spritesheet = '../../../images/characters.png';
}
if (item.type === 'skin') {
offset = 4;
size = 8;
}

let imgX = (-item.sprite[0] * size) + offset;
let imgY = (-item.sprite[1] * size) + offset;
let itemEl = renderItem(container, item);

itemEl
.data('item', item)
.find('.icon')
.css('background', 'url(' + spritesheet + ') ' + imgX + 'px ' + imgY + 'px')
.addClass(item.type);

if (isMobile)
@@ -108,11 +85,6 @@ define([
.on('mouseleave', uiInventory.hideTooltip.bind(uiInventory, itemEl, item));
}

if (item.quantity)
itemEl.find('.quantity').html(item.quantity);
else if (item.eq)
itemEl.find('.quantity').html('EQ');

if (action === 'buy') {
let noAfford = false;
if (item.worth.currency) {
@@ -132,13 +104,6 @@ define([
item.worthText = item.worth.amount + 'x ' + item.worth.currency;
else
item.worthText = ~~(itemList.markup * item.worth);

if (item.eq)
itemEl.addClass('eq');
else if (item.isNew) {
itemEl.addClass('new');
itemEl.find('.quantity').html('NEW');
}
}

this.center();


+ 33
- 18
src/client/ui/templates/workbench/styles.less Прегледај датотеку

@@ -18,6 +18,7 @@
padding-top: 8px;
margin: auto;
}

}

.bottom {
@@ -29,8 +30,9 @@
color: @blueB;
margin-bottom: 10px;
}
.left, .right {

.left,
.right {
float: left;
height: 100%;
padding: 10px;
@@ -55,8 +57,11 @@
&:hover {
background-color: @blackB;
}

}

}

}

.right {
@@ -70,9 +75,10 @@
height: calc(100% - 100px - 35px);

.title {
color: @orange;
color: @orangeA;
padding-bottom: 10px;
}

}

.materialList {
@@ -80,12 +86,12 @@
visibility: hidden;

.material {


&.need {
color: @redB;
}

}

}

.buttons {
@@ -93,23 +99,32 @@

> .btn {
height: 35px;
width: 100px;
color: @white;
text-align: center;
padding-top: 10px;
background-color: @blackB;
cursor: pointer;
float: left;
&:last-child {
width: 100px;
color: @white;
text-align: center;
padding-top: 10px;
background-color: @blackB;
cursor: pointer;
float: left;
&:last-child {
float: right;
}
}

&:hover {
background-color: @blackA;
}

&:hover {
background-color: @blackA;
}
}

}

}

}

}

.mobile .uiWorkbench {
z-index: 2;
}

+ 15
- 3
src/client/ui/uiBase.js Прегледај датотеку

@@ -96,11 +96,20 @@ define([
},

show: function () {
if (this.modal)
$('.modal').hide();
if (this.modal) {
//Close any other open modal
$('.modal').toArray().forEach(el => {
const ui = $(el).data('ui');
if (ui.shown)
ui.hide();
});
}

this.shown = true;
this.el.show();
if (this.isFlex)
this.el.css('display', 'flex');
else
this.el.show();

if (this.onAfterShow)
this.onAfterShow();
@@ -115,6 +124,9 @@ define([

this.shown = false;
this.el.hide();

if (this.afterHide)
this.afterHide();
},

destroy: function () {


+ 29
- 4
src/server/components/extensions/socialCommands.js Прегледај датотеку

@@ -6,6 +6,8 @@ let factions = require('../../config/factions');
let connections = require('../../security/connections');

const ban = require('../social/ban');
const rezone = require('../social/rezone');
const canChat = require('../social/canChat');

let commandRoles = {
//Regular players
@@ -15,6 +17,7 @@ let commandRoles = {
roll: 0,
block: 0,
unblock: 0,
help: 0,

//Mods
ban: 5,
@@ -39,7 +42,8 @@ let commandRoles = {
getXp: 10,
setPassword: 10,
giveSkin: 10,
getMaterials: 10
getMaterials: 10,
rezone: 10
};

//Commands that should be run on the main thread (not the zone thread)
@@ -56,7 +60,8 @@ const localCommands = [
'unblock',
'broadcast',
'saveAll',
'ban'
'ban',
'help'
];

//Actions that should appear when a player is right clicked
@@ -281,18 +286,34 @@ module.exports = {
});
},

help: function () {
const msg = [
'You can use the following commands:',
...Object.keys(commandRoles)
.filter(c => this.roleLevel >= commandRoles[c])
.map(c => `/${c}`)
].join('<br />');
this.sendMessage(msg, 'color-yellowB');
},

isInChannel: function (character, channel) {
return character.auth.customChannels.some(c => (c === channel));
},

roll: function () {
let roll = 1 + ~~(Math.random() * 100);
if (!canChat(this.obj)) {
this.sendMessage('Your character needs to be played for at least 3 minutes or be at least level 3 to be able to send messages in chat.', 'color-redA');
return;
}

const roll = 1 + ~~(Math.random() * 100);
cons.emit('event', {
event: 'onGetMessages',
data: {
messages: [{
class: 'color-grayB',
message: this.obj.name + ' rolled ' + roll,
message: `${this.obj.name} rolled ${roll}`,
type: 'chat'
}]
}
@@ -674,5 +695,9 @@ module.exports = {

ban: function (msg) {
ban(this, msg);
},

rezone: function (msg) {
rezone(this, msg);
}
};

+ 17
- 8
src/server/components/inventory.js Прегледај датотеку

@@ -5,6 +5,7 @@ let classes = require('../config/spirits');
let mtx = require('../mtx/mtx');
let factions = require('../config/factions');
let itemEffects = require('../items/itemEffects');
const transactions = require('../security/transactions');

const { applyItemStats } = require('./equipment/helpers');

@@ -449,8 +450,9 @@ module.exports = {
},

mailItem: async function (msg) {
/*let item = this.findItem(msg.itemId);
if ((!item) || (item.noDrop) || (item.quest)) {
let item = this.findItem(msg.itemId);

if (!item || item.noDrop || item.quest) {
this.resolveCallback(msg);
return;
}
@@ -468,6 +470,8 @@ module.exports = {
} else if (!this.findItem(msg.itemId))
return;

const resolveTrans = transactions.register();

let blocked = false;
if (res.components) {
let social = res.components.find(f => f.type === 'social');
@@ -475,13 +479,15 @@ module.exports = {
blocked = true;
}

if (!blocked) {
const mappedItem = this.simplifyItem(item);
this.obj.instance.mail.sendMail(msg.recipient, [mappedItem]);
}
const mappedItem = this.simplifyItem(item);
this.destroyItem(item.id);

this.resolveCallback(msg);*/
if (!blocked)
await this.obj.instance.mail.sendMail(msg.recipient, [mappedItem]);

this.resolveCallback(msg);

resolveTrans();
},

hookItemEvents: function (items) {
@@ -554,9 +560,12 @@ module.exports = {
this.items
.filter(i => !i.eq)
.map(i => {
//If we don't do this, [waist] goes before [undefined]
const useSlot = i.slot ? i.slot : 'z';

return {
item: i,
sortId: `${i.slot}${i.material}${i.quest}${i.spell}${i.quality}${i.level}${i.sprite}${i.id}`
sortId: `${useSlot}${i.material}${i.quest}${i.spell}${i.quality}${i.level}${i.sprite}${i.id}`
};
})
.sort((a, b) => {


+ 1
- 0
src/server/components/passives.js Прегледај датотеку

@@ -109,6 +109,7 @@ module.exports = {
this.selected.push(passiveTree.nodes.find(n => (n.spiritStart === this.obj.class)).id);

this.obj.spellbook.calcDps();
this.obj.equipment.unequipAttrRqrGear();
},

simplify: function (self) {


+ 1
- 0
src/server/components/player.js Прегледај датотеку

@@ -75,6 +75,7 @@ module.exports = {
obj.addComponent('stash', {
items: character.stash
});
obj.stash.calculateMaxItems(roles.getExtraStashSlots(character.account));

let blueprintEffects = character.components.find(c => c.type === 'effects') || {};
if (blueprintEffects.effects) {


+ 3
- 1
src/server/components/quests.js Прегледај датотеку

@@ -30,7 +30,9 @@ module.exports = {
if (!quest.init(hideMessage)) {
this.quests.spliceWhere(q => (q === quest));
return false;
} return true;
}

return true;
},

complete: function (id) {


+ 13
- 0
src/server/components/social/canChat.js Прегледај датотеку

@@ -0,0 +1,13 @@
module.exports = (obj, time) => {
if (!time)
time = +new Date();
const playerLevel = obj.level;
const playedTime = obj.stats.stats.played * 1000;
const sessionStart = obj.player.sessionStart;
const sessionDelta = time - sessionStart;

const canChat = (playerLevel >= 3 || playedTime + sessionDelta >= 180000);
return canChat;
};

+ 2
- 6
src/server/components/social/chat.js Прегледај датотеку

@@ -1,6 +1,7 @@
let roles = require('../../config/roles');
let events = require('../../misc/events');
const profanities = require('../../misc/profanities');
const canChat = require('./canChat');

module.exports = (cpnSocial, msg) => {
if (!msg.data.message)
@@ -54,12 +55,7 @@ module.exports = (cpnSocial, msg) => {
return;
}

let playerLevel = obj.level;
let playedTime = obj.stats.stats.played * 1000;
let sessionStart = obj.player.sessionStart;
let sessionDelta = time - sessionStart;

if (playerLevel < 3 && playedTime + sessionDelta < 180000) {
if (!canChat(obj, time)) {
sendMessage('Your character needs to be played for at least 3 minutes or be at least level 3 to be able to send messages in chat.', 'color-redA');
return;
}


+ 18
- 0
src/server/components/social/rezone.js Прегледај датотеку

@@ -0,0 +1,18 @@
module.exports = async (cpnSocial, targetZone) => {
const { obj } = cpnSocial;

obj.fireEvent('beforeRezone');

obj.destroyed = true;

const simpleObj = obj.getSimple(true, false, true);

process.send({
method: 'rezone',
id: obj.serverId,
args: {
obj: simpleObj,
newZone: targetZone
}
});
};

+ 21
- 19
src/server/components/spellbook.js Прегледај датотеку

@@ -351,25 +351,6 @@ module.exports = {
if (!isAuto)
this.sendAnnouncement('Insufficient mana to cast spell');
success = false;
} else if (spell.manaReserve) {
let reserve = spell.manaReserve;

if (reserve.percentage) {
let reserveEvent = {
spell: spell.name,
reservePercent: reserve.percentage
};
this.obj.fireEvent('onBeforeReserveMana', reserveEvent);

if (!spell.active) {
if (1 - this.obj.stats.values.manaReservePercent < reserve.percentage) {
this.sendAnnouncement('Insufficient mana to cast spell');
success = false;
} else
this.obj.stats.addStat('manaReservePercent', reserveEvent.reservePercent);
} else
this.obj.stats.addStat('manaReservePercent', -reserveEvent.reservePercent);
}
} else if (spell.has('range')) {
let distance = Math.max(Math.abs(action.target.x - this.obj.x), Math.abs(action.target.y - this.obj.y));
let range = spell.range;
@@ -410,6 +391,27 @@ module.exports = {
if (!castSuccess.success)
return false;

if (spell.manaReserve) {
let reserve = spell.manaReserve;

if (reserve.percentage) {
let reserveEvent = {
spell: spell.name,
reservePercent: reserve.percentage
};
this.obj.fireEvent('onBeforeReserveMana', reserveEvent);

if (!spell.active) {
if (1 - this.obj.stats.values.manaReservePercent < reserve.percentage) {
this.sendAnnouncement('Insufficient mana to cast spell');
success = false;
} else
this.obj.stats.addStat('manaReservePercent', reserveEvent.reservePercent);
} else
this.obj.stats.addStat('manaReservePercent', -reserveEvent.reservePercent);
}
}

if (spell.targetFurthest)
spell.target = this.obj.aggro.getFurthest();
else if (spell.targetRandom)


+ 13
- 4
src/server/components/stash.js Прегледај датотеку

@@ -1,5 +1,7 @@
const cpnInventory = require('./inventory');

const maxItems = 50;

module.exports = {
type: 'stash',

@@ -7,6 +9,8 @@ module.exports = {
items: [],
changed: false,

maxItems,

init: function (blueprint) {
let items = blueprint.items || [];
let iLen = items.length;
@@ -18,6 +22,10 @@ module.exports = {
this.blueprint = blueprint;
},

calculateMaxItems: function (extraSlots) {
this.maxItems = maxItems + extraSlots;
},

getItem: function (item) {
//Material?
let exists = false;
@@ -57,7 +65,7 @@ module.exports = {
deposit: function (item) {
if (!this.active)
return;
else if (this.items.length >= 50) {
else if (this.items.length >= this.maxItems) {
let isMaterial = this.items.some(stashedItem => item.name === stashedItem.name && (item.quantity || item.material));
if (!isMaterial) {
this.obj.instance.syncer.queue('onGetMessages', {
@@ -137,12 +145,12 @@ module.exports = {
}
});

if (this.active && this.items.length > 50) {
if (this.active && this.items.length > this.maxItems) {
obj.instance.syncer.queue('onGetMessages', {
id: this.obj.id,
messages: [{
class: 'color-redA',
message: 'You have more than 50 items in your stash. In the next version (v0.3.1) you will lose all items that put you over the limit',
message: `You have more than ${this.maxItems} items in your stash. In the next version (v0.3.1) you will lose all items that put you over the limit`,
type: 'info'
}]
}, [obj.serverId]);
@@ -161,7 +169,8 @@ module.exports = {
return {
type: 'stash',
active: this.active,
items: this.items
items: this.items,
maxItems: this.maxItems
};
},



+ 17
- 5
src/server/config/clientConfig.js Прегледај датотеку

@@ -1,13 +1,25 @@
let events = require('../misc/events');
const events = require('../misc/events');
const tos = require('./tos');

module.exports = {
const config = {
resourceList: [],
uiList: [],
contextMenuActions: {
player: [],
npc: []
},
tos
};

module.exports = {
init: function () {
events.emit('onBeforeGetResourceList', this.resourceList);
events.emit('onBeforeGetResourceList', config.resourceList);
events.emit('onBeforeGetUiList', config.uiList);
events.emit('onBeforeGetContextMenuActions', config.contextMenuActions);
events.emit('onBeforeGetTermsOfService', config.tos);
},

getResourcesList: function (msg) {
msg.callback(this.resourceList);
getClientConfig: function (msg) {
msg.callback(config);
}
};

+ 4
- 0
src/server/config/effects/effectStunned.js Прегледај датотеку

@@ -1,6 +1,10 @@
module.exports = {
type: 'stunned',

init: function () {
this.obj.spellbook.stopCasting();
},

events: {
beforeMove: function (targetPos) {
targetPos.success = false;


+ 46
- 4
src/server/config/maps/cave/map.json
Разлика између датотеке није приказан због своје велике величине
Прегледај датотеку


+ 13
- 1
src/server/config/maps/fjolarok/zone.js Прегледај датотеку

@@ -675,7 +675,19 @@ module.exports = {
}
},
rare: {
name: 'Fleshripper'
name: 'Fleshripper',
drops: {
rolls: 1,
noRandom: true,
alsoRandom: true,
blueprints: [{
chance: 80,
name: 'Eagle Feather',
material: true,
sprite: [0, 0],
spritesheet: 'images/questItems.png'
}]
}
}
},
hermit: {


+ 2
- 2
src/server/config/maps/sewer/events/plagueOfRats.js Прегледај датотеку

@@ -278,7 +278,7 @@ module.exports = {
}, {
type: 'setDescription',
desc: descriptionStrings.success,
ttl: 50
ttl: 100
}, {
type: 'giveRewards'
}, {
@@ -286,6 +286,6 @@ module.exports = {
}, {
type: 'setDescription',
desc: descriptionStrings.failure,
ttl: 50
ttl: 100
}]
};

+ 17
- 1
src/server/config/maps/sewer/zone.js Прегледај датотеку

@@ -5,6 +5,9 @@ const balance = {
giantRat: {
clawChance: 5
},
enragedRat: {
clawChance: 80
},
stinktooth: {
runestoneChance: 10,
recipeChance: 3,
@@ -63,7 +66,20 @@ module.exports = {

rare: {
name: 'Enraged Rat',
cell: 24
cell: 24,

drops: {
rolls: 1,
noRandom: true,
alsoRandom: true,
blueprints: [{
chance: balance.enragedRat.clawChance,
name: 'Rat Claw',
material: true,
sprite: [3, 0],
spritesheet: 'images/materials.png'
}]
}
}
},



+ 5
- 0
src/server/config/quests/questBuilder.js Прегледај датотеку

@@ -8,6 +8,7 @@ module.exports = {
init: function (instance) {
this.instance = instance;
},

obtain: function (obj, template) {
let zoneName = template ? template.zoneName : obj.zoneName;
let zonePath = mapList.mapList.find(m => m.name === zoneName).path;
@@ -31,6 +32,10 @@ module.exports = {
if (config.infini.length === 0)
return;

const minPlayerLevel = ~~(obj.instance.map.zone.level[0] * 0.75);
if (obj.stats.values.level < minPlayerLevel)
return;

let pickQuest = null;
if ((template) && (template.type))
pickQuest = config.infini.find(c => c.type === template.type);


+ 2
- 2
src/server/config/recipes/etching.js Прегледај датотеку

@@ -2,7 +2,7 @@ module.exports = [{
id: 'runeWhirlwind',
name: 'Rune of Whirlwind',
default: false,
description: 'Wiggle-wiggly woo-woo.',
description: 'You furiously spin in a circle, striking all foes around you.',
item: {
name: 'Rune of Whirlwind',
generate: true,
@@ -20,7 +20,7 @@ module.exports = [{
id: 'runeAmbush',
name: 'Rune of Ambush',
default: false,
description: 'Wiggle-wiggly woo-woo.',
description: 'Step into the shadows and reappear behind your target before delivering a concussing blow.',
item: {
name: 'Rune of Ambush',
generate: true,


+ 8
- 0
src/server/config/roles.js Прегледај датотеку

@@ -73,6 +73,14 @@ module.exports = {
return skins;
},

getExtraStashSlots: function (accountName) {
const account = this.getAccount(accountName);
if (!account)
return 0;

return account.extraStashSlots || 0;
},

sendMessage: function (player, msg) {
msg = 'Only certain roles can ' + msg + ' at the moment';



+ 1
- 1
src/server/config/serverConfig.js Прегледај датотеку

@@ -1,5 +1,5 @@
module.exports = {
version: '0.4.2',
version: '0.4.3',
port: 4000,
startupMessage: 'Server: ready',
defaultZone: 'fjolarok',


+ 3
- 3
src/server/config/spells/spellFireblast.js Прегледај датотеку

@@ -1,4 +1,4 @@
const getTargetPos = (physics, obj, m) => {
const getTargetPos = (physics, obj, m, pushback) => {
let targetPos = {
x: m.x,
y: m.y
@@ -14,7 +14,7 @@ const getTargetPos = (physics, obj, m) => {

dx = ~~(dx / Math.abs(dx));
dy = ~~(dy / Math.abs(dy));
for (let l = 0; l < this.pushback; l++) {
for (let l = 0; l < pushback; l++) {
if (physics.isTileBlocking(targetPos.x + dx, targetPos.y + dy)) {
if (physics.isTileBlocking(targetPos.x + dx, targetPos.y)) {
if (physics.isTileBlocking(targetPos.x, targetPos.y + dy))
@@ -89,7 +89,7 @@ module.exports = {
else if (!obj.aggro.canAttack(m))
continue;

const targetPos = getTargetPos(physics, obj, m);
const targetPos = getTargetPos(physics, obj, m, this.pushback);

let distance = Math.max(Math.abs(m.x - targetPos.x), Math.abs(m.y - targetPos.y));
let ttl = distance * 125;


+ 18
- 0
src/server/config/tos.js Прегледај датотеку

@@ -0,0 +1,18 @@
const version = '0.0.1';

const content = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus venenatis risus enim, a bibendum est suscipit vel. Donec consectetur justo nec sodales varius. Ut dignissim condimentum lacus, at euismod arcu scelerisque in. Vestibulum et orci quis nulla laoreet placerat. Fusce tempus, tortor eu commodo suscipit, massa urna rhoncus nisi, eget malesuada lorem mauris nec lorem. Vestibulum eu turpis rutrum, auctor nulla eget, placerat mi. Praesent porta, tortor pulvinar euismod ornare, quam sem porta nulla, rhoncus egestas odio nulla sit amet massa. Phasellus non lacus eu massa commodo feugiat. Proin cursus augue nibh, at egestas nibh facilisis at. Nam tempus dictum mollis. In ante ex, commodo ut tortor in, fermentum posuere felis. Donec vel ipsum maximus nisi lacinia finibus non a enim. Maecenas elementum, diam id placerat gravida, mi ex tristique eros, id rhoncus ex diam eget nibh.

Vestibulum non viverra elit. Cras nec turpis nibh. Ut eu diam nisl. Pellentesque scelerisque augue imperdiet, bibendum ante non, imperdiet est. Praesent eu lacus porttitor, maximus sem vel, fringilla arcu. Nunc aliquet dictum justo, eu blandit dolor finibus eget. Vestibulum massa risus, convallis sit amet venenatis ac, viverra interdum diam. Aenean at condimentum enim, ut blandit odio. Proin congue nulla nisi, at consequat ipsum imperdiet ut. Morbi nec varius risus. Mauris dui erat, semper ut massa quis, ornare congue nisl. Duis sed dolor iaculis, egestas ligula nec, pretium libero. Nulla leo elit, lacinia imperdiet nisl et, viverra aliquet ex. Sed quis fringilla felis.

Donec eget ligula tristique, consequat nunc in, porttitor elit. Nulla faucibus eleifend elit eget vestibulum. Nam imperdiet dui nec felis egestas, at dapibus turpis volutpat. Sed faucibus ultrices porta. Aliquam tempus est libero, sed pulvinar erat luctus et. Integer convallis maximus justo, non pulvinar nisl viverra vitae. In hac habitasse platea dictumst. Etiam ut nibh vel odio accumsan fermentum vitae consectetur metus.

Mauris eget erat ipsum. Suspendisse efficitur dictum metus, ac vulputate risus euismod id. Quisque suscipit quis sem ac luctus. Integer tincidunt sit amet massa feugiat auctor. Ut faucibus cursus augue eu ornare. Morbi arcu elit, tincidunt eu elit non, rhoncus egestas justo. Fusce viverra fermentum purus sed finibus. Nunc consectetur, massa vehicula laoreet mattis, sapien neque facilisis quam, vel ultrices mi lacus nec odio. Sed eros sapien, cursus vel euismod a, ornare eu magna. Vestibulum pharetra in sapien vehicula commodo. Aliquam erat volutpat. Duis eget risus augue. Maecenas at lobortis urna. Morbi ultrices porttitor lorem consequat volutpat. Phasellus ac tristique purus, eu vestibulum quam.

In vehicula mauris neque, nec hendrerit enim accumsan quis. Nunc sed sapien ac odio venenatis blandit. Vestibulum et ipsum arcu. Ut lectus dolor, venenatis et massa quis, auctor mollis tellus. Nulla mauris velit, lacinia id ligula id, molestie ullamcorper risus. Sed tincidunt feugiat metus, a mattis eros aliquet non. Sed gravida risus at vestibulum aliquet. Maecenas pellentesque libero eu elit cursus, a blandit massa ultricies. Donec urna eros, facilisis ac lacus eu, vulputate volutpat nibh. Nam feugiat molestie ligula, vitae lacinia nibh interdum in. In pellentesque est et lorem euismod, eu vehicula justo placerat. Mauris quis ligula nec enim consectetur congue. Vestibulum et maximus ex.
`;

module.exports = {
version,
required: true,
content
};

+ 2
- 0
src/server/index.js Прегледај датотеку

@@ -15,6 +15,7 @@ let mapList = require('./config/maps/mapList');
let sheets = require('./security/sheets');
let fixes = require('./fixes/fixes');
let profanities = require('./misc/profanities');
const routerConfig = require('./security/routerConfig');

let startup = {
init: function () {
@@ -32,6 +33,7 @@ let startup = {
},

onModsLoaded: function () {
routerConfig.init();
classes.init();
spellsConfig.init();
spells.init();


+ 1
- 0
src/server/items/enchanter.js Прегледај датотеку

@@ -103,6 +103,7 @@ const reslot = (item, msg) => {
delete item.spell;
delete item.implicitStats;
delete item.power;
delete item.range;

extend(item, newItem);
};


+ 2
- 8
src/server/mail/mailSqlite.js Прегледај датотеку

@@ -138,20 +138,14 @@ module.exports = {
noParse: true
});

this.doSendMail(playerName, items, callback, result);
},

doSendMail: async function (playerName, items, callback, result) {
if (result === 'null')
result = null;

result = JSON.parse(result || '[]');

items.forEach(function (i) {
result.push(i);
});
result.push(...items);

let itemString = JSON.stringify(result).split('\'').join('`');
const itemString = JSON.stringify(result).split('\'').join('`');

await io.setAsync({
key: playerName,


+ 25
- 0
src/server/objects/objBase.js Прегледај датотеку

@@ -5,6 +5,8 @@ module.exports = {

actionQueue: [],

eventListeners: [],

addComponent: function (type, blueprint, isTransfer) {
let cpn = this[type];
if (!cpn) {
@@ -355,6 +357,21 @@ module.exports = {
}
},

onEvent: function (eventName, callback) {
const entry = {
eventName,
callback
};

this.eventListeners.push(entry);

return this.offEvent.bind(this, entry);
},

offEvent: function (entry) {
this.eventListeners.spliceWhere(e => e === entry);
},

fireEvent: function (event) {
let args = [].slice.call(arguments, 1);

@@ -373,6 +390,14 @@ module.exports = {
callback.apply(cpn, args);
}

this.eventListeners.forEach(l => {
const { eventName, callback } = l;
if (eventName !== event)
return;

callback.apply(null, args);
});

if (this.effects)
this.effects.fireEvent(event, args);
if (this.quests)


+ 14
- 0
src/server/security/connections.js Прегледај датотеку

@@ -14,6 +14,7 @@ module.exports = {

this.players.push(p);
},

onDisconnect: function (socket) {
let player = this.players.find(p => p.socket.id === socket.id);

@@ -52,6 +53,7 @@ module.exports = {

this.players.spliceWhere(p => p.socket.id === socket.id);
},

route: function (socket, msg) {
let player = null;

@@ -79,6 +81,17 @@ module.exports = {
)
return;

if (msg.threadModule) {
const source = this.players.find(p => p.socket.id === socket.id);
if (!source)
return;

msg.data.sourceId = source.id;
atlas.send(player.zone, msg);

return;
}

let cpn = player[msg.cpn];
if (!cpn)
return;
@@ -87,6 +100,7 @@ module.exports = {
if (cpn[method])
cpn[method](msg);
},

unzone: function (msg) {
let socket = msg.socket;
let player = this.players.find(p => p.socket.id === socket.id);


+ 4
- 3
src/server/security/rest.js Прегледај датотеку

@@ -1,5 +1,4 @@
const serverConfig = require('../config/serverConfig');
const connections = require('../security/connections');
const version = serverConfig.version;
const bcrypt = require('bcrypt-nodejs');
const roles = require('../config/roles');
@@ -37,7 +36,7 @@ module.exports = {
bcrypt.compare(config.pwd, storedPassword, this.doSaveAll.bind(this, res, config));
},

doSaveAll: function (res, config, err, compareResult) {
doSaveAll: async function (res, config, err, compareResult) {
if (!compareResult)
return;

@@ -47,6 +46,8 @@ module.exports = {
if (roleLevel < 9)
return;

await atlas.returnWhenZonesIdle();

cons.emit('event', {
event: 'onGetMessages',
data: {
@@ -58,7 +59,7 @@ module.exports = {
}
});

connections.forceSaveAll();
cons.forceSaveAll();

res.jsonp({
success: true


+ 14
- 29
src/server/security/router.js Прегледај датотеку

@@ -1,43 +1,28 @@
const { routerConfig: { allowed, secondaryAllowed, globalAllowed } } = require('./routerConfig');

module.exports = {
allowedCpn: function (msg) {
let allowed = {
player: ['performAction', 'queueAction', 'move'],
auth: ['login', 'register', 'play', 'getCharacterList', 'getCharacter', 'deleteCharacter', 'getSkinList', 'createCharacter', 'getCustomChannels'],
social: ['chat', 'getInvite', 'acceptInvite', 'declineInvite', 'removeFromParty', 'leaveParty']
};

let valid = ((allowed[msg.cpn]) && (allowed[msg.cpn].indexOf(msg.method) > -1));
let valid = allowed[msg.cpn] && allowed[msg.cpn].includes(msg.method);
if (!valid)
return false;

if (!msg.data.cpn)
return true;

let secondaryAllowed = {
dialogue: ['talk'],
gatherer: ['gather'],
quests: ['complete'],
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'enchantItem', 'getEnchantMaterials', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'],
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'],
stash: ['withdraw', 'open'],
trade: ['buySell'],
door: ['lock', 'unlock'],
wardrobe: ['open', 'apply'],
stats: ['respawn'],
passives: ['tickNode', 'untickNode'],
workbench: ['open', 'craft', 'getRecipe']
};

return ((secondaryAllowed[msg.data.cpn]) && (secondaryAllowed[msg.data.cpn].indexOf(msg.data.method) > -1));
const result = secondaryAllowed[msg.data.cpn] && secondaryAllowed[msg.data.cpn].includes(msg.data.method);

return result;
},

allowedGlobal: function (msg) {
let allowed = {
clientConfig: ['getResourcesList'],
leaderboard: ['requestList'],
cons: ['unzone']
};
const result = globalAllowed[msg.module] && globalAllowed[msg.module].includes(msg.method);

return result;
},

allowedGlobalCall: function (threadModule, method) {
const result = globalAllowed[threadModule] && globalAllowed[threadModule].includes(method);

return ((allowed[msg.module]) && (allowed[msg.module].indexOf(msg.method) > -1));
return result;
}
};

+ 36
- 0
src/server/security/routerConfig.js Прегледај датотеку

@@ -0,0 +1,36 @@
let events = require('../misc/events');

const routerConfig = {
allowed: {
player: ['performAction', 'queueAction', 'move'],
auth: ['login', 'register', 'play', 'getCharacterList', 'getCharacter', 'deleteCharacter', 'getSkinList', 'createCharacter', 'getCustomChannels'],
social: ['chat', 'getInvite', 'acceptInvite', 'declineInvite', 'removeFromParty', 'leaveParty']
},
secondaryAllowed: {
dialogue: ['talk'],
gatherer: ['gather'],
quests: ['complete'],
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'enchantItem', 'getEnchantMaterials', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'],
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'],
stash: ['withdraw', 'open'],
trade: ['buySell'],
door: ['lock', 'unlock'],
wardrobe: ['open', 'apply'],
stats: ['respawn'],
passives: ['tickNode', 'untickNode'],
workbench: ['open', 'craft', 'getRecipe']
},
globalAllowed: {
clientConfig: ['getClientConfig'],
leaderboard: ['requestList'],
cons: ['unzone']
}
};

module.exports = {
routerConfig,

init: function () {
events.emit('onBeforeGetRouterConfig', routerConfig);
}
};

+ 2
- 0
src/server/security/sheets.js Прегледај датотеку

@@ -55,6 +55,8 @@ module.exports = {
o.messagePrefix = o.messageprefix;
delete o.messageprefix;

o.extraStashSlots = ~~o.extrastashslots;

if (typeof (o.items) === 'string')
o.items = JSON.parse(o.items || '[]');
if (typeof (o.skins) === 'string')


+ 2
- 1
src/server/security/sheetsConfig.js Прегледај датотеку

@@ -12,6 +12,7 @@ module.exports = {
name: 'Key to the world',
sprite: [12, 0],
keyId: 'world'
}]
}],
extrastashslots: 10
}]
};

+ 37
- 0
src/server/security/transactions.js Прегледај датотеку

@@ -0,0 +1,37 @@
let lastId = 0;
const list = [];

const complete = id => {
list.spliceWhere(l => l === id);
};

const register = () => {
const nextId = ++lastId;
list.push(nextId);

return complete.bind(null, nextId);
};

const returnWhenDone = async () => {
if (!list.length)
return;

return new Promise(res => {
const checker = () => {
if (!list.length) {
res();

return;
}

setTimeout(checker, 100);
};

checker();
});
};

module.exports = {
register,
returnWhenDone
};

+ 17
- 1
src/server/server.js Прегледај датотеку

@@ -72,6 +72,11 @@ module.exports = {
if (!router.allowedCpn(msg))
return;

cons.route(socket, msg);
} else if (msg.threadModule) {
if (!router.allowedGlobalCall(msg.threadModule, msg.method))
return;

cons.route(socket, msg);
} else {
if (!router.allowedGlobal(msg))
@@ -92,7 +97,18 @@ module.exports = {

file = file.replace('/' + root + '/', '');

if (root === 'server' && (file.indexOf('mods') === -1 || file.indexOf('png') === -1))
const validRequest = (
root !== 'server' ||
(
file.includes('mods/') &&
(
file.includes('.png') ||
file.includes('/ui/')
)
)
);

if (!validRequest)
return null;

res.sendFile(file, {


+ 30
- 0
src/server/world/atlas.js Прегледај датотеку

@@ -5,6 +5,8 @@ let connections = require('../security/connections');
let serverConfig = require('../config/serverConfig');
let events = require('../misc/events');

const listenersOnZoneIdle = [];

module.exports = {
nextId: 0,
lastCallbackId: 0,
@@ -220,6 +222,34 @@ module.exports = {
serverObj.player.broadcastSelf();

this.addObject(obj, true, true);
},

onZoneIdle: function (thread) {
listenersOnZoneIdle.forEach(l => l(thread));
}
},

returnWhenZonesIdle: async function () {
return new Promise(res => {
const waiting = [...this.threads];

const onZoneIdle = thread => {
waiting.spliceWhere(w => w === thread);

if (waiting.length)
return;

listenersOnZoneIdle.spliceWhere(l => l === onZoneIdle);
res();
};

listenersOnZoneIdle.push(onZoneIdle);

this.threads.forEach(t => {
t.worker.send({
method: 'notifyOnceIdle'
});
});
});
}
};

+ 10
- 1
src/server/world/instancer.js Прегледај датотеку

@@ -12,6 +12,7 @@ let scheduler = require('../misc/scheduler');
let mail = require('../mail/mail');
let herbs = require('../config/herbs');
let eventEmitter = require('../misc/events');
const transactions = require('../security/transactions');

module.exports = {
instances: [],
@@ -27,7 +28,7 @@ module.exports = {
herbs.init();
map.init(args);

let fakeInstance = {
const fakeInstance = {
objects: objects,
syncer: syncer,
physics: physics,
@@ -211,5 +212,13 @@ module.exports = {
}
});
}
},

notifyOnceIdle: async function () {
await transactions.returnWhenDone();

process.send({
method: 'onZoneIdle'
});
}
};

+ 3
- 3
src/server/world/map/canPathFromPos.js Прегледај датотеку

@@ -5,13 +5,13 @@ const canPath = (pos, positions, maxDistance = 0) => {
return positions.some(p => {
const path = physics.getPath(pos, p);
//Are we on the position?
if (!path.length)
return true;
if (!path.length)
return (p.x === pos.x && p.y === pos.y);

const { x, y } = path[path.length - 1];
//Can we get close enough to the position?
const isCloseEnough = Math.max(Math.abs(p.x - x), Math.abs(p.y - y)) <= maxDistance;
if (isCloseEnough)
if (isCloseEnough)
return true;

return false;


+ 3
- 1
src/server/world/worker.js Прегледај датотеку

@@ -91,6 +91,8 @@ process.on('message', m => {
if (found)
break;
}
} else if (m.method)
} else if (m.threadModule)
global[m.threadModule][m.method](m.data);
else if (m.method)
instancer[m.method](m.args);
});

Loading…
Откажи
Сачувај