Q1 - problem with Stats and demos
Moderator: InsideQC Admins
4 posts
• Page 1 of 1
Q1 - problem with Stats and demos
Hello everyone :>
I'm trying to make an engine based on NetQuake, cross-compilable for PC, PSP, and Wii, just for some educationnal purposes.
To begin with, I only started from an older PSP engine of Quake, and adapted-it from the original NQ source, to finish using some old sources of QuakeWii... I needed to know how to adapt X or Y thing...
I've implanted some features from QuakeWorld and a very few from ProQuake (exactly the client recording ingame and a more precise aiming angle fix), but I'm also trying to implant new elements, and trying to remake the QuakeC source to be more "mod"-flexible.
But I have a problem about one feature.
I've implanted an Alt. Ammo System on the HUD, like on HL1 with the mp5.
So I've added STAT_ALTAMMO to the stats on Quakedef.h , as well as adding from Client_state_t altammo_items .
I also added to protocol.h a new SU_ bit
I've linked from sv_main to cl_parse the Msg_ReadLong message, and the status bar seems to read it. It seems it works well.

However, when I'm trying to record ingame, and playdemo it, the only message I get is
I'm quite sure I forgot to adapt something in particular... But yet, I don't know exactly what.
I also modified a bit the QuakeC source, but it's not the source of the problem, since I have recorded and playdemo'd it well.
Here's what I modified in cl_parse.c
and in Sv_main.c ...
Thanks in advance.
I'm trying to make an engine based on NetQuake, cross-compilable for PC, PSP, and Wii, just for some educationnal purposes.
To begin with, I only started from an older PSP engine of Quake, and adapted-it from the original NQ source, to finish using some old sources of QuakeWii... I needed to know how to adapt X or Y thing...
I've implanted some features from QuakeWorld and a very few from ProQuake (exactly the client recording ingame and a more precise aiming angle fix), but I'm also trying to implant new elements, and trying to remake the QuakeC source to be more "mod"-flexible.
But I have a problem about one feature.
I've implanted an Alt. Ammo System on the HUD, like on HL1 with the mp5.
So I've added STAT_ALTAMMO to the stats on Quakedef.h , as well as adding from Client_state_t altammo_items .
I also added to protocol.h a new SU_ bit
- Code: Select all
#define SU_ALTITEMS (1<<15)
I've linked from sv_main to cl_parse the Msg_ReadLong message, and the status bar seems to read it. It seems it works well.

However, when I'm trying to record ingame, and playdemo it, the only message I get is
- Code: Select all
HOST_ERROR: CL_ParseServerMessage: Bad server message
I'm quite sure I forgot to adapt something in particular... But yet, I don't know exactly what.
I also modified a bit the QuakeC source, but it's not the source of the problem, since I have recorded and playdemo'd it well.
Here's what I modified in cl_parse.c
- Code: Select all
/*
==================
CL_ParseClientdata
Server information pertaining to this client only
==================
*/
void CL_ParseClientdata (int bits)
{
int i, j;
if (bits & SU_VIEWHEIGHT)
cl.viewheight = MSG_ReadChar ();
else
cl.viewheight = DEFAULT_VIEWHEIGHT;
if (bits & SU_IDEALPITCH)
cl.idealpitch = MSG_ReadChar ();
else
cl.idealpitch = 0;
VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i) )
cl.punchangle[i] = MSG_ReadChar();
else
cl.punchangle[i] = 0;
if (bits & (SU_VELOCITY1<<i) )
cl.mvelocity[0][i] = MSG_ReadChar()*16;
else
cl.mvelocity[0][i] = 0;
}
// [always sent] if (bits & SU_ITEMS)
i = MSG_ReadLong ();
if (cl.items != i)
{ // set flash times
Sbar_Changed ();
for (j=0 ; j<32 ; j++)
if ( (i & (1<<j)) && !(cl.items & (1<<j)))
cl.item_gettime[j] = cl.time;
cl.items = i;
}
//*CH0WW : PLEASE FIX AMMO ONLY !!! */
i = MSG_ReadLong ();
if (cl.altammo_items != i)
{ // set flash times
Sbar_Changed ();
cl.altammo_items = i;
}
cl.onground = (bits & SU_ONGROUND) != 0;
cl.inwater = (bits & SU_INWATER) != 0;
if (bits & SU_WEAPONFRAME)
cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
else
cl.stats[STAT_WEAPONFRAME] = 0;
if (bits & SU_ARMOR)
i = MSG_ReadByte ();
else
i = 0;
if (cl.stats[STAT_ARMOR] != i)
{
cl.stats[STAT_ARMOR] = i;
Sbar_Changed ();
}
if (bits & SU_WEAPON)
i = MSG_ReadByte ();
else
i = 0;
if (cl.stats[STAT_WEAPON] != i)
{
cl.stats[STAT_WEAPON] = i;
Sbar_Changed ();
}
i = MSG_ReadShort ();
if (cl.stats[STAT_HEALTH] != i)
{
cl.stats[STAT_HEALTH] = i;
Sbar_Changed ();
}
i = MSG_ReadByte (); // Read ammo byte
if (cl.stats[STAT_AMMO] != i) // if it changed...
{
cl.stats[STAT_AMMO] = i; // Update it!
Sbar_Changed ();
}
//----- Ch0wW : Addition of AltAmmo HUD -- MSG_WriteByte (msg, ent->v.currentammo_sec);
i = MSG_ReadByte ();
if (cl.stats[STAT_ALTAMMO] != i)
{
cl.stats[STAT_ALTAMMO] = i;
Sbar_Changed ();
}
for (i=0 ; i<4 ; i++) // Shat_shells -> stat_cells = 0/1/2/3 = 4 - TODO : Remake it for dynamically linking with QuakeC
{
j = MSG_ReadByte ();
if (cl.stats[STAT_SHELLS+i] != j)// On part de Stat_SHELLS - TODO : Remake it for linking with QuakeC
{
cl.stats[STAT_SHELLS+i] = j;
Sbar_Changed ();
}
}
i = MSG_ReadByte ();
if (standard_quake)
{
if (cl.stats[STAT_ACTIVEWEAPON] != i)
{
cl.stats[STAT_ACTIVEWEAPON] = i;
Sbar_Changed ();
}
}
else
{
if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
{
cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
Sbar_Changed ();
}
}
}
and in Sv_main.c ...
- Code: Select all
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
{
int bits;
int i;
edict_t *other;
int items, altitems;
#ifndef QUAKE2
eval_t *val;
#endif
//
// send a damage message
//
if (ent->v.dmg_take || ent->v.dmg_save)
{
other = PROG_TO_EDICT(ent->v.dmg_inflictor);
MSG_WriteByte (msg, svc_damage);
MSG_WriteByte (msg, ent->v.dmg_save);
MSG_WriteByte (msg, ent->v.dmg_take);
for (i=0 ; i<3 ; i++)
MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
ent->v.dmg_take = 0;
ent->v.dmg_save = 0;
}
//
// send the current viewpos offset from the view entity
//
SV_SetIdealPitch (); // how much to look up / down ideally
// a fixangle might get lost in a dropped packet. Oh well.
if ( ent->v.fixangle )
{
MSG_WriteByte (msg, svc_setangle);
for (i=0 ; i < 3 ; i++)
MSG_WriteAngle (msg, ent->v.angles[i] );
ent->v.fixangle = 0;
}
bits = 0;
if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
bits |= SU_VIEWHEIGHT;
if (ent->v.idealpitch)
bits |= SU_IDEALPITCH;
// stuff the sigil bits into the high bits of items for sbar, or else
// mix in items2
#ifdef QUAKE2
items = (int)ent->v.items | ((int)ent->v.items2 << 23);
#else
/*val = GetEdictFieldValue(ent, "items2");
if (val)
items = (int)ent->v.items | ((int)val->_float << 23);
else*/
items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
#endif
bits |= SU_ITEMS | SU_ALTITEMS;
altitems = (int)ent->v.altammo_items | ((int)pr_global_struct->serverflags << 28); // Ch0wW 02/12/11 -- Alt Ammo Addition (HUD) -- Dirty hack :/
if ( (int)ent->v.flags & FL_ONGROUND)
bits |= SU_ONGROUND;
if ( ent->v.waterlevel >= 2)
bits |= SU_INWATER;
for (i=0 ; i<3 ; i++)
{
if (ent->v.punchangle[i])
bits |= (SU_PUNCH1<<i);
if (ent->v.velocity[i])
bits |= (SU_VELOCITY1<<i);
}
if (ent->v.weaponframe)
bits |= SU_WEAPONFRAME;
if (ent->v.armorvalue)
bits |= SU_ARMOR;
// if (ent->v.weapon)
bits |= SU_WEAPON;
// send the data
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteShort (msg, bits);
if (bits & SU_VIEWHEIGHT)
MSG_WriteChar (msg, ent->v.view_ofs[2]);
if (bits & SU_IDEALPITCH)
MSG_WriteChar (msg, ent->v.idealpitch);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
MSG_WriteChar (msg, ent->v.punchangle[i]);
if (bits & (SU_VELOCITY1<<i))
MSG_WriteChar (msg, ent->v.velocity[i]/16);
}
// [always sent] if (bits & SU_ITEMS)
MSG_WriteLong (msg, items); // ITEMS
MSG_WriteLong (msg, altitems); // Ch0wW 02/12/11 -- Alt Ammo Addition (HUD)
if (bits & SU_WEAPONFRAME)
MSG_WriteByte (msg, ent->v.weaponframe);
if (bits & SU_ARMOR)
MSG_WriteByte (msg, ent->v.armorvalue);
if (bits & SU_WEAPON)
MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel));
MSG_WriteShort (msg, ent->v.health);
MSG_WriteByte (msg, ent->v.currentammo);
MSG_WriteByte (msg, ent->v.currentammo_sec); // Ch0wW 06/11/11 -- Secondary Ammo Type Addition
// MSG_WriteByte (msg, ent->v.maxammo);
MSG_WriteByte (msg, ent->v.ammo_shells);
MSG_WriteByte (msg, ent->v.ammo_nails);
MSG_WriteByte (msg, ent->v.ammo_rockets);
MSG_WriteByte (msg, ent->v.ammo_cells);
if (standard_quake)
{
MSG_WriteByte (msg, ent->v.weapon);
}
else
{
for(i=0;i<32;i++)
{
if ( ((int)ent->v.weapon) & (1<<i) )
{
MSG_WriteByte (msg, i);
break;
}
}
}
}
Thanks in advance.
- ChOwW
- Posts: 21
- Joined: Sat Dec 03, 2011 1:20 pm
Re: Q1 - problem with Stats and demos
if its just demos that fail, your problem is not due to svc_clientdata.
check what changes you've made in cl_demo.c. make sure that whatever enables your higher precision aiming angles is also enabled for playing back those demos. considering you're not aiming for quake compatibility, and not even with the id demos, you should perhaps consider unconditionally sending/reading shorts for your angles in the clc_move commands, which would permit you to forgo any protocol toggles/detection.
check what changes you've made in cl_demo.c. make sure that whatever enables your higher precision aiming angles is also enabled for playing back those demos. considering you're not aiming for quake compatibility, and not even with the id demos, you should perhaps consider unconditionally sending/reading shorts for your angles in the clc_move commands, which would permit you to forgo any protocol toggles/detection.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: Q1 - problem with Stats and demos
If you need help with the Wii, feel free to ask me, I'm the author of the Wii port. (A port of the gamecube port with my own GX renderer)
- Eluan
- Posts: 10
- Joined: Sun Jun 15, 2008 9:03 am
- Location: Florianópolis, Brazil
Re: Q1 - problem with Stats and demos
Thanks Eluan, but I prefer to understand it by myself... That'll help me too discovering more of the wii's devkit abilities.
Spike : Actually, I haven't done any modification to cl_demo.c taken from ProQuake 3.50 ; I saw what to modify in view.c , but that's all I did.
It recorded well before implanting that Alt-Ammo system on the HUD. (except the fact I couldn't continue the demo if I changelevel'd, but I think that was an issue in the past)
Anyway, I've found what was my problem.
In PQ's cl_demo.c file, in CL_GetMessage, I commented by mistake that part (easily found):
I think it corrupted the messagedata written to the demo, hence that Cl_ParseServerMessage error...
Anyway, thanks a lot helping me.
Spike : Actually, I haven't done any modification to cl_demo.c taken from ProQuake 3.50 ; I saw what to modify in view.c , but that's all I did.
It recorded well before implanting that Alt-Ammo system on the HUD. (except the fact I couldn't continue the demo if I changelevel'd, but I think that was an issue in the past)
Anyway, I've found what was my problem.
In PQ's cl_demo.c file, in CL_GetMessage, I commented by mistake that part (easily found):
- Code: Select all
demo_head_size[cls.signon] = net_message.cursize;
if (!cls.signon)
{
char *ch;
int len;
len = strlen(demo_head[0]);
// ch = strstr(demo_head[0] + len + 1, "ProQuake Server Version");
//if (ch)
// memcpy(ch, va("ProQuake \217Demo\217 Version %4.2f", PROQUAKE_VERSION), 28);
// else
// {
ch = demo_head[0] + demo_head_size[0];
*ch++ = svc_print;
<---- MY MISTAKE - 0
/* ch += 1 + sprintf(ch, "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"
"\n \01\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\03");
*/
>---- MY MISTAKE - 1
demo_head_size[0] = ch - (char *) demo_head[0];
// }
}
I think it corrupted the messagedata written to the demo, hence that Cl_ParseServerMessage error...
Anyway, thanks a lot helping me.
- ChOwW
- Posts: 21
- Joined: Sat Dec 03, 2011 1:20 pm
4 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest