?? g_game.c
字號(hào):
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION: none
//
//-----------------------------------------------------------------------------
static const char
rcsid[] = "$Id: g_game.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
#include <string.h>
#include <stdlib.h>
#include "doomdef.h"
#include "doomstat.h"
#include "z_zone.h"
#include "f_finale.h"
#include "m_argv.h"
#include "m_misc.h"
#include "m_menu.h"
#include "m_random.h"
#include "i_system.h"
#include "p_setup.h"
#include "p_saveg.h"
#include "p_tick.h"
#include "d_main.h"
#include "wi_stuff.h"
#include "hu_stuff.h"
#include "st_stuff.h"
#include "am_map.h"
// Needs access to LFB.
#include "v_video.h"
#include "w_wad.h"
#include "p_local.h"
#include "s_sound.h"
// Data.
#include "dstrings.h"
#include "sounds.h"
// SKY handling - still the wrong place.
#include "r_data.h"
#include "r_sky.h"
#include "g_game.h"
#define SAVEGAMESIZE 0x2c000
#define SAVESTRINGSIZE 24
void WriteDebug(char *);
char MsgText[256];
boolean G_CheckDemoStatus (void);
void G_ReadDemoTiccmd (ticcmd_t* cmd);
void G_WriteDemoTiccmd (ticcmd_t* cmd);
void G_PlayerReborn (int player);
void G_InitNew (skill_t skill, int episode, int map);
void G_DoReborn (int playernum);
void G_DoLoadLevel (void);
void G_DoNewGame (void);
void G_DoLoadGame (void);
void G_DoPlayDemo (void);
void G_DoPlayDemo_II(void);
void G_DoCompleted (void);
void G_DoVictory (void);
void G_DoWorldDone (void);
void G_DoSaveGame (void);
gameaction_t gameaction;
gamestate_t gamestate;
skill_t gameskill;
boolean respawnmonsters;
int gameepisode;
int gamemap;
boolean paused;
boolean sendpause; // send a pause event next tic
boolean sendsave; // send a save event next tic
boolean usergame; // ok to save / end game
boolean timingdemo; // if true, exit with report on completion
boolean nodrawers; // for comparative timing purposes
boolean noblit; // for comparative timing purposes
int starttime; // for comparative timing purposes
boolean viewactive;
boolean deathmatch; // only if started as net death
boolean netgame; // only true if packets are broadcast
boolean playeringame[MAXPLAYERS];
player_t players[MAXPLAYERS];
int consoleplayer; // player taking events and displaying
int displayplayer; // view being displayed
int gametic;
int levelstarttic; // gametic at level start
int totalkills, totalitems, totalsecret; // for intermission
char demoname[32];
int demotype;
boolean demorecording;
boolean demoplayback;
boolean netdemo;
byte* demobuffer;
byte* demo_p;
byte* demoend;
boolean singledemo; // quit after playing a demo from cmdline
boolean precache = true; // if true, load all graphics at start
wbstartstruct_t wminfo; // parms for world map / intermission
short consistancy[MAXPLAYERS][BACKUPTICS];
byte* savebuffer;
//
// controls (have defaults)
//
int key_right;
int key_left;
int key_up;
int key_down;
int key_strafeleft;
int key_straferight;
int key_fire;
int key_use;
int key_strafe;
int key_speed;
int key_mvert;
int mousebfire;
int mousebstrafe;
int mousebforward;
int mouseb1;
int mouseb2;
int mouseb3;
int joybfire;
int joybstrafe;
int joybuse;
int joybspeed;
int joyb1;
int joyb2;
int joyb3;
int joyb4;
int always_run;
int swap_stereo;
int mvert;
int keylink;
int link_alt;
#define MAXPLMOVE (forwardmove[1])
#define TURBOTHRESHOLD 0x32
fixed_t forwardmove[2] = {0x19, 0x32};
fixed_t sidemove[2] = {0x18, 0x28};
fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
#define SLOWTURNTICS 6
#define NUMKEYS 256
boolean gamekeydown[NUMKEYS];
int turnheld; // for accelerative turning
boolean mousearray[4];
boolean* mousebuttons = &mousearray[1]; // allow [-1]
// mouse values are used once
int mousex;
int mousey;
int dclicktime;
int dclickstate;
int dclicks;
int dclicktime2;
int dclickstate2;
int dclicks2;
// joystick values are repeated
int joyxmove;
int joyymove;
boolean joyarray[5];
boolean* joybuttons = &joyarray[1]; // allow [-1]
int savegameslot;
char savedescription[32];
#define BODYQUESIZE 32
mobj_t* bodyque[BODYQUESIZE];
int bodyqueslot;
void* statcopy; // for statistics driver
// DQ start addition
extern int gEyePixelOffset;
extern long ScreensYLookup[];
extern BUFFER gRenderBuffer;
// DQ end addition
int G_CmdChecksum (ticcmd_t* cmd)
{
int i;
int sum = 0;
for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++)
sum += ((int *)cmd)[i];
return sum;
}
//
// G_BuildTiccmd
// Builds a ticcmd from all of the available inputs
// or reads it from the demo buffer.
// If recording a demo, write it out
//
void G_BuildTiccmd (ticcmd_t* cmd)
{
int i;
boolean strafe;
boolean bstrafe;
int speed;
int tspeed;
int forward;
ticcmd_t *base;
base = I_BaseTiccmd (); // empty, or external driver
memcpy (cmd,base,sizeof(*cmd));
cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] || joybuttons[joybstrafe];
if ((joybspeed == 31) || (always_run == TRUE))
speed = 1;
else
speed = gamekeydown[key_speed] || joybuttons[joybspeed];
forward = side = 0;
// use two stage accelerative turning on the keyboard and joystick
if (joyxmove < 0 || joyxmove > 0 || gamekeydown[key_right] || gamekeydown[key_left])
turnheld += ticdup;
else
turnheld = 0;
if (turnheld < SLOWTURNTICS)
tspeed = 2; // slow turn
else
tspeed = speed;
// let movement keys cancel each other out
if (strafe)
{
if (gamekeydown[key_right])
{
// fprintf(stderr, "strafe right\n");
side += sidemove[speed];
}
if (gamekeydown[key_left])
{
// fprintf(stderr, "strafe left\n");
side -= sidemove[speed];
}
if (joyxmove > 0)
side += sidemove[speed];
if (joyxmove < 0)
side -= sidemove[speed];
}
else
{
if (gamekeydown[key_right])
cmd->angleturn -= angleturn[tspeed];
if (gamekeydown[key_left])
cmd->angleturn += angleturn[tspeed];
if (joyxmove > 0)
cmd->angleturn -= angleturn[tspeed];
if (joyxmove < 0)
cmd->angleturn += angleturn[tspeed];
}
if (gamekeydown[key_up])
{
// fprintf(stderr, "up\n");
forward += forwardmove[speed];
}
if (gamekeydown[key_down])
{
// fprintf(stderr, "down\n");
forward -= forwardmove[speed];
}
if (joyymove < 0)
forward += forwardmove[speed];
if (joyymove > 0)
forward -= forwardmove[speed];
if (gamekeydown[key_straferight])
side += sidemove[speed];
if (gamekeydown[key_strafeleft])
side -= sidemove[speed];
// buttons
cmd->chatchar = HU_dequeueChatChar();
if (gamekeydown[key_fire] || mousebuttons[mousebfire] || joybuttons[joybfire])
{
cmd->buttons |= BT_ATTACK;
}
if (gamekeydown[key_use] || joybuttons[joybuse] )
{
cmd->buttons |= BT_USE;
// clear double clicks if hit use button
dclicks = 0;
}
// chainsaw overrides
for (i = 0; i < NUMWEAPONS-1; i++)
if (gamekeydown[KEY_1+i])
{
cmd->buttons |= BT_CHANGE;
cmd->buttons |= i<<BT_WEAPONSHIFT;
break;
}
// mouse
if (mousebuttons[mousebforward])
forward += forwardmove[speed];
// forward double click
if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
{
dclickstate = mousebuttons[mousebforward];
if (dclickstate)
dclicks++;
if (dclicks == 2)
{
cmd->buttons |= BT_USE;
dclicks = 0;
}
else
dclicktime = 0;
}
else
{
dclicktime += ticdup;
if (dclicktime > 20)
{
dclicks = 0;
dclickstate = 0;
}
}
// strafe double click
bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe];
if (bstrafe != dclickstate2 && dclicktime2 > 1 )
{
dclickstate2 = bstrafe;
if (dclickstate2)
dclicks2++;
if (dclicks2 == 2)
{
cmd->buttons |= BT_USE;
dclicks2 = 0;
}
else
dclicktime2 = 0;
}
else
{
dclicktime2 += ticdup;
if (dclicktime2 > 20)
{
dclicks2 = 0;
dclickstate2 = 0;
}
}
forward += mousey;
if (strafe)
side += mousex*2;
else
cmd->angleturn -= mousex*0x8;
mousex = mousey = 0;
if (forward > MAXPLMOVE)
forward = MAXPLMOVE;
else
if (forward < -MAXPLMOVE)
forward = -MAXPLMOVE;
if (side > MAXPLMOVE)
side = MAXPLMOVE;
else
if (side < -MAXPLMOVE)
side = -MAXPLMOVE;
cmd->forwardmove += forward;
cmd->sidemove += side;
// special buttons
if (sendpause)
{
sendpause = false;
cmd->buttons = BT_SPECIAL | BTS_PAUSE;
}
if (sendsave)
{
sendsave = false;
cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT);
}
}
//
// G_DoLoadLevel
//
extern gamestate_t wipegamestate;
void G_DoLoadLevel (void)
{
int i;
BUFFER TempBuffer;
// Set the sky map.
// First thing, we have a dummy sky texture name,
// a flat. The data is in the WAD only because
// we look for an actual index, instead of simply
// setting one.
skyflatnum = R_FlatNumForName ( SKYFLATNAME );
// DOOM determines the sky texture to be used
// depending on the current episode, and the game version.
if ( (gamemode == commercial) // Doom II
|| ( gamemode == addon_tnt )
|| ( gamemode == addon_plut ) )
{
skytexture = R_TextureNumForName ("SKY3");
if (gamemap < 12)
skytexture = R_TextureNumForName ("SKY1");
else
if (gamemap < 21)
skytexture = R_TextureNumForName ("SKY2");
//WriteDebug("Sky set...\n");
}
levelstarttic = gametic; // for time calculation
if (wipegamestate == GS_LEVEL)
wipegamestate = -1; // force a wipe
gamestate = GS_LEVEL;
for (i=0 ; i<MAXPLAYERS ; i++)
{
if (playeringame[i] && players[i].playerstate == PST_DEAD)
players[i].playerstate = PST_REBORN;
memset (players[i].frags,0,sizeof(players[i].frags));
}
//WriteDebug("P_SetupLevel\n");
P_SetupLevel (gameepisode, gamemap, 0, gameskill);
displayplayer = consoleplayer; // view the guy you are playing
starttime = I_GetTime ();
gameaction = ga_nothing;
//WriteDebug("Z_CheckHeap\n");
Z_CheckHeap ();
// clear cmd building stuff
memset (gamekeydown, 0, sizeof(gamekeydown));
joyxmove = joyymove = 0;
mousex = mousey = 0;
sendpause = sendsave = paused = false;
memset (mousebuttons, 0, sizeof(mousebuttons));
memset (joybuttons, 0, sizeof(joybuttons));
//WriteDebug("G_DoLoadLevel done\n");
TempBuffer.Buffer = screens[1]; // DQ - background screens
TempBuffer.YLookup = ScreensYLookup; // DQ
R_FillBackScreen(&TempBuffer/*DQ*/);
}
//
// G_Responder
// Get info needed to make ticcmd_ts for the players.
//
boolean G_Responder(event_t* ev)
{
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown && ev->data1 == KEY_F12 && (singledemo || !deathmatch))
{
// spy mode
do
{
displayplayer++;
if (displayplayer == MAXPLAYERS)
displayplayer = 0;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -