diff --git a/src/client/css/main.less b/src/client/css/main.less index b50bf2d1..ff2d59a4 100644 --- a/src/client/css/main.less +++ b/src/client/css/main.less @@ -16,6 +16,12 @@ body { top: 0px; z-index: 20; overflow: hidden; + + > .right { + position: absolute; + right: 10px; + top: 100px; + } } @font-face diff --git a/src/client/index.html b/src/client/index.html index 860b1884..c1144ef1 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -11,6 +11,8 @@
-
+
+
+
\ No newline at end of file diff --git a/src/client/js/components/components.js b/src/client/js/components/components.js index c3f63851..0e84d83c 100644 --- a/src/client/js/components/components.js +++ b/src/client/js/components/components.js @@ -18,6 +18,7 @@ var components = [ 'effects', 'aggro', 'quests', + 'events', 'resourceNode', 'gatherer', 'stash', diff --git a/src/client/js/components/events.js b/src/client/js/components/events.js new file mode 100644 index 00000000..26a1b978 --- /dev/null +++ b/src/client/js/components/events.js @@ -0,0 +1,25 @@ +define([ + 'js/system/events' +], function( + events +) { + return { + type: 'events', + list: [], + + init: function() { + this.list.forEach(function(q) { + events.emit('onObtainEvent', q); + }); + }, + + extend: function(blueprint) { + if (blueprint.updateList) { + blueprint.updateList.forEach(function(q) { + events.emit('onObtainEvent', q); + this.list.push(q); + }, this); + } + } + }; +}); \ No newline at end of file diff --git a/src/client/js/main.js b/src/client/js/main.js index f2aa49b1..20cf0f3f 100644 --- a/src/client/js/main.js +++ b/src/client/js/main.js @@ -14,6 +14,7 @@ define([ 'ui/templates/hud/hud', 'ui/templates/online/online', 'ui/templates/quests/quests', + 'ui/templates/events/events', 'ui/templates/dialogue/dialogue', 'ui/templates/smithing/smithing', 'ui/templates/overlay/overlay', diff --git a/src/client/ui/factory.js b/src/client/ui/factory.js index 1898e872..3b2b083d 100644 --- a/src/client/ui/factory.js +++ b/src/client/ui/factory.js @@ -39,6 +39,7 @@ define([ 'tooltipItem', 'announcements', 'quests', + 'events', 'progressBar', 'stash', 'smithing', diff --git a/src/client/ui/templates/events/events.js b/src/client/ui/templates/events/events.js new file mode 100644 index 00000000..0a6a8ce0 --- /dev/null +++ b/src/client/ui/templates/events/events.js @@ -0,0 +1,98 @@ +define([ + 'js/system/client', + 'js/system/events', + 'html!ui/templates/events/template', + 'html!ui/templates/events/templateEvent', + 'css!ui/templates/events/styles' +], function( + client, + events, + tpl, + templateEvent, + styles +) { + return { + tpl: tpl, + + list: [], + + container: '.right', + + postRender: function() { + this.onEvent('onRezone', this.onRezone.bind(this)); + + this.onEvent('onObtainEvent', this.onObtainEvent.bind(this)); + this.onEvent('onUpdateEvent', this.onUpdateEvent.bind(this)); + this.onEvent('onCompleteEvent', this.onCompleteEvent.bind(this)); + }, + + onRezone: function() { + this.list = []; + this.el.find('.list').empty(); + }, + + onObtainEvent: function(event) { + var container = this.el.find('.list'); + + var html = templateEvent + .replace('$NAME$', event.name) + .replace('$DESCRIPTION$', event.description); + + var el = $(html).appendTo(container); + + if (event.isReady) + el.addClass('ready'); + + /*if (event.active) + el.addClass('active'); + else if (!event.isReady) + el.addClass('disabled');*/ + + this.list.push({ + id: event.id, + el: el, + event: event + }); + + var event = container.find('.event'); + + event + .sort(function(a, b) { + a = $(a).hasClass('active') ? 1 : 0; + b = $(b).hasClass('active') ? 1 : 0; + return b - a; + }) + .appendTo(container); + }, + + onUpdateEvent: function(event) { + var e = this.list.find(function(l) { + return (l.id == event.id); + }); + + e.event.isReady = event.isReady; + + e.el.find('.description').html(event.description); + + e.el.removeClass('ready'); + if (event.isReady) { + e.el.removeClass('disabled'); + e.el.addClass('ready'); + } + }, + + onCompleteEvent: function(id) { + var e = this.list.find(function(l) { + return (l.id == id); + }); + + if (!e) + return; + + e.el.remove(); + this.list.spliceWhere(function(l) { + return (l.id == id); + }); + } + } +}); \ No newline at end of file diff --git a/src/client/ui/templates/events/styles.less b/src/client/ui/templates/events/styles.less new file mode 100644 index 00000000..0a9fc6d3 --- /dev/null +++ b/src/client/ui/templates/events/styles.less @@ -0,0 +1,49 @@ +@import "../../../css/ui.less"; + +.uiEvents { + margin-top: 10px; + width: 320px; + + .heading { + color: @yellow; + padding: 8px; + background-color: fade(#3a3b4a, 90%); + } + + .list { + .event { + cursor: pointer; + padding: 8px; + background-color: fade(#3a3b4a, 90%); + + &:hover { + background-color: fade(lighten(#3a3b4a, 15%), 90%); + } + + .name { + color: @white; + margin-bottom: 3px; + } + + .description { + color: darken(@white, 35%); + } + + &.active { + .name { + color: @blue; + } + } + + &.ready { + .name { + color: @green; + } + + .description { + display: none; + } + } + } + } +} \ No newline at end of file diff --git a/src/client/ui/templates/events/template.html b/src/client/ui/templates/events/template.html new file mode 100644 index 00000000..a9af9eff --- /dev/null +++ b/src/client/ui/templates/events/template.html @@ -0,0 +1,4 @@ +
+
Events
+
+
\ No newline at end of file diff --git a/src/client/ui/templates/events/templateEvent.html b/src/client/ui/templates/events/templateEvent.html new file mode 100644 index 00000000..9c2aad77 --- /dev/null +++ b/src/client/ui/templates/events/templateEvent.html @@ -0,0 +1,4 @@ +
+
$NAME$
+
$DESCRIPTION$
+
\ No newline at end of file diff --git a/src/client/ui/templates/quests/quests.js b/src/client/ui/templates/quests/quests.js index cb3c7151..857346c2 100644 --- a/src/client/ui/templates/quests/quests.js +++ b/src/client/ui/templates/quests/quests.js @@ -15,6 +15,7 @@ define([ tpl: tpl, quests: [], + container: '.right', postRender: function() { this.onEvent('onRezone', this.onRezone.bind(this)); diff --git a/src/client/ui/templates/quests/styles.less b/src/client/ui/templates/quests/styles.less index f152eaf7..7757c61b 100644 --- a/src/client/ui/templates/quests/styles.less +++ b/src/client/ui/templates/quests/styles.less @@ -1,10 +1,7 @@ @import "../../../css/ui.less"; .uiQuests { - position: absolute; - right: 10px; - top: 100px; - + width: 320px; .heading { color: @yellow; @@ -24,6 +21,7 @@ .name { color: @white; + margin-bottom: 3px; } .description { diff --git a/src/client/ui/uiBase.js b/src/client/ui/uiBase.js index ab21c357..35d86dc2 100644 --- a/src/client/ui/uiBase.js +++ b/src/client/ui/uiBase.js @@ -15,8 +15,8 @@ define([ render: function() { var container = '.ui-container'; - if ((this.options) && (this.options.container)) - container = this.options.container;; + if (this.container) + container += ' > ' + this.container; this.el = $(this.tpl) .appendTo(container) diff --git a/src/server/components/events.js b/src/server/components/events.js new file mode 100644 index 00000000..245d9a6b --- /dev/null +++ b/src/server/components/events.js @@ -0,0 +1,51 @@ +define([ + +], function( + +) { + return { + type: 'events', + + list: [], + + simplify: function(self) { + if (!self) + return; + + var result = { + type: 'events' + }; + + if (this.list.length > 0) { + result.list = this.list.map(l => ({ + name: l.name, + description: l.description + })); + } + + return result; + }, + + save: function() { + return null; + }, + + events: { + afterMove: function() { + var events = this.obj.instance.events; + var closeEvents = events.getCloseEvents(this.obj); + if (!closeEvents) + return; + + closeEvents.forEach(function(c) { + this.list.push(c); + + this.obj.syncer.setArray(true, 'events', 'updateList', { + name: c.config.name, + description: c.config.description + }); + }, this); + } + } + }; +}); \ No newline at end of file diff --git a/src/server/components/player.js b/src/server/components/player.js index c35d6321..0baad066 100644 --- a/src/server/components/player.js +++ b/src/server/components/player.js @@ -78,6 +78,7 @@ define([ obj.addComponent('equipment', character.components.find(c => c.type == 'equipment')); obj.addComponent('inventory', character.components.find(c => c.type == 'inventory')); obj.addComponent('quests', character.components.find(c => c.type == 'quests')); + obj.addComponent('events', character.components.find(c => c.type == 'events')); var prophecies = character.components.find(c => c.type == 'prophecies'); if (prophecies) diff --git a/src/server/config/eventPhases/phaseSpawnMob.js b/src/server/config/eventPhases/phaseSpawnMob.js index c453e66f..af5529ec 100644 --- a/src/server/config/eventPhases/phaseSpawnMob.js +++ b/src/server/config/eventPhases/phaseSpawnMob.js @@ -61,6 +61,7 @@ define([ } }); this.spawnAnimation(mob); + this.event.objects.push(mob); } else { var mob = objects.buildObjects([{ x: x, @@ -80,6 +81,8 @@ define([ var id = l.id.split('$').join(i); mob.id = id; } + + this.event.objects.push(mob); } } }, this); diff --git a/src/server/config/maps/tutorial/events.js b/src/server/config/maps/tutorial/events.js index a4ef5b9c..cf22607a 100644 --- a/src/server/config/maps/tutorial/events.js +++ b/src/server/config/maps/tutorial/events.js @@ -1,6 +1,7 @@ module.exports = [{ name: 'Rodriguez Heist', description: `Rodriguez, the Hermit's only chicken companion, has been kidnapped by a band of imps. Who knows what they plan on doing with him.`, + distance: 10, phases: [{ type: 'spawnMob', diff --git a/src/server/events/events.js b/src/server/events/events.js index 045c72da..8066fac3 100644 --- a/src/server/events/events.js +++ b/src/server/events/events.js @@ -47,6 +47,8 @@ define([ var event = { config: config, phases: [], + participators: [], + objects: [], nextPhase: 0 }; @@ -54,6 +56,16 @@ define([ }, updateEvent: function(event) { + var objects = event.objects; + var oLen = objects.length; + for (var i = 0; i < oLen; i++) { + if (objects[i].destroyed) { + objects.splice(i, 1); + i--; + oLen--; + } + } + var currentPhases = event.phases; var cLen = currentPhases.length; var stillBusy = false; @@ -80,7 +92,8 @@ define([ var phaseFile = 'phase' + p.type[0].toUpperCase() + p.type.substr(1); var typeTemplate = require('config/eventPhases/' + phaseFile); var phase = extend(true, { - instance: this.instance + instance: this.instance, + event: event }, phaseTemplate, typeTemplate, p); event.phases.push(phase); @@ -92,6 +105,41 @@ define([ if (!p.auto) break; } + }, + + getCloseEvents: function(obj) { + var x = obj.x; + var y = obj.y; + + var configs = this.configs; + if (!configs) + return; + + var cLen = configs.length; + var result = []; + for (var i = 0; i < cLen; i++) { + var event = configs[i].event; + if (!event) + continue; + else if (event.participators.some(p => (p == obj))) + continue; + + var distance = event.config.distance; + + var objects = event.objects; + var oLen = objects.length; + for (var j = 0; j < oLen; j++) { + var o = objects[j]; + + if ((Math.abs(x - o.x) < distance) && (Math.abs(y - o.y) < distance)) { + event.participators.push(obj); + result.push(event); + break; + } + } + } + + return result; } }; }); \ No newline at end of file diff --git a/src/server/objects/objBase.js b/src/server/objects/objBase.js index e4e93884..8b728d59 100644 --- a/src/server/objects/objBase.js +++ b/src/server/objects/objBase.js @@ -291,6 +291,8 @@ define([ if (this.aggro) this.aggro.move(); + this.fireEvent('afterMove'); + return true; }, diff --git a/src/server/world/instancer.js b/src/server/world/instancer.js index c8c4cbe0..91ad49d1 100644 --- a/src/server/world/instancer.js +++ b/src/server/world/instancer.js @@ -45,6 +45,7 @@ define([ zoneId: this.zoneId, spawners: spawners, questBuilder: questBuilder, + events: events, zone: map.zone, map: map };