1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/lua/lauxlib.h"
24
25 #include "ultima/nuvie/core/nuvie_defs.h"
26 #include "ultima/nuvie/misc/u6_misc.h"
27 #include "ultima/nuvie/files/u6_lib_n.h"
28 #include "ultima/nuvie/files/nuvie_io.h"
29 #include "ultima/nuvie/files/nuvie_io_file.h"
30 #include "ultima/nuvie/files/u6_lzw.h"
31 #include "ultima/nuvie/misc/u6_line_walker.h"
32 #include "ultima/nuvie/screen/game_palette.h"
33 #include "ultima/nuvie/sound/sound_manager.h"
34 #include "ultima/nuvie/fonts/font.h"
35 #include "ultima/nuvie/fonts/wou_font.h"
36 #include "ultima/nuvie/core/cursor.h"
37 #include "ultima/nuvie/keybinding/keys.h"
38 #include "ultima/nuvie/script/script_cutscene.h"
39 #include "common/system.h"
40
41 namespace Ultima {
42 namespace Nuvie {
43
44 #define DELUXE_PAINT_MAGIC 0x4d524f46 // "FORM"
45
46 #define INPUT_KEY_RIGHT 79 | (1<<30)
47 #define INPUT_KEY_LEFT 80 | (1<<30)
48 #define INPUT_KEY_DOWN 81 | (1<<30)
49 #define INPUT_KEY_UP 82 | (1<<30)
50
51 static ScriptCutscene *cutScene = NULL;
get_cutscene()52 ScriptCutscene *get_cutscene() {
53 return cutScene;
54 }
55
56 static int nscript_image_set(lua_State *L);
57 static int nscript_image_get(lua_State *L);
58
59 bool nscript_new_image_var(lua_State *L, CSImage *image);
60 static int nscript_image_gc(lua_State *L);
61
62 static sint32 nscript_dec_image_ref_count(CSImage *image);
63
64 static int nscript_image_new(lua_State *L);
65 static int nscript_image_new_starfield(lua_State *L);
66 static int nscript_image_copy(lua_State *L);
67 static int nscript_image_load(lua_State *L);
68 static int nscript_image_load_all(lua_State *L);
69 static int nscript_image_print(lua_State *L);
70 static int nscript_image_draw_line(lua_State *L);
71 static int nscript_image_blit(lua_State *L);
72 static int nscript_image_update_effect(lua_State *L);
73 static int nscript_image_static(lua_State *L);
74 static int nscript_image_set_transparency_colour(lua_State *L);
75 static int nscript_image_bubble_effect_add_color(lua_State *L);
76 static int nscript_image_bubble_effect(lua_State *L);
77
78 static const struct luaL_Reg nscript_imagelib_m[] = {
79 { "__index", nscript_image_get },
80 { "__newindex", nscript_image_set },
81 { "__gc", nscript_image_gc },
82 { NULL, NULL }
83 };
84
85 static int nscript_sprite_set(lua_State *L);
86 static int nscript_sprite_get(lua_State *L);
87
88 bool nscript_new_sprite_var(lua_State *L, CSSprite *image);
89 static int nscript_sprite_gc(lua_State *L);
90
91 static const struct luaL_Reg nscript_spritelib_m[] = {
92 { "__index", nscript_sprite_get },
93 { "__newindex", nscript_sprite_set },
94 { "__gc", nscript_sprite_gc },
95 { NULL, NULL }
96 };
97
98 static int nscript_sprite_new(lua_State *L);
99 static int nscript_sprite_move_to_front(lua_State *L);
100
101 static int nscript_text_load(lua_State *L);
102 static int nscript_midgame_load(lua_State *L);
103
104 static int nscript_canvas_set_bg_color(lua_State *L);
105 static int nscript_canvas_set_palette(lua_State *L);
106 static int nscript_canvas_set_palette_entry(lua_State *L);
107 static int nscript_canvas_rotate_palette(lua_State *L);
108 static int nscript_canvas_set_update_interval(lua_State *L);
109 static int nscript_canvas_set_opacity(lua_State *L);
110 static int nscript_canvas_set_solid_bg(lua_State *L);
111 static int nscript_canvas_update(lua_State *L);
112 static int nscript_canvas_show(lua_State *L);
113 static int nscript_canvas_hide(lua_State *L);
114 static int nscript_canvas_hide_all_sprites(lua_State *L);
115 static int nscript_canvas_string_length(lua_State *L);
116 static int nscript_canvas_rotate_game_palette(lua_State *L);
117
118 static int nscript_music_play(lua_State *L);
119 static int nscript_music_stop(lua_State *L);
120 static int nscript_get_mouse_x(lua_State *L);
121 static int nscript_get_mouse_y(lua_State *L);
122 static int nscript_input_poll(lua_State *L);
123
124 static int nscript_config_set(lua_State *L);
125
126 static int nscript_engine_should_quit(lua_State *L);
127
nscript_init_cutscene(lua_State * L,Configuration * cfg,GUI * gui,SoundManager * sm)128 void nscript_init_cutscene(lua_State *L, Configuration *cfg, GUI *gui, SoundManager *sm) {
129 cutScene = new ScriptCutscene(gui, cfg, sm);
130
131 luaL_newmetatable(L, "nuvie.Image");
132 luaL_register(L, NULL, nscript_imagelib_m);
133
134 luaL_newmetatable(L, "nuvie.Sprite");
135 luaL_register(L, NULL, nscript_spritelib_m);
136
137 lua_pushcfunction(L, nscript_image_new);
138 lua_setglobal(L, "image_new");
139
140 lua_pushcfunction(L, nscript_image_new_starfield);
141 lua_setglobal(L, "image_new_starfield");
142
143 lua_pushcfunction(L, nscript_image_copy);
144 lua_setglobal(L, "image_copy");
145
146 lua_pushcfunction(L, nscript_image_load);
147 lua_setglobal(L, "image_load");
148
149 lua_pushcfunction(L, nscript_image_load_all);
150 lua_setglobal(L, "image_load_all");
151
152 lua_pushcfunction(L, nscript_image_print);
153 lua_setglobal(L, "image_print");
154
155 lua_pushcfunction(L, nscript_image_static);
156 lua_setglobal(L, "image_static");
157
158 lua_pushcfunction(L, nscript_image_set_transparency_colour);
159 lua_setglobal(L, "image_set_transparency_colour");
160
161 lua_pushcfunction(L, nscript_image_update_effect);
162 lua_setglobal(L, "image_update_effect");
163
164 lua_pushcfunction(L, nscript_sprite_new);
165 lua_setglobal(L, "sprite_new");
166
167 lua_pushcfunction(L, nscript_sprite_move_to_front);
168 lua_setglobal(L, "sprite_move_to_front");
169
170 lua_pushcfunction(L, nscript_image_bubble_effect_add_color);
171 lua_setglobal(L, "image_bubble_effect_add_color");
172
173 lua_pushcfunction(L, nscript_image_bubble_effect);
174 lua_setglobal(L, "image_bubble_effect");
175
176 lua_pushcfunction(L, nscript_image_draw_line);
177 lua_setglobal(L, "image_draw_line");
178
179 lua_pushcfunction(L, nscript_image_blit);
180 lua_setglobal(L, "image_blit");
181
182 lua_pushcfunction(L, nscript_text_load);
183 lua_setglobal(L, "text_load");
184
185 lua_pushcfunction(L, nscript_midgame_load);
186 lua_setglobal(L, "midgame_load");
187
188 lua_pushcfunction(L, nscript_canvas_set_bg_color);
189 lua_setglobal(L, "canvas_set_bg_color");
190
191 lua_pushcfunction(L, nscript_canvas_set_palette);
192 lua_setglobal(L, "canvas_set_palette");
193
194 lua_pushcfunction(L, nscript_canvas_set_palette_entry);
195 lua_setglobal(L, "canvas_set_palette_entry");
196
197 lua_pushcfunction(L, nscript_canvas_rotate_palette);
198 lua_setglobal(L, "canvas_rotate_palette");
199
200 lua_pushcfunction(L, nscript_canvas_set_update_interval);
201 lua_setglobal(L, "canvas_set_update_interval");
202
203 lua_pushcfunction(L, nscript_canvas_set_solid_bg);
204 lua_setglobal(L, "canvas_set_solid_bg");
205
206 lua_pushcfunction(L, nscript_canvas_set_opacity);
207 lua_setglobal(L, "canvas_set_opacity");
208
209 lua_pushcfunction(L, nscript_canvas_update);
210 lua_setglobal(L, "canvas_update");
211
212 lua_pushcfunction(L, nscript_canvas_show);
213 lua_setglobal(L, "canvas_show");
214
215 lua_pushcfunction(L, nscript_canvas_hide);
216 lua_setglobal(L, "canvas_hide");
217
218 lua_pushcfunction(L, nscript_canvas_hide_all_sprites);
219 lua_setglobal(L, "canvas_hide_all_sprites");
220
221 lua_pushcfunction(L, nscript_canvas_string_length);
222 lua_setglobal(L, "canvas_string_length");
223
224 lua_pushcfunction(L, nscript_canvas_rotate_game_palette);
225 lua_setglobal(L, "canvas_rotate_game_palette");
226
227 lua_pushcfunction(L, nscript_music_play);
228 lua_setglobal(L, "music_play");
229
230 lua_pushcfunction(L, nscript_music_stop);
231 lua_setglobal(L, "music_stop");
232
233 lua_pushcfunction(L, nscript_get_mouse_x);
234 lua_setglobal(L, "get_mouse_x");
235
236 lua_pushcfunction(L, nscript_get_mouse_y);
237 lua_setglobal(L, "get_mouse_y");
238
239 lua_pushcfunction(L, nscript_input_poll);
240 lua_setglobal(L, "input_poll");
241
242 lua_pushcfunction(L, nscript_config_set);
243 lua_setglobal(L, "config_set");
244
245 lua_pushcfunction(L, nscript_engine_should_quit);
246 lua_setglobal(L, "engine_should_quit");
247 }
248
nscript_new_image_var(lua_State * L,CSImage * image)249 bool nscript_new_image_var(lua_State *L, CSImage *image) {
250 CSImage **userdata;
251
252 userdata = (CSImage **)lua_newuserdata(L, sizeof(CSImage *));
253
254 luaL_getmetatable(L, "nuvie.Image");
255 lua_setmetatable(L, -2);
256
257 *userdata = image;
258
259 if (image)
260 image->refcount++;
261
262 return true;
263 }
264
nscript_get_image_from_args(lua_State * L,int lua_stack_offset)265 CSImage *nscript_get_image_from_args(lua_State *L, int lua_stack_offset) {
266 CSImage **s_image = (CSImage **)luaL_checkudata(L, lua_stack_offset, "nuvie.Image");
267 if (s_image == NULL)
268 return NULL;
269
270 return *s_image;
271 }
272
nscript_image_set(lua_State * L)273 static int nscript_image_set(lua_State *L) {
274 CSImage **s_image;
275 CSImage *image;
276 const char *key;
277
278 s_image = (CSImage **)lua_touserdata(L, 1);
279 if (s_image == NULL)
280 return 0;
281
282 image = *s_image;
283 if (image == NULL)
284 return 0;
285
286 key = lua_tostring(L, 2);
287
288 if (!strcmp(key, "scale")) {
289 image->setScale((uint16)lua_tointeger(L, 3));
290 return 0;
291 }
292
293 return 0;
294 }
295
296
nscript_image_get(lua_State * L)297 static int nscript_image_get(lua_State *L) {
298 CSImage **s_image;
299 CSImage *image;
300 const char *key;
301
302 s_image = (CSImage **)lua_touserdata(L, 1);
303 if (s_image == NULL)
304 return 0;
305
306 image = *s_image;
307 if (image == NULL)
308 return 0;
309
310 key = lua_tostring(L, 2);
311
312 if (!strcmp(key, "w")) {
313 uint16 w, h;
314 image->shp->get_size(&w, &h);
315 lua_pushinteger(L, w);
316 return 1;
317 }
318
319 if (!strcmp(key, "h")) {
320 uint16 w, h;
321 image->shp->get_size(&w, &h);
322 lua_pushinteger(L, h);
323 return 1;
324 }
325
326 if (!strcmp(key, "scale")) {
327 lua_pushinteger(L, image->getScale());
328 return 1;
329 }
330
331 return 0;
332 }
333
nscript_dec_image_ref_count(CSImage * image)334 static sint32 nscript_dec_image_ref_count(CSImage *image) {
335 if (image == NULL)
336 return -1;
337
338 image->refcount--;
339
340 return image->refcount;
341 }
342
nscript_image_gc(lua_State * L)343 static int nscript_image_gc(lua_State *L) {
344 //DEBUG(0, LEVEL_INFORMATIONAL, "\nImage garbage Collection!\n");
345
346 CSImage **p_image = (CSImage **)lua_touserdata(L, 1);
347 CSImage *image;
348
349 if (p_image == NULL)
350 return false;
351
352 image = *p_image;
353
354 if (nscript_dec_image_ref_count(image) == 0) {
355 if (image->shp)
356 delete image->shp;
357 delete image;
358 }
359
360 return 0;
361 }
362
nscript_image_new(lua_State * L)363 static int nscript_image_new(lua_State *L) {
364 uint16 width = lua_tointeger(L, 1);
365 uint16 height = lua_tointeger(L, 2);
366
367 U6Shape *shp = new U6Shape();
368 if (shp->init(width, height) == false)
369 return 0;
370
371 if (lua_gettop(L) >= 3)
372 shp->fill((uint8)lua_tointeger(L, 3));
373
374 CSImage *image = new CSImage(shp);
375
376 nscript_new_image_var(L, image);
377 return 1;
378 }
379
nscript_image_new_starfield(lua_State * L)380 static int nscript_image_new_starfield(lua_State *L) {
381 uint16 width = lua_tointeger(L, 1);
382 uint16 height = lua_tointeger(L, 2);
383
384 U6Shape *shp = new U6Shape();
385 if (shp->init(width, height) == false)
386 return 0;
387
388 CSStarFieldImage *image = new CSStarFieldImage(shp);
389
390 nscript_new_image_var(L, image);
391 return 1;
392 }
393
nscript_image_copy(lua_State * L)394 static int nscript_image_copy(lua_State *L) {
395 CSImage *img = nscript_get_image_from_args(L, 1);
396 uint16 w, h;
397
398 U6Shape *shp = new U6Shape();
399 img->shp->get_size(&w, &h);
400 if (shp->init(w, h) == false) {
401 return 0;
402 }
403 shp->blit(img->shp, 0, 0);
404
405 CSImage *image = new CSImage(shp);
406
407 nscript_new_image_var(L, image);
408 return 1;
409 }
410
nscript_image_load(lua_State * L)411 static int nscript_image_load(lua_State *L) {
412 const char *filename = lua_tostring(L, 1);
413 int idx = -1;
414 int sub_idx = 0;
415
416 if (lua_gettop(L) >= 2)
417 idx = lua_tointeger(L, 2);
418
419 if (lua_gettop(L) >= 3)
420 sub_idx = lua_tointeger(L, 3);
421
422 CSImage *image = cutScene->load_image(filename, idx, sub_idx);
423
424 if (image) {
425 nscript_new_image_var(L, image);
426 return 1;
427 }
428
429 return 0;
430 }
431
nscript_image_load_all(lua_State * L)432 static int nscript_image_load_all(lua_State *L) {
433 const char *filename = lua_tostring(L, 1);
434 Std::vector<Std::vector<CSImage *> > images = cutScene->load_all_images(filename);
435
436 if (images.empty()) {
437 return 0;
438 }
439
440 lua_newtable(L);
441
442 for (uint16 i = 0; i < images.size(); i++) {
443 lua_pushinteger(L, i);
444 if (images[i].size() > 1) {
445 lua_newtable(L);
446 for (uint16 j = 0; j < images[i].size(); j++) {
447 lua_pushinteger(L, j);
448 nscript_new_image_var(L, images[i][j]);
449 lua_settable(L, -3);
450 }
451 } else {
452 nscript_new_image_var(L, images[i][0]);
453 }
454 lua_settable(L, -3);
455 }
456
457 return 1;
458 }
459
nscript_image_print(lua_State * L)460 static int nscript_image_print(lua_State *L) {
461 CSImage *img = nscript_get_image_from_args(L, 1);
462 const char *text = lua_tostring(L, 2);
463 uint16 startx = lua_tointeger(L, 3);
464 uint16 width = lua_tointeger(L, 4);
465 uint16 x = lua_tointeger(L, 5);
466 uint16 y = lua_tointeger(L, 6);
467 uint8 color = lua_tointeger(L, 7);
468
469 cutScene->print_text(img, text, &x, &y, startx, width, color);
470
471 lua_pushinteger(L, x);
472 lua_pushinteger(L, y);
473
474 return 2;
475 }
476
nscript_image_draw_line(lua_State * L)477 static int nscript_image_draw_line(lua_State *L) {
478 CSImage *img = nscript_get_image_from_args(L, 1);
479 uint16 sx = lua_tointeger(L, 2);
480 uint16 sy = lua_tointeger(L, 3);
481 uint16 ex = lua_tointeger(L, 4);
482 uint16 ey = lua_tointeger(L, 5);
483 uint8 color = lua_tointeger(L, 6);
484
485 if (img) {
486 img->shp->draw_line(sx, sy, ex, ey, color);
487 }
488
489 return 0;
490 }
491
nscript_image_blit(lua_State * L)492 static int nscript_image_blit(lua_State *L) {
493 CSImage *dest_img = nscript_get_image_from_args(L, 1);
494 CSImage *src_img = nscript_get_image_from_args(L, 2);
495 uint16 x = lua_tointeger(L, 3);
496 uint16 y = lua_tointeger(L, 4);
497
498 if (dest_img && src_img) {
499 dest_img->shp->blit(src_img->shp, x, y);
500 }
501
502 return 0;
503 }
nscript_image_update_effect(lua_State * L)504 static int nscript_image_update_effect(lua_State *L) {
505 CSImage *img = nscript_get_image_from_args(L, 1);
506 if (img) {
507 img->updateEffect();
508 }
509
510 return 0;
511 }
512
513 static uint8 u6_flask_num_colors = 0;
514 static uint8 u6_flask_liquid_colors[8];
515
nscript_image_bubble_effect_add_color(lua_State * L)516 static int nscript_image_bubble_effect_add_color(lua_State *L) {
517 if (u6_flask_num_colors != 8) {
518 u6_flask_liquid_colors[u6_flask_num_colors++] = lua_tointeger(L, 1);
519 }
520
521 return 0;
522 }
523
nscript_image_bubble_effect(lua_State * L)524 static int nscript_image_bubble_effect(lua_State *L) {
525 CSImage *img = nscript_get_image_from_args(L, 1);
526
527 if (img && u6_flask_num_colors > 0) {
528 unsigned char *data = img->shp->get_data();
529 uint16 w, h;
530 img->shp->get_size(&w, &h);
531
532 for (int i = 0; i < w * h; i++) {
533 if (*data != 0xff) {
534 *data = u6_flask_liquid_colors[NUVIE_RAND() % u6_flask_num_colors];
535 }
536
537 data++;
538 }
539
540 }
541 return 0;
542 }
543
nscript_image_set_transparency_colour(lua_State * L)544 static int nscript_image_set_transparency_colour(lua_State *L) {
545 CSImage *img = nscript_get_image_from_args(L, 1);
546 uint8 pal_index = lua_tointeger(L, 2);
547 if (img) {
548 unsigned char *data = img->shp->get_data();
549 uint16 w, h;
550 img->shp->get_size(&w, &h);
551 for (int i = 0; i < w * h; i++) {
552 if (data[i] == pal_index)
553 data[i] = 0xff;
554 }
555 }
556 return 0;
557 }
558
nscript_image_static(lua_State * L)559 static int nscript_image_static(lua_State *L) {
560 CSImage *img = nscript_get_image_from_args(L, 1);
561
562 if (img) {
563 unsigned char *data = img->shp->get_data();
564 uint16 w, h;
565 img->shp->get_size(&w, &h);
566 memset(data, 16, w * h);
567 for (int i = 0; i < 1000; i++) {
568 data[NUVIE_RAND() % (w * h)] = 0;
569 }
570 }
571 return 0;
572 }
573
nscript_get_sprite_from_args(lua_State * L,int lua_stack_offset)574 CSSprite *nscript_get_sprite_from_args(lua_State *L, int lua_stack_offset) {
575 CSSprite **s_sprite;
576 CSSprite *sprite;
577
578 s_sprite = (CSSprite **)lua_touserdata(L, 1);
579 if (s_sprite == NULL)
580 return NULL;
581
582 sprite = *s_sprite;
583 return sprite;
584 }
585
nscript_new_sprite_var(lua_State * L,CSSprite * sprite)586 bool nscript_new_sprite_var(lua_State *L, CSSprite *sprite) {
587 CSSprite **userdata;
588
589 userdata = (CSSprite **)lua_newuserdata(L, sizeof(CSSprite *));
590
591 luaL_getmetatable(L, "nuvie.Sprite");
592 lua_setmetatable(L, -2);
593
594 *userdata = sprite;
595
596 return true;
597 }
598
nscript_sprite_set(lua_State * L)599 static int nscript_sprite_set(lua_State *L) {
600 CSSprite **s_sprite;
601 CSSprite *sprite;
602 const char *key;
603
604 s_sprite = (CSSprite **)lua_touserdata(L, 1);
605 if (s_sprite == NULL)
606 return 0;
607
608 sprite = *s_sprite;
609 if (sprite == NULL)
610 return 0;
611
612 key = lua_tostring(L, 2);
613
614 if (!strcmp(key, "x")) {
615 sprite->x = lua_tointeger(L, 3);
616 return 0;
617 }
618
619 if (!strcmp(key, "y")) {
620 sprite->y = lua_tointeger(L, 3);
621 return 0;
622 }
623
624 if (!strcmp(key, "opacity")) {
625 int opacity = lua_tointeger(L, 3);
626 sprite->opacity = (uint8)clamp(opacity, 0, 255);
627 return 0;
628 }
629
630 if (!strcmp(key, "visible")) {
631 sprite->visible = lua_toboolean(L, 3);
632 return 0;
633 }
634
635 if (!strcmp(key, "image")) {
636 if (sprite->image) {
637 sprite->image->refcount--;
638 if (sprite->image->refcount == 0)
639 delete sprite->image;
640 }
641
642 sprite->image = nscript_get_image_from_args(L, 3);
643 if (sprite->image)
644 sprite->image->refcount++;
645
646 return 0;
647 }
648
649 if (!strcmp(key, "clip_x")) {
650 sprite->clip_rect.left = lua_tointeger(L, 3) + cutScene->get_x_off();
651 return 0;
652 }
653
654 if (!strcmp(key, "clip_y")) {
655 sprite->clip_rect.top = lua_tointeger(L, 3) + cutScene->get_y_off();
656 return 0;
657 }
658
659 if (!strcmp(key, "clip_w")) {
660 sprite->clip_rect.setWidth(lua_tointeger(L, 3));
661 return 0;
662 }
663
664 if (!strcmp(key, "clip_h")) {
665 sprite->clip_rect.setHeight(lua_tointeger(L, 3));
666 return 0;
667 }
668 if (!strcmp(key, "text")) {
669 const char *text = lua_tostring(L, 3);
670 sprite->text = Std::string(text);
671 }
672 if (!strcmp(key, "text_color")) {
673 sprite->text_color = lua_tointeger(L, 3);
674 return 0;
675 }
676 if (!strcmp(key, "text_align")) {
677 int align_val = lua_tointeger(L, 3);
678 sprite->text_align = (uint8) align_val;
679 return 0;
680 }
681 return 0;
682 }
683
684
nscript_sprite_get(lua_State * L)685 static int nscript_sprite_get(lua_State *L) {
686 CSSprite **s_sprite;
687 CSSprite *sprite;
688 const char *key;
689
690 s_sprite = (CSSprite **)lua_touserdata(L, 1);
691 if (s_sprite == NULL)
692 return 0;
693
694 sprite = *s_sprite;
695 if (sprite == NULL)
696 return 0;
697
698 key = lua_tostring(L, 2);
699
700 if (!strcmp(key, "x")) {
701 lua_pushinteger(L, sprite->x);
702 return 1;
703 }
704
705 if (!strcmp(key, "y")) {
706 lua_pushinteger(L, sprite->y);
707 return 1;
708 }
709
710 if (!strcmp(key, "opacity")) {
711 lua_pushinteger(L, sprite->opacity);
712 return 1;
713 }
714
715 if (!strcmp(key, "visible")) {
716 lua_pushboolean(L, sprite->visible);
717 return 1;
718 }
719
720 if (!strcmp(key, "image")) {
721 if (sprite->image) {
722 nscript_new_image_var(L, sprite->image);
723 return 1;
724 }
725 }
726
727 if (!strcmp(key, "text")) {
728 lua_pushstring(L, sprite->text.c_str());
729 return 1;
730 }
731
732 if (!strcmp(key, "text_color")) {
733 lua_pushinteger(L, sprite->text_color);
734 return 1;
735 }
736
737 if (!strcmp(key, "text_width")) {
738 lua_pushinteger(L, cutScene->get_text_width(sprite->text.c_str()));
739 return 1;
740 }
741
742 return 0;
743 }
744
nscript_sprite_gc(lua_State * L)745 static int nscript_sprite_gc(lua_State *L) {
746 //DEBUG(0, LEVEL_INFORMATIONAL, "\nSprite garbage Collection!\n");
747
748 CSSprite **p_sprite = (CSSprite **)lua_touserdata(L, 1);
749 CSSprite *sprite;
750
751 if (p_sprite == NULL)
752 return false;
753
754 sprite = *p_sprite;
755
756 if (sprite) {
757 if (sprite->image) {
758 if (nscript_dec_image_ref_count(sprite->image) == 0)
759 delete sprite->image;
760 }
761 cutScene->remove_sprite(sprite);
762 delete sprite;
763 }
764
765 return 0;
766 }
767
nscript_sprite_new(lua_State * L)768 static int nscript_sprite_new(lua_State *L) {
769 CSSprite *sprite = new CSSprite();
770
771 if (lua_gettop(L) >= 1 && !lua_isnil(L, 1)) {
772 sprite->image = nscript_get_image_from_args(L, 1);
773 if (sprite->image)
774 sprite->image->refcount++;
775 }
776
777 if (lua_gettop(L) >= 2 && !lua_isnil(L, 2)) {
778 sprite->x = lua_tointeger(L, 2);
779 }
780
781 if (lua_gettop(L) >= 3 && !lua_isnil(L, 3)) {
782 sprite->y = lua_tointeger(L, 3);
783 }
784
785 if (lua_gettop(L) >= 4 && !lua_isnil(L, 4)) {
786 sprite->visible = lua_toboolean(L, 4);
787 }
788
789 cutScene->add_sprite(sprite);
790
791 nscript_new_sprite_var(L, sprite);
792 return 1;
793 }
794
nscript_sprite_move_to_front(lua_State * L)795 static int nscript_sprite_move_to_front(lua_State *L) {
796 CSSprite *sprite = nscript_get_sprite_from_args(L, 1);
797 if (sprite) {
798 cutScene->remove_sprite(sprite);
799 cutScene->add_sprite(sprite);
800 }
801
802 return 0;
803 }
804
nscript_text_load(lua_State * L)805 static int nscript_text_load(lua_State *L) {
806 const char *filename = lua_tostring(L, 1);
807 uint8 idx = lua_tointeger(L, 2);
808
809 Std::vector<Std::string> text = cutScene->load_text(filename, idx);
810
811 if (text.empty()) {
812 return 0;
813 }
814
815 lua_newtable(L);
816
817 for (uint16 i = 0; i < text.size(); i++) {
818 lua_pushinteger(L, i);
819 lua_pushstring(L, text[i].c_str());
820 lua_settable(L, -3);
821 }
822
823 return 1;
824 }
825
nscript_midgame_load(lua_State * L)826 static int nscript_midgame_load(lua_State *L) {
827 const char *filename = lua_tostring(L, 1);
828 Std::vector<CSMidGameData> v = cutScene->load_midgame_file(filename);
829
830 if (v.empty()) {
831 return 0;
832 }
833
834 lua_newtable(L);
835
836 for (uint16 i = 0; i < v.size(); i++) {
837 lua_pushinteger(L, i);
838
839 lua_newtable(L);
840
841 lua_pushstring(L, "text");
842 lua_newtable(L);
843 for (uint16 j = 0; j < v[i].text.size(); j++) {
844 lua_pushinteger(L, j);
845 lua_pushstring(L, v[i].text[j].c_str());
846 lua_settable(L, -3);
847 }
848 lua_settable(L, -3);
849
850 lua_pushstring(L, "images");
851 lua_newtable(L);
852 for (uint16 j = 0; j < v[i].images.size(); j++) {
853 lua_pushinteger(L, j);
854 nscript_new_image_var(L, v[i].images[j]);
855 lua_settable(L, -3);
856 }
857 lua_settable(L, -3);
858
859 lua_settable(L, -3);
860 }
861
862 return 1;
863 }
864
nscript_canvas_set_bg_color(lua_State * L)865 static int nscript_canvas_set_bg_color(lua_State *L) {
866 uint8 color = lua_tointeger(L, 1);
867 cutScene->set_bg_color(color);
868
869 return 0;
870 }
871
nscript_canvas_set_palette(lua_State * L)872 static int nscript_canvas_set_palette(lua_State *L) {
873 const char *filename = lua_tostring(L, 1);
874 uint8 idx = lua_tointeger(L, 2);
875
876 cutScene->load_palette(filename, idx);
877
878 return 0;
879 }
880
nscript_canvas_set_palette_entry(lua_State * L)881 static int nscript_canvas_set_palette_entry(lua_State *L) {
882 uint8 idx = lua_tointeger(L, 1);
883 uint8 r = lua_tointeger(L, 2);
884 uint8 g = lua_tointeger(L, 3);
885 uint8 b = lua_tointeger(L, 4);
886
887 cutScene->set_palette_entry(idx, r, g, b);
888
889 return 0;
890 }
891
nscript_canvas_rotate_palette(lua_State * L)892 static int nscript_canvas_rotate_palette(lua_State *L) {
893 uint8 idx = lua_tointeger(L, 1);
894 uint8 len = lua_tointeger(L, 2);
895
896 cutScene->rotate_palette(idx, len);
897
898 return 0;
899 }
900
nscript_canvas_set_update_interval(lua_State * L)901 static int nscript_canvas_set_update_interval(lua_State *L) {
902 uint16 loop_interval = lua_tointeger(L, 1);
903
904 cutScene->set_update_interval(loop_interval);
905 return 0;
906 }
907
nscript_canvas_set_solid_bg(lua_State * L)908 static int nscript_canvas_set_solid_bg(lua_State *L) {
909 bool solid_bg = lua_toboolean(L, 1);
910 cutScene->set_solid_bg(solid_bg);
911 return 0;
912 }
913
nscript_canvas_set_opacity(lua_State * L)914 static int nscript_canvas_set_opacity(lua_State *L) {
915 uint8 opacity = lua_tointeger(L, 1);
916
917 cutScene->set_screen_opacity(opacity);
918 return 0;
919 }
920
nscript_canvas_update(lua_State * L)921 static int nscript_canvas_update(lua_State *L) {
922 cutScene->update();
923 return 0;
924 }
925
nscript_canvas_show(lua_State * L)926 static int nscript_canvas_show(lua_State *L) {
927 cutScene->moveToFront();
928 return 0;
929 }
930
nscript_canvas_hide(lua_State * L)931 static int nscript_canvas_hide(lua_State *L) {
932 cutScene->Hide();
933 return 0;
934 }
935
nscript_canvas_hide_all_sprites(lua_State * L)936 static int nscript_canvas_hide_all_sprites(lua_State *L) {
937 cutScene->hide_sprites();
938 return 0;
939 }
940
nscript_canvas_string_length(lua_State * L)941 static int nscript_canvas_string_length(lua_State *L) {
942 Font *font = cutScene->get_font();
943 const char *str = lua_tostring(L, 1);
944
945 lua_pushinteger(L, font->getStringWidth(str));
946 return 1;
947 }
948
nscript_canvas_rotate_game_palette(lua_State * L)949 static int nscript_canvas_rotate_game_palette(lua_State *L) {
950 bool val = lua_toboolean(L, 1);
951 cutScene->enable_game_palette_rotation(val);
952 return 0;
953 }
954
nscript_music_play(lua_State * L)955 static int nscript_music_play(lua_State *L) {
956 uint16 song_num = 0;
957 const char *filename = lua_tostring(L, 1);
958
959 if (lua_gettop(L) >= 2 && !lua_isnil(L, 2)) {
960 song_num = lua_tointeger(L, 2);
961 }
962
963 cutScene->get_sound_manager()->musicPlay(filename, song_num);
964
965 return 0;
966 }
967
nscript_music_stop(lua_State * L)968 static int nscript_music_stop(lua_State *L) {
969 cutScene->get_sound_manager()->musicStop();
970
971 return 0;
972 }
973
nscript_get_mouse_x(lua_State * L)974 static int nscript_get_mouse_x(lua_State *L) {
975 int x, y;
976 cutScene->get_screen()->get_mouse_location(&x, &y);
977 x -= cutScene->get_x_off();
978 lua_pushinteger(L, x);
979 return 1;
980 }
981
nscript_get_mouse_y(lua_State * L)982 static int nscript_get_mouse_y(lua_State *L) {
983 int x, y;
984 cutScene->get_screen()->get_mouse_location(&x, &y);
985 y -= cutScene->get_y_off();
986 lua_pushinteger(L, y);
987 return 1;
988 }
989
nscript_input_poll(lua_State * L)990 static int nscript_input_poll(lua_State *L) {
991 Common::Event event;
992 bool poll_mouse_motion;
993 if (lua_isnil(L, 1))
994 poll_mouse_motion = false;
995 else
996 poll_mouse_motion = lua_toboolean(L, 1);
997
998 while (Events::get()->pollEvent(event)) {
999 //FIXME do something here.
1000 KeyBinder *keybinder = Game::get_game()->get_keybinder();
1001
1002 if (event.type == Common::EVENT_JOYAXIS_MOTION ||
1003 event.type == Common::EVENT_JOYBUTTON_DOWN ||
1004 event.type == Common::EVENT_JOYBUTTON_UP) {
1005 event.kbd.flags = 0;
1006 event.kbd.keycode = keybinder->get_key_from_joy_events(&event);
1007 if (event.kbd.keycode == Common::KEYCODE_INVALID)
1008 // button isn't mapped or was in deadzone
1009 return 0; // pretend nothing happened
1010
1011 event.type = Common::EVENT_KEYDOWN;
1012 }
1013
1014 if (event.type == Common::EVENT_KEYDOWN) {
1015 Common::KeyState key = event.kbd;
1016
1017 if ((((key.flags & Common::KBD_CAPS) == Common::KBD_CAPS
1018 && (key.flags & Common::KBD_SHIFT) == 0) || ((key.flags & Common::KBD_CAPS) == 0 && (key.flags & Common::KBD_SHIFT)))
1019 && key.keycode >= Common::KEYCODE_a && key.keycode <= Common::KEYCODE_z)
1020 key.keycode = (Common::KeyCode)(key.keycode - 32);
1021 if (key.keycode > 0xFF || !Common::isPrint((char)key.keycode) || (key.flags & Common::KBD_ALT) || (key.flags & Common::KBD_CTRL)) {
1022 ActionType a = keybinder->get_ActionType(key);
1023 switch (keybinder->GetActionKeyType(a)) {
1024 case WEST_KEY:
1025 lua_pushinteger(L, INPUT_KEY_LEFT);
1026 return 1;
1027 case EAST_KEY:
1028 lua_pushinteger(L, INPUT_KEY_RIGHT);
1029 return 1;
1030 case SOUTH_KEY:
1031 lua_pushinteger(L, INPUT_KEY_DOWN);
1032 return 1;
1033 case NORTH_KEY:
1034 lua_pushinteger(L, INPUT_KEY_UP);
1035 return 1;
1036 case CANCEL_ACTION_KEY:
1037 key.keycode = Common::KEYCODE_ESCAPE;
1038 break;
1039 case DO_ACTION_KEY:
1040 key.keycode = Common::KEYCODE_RETURN;
1041 break;
1042 default:
1043 if (keybinder->handle_always_available_keys(a)) return 0;
1044 break;
1045 }
1046 }
1047 lua_pushinteger(L, key.keycode);
1048 return 1;
1049 }
1050 if (event.type == Common::EVENT_QUIT) {
1051 lua_pushinteger(L, 'Q');
1052 return 1;
1053 }
1054
1055 if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_RBUTTONDOWN) {
1056 lua_pushinteger(L, 0);
1057 return 1;
1058 }
1059 if (poll_mouse_motion && event.type == Common::EVENT_MOUSEMOVE) {
1060 lua_pushinteger(L, 1);
1061 return 1;
1062 }
1063 }
1064
1065 return 0;
1066 }
1067
nscript_config_set(lua_State * L)1068 static int nscript_config_set(lua_State *L) {
1069 const char *config_key = lua_tostring(L, 1);
1070
1071 if (lua_isstring(L, 2)) {
1072 cutScene->get_config()->set(config_key, lua_tostring(L, 2));
1073 } else if (lua_isnumber(L, 2)) {
1074 cutScene->get_config()->set(config_key, (int)lua_tointeger(L, 2));
1075 } else if (lua_isboolean(L, 2)) {
1076 cutScene->get_config()->set(config_key, (bool)lua_toboolean(L, 2));
1077 }
1078
1079 return 0;
1080 }
1081
nscript_engine_should_quit(lua_State * L)1082 static int nscript_engine_should_quit(lua_State *L) {
1083 int x = g_engine->shouldQuit();
1084 lua_pushinteger(L, x);
1085 return 1;
1086 }
1087
ScriptCutscene(GUI * g,Configuration * cfg,SoundManager * sm)1088 ScriptCutscene::ScriptCutscene(GUI *g, Configuration *cfg, SoundManager *sm) : GUI_Widget(NULL) {
1089 config = cfg;
1090 gui = g;
1091
1092 cursor = Game::get_game()->get_cursor();
1093 x_off = Game::get_game()->get_game_x_offset();
1094 y_off = Game::get_game()->get_game_y_offset();
1095
1096 x_off += (Game::get_game()->get_game_width() - 320) / 2; // center it
1097 y_off += (Game::get_game()->get_game_height() - 200) / 2; // center it
1098
1099 nuvie_game_t game_type = Game::get_game()->get_game_type();
1100
1101 GUI_Widget::Init(NULL, 0, 0, g->get_width(), g->get_height());
1102
1103 clip_rect = Common::Rect(x_off, y_off, x_off + 320, y_off + 200);
1104 screen = g->get_screen();
1105 gui->AddWidget(this);
1106 Hide();
1107 sound_manager = sm;
1108
1109 //FIXME this should be loaded by script.
1110 Std::string path;
1111
1112
1113 font = new WOUFont();
1114
1115 if (game_type == NUVIE_GAME_U6) {
1116 config_get_path(config, "u6.set", path);
1117 font->init(path.c_str());
1118 }
1119 //FIXME load other fonts for MD / SE if needed here.
1120 if (game_type == NUVIE_GAME_SE) {
1121 Std::string filePath;
1122 U6Lib_n lib_file;
1123
1124 config_get_path(config, "savage.fnt", filePath);
1125
1126 lib_file.open(filePath, 4, NUVIE_GAME_SE); //can be either SE or MD just as long as it isn't set to U6 type.
1127
1128 unsigned char *buf = lib_file.get_item(0);
1129 font->initWithBuffer(buf, lib_file.get_item_size(0)); //buf will be freed by ~Font()
1130 }
1131
1132 if (game_type == NUVIE_GAME_MD) {
1133 Std::string filePath;
1134 U6Lib_n lib_file;
1135
1136 config_get_path(config, "fonts.lzc", filePath);
1137
1138 lib_file.open(filePath, 4, NUVIE_GAME_MD);
1139
1140 unsigned char *buf = lib_file.get_item(0);
1141 font->initWithBuffer(buf, lib_file.get_item_size(0)); //buf will be freed by ~Font()
1142 }
1143 next_time = 0;
1144 loop_interval = 40;
1145
1146 screen_opacity = 255;
1147 bg_color = 0;
1148 solid_bg = true;
1149 rotate_game_palette = false;
1150 palette = NULL;
1151 }
1152
~ScriptCutscene()1153 ScriptCutscene::~ScriptCutscene() {
1154 delete font;
1155 }
1156
is_lzc(const char * filename)1157 bool ScriptCutscene::is_lzc(const char *filename) {
1158 if (strlen(filename) > 4 && scumm_stricmp((const char *)&filename[strlen(filename) - 4], ".lzc") == 0)
1159 return true;
1160
1161 return false;
1162 }
1163
load_image_from_lzc(Std::string filename,uint16 idx,uint16 sub_idx)1164 CSImage *ScriptCutscene::load_image_from_lzc(Std::string filename, uint16 idx, uint16 sub_idx) {
1165 CSImage *image = nullptr;
1166 U6Lib_n lib_n;
1167 unsigned char *buf = NULL;
1168
1169 if (!lib_n.open(filename, 4, NUVIE_GAME_MD)) {
1170 return NULL;
1171 }
1172
1173 if (idx >= lib_n.get_num_items()) {
1174 return NULL;
1175 }
1176
1177 buf = lib_n.get_item(idx, NULL);
1178 NuvieIOBuffer io;
1179 io.open(buf, lib_n.get_item_size(idx), false);
1180 U6Lib_n lib1;
1181 lib1.open(&io, 4, NUVIE_GAME_MD);
1182
1183 if (sub_idx >= lib1.get_num_items()) {
1184 return NULL;
1185 }
1186
1187 U6Shape *shp = new U6Shape();
1188 if (shp->load(&lib1, (uint32)sub_idx)) {
1189 image = new CSImage(shp);
1190 }
1191
1192 free(buf);
1193
1194 return image;
1195 }
1196
load_image(const char * filename,int idx,int sub_idx)1197 CSImage *ScriptCutscene::load_image(const char *filename, int idx, int sub_idx) {
1198 U6Lib_n lib_n;
1199 Std::string path;
1200 CSImage *image = NULL;
1201
1202 config_get_path(config, filename, path);
1203
1204 if (is_lzc(filename)) {
1205 return load_image_from_lzc(path, (uint16)idx, (uint16)sub_idx);
1206 }
1207
1208 U6Shape *shp = new U6Shape();
1209
1210 if (idx >= 0) {
1211 U6Lzw lzw;
1212
1213 uint32 decomp_size;
1214 unsigned char *buf = lzw.decompress_file(path.c_str(), decomp_size);
1215 NuvieIOBuffer io;
1216 io.open(buf, decomp_size, false);
1217 {
1218 // Note: libN needs to be destroyed before the io object.
1219 U6Lib_n libN;
1220 if (libN.open(&io, 4, NUVIE_GAME_MD)) {
1221 if (shp->load(&libN, (uint32)idx)) {
1222 image = new CSImage(shp);
1223 }
1224 }
1225 }
1226 free(buf);
1227 } else {
1228 if (shp->load(path)) {
1229 image = new CSImage(shp);
1230 }
1231 }
1232
1233 if (image == NULL)
1234 delete shp;
1235
1236 return image;
1237 }
1238
load_all_images(const char * filename)1239 Std::vector<Std::vector<CSImage *> > ScriptCutscene::load_all_images(const char *filename) {
1240 Std::string path;
1241 CSImage *image = NULL;
1242
1243 config_get_path(config, filename, path);
1244
1245 Std::vector<Std::vector<CSImage *> > v;
1246 U6Lzw lzw;
1247
1248 U6Lib_n lib_n;
1249 unsigned char *buf = NULL;
1250
1251 if (is_lzc(filename)) {
1252 if (!lib_n.open(path, 4, NUVIE_GAME_MD)) {
1253 return v;
1254 }
1255 for (uint32 idx = 0; idx < lib_n.get_num_items(); idx++) {
1256 buf = lib_n.get_item(idx, NULL);
1257 NuvieIOBuffer io;
1258 io.open(buf, lib_n.get_item_size(idx), false);
1259 U6Lib_n lib1;
1260 lib1.open(&io, 4, NUVIE_GAME_MD);
1261 //printf("lib_size = %d\n", lib1.get_num_items());
1262 Std::vector<CSImage *> v1;
1263 for (uint32 idx1 = 0; idx1 < lib1.get_num_items(); idx1++) {
1264 U6Shape *shp = new U6Shape();
1265 if (shp->load(&lib1, (uint32)idx1)) {
1266 image = new CSImage(shp);
1267 v1.push_back(image);
1268 }
1269 }
1270 free(buf);
1271 buf = NULL;
1272 v.push_back(v1);
1273 }
1274 } else {
1275 uint32 decomp_size;
1276 buf = lzw.decompress_file(path.c_str(), decomp_size);
1277 NuvieIOBuffer io;
1278 io.open(buf, decomp_size, false);
1279 if (!lib_n.open(&io, 4, NUVIE_GAME_MD)) {
1280 free(buf);
1281 return v;
1282 }
1283
1284 for (uint32 idx = 0; idx < lib_n.get_num_items(); idx++) {
1285 Std::vector<CSImage *> v1;
1286 U6Shape *shp = new U6Shape();
1287 if (shp->load(&lib_n, (uint32)idx)) {
1288 image = new CSImage(shp);
1289 v1.push_back(image);
1290 v.push_back(v1);
1291 }
1292 }
1293
1294 lib_n.close();
1295 }
1296
1297 if (buf)
1298 free(buf);
1299
1300 return v;
1301
1302 }
1303
load_images_from_lib(Std::vector<CSImage * > * images,U6Lib_n * lib,uint32 index)1304 void load_images_from_lib(Std::vector<CSImage *> *images, U6Lib_n *lib, uint32 index) {
1305 unsigned char *buf = lib->get_item(index, NULL);
1306 if (buf == NULL) {
1307 return;
1308 }
1309
1310 NuvieIOBuffer io;
1311 io.open(buf, lib->get_item_size(index), false);
1312 U6Lib_n lib1;
1313 lib1.open(&io, 4, NUVIE_GAME_MD);
1314
1315 for (uint16 i = 0; i < lib1.get_num_items(); i++) {
1316 U6Shape *shp = new U6Shape();
1317 if (shp->load(&lib1, i)) {
1318 images->push_back(new CSImage(shp));
1319 }
1320 }
1321 free(buf);
1322 }
1323
load_midgame_file(const char * filename)1324 Std::vector<CSMidGameData> ScriptCutscene::load_midgame_file(const char *filename) {
1325 Std::string path;
1326 U6Lib_n lib_n;
1327 Std::vector<CSMidGameData> v;
1328 nuvie_game_t game_type = Game::get_game()->get_game_type();
1329
1330 config_get_path(config, filename, path);
1331
1332 if (!lib_n.open(path, 4, NUVIE_GAME_MD)) {
1333 return v;
1334 }
1335
1336 for (uint32 idx = 0; idx < lib_n.get_num_items();) {
1337 if (game_type == NUVIE_GAME_MD && idx == 0) { //Skip the first entry in the lib for MD it is *bogus*
1338 idx++;
1339 continue;
1340 }
1341
1342 CSMidGameData data;
1343 for (int i = 0; i < 3; i++, idx++) {
1344 unsigned char *buf = lib_n.get_item(idx, NULL);
1345 data.text.push_back(string((const char *)buf));
1346 free(buf);
1347 }
1348
1349 load_images_from_lib(&data.images, &lib_n, idx++);
1350
1351 if (game_type == NUVIE_GAME_MD) {
1352 load_images_from_lib(&data.images, &lib_n, idx++);
1353 }
1354
1355 v.push_back(data);
1356 }
1357
1358 return v;
1359 }
1360
load_text(const char * filename,uint8 idx)1361 Std::vector<Std::string> ScriptCutscene::load_text(const char *filename, uint8 idx) {
1362 Std::string path;
1363 U6Lib_n lib_n;
1364 Std::vector<string> v;
1365 unsigned char *buf = NULL;
1366
1367 config_get_path(config, filename, path);
1368
1369 if (!lib_n.open(path, 4, NUVIE_GAME_MD) || idx >= lib_n.get_num_items()) {
1370 return v;
1371 }
1372
1373 buf = lib_n.get_item(idx, NULL);
1374 uint16 len = lib_n.get_item_size(idx);
1375 if (buf != NULL) {
1376 uint16 start = 0;
1377 for (uint16 i = 0; i < len; i++) {
1378 if (buf[i] == '\r') {
1379 buf[i] = '\0';
1380 v.push_back(string((const char *)&buf[start]));
1381 i++;
1382 buf[i] = '\0'; // skip the '\n' character
1383 start = i + 1;
1384 }
1385 }
1386
1387 free(buf);
1388 }
1389
1390 return v;
1391 }
1392
print_text(CSImage * image,const char * s,uint16 * x,uint16 * y,uint16 startx,uint16 width,uint8 color)1393 void ScriptCutscene::print_text(CSImage *image, const char *s, uint16 *x, uint16 *y, uint16 startx, uint16 width, uint8 color) {
1394 int len = *x - startx;
1395 size_t start = 0;
1396 size_t found;
1397 Std::string str = s;
1398 Std::list<Std::string> tokens;
1399 int space_width = font->getStringWidth(" ");
1400 //uint16 x1 = startx;
1401
1402 found = str.findFirstOf(" ", start);
1403 while (found != string::npos) {
1404 Std::string token = str.substr(start, found - start);
1405
1406 int token_len = font->getStringWidth(token.c_str());
1407
1408 if (len + token_len + space_width > width) {
1409 //FIXME render line here.
1410 list<Std::string>::iterator it;
1411 int new_space = 0;
1412 if (tokens.size() > 1)
1413 new_space = floor((width - (len - space_width * (tokens.size() - 1))) / (tokens.size() - 1));
1414
1415 for (it = tokens.begin() ; it != tokens.end() ; it++) {
1416 *x = ((WOUFont *)font)->drawStringToShape(image->shp, (*it).c_str(), *x, *y, color);
1417 *x += new_space;
1418 }
1419 *y += 8;
1420 *x = startx;
1421 len = token_len + space_width;
1422 tokens.clear();
1423 tokens.push_back(token);
1424 } else {
1425 tokens.push_back(token);
1426 len += token_len + space_width;
1427 }
1428
1429 start = found + 1;
1430 found = str.findFirstOf(" ", start);
1431 }
1432
1433 list<Std::string>::iterator it;
1434
1435 for (it = tokens.begin() ; it != tokens.end() ; it++) {
1436 *x = ((WOUFont *)font)->drawStringToShape(image->shp, (*it).c_str(), *x, *y, color);
1437 *x += space_width;
1438 }
1439
1440 if (start < str.length()) {
1441 Std::string token = str.substr(start, str.length() - start);
1442 if (len + font->getStringWidth(token.c_str()) > width) {
1443 *y += 8;
1444 *x = startx;
1445 }
1446 *x = ((WOUFont *)font)->drawStringToShape(image->shp, token.c_str(), *x, *y, color);
1447 }
1448
1449
1450 //font->drawStringToShape(image->shp, string, x, y, color);
1451 }
1452
load_palette(const char * filename,int idx)1453 void ScriptCutscene::load_palette(const char *filename, int idx) {
1454 NuvieIOFileRead file;
1455 uint8 buf[0x240 + 1];
1456 uint8 unpacked_palette[0x300];
1457 Std::string path;
1458
1459 config_get_path(config, filename, path);
1460
1461
1462 if (file.open(path.c_str()) == false) {
1463 DEBUG(0, LEVEL_ERROR, "loading palette.\n");
1464 return;
1465 }
1466
1467 if (file.read4() == DELUXE_PAINT_MAGIC || has_file_extension(filename, ".lbm")) {
1468 //deluxe paint palette file.
1469 file.seek(0x30);
1470 file.readToBuf(unpacked_palette, 0x300);
1471 } else if (has_file_extension(filename, ".pal")) {
1472 U6Lib_n lib;
1473 lib.open(path, 4, NUVIE_GAME_MD);
1474 unsigned char *decomp_buf = lib.get_item(0, NULL);
1475 memcpy(unpacked_palette, &decomp_buf[idx * 0x300], 0x300);
1476
1477 free(decomp_buf);
1478 } else {
1479 file.seek(idx * 0x240);
1480
1481 file.readToBuf(buf, 0x240);
1482 buf[0x240] = 0; //protect from buf[byte_pos+1] overflow when processing last byte of data.
1483
1484 for (int i = 0; i < 0x100; i++) {
1485 for (int j = 0; j < 3; j++) {
1486 int byte_pos = (i * 3 * 6 + j * 6) / 8;
1487 int shift_val = (i * 3 * 6 + j * 6) % 8;
1488 int color = ((buf[byte_pos] +
1489 (buf[byte_pos + 1] << 8))
1490 >> shift_val) & 0x3F;
1491 unpacked_palette[i * 3 + j] = (uint8)(color << 2);
1492 }
1493 }
1494 }
1495
1496 /*
1497 printf("GIMP Palette\nName: U6 ending\n#\n");
1498 for (int i = 0; i < 0x100; i++)
1499 {
1500 for (int j = 0; j < 3; j++)
1501 {
1502 printf("% 3d ", unpacked_palette[i*3+j]);
1503 }
1504 printf(" untitled\n");
1505 }
1506 */
1507 screen->set_palette(unpacked_palette);
1508 }
1509
set_palette_entry(uint8 idx,uint8 r,uint8 g,uint8 b)1510 void ScriptCutscene::set_palette_entry(uint8 idx, uint8 r, uint8 g, uint8 b) {
1511 screen->set_palette_entry(idx, r, g, b);
1512 }
1513
rotate_palette(uint8 idx,uint8 length)1514 void ScriptCutscene::rotate_palette(uint8 idx, uint8 length) {
1515 screen->rotate_palette(idx, length);
1516 }
1517
set_update_interval(uint16 interval)1518 void ScriptCutscene::set_update_interval(uint16 interval) {
1519 loop_interval = interval;
1520 }
1521
set_screen_opacity(uint8 new_opacity)1522 void ScriptCutscene::set_screen_opacity(uint8 new_opacity) {
1523 screen_opacity = new_opacity;
1524 }
1525
hide_sprites()1526 void ScriptCutscene::hide_sprites() {
1527 for (Std::list<CSSprite *>::iterator it = sprite_list.begin(); it != sprite_list.end(); it++) {
1528 CSSprite *s = *it;
1529 if (s->visible)
1530 s->visible = false;
1531 }
1532 }
1533
update()1534 void ScriptCutscene::update() {
1535 if (cutScene->Status() == WIDGET_HIDDEN) {
1536 cutScene->Show();
1537 gui->force_full_redraw();
1538 }
1539
1540 if (rotate_game_palette) {
1541 GamePalette *pal = Game::get_game()->get_palette();
1542 if (pal) {
1543 pal->rotatePalette();
1544 }
1545 }
1546 gui->Display();
1547 screen->preformUpdate();
1548 sound_manager->update();
1549 wait();
1550 }
1551
wait()1552 void ScriptCutscene::wait() {
1553 uint32 now = SDL_GetTicks();
1554 if (next_time <= now) {
1555 next_time = now + loop_interval;
1556 return;
1557 }
1558
1559 uint32 delay = next_time - now;
1560 next_time += loop_interval;
1561 g_system->delayMillis(delay);
1562 }
1563
1564 /* Show the widget */
Display(bool full_redraw)1565 void ScriptCutscene::Display(bool full_redraw) {
1566 if (cursor && cursor->is_visible())
1567 cursor->clear();
1568
1569 if (solid_bg) {
1570 if (full_redraw)
1571 screen->fill(bg_color, 0, 0, area.width(), area.height());
1572 else
1573 screen->fill(bg_color, x_off, y_off, 320, 200);
1574 }
1575
1576 if (screen_opacity > 0) {
1577 for (Std::list<CSSprite *>::iterator it = sprite_list.begin(); it != sprite_list.end(); it++) {
1578 CSSprite *s = *it;
1579 if (s->visible) {
1580 if (s->image) {
1581 uint16 w, h;
1582 s->image->shp->get_size(&w, &h);
1583 uint16 x, y;
1584 s->image->shp->get_hot_point(&x, &y);
1585 screen->blit(x_off + s->x - x, y_off + s->y - y, s->image->shp->get_data(), 8, w, h, w, true, s->clip_rect.width() != 0 ? &s->clip_rect : &clip_rect, s->opacity);
1586 }
1587
1588 if (s->text.length() > 0) {
1589 if (s->text_align != 0) {
1590 display_wrapped_text(s);
1591 } else {
1592 if (s->text_color == 0xffff) {
1593 font->drawString(screen, s->text.c_str(), s->x + x_off, s->y + y_off);
1594 } else {
1595 font->drawString(screen, s->text.c_str(), s->x + x_off, s->y + y_off, (uint8) s->text_color, (uint8) s->text_color);
1596 }
1597 }
1598 }
1599 }
1600 }
1601
1602 if (screen_opacity < 255) {
1603 screen->fade(x_off, y_off, 320, 200, screen_opacity, bg_color);
1604 }
1605 }
1606
1607 if (cursor)
1608 cursor->display();
1609
1610 if (full_redraw)
1611 screen->update(0, 0, area.width(), area.height());
1612 else
1613 screen->update(x_off, y_off, 320, 200);
1614 }
1615
Hide()1616 void ScriptCutscene::Hide() {
1617 GUI_Widget::Hide();
1618 gui->force_full_redraw();
1619 }
1620
display_wrapped_text(CSSprite * s)1621 void ScriptCutscene::display_wrapped_text(CSSprite *s) {
1622 uint8 text_color = (uint8) s->text_color;
1623
1624 size_t start = 0;
1625 size_t found;
1626 Std::string str = s->text + "^";
1627 Std::list<Std::string> tokens;
1628 int y = s->y;
1629
1630
1631 Std::string line = "";
1632
1633 found = str.findFirstOf("^", start);
1634 while (found != string::npos) {
1635 Std::string token = str.substr(start, found - start);
1636
1637 y = display_wrapped_text_line(token, text_color, s->x, y, s->text_align);
1638
1639 start = found + 1;
1640 found = str.findFirstOf("^", start);
1641 }
1642 }
1643
display_wrapped_text_line(Std::string str,uint8 text_color,int x,int y,uint8 align_val)1644 int ScriptCutscene::display_wrapped_text_line(Std::string str, uint8 text_color, int x, int y, uint8 align_val) {
1645
1646 //font->drawString(screen, s->text.c_str(), s->x + x_off, s->y + y_off, text_color, text_color);
1647 int len = 0;
1648 size_t start = 0;
1649 size_t found;
1650 str = str + " ";
1651 Std::list<Std::string> tokens;
1652 int space_width = font->getStringWidth(" ");
1653 //uint16 x1 = startx;
1654 int width = 320 - x * 2;
1655
1656 int char_height = font->getCharHeight();
1657
1658 Std::string line = "";
1659
1660 found = str.findFirstOf(" ", start);
1661 while (found != string::npos) {
1662 Std::string token = str.substr(start, found - start);
1663
1664 int token_len = font->getStringWidth(token.c_str());
1665
1666 if (len + token_len > width) {
1667 if (len > 0) {
1668 len -= space_width;
1669 }
1670 font->drawString(screen, line.c_str(), x + x_off + (align_val == 1 ? 0 : (width - len)) / 2, y + y_off, text_color, text_color);
1671 line = "";
1672 y += char_height + 2;
1673 len = 0;
1674 }
1675
1676 len += token_len + space_width;
1677 line = line + token + " ";
1678
1679 start = found + 1;
1680 found = str.findFirstOf(" ", start);
1681 }
1682
1683 if (len > 0) {
1684 len -= space_width;
1685 font->drawString(screen, line.c_str(), x + x_off + (align_val == 1 ? 0 : (width - len)) / 2, y + y_off, text_color, text_color);
1686 y += char_height + 2;
1687 }
1688
1689 return y;
1690 }
setScale(uint16 percentage)1691 void CSImage::setScale(uint16 percentage) {
1692 if (scale == percentage) {
1693 return;
1694 }
1695
1696 if (scaled_shp)
1697 delete scaled_shp;
1698
1699 scale = percentage;
1700 if (scale == 100) {
1701 scaled_shp = NULL;
1702 shp = orig_shp;
1703 return;
1704 }
1705
1706 uint16 sw, sh;
1707 uint16 sx, sy;
1708
1709 uint16 tw, th;
1710 uint16 tx, ty;
1711
1712 float scale_factor = (float)scale / 100;
1713
1714 orig_shp->get_size(&sw, &sh);
1715 orig_shp->get_hot_point(&sx, &sy);
1716
1717 tw = (uint16)((float)sw * scale_factor);
1718 th = (uint16)((float)sh * scale_factor);
1719 tx = (uint16)((float)sx * scale_factor);
1720 ty = (uint16)((float)sy * scale_factor);
1721
1722 scaled_shp = new U6Shape();
1723 if (!scaled_shp->init(tw, th, tx, ty)) {
1724 scale = 100;
1725 delete scaled_shp;
1726 scaled_shp = NULL;
1727 return;
1728 }
1729
1730 scale_rect_8bit(orig_shp->get_data(), scaled_shp->get_data(), sw, sh, tw, th);
1731 shp = scaled_shp;
1732
1733 return;
1734 }
1735
CSStarFieldImage(U6Shape * shape)1736 CSStarFieldImage::CSStarFieldImage(U6Shape *shape) : CSImage(shape) {
1737 shp->get_size(&w, &h);
1738
1739 for (int i = 0; i < STAR_FIELD_NUM_STARS; i++) {
1740 stars[i].color = 2;
1741 stars[i].line = NULL;
1742 }
1743 }
1744
updateEffect()1745 void CSStarFieldImage::updateEffect() {
1746 unsigned char *data = shp->get_data();
1747
1748 memset(data, 0, w * h);
1749
1750 for (int i = 0; i < STAR_FIELD_NUM_STARS; i++) {
1751 if (stars[i].line == NULL) {
1752 switch (NUVIE_RAND() % 4) {
1753 case 0 :
1754 stars[i].line = new U6LineWalker(w / 2, h / 2, 0, NUVIE_RAND() % h);
1755 break;
1756 case 1 :
1757 stars[i].line = new U6LineWalker(w / 2, h / 2, w - 1, NUVIE_RAND() % h);
1758 break;
1759 case 2 :
1760 stars[i].line = new U6LineWalker(w / 2, h / 2, NUVIE_RAND() % w, 0);
1761 break;
1762 case 3 :
1763 stars[i].line = new U6LineWalker(w / 2, h / 2, NUVIE_RAND() % w, h - 1);
1764 break;
1765 }
1766
1767 stars[i].color = NUVIE_RAND() % 10 + 229;
1768 uint16 start_pos = NUVIE_RAND() % (w / 2);
1769 for (int j = 0; j < start_pos; j++) {
1770 if (stars[i].line->step() == false) {
1771 delete stars[i].line;
1772 stars[i].line = NULL;
1773 break;
1774 }
1775 }
1776 } else {
1777 uint32 cur_x, cur_y;
1778 if (stars[i].line->next(&cur_x, &cur_y) == false) {
1779 delete stars[i].line;
1780 stars[i].line = NULL;
1781 } else {
1782 data[cur_y * w + cur_x] = stars[i].color;
1783 }
1784 }
1785 }
1786 }
1787
1788 } // End of namespace Nuvie
1789 } // End of namespace Ultima
1790