1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 /*
20 * $Source: r:/prj/cit/src/RCS/plotware.c $
21 * $Revision: 1.19 $
22 * $Author: xemu $
23 * $Date: 1994/11/09 16:27:33 $
24 *
25 *
26 */
27
28 #include <stdbool.h>
29 #include <string.h>
30
31 #include "mfdint.h"
32 #include "mfdext.h"
33 #include "mfddims.h"
34 #include "objsim.h"
35 #include "gamestrn.h"
36 #include "tools.h"
37 #include "mfdgadg.h"
38 #include "wares.h"
39 #include "cit2d.h"
40 #include "gr2ss.h"
41
42 #include "mfdart.h"
43 #include "gamescr.h"
44 #include "otrip.h"
45 #include "cybstrng.h"
46
47 #include "shodan.h"
48
49 // ============================================================
50 // DA PLOTWARE
51 // ============================================================
52
53 // -------
54 // DEFINES
55 // -------
56 extern short qdata_get(short);
57
58 #define MFD_PLOTWARE_FUNC 16
59 #define ITEM_COLOR 0x5A
60 #define TITLE_COLOR 0x35
61
62 #define NULL_PAGE 0xFF
63 #define PLOTWARE_VERSION (player_struct.hardwarez[CPTRIP(STATUS_HARD_TRIPLE)])
64 #define NUM_PAGES 3
65
66 typedef struct _plot_display {
67 ubyte page; // Page number of this display.
68 int name; // string id of name.
69 ubyte color; // color to display in
70 int baseval; // base string id for val, zero means display as int
71 short questvar; // Quest variable
72 } plot_display;
73
74 #define INT_TYPE 0
75 #define COUNTDOWN_TYPE 1
76 #define HACK_TYPE 2
77 #define PLAYER_FIELD(fld) (char *)&(((Player *)(0))->fld)
78
79 #define MAIN_PROGRAM_QDATA 0x1009
80
81 // ----------
82 // PROTOTYPES
83 // ----------
84 void fill_time(short val, char *vbuf);
85 bool do_plotware_hack(int hack_num, char *vbuf);
86 void mfd_plotware_expose(MFD *mfd, ubyte control);
87 void plotware_showpage(uchar page);
88 uchar plotware_button_handler(MFD *m, LGPoint bttn, uiEvent *ev, void *data);
89 errtype mfd_plotware_init(MFD_Func *f);
90 void plotware_turnon(uchar visible, uchar real);
91
92 // --------
93 // GLOBALS
94 // --------
95 plot_display PlotDisplays[] = {
96 {0, REF_STR_pwShodometer, ITEM_COLOR, HACK_TYPE, 2},
97 {0, REF_STR_pwLaser, ITEM_COLOR, REF_STR_pwLaser0, 0x2008},
98 {0, REF_STR_pwLifePods, ITEM_COLOR, REF_STR_pwEnabled, 0x2014},
99 {0, REF_STR_pwShield, ITEM_COLOR, REF_STR_pwShield0, 0x2006},
100 {0, REF_STR_pwCooling, ITEM_COLOR, REF_STR_pwCooling0, 0x2014},
101 {0, REF_STR_pwDestructTime, ITEM_COLOR, HACK_TYPE, 1},
102
103 {1, REF_STR_pwNodes, ITEM_COLOR, HACK_TYPE, 6},
104 // {1, REF_STR_pwMulti, ITEM_COLOR, INT_TYPE, 0x1000},
105 // {1, REF_STR_pwCPUcool, ITEM_COLOR, REF_STR_pwCPUcool0, 0x2010},
106 {1, REF_STR_pwMainProgram, ITEM_COLOR, REF_STR_pwNull, 0},
107 {1, REF_STR_Null, ITEM_COLOR, REF_STR_pwMainProgram0, MAIN_PROGRAM_QDATA},
108 // {1, REF_STR_pwDownLoadTime, ITEM_COLOR, HACK_TYPE, 0 },
109 // {1, REF_STR_pwBridgeTime, ITEM_COLOR, HACK_TYPE, 4 },
110 // {1, REF_STR_pwVirusTime, ITEM_COLOR, HACK_TYPE, 5 },
111 {1, REF_STR_pwComm, ITEM_COLOR, REF_STR_pwComm0, 0x1002},
112
113 {2, REF_STR_pwGroveStatus, TITLE_COLOR, REF_STR_pwNull, 0},
114 {2, REF_STR_pwAlpha, ITEM_COLOR, HACK_TYPE, 7},
115 {2, REF_STR_pwBeta, ITEM_COLOR, HACK_TYPE, 8},
116 {2, REF_STR_pwGamma, ITEM_COLOR, REF_STR_pwGamma0, 0},
117 {2, REF_STR_pwDelta, ITEM_COLOR, HACK_TYPE, 9},
118
119 {NULL_PAGE}
120 };
121
fill_time(short val,char * vbuf)122 void fill_time(short val, char *vbuf) {
123 if (val != 0) {
124 int16_t hours = val / 3600;
125 int16_t minutes = (val - (3600 * hours)) / 60;
126 int16_t seconds = (val - (3600 * hours) - minutes * 60);
127 sprintf(vbuf, "%d:%02d:%02d", hours, minutes, seconds);
128 } else {
129 strcpy(vbuf, "-:--:--");
130 }
131 }
132
133 #define DOWNLOAD_TIME 100
134 #define DOWNLOAD_PROGNUM 2
135 #define VIRUS_PROGNUM 1
136 #define BRIDGE_PROGNUM 4
137
138 #define REACTOR_QDATA 0x1002
139 #define REACTOR_DESTRUCT 1
140
141 #define SHODOMETER_BASE 0x1010
142 #define SHODOMETER_LEVELS MAX_SHODOMETER_LEVEL + 1
143
144 #define NODES_QDATA 0x1001
145 #define TOTAL_NODES 27
146
do_plotware_hack(int hack_num,char * vbuf)147 bool do_plotware_hack(int hack_num, char *vbuf) {
148 switch (hack_num) {
149 case 0:
150 if (qdata_get(MAIN_PROGRAM_QDATA) != DOWNLOAD_PROGNUM)
151 return false;
152 sprintf(vbuf, "%d%%", player_struct.time2comp * 100 / DOWNLOAD_TIME);
153 return true;
154 case 1:
155 if (qdata_get(REACTOR_QDATA) != REACTOR_DESTRUCT)
156 return false;
157 fill_time(player_struct.time2comp, vbuf);
158 return true;
159 case 2:
160 if (player_struct.level >= SHODOMETER_LEVELS)
161 return false;
162 else {
163 sprintf(vbuf, "%d%%",
164 QUESTVAR_GET(0x10 + player_struct.level) * 100 / player_struct.initial_shodan_vals[player_struct.level]);
165 return true;
166 }
167 // There is nooooooooooooooooooo case 3.
168 // Mostly because we haven't necessarily loaded the other levels to figure
169 // out what their shodometer levels were.
170 case 4:
171 if (qdata_get(MAIN_PROGRAM_QDATA) != BRIDGE_PROGNUM)
172 return false;
173 fill_time(player_struct.time2comp, vbuf);
174 return true;
175 case 5:
176 if (qdata_get(MAIN_PROGRAM_QDATA) != VIRUS_PROGNUM)
177 return false;
178 fill_time(player_struct.time2comp, vbuf);
179 return true;
180 case 6:
181 sprintf(vbuf, "%d", TOTAL_NODES - qdata_get(NODES_QDATA));
182 return true;
183 case 7:
184 if (QUESTBIT_GET(0x0B))
185 get_string(REF_STR_pwAlpha0 + 1, vbuf, 9);
186 else
187 get_string(REF_STR_pwAlpha0, vbuf, 9);
188 return true;
189 case 8:
190 if (QUESTBIT_GET(0x0F))
191 get_string(REF_STR_pwBeta0 + 2, vbuf, 9);
192 else if (QUESTBIT_GET(0x0C))
193 get_string(REF_STR_pwBeta0 + 1, vbuf, 9);
194 else
195 get_string(REF_STR_pwBeta0, vbuf, 9);
196 return true;
197 case 9:
198 if (QUESTBIT_GET(0x0A))
199 get_string(REF_STR_pwDelta0 + 1, vbuf, 9);
200 else
201 get_string(REF_STR_pwDelta0, vbuf, 9);
202 return true;
203
204 default:
205 *vbuf = '\0';
206 return false;
207 }
208 }
209
210 // ---------------
211 // EXPOSE FUNCTION
212 // ---------------
213
214 #define PLOTWARE_MFD_FUNC 16
215
216 #define DISPLAY_TOP_MARGIN 10
217 #define LEFT_X 2
218 #define RIGHT_X (MFD_VIEW_WID - 2)
219 #define PLOTWARE_PAGENUM (player_struct.mfd_func_data[PLOTWARE_MFD_FUNC][0])
220
221 #define BUTTON_Y (MFD_VIEW_HGT - res_bm_height(REF_IMG_PrevPage) - 2)
222
223 extern void mfd_item_micro_expose(uchar full, int triple);
224
mfd_plotware_expose(MFD * mfd,ubyte control)225 void mfd_plotware_expose(MFD *mfd, ubyte control) {
226 extern void mfd_item_micro_hires_expose(bool, int);
227 uchar full = control & MFD_EXPOSE_FULL;
228 if (control == 0) // MFD is drawing stuff
229 {
230 // Do unexpose stuff here.
231 }
232 if (control & MFD_EXPOSE) // Time to draw stuff
233 {
234 short y = DISPLAY_TOP_MARGIN;
235 int i;
236 // clear update rects
237 mfd_clear_rects();
238 // set up canvas
239 gr_push_canvas(pmfd_canvas);
240 ss_safe_set_cliprect(0, 0, MFD_VIEW_WID, MFD_VIEW_HGT);
241
242 mfd_item_micro_expose(true, STATUS_HARD_TRIPLE);
243 // mfd_item_micro_hires_expose(true,STATUS_HARD_TRIPLE);
244 if (!full)
245 mfd_clear_rects();
246
247 // INSERT GRAPHICS CODE HERE
248 gr_set_font(ResLock(MFD_FONT));
249 for (i = 0; PlotDisplays[i].page < NUM_PAGES; i++) {
250 char buf[40], vbuf[40];
251 short val;
252 short w, h;
253 plot_display *dp = &PlotDisplays[i];
254 if (dp->page != PLOTWARE_PAGENUM)
255 continue;
256 switch (dp->baseval) {
257 case INT_TYPE:
258 val = qdata_get(dp->questvar);
259 sprintf(vbuf, "%d", val);
260 break;
261 case COUNTDOWN_TYPE:
262 val = *(short *)(((char *)&player_struct) + dp->questvar);
263 fill_time(val, vbuf);
264 break;
265 case HACK_TYPE:
266 if (!do_plotware_hack(dp->questvar, vbuf))
267 continue;
268 break;
269 default:
270 val = qdata_get(dp->questvar);
271 if (dp->questvar & 0x2000)
272 if (val)
273 val = 1;
274 get_string(dp->baseval + val, vbuf, sizeof(vbuf));
275 break;
276 }
277 get_string(dp->name, buf, sizeof(buf));
278 mfd_full_draw_string(buf, LEFT_X, y, dp->color, MFD_FONT, true, true);
279 gr_string_size(vbuf, &w, &h);
280 mfd_full_draw_string(vbuf, RIGHT_X - w, y, dp->color, MFD_FONT, true, true);
281 y += h + 1;
282 }
283 if (full) {
284 char buf[50];
285 short w, h;
286 // Draw the page number
287 get_string(REF_STR_pwPage0 + PLOTWARE_PAGENUM, buf, sizeof(buf));
288 gr_string_size(buf, &w, &h);
289 mfd_draw_string(buf, (MFD_VIEW_WID - w) / 2, BUTTON_Y + (res_bm_height(REF_IMG_NextPage) - h) / 2,
290 ITEM_COLOR, true);
291 // Draw the page buttons
292 draw_raw_resource_bm(REF_IMG_PrevPage, LEFT_X, BUTTON_Y);
293 draw_raw_resource_bm(REF_IMG_NextPage, RIGHT_X - res_bm_width(REF_IMG_NextPage), BUTTON_Y);
294 }
295
296 ResUnlock(MFD_FONT);
297 // on a full expose, make sure to draw everything
298
299 if (full)
300 mfd_add_rect(0, 0, MFD_VIEW_WID, MFD_VIEW_HGT);
301
302 // Pop the canvas
303 gr_pop_canvas();
304 // Now that we've popped the canvas, we can send the
305 // updated mfd to screen
306 mfd_update_rects(mfd);
307 }
308 }
309
plotware_showpage(uchar page)310 void plotware_showpage(uchar page) {
311 if (PLOTWARE_VERSION == 0 || page >= NUM_PAGES)
312 return;
313 PLOTWARE_PAGENUM = page;
314 plotware_turnon(true, true);
315 }
316
317 // --------------
318 // BUTTON HANDLER
319 // --------------
plotware_button_handler(MFD * n,LGPoint bttn,uiEvent * ev,void * data)320 uchar plotware_button_handler(MFD *n, LGPoint bttn, uiEvent *ev, void *data) {
321 if (!(ev->subtype & MOUSE_LDOWN))
322 return true;
323 if (bttn.x == 0)
324 PLOTWARE_PAGENUM = (PLOTWARE_PAGENUM == 0) ? NUM_PAGES - 1 : PLOTWARE_PAGENUM - 1;
325 if (bttn.x == 1)
326 PLOTWARE_PAGENUM = (PLOTWARE_PAGENUM >= NUM_PAGES - 1) ? 0 : PLOTWARE_PAGENUM + 1;
327 mfd_notify_func(MFD_PLOTWARE_FUNC, MFD_ITEM_SLOT, false, MFD_ACTIVE, true);
328 return true;
329 }
330
331 // --------------
332 // INITIALIZATION
333 // --------------
mfd_plotware_init(MFD_Func * f)334 errtype mfd_plotware_init(MFD_Func *f) {
335 int cnt = 0;
336 LGPoint bsize;
337 LGPoint bdims;
338 LGRect r;
339 errtype err;
340 bsize.x = res_bm_width(REF_IMG_PrevPage);
341 bsize.y = res_bm_height(REF_IMG_NextPage);
342 bdims.x = 2;
343 bdims.y = 1;
344 r.ul.x = LEFT_X;
345 r.ul.y = BUTTON_Y;
346 r.lr.x = RIGHT_X;
347 r.lr.y = r.ul.y + bsize.y;
348 err = MFDBttnArrayInit(&f->handlers[cnt++], &r, bdims, bsize, plotware_button_handler, NULL);
349 if (err != OK)
350 return err;
351 f->handler_count = cnt;
352 return OK;
353 }
354
plotware_turnon(uchar visible,uchar realstart)355 void plotware_turnon(uchar visible, uchar realstart) {
356 if (visible) {
357 set_inventory_mfd(MFD_INV_HARDWARE, CPTRIP(STATUS_HARD_TRIPLE), true);
358 mfd_change_slot(mfd_grab_func(MFD_PLOTWARE_FUNC, MFD_ITEM_SLOT), MFD_ITEM_SLOT);
359 }
360 player_struct.hardwarez_status[CPTRIP(STATUS_HARD_TRIPLE)] &= ~(WARE_ON);
361 }
362