/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
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 __G_SHARED_H__
#define __G_SHARED_H__
#include "bg_public.h"
#include "g_public.h"
#include "b_public.h"
#include "../icarus/StdAfx.h" //need stl
#include "../rd-common/tr_types.h"
#include "../cgame/cg_public.h"
#include "g_vehicles.h"
#include "hitlocs.h"
#include "bset.h"
#define FOFS(x) offsetof(gentity_t, x)
typedef enum //# taskID_e
{
TID_CHAN_VOICE = 0, // Waiting for a voice sound to complete
TID_ANIM_UPPER, // Waiting to finish a lower anim holdtime
TID_ANIM_LOWER, // Waiting to finish a lower anim holdtime
TID_ANIM_BOTH, // Waiting to finish lower and upper anim holdtimes or normal md3 animating
TID_MOVE_NAV, // Trying to get to a navgoal or For ET_MOVERS
TID_ANGLE_FACE, // Turning to an angle or facing
TID_BSTATE, // Waiting for a certain bState to finish
TID_LOCATION, // Waiting for ent to enter a specific trigger_location
// TID_MISSIONSTATUS, // Waiting for player to finish reading MISSION STATUS SCREEN
TID_RESIZE, // Waiting for clear bbox to inflate size
TID_SHOOT, // Waiting for fire event
NUM_TIDS, // for def of taskID array
} taskID_t;
typedef enum //# material_e
{
MAT_METAL = 0, // scorched blue-grey metal
MAT_GLASS, // not a real chunk type, just plays an effect with glass sprites
MAT_ELECTRICAL, // sparks only
MAT_ELEC_METAL, // sparks/electrical type metal
MAT_DRK_STONE, // brown
MAT_LT_STONE, // tan
MAT_GLASS_METAL,// glass sprites and METAl chunk
MAT_METAL2, // electrical metal type
MAT_NONE, // no chunks
MAT_GREY_STONE, // grey
MAT_METAL3, // METAL and METAL2 chunks
MAT_CRATE1, // yellow multi-colored crate chunks
MAT_GRATE1, // grate chunks
MAT_ROPE, // for yavin trial...no chunks, just wispy bits
MAT_CRATE2, // read multi-colored crate chunks
MAT_WHITE_METAL,// white angular chunks
NUM_MATERIALS
} material_t;
//===From cg_local.h================================================
#define DEFAULT_HEADMODEL ""
#define DEFAULT_TORSOMODEL ""
#define DEFAULT_LEGSMODEL "mouse"
// each client has an associated clientInfo_t
// that contains media references necessary to present the
// client model and other color coded effects
// this is regenerated each time a userinfo configstring changes
#define MAX_CUSTOM_BASIC_SOUNDS 14
#define MAX_CUSTOM_COMBAT_SOUNDS 17
#define MAX_CUSTOM_EXTRA_SOUNDS 36
#define MAX_CUSTOM_JEDI_SOUNDS 22
#define MAX_CUSTOM_SOUNDS (MAX_CUSTOM_JEDI_SOUNDS + MAX_CUSTOM_EXTRA_SOUNDS + MAX_CUSTOM_COMBAT_SOUNDS + MAX_CUSTOM_BASIC_SOUNDS)
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class clientInfo_t
{
public:
qboolean infoValid;
char name[MAX_QPATH];
team_t team;
int score; // updated by score servercmds
int handicap;
qhandle_t legsModel;
qhandle_t legsSkin;
qhandle_t torsoModel;
qhandle_t torsoSkin;
qhandle_t headModel;
qhandle_t headSkin;
int animFileIndex;
sfxHandle_t sounds[MAX_CUSTOM_SOUNDS];
char *customBasicSoundDir;
char *customCombatSoundDir;
char *customExtraSoundDir;
char *customJediSoundDir;
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(infoValid);
saved_game.write(name);
saved_game.write(team);
saved_game.write(score);
saved_game.write(handicap);
saved_game.write(legsModel);
saved_game.write(legsSkin);
saved_game.write(torsoModel);
saved_game.write(torsoSkin);
saved_game.write(headModel);
saved_game.write(headSkin);
saved_game.write(animFileIndex);
saved_game.write(sounds);
saved_game.write(customBasicSoundDir);
saved_game.write(customCombatSoundDir);
saved_game.write(customExtraSoundDir);
saved_game.write(customJediSoundDir);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(infoValid);
saved_game.read(name);
saved_game.read(team);
saved_game.read(score);
saved_game.read(handicap);
saved_game.read(legsModel);
saved_game.read(legsSkin);
saved_game.read(torsoModel);
saved_game.read(torsoSkin);
saved_game.read(headModel);
saved_game.read(headSkin);
saved_game.read(animFileIndex);
saved_game.read(sounds);
saved_game.read(customBasicSoundDir);
saved_game.read(customCombatSoundDir);
saved_game.read(customExtraSoundDir);
saved_game.read(customJediSoundDir);
}
}; // clientInfo_t
//==================================================================
typedef enum
{
MOVER_POS1,
MOVER_POS2,
MOVER_1TO2,
MOVER_2TO1
} moverState_t;
// Rendering information structure
typedef enum
{
MODEL_LEGS = 0,
MODEL_TORSO,
MODEL_HEAD,
MODEL_WEAPON1,
MODEL_WEAPON2,
MODEL_WEAPON3,
MODEL_EXTRA1,
MODEL_EXTRA2,
NUM_TARGET_MODELS
} targetModel_t;
//renderFlags
#define RF_LOCKEDANGLE 1
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class renderInfo_t
{
public:
// Legs model, or full model on one piece entities
union
{
char legsModelName[32]; // -slc[]
char modelName[32]; // -slc[]
};
char torsoModelName[32]; // -slc[]
char headModelName[32]; // -slc[]
//In whole degrees, How far to let the different model parts yaw and pitch
int headYawRangeLeft;
int headYawRangeRight;
int headPitchRangeUp;
int headPitchRangeDown;
int torsoYawRangeLeft;
int torsoYawRangeRight;
int torsoPitchRangeUp;
int torsoPitchRangeDown;
int legsFrame;
int torsoFrame;
float legsFpsMod;
float torsoFpsMod;
//Fields to apply to entire model set, individual model's equivalents will modify this value
byte customRGBA[4];//Red Green Blue, 0 = don't apply
//Allow up to 4 PCJ lookup values to be stored here.
//The resolve to configstrings which contain the name of the
//desired bone.
int boneIndex1;
int boneIndex2;
int boneIndex3;
int boneIndex4;
//packed with x, y, z orientations for bone angles
int boneOrient;
//I.. feel bad for doing this, but NPCs really just need to
//be able to control this sort of thing from the server sometimes.
//At least it's at the end so this stuff is never going to get sent
//over for anything that isn't an NPC.
vec3_t boneAngles1; //angles of boneIndex1
vec3_t boneAngles2; //angles of boneIndex2
vec3_t boneAngles3; //angles of boneIndex3
vec3_t boneAngles4; //angles of boneIndex4
//RF?
int renderFlags;
//
vec3_t muzzlePoint;
vec3_t muzzleDir;
vec3_t muzzlePointOld;
vec3_t muzzleDirOld;
//vec3_t muzzlePointNext; // Muzzle point one server frame in the future!
//vec3_t muzzleDirNext;
int mPCalcTime;//Last time muzzle point was calced
//
float lockYaw;//
//
vec3_t headPoint;//Where your tag_head is
vec3_t headAngles;//where the tag_head in the torso is pointing
vec3_t handRPoint;//where your right hand is
vec3_t handLPoint;//where your left hand is
vec3_t crotchPoint;//Where your crotch is
vec3_t footRPoint;//where your right hand is
vec3_t footLPoint;//where your left hand is
vec3_t torsoPoint;//Where your chest is
vec3_t torsoAngles;//Where the chest is pointing
vec3_t eyePoint;//Where your eyes are
vec3_t eyeAngles;//Where your eyes face
int lookTarget;//Which ent to look at with lookAngles
lookMode_t lookMode;
int lookTargetClearTime;//Time to clear the lookTarget
int lastVoiceVolume;//Last frame's voice volume
vec3_t lastHeadAngles;//Last headAngles, NOT actual facing of head model
vec3_t headBobAngles;//headAngle offsets
vec3_t targetHeadBobAngles;//head bob angles will try to get to targetHeadBobAngles
int lookingDebounceTime;//When we can stop using head looking angle behavior
float legsYaw;//yaw angle your legs are actually rendering at
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(legsModelName);
saved_game.write(torsoModelName);
saved_game.write(headModelName);
saved_game.write(headYawRangeLeft);
saved_game.write(headYawRangeRight);
saved_game.write(headPitchRangeUp);
saved_game.write(headPitchRangeDown);
saved_game.write(torsoYawRangeLeft);
saved_game.write(torsoYawRangeRight);
saved_game.write(torsoPitchRangeUp);
saved_game.write(torsoPitchRangeDown);
saved_game.write(legsFrame);
saved_game.write(torsoFrame);
saved_game.write(legsFpsMod);
saved_game.write(torsoFpsMod);
saved_game.write(customRGBA);
saved_game.write(boneIndex1);
saved_game.write(boneIndex2);
saved_game.write(boneIndex3);
saved_game.write(boneIndex4);
saved_game.write(boneOrient);
saved_game.write(boneAngles1);
saved_game.write(boneAngles2);
saved_game.write(boneAngles3);
saved_game.write(boneAngles4);
saved_game.write(renderFlags);
saved_game.write(muzzlePoint);
saved_game.write(muzzleDir);
saved_game.write(muzzlePointOld);
saved_game.write(muzzleDirOld);
saved_game.write(mPCalcTime);
saved_game.write(lockYaw);
saved_game.write(headPoint);
saved_game.write(headAngles);
saved_game.write(handRPoint);
saved_game.write(handLPoint);
saved_game.write(crotchPoint);
saved_game.write(footRPoint);
saved_game.write(footLPoint);
saved_game.write(torsoPoint);
saved_game.write(torsoAngles);
saved_game.write(eyePoint);
saved_game.write(eyeAngles);
saved_game.write(lookTarget);
saved_game.write(lookMode);
saved_game.write(lookTargetClearTime);
saved_game.write(lastVoiceVolume);
saved_game.write(lastHeadAngles);
saved_game.write(headBobAngles);
saved_game.write(targetHeadBobAngles);
saved_game.write(lookingDebounceTime);
saved_game.write(legsYaw);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(legsModelName);
saved_game.read(torsoModelName);
saved_game.read(headModelName);
saved_game.read(headYawRangeLeft);
saved_game.read(headYawRangeRight);
saved_game.read(headPitchRangeUp);
saved_game.read(headPitchRangeDown);
saved_game.read(torsoYawRangeLeft);
saved_game.read(torsoYawRangeRight);
saved_game.read(torsoPitchRangeUp);
saved_game.read(torsoPitchRangeDown);
saved_game.read(legsFrame);
saved_game.read(torsoFrame);
saved_game.read(legsFpsMod);
saved_game.read(torsoFpsMod);
saved_game.read(customRGBA);
saved_game.read(boneIndex1);
saved_game.read(boneIndex2);
saved_game.read(boneIndex3);
saved_game.read(boneIndex4);
saved_game.read(boneOrient);
saved_game.read(boneAngles1);
saved_game.read(boneAngles2);
saved_game.read(boneAngles3);
saved_game.read(boneAngles4);
saved_game.read(renderFlags);
saved_game.read(muzzlePoint);
saved_game.read(muzzleDir);
saved_game.read(muzzlePointOld);
saved_game.read(muzzleDirOld);
saved_game.read(mPCalcTime);
saved_game.read(lockYaw);
saved_game.read(headPoint);
saved_game.read(headAngles);
saved_game.read(handRPoint);
saved_game.read(handLPoint);
saved_game.read(crotchPoint);
saved_game.read(footRPoint);
saved_game.read(footLPoint);
saved_game.read(torsoPoint);
saved_game.read(torsoAngles);
saved_game.read(eyePoint);
saved_game.read(eyeAngles);
saved_game.read(lookTarget);
saved_game.read(lookMode);
saved_game.read(lookTargetClearTime);
saved_game.read(lastVoiceVolume);
saved_game.read(lastHeadAngles);
saved_game.read(headBobAngles);
saved_game.read(targetHeadBobAngles);
saved_game.read(lookingDebounceTime);
saved_game.read(legsYaw);
}
}; // renderInfo_t
// Movement information structure
/*
typedef struct moveInfo_s // !!!!!!!!!! LOADSAVE-affecting struct !!!!!!!!
{
vec3_t desiredAngles; // Desired facing angles
float speed; // Speed of movement
float aspeed; // Speed of angular movement
vec3_t moveDir; // Direction of movement
vec3_t velocity; // movement velocity
int flags; // Special state flags
} moveInfo_t;
*/
typedef enum {
CON_DISCONNECTED,
CON_CONNECTING,
CON_CONNECTED
} clientConnected_t;
typedef enum {
TEAM_BEGIN, // Beginning a team game, spawn at base
TEAM_ACTIVE // Now actively playing
} playerTeamStateState_t;
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class playerTeamState_t
{
public:
playerTeamStateState_t state;
int captures;
int basedefense;
int carrierdefense;
int flagrecovery;
int fragcarrier;
int assists;
float lasthurtcarrier;
float lastreturnedflag;
float flagsince;
float lastfraggedcarrier;
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(state);
saved_game.write(captures);
saved_game.write(basedefense);
saved_game.write(carrierdefense);
saved_game.write(flagrecovery);
saved_game.write(fragcarrier);
saved_game.write(assists);
saved_game.write(lasthurtcarrier);
saved_game.write(lastreturnedflag);
saved_game.write(flagsince);
saved_game.write(lastfraggedcarrier);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(state);
saved_game.read(captures);
saved_game.read(basedefense);
saved_game.read(carrierdefense);
saved_game.read(flagrecovery);
saved_game.read(fragcarrier);
saved_game.read(assists);
saved_game.read(lasthurtcarrier);
saved_game.read(lastreturnedflag);
saved_game.read(flagsince);
saved_game.read(lastfraggedcarrier);
}
}; // playerTeamState_t
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class objectives_t
{
public:
qboolean display; // A displayable objective?
int status; // Succeed or fail or pending
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(display);
saved_game.write(status);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(display);
saved_game.read(status);
}
}; // objectives_t
// NOTE: This is an arbitrary number greater than our current number of objectives with
// some fluff just in case we add more in the future.
#define MAX_MISSION_OBJ 100
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class missionStats_t
{
public:
int secretsFound; // # of secret areas found
int totalSecrets; // # of secret areas that could have been found
int shotsFired; // total number of shots fired
int hits; // Shots that did damage
int enemiesSpawned; // # of enemies spawned
int enemiesKilled; // # of enemies killed
int saberThrownCnt; // # of times saber was thrown
int saberBlocksCnt; // # of times saber was used to block
int legAttacksCnt; // # of times legs were hit with saber
int armAttacksCnt; // # of times arm were hit with saber
int torsoAttacksCnt; // # of times torso was hit with saber
int otherAttacksCnt; // # of times anything else on a monster was hit with saber
int forceUsed[NUM_FORCE_POWERS]; // # of times each force power was used
int weaponUsed[WP_NUM_WEAPONS]; // # of times each weapon was used
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(secretsFound);
saved_game.write(totalSecrets);
saved_game.write(shotsFired);
saved_game.write(hits);
saved_game.write(enemiesSpawned);
saved_game.write(enemiesKilled);
saved_game.write(saberThrownCnt);
saved_game.write(saberBlocksCnt);
saved_game.write(legAttacksCnt);
saved_game.write(armAttacksCnt);
saved_game.write(torsoAttacksCnt);
saved_game.write(otherAttacksCnt);
saved_game.write(forceUsed);
saved_game.write(weaponUsed);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(secretsFound);
saved_game.read(totalSecrets);
saved_game.read(shotsFired);
saved_game.read(hits);
saved_game.read(enemiesSpawned);
saved_game.read(enemiesKilled);
saved_game.read(saberThrownCnt);
saved_game.read(saberBlocksCnt);
saved_game.read(legAttacksCnt);
saved_game.read(armAttacksCnt);
saved_game.read(torsoAttacksCnt);
saved_game.read(otherAttacksCnt);
saved_game.read(forceUsed);
saved_game.read(weaponUsed);
}
}; // missionStats_t
// the auto following clients don't follow a specific client
// number, but instead follow the first two active players
#define FOLLOW_ACTIVE1 -1
#define FOLLOW_ACTIVE2 -2
// client data that stays across multiple levels or tournament restarts
// this is achieved by writing all the data to cvar strings at game shutdown
// time and reading them back at connection time. Anything added here
// MUST be dealt with in G_InitSessionData() / G_ReadSessionData() / G_WriteSessionData()
//
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class clientSession_t
{
public:
int missionObjectivesShown; // Number of times mission objectives have been updated
team_t sessionTeam;
objectives_t mission_objectives[MAX_MISSION_OBJ];
missionStats_t missionStats; // Various totals while on a mission
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(missionObjectivesShown);
saved_game.write(sessionTeam);
saved_game.write<>(mission_objectives);
saved_game.write<>(missionStats);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(missionObjectivesShown);
saved_game.read(sessionTeam);
saved_game.read<>(mission_objectives);
saved_game.read<>(missionStats);
}
}; // clientSession_t
// client data that stays across multiple respawns, but is cleared
// on each level change or team change at ClientBegin()
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
class clientPersistant_t
{
public:
clientConnected_t connected;
usercmd_t lastCommand;
char netname[34];
int maxHealth; // for handicapping
int enterTime; // level.time the client entered the game
short cmd_angles[3]; // angles sent over in the last command
playerTeamState_t teamState; // status in teamplay games
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write(connected);
saved_game.write<>(lastCommand);
saved_game.write(netname);
saved_game.skip(2);
saved_game.write(maxHealth);
saved_game.write(enterTime);
saved_game.write(cmd_angles);
saved_game.skip(2);
saved_game.write<>(teamState);
}
void sg_import(
ojk::SavedGameHelper& saved_game)
{
saved_game.read(connected);
saved_game.read<>(lastCommand);
saved_game.read(netname);
saved_game.skip(2);
saved_game.read(maxHealth);
saved_game.read(enterTime);
saved_game.read(cmd_angles);
saved_game.skip(2);
saved_game.read<>(teamState);
}
}; // clientPersistant_t
typedef enum {
BLK_NO,
BLK_TIGHT, // Block only attacks and shots around the saber itself, a bbox of around 12x12x12
BLK_WIDE // Block all attacks in an area around the player in a rough arc of 180 degrees
} saberBlockType_t;
typedef enum {
BLOCKED_NONE,
BLOCKED_PARRY_BROKEN,
BLOCKED_ATK_BOUNCE,
BLOCKED_UPPER_RIGHT,
BLOCKED_UPPER_LEFT,
BLOCKED_LOWER_RIGHT,
BLOCKED_LOWER_LEFT,
BLOCKED_TOP,
BLOCKED_UPPER_RIGHT_PROJ,
BLOCKED_UPPER_LEFT_PROJ,
BLOCKED_LOWER_RIGHT_PROJ,
BLOCKED_LOWER_LEFT_PROJ,
BLOCKED_TOP_PROJ
} saberBlockedType_t;
typedef enum //# movetype_e
{
MT_STATIC = 0,
MT_WALK,
MT_RUNJUMP,
MT_FLYSWIM,
NUM_MOVETYPES
} movetype_t;
// !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!!
// this structure is cleared on each ClientSpawn(),
// except for 'client->pers' and 'client->sess'
template
class GClientBase
{
public:
// ps MUST be the first element, because the server expects it
PlayerStateBase ps; // communicated by server to clients
// private to game
clientPersistant_t pers;
clientSession_t sess;
int lastCmdTime; // level.time of last usercmd_t, for EF_CONNECTION
usercmd_t usercmd; // most recent usercmd
int buttons;
int oldbuttons;
int latched_buttons;
// sum up damage over an entire frame, so
// shotgun blasts give a single big kick
int damage_armor; // damage absorbed by armor
int damage_blood; // damage taken out of health
vec3_t damage_from; // origin for vector calculation
bool damage_fromWorld; // if true, don't use the damage_from vector
bool noclip;
//icarus forced moving. is this still used?
signed char forced_forwardmove;
signed char forced_rightmove;
// timers
int respawnTime; // can respawn when time > this, force after g_forcerespwan
int idleTime; // for playing idleAnims
int airOutTime;
// timeResidual is used to handle events that happen every second
// like health / armor countdowns and regeneration
int timeResidual;
// Facial Expression Timers
float facial_blink; // time before next blink. If a minus value, we are in blink mode
float facial_timer; // time before next alert, frown or smile. If a minus value, we are in anim mode
int facial_anim; // anim to show in anim mode
//Client info - updated when ClientInfoChanged is called, instead of using configstrings
clientInfo_t clientInfo;
movetype_t moveType;
int jetPackTime;
int fireDelay; //msec to delay calling G_FireWeapon after EV_FIREWEAPON event is called
// The time at which a breath should be triggered. -Aurelio
int breathPuffTime;
//Used to be in gentity_t, now here.. mostly formation stuff
team_t playerTeam;
team_t enemyTeam;
gentity_t *leader;
class_t NPC_class;
//FIXME: could combine these
float hiddenDist;//How close ents have to be to pick you up as an enemy
vec3_t hiddenDir;//Normalized direction in which NPCs can't see you (you are hidden)
renderInfo_t renderInfo;
//dismember tracker
bool dismembered;
char dismemberProbLegs; // probability of the legs being dismembered (located in NPC.cfg, 0 = never, 100 = always)
char dismemberProbHead; // probability of the head being dismembered (located in NPC.cfg, 0 = never, 100 = always)
char dismemberProbArms; // probability of the arms being dismembered (located in NPC.cfg, 0 = never, 100 = always)
char dismemberProbHands; // probability of the hands being dismembered (located in NPC.cfg, 0 = never, 100 = always)
char dismemberProbWaist; // probability of the waist being dismembered (located in NPC.cfg, 0 = never, 100 = always)
int standheight;
int crouchheight;
int poisonDamage; // Amount of poison damage to be given
int poisonTime; // When to apply poison damage
int slopeRecalcTime; // debouncer for slope-foot-height-diff calcing
vec3_t pushVec;
int pushVecTime;
int noRagTime; //don't do ragdoll stuff if > level.time
qboolean isRagging;
int overridingBones; //dragging body or doing something else to override one or more ragdoll effector's/pcj's
vec3_t ragLastOrigin; //keeping track of positions between rags while dragging corpses
int ragLastOriginTime;
//push refraction effect vars
int pushEffectFadeTime;
vec3_t pushEffectOrigin;
//Rocket locking vars for non-player clients (only Vehicles use these right now...)
int rocketLockIndex;
float rocketLastValidTime;
float rocketLockTime;
float rocketTargetTime;
//for trigger_space brushes
int inSpaceSuffocation;
int inSpaceIndex;
void sg_export(
ojk::SavedGameHelper& saved_game) const
{
saved_game.write<>(ps);
saved_game.write<>(pers);
saved_game.write<>(sess);
saved_game.write(lastCmdTime);
saved_game.write<>(usercmd);
saved_game.write(buttons);
saved_game.write(oldbuttons);
saved_game.write(latched_buttons);
saved_game.write(damage_armor);
saved_game.write(damage_blood);
saved_game.write(damage_from);
saved_game.write(damage_fromWorld);
saved_game.write(noclip);
saved_game.write(forced_forwardmove);
saved_game.write(forced_rightmove);
saved_game.write(respawnTime);
saved_game.write(idleTime);
saved_game.write(airOutTime);
saved_game.write(timeResidual);
saved_game.write(facial_blink);
saved_game.write(facial_timer);
saved_game.write(facial_anim);
saved_game.write<>(clientInfo);
saved_game.write(moveType);
saved_game.write(jetPackTime);
saved_game.write(fireDelay);
saved_game.write(breathPuffTime);
saved_game.write(playerTeam);
saved_game.write(enemyTeam);
saved_game.write(leader);
saved_game.write(NPC_class);
saved_game.write(hiddenDist);
saved_game.write(hiddenDir);
saved_game.write<>(renderInfo);
saved_game.write(dismembered);
saved_game.write(dismemberProbLegs);
saved_game.write(dismemberProbHead);
saved_game.write(dismemberProbArms);
saved_game.write(dismemberProbHands);
saved_game.write(dismemberProbWaist);
saved_game.skip(2);
saved_game.write(standheight);
saved_game.write(crouchheight);
saved_game.write(poisonDamage);
saved_game.write(poisonTime);
saved_game.write(slopeRecalcTime);
saved_game.write(pushVec);
saved_game.write(pushVecTime);
saved_game.write(noRagTime);
saved_game.write(isRagging);
saved_game.write(overridingBones);
saved_game.write(ragLastOrigin);
saved_game.write(ragLastOriginTime);
saved_game.write