rott/rott/rt_draw.c

6510 lines
147 KiB
C
Executable File

/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// RT_DRAW.C
#include "profile.h"
#include "rt_def.h"
#include <string.h>
#ifdef DOS
#include <dos.h>
#include <conio.h>
#endif
#include "watcom.h"
#include "sprites.h"
#include "rt_actor.h"
#include "rt_stat.h"
#include "rt_draw.h"
#include "_rt_draw.h"
#include "rt_dr_a.h"
#include "rt_fc_a.h"
#include "rt_scale.h"
#include "rt_floor.h"
#include "rt_main.h"
#include "rt_playr.h"
#include "rt_door.h"
#include "rt_ted.h"
#include "isr.h"
#include "rt_util.h"
#include "engine.h"
#include "z_zone.h"
#include "w_wad.h"
#include "lumpy.h"
#include "rt_menu.h"
#include "rt_game.h"
#include "rt_vid.h"
#include "rt_view.h"
#include <stdio.h>
#include <stdlib.h>
#include "rt_cfg.h"
#include "rt_str.h"
#include "develop.h"
#include "rt_sound.h"
#include "rt_msg.h"
#include "modexlib.h"
#include "rt_rand.h"
#include "rt_net.h"
#include "rt_sc_a.h"
//MED
#include "memcheck.h"
extern void VH_UpdateScreen (void);
//int testval;
/*
=============================================================================
Global Variables GLOBAL VARIABLES
=============================================================================
*/
int iG_masked;
int whereami=-1;
byte * shadingtable;
word tilemap[MAPSIZE][MAPSIZE]; // wall values only
byte spotvis[MAPSIZE][MAPSIZE];
byte mapseen[MAPSIZE][MAPSIZE];
unsigned long * lights;
int wstart;
const int dirangle8[9] = {0,FINEANGLES/8,2*FINEANGLES/8,3*FINEANGLES/8,4*FINEANGLES/8,
5*FINEANGLES/8,6*FINEANGLES/8,7*FINEANGLES/8,8*FINEANGLES/8};
const int dirangle16[16] = {0,FINEANGLES/16,2*FINEANGLES/16,3*FINEANGLES/16,
4*FINEANGLES/16,5*FINEANGLES/16,6*FINEANGLES/16,
7*FINEANGLES/16,8*FINEANGLES/16,9*FINEANGLES/16,
10*FINEANGLES/16,11*FINEANGLES/16,12*FINEANGLES/16,
13*FINEANGLES/16,14*FINEANGLES/16,15*FINEANGLES/16};
//
// math tables
//
short tantable[FINEANGLES];
int sintable[FINEANGLES+FINEANGLEQUAD+1],
*costable = sintable+(FINEANGLES/4);
//
// refresh variables
//
fixed viewx,viewy; // the focal point
int viewangle;
int c_startx, c_starty;
fixed viewsin,viewcos;
int tics;
//
// ray tracing variables
//
long xintercept,yintercept;
int doublestep=0;
int hp_startfrac;
int hp_srcstep;
int levelheight;
int actortime=0;
int drawtime=0;
visobj_t vislist[MAXVISIBLE],*visptr,*visstep,*farthest;
int firstcoloffset=0;
/*
==================
=
= Local Variables
=
==================
*/
static int nonbobpheight;
static visobj_t * sortedvislist[MAXVISIBLE];
static const fixed mindist = 0x1000;
static int walltime=0;
static int weaponbobx, weaponboby;
static int pretics[3];
static int preindex;
static int netlump;
static int gmasklump;
int G_gmasklump;
static const int weaponshape[NUMWEAPGRAPHICS] =
{
#if (SHAREWARE == 0)
W_KNIFE,
#endif
W_MALEPISTOL1,
W_MRIGHTPISTOL1,
W_MP40,
W_BAZOOKA,
W_HEATSEEKER,
W_DRUNK,
W_FIREBOMB,
W_FIREWALL,
W_GODHAND,
#if (SHAREWARE == 0)
W_SPLIT,
W_KES,
W_BAT,
W_DOG,
W_FEMALEPISTOL1,
W_BMALEPISTOL1
#endif
};
void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright);
void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked);
void InterpolateMaskedWall (visobj_t * plane);
void InterpolateDoor (visobj_t * plane);
void InterpolateWall (visobj_t * plane);
/*
==================
=
= BuildTables
=
==================
*/
void BuildTables (void)
{
byte * table;
byte * ptr;
int length;
int i;
//
// load in tables file
//
table=W_CacheLumpName("tables",PU_STATIC, CvtNull, 1);
ptr=table;
//
// get size of first table
//
memcpy(&length,ptr,sizeof(int));
SwapIntelLong(&length);
//
// skip first table
//
ptr+=(length+1)*sizeof(int);
//
// get size of sin/cos table
//
memcpy(&length,ptr,sizeof(int));
SwapIntelLong(&length);
ptr+=sizeof(int);
//
// get sin/cos table
//
memcpy(&sintable[0],ptr,length*sizeof(int));
SwapIntelLongArray(&sintable[0], length);
ptr+=(length)*sizeof(int);
//
// get size of tangent table
//
memcpy(&length,ptr,sizeof(int));
SwapIntelLong(&length);
ptr+=sizeof(int);
//
// get tangent table
//
memcpy(tantable,ptr,length*sizeof(short));
SwapIntelShortArray(tantable, length);
ptr+=(length)*sizeof(short);
//
// get size of gamma table
//
memcpy(&length,ptr,sizeof(int));
SwapIntelLong(&length);
ptr+=sizeof(int);
//
// get gamma table
//
memcpy(&gammatable[0],ptr,length*sizeof(byte));
table=W_CacheLumpName("tables",PU_CACHE, CvtNull, 1);
costable = (fixed *)&(sintable[FINEANGLES/4]);
wstart=W_GetNumForName("WALLSTRT");
#if (SHAREWARE==0)
netlump=W_GetNumForName("net1");
#endif
gmasklump=W_GetNumForName("p_gmask");
G_gmasklump = gmasklump;
preindex=0;
pretics[0]=0x10000;
pretics[2]=0x10000;
pretics[1]=0x10000;
for(i=0;i<ANGLES;i++)
{angletodir[i] = (i + (ANGLES/16))/(ANGLES/8);
if (angletodir[i] == 8)
angletodir[i] = 0;
}
// Check out VENDOR.DOC file
CheckVendor();
if (!quiet)
printf("RT_DRAW: Tables Initialized\n");
}
/*
========================
=
= TransformObject
=
========================
*/
boolean TransformObject (int x, int y, int *dispx, int *dispheight)
{
fixed gx,gy,gxt,gyt,nx,ny;
//
// translate point to view centered coordinates
//
gx = x-viewx;
gy = y-viewy;
//
// calculate newx
//
gxt = FixedMul(gx,viewcos);
gyt = FixedMul(gy,viewsin);
nx = gxt-gyt;
if (nx<MINZ)
return false;
// the midpoint could put parts of the shape
// into an adjacent wall
//
// calculate newy
//
gxt = FixedMul(gx,viewsin);
gyt = FixedMul(gy,viewcos);
ny = gyt+gxt;
//
// calculate perspective ratio
//
*dispx = centerx + ny*scale/nx; // DEBUG: use assembly divide
*dispheight = heightnumerator/nx;
return true;
}
/*
========================
=
= TransformPoint
=
========================
*/
void TransformPoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
{
fixed gxt,gyt,nx,ny;
fixed gxtt,gytt;
int gx,gy;
int vx,vy;
int svs,svc;
//
// translate point to view centered coordinates
//
gx = x-viewx;
gy = y-viewy;
//
// calculate newx
//
gxt = FixedMul(gx,viewcos);
gyt = FixedMul(gy,viewsin);
nx =gxt-gyt;
if (nx<10)
nx=10;
//
// calculate newy
//
gxtt = FixedMul(gx,viewsin);
gytt = FixedMul(gy,viewcos);
ny = gytt+gxtt;
// too close, don't overflow the divid'
*screenx = centerx + ((ny*scale)/nx); // DEBUG: use assembly divide
*height = heightnumerator/nx;
if (*screenx<0)
{
svc=(-centerx)*viewcos;
svs=(-centerx)*viewsin;
vx=(scale*viewcos)+svs;
vy=(-scale*viewsin)+svc;
if (vertical)
{
if ((viewcos-viewsin)==0)
{
*height=20000<<HEIGHTFRACTION;
return;
}
gy=FixedScale(gx,vy,vx);
y=gy+viewy;
gyt = FixedMul(gy,viewsin);
nx =gxt-gyt;
if (nx<10)
nx=10;
*screenx = 0;
*height = heightnumerator/nx;
}
else
{
if ((-viewsin-viewcos)==0)
{
*height=20000<<HEIGHTFRACTION;
return;
}
gx=FixedScale(gy,vx,vy);
x=gx+viewx;
gxt = FixedMul(gx,viewcos);
nx =gxt-gyt;
if (nx<10)
nx=10;
*screenx = 0;
*height = heightnumerator/nx;
}
}
else if (*screenx>=viewwidth)
{
svc=(centerx)*viewcos;
svs=(centerx)*viewsin;
vx=(scale*viewcos)+svs;
vy=(-scale*viewsin)+svc;
if (vertical)
{
if ((viewcos+viewsin)==0)
{
*height=20000<<HEIGHTFRACTION;
return;
}
gy=FixedScale(gx,vy,vx);
y=gy+viewy;
gyt = FixedMul(gy,viewsin);
nx =gxt-gyt;
if (nx<10)
nx=10;
*screenx = viewwidth-1;
*height = heightnumerator/nx;
}
else
{
if ((-viewsin+viewcos)==0)
{
*height=20000<<HEIGHTFRACTION;
return;
}
gx=FixedScale(gy,vx,vy);
x=gx+viewx;
gxt = FixedMul(gx,viewcos);
nx =gxt-gyt;
if (nx<10)
nx=10;
*screenx = viewwidth-1;
*height = heightnumerator/nx;
}
}
if (vertical)
*texture=(y-*texture)&0xffff;
else
*texture=(x-*texture)&0xffff;
}
/*
========================
=
= TransformSimplePoint
=
========================
*/
boolean TransformSimplePoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
{
fixed gxt,gyt,nx,ny;
fixed gxtt,gytt;
int gx,gy;
//
// translate point to view centered coordinates
//
gx = x-viewx;
gy = y-viewy;
//
// calculate newx
//
gxt = FixedMul(gx,viewcos);
gyt = FixedMul(gy,viewsin);
nx =gxt-gyt;
if (nx<MINZ)
return false;
//
// calculate newy
//
gxtt = FixedMul(gx,viewsin);
gytt = FixedMul(gy,viewcos);
ny = gytt+gxtt;
// too close, don't overflow the divid'
*screenx = centerx + ((ny*scale)/nx); // DEBUG: use assembly divide
*height = heightnumerator/nx;
if (vertical)
*texture=(y-*texture)&0xffff;
else
*texture=(x-*texture)&0xffff;
return true;
}
/*
========================
=
= TransformPlane
=
========================
*/
boolean TransformPlane (int x1, int y1, int x2, int y2, visobj_t * plane)
{
boolean result2;
boolean result1;
boolean vertical;
int txstart,txend;
vertical=((x2-x1)==0);
plane->viewx=vertical;
txstart=plane->texturestart;
txend=plane->textureend;
result1=TransformSimplePoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
result2=TransformSimplePoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
if (result1==true)
{
if (plane->x1>=viewwidth)
return false;
if (result2==false)
{
plane->textureend=txend;
TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
}
}
else
{
if (result2==false)
return false;
else
{
if (plane->x2<0)
return false;
plane->texturestart=txstart;
TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
}
}
if (plane->x1<0)
{
plane->texturestart=txstart;
TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
}
if (plane->x2>=viewwidth)
{
plane->textureend=txend;
TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
}
plane->viewheight=(plane->h1+plane->h2)>>1;
if ((plane->viewheight>=(2000<<HEIGHTFRACTION)) || (plane->x1>=viewwidth-1) || (plane->x2<=0))
return false;
return true;
}
//==========================================================================
/*
====================
=
= CalcHeight
=
= Calculates the height of xintercept,yintercept from viewx,viewy
=
====================
*/
int CalcHeight (void)
{
fixed gxt,gyt,nx;
long gx,gy;
whereami=0;
gx = xintercept-viewx;
gxt = FixedMul(gx,viewcos);
gy = yintercept-viewy;
gyt = FixedMul(gy,viewsin);
nx = gxt-gyt;
if (nx<mindist)
nx=mindist; // don't let divide overflo'
return (heightnumerator/nx);
}
#if 0
//==========================================================================
//******************************************************************************
//
// NextPlaneptr
//
//******************************************************************************
void NextPlaneptr ( void )
{
if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo'
planeptr++;
}
//******************************************************************************
//
// RestPlaneptr
//
//******************************************************************************
void ResetPlaneptr ( void )
{
planeptr = &planelist[0];
}
//******************************************************************************
//
// NextVisptr
//
//******************************************************************************
void NextVisptr ( void )
{
if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
visptr++;
}
//******************************************************************************
//
// ResetVisptr
//
//******************************************************************************
void ResetVisptr ( void )
{
visptr = &vislist[0];
}
#endif
//==========================================================================
/*
=====================
=
= StatRotate
=
=====================
*/
int StatRotate (statobj_t *temp)
{
int angle;
int dx,dy;
whereami=2;
dx = temp->x - player->x;
dy = player->y - temp->y;
angle = atan2_appx(dx,dy);
angle = angle-VANG180-dirangle8[temp->count];
angle+=ANGLES/16;
while (angle>=ANGLES)
angle-=ANGLES;
while (angle<0)
angle+=ANGLES;
return angle/(ANGLES/8);
}
/*
=====================
=
= CalcRotate
=
=====================
*/
int CalcRotate (objtype *ob)
{
int angle,viewangle;
int dx,dy;
int rotation;
whereami=1;
// this isn't exactly correct, as it should vary by a trig value'
// but it is close enough with only eight rotations
/*
if (ob->obclass == b_robobossobj)
viewangle = player->angle;
else
viewangle = player->angle + (centerx - ob->viewx)/8;*/
dx = ob->x - player->x;
dy = player->y - ob->y;
viewangle = atan2_appx(dx,dy);
if ((ob->obclass >= p_bazookaobj) || (ob->obclass == missileobj))
{angle = viewangle - ob->angle;
#if (0)
Debug("\nviewangle: %d, angle: %d",viewangle,angle);
#endif
}
else if ((ob->obclass > wallopobj) && (ob->obclass != b_darksnakeobj))
angle = (viewangle-ANG180)- ob->angle;
else if (ob->state->rotate == 16)
angle = (viewangle-ANG180)- dirangle16[ob->dir];
else
angle = (viewangle-ANG180)- dirangle8[ob->dir];
if (ob->state->rotate == true)
angle += ANGLES/16;
else if (ob->state->rotate == 16)
angle += ANGLES/32;
while (angle>=ANGLES)
angle-=ANGLES;
while (angle<0)
angle+=ANGLES;
if (ob->state->rotate == 2) // 2 rotation pain frame
{rotation = 4*(angle/(ANG180));
return rotation;
}
if (ob->state->rotate == 16)
{rotation = angle/(ANGLES/16);
#if (0)
Debug("\nrotation: %d", rotation);
#endif
return rotation;
}
rotation = angle/(ANGLES/8);
return rotation;
}
#if 0
/*
=====================
=
= DrawMaskedWalls
=
=====================
*/
void DrawMaskedWalls (void)
{
int i,numvisible;
int gx,gy;
unsigned short int *tilespot;
byte *visspot;
boolean result;
statobj_t *statptr;
objtype *obj;
maskedwallobj_t* tmwall;
whereami=6;
//
// place maskwall objects
//
for(tmwall=FIRSTMASKEDWALL;tmwall;tmwall=tmwall->next)
{
if (spotvis[tmwall->tilex][tmwall->tiley])
{
mapseen[tmwall->tilex][tmwall->tiley]=1;
if (tmwall->vertical)
{
gx=(tmwall->tilex<<16)+0x8000;
gy=(tmwall->tiley<<16);
visptr->texturestart=0;
visptr->textureend=0;
if (viewx<gx)
result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
else
result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
visptr->shapenum=tmwall->bottomtexture;
visptr->altshapenum=tmwall->midtexture;
visptr->viewx=tmwall->toptexture;
visptr->shapesize=2;
}
else
{
gx=(tmwall->tilex<<16);
gy=(tmwall->tiley<<16)+0x8000;
visptr->texturestart=0;
visptr->textureend=0;
if (viewy<gy)
result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
else
result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
visptr->shapenum=tmwall->bottomtexture;
visptr->altshapenum=tmwall->midtexture;
visptr->viewx=tmwall->toptexture;
visptr->shapesize=2;
}
if ((tmwall->flags&MW_TOPFLIPPING) &&
(nonbobpheight>64)
)
{
visptr->viewx++;
}
else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
(nonbobpheight>maxheight-32)
)
{
visptr->shapenum++;
}
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
}
}
}
#endif
/*
======================
=
= SortScaleds
= Sort the scaleds using a HEAPSORT
=
======================
*/
#define SGN(x) ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
/*--------------------------------------------------------------------------*/
int CompareHeights(s1p,s2p) visobj_t **s1p,**s2p;
{
whereami=3;
return SGN((*s1p)->viewheight-(*s2p)->viewheight);
}
void SwitchPointers(s1p,s2p) visobj_t **s1p,**s2p;
{
visobj_t * temp;
whereami=4;
temp=*s1p;
*s1p=*s2p;
*s2p=temp;
}
void SortVisibleList( int numvisible, visobj_t * vlist )
{
int i;
whereami=5;
for (i=0;i<numvisible;i++)
sortedvislist[i]=&(vlist[i]);
hsort((char *)&(sortedvislist[0]),numvisible,sizeof(visobj_t *),&CompareHeights,&SwitchPointers);
}
/*
=====================
=
= DrawScaleds
=
= Draws all objects that are visible
=
=====================
*/
#define HF_1 (24)
#define HF_2 (72)
void DrawScaleds (void)
{
int i,numvisible;
int gx,gy;
unsigned short int *tilespot;
byte *visspot;
boolean result;
statobj_t *statptr;
objtype *obj;
maskedwallobj_t* tmwall;
whereami=6;
//
// place maskwall objects
//
for(tmwall=FIRSTMASKEDWALL;tmwall;tmwall=tmwall->next)
{
if (spotvis[tmwall->tilex][tmwall->tiley])
{
mapseen[tmwall->tilex][tmwall->tiley]=1;
if (tmwall->vertical)
{
gx=(tmwall->tilex<<16)+0x8000;
gy=(tmwall->tiley<<16);
visptr->texturestart=0;
visptr->textureend=0;
if (viewx<gx)
result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
else
result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
visptr->shapenum=tmwall->bottomtexture;
visptr->altshapenum=tmwall->midtexture;
visptr->viewx=tmwall->toptexture;
visptr->shapesize=2;
}
else
{
gx=(tmwall->tilex<<16);
gy=(tmwall->tiley<<16)+0x8000;
visptr->texturestart=0;
visptr->textureend=0;
if (viewy<gy)
result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
else
result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
visptr->shapenum=tmwall->bottomtexture;
visptr->altshapenum=tmwall->midtexture;
visptr->viewx=tmwall->toptexture;
visptr->shapesize=2;
}
if ((tmwall->flags&MW_TOPFLIPPING) &&
(nonbobpheight>64)
)
{
visptr->viewx++;
}
else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
(nonbobpheight>maxheight-32)
)
{
visptr->shapenum++;
}
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
}
}
//
// place static objects
//
UpdateClientControls();
for (statptr = firstactivestat ; statptr; statptr=statptr->nextactive)
{ //redraw:
if((visptr->shapenum = statptr->shapenum) == NOTHING)
continue;
visptr->shapenum += shapestart;
if ((visptr->shapenum <= shapestart) ||
(visptr->shapenum >= shapestop))
Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
visspot = statptr->visspot;
if (!((*(visspot-0)) ||
(*(visspot-1)) ||
(*(visspot+1)) ||
(*(visspot-129)) ||
(*(visspot-128)) ||
(*(visspot-127)) ||
(*(visspot+129)) ||
(*(visspot+128)) ||
(*(visspot+127))))
{statptr->flags &= ~FL_VISIBLE;
continue; // not visible
}
result = TransformObject (statptr->x,statptr->y,&(visptr->viewx),&(visptr->viewheight));
if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
continue; // to close to the object
statptr->flags |= FL_SEEN;
statptr->flags |= FL_VISIBLE;
if (statptr->flags & FL_ROTATING)
visptr->shapenum += StatRotate(statptr);
if (statptr->flags&FL_TRANSLUCENT)
{
visptr->shapesize=1;
if (statptr->flags&FL_FADING)
visptr->h2=transparentlevel;
else
visptr->h2=FIXEDTRANSLEVEL;
SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
}
else if (statptr->flags&FL_SOLIDCOLOR)
{
visptr->shapesize=4;
visptr->h2=statptr->hitpoints;
}
else if (statptr->flags&FL_COLORED)
{
visptr->shapesize=0;
#if (DEVELOPMENT == 1)
if ((statptr->hitpoints>=0) &&
(statptr->hitpoints<MAXPLAYERCOLORS))
{
#endif
SetColorLightLevel(statptr->x,statptr->y,visptr,
0,statptr->hitpoints,
(statptr->flags&FL_FULLLIGHT));
#if (DEVELOPMENT == 1)
}
else
{
Error("Illegal color map for sprite type %d\n",statptr->itemnumber);
}
#endif
}
else
{
visptr->shapesize=0;
SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
}
visptr->h1=pheight-statptr->z;
if ((statptr->itemnumber != (unsigned int)-1) &&
(statptr->flags&FL_HEIGHTFLIPPABLE)
)
{
if (statptr->itemnumber==stat_disk)
{
int value;
value=nonbobpheight-statptr->z-32;
if ((value<=HF_2) && (value>HF_1))
{
visptr->shapenum++;
}
else if ((value<=HF_1) && (value>=-HF_1))
{
visptr->shapenum+=2;
}
else if ((value<-HF_1) && (value>=-HF_2))
{
visptr->shapenum+=3;
}
else if (value<-HF_2)
{
visptr->shapenum+=4;
}
}
else if ((nonbobpheight-statptr->z)<-16)
{
visptr->shapenum++;
}
}
if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
visptr++;
}
//
// place active objects
//
UpdateClientControls();
for (obj = firstactive;obj;obj=obj->nextactive)
{
if (obj==player)
continue;
if ((visptr->shapenum = obj->shapenum) == NOTHING)
continue; // no shape
visptr->shapenum += shapestart;
if ((visptr->shapenum <= shapestart) ||
(visptr->shapenum >= shapestop))
Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
visspot = &spotvis[obj->tilex][obj->tiley];
tilespot = &tilemap[obj->tilex][obj->tiley];
//
// could be in any of the nine surrounding tiles
//
if (*visspot
|| ( *(visspot-1))
|| ( *(visspot+1))
|| ( *(visspot-129))
|| ( *(visspot-128))
|| ( *(visspot-127))
|| ( *(visspot+129))
|| ( *(visspot+128))
|| ( *(visspot+127)) )
{
// result = TransformObject (obj->drawx, obj->drawy,&(visptr->viewx),&(visptr->viewheight));
result = TransformObject (obj->x, obj->y,&(visptr->viewx),&(visptr->viewheight));
if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
continue; // to close to the object
if (obj->state->rotate)
visptr->shapenum += CalcRotate (obj);
visptr->shapesize=0;
if (player->flags&FL_SHROOMS)
{
visptr->shapesize=4;
visptr->h2=(GetTicCount()&0xff);
}
if (obj->obclass==playerobj)
{
if (obj->flags&FL_GODMODE)
{
visptr->shapesize=4;
visptr->h2=240+(GetTicCount()&0x7);
}
else if (obj->flags & FL_COLORED)
{
playertype *pstate;
M_LINKSTATE(obj,pstate);
#if (DEVELOPMENT == 1)
if ((pstate->uniformcolor>=0) &&
(pstate->uniformcolor<MAXPLAYERCOLORS))
{
#endif
SetColorLightLevel(obj->x,obj->y,visptr,
obj->dir,pstate->uniformcolor,
(obj->flags&FL_FULLLIGHT) );
#if (DEVELOPMENT == 1)
}
else
{
Error("Illegal color map for players\n");
}
#endif
}
else
SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
}
else
{
if ((obj->obclass >= b_darianobj) && (obj->obclass <= b_robobossobj) &&
MISCVARS->redindex)
{
visptr->colormap=redmap+((MISCVARS->redindex-1)<<8);
}
else
{
SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
}
}
visptr->h1= pheight - obj->z;
if (obj->obclass==diskobj)
{
int value;
value=nonbobpheight-obj->z-32;
if ((value<=HF_2) && (value>HF_1))
{
visptr->shapenum++;
}
else if ((value<=HF_1) && (value>=-HF_1))
{
visptr->shapenum+=2;
}
else if ((value<-HF_1) && (value>=-HF_2))
{
visptr->shapenum+=3;
}
else if (value<-HF_2)
{
visptr->shapenum+=4;
}
}
else if ( (obj->obclass==pillarobj) &&
((nonbobpheight-obj->z)<-16)
)
{
visptr->shapenum++;
}
if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
visptr++;
obj->flags |= FL_SEEN;
obj->flags |= FL_VISIBLE;
}
else
obj->flags &= ~FL_VISIBLE;
}
//
// draw from back to front
//
numvisible = visptr-&vislist[0];
if (!numvisible)
return; // no visible objects
SortVisibleList( numvisible, &vislist[0] );
UpdateClientControls();
for (i = 0; i<numvisible; i++)
{
//
// draw farthest
//
if (sortedvislist[i]->shapesize==4) {
ScaleSolidShape(sortedvislist[i]);
} else if (sortedvislist[i]->shapesize==3) {
InterpolateDoor (sortedvislist[i]);
} else if (sortedvislist[i]->shapesize==2) {
InterpolateMaskedWall (sortedvislist[i]);
} else if (sortedvislist[i]->shapesize==1) {
ScaleTransparentShape(sortedvislist[i]);
} else {
ScaleShape(sortedvislist[i]);
}
}
}
//==========================================================================
/*
==============
=
= DrawPlayerWeapon
=
= Draw the player's hand'
=
==============
*/
void DrawPlayerWeapon (void)
{
int shapenum,index;
int xdisp=0;
int ydisp=0;
int female,black;
int altshape=0;
whereami=7;
SoftError("\n attackframe: %d, weaponframe: %d, weapondowntics: %d"
" weaponuptics: %d",locplayerstate->attackframe,
locplayerstate->weaponframe,locplayerstate->weapondowntics,
locplayerstate->weaponuptics);
if ((locplayerstate->NETCAPTURED == 1) && (!locplayerstate->HASKNIFE))
return;
if (locplayerstate->weapon != -1)
{female = ((locplayerstate->player == 1) || (locplayerstate->player == 3));
black = (locplayerstate->player == 2);
if (((locplayerstate->NETCAPTURED >= 1) || (locplayerstate->NETCAPTURED == -2)) && (locplayerstate->HASKNIFE == 1)) // if raising or lowering
{index = 0;
shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
}
else if (locplayerstate->weapon != wp_twopistol)
{if (locplayerstate->weapon==wp_pistol)
{if (female)
index = NUMWEAPGRAPHICS-2;
else if (black)
index = NUMWEAPGRAPHICS-1;
else
#if (SHAREWARE == 0)
index = 1;
#else
index = 0;
#endif
}
else
#if (SHAREWARE == 0)
index = locplayerstate->weapon + 1;
#else
index = locplayerstate->weapon;
#endif
if ((index<0) || (index>=NUMWEAPGRAPHICS))
Error ("Weapon shapenum out of range\n");
shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
#if (SHAREWARE == 0)
if ((shapenum < W_GetNumForName("KNIFE1")) ||
(shapenum > W_GetNumForName("DOGPAW4"))
)
#else
if ((shapenum < W_GetNumForName("MPIST11")) ||
(shapenum > W_GetNumForName("GODHAND8"))
)
#endif
Error("\n illegal weapon shapenum %d, index %d, weaponframe %d",
shapenum,index,locplayerstate->weaponframe);
}
else
{
#if (SHAREWARE == 0)
if (female)
{altshape = W_FLEFTPISTOL1;
shapenum = W_FRIGHTPISTOL1;
}
else if (black)
{altshape = W_BMLEFTPISTOL1;
shapenum = W_BMRIGHTPISTOL1;
}
else
#endif
{altshape = W_MLEFTPISTOL1;
shapenum = W_MRIGHTPISTOL1;
}
altshape += gunsstart;
shapenum += gunsstart;
if (locplayerstate->weaponframe > 2)
altshape += (locplayerstate->weaponframe - 3);
else
shapenum += locplayerstate->weaponframe;
}
if (!(locplayerstate->NETCAPTURED) ||
(locplayerstate->NETCAPTURED == -1) ||
(locplayerstate->HASKNIFE == 0))
{switch (locplayerstate->weapon)
{
case wp_godhand:
break;
case wp_mp40:
break;
case wp_firewall:
ydisp = 10;
break;
case wp_bazooka:
break;
case wp_heatseeker:
ydisp = 20;
break;
case wp_pistol:
break;
case wp_twopistol:
xdisp = 80;
break;
case wp_drunk:
ydisp = 10;
break;
case wp_firebomb:
break;
#if (SHAREWARE == 0)
case wp_kes:
break;
case wp_bat:
xdisp = 20;
break;
case wp_split:
ydisp = 20;
break;
case wp_dog:
break;
#endif
default:
Error("Illegal weapon value = %d\n",locplayerstate->weapon);
break;
}
}
else
xdisp = 60;
if (altshape)
{
int temp;
int delta;
temp = weaponscale;
delta = FixedMul((weaponbobx<<9),weaponscale);
weaponscale += delta;
ScaleWeapon(xdisp - weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
weaponscale -= delta;
ScaleWeapon(weaponbobx - 80,ydisp + weaponboby + locplayerstate->weaponheight,altshape);
weaponscale = temp;
}
else
{
int temp;
int delta;
temp = weaponscale;
delta = FixedMul((weaponbobx<<9),weaponscale);
weaponscale -= delta;
ScaleWeapon(xdisp + weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
weaponscale = temp;
}
}
}
void AdaptDetail ( void )
{
#if PROFILE
return;
#else
whereami=8;
if ((preindex<0) || (preindex>2))
Error("preindex out of range\n");
pretics[preindex]=(pretics[0]+pretics[1]+pretics[2]+(tics<<16)+0x8000)>>2;
if (pretics[preindex]>GOLOWER)
{
pretics[0]=GOHIGHER;
pretics[1]=GOHIGHER;
pretics[2]=GOHIGHER;
doublestep++;
if (doublestep>2) doublestep=2;
}
else if (pretics[preindex]<GOHIGHER)
{
if (doublestep>0)
doublestep--;
}
preindex++;
if (preindex>2)
preindex=0;
#endif
}
/*
=====================
=
= CalcTics
=
=====================
*/
void CalcTics (void)
{
#if PROFILE
tics=PROFILETICS;
GetTicCount()+=PROFILETICS;
oldtime=GetTicCount();
return;
#else
#if (DEVELOPMENT == 1)
int i;
#endif
volatile int tc;
whereami=9;
// SoftError("InCalcTics\n");
// SoftError("CT GetTicCount()=%ld\n",GetTicCount());
// SoftError("CT oldtime=%ld\n",oldtime);
//
// calculate tics since last refresh for adaptive timing
//
tc=GetTicCount();
while (tc==oldtime) { tc=GetTicCount(); } /* endwhile */
tics=tc-oldtime;
// SoftError("CT GetTicCount()=%ld\n",GetTicCount());
// if (tics>MAXTICS)
// {
// tc-=(tics-MAXTICS);
// GetTicCount() = tc;
// tics = MAXTICS;
// }
if (demoplayback || demorecord)
{
if (tics>MAXTICS)
{
tc=oldtime+MAXTICS;
tics=MAXTICS;
ISR_SetTime(tc);
}
}
oldtime=tc;
#if (DEVELOPMENT == 1)
if (graphicsmode==true)
{
int drawntics;
VGAWRITEMAP(1);
drawntics=tics;
if (drawntics>MAXDRAWNTICS)
drawntics=MAXDRAWNTICS;
for (i=0;i<drawntics;i++)
*((byte *)displayofs+screenofs+(SCREENBWIDE*3)+i)=egacolor[15];
}
/*
if (drawtime>MAXDRAWNTICS)
drawtime=MAXDRAWNTICS;
for (i=0;i<drawtime;i++)
*((byte *)displayofs+screenofs+(SCREENBWIDE*5)+i)=egacolor[2];
if (walltime>MAXDRAWNTICS)
walltime=MAXDRAWNTICS;
for (i=0;i<walltime;i++)
*((byte *)displayofs+screenofs+(SCREENBWIDE*7)+i)=egacolor[14];
if (actortime>MAXDRAWNTICS)
actortime=MAXDRAWNTICS;
for (i=0;i<actortime;i++)
*((byte *)displayofs+screenofs+(SCREENBWIDE*9)+i)=egacolor[4];
}
*/
#endif
#endif
}
/*
==========================
=
= SetSpriteLightLevel
=
==========================
*/
void SetSpriteLightLevel (int x, int y, visobj_t * sprite, int dir, int fullbright)
{
int i;
int lv;
int intercept;
whereami=10;
if (MISCVARS->GASON==1)
{
sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
return;
}
if (fulllight || fullbright)
{
sprite->colormap=colormap+(1<<12);
return;
}
if (fog)
{
i=(sprite->viewheight>>normalshade)+minshade;
if (i>maxshade) i=maxshade;
sprite->colormap=colormap+(i<<8);
}
else
{
if (lightsource)
{
if (dir==east || dir==west)
intercept=(x>>11)&0x1c;
else
intercept=(y>>11)&0x1c;
lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
i=maxshade-(sprite->viewheight>>normalshade)-lv;
if (i<minshade) i=minshade;
sprite->colormap=colormap+(i<<8);
}
else
{
i=maxshade-(sprite->viewheight>>normalshade);
if (i<minshade) i=minshade;
sprite->colormap=colormap+(i<<8);
}
}
}
/*
==========================
=
= SetColorLightLevel
=
==========================
*/
void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright)
{
int i;
int lv;
int intercept;
int height;
byte * map;
whereami=11;
height=sprite->viewheight<<1;
map=playermaps[color];
if (MISCVARS->GASON==1)
{
sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
return;
}
if ((fulllight) || (fullbright))
{
sprite->colormap=map+(1<<12);
return;
}
if (fog)
{
i=(height>>normalshade)+minshade;
if (i>maxshade) i=maxshade;
sprite->colormap=map+(i<<8);
}
else
{
if (lightsource)
{
if (dir==east || dir==west)
intercept=(x>>11)&0x1c;
else
intercept=(y>>11)&0x1c;
lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
i=maxshade-(height>>normalshade)-lv;
if (i<minshade) i=minshade;
sprite->colormap=map+(i<<8);
}
else
{
i=maxshade-(height>>normalshade);
if (i<minshade) i=minshade;
sprite->colormap=map+(i<<8);
}
}
}
/*
==========================
=
= SetWallLightLevel
=
==========================
*/
void SetWallLightLevel (wallcast_t * post)
{
int la;
int lv;
int i;
whereami=12;
if (MISCVARS->GASON==1)
{
shadingtable=greenmap+(MISCVARS->gasindex<<8);
return;
}
switch (post->posttype)
{
case 0:
la=0;
break;
case 1:
la=4;
break;
case 2:
la=(4-gamestate.difficulty);
break;
case 3:
la=3+(4-gamestate.difficulty);
break;
}
if (lightsource)
{
int x,y;
int intercept;
x=post->offset>>7;
y=post->offset&0x7f;
intercept=(post->texture>>11)&0x1c;
lv=(((LightSourceAt(x,y)>>intercept)&0xf)>>1);
}
else
lv=0;
if (fulllight)
{
if (fog)
{
i =16+minshade-lv+la;
if (i>maxshade+la) i=maxshade+la;
shadingtable=colormap+(i<<8);
}
else
{
i =maxshade-16-lv+la;
if (i>=maxshade) i=maxshade;
if (i<minshade+la) i=minshade+la;
shadingtable=colormap+(i<<8);
}
return;
}
if (fog)
{
i =(post->wallheight>>normalshade)+minshade-lv+la;
if (i>maxshade+la) i=maxshade+la;
shadingtable=colormap+(i<<8);
}
else
{
i =maxshade-(post->wallheight>>normalshade)-lv+la;
if (i>=maxshade) i=maxshade;
if (i<minshade+la) i=minshade+la;
shadingtable=colormap+(i<<8);
}
}
/*
====================
=
= DrawWallPost
=
====================
*/
void DrawWallPost ( wallcast_t * post, byte * buf)
{
int ht;
int topscreen;
int bottomscreen;
byte * src;
byte * src2;
whereami=42;
if (post->lump)
src=W_CacheLumpNum(post->lump,PU_CACHE, CvtNull, 1);
if (post->alttile!=0)
{
if (post->alttile==-1)
{
ht=maxheight+32;
dc_invscale = post->wallheight<<(10-HEIGHTFRACTION);
dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
bottomscreen = topscreen + (dc_invscale*ht);
dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
if (dc_yh < 0)
{
post->floorclip=-1;
post->ceilingclip=0;
}
else if (dc_yh >= viewheight)
{
post->floorclip=viewheight-1;
post->ceilingclip=viewheight;
}
else
{
post->floorclip=dc_yh-1;
post->ceilingclip=dc_yh;
}
return;
}
else
{
ht=nominalheight;
src2=W_CacheLumpNum(post->alttile,PU_CACHE, CvtNull, 1);
}
}
else
{
ht=maxheight+32;
src2=src;
}
dc_invscale = post->wallheight<<(10-HEIGHTFRACTION);
dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
bottomscreen = topscreen + (dc_invscale*ht);
dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
if (dc_yl >= viewheight)
{
post->ceilingclip=viewheight;
post->floorclip=viewheight-1;
return;
}
else if (dc_yl < 0)
dc_yl = 0;
dc_iscale = (64<<(16+HEIGHTFRACTION))/post->wallheight;
if (dc_yh < 0)
{
post->floorclip=-1;
post->ceilingclip=0;
goto bottomcheck;
}
else if (dc_yh > viewheight)
dc_yh = viewheight;
post->ceilingclip=dc_yl;
post->floorclip=dc_yh-1;
dc_source=src2+((post->texture>>4)&0xfc0);
R_DrawWallColumn (buf);
bottomcheck:
if (ht!=nominalheight)
return;
dc_texturemid-=(nominalheight<<SFRACBITS);
topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
bottomscreen = topscreen + (dc_invscale<<6);
dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
dc_yh = ((bottomscreen-1)>>SFRACBITS);
if (dc_yl >= viewheight)
return;
else if (dc_yl < 0)
dc_yl = 0;
if (dc_yh < 0)
return;
else if (dc_yh > viewheight)
dc_yh = viewheight;
post->floorclip=dc_yh-1;
dc_source=src+((post->texture>>4)&0xfc0);
R_DrawWallColumn (buf);
}
/*
====================
=
= DrawWalls
=
====================
*/
void DrawWalls (void)
{
char * buf;
int plane;
wallcast_t * post;
whereami=13;
plane = 0;
if (doublestep>1)
{
#ifdef DOS
for (plane=0;plane<4;plane+=2)
#endif
{
VGAMAPMASK((1<<plane)+(1<<(plane+1)));
buf=(byte *)(bufferofs);
#ifdef DOS
for (post=&posts[plane];post<&posts[viewwidth];post+=4,buf++)
#else
for (post=&posts[plane];post<&posts[viewwidth];post+=2,buf+=2)
#endif
{
SetWallLightLevel(post);
DrawWallPost(post,buf);
#ifndef DOS
DrawWallPost(post,buf+1);
#endif
(post+1)->ceilingclip=post->ceilingclip;
(post+1)->floorclip=post->floorclip;
}
}
}
else
{
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAWRITEMAP(plane);
buf=(byte *)(bufferofs);
#ifdef DOS
for (post=&posts[plane];post<&posts[viewwidth];post+=4,buf++)
#else
for (post=&posts[plane];post<&posts[viewwidth];post++,buf++)
#endif
{
SetWallLightLevel(post);
DrawWallPost(post,buf);
}
}
}
}
/*
====================
=
= TransformDoors
=
====================
*/
void TransformDoors( void )
{
int i;
int numvisible;
boolean result;
int gx,gy;
visobj_t visdoorlist[MAXVISIBLEDOORS],*doorptr;
whereami=14;
doorptr=&visdoorlist[0];
//
// place door objects
//
for (i = 0;i<doornum;i++)
{
if (spotvis[doorobjlist[i]->tilex][doorobjlist[i]->tiley])
{
mapseen[doorobjlist[i]->tilex][doorobjlist[i]->tiley]=1;
doorptr->texturestart=0;
doorptr->textureend=0;
if (doorobjlist[i]->vertical)
{
gx=(doorobjlist[i]->tilex<<16)+0x8000;
gy=(doorobjlist[i]->tiley<<16);
if (viewx<gx)
result=TransformPlane(gx,gy,gx,gy+0xffff,doorptr);
else
result=TransformPlane(gx,gy+0xffff,gx,gy,doorptr);
}
else
{
gx=(doorobjlist[i]->tilex<<16);
gy=(doorobjlist[i]->tiley<<16)+0x8000;
if (viewy<gy)
result=TransformPlane(gx+0xffff,gy,gx,gy,doorptr);
else
result=TransformPlane(gx,gy,gx+0xffff,gy,doorptr);
}
if (result==true)
{
doorptr->viewx=0;
doorptr->shapenum=doorobjlist[i]->texture;
doorptr->altshapenum=doorobjlist[i]->alttexture;
if (doorobjlist[i]->texture==doorobjlist[i]->basetexture)
{
doorptr->shapesize=(doorobjlist[i]->tilex<<7)+doorobjlist[i]->tiley;
if (doorptr < &visdoorlist[MAXVISIBLEDOORS-1]) // don't let it overflo'
doorptr++;
}
else
{
doorptr->shapesize=3;
memcpy(visptr,doorptr,sizeof(visobj_t));
if (visptr < &vislist[MAXVISIBLE-1])
visptr++;
}
}
}
}
//
// draw from back to front
//
numvisible = doorptr-&visdoorlist[0];
if (!numvisible)
return;
SortVisibleList( numvisible, &visdoorlist[0] );
for (i = 0; i<numvisible; i++)
{
//
// draw farthest
//
InterpolateWall (sortedvislist[i]);
}
}
/*
====================
=
= TransformPushWalls
=
====================
*/
void TransformPushWalls( void )
{
int i;
int gx,gy;
byte *visspot;
visobj_t *savedptr;
int numvisible;
boolean result;
whereami=15;
savedptr=visptr;
//
// place pwall objects
//
for (i = 0;i<pwallnum;i++)
{
if ((pwallobjlist[i]->action==pw_pushed) || (pwallobjlist[i]->action==pw_npushed))
continue;
visspot = &spotvis[pwallobjlist[i]->x>>16][pwallobjlist[i]->y>>16];
if (*visspot
|| ( *(visspot-1))
|| ( *(visspot+1))
|| ( *(visspot-128))
|| ( *(visspot+128)))
{
gx=pwallobjlist[i]->x;
gy=pwallobjlist[i]->y;
mapseen[gx>>16][gy>>16]=1;
if (viewx<gx)
{
if (viewy<gy)
{
visptr->texturestart=(gx-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;
result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
visptr->texturestart^=0xffff;
visptr->textureend^=0xffff;
visptr->shapenum=pwallobjlist[i]->texture;
visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
visptr->viewx+=2;
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
visptr->texturestart=(gy-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;//-0xffff;
result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
}
else
{
visptr->texturestart=(gy-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;//-0xffff;
result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
visptr->shapenum=pwallobjlist[i]->texture;
visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
visptr->viewx+=2;
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
visptr->texturestart=(gx-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;//-0xffff;
result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
}
}
else
{
if (viewy<gy)
{
visptr->texturestart=(gy-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;
result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
visptr->texturestart^=0xffff;
visptr->textureend^=0xffff;
visptr->shapenum=pwallobjlist[i]->texture;
visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
visptr->viewx+=2;
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
visptr->texturestart=(gx-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;
result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
visptr->texturestart^=0xffff;
visptr->textureend^=0xffff;
}
else
{
visptr->texturestart=(gx-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;//-0xffff;
result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
visptr->shapenum=pwallobjlist[i]->texture;
visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
visptr->viewx+=2;
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
visptr->texturestart=(gy-0x8000)&0xffff;
visptr->textureend=visptr->texturestart;
result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
visptr->texturestart^=0xffff;
visptr->textureend^=0xffff;
}
}
visptr->viewx+=2;
visptr->shapenum=pwallobjlist[i]->texture;
visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
visptr++;
}
}
//
// draw from back to front
//
numvisible = visptr-savedptr;
if (!numvisible)
return;
SortVisibleList( numvisible, savedptr );
for (i = 0; i<numvisible; i++)
{
//
// draw farthest
//
if (sortedvislist[i]->shapenum & 0x1000)
sortedvislist[i]->shapenum=animwalls[sortedvislist[i]->shapenum&0x3ff].texture;
sortedvislist[i]->altshapenum=0;
InterpolateWall (sortedvislist[i]);
}
visptr=savedptr;
}
/*
====================
=
= WallRefresh
=
====================
*/
void WallRefresh (void)
{
volatile int dtime;
int mag;
int yzangle;
whereami=16;
firstcoloffset=(firstcoloffset+(tics<<8))&65535;
dtime=GetFastTics();
if (missobj)
{
viewangle=missobj->angle;
viewx=missobj->x-costable[viewangle];
viewy=missobj->y+sintable[viewangle];
pheight = missobj->z + 32;
nonbobpheight=pheight;
spotvis[missobj->tilex][missobj->tiley]=1;
yzangle=missobj->yzangle;
}
else
{
if (player->flags&FL_SHROOMS)
{
viewangle = (player->angle + FixedMulShift(FINEANGLES,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],(16+4)))&(FINEANGLES-1);
ChangeFocalWidth(FixedMulShift(40,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],16));
}
else
viewangle = player->angle;
if ((viewangle<0) && (viewangle>=FINEANGLES))
Error ("View angle out of range = %d\n",viewangle);
viewx = player->x;
viewy = player->y;
pheight = player->z + locplayerstate->playerheight + locplayerstate->heightoffset;
nonbobpheight=pheight;
if (
(
(player->z == nominalheight) ||
(IsPlatform(player->tilex,player->tiley)) ||
(DiskAt(player->tilex,player->tiley))
) &&
(!(player->flags & FL_DOGMODE)) &&
(BobbinOn==true) &&
(GamePaused==false)
)
{
int mag;
mag=(player->speed>MAXBOB ? MAXBOB : player->speed);
pheight+=FixedMulShift(mag,sintable[(GetTicCount()<<7)&2047],28);
weaponbobx=FixedMulShift(mag,costable[((GetTicCount()<<5))&(FINEANGLES-1)],27);
weaponboby=FixedMulShift(mag,sintable[((GetTicCount()<<5))&((FINEANGLES/2)-1)],26);
}
else
{
weaponbobx=0;
weaponboby=0;
}
yzangle=player->yzangle;
spotvis[player->tilex][player->tiley]=1;
}
if (yzangle > ANG180)
pheight -= (sintable[yzangle&2047] >> 14);
else
pheight += (sintable[yzangle&2047] >> 14);
viewx -= (FixedMul(sintable[yzangle&2047],costable[viewangle&2047])>>1);
viewy += (FixedMul(sintable[yzangle&2047],sintable[viewangle&2047])>>1);
// Set YZ angle
centery=viewheight>>1;
if (yzangle>ANG180)
centery-=FixedMul(FINEANGLES-yzangle,yzangleconverter);
else
centery+=FixedMul(yzangle,yzangleconverter);
centeryfrac=(centery<<16);
if (pheight < 1)
pheight = 1;
else if (pheight > maxheight+30)
pheight = maxheight+30;
if (nonbobpheight < 1)
nonbobpheight = 1;
else if (nonbobpheight > maxheight+30)
nonbobpheight = maxheight+30;
// Set light level of touchplates etc.
mag=7+((3-gamestate.difficulty)<<2);
transparentlevel=FixedMul(mag,sintable[(GetTicCount()<<5)&(FINEANGLES-1)])+mag;
viewsin = sintable[viewangle];
viewcos = costable[viewangle];
c_startx=(scale*viewcos)-(centerx*viewsin);
c_starty=(-scale*viewsin)-(centerx*viewcos);
Refresh ();
UpdateClientControls();
TransformPushWalls();
TransformDoors();
UpdateClientControls();
DrawWalls();
UpdateClientControls();
walltime=GetFastTics()-dtime;
}
/*
====================
=
= GetRainBoundingBox
=
====================
*/
void GetRainBoundingBox (int * xmin, int * xmax, int * ymin, int * ymax)
{
wallcast_t * post;
int x,y;
// zero out all boundaries by default
*xmax=0;
*ymax=0;
*xmin=127<<16;
*ymin=127<<16;
// check player's x and y
if (viewx<(*xmin))
(*xmin)=viewx;
else if (viewx>(*xmax))
(*xmax)=viewx;
if (viewy<(*ymin))
(*ymin)=viewy;
else if (viewy>(*ymax))
(*ymax)=viewy;
for (post=&posts[0];post<&posts[viewwidth];post+=(viewwidth>>2))
{
x=(post->offset>>7)<<16;
y=(post->offset&0x7f)<<16;
if (x<(*xmin))
(*xmin)=x;
else if (x>(*xmax))
(*xmax)=x;
if (y<(*ymin))
(*ymin)=y;
else if (y>(*ymax))
(*ymax)=y;
}
}
/*
========================
=
= InterpolateWall
=
========================
*/
void InterpolateWall (visobj_t * plane)
{
int d1,d2;
int top;
int topinc;
int bot;
int botinc;
int i;
int texture;
int dh;
int dx;
int height;
byte * buf;
whereami=17;
dx=(plane->x2-plane->x1+1);
if (plane->h1<=0 || plane->h2<=0 || dx==0)
return;
d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
top=0;
topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
bot=d2*dx;
botinc=d1-d2;
height=plane->h1<<DHEIGHTFRACTION;
buf=(byte *)bufferofs;
if (plane->x1>=viewwidth)
return;
for (i=plane->x1;i<=plane->x2;i++)
{
if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<=(height>>DHEIGHTFRACTION)))
{
if (bot)
{
texture=((top/bot)+(plane->texturestart>>4))&0xfc0;
posts[i].texture=texture<<4;
posts[i].lump=plane->shapenum;
posts[i].alttile=plane->altshapenum;
posts[i].posttype=plane->viewx;
posts[i].offset=plane->shapesize;
posts[i].wallheight=height>>DHEIGHTFRACTION;
}
}
top+=topinc;
bot+=botinc;
height+=dh;
}
}
/*
========================
=
= InterpolateDoor
=
========================
*/
void InterpolateDoor (visobj_t * plane)
{
int d1,d2;
int top;
int topinc;
int bot;
int botinc;
int i;
int texture;
int dh;
int dx;
int height;
int bottomscreen;
byte * shape;
byte * shape2;
byte * buf;
patch_t *p;
int pl;
whereami=18;
dx=(plane->x2-plane->x1+1);
if (plane->h1<=0 || plane->h2<=0 || dx==0)
return;
shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_patch_t, 1);
shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
p=(patch_t *)shape;
d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
botinc=d1-d2;
if (plane->x1>=viewwidth)
return;
#ifdef DOS
for (pl=0;pl<4;pl++)
#endif
{
#ifdef DOS
top=topinc*pl;
bot=(d2*dx)+(pl*botinc);
height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
buf=(byte *)bufferofs+((pl+plane->x1)>>2);
VGAWRITEMAP((plane->x1+pl)&3);
for (i=plane->x1+pl;i<=plane->x2;i+=4,buf++)
#else
top=0;
bot=(d2*dx);
height=(plane->h1<<DHEIGHTFRACTION);
buf=(byte *)bufferofs+(plane->x1);
for (i=plane->x1;i<=plane->x2;i++,buf++)
#endif
{
if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
{
dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
dc_texturemid=((pheight-nominalheight+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
texture=((top/bot)+(plane->texturestart>>4))>>6;
SetLightLevel(height>>DHEIGHTFRACTION);
ScaleMaskedPost (p->collumnofs[texture]+shape,buf);
if (levelheight>1)
{
sprtopoffset-=(dc_invscale<<6)*(levelheight-1);
bottomscreen =sprtopoffset + (dc_invscale*nominalheight);
dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
if (dc_yl >= viewheight)
continue;
else if (dc_yl < 0)
dc_yl = 0;
if (dc_yh > viewheight)
dc_yh = viewheight;
dc_source=shape2+((texture<<6)&0xfc0);
R_DrawWallColumn (buf);
}
}
#ifdef DOS
top+=topinc<<2;
bot+=botinc<<2;
height+=dh<<2;
#else
top+=topinc;
bot+=botinc;
height+=dh;
#endif
}
}
}
/*
========================
=
= InterpolateMaskedWall
=
========================
*/
void InterpolateMaskedWall (visobj_t * plane)
{
int d1,d2;
int top;
int topinc;
int bot;
int botinc;
int i;
int j;
int texture;
int dh;
int dx;
int height;
byte * shape;
byte * shape2;
byte * shape3;
byte * buf;
transpatch_t *p;
patch_t *p2;
patch_t *p3;
int pl;
boolean drawbottom,drawmiddle,drawtop;
int topoffset;
whereami=19;
dx=(plane->x2-plane->x1+1);
if (plane->h1<=0 || plane->h2<=0 || dx==0)
return;
if (plane->altshapenum>=0)
{
drawmiddle=true;
shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
p2=(patch_t *)shape2;
topoffset=p2->topoffset;
}
else
{
drawmiddle=false;
}
if (plane->viewx>=0)
{
drawtop=true;
shape3=W_CacheLumpNum(plane->viewx,PU_CACHE, Cvt_patch_t, 1);
p3=(patch_t *)shape3;
topoffset=p3->topoffset;
}
else
{
drawtop=false;
}
if (plane->shapenum>=0)
{
drawbottom=true;
shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_transpatch_t, 1);
p = (transpatch_t *)shape;
topoffset=p->topoffset;
}
else
{
drawbottom=false;
}
d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
botinc=d1-d2;
if (plane->x1>=viewwidth)
return;
#ifdef DOS
for (pl=0;pl<4;pl++)
#endif
{
#ifdef DOS
int planenum;
top=topinc*pl;
bot=(d2*dx)+(pl*botinc);
height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
buf=(byte *)bufferofs+((pl+plane->x1)>>2);
planenum=((plane->x1+pl)&3);
VGAWRITEMAP(planenum);
VGAREADMAP(planenum);
for (i=plane->x1+pl;i<=plane->x2;i+=4,buf++)
#else
top=0;
bot=(d2*dx);
height=(plane->h1<<DHEIGHTFRACTION);
buf=(byte *)bufferofs+(plane->x1);
for (i=plane->x1;i<=plane->x2;i++,buf++)
#endif
{
if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
{
dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
dc_texturemid=((pheight-nominalheight+topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
texture=((top/bot)+(plane->texturestart>>4))>>6;
SetLightLevel(height>>DHEIGHTFRACTION);
if (drawbottom==true)
ScaleTransparentPost (p->collumnofs[texture]+shape,buf,(p->translevel+8));
for (j=0;j<levelheight-2;j++)
{
sprtopoffset-=(dc_invscale<<6);
dc_texturemid+=(1<<22);
if (drawmiddle==true)
ScaleMaskedPost (p2->collumnofs[texture]+shape2,buf);
}
if (levelheight>1)
{
sprtopoffset-=(dc_invscale<<6);
dc_texturemid+=(1<<22);
if (drawtop==true)
ScaleMaskedPost (p3->collumnofs[texture]+shape3,buf);
}
}
#ifdef DOS
top+=topinc<<2;
bot+=botinc<<2;
height+=dh<<2;
#else
top+=topinc;
bot+=botinc;
height+=dh;
#endif
}
}
}
/*
========================
=
= DrawPlayerLocation
=
========================
*/
#define PLX (320-24)
#define PLY 16
void DrawPlayerLocation ( void )
{
int i;
char buf[30];
CurrentFont=tinyfont;
whereami=20;
VGAMAPMASK(15);
for (i=0;i<18;i++)
#ifdef DOS
memset((byte *)bufferofs+(ylookup[i+PLY])+(PLX>>2),0,6);
#else
memset((byte *)bufferofs+(ylookup[i+PLY])+PLX,0,6);
#endif
px=PLX;
py=PLY;
VW_DrawPropString(strupr(itoa(player->x,&buf[0],16)));
px=PLX;
py=PLY+6;
VW_DrawPropString(strupr(itoa(player->y,&buf[0],16)));
px=PLX;
py=PLY+12;
VW_DrawPropString(strupr(itoa(player->angle,&buf[0],16)));
}
/*
========================
=
= ThreeDRefresh
=
========================
*/
int playerview=0;
void ThreeDRefresh (void)
{
objtype * tempptr;
whereami=21;
tempptr=player;
#if (DEVELOPMENT == 1)
if (Keyboard[sc_9])
{
while (Keyboard[sc_9])
{
IN_UpdateKeyboard();
}
playerview++;
if (playerview>numplayers)
playerview=1;
}
if (playerview!=0)
{
player=PLAYER[playerview-1];
}
#endif
//
// Erase old messages
//
RestoreMessageBackground();
bufferofs += screenofs;
RefreshClear();
UpdateClientControls ();
//
// follow the walls from there to the right, drawwing as we go
//
visptr = &vislist[0];
WallRefresh ();
UpdateClientControls ();
if (fandc)
DrawPlanes();
UpdateClientControls ();
//
// draw all the scaled images
//
DrawScaleds(); // draw scaled stuff
UpdateClientControls ();
if (!missobj)
{
if (locplayerstate->NETCAPTURED && (locplayerstate->NETCAPTURED != -2))
{
int value;
if (locplayerstate->NETCAPTURED < 0)
value = -locplayerstate->NETCAPTURED;
else
value = locplayerstate->NETCAPTURED;
DrawScreenSizedSprite(netlump+value-1);
}
DrawPlayerWeapon (); // draw player's hand'
if (SCREENEYE)
DrawScreenSprite(SCREENEYE->targettilex,SCREENEYE->targettiley,SCREENEYE->state->condition + GIBEYE1 + shapestart);
UpdateClientControls ();
if (player->flags&FL_GASMASK)
DrawScreenSizedSprite(gmasklump);
if ( SHOW_PLAYER_STATS() )
{
DrawStats ();
}
DoBorderShifts ();
UpdateClientControls ();
}
bufferofs -= screenofs;
DrawMessages();
bufferofs += screenofs;
if ( ((GamePaused==true) && (!Keyboard[sc_LShift])) ||
(controlupdatestarted==0)
)
DrawPause ();
//
// show screen and time last cycle
//
if ((fizzlein==true) && (modemgame==false))
{
if (newlevel==true)
ShutdownClientControls();
bufferofs-=screenofs;
DrawPlayScreen (true);
RotateBuffer(0,FINEANGLES,FINEANGLES*8,FINEANGLES,(VBLCOUNTER*3)/4);
bufferofs+=screenofs;
fizzlein = false;
StartupClientControls();
}
bufferofs -= screenofs;
UpdateClientControls ();
if (HUD == true)
DrawPlayerLocation();
FlipPage();
gamestate.frame++;
player=tempptr;
}
//******************************************************************************
//
// FlipPage
//
//******************************************************************************
void FlipPage ( void )
{
#ifdef DOS
unsigned displaytemp;
whereami=22;
displayofs = bufferofs;
displaytemp = displayofs;
if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
( !fizzlein ) )
{
ScreenShake ();
}
// _disable();
OUTP(CRTC_INDEX,CRTC_STARTHIGH);
OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
if (SHAKETICS != 0xFFFF)
{
if (SHAKETICS > 0)
{
OUTP (CRTC_INDEX, CRTC_STARTLOW);
OUTP (CRTC_DATA, (displayofs&0x000000FF));
displayofs = displaytemp;
}
else
{
displayofs = displaytemp;
OUTP(CRTC_INDEX,CRTC_STARTHIGH);
OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
OUTP (CRTC_INDEX, CRTC_STARTLOW);
OUTP (CRTC_DATA, (displayofs&0x000000FF));
SHAKETICS = 0xFFFF;
}
}
// _enable();
bufferofs += screensize;
if (bufferofs > page3start)
bufferofs = page1start;
#else
whereami=22;
if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
( !fizzlein ) )
{
ScreenShake ();
}
/* TODO some shake thing */
/* just call the one in modexlib.c */
XFlipPage();
#endif
}
//******************************************************************************
//
// TurnShakeOff
//
//******************************************************************************
void TurnShakeOff
(
void
)
{
// _disable();
OUTP (CRTC_INDEX, CRTC_STARTHIGH );
OUTP (CRTC_DATA, ( ( displayofs & 0x0000ffff ) >> 8 ) );
OUTP (CRTC_INDEX, CRTC_STARTLOW);
OUTP (CRTC_DATA, (displayofs&0x000000FF));
// _enable();
SHAKETICS = 0xFFFF;
}
//******************************************************************************
//
// DrawScaledScreen
// draw sreen after reentering fro restore game
//******************************************************************************
void DrawScaledScreen(int x, int y, int step, byte * src)
{
int xfrac;
int yfrac;
// int plane;
int i,j;
byte * p;
byte * buf;
int xsize;
int ysize;
xsize=(iGLOBAL_SCREENWIDTH<<16)/step;
if (xsize>iGLOBAL_SCREENWIDTH) xsize=iGLOBAL_SCREENWIDTH;
ysize=(iGLOBAL_SCREENHEIGHT<<16)/step;
if (ysize>iGLOBAL_SCREENHEIGHT) ysize=iGLOBAL_SCREENHEIGHT;
#ifdef DOS
for (plane=x;plane<x+4;plane++)
#endif
{
yfrac=0;
#ifdef DOS
VGAWRITEMAP(plane&3);
#endif
for (j=y;j<y+ysize;j++)
{
p=src+(iGLOBAL_SCREENWIDTH*(yfrac>>16));
#ifdef DOS
buf=(byte *)bufferofs+ylookup[j]+(plane>>2);
#else
buf=(byte *)bufferofs+ylookup[j]+x;
#endif
#ifdef DOS
xfrac=(plane-x)*step;
#else
xfrac=0;
#endif
yfrac+=step;
#ifdef DOS
for (i=plane;i<x+xsize;i+=4)
#else
for (i=x;i<x+xsize;i++)
#endif
{
*buf=*(p+(xfrac>>16));
buf++;
#ifdef DOS
xfrac+=(step<<2);
#else
xfrac+=step;
#endif
}
}
}
}
//******************************************************************************
//
// DoLoadGameSequence
//
//******************************************************************************
void DoLoadGameSequence ( void )
{
int x;
int y;
int dx;
int dy;
int s;
int ds;
int time;
int i;
byte * destscreen;
pic_t *shape;//bna++
fizzlein=false;
x=(18+SaveGamePicX)<<16;
y=(30+SaveGamePicY)<<16;
time=VBLCOUNTER;
s=0x2000000;
dx=(-x)/time;
dy=(-y)/time;
ds=-((s-0x1000000)/time);
destscreen=SafeMalloc(64000*8);//bna fixme
SetupScreen(false);
ThreeDRefresh();
FlipPage();
FlipPage();
VL_CopyPlanarPageToMemory ( (byte *)bufferofs, destscreen );
VL_CopyDisplayToHidden ();
CalcTics();
for (i=0;i<time;i+=tics)
{
CalcTics();
DrawScaledScreen((x>>16),(y>>16),(s>>8),destscreen);
FlipPage();
x+=(dx*tics);
if (x<0) x=0;
y+=(dy*tics);
if (y<0) y=0;
s+=(ds*tics);
}
DrawScaledScreen(0,0,0x10000,destscreen);
FlipPage();
VL_CopyDisplayToHidden ();
SafeFree(destscreen);
CalcTics();
CalcTics();
//bna++ section
shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
DrawPlayScreen(false);
DisableScreenStretch();
SHAKETICS = 0xFFFF;
//bna section end
}
//******************************************************************************
//
// StartupRotateBuffer
//
//******************************************************************************
byte * RotatedImage;
boolean RotateBufferStarted = false;
void StartupRotateBuffer ( int masked)
{
int k;////zxcv
int a,b;
// int Xres = 320;//org
// int Yres = 200;//org
int Xres = iGLOBAL_SCREENWIDTH;//bna val 800
int Yres = iGLOBAL_SCREENHEIGHT;//bna val 600
iG_masked = masked;
if (RotateBufferStarted == true)
return;
RotateBufferStarted = true;
// RotatedImage=SafeMalloc(131072);org
//RotatedImage=SafeMalloc(131072*8);
if (iGLOBAL_SCREENWIDTH == 320) {
RotatedImage=SafeMalloc(131072);
}else if (iGLOBAL_SCREENWIDTH == 640) {
RotatedImage=SafeMalloc(131072*4);
}else if (iGLOBAL_SCREENWIDTH == 800) {
RotatedImage=SafeMalloc(131072*8);
}
//SetupScreen(false);//used these 2 to test screen size
//VW_UpdateScreen ();
if (masked==0) {
if (iGLOBAL_SCREENWIDTH == 320) {
memset(RotatedImage,0,131072);
}else if (iGLOBAL_SCREENWIDTH == 640) {
memset(RotatedImage,0,131072*4);
}else if (iGLOBAL_SCREENWIDTH == 800) {
//memset(RotatedImage,0,131072);//org
memset(RotatedImage,0,131072*8);
}
} else {
if (iGLOBAL_SCREENWIDTH == 320) {
memset(RotatedImage,0xff,131072);
}else if (iGLOBAL_SCREENWIDTH == 640) {
memset(RotatedImage,0xff,131072*4);
}else if (iGLOBAL_SCREENWIDTH == 800) {
memset(RotatedImage,0xff,131072*8);
}
}
//memset(RotatedImage,0xff,131072);//org
//memset(RotatedImage,0xff,131072*8);
if ((masked == false)&&(iGLOBAL_SCREENWIDTH == 800)) {
DisableScreenStretch();
// SetTextMode ( );
k=(28*512);//14336;
//k=((0+28)<<10);//28672
for (a=0;a<iGLOBAL_SCREENHEIGHT;a++){
for (b=0;b<iGLOBAL_SCREENWIDTH;b++){
//*(RotatedImage+99+((a+28)<<9)+b) = *((byte *)bufferofs+(a*linewidth)+b);
// 99 is some offset value
k = ((a+28)<<10);
*(RotatedImage+(k)+b) = *((byte *)bufferofs+(a*linewidth)+b);
//*(RotatedImage+b) = *((byte *)bufferofs+(a*linewidth)+b);
}
//k+=512*2;
}
}else if ((masked == false)&&(iGLOBAL_SCREENWIDTH == 640)) {
DisableScreenStretch();
k=(28*512);//14336;
for (a=0;a<iGLOBAL_SCREENHEIGHT;a++){
for (b=0;b<iGLOBAL_SCREENWIDTH;b++){
k = ((a+28)<<10);
*(RotatedImage+(k)+b) = *((byte *)bufferofs+(a*linewidth)+b);
}
}
}else if ((masked == true)||(iGLOBAL_SCREENWIDTH == 320)) {
for (a=0;a<200;a++){
for (b=0;b<320;b++)
*(RotatedImage+99+((a+28)<<9)+b)=*((byte *)bufferofs+(a*linewidth)+b);
}
}
}
/* copier liner af 1024 bredde
a=0=14436 a=1=14848 a=2=15360 a=3=15872 -> 512 i difference
*(RotatedImage+(512)+0) = bufferofs+(0*800)+0);
*(RotatedImage+(512)+100) = bufferofs+(100*800)+0);
*/
//******************************************************************************
//
// ShutdownRotateBuffer
//
//******************************************************************************
void ShutdownRotateBuffer ( void )
{
if (RotateBufferStarted == false)
return;
RotateBufferStarted = false;
SafeFree(RotatedImage);
}
//******************************************************************************
//
// ScaleAndRotateBuffer
//
//******************************************************************************
void ScaleAndRotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
{
int anglestep;
int scalestep;
int angle;
int scale;
int i;
//bna section
// int Xh = 160;//org
// int Yh = 100;//org
int Xh = iGLOBAL_SCREENWIDTH/2;
int Yh = iGLOBAL_SCREENHEIGHT/2;
// Xh = 259;
// Yh = 109;
time = time;
////zxcv
DisableScreenStretch();//bna++
anglestep=((endangle-startangle)<<16)/time;
scalestep=((endscale-startscale)<<6)/time;
angle=(startangle<<16);
scale=(startscale<<6);
CalcTics();
CalcTics();
for (i=0;i<time;i+=tics)
{//zxcv
DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>6,0);
FlipPage();
scale+=(scalestep*tics);
angle+=(anglestep*tics);
CalcTics();
}
DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
FlipPage();
DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
FlipPage();
DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
CalcTics();
CalcTics();
//I_Delay (240);//bna++
//bna++ section
if ( playstate == ex_stillplaying ) {//bna++
pic_t *shape;
shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
DisableScreenStretch();//dont strech when we go BACK TO GAME
DrawPlayScreen(true);//repaint ammo and life stat
}
}
//bna section end
//******************************************************************************
//
// RotateBuffer
//
//******************************************************************************
void RotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
{
int savetics;
//save off fastcounter
savetics=GetFastTics();
StartupRotateBuffer (0);
ScaleAndRotateBuffer (startangle, endangle, startscale, endscale, time);
ShutdownRotateBuffer ();
// restore fast counter
SetFastTics(savetics);
}
//******************************************************************************
//
// DrawRotatedScreen
//
//******************************************************************************
void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked)
{//ZXCV
int c, s;
int xst, xct;
int y;
byte * screen;
//int Xres = 320;//old value
//int Yres = 200;//old val
int Xr = iGLOBAL_SCREENWIDTH;//640;
int Yr = (iGLOBAL_SCREENHEIGHT);//400; //bna aaaa fix
// SetTextMode ( );
c = FixedMulShift(scale,costable[angle],11);
s = FixedMulShift(scale,sintable[angle],11);
// c = c/2; //these values are to rotate degres or?
// s = s/2;
// xst & xct= start center values ;
if ((iGLOBAL_SCREENWIDTH == 320 )||(masked == true)) {
xst = (((-cx)*s)+(128<<16))-(cy*c);
xct = (((-cx)*c)+(256<<16)+(1<<18)-(1<<16))+(cy*s);
}
else if ((iGLOBAL_SCREENWIDTH == 640 )&&(masked == false)) {
xst = (((-cx)*s)+((268)<<16))-(cy*c);
xct = (((-cx)*c)+((317)<<16)+(1<<18)-(1<<16))+(cy*s);
}//y=268;x=317
else if ((iGLOBAL_SCREENWIDTH == 800 )&&(masked == false)) {
xst = (((-cx)*s)+((328)<<16))-(cy*c);
xct = (((-cx)*c)+((397)<<16)+(1<<18)-(1<<16))+(cy*s);
}//328 397
mr_xstep=s;
mr_ystep=c;
if ((iGLOBAL_SCREENWIDTH == 800)&&(masked==0)) {
screen=destscreen+iGLOBAL_SCREENWIDTH;//bna aaaa fix
}else{
screen=destscreen;
}
if (masked==0)
{
// paint hole 800x600 screen
{
mr_yfrac=xct;
mr_xfrac=xst;
VGAWRITEMAP(plane);
for (y=0; y<Yr; y++,mr_xfrac+=c,mr_yfrac-=s)
DrawRotRow(Xr,screen+ylookup[y],RotatedImage);
}
}
else
{
{
mr_yfrac=xct;
mr_xfrac=xst;
VGAWRITEMAP(plane);
for (y=0; y<Yr; y++,mr_xfrac+=c,mr_yfrac-=s)
DrawMaskedRotRow(Xr,screen+ylookup[y],RotatedImage);
}
}
}
//******************************************************************************
//
// DrawScaledPost
//
//******************************************************************************
void DrawScaledPost ( int height, byte * src, int offset, int x)
{
patch_t *p;
p=(patch_t *)src;
dc_invscale=(height<<16)/p->origsize;
dc_iscale=(p->origsize<<16)/height;
dc_texturemid=(((p->origsize>>1)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
shadingtable=colormap+(1<<12);
VGAWRITEMAP(x&3);
#ifdef DOS
ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+(x>>2));
#else
ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+x);
#endif
}
void ApogeeTitle (void)
{
byte pal[768];
int angle;
int scale;
int x,y;
int danglex;
int anglex;
int dy,dangle,dscale;
int time;
CalcTics();
CalcTics();
IN_ClearKeysDown();
viewwidth=320;
viewheight=200;
memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE, CvtNull, 1),768);
shadingtable=colormap+(1<<12);
VL_NormalizePalette(&pal[0]);
SwitchPalette(&pal[0],35);
// DrawWorld();
// RotateBuffer(0,FINEANGLES*6,FINEANGLES*48,FINEANGLES,(VBLCOUNTER*2));
// DoLaserShoot("apogee");
// DoZIntro();
VL_ClearBuffer (bufferofs, 255);
DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
StartupRotateBuffer (1);
//save off fastcounter
#define APOGEEXANGLE 913
#define APOGEEXMAG 180
#define APOGEESTARTY 0
#define APOGEEENDY 100
#define APOGEESCALESTART (FINEANGLES<<4)
#define APOGEESCALEEND (FINEANGLES)
#define APOGEESONGTIME (124-1)
time = APOGEESONGTIME;
anglex=0;
danglex=(APOGEEXANGLE<<16)/time;
y=APOGEESTARTY<<16;
dy=((APOGEEENDY-APOGEESTARTY)<<16)/time;
dscale=((APOGEESCALEEND-APOGEESCALESTART)<<16)/time;
scale=APOGEESCALESTART<<16;
angle=0;
dangle=(FINEANGLES<<17)/time;
MU_StartSong(song_apogee);
CalcTics();
while (time>=0)
{
VL_DrawPostPic (W_GetNumForName("ap_wrld"));
IN_PumpEvents();
x=100+FixedMul(APOGEEXMAG,sintable[anglex>>16]);
DrawRotatedScreen(x,y>>16,(byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>16,1);
FlipPage();
CalcTics();
angle+=dangle*tics;
scale+=dscale*tics;
y+=dy*tics;
anglex+=danglex*tics;
time-=tics;
if ((LastScan) || IN_GetMouseButtons())
goto apogeeexit;
}
CalcTics();
CalcTics();
VL_DrawPostPic (W_GetNumForName("ap_wrld"));
DrawRotatedScreen(x,y>>16,(byte *)bufferofs,0,APOGEESCALEEND,1);
FlipPage();
while (MU_SongPlaying())
{
IN_PumpEvents();
if ((LastScan) || IN_GetMouseButtons())
goto apogeeexit;
}
// I_Delay(65); //bna added
apogeeexit:
VL_ClearBuffer (bufferofs, 0); //bna added
MenuFadeOut(); //bna added
VH_UpdateScreen (); //bna added
ShutdownRotateBuffer ();
}
#if (SHAREWARE==0)
void DopefishTitle (void)
{
int shapenum;
int height;
shapenum=W_GetNumForName("scthead1");
CalcTics();
CalcTics();
IN_ClearKeysDown();
MU_StartSong( song_secretmenu);
viewwidth=320;
viewheight=200;
SwitchPalette(origpal,35);
oldtime=GetTicCount();
FlipPage();
for (height=1;height<200;height+=(tics<<2))
{
DrawPositionedScaledSprite (160, 100, shapenum, height, 0);
FlipPage();
CalcTics();
if ((LastScan) || IN_GetMouseButtons())
break;
}
SD_Play ( SD_DOPEFISHSND );
oldtime=GetTicCount();
for (height=0;height<FINEANGLES<<1;height+=(tics<<5))
{
DrawPositionedScaledSprite (160+FixedMul(60,costable[height&(FINEANGLES-1)]), 100+FixedMul(60,sintable[height&(FINEANGLES-1)]), shapenum, 200, 0);
FlipPage();
VL_CopyPlanarPage ( (byte *) displayofs, (byte *) bufferofs );
CalcTics();
if ((LastScan) || IN_GetMouseButtons())
break;
}
SD_Play ( SD_DOPEFISHSND );
FlipPage();
}
#endif
//******************************************************************************
//
// RotationFun
//
//******************************************************************************
void RotationFun ( void )
{
int angle;
int scale;
int x,y;
word buttons;
//save off fastcounter
angle=0;
scale=FINEANGLES;
StartupRotateBuffer (0);
CalcTics();
CalcTics();
while (!Keyboard[sc_Escape])
{
IN_UpdateKeyboard ();
DrawRotatedScreen(160,100,(byte *)bufferofs,angle,scale,0);
FlipPage();
CalcTics();
INL_GetMouseDelta(&x, &y);
buttons=IN_GetMouseButtons ();
angle=(angle-x)&(FINEANGLES-1);
if (buttons & (1 << 0))
{
if (scale>0)
scale-=30;
}
else if (buttons & (1 << 1))
{
scale+=30;
}
}
CalcTics();
CalcTics();
Keyboard[sc_Escape]=0;
ShutdownRotateBuffer ();
}
boolean ScreenSaverStarted=false;
screensaver_t * ScreenSaver;
#define PAUSETIME (70)
//******************************************************************************
//
// SetupScreenSaverPhase
//
//******************************************************************************
void SetupScreenSaverPhase ( void )
{
if (ScreenSaverStarted==false)
return;
if (ScreenSaver->phase==0)
{
ScreenSaver->x=160;
ScreenSaver->y=100;
ScreenSaver->angle=0;
ScreenSaver->scale=FINEANGLES;
ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
ScreenSaver->dx=0;
ScreenSaver->dy=0;
ScreenSaver->dscale=((FINEANGLES<<2)-(FINEANGLES))/VBLCOUNTER;
ScreenSaver->time=VBLCOUNTER;
}
else if (ScreenSaver->phase==1)
{
ScreenSaver->x=160;
ScreenSaver->y=100;
ScreenSaver->angle=0;
ScreenSaver->scale=FINEANGLES<<2;
ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
ScreenSaver->dx=RandomNumber("StartupScreen",0)>>5;
ScreenSaver->dy=RandomNumber("StartupScreen",0)>>5;
ScreenSaver->dscale=0;
ScreenSaver->time=-1;
}
}
//******************************************************************************
//
// StartupScreenSaver
//
//******************************************************************************
void StartupScreenSaver ( void )
{
if (ScreenSaverStarted==true)
return;
ScreenSaverStarted=true;
StartupRotateBuffer (0);
ScreenSaver=(screensaver_t *)SafeMalloc(sizeof(screensaver_t));
ScreenSaver->phase=0;
ScreenSaver->pausetime=PAUSETIME;
if (iGLOBAL_SCREENWIDTH == 320){
ScreenSaver->pausex=120;
ScreenSaver->pausey=84;
}else if (iGLOBAL_SCREENWIDTH == 640){
ScreenSaver->pausex=240;
ScreenSaver->pausey=201;
}else if (iGLOBAL_SCREENWIDTH == 800){
ScreenSaver->pausex=300;
ScreenSaver->pausey=252;
}
ScreenSaver->pausex=120;
ScreenSaver->pausey=84;
SetupScreenSaverPhase();
}
//******************************************************************************
//
// ShutdownScreenSaver
//
//******************************************************************************
void ShutdownScreenSaver ( void )
{
if (ScreenSaverStarted==false)
return;
ScreenSaverStarted=false;
ShutdownRotateBuffer ();
SafeFree(ScreenSaver);
//bna section
StartupClientControls();
}
//******************************************************************************
//
// UpdateScreenSaver
//
//******************************************************************************
#define SPINSIZE 40
#define MAXSPEED 8
void UpdateScreenSaver ( void )
{
//EnableScreenStretch();
if (ScreenSaver->time!=-1)
{
ScreenSaver->time-=tics;
if (ScreenSaver->time<0)
{
ScreenSaver->phase++;
SetupScreenSaverPhase();
}
}
ScreenSaver->x+=ScreenSaver->dx*tics;
ScreenSaver->y+=ScreenSaver->dy*tics;
ScreenSaver->angle=(ScreenSaver->angle+(ScreenSaver->dangle*tics))&(FINEANGLES-1);
ScreenSaver->scale+=ScreenSaver->dscale*tics;
if (ScreenSaver->x<SPINSIZE)
{
ScreenSaver->x=SPINSIZE;
ScreenSaver->dx=abs(ScreenSaver->dx);
ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
}
else if (ScreenSaver->x>iGLOBAL_SCREENWIDTH-SPINSIZE)
{
ScreenSaver->x=iGLOBAL_SCREENWIDTH-SPINSIZE;
ScreenSaver->dx=-(abs(ScreenSaver->dx));
ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
}
if (ScreenSaver->y<SPINSIZE)
{
ScreenSaver->y=SPINSIZE;
ScreenSaver->dy=abs(ScreenSaver->dy);
ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
}
else if (ScreenSaver->y>iGLOBAL_SCREENHEIGHT-SPINSIZE)
{
ScreenSaver->y=iGLOBAL_SCREENHEIGHT-SPINSIZE;
ScreenSaver->dy=-(abs(ScreenSaver->dy));
ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
}
if (abs(ScreenSaver->dx)>MAXSPEED)
ScreenSaver->dx=SGN(ScreenSaver->dx)*MAXSPEED;
if (abs(ScreenSaver->dy)>MAXSPEED)
ScreenSaver->dy=SGN(ScreenSaver->dy)*MAXSPEED;
DrawRotatedScreen(ScreenSaver->x,ScreenSaver->y, (byte *)bufferofs,ScreenSaver->angle,ScreenSaver->scale,0);
ScreenSaver->pausetime-=tics;
if (ScreenSaver->pausetime<=0)
{
ScreenSaver->pausetime=PAUSETIME;
if (iGLOBAL_SCREENWIDTH == 320){
ScreenSaver->pausex=RandomNumber ("pausex",0)%240;
ScreenSaver->pausey=RandomNumber ("pausey",0)%168;
}else if (iGLOBAL_SCREENWIDTH == 640){
ScreenSaver->pausex=RandomNumber ("pausex",0)%480;
ScreenSaver->pausey=RandomNumber ("pausey",0)%403;
}else if (iGLOBAL_SCREENWIDTH == 800){
ScreenSaver->pausex=RandomNumber ("pausex",0)%600;
ScreenSaver->pausey=RandomNumber ("pausey",0)%504;
}
}
DrawPauseXY (ScreenSaver->pausex, ScreenSaver->pausey);
FlipPage();
}
#if 0
//******************************************************************************
//
// DoLaserShoot
//
//******************************************************************************
void DoLaserShoot (char * name)
{
int sourcex;
int lastx;
int sourceheight;
int destheight;
int sourcestep;
int xstep;
int hstep;
int midx;
int startx;
int dx;
int f;
int s;
int height;
int x;
int sx;
int size;
patch_t *p;
byte * shape;
DrawWorld();
midx=160;
shape=W_CacheLumpName(name,PU_CACHE);
p=(patch_t *)shape;
size=p->origsize;
startx=midx-(size>>1)-(p->leftoffset);
sourcex=0;
lastx=startx+p->width;
sourcestep=(320*65536)/p->width;
sourceheight=p->origsize<<3;
destheight=p->origsize;
CalcTics();
CalcTics();
for (x=startx;x<lastx;x+=tics,sourcex+=(sourcestep*tics))
{
for (f=startx;f<=x;f++)
DrawScaledPost(destheight,shape,f-startx,f);
height=sourceheight<<16;
if (x<=midx)
{
dx=x-(sourcex>>16);
xstep=1;
}
else
{
dx=(sourcex>>16)-x;
xstep=-1;
}
sx=sourcex>>16;
if (dx)
hstep=((-destheight+sourceheight)<<16)/dx;
else
hstep=0;
for (s=0;s<dx;s++,height-=hstep,sx+=xstep)
DrawScaledPost(height>>16,shape,x-startx,sx);
FlipPage();
CalcTics();
DrawWorld();
break;
}
// Write out one more time so that the rest of the screen is clear
for (f=startx;f<lastx;f++)
DrawScaledPost(destheight,shape,f-startx,f);
FlipPage();
}
//******************************************************************************
//
// DoIntro
//
//******************************************************************************
#define MAXMAG (80)
#define OSCTIME (5*VBLCOUNTER)
#define OSCXSHIFT (4)
#define OSCTSHIFT (4)
void DoIntro (void)
{
byte * shape;
byte * origshape;
int mag;
int currentmag;
int magstep;
int time;
int x;
int t;
shadingtable=colormap+(1<<12);
origshape=W_CacheLumpName("ap_wrld",PU_CACHE);
mag=MAXMAG<<16;
magstep = (MAXMAG<<16)/OSCTIME;
time = OSCTIME;
t=0;
CalcTics();
while (time>0)
{
int yoffset;
int ylow;
int yhigh;
int offset;
int postheight;
byte * src;
shape=origshape;
VL_ClearBuffer (bufferofs, 0);
currentmag=mag>>16;
for (x=0;x<320;x++,shape+=200)
{
VGAWRITEMAP(x&3);
src=shape;
offset=(t+(x<<OSCXSHIFT))&(FINEANGLES-1);
yoffset=FixedMul(currentmag,sintable[offset]);
ylow=yoffset;
if (ylow<0)
{
src-=ylow;
ylow=0;
}
if (ylow>199)
ylow=199;
yhigh=yoffset+200;
if (yhigh>199)
{
yhigh=199;
}
if (yhigh<0)
yhigh=0;
postheight=yhigh-ylow+1;
if (postheight>0)
#ifdef DOS
DrawSkyPost((byte *)bufferofs + (x>>2) + ylookup[ylow],src,postheight);
#else
DrawSkyPost((byte *)bufferofs + x + ylookup[ylow],src,postheight);
#endif
}
FlipPage();
CalcTics();
mag -= (magstep * tics);
time -= tics;
t += (tics<<OSCTSHIFT);
if (mag<0) mag = 0;
}
}
//******************************************************************************
//
// DoZIntro
//
//******************************************************************************
#define ZMAXMAG (199)
#define ZOSCTIME (3*VBLCOUNTER)
#define ZOSCXSHIFT (2)
#define ZOSCXSTEP ( (FINEANGLES<<(ZOSCXSHIFT+16))/320 )
#define ZOSCTSHIFT (2)
void DoZIntro (void)
{
byte * shape;
int mag;
int currentmag;
int magstep;
int time;
int x;
int t;
SetViewSize (MAXVIEWSIZES-1);
shadingtable=colormap+(1<<12);
shape=W_CacheLumpName("ap_wrld",PU_CACHE);
mag=ZMAXMAG<<16;
magstep = (ZMAXMAG<<16)/ZOSCTIME;
time = ZOSCTIME;
t=0;
CalcTics();
while (time>0)
{
int zoffset;
int hoffset;
int offset;
int srcoffset;
int bottomscreen;
int src;
// int i;
VL_ClearBuffer (bufferofs, 0);
currentmag=mag>>16;
srcoffset=0;
for (x=0;x<320;)
{
VGAWRITEMAP(x&3);
offset=(t+(FixedMul(x,ZOSCXSTEP)))&(FINEANGLES-1);
zoffset=FixedMul(currentmag,sintable[offset]);
// hoffset=FixedMulShift(currentmag,sintable[offset],17);
hoffset=0;
dc_texturemid=((100+hoffset)<<SFRACBITS)+(SFRACUNIT>>1);
dc_invscale=((200+zoffset)<<16)/200;
dc_iscale=0xffffffffu/(unsigned)dc_invscale;
srcoffset+=dc_invscale;
sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
bottomscreen = sprtopoffset + (dc_invscale*200);
dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
dc_yh = ((bottomscreen-1)>>SFRACBITS);
if (dc_yh >= viewheight)
dc_yh = viewheight-1;
if (dc_yl < 0)
dc_yl = 0;
if (dc_yl <= dc_yh)
{
src=srcoffset>>16;
if (src>319)
src=319;
if (src<0)
src=0;
dc_source=shape+(src * 200);
// if (RandomNumber("hello",0)<128)
#ifdef DOS
R_DrawColumn ((byte *)bufferofs+(x>>2));
#else
R_DrawColumn ((byte *)bufferofs+x);
#endif
}
// srcoffset+=0x10000;
x++;
if ((LastScan) || IN_GetMouseButtons())
return;
}
FlipPage();
CalcTics();
mag -= (magstep * tics);
// mag += FixedMulShift((magstep * tics),sintable[time&(FINEANGLES-1)],19);
time -= tics;
t += (tics<<ZOSCTSHIFT);
if (mag<0) mag = 0;
}
}
#endif
// Old Stuff
/*
int y1;
int y2;
if (post->alttile!=0)
{
ht=nominalheight;
src2=W_CacheLumpNum(1+post->alttile,PU_CACHE);
// src2+=8;
}
else
{
ht=maxheight;
src2=src;
}
hp_srcstep=(64<<(16+HEIGHTFRACTION))/post->wallheight;
y1 = (((centery<<HFRACTION)-(post->wallheight*pheight)+(1<<(HFRACTION-1))));
y2 = (((post->wallheight*ht)+y1)>>HFRACTION);
if ((y1>>HFRACTION)>=viewheight)
{
post->ceilingclip=viewheight-1;
post->floorclip=viewheight-1;
return;
}
else if (y1<0)
{
hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
y1=0;
post->ceilingclip=0;
}
else
{
hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
y1>>=HFRACTION;
post->ceilingclip=y1;
}
if (y2<0)
{
post->floorclip=0;
post->ceilingclip=0;
}
else if (y2>viewheight)
{
DrawHeightPost(viewheight-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
post->floorclip=viewheight-1;
}
else
{
DrawHeightPost(y2-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
post->floorclip=y2-1;
}
if (ht==maxheight)
return;
y1 = (((centery<<HFRACTION)-(post->wallheight*(pheight-ht))+(1<<(HFRACTION-1))));
y2 = (((post->wallheight<<6)+y1)>>HFRACTION);
if ((y1>>HFRACTION)>=viewheight)
return;
else if (y1<0)
{
hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
y1=0;
}
else
{
hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
y1>>=HFRACTION;
}
if (y2<0)
return;
else if (y2>viewheight)
{
DrawHeightPost(viewheight-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
post->floorclip=viewheight-1;
}
else
{
DrawHeightPost(y2-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
post->floorclip=y2-1;
}
}
*/
//******************************************************************************
//
// DrawBackground
//
//******************************************************************************
void DrawBackground ( byte * bkgnd )
{
// int plane;
int size;
size=linewidth*400;
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAWRITEMAP(plane);
memcpy((byte *)bufferofs,bkgnd,size);
bkgnd+=size;
}
}
//******************************************************************************
//
// PrepareBackground
//
//******************************************************************************
void PrepareBackground ( byte * bkgnd )
{
// int plane;
int size;
size=linewidth*400;
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAREADMAP(plane);
memcpy(bkgnd,(byte *)bufferofs,size);
bkgnd+=size;
}
}
//******************************************************************************
//
// WarpString
//
//******************************************************************************
void WarpString (
int x, int y, int endx, int endy,
int time, byte * back, char * str
)
{
int dx;
int dy;
int cx;
int cy;
int starttime;
LastScan = 0;
dx=((endx-x)<<16)/time;
dy=((endy-y)<<16)/time;
cx=x<<16;
cy=y<<16;
starttime=time;
CalcTics();
while (time>0)
{
DrawBackground ( back );
US_ClippedPrint (cx>>16, cy>>16, str);
FlipPage();
CalcTics();
cx+=dx*tics;
cy+=dy*tics;
time-=tics;
if (LastScan != 0)
break;
}
// DrawBackground ( back );
// US_ClippedPrint (endx, endy, str);
// FlipPage();
}
#if (SHAREWARE==1)
//******************************************************************************
//
// DoEndCinematic
//
//******************************************************************************
//******************************************************************************
//
// WarpSprite
//
//******************************************************************************
void WarpSprite (
int x, int y, int endx, int endy,
int time, byte * back, int shape
)
{
int dx;
int dy;
int cx;
int cy;
int starttime;
LastScan = 0;
dx=((endx-x)<<16)/time;
dy=((endy-y)<<16)/time;
cx=x<<16;
cy=y<<16;
starttime=time;
CalcTics();
while (time>0)
{
DrawBackground ( back );
DrawUnScaledSprite (cx>>16, cy>>16, shape, 16);
FlipPage();
CalcTics();
cx+=dx*tics;
cy+=dy*tics;
time-=tics;
if (LastScan != 0)
break;
}
}
char *EndCinematicPicNames[5] =
{
"lwgshoo2",
"hg2shoo2",
"ankshoo1",
"ligrise4",
"tritoss5",
};
#define NUMENDMESSAGES 24
char *EndCinematicText[NUMENDMESSAGES] =
{
"You've won the battle, Cassatt.\n"
"But when the Oscuridos return,\n"
"will you be ready as they wage\n"
"their Dark War?",
"Armed with only a pistol and 30\n"
"bucks, you must stop the minions of\n"
"El Oscuro before they kill millions\n"
"of innocent people.",
"But for now, hey, enjoy the medal\n"
"you received and take a vacation.\n"
"You've earned it. Maybe on \n"
"San Nicolas Island . . ." ,
"Thanks for playing. If you liked\n"
"\"The HUNT Begins\", check Ordering\n"
"Info for information about \n"
"continuing your adventure.",
"Okay, you can stop reading now.",
"Press a key. That's all there is.\n"
"Thanks.",
"Are you lazy, or illiterate?\n"
"PRESS A KEY.",
"Look, this is pointless. You\n"
"are done. Push off.",
"Okay, show's over. Nothing\n"
"more to see here.",
"Wow, you must like this fine\n"
"background screen.",
"For waiting this long, you get . . .\n"
"nothing! Go away!",
"I mean, I like you as a friend,\n"
"but . . .",
"\"Bob\"",
"All right, um . . . you found the\n"
"secret message! Congratulations!",
"Didn't work, huh? Okay, how about\n"
"this . . .",
"THE END",
"Dang. Thought I had you there.",
"Stop watching.",
"You know that if you registered,\n"
"there would be a lot more cool\n"
"stuff happening right now.",
"Episode IV: A New Hope\n",
"Just think of all the new secret\n"
"messages you could find hidden\n"
"in the registered version!",
"Someone right now is probably\n"
"enjoying the really exciting\n"
"ending of the registered version.",
"ROTT was filmed before\n"
"a live audience.",
"No animals were harmed during the\n"
"creation of this video game, although\n"
"one dog did get its butt spanked\n"
"when it peed on the carpet.\n",
};
char NextGameString1[] = "The Developers of Incredible Power";
char NextGameString2[] = "shall return";
void DoEndCinematic ( void )
{
int trilogo;
int group;
int world;
int width;
int height;
int x,y;
int shape;
int time1,time2;
byte * tmp;
byte * sky;
byte * bkgnd;
int i;
byte pal[768];
EnableScreenStretch();
viewwidth = 320;//MAXSCREENWIDTH;
viewheight = 200;//MAXSCREENHEIGHT;
MU_StartSong(song_youwin);
bkgnd=SafeMalloc(800*linewidth);
trilogo=W_GetNumForName("trilogo");
world=W_GetNumForName("ap_wrld");
group=W_GetNumForName("mmbk");
VL_DrawPostPic (trilogo);
PrepareBackground ( bkgnd );
WarpSprite (160, -100, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("youwin"));
if (LastScan !=0)
goto fadelogo;
I_Delay(30);
fadelogo:
MenuFadeOut();
ClearGraphicsScreen();
memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE,CvtNull,1),768);
VL_NormalizePalette(&pal[0]);
SwitchPalette(&pal[0],35);
VL_DrawPostPic (world);
PrepareBackground ( bkgnd );
WarpSprite (160, 250, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
if (LastScan !=0)
goto fadeworld;
I_Delay(10);
if (LastScan !=0)
goto fadeworld;
WarpSprite (160, 100, 160, -50, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
if (LastScan !=0)
goto fadeworld;
I_Delay(20);
fadeworld:
MenuFadeOut();
ClearGraphicsScreen();
MenuFadeIn();
sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
tmp=sky;
for (x=0;x<256;x++)
{
VGAWRITEMAP(x&3);
for (y=0;y<200;y++)
{
#ifdef DOS
*((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
#else
*((byte *)bufferofs+ylookup[y]+x)=*tmp++;
#endif
}
}
tmp=sky;
for (x=256;x<320;x++)
{
VGAWRITEMAP(x&3);
for (y=0;y<200;y++)
{
#ifdef DOS
*((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
#else
*((byte *)bufferofs+ylookup[y]+x)=*tmp++;
#endif
}
}
for(i=0;i<5;i++)
{
int tx,ty;
tx = 32 + (i << 6);
ty = 100;
shape = W_GetNumForName(EndCinematicPicNames[i]);
DrawUnScaledSprite (tx, ty, shape,16);
}
PrepareBackground ( bkgnd );
//CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE);
CurrentFont = smallfont;
LastScan = 0;
for(i=0;i<NUMENDMESSAGES;i++)
{
if (i>3)
I_Delay(50);
US_MeasureStr (&width, &height, "%s", &(EndCinematicText[i][0]));
if (LastScan !=0)
break;
x=(320-width)>>1;
y=(200-height)>>1;
time1 = (300 - y)*(VBLCOUNTER*4)/300;
time2 = VBLCOUNTER*4-time1;
WarpString (x, 250, x, y-50,time1, bkgnd, EndCinematicText[i]);
if (LastScan !=0)
break;
I_Delay(40);
if (LastScan !=0)
break;
if (i<=3)
I_Delay(40);
if (LastScan !=0)
break;
WarpString (x, y-50, x, -50, time2, bkgnd, EndCinematicText[i]);
if (LastScan !=0)
break;
}
if (LastScan!=0)
goto finalfade;
sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
tmp=sky;
for (x=0;x<256;x++)
{
VGAWRITEMAP(x&3);
for (y=0;y<200;y++)
{
#ifdef DOS
*((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
#else
*((byte *)bufferofs+ylookup[y]+x)=*tmp++;
#endif
}
}
tmp=sky;
for (x=256;x<320;x++)
{
VGAWRITEMAP(x&3);
for (y=0;y<200;y++)
{
#ifdef DOS
*((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
#else
*((byte *)bufferofs+ylookup[y]+x)=*tmp++;
#endif
}
}
for(i=0;i<5;i++)
{
int tx,ty;
tx = 32 + (i << 6);
ty = 100;
shape = W_GetNumForName(EndCinematicPicNames[i]);
DrawUnScaledSprite (tx, ty, shape,16);
}
shape = W_GetNumForName("robogrd3");
PrepareBackground ( bkgnd );
WarpSprite (420,100,300,100,VBLCOUNTER*3,bkgnd,shape);
if (LastScan !=0)
goto finalfade;
PrepareBackground ( bkgnd );
WarpString (200,80,200,80,VBLCOUNTER*3,bkgnd, "Am I late?");
if (LastScan !=0)
goto finalfade;
I_Delay(20);
finalfade:
MenuFadeOut();
VL_ClearVideo (0);
I_Delay(10);
if (LastScan == 0)
{
US_MeasureStr (&width, &height, "%s", NextGameString1);
x=(320-width)>>1;
y=(200-height)>>1;
US_ClippedPrint (x,y-6, NextGameString1);
US_MeasureStr (&width, &height, "%s", NextGameString2);
x=(320-width)>>1;
y=(200-height)>>1;
US_ClippedPrint (x,y+6, NextGameString2);
FlipPage();
VL_FadeIn(0,255,origpal,150);
I_Delay(50);
VL_FadeOut(0,255,0,0,0,150);
VL_ClearVideo (0);
I_Delay(10);
}
SafeFree(bkgnd);
}
#else
// REGISTERED VERSION ======================================================
static char burnCastle1Msg []=
"The monastery burns.\n"
"\n"
"El Oscuro is dead.\n"
"\n"
"The world is safe.\n";
// If all Snake Eggs not destroyed on final level:
static char notDoneMsg[] =
"Unfortunately not all\n"
"of El Oscuro's larvae\n"
"were destroyed.\n"
"\n"
"Thirty years later,\n"
"a descendant of\n"
"El Oscuro wiped out\n"
"the entire world,\n"
"but nice job anyway.\n";
static char tryAgainMsg[] =
"Try Again.\n"
"\n"
"The world will not be\n"
"safe until all of El\n"
"Oscuro's larvae are\n"
"destroyed. Find them.\n";
// If all snake eggs destroyed:
static char doneMsg[] =
"You have destroyed\n"
"El Oscuro and all his\n"
"descendants. Well done!\n";
// On Triad background, in bigger font.
static char youWin1Msg[] =
"So, HUNT Members, how\n"
"do you think the\n"
"mission went?\n";
// Place menu pix of characters here (maybe modem frame too?)
static char youWin2Msg[] =
"Barrett: Well, I think\n"
"I got shin splints from\n"
"all those jump pads.\n"
"But hey, action-wise,\n"
"I've been in tougher\n"
"bar fights, for crying\n"
"out loud.\n";
static char youWin3Msg[] =
"Cassatt: Apart from\n"
"the other HUNT members\n"
"saying I look like\n"
"Richard Mulligan, it\n"
"was quite a success.\n"
"And some of the\n"
"monastery's ironwork\n"
"was very nice.\n";
static char youWin4Msg[] =
"Ni: it was quite easy,\n"
"actually. I just\n"
"pictured the enemy\n"
"having the face of\n"
"my ex-husband, and\n"
"man, I was a force\n"
"of Nature.\n";
static char youWin5Msg[] =
"Wendt: I was kind of\n"
"disappointed. I think\n"
"I used the missile\n"
"weapons way too much.\n"
"Next time, bullets\n"
"only. Nothing sweeter\n"
"than a head shot from\n"
"a hundred feet.\n";
static char youWin6Msg[] =
"Freeley: I'm still\n"
"trying to adjust in\n"
"the aftermath. It's\n"
"kinda tough. I mean,\n"
"I save the damn world,\n"
"and all people ask\n"
"about is my name.\n"
"Sheesh.\n";
// On caching screen
static char youWin7Msg[] =
"The HUNT is victorious!\n"
"\n"
" THE END\n";
static char youWin8Msg[] =
"Now go and celebrate!\n"
"\n"
" THE REAL END";
#define NUMEXPLOSIONTYPES 4
typedef struct {
char name[11];
byte numframes;
} ExplosionInfoType;
ExplosionInfoType ExplosionInfo[NUMEXPLOSIONTYPES]=
{
{"EXPLOS1\0",20},
{"EXP1\0",20},
{"GREXP1\0",25},
{"PART1\0",12},
#if 0
{"GUTS1\0",12},
{"ORGAN1\0",12},
{"RIB1\0",12},
{"GPINK1\0",12},
{"GHEAD1\0",12},
{"GARM1\0",12},
{"GLEG1\0",12},
{"GHUM1\0",12},
{"GHIP1\0",12},
{"GLIMB1\0",12},
#endif
};
typedef struct {
byte which;
byte frame;
byte x;
byte y;
} ExplosionType;
#define MAXTRANSMITTEREXPLOSIONS 30
static ExplosionType Explosions[MAXTRANSMITTEREXPLOSIONS];
void ResetTransmitterExplosion ( ExplosionType * Explosion )
{
Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
Explosion->frame=0;
Explosion->x=(RandomNumber("Explosion",2)>>1)+(160-64);
Explosion->y=(RandomNumber("Explosion",3)>>1);
}
void CacheTransmitterExplosions ( void )
{
int i,j,num;
for (i=0;i<NUMEXPLOSIONTYPES;i++)
{
num=W_GetNumForName(ExplosionInfo[i].name);
for (j=0;j<ExplosionInfo[i].numframes;j++)
{
W_CacheLumpNum(num+j, PU_CACHE, Cvt_patch_t, 1);
}
}
}
void SetupTransmitterExplosions ( void )
{
int i;
for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
{
ResetTransmitterExplosion(&Explosions[i]);
}
}
void UpdateTransmitterExplosions ( void )
{
int i;
for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
{
Explosions[i].frame+=tics;
if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
{
ResetTransmitterExplosion(&Explosions[i]);
SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
}
}
}
void DrawTransmitterExplosions ( void )
{
int i;
for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
{
DrawUnScaledSprite (
Explosions[i].x,
Explosions[i].y,
(W_GetNumForName(ExplosionInfo[Explosions[i].which].name) +
(Explosions[i].frame>>1)),
16
);
}
}
void DoTransmitterExplosion ( void )
{
byte * back;
int i;
VL_ClearVideo(0);
back=SafeMalloc(800*linewidth);
CalcTics();
CalcTics();
DrawNormalSprite(0,0,W_GetNumForName("transmit"));
PrepareBackground ( back );
SetupTransmitterExplosions ();
CacheTransmitterExplosions ();
DrawBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
SHAKETICS=VBLCOUNTER*15;
for (i=0;i<(VBLCOUNTER*15);i+=tics)
{
DrawBackground ( back );
DrawTransmitterExplosions ();
FlipPage();
CalcTics();
UpdateTransmitterExplosions ();
}
VL_FadeOut (0, 255, 63, 63, 63, 150);
screenfaded=false;
SD_Play(SD_PLAYERTCSND);
SD_Play(SD_PLAYERTBSND);
SD_Play(SD_PLAYERDWSND);
SD_Play(SD_PLAYERLNSND);
SD_Play(SD_PLAYERIPFSND);
VL_FadeOut (0, 255, 0, 0, 0, 30);
TurnShakeOff();
SafeFree(back);
}
void ShowTransmitter ( void )
{
MenuFadeOut();
DrawNormalSprite(0,0,W_GetNumForName("transmit"));
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
I_Delay(30);
VL_FadeOut (0, 255, 0, 0, 0, 30);
}
void ShowFinalDoor ( void )
{
byte pal[768];
MenuFadeOut();
VL_ClearBuffer (bufferofs, 0);
DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finldoor"));
FlipPage();
memcpy(&pal[0],W_CacheLumpName("findrpal",PU_CACHE,CvtNull, 1),768);
VL_NormalizePalette(&pal[0]);
SD_Play(SD_OPENDOORSND);
VL_FadeIn (0, 255, pal, 30);
I_Delay(30);
VL_FadeOut (0, 255, 0, 0, 0, 30);
}
void ShowFinalFire ( void )
{
byte pal[768];
MenuFadeOut();
VL_ClearBuffer (bufferofs, 0);
DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finlfire"));
FlipPage();
memcpy(&pal[0],W_CacheLumpName("finfrpal",PU_CACHE,CvtNull, 1),768);
VL_NormalizePalette(&pal[0]);
SD_Play(SD_BAZOOKAFIRESND);
VL_FadeIn (0, 255, pal, 30);
SD_Play(SD_FIREBOMBFIRESND);
I_Delay(2);
SD_Play(SD_HEATSEEKFIRESND);
I_Delay(2);
SD_Play(SD_DRUNKFIRESND);
SD_Play(SD_HEATSEEKFIRESND);
I_Delay(2);
SD_Play(SD_ATKMP40SND);
SD_Play(SD_ATKMP40SND);
I_Delay(2);
SD_Play(SD_HEATSEEKFIRESND);
SD_Play(SD_FIREBOMBFIRESND);
I_Delay(2);
SD_Play(SD_ATKMP40SND);
SD_Play(SD_HEATSEEKFIRESND);
I_Delay(2);
SD_Play(SD_DRUNKFIRESND);
I_Delay(2);
SD_Play(SD_FIREBOMBFIRESND);
I_Delay(2);
SD_Play(SD_HEATSEEKFIRESND);
SD_Play(SD_ATKMP40SND);
I_Delay(2);
SD_Play(SD_DRUNKFIRESND);
SD_Play(SD_HEATSEEKFIRESND);
I_Delay(2);
SD_Play(SD_FIREBOMBFIRESND);
SD_Play(SD_ATKMP40SND);
I_Delay(2);
SD_Play(SD_DRUNKFIRESND);
I_Delay(2);
SD_Play(SD_HEATSEEKFIRESND);
SD_Play(SD_FIREBOMBFIRESND);
I_Delay(2);
SD_Play(SD_ATKMP40SND);
SD_Play(SD_HEATSEEKFIRESND);
I_Delay(2);
SD_Play(SD_DRUNKFIRESND);
SD_Play(SD_FIREBOMBFIRESND);
I_Delay(2);
SD_Play(SD_HEATSEEKFIRESND);
SD_Play(SD_DRUNKFIRESND);
SD_Play(SD_BAZOOKAFIRESND);
I_Delay(4);
VL_FadeOut (0, 255, 0, 0, 0, 30);
}
void ScrollString ( int cy, char * string, byte * bkgnd, int scrolltime, int pausetime )
{
int x,y;
int width,height;
int time1,time2;
LastScan=0;
US_MeasureStr (&width, &height, "%s", string);
x=(320-width)>>1;
y=cy-(height>>1);
time1 = ((220 - y)*scrolltime)/(220+height);
time2 = scrolltime-time1;
WarpString (x, 210, x, y, time1, bkgnd, string);
if (LastScan !=0)
return;
I_Delay(pausetime);
if (LastScan !=0)
return;
WarpString (x, y, x, -10-height, time2, bkgnd, string);
}
void DoBurningCastle ( void )
{
byte * back;
LastScan=0;
VL_ClearVideo(0);
back=SafeMalloc(800*linewidth);
DrawNormalSprite(0,0,W_GetNumForName("finale"));
PrepareBackground ( back );
CurrentFont = smallfont;
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1 );
ScrollString ( 150, &burnCastle1Msg[0], back, 4*VBLCOUNTER, 80);
W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
}
void DoFailedScreen ( void )
{
byte * back;
back=SafeMalloc(800*linewidth);
VL_DrawPostPic (W_GetNumForName("trilogo"));
PrepareBackground ( back );
CurrentFont = smallfont;
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
ScrollString ( 100, &notDoneMsg[0], back, 4*VBLCOUNTER, 100);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
}
void DoTryAgainScreen ( void )
{
byte * back;
back=SafeMalloc(800*linewidth);
VL_DrawPostPic (W_GetNumForName("trilogo"));
PrepareBackground ( back );
CurrentFont = smallfont;
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
ScrollString ( 100, tryAgainMsg, back, 4*VBLCOUNTER, 80);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
}
void ResetWorldExplosion ( ExplosionType * Explosion )
{
Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
Explosion->frame=0;
// RandomNumber("Explosion",1)%ExplosionInfo[Explosions[i].which].numframes;
Explosion->x=(RandomNumber("Explosion",2))+64;
Explosion->y=(RandomNumber("Explosion",3)%180);
}
void SetupWorldExplosions ( void )
{
int i;
for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
{
ResetWorldExplosion(&Explosions[i]);
}
}
void UpdateWorldExplosions ( void )
{
int i;
for (i=0;i<MAXTRANSMITTEREXPLOSIONS;i++)
{
Explosions[i].frame+=tics;
if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
{
ResetWorldExplosion(&Explosions[i]);
SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
}
}
}
void DestroyEarth ( void )
{
byte * back;
int i;
VL_ClearVideo(0);
back=SafeMalloc(800*linewidth);
CalcTics();
CalcTics();
DrawNormalSprite(0,0,W_GetNumForName("ourearth"));
PrepareBackground ( back );
SetupWorldExplosions ();
CacheTransmitterExplosions ();
DrawBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
SHAKETICS=VBLCOUNTER*10;
for (i=0;i<(VBLCOUNTER*10);i+=tics)
{
DrawBackground ( back );
DrawTransmitterExplosions ();
FlipPage();
CalcTics();
UpdateWorldExplosions ();
}
VL_FadeOut (0, 255, 63, 63, 63, 150);
screenfaded=false;
if (gamestate.violence==vl_excessive)
SD_Play(SD_YOUSUCKSND);
VL_FadeOut (0, 255, 0, 0, 0, 50);
TurnShakeOff();
SafeFree(back);
}
boolean DestroyedAllEggs ( void )
{
statobj_t * temp;
for(temp=FIRSTSTAT;temp;temp=temp->statnext)
{
if (temp->itemnumber==stat_tomlarva)
return false;
}
return true;
}
void DoSanNicolas ( void )
{
byte pal[768];
LastScan=0;
VL_ClearVideo(0);
DrawNormalSprite(0,16,W_GetNumForName("nicolas"));
DrawNormalSprite(10,200-58,W_GetNumForName("budgcut"));
FlipPage();
memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768);
VL_NormalizePalette(&pal[0]);
VL_FadeIn (0, 255, pal, 30);
I_Delay(60);
VL_FadeOut (0, 255, 0, 0, 0, 80);
}
void PlayerQuestionScreen ( void )
{
byte * back;
back=SafeMalloc(800*linewidth);
VL_DrawPostPic (W_GetNumForName("trilogo"));
PrepareBackground ( back );
CurrentFont = smallfont;
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &doneMsg[0], back, 4*VBLCOUNTER, 40);
ScrollString ( 100, &youWin1Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawXYPic ( 8, 100-24, W_GetNumForName("player2"));
PrepareBackground ( back );
CurrentFont = smallfont;
SD_Play(SD_PLAYERTBSND);
ScrollString ( 100, &youWin2Msg[0], back, 4*VBLCOUNTER, 100);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawXYPic ( 8, 100-24, W_GetNumForName("player1"));
PrepareBackground ( back );
SD_Play(SD_PLAYERTCSND);
ScrollString ( 100, &youWin3Msg[0], back, 4*VBLCOUNTER, 100);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawXYPic ( 8, 100-24, W_GetNumForName("player4"));
PrepareBackground ( back );
SD_Play(SD_PLAYERLNSND);
ScrollString ( 100, &youWin4Msg[0], back, 4*VBLCOUNTER, 100);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawXYPic ( 8, 100-24, W_GetNumForName("player3"));
PrepareBackground ( back );
SD_Play(SD_PLAYERDWSND);
ScrollString ( 100, &youWin5Msg[0], back, 4*VBLCOUNTER, 100);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawXYPic ( 8, 100-24, W_GetNumForName("player5"));
PrepareBackground ( back );
SD_Play(SD_PLAYERIPFSND);
ScrollString ( 100, &youWin6Msg[0], back, 4*VBLCOUNTER, 100);
W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
}
void DoYouWin ( void )
{
pic_t * pic;
byte * back;
back=SafeMalloc(800*linewidth);
LastScan=0;
VL_ClearVideo(0);
pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
VWB_DrawPic (0, 0, pic);
PrepareBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &youWin7Msg[0], back, 4*VBLCOUNTER, 300);
W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
}
void DoFinalEnd ( void )
{
pic_t * pic;
byte * back;
back=SafeMalloc(800*linewidth);
LastScan=0;
VL_ClearVideo(0);
pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
VWB_DrawPic (0, 0, pic);
DrawNormalSprite(0,0,W_GetNumForName("sombrero"));
DrawNormalSprite(0,0,W_GetNumForName("amflag"));
DrawNormalSprite(0,0,W_GetNumForName("witchhat"));
DrawNormalSprite(0,0,W_GetNumForName("esterhat"));
DrawNormalSprite(0,0,W_GetNumForName("santahat"));
PrepareBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &youWin8Msg[0], back, 4*VBLCOUNTER, 100);
W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
VL_FadeOut (0, 255, 0, 0, 0, 80);
SafeFree(back);
VL_ClearVideo(0);
}
static char dipMsg[] =
"The Developers of Incredible Power!\n"
"\n"
"Susan Tom Jim Stephen\n"
"Mark William Chuck\n";
static char creditsMsg[] =
"Rise of the Triad Credits\n";
static char credits1Msg[] =
"Programmers\n"
"\n"
"Mark Dochtermann\n"
"William Scarboro\n"
"Jim Dose'\n"
"Nolan Martin\n";
static char credits2Msg[] =
"Creative Director\n"
"\n"
"Tom Hall\n";
static char credits3Msg[] =
"Artists\n"
"\n"
"Stephen Hornback\n"
"Tim Neveu\n"
"Chuck Jones\n"
"Susan Singer\n"
"James Storey\n"
"Cygnus Multimedia\n";
static char credits4Msg[] =
"Level Designers\n"
"\n"
"Tom Hall\n"
"Joseph Selinske\n"
"Marianna Vayntrub\n"
"Joe Siegler\n";
static char credits5Msg[] =
"Music\n"
"\n"
"Lee Jackson\n"
"Bobby Prince\n";
static char credits6Msg[] =
"Robot Models\n"
"\n"
"Gregor Punchatz\n";
static char credits7Msg[] =
"Special Thanks\n"
"\n"
"George Broussard\n"
"Scott Miller\n"
"Steven Blackburn\n"
"Apogee Technical Support\n"
"Apogee Support Staff\n"
"John Carmack\n"
"Ken Silverman\n";
static char credits8Msg[] =
"The Hand of God\n"
"\n"
"Tim Neveu's Hand\n";
static char credits9Msg[] =
"Dog Snout and Paw\n"
"\n"
"Loki\n"
"The Carpet Wetting Maestro\n";
static char credits10Msg[] =
"Krist's chair\n"
"\n"
"Stephen Blackburn's Comfy Chair\n"
"Marianna's Paper and Glue\n";
static char credits11Msg[] =
"Character Voices\n"
"\n"
"Darian - Mark Dochtermann\n"
"Krist - Joe Siegler\n"
"NME - Sound CD#4005\n"
"Oscuro - Tom Hall\n"
"Low Guard - Steve Quarrella\n"
"High Guard - Steven Blackburn\n"
"Over Patrol - Chuck Jones\n";
static char credits12Msg[] =
"Character Voices Continued\n"
"\n"
"Strike Team - Scott Miller\n"
"Lightning Guard - William Scarboro\n"
"Triad Enforcer - George Broussard\n"
"All Monks - Tom Hall\n"
"Taradino - Joe Selinske\n"
"Lorelei - Pau Suet Ying\n"
"Ian Paul - Jim Dose'\n"
"Doug - Lee Jackson\n"
"Thi - Susan Singer\n";
static char actorsMsg[] =
"The Actors\n";
static char actors1Msg[] =
"Low Guard\n"
"\n"
"Steve Quarrella\n";
static char actors2Msg[] =
"High Guard\n"
"\n"
"Steven Blackburn\n";
static char actors3Msg[] =
"Over Patrol\n"
"\n"
"Nolan Martin\n";
static char actors4Msg[] =
"Strike Team\n"
"\n"
"Scott Miller\n";
static char actors5Msg[] =
"Lightning Guard\n"
"\n"
"Kevin Green\n";
static char actors6Msg[] =
"Triad Enforcer\n"
"\n"
"George Broussard\n";
static char actors7Msg[] =
"Death Monk\n"
"\n"
"Lee Jackson\n";
static char actors8Msg[] =
"Deathfire Monk\n"
"\n"
"Allen Blum III\n";
static char actors9Msg[] =
"Robot Guard\n"
"\n"
"Himself\n";
static char actors10Msg[] =
"General Darian\n"
"\n"
"Steve Maines\n";
static char actors11Msg[] =
"Sebastian Krist\n"
"\n"
"Joe Siegler\n";
static char actors12Msg[] =
"The NME\n"
"\n"
"Himself\n";
static char actors13Msg[] =
"El Oscuro\n"
"\n"
"Tom Hall\n";
static char cut1Msg[] =
"Deathfire Monk\n"
"\n"
"Mark Dochtermann\n";
static char cut2Msg[] =
"Over Patrol\n"
"\n"
"Pat Miller\n";
static char cut3Msg[] =
"Low Guard\n"
"\n"
"Marianna Vayntrub\n";
static char cut4Msg[] =
"Strike Team\n"
"\n"
"Ann Grauerholz\n";
static char cut5Msg[] =
"Lightning Guard\n"
"\n"
"William Scarboro\n";
static char cut6Msg[] =
"High Guard\n"
"\n"
"Stephen Hornback\n";
static char playersCutMsg[] =
"Actors who were\n"
"cut from the game\n";
void DIPCredits ( void )
{
byte * back;
back=SafeMalloc(800*linewidth);
VL_DrawPostPic (W_GetNumForName("trilogo"));
PrepareBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &creditsMsg[0], back, 4*VBLCOUNTER, 30);
CurrentFont = smallfont;
ScrollString ( 100, &credits1Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits2Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits3Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits4Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits5Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits6Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits7Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits8Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits9Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits10Msg[0], back, 4*VBLCOUNTER, 50);
ScrollString ( 100, &credits11Msg[0], back, 4*VBLCOUNTER, 80);
ScrollString ( 100, &credits12Msg[0], back, 4*VBLCOUNTER, 80);
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &actorsMsg[0], back, 4*VBLCOUNTER, 50);
CurrentFont = smallfont;
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("lwgshoo2"));
PrepareBackground ( back );
ScrollString ( 100, &actors1Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hg2shoo2"));
PrepareBackground ( back );
ScrollString ( 100, &actors2Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("obpshoo1"));
PrepareBackground ( back );
ScrollString ( 100, &actors3Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ankshoo1"));
PrepareBackground ( back );
ScrollString ( 100, &actors4Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ligrise4"));
PrepareBackground ( back );
ScrollString ( 100, &actors5Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tritoss5"));
PrepareBackground ( back );
ScrollString ( 100, &actors6Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("monkdr4"));
PrepareBackground ( back );
ScrollString ( 100, &actors7Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("allksh4"));
PrepareBackground ( back );
ScrollString ( 100, &actors8Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("robogrd1"));
PrepareBackground ( back );
ScrollString ( 100, &actors9Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("darshoo1"));
PrepareBackground ( back );
ScrollString ( 100, &actors10Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hdope8"));
PrepareBackground ( back );
ScrollString ( 100, &actors11Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rbody101"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rhead101"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rsw01"));
PrepareBackground ( back );
ScrollString ( 100, &actors12Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tomfly21"));
PrepareBackground ( back );
ScrollString ( 100, &actors13Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
PrepareBackground ( back );
CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
ScrollString ( 100, &playersCutMsg[0], back, 4*VBLCOUNTER, 40);
CurrentFont = smallfont;
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmark"));
PrepareBackground ( back );
ScrollString ( 100, &cut1Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutpat"));
PrepareBackground ( back );
ScrollString ( 100, &cut2Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmari"));
PrepareBackground ( back );
ScrollString ( 100, &cut3Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutann"));
PrepareBackground ( back );
ScrollString ( 100, &cut4Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutwill"));
PrepareBackground ( back );
ScrollString ( 100, &cut5Msg[0], back, 4*VBLCOUNTER, 50);
VL_DrawPostPic (W_GetNumForName("trilogo"));
DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutstev"));
PrepareBackground ( back );
ScrollString ( 100, &cut6Msg[0], back, 4*VBLCOUNTER, 50);
VL_FadeOut (0, 255, 0, 0, 0, 80);
DrawNormalSprite(0,0,W_GetNumForName("grouppic"));
PrepareBackground ( back );
FlipPage();
VL_FadeIn (0, 255, origpal, 30);
ScrollString ( 175, &dipMsg[0], back, 4*VBLCOUNTER, 140);
VL_FadeOut (0, 255, 0, 0, 0, 80);
W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
SafeFree(back);
}
void DoEndCinematic ( void )
{
EnableScreenStretch();
viewwidth = 320;//MAXSCREENWIDTH;
viewheight = 200;//MAXSCREENHEIGHT;
MU_FadeOut ( 1000 );
MU_StopSong ();
ShowFinalDoor();
ShowTransmitter ();
ShowFinalFire();
DoTransmitterExplosion();
MU_StartSong(song_youwin);
DoBurningCastle ();
DoSanNicolas();
if (DestroyedAllEggs () == true)
{
PlayerQuestionScreen();
DIPCredits();
DoYouWin();
if (LastScan !=0)
{
IN_UpdateKeyboard();
return;
}
DoFinalEnd();
}
else
{
MU_StartSong(song_gameover);
DoFailedScreen();
DestroyEarth();
DoTryAgainScreen ();
playstate=ex_warped;
gamestate.mapon=33;
}
IN_UpdateKeyboard();
}
void DoInBetweenCinematic (int yoffset, int lump, int delay, char * string )
{
int width,height;
int x,y;
VL_FadeOut (0, 255, 0, 0, 0, 20);
VL_ClearBuffer (bufferofs, 0);
DrawNormalSprite(0,yoffset,lump);
CurrentFont=smallfont;
US_MeasureStr (&width, &height, "%s", string);
x=(320-width)>>1;
y=190-height;
US_ClippedPrint (x, y, string);
FlipPage();
VL_FadeIn(0,255,origpal,20);
I_Delay (delay);
VL_FadeOut (0, 255, 0, 0, 0, 20);
}
#endif
//******************************************************************************
//
// DoCreditScreen
//
//******************************************************************************
#define NUMFIRSTCREDITMESSAGES 22
#define NUMSECONDCREDITMESSAGES 28
typedef struct CreditType {
char text[80];
byte font;
byte endy;
} CreditType;
CreditType FirstCredits[NUMFIRSTCREDITMESSAGES] =
{
{"Rise of the Triad Credits",0,0},
{"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
{"Apogee's Developers of Incredible Power",1,20},
{"Creative Director",0,30},
{"Tom Hall",1,40},
{"Programmers",0,50},
{"Mark Dochtermann William Scarboro",1,60},
{"Jim Dose' Nolan Martin",1,66},
{"Artists",0,76},
{"Stephen Hornback Chuck Jones",1,86},
{"Susan Singer Tim Neveu",1,92},
{"James Storey Cygnus Multimedia",1,98},
{"Level Designers",0,108},
{"Joseph Selinske Tom Hall",1,118},
{"Marianna Vayntrub Joe Siegler",1,124},
{"Musicians",0,134},
{"Lee Jackson Robert Prince",1,144},
{"Uniforms",0,154},
{"D.J. Goodwin Matt McKinney",1,164},
{"Special Thanks",0,174},
{"John Carmack Ken Silverman Gregor Punchatz",1,184},
};
CreditType SecondCredits[NUMSECONDCREDITMESSAGES] =
{
{"Rise of the Triad Credits",0,0},
{"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
{"Executive Producers",0,20},
{"George Broussard Scott Miller",1,30},
{"Manual Design",0,40},
{"Robert Atkins",1,50},
{"Beta Testers",0,60},
{"Steven Blackburn",1,70},
{"Todd Aubin Mike Bartelt",1,76},
{"Wayne Benner Neil Bonner",1,82},
{"Glenn Brensinger Douglas Brewer",1,88},
{"David Butler Daniel Creeron",1,94},
{"Scott Darling Jason Ewasiuk",1,100},
{"Craig Hamilton Ken Heckbert",1,106},
{"Terry Herrin Greg Hively",1,112},
{"John Howard Douglas Howell",1,118},
{"Dennis Kurek Hank Leukart",1,124},
{"Jim Lietzan Ken Mayer",1,130},
{"Wayne Millard Penny Plant",1,136},
{"Brian Prinner Jeff Rausch",1,142},
{"Kelly Rogers Neil Rubenking",1,148},
{"Steven Salter Chris White",1,154},
{"Special Thanks",0,162},
{"Apogee Technical Support Pau Suet Ying",1,172},
{"Anthony, Zach, Rajan, Miki, Loki",1,178},
{"Nathan, Petro, Tim, Jake, MacKay",1,184},
{"Loyal, Ric, Teller, Amano",1,190},
};
void DrawPreviousCredits ( int num, CreditType * Credits )
{
int width;
int height;
int x,y;
int i;
for(i=0;i<num;i++)
{
if (Credits[i].font==0)
CurrentFont=smallfont;
else
CurrentFont=tinyfont;
US_MeasureStr (&width, &height, "%s", &(Credits[i].text[0]));
x=(320-width)>>1;
y=Credits[i].endy;
US_ClippedPrint (x, y+4, &Credits[i].text[0]);
}
}
#define CREDITSTARTY 220
//******************************************************************************
//
// WarpCreditString
//
//******************************************************************************
extern boolean dopefish;
void WarpCreditString ( int time, byte * back, int num, CreditType * Credits)
{
int dy;
int cy;
int x;
int y;
int width;
int height;
boolean soundplayed;
LastScan = 0;
if (Credits[num].font==0)
CurrentFont=smallfont;
else
CurrentFont=tinyfont;
US_MeasureStr (&width, &height, "%s", &(Credits[num].text[0]));
x=(320-width)>>1;
y=Credits[num].endy;
dy=((y-CREDITSTARTY)<<16)/time;
cy=CREDITSTARTY<<16;
CalcTics();
soundplayed=false;
while (time>0)
{
DrawBackground ( back );
DrawPreviousCredits ( num, Credits );
if (Credits[num].font==0)
CurrentFont=smallfont;
else
CurrentFont=tinyfont;
US_ClippedPrint (x, (cy>>16)+4, &Credits[num].text[0]);
if ( ((cy>>16)<196) && (soundplayed==false))
{
if ((dopefish==true) && (SD_Started==true))
{
int snd;
do
{
snd=(RandomNumber("DoCredits",0)+RandomNumber("DoCredits",0))%MAXSOUNDS;
}
while (SD_SoundOkay ( snd ) == false);
SD_Play ( snd );
}
else
{
// SD_Play ( SD_BAZOOKAFIRESND );
#if (SHAREWARE == 0)
SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%13) );
#else
SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%6) );
#endif
soundplayed=true;
}
}
FlipPage();
CalcTics();
cy+=dy*tics;
time-=tics;
if (LastScan != 0)
break;
}
}
void DoCreditScreen ( void )
{
int trilogo;
int time;
byte * bkgnd;
font_t * oldfont;
int i;
EnableScreenStretch();
viewwidth = 320;//MAXSCREENWIDTH;
viewheight = 200;//MAXSCREENHEIGHT;
bkgnd=SafeMalloc(800*linewidth);
trilogo=W_GetNumForName("trilogo");
VL_DrawPostPic (trilogo);
// SetTextMode ( );
PrepareBackground ( bkgnd );
oldfont=CurrentFont;
for(i=0;i<NUMFIRSTCREDITMESSAGES;i++)
{
time = (CREDITSTARTY - FirstCredits[i].endy)*(VBLCOUNTER*1)/CREDITSTARTY;
// time = VBLCOUNTER;
WarpCreditString ( time, bkgnd, i, FirstCredits );
IN_PumpEvents();
// SD_Play ( SD_EXPLODESND );
if (LastScan !=0)
break;
}
i=NUMFIRSTCREDITMESSAGES;
DrawBackground ( bkgnd );
DrawPreviousCredits ( i, FirstCredits );
FlipPage();
IN_PumpEvents();
I_Delay(40);
for(i=0;i<NUMSECONDCREDITMESSAGES;i++)
{
time = (CREDITSTARTY - SecondCredits[i].endy)*(VBLCOUNTER/2)/CREDITSTARTY;
// time = VBLCOUNTER;
WarpCreditString ( time, bkgnd, i, SecondCredits );
IN_PumpEvents();
// SD_Play ( SD_EXPLODESND );
if (LastScan !=0)
break;
}
i=NUMSECONDCREDITMESSAGES;
DrawBackground ( bkgnd );
DrawPreviousCredits ( i, SecondCredits );
FlipPage();
IN_PumpEvents();
I_Delay(40);
MenuFadeOut();
VL_ClearVideo (0);
SafeFree(bkgnd);
CurrentFont=oldfont;
}
#define NUMSTORYLINES 16
char * MicroStory[NUMSTORYLINES] =
{
"You are a member of HUNT, the",
"High-Risk United Nations Taskforce.",
"Stranded on an island in the",
"Pacific, you must battle a master",
"of pyrotechnics, hundreds of",
"members of a death cult, and their",
"leader, El Oscuro.",
"\0",
"You must reach the transmitter",
"that is signalling the systematic",
"destruction of Los Angeles.",
"\0",
"If you fail, millions will die",
"and you will be tortured.",
"\0",
"So, you know, don't fail."
};
void DoMicroStoryScreen ( void )
{
pic_t * pic;
int x,y;
int i;
VL_FadeOut (0, 255, 0, 0, 0, 20);
pic=(pic_t *)W_CacheLumpName("mmbk",PU_CACHE,Cvt_pic_t,1);
VWB_DrawPic (0, 0, pic);
CheckHolidays();
x=15;
y=30;
IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1);
for(i=0;i<NUMSTORYLINES;i++)
{
DrawIntensityString (x, y, MicroStory[i], 241);
y += 9;
}
FlipPage();
MenuFadeIn();
I_Delay (100);//240
VL_FadeOut (0, 255, 0, 0, 0, 20);
}
#ifndef DOS
void DrawMenuPost (int height, byte * src, byte * buf)
{
int frac = hp_startfrac;
while (height--) {
*buf = src[frac >> 16];
buf += linewidth;
frac += hp_srcstep;
}
}
void DrawMapPost (int height, byte * src, byte * buf)
{
int frac = 0;
while (height--) {
*buf = src[frac >> 16];
buf += linewidth;
frac += hp_srcstep;
}
}
void DrawRotRow(int count, byte * dest, byte * src)
{
unsigned eax, ecx, edx;
// unsigned a, b, c,d;
byte * srctmp;
byte * desttmp;
ecx = mr_yfrac;
edx = mr_xfrac;
if ((iGLOBAL_SCREENWIDTH == 320)||(iG_masked==true))
{
while (count--) {
eax = edx >> 16;
if (eax < 256 && (ecx >> 16) < 512) {
eax = (eax << 9) | ((ecx << 7) >> (32-9));
} else {
eax = 0;
}
*dest++ = src[eax];
edx += mr_xstep;
ecx += mr_ystep;
}
}else if (iGLOBAL_SCREENWIDTH == 640) {
while (count--) {
eax = edx >> 16;
if (eax < (256*2.0) && (ecx >> 16) < (512*1.8)) {
eax = (eax << 10) | ((ecx << 6) >> (32-10));
} else {
eax = 0;
}
*dest++ = src[eax];
edx += mr_xstep;
ecx += mr_ystep;
}
}else if (iGLOBAL_SCREENWIDTH == 800) {
srctmp = src;
desttmp = dest;
desttmp -= (iGLOBAL_SCREENWIDTH*1);
ecx = mr_yfrac;
edx = mr_xfrac;
//count = 800
//zxcv
while (count--) {
eax = edx >> 16;//edx=4146069504 eax=63264 edx/eax = 65536->0x10000
//a=(eax << 9); //=eax*512
//a=(eax << 7); //=eax*128
//a=512|128; = 640;
//SetTextMode ( );
//a=(ecx >> 16);//ecx=4102225920 a=62595 ecx/65536 = 62595
// Y-dir x-dir
if (eax < (256*2.5) && (ecx >> 16) < (512*2)) {
//eax = (eax << 9) | ((ecx << 7) >> (32-9));
eax = (eax << 10) | ((ecx << 6) >> (32-10));
/* eax = (eax * 512*2) ;
//(23)
eax += ((ecx ) >> (32-9));//ecx=196608
*/
} else {
eax = 0;
}
//desttmp -= centeroffset;
*desttmp++ = srctmp[eax];
//*desttmp++ = srctmp[eax];
edx += mr_xstep;
ecx += mr_ystep;
}
}
}
void DrawMaskedRotRow(int count, byte * dest, byte * src)
{
unsigned eax;
unsigned xfrac, yfrac;
xfrac = mr_xfrac;
yfrac = mr_yfrac;
while (count--) {
eax = xfrac >> 16;
if (eax < 256 && (yfrac >> 16) < 512) {
eax = (eax << 9) | ((yfrac << 7) >> (32-9));
} else {
eax = 0;
}
if (src[eax] != 0xff) *dest = src[eax];
dest++;
xfrac += mr_xstep;
yfrac += mr_ystep;
}
}
void DrawSkyPost (byte * buf, byte * src, int height)
{
// bna fix for missing sky by high res eg 800x600
// when sky is >400 (max skyheight) then reverse mouintain to missing spot
// there should be 200 line of mouintain (400+200) = 600 height lines
// not the best solution but what it works
if (iGLOBAL_SCREENWIDTH > 320){
// bna section start
//int n = 0;
int orgh = 0;//height;
if (height > 400){orgh=height;}
while (height--) {
if ((orgh > 0)&&( height<(orgh-400))){
src-=2;
*buf = shadingtable[*src];
}else{
*buf = shadingtable[*src];
}
buf += linewidth;
src++;
}
// bna section end
}
else {
// org code
while (height--) {
*buf = shadingtable[*src];
buf += linewidth;
src++;
}
//
}
/*
int lw = linewidth * 2;
int h = height;
while (h--) {
*(buf) = shadingtable[*src];
buf += lw;
*(buf) = shadingtable[*src];
buf += lw;
//buf += lw;
src++;
}*/
}
#define CEILINGCOLOR 24 //default color when no sky or floor
#define FLOORCOLOR 32
void RefreshClear (void)
{
int start, base;
memset(spotvis, 0, sizeof(spotvis));
if (fandc) {
return;
}
start = min(centery, viewheight);
if (start > 0) {
VL_Bar(0, 0, iGLOBAL_SCREENHEIGHT, start, CEILINGCOLOR);
} else {
start = 0;
}
base = start;
start = min(viewheight-start, viewheight);
if (start > 0) {
VL_Bar(0, base, iGLOBAL_SCREENHEIGHT, start, FLOORCOLOR);
}
}
#endif
#if 0
typedef struct {
int x;
int y;
int angle;
int speed;
int color;
int endx;
int endy;
int plane;
int time;
} ParticleType;
#define NUMPARTICLES 300
#define PARTICLETHINKTIME 5
#define Fix(a) (a &= (FINEANGLES-1))
ParticleType * Particle;
int numparticles;
//******************************************************************************
//
// InitializeParticles
//
//******************************************************************************
void InitializeParticles (void)
{
int i;
ParticleType * part;
Particle=(ParticleType *)SafeMalloc ( sizeof(ParticleType) * numparticles );
memset ( Particle, 0, sizeof(ParticleType) * numparticles );
for (i=0;i<numparticles;i++)
{
part=&Particle[i];
part->x=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewwidth)<<16;
part->y=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewheight)<<16;
// part->x=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewwidth-40)+20)<<16);
// part->y=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewheight-40)+20)<<16);
part->angle=(RandomNumber("hello",0)*RandomNumber("hello",0))%FINEANGLES;
// part->speed=(RandomNumber("hello",0)%2)<<16;
part->speed=(1<<16)-1;
part->color=RandomNumber("hello",0);
part->endx=-1;
part->endy=-1;
part->plane=(part->x>>16)&3;
part->time=(RandomNumber("",0)%PARTICLETHINKTIME)+1;
// part->color=255;
}
}
//******************************************************************************
//
// ShutdownParticles
//
//******************************************************************************
void ShutdownParticles (void)
{
SafeFree(Particle);
}
void AdjustParticleAngle(int maxadjust, int *currangle,int targetangle)
{
int dangle,i,magangle;
for(i=0;i<maxadjust;i++)
{
dangle = *currangle - targetangle;
if (dangle)
{
magangle = abs(dangle);
if (magangle > (ANGLES/2))
{
if (dangle > 0)
(*currangle) ++;
else
(*currangle) --;
}
else
{
if (dangle > 0)
(*currangle) --;
else
(*currangle) ++;
}
Fix(*currangle);
}
}
}
//******************************************************************************
//
// UpdateParticles
//
//******************************************************************************
//#define MAXADJUST (FINEANGLES/40)
#define MAXADJUST (FINEANGLES/20)
void UpdateParticles (int type)
{
int i;
int dx,dy;
ParticleType * target;
ParticleType * part;
if (type==0)
{
for (i=0;i<numparticles-1;i++)
{
int angle;
part=&Particle[i];
// target=&Particle[numparticles-1];
// target=&Particle[i+1];
target=&Particle[(RandomNumber("",0)*RandomNumber("",0))%numparticles];
part->x+=-FixedMul (part->speed, costable[part->angle]);
part->y+= FixedMul (part->speed, sintable[part->angle]);
part->plane=(part->x>>16)&3;
dx = part->x - target->x;
dy = target->y - part->y;
if (dx && dy)
{
angle = atan2_appx(dx,dy);
AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
}
}
part=&Particle[numparticles-1];
part->x+=-FixedMul (part->speed, costable[part->angle]);
part->y+= FixedMul (part->speed, sintable[part->angle]);
part->plane=(part->x>>16)&3;
dx=part->x>>16;
dy=part->y>>16;
if ( (dx<20) || (dx>(viewwidth-20)) )
{
if ( part->angle < (FINEANGLES/2) )
{
part->angle=FINEANGLES/2-part->angle;
Fix(part->angle);
}
else
{
part->angle=FINEANGLES-part->angle;
Fix(part->angle);
}
}
if ( (dy<20) || (dy>(viewheight-20)) )
{
part->angle=FINEANGLES-part->angle;
Fix(part->angle);
}
}
else
{
for (i=0;i<numparticles;i++)
{
int angle;
part=&Particle[i];
if ((part->x>>16)!=part->endx)
part->x+=-FixedMul (part->speed, costable[part->angle]);
else
part->x=part->endx<<16;
if ((part->y>>16)!=part->endy)
part->y+= FixedMul (part->speed, sintable[part->angle]);
else
part->y=part->endy<<16;
part->plane=(part->x>>16)&3;
part->time--;
if (part->time==0)
{
part->time=PARTICLETHINKTIME;
dx = part->x - (part->endx<<16);
dy = (part->endy<<16) - part->y;
if (dx && dy)
{
angle = atan2_appx(dx,dy);
AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
}
}
}
}
}
//******************************************************************************
//
// DrawParticles
//
//******************************************************************************
void DrawParticles (void)
{
int i;
int dx,dy;
int plane;
ParticleType * part;
VL_ClearBuffer (bufferofs, 0);
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAWRITEMAP(plane);
for (i=0;i<numparticles;i++)
{
part=&Particle[i];
if (part->plane!=plane)
continue;
dx=part->x>>16;
dy=part->y>>16;
if (dx<0) dx=0;
if (dx>=viewwidth) dx=viewwidth-1;
if (dy<0) dy=0;
if (dy>=viewheight) dy=viewheight-1;
#ifdef DOS
*( (byte *) bufferofs + (dx>>2) + ylookup[dy] ) = part->color;
#else
*( (byte *) bufferofs + dx + ylookup[dy] ) = part->color;
#endif
}
}
}
void DrawParticleTemplate (void)
{
byte pal[768];
viewwidth=320;
viewheight=200;
memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE),768);
VL_NormalizePalette(&pal[0]);
SwitchPalette(&pal[0],35);
VL_ClearBuffer (bufferofs, 255);
DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
}
void DrawAlternateParticleTemplate (void)
{
viewwidth=320;
viewheight=200;
VL_ClearBuffer (bufferofs, 255);
DrawNormalSprite (0, 0, W_GetNumForName("LIFE_C1"));
}
int CountParticles (void)
{
int plane,a,b;
int count;
count=0;
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAREADMAP(plane);
for (a=0;a<200;a++)
{
#ifdef DOS
for (b=0;b<80;b++)
#else
for (b=0;b<320;b++)
#endif
{
if (*((byte *)bufferofs+(a*linewidth)+b)!=255)
count++;
}
}
}
return count;
}
void AssignParticles (void)
{
int plane,a,b;
byte pixel;
ParticleType * part;
part=&Particle[0];
#ifdef DOS
for (plane=0;plane<4;plane++)
#endif
{
VGAREADMAP(plane);
for (a=0;a<200;a++)
{
#ifdef DOS
for (b=0;b<80;b++)
#else
for (b=0;b<320;b++)
#endif
{
pixel = *((byte *)bufferofs+(a*linewidth)+b);
if (pixel!=255)
{
#ifdef DOS
part->endx=plane+(b<<2);
#else
part->endx=b;
#endif
part->endy=a;
part->color=pixel;
part++;
}
}
}
}
}
//******************************************************************************
//
// ParticleIntro
//
//******************************************************************************
void ParticleIntro (void)
{
int i,j;
SetViewSize (MAXVIEWSIZES-1);
numparticles=NUMPARTICLES;
DrawAlternateParticleTemplate ();
// DrawParticleTemplate ();
numparticles=CountParticles ();
InitializeParticles ();
AssignParticles();
// numparticles>>=1;
CalcTics();
CalcTics();
LastScan=0;
for (i=0;i<VBLCOUNTER*15;i+=tics)
{
DrawParticles();
FlipPage();
for (j=0;j<tics;j++)
{
UpdateParticles(0);
}
CalcTics();
if ((LastScan) || IN_GetMouseButtons())
break;;
}
LastScan=0;
for (i=0;i<VBLCOUNTER*15;i+=tics)
{
DrawParticles();
FlipPage();
for (j=0;j<tics;j++)
{
UpdateParticles(1);
}
CalcTics();
if ((LastScan) || IN_GetMouseButtons())
break;;
}
ShutdownParticles ();
}
#endif