@makefully/platypus 4.1.5 → 4.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +3 -3
  3. package/lib/platypus.js +1 -1
  4. package/package.json +6 -5
  5. package/src/AABB.js +685 -0
  6. package/src/ActionState.js +121 -0
  7. package/src/AssetManager.js +206 -0
  8. package/src/CollisionData.js +96 -0
  9. package/src/CollisionDataContainer.js +127 -0
  10. package/src/CollisionShape.js +315 -0
  11. package/src/Component.js +231 -0
  12. package/src/Data.js +64 -0
  13. package/src/DataMap.js +204 -0
  14. package/src/Entity.js +404 -0
  15. package/src/EntityLinker.js +113 -0
  16. package/src/EventHandler.js +115 -0
  17. package/src/EventHandlerList.js +251 -0
  18. package/src/Game.js +840 -0
  19. package/src/Gamepad.js +175 -0
  20. package/src/ID3CaptionPlayer.js +61 -0
  21. package/src/Messenger.js +365 -0
  22. package/src/PIXIAnimation.js +622 -0
  23. package/src/RandomSet.js +140 -0
  24. package/src/SFXPlayer.js +120 -0
  25. package/src/StateMap.js +252 -0
  26. package/src/Storage.js +152 -0
  27. package/src/TickerClient.js +48 -0
  28. package/src/TickerServer.js +23 -0
  29. package/src/TimeEvent.js +50 -0
  30. package/src/TimeEventList.js +100 -0
  31. package/src/VOPlayer.js +684 -0
  32. package/src/Vector.js +702 -0
  33. package/src/components/AIChaser.js +161 -0
  34. package/src/components/AIPacer.js +107 -0
  35. package/src/components/AudioMusic.js +151 -0
  36. package/src/components/AudioSFX.js +673 -0
  37. package/src/components/AudioVO.js +301 -0
  38. package/src/components/CollisionBasic.js +826 -0
  39. package/src/components/CollisionFilter.js +74 -0
  40. package/src/components/CollisionGroup.js +448 -0
  41. package/src/components/CollisionTiles.js +608 -0
  42. package/src/components/ComponentSwitcher.js +173 -0
  43. package/src/components/ControllerInput.js +65 -0
  44. package/src/components/Counter.js +165 -0
  45. package/src/components/EntityCamera.js +215 -0
  46. package/src/components/EntityContainer.js +549 -0
  47. package/src/components/EntityController.js +541 -0
  48. package/src/components/HandlerCamera.js +1052 -0
  49. package/src/components/HandlerCollision.js +1318 -0
  50. package/src/components/HandlerController.js +291 -0
  51. package/src/components/HandlerLogic.js +394 -0
  52. package/src/components/HandlerRender.js +217 -0
  53. package/src/components/Interactive.js +502 -0
  54. package/src/components/LevelBuilder.js +524 -0
  55. package/src/components/LogicAngularMovement.js +154 -0
  56. package/src/components/LogicAttachment.js +265 -0
  57. package/src/components/LogicButton.js +466 -0
  58. package/src/components/LogicCarrier.js +39 -0
  59. package/src/components/LogicDestroyMe.js +58 -0
  60. package/src/components/LogicDirectionalMovement.js +325 -0
  61. package/src/components/LogicDragDrop.js +371 -0
  62. package/src/components/LogicImpactLaunch.js +144 -0
  63. package/src/components/LogicPacingPlatform.js +64 -0
  64. package/src/components/LogicPortable.js +112 -0
  65. package/src/components/LogicPortal.js +115 -0
  66. package/src/components/LogicPushable.js +98 -0
  67. package/src/components/LogicRebounder.js +136 -0
  68. package/src/components/LogicRegionSpawner.js +139 -0
  69. package/src/components/LogicRotationalMovement.js +205 -0
  70. package/src/components/LogicSpawner.js +159 -0
  71. package/src/components/LogicStateMachine.js +382 -0
  72. package/src/components/LogicSwitch.js +77 -0
  73. package/src/components/LogicTeleportee.js +68 -0
  74. package/src/components/LogicTeleporter.js +93 -0
  75. package/src/components/LogicTimer.js +178 -0
  76. package/src/components/LogicWindUpRacer.js +179 -0
  77. package/src/components/Motion.js +371 -0
  78. package/src/components/Mover.js +566 -0
  79. package/src/components/Node.js +289 -0
  80. package/src/components/NodeMap.js +295 -0
  81. package/src/components/NodeResident.js +636 -0
  82. package/src/components/Orientation.js +697 -0
  83. package/src/components/RandomEvents.js +73 -0
  84. package/src/components/RelativePosition.js +204 -0
  85. package/src/components/RelayFamily.js +106 -0
  86. package/src/components/RelayGame.js +53 -0
  87. package/src/components/RelayLinker.js +94 -0
  88. package/src/components/RelayParent.js +57 -0
  89. package/src/components/RelaySelf.js +55 -0
  90. package/src/components/Render.js +178 -0
  91. package/src/components/RenderAnimator.js +275 -0
  92. package/src/components/RenderContainer.js +646 -0
  93. package/src/components/RenderDebug.js +319 -0
  94. package/src/components/RenderDestroyMe.js +59 -0
  95. package/src/components/RenderLottie.js +149 -0
  96. package/src/components/RenderProgress.js +120 -0
  97. package/src/components/RenderSpine.js +833 -0
  98. package/src/components/RenderSprite.js +527 -0
  99. package/src/components/RenderText.js +147 -0
  100. package/src/components/RenderTiles.js +1391 -0
  101. package/src/components/SceneChanger.js +128 -0
  102. package/src/components/TiledLoader.js +1451 -0
  103. package/src/components/Timeline.js +314 -0
  104. package/src/components/Tutorial.js +267 -0
  105. package/src/components/Tween.js +296 -0
  106. package/src/components/VoiceOver.js +373 -0
  107. package/src/components/XHR.js +129 -0
  108. package/src/components/index.js +79 -0
  109. package/src/factory.js +305 -0
  110. package/src/index.js +159 -0
  111. package/src/mixins/PIXI.Graphics.js +41 -0
  112. package/src/platypus.css +68 -0
  113. package/src/sayHello.js +50 -0
  114. package/src/shapes/Capsule.js +74 -0
  115. package/src/shapes/Circle.js +43 -0
  116. package/src/shapes/Ellipse.js +117 -0
  117. package/src/shapes/Point.js +191 -0
  118. package/src/shapes/Polygon.js +112 -0
  119. package/src/shapes/Polyline.js +97 -0
  120. package/src/shapes/Rectangle.js +78 -0
  121. package/src/shapes/RoundedRectangle.js +33 -0
  122. package/src/shapes/Segment.js +346 -0
  123. package/src/shapes/adjustedXY.js +19 -0
  124. package/src/shapes/castFromBox2D.js +92 -0
  125. package/src/shapes/castFromObject.js +53 -0
  126. package/src/shapes/castFromPixiGraphics.js +6 -0
  127. package/src/shapes/castFromPixiShape.js +89 -0
  128. package/src/shapes/castToBox2D.js +190 -0
  129. package/src/shapes/castToPixiGraphics.js +100 -0
  130. package/src/shapes/castToPixiShape.js +61 -0
  131. package/src/shapes/checkPointsMap.js +313 -0
  132. package/src/shapes/index.js +35 -0
  133. package/src/utils/array.js +73 -0
  134. package/src/utils/string.js +39 -0
  135. package/lib/243.platypus.mjs +0 -1
  136. package/lib/platypus.mjs +0 -1
@@ -0,0 +1,314 @@
1
+ /* global platypus */
2
+ import {arrayCache, greenSplice} from '../utils/array.js';
3
+ import Data from '../Data.js';
4
+ import createComponentClass from '../factory.js';
5
+ import TimeEventList from '../TimeEventList.js';
6
+
7
+ const
8
+ pause = function () {
9
+ this.active--;
10
+ },
11
+ play = function () {
12
+ this.active++;
13
+ },
14
+ updateLogic = function (tick) {
15
+ const
16
+ {executionFlow, owner, timelineInstances} = this,
17
+ delta = tick.delta;
18
+ let i = timelineInstances.length,
19
+ removalOccurred = false;
20
+
21
+ while (i--) {
22
+ const
23
+ instance = timelineInstances[i];
24
+
25
+ if (instance.remove) {
26
+ greenSplice(timelineInstances, i);
27
+ instance.timeline.recycle();
28
+ instance.recycle();
29
+ removalOccurred = true;
30
+ } else if (instance.active) {
31
+ if (instance.timeline.list.length === 0) {
32
+ greenSplice(timelineInstances, i);
33
+ instance.timeline.recycle();
34
+ instance.recycle();
35
+ removalOccurred = true;
36
+ } else {
37
+ this.progressTimeline(instance, delta);
38
+ }
39
+ }
40
+ }
41
+
42
+ if (timelineInstances.length) {
43
+ if (removalOccurred && executionFlow === 'serial') {
44
+ const
45
+ timeline = timelineInstances[0];
46
+
47
+ if (!timeline.active) {
48
+ timeline.play();
49
+ }
50
+ }
51
+ owner.triggerEvent('timeline-progress', timelineInstances);
52
+ }
53
+ };
54
+
55
+ export default createComponentClass(/** @lends platypus.components.Timeline.prototype */{
56
+
57
+ id: 'Timeline',
58
+
59
+ properties: {
60
+ /**
61
+ * Sets the execution flow if multiple timelines are triggered.
62
+ * * "parallel" - Each timeline begins immediately when triggered and does not directly affect other timelines.
63
+ * * "serial" - A timeline doesn't start if another timeline is currently active: it will append itself to a queue of timelines and run eventually.
64
+ * * "exclusive" - Timeline begins immediately and will stop any other active timeline.
65
+ * * "tentative" - Timeline begins if no other timelines are active, otherwise it is ignored.
66
+ */
67
+ executionFlow: 'parallel',
68
+
69
+ /**
70
+ * Defines the set of timelines. Triggering the key for one of the events will run the timeline. A timeline can contain three different types integers >= 0, strings, and objects. Integers are interpreted as waits and define
71
+ * pauses between events. Strings are intepreted as event calls. Objects can contain several parameters: entity, event, message. The entity is the id of the entity that
72
+ * the event will be fired on. The event can be a string or array. If a string, it will call that event on the entity or owner. If an array, the value will be passed
73
+ * to the event handling system.
74
+ *
75
+ * "timelines": {
76
+ * "sample-timeline-1": [
77
+ * 500,
78
+ * "sample-event",
79
+ * {"event": "sample-event", "message": "sample-message"},
80
+ * {"entity": "entity-id-to-trigger-event-on", "event": "sample-event"},
81
+ * {"event": ["sample-event", "sample-event-2", {"event": "sample-event-3", "message": "sample-message"}]},
82
+ * ],
83
+ * "sample-timeline-2": [
84
+ * 200,
85
+ * "sample-event"
86
+ * ]
87
+ * }
88
+ *
89
+ * @property timelines
90
+ * @type Object
91
+ * @default {}
92
+ */
93
+ timelines: {}
94
+ },
95
+
96
+ /**
97
+ * Timeline enables the scheduling of events based on a linear timeline
98
+ *
99
+ * @memberof platypus.components
100
+ * @uses platypus.Component
101
+ * @constructs
102
+ * @listens platypus.Entity#handle-logic
103
+ * @listens platypus.Entity#stop-active-timelines
104
+ */
105
+ initialize: function () {
106
+ const
107
+ keys = Object.keys(this.timelines),
108
+ {length} = keys;
109
+
110
+ this.timelineInstances = arrayCache.setUp();
111
+
112
+ for (let i = 0; i < length; i++) {
113
+ const
114
+ timelineId = keys[i];
115
+
116
+ this.addTimeline(timelineId, this.timelines[timelineId]);
117
+ }
118
+ },
119
+
120
+ events: {
121
+ "handle-logic": updateLogic,
122
+
123
+ "pause-timelines": function () {
124
+ this.timelineInstances.forEach((timeline) => {
125
+ if (timeline.active) {
126
+ timeline.pause();
127
+ }
128
+ });
129
+ },
130
+
131
+ "play-timelines": function () {
132
+ const
133
+ {executionFlow, timelineInstances} = this;
134
+
135
+ if (executionFlow === 'serial') {
136
+ if (timelineInstances.length) {
137
+ const
138
+ timeline = timelineInstances[0];
139
+
140
+ if (!timeline.active) {
141
+ timeline.play();
142
+ }
143
+ }
144
+ } else {
145
+ timelineInstances.forEach((timeline) => {
146
+ if (!timeline.active) {
147
+ timeline.play();
148
+ }
149
+ });
150
+ }
151
+ },
152
+
153
+ /**
154
+ * Stops active timelines.
155
+ *
156
+ * @event platypus.Entity#stop-active-timelines
157
+ */
158
+ "stop-active-timelines": function () {
159
+ const
160
+ instances = this.timelineInstances;
161
+ let i = instances.length;
162
+
163
+ while (i--) {
164
+ if (instances[i].active) {
165
+ instances[i].remove = true;
166
+ }
167
+ }
168
+ },
169
+
170
+ /**
171
+ * Stops all timelines.
172
+ *
173
+ * @event platypus.Entity#stop-all-timelines
174
+ */
175
+ "stop-all-timelines": function () {
176
+ const
177
+ instances = this.timelineInstances;
178
+ let i = instances.length;
179
+
180
+ while (i--) {
181
+ instances[i].remove = true;
182
+ }
183
+ },
184
+
185
+ /**
186
+ * Add a timeline dynamically.
187
+ *
188
+ * @event platypus.Entity#add-timeline
189
+ * @param eventId {String} The event to listen for to trigger the timeline.
190
+ * @param timeline {Array} The array of timeline data.
191
+ */
192
+ "add-timeline": function (eventId, timeline) {
193
+ this.addTimeline(eventId, timeline);
194
+ },
195
+
196
+ /**
197
+ * Play a timeline dynamically.
198
+ *
199
+ * @event platypus.Entity#start-timeline
200
+ * @param timeline {Array} The array of timeline data.
201
+ */
202
+ "start-timeline": function (timeline) {
203
+ this.startTimeline(timeline);
204
+ }
205
+ },
206
+
207
+ methods: {
208
+ addTimeline: function (eventId, timeline) {
209
+ this.addEventListener(eventId, () => this.startTimeline(timeline));
210
+ },
211
+ createTimeStampedTimeline: function (timeline, active = 1) {
212
+ const
213
+ timeStampedTimeline = TimeEventList.setUp(timeline);
214
+
215
+ return Data.setUp(
216
+ "timeline", timeStampedTimeline,
217
+ "time", 0,
218
+ "total", timeStampedTimeline.getDuration(),
219
+ "active", 1,
220
+ "pause", pause,
221
+ "play", play,
222
+ "remove", false
223
+ );
224
+ },
225
+ startTimeline (timeline) {
226
+ const
227
+ {executionFlow, timelineInstances} = this;
228
+
229
+ switch (executionFlow) {
230
+ case 'serial':
231
+ timelineInstances.push(this.createTimeStampedTimeline(timeline), timelineInstances.some(({active}) => active) ? 0 : 1);
232
+ return true;
233
+ case 'exclusive':
234
+ timelineInstances.forEach((instance) => instance.remove = true);
235
+ timelineInstances.push(this.createTimeStampedTimeline(timeline));
236
+ return true;
237
+ case 'tentative':
238
+ if (!timelineInstances.some(({active}) => active)) {
239
+ timelineInstances.push(this.createTimeStampedTimeline(timeline));
240
+ return true;
241
+ }
242
+ return false;
243
+ default:
244
+ timelineInstances.push(this.createTimeStampedTimeline(timeline));
245
+ return true;
246
+ }
247
+ },
248
+ progressTimeline (instance, delta) {
249
+ const
250
+ timeline = instance.timeline;
251
+
252
+ instance.time += delta;
253
+
254
+ //Go through the timeline playing events if the time has progressed far enough to trigger them.
255
+ timeline.getEvents(instance.time).forEach((entry) => {
256
+ const
257
+ {event, entity} = entry;
258
+
259
+ if (typeof event === 'function') {
260
+ event(this.owner, instance);
261
+ } else {
262
+ let triggerOn = this.owner;
263
+
264
+ if (entity) {
265
+ if (typeof entity === 'string') {
266
+ if (this.owner.getEntityById) {
267
+ triggerOn = this.owner.getEntityById(entity);
268
+ } else {
269
+ triggerOn = this.owner.parent.getEntityById(entity);
270
+ }
271
+ } else {
272
+ triggerOn = entity; // Maybe it's an Entity.
273
+ }
274
+
275
+ if (!triggerOn) {
276
+ platypus.debug.warn('No entity of that id');
277
+ triggerOn = this.owner;
278
+ }
279
+ }
280
+
281
+ triggerOn.trigger(entry);
282
+ }
283
+
284
+ entry.recycle();
285
+ });
286
+ },
287
+ destroy: function () {
288
+ const
289
+ instances = this.timelineInstances;
290
+ let i = instances.length;
291
+
292
+ while (i--) {
293
+ const
294
+ instance = instances[i];
295
+
296
+ instance.timeline.recycle();
297
+ instance.recycle();
298
+ }
299
+ arrayCache.recycle(instances);
300
+ this.timelineInstances = null;
301
+ }
302
+ },
303
+
304
+ publicMethods: {
305
+ // asynchronous wait that incorporates ticker pauses.
306
+ wait (time) {
307
+ return new Promise ((resolve, reject) => {
308
+ if (!this.startTimeline([time, resolve])) {
309
+ reject();
310
+ }
311
+ });
312
+ }
313
+ }
314
+ });
@@ -0,0 +1,267 @@
1
+ /* global platypus */
2
+ import createComponentClass from '../factory.js';
3
+ import {greenSlice} from '../utils/array.js';
4
+
5
+ const
6
+ entityAdded = function (entity) {
7
+ if (entity.type in this.watchedEntities) {
8
+ this.watchedEntities[entity.type].push(entity);
9
+ }
10
+ },
11
+ entityRemoved = function (entity) {
12
+ const
13
+ watchedEntities = this.watchedEntities[entity.type];
14
+
15
+ for (let x = watchedEntities.length - 1; x >= 0; x--) {
16
+ if (watchedEntities[x] === entity) {
17
+ watchedEntities.splice(x, 1);
18
+ break;
19
+ }
20
+ }
21
+ },
22
+ updateLogic = function (tick) {
23
+ const
24
+ delta = tick.delta;
25
+ let toPlay = null,
26
+ toPlayIndex = -1;
27
+
28
+ for (let x = 0; x < this.tutorials.length; x++) {
29
+ const
30
+ tut = this.tutorials[x];
31
+ let keepChecking = false;
32
+
33
+ if (!this.playing && this.theQueue.length === 0) {
34
+ keepChecking = true;
35
+ } else if ((!this.playing && this.theQueue.length > 0) && (tut.priority > this.theQueue[0].priority)) {
36
+ keepChecking = true;
37
+ } else if (this.playing && (this.playing.priority < tut.priority)) {
38
+ keepChecking = true;
39
+ } else if (tut.queue) {
40
+ keepChecking = true;
41
+ }
42
+
43
+ if (!keepChecking) {
44
+ continue;
45
+ }
46
+
47
+ if (this.checkRequirements(tut.requirements)) {
48
+ if (tut.replayDelay && tut.replayDelayTimer > 0) {
49
+ tut.replayDelayTimer -= delta;
50
+ if (tut.replayDelayTimer > 0) {
51
+ continue;
52
+ }
53
+ }
54
+
55
+ if (!toPlay || toPlay.priority < tut.priority) {
56
+ //TML - If we only have one item we try to play, then we may prevent certain audio from playing if it's only valid for a single tick.
57
+ toPlay = tut;
58
+ toPlayIndex = x;
59
+ }
60
+ }
61
+ }
62
+
63
+ if (toPlay) {
64
+ const
65
+ tutorial = this.tutorials.splice(toPlayIndex, 1)[0];
66
+
67
+ if (this.playing) {
68
+ if (tutorial.priority > this.playing.priority) {
69
+ /**
70
+ * On receiving this message, audio will stop playing.
71
+ *
72
+ * @event platypus.Entity#stop-audio
73
+ * @param audioId {String} If an audioId is provided, that particular sound instance is stopped. Otherwise all audio is stopped.
74
+ */
75
+ this.owner.triggerEvent('stop-audio');
76
+ this.play(tutorial);
77
+ } else {
78
+ this.queue(tutorial);
79
+ }
80
+ } else if (this.theQueue.length > 0) {
81
+ if (tutorial.priority > this.theQueue[0].priority) {
82
+ this.play(tutorial);
83
+ } else {
84
+ this.play(this.theQueue.splice(0, 1)[0]);
85
+ this.queue(tutorial);
86
+ }
87
+ } else {
88
+ this.play(tutorial);
89
+ }
90
+ } else if (!this.playing && this.theQueue.length > 0) {
91
+ this.play(this.theQueue.splice(0, 1)[0]);
92
+ }
93
+ };
94
+
95
+ export default createComponentClass(/** @lends platypus.components.Tutorial.prototype */{
96
+
97
+ id: 'Tutorial',
98
+
99
+ properties: {
100
+
101
+ /* An array of tutorial definition objects. These objects define what events will be called by the tutorial, the priority of the tutorial, how often and how many times it will fire, the required conditions for it to fire, and more.
102
+ *
103
+ * "tutorialDefs": [
104
+ * {
105
+ * "events": ["example-vo-event"], //An Array of Strings. Defines the events to fire when all the conditions for this tutorial are met. If there are multiple events, one is chosen at random. All events in the array will play before any repeat.
106
+ * "priority": 5, //The priorioty of the tutorial. Higher numbered tutorials interrupt lower numbered. Default: 0.
107
+ * "queue": true, //Will the tutorial queue up if played while another tutorial is playing? Default: false.
108
+ * "timesToReplay": 3, //The number of times a tutorial will replay. Set to 0 to make a tutorial play only once. Default: Infinity.
109
+ * "replayDelay": 10000, //While the conditions are met, the tutorial will replay at this interval in milliseconds. If set to null, it will not repeat. Default: null.
110
+ * "level": "example-level", //Tutorial will only play when this level is the currently loaded level.
111
+ * "requirements": { //The requirements is a collection of entities types that are watched by the tutorial to determine if the conditions to play this tutorial are true.
112
+ * "example-entity-type": ["example-entity-state"] //The requirements is a set of key-value pairs. The keys are entity types that the tutorial will watch. The values are arrays of states of that entity type which must be true for the tutorial to play.
113
+ * }
114
+ * }
115
+ * ]
116
+ *
117
+ * @property tutorialDefs
118
+ * @type Array [Object]
119
+ * @default []
120
+ */
121
+ "tutorialDefs": []
122
+ },
123
+
124
+ /**
125
+ * Tutorial provides a framework for playing tutorials. It allows the user to define things such as under what conditions tutorials will play, how often they play, and which tutorials have priority.
126
+ *
127
+ * @memberof platypus.components
128
+ * @uses platypus.Component
129
+ * @constructs
130
+ * @listens platypus.Entity#child-entity-added
131
+ * @listens platypus.Entity#child-entity-removed
132
+ * @listens platypus.Entity#handle-logic
133
+ * @listens platypus.Entity#peer-entity-added
134
+ * @listens platypus.Entity#peer-entity-removed
135
+ * @listens platypus.Entity#sequence-complete
136
+ * @fires platypus.Entity#stop-audio
137
+ */
138
+ initialize: function () {
139
+ this.playing = null;
140
+ this.theQueue = [];
141
+ this.watchedEntities = {};
142
+ this.tutorials = [];
143
+
144
+
145
+ for (let x = 0; x < this.tutorialDefs.length; x++) {
146
+ const
147
+ tutDef = this.tutorialDefs[x];
148
+
149
+ if (!tutDef.events) {
150
+ platypus.debug.warn("Tutorial definition lacks events.");
151
+ } else {
152
+ const
153
+ tutorial = {
154
+ events: greenSlice(tutDef.events),
155
+ originalEvents: greenSlice(tutDef.events),
156
+ priority: tutDef.priority || 0,
157
+ queue: tutDef.queue || false,
158
+ timesToReplay: (typeof tutDef.timesToReplay === 'number') ? tutDef.timesToReplay : Infinity,
159
+ replayDelay: tutDef.replayDelay || null,
160
+ replayDelayTimer: tutDef.replayDelay || null,
161
+ level: tutDef.level,
162
+ requirements: {}
163
+ },
164
+ keys = Object.keys(tutDef.requirements),
165
+ {length} = keys;
166
+
167
+ for (let i = 0; i < length; i++) {
168
+ const
169
+ entityType = keys[i];
170
+
171
+ tutorial.requirements[entityType] = greenSlice(tutDef.requirements[entityType]);
172
+ if (!this.watchedEntities[entityType]) {
173
+ this.watchedEntities[entityType] = [];
174
+ }
175
+ }
176
+ this.tutorials.push(tutorial);
177
+ }
178
+ }
179
+ },
180
+
181
+ events: {// These are messages that this component listens for
182
+ "child-entity-added": entityAdded,
183
+
184
+ "peer-entity-added": entityAdded,
185
+
186
+ "child-entity-removed": entityRemoved,
187
+
188
+ "peer-entity-removed": entityRemoved,
189
+
190
+ "handle-logic": updateLogic,
191
+
192
+ "sequence-complete": function () {
193
+ if (this.playing.timesToReplay >= 0) {
194
+ this.tutorials.push(this.playing);
195
+ }
196
+ this.playing = null;
197
+ }
198
+ },
199
+
200
+ methods: {// These are internal methods that are invoked by this component.
201
+ play: function (tutorial) {
202
+ this.playing = tutorial;
203
+ if (this.playing.events.length === 0) {
204
+ this.playing.events = greenSlice(this.playing.originalEvents);
205
+ }
206
+
207
+ this.owner.triggerEvent(this.playing.events.splice(Math.floor(Math.random() * this.playing.events.length), 1)[0]);
208
+
209
+ tutorial.timesToReplay -= 1;
210
+ tutorial.replayDelayTimer = tutorial.replayDelay;
211
+ },
212
+ queue: function (tutorial) {
213
+ let added = false;
214
+
215
+ for (let x = 0; x < this.theQueue.length; x++) {
216
+ if (this.theQueue[x].priority < tutorial.priority) {
217
+ this.theQueue.splice(x, 0, tutorial);
218
+ added = true;
219
+ break;
220
+ }
221
+ }
222
+
223
+ if (!added) {
224
+ this.theQueue.push(tutorial);
225
+ }
226
+ },
227
+ checkRequirements: function (requirements) {
228
+ const
229
+ keys = Object.keys(requirements),
230
+ {length} = keys;
231
+
232
+ //Going through the types of entities
233
+ for (let i = 0; i < length; i++) {
234
+ const
235
+ entityType = keys[i],
236
+ states = requirements[entityType];
237
+ let metRequirement = true;
238
+
239
+ for (let y = this.watchedEntities[entityType].length - 1; y >= 0; y--) { //Going through the instances of those entities
240
+ const
241
+ anEntity = this.watchedEntities[entityType][y];
242
+
243
+ metRequirement = true;
244
+ for (let x = 0; x < states.length; x++) { //Going through the required states of an entity instance
245
+ if (!anEntity.state.get(states[x])) {
246
+ metRequirement = false;
247
+ break;
248
+ }
249
+ }
250
+ if (metRequirement) {
251
+ break;
252
+ }
253
+ }
254
+ if (!metRequirement) {
255
+ return false;
256
+ }
257
+ }
258
+ return true;
259
+ },
260
+ destroy: function () {
261
+ this.watchedEntities = null;
262
+ this.theQueue = null;
263
+ this.playing = null;
264
+ this.tutorials = null;
265
+ }
266
+ }
267
+ });