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