/* Copyright (C) 2015-2018 Night Dive Studios, LLC. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* * $Source: r:/prj/cit/src/RCS/plotware.c $ * $Revision: 1.19 $ * $Author: xemu $ * $Date: 1994/11/09 16:27:33 $ * * */ #include #include #include "mfdint.h" #include "mfdext.h" #include "mfdfunc.h" #include "mfddims.h" #include "objsim.h" #include "gamestrn.h" #include "tools.h" #include "mfdgadg.h" #include "wares.h" #include "gr2ss.h" #include "mfdart.h" #include "gamescr.h" #include "otrip.h" #include "cybstrng.h" #include "plotware.h" #include "shodan.h" #include "trigger.h" // ============================================================ // DA PLOTWARE // ============================================================ // ------- // DEFINES // ------- #define MFD_PLOTWARE_FUNC 16 #define ITEM_COLOR 0x5A #define TITLE_COLOR 0x35 #define NULL_PAGE 0xFF #define PLOTWARE_VERSION (player_struct.hardwarez[CPTRIP(STATUS_HARD_TRIPLE)]) #define NUM_PAGES 3 typedef struct _plot_display { ubyte page; // Page number of this display. int name; // string id of name. ubyte color; // color to display in int baseval; // base string id for val, zero means display as int short questvar; // Quest variable } plot_display; #define INT_TYPE 0 #define COUNTDOWN_TYPE 1 #define HACK_TYPE 2 #define PLAYER_FIELD(fld) (char *)&(((Player *)(0))->fld) #define MAIN_PROGRAM_QDATA 0x1009 // ---------- // PROTOTYPES // ---------- void fill_time(short val, char *vbuf); bool do_plotware_hack(int hack_num, char *vbuf); void plotware_showpage(uchar page); uchar plotware_button_handler(MFD *m, LGPoint bttn, uiEvent *ev, void *data); // -------- // GLOBALS // -------- plot_display PlotDisplays[] = { {0, REF_STR_pwShodometer, ITEM_COLOR, HACK_TYPE, 2}, {0, REF_STR_pwLaser, ITEM_COLOR, REF_STR_pwLaser0, 0x2008}, {0, REF_STR_pwLifePods, ITEM_COLOR, REF_STR_pwEnabled, 0x2014}, {0, REF_STR_pwShield, ITEM_COLOR, REF_STR_pwShield0, 0x2006}, {0, REF_STR_pwCooling, ITEM_COLOR, REF_STR_pwCooling0, 0x2014}, {0, REF_STR_pwDestructTime, ITEM_COLOR, HACK_TYPE, 1}, {1, REF_STR_pwNodes, ITEM_COLOR, HACK_TYPE, 6}, // {1, REF_STR_pwMulti, ITEM_COLOR, INT_TYPE, 0x1000}, // {1, REF_STR_pwCPUcool, ITEM_COLOR, REF_STR_pwCPUcool0, 0x2010}, {1, REF_STR_pwMainProgram, ITEM_COLOR, REF_STR_pwNull, 0}, {1, REF_STR_Null, ITEM_COLOR, REF_STR_pwMainProgram0, MAIN_PROGRAM_QDATA}, // {1, REF_STR_pwDownLoadTime, ITEM_COLOR, HACK_TYPE, 0 }, // {1, REF_STR_pwBridgeTime, ITEM_COLOR, HACK_TYPE, 4 }, // {1, REF_STR_pwVirusTime, ITEM_COLOR, HACK_TYPE, 5 }, {1, REF_STR_pwComm, ITEM_COLOR, REF_STR_pwComm0, 0x1002}, {2, REF_STR_pwGroveStatus, TITLE_COLOR, REF_STR_pwNull, 0}, {2, REF_STR_pwAlpha, ITEM_COLOR, HACK_TYPE, 7}, {2, REF_STR_pwBeta, ITEM_COLOR, HACK_TYPE, 8}, {2, REF_STR_pwGamma, ITEM_COLOR, REF_STR_pwGamma0, 0}, {2, REF_STR_pwDelta, ITEM_COLOR, HACK_TYPE, 9}, {NULL_PAGE} }; void fill_time(short val, char *vbuf) { if (val != 0) { int16_t hours = val / 3600; int16_t minutes = (val - (3600 * hours)) / 60; int16_t seconds = (val - (3600 * hours) - minutes * 60); sprintf(vbuf, "%d:%02d:%02d", hours, minutes, seconds); } else { strcpy(vbuf, "-:--:--"); } } #define DOWNLOAD_TIME 100 #define DOWNLOAD_PROGNUM 2 #define VIRUS_PROGNUM 1 #define BRIDGE_PROGNUM 4 #define REACTOR_QDATA 0x1002 #define REACTOR_DESTRUCT 1 #define SHODOMETER_BASE 0x1010 #define SHODOMETER_LEVELS MAX_SHODOMETER_LEVEL + 1 #define NODES_QDATA 0x1001 #define TOTAL_NODES 27 bool do_plotware_hack(int hack_num, char *vbuf) { switch (hack_num) { case 0: if (qdata_get(MAIN_PROGRAM_QDATA) != DOWNLOAD_PROGNUM) return false; sprintf(vbuf, "%d%%", player_struct.time2comp * 100 / DOWNLOAD_TIME); return true; case 1: if (qdata_get(REACTOR_QDATA) != REACTOR_DESTRUCT) return false; fill_time(player_struct.time2comp, vbuf); return true; case 2: if (player_struct.level >= SHODOMETER_LEVELS) return false; else { sprintf(vbuf, "%d%%", QUESTVAR_GET(0x10 + player_struct.level) * 100 / player_struct.initial_shodan_vals[player_struct.level]); return true; } // There is nooooooooooooooooooo case 3. // Mostly because we haven't necessarily loaded the other levels to figure // out what their shodometer levels were. case 4: if (qdata_get(MAIN_PROGRAM_QDATA) != BRIDGE_PROGNUM) return false; fill_time(player_struct.time2comp, vbuf); return true; case 5: if (qdata_get(MAIN_PROGRAM_QDATA) != VIRUS_PROGNUM) return false; fill_time(player_struct.time2comp, vbuf); return true; case 6: sprintf(vbuf, "%d", TOTAL_NODES - qdata_get(NODES_QDATA)); return true; case 7: if (QUESTBIT_GET(0x0B)) get_string(REF_STR_pwAlpha0 + 1, vbuf, 9); else get_string(REF_STR_pwAlpha0, vbuf, 9); return true; case 8: if (QUESTBIT_GET(0x0F)) get_string(REF_STR_pwBeta0 + 2, vbuf, 9); else if (QUESTBIT_GET(0x0C)) get_string(REF_STR_pwBeta0 + 1, vbuf, 9); else get_string(REF_STR_pwBeta0, vbuf, 9); return true; case 9: if (QUESTBIT_GET(0x0A)) get_string(REF_STR_pwDelta0 + 1, vbuf, 9); else get_string(REF_STR_pwDelta0, vbuf, 9); return true; default: *vbuf = '\0'; return false; } } // --------------- // EXPOSE FUNCTION // --------------- #define PLOTWARE_MFD_FUNC 16 #define DISPLAY_TOP_MARGIN 10 #define LEFT_X 2 #define RIGHT_X (MFD_VIEW_WID - 2) #define PLOTWARE_PAGENUM (player_struct.mfd_func_data[PLOTWARE_MFD_FUNC][0]) #define BUTTON_Y (MFD_VIEW_HGT - res_bm_height(REF_IMG_PrevPage) - 2) void mfd_plotware_expose(MFD *mfd, ubyte control) { uchar full = control & MFD_EXPOSE_FULL; if (control == 0) // MFD is drawing stuff { // Do unexpose stuff here. } if (control & MFD_EXPOSE) // Time to draw stuff { short y = DISPLAY_TOP_MARGIN; int i; // clear update rects mfd_clear_rects(); // set up canvas gr_push_canvas(pmfd_canvas); ss_safe_set_cliprect(0, 0, MFD_VIEW_WID, MFD_VIEW_HGT); mfd_item_micro_expose(true, STATUS_HARD_TRIPLE); // mfd_item_micro_hires_expose(true,STATUS_HARD_TRIPLE); if (!full) mfd_clear_rects(); // INSERT GRAPHICS CODE HERE gr_set_font(ResLock(MFD_FONT)); for (i = 0; PlotDisplays[i].page < NUM_PAGES; i++) { char buf[40], vbuf[40]; short val; short w, h; plot_display *dp = &PlotDisplays[i]; if (dp->page != PLOTWARE_PAGENUM) continue; switch (dp->baseval) { case INT_TYPE: val = qdata_get(dp->questvar); sprintf(vbuf, "%d", val); break; case COUNTDOWN_TYPE: val = *(short *)(((char *)&player_struct) + dp->questvar); fill_time(val, vbuf); break; case HACK_TYPE: if (!do_plotware_hack(dp->questvar, vbuf)) continue; break; default: val = qdata_get(dp->questvar); if (dp->questvar & 0x2000) if (val) val = 1; get_string(dp->baseval + val, vbuf, sizeof(vbuf)); break; } get_string(dp->name, buf, sizeof(buf)); mfd_full_draw_string(buf, LEFT_X, y, dp->color, MFD_FONT, true, true); gr_string_size(vbuf, &w, &h); mfd_full_draw_string(vbuf, RIGHT_X - w, y, dp->color, MFD_FONT, true, true); y += h + 1; } if (full) { char buf[50]; short w, h; // Draw the page number get_string(REF_STR_pwPage0 + PLOTWARE_PAGENUM, buf, sizeof(buf)); gr_string_size(buf, &w, &h); mfd_draw_string(buf, (MFD_VIEW_WID - w) / 2, BUTTON_Y + (res_bm_height(REF_IMG_NextPage) - h) / 2, ITEM_COLOR, true); // Draw the page buttons draw_raw_resource_bm(REF_IMG_PrevPage, LEFT_X, BUTTON_Y); draw_raw_resource_bm(REF_IMG_NextPage, RIGHT_X - res_bm_width(REF_IMG_NextPage), BUTTON_Y); } ResUnlock(MFD_FONT); // on a full expose, make sure to draw everything if (full) mfd_add_rect(0, 0, MFD_VIEW_WID, MFD_VIEW_HGT); // Pop the canvas gr_pop_canvas(); // Now that we've popped the canvas, we can send the // updated mfd to screen mfd_update_rects(mfd); } } void plotware_showpage(uchar page) { if (PLOTWARE_VERSION == 0 || page >= NUM_PAGES) return; PLOTWARE_PAGENUM = page; plotware_turnon(true, true); } // -------------- // BUTTON HANDLER // -------------- uchar plotware_button_handler(MFD *n, LGPoint bttn, uiEvent *ev, void *data) { if (!(ev->subtype & MOUSE_LDOWN)) return true; if (bttn.x == 0) PLOTWARE_PAGENUM = (PLOTWARE_PAGENUM == 0) ? NUM_PAGES - 1 : PLOTWARE_PAGENUM - 1; if (bttn.x == 1) PLOTWARE_PAGENUM = (PLOTWARE_PAGENUM >= NUM_PAGES - 1) ? 0 : PLOTWARE_PAGENUM + 1; mfd_notify_func(MFD_PLOTWARE_FUNC, MFD_ITEM_SLOT, false, MFD_ACTIVE, true); return true; } // -------------- // INITIALIZATION // -------------- errtype mfd_plotware_init(MFD_Func *f) { int cnt = 0; LGPoint bsize; LGPoint bdims; LGRect r; errtype err; bsize.x = res_bm_width(REF_IMG_PrevPage); bsize.y = res_bm_height(REF_IMG_NextPage); bdims.x = 2; bdims.y = 1; r.ul.x = LEFT_X; r.ul.y = BUTTON_Y; r.lr.x = RIGHT_X; r.lr.y = r.ul.y + bsize.y; err = MFDBttnArrayInit(&f->handlers[cnt++], &r, bdims, bsize, plotware_button_handler, NULL); if (err != OK) return err; f->handler_count = cnt; return OK; } void plotware_turnon(uchar visible, uchar realstart) { if (visible) { set_inventory_mfd(MFD_INV_HARDWARE, CPTRIP(STATUS_HARD_TRIPLE), true); mfd_change_slot(mfd_grab_func(MFD_PLOTWARE_FUNC, MFD_ITEM_SLOT), MFD_ITEM_SLOT); } player_struct.hardwarez_status[CPTRIP(STATUS_HARD_TRIPLE)] &= ~(WARE_ON); }