1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 
15 #include <stdio.h>
16 #include "ac/dialog.h"
17 #include "ac/common.h"
18 #include "ac/character.h"
19 #include "ac/characterinfo.h"
20 #include "ac/dialogtopic.h"
21 #include "ac/display.h"
22 #include "ac/draw.h"
23 #include "ac/gamestate.h"
24 #include "ac/gamesetupstruct.h"
25 #include "ac/global_character.h"
26 #include "ac/global_dialog.h"
27 #include "ac/global_display.h"
28 #include "ac/global_game.h"
29 #include "ac/global_gui.h"
30 #include "ac/global_room.h"
31 #include "ac/global_translation.h"
32 #include "ac/keycode.h"
33 #include "ac/overlay.h"
34 #include "ac/mouse.h"
35 #include "ac/parser.h"
36 #include "ac/record.h"
37 #include "ac/string.h"
38 #include "ac/dynobj/scriptdialogoptionsrendering.h"
39 #include "ac/dynobj/scriptdrawingsurface.h"
40 #include "ac/system.h"
41 #include "font/fonts.h"
42 #include "script/cc_instance.h"
43 #include "gui/guimain.h"
44 #include "gui/guitextbox.h"
45 #include "main/game_run.h"
46 #include "media/audio/audio.h"
47 #include "platform/base/agsplatformdriver.h"
48 #include "script/script.h"
49 #include "ac/spritecache.h"
50 #include "gfx/ddb.h"
51 #include "gfx/gfx_util.h"
52 #include "gfx/graphicsdriver.h"
53 
54 using namespace AGS::Common;
55 
56 extern GameSetupStruct game;
57 extern GameState play;
58 extern ccInstance *dialogScriptsInst;
59 extern int in_new_room;
60 extern CharacterInfo*playerchar;
61 extern SpriteCache spriteset;
62 extern int spritewidth[MAX_SPRITES],spriteheight[MAX_SPRITES];
63 extern volatile int timerloop;
64 extern AGSPlatformDriver *platform;
65 extern int cur_mode,cur_cursor;
66 extern Bitmap *virtual_screen;
67 extern IGraphicsDriver *gfxDriver;
68 
69 DialogTopic *dialog;
70 ScriptDialogOptionsRendering ccDialogOptionsRendering;
71 ScriptDrawingSurface* dialogOptionsRenderingSurface;
72 
73 int said_speech_line; // used while in dialog to track whether screen needs updating
74 
75 // Old dialog support
76 std::vector< stdtr1compat::shared_ptr<unsigned char> > old_dialog_scripts;
77 std::vector<String> old_speech_lines;
78 
79 int said_text = 0;
80 int longestline = 0;
81 
82 
83 
84 
Dialog_Start(ScriptDialog * sd)85 void Dialog_Start(ScriptDialog *sd) {
86   RunDialog(sd->id);
87 }
88 
89 #define CHOSE_TEXTPARSER -3053
90 #define SAYCHOSEN_USEFLAG 1
91 #define SAYCHOSEN_YES 2
92 #define SAYCHOSEN_NO  3
93 
Dialog_DisplayOptions(ScriptDialog * sd,int sayChosenOption)94 int Dialog_DisplayOptions(ScriptDialog *sd, int sayChosenOption)
95 {
96   if ((sayChosenOption < 1) || (sayChosenOption > 3))
97     quit("!Dialog.DisplayOptions: invalid parameter passed");
98 
99   int chose = show_dialog_options(sd->id, sayChosenOption, (game.options[OPT_RUNGAMEDLGOPTS] != 0));
100   if (chose != CHOSE_TEXTPARSER)
101   {
102     chose++;
103   }
104   return chose;
105 }
106 
Dialog_SetOptionState(ScriptDialog * sd,int option,int newState)107 void Dialog_SetOptionState(ScriptDialog *sd, int option, int newState) {
108   SetDialogOption(sd->id, option, newState);
109 }
110 
Dialog_GetOptionState(ScriptDialog * sd,int option)111 int Dialog_GetOptionState(ScriptDialog *sd, int option) {
112   return GetDialogOption(sd->id, option);
113 }
114 
Dialog_HasOptionBeenChosen(ScriptDialog * sd,int option)115 int Dialog_HasOptionBeenChosen(ScriptDialog *sd, int option)
116 {
117   if ((option < 1) || (option > dialog[sd->id].numoptions))
118     quit("!Dialog.HasOptionBeenChosen: Invalid option number specified");
119   option--;
120 
121   if (dialog[sd->id].optionflags[option] & DFLG_HASBEENCHOSEN)
122     return 1;
123   return 0;
124 }
125 
Dialog_SetHasOptionBeenChosen(ScriptDialog * sd,int option,bool chosen)126 void Dialog_SetHasOptionBeenChosen(ScriptDialog *sd, int option, bool chosen)
127 {
128     if (option < 1 || option > dialog[sd->id].numoptions)
129     {
130         quit("!Dialog.HasOptionBeenChosen: Invalid option number specified");
131     }
132     option--;
133     if (chosen)
134     {
135         dialog[sd->id].optionflags[option] |= DFLG_HASBEENCHOSEN;
136     }
137     else
138     {
139         dialog[sd->id].optionflags[option] &= ~DFLG_HASBEENCHOSEN;
140     }
141 }
142 
Dialog_GetOptionCount(ScriptDialog * sd)143 int Dialog_GetOptionCount(ScriptDialog *sd)
144 {
145   return dialog[sd->id].numoptions;
146 }
147 
Dialog_GetShowTextParser(ScriptDialog * sd)148 int Dialog_GetShowTextParser(ScriptDialog *sd)
149 {
150   return (dialog[sd->id].topicFlags & DTFLG_SHOWPARSER) ? 1 : 0;
151 }
152 
Dialog_GetOptionText(ScriptDialog * sd,int option)153 const char* Dialog_GetOptionText(ScriptDialog *sd, int option)
154 {
155   if ((option < 1) || (option > dialog[sd->id].numoptions))
156     quit("!Dialog.GetOptionText: Invalid option number specified");
157 
158   option--;
159 
160   return CreateNewScriptString(get_translation(dialog[sd->id].optionnames[option]));
161 }
162 
Dialog_GetID(ScriptDialog * sd)163 int Dialog_GetID(ScriptDialog *sd) {
164   return sd->id;
165 }
166 
167 //=============================================================================
168 
169 #define RUN_DIALOG_STAY          -1
170 #define RUN_DIALOG_STOP_DIALOG   -2
171 #define RUN_DIALOG_GOTO_PREVIOUS -4
172 // dialog manager stuff
173 
get_dialog_script_parameters(unsigned char * & script,unsigned short * param1,unsigned short * param2)174 void get_dialog_script_parameters(unsigned char* &script, unsigned short* param1, unsigned short* param2)
175 {
176   script++;
177   *param1 = *script;
178   script++;
179   *param1 += *script * 256;
180   script++;
181 
182   if (param2)
183   {
184     *param2 = *script;
185     script++;
186     *param2 += *script * 256;
187     script++;
188   }
189 }
190 
run_dialog_script(DialogTopic * dtpp,int dialogID,int offse,int optionIndex)191 int run_dialog_script(DialogTopic*dtpp, int dialogID, int offse, int optionIndex) {
192   said_speech_line = 0;
193   int result = RUN_DIALOG_STAY;
194 
195   if (dialogScriptsInst)
196   {
197     char funcName[100];
198     sprintf(funcName, "_run_dialog%d", dialogID);
199     dialogScriptsInst->RunTextScriptIParam(funcName, RuntimeScriptValue().SetInt32(optionIndex));
200     result = dialogScriptsInst->returnValue;
201   }
202   else
203   {
204     // old dialog format
205     if (offse == -1)
206       return result;
207 
208     unsigned char* script = old_dialog_scripts[dialogID].get() + offse;
209 
210     unsigned short param1 = 0;
211     unsigned short param2 = 0;
212     bool script_running = true;
213 
214     while (script_running)
215     {
216       switch (*script)
217       {
218         case DCMD_SAY:
219           get_dialog_script_parameters(script, &param1, &param2);
220 
221           if (param1 == DCHAR_PLAYER)
222             param1 = game.playercharacter;
223 
224           if (param1 == DCHAR_NARRATOR)
225             Display(get_translation(old_speech_lines[param2]));
226           else
227             DisplaySpeech(get_translation(old_speech_lines[param2]), param1);
228 
229           said_speech_line = 1;
230           break;
231 
232         case DCMD_OPTOFF:
233           get_dialog_script_parameters(script, &param1, NULL);
234           SetDialogOption(dialogID, param1 + 1, 0, true);
235           break;
236 
237         case DCMD_OPTON:
238           get_dialog_script_parameters(script, &param1, NULL);
239           SetDialogOption(dialogID, param1 + 1, DFLG_ON, true);
240           break;
241 
242         case DCMD_RETURN:
243           script_running = false;
244           break;
245 
246         case DCMD_STOPDIALOG:
247           result = RUN_DIALOG_STOP_DIALOG;
248           script_running = false;
249           break;
250 
251         case DCMD_OPTOFFFOREVER:
252           get_dialog_script_parameters(script, &param1, NULL);
253           SetDialogOption(dialogID, param1 + 1, DFLG_OFFPERM, true);
254           break;
255 
256         case DCMD_RUNTEXTSCRIPT:
257           get_dialog_script_parameters(script, &param1, NULL);
258           result = run_dialog_request(param1);
259           script_running = (result == RUN_DIALOG_STAY);
260           break;
261 
262         case DCMD_GOTODIALOG:
263           get_dialog_script_parameters(script, &param1, NULL);
264           result = param1;
265           script_running = false;
266           break;
267 
268         case DCMD_PLAYSOUND:
269           get_dialog_script_parameters(script, &param1, NULL);
270           play_sound(param1);
271           break;
272 
273         case DCMD_ADDINV:
274           get_dialog_script_parameters(script, &param1, NULL);
275           add_inventory(param1);
276           break;
277 
278         case DCMD_SETSPCHVIEW:
279           get_dialog_script_parameters(script, &param1, &param2);
280           SetCharacterSpeechView(param1, param2);
281           break;
282 
283         case DCMD_NEWROOM:
284           get_dialog_script_parameters(script, &param1, NULL);
285           NewRoom(param1);
286           in_new_room = 1;
287           result = RUN_DIALOG_STOP_DIALOG;
288           script_running = false;
289           break;
290 
291         case DCMD_SETGLOBALINT:
292           get_dialog_script_parameters(script, &param1, &param2);
293           SetGlobalInt(param1, param2);
294           break;
295 
296         case DCMD_GIVESCORE:
297           get_dialog_script_parameters(script, &param1, NULL);
298           GiveScore(param1);
299           break;
300 
301         case DCMD_GOTOPREVIOUS:
302           result = RUN_DIALOG_GOTO_PREVIOUS;
303           script_running = false;
304           break;
305 
306         case DCMD_LOSEINV:
307           get_dialog_script_parameters(script, &param1, NULL);
308           lose_inventory(param1);
309           break;
310 
311         case DCMD_ENDSCRIPT:
312           result = RUN_DIALOG_STOP_DIALOG;
313           script_running = false;
314           break;
315       }
316     }
317   }
318 
319   if (in_new_room > 0)
320     return RUN_DIALOG_STOP_DIALOG;
321 
322   if (said_speech_line > 0) {
323     // the line below fixes the problem with the close-up face remaining on the
324     // screen after they finish talking; however, it makes the dialog options
325     // area flicker when going between topics.
326     DisableInterface();
327     UpdateGameOnce(); // redraw the screen to make sure it looks right
328     EnableInterface();
329     // if we're not about to abort the dialog, switch back to arrow
330     if (result != RUN_DIALOG_STOP_DIALOG)
331       set_mouse_cursor(CURS_ARROW);
332   }
333 
334   return result;
335 }
336 
write_dialog_options(Bitmap * ds,bool ds_has_alpha,int dlgxp,int curyp,int numdisp,int mouseison,int areawid,int bullet_wid,int usingfont,DialogTopic * dtop,char * disporder,short * dispyp,int linespacing,int utextcol,int padding)337 int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, int numdisp, int mouseison, int areawid,
338     int bullet_wid, int usingfont, DialogTopic*dtop, char*disporder, short*dispyp,
339     int linespacing, int utextcol, int padding) {
340   int ww;
341 
342   color_t text_color;
343   for (ww=0;ww<numdisp;ww++) {
344 
345     if ((dtop->optionflags[disporder[ww]] & DFLG_HASBEENCHOSEN) &&
346         (play.read_dialog_option_colour >= 0)) {
347       // 'read' colour
348       text_color = ds->GetCompatibleColor(play.read_dialog_option_colour);
349     }
350     else {
351       // 'unread' colour
352       text_color = ds->GetCompatibleColor(playerchar->talkcolor);
353     }
354 
355     if (mouseison==ww) {
356       if (text_color == ds->GetCompatibleColor(utextcol))
357         text_color = ds->GetCompatibleColor(13); // the normal colour is the same as highlight col
358       else text_color = ds->GetCompatibleColor(utextcol);
359     }
360 
361     break_up_text_into_lines(areawid-(2*padding+2+bullet_wid),usingfont,get_translation(dtop->optionnames[disporder[ww]]));
362     dispyp[ww]=curyp;
363     if (game.dialog_bullet > 0)
364     {
365         draw_gui_sprite_v330(ds, game.dialog_bullet, dlgxp, curyp, ds_has_alpha);
366     }
367     int cc;
368     if (game.options[OPT_DIALOGNUMBERED] == kDlgOptNumbering) {
369       char tempbfr[20];
370       int actualpicwid = 0;
371       if (game.dialog_bullet > 0)
372         actualpicwid = spritewidth[game.dialog_bullet]+3;
373 
374       sprintf (tempbfr, "%d.", ww + 1);
375       wouttext_outline (ds, dlgxp + actualpicwid, curyp, usingfont, text_color, tempbfr);
376     }
377     for (cc=0;cc<numlines;cc++) {
378       wouttext_outline(ds, dlgxp+((cc==0) ? 0 : 9)+bullet_wid, curyp, usingfont, text_color, lines[cc]);
379       curyp+=linespacing;
380     }
381     if (ww < numdisp-1)
382       curyp += multiply_up_coordinate(game.options[OPT_DIALOGGAP]);
383   }
384   return curyp;
385 }
386 
387 
388 
389 #define GET_OPTIONS_HEIGHT {\
390   needheight = 0;\
391   for (int i = 0; i < numdisp; ++i) {\
392     break_up_text_into_lines(areawid-(2*padding+2+bullet_wid),usingfont,get_translation(dtop->optionnames[disporder[i]]));\
393     needheight += getheightoflines(usingfont, numlines) + multiply_up_coordinate(game.options[OPT_DIALOGGAP]);\
394   }\
395   if (parserInput) needheight += parserInput->hit + multiply_up_coordinate(game.options[OPT_DIALOGGAP]);\
396  }
397 
398 
draw_gui_for_dialog_options(Bitmap * ds,GUIMain * guib,int dlgxp,int dlgyp)399 void draw_gui_for_dialog_options(Bitmap *ds, GUIMain *guib, int dlgxp, int dlgyp) {
400   if (guib->BgColor != 0) {
401     color_t draw_color = ds->GetCompatibleColor(guib->BgColor);
402     ds->FillRect(Rect(dlgxp, dlgyp, dlgxp + guib->Width, dlgyp + guib->Height), draw_color);
403   }
404   if (guib->BgImage > 0)
405       GfxUtil::DrawSpriteWithTransparency(ds, spriteset[guib->BgImage], dlgxp, dlgyp);
406 }
407 
get_custom_dialog_options_dimensions(int dlgnum)408 bool get_custom_dialog_options_dimensions(int dlgnum)
409 {
410   ccDialogOptionsRendering.Reset();
411   ccDialogOptionsRendering.dialogID = dlgnum;
412 
413   getDialogOptionsDimensionsFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
414   run_function_on_non_blocking_thread(&getDialogOptionsDimensionsFunc);
415 
416   if ((ccDialogOptionsRendering.width > 0) &&
417       (ccDialogOptionsRendering.height > 0))
418   {
419     return true;
420   }
421   return false;
422 }
423 
424 #define MAX_TOPIC_HISTORY 50
425 #define DLG_OPTION_PARSER 99
426 
427 struct DialogOptions
428 {
429     int dlgnum;
430     bool runGameLoopsInBackground;
431 
432     int dlgxp;
433     int dlgyp;
434     int dialog_abs_x; // absolute dialog position on screen
435     int padding;
436     int usingfont;
437     int lineheight;
438     int linespacing;
439     int curswas;
440     int bullet_wid;
441     int needheight;
442     IDriverDependantBitmap *ddb;
443     Bitmap *subBitmap;
444     GUITextBox *parserInput;
445     DialogTopic*dtop;
446 
447     char disporder[MAXTOPICOPTIONS];
448     short dispyp[MAXTOPICOPTIONS];
449 
450     int numdisp;
451     int chose;
452 
453     Bitmap *tempScrn;
454     int parserActivated;
455 
456     int curyp;
457     bool wantRefresh;
458     bool usingCustomRendering;
459     int orixp;
460     int oriyp;
461     int areawid;
462     int is_textwindow;
463     int dirtyx;
464     int dirtyy;
465     int dirtywidth;
466     int dirtyheight;
467 
468     int mouseison;
469     int mousewason;
470 
471     int forecol;
472 
473     void Prepare(int _dlgnum, bool _runGameLoopsInBackground);
474     void Show();
475     void Redraw();
476     bool Run();
477     void Close();
478 };
479 
Prepare(int _dlgnum,bool _runGameLoopsInBackground)480 void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground)
481 {
482   dlgnum = _dlgnum;
483   runGameLoopsInBackground = _runGameLoopsInBackground;
484 
485   dlgyp = get_fixed_pixel_size(160);
486   usingfont=FONT_NORMAL;
487   lineheight = getfontheight_outlined(usingfont);
488   linespacing = getfontspacing_outlined(usingfont);
489   curswas=cur_cursor;
490   bullet_wid = 0;
491   ddb = NULL;
492   subBitmap = NULL;
493   parserInput = NULL;
494   dtop = NULL;
495 
496   if ((dlgnum < 0) || (dlgnum >= game.numdialog))
497     quit("!RunDialog: invalid dialog number specified");
498 
499   can_run_delayed_command();
500 
501   play.in_conversation ++;
502 
503   update_polled_stuff_if_runtime();
504 
505   if (game.dialog_bullet > 0)
506     bullet_wid = spritewidth[game.dialog_bullet]+3;
507 
508   // numbered options, leave space for the numbers
509   if (game.options[OPT_DIALOGNUMBERED] == kDlgOptNumbering)
510     bullet_wid += wgettextwidth_compensate("9. ", usingfont);
511 
512   said_text = 0;
513 
514   update_polled_stuff_if_runtime();
515 
516   tempScrn = BitmapHelper::CreateBitmap(BitmapHelper::GetScreenBitmap()->GetWidth(), BitmapHelper::GetScreenBitmap()->GetHeight(), game.GetColorDepth());
517 
518   set_mouse_cursor(CURS_ARROW);
519 
520   dtop=&dialog[dlgnum];
521 
522   chose=-1;
523   numdisp=0;
524 
525   parserActivated = 0;
526   if ((dtop->topicFlags & DTFLG_SHOWPARSER) && (play.disable_dialog_parser == 0)) {
527     parserInput = new GUITextBox();
528     parserInput->hit = lineheight + get_fixed_pixel_size(4);
529     parserInput->exflags = 0;
530     parserInput->font = usingfont;
531   }
532 
533   numdisp=0;
534   for (int i = 0; i < dtop->numoptions; ++i) {
535     if ((dtop->optionflags[i] & DFLG_ON)==0) continue;
536     ensure_text_valid_for_font(dtop->optionnames[i], usingfont);
537     disporder[numdisp]=i;
538     numdisp++;
539   }
540 }
541 
Show()542 void DialogOptions::Show()
543 {
544   if (numdisp<1) quit("!DoDialog: all options have been turned off");
545   // Don't display the options if there is only one and the parser
546   // is not enabled.
547   if (!((numdisp > 1) || (parserInput != NULL) || (play.show_single_dialog_option)))
548   {
549       chose = disporder[0];  // only one choice, so select it
550       return;
551   }
552 
553     SetVirtualScreen(virtual_screen);
554 
555     is_textwindow = 0;
556     forecol = play.dialog_options_highlight_color;
557 
558     mouseison=-1;
559     mousewason=-10;
560     dirtyx = 0;
561     dirtyy = 0;
562     dirtywidth = virtual_screen->GetWidth();
563     dirtyheight = virtual_screen->GetHeight();
564     usingCustomRendering = false;
565 
566 
567     dlgxp = 1;
568     if (get_custom_dialog_options_dimensions(dlgnum))
569     {
570       usingCustomRendering = true;
571       dirtyx = multiply_up_coordinate(ccDialogOptionsRendering.x);
572       dirtyy = multiply_up_coordinate(ccDialogOptionsRendering.y);
573       dirtywidth = multiply_up_coordinate(ccDialogOptionsRendering.width);
574       dirtyheight = multiply_up_coordinate(ccDialogOptionsRendering.height);
575       dialog_abs_x = dirtyx;
576     }
577     else if (game.options[OPT_DIALOGIFACE] > 0)
578     {
579       GUIMain*guib=&guis[game.options[OPT_DIALOGIFACE]];
580       if (guib->IsTextWindow()) {
581         // text-window, so do the QFG4-style speech options
582         is_textwindow = 1;
583         forecol = guib->FgColor;
584       }
585       else {
586         dlgxp = guib->X;
587         dlgyp = guib->Y;
588 
589         dirtyx = dlgxp;
590         dirtyy = dlgyp;
591         dirtywidth = guib->Width;
592         dirtyheight = guib->Height;
593         dialog_abs_x = guib->X;
594 
595         areawid=guib->Width - 5;
596         padding = TEXTWINDOW_PADDING_DEFAULT;
597 
598         GET_OPTIONS_HEIGHT
599 
600         if (game.options[OPT_DIALOGUPWARDS]) {
601           // They want the options upwards from the bottom
602           dlgyp = (guib->Y + guib->Height) - needheight;
603         }
604 
605       }
606     }
607     else {
608       //dlgyp=(play.viewport.GetHeight()-numdisp*txthit)-1;
609       areawid=play.viewport.GetWidth()-5;
610       padding = TEXTWINDOW_PADDING_DEFAULT;
611       GET_OPTIONS_HEIGHT
612       dlgyp = play.viewport.GetHeight() - needheight;
613 
614       dirtyx = 0;
615       dirtyy = dlgyp - 1;
616       dirtywidth = play.viewport.GetWidth();
617       dirtyheight = play.viewport.GetHeight() - dirtyy;
618       dialog_abs_x = 0;
619     }
620     if (!is_textwindow)
621       areawid -= multiply_up_coordinate(play.dialog_options_x) * 2;
622 
623     orixp = dlgxp;
624     oriyp = dlgyp;
625     wantRefresh = false;
626     mouseison=-10;
627 
628     update_polled_stuff_if_runtime();
629     //->Blit(virtual_screen, tempScrn, 0, 0, 0, 0, screen->GetWidth(), screen->GetHeight());
630     if (!play.mouse_cursor_hidden)
631       domouse(1);
632     update_polled_stuff_if_runtime();
633 
634     Redraw();
635     while(Run());
636 
637     if (!play.mouse_cursor_hidden)
638       domouse(2);
639 }
640 
Redraw()641 void DialogOptions::Redraw()
642 {
643     wantRefresh = true;
644 
645     if (usingCustomRendering)
646     {
647       tempScrn = recycle_bitmap(tempScrn, game.GetColorDepth(),
648         multiply_up_coordinate(ccDialogOptionsRendering.width),
649         multiply_up_coordinate(ccDialogOptionsRendering.height));
650     }
651 
652     tempScrn->ClearTransparent();
653     Bitmap *ds = SetVirtualScreen(tempScrn);
654 
655     dlgxp = orixp;
656     dlgyp = oriyp;
657     // lengthy drawing to screen, so lock it for speed
658     //acquire_screen();
659 
660     bool options_surface_has_alpha = false;
661 
662     if (usingCustomRendering)
663     {
664       ccDialogOptionsRendering.surfaceToRenderTo = dialogOptionsRenderingSurface;
665       ccDialogOptionsRendering.surfaceAccessed = false;
666       dialogOptionsRenderingSurface->linkedBitmapOnly = tempScrn;
667       dialogOptionsRenderingSurface->hasAlphaChannel = ccDialogOptionsRendering.hasAlphaChannel;
668       options_surface_has_alpha = dialogOptionsRenderingSurface->hasAlphaChannel != 0;
669 
670       renderDialogOptionsFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
671       run_function_on_non_blocking_thread(&renderDialogOptionsFunc);
672 
673       if (!ccDialogOptionsRendering.surfaceAccessed)
674         quit("!dialog_options_get_dimensions was implemented, but no dialog_options_render function drew anything to the surface");
675 
676       if (parserInput)
677       {
678         parserInput->x = multiply_up_coordinate(ccDialogOptionsRendering.parserTextboxX);
679         curyp = multiply_up_coordinate(ccDialogOptionsRendering.parserTextboxY);
680         areawid = multiply_up_coordinate(ccDialogOptionsRendering.parserTextboxWidth);
681         if (areawid == 0)
682           areawid = tempScrn->GetWidth();
683       }
684       ccDialogOptionsRendering.needRepaint = false;
685     }
686     else if (is_textwindow) {
687       // text window behind the options
688       areawid = multiply_up_coordinate(play.max_dialogoption_width);
689       int biggest = 0;
690       padding = guis[game.options[OPT_DIALOGIFACE]].Padding;
691       for (int i = 0; i < numdisp; ++i) {
692         break_up_text_into_lines(areawid-((2*padding+2)+bullet_wid),usingfont,get_translation(dtop->optionnames[disporder[i]]));
693         if (longestline > biggest)
694           biggest = longestline;
695       }
696       if (biggest < areawid - ((2*padding+6)+bullet_wid))
697         areawid = biggest + ((2*padding+6)+bullet_wid);
698 
699       if (areawid < multiply_up_coordinate(play.min_dialogoption_width)) {
700         areawid = multiply_up_coordinate(play.min_dialogoption_width);
701         if (play.min_dialogoption_width > play.max_dialogoption_width)
702           quit("!game.min_dialogoption_width is larger than game.max_dialogoption_width");
703       }
704 
705       GET_OPTIONS_HEIGHT
706 
707       int savedwid = areawid;
708       int txoffs=0,tyoffs=0,yspos = play.viewport.GetHeight()/2-(2*padding+needheight)/2;
709       int xspos = play.viewport.GetWidth()/2 - areawid/2;
710       // shift window to the right if QG4-style full-screen pic
711       if ((game.options[OPT_SPEECHTYPE] == 3) && (said_text > 0))
712         xspos = (play.viewport.GetWidth() - areawid) - get_fixed_pixel_size(10);
713 
714       // needs to draw the right text window, not the default
715       push_screen(ds);
716       Bitmap *text_window_ds = ds;
717       draw_text_window(&text_window_ds, false, &txoffs,&tyoffs,&xspos,&yspos,&areawid,NULL,needheight, game.options[OPT_DIALOGIFACE]);
718       options_surface_has_alpha = guis[game.options[OPT_DIALOGIFACE]].HasAlphaChannel();
719       ds = pop_screen();
720       // snice draw_text_window incrases the width, restore it
721       areawid = savedwid;
722       //wnormscreen();
723 
724       dirtyx = xspos;
725       dirtyy = yspos;
726       dirtywidth = text_window_ds->GetWidth();
727       dirtyheight = text_window_ds->GetHeight();
728       dialog_abs_x = txoffs + xspos;
729 
730       GfxUtil::DrawSpriteWithTransparency(ds, text_window_ds, xspos, yspos);
731       delete text_window_ds;
732 
733       // Ignore the dialog_options_x/y offsets when using a text window
734       txoffs += xspos;
735       tyoffs += yspos;
736       dlgyp = tyoffs;
737       curyp = write_dialog_options(ds, options_surface_has_alpha, txoffs,tyoffs,numdisp,mouseison,areawid,bullet_wid,usingfont,dtop,disporder,dispyp,linespacing,forecol,padding);
738       if (parserInput)
739         parserInput->x = txoffs;
740     }
741     else {
742 
743       if (wantRefresh) {
744         // redraw the black background so that anti-alias
745         // fonts don't re-alias themselves
746         if (game.options[OPT_DIALOGIFACE] == 0) {
747           color_t draw_color = ds->GetCompatibleColor(16);
748           ds->FillRect(Rect(0,dlgyp-1,play.viewport.GetWidth()-1,play.viewport.GetHeight()-1), draw_color);
749         }
750         else {
751           GUIMain* guib = &guis[game.options[OPT_DIALOGIFACE]];
752           if (!guib->IsTextWindow())
753             draw_gui_for_dialog_options(ds, guib, dlgxp, dlgyp);
754         }
755       }
756 
757       dirtyx = 0;
758       dirtywidth = play.viewport.GetWidth();
759 
760       if (game.options[OPT_DIALOGIFACE] > 0)
761       {
762         // the whole GUI area should be marked dirty in order
763         // to ensure it gets drawn
764         GUIMain* guib = &guis[game.options[OPT_DIALOGIFACE]];
765         dirtyheight = guib->Height;
766         dirtyy = dlgyp;
767         options_surface_has_alpha = guib->HasAlphaChannel();
768       }
769       else
770       {
771         dirtyy = dlgyp - 1;
772         dirtyheight = needheight + 1;
773         options_surface_has_alpha = false;
774       }
775 
776       dlgxp += multiply_up_coordinate(play.dialog_options_x);
777       dlgyp += multiply_up_coordinate(play.dialog_options_y);
778 
779       // if they use a negative dialog_options_y, make sure the
780       // area gets marked as dirty
781       if (dlgyp < dirtyy)
782         dirtyy = dlgyp;
783 
784       //curyp = dlgyp + 1;
785       curyp = dlgyp;
786       curyp = write_dialog_options(ds, options_surface_has_alpha, dlgxp,curyp,numdisp,mouseison,areawid,bullet_wid,usingfont,dtop,disporder,dispyp,linespacing,forecol,padding);
787 
788       /*if (curyp > play.viewport.GetHeight()) {
789         dlgyp = play.viewport.GetHeight() - (curyp - dlgyp);
790         ds->FillRect(Rect(0,dlgyp-1,play.viewport.GetWidth()-1,play.viewport.GetHeight()-1);
791         goto redraw_options;
792       }*/
793       if (parserInput)
794         parserInput->x = dlgxp;
795     }
796 
797     if (parserInput) {
798       // Set up the text box, if present
799       parserInput->y = curyp + multiply_up_coordinate(game.options[OPT_DIALOGGAP]);
800       parserInput->wid = areawid - get_fixed_pixel_size(10);
801       parserInput->textcol = playerchar->talkcolor;
802       if (mouseison == DLG_OPTION_PARSER)
803         parserInput->textcol = forecol;
804 
805       if (game.dialog_bullet)  // the parser X will get moved in a second
806       {
807           draw_gui_sprite_v330(ds, game.dialog_bullet, parserInput->x, parserInput->y, options_surface_has_alpha);
808       }
809 
810       parserInput->wid -= bullet_wid;
811       parserInput->x += bullet_wid;
812 
813       parserInput->Draw(ds);
814       parserInput->activated = 0;
815     }
816 
817     wantRefresh = false;
818     ds = SetVirtualScreen(virtual_screen);
819 
820     update_polled_stuff_if_runtime();
821 
822     subBitmap = recycle_bitmap(subBitmap, tempScrn->GetColorDepth(), dirtywidth, dirtyheight);
823     subBitmap = ReplaceBitmapWithSupportedFormat(subBitmap);
824 
825     update_polled_stuff_if_runtime();
826 
827     if (usingCustomRendering)
828     {
829       subBitmap->Blit(tempScrn, 0, 0, 0, 0, tempScrn->GetWidth(), tempScrn->GetHeight());
830       invalidate_rect(dirtyx, dirtyy, dirtyx + subBitmap->GetWidth(), dirtyy + subBitmap->GetHeight());
831     }
832     else
833     {
834       subBitmap->Blit(tempScrn, dirtyx, dirtyy, 0, 0, dirtywidth, dirtyheight);
835     }
836 
837     if ((ddb != NULL) &&
838       ((ddb->GetWidth() != dirtywidth) ||
839        (ddb->GetHeight() != dirtyheight)))
840     {
841       gfxDriver->DestroyDDB(ddb);
842       ddb = NULL;
843     }
844 
845     if (ddb == NULL)
846       ddb = gfxDriver->CreateDDBFromBitmap(subBitmap, options_surface_has_alpha, false);
847     else
848       gfxDriver->UpdateDDBFromBitmap(ddb, subBitmap, options_surface_has_alpha);
849 
850     if (runGameLoopsInBackground)
851     {
852         render_graphics(ddb, dirtyx, dirtyy);
853     }
854 }
855 
Run()856 bool DialogOptions::Run()
857 {
858     const bool new_custom_render = usingCustomRendering && game.options[OPT_DIALOGOPTIONSAPI] >= 0;
859 
860       if (runGameLoopsInBackground)
861       {
862         play.disabled_user_interface++;
863         UpdateGameOnce(false, ddb, dirtyx, dirtyy);
864         play.disabled_user_interface--;
865       }
866       else
867       {
868         timerloop = 0;
869         NEXT_ITERATION();
870 
871         render_graphics(ddb, dirtyx, dirtyy);
872 
873         update_polled_audio_and_crossfade();
874       }
875 
876       if (new_custom_render)
877       {
878         runDialogOptionRepExecFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
879         run_function_on_non_blocking_thread(&runDialogOptionRepExecFunc);
880       }
881 
882       int gkey;
883       if (run_service_key_controls(gkey)) {
884         if (parserInput) {
885           wantRefresh = true;
886           // type into the parser
887           if ((gkey == 361) || ((gkey == ' ') && (strlen(parserInput->text) == 0))) {
888             // write previous contents into textbox (F3 or Space when box is empty)
889             for (unsigned int i = strlen(parserInput->text); i < strlen(play.lastParserEntry); i++) {
890               parserInput->KeyPress(play.lastParserEntry[i]);
891             }
892             //domouse(2);
893             Redraw();
894             return true; // continue running loop
895           }
896           else if ((gkey >= 32) || (gkey == 13) || (gkey == 8)) {
897             parserInput->KeyPress(gkey);
898             if (!parserInput->activated) {
899               //domouse(2);
900               Redraw();
901               return true; // continue running loop
902             }
903           }
904         }
905         else if (new_custom_render)
906         {
907             runDialogOptionKeyPressHandlerFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
908             runDialogOptionKeyPressHandlerFunc.params[1].SetInt32(GetKeyForKeyPressCb(gkey));
909             run_function_on_non_blocking_thread(&runDialogOptionKeyPressHandlerFunc);
910         }
911         // Allow selection of options by keyboard shortcuts
912         else if (game.options[OPT_DIALOGNUMBERED] >= kDlgOptKeysOnly &&
913                  gkey >= '1' && gkey <= '9')
914         {
915           gkey -= '1';
916           if (gkey < numdisp) {
917             chose = disporder[gkey];
918             return false; // end dialog options running loop
919           }
920         }
921       }
922       mousewason=mouseison;
923       mouseison=-1;
924       if (new_custom_render); // do not automatically detect option under mouse
925       else if (usingCustomRendering)
926       {
927         if ((mousex >= dirtyx) && (mousey >= dirtyy) &&
928             (mousex < dirtyx + tempScrn->GetWidth()) &&
929             (mousey < dirtyy + tempScrn->GetHeight()))
930         {
931           getDialogOptionUnderCursorFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
932           run_function_on_non_blocking_thread(&getDialogOptionUnderCursorFunc);
933 
934           if (!getDialogOptionUnderCursorFunc.atLeastOneImplementationExists)
935             quit("!The script function dialog_options_get_active is not implemented. It must be present to use a custom dialogue system.");
936 
937           mouseison = ccDialogOptionsRendering.activeOptionID;
938         }
939         else
940         {
941           ccDialogOptionsRendering.activeOptionID = -1;
942         }
943       }
944       else if (mousex >= dialog_abs_x && mousex < (dialog_abs_x + areawid) &&
945                mousey >= dlgyp && mousey < curyp)
946       {
947         mouseison=numdisp-1;
948         for (int i = 0; i < numdisp; ++i) {
949           if (mousey < dispyp[i]) { mouseison=i-1; break; }
950         }
951         if ((mouseison<0) | (mouseison>=numdisp)) mouseison=-1;
952       }
953 
954       if (parserInput != NULL) {
955         int relativeMousey = mousey;
956         if (usingCustomRendering)
957           relativeMousey -= dirtyy;
958 
959         if ((relativeMousey > parserInput->y) &&
960             (relativeMousey < parserInput->y + parserInput->hit))
961           mouseison = DLG_OPTION_PARSER;
962 
963         if (parserInput->activated)
964           parserActivated = 1;
965       }
966 
967       int mouseButtonPressed = mgetbutton();
968 
969       if (mouseButtonPressed != NONE)
970       {
971         if (mouseison < 0 && !new_custom_render)
972         {
973           if (usingCustomRendering)
974           {
975             runDialogOptionMouseClickHandlerFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
976             runDialogOptionMouseClickHandlerFunc.params[1].SetInt32(mouseButtonPressed + 1);
977             run_function_on_non_blocking_thread(&runDialogOptionMouseClickHandlerFunc);
978 
979             if (runDialogOptionMouseClickHandlerFunc.atLeastOneImplementationExists)
980             {
981               Redraw();
982               return true; // continue running loop
983             }
984           }
985           return true; // continue running loop
986         }
987         if (mouseison == DLG_OPTION_PARSER) {
988           // they clicked the text box
989           parserActivated = 1;
990         }
991         else if (new_custom_render)
992         {
993             runDialogOptionMouseClickHandlerFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
994             runDialogOptionMouseClickHandlerFunc.params[1].SetInt32(mouseButtonPressed + 1);
995             run_function_on_non_blocking_thread(&runDialogOptionMouseClickHandlerFunc);
996         }
997         else if (usingCustomRendering)
998         {
999           chose = mouseison;
1000           return false; // end dialog options running loop
1001         }
1002         else {
1003           chose=disporder[mouseison];
1004           return false; // end dialog options running loop
1005         }
1006       }
1007 
1008       if (usingCustomRendering)
1009       {
1010         int mouseWheelTurn = check_mouse_wheel();
1011         if (mouseWheelTurn != 0)
1012         {
1013             runDialogOptionMouseClickHandlerFunc.params[0].SetDynamicObject(&ccDialogOptionsRendering, &ccDialogOptionsRendering);
1014             runDialogOptionMouseClickHandlerFunc.params[1].SetInt32((mouseWheelTurn < 0) ? 9 : 8);
1015             run_function_on_non_blocking_thread(&runDialogOptionMouseClickHandlerFunc);
1016 
1017             if (!new_custom_render)
1018             {
1019                 if (runDialogOptionMouseClickHandlerFunc.atLeastOneImplementationExists)
1020                     Redraw();
1021                 return true; // continue running loop
1022             }
1023         }
1024       }
1025 
1026       if (parserActivated) {
1027         // They have selected a custom parser-based option
1028         if (parserInput->text[0] != 0) {
1029           chose = DLG_OPTION_PARSER;
1030           return false; // end dialog options running loop
1031         }
1032         else {
1033           parserActivated = 0;
1034           parserInput->activated = 0;
1035         }
1036       }
1037       if (mousewason != mouseison) {
1038         //domouse(2);
1039         Redraw();
1040         return true; // continue running loop
1041       }
1042       if (new_custom_render)
1043       {
1044         if (ccDialogOptionsRendering.chosenOptionID >= 0)
1045         {
1046             chose = ccDialogOptionsRendering.chosenOptionID;
1047             ccDialogOptionsRendering.chosenOptionID = -1;
1048             return false; // end dialog options running loop
1049         }
1050         if (ccDialogOptionsRendering.needRepaint)
1051         {
1052             Redraw();
1053             return true; // continue running loop
1054         }
1055       }
1056       update_polled_stuff_if_runtime();
1057       if (play.fast_forward == 0) WaitForNextFrame();
1058       return true; // continue running loop
1059 }
1060 
Close()1061 void DialogOptions::Close()
1062 {
1063   clear_input_buffer();
1064   //leave_real_screen();
1065   construct_virtual_screen(true);
1066 
1067   if (parserActivated)
1068   {
1069     strcpy (play.lastParserEntry, parserInput->text);
1070     ParseText (parserInput->text);
1071     chose = CHOSE_TEXTPARSER;
1072   }
1073 
1074   if (parserInput) {
1075     delete parserInput;
1076     parserInput = NULL;
1077   }
1078 
1079   if (ddb != NULL)
1080     gfxDriver->DestroyDDB(ddb);
1081   delete subBitmap;
1082 
1083   set_mouse_cursor(curswas);
1084   // In case it's the QFG4 style dialog, remove the black screen
1085   play.in_conversation--;
1086   remove_screen_overlay(OVER_COMPLETE);
1087 
1088   delete tempScrn;
1089 }
1090 
1091 DialogOptions DlgOpt;
1092 
show_dialog_options(int _dlgnum,int sayChosenOption,bool _runGameLoopsInBackground)1093 int show_dialog_options(int _dlgnum, int sayChosenOption, bool _runGameLoopsInBackground)
1094 {
1095   DlgOpt.Prepare(_dlgnum, _runGameLoopsInBackground);
1096   DlgOpt.Show();
1097   DlgOpt.Close();
1098 
1099   int dialog_choice = DlgOpt.chose;
1100   if (dialog_choice != CHOSE_TEXTPARSER)
1101   {
1102     DialogTopic *dialog_topic = DlgOpt.dtop;
1103     int &option_flags = dialog_topic->optionflags[dialog_choice];
1104     const char *option_name = DlgOpt.dtop->optionnames[dialog_choice];
1105 
1106     option_flags |= DFLG_HASBEENCHOSEN;
1107     bool sayTheOption = false;
1108     if (sayChosenOption == SAYCHOSEN_YES)
1109     {
1110       sayTheOption = true;
1111     }
1112     else if (sayChosenOption == SAYCHOSEN_USEFLAG)
1113     {
1114       sayTheOption = ((option_flags & DFLG_NOREPEAT) == 0);
1115     }
1116 
1117     if (sayTheOption)
1118       DisplaySpeech(get_translation(option_name), game.playercharacter);
1119   }
1120 
1121   return dialog_choice;
1122 }
1123 
do_conversation(int dlgnum)1124 void do_conversation(int dlgnum)
1125 {
1126   EndSkippingUntilCharStops();
1127 
1128   // AGS 2.x always makes the mouse cursor visible when displaying a dialog.
1129   if (loaded_game_file_version <= kGameVersion_272)
1130     play.mouse_cursor_hidden = 0;
1131 
1132   int dlgnum_was = dlgnum;
1133   int previousTopics[MAX_TOPIC_HISTORY];
1134   int numPrevTopics = 0;
1135   DialogTopic *dtop = &dialog[dlgnum];
1136 
1137   // run the startup script
1138   int tocar = run_dialog_script(dtop, dlgnum, dtop->startupentrypoint, 0);
1139   if ((tocar == RUN_DIALOG_STOP_DIALOG) ||
1140       (tocar == RUN_DIALOG_GOTO_PREVIOUS))
1141   {
1142     // 'stop' or 'goto-previous' from first startup script
1143     remove_screen_overlay(OVER_COMPLETE);
1144     play.in_conversation--;
1145     return;
1146   }
1147   else if (tocar >= 0)
1148     dlgnum = tocar;
1149 
1150   while (dlgnum >= 0)
1151   {
1152     if (dlgnum >= game.numdialog)
1153       quit("!RunDialog: invalid dialog number specified");
1154 
1155     dtop = &dialog[dlgnum];
1156 
1157     if (dlgnum != dlgnum_was)
1158     {
1159       // dialog topic changed, so play the startup
1160       // script for the new topic
1161       tocar = run_dialog_script(dtop, dlgnum, dtop->startupentrypoint, 0);
1162       dlgnum_was = dlgnum;
1163       if (tocar == RUN_DIALOG_GOTO_PREVIOUS) {
1164         if (numPrevTopics < 1) {
1165           // goto-previous on first topic -- end dialog
1166           tocar = RUN_DIALOG_STOP_DIALOG;
1167         }
1168         else {
1169           tocar = previousTopics[numPrevTopics - 1];
1170           numPrevTopics--;
1171         }
1172       }
1173       if (tocar == RUN_DIALOG_STOP_DIALOG)
1174         break;
1175       else if (tocar >= 0) {
1176         // save the old topic number in the history
1177         if (numPrevTopics < MAX_TOPIC_HISTORY) {
1178           previousTopics[numPrevTopics] = dlgnum;
1179           numPrevTopics++;
1180         }
1181         dlgnum = tocar;
1182         continue;
1183       }
1184     }
1185 
1186     int chose = show_dialog_options(dlgnum, SAYCHOSEN_USEFLAG, (game.options[OPT_RUNGAMEDLGOPTS] != 0));
1187 
1188     if (chose == CHOSE_TEXTPARSER)
1189     {
1190       said_speech_line = 0;
1191 
1192       tocar = run_dialog_request(dlgnum);
1193 
1194       if (said_speech_line > 0) {
1195         // fix the problem with the close-up face remaining on screen
1196         DisableInterface();
1197         UpdateGameOnce(); // redraw the screen to make sure it looks right
1198         EnableInterface();
1199         set_mouse_cursor(CURS_ARROW);
1200       }
1201     }
1202     else
1203     {
1204       tocar = run_dialog_script(dtop, dlgnum, dtop->entrypoints[chose], chose + 1);
1205     }
1206 
1207     if (tocar == RUN_DIALOG_GOTO_PREVIOUS) {
1208       if (numPrevTopics < 1) {
1209         tocar = RUN_DIALOG_STOP_DIALOG;
1210       }
1211       else {
1212         tocar = previousTopics[numPrevTopics - 1];
1213         numPrevTopics--;
1214       }
1215     }
1216     if (tocar == RUN_DIALOG_STOP_DIALOG) break;
1217     else if (tocar >= 0) {
1218       // save the old topic number in the history
1219       if (numPrevTopics < MAX_TOPIC_HISTORY) {
1220         previousTopics[numPrevTopics] = dlgnum;
1221         numPrevTopics++;
1222       }
1223       dlgnum = tocar;
1224     }
1225 
1226   }
1227 
1228 }
1229 
1230 // end dialog manager
1231 
1232 
1233 //=============================================================================
1234 //
1235 // Script API Functions
1236 //
1237 //=============================================================================
1238 
1239 #include "debug/out.h"
1240 #include "script/script_api.h"
1241 #include "script/script_runtime.h"
1242 #include "ac/dynobj/scriptstring.h"
1243 
1244 extern ScriptString myScriptStringImpl;
1245 
1246 // int (ScriptDialog *sd)
Sc_Dialog_GetID(void * self,const RuntimeScriptValue * params,int32_t param_count)1247 RuntimeScriptValue Sc_Dialog_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count)
1248 {
1249     API_OBJCALL_INT(ScriptDialog, Dialog_GetID);
1250 }
1251 
1252 // int (ScriptDialog *sd)
Sc_Dialog_GetOptionCount(void * self,const RuntimeScriptValue * params,int32_t param_count)1253 RuntimeScriptValue Sc_Dialog_GetOptionCount(void *self, const RuntimeScriptValue *params, int32_t param_count)
1254 {
1255     API_OBJCALL_INT(ScriptDialog, Dialog_GetOptionCount);
1256 }
1257 
1258 // int (ScriptDialog *sd)
Sc_Dialog_GetShowTextParser(void * self,const RuntimeScriptValue * params,int32_t param_count)1259 RuntimeScriptValue Sc_Dialog_GetShowTextParser(void *self, const RuntimeScriptValue *params, int32_t param_count)
1260 {
1261     API_OBJCALL_INT(ScriptDialog, Dialog_GetShowTextParser);
1262 }
1263 
1264 // int (ScriptDialog *sd, int sayChosenOption)
Sc_Dialog_DisplayOptions(void * self,const RuntimeScriptValue * params,int32_t param_count)1265 RuntimeScriptValue Sc_Dialog_DisplayOptions(void *self, const RuntimeScriptValue *params, int32_t param_count)
1266 {
1267     API_OBJCALL_INT_PINT(ScriptDialog, Dialog_DisplayOptions);
1268 }
1269 
1270 // int (ScriptDialog *sd, int option)
Sc_Dialog_GetOptionState(void * self,const RuntimeScriptValue * params,int32_t param_count)1271 RuntimeScriptValue Sc_Dialog_GetOptionState(void *self, const RuntimeScriptValue *params, int32_t param_count)
1272 {
1273     API_OBJCALL_INT_PINT(ScriptDialog, Dialog_GetOptionState);
1274 }
1275 
1276 // const char* (ScriptDialog *sd, int option)
Sc_Dialog_GetOptionText(void * self,const RuntimeScriptValue * params,int32_t param_count)1277 RuntimeScriptValue Sc_Dialog_GetOptionText(void *self, const RuntimeScriptValue *params, int32_t param_count)
1278 {
1279     API_OBJCALL_OBJ_PINT(ScriptDialog, const char, myScriptStringImpl, Dialog_GetOptionText);
1280 }
1281 
1282 // int (ScriptDialog *sd, int option)
Sc_Dialog_HasOptionBeenChosen(void * self,const RuntimeScriptValue * params,int32_t param_count)1283 RuntimeScriptValue Sc_Dialog_HasOptionBeenChosen(void *self, const RuntimeScriptValue *params, int32_t param_count)
1284 {
1285     API_OBJCALL_INT_PINT(ScriptDialog, Dialog_HasOptionBeenChosen);
1286 }
1287 
Sc_Dialog_SetHasOptionBeenChosen(void * self,const RuntimeScriptValue * params,int32_t param_count)1288 RuntimeScriptValue Sc_Dialog_SetHasOptionBeenChosen(void *self, const RuntimeScriptValue *params, int32_t param_count)
1289 {
1290     API_OBJCALL_VOID_PINT_PBOOL(ScriptDialog, Dialog_SetHasOptionBeenChosen);
1291 }
1292 
1293 // void (ScriptDialog *sd, int option, int newState)
Sc_Dialog_SetOptionState(void * self,const RuntimeScriptValue * params,int32_t param_count)1294 RuntimeScriptValue Sc_Dialog_SetOptionState(void *self, const RuntimeScriptValue *params, int32_t param_count)
1295 {
1296     API_OBJCALL_VOID_PINT2(ScriptDialog, Dialog_SetOptionState);
1297 }
1298 
1299 // void (ScriptDialog *sd)
Sc_Dialog_Start(void * self,const RuntimeScriptValue * params,int32_t param_count)1300 RuntimeScriptValue Sc_Dialog_Start(void *self, const RuntimeScriptValue *params, int32_t param_count)
1301 {
1302     API_OBJCALL_VOID(ScriptDialog, Dialog_Start);
1303 }
1304 
RegisterDialogAPI()1305 void RegisterDialogAPI()
1306 {
1307     ccAddExternalObjectFunction("Dialog::get_ID",               Sc_Dialog_GetID);
1308     ccAddExternalObjectFunction("Dialog::get_OptionCount",      Sc_Dialog_GetOptionCount);
1309     ccAddExternalObjectFunction("Dialog::get_ShowTextParser",   Sc_Dialog_GetShowTextParser);
1310     ccAddExternalObjectFunction("Dialog::DisplayOptions^1",     Sc_Dialog_DisplayOptions);
1311     ccAddExternalObjectFunction("Dialog::GetOptionState^1",     Sc_Dialog_GetOptionState);
1312     ccAddExternalObjectFunction("Dialog::GetOptionText^1",      Sc_Dialog_GetOptionText);
1313     ccAddExternalObjectFunction("Dialog::HasOptionBeenChosen^1", Sc_Dialog_HasOptionBeenChosen);
1314     ccAddExternalObjectFunction("Dialog::SetHasOptionBeenChosen^2", Sc_Dialog_SetHasOptionBeenChosen);
1315     ccAddExternalObjectFunction("Dialog::SetOptionState^2",     Sc_Dialog_SetOptionState);
1316     ccAddExternalObjectFunction("Dialog::Start^0",              Sc_Dialog_Start);
1317 
1318     /* ----------------------- Registering unsafe exports for plugins -----------------------*/
1319 
1320     ccAddExternalFunctionForPlugin("Dialog::get_ID",               (void*)Dialog_GetID);
1321     ccAddExternalFunctionForPlugin("Dialog::get_OptionCount",      (void*)Dialog_GetOptionCount);
1322     ccAddExternalFunctionForPlugin("Dialog::get_ShowTextParser",   (void*)Dialog_GetShowTextParser);
1323     ccAddExternalFunctionForPlugin("Dialog::DisplayOptions^1",     (void*)Dialog_DisplayOptions);
1324     ccAddExternalFunctionForPlugin("Dialog::GetOptionState^1",     (void*)Dialog_GetOptionState);
1325     ccAddExternalFunctionForPlugin("Dialog::GetOptionText^1",      (void*)Dialog_GetOptionText);
1326     ccAddExternalFunctionForPlugin("Dialog::HasOptionBeenChosen^1", (void*)Dialog_HasOptionBeenChosen);
1327     ccAddExternalFunctionForPlugin("Dialog::SetOptionState^2",     (void*)Dialog_SetOptionState);
1328     ccAddExternalFunctionForPlugin("Dialog::Start^0",              (void*)Dialog_Start);
1329 }
1330