root/scn2k/scn2k_textimpl.cc

Revision 68:043d5db57474, 16.3 KB (checked in by Thibaut Girka <thib@…>, 15 months ago)
Fix index_series implementation (still incomplete)
Line 
1/*
2 * Copyright (c) 2009 Thibaut GIRKA
3 * Copyright (c) 2004-2006  Kazunori "jagarl" Ueno
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "scn2k_text.h"
30
31void Text::impl_txtClear(Cmd& cmd) {
32        if (text != NULL) {
33                text->ResetFace();
34                if (cmd.cmd2 == 3 && cmd.cmd3 == 151)
35                        text->wid->Clear();
36        }
37        cur_backlog_item.face = "";
38        if (cmd.cmd2 == 3 && cmd.cmd3 == 151)
39                text_stream.Clear();
40        hide();
41}
42
43void Text::impl_logKoe(Cmd& cmd) {
44        // PlayKoe ; 声出力コマンドをチェックする */
45        cur_backlog_item.koe = cmd.args[0].value;
46}
47
48void Text::impl_pause(Cmd& cmd) {
49        if (text != NULL) {
50                eprintf("start\n");
51                text->StartText(text_stream);
52                if (skip_mode & SKIP_TEXT) text->wid->Flush();
53                else if (kcursor) kcursor->show();
54                status = WAIT_TEXT;
55                text_parsing = false;
56        }
57        backlog_item = cur_backlog_item;
58        if (cur_backlog_item.scn == 0 && cur_backlog_item.pos == -1) backlog_item.text = text_stream;
59        cur_backlog_item.Clear();
60
61        cmd.clear();
62        cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
63}
64
65void Text::impl_PauseCursor(Cmd& cmd)
66{
67        /* なんかよくわからないけどカヌ゜ル圢状倉曎にしずく */
68        SetCursor(cmd.args[0].value);
69        cmd.clear();
70}
71
72void Text::impl_br(Cmd& cmd) {
73        text_stream.AddReturn();
74        cur_backlog_item.DeleteTextPos();
75        cmd.clear();
76}
77
78void Text::impl_FaceOpen(Cmd& cmd) {
79        if (text == NULL)
80                show();
81        string s = cmd.Str(cmd.args[0]);
82        s += ".g00";
83        if (text != NULL)
84                text->ShowFace(s.c_str());
85        cur_backlog_item.face = s;
86        cmd.cmd_type = CMD_SAVECMD_ONCE;
87}
88
89void Text::impl_FaceClear(Cmd& cmd) {
90        if (text == NULL)
91                show();
92        if (text)
93                text->ResetFace();
94        cur_backlog_item.face = "";
95        cmd.cmd_type = CMD_SAVECMD_ONCE;
96}
97
98void Text::impl_doRuby(Cmd& cmd) {
99        if (text == NULL) {
100                show();
101        }
102        if (cmd.cmd4 == 1) {
103                ruby_text_flag = true;
104                eprintf("SetRubyText.");
105                cmd.clear();
106        } else if (cmd.cmd4 == 0) {
107                if (ruby_text.length() == 0) { // ルビを振るテキストがない
108                        eprintf("Cannot find ruby text.\n");
109                        return;
110                }
111                if (cmd.args.size() != 1) return;
112                char debug1[1024], debug2[1024];
113                kconv( (unsigned char*)ruby_text.c_str(), (unsigned char*)debug1);
114                kconv( (unsigned char*)cmd.Str(cmd.args[0]), (unsigned char*)debug2);
115                eprintf("SetRuby. %s, %s",debug1, debug2);
116                text_stream.AddRuby(ruby_text.c_str(), cmd.Str(cmd.args[0]));
117                cur_backlog_item.DeleteTextPos();
118                cmd.clear();
119        }
120}
121
122void Text::impl_TextWindow(Cmd& cmd) {
123        if (cmd.cmd4 == 0) {
124                eprintf("set text window <- %d\n",cmd.args[0].value);
125                if (text != NULL) show(cmd.args[0].value);
126                else text_window_number = cmd.args[0].value;
127        } else if (cmd.cmd4 == 1) { // default value
128                eprintf("set text window <- default\n");
129                if (text != NULL) show(0);
130                else text_window_number = 0;
131        }
132        cmd.clear();
133}
134
135void Text::impl_FastText(Cmd& cmd) {
136        //I think it's broken. For now, it's disabled.
137        if (cmd.cmd3 == 103) {
138                // テキストりィンドり衚瀺
139                show();
140// 衚瀺の際はテキストをクリアしない
141//              if (text) text->wid->Clear();
142//              text_stream.Clear();
143                cmd.clear();
144        }
145        else if (cmd.cmd3 == 104) { // テキスト衚瀺
146                // 党テキスト衚瀺
147                if (text != NULL) {
148                        text->StartText(text_stream);
149                        text->wid->Flush();
150                }
151                cmd.clear();
152        }
153}
154
155void Text::impl_msgClear(Cmd& cmd) {
156        show();
157        if (text != NULL) text->wid->Clear();
158        text_stream.Clear();
159        cmd.clear();
160}
161
162void Text::impl_createSelect(Cmd& cmd) {
163        if (cmd.cmd4 == 0) {
164                // 遞択肢
165                CreateSelect(cmd);
166                //FIXME: Check if it's really clean
167                if (text_parsing) {
168                        show();
169                        text->StartText(text_stream);
170                        if (skip_mode & SKIP_TEXT) text->wid->Flush();
171                        else if (kcursor) kcursor->hide();
172                        text_parsing = false;
173                                text_stream.Clear();
174                }
175                cmd.cmd_type = CMD_ROLLBACKPOINT; /* 遞択肢はセヌブ䜍眮 / シナリオ巻き戻し䜍眮 */
176                // cmd.clear();
177        }
178        else
179                PrintCmd(cmd); //FIXME
180}
181
182void Text::impl_ShowBackground(Cmd& cmd) {
183        status_mask = Status(CLEARSCR_MASK | status_mask);
184        cmd.clear();
185}
186
187void Text::impl_SetSkipMode(Cmd& cmd) {
188        status_mask = Status(SKIPMASK | status_mask);
189        cmd.clear();
190}
191
192void Text::impl_Wait(Cmd& cmd) {
193        eprintf("wait %dmsec\n",cmd.args[0].value);
194
195        if (cmd.cmd3 == 100 && text != NULL) {
196                /* 0x64 だず文字描画䞭の埅ちに䜿うこずがある */
197                text->StartText(text_stream);
198                text->wid->Flush();
199        }
200
201        if (cmd.cmd3 == 111 || cmd.cmd3 == 112 || cmd.cmd3 == 121)
202        {
203                int index;
204                if (cmd.cmd4 == 1)
205                        index = 0;
206                else
207                        index = cmd.args[1].value;
208                wait_time = timer_var[index].start_time + cmd.args[0].value;
209        }
210        else
211                wait_time = old_time + cmd.args[0].value;
212
213        if (cmd.cmd3 == 101 || cmd.cmd3 == 112)
214                status = WAIT_CLICK;
215        else
216                status = WAIT;
217
218        cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
219}
220
221void Text::impl_GetClick(Cmd& cmd) {
222        eprintf("wait and get mouse pos at click\n");
223        wait_time = old_time + 1000 * 1000;
224        status = WAIT_CLICK_MOUSEPOS;
225        wait_savedvar[0] = cmd.args[0];
226        wait_savedvar[1] = cmd.args[1];
227        cmd.clear();
228}
229
230void Text::impl_ResetTimer(Cmd& cmd) {
231        int index;
232
233        if (cmd.cmd4 == 1)
234                index = 0;
235        else
236                index = cmd.args[0].value;
237
238        eprintf("set basetime (%d)\n",index);
239        //TODO: Handle EX timer set
240        TimerAtom& atom = timer_var[index];
241        atom.start_time = old_time;
242
243        cmd.clear();
244}
245
246void Text::impl_Timer(Cmd& cmd) {
247        int index;
248
249        if (cmd.cmd4 == 1)
250                index = 0;
251        else
252                index = cmd.args[0].value;
253
254        eprintf("get time %dth\n",index);
255        if (timer_var.find(index) == timer_var.end())
256                cmd.SetSysvar(0);
257        else
258                cmd.SetSysvar(old_time - timer_var[index].start_time);
259}
260
261void Text::impl_ReadFrame(Cmd& cmd) {
262        eprintf("get timer value[%d]\n", cmd.args[0].value);
263        if (frame_var.find(cmd.args[0].value) == frame_var.end())
264                cmd.SetSysvar(0);
265        else {
266                FrameTimerAtom& atom = frame_var[cmd.args[0].value];
267                if (atom.total_time <= 0) atom.total_time = 1;
268                int cur_tm = old_time - atom.start_time;
269                if (cur_tm < 0) cur_tm = atom.total_time; // ゚ラヌなら最終時間に合わせる
270                if (cur_tm > atom.total_time) cur_tm = atom.total_time;
271                // use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
272                int v = atom.from + (long long)(atom.to - atom.from)*cur_tm/int(atom.total_time);
273                cmd.SetSysvar(v);
274        }
275}
276
277void Text::impl_InitFrame(Cmd& cmd) {
278        FrameTimerAtom& atom = frame_var[cmd.args[0].value];
279        atom.from = cmd.args[1].value;
280        atom.to = cmd.args[2].value;
281        atom.total_time = cmd.args[3].value;
282        atom.start_time = old_time;
283        cmd.clear();
284}
285
286void Text::impl_InitFrames(Cmd& cmd) {
287        int i, j = 0;
288        for (i = 0; i < cmd.argc; i++)
289        {
290                int cnt = cmd.args[j++].value; // £³€Ê€Î€Ç̵»ë
291                int num = cmd.args[j++].value;
292                FrameTimerAtom& atom = frame_var[num];
293                atom.from = cmd.args[j++].value;
294                atom.to = cmd.args[j++].value;
295                atom.total_time = cmd.args[j++].value;
296                atom.start_time = old_time;
297        }
298        cmd.clear();
299}
300
301void Text::impl_ReadFrames(Cmd& cmd) {
302        vector<VarInfo> args = cmd.args;
303        vector<VarInfo>::iterator it = args.begin();
304        int argc = cmd.argc;
305        int timers_active = 0;
306        int i;
307        for (i=0; i < argc; i++)
308        {
309                int cnt = (it++)->value;
310                int num = (it++)->value;
311
312                if (frame_var.find(num) == frame_var.end()) {
313                        cmd.SetFlagvar(*it++, 0);
314                }
315                else
316                {
317                        FrameTimerAtom& atom = frame_var[num];
318                        if (atom.total_time <= 0)
319                                atom.total_time = 1;
320                        int cur_tm = old_time - atom.start_time;
321                        if (cur_tm < 0)
322                                cur_tm = atom.total_time; // ¥š¥é¡Œ€Ê€éºÇœª»ßŜր˹ç€ï€»€ë
323                        if (cur_tm > atom.total_time)
324                                cur_tm = atom.total_time;
325                        // use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
326                        int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
327                        cmd.SetFlagvar(*it++, v);
328                        if (atom.total_time != -1 && cur_tm < atom.total_time)
329                                timers_active = 1;
330                }
331        }
332        cmd.SetSysvar(timers_active);
333}
334
335#include "math.h"
336
337void Text::impl_rnd(Cmd& cmd)
338{
339        /* rand() */
340        int min, max;
341        if (cmd.args.size() == 2)
342        {
343                min = cmd.args[0].value;
344                max = cmd.args[1].value;
345        }
346        else
347        {
348                min = 0;
349                max = cmd.args[0].value;
350        }
351        if (min > max)
352        {
353                int tmp = max;
354                max = min;
355                min = tmp;
356        }
357        int r = random();
358        if (min == max)
359                r = min;
360        else
361                r = (r % (max-min)) + min;
362        cmd.SetSysvar(r);
363}
364
365void Text::impl_pcnt(Cmd& cmd)
366{
367        cmd.SetSysvar(100 * cmd.args[0].value / cmd.args[1].value);
368}
369
370void Text::impl_abs(Cmd& cmd)
371{
372        cmd.SetSysvar(abs(cmd.args[0].value));
373}
374
375void Text::impl_power(Cmd& cmd)
376{
377        cmd.SetSysvar(pow(cmd.args[0].value, cmd.args[1].value));
378}
379
380void Text::impl_sin(Cmd& cmd)
381{
382        cmd.SetSysvar(sin(cmd.args[0].value * M_PI / 180) * 32640 / cmd.args[1].value);
383}
384
385void Text::impl_min(Cmd& cmd)
386{
387        int a = cmd.args[0].value;
388        int b = cmd.args[1].value;
389        cmd.SetSysvar((a < b) ? a : b);
390}
391
392void Text::impl_max(Cmd& cmd)
393{
394        int a = cmd.args[0].value;
395        int b = cmd.args[1].value;
396        cmd.SetSysvar((a > b) ? a : b);
397}
398
399void Text::impl_index_series(Cmd& cmd)
400{
401        //TODO: This one is not fully documented in
402        // http://dev.haeleth.net/rldev/manual.html
403        // Try to figure out what's it...
404
405        /* range conversion : 比率に䞞める */
406        // アルゎリズムは間違えおるような気がする
407        //
408        if (cmd.args.size() >= 7)
409        {
410                int i, val;
411                int x, startval;
412                int start, end, endval, mode;
413
414                //TODO: why index and offset, and not x?
415                x = cmd.args[0].value + cmd.args[1].value;
416                startval = cmd.args[2].value;
417                start = end = 0;
418                val = endval = startval;
419                for (i=3; i < cmd.args.size(); i += 4)
420                {
421                        startval = endval;
422                        start = cmd.args[i].value;
423                        end = cmd.args[i + 1].value;
424                        endval = cmd.args[i + 2].value;
425                        int mode = cmd.args[i + 3].value;
426                        if (start <= x && x <= end)
427                        {
428                                // rldev : mode == 1,3 : 'acceralating curve', 2,3: 'decelerating curve'
429                                // 耇数の匕数リスト(r_minからmodeたでのリスト)も぀こずもあり、その堎合は
430                                // "cancel out in some way" らしい
431                                // Assume mode 0, as we only know of it
432                                // TODO: find out how other mode works (exp/log?)
433                                // TODO: "When two ranges overlap, they appear to cancel out in some way"
434                                val = startval + (endval - startval) * (x - start) / (end - start);
435                        }
436                }
437                if (i != cmd.args.size())
438                        fprintf(stderr, "\n%d/%d: cmd 01-04:0320 : WARNING: %d unconsumed arguments\n", cmd.scn, cmd.pos, cmd.args.size() - i);
439                if (x > end)
440                        x = endval;
441                cmd.SetSysvar(val);
442        }
443        else
444                fprintf(stderr, "\n%d/%d: cmd 01-04:0320 : Not enough arguments?!\n", cmd.scn, cmd.pos);
445}
446
447void Text::impl_constrain(Cmd& cmd)
448{
449        /* range 内に䞞める */
450        int min = cmd.args[0].value;
451        int val = cmd.args[1].value;
452        int max = cmd.args[2].value;
453        if (min > max) {
454                max = cmd.args[0].value;
455                min = cmd.args[2].value;
456        }
457        if (val < min)
458                val = min;
459        if (val > max)
460                val = max;
461        cmd.SetSysvar(val);
462}
463
464
465void Text::impl_load(Cmd& cmd)
466{
467        // メニュヌからのロヌド
468        cmd.cmd_type = CMD_LOADREQ;
469}
470
471void Text::impl_GetWindowAttr(Cmd& cmd)
472{
473        // テキストりィンドりの色蚭定
474        int r, g, b, a, flag;
475
476        if (cmd.cmd3 == 2617) // 元蚭定を取り出す
477                config->GetOriginalParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
478        else
479                config->GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
480
481        if (cmd.args.size() != 5) {
482                fprintf(stderr,"cmd 01-04:%4d : invalid arg size\n", cmd.cmd3);
483        } else {
484                vector<VarInfo> args(cmd.args);
485                cmd.SetFlagvar(args[0], r);
486                cmd.SetFlagvar(args[1], g);
487                cmd.SetFlagvar(args[2], b);
488                cmd.SetFlagvar(args[3], a);
489                cmd.SetFlagvar(args[4], flag);
490        }
491}
492
493void Text::impl_SetWindowAttr(Cmd& cmd)
494{
495        int r, g, b, a, flag;
496        config->GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
497
498        switch(cmd.cmd3) {
499                case 2260:
500                        r = cmd.args[0].value;
501                        break;
502                case 2261:
503                        g = cmd.args[0].value;
504                        break;
505                case 2262:
506                        b = cmd.args[0].value;
507                        break;
508                case 2263:
509                        a = cmd.args[0].value;
510                        break;
511                case 2264:
512                        flag = cmd.args[0].value;
513                        break;
514                case 2267: 
515                        r = cmd.args[0].value;
516                        g = cmd.args[1].value;
517                        b = cmd.args[2].value;
518                        a = cmd.args[3].value;
519                        flag = cmd.args[4].value;
520                        break;
521        }
522        config->SetParam("#WINDOW_ATTR", 5, r, g, b, a, flag);
523        SetWindowColor(r, g, b, a, flag);
524        cmd.clear();
525}
526
527void Text::impl_GetDefConfig(Cmd& cmd)
528{
529        int v = 0;
530        switch(cmd.cmd3) {
531                case 2600:
532                case 2605:
533                        config->GetOriginalParam("#INIT_MESSAGE_SPEED", 1, &v);
534                        break;
535                case 2601:
536                        config->GetOriginalParam("#INIT_MESSAGE_SPEED_MOD", 1, &v);
537                        break;
538                case 2604:
539                        config->GetOriginalParam("#MESSAGE_KEY_WAIT_USE", 1, &v);
540                        break;
541                case 2606:
542                        config->GetOriginalParam("#MESSAGE_KEY_WAIT_TIME", 1, &v);
543                        break;
544        }
545        cmd.SetSysvar(v);
546}
547
548void Text::impl_GetConfig(Cmd& cmd)
549{
550        int v;
551        switch (cmd.cmd3)
552        {
553                case 2323:
554                case 2351:
555                        config->GetParam("#INIT_MESSAGE_SPEED", 1, &v);
556                        break;
557                case 2324:
558                        config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &v);
559                        break;
560                case 2350:
561                        config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &v);
562                        break;
563                case 2352:
564                        config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &v);
565                        break;
566        }
567
568        cmd.SetSysvar(v);
569}
570
571void Text::impl_SetConfig(Cmd& cmd)
572{
573        int speed, use_speed_mod, wait, use_wait_mod;
574        config->GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
575        config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &use_speed_mod);
576        config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &use_wait_mod);
577        config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
578        switch (cmd.cmd3)
579        {
580                case 2223:
581                case 2251:
582                        speed = cmd.args[0].value;
583                        if (speed < 10) //FIXME: ??? 0 ???
584                                speed = 10;
585                        if (speed > 10000) //FIXME: ??? 255 ???
586                                speed = 10000;
587                        config->SetParam("#INIT_MESSAGE_SPEED", 1, speed);
588                        break;
589                case 2224:
590                        use_speed_mod = cmd.args[0].value;
591                        config->SetParam("#INIT_MESSAGE_SPEED_MOD", 1, use_speed_mod);
592                        break;
593                case 2250:
594                        use_wait_mod = cmd.args[0].value;
595                        config->SetParam("#MESSAGE_KEY_WAIT_USE", 1, use_wait_mod);
596                        break;
597                case 2252:
598                        int wait = cmd.args[0].value;
599                        if (wait < 0)
600                                wait = 0;
601                        else if (wait > 60000)
602                                wait = 60000;
603                        config->SetParam("#MESSAGE_KEY_WAIT_TIME", 1, wait);
604                        break;
605        }
606
607        if (use_speed_mod) // FIXME: Not the other way around?
608                SetTextSpeed(-1);
609        else
610                SetTextSpeed(speed);
611
612        if (use_wait_mod)
613                SetTextWait(wait);
614        else
615                SetTextWait(-1);
616
617        cmd.clear();
618}
619
620void Text::impl_GetName(Cmd& cmd)
621{
622        // replace_name を埗る
623        int n = cmd.args[0].value;
624        if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
625                cmd.SetStrvar(cmd.args[1], replace_name[n]);
626        else
627                cmd.SetStrvar(cmd.args[1], "");
628}
629
630void Text::impl_SetName(Cmd& cmd)
631{
632        // replace_name を埗る
633        int n = cmd.args[0].value;
634        if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
635                replace_name[n] = cmd.Str(cmd.args[1]);
636}
637
638void Text::impl_GetLocalName(Cmd& cmd)
639{
640        // replace_name2 を埗る
641        int n = cmd.args[0].value;
642        if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
643                cmd.SetStrvar(cmd.args[1], replace_name2[n]);
644        else
645                cmd.SetStrvar(cmd.args[1], "");
646}
647
648void Text::impl_SetLocalName(Cmd& cmd)
649{
650        // replace_name2 の蚭定
651        int n = cmd.args[0].value;
652        if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
653                replace_name2[n] = cmd.Str(cmd.args[1]);
654
655        cmd.clear();
656}
657
Note: See TracBrowser for help on using the browser.