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 <stdarg.h>
16 #include <stdio.h>
17 #include "ac/common.h"
18 #include "ac/character.h"
19 #include "ac/display.h"
20 #include "ac/draw.h"
21 #include "ac/game.h"
22 #include "ac/gamesetupstruct.h"
23 #include "ac/gamestate.h"
24 #include "ac/global_character.h"
25 #include "ac/global_display.h"
26 #include "ac/global_screen.h"
27 #include "ac/global_translation.h"
28 #include "ac/roomstruct.h"
29 #include "ac/runtime_defines.h"
30 #include "ac/speech.h"
31 #include "ac/string.h"
32 #include "ac/topbarsettings.h"
33 #include "debug/debug_log.h"
34 #include "main/game_run.h"
35 #include "util/c99_snprintf.h"
36
37 extern TopBarSettings topBar;
38 extern GameState play;
39 extern roomstruct thisroom;
40 extern int display_message_aschar;
41 extern GameSetupStruct game;
42 extern int screen_is_dirty;
43
Display(const char * texx,...)44 void Display(const char*texx, ...) {
45 char displbuf[STD_BUFFER_SIZE];
46 va_list ap;
47 va_start(ap,texx);
48 vsprintf(displbuf, get_translation(texx), ap);
49 va_end(ap);
50 DisplayAtY (-1, displbuf);
51 }
52
DisplaySimple(const char * text)53 void DisplaySimple(const char *text)
54 {
55 DisplayAtY (-1, text);
56 }
57
DisplayTopBar(int ypos,int ttexcol,int backcol,const char * title,const char * text)58 void DisplayTopBar(int ypos, int ttexcol, int backcol, const char *title, const char *text)
59 {
60 // FIXME: refactor source_text_length and get rid of this ugly hack!
61 const int real_text_sourcelen = source_text_length;
62 snprintf(topBar.text, sizeof(topBar.text), "%s", get_translation(title));
63 source_text_length = real_text_sourcelen;
64
65 if (ypos > 0)
66 play.top_bar_ypos = ypos;
67 if (ttexcol > 0)
68 play.top_bar_textcolor = ttexcol;
69 if (backcol > 0)
70 play.top_bar_backcolor = backcol;
71
72 topBar.wantIt = 1;
73 topBar.font = FONT_NORMAL;
74 topBar.height = getfontheight_outlined(topBar.font);
75 topBar.height += multiply_up_coordinate(play.top_bar_borderwidth) * 2 + get_fixed_pixel_size(1);
76
77 // they want to customize the font
78 if (play.top_bar_font >= 0)
79 topBar.font = play.top_bar_font;
80
81 // DisplaySpeech normally sets this up, but since we're not going via it...
82 if (play.cant_skip_speech & SKIP_AUTOTIMER)
83 play.messagetime = GetTextDisplayTime(text);
84
85 DisplayAtY(play.top_bar_ypos, text);
86 }
87
88 // Display a room/global message in the bar
DisplayMessageBar(int ypos,int ttexcol,int backcol,const char * title,int msgnum)89 void DisplayMessageBar(int ypos, int ttexcol, int backcol, const char *title, int msgnum) {
90 char msgbufr[3001];
91 get_message_text(msgnum, msgbufr);
92 DisplayTopBar(ypos, ttexcol, backcol, title, msgbufr);
93 }
94
DisplayMessageAtY(int msnum,int ypos)95 void DisplayMessageAtY(int msnum, int ypos) {
96 char msgbufr[3001];
97 if (msnum>=500) { //quit("global message requseted, nto yet supported");
98 get_message_text (msnum, msgbufr);
99 if (display_message_aschar > 0)
100 DisplaySpeech(msgbufr, display_message_aschar);
101 else
102 DisplayAtY(ypos, msgbufr);
103 display_message_aschar=0;
104 return;
105 }
106
107 if (display_message_aschar > 0) {
108 display_message_aschar=0;
109 quit("!DisplayMessage: data column specified a character for local\n"
110 "message; use the message editor to select the character for room\n"
111 "messages.\n");
112 }
113
114 int repeatloop=1;
115 while (repeatloop) {
116 get_message_text (msnum, msgbufr);
117
118 if (thisroom.msgi[msnum].displayas>0) {
119 DisplaySpeech(msgbufr, thisroom.msgi[msnum].displayas - 1);
120 }
121 else {
122 // time out automatically if they have set that
123 int oldGameSkipDisp = play.skip_display;
124 if (thisroom.msgi[msnum].flags & MSG_TIMELIMIT)
125 play.skip_display = 0;
126
127 DisplayAtY(ypos, msgbufr);
128
129 play.skip_display = oldGameSkipDisp;
130 }
131 if (thisroom.msgi[msnum].flags & MSG_DISPLAYNEXT) {
132 msnum++;
133 repeatloop=1;
134 }
135 else
136 repeatloop=0;
137 }
138
139 }
140
DisplayMessage(int msnum)141 void DisplayMessage(int msnum) {
142 DisplayMessageAtY (msnum, -1);
143 }
144
DisplayAt(int xxp,int yyp,int widd,const char * text)145 void DisplayAt(int xxp,int yyp,int widd, const char* text) {
146 multiply_up_coordinates(&xxp, &yyp);
147 widd = multiply_up_coordinate(widd);
148
149 if (widd<1) widd=play.viewport.GetWidth()/2;
150 if (xxp<0) xxp=play.viewport.GetWidth()/2-widd/2;
151 _display_at(xxp,yyp,widd,text,1,0, 0, 0, false);
152 }
153
DisplayAtY(int ypos,const char * texx)154 void DisplayAtY (int ypos, const char *texx) {
155 if ((ypos < -1) || (ypos >= BASEHEIGHT))
156 quitprintf("!DisplayAtY: invalid Y co-ordinate supplied (used: %d; valid: 0..%d)", ypos, BASEHEIGHT);
157
158 // Display("") ... a bit of a stupid thing to do, so ignore it
159 if (texx[0] == 0)
160 return;
161
162 if (ypos > 0)
163 ypos = multiply_up_coordinate(ypos);
164
165 if (game.options[OPT_ALWAYSSPCH])
166 DisplaySpeechAt(-1, (ypos > 0) ? divide_down_coordinate(ypos) : ypos, -1, game.playercharacter, texx);
167 else {
168 // Normal "Display" in text box
169
170 if (screen_is_dirty) {
171 // erase any previous DisplaySpeech
172 play.disabled_user_interface ++;
173 UpdateGameOnce();
174 play.disabled_user_interface --;
175 }
176
177 _display_at(-1,ypos,play.viewport.GetWidth()/2+play.viewport.GetWidth()/4,get_translation(texx),1,0, 0, 0, false);
178 }
179 }
180
SetSpeechStyle(int newstyle)181 void SetSpeechStyle (int newstyle) {
182 if ((newstyle < 0) || (newstyle > 3))
183 quit("!SetSpeechStyle: must use a SPEECH_* constant as parameter");
184 game.options[OPT_SPEECHTYPE] = newstyle;
185 }
186
SetSkipSpeech(SkipSpeechStyle newval)187 void SetSkipSpeech (SkipSpeechStyle newval) {
188 if ((newval < kSkipSpeechFirst) || (newval > kSkipSpeechLast))
189 quit("!SetSkipSpeech: invalid skip mode specified");
190
191 debug_script_log("SkipSpeech style set to %d", newval);
192 play.cant_skip_speech = user_to_internal_skip_speech((SkipSpeechStyle)newval);
193 }
194
GetSkipSpeech()195 SkipSpeechStyle GetSkipSpeech()
196 {
197 return internal_skip_speech_to_user(play.cant_skip_speech);
198 }
199