Added support for *Team Assault* and *Team Tactics*

This commit is contained in:
OM 2023-05-21 19:59:36 +02:00
parent 238e94b4d5
commit ab2a26a14e
12 changed files with 1353 additions and 264 deletions

View file

@ -300,16 +300,7 @@ void CG_ProcessConfigString(int num)
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
sscanf
(
str,
"%d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2]
);
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf
@ -776,4 +767,45 @@ void Com_Printf( const char *msg, ... ) {
#endif
#if TARGET_GAME_PROTOCOL >= 15
void CG_ParseFogInfo(const char* str) {
sscanf(
str,
"%d %f %f %f %f %f %f %f %d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_bias,
&cg.skyboxFarplane,
&cg.skyboxSpeed,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2],
&cg.renderTerrain,
&cg.farclipOverride,
&cg.farplaneColorOverride[0],
&cg.farplaneColorOverride[1],
&cg.farplaneColorOverride[2]
);
}
#else
void CG_ParseFogInfo(const char* str) {
cg.farclipOverride = 0.0;
cg.farplaneColorOverride[0] = -1.0;
cg.farplaneColorOverride[1] = -1.0;
cg.farplaneColorOverride[2] = -1.0;
sscanf
(
str,
"%d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2]
);
}
#endif

View file

@ -64,7 +64,7 @@ static void CG_MakeBulletHole(vec3_t i_vPos, vec3_t i_vNorm, int iLarge, trace_t
// FIXME: unimplemented
}
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge)
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge, float alpha = 1.0f)
{
// FIXME: unimplemented
}
@ -79,7 +79,7 @@ static void CG_MakeBulletTracerInternal(vec3_t i_vBarrel, vec3_t i_vStart, vec3_
// FIXME: unimplemented
}
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities) {
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities, float alpha) {
bullet_tracer_t* bullet_tracer;
int i;
@ -306,6 +306,463 @@ void CG_MakeVehicleEffect(vec3_t i_vStart, vec3_t i_vEnd , vec3_t i_vDir) {
cgi.R_DebugLine(vFrom, trace.endpos, 1.0, 1.0, 1.0, 1.0);
}
#if TARGET_GAME_PROTOCOL >= 15
void CG_ParseCGMessage()
{
int i;
int iType;
int iLarge;
int iInfo;
int iCount;
char* szTmp;
vec3_t vStart, vEnd, vTmp;
vec3_t vEndArray[MAX_IMPACTS];
float alpha;
int value;
qboolean bMoreCGameMessages = qtrue;
while (bMoreCGameMessages) {
iType = cgi.MSG_ReadBits(6);
switch (iType)
{
case 1:
case 2:
case 5:
if (iType == 1)
{
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
}
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
if (iType != 1)
{
vTmp[0] = vStart[0];
vTmp[1] = vStart[1];
vTmp[2] = vStart[2];
}
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
if (iType == 1) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
}
else if (iType == 2) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
}
else {
CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge, alpha);
}
break;
case 3:
case 4:
if (iType == 3)
{
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
iInfo = cgi.MSG_ReadBits(6);
}
else
{
iInfo = 0;
}
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
iCount = cgi.MSG_ReadBits(6);
for (i = 0; i < iCount; ++i)
{
vEndArray[i][0] = cgi.MSG_ReadCoord();
vEndArray[i][1] = cgi.MSG_ReadCoord();
vEndArray[i][2] = cgi.MSG_ReadCoord();
}
if (iCount) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue, alpha);
}
break;
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
iLarge = cgi.MSG_ReadBits(2);
switch (iType)
{
case 6:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = -1;
wall_impact_count++;
}
break;
case 7:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 6;
wall_impact_count++;
}
break;
case 8:
if (flesh_impact_count < MAX_IMPACTS)
{
// negative
VectorNegate(vEnd, vEnd);
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
flesh_impact_large[flesh_impact_count] = iLarge;
flesh_impact_count++;
}
break;
case 9:
if (flesh_impact_count < MAX_IMPACTS)
{
// negative
VectorNegate(vEnd, vEnd);
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
flesh_impact_large[flesh_impact_count] = iLarge;
flesh_impact_count++;
}
break;
case 10:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 2;
wall_impact_count++;
}
break;
case 11:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 4;
wall_impact_count++;
}
break;
default:
continue;
}
break;
case 12:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
CG_MeleeImpact(vStart, vEnd);
break;
case 13:
case 14:
case 15:
case 16:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
CG_MakeExplosionEffect(vStart, iType);
break;
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
sfxManager.MakeEffect_Normal(iType + 67, vStart, vEnd);
break;
case 26:
case 27:
{
str sEffect;
char cTmp[8];
vec3_t axis[3];
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadByte();
// get the integer as string
snprintf(cTmp, sizeof(cTmp), "%d", iLarge);
if (iType == 23) {
sEffect = "models/fx/crates/debris_";
}
else {
sEffect = "models/fx/windows/debris_";
}
sEffect += cTmp;
sEffect += ".tik";
VectorSet(axis[0], 0, 0, 1);
VectorSet(axis[1], 0, 1, 0);
VectorSet(axis[2], 1, 0, 0);
cgi.R_SpawnEffectModel(sEffect.c_str(), vStart, axis);
}
break;
case 28:
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha);
break;
case 29:
memset(vTmp, 0, sizeof(vTmp));
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(1);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
break;
case 30:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString());
cgi.HudDrawElements[iInfo].string[0] = 0;
cgi.HudDrawElements[iInfo].pFont = NULL;
cgi.HudDrawElements[iInfo].fontName[0] = 0;
// set the shader
CG_HudDrawShader(iInfo);
break;
case 31:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2);
cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2);
break;
case 32:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iWidth = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort();
break;
case 33:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
break;
case 34:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
break;
case 35:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
break;
case 36:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].hShader = 0;
strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString());
break;
case 37:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString());
cgi.HudDrawElements[iInfo].hShader = 0;
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
// load the font
CG_HudDrawFont(iInfo);
break;
case 38:
case 39:
{
int iOldEnt;
iOldEnt = current_entity_number;
current_entity_number = cg.snap->ps.clientNum;
if (iType == 36) {
commandManager.PlaySound(
"dm_kill_notify",
NULL,
CHAN_LOCAL,
2.0,
-1,
-1,
1
);
}
else {
commandManager.PlaySound(
"dm_hit_notify",
NULL,
CHAN_LOCAL,
2.0,
-1,
-1,
1
);
}
current_entity_number = iOldEnt;
}
break;
case 40:
{
int iOldEnt;
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(1);
iInfo = cgi.MSG_ReadBits(6);
szTmp = cgi.MSG_ReadString();
iOldEnt = current_entity_number;
if (iLarge) {
current_entity_number = iInfo;
commandManager.PlaySound(
szTmp,
vStart,
CHAN_LOCAL,
-1,
-1,
-1,
0
);
}
else {
current_entity_number = cg.snap->ps.clientNum;
commandManager.PlaySound(
szTmp,
vStart,
CHAN_AUTO,
-1,
-1,
-1,
1
);
}
current_entity_number = iOldEnt;
}
break;
case 41:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadByte();
cgi.MSG_ReadByte();
VectorSubtract(vEnd, vStart, vTmp);
// FIXME: unimplemented
// ?? can't figure out what is this
break;
default:
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
break;
}
bMoreCGameMessages = cgi.MSG_ReadBits(1);
}
}
#else
void CG_ParseCGMessage()
{
int i;
@ -684,10 +1141,12 @@ void CG_ParseCGMessage()
current_entity_number = iOldEnt;
}
break;
default:
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
break;
}
bMoreCGameMessages = cgi.MSG_ReadBits(1);
}
// FIXME: unimplemented
}
#endif

View file

@ -25,6 +25,58 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
static const char* IsWeaponAllowed(int dmFlags, int flags) {
return (dmFlags & flags) ? "0" : "1";
}
static qboolean QueryLandminesAllowed2(const char* mapname, int dmflags) {
if (dmflags & DF_WEAPON_NO_LANDMINE) {
return qfalse;
}
if (dmflags & DF_WEAPON_LANDMINE_ALWAYS) {
return qtrue;
}
if (!Q_stricmpn(mapname, "obj/obj_", 8u))
return qfalse;
if (!Q_stricmpn(mapname, "dm/mohdm", 8u))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Bahnhof_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Ardennes_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Bazaar_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Berlin_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Brest_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Druckkammern_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Gewitter_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Flughafen_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Holland_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Malta_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Stadt_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Unterseite_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
return qfalse;
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
return qfalse;
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
return qfalse;
return qtrue;
}
/*
================
CG_ParseServerinfo
@ -39,6 +91,7 @@ void CG_ParseServerinfo(void)
const char* mapname;
char map[MAX_QPATH];
char* spawnpos;
const char* version;
info = CG_ConfigString(CS_SERVERINFO);
cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype"));
@ -48,6 +101,13 @@ void CG_ParseServerinfo(void)
cgs.timelimit = atoi(Info_ValueForKey(info, "timelimit"));
cgs.maxclients = atoi(Info_ValueForKey(info, "sv_maxclients"));
version = Info_ValueForKey(info, "version");
if (strstr(version, "Spearhead")) {
cgi.Cvar_Set("g_servertype", "1");
} else {
cgi.Cvar_Set("g_servertype", "2");
}
cgi.Cvar_Set("cg_gametype", Info_ValueForKey(info, "g_gametype"));
cgi.Cvar_Set("cg_fraglimit", Info_ValueForKey(info, "fraglimit"));
cgi.Cvar_Set("cg_timelimit", Info_ValueForKey(info, "timelimit"));
@ -60,9 +120,18 @@ void CG_ParseServerinfo(void)
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3"));
cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic"));
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
cgs.mapChecksum = Info_ValueForKey(info, "sv_mapChecksum");
mapname = Info_ValueForKey(info, "mapname");
cgi.Cvar_Set("cg_weapon_rifle", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_RIFLE));
cgi.Cvar_Set("cg_weapon_sniper", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SNIPER));
cgi.Cvar_Set("cg_weapon_mg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_MG));
cgi.Cvar_Set("cg_weapon_smg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SMG));
cgi.Cvar_Set("cg_weapon_rocket", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_ROCKET));
cgi.Cvar_Set("cg_weapon_shotgun", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SHOTGUN));
cgi.Cvar_Set("cg_weapon_landmine", QueryLandminesAllowed2(mapname, cgs.dmflags) ? "1" : "0");
spawnpos = strchr(mapname, '$');
if (spawnpos) {
Q_strncpyz(map, mapname, spawnpos - mapname + 1);
@ -152,7 +221,7 @@ CG_Stopwatch_f
*/
static void CG_Stopwatch_f()
{
if (cgi.Argc() != 3) {
if (cgi.Argc() < 3) {
Com_Error(1, "stopwatch didn't have 2 parameters");
}

View file

@ -46,7 +46,40 @@ static const char* AnimPrefixList[] =
"bazooka",
"panzerschreck",
"shotgun",
"unarmed"
"unarmed",
//
// Team Assault and Team Tactics weapons
"mg42portable",
"webley",
"nagantrev",
"beretta",
"enfield",
"svt",
"mosin",
"g43",
"enfieldl42a1",
"carcano",
"delisle",
"thompson",
"sten",
"ppsh",
"moschetto",
"fg42",
"vickers",
"breda",
"f1grenade",
"millsgrenade",
"nebelhandgranate",
"m18smokegrenade",
"rdg1smokegrenade",
"bomba",
"bombabreda",
"mine",
"minedetector",
"minedetectoraxis",
"detonator",
"kar98mortar",
"PIAT"
};
enum animPrefix_e
@ -69,7 +102,39 @@ enum animPrefix_e
WPREFIX_BAZOOKA,
WPREFIX_PANZERSCHRECK,
WPREFIX_SHOTGUN,
WPREFIX_UNARMED
WPREFIX_UNARMED,
//
// Team Assault and Team Tactics weapons
WPREFIX_MG42_PORTABLE,
WPREFIX_WEBLEY,
WPREFIX_NAGANTREV,
WPREFIX_BERETTA,
WPREFIX_ENFIELD,
WPREFIX_SVT,
WPREFIX_MOSIN,
WPREFIX_G43,
WPREFIX_ENFIELDL42A,
WPREFIX_CARCANO,
WPREFIX_DELISLE,
WPREFIX_STEN,
WPREFIX_PPSH,
WPREFIX_MOSCHETTO,
WPREFIX_FG42,
WPREFIX_VICKERS,
WPREFIX_BREDA,
WPREFIX_F1_GRENADE,
WPREFIX_MILLS_GRENADE,
WPREFIX_NEBELHANDGRANATE,
WPREFIX_M18_SMOKE_GRENADE,
WPREFIX_RDG1_SMOKE_GRENADE,
WPREFIX_BOMBA,
WPREFIX_BOMBA_BREDA,
WPREFIX_MINE,
WPREFIX_MINE_DETECTOR,
WPREFIX_MINE_DETECTOR_AXIS,
WPREFIX_DETONATOR,
WPREFIX_KAR98_MORTAR,
WPREFIX_PIAT
};
int CG_GetVMAnimPrefixIndex()
@ -83,7 +148,9 @@ int CG_GetVMAnimPrefixIndex()
if (iWeaponClass & WEAPON_CLASS_ANY_ITEM)
{
if (!Q_stricmp(szWeaponName, "Papers"))
return WPREFIX_PAPERS;
return WPREFIX_PAPERS;
if (!Q_stricmp(szWeaponName, "Packed MG42 Turret"))
return WPREFIX_MG42_PORTABLE;
}
else if (iWeaponClass & WEAPON_CLASS_PISTOL)
{
@ -92,7 +159,19 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "Walther P38"))
return WPREFIX_P38;
if (!Q_stricmp(szWeaponName, "Hi-Standard Silenced"))
return WPREFIX_HISTANDARD;
return WPREFIX_HISTANDARD;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Webley Revolver"))
return WPREFIX_WEBLEY;
if (!Q_stricmp(szWeaponName, "Nagant Revolver"))
return WPREFIX_NAGANTREV;
if (!Q_stricmp(szWeaponName, "Beretta"))
return WPREFIX_BERETTA;
return WPREFIX_COLT45;
}
else if (iWeaponClass & WEAPON_CLASS_RIFLE)
{
@ -103,28 +182,97 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "KAR98 - Sniper"))
return WPREFIX_KAR98SNIPER;
if (!Q_stricmp(szWeaponName, "Springfield '03 Sniper"))
return WPREFIX_SPRINGFIELD;
return WPREFIX_SPRINGFIELD;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Lee-Enfield"))
return WPREFIX_SPRINGFIELD;
if (!Q_stricmp(szWeaponName, "SVT 40"))
return WPREFIX_SVT;
if (!Q_stricmp(szWeaponName, "Mosin Nagant Rifle"))
return WPREFIX_MOSIN;
if (!Q_stricmp(szWeaponName, "G 43"))
return WPREFIX_G43;
if (!Q_stricmp(szWeaponName, "Enfield L42A1"))
return WPREFIX_ENFIELD;
if (!Q_stricmp(szWeaponName, "Carcano"))
return WPREFIX_CARCANO;
if (!Q_stricmp(szWeaponName, "DeLisle"))
return WPREFIX_DELISLE;
return WPREFIX_GARAND;
}
else if (iWeaponClass & WEAPON_CLASS_SMG)
{
if (!Q_stricmp(szWeaponName, "Thompson"))
return WPREFIX_THOMPSON;
if (!Q_stricmp(szWeaponName, "MP40"))
return WPREFIX_MP40;
return WPREFIX_MP40;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Sten Mark II"))
return WPREFIX_STEN;
if (!Q_stricmp(szWeaponName, "PPSH SMG"))
return WPREFIX_PPSH;
if (!Q_stricmp(szWeaponName, "Moschetto"))
return WPREFIX_MOSCHETTO;
return WPREFIX_THOMPSON;
}
else if (iWeaponClass & WEAPON_CLASS_MG)
{
if (!Q_stricmp(szWeaponName, "BAR"))
return WPREFIX_BAR;
if (!Q_stricmp(szWeaponName, "StG 44"))
return WPREFIX_MP44;
return WPREFIX_MP44;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "FG 42"))
return WPREFIX_MP44;
if (!Q_stricmp(szWeaponName, "Vickers-Berthier"))
return WPREFIX_MP44;
if (!Q_stricmp(szWeaponName, "Breda"))
return WPREFIX_MP44;
return WPREFIX_BAR;
}
else if (iWeaponClass & WEAPON_CLASS_GRENADE)
{
if (!Q_stricmp(szWeaponName, "Frag Grenade"))
return WPREFIX_FRAGGRENADE;
if (!Q_stricmp(szWeaponName, "Stielhandgranate"))
return WPREFIX_STIELHANDGRANATE;
return WPREFIX_STIELHANDGRANATE;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "F1 Grenade"))
return WPREFIX_F1_GRENADE;
if (!Q_stricmp(szWeaponName, "Mills Grenade"))
return WPREFIX_MILLS_GRENADE;
if (!Q_stricmp(szWeaponName, "Nebelhandgranate"))
return WPREFIX_NEBELHANDGRANATE;
if (!Q_stricmp(szWeaponName, "M18 Smoke Grenade"))
return WPREFIX_M18_SMOKE_GRENADE;
if (!Q_stricmp(szWeaponName, "RDG-1 Smoke Grenade"))
return WPREFIX_RDG1_SMOKE_GRENADE;
if (!Q_stricmp(szWeaponName, "Bomba A Mano"))
return WPREFIX_BOMBA;
if (!Q_stricmp(szWeaponName, "Bomba A Mano Breda"))
return WPREFIX_BOMBA_BREDA;
if (!Q_stricmp(szWeaponName, "LandmineAllies"))
return WPREFIX_MINE;
if (!Q_stricmp(szWeaponName, "LandmineAxis"))
return WPREFIX_MINE;
if (!Q_stricmp(szWeaponName, "Minensuchgerat"))
return WPREFIX_MINE_DETECTOR_AXIS;
if (!Q_stricmp(szWeaponName, "Minedetector"))
return WPREFIX_MINE_DETECTOR;
return WPREFIX_FRAGGRENADE;
}
else if (iWeaponClass & WEAPON_CLASS_HEAVY)
{
@ -133,7 +281,14 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "Panzerschreck"))
return WPREFIX_PANZERSCHRECK;
if (!Q_stricmp(szWeaponName, "Shotgun"))
return WPREFIX_SHOTGUN;
return WPREFIX_SHOTGUN;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "PIAT"))
return WPREFIX_PIAT;
return WPREFIX_BAZOOKA;
}
return WPREFIX_UNARMED;
@ -226,10 +381,22 @@ void CG_ViewModelAnimation(refEntity_t* pModel)
case VM_ANIM_LADDERSTEP:
pszAnimSuffix = "ladderstep";
break;
case VM_ANIM_IDLE:
case VM_ANIM_IDLE_0:
pszAnimSuffix = "idle0";
break;
case VM_ANIM_IDLE_1:
pszAnimSuffix = "idle1";
break;
case VM_ANIM_IDLE_2:
pszAnimSuffix = "idle2";
break;
case VM_ANIM_DISABLED:
pszAnimSuffix = "disabled";
break;
default:
pszAnimSuffix = "idle";
break;
case VM_ANIM_IDLE:
pszAnimSuffix = "idle";
break;
}
sprintf(szAnimName, "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix);

View file

@ -865,7 +865,7 @@ void CL_WritePacket( void ) {
for ( i = clc.reliableAcknowledge + 1 ; i <= clc.reliableSequence ; i++ ) {
MSG_WriteByte( &buf, clc_clientCommand );
MSG_WriteLong( &buf, i );
MSG_WriteString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
MSG_WriteScrambledString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
}
// we want to send all the usercmds that were generated in the last

View file

@ -1820,7 +1820,11 @@ wombat: sending conect here: an example connect string from MOHAA looks like thi
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
Info_SetValueForKey( info, "protocol", va("%i", PROTOCOL_VERSION ) );
Info_SetValueForKey( info, "qport", va("%i", port ) );
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
Info_SetValueForKey(info, "challenge", va("%i", clc.challenge));
Info_SetValueForKey(info, "version", TARGET_GAME_VERSION);
#if TARGET_GAME_TYPE == 2
Info_SetValueForKey(info, "clientType", "Breakthrough");
#endif
strcpy(data, "connect ");
// TTimo adding " " around the userinfo string to avoid truncated userinfo on the server

View file

@ -75,8 +75,7 @@ void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t
if ( unchanged ) {
*state = *old;
} else {
// FIXME: frametime
MSG_ReadDeltaEntity( msg, old, state, newnum, 0.0);
MSG_ReadDeltaEntity( msg, old, state, newnum, cls.serverFrameTime);
}
if ( state->number == (MAX_GENTITIES-1) ) {
@ -117,7 +116,7 @@ void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *n
while ( 1 ) {
// read the entity index number
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
newnum = MSG_ReadEntityNum(msg);
if ( newnum == (MAX_GENTITIES-1) ) {
break;
@ -274,11 +273,10 @@ void CL_ParseSnapshot( msg_t *msg ) {
// read playerinfo
SHOWNET(msg, "playerstate");
// FIXME: frametime
if ( old ) {
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, 0.0 );
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, cls.serverFrameTime );
} else {
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, 0.0);
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, cls.serverFrameTime);
}
// read packet entities
@ -446,6 +444,28 @@ static void CL_ParseServerInfo(void)
sizeof(clc.sv_dlURL));
}
#if TARGET_GAME_PROTOCOL >= 15
char* MSG_ReadGameStateChar(msg_t* msg) {
return MSG_ReadScrambledBigString(msg);
}
float MSG_ReadServerFrameTime(msg_t* msg) {
return MSG_ReadFloat(msg);
}
#else
char* MSG_ReadGameStateChar(msg_t* msg) {
return MSG_ReadString(msg);
}
float MSG_ReadServerFrameTime(msg_t* msg) {
return 1.f / atof(Info_ValueForKey(cl.gameState.stringData + cl.gameState.stringOffsets[CS_SYSTEMINFO], "sv_fps"));
}
#endif
/*
==================
CL_ParseGamestate
@ -488,7 +508,7 @@ void CL_ParseGamestate( msg_t *msg ) {
if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
}
s = MSG_ReadString( msg );
s = MSG_ReadGameStateChar( msg );
len = strlen( s );
if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
@ -499,7 +519,7 @@ void CL_ParseGamestate( msg_t *msg ) {
Com_Memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
cl.gameState.dataCount += len + 1;
} else if ( cmd == svc_baseline ) {
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
newnum = MSG_ReadEntityNum(msg);
if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
}
@ -516,6 +536,7 @@ void CL_ParseGamestate( msg_t *msg ) {
clc.clientNum = MSG_ReadLong(msg);
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
cls.serverFrameTime = MSG_ReadServerFrameTime(msg);
// parse serverId and other cvars
CL_SystemInfoChanged();
@ -727,7 +748,7 @@ void CL_ParseCommandString( msg_t *msg ) {
int index;
seq = MSG_ReadLong( msg );
s = MSG_ReadString( msg );
s = MSG_ReadScrambledString( msg );
// see if we have already executed stored it off
if ( clc.serverCommandSequence >= seq ) {
@ -764,10 +785,9 @@ void CL_ParseLocationprint( msg_t *msg ) {
x = MSG_ReadShort( msg );
y = MSG_ReadShort( msg );
string = MSG_ReadString(msg);
string = MSG_ReadScrambledString(msg);
// FIXME
//UI_UpdateLocationPrint( x, y, string, 1.0 );
UI_UpdateLocationPrint( x, y, string, 1.0 );
}
/*
@ -778,10 +798,10 @@ CL_ParseCenterprint
void CL_ParseCenterprint( msg_t *msg ) {
char *string;
string = MSG_ReadString( msg );
string = MSG_ReadScrambledString( msg );
// FIXME
//UI_UpdateCenterPrintf( string, 1.0 );
UI_UpdateCenterPrint( string, 1.0 );
}
/*

View file

@ -882,9 +882,9 @@ void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
}
if ( header.version != BSP_VERSION ) {
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
, name, header.version, BSP_VERSION );
if ( header.version < BSP_MIN_VERSION || header.version > BSP_MAX_VERSION ) {
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be between %i and %i)"
, name, header.version, BSP_MIN_VERSION, BSP_MAX_VERSION );
}
cmod_base = ( byte * )&header;

View file

@ -3068,7 +3068,7 @@ static void FS_ReorderPurePaks( void )
FS_Startup
================
*/
static void FS_Startup( const char *gameName )
static void FS_Startup(const char* gameName, const char* extensionName)
{
const char* homePath;
@ -3087,10 +3087,16 @@ static void FS_Startup( const char *gameName )
fs_gamedirvar = Cvar_Get( "fs_game", "", CVAR_INIT | CVAR_SYSTEMINFO );
fs_restrict = Cvar_Get( "fs_restrict", "", CVAR_INIT );
FS_AddGameDirectory( fs_basepath->string, gameName );
if (gameName) {
FS_AddGameDirectory(fs_basepath->string, gameName);
}
if( *fs_gamedirvar->string && !Q_stricmp( gameName, "main" ) && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
FS_AddGameDirectory( fs_basepath->string, fs_gamedirvar->string );
if (Q_stricmp(gameName, extensionName)) {
FS_AddGameDirectory(fs_basepath->string, extensionName);
}
if (*fs_gamedirvar->string && !Q_stricmp(gameName, GAME_EXTENSION_BASE) && Q_stricmp(fs_gamedirvar->string, gameName)) {
FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string);
}
fs_mapdir = Cvar_Get( "mapdir", "", 0 );
@ -3594,7 +3600,7 @@ void FS_InitFilesystem( void ) {
Com_StartupVariable( "fs_homepath" );
// try to start up normally
FS_Startup( BASEGAME );
FS_Startup( BASEGAME, GAME_EXTENSION_BASE);
FS_SetRestrictions();
if( !silentStart ) {
@ -3640,7 +3646,7 @@ void FS_Restart( int checksumFeed ) {
FS_ClearPakReferences(0);
// try to start up normally
FS_Startup( BASEGAME );
FS_Startup(BASEGAME, GAME_EXTENSION_BASE);
FS_CheckPak0( );

View file

@ -32,10 +32,10 @@ int oldsize = 0;
// TA stuff
//===================
static constexpr unsigned int MAX_PACKED_COORD = 65536;
static constexpr unsigned int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
static constexpr unsigned int MAX_PACKED_COORD_EXTRA = 262144;
static constexpr unsigned int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
static constexpr int MAX_PACKED_COORD = 65536;
static constexpr int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
static constexpr int MAX_PACKED_COORD_EXTRA = 262144;
static constexpr int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
//===
// Statistics for changes reporting
@ -327,8 +327,10 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
msg->readcount = (msg->bit>>3)+1;
}
if (sgn) {
if (value & (1 << (bits - 1))) {
value |= -1 ^ ((1 << bits) - 1);
if (value & 1) {
value = ~(value >> 1);
} else {
value >>= 1;
}
}
@ -417,6 +419,32 @@ void MSG_WriteString( msg_t *sb, const char *s ) {
}
}
void MSG_WriteBigString( msg_t *sb, const char *s ) {
if ( !s ) {
MSG_WriteByte(sb, 0);
} else {
size_t l;
int i;
char string[BIG_INFO_STRING];
l = strlen( s );
if ( l >= BIG_INFO_STRING ) {
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
MSG_WriteByte(sb, 0);
return;
}
Q_strncpyz( string, s, sizeof( string ) );
for ( i = 0 ; i <= l ; i++ ) {
MSG_WriteByte(sb, string[i]);
}
}
}
#if TARGET_GAME_PROTOCOL >= 15
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
if (!s) {
strstats[0]++;
@ -444,28 +472,6 @@ void MSG_WriteScrambledString(msg_t* sb, const char* s) {
}
}
void MSG_WriteBigString( msg_t *sb, const char *s ) {
if ( !s ) {
MSG_WriteByte(sb, 0);
} else {
size_t l;
int i;
char string[BIG_INFO_STRING];
l = strlen( s );
if ( l >= BIG_INFO_STRING ) {
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
MSG_WriteByte(sb, 0);
return;
}
Q_strncpyz( string, s, sizeof( string ) );
for ( i = 0 ; i <= l ; i++ ) {
MSG_WriteByte(sb, string[i]);
}
}
}
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
if (!s) {
strstats[0]++;
@ -493,6 +499,18 @@ void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
}
}
#else
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
return MSG_WriteString(sb, s);
}
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
return MSG_WriteBigString(sb, s);
}
#endif
void MSG_WriteAngle( msg_t *sb, float f ) {
MSG_WriteByte (sb, (int)(f*256/360) & 255);
}
@ -598,6 +616,8 @@ float MSG_ReadFloat( msg_t *msg ) {
return dat.f;
}
#if TARGET_GAME_PROTOCOL >= 15
char* MSG_ReadScrambledString(msg_t* msg) {
static char string[MAX_STRING_CHARS];
int l, c;
@ -610,6 +630,9 @@ char* MSG_ReadScrambledString(msg_t* msg) {
}
c = NetByteToStrChar[c];
if (!c) {
break;
}
// translate all fmt spec to avoid crash bugs
if (c == '%') {
c = '.';
@ -629,6 +652,52 @@ char* MSG_ReadScrambledString(msg_t* msg) {
return string;
}
char* MSG_ReadScrambledBigString(msg_t* msg) {
static char string[BIG_INFO_STRING];
int l, c;
l = 0;
do {
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
if (c == -1) {
break;
}
c = NetByteToStrChar[c];
if (!c) {
break;
}
// translate all fmt spec to avoid crash bugs
if (c == '%') {
c = '.';
}
// don't allow higher ascii values
// (su44: this check is missing in MoHAA)
if (c > 127) {
c = '.';
}
string[l] = c;
l++;
} while (l < sizeof(string) - 1);
string[l] = 0;
return string;
}
#else
char* MSG_ReadScrambledString(msg_t* msg) {
return MSG_ReadString(msg);
}
char* MSG_ReadScrambledBigString(msg_t* msg) {
return MSG_ReadBigString(msg);
}
#endif
char *MSG_ReadString( msg_t *msg ) {
static char string[MAX_STRING_CHARS];
int l,c;
@ -1171,6 +1240,157 @@ typedef struct {
// using the stringizing operator to save typing...
#define NETF(x) #x,(size_t)&((entityState_t*)0)->x
#if TARGET_GAME_PROTOCOL >= 15
netField_t entityStateFields[] =
{
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
{ NETF(netorigin[1]), 0, netFieldType_t::coord },
{ NETF(netangles[1]), 12, netFieldType_t::angle },
{ NETF(frameInfo[0].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[1].time), 15, netFieldType_t::animTime },
{ NETF(bone_angles[0][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[1][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][0]), -13, netFieldType_t::angle },
{ NETF(netorigin[2]), 0, netFieldType_t::coord },
{ NETF(frameInfo[0].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[1].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[3].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[0].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[1].index), 12, netFieldType_t::regular },
{ NETF(actionWeight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[3].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[3].index), 12, netFieldType_t::regular },
{ NETF(eType), 8, netFieldType_t::regular },
{ NETF(modelindex), 16, netFieldType_t::regular },
{ NETF(parent), 16, netFieldType_t::regular },
{ NETF(constantLight), 32, netFieldType_t::regular },
{ NETF(renderfx), 32, netFieldType_t::regular },
{ NETF(bone_tag[0]), -8, netFieldType_t::regular },
{ NETF(bone_tag[1]), -8, netFieldType_t::regular },
{ NETF(bone_tag[2]), -8, netFieldType_t::regular },
{ NETF(bone_tag[3]), -8, netFieldType_t::regular },
{ NETF(bone_tag[4]), -8, netFieldType_t::regular },
{ NETF(scale), 10, netFieldType_t::scale },
{ NETF(alpha), 8, netFieldType_t::alpha },
{ NETF(usageIndex), 16, netFieldType_t::regular },
{ NETF(eFlags), 16, netFieldType_t::regular },
{ NETF(solid), 32, netFieldType_t::regular },
{ NETF(netangles[2]), 12, netFieldType_t::angle },
{ NETF(netangles[0]), 12, netFieldType_t::angle },
{ NETF(tag_num), 10, netFieldType_t::regular },
{ NETF(bone_angles[1][2]), -13, netFieldType_t::angle },
{ NETF(attach_use_angles), 1, netFieldType_t::regular },
{ NETF(origin2[1]), 0, netFieldType_t::coord },
{ NETF(origin2[0]), 0, netFieldType_t::coord },
{ NETF(origin2[2]), 0, netFieldType_t::coord },
{ NETF(bone_angles[0][2]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][2]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][2]), -13, netFieldType_t::angle },
{ NETF(surfaces[0]), 8, netFieldType_t::regular },
{ NETF(surfaces[1]), 8, netFieldType_t::regular },
{ NETF(surfaces[2]), 8, netFieldType_t::regular },
{ NETF(surfaces[3]), 8, netFieldType_t::regular },
{ NETF(bone_angles[0][1]), -13, netFieldType_t::angle },
{ NETF(surfaces[4]), 8, netFieldType_t::regular },
{ NETF(surfaces[5]), 8, netFieldType_t::regular },
{ NETF(pos.trTime), 32, netFieldType_t::regular },
{ NETF(pos.trDelta[0]), 0, netFieldType_t::velocity },
{ NETF(pos.trDelta[1]), 0, netFieldType_t::velocity },
{ NETF(pos.trDelta[2]), 0, netFieldType_t::velocity },
{ NETF(loopSound), 16, netFieldType_t::regular },
{ NETF(loopSoundVolume), 0, netFieldType_t::regular },
{ NETF(loopSoundMinDist), 0, netFieldType_t::regular },
{ NETF(loopSoundMaxDist), 0, netFieldType_t::regular },
{ NETF(loopSoundPitch), 0, netFieldType_t::regular },
{ NETF(loopSoundFlags), 8, netFieldType_t::regular },
{ NETF(attach_offset[0]), 0, netFieldType_t::regular },
{ NETF(attach_offset[1]), 0, netFieldType_t::regular },
{ NETF(attach_offset[2]), 0, netFieldType_t::regular },
{ NETF(beam_entnum), 16, netFieldType_t::regular },
{ NETF(skinNum), 16, netFieldType_t::regular },
{ NETF(wasframe), 10, netFieldType_t::regular },
{ NETF(frameInfo[4].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[5].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[6].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[7].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[8].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[9].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[10].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[11].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[12].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[13].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[14].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[15].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[4].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[5].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[6].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[7].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[8].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[9].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[10].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[11].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[12].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[13].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[14].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[15].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[4].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[5].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[6].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[7].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[8].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[9].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[10].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[11].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[12].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[13].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[14].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[15].weight), 8, netFieldType_t::animWeight },
{ NETF(bone_angles[1][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][2]), -13, netFieldType_t::angle },
{ NETF(clientNum), 8, netFieldType_t::regular },
{ NETF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
{ NETF(shader_data[0]), 0, netFieldType_t::regular },
{ NETF(shader_data[1]), 0, netFieldType_t::regular },
{ NETF(shader_time), 0, netFieldType_t::regular },
{ NETF(eyeVector[0]), 0, netFieldType_t::regular },
{ NETF(eyeVector[1]), 0, netFieldType_t::regular },
{ NETF(eyeVector[2]), 0, netFieldType_t::regular },
{ NETF(surfaces[6]), 8, netFieldType_t::regular },
{ NETF(surfaces[7]), 8, netFieldType_t::regular },
{ NETF(surfaces[8]), 8, netFieldType_t::regular },
{ NETF(surfaces[9]), 8, netFieldType_t::regular },
{ NETF(surfaces[10]), 8, netFieldType_t::regular },
{ NETF(surfaces[11]), 8, netFieldType_t::regular },
{ NETF(surfaces[12]), 8, netFieldType_t::regular },
{ NETF(surfaces[13]), 8, netFieldType_t::regular },
{ NETF(surfaces[14]), 8, netFieldType_t::regular },
{ NETF(surfaces[15]), 8, netFieldType_t::regular },
{ NETF(surfaces[16]), 8, netFieldType_t::regular },
{ NETF(surfaces[17]), 8, netFieldType_t::regular },
{ NETF(surfaces[18]), 8, netFieldType_t::regular },
{ NETF(surfaces[19]), 8, netFieldType_t::regular },
{ NETF(surfaces[20]), 8, netFieldType_t::regular },
{ NETF(surfaces[21]), 8, netFieldType_t::regular },
{ NETF(surfaces[22]), 8, netFieldType_t::regular },
{ NETF(surfaces[23]), 8, netFieldType_t::regular },
{ NETF(surfaces[24]), 8, netFieldType_t::regular },
{ NETF(surfaces[25]), 8, netFieldType_t::regular },
{ NETF(surfaces[26]), 8, netFieldType_t::regular },
{ NETF(surfaces[27]), 8, netFieldType_t::regular },
{ NETF(surfaces[28]), 8, netFieldType_t::regular },
{ NETF(surfaces[29]), 8, netFieldType_t::regular },
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
};
#else
netField_t entityStateFields[] =
{
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
@ -1320,6 +1540,7 @@ netField_t entityStateFields[] =
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
};
#endif
static constexpr unsigned long numEntityFields = sizeof(entityStateFields) / sizeof(entityStateFields[0]);
// if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
@ -1343,22 +1564,25 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
if (!MSG_ReadBits(sb, 1))
{
// integral float
int32_t truncFloat = MSG_ReadBits(sb, -FLOAT_INT_BITS);
// bias to allow equal parts positive and negative
truncFloat -= FLOAT_INT_BIAS;
*(float*)toF = (float)truncFloat;
*(float*)toF = MSG_ReadBits(sb, -FLOAT_INT_BITS);
}
else
{
// full floating point value
*(float*)toF = MSG_ReadFloat(sb);
unsigned int v = MSG_ReadBits(sb, 32);
if (v & 1) {
*(int*)toF = ((v + 0x7A000000) >> 1) | 0x80000000;
}
else {
*(int*)toF = (v + 0x7A000000) >> 1;
}
}
}
}
else
{
if (MSG_ReadBits(msg, 1)) {
*(int*)toF = MSG_ReadBits(msg, bits);
if (MSG_ReadBits(sb, 1)) {
*(int*)toF = MSG_ReadBits(sb, bits);
}
else {
*(int*)toF = 0;
@ -1366,6 +1590,11 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
}
}
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
{
MSG_ReadRegular(sb, bits, toF);
}
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
{
float fullFloat;
@ -1418,9 +1647,9 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
MSG_WriteBits(sb, (number + 1) % MAX_GENTITIES, GENTITYNUM_BITS);
}
short MSG_ReadEntityNum(msg_t* sb)
unsigned short MSG_ReadEntityNum(msg_t* sb)
{
return (MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
return (unsigned short)(MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
}
#else
@ -1436,7 +1665,7 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
else
{
if (!MSG_ReadBits(sb, 1)) {
*(float*)toF = (float)MSG_ReadBits(sb, FLOAT_INT_BITS);
*(float*)toF = (int)MSG_ReadBits(sb, FLOAT_INT_BITS) - FLOAT_INT_BIAS;
}
else
{
@ -1456,6 +1685,28 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
}
}
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
{
if (bits == 0) {
// float
if (MSG_ReadBits(sb, 1) == 0) {
// integral float
int trunc = MSG_ReadBits(sb, FLOAT_INT_BITS);
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float*)toF = trunc;
}
else {
// full floating point value
*(int*)toF = MSG_ReadBits(sb, 32);
}
}
else {
// integer
*(int*)toF = MSG_ReadBits(sb, bits);
}
}
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
{
float fullFloat;
@ -1530,7 +1781,7 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
MSG_WriteBits(sb, number % MAX_GENTITIES, GENTITYNUM_BITS);
}
short MSG_ReadEntityNum(msg_t* sb)
unsigned short MSG_ReadEntityNum(msg_t* sb)
{
return MSG_ReadBits(sb, GENTITYNUM_BITS) % MAX_GENTITIES;
}
@ -1568,7 +1819,7 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity
if ( from == NULL ) {
return;
}
MSG_WriteBits( msg, from->number, GENTITYNUM_BITS );
MSG_WriteEntityNum(msg, to->number);
MSG_WriteBits( msg, 1, 1 );
return;
}
@ -1813,6 +2064,55 @@ int MSG_PackCoordExtra(float coord)
#if TARGET_GAME_PROTOCOL >= 15
float MSG_ReadPackedAngle(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAngle(packed, bits);
}
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
{
int packed;
if (!MSG_ReadBits(msg, 1)) {
return fromValue + frameTime;
}
packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAnimTime(packed);
}
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAnimWeight(packed, bits);
}
float MSG_ReadPackedScale(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackScale(packed);
}
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAlpha(packed, bits);
}
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoord(fromValue);
int packedTo = MSG_ReadDeltaCoord(msg, packedFrom);
return MSG_UnpackCoord(packedTo, bits);
}
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoordExtra(fromValue);
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
return MSG_UnpackCoordExtra(packedTo, bits);
}
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
{
int packed = MSG_PackAngle(value, bits);
@ -1823,7 +2123,7 @@ void MSG_WritePackedAnimTime(msg_t* msg, float fromValue, float toValue, float f
{
int packed;
if (abs(fromValue - toValue) < frameTime) {
if (fabs(fromValue - toValue) < frameTime) {
// below the frame time, don't send
MSG_WriteBits(msg, 0, 1);
}
@ -1923,6 +2223,80 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
#else
float MSG_ReadPackedAngle(msg_t* msg, int bits)
{
int result;
float tmp = 1.0f;
if (bits < 0) {
if (MSG_ReadBits(msg, 1))
tmp = -1.0f;
bits = ~bits;
}
result = MSG_ReadBits(msg, bits);
switch (bits)
{
case 8:
return tmp * 360.f / 256.f;
case 12:
return tmp * result * 360.f / 4096.f;
case 16:
return tmp * result * 360.f / 65536.f;
default:
return tmp * 360.f / (1 << bits) * result;
}
}
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
{
return MSG_ReadBits(msg, 15) / 100.0f;
}
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
{
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
if (tmp < 0.0f)
return 0.0f;
else if (tmp > 1.0f)
return 1.0f;
else
return tmp;
}
float MSG_ReadPackedScale(msg_t* msg, int bits)
{
return MSG_ReadBits(msg, 10) / 100.0f;
}
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
{
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
if (tmp < 0.0f)
return 0.0f;
else if (tmp > 1.0f)
return 1.0f;
else
return tmp;
}
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
{
float tmp = 1.0f;
int value = MSG_ReadBits(msg, 19);
if (value & 262144) // test for 19th bit
tmp = -1.0f;
value &= ~262144; // remove that bit
return tmp * value / 16.0f;
}
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoordExtra(fromValue);
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
return MSG_UnpackCoordExtra(packedTo, bits);
}
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
{
// angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
@ -2044,6 +2418,25 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
#endif
float MSG_ReadPackedVelocity(msg_t* msg, int bits)
{
float tmp = 1.0f;
int value = MSG_ReadBits(msg, 17);
if (value & 65536) // test for 17th bit
tmp = -1.0f;
value &= ~65536; // remove that bit
return tmp * value / 8.0f;
}
int MSG_ReadPackedSimple(msg_t* msg, int fromValue, int bits)
{
if (!MSG_ReadBits(msg, 1)) {
return fromValue;
}
return MSG_ReadBits(msg, bits);
}
void MSG_WritePackedVelocity(msg_t* msg, float value, int bits)
{
int32_t packed = (uint32_t)(value * 8.0f);
@ -2159,106 +2552,34 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to,
} else {
switch (field->type) {
case netFieldType_e::regular:
if ( field->bits == 0 ) {
// float
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
*(float *)toF = 0.0f;
} else {
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
// integral float
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float *)toF = trunc;
if ( print ) {
Com_Printf( "%s:%i ", field->name, trunc );
}
} else {
// full floating point value
*toF = MSG_ReadBits( msg, 32 );
if ( print ) {
Com_Printf( "%s:%f ", field->name, *(float *)toF );
}
}
}
} else {
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
*toF = 0;
} else {
// integer
*toF = MSG_ReadBits( msg, field->bits );
if ( print ) {
Com_Printf( "%s:%i ", field->name, *toF );
}
}
}
MSG_ReadRegular(msg, field->bits, toF);
break;
case netFieldType_e::angle: // angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
tmp = 1.0f;
if ( field->bits < 0 ) {
if ( MSG_ReadBits( msg, 1 ) )
tmp = -1.0f;
bits = ~field->bits;
}
else bits = field->bits;
result = MSG_ReadBits(msg, bits);
switch (bits)
{
case 8:
*(float*)toF = tmp * 360.f / 256.f;
break;
case 12:
*(float*)toF = tmp * result * 360.f / 4096.f;
break;
case 16:
*(float*)toF = tmp * result * 360.f / 65536.f;
break;
default:
*(float*)toF = tmp * 360.f / (1 << bits) * result;
break;
}
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
break;
case netFieldType_e::animTime: // time
*(float *)toF = MSG_ReadBits( msg, 15 ) * 0.0099999998f;
*(float*)toF = MSG_ReadPackedAnimTime(msg, field->bits, *(float*)fromF, frameTime);
break;
case netFieldType_e::animWeight: // nasty!
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
if ( tmp < 0.0f )
*(float *)toF = 0.0f;
else if ( tmp > 1.0f )
*(float *)toF = 1.0f;
else
*(float *)toF = tmp;
// FPU instructions yay
*(float*)toF = MSG_ReadPackedAnimWeight(msg, field->bits);
break;
case netFieldType_e::scale:
*(float *)toF = MSG_ReadBits( msg, 10 ) *0.0099999998f;
*(float*)toF = MSG_ReadPackedScale(msg, field->bits);
break;
case netFieldType_e::alpha:
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
if ( tmp < 0.0f )
*(float *)toF = 0.0f;
else if ( tmp > 1.0f )
*(float *)toF = 1.0f;
else
*(float *)toF = tmp;
*(float*)toF = MSG_ReadPackedAlpha(msg, field->bits);
break;
case netFieldType_e::coord:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 19 );
if ( bits & 262144 ) // test for 19th bit
tmp = -1.0f;
bits &= ~262144; // remove that bit
*(float *)toF = tmp * bits / 16.0f;
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::coordExtra:
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::velocity:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 17 );
if ( bits & 65536 ) // test for 17th bit
tmp = -1.0f;
bits &= ~65536; // remove that bit
*(float *)toF = tmp * bits / 8.0f;
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
break;
case netFieldType_e::simple:
*(int*)toF = MSG_ReadPackedSimple(msg, *(int*)fromF, field->bits);
break;
default:
Com_Error( ERR_DROP, "MSG_ReadDeltaEntity: unrecognized entity field type %i for field\n", i );
@ -2336,6 +2657,16 @@ float MSG_UnpackAnimTime(int packed)
return packed / 100.f;
}
float MSG_UnpackAnimWeight(int result, int bits)
{
const int32_t max = (1 << bits) - 1;
const float tmp = (float)result / (float)max;
if (tmp < 0.0f) return 0.f;
else if (tmp > 1.0f) return 1.f;
else return tmp;
}
float MSG_UnpackScale(int packed)
{
return packed / 100.f;
@ -2508,6 +2839,66 @@ plyer_state_t communication
// using the stringizing operator to save typing...
#define PSF(x) #x,(size_t)&((playerState_t*)0)->x
#if TARGET_GAME_PROTOCOL >= 15
netField_t playerStateFields[] =
{
{ PSF(commandTime), 32, netFieldType_t::regular },
{ PSF(origin[0]), 0, netFieldType_t::coordExtra },
{ PSF(origin[1]), 0, netFieldType_t::coordExtra },
{ PSF(viewangles[1]), 0, netFieldType_t::regular },
{ PSF(velocity[1]), 0, netFieldType_t::velocity },
{ PSF(velocity[0]), 0, netFieldType_t::velocity },
{ PSF(viewangles[0]), 0, netFieldType_t::regular },
{ PSF(origin[2]), 0, netFieldType_t::coordExtra },
{ PSF(velocity[2]), 0, netFieldType_t::velocity },
{ PSF(iViewModelAnimChanged), 2, netFieldType_t::regular },
{ PSF(damage_angles[0]), -13, netFieldType_t::angle },
{ PSF(damage_angles[1]), -13, netFieldType_t::angle },
{ PSF(damage_angles[2]), -13, netFieldType_t::angle },
{ PSF(speed), 16, netFieldType_t::regular },
{ PSF(delta_angles[1]), 16, netFieldType_t::regular },
{ PSF(viewheight), -8, netFieldType_t::regular },
{ PSF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
{ PSF(delta_angles[0]), 16, netFieldType_t::regular },
{ PSF(iViewModelAnim), 4, netFieldType_t::regular },
{ PSF(fov), 0, netFieldType_t::regular },
{ PSF(current_music_mood), 8, netFieldType_t::regular },
{ PSF(gravity), 16, netFieldType_t::regular },
{ PSF(fallback_music_mood), 8, netFieldType_t::regular },
{ PSF(music_volume), 0, netFieldType_t::regular },
{ PSF(pm_flags), 16, netFieldType_t::regular },
{ PSF(clientNum), 8, netFieldType_t::regular },
{ PSF(fLeanAngle), 0, netFieldType_t::regular },
{ PSF(blend[3]), 0, netFieldType_t::regular },
{ PSF(blend[0]), 0, netFieldType_t::regular },
{ PSF(pm_type), 8, netFieldType_t::regular },
{ PSF(feetfalling), 8, netFieldType_t::regular },
{ PSF(radarInfo), 26, netFieldType_t::regular },
{ PSF(camera_angles[0]), 16, netFieldType_t::angle },
{ PSF(camera_angles[1]), 16, netFieldType_t::angle },
{ PSF(camera_angles[2]), 16, netFieldType_t::angle },
{ PSF(camera_origin[0]), 0, netFieldType_t::coordExtra },
{ PSF(camera_origin[1]), 0, netFieldType_t::coordExtra },
{ PSF(camera_origin[2]), 0, netFieldType_t::coordExtra },
{ PSF(camera_posofs[0]), 0, netFieldType_t::coordExtra },
{ PSF(camera_posofs[2]), 0, netFieldType_t::coordExtra },
{ PSF(camera_time), 0, netFieldType_t::regular },
{ PSF(voted), 1, netFieldType_t::regular },
{ PSF(bobCycle), 8, netFieldType_t::regular },
{ PSF(delta_angles[2]), 16, netFieldType_t::regular },
{ PSF(viewangles[2]), 0, netFieldType_t::regular },
{ PSF(music_volume_fade_time), 0, netFieldType_t::regular },
{ PSF(reverb_type), 6, netFieldType_t::regular },
{ PSF(reverb_level), 0, netFieldType_t::regular },
{ PSF(blend[1]), 0, netFieldType_t::regular },
{ PSF(blend[2]), 0, netFieldType_t::regular },
{ PSF(camera_offset[0]), 0, netFieldType_t::regular },
{ PSF(camera_offset[1]), 0, netFieldType_t::regular },
{ PSF(camera_offset[2]), 0, netFieldType_t::regular },
{ PSF(camera_posofs[1]), 0, netFieldType_t::coordExtra },
{ PSF(camera_flags), 16, netFieldType_t::regular }
};
#else
netField_t playerStateFields[] =
{
{ PSF(commandTime), 32, netFieldType_t::regular },
@ -2566,6 +2957,7 @@ netField_t playerStateFields[] =
{ PSF(camera_posofs[1]), 0, netFieldType_t::coord },
{ PSF(camera_flags), 16, netFieldType_t::regular }
};
#endif
/*
=============
@ -2800,88 +3192,29 @@ void MSG_ReadDeltaPlayerstate(msg_t *msg, playerState_t *from, playerState_t *to
numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
lc = MSG_ReadByte(msg);
//Com_DPrintf( "===\nMSG_ReadDeltaPlayerstate: count %i\n===\n", lc );
assert(lc <= numFields);
for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
fromF = (int *)( (byte *)from + field->offset );
toF = (int *)( (byte *)to + field->offset );
//Com_DPrintf( "field %s ", field->name );
if ( ! MSG_ReadBits( msg, 1 ) ) {
// no change
*toF = *fromF;
//Com_DPrintf( "NO CHANGE " );
//Com_DPrintf( "value int %i, float %f\n", *toF, *(float *)toF );
} else {
//Com_DPrintf( "type %i, ", field->type );
switch ( field->type ) {
case netFieldType_e::regular:
if ( field->bits == 0 ) {
// float
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
// integral float
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float *)toF = trunc;
if ( print ) {
Com_Printf( "%s:%i ", field->name, trunc );
}
} else {
// full floating point value
*toF = MSG_ReadBits( msg, 32 );
if ( print ) {
Com_Printf( "%s:%f ", field->name, *(float *)toF );
}
}
} else {
// integer
*toF = MSG_ReadBits( msg, field->bits );
if ( print ) {
Com_Printf( "%s:%i ", field->name, *toF );
}
}
MSG_ReadRegularSimple(msg, field->bits, toF);
break;
case netFieldType_e::angle:
tmp = 1.0f;
if ( field->bits < 0 ) {
if ( MSG_ReadBits( msg, 1 ) )
tmp = -1.0f;
bits = - field->bits -1;
}
else bits = field->bits;
result = MSG_ReadBits(msg, bits);
switch (bits)
{
case 8:
*(float*)toF = tmp * 360.f / 256.f;
break;
case 12:
*(float*)toF = tmp * result * 360.f / 4096.f;
break;
case 16:
*(float*)toF = tmp * result * 360.f / 65536.f;
break;
default:
*(float*)toF = tmp * 360.f / (1 << bits) * result;
break;
}
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
break;
case netFieldType_e::coord:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 19 );
if ( bits & 262144 ) // test for 19th bit
tmp = -1.0f;
bits &= ~262144; // 4294705151; // remove that bit
*(float *)toF = tmp * bits / 16.0f;
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::coordExtra:
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::velocity:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 17 );
if ( bits & 65536 ) // test for 17th bit
tmp = -1.0f;
bits &= ~65536; // 4294901759; // remove that bit
*(float *)toF = tmp * bits / 8.0f;
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
break;
default:
break;

View file

@ -47,6 +47,8 @@ extern "C" {
#define PRODUCT_VERSION PRODUCT_VERSION_NUMBER_STRING "-" PRODUCT_VERSION_STAGE
#define PRODUCT_DATE __DATE__
#define BASEGAME "main"
//
// The target type specifies which content pack the engine targets.
//
@ -57,7 +59,7 @@ extern "C" {
//
// Team Assault
//
#define BASEGAME "mainta"
#define GAME_EXTENSION_BASE "mainta"
#define PRODUCT_EXTENSION "spearhead"
// The version string must be equal or above 2.0 to be able to connect to spearhead servers
#define TARGET_GAME_VERSION "2.16"
@ -71,7 +73,7 @@ extern "C" {
//
// Team Tactics
//
#define BASEGAME "maintt"
#define GAME_EXTENSION_BASE "maintt"
#define PRODUCT_EXTENSION "breakthrough"
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
#define TARGET_GAME_VERSION "2.41"
@ -85,8 +87,8 @@ extern "C" {
//
// Base game
//
#define BASEGAME "main"
#define GAME_EXTENSION_BASE "main"
#define PRODUCT_EXTENSION "base"
// The version string must be 1.1x or below, otherwise it's not possible to connect
#define TARGET_GAME_VERSION "1.12"
@ -1729,6 +1731,11 @@ typedef struct playerState_s {
float camera_posofs[3];
int camera_flags;
float damage_angles[3];
// --
// Team Assault
int radarInfo;
qboolean voted;
// --
// not communicated over the net at all
int ping; // server to game info for scoreboard
@ -2056,20 +2063,6 @@ typedef struct hdelement_s {
struct fontheader_s *pFont;
} hdelement_t;
enum vmAnim_e {
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP
};
typedef struct {
frameInfo_t g_VMFrameInfo[MAX_FRAMEINFOS];

View file

@ -83,6 +83,8 @@ void MSG_WriteLong (msg_t *sb, int c);
void MSG_WriteFloat (msg_t *sb, float f);
void MSG_WriteString (msg_t *sb, const char *s);
void MSG_WriteBigString (msg_t *sb, const char *s);
void MSG_WriteScrambledString(msg_t* sb, const char* s);
void MSG_WriteScrambledBigString(msg_t* sb, const char* s);
void MSG_WriteAngle16 (msg_t *sb, float f);
void MSG_BeginReading (msg_t *sb);
@ -104,9 +106,12 @@ float MSG_ReadFloat (msg_t *sb);
char *MSG_ReadString (msg_t *sb);
char *MSG_ReadBigString (msg_t *sb);
char *MSG_ReadStringLine( msg_t *sb );
char* MSG_ReadScrambledString(msg_t* msg);
char* MSG_ReadScrambledBigString(msg_t* msg);
float MSG_ReadAngle8( msg_t *sb );
float MSG_ReadAngle16 (msg_t *sb);
void MSG_ReadData (msg_t *sb, void *buffer, int size);
unsigned short MSG_ReadEntityNum(msg_t* sb);
void MSG_WriteDeltaUsercmd( msg_t *msg, struct usercmd_s *from, struct usercmd_s *to );
@ -158,6 +163,7 @@ void MSG_WritePackedSimple(msg_t* msg, int value, int bits);
float MSG_UnpackAngle(int value, int bits);
float MSG_UnpackAnimTime(int packed);
float MSG_UnpackAnimWeight(int result, int bits);
float MSG_UnpackScale(int packed);
float MSG_UnpackAlpha(int packed, int bits);
float MSG_UnpackCoord(int packed, int bits);