Vendor the Shockolate engine and build it via a Docker image with every
build / build (push) Failing after 5s
build / build (push) Failing after 5s
dependency (SDL2, SDL2_mixer, fluidsynth-lite, a MIDI soundfont) prebuilt, so compiling the engine needs no network access - just the image and the engine source. Add res/assets/extract_assets.sh to pull the game's data files out of a purchased GOG installer, and a Makefile that assembles a runnable dist/ from the two. Also add `make package`, which builds a redistributable tarball that omits the proprietary game assets (shipping res/GET_ASSETS.txt instead) plus license information for both the MIT tooling and the GPLv3 engine, and a Gitea Actions workflow that builds and publishes it to dl.ladkau.de on every push.
This commit is contained in:
@@ -0,0 +1,963 @@
|
||||
/*
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
/*
|
||||
* $Source: r:/prj/cit/src/RCS/status.c $
|
||||
* $Revision: 1.77 $
|
||||
* $Author: kevin $
|
||||
* $Date: 1994/11/29 11:50:25 $
|
||||
*/
|
||||
|
||||
// Source code for handling the status indicators for the
|
||||
// Citadel game screen
|
||||
//
|
||||
// Source is divided into two segments; first comes all the
|
||||
// biorhythm stuff (upper left hand corner of the game screen)
|
||||
// and second, the upper right hand healthy/suit-energy measuring
|
||||
// bar graphs
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "status.h"
|
||||
#include "player.h"
|
||||
#include "tools.h"
|
||||
#include "gamescr.h"
|
||||
#include "faketime.h"
|
||||
#include "fullscrn.h"
|
||||
#include "gamesys.h"
|
||||
#include "physics.h"
|
||||
#include "objsim.h"
|
||||
#include "biotrax.h"
|
||||
#include "otrip.h"
|
||||
|
||||
#include "curdat.h"
|
||||
|
||||
#include "gr2ss.h"
|
||||
|
||||
// Defines
|
||||
#define NUM_BIO_TRACKS 8
|
||||
|
||||
#define GAMESCR_BIO 0
|
||||
#define GAMESCR_BIO_X 5
|
||||
#define GAMESCR_BIO_Y 1
|
||||
//#define GAMESCR_BIO_WIDTH 149
|
||||
#define GAMESCR_BIO_WIDTH 131
|
||||
#define GAMESCR_BIO_HEIGHT 17
|
||||
|
||||
#define DIFF_BIO 1
|
||||
#define DIFF_BIO_X 6
|
||||
#define DIFF_BIO_Y 181
|
||||
#define DIFF_BIO_WIDTH 307
|
||||
#define DIFF_BIO_HEIGHT 17
|
||||
|
||||
#define STATUS_CHI_AMP 8
|
||||
|
||||
#define STATUS_BIO_X curr_bio_x
|
||||
#define STATUS_BIO_Y curr_bio_y
|
||||
#define STATUS_BIO_WIDTH curr_bio_w
|
||||
#define STATUS_BIO_HEIGHT curr_bio_h
|
||||
|
||||
#define STATUS_START_OFFSET 0
|
||||
#define STATUS_BIO_Y_DELTA 1
|
||||
#define MAX_BIO_LENGTH 307
|
||||
#define STATUS_BIO_LENGTH (STATUS_BIO_WIDTH - STATUS_START_OFFSET)
|
||||
#define STATUS_BIO_TAIL 30
|
||||
#define STATUS_BIO_PEAK (STATUS_BIO_HEIGHT - 3) // 3 because of zany art size
|
||||
#define STATUS_BIO_X_BASE (STATUS_BIO_X + STATUS_START_OFFSET)
|
||||
#define STATUS_BIO_Y_BASE (STATUS_BIO_Y + STATUS_BIO_HEIGHT - STATUS_BIO_Y_DELTA - 2)
|
||||
|
||||
#define SPIKE_THRESHOLD 4
|
||||
#define COLOR_CHANGES 6
|
||||
#define COLOR_LENGTH (STATUS_BIO_TAIL / COLOR_CHANGES)
|
||||
|
||||
#define MAX_TAIL_LENGTH 5
|
||||
#define NO_HEIGHT 0x1f
|
||||
#define INVALID_HEIGHT 0xE0
|
||||
|
||||
#define COLOR_BIO_MASK 0xE0 // Top Three bits signify depth of color
|
||||
#define HEIGHT_BIO_MASK 0x1f // Bottom Five bits signify height
|
||||
#define BIT6 0x20 // First bit of the color field.
|
||||
|
||||
#define COLOR_BIT_SHIFT(x) ((x) << 5)
|
||||
|
||||
//#define FIND_OVERLAP(x,y) (((x) - y + STATUS_BIO_LENGTH) % STATUS_BIO_LENGTH)
|
||||
|
||||
#define STATUS_VITALS_X 184
|
||||
#define STATUS_VITALS_Y 0
|
||||
#define STATUS_VITALS_WIDTH 130
|
||||
#define STATUS_VITALS_HEIGHT 17
|
||||
|
||||
#define STATUS_VITALS_X_BASE (STATUS_VITALS_X + 4)
|
||||
#define STATUS_VITALS_Y_TOP (STATUS_VITALS_Y + 1)
|
||||
#define STATUS_VITALS_Y_BOTTOM (STATUS_VITALS_Y + 11)
|
||||
#define STATUS_VITALS_H 8
|
||||
#define STATUS_VITALS_W (STATUS_VITALS_WIDTH - 9)
|
||||
|
||||
#define STATUS_X 4
|
||||
#define STATUS_Y 1
|
||||
#define STATUS_HEIGHT 20
|
||||
#define STATUS_WIDTH 312
|
||||
|
||||
#define GAMESCR_BIO_REF REF_IMG_bmBiorhythm
|
||||
#define DIFF_BIO_REF REF_IMG_bmDiffBio
|
||||
#define STATUS_RESID curr_bio_ref
|
||||
#define STATUS_RES_VITALSID REF_IMG_bmVitals
|
||||
#define STATUS_RES_HEALTH_ID REF_IMG_bmVitalInnardsTop
|
||||
#define STATUS_RES_ENERGY_ID REF_IMG_bmVitalInnardsBottom
|
||||
|
||||
// Special Status Biorhythm variables
|
||||
|
||||
#define NO_SPIKE 0x01
|
||||
#define SPIKE_NOISE 0x02
|
||||
|
||||
// Look ma, a new biorhythm option.
|
||||
#define BOTTOMLESS 0x04 // things that fall off the bottom don't get drawn.
|
||||
|
||||
// For now, turn these on so it won't try to draw any biorhythm stuff
|
||||
#define TIMING_PROCEDURES_OFF
|
||||
//#define TIMING_CALLBACK_OFF
|
||||
|
||||
// Struct to contain information about tail
|
||||
|
||||
typedef struct {
|
||||
uchar free;
|
||||
int *data;
|
||||
uchar height[MAX_BIO_LENGTH];
|
||||
int head;
|
||||
uchar tail;
|
||||
uchar tail_length;
|
||||
uchar color_length;
|
||||
int update_time;
|
||||
int counter;
|
||||
int max_value;
|
||||
uchar special;
|
||||
uchar active;
|
||||
} bio_data_block;
|
||||
|
||||
uchar gBioInited = FALSE;
|
||||
|
||||
uchar status_background[(DIFF_BIO_WIDTH + 4) * (DIFF_BIO_HEIGHT + 2)];
|
||||
// uchar status_background[(266+4)*(44+2)];
|
||||
uchar bio_data_buffer[NUM_BIO_TRACKS * sizeof(bio_data_block)];
|
||||
|
||||
#define FRAME_RATE_SCALE 20
|
||||
#define LOOPLINE_SCALE 0x2F
|
||||
|
||||
bio_data_block *bio_data;
|
||||
|
||||
int bio_time_id;
|
||||
|
||||
int curr_bio_x, curr_bio_y;
|
||||
int curr_bio_w, curr_bio_h;
|
||||
short curr_bio_mode;
|
||||
Ref curr_bio_ref;
|
||||
|
||||
static uchar track_colors[NUM_BIO_TRACKS] = {
|
||||
0x66, // turquoise
|
||||
0x57, // yellow green?
|
||||
0x73, // blue
|
||||
0x40, // orange
|
||||
0x4A, // yellow
|
||||
0x28, // gold
|
||||
0x33, // red
|
||||
0x20, // purple
|
||||
};
|
||||
|
||||
/* bio keeps private canvas so we don't have to save/restore stuff from
|
||||
the real screen canvas. */
|
||||
static grs_canvas bio_canvas;
|
||||
|
||||
#ifdef SYNCH_BIORHYTHMS
|
||||
grs_bitmap bio_bitmap;
|
||||
|
||||
#define BIO_BITMAP_SIZE ((GAMESCR_BIO_X + GAMESCR_BIO_WIDTH) * (GAMESCR_BIO_Y + GAMESCR_BIO_HEIGHT))
|
||||
uchar bio_bitmap_bits[BIO_BITMAP_SIZE];
|
||||
#endif
|
||||
|
||||
extern LGPoint LastCursorPos;
|
||||
|
||||
// Internal Prototype
|
||||
|
||||
uchar under_bio(int x);
|
||||
void ss_save_under_set_pixel(int color, short i, short j);
|
||||
void bio_set_pixel(int color, short x, short y);
|
||||
void bio_restore_pixel(grs_bitmap *bmp, short x, short y);
|
||||
void bio_vline(int color, int x, int y, int y1);
|
||||
uchar status_track_free(int track);
|
||||
uchar status_track_active(int track);
|
||||
void status_track_activate(int track, uchar active);
|
||||
void draw_lower_tracks(int track_number, int location);
|
||||
void draw_one_location_tracks(int location);
|
||||
void draw_bio_height(int track_number, int draw_location);
|
||||
errtype clear_bio_tracks(void);
|
||||
void clear_tail(int track_number, int delete_location);
|
||||
int FIND_OVERLAP(int x, int y);
|
||||
|
||||
void change_bio_vars(void);
|
||||
|
||||
void (*bio_funcs[])(void) = {gamescr_bio_func, diff_bio_func};
|
||||
|
||||
uchar under_bio(int x) {
|
||||
if (((x >= 16) && (x <= 22)) || ((x >= 69) && (x <= 74)) || ((x >= 114) && (x <= 208)) ||
|
||||
((x >= 252) && (x <= 258)) || ((x >= 298) && (x <= 303)))
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// bio_set_pixel(int color, int x, int y)
|
||||
//
|
||||
// calls gr_set_pixel as normal, unless the biorhythms is
|
||||
// going "under" something
|
||||
|
||||
void ss_save_under_set_pixel(int color, short i, short j) {
|
||||
extern LGPoint LastCursorPos;
|
||||
|
||||
if (LastCursor != NULL) {
|
||||
if ((LastCursorPos.x + SaveUnder.bm.w > i) && (LastCursorPos.x <= i)) {
|
||||
if ((LastCursorPos.y + SaveUnder.bm.h > j) && (LastCursorPos.y <= j)) {
|
||||
grs_bitmap *bm = (grs_bitmap *)(LastCursor->state);
|
||||
int k = (i - LastCursorPos.x) + SaveUnder.bm.row * (j - LastCursorPos.y);
|
||||
SaveUnder.bm.bits[k] = color;
|
||||
k = (i - LastCursorPos.x) + bm->row * (j - LastCursorPos.y);
|
||||
if (bm->bits[k]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gr_set_pixel(color, i, j);
|
||||
// mprintf("x:%i, y:%i, w:%i, h:%i\n",LastCursorPos.x,LastCursorPos.y,SaveUnder.bm.w,SaveUnder.bm.h);
|
||||
}
|
||||
|
||||
void bio_set_pixel(int color, short x, short y) {
|
||||
short x0, x1, y0, y1, i, j;
|
||||
|
||||
if ((curr_bio_mode == DIFF_BIO) && (under_bio(x)))
|
||||
return;
|
||||
if (convert_use_mode) {
|
||||
x0 = SCONV_X(x);
|
||||
y0 = SCONV_Y(y);
|
||||
x1 = SCONV_X(x + 1);
|
||||
y1 = SCONV_Y(y + 1);
|
||||
for (i = x0; i < x1; i++)
|
||||
for (j = y0; j < y1; j++)
|
||||
ss_save_under_set_pixel(color, i, j);
|
||||
} else
|
||||
ss_save_under_set_pixel(color, x, y);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Restore the pixels from the offscreen background bitmap.
|
||||
// ---------------------------------------------------------
|
||||
void bio_restore_pixel(grs_bitmap *bmp, short x, short y) {
|
||||
if ((curr_bio_mode == DIFF_BIO) && (under_bio(x)))
|
||||
return;
|
||||
|
||||
short a, b, c, d;
|
||||
STORE_CLIP(a, b, c, d);
|
||||
ss_cset_cliprect(&bio_canvas, x, y, x + 1, y + 1);
|
||||
ss_bitmap(bmp, STATUS_BIO_X, STATUS_BIO_Y);
|
||||
RESTORE_CLIP(a, b, c, d);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// bio_vline(int x, int y, int y1)
|
||||
//
|
||||
// calls bio_vline as normal, unless the biorhythms is
|
||||
// going "under" something
|
||||
|
||||
void bio_vline(int color, int x, int y, int y1) {
|
||||
if ((curr_bio_mode == DIFF_BIO) && (under_bio(x)))
|
||||
return;
|
||||
#ifdef SVGA_SUPPORT
|
||||
if (convert_use_mode != 0) {
|
||||
short x0, x1, i, j;
|
||||
x0 = SCONV_X(x);
|
||||
x1 = SCONV_X(x + 1);
|
||||
y = SCONV_Y(y);
|
||||
y1 = SCONV_Y(y1);
|
||||
if (y > y1) {
|
||||
int foo = y;
|
||||
y = y1;
|
||||
y1 = foo;
|
||||
}
|
||||
for (i = x0; i < x1; i++)
|
||||
for (j = y; j <= y1; j++)
|
||||
ss_save_under_set_pixel(color, i, j);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (y > y1) {
|
||||
int foo = y;
|
||||
y = y1;
|
||||
y1 = foo;
|
||||
}
|
||||
for (; y <= y1; y++)
|
||||
ss_save_under_set_pixel(color, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// status_bio_set(short bio_mode)
|
||||
//
|
||||
// Tell the biorhythm code which screen we are on
|
||||
|
||||
short bios_x[2] = {GAMESCR_BIO_X, DIFF_BIO_X};
|
||||
short bios_y[2] = {GAMESCR_BIO_Y, DIFF_BIO_Y};
|
||||
short bios_w[2] = {GAMESCR_BIO_WIDTH, DIFF_BIO_WIDTH};
|
||||
short bios_h[2] = {GAMESCR_BIO_HEIGHT, DIFF_BIO_HEIGHT};
|
||||
Ref bio_refs[2] = {GAMESCR_BIO_REF, DIFF_BIO_REF};
|
||||
|
||||
grs_bitmap bio_background_bitmap;
|
||||
|
||||
void status_bio_set(short bio_mode) {
|
||||
FrameDesc *f;
|
||||
int i;
|
||||
#ifdef SVGA_SUPPORT
|
||||
uchar old_over = gr2ss_override;
|
||||
#endif
|
||||
|
||||
curr_bio_mode = bio_mode;
|
||||
|
||||
// Assuming there are only 8 bio tracks!!!!!
|
||||
/* set biorhythm positions & clipping rectangle. */
|
||||
curr_bio_x = bios_x[bio_mode];
|
||||
curr_bio_y = bios_y[bio_mode];
|
||||
curr_bio_w = bios_w[bio_mode];
|
||||
curr_bio_h = bios_h[bio_mode];
|
||||
#ifdef SVGA_SUPPORT
|
||||
gr2ss_override = OVERRIDE_ALL;
|
||||
#endif
|
||||
ss_cset_cliprect(&bio_canvas, STATUS_BIO_X, STATUS_BIO_Y, STATUS_BIO_X + STATUS_BIO_WIDTH,
|
||||
STATUS_BIO_Y + STATUS_BIO_HEIGHT);
|
||||
#ifdef SVGA_SUPPORT
|
||||
gr2ss_override = old_over;
|
||||
#endif
|
||||
|
||||
curr_bio_ref = bio_refs[bio_mode];
|
||||
f = RefLock(STATUS_RESID);
|
||||
bio_background_bitmap = f->bm;
|
||||
|
||||
// let's try to do the right thing!
|
||||
bio_background_bitmap.bits = status_background;
|
||||
|
||||
LG_memcpy(bio_background_bitmap.bits, (char *)(f + 1), sizeof(char) * f->bm.w * f->bm.h);
|
||||
|
||||
bio_data = (bio_data_block *)bio_data_buffer;
|
||||
for (i = 0; i < NUM_BIO_TRACKS; i++)
|
||||
bio_data[i].free = TRUE;
|
||||
|
||||
RefUnlock(STATUS_RESID);
|
||||
bio_funcs[curr_bio_mode]();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// status_bio_init()
|
||||
//
|
||||
// Do the init stuff for the biorhythm. 2d should be initialized and
|
||||
// screen canvas should be unchanged when this is called.
|
||||
|
||||
void status_bio_update_screenmode() { bio_canvas = *grd_screen_canvas; /* make copy for int routine */ }
|
||||
|
||||
void status_bio_init(void) {
|
||||
status_bio_update_screenmode();
|
||||
|
||||
#ifndef TIMING_PROCEDURES_OFF
|
||||
bio_time_id = tm_add_process((void (*)())status_bio_update, 0, TMD_FREQ / 140);
|
||||
#endif
|
||||
}
|
||||
|
||||
void status_bio_start(void) {
|
||||
if (!full_game_3d)
|
||||
gBioInited = TRUE;
|
||||
|
||||
#ifndef TIMING_PROCEDURES_OFF
|
||||
tm_activate_process(bio_time_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
void status_bio_end(void) {
|
||||
gBioInited = FALSE;
|
||||
// Free(bio_background_bitmap.bits);
|
||||
#ifndef TIMING_PROCEDURES_OFF
|
||||
tm_deactivate_process(bio_time_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// status_bio_draw()
|
||||
//
|
||||
// Draw the biorhythm background
|
||||
|
||||
void status_bio_draw(void) {
|
||||
int i;
|
||||
|
||||
// Draw the background map
|
||||
ss_bitmap(&bio_background_bitmap, STATUS_BIO_X, STATUS_BIO_Y);
|
||||
// gr_bitmap(&bio_background_bitmap, SCONV_X(STATUS_BIO_X), SCONV_Y(STATUS_BIO_Y));
|
||||
|
||||
// Go from left to right and draw all the tracks
|
||||
for (i = 0; i < STATUS_BIO_LENGTH; i++)
|
||||
draw_one_location_tracks(i);
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
// Accessors for the "active" field.
|
||||
|
||||
uchar status_track_free(int track) { return bio_data[track].free; }
|
||||
|
||||
uchar status_track_active(int track) { return bio_data[track].active; }
|
||||
|
||||
void status_track_activate(int track, uchar active) { bio_data[track].active = active; }
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------
|
||||
// status_bio_add()
|
||||
//
|
||||
// *var - address of variable to be tracked
|
||||
// max_value - scale factor for value of variable
|
||||
// update_time - "bio time blocks" between update (can be any value)
|
||||
// track_number - track which this biorhythm should take (0 to NUM_BIO_TRACKS-1)
|
||||
// tail_length - length of tail (value * STATUS_BIO_TAIL)
|
||||
// special - special characteristics of this biorhythm
|
||||
//
|
||||
// Add a variable to be tracked by the biorhythm monitor.
|
||||
// Track the NULL pointer to clear out a track slot.
|
||||
//
|
||||
|
||||
errtype status_bio_add(int *var, int max_value, int update_time, int track_number, int tail_length, uchar special) {
|
||||
bio_data_block *new_block;
|
||||
uchar value;
|
||||
int var_value;
|
||||
|
||||
if (var == NULL) // are we trying to clear out a track slot??
|
||||
{
|
||||
if (bio_data[track_number].free == TRUE)
|
||||
return (ERR_NOEFFECT);
|
||||
else {
|
||||
bio_data[track_number].free = TRUE;
|
||||
bio_data[track_number].active = FALSE;
|
||||
return (OK);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we have a valid entry
|
||||
if ((bio_data[track_number].free == FALSE) || // unused track?
|
||||
(track_number >= NUM_BIO_TRACKS) || // correct track number?
|
||||
(tail_length < 1) || // non-negative tail length?
|
||||
(tail_length > MAX_TAIL_LENGTH)) // too long of a tail?
|
||||
return (ERR_NOEFFECT);
|
||||
else {
|
||||
// Initialize the new biorhythm
|
||||
|
||||
new_block = bio_data + track_number;
|
||||
new_block->free = FALSE;
|
||||
new_block->data = var;
|
||||
LG_memset(&(new_block->height), INVALID_HEIGHT, sizeof(uchar) * MAX_BIO_LENGTH);
|
||||
|
||||
// We must first check if the variable is greater than max value, if so make it max_value
|
||||
var_value = (*var > max_value) ? max_value : *var;
|
||||
|
||||
// Then check that it's not below 0
|
||||
if (var_value < 0)
|
||||
var_value = 0;
|
||||
|
||||
value = (var_value * STATUS_BIO_PEAK) / max_value;
|
||||
|
||||
// Set the end of the bio line to be the same as the initial
|
||||
// This way - we don't have to check if we've started a tail
|
||||
// when we erase the first value.
|
||||
new_block->height[STATUS_BIO_LENGTH - 1] = value | INVALID_HEIGHT;
|
||||
|
||||
// Initialize the struct
|
||||
new_block->head = 0; // head represents the first "new" x location
|
||||
new_block->tail = FALSE;
|
||||
new_block->tail_length = tail_length * STATUS_BIO_TAIL;
|
||||
new_block->color_length = tail_length * COLOR_LENGTH;
|
||||
new_block->update_time = update_time;
|
||||
new_block->counter = 0;
|
||||
new_block->max_value = max_value;
|
||||
new_block->special = special;
|
||||
new_block->active = TRUE;
|
||||
|
||||
return (OK);
|
||||
}
|
||||
}
|
||||
|
||||
errtype clear_bio_tracks() {
|
||||
int i;
|
||||
for (i = 0; i < NUM_BIO_TRACKS; i++)
|
||||
status_bio_add(NULL, 0, 0, i, 0, 0);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
//#define FIND_OVERLAP(x,y) (((x) - y + STATUS_BIO_LENGTH) % STATUS_BIO_LENGTH)
|
||||
int FIND_OVERLAP(int x, int y) { return (((x)-y + STATUS_BIO_LENGTH) % STATUS_BIO_LENGTH); }
|
||||
|
||||
#ifdef SYNCH_BIORHYTHMS
|
||||
#ifdef SVGA_SUPPORT
|
||||
// ------------------------------------------------------------------------
|
||||
// status_bio_synchronous()
|
||||
//
|
||||
// Does the synchronous blitting of biorhythm canvas
|
||||
void status_bio_synchronous() {
|
||||
if (!convert_use_mode)
|
||||
return;
|
||||
gr_push_canvas(grd_screen_canvas);
|
||||
ss_scale_bitmap(&bio_bitmap, 0, 0, GAMESCR_BIO_WIDTH, GAMESCR_BIO_HEIGHT);
|
||||
gr_pop_canvas();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// status_bio_update()
|
||||
//
|
||||
// Draw in the biorhythm stuff
|
||||
// Does clever incremental redraw (but not yet)
|
||||
|
||||
void status_bio_update(void) {
|
||||
#ifndef TIMING_CALLBACK_OFF
|
||||
uchar color;
|
||||
int i;
|
||||
int j;
|
||||
bio_data_block *curr_blk;
|
||||
int the_head;
|
||||
long color_base;
|
||||
int draw_location;
|
||||
int var_value;
|
||||
static grs_canvas *old_canvas;
|
||||
|
||||
if (!gBioInited)
|
||||
return;
|
||||
|
||||
MouseLock++;
|
||||
if (MouseLock > 1) {
|
||||
MouseLock--;
|
||||
return;
|
||||
}
|
||||
change_bio_vars();
|
||||
old_canvas = grd_canvas;
|
||||
gr_set_canvas(&bio_canvas);
|
||||
curr_blk = bio_data;
|
||||
|
||||
#ifdef SVGA_SUPPORT
|
||||
gr_push_state();
|
||||
#endif
|
||||
for (i = 0; i < NUM_BIO_TRACKS; i++, curr_blk++) {
|
||||
if (curr_blk->free == FALSE) {
|
||||
// We must check to see if this track should be drawn now,
|
||||
// or must it wait until it's time
|
||||
if (curr_blk->counter < curr_blk->update_time) {
|
||||
curr_blk->counter++;
|
||||
} else {
|
||||
curr_blk->counter = 0;
|
||||
color_base = track_colors[i]; // Prevent need to use index every time
|
||||
the_head = curr_blk->head; // Prevent need to look inside data structure every time
|
||||
|
||||
// We must first check if the variable is greater than max value, if so make it max_value
|
||||
var_value = (*(curr_blk->data) > curr_blk->max_value) ? curr_blk->max_value : (*(curr_blk->data));
|
||||
|
||||
// Then check that it's not below 0
|
||||
curr_blk->height[the_head] = (var_value <= 0) ? 0 : (var_value * STATUS_BIO_PEAK) / curr_blk->max_value;
|
||||
|
||||
if (curr_blk->special & BOTTOMLESS && curr_blk->height[the_head] == 0)
|
||||
curr_blk->height[the_head] = INVALID_HEIGHT;
|
||||
|
||||
// draw the head
|
||||
draw_lower_tracks(i, the_head);
|
||||
|
||||
// Draw the first trailer pixel - We know that this pixel must exist because we drew the first pixel
|
||||
// when we started the biorhythm
|
||||
|
||||
draw_location = FIND_OVERLAP(the_head, 1);
|
||||
curr_blk->height[draw_location] |= COLOR_BIT_SHIFT(1); // shift color
|
||||
draw_lower_tracks(i, draw_location);
|
||||
|
||||
if (curr_blk->tail == FALSE) {
|
||||
// Since we don't have a tail -
|
||||
// we don't know how long the biorhythm is
|
||||
// Let's find out what we have to dim!!!!
|
||||
|
||||
for (j = 0, draw_location = the_head - curr_blk->color_length;
|
||||
j < the_head / curr_blk->color_length; j++, draw_location -= curr_blk->color_length) {
|
||||
color = curr_blk->height[draw_location] & COLOR_BIO_MASK;
|
||||
if ((color != COLOR_BIT_SHIFT(j + 1)) || (rand() > (RAND_MAX / 2))) {
|
||||
curr_blk->height[draw_location] &= HEIGHT_BIO_MASK;
|
||||
curr_blk->height[draw_location] |= COLOR_BIT_SHIFT(j + 2);
|
||||
draw_lower_tracks(i, draw_location);
|
||||
}
|
||||
}
|
||||
|
||||
// Have we gotten to the point where we can see the end of the tail????
|
||||
|
||||
if (the_head == curr_blk->tail_length) {
|
||||
curr_blk->tail = TRUE; // start the tail
|
||||
clear_tail(i, 0); // clear the first spot
|
||||
}
|
||||
} else {
|
||||
// Since we have a tail - we know that we will have three spots to dim and one
|
||||
// to delete from the biorhythm - let's dim the three spots first.
|
||||
|
||||
for (j = 0, draw_location = FIND_OVERLAP(the_head, curr_blk->color_length); j < (COLOR_CHANGES - 1);
|
||||
j++, draw_location = FIND_OVERLAP(draw_location, curr_blk->color_length)) {
|
||||
color = curr_blk->height[draw_location] & COLOR_BIO_MASK;
|
||||
if ((color != COLOR_BIT_SHIFT(j + 1)) || (rand() > (RAND_MAX / 2))) {
|
||||
curr_blk->height[draw_location] &= HEIGHT_BIO_MASK;
|
||||
curr_blk->height[draw_location] |= COLOR_BIT_SHIFT(j + 2);
|
||||
draw_lower_tracks(i, draw_location);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's delete the end of the tail
|
||||
clear_tail(i, draw_location);
|
||||
}
|
||||
|
||||
// Advance the head
|
||||
curr_blk->head = (curr_blk->head + 1) % STATUS_BIO_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SVGA_SUPPORT
|
||||
gr_pop_state();
|
||||
#endif
|
||||
gr_set_canvas(old_canvas);
|
||||
MouseLock--;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// draw_bio_height()
|
||||
//
|
||||
// Note: requires bio_mouse_rect's x coordinates have already
|
||||
// been set. We do this since we only draw_one_location_tracks
|
||||
// calls this function.
|
||||
|
||||
void draw_bio_height(int track_number, int draw_location) {
|
||||
bio_data_block *curr_blk;
|
||||
long color;
|
||||
int x;
|
||||
int y;
|
||||
int y1;
|
||||
uchar height;
|
||||
int prevHeight;
|
||||
int prevSpike;
|
||||
|
||||
curr_blk = bio_data + track_number;
|
||||
|
||||
// Extract the raw "height" information
|
||||
height = curr_blk->height[draw_location];
|
||||
|
||||
if ((height & HEIGHT_BIO_MASK) == 0 && (curr_blk->special & BOTTOMLESS))
|
||||
return;
|
||||
|
||||
// If we have an invalid height, continue no further
|
||||
if ((height & INVALID_HEIGHT) == INVALID_HEIGHT)
|
||||
return;
|
||||
|
||||
// Extract the color offset
|
||||
color = track_colors[track_number] + ((height & COLOR_BIO_MASK) >> 5);
|
||||
|
||||
// Extract the actual height
|
||||
height &= HEIGHT_BIO_MASK;
|
||||
|
||||
// Get the previous height - to check for a spike
|
||||
prevHeight = prevSpike = curr_blk->height[FIND_OVERLAP(draw_location, 1)];
|
||||
prevHeight &= HEIGHT_BIO_MASK;
|
||||
|
||||
x = STATUS_BIO_X_BASE + draw_location;
|
||||
y = STATUS_BIO_Y_BASE - height;
|
||||
|
||||
if ((abs(height - prevHeight) < SPIKE_THRESHOLD) || (curr_blk->special & NO_SPIKE) ||
|
||||
((prevSpike & INVALID_HEIGHT) == INVALID_HEIGHT)) {
|
||||
bio_set_pixel(color, x, y);
|
||||
} else {
|
||||
y1 = STATUS_BIO_Y_BASE - prevHeight;
|
||||
|
||||
bio_vline(color, x, y, y1);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// clear_tail()
|
||||
//
|
||||
// KLC - greatly simplified this for Mac version, where the offscreen background
|
||||
// bitmap is the same size as onscreen. When clearing, we simply copy the back-
|
||||
// ground bitmap directly back onto the screen. bio_restore_pixel() handles
|
||||
// figuring out where to restore from.
|
||||
// ----------------------------------------------------------
|
||||
void clear_tail(int track_number, int delete_location) {
|
||||
bio_data_block *curr_blk;
|
||||
int prevHeight;
|
||||
int prevLocation;
|
||||
int height;
|
||||
int x, y, y1;
|
||||
int i, delta, base;
|
||||
|
||||
curr_blk = bio_data + track_number;
|
||||
prevLocation = FIND_OVERLAP(delete_location, 1);
|
||||
|
||||
prevHeight = curr_blk->height[prevLocation] & HEIGHT_BIO_MASK;
|
||||
height = curr_blk->height[delete_location] & HEIGHT_BIO_MASK;
|
||||
|
||||
x = STATUS_BIO_X_BASE + delete_location;
|
||||
y = STATUS_BIO_Y_BASE - height;
|
||||
|
||||
// First, check to see if we're restoring for a v-line spike.
|
||||
delta = abs(height - prevHeight);
|
||||
if ((delta >= SPIKE_THRESHOLD) && !((delete_location == 0) && (curr_blk->tail == FALSE))) {
|
||||
y1 = STATUS_BIO_Y_BASE - prevHeight;
|
||||
if (y > y1)
|
||||
base = y1;
|
||||
else
|
||||
base = y;
|
||||
for (i = 0; i < delta + 1; i++) {
|
||||
bio_restore_pixel(&bio_background_bitmap, x, base + i);
|
||||
}
|
||||
} else {
|
||||
bio_restore_pixel(&bio_background_bitmap, x, y);
|
||||
}
|
||||
|
||||
// Invalidate the height at the delete location
|
||||
curr_blk->height[delete_location] |= INVALID_HEIGHT;
|
||||
|
||||
draw_one_location_tracks(delete_location);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
// draw_one_location_tracks()
|
||||
//
|
||||
// procedure draws all tracks at a location along
|
||||
// the biorhythm
|
||||
// use this to draw to preserve ordering of tracks (overlapping)
|
||||
|
||||
void draw_one_location_tracks(int location) {
|
||||
int i;
|
||||
|
||||
for (i = (NUM_BIO_TRACKS - 1); i >= 0; i--) {
|
||||
if (!bio_data[i].free && bio_data[i].active)
|
||||
draw_bio_height(i, location);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// draw_lower_tracks()
|
||||
//
|
||||
// procedure differs from draw_one_location_tracks in that it only
|
||||
// draws tracks that are under the track number, including the track
|
||||
// number given. Saves a little work.
|
||||
//
|
||||
|
||||
void draw_lower_tracks(int track_number, int location) {
|
||||
int i;
|
||||
|
||||
for (i = track_number; i >= 0; i--) {
|
||||
if (!bio_data[i].free && bio_data[i].active)
|
||||
draw_bio_height(i, location);
|
||||
}
|
||||
}
|
||||
|
||||
// RANDOM SPEW STUFF
|
||||
// moved here by doug to make things looking pretty
|
||||
|
||||
#define SIN_MAG 20
|
||||
|
||||
// Temporary biorhythm variables
|
||||
ulong time1 = 0;
|
||||
ulong time2 = 0;
|
||||
ulong time3 = 0;
|
||||
ulong time4 = 0;
|
||||
ulong time5 = 0;
|
||||
ulong time6 = 0;
|
||||
ulong time7 = 0;
|
||||
int bio_delta = 1;
|
||||
extern int diff_sum;
|
||||
extern int curr_ll;
|
||||
|
||||
// this simulates the heart beat!
|
||||
int test_bio_var = 10;
|
||||
int test_bio_var2 = 2;
|
||||
|
||||
// this simulates the sine wave
|
||||
int test_bio_var3 = 19;
|
||||
|
||||
int bio_energy_var;
|
||||
fix sinX = 0;
|
||||
fix sinChi = 0;
|
||||
|
||||
void gamescr_bio_func(void) {
|
||||
extern int rad_absorb, bio_absorb;
|
||||
int i;
|
||||
|
||||
clear_bio_tracks();
|
||||
|
||||
// KLC - the "update_time" parameter is halved for Mac version, because we're only
|
||||
// getting called 70 times/sec rather than 140.
|
||||
|
||||
status_bio_add(&bio_energy_var, MAX_ENERGY, 2, ENERGY_TRACK, 2, 0);
|
||||
{
|
||||
short ver = player_struct.hardwarez[CPTRIP(ENV_HARD_TRIPLE)];
|
||||
if (ver >= 1)
|
||||
status_bio_add(&bio_absorb, 24, 2, BIOHAZARD_TRACK, 3, BOTTOMLESS);
|
||||
if (ver >= 2)
|
||||
status_bio_add(&rad_absorb, 24, 2, RADIATION_TRACK, 3, BOTTOMLESS);
|
||||
}
|
||||
status_bio_add(&test_bio_var, 20, 1, HEART_TRACK, 3, 0);
|
||||
status_bio_add(&test_bio_var3, SIN_MAG, 4, SINE_TRACK, 2, 0);
|
||||
|
||||
for (i = 0; i < NUM_BIO_TRACKS; i++)
|
||||
status_track_activate(i, (player_struct.active_bio_tracks & (1 << i)) != 0);
|
||||
}
|
||||
|
||||
void diff_bio_func(void) {
|
||||
clear_bio_tracks();
|
||||
// max_value, update_time, track_number, tail_length, special
|
||||
status_bio_add(&diff_sum, 12, 6, 0, 2, 0);
|
||||
status_bio_add(&test_bio_var, 20, 2, 1, 3, 0);
|
||||
status_bio_add(&test_bio_var3, 20, 8, 2, 2, 0);
|
||||
status_bio_add(&test_bio_var2, SIN_MAG, 4, 4, 3, 0);
|
||||
}
|
||||
|
||||
uchar heart_beat = 0;
|
||||
ulong heart_time = 0;
|
||||
ulong heart_delay = 5;
|
||||
uchar flatline_heart;
|
||||
|
||||
uchar chi_amp = STATUS_CHI_AMP;
|
||||
|
||||
extern ubyte fatigue_threshold;
|
||||
|
||||
#define FATIGUE_RANGE (CONTROL_MAX_VAL - SPRINT_CONTROL_THRESHOLD)
|
||||
#define ENERGY_ZERO 50
|
||||
|
||||
void change_bio_vars(void) {
|
||||
// Demo for biorhythm
|
||||
int fatigue_ratio;
|
||||
int fatigue_amp;
|
||||
int chi_per;
|
||||
|
||||
if ((*tmd_ticks - heart_time) > heart_delay) {
|
||||
switch (heart_beat) {
|
||||
case 0:
|
||||
|
||||
{
|
||||
int f = lg_max(0, (player_struct.fatigue - (CIT_CYCLE * fatigue_threshold)) / CIT_CYCLE);
|
||||
int heart_ratio = 3400 / (f + 7);
|
||||
if (heart_ratio > 500)
|
||||
heart_ratio = 500;
|
||||
else if (heart_ratio < 90)
|
||||
heart_ratio = 90;
|
||||
if (!flatline_heart && (*tmd_ticks - time1) > heart_ratio) {
|
||||
test_bio_var = 19;
|
||||
heart_delay = 5;
|
||||
time1 = heart_time = *tmd_ticks;
|
||||
heart_beat = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 1:
|
||||
heart_beat = 2;
|
||||
test_bio_var = 20;
|
||||
heart_delay = 5;
|
||||
break;
|
||||
case 2:
|
||||
heart_beat = 3;
|
||||
test_bio_var = 10;
|
||||
heart_delay = 7;
|
||||
break;
|
||||
case 3:
|
||||
heart_beat = 4;
|
||||
test_bio_var = 2;
|
||||
heart_delay = 5;
|
||||
break;
|
||||
case 4:
|
||||
heart_beat = 5;
|
||||
test_bio_var = 1;
|
||||
heart_delay = 5;
|
||||
break;
|
||||
case 5:
|
||||
heart_beat = 0;
|
||||
test_bio_var = 10;
|
||||
heart_delay = 5;
|
||||
break;
|
||||
}
|
||||
heart_time = *tmd_ticks;
|
||||
}
|
||||
// bio_energy_var
|
||||
{
|
||||
static ubyte energy_spike = 0;
|
||||
static int last_val = 0;
|
||||
if (bio_energy_var != last_val)
|
||||
energy_spike = 3;
|
||||
if (energy_spike == 0) {
|
||||
bio_energy_var = ENERGY_ZERO + player_struct.energy_spend - player_struct.energy_regen;
|
||||
} else {
|
||||
energy_spike--;
|
||||
}
|
||||
last_val = bio_energy_var;
|
||||
}
|
||||
// MR. SINUSOID biorhythm
|
||||
if (player_struct.fatigue)
|
||||
fatigue_ratio = fatigue_amp = (150000 / player_struct.fatigue);
|
||||
else {
|
||||
fatigue_ratio = 40;
|
||||
fatigue_amp = SIN_MAG;
|
||||
}
|
||||
|
||||
if (fatigue_ratio < 5)
|
||||
fatigue_ratio = 5;
|
||||
else if (fatigue_ratio > 40)
|
||||
fatigue_ratio = 40;
|
||||
|
||||
fatigue_amp -= 5;
|
||||
if (fatigue_amp < 0)
|
||||
fatigue_amp = 0;
|
||||
else if (fatigue_amp > SIN_MAG)
|
||||
fatigue_amp = SIN_MAG;
|
||||
|
||||
if ((*tmd_ticks - time2) > fatigue_ratio) {
|
||||
sinX += FIX_UNIT / 10;
|
||||
test_bio_var2 = (((FIX_UNIT - fix_fastsin(sinX)) / 2) * fatigue_amp) + 1 + ((SIN_MAG - fatigue_amp) / 2);
|
||||
time2 = *tmd_ticks;
|
||||
}
|
||||
|
||||
chi_per = chi_amp;
|
||||
if (player_struct.drug_status[CPTRIP(LSD_DRUG_TRIPLE)])
|
||||
chi_per <<= 1;
|
||||
if (player_struct.drug_status[CPTRIP(GENIUS_DRUG_TRIPLE)])
|
||||
chi_per >>= 2;
|
||||
if (chi_per < 2) {
|
||||
test_bio_var3 = 10;
|
||||
time3 = *tmd_ticks;
|
||||
sinChi = 0;
|
||||
} else if ((*tmd_ticks - time3) > chi_per) {
|
||||
fix s;
|
||||
sinChi += FIX_UNIT / 20;
|
||||
if (sinChi > 6 * FIX_UNIT)
|
||||
sinChi -= 6 * FIX_UNIT;
|
||||
if (sinChi < fix_make(3, 0))
|
||||
s = -fix_mul(sinChi, sinChi - 3 * FIX_UNIT) * 4 / 9;
|
||||
else
|
||||
s = fix_mul(sinChi - 3 * FIX_UNIT, sinChi - 6 * FIX_UNIT) * 4 / 9;
|
||||
test_bio_var3 = 10 + fix_int(chi_amp * s);
|
||||
time3 = *tmd_ticks;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user