/* =========================================================================== Copyright (C) 1999 - 2005, Id Software, Inc. Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2005 - 2015, ioquake3 contributors Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =========================================================================== */ #ifndef __Q_SHARED_H #define __Q_SHARED_H // q_shared.h -- included first by ALL program modules. // A user mod should never modify this file #include "qcommon/q_math.h" #include "qcommon/q_color.h" #include "qcommon/q_string.h" #ifdef _MSC_VER #pragma warning(disable : 4018) // signed/unsigned mismatch //#pragma warning(disable : 4032) //formal parameter 'number' has different type when promoted //#pragma warning(disable : 4051) //type conversion; possible loss of data //#pragma warning(disable : 4057) // slightly different base types #pragma warning(disable : 4100) // unreferenced formal parameter //#pragma warning(disable : 4115) //'type' : named type definition in parentheses #pragma warning(disable : 4125) // decimal digit terminates octal escape sequence #pragma warning(disable : 4127) // conditional expression is constant //#pragma warning(disable : 4136) //conversion between different floating-point types //#pragma warning(disable : 4201) //nonstandard extension used : nameless struct/union //#pragma warning(disable : 4214) //nonstandard extension used : bit field types other than int //#pragma warning(disable : 4220) // varargs matches remaining parameters #pragma warning(disable : 4244) //'conversion' conversion from 'type1' to 'type2', possible loss of data #pragma warning(disable : 4284) // return type not UDT //#pragma warning(disable : 4305) // truncation from const double to float #pragma warning(disable : 4310) // cast truncates constant value #pragma warning(disable : 4514) //unreferenced inline/local function has been removed #pragma warning(disable : 4710) // not inlined #pragma warning(disable : 4711) // selected for automatic inline expansion #pragma warning(disable : 4786) // identifier was truncated #pragma warning(disable : 5208) // unnamed class used in typedef name cannot declare members other than non-static data members, member enumerations, or member classes #pragma warning(disable : 4996) // This function or variable may be unsafe. #endif //rww - conveniently toggle "gore" code, for model decals and stuff. #ifndef JK2_MODE #define _G2_GORE #endif // !JK2_MODE #if JK2_MODE #define PRODUCT_NAME "openjo_sp" #define CLIENT_WINDOW_TITLE "OpenJO (SP)" #define CLIENT_CONSOLE_TITLE "OpenJO Console (SP)" #define HOMEPATH_NAME_UNIX "openjo" #define HOMEPATH_NAME_WIN "OpenJO" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN #else #define PRODUCT_NAME "openjk_sp" #define CLIENT_WINDOW_TITLE "OpenJK (SP)" #define CLIENT_CONSOLE_TITLE "OpenJK Console (SP)" #define HOMEPATH_NAME_UNIX "openjk" #define HOMEPATH_NAME_WIN "OpenJK" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN #endif #define BASEGAME "base" #define OPENJKGAME "OpenJK" #define Q3CONFIG_NAME PRODUCT_NAME ".cfg" #define BASE_SAVE_COMPAT // this is defined to disable/fix some changes that break save compatibility #define VALIDSTRING( a ) ( ( a != NULL ) && ( a[0] != '\0' ) ) //JAC: Added #define ARRAY_LEN( x ) ( sizeof( x ) / sizeof( *(x) ) ) #define STRING( a ) #a #define XSTRING( a ) STRING( a ) #ifndef FINAL_BUILD #ifdef _WIN32 #define G2_PERFORMANCE_ANALYSIS #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus #include #endif //Ignore __attribute__ on non-gcc platforms #if !defined(__GNUC__) && !defined(__attribute__) #define __attribute__(x) #endif #if defined(__GNUC__) #define UNUSED_VAR __attribute__((unused)) #else #define UNUSED_VAR #endif #if (defined _MSC_VER) #define Q_EXPORT __declspec(dllexport) #elif (defined __SUNPRO_C) #define Q_EXPORT __global #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun)) #define Q_EXPORT __attribute__((visibility("default"))) #else #define Q_EXPORT #endif // this is the define for determining if we have an asm version of a C function #if (defined(_M_IX86) || defined(__i386__)) && !defined(__sun__) #define id386 1 #else #define id386 0 #endif #if (defined(powerc) || defined(powerpc) || defined(ppc) || defined(__ppc) || defined(__ppc__)) && !defined(C_ONLY) #define idppc 1 #else #define idppc 0 #endif #include "qcommon/q_platform.h" #include "ojk_saved_game_helper_fwd.h" // ================================================================ // TYPE DEFINITIONS // ================================================================ typedef int32_t qhandle_t, thandle_t, fxHandle_t, sfxHandle_t, fileHandle_t, clipHandle_t; #define NULL_HANDLE ((qhandle_t)0) #define NULL_SOUND ((sfxHandle_t)0) #define NULL_FX ((fxHandle_t)0) #define NULL_SFX ((sfxHandle_t)0) #define NULL_FILE ((fileHandle_t)0) #define NULL_CLIP ((clipHandle_t)0) #define PAD(base, alignment) (((base)+(alignment)-1) & ~((alignment)-1)) #define PADLEN(base, alignment) (PAD((base), (alignment)) - (base)) #define PADP(base, alignment) ((void *) PAD((intptr_t) (base), (alignment))) #ifdef __GNUC__ #define QALIGN(x) __attribute__((aligned(x))) #else #define QALIGN(x) #endif #ifndef NULL // NOTE: This is all c++ so casting to void * is wrong #define NULL ((void *)0) #endif #define INT_ID( a, b, c, d ) (uint32_t)((((a) & 0xff) << 24) | (((b) & 0xff) << 16) | (((c) & 0xff) << 8) | ((d) & 0xff)) // the game guarantees that no string from the network will ever // exceed MAX_STRING_CHARS #define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString #define MAX_STRING_TOKENS 1024 // max tokens resulting from Cmd_TokenizeString #define MAX_TOKEN_CHARS 1024 // max length of an individual token #define MAX_INFO_STRING 1024 #define MAX_INFO_KEY 1024 #define MAX_INFO_VALUE 1024 #define BIG_INFO_STRING 8192 // used for system info key only #define BIG_INFO_KEY 8192 #define BIG_INFO_VALUE 8192 #define MAX_QPATH 64 // max length of a quake game pathname #ifdef PATH_MAX #define MAX_OSPATH PATH_MAX #else #define MAX_OSPATH 256 // max length of a filesystem pathname #endif #define MAX_NAME_LENGTH 32 // max length of a client name // paramters for command buffer stuffing typedef enum { EXEC_NOW, // don't return until completed, a VM should NEVER use this, // because some commands might cause the VM to be unloaded... EXEC_INSERT, // insert at current position, but don't run yet EXEC_APPEND // add to end of the command buffer (normal case) } cbufExec_t; // // these aren't needed by any of the VMs. put in another header? // #define MAX_MAP_AREA_BYTES 32 // bit vector of area visibility // Light Style Constants #define LS_STYLES_START 0 #define LS_NUM_STYLES 32 #define LS_SWITCH_START (LS_STYLES_START+LS_NUM_STYLES) #define LS_NUM_SWITCH 32 #define MAX_LIGHT_STYLES 64 // print levels from renderer (FIXME: set up for game / cgame?) typedef enum { PRINT_ALL, PRINT_DEVELOPER, // only print when "developer 1" PRINT_WARNING, PRINT_ERROR } printParm_t; // parameters to the main Error routine typedef enum { ERR_FATAL, // exit the entire game with a popup window ERR_DROP, // print to console and disconnect from game ERR_DISCONNECT, // don't kill server } errorParm_t; // font rendering values used by ui and cgame #define PROP_GAP_WIDTH 2 // 3 #define PROP_SPACE_WIDTH 4 #define PROP_HEIGHT 16 #define PROP_TINY_SIZE_SCALE 1 #define PROP_SMALL_SIZE_SCALE 1 #define PROP_BIG_SIZE_SCALE 1 #define PROP_GIANT_SIZE_SCALE 2 #define PROP_TINY_HEIGHT 10 #define PROP_GAP_TINY_WIDTH 1 #define PROP_SPACE_TINY_WIDTH 3 #define PROP_BIG_HEIGHT 24 #define PROP_GAP_BIG_WIDTH 3 #define PROP_SPACE_BIG_WIDTH 6 #define BLINK_DIVISOR 600 #define PULSE_DIVISOR 75 #define UI_LEFT 0x00000000 // default #define UI_CENTER 0x00000001 #define UI_RIGHT 0x00000002 #define UI_FORMATMASK 0x00000007 #define UI_SMALLFONT 0x00000010 #define UI_BIGFONT 0x00000020 // default #define UI_DROPSHADOW 0x00000800 #define UI_BLINK 0x00001000 #define UI_INVERSE 0x00002000 #define UI_PULSE 0x00004000 #define Com_Memset memset #define Com_Memcpy memcpy // stuff for TA's ROQ cinematic code... // #define CIN_system 1 #define CIN_loop 2 #define CIN_hold 4 #define CIN_silent 8 #define CIN_shader 16 // all drawing is done to a 640*480 virtual screen size // and will be automatically scaled to the real resolution #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define TINYCHAR_WIDTH (SMALLCHAR_WIDTH) #define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2) #define SMALLCHAR_WIDTH 8 #define SMALLCHAR_HEIGHT 16 #define BIGCHAR_WIDTH 16 #define BIGCHAR_HEIGHT 16 #define GIANTCHAR_WIDTH 32 #define GIANTCHAR_HEIGHT 48 // Player weapons effects typedef enum { SABER_RED, SABER_ORANGE, SABER_YELLOW, SABER_GREEN, SABER_BLUE, SABER_PURPLE } saber_colors_t; #define MAX_BATTERIES 2500 #define ENUM2STRING(arg) { #arg,arg } //============================================= char *COM_SkipPath( char *pathname ); const char *COM_GetExtension( const char *name ); void COM_StripExtension( const char *in, char *out, int destsize ); qboolean COM_CompareExtension(const char *in, const char *ext); void COM_DefaultExtension( char *path, int maxSize, const char *extension ); //JLFCALLOUT include MPNOTUSED void COM_BeginParseSession( void ); void COM_EndParseSession( void ); // For compatibility with shared code QINLINE void COM_BeginParseSession( const char *sessionName ) { COM_BeginParseSession(); } class COM_ParseSession { public: COM_ParseSession() { COM_BeginParseSession(); }; ~COM_ParseSession() { COM_EndParseSession(); }; }; int COM_GetCurrentParseLine( void ); char *COM_Parse( const char **data_p ); char *COM_ParseExt( const char **data_p, qboolean allowLineBreak ); int COM_Compress( char *data_p ); qboolean COM_ParseString( const char **data, const char **s ); qboolean COM_ParseInt( const char **data, int *i ); qboolean COM_ParseFloat( const char **data, float *f ); qboolean COM_ParseVec4( const char **buffer, vec4_t *c); // data is an in/out parm, returns a parsed out token void COM_MatchToken( char**buf_p, char *match ); void SkipBracedSection (const char **program); void SkipRestOfLine ( const char **data ); void Parse1DMatrix (const char **buf_p, int x, float *m); void Parse2DMatrix (const char **buf_p, int y, int x, float *m); void Parse3DMatrix (const char **buf_p, int z, int y, int x, float *m); int Com_HexStrToInt( const char *str ); int QDECL Com_sprintf (char *dest, int size, const char *fmt, ...); char *Com_SkipTokens( char *s, int numTokens, char *sep ); char *Com_SkipCharset( char *s, char *sep ); // mode parm for FS_FOpenFile typedef enum { FS_READ, FS_WRITE, FS_APPEND, FS_APPEND_SYNC } fsMode_t; typedef enum { FS_SEEK_CUR, FS_SEEK_END, FS_SEEK_SET } fsOrigin_t; //============================================= char * QDECL va(const char *format, ...); #define TRUNCATE_LENGTH 64 void Com_TruncateLongString( char *buffer, const char *s ); //============================================= // // key / value info strings // const char *Info_ValueForKey( const char *s, const char *key ); void Info_RemoveKey( char *s, const char *key ); void Info_SetValueForKey( char *s, const char *key, const char *value ); qboolean Info_Validate( const char *s ); void Info_NextPair( const char **s, char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ); // this is only here so the functions in q_shared.c and bg_*.c can link void NORETURN QDECL Com_Error( int level, const char *error, ... ); void QDECL Com_Printf( const char *msg, ... ); /* ========================================================== CVARS (console variables) Many variables can be used for cheating purposes, so when cheats is zero, force all unspecified variables to their default values. ========================================================== */ #define CVAR_TEMP 0 // can be set even when cheats are disabled, but is not archived #define CVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc // used for system variables, not for player // specific configurations #define CVAR_USERINFO 2 // sent to server on connect or change #define CVAR_SERVERINFO 4 // sent in response to front end requests #define CVAR_SYSTEMINFO 8 // these cvars will be duplicated on all clients #define CVAR_INIT 16 // don't allow change from console at all, // but can be set from the command line #define CVAR_LATCH 32 // will only change when C code next does // a Cvar_Get(), so it can't be changed // without proper initialization. modified // will be set, even though the value hasn't // changed yet #define CVAR_ROM 64 // display only, cannot be set by user at all #define CVAR_USER_CREATED 128 // created by a set command #define CVAR_SAVEGAME 256 // store this in the savegame #define CVAR_CHEAT 512 // can not be changed if cheats are disabled #define CVAR_NORESTART 1024 // do not clear when a cvar_restart is issued #define CVAR_SERVER_CREATED 2048 // cvar was created by a server the client connected to. #define CVAR_VM_CREATED 4096 // cvar was created exclusively in one of the VMs. #define CVAR_PROTECTED 8192 // prevent modifying this var from VMs or the server #define CVAR_NODEFAULT 16384 // do not write to config if matching with default value #define CVAR_ARCHIVE_ND (CVAR_ARCHIVE | CVAR_NODEFAULT) // These flags are only returned by the Cvar_Flags() function #define CVAR_MODIFIED 0x40000000 // Cvar was modified #define CVAR_NONEXISTENT 0x80000000 // Cvar doesn't exist. // nothing outside the Cvar_*() functions should modify these fields! typedef struct cvar_s { char *name; char *string; char *resetString; // cvar_restart will reset to this value char *latchedString; // for CVAR_LATCH vars int flags; qboolean modified; // set each time the cvar is changed int modificationCount; // incremented each time the cvar is changed float value; // atof( string ) int integer; // atoi( string ) qboolean validate; qboolean integral; float min; float max; struct cvar_s *next; struct cvar_s *prev; struct cvar_s *hashNext; struct cvar_s *hashPrev; int hashIndex; } cvar_t; #define MAX_CVAR_VALUE_STRING 256 typedef int cvarHandle_t; // the modules that run in the virtual machine can't access the cvar_t directly, // so they must ask for structured updates typedef struct { cvarHandle_t handle; int modificationCount; float value; int integer; char string[MAX_CVAR_VALUE_STRING]; } vmCvar_t; /* ============================================================== COLLISION DETECTION ============================================================== */ #include "../game/surfaceflags.h" // shared with the q3map utility /* Ghoul2 Insert Start */ #if !defined(GHOUL2_SHARED_H_INC) #include "../game/ghoul2_shared.h" //for CGhoul2Info_v #endif /* Ghoul2 Insert End */ #define MAX_G2_COLLISIONS 64 // a trace is returned when a box is swept through the world typedef struct { qboolean allsolid; // if true, plane is not valid qboolean startsolid; // if true, the initial point was in a solid area float fraction; // time completed, 1.0 = didn't hit anything vec3_t endpos; // final position cplane_t plane; // surface normal at impact, transformed to world space int surfaceFlags; // surface hit int contents; // contents on other side of surface hit int entityNum; // entity the contacted sirface is a part of /* Ghoul2 Insert Start */ CCollisionRecord G2CollisionMap[MAX_G2_COLLISIONS]; // map that describes all of the parts of ghoul2 models that got hit /* Ghoul2 Insert End */ void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(allsolid); saved_game.write(startsolid); saved_game.write(fraction); saved_game.write(endpos); saved_game.write<>(plane); saved_game.write(surfaceFlags); saved_game.write(contents); saved_game.write(entityNum); saved_game.write<>(G2CollisionMap); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(allsolid); saved_game.read(startsolid); saved_game.read(fraction); saved_game.read(endpos); saved_game.read<>(plane); saved_game.read(surfaceFlags); saved_game.read(contents); saved_game.read(entityNum); saved_game.read<>(G2CollisionMap); } } trace_t; // trace->entityNum can also be 0 to (MAX_GENTITIES-1) // or ENTITYNUM_NONE, ENTITYNUM_WORLD // markfragments are returned by CM_MarkFragments() typedef struct { int firstPoint; int numPoints; } markFragment_t; typedef struct { vec3_t origin; vec3_t axis[3]; } orientation_t; //===================================================================== // in order from highest priority to lowest // if none of the catchers are active, bound key strings will be executed #define KEYCATCH_CONSOLE 1 #define KEYCATCH_UI 2 // sound channels // channel 0 never willingly overrides // other channels will allways override a playing sound on that channel #include "../game/channels.h" /* ======================================================================== ELEMENTS COMMUNICATED ACROSS THE NET ======================================================================== */ #define ANGLE2SHORT(x) ((int)((x)*65536/360) & 65535) #define SHORT2ANGLE(x) ((x)*(360.0f/65536)) #define SNAPFLAG_RATE_DELAYED 1 #define SNAPFLAG_NOT_ACTIVE 2 // snapshot used during connection and for zombies #define SNAPFLAG_SERVERCOUNT 4 // toggled every map_restart so transitions can be detected // // per-level limits // #define MAX_CLIENTS 1 // 128 // absolute limit #define MAX_TERRAINS 1 //32 #define GENTITYNUM_BITS 10 // don't need to send any more #define MAX_GENTITIES (1< MAX_CONFIGSTRINGS #error overflow: (CS_MAX) > MAX_CONFIGSTRINGS #endif #define MAX_GAMESTATE_CHARS 16000 typedef struct { int stringOffsets[MAX_CONFIGSTRINGS]; char stringData[MAX_GAMESTATE_CHARS]; int dataCount; } gameState_t; typedef enum { FP_FIRST = 0,//marker FP_HEAL = 0,//instant FP_LEVITATION,//hold/duration FP_SPEED,//duration FP_PUSH,//hold/duration FP_PULL,//hold/duration FP_TELEPATHY,//instant FP_GRIP,//hold/duration FP_LIGHTNING,//hold/duration FP_SABERTHROW, FP_SABER_DEFENSE, FP_SABER_OFFENSE, #ifndef JK2_MODE //new Jedi Academy powers FP_RAGE,//duration - speed, invincibility and extra damage for short period, drains your health and leaves you weak and slow afterwards. FP_PROTECT,//duration - protect against physical/energy (level 1 stops blaster/energy bolts, level 2 stops projectiles, level 3 protects against explosions) FP_ABSORB,//duration - protect against dark force powers (grip, lightning, drain - maybe push/pull, too?) FP_DRAIN,//hold/duration - drain force power for health FP_SEE,//duration - detect/see hidden enemies #endif // !JK2_MODE NUM_FORCE_POWERS } forcePowers_t; typedef enum { ST_NONE = -1, // Used to indicate no active selection (rather than type) ST_WEAPON, ST_GADGET, ST_FIGHTING_STYLE, ST_FORCE_POWER, ST_QUICK_MENU } selectorType_t; typedef enum { SABER_NONE = 0, SABER_SINGLE, SABER_STAFF, SABER_DAGGER, SABER_BROAD, SABER_PRONG, SABER_ARC, SABER_SAI, SABER_CLAW, SABER_LANCE, SABER_STAR, SABER_TRIDENT, SABER_SITH_SWORD, NUM_SABERS } saberType_t; //========================================================= // bit field limits #define MAX_STATS 16 // NOTE!!! be careful about altering this because although it's used to define an array size, the entry indexes come from // the typedef'd enum "persEnum_t" in bg_public.h, and there's no compile-tie between the 2 -slc // #define MAX_PERSISTANT 16 #define MAX_POWERUPS 16 #define MAX_WEAPONS 32 #define MAX_AMMO 10 #define MAX_INVENTORY 15 // See INV_MAX #define MAX_SECURITY_KEYS 5 #define MAX_SECURITY_KEY_MESSSAGE 24 #define MAX_PS_EVENTS 2 // this must be a power of 2 unless you change some &'s to %'s -ste #define MAX_WORLD_COORD ( 64*1024 ) #define MIN_WORLD_COORD ( -64*1024 ) #define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD ) typedef enum { WHL_NONE, WHL_ANKLES, WHL_KNEES, WHL_WAIST, WHL_TORSO, WHL_SHOULDERS, WHL_HEAD, WHL_UNDER } waterHeightLevel_t; // !!!!!!! loadsave affecting struct !!!!!!! typedef struct { // Actual trail stuff int inAction; // controls whether should we even consider starting one int duration; // how long each trail seg stays in existence int lastTime; // time a saber segement was last stored vec3_t base; vec3_t tip; // Marks stuff qboolean haveOldPos[2]; vec3_t oldPos[2]; vec3_t oldNormal[2]; // store this in case we don't have a connect-the-dots situation // ..then we'll need the normal to project a mark blob onto the impact point void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(inAction); saved_game.write(duration); saved_game.write(lastTime); saved_game.write(base); saved_game.write(tip); saved_game.write(haveOldPos); saved_game.write(oldPos); saved_game.write(oldNormal); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(inAction); saved_game.read(duration); saved_game.read(lastTime); saved_game.read(base); saved_game.read(tip); saved_game.read(haveOldPos); saved_game.read(oldPos); saved_game.read(oldNormal); } } saberTrail_t; #define MAX_SABER_TRAIL_SEGS 8 // !!!!!!!!!!!!! loadsave affecting struct !!!!!!!!!!!!!!! typedef struct { qboolean active; saber_colors_t color; float radius; float length; float lengthMax; float lengthOld; vec3_t muzzlePoint; vec3_t muzzlePointOld; vec3_t muzzleDir; vec3_t muzzleDirOld; saberTrail_t trail; void ActivateTrail ( float duration ) { trail.inAction = qtrue; trail.duration = duration; }; void DeactivateTrail ( float duration ) { trail.inAction = qfalse; trail.duration = duration; }; void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(active); saved_game.write(color); saved_game.write(radius); saved_game.write(length); saved_game.write(lengthMax); saved_game.write(lengthOld); saved_game.write(muzzlePoint); saved_game.write(muzzlePointOld); saved_game.write(muzzleDir); saved_game.write(muzzleDirOld); saved_game.write<>(trail); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(active); saved_game.read(color); saved_game.read(radius); saved_game.read(length); saved_game.read(lengthMax); saved_game.read(lengthOld); saved_game.read(muzzlePoint); saved_game.read(muzzlePointOld); saved_game.read(muzzleDir); saved_game.read(muzzleDirOld); saved_game.read<>(trail); } } bladeInfo_t; #define MAX_BLADES 8 typedef enum { SS_NONE = 0, SS_FAST, SS_MEDIUM, SS_STRONG, SS_DESANN, SS_TAVION, SS_DUAL, SS_STAFF, SS_NUM_SABER_STYLES } saber_styles_t; //SABER FLAGS //Old bools converted to a flag now #define SFL_NOT_LOCKABLE (1<<0)//can't get into a saberlock #define SFL_NOT_THROWABLE (1<<1)//can't be thrown - FIXME: maybe make this a max level of force saber throw that can be used with this saber? #define SFL_NOT_DISARMABLE (1<<2)//can't be dropped #define SFL_NOT_ACTIVE_BLOCKING (1<<3)//don't to try to block incoming shots with this saber #define SFL_TWO_HANDED (1<<4)//uses both hands #define SFL_SINGLE_BLADE_THROWABLE (1<<5)//can throw this saber if only the first blade is on #define SFL_RETURN_DAMAGE (1<<6)//when returning from a saber throw, it keeps spinning and doing damage //NEW FLAGS #define SFL_ON_IN_WATER (1<<7)//if set, weapon stays active even in water #define SFL_BOUNCE_ON_WALLS (1<<8)//if set, the saber will bounce back when it hits solid architecture (good for real-sword type mods) #define SFL_BOLT_TO_WRIST (1<<9)//if set, saber model is bolted to wrist, not in hand... useful for things like claws & shields, etc. //#define SFL_STICK_ON_IMPACT (1<= numBlades ) return; blade[iBlade].active = bActive; } qboolean Active() { for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].active ) { return qtrue; } } return qfalse; } qboolean ActiveManualOnly() { for ( int i = 0; i < numBlades; i++ ) { if ( bladeStyle2Start > 0 ) { if ( i >= bladeStyle2Start ) { if ( (saberFlags2&SFL2_NO_MANUAL_DEACTIVATE2) ) {//don't count this blade continue; } } else if ( (saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) ) {//don't count this blade continue; } } else if ( (saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) ) {//don't count any of these blades! continue; } else if ( blade[i].active ) { return qtrue; } } return qfalse; } void SetLength( float length ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].length = length; } } float Length() {//return largest length float len1 = 0; for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].length > len1 ) { len1 = blade[i].length; } } return len1; }; float LengthMax() { float len1 = 0; for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].lengthMax > len1 ) { len1 = blade[i].lengthMax; } } return len1; }; void ActivateTrail ( float duration ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].ActivateTrail( duration ); } }; void DeactivateTrail ( float duration ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].DeactivateTrail( duration ); } }; void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(name); saved_game.write(fullName); saved_game.write(type); saved_game.write(model); saved_game.write(skin); saved_game.write(soundOn); saved_game.write(soundLoop); saved_game.write(soundOff); saved_game.write(numBlades); saved_game.write<>(blade); saved_game.write(stylesLearned); saved_game.write(stylesForbidden); saved_game.write(maxChain); saved_game.write(forceRestrictions); saved_game.write(lockBonus); saved_game.write(parryBonus); saved_game.write(breakParryBonus); saved_game.write(breakParryBonus2); saved_game.write(disarmBonus); saved_game.write(disarmBonus2); saved_game.write(singleBladeStyle); saved_game.write(brokenSaber1); saved_game.write(brokenSaber2); saved_game.write(saberFlags); saved_game.write(saberFlags2); saved_game.write(spinSound); saved_game.write(swingSound); saved_game.write(fallSound); saved_game.write(moveSpeedScale); saved_game.write(animSpeedScale); saved_game.write(kataMove); saved_game.write(lungeAtkMove); saved_game.write(jumpAtkUpMove); saved_game.write(jumpAtkFwdMove); saved_game.write(jumpAtkBackMove); saved_game.write(jumpAtkRightMove); saved_game.write(jumpAtkLeftMove); saved_game.write(readyAnim); saved_game.write(drawAnim); saved_game.write(putawayAnim); saved_game.write(tauntAnim); saved_game.write(bowAnim); saved_game.write(meditateAnim); saved_game.write(flourishAnim); saved_game.write(gloatAnim); saved_game.write(bladeStyle2Start); saved_game.write(trailStyle); saved_game.write(g2MarksShader); saved_game.write(g2WeaponMarkShader); saved_game.write(hitSound); saved_game.write(blockSound); saved_game.write(bounceSound); saved_game.write(blockEffect); saved_game.write(hitPersonEffect); saved_game.write(hitOtherEffect); saved_game.write(bladeEffect); saved_game.write(knockbackScale); saved_game.write(damageScale); saved_game.write(splashRadius); saved_game.write(splashDamage); saved_game.write(splashKnockback); saved_game.write(trailStyle2); saved_game.write(g2MarksShader2); saved_game.write(g2WeaponMarkShader2); saved_game.write(hit2Sound); saved_game.write(block2Sound); saved_game.write(bounce2Sound); saved_game.write(blockEffect2); saved_game.write(hitPersonEffect2); saved_game.write(hitOtherEffect2); saved_game.write(bladeEffect2); saved_game.write(knockbackScale2); saved_game.write(damageScale2); saved_game.write(splashRadius2); saved_game.write(splashDamage2); saved_game.write(splashKnockback2); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(name); saved_game.read(fullName); saved_game.read(type); saved_game.read(model); model = NULL; saved_game.read(skin); saved_game.read(soundOn); saved_game.read(soundLoop); saved_game.read(soundOff); saved_game.read(numBlades); saved_game.read<>(blade); saved_game.read(stylesLearned); saved_game.read(stylesForbidden); saved_game.read(maxChain); saved_game.read(forceRestrictions); saved_game.read(lockBonus); saved_game.read(parryBonus); saved_game.read(breakParryBonus); saved_game.read(breakParryBonus2); saved_game.read(disarmBonus); saved_game.read(disarmBonus2); saved_game.read(singleBladeStyle); saved_game.read(brokenSaber1); saved_game.read(brokenSaber2); saved_game.read(saberFlags); saved_game.read(saberFlags2); saved_game.read(spinSound); saved_game.read(swingSound); saved_game.read(fallSound); saved_game.read(moveSpeedScale); saved_game.read(animSpeedScale); saved_game.read(kataMove); saved_game.read(lungeAtkMove); saved_game.read(jumpAtkUpMove); saved_game.read(jumpAtkFwdMove); saved_game.read(jumpAtkBackMove); saved_game.read(jumpAtkRightMove); saved_game.read(jumpAtkLeftMove); saved_game.read(readyAnim); saved_game.read(drawAnim); saved_game.read(putawayAnim); saved_game.read(tauntAnim); saved_game.read(bowAnim); saved_game.read(meditateAnim); saved_game.read(flourishAnim); saved_game.read(gloatAnim); saved_game.read(bladeStyle2Start); saved_game.read(trailStyle); saved_game.read(g2MarksShader); saved_game.read(g2WeaponMarkShader); saved_game.read(hitSound); saved_game.read(blockSound); saved_game.read(bounceSound); saved_game.read(blockEffect); saved_game.read(hitPersonEffect); saved_game.read(hitOtherEffect); saved_game.read(bladeEffect); saved_game.read(knockbackScale); saved_game.read(damageScale); saved_game.read(splashRadius); saved_game.read(splashDamage); saved_game.read(splashKnockback); saved_game.read(trailStyle2); saved_game.read(g2MarksShader2); saved_game.read(g2WeaponMarkShader2); saved_game.read(hit2Sound); saved_game.read(block2Sound); saved_game.read(bounce2Sound); saved_game.read(blockEffect2); saved_game.read(hitPersonEffect2); saved_game.read(hitOtherEffect2); saved_game.read(bladeEffect2); saved_game.read(knockbackScale2); saved_game.read(damageScale2); saved_game.read(splashRadius2); saved_game.read(splashDamage2); saved_game.read(splashKnockback2); } } saberInfo_t; //NOTE: Below is the *retail* version of the saberInfo_t structure - it is ONLY used for loading retail-version savegames (we load the savegame into this smaller structure, then copy each field into the appropriate field in the new structure - see SG_ConvertRetailSaberinfoToNewSaberinfo() class saberInfoRetail_t { public: char *name; //entry in sabers.cfg, if any char *fullName; //the "Proper Name" of the saber, shown in the UI saberType_t type; //none, single or staff char *model; //hilt model char *skin; //hilt custom skin int soundOn; //game soundindex for turning on sound int soundLoop; //game soundindex for hum/loop sound int soundOff; //game soundindex for turning off sound int numBlades; bladeInfo_t blade[MAX_BLADES]; //blade info - like length, trail, origin, dir, etc. saber_styles_t style; //locked style to use, if any int maxChain; //how many moves can be chained in a row with this weapon (-1 is infinite, 0 is use default behavior) qboolean lockable; //can get into a saberlock qboolean throwable; //whether or not this saber can be thrown - FIXME: maybe make this a max level of force saber throw that can be used with this saber? qboolean disarmable; //whether or not this saber can be dropped qboolean activeBlocking; //whether or not to try to block incoming shots with this saber qboolean twoHanded; //uses both hands int forceRestrictions; //force powers that cannot be used while this saber is on (bitfield) - FIXME: maybe make this a limit on the max level, per force power, that can be used with this type? int lockBonus; //in saberlocks, this type of saber pushes harder or weaker int parryBonus; //added to strength of parry with this saber int breakParryBonus; //added to strength when hit a parry int disarmBonus; //added to disarm chance when win saberlock or have a good parry (knockaway) saber_styles_t singleBladeStyle; //makes it so that you use a different style if you only have the first blade active qboolean singleBladeThrowable; //makes it so that you can throw this saber if only the first blade is on char *brokenSaber1; //if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your right hand char *brokenSaber2; //if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your left hand qboolean returnDamage; //when returning from a saber throw, it keeps spinning and doing damage void Activate( void ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].active = qtrue; } }; void Deactivate( void ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].active = qfalse; } }; // Description: Activate a specific Blade of this Saber. // Created: 10/03/02 by Aurelio Reis, Modified: 10/03/02 by Aurelio Reis. // [in] int iBlade Which Blade to activate. // [in] bool bActive Whether to activate it (default true), or deactivate it (false). // [return] void void BladeActivate( int iBlade, qboolean bActive = qtrue ) { // Validate blade ID/Index. if ( iBlade < 0 || iBlade >= numBlades ) return; blade[iBlade].active = bActive; } qboolean Active() { for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].active ) { return qtrue; } } return qfalse; } void SetLength( float length ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].length = length; } } float Length() {//return largest length float len1 = 0; for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].length > len1 ) { len1 = blade[i].length; } } return len1; }; float LengthMax() { float len1 = 0; for ( int i = 0; i < numBlades; i++ ) { if ( blade[i].lengthMax > len1 ) { len1 = blade[i].lengthMax; } } return len1; }; void ActivateTrail ( float duration ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].ActivateTrail( duration ); } }; void DeactivateTrail ( float duration ) { for ( int i = 0; i < numBlades; i++ ) { blade[i].DeactivateTrail( duration ); } }; void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(name); saved_game.write(fullName); saved_game.write(type); saved_game.write(model); saved_game.write(skin); saved_game.write(soundOn); saved_game.write(soundLoop); saved_game.write(soundOff); saved_game.write(numBlades); saved_game.write<>(blade); saved_game.write(style); saved_game.write(maxChain); saved_game.write(lockable); saved_game.write(throwable); saved_game.write(disarmable); saved_game.write(activeBlocking); saved_game.write(twoHanded); saved_game.write(forceRestrictions); saved_game.write(lockBonus); saved_game.write(parryBonus); saved_game.write(breakParryBonus); saved_game.write(disarmBonus); saved_game.write(singleBladeStyle); saved_game.write(singleBladeThrowable); saved_game.write(brokenSaber1); saved_game.write(brokenSaber2); saved_game.write(returnDamage); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(name); saved_game.read(fullName); saved_game.read(type); saved_game.read(model); model = NULL; saved_game.read(skin); saved_game.read(soundOn); saved_game.read(soundLoop); saved_game.read(soundOff); saved_game.read(numBlades); saved_game.read<>(blade); saved_game.read(style); saved_game.read(maxChain); saved_game.read(lockable); saved_game.read(throwable); saved_game.read(disarmable); saved_game.read(activeBlocking); saved_game.read(twoHanded); saved_game.read(forceRestrictions); saved_game.read(lockBonus); saved_game.read(parryBonus); saved_game.read(breakParryBonus); saved_game.read(disarmBonus); saved_game.read(singleBladeStyle); saved_game.read(singleBladeThrowable); saved_game.read(brokenSaber1); saved_game.read(brokenSaber2); saved_game.read(returnDamage); } void sg_export( saberInfo_t& dst) const; }; // saberInfoRetail_t #define MAX_SABERS 2 // if this ever changes then update the table "static const save_field_t savefields_gClient[]"!!!!!!!!!!!! // playerState_t is the information needed by both the client and server // to predict player motion and actions // nothing outside of pmove should modify these, or some degree of prediction error // will occur // you can't add anything to this without modifying the code in msg.c // playerState_t is a full superset of entityState_t as it is used by players, // so if a playerState_t is transmitted, the entityState_t can be fully derived // from it. // !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!! template class PlayerStateBase { public: int commandTime; // cmd->serverTime of last executed command int pm_type; int bobCycle; // for view bobbing and footstep generation int pm_flags; // ducked, jump_held, etc int pm_time; vec3_t origin; vec3_t velocity; int weaponTime; int weaponChargeTime; int rechargeTime; // for the phaser int gravity; int leanofs; int friction; int speed; int delta_angles[3]; // add to command angles to get view direction // changed by spawns, rotating objects, and teleporters int groundEntityNum;// ENTITYNUM_NONE = in air int legsAnim; // int legsAnimTimer; // don't change low priority animations on legs until this runs out int torsoAnim; // int torsoAnimTimer; // don't change low priority animations on torso until this runs out int movementDir; // a number 0 to 7 that represents the relative angle // of movement to the view angle (axial and diagonals) // when at rest, the value will remain unchanged // used to twist the legs during strafing int eFlags; // copied to entityState_t->eFlags int eventSequence; // pmove generated events int events[MAX_PS_EVENTS]; int eventParms[MAX_PS_EVENTS]; int externalEvent; // events set on player from another source int externalEventParm; int externalEventTime; int clientNum; // ranges from 0 to MAX_CLIENTS-1 int weapon; // copied to entityState_t->weapon int weaponstate; int batteryCharge; vec3_t viewangles; // for fixed views float legsYaw; // actual legs forward facing int viewheight; // damage feedback int damageEvent; // when it changes, latch the other parms int damageYaw; int damagePitch; int damageCount; int stats[MAX_STATS]; int persistant[MAX_PERSISTANT]; // stats that aren't cleared on death int powerups[MAX_POWERUPS]; // level.time that the powerup runs out int ammo[MAX_AMMO]; int inventory[MAX_INVENTORY]; // Count of each inventory item. char security_key_message[MAX_SECURITY_KEYS][MAX_SECURITY_KEY_MESSSAGE]; // Security key types vec3_t serverViewOrg; qboolean saberInFlight; #ifdef JK2_MODE qboolean saberActive; // -- JK2 -- int vehicleModel; // -- JK2 -- int viewEntity; // For overriding player movement controls and vieworg saber_colors_t saberColor; // -- JK2 -- float saberLength; // -- JK2 -- float saberLengthMax; // -- JK2 -- int forcePowersActive; //prediction needs to know this #else int viewEntity; // For overriding player movement controls and vieworg int forcePowersActive; //prediction needs to know this #endif //NEW vehicle stuff // This has been localized to the vehicle stuff (NOTE: We can still use it later, I'm just commenting it to // root out all the calls. We can store the data in vehicles and update by copying it here). //int vehicleIndex; // Index into vehicleData table //vec3_t vehicleAngles; // current angles of your vehicle //int vehicleArmor; // current armor of your vehicle (explodes if drops to 0) // !! // not communicated over the net at all // !! //int vehicleLastFXTime; //timer for all cgame-FX...? //int vehicleExplodeTime; //when it will go BOOM! int useTime; //not sent int lastShotTime;//last time you shot your weapon int ping; // server to game info for scoreboard int lastOnGround; //last time you were on the ground int lastStationary; //last time you were on the ground int weaponShotCount; #ifndef JK2_MODE //FIXME: maybe allocate all these structures (saber, force powers, vehicles) // or descend them as classes - so not every client has all this info TSaberInfo saber[MAX_SABERS]; qboolean dualSabers; qboolean SaberStaff( void ) { return (qboolean)( saber[0].type == SABER_STAFF || (dualSabers && saber[1].type == SABER_STAFF) ); }; qboolean SaberActive() { return (qboolean)( saber[0].Active() || (dualSabers&&saber[1].Active()) ); }; void SetSaberLength( float length ) { saber[0].SetLength( length ); if ( dualSabers ) { saber[1].SetLength( length ); } } float SaberLength() {//return largest length float len1 = saber[0].Length(); if ( dualSabers && saber[1].Length() > len1 ) { return saber[1].Length(); } return len1; }; float SaberLengthMax() { if ( saber[0].LengthMax() > saber[1].LengthMax() ) { return saber[0].LengthMax(); } else if ( dualSabers ) { return saber[1].LengthMax(); } return 0.0f; }; // Activate or deactivate a specific Blade of a Saber. // Created: 10/03/02 by Aurelio Reis, Modified: 10/03/02 by Aurelio Reis. // [in] int iSaber Which Saber to modify. // [in] int iBlade Which blade to modify (0 - (NUM_BLADES - 1)). // [in] bool bActive Whether to make it active (default true) or inactive (false). // [return] void void SaberBladeActivate( int iSaber, int iBlade, qboolean bActive = qtrue ) { // Validate saber (if it's greater than or equal to zero, OR it above the first saber but we // are not doing duel Sabers, leave, something is not right. if ( iSaber < 0 || ( iSaber > 0 && !dualSabers ) ) return; saber[iSaber].BladeActivate( iBlade, bActive ); } void SaberActivate( void ) { saber[0].Activate(); if ( dualSabers ) { saber[1].Activate(); } } void SaberDeactivate( void ) { saber[0].Deactivate(); saber[1].Deactivate(); }; void SaberActivateTrail ( float duration ) { saber[0].ActivateTrail( duration ); if ( dualSabers ) { saber[1].ActivateTrail( duration ); } }; void SaberDeactivateTrail ( float duration ) { saber[0].DeactivateTrail( duration ); if ( dualSabers ) { saber[1].DeactivateTrail( duration ); } }; int SaberDisarmBonus( int bladeNum ) { int disarmBonus = 0; if ( saber[0].Active() ) { if ( saber[0].bladeStyle2Start > 0 && bladeNum >= saber[0].bladeStyle2Start ) { disarmBonus += saber[0].disarmBonus2; } else { disarmBonus += saber[0].disarmBonus; } } if ( dualSabers && saber[1].Active() ) {//bonus for having 2 sabers if ( saber[1].bladeStyle2Start > 0 && bladeNum >= saber[1].bladeStyle2Start ) { disarmBonus += 1 + saber[1].disarmBonus2; } else { disarmBonus += 1 + saber[1].disarmBonus; } } return disarmBonus; }; int SaberParryBonus( void ) { int parryBonus = 0; if ( saber[0].Active() ) { parryBonus += saber[0].parryBonus; } if ( dualSabers && saber[1].Active() ) {//bonus for having 2 sabers parryBonus += 1 + saber[1].parryBonus; } return parryBonus; }; #endif // !JK2_MODE short saberMove; #ifndef JK2_MODE short saberMoveNext; #endif // !JK2_MODE short saberBounceMove; short saberBlocking; short saberBlocked; short leanStopDebounceTime; #ifdef JK2_MODE float saberLengthOld; #endif int saberEntityNum; float saberEntityDist; int saberThrowTime; int saberEntityState; int saberDamageDebounceTime; int saberHitWallSoundDebounceTime; int saberEventFlags; int saberBlockingTime; int saberAnimLevel; int saberAttackChainCount; int saberLockTime; int saberLockEnemy; int saber2EntityNum; #ifndef JK2_MODE int saberStylesKnown; #endif // !JK2_MODE #ifdef JK2_MODE char *saberModel; #endif int forcePowersKnown; int forcePowerDuration[NUM_FORCE_POWERS]; //for effects that have a duration int forcePowerDebounce[NUM_FORCE_POWERS]; //for effects that must have an interval int forcePower; int forcePowerMax; int forcePowerRegenDebounceTime; #ifndef JK2_MODE int forcePowerRegenRate; //default is 100ms int forcePowerRegenAmount; //default is 1 #endif // !JK2_MODE int forcePowerLevel[NUM_FORCE_POWERS]; //so we know the max forceJump power you have float forceJumpZStart; //So when you land, you don't get hurt as much float forceJumpCharge; //you're current forceJump charge-up level, increases the longer you hold the force jump button down int forceGripEntityNum; //what entity I'm gripping float forceGripEntityInitialDist; //the initial distance of the gripped entity vec3_t forceGripOrg; //where the gripped ent should be lifted to #ifndef JK2_MODE int forceDrainEntityNum; //what entity I'm draining vec3_t forceDrainOrg; //where the drained ent should be lifted to #endif // !JK2_MODE int forceHealCount; //how many points of force heal have been applied so far #ifndef JK2_MODE //new Jedi Academy force powers int forceAllowDeactivateTime; int forceRageDrainTime; int forceRageRecoveryTime; int forceDrainEntNum; float forceDrainTime; int forcePowersForced; //client is being forced to use these powers (FIXME: and only these?) int pullAttackEntNum; int pullAttackTime; int lastKickedEntNum; #endif // !JK2_MODE int taunting; //replaced BUTTON_GESTURE float jumpZStart; //So when you land, you don't get hurt as much vec3_t moveDir; float waterheight; //exactly what the z org of the water is (will be +4 above if under water, -4 below if not in water) waterHeightLevel_t waterHeightLevel; //how high it really is #ifndef JK2_MODE //testing IK grabbing qboolean ikStatus; //for IK int heldClient; //for IK, who I'm grabbing, if anyone int heldByClient; //for IK, someone is grabbing me int heldByBolt; //for IK, what bolt I'm attached to on the holdersomeone is grabbing me by int heldByBone; //for IK, what bone I'm being held by //vehicle turn-around stuff... FIXME: only vehicles need this in SP... int vehTurnaroundIndex; int vehTurnaroundTime; //NOTE: not really used in SP, just for Fighter Vehicle damage stuff int brokenLimbs; int electrifyTime; #endif // !JK2_MODE void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(commandTime); saved_game.write(pm_type); saved_game.write(bobCycle); saved_game.write(pm_flags); saved_game.write(pm_time); saved_game.write(origin); saved_game.write(velocity); saved_game.write(weaponTime); saved_game.write(weaponChargeTime); saved_game.write(rechargeTime); saved_game.write(gravity); saved_game.write(leanofs); saved_game.write(friction); saved_game.write(speed); saved_game.write(delta_angles); saved_game.write(groundEntityNum); saved_game.write(legsAnim); saved_game.write(legsAnimTimer); saved_game.write(torsoAnim); saved_game.write(torsoAnimTimer); saved_game.write(movementDir); saved_game.write(eFlags); saved_game.write(eventSequence); saved_game.write(events); saved_game.write(eventParms); saved_game.write(externalEvent); saved_game.write(externalEventParm); saved_game.write(externalEventTime); saved_game.write(clientNum); saved_game.write(weapon); saved_game.write(weaponstate); saved_game.write(batteryCharge); saved_game.write(viewangles); saved_game.write(legsYaw); saved_game.write(viewheight); saved_game.write(damageEvent); saved_game.write(damageYaw); saved_game.write(damagePitch); saved_game.write(damageCount); saved_game.write(stats); saved_game.write(persistant); saved_game.write(powerups); saved_game.write(ammo); saved_game.write(inventory); saved_game.write(security_key_message); saved_game.write(serverViewOrg); saved_game.write(saberInFlight); #ifdef JK2_MODE saved_game.write(saberActive); saved_game.write(vehicleModel); saved_game.write(viewEntity); saved_game.write(saberColor); saved_game.write(saberLength); saved_game.write(saberLengthMax); saved_game.write(forcePowersActive); #else saved_game.write(viewEntity); saved_game.write(forcePowersActive); #endif // JK2_MODE saved_game.write(useTime); saved_game.write(lastShotTime); saved_game.write(ping); saved_game.write(lastOnGround); saved_game.write(lastStationary); saved_game.write(weaponShotCount); #ifndef JK2_MODE saved_game.write<>(saber); saved_game.write(dualSabers); #endif // !JK2_MODE saved_game.write(saberMove); #ifndef JK2_MODE saved_game.write(saberMoveNext); #endif // !JK2_MODE saved_game.write(saberBounceMove); saved_game.write(saberBlocking); saved_game.write(saberBlocked); saved_game.write(leanStopDebounceTime); #ifdef JK2_MODE saved_game.skip(2); saved_game.write(saberLengthOld); #endif // JK2_MODE saved_game.write(saberEntityNum); saved_game.write(saberEntityDist); saved_game.write(saberThrowTime); saved_game.write(saberEntityState); saved_game.write(saberDamageDebounceTime); saved_game.write(saberHitWallSoundDebounceTime); saved_game.write(saberEventFlags); saved_game.write(saberBlockingTime); saved_game.write(saberAnimLevel); saved_game.write(saberAttackChainCount); saved_game.write(saberLockTime); saved_game.write(saberLockEnemy); #ifndef JK2_MODE saved_game.write(saberStylesKnown); #endif // !JK2_MODE #ifdef JK2_MODE saved_game.write(saberModel); #endif // JK2_MODE saved_game.write(forcePowersKnown); saved_game.write(forcePowerDuration); saved_game.write(forcePowerDebounce); saved_game.write(forcePower); saved_game.write(forcePowerMax); saved_game.write(forcePowerRegenDebounceTime); #ifndef JK2_MODE saved_game.write(forcePowerRegenRate); saved_game.write(forcePowerRegenAmount); #endif // !JK2_MODE saved_game.write(forcePowerLevel); saved_game.write(forceJumpZStart); saved_game.write(forceJumpCharge); saved_game.write(forceGripEntityNum); saved_game.write(forceGripOrg); #ifndef JK2_MODE saved_game.write(forceDrainEntityNum); saved_game.write(forceDrainOrg); #endif // !JK2_MODE saved_game.write(forceHealCount); #ifndef JK2_MODE saved_game.write(forceAllowDeactivateTime); saved_game.write(forceRageDrainTime); saved_game.write(forceRageRecoveryTime); saved_game.write(forceDrainEntNum); saved_game.write(forceDrainTime); saved_game.write(forcePowersForced); saved_game.write(pullAttackEntNum); saved_game.write(pullAttackTime); saved_game.write(lastKickedEntNum); #endif // !JK2_MODE saved_game.write(taunting); saved_game.write(jumpZStart); saved_game.write(moveDir); saved_game.write(waterheight); saved_game.write(waterHeightLevel); #ifndef JK2_MODE saved_game.write(ikStatus); saved_game.write(heldClient); saved_game.write(heldByClient); saved_game.write(heldByBolt); saved_game.write(heldByBone); saved_game.write(vehTurnaroundIndex); saved_game.write(vehTurnaroundTime); saved_game.write(brokenLimbs); saved_game.write(electrifyTime); #endif // !JK2_MODE } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(commandTime); saved_game.read(pm_type); saved_game.read(bobCycle); saved_game.read(pm_flags); saved_game.read(pm_time); saved_game.read(origin); saved_game.read(velocity); saved_game.read(weaponTime); saved_game.read(weaponChargeTime); saved_game.read(rechargeTime); saved_game.read(gravity); saved_game.read(leanofs); saved_game.read(friction); saved_game.read(speed); saved_game.read(delta_angles); saved_game.read(groundEntityNum); saved_game.read(legsAnim); saved_game.read(legsAnimTimer); saved_game.read(torsoAnim); saved_game.read(torsoAnimTimer); saved_game.read(movementDir); saved_game.read(eFlags); saved_game.read(eventSequence); saved_game.read(events); saved_game.read(eventParms); saved_game.read(externalEvent); saved_game.read(externalEventParm); saved_game.read(externalEventTime); saved_game.read(clientNum); saved_game.read(weapon); saved_game.read(weaponstate); saved_game.read(batteryCharge); saved_game.read(viewangles); saved_game.read(legsYaw); saved_game.read(viewheight); saved_game.read(damageEvent); saved_game.read(damageYaw); saved_game.read(damagePitch); saved_game.read(damageCount); saved_game.read(stats); saved_game.read(persistant); saved_game.read(powerups); saved_game.read(ammo); saved_game.read(inventory); saved_game.read(security_key_message); saved_game.read(serverViewOrg); saved_game.read(saberInFlight); #ifdef JK2_MODE saved_game.read(saberActive); saved_game.read(vehicleModel); saved_game.read(viewEntity); saved_game.read(saberColor); saved_game.read(saberLength); saved_game.read(saberLengthMax); saved_game.read(forcePowersActive); #else saved_game.read(viewEntity); saved_game.read(forcePowersActive); #endif // JK2_MODE saved_game.read(useTime); saved_game.read(lastShotTime); saved_game.read(ping); saved_game.read(lastOnGround); saved_game.read(lastStationary); saved_game.read(weaponShotCount); #ifndef JK2_MODE saved_game.read<>(saber); saved_game.read(dualSabers); #endif // !JK2_MODE saved_game.read(saberMove); #ifndef JK2_MODE saved_game.read(saberMoveNext); #endif // !JK2_MODE saved_game.read(saberBounceMove); saved_game.read(saberBlocking); saved_game.read(saberBlocked); saved_game.read(leanStopDebounceTime); #ifdef JK2_MODE saved_game.skip(2); saved_game.read(saberLengthOld); #endif // JK2_MODE saved_game.read(saberEntityNum); saved_game.read(saberEntityDist); saved_game.read(saberThrowTime); saved_game.read(saberEntityState); saved_game.read(saberDamageDebounceTime); saved_game.read(saberHitWallSoundDebounceTime); saved_game.read(saberEventFlags); saved_game.read(saberBlockingTime); saved_game.read(saberAnimLevel); saved_game.read(saberAttackChainCount); saved_game.read(saberLockTime); saved_game.read(saberLockEnemy); #ifndef JK2_MODE saved_game.read(saberStylesKnown); #endif // !JK2_MODE #ifdef JK2_MODE saved_game.read(saberModel); #endif // JK2_MODE saved_game.read(forcePowersKnown); saved_game.read(forcePowerDuration); saved_game.read(forcePowerDebounce); saved_game.read(forcePower); saved_game.read(forcePowerMax); saved_game.read(forcePowerRegenDebounceTime); #ifndef JK2_MODE saved_game.read(forcePowerRegenRate); saved_game.read(forcePowerRegenAmount); #endif // !JK2_MODE saved_game.read(forcePowerLevel); saved_game.read(forceJumpZStart); saved_game.read(forceJumpCharge); saved_game.read(forceGripEntityNum); saved_game.read(forceGripOrg); #ifndef JK2_MODE saved_game.read(forceDrainEntityNum); saved_game.read(forceDrainOrg); #endif // !JK2_MODE saved_game.read(forceHealCount); #ifndef JK2_MODE saved_game.read(forceAllowDeactivateTime); saved_game.read(forceRageDrainTime); saved_game.read(forceRageRecoveryTime); saved_game.read(forceDrainEntNum); saved_game.read(forceDrainTime); saved_game.read(forcePowersForced); saved_game.read(pullAttackEntNum); saved_game.read(pullAttackTime); saved_game.read(lastKickedEntNum); #endif // !JK2_MODE saved_game.read(taunting); saved_game.read(jumpZStart); saved_game.read(moveDir); saved_game.read(waterheight); saved_game.read(waterHeightLevel); #ifndef JK2_MODE saved_game.read(ikStatus); saved_game.read(heldClient); saved_game.read(heldByClient); saved_game.read(heldByBolt); saved_game.read(heldByBone); saved_game.read(vehTurnaroundIndex); saved_game.read(vehTurnaroundTime); saved_game.read(brokenLimbs); saved_game.read(electrifyTime); #endif // !JK2_MODE } }; // PlayerStateBase using playerState_t = PlayerStateBase; //==================================================================== // // usercmd_t->button bits, many of which are generated by the client system, // so they aren't game/cgame only definitions // #define BUTTON_ATTACK 1 #define BUTTON_FORCE_LIGHTNING 2 // displays talk balloon and disables actions #define BUTTON_USE_FORCE 4 #define BUTTON_FORCE_DRAIN 8 // draining #define BUTTON_BLOCKING 8 #define BUTTON_VEH_SPEED 8 // used for some horrible vehicle hack... :) #define BUTTON_WALKING 16 // walking can't just be infered from MOVE_RUN because a key pressed late in the frame will // only generate a small move value for that frame walking will use different animations and // won't generate footsteps #define BUTTON_USE 32 // the ol' use key returns! #define BUTTON_FORCEGRIP 64 // #define BUTTON_ALT_ATTACK 128 #define BUTTON_FORCE_FOCUS 256 // any key whatsoever #define BUTTON_ALT_USE 512 #define MOVE_RUN 120 // if forwardmove or rightmove are >= MOVE_RUN, // then BUTTON_WALKING should be set typedef enum { GENCMD_FORCE_HEAL = 1, GENCMD_FORCE_SPEED, GENCMD_FORCE_THROW, GENCMD_FORCE_PULL, GENCMD_FORCE_DISTRACT, GENCMD_FORCE_GRIP, GENCMD_FORCE_LIGHTNING, GENCMD_FORCE_RAGE, GENCMD_FORCE_PROTECT, GENCMD_FORCE_ABSORB, GENCMD_FORCE_DRAIN, GENCMD_FORCE_SEEING, } genCmds_t; // usercmd_t is sent to the server each client frame // !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!! typedef struct usercmd_s { int serverTime; int buttons; byte weapon; int angles[3]; byte generic_cmd; signed char forwardmove, rightmove, upmove; void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(serverTime); saved_game.write(buttons); saved_game.write(weapon); saved_game.skip(3); saved_game.write(angles); saved_game.write(generic_cmd); saved_game.write(forwardmove); saved_game.write(rightmove); saved_game.write(upmove); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(serverTime); saved_game.read(buttons); saved_game.read(weapon); saved_game.skip(3); saved_game.read(angles); saved_game.read(generic_cmd); saved_game.read(forwardmove); saved_game.read(rightmove); saved_game.read(upmove); } } usercmd_t; //=================================================================== // if entityState->solid == SOLID_BMODEL, modelindex is an inline model number #define SOLID_BMODEL 0xffffff typedef enum {// !!!!!!!!!!! LOADSAVE-affecting struct !!!!!!!!!! TR_STATIONARY, TR_INTERPOLATE, // non-parametric, but interpolate between snapshots TR_LINEAR, TR_LINEAR_STOP, TR_NONLINEAR_STOP, TR_SINE, // value = base + sin( time / duration ) * delta TR_GRAVITY } trType_t; typedef struct {// !!!!!!!!!!! LOADSAVE-affecting struct !!!!!!!!!! trType_t trType; int trTime; int trDuration; // if non 0, trTime + trDuration = stop time vec3_t trBase; vec3_t trDelta; // velocity, etc void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(trType); saved_game.write(trTime); saved_game.write(trDuration); saved_game.write(trBase); saved_game.write(trDelta); } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(trType); saved_game.read(trTime); saved_game.read(trDuration); saved_game.read(trBase); saved_game.read(trDelta); } } trajectory_t; // entityState_t is the information conveyed from the server // in an update message about entities that the client will // need to render in some way // Different eTypes may use the information in different ways // The messages are delta compressed, so it doesn't really matter if // the structure size is fairly large typedef struct entityState_s {// !!!!!!!!!!! LOADSAVE-affecting struct !!!!!!!!!!!!! int number; // entity index int eType; // entityType_t int eFlags; trajectory_t pos; // for calculating position trajectory_t apos; // for calculating angles int time; int time2; vec3_t origin; vec3_t origin2; vec3_t angles; vec3_t angles2; int otherEntityNum; // shotgun sources, etc int otherEntityNum2; int groundEntityNum; // -1 = in air int constantLight; // r + (g<<8) + (b<<16) + (intensity<<24) int loopSound; // constantly loop this sound int modelindex; int modelindex2; int modelindex3; int clientNum; // 0 to (MAX_CLIENTS - 1), for players and corpses int frame; int solid; // for client side prediction, gi.linkentity sets this properly int event; // impulse events -- muzzle flashes, footsteps, etc int eventParm; // for players int powerups; // bit flags int weapon; // determines weapon and flash model, etc int legsAnim; // int legsAnimTimer; // don't change low priority animations on legs until this runs out int torsoAnim; // int torsoAnimTimer; // don't change low priority animations on torso until this runs out int scale; //Scale players //FIXME: why did IMMERSION dupe these 2 fields here? There's no reason for this!!! qboolean saberInFlight; qboolean saberActive; #ifdef JK2_MODE int vehicleModel; // For overriding your playermodel with a drivable vehicle #endif #ifndef JK2_MODE //int vehicleIndex; // What kind of vehicle you're driving vec3_t vehicleAngles; // int vehicleArmor; // current armor of your vehicle (explodes if drops to 0) // 0 if not in a vehicle, otherwise the client number. int m_iVehicleNum; #endif // !JK2_MODE /* Ghoul2 Insert Start */ vec3_t modelScale; // used to scale models in any axis int radius; // used for culling all the ghoul models attached to this ent NOTE - this is automatically scaled by Ghoul2 if/when you scale the model. This is a 100% size value int boltInfo; // info used for bolting entities to Ghoul2 models - NOT used for bolting ghoul2 models to themselves, more for stuff like bolting effects to ghoul2 models /* Ghoul2 Insert End */ #ifndef JK2_MODE qboolean isPortalEnt; #endif // !JK2_MODE void sg_export( ojk::SavedGameHelper& saved_game) const { saved_game.write(number); saved_game.write(eType); saved_game.write(eFlags); saved_game.write<>(pos); saved_game.write<>(apos); saved_game.write(time); saved_game.write(time2); saved_game.write(origin); saved_game.write(origin2); saved_game.write(angles); saved_game.write(angles2); saved_game.write(otherEntityNum); saved_game.write(otherEntityNum2); saved_game.write(groundEntityNum); saved_game.write(constantLight); saved_game.write(loopSound); saved_game.write(modelindex); saved_game.write(modelindex2); saved_game.write(modelindex3); saved_game.write(clientNum); saved_game.write(frame); saved_game.write(solid); saved_game.write(event); saved_game.write(eventParm); saved_game.write(powerups); saved_game.write(weapon); saved_game.write(legsAnim); saved_game.write(legsAnimTimer); saved_game.write(torsoAnim); saved_game.write(torsoAnimTimer); saved_game.write(scale); saved_game.write(saberInFlight); saved_game.write(saberActive); #ifdef JK2_MODE saved_game.write(vehicleModel); #endif // JK2_MODE #ifndef JK2_MODE saved_game.write(vehicleAngles); saved_game.write(vehicleArmor); saved_game.write(m_iVehicleNum); #endif // !JK2_MODE saved_game.write(modelScale); saved_game.write(radius); saved_game.write(boltInfo); #ifndef JK2_MODE saved_game.write(isPortalEnt); #endif // !JK2_MODE } void sg_import( ojk::SavedGameHelper& saved_game) { saved_game.read(number); saved_game.read(eType); saved_game.read(eFlags); saved_game.read<>(pos); saved_game.read<>(apos); saved_game.read(time); saved_game.read(time2); saved_game.read(origin); saved_game.read(origin2); saved_game.read(angles); saved_game.read(angles2); saved_game.read(otherEntityNum); saved_game.read(otherEntityNum2); saved_game.read(groundEntityNum); saved_game.read(constantLight); saved_game.read(loopSound); saved_game.read(modelindex); saved_game.read(modelindex2); saved_game.read(modelindex3); saved_game.read(clientNum); saved_game.read(frame); saved_game.read(solid); saved_game.read(event); saved_game.read(eventParm); saved_game.read(powerups); saved_game.read(weapon); saved_game.read(legsAnim); saved_game.read(legsAnimTimer); saved_game.read(torsoAnim); saved_game.read(torsoAnimTimer); saved_game.read(scale); saved_game.read(saberInFlight); saved_game.read(saberActive); #ifdef JK2_MODE saved_game.read(vehicleModel); #endif // JK2_MODE #ifndef JK2_MODE saved_game.read(vehicleAngles); saved_game.read(vehicleArmor); saved_game.read(m_iVehicleNum); #endif // !JK2_MODE saved_game.read(modelScale); saved_game.read(radius); saved_game.read(boltInfo); #ifndef JK2_MODE saved_game.read(isPortalEnt); #endif // !JK2_MODE } } entityState_t; typedef enum { CA_UNINITIALIZED, CA_DISCONNECTED, // not talking to a server CA_CONNECTING, // sending request packets to the server CA_CHALLENGING, // sending challenge packets to the server CA_CONNECTED, // netchan_t established, getting gamestate CA_LOADING, // only during cgame initialization, never during main loop CA_PRIMED, // got gamestate, waiting for first frame CA_ACTIVE, // game views should be displayed CA_CINEMATIC // playing a cinematic or a static pic, not connected to a server } connstate_t; typedef struct SSkinGoreData_s { vec3_t angles; vec3_t position; int currentTime; int entNum; vec3_t rayDirection; // in world space vec3_t hitLocation; // in world space vec3_t scale; float SSize; // size of splotch in the S texture direction in world units float TSize; // size of splotch in the T texture direction in world units float theta; // angle to rotate the splotch vec3_t uaxis; //mark direction float depthStart; // limit marks begin depth float depthEnd; // depth to stop making marks bool useTheta; bool frontFaces; bool backFaces; bool fadeRGB; //specify fade method to modify RGB (by default, the alpha is set instead) // growing stuff int growDuration; // time over which we want this to scale up, set to -1 for no scaling float goreScaleStartFraction; // fraction of the final size at which we want the gore to initially appear //qboolean baseModelOnly; int lifeTime; // effect expires after this amount of time int firstModel; // which model to start the gore on (can skip the first) int fadeOutTime; //specify the duration of fading, from the lifeTime (e.g. 3000 will start fading 3 seconds before removal and be faded entirely by removal) //int shrinkOutTime; // unimplemented //float alphaModulate; // unimplemented //vec3_t tint; // unimplemented //float impactStrength; // unimplemented int shader; // shader handle int myIndex; // used internally } SSkinGoreData; //rww - used for my ik stuff (ported directly from mp) typedef struct { vec3_t angles; vec3_t position; vec3_t scale; vec3_t velocity; int me; } sharedRagDollUpdateParams_t; //rww - update parms for ik bone stuff typedef struct { char boneName[512]; //name of bone vec3_t desiredOrigin; //world coordinate that this bone should be attempting to reach vec3_t origin; //world coordinate of the entity who owns the g2 instance that owns the bone float movementSpeed; //how fast the bone should move toward the destination } sharedIKMoveParams_t; typedef struct { vec3_t pcjMins; //ik joint limit vec3_t pcjMaxs; //ik joint limit vec3_t origin; //origin of caller vec3_t angles; //angles of caller vec3_t scale; //scale of caller float radius; //bone rad int blendTime; //bone blend time int pcjOverrides; //override ik bone flags int startFrame; //base pose start int endFrame; //base pose end } sharedSetBoneIKStateParams_t; enum sharedEIKMoveState { IKS_NONE = 0, IKS_DYNAMIC }; /* ======================================================================== String ID Tables ======================================================================== */ typedef struct stringID_table_s { const char *name; int id; } stringID_table_t; int GetIDForString ( const stringID_table_t *table, const char *string ); const char *GetStringForID( const stringID_table_t *table, int id ); // savegame screenshot size stuff... // #define SG_SCR_WIDTH 512 //256 #define SG_SCR_HEIGHT 512 //256 #define iSG_COMMENT_SIZE 64 #define sCVARNAME_PLAYERSAVE "playersave" // used for level-transition, accessed by game and server modules /* Ghoul2 Insert Start */ // For ghoul2 axis use enum Eorientations { ORIGIN = 0, POSITIVE_X, POSITIVE_Z, POSITIVE_Y, NEGATIVE_X, NEGATIVE_Z, NEGATIVE_Y }; /* Ghoul2 Insert End */ #define MAX_PARSEFILES 16 typedef struct parseData_s { char fileName[MAX_QPATH]; // Name of current file being read in int com_lines; // Number of lines read in int com_tokenline; const char *bufferStart; // Start address of buffer holding data that was read in const char *bufferCurrent; // Where data is currently being parsed from buffer } parseData_t; //JFLCALLOUT include //changed to array extern parseData_t parseData[]; extern int parseDataCount; // cinematic states typedef enum { FMV_IDLE, FMV_PLAY, // play FMV_EOF, // all other conditions, i.e. stop/EOF/abort FMV_ID_BLT, FMV_ID_IDLE, FMV_LOOPED, FMV_ID_WAIT } e_status; // define the new memory tags for the zone, used by all modules now // #define TAGDEF(blah) TAG_ ## blah enum { #include "../qcommon/tags.h" }; typedef unsigned memtag_t; // stuff to help out during development process, force reloading/uncacheing of certain filetypes... // typedef enum { eForceReload_NOTHING, eForceReload_BSP, eForceReload_MODELS, eForceReload_ALL } ForceReload_e; qboolean Q_InBitflags( const uint32_t *bits, int index, uint32_t bitsPerByte ); void Q_AddToBitflags( uint32_t *bits, int index, uint32_t bitsPerByte ); void Q_RemoveFromBitflags( uint32_t *bits, int index, uint32_t bitsPerByte ); typedef int( *cmpFunc_t )(const void *a, const void *b); void *Q_LinearSearch( const void *key, const void *ptr, size_t count, size_t size, cmpFunc_t cmp ); #endif // __Q_SHARED_H