@@ -49,10 +49,13 @@ WillOWisp::WillOWisp(const ReaderMapping& reader) :
49
49
m_color(0 , 1 , 0 ),
50
50
m_starting_node(0 )
51
51
{
52
- if (Editor::is_active ()) {
52
+ if (Editor::is_active ())
53
+ {
53
54
reader.get (" sector" , m_target_sector);
54
55
reader.get (" spawnpoint" , m_target_spawnpoint);
55
- } else {
56
+ }
57
+ else
58
+ {
56
59
reader.get (" sector" , m_target_sector, DEFAULT_SECTOR_NAME.c_str ());
57
60
reader.get (" spawnpoint" , m_target_spawnpoint, DEFAULT_SPAWNPOINT_NAME.c_str ());
58
61
}
@@ -62,16 +65,16 @@ WillOWisp::WillOWisp(const ReaderMapping& reader) :
62
65
reader.get (" vanish-range" , m_vanish_range, VANISH_RANGE);
63
66
reader.get (" hit-script" , m_hit_script, " " );
64
67
65
- bool running;
66
- if ( ! reader.get (" running" , running)) running = false ;
68
+ bool running = false ;
69
+ reader.get (" running" , running);
67
70
68
71
std::vector<float > color;
69
72
if (reader.get (" color" , color))
70
73
{
71
74
m_color = Color (color);
72
75
}
73
76
74
- reader.get (" starting-node" , m_starting_node, 0 . f );
77
+ reader.get (" starting-node" , m_starting_node, 0 );
75
78
76
79
init_path (reader, running);
77
80
@@ -88,14 +91,60 @@ WillOWisp::WillOWisp(const ReaderMapping& reader) :
88
91
set_action (" idle" );
89
92
}
90
93
94
+ void
95
+ WillOWisp::synchronize_position_from_path ()
96
+ {
97
+ if (!has_valid_path ())
98
+ return ;
99
+
100
+ const auto & nodes = get_path ()->get_nodes ();
101
+ if (nodes.empty ())
102
+ return ;
103
+
104
+ const int size = static_cast <int >(nodes.size ());
105
+
106
+ if (m_starting_node < 0 )
107
+ {
108
+ m_starting_node = 0 ;
109
+ }
110
+ if (m_starting_node >= size)
111
+ {
112
+ m_starting_node = size - 1 ;
113
+ }
114
+
115
+ set_pos (m_path_handle.get_pos (m_col.m_bbox .get_size (), nodes[m_starting_node].position ));
116
+ }
117
+
91
118
void
92
119
WillOWisp::finish_construction ()
93
120
{
94
- if (get_walker () && get_walker ()->is_running ()) {
95
- m_mystate = STATE_PATHMOVING_TRACK;
121
+ if (!get_path ())
122
+ init_path_pos (m_col.m_bbox .p1 ());
123
+
124
+ synchronize_position_from_path ();
125
+
126
+ if (has_valid_path ())
127
+ {
128
+ const auto & nodes = get_path ()->get_nodes ();
129
+ if (!nodes.empty ())
130
+ {
131
+ get_walker ()->jump_to_node (m_starting_node);
132
+
133
+ if (get_walker ()->is_running ())
134
+ {
135
+ m_mystate = STATE_PATHMOVING_TRACK;
136
+ get_walker ()->start_moving ();
137
+ }
138
+ }
96
139
}
97
140
}
98
141
142
+ void
143
+ WillOWisp::editor_update ()
144
+ {
145
+ synchronize_position_from_path ();
146
+ }
147
+
99
148
void
100
149
WillOWisp::after_editor_set ()
101
150
{
@@ -105,72 +154,91 @@ WillOWisp::after_editor_set()
105
154
m_color.green * 0 .2f ,
106
155
m_color.blue * 0 .2f ));
107
156
m_sprite->set_color (m_color);
157
+
158
+ if (Editor::is_active ())
159
+ {
160
+ synchronize_position_from_path ();
161
+ }
108
162
}
109
163
110
164
void
111
165
WillOWisp::active_update (float dt_sec)
112
166
{
113
- if (Editor::is_active () && get_path () && get_path ()->is_valid ()) {
167
+ if (Editor::is_active () && get_path () && get_path ()->is_valid ())
168
+ {
114
169
get_walker ()->update (dt_sec);
115
170
set_pos (get_walker ()->get_pos (m_col.m_bbox .get_size (), m_path_handle));
116
171
return ;
117
172
}
118
173
119
174
auto player = get_nearest_player ();
120
175
if (!player) return ;
121
- Vector p1 = m_col.m_bbox .get_middle ();
122
- Vector p2 = player->get_bbox ().get_middle ();
176
+ const Vector p1 = m_col.m_bbox .get_middle ();
177
+ const Vector p2 = player->get_bbox ().get_middle ();
123
178
Vector dist = (p2 - p1);
124
179
125
- switch (m_mystate) {
180
+ switch (m_mystate)
181
+ {
126
182
case STATE_STOPPED:
127
183
break ;
128
-
129
184
case STATE_IDLE:
130
- if (glm::length (dist) <= m_track_range) {
185
+ if (glm::length (dist) <= m_track_range)
186
+ {
131
187
m_mystate = STATE_TRACKING;
132
188
}
133
189
break ;
134
-
135
190
case STATE_TRACKING:
136
- if (glm::length (dist) > m_vanish_range) {
191
+ if (glm::length (dist) > m_vanish_range)
192
+ {
137
193
vanish ();
138
- } else if (glm::length (dist) >= 1 ) {
194
+ }
195
+ else if (glm::length (dist) >= 1 )
196
+ {
139
197
Vector dir_ = glm::normalize (dist);
140
198
m_col.set_movement (dir_ * dt_sec * m_flyspeed);
141
- } else {
199
+ }
200
+ else
201
+ {
142
202
/* We somehow landed right on top of the player without colliding.
143
203
* Sit tight and avoid a division by zero. */
144
204
}
145
205
m_sound_source->set_position (get_pos ());
146
206
break ;
147
-
148
207
case STATE_WARPING:
149
- if (m_sprite->animation_done ()) {
208
+ m_col.set_movement (Vector (0 .0f , 0 .0f ));
209
+ if (m_sprite->animation_done ())
210
+ {
150
211
remove_me ();
151
212
}
152
213
break ;
153
-
154
- case STATE_VANISHING: {
214
+ case STATE_VANISHING:
215
+ {
155
216
Vector dir_ = glm::normalize (dist);
156
217
m_col.set_movement (dir_ * dt_sec * m_flyspeed);
157
- if (m_sprite->animation_done ()) {
218
+ if (m_sprite->animation_done ())
219
+ {
158
220
remove_me ();
159
221
}
160
222
break ;
161
223
}
162
224
163
225
case STATE_PATHMOVING:
164
226
case STATE_PATHMOVING_TRACK:
165
- if (get_walker () == nullptr )
227
+ if (!PathObject::has_valid_path ())
228
+ {
229
+ m_mystate = STATE_IDLE;
166
230
return ;
231
+ }
232
+
167
233
get_walker ()->update (dt_sec);
234
+
168
235
m_col.set_movement (get_walker ()->get_pos (m_col.m_bbox .get_size (), m_path_handle) - get_pos ());
169
- if (m_mystate == STATE_PATHMOVING_TRACK && glm::length (dist) <= m_track_range) {
236
+ if (m_mystate == STATE_PATHMOVING_TRACK && glm::length (dist) <= m_track_range)
237
+ {
170
238
m_mystate = STATE_TRACKING;
171
239
}
172
- break ;
173
240
241
+ break ;
174
242
default :
175
243
assert (false );
176
244
}
@@ -195,7 +263,8 @@ WillOWisp::deactivate()
195
263
{
196
264
m_sound_source.reset (nullptr );
197
265
198
- switch (m_mystate) {
266
+ switch (m_mystate)
267
+ {
199
268
case STATE_STOPPED:
200
269
case STATE_IDLE:
201
270
case STATE_PATHMOVING:
@@ -225,7 +294,8 @@ WillOWisp::vanish()
225
294
}
226
295
227
296
bool
228
- WillOWisp::collides (MovingObject& other, const CollisionHit& ) const {
297
+ WillOWisp::collides (MovingObject& other, const CollisionHit&) const
298
+ {
229
299
auto lantern = dynamic_cast <Lantern*>(&other);
230
300
231
301
// vv 'xor'
@@ -239,7 +309,8 @@ WillOWisp::collides(MovingObject& other, const CollisionHit& ) const {
239
309
}
240
310
241
311
HitResponse
242
- WillOWisp::collision_player (Player& player, const CollisionHit& ) {
312
+ WillOWisp::collision_player (Player& player, const CollisionHit&)
313
+ {
243
314
if (player.is_invincible ())
244
315
return ABORT_MOVE;
245
316
@@ -249,9 +320,12 @@ WillOWisp::collision_player(Player& player, const CollisionHit& ) {
249
320
m_mystate = STATE_WARPING;
250
321
set_action (" warping" , 1 );
251
322
252
- if (!m_hit_script.empty ()) {
323
+ if (!m_hit_script.empty ())
324
+ {
253
325
Sector::get ().run_script (m_hit_script, " hit-script" );
254
- } else {
326
+ }
327
+ else
328
+ {
255
329
GameSession::current ()->respawn (m_target_sector, m_target_spawnpoint);
256
330
}
257
331
SoundManager::current ()->play (" sounds/warp.wav" , get_pos ());
@@ -262,6 +336,15 @@ WillOWisp::collision_player(Player& player, const CollisionHit& ) {
262
336
void
263
337
WillOWisp::goto_node (int node_idx)
264
338
{
339
+ // If the wisp is following a player refuse to "snap back" to the path it was supposed to follow.
340
+ if (m_mystate == STATE_TRACKING)
341
+ return ;
342
+
343
+ if (!has_valid_path ())
344
+ {
345
+ return ;
346
+ }
347
+
265
348
PathObject::goto_node (node_idx);
266
349
267
350
if (m_mystate != STATE_PATHMOVING && m_mystate != STATE_PATHMOVING_TRACK)
@@ -277,22 +360,35 @@ WillOWisp::set_state(const std::string& new_state)
277
360
m_mystate = STATE_IDLE;
278
361
else if (new_state == " move_path" )
279
362
{
280
- m_mystate = STATE_PATHMOVING;
281
- if (get_walker ())
282
- get_walker ()->start_moving ();
363
+ if (has_valid_path ())
364
+ {
365
+ m_mystate = STATE_PATHMOVING;
366
+ if (get_walker ())
367
+ get_walker ()->start_moving ();
368
+ }
369
+ else
370
+ {
371
+ m_mystate = STATE_IDLE;
372
+ }
283
373
}
284
374
else if (new_state == " move_path_track" )
285
375
{
286
- m_mystate = STATE_PATHMOVING_TRACK;
287
- if (get_walker ())
288
- get_walker ()->start_moving ();
376
+ if (has_valid_path ())
377
+ {
378
+ m_mystate = STATE_PATHMOVING_TRACK;
379
+ if (get_walker ()) get_walker ()->start_moving ();
380
+ }
381
+ else
382
+ {
383
+ m_mystate = STATE_IDLE;
384
+ }
289
385
}
290
386
else if (new_state == " normal" )
291
387
m_mystate = STATE_IDLE;
292
388
else if (new_state == " vanish" )
293
389
vanish ();
294
390
else
295
- log_warning << " Cannot set unknown Will-O-Wisp state: '" << new_state << " '." << std::endl;
391
+ log_warning << " Cannot set an unknown WillOWisp state: '" << new_state << " '." << std::endl;
296
392
}
297
393
298
394
ObjectSettings
@@ -309,27 +405,34 @@ WillOWisp::get_settings()
309
405
result.add_path_ref (_ (" Path" ), *this , get_path_ref (), " path-ref" );
310
406
result.add_int (_ (" Starting Node" ), &m_starting_node, " starting-node" , 0 , 0U );
311
407
result.add_color (_ (" Color" ), &m_color, " color" );
312
- if (get_path ())
408
+
409
+ if (get_path_gameobject () && get_path ())
313
410
{
314
- result.add_bool (_ (" Adapt Speed" ), &get_path ()->m_adapt_speed , {}, {});
411
+ result.add_walk_mode (_ (" Path Mode" ), &get_path ()->m_mode , {}, {});
412
+ result.add_bool (_ (" Adapt Speed" ), &get_path ()->m_adapt_speed , " adapt-speed" , {});
315
413
result.add_path_handle (_ (" Handle" ), m_path_handle, " handle" );
414
+ result.add_bool (_ (" Running" ), &get_walker ()->m_running , " running" , false , 0 );
316
415
}
317
416
318
- result.reorder ({" sector " , " spawnpoint " , " flyspeed " , " track-range " , " hit-script " , " vanish-range " , " name " , " path-ref " , " width " , " height " , " x " , " y " });
417
+ result.reorder ({ " name " , " x " , " y " , " width " , " height " , " path-ref " , " starting-node " , " running " , " path-walk-mode " , " adapt-speed " , " handle " , " flyspeed " , " track-range " , " vanish-range " , " sector " , " spawnpoint " , " hit-script " , " color " });
319
418
320
419
return result;
321
420
}
322
421
323
- void WillOWisp::stop_looping_sounds ()
422
+ void
423
+ WillOWisp::stop_looping_sounds ()
324
424
{
325
- if (m_sound_source) {
425
+ if (m_sound_source)
426
+ {
326
427
m_sound_source->stop ();
327
428
}
328
429
}
329
430
330
- void WillOWisp::play_looping_sounds ()
431
+ void
432
+ WillOWisp::play_looping_sounds ()
331
433
{
332
- if (m_sound_source) {
434
+ if (m_sound_source)
435
+ {
333
436
m_sound_source->play ();
334
437
}
335
438
}
338
441
WillOWisp::move_to (const Vector& pos)
339
442
{
340
443
Vector shift = pos - m_col.m_bbox .p1 ();
341
- if (get_path ()) {
444
+ if (get_path ())
445
+ {
342
446
get_path ()->move_by (shift);
343
447
}
344
448
set_pos (pos);
0 commit comments