Jump to content

Home

Q3 Engine Game Bugs / JA bugs


ensiform

Recommended Posts

there seems to be a bug in interpolation on playback of demos recorded from a localhost server (created through the create game ui option). if you watch one of these demos, especially in lower timescale, the motion seems jerky compared to normal remote-server demos. i've found this fix for it:

 

cg_snapshot.c function CG_ReadNextSnapshot

find the line

// FIXME: why would trap_GetSnapshot return a snapshot with the same server time

and change it to

// FIXME: why would trap_GetSnapshot return a snapshot with the same server time
	if ( cg.snap && r && dest->serverTime == cg.snap->serverTime ) {
		// because we're playing back demos taken by local servers apparently 
		if ( cg.demoPlayback ) continue;
		//continue;
	}

:twogun:

Link to comment
Share on other sites

  • Replies 229
  • Created
  • Last Reply

For whatever reason, Raven chose to use strcpy and strncpy in a lot of places instead of Q_strncpyz. This can cause buffer overflows and overruns. There are only a few places i can think of that should be left. Ususally when the dest is a char *something, however a few can be still length checked only when you don't really know what length should be. Also, bg_vehicleLoad and q_shared really should be left alone.

Link to comment
Share on other sites

Thanks to hex on this one also.

 

speed and rage don't work together to give you more speed like it did in jk2.

 

cause: raven used an if speed else if rage else ragerecovery

 

fix: revert it back (use a cvar though)

 

bg_pmove.c "BG_AdjustClientSpeed"

 

look for and replace this code:

 

	if (ps->fd.forcePowersActive & (1 << FP_SPEED))
{
	ps->speed *= 1.7;
}
else if (ps->fd.forcePowersActive & (1 << FP_RAGE))
{
	ps->speed *= 1.3;
}
else if (ps->fd.forceRageRecoveryTime > svTime)
{
	ps->speed *= 0.75;
}

 

with:

 

	if (ps->fd.forcePowersActive & (1 << FP_SPEED))
{
	ps->speed *= 1.7;
}

if (ps->fd.forcePowersActive & (1 << FP_RAGE))
{
	ps->speed *= 1.3;
}
else if (ps->fd.forceRageRecoveryTime > svTime)
{
	ps->speed *= 0.75;
}

 

The client-side will be needed for this for best performance.

Link to comment
Share on other sites

If you haven't respawned into temp spectator mode and in siege, you can still use your holdable items because they are not cleared :doh:

 

g_combat.c "player_die"

 

look for these lines:

 

	// remove powerups
memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) );

 

below it add:

 

	self->client->ps.stats[sTAT_HOLDABLE_ITEMS] = 0;
self->client->ps.stats[sTAT_HOLDABLE_ITEM] = 0;

Link to comment
Share on other sites

setting forcepowers to something illegal can cause a crash after forcechanged and respawn.

This is caused by a malformed forcepower string. To fix this we need to take any garbage the client sends us and turn it into a real forcepower string. A real forcepower string looks like #-#-##################. To do this we try to read anything the client gives us and then we fill in the blanks.

 

Add the following somewhere:

void FR_NormalizeForcePowers(char *powerOut, int powerLen)
{
char powerBuf[128];
char readBuf[2];
int finalPowers[21] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int i, c;

if (powerLen >= 128 || powerLen < 1)
{ //This should not happen. If it does, this is obviously a bogus string.
	//They can have this string. Because I said so.
	strcpy(powerBuf, "7-1-032330000000001333");
}
else
{
	Q_strncpyz(powerBuf, powerOut, sizeof(powerBuf)); //copy it as the original
}

c = 0;
i = 0;
while (i < powerLen && i < 128 && powerBuf[i] && powerBuf[i] != '\n' && powerBuf != '\0' && c < NUM_FORCE_POWERS+2)
{
	if (powerBuf[i] != '-')
	{
		readBuf[0] = powerBuf[i];
		readBuf[1] = 0;
		finalPowers[c] = atoi(readBuf);
		c++;
	}
	i++;
}

strcpy(powerOut, va("%i-%i-%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i\0",
					finalPowers[0], finalPowers[1], finalPowers[2], 
					finalPowers[3], finalPowers[4], finalPowers[5], 
					finalPowers[6], finalPowers[7], finalPowers[8], 
					finalPowers[9], finalPowers[10], finalPowers[11], 
					finalPowers[12], finalPowers[13], finalPowers[14], 
					finalPowers[15], finalPowers[16], finalPowers[17], 
					finalPowers[18], finalPowers[19], finalPowers[20]));
}

 

In g_client.c, look for:

Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );

replace with:

if (!(ent->r.svFlags & SVF_BOT))
{ // clients could have a bad forcepower string
	char *n;
	n = Info_ValueForKey (userinfo, "forcepowers");
	FR_NormalizeForcePowers(n, strlen(n));
	strcpy( forcePowers, n );
}
else
{
	Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );
}

 

in w_force.c, look for:

Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );

replace with:

if (!(ent->r.svFlags & SVF_BOT))
{
	char *s;
	s = Info_ValueForKey (userinfo, "forcepowers");
	FR_NormalizeForcePowers(s, strlen(s));
	strcpy( forcePowers, s );
}
else
{
	Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );
}

 

**EDIT** Fixed to correct bot name issues.

Link to comment
Share on other sites

K, applied the fix. i will test the blank name thing again to see.

 

Also i would suggest using Q_strncpyz instead of strcpy in these situations:

 

strcpy(powerBuf, "7-1-032330000000001333"); => Q_strncpyz(powerBuf, "7-1-032330000000001333", sizeof(powerBuf));

 

strcpy(powerBuf, powerOut); //copy it as the original => Q_strncpyz(powerBuf, powerOut, sizeof(powerBuf)); //copy it as the original

 

strcpy( forcePowers, n ); => Q_strncpyz( forcePowers, n, sizeof(forcePowers) );

 

strcpy( forcePowers, s ); => Q_strncpyz( forcePowers, s, sizeof(forcePowers) );

Link to comment
Share on other sites

Here's a really old bug fix that CerburuS told me about ages ago. However, I never actually tried it so your mileage may vary. I'll give this a shot when I have time as well.

 

just wanted to let you know that there's a bug in basejka which disables Areaportals in Siege permanently if that Areaportal is "open" when the round is being restarted (i.e. the Areaportal will not work at all in the next round, causing bad FPS for the players).

 

In basejka Siege it's obviously not as much of an issue as it is in MBII since there's only one round restart per map at max (opposed to 20+ in MBII). Thought you might be interested nonetheless...

 

I've written a relatively simple fix for this problems - could forward to you if you want. It'd need a small modification for basejka though since I'm using a MBII-specific value to determine whether the server is currently in round transition.

 

Well, area portals should be used quite frequently in Siege maps - I imagine that siege_desert for example uses quite a few. The only one I know for sure is located at the Command Center doors at siege_hoth. They should be easy to detect via /r_showtris 1 though.

 

		//fix for self-deactivating areaportals in Siege
	if ( ent->s.eType == ET_MOVER && g_gametype.integer == GT_SIEGE && level.MBIntermission)
	{
		if ( !Q_stricmp("func_door", ent->classname) && ent->moverState != MOVER_POS1 )
		{
			SetMoverState( ent, MOVER_POS1, level.time );
			if ( ent->teammaster == ent || !ent->teammaster ) 
			{
				trap_AdjustAreaPortalState( ent, qfalse );
			}

			//stop the looping sound
			ent->s.loopSound = 0;
			ent->s.loopIsSoundset = qfalse;			}
		continue;
	}

This is the code I inserted in g_main.c (around line 4169 in the MB version). I'd just send you the file but since my comp just got fried 2 hours ago, this would take a while ;) Basically you should be able to insert it anywhere in the G_RunFrame function.

 

Basically it closes any door that is not closed (i.e. opening, closing, or open) and activates the areaportal again. According to our beta testers, it works pretty well so far. If you can think of a better way to do this though, just let me know :)

 

The only thing that will need adapting is the level.MBintermission value I'm using since that one's MB specific.

 

Hope it's at least of some help.

 

EDIT: Ensiform has come up with code to fix this bug for basejka. Look down in this thread for it.

Link to comment
Share on other sites

For those not able to understand how the areaportal fix works with non-MB2 code open up g_main.c and look for the following piece of code:

 

		if ( ent->s.eType == ET_MOVER ) {
		G_RunMover( ent );
		continue;
	}

 

below it add:

 

		//fix for self-deactivating areaportals in Siege
	if ( ent->s.eType == ET_MOVER && g_gametype.integer == GT_SIEGE && level.intermissiontime)
	{
		if ( !Q_stricmp("func_door", ent->classname) && ent->moverState != MOVER_POS1 )
		{
			SetMoverState( ent, MOVER_POS1, level.time );
			if ( ent->teammaster == ent || !ent->teammaster ) 
			{
				trap_AdjustAreaPortalState( ent, qfalse );
			}

			//stop the looping sound
			ent->s.loopSound = 0;
			ent->s.loopIsSoundset = qfalse;
		}
		continue;
	}

Link to comment
Share on other sites

The following appears to fix the bug with saber collision after you die when your saber was knocked away.

 

In g_combat.c, function player_die

Find:

self->client->ps.saberEntityNum = self->client->saberStoredIndex; //in case we died while our saber was knocked away.

After, add:

if (self->client->ps.weapon == WP_SABER && self->client->saberKnockedTime)
{
	gentity_t *saberEnt = &g_entities[self->client->ps.saberEntityNum];
	//G_Printf("DEBUG: Running saber cleanup for %s\n", self->client->pers.netname);
	self->client->saberKnockedTime = 0;
	saberReactivate(saberEnt, self);
	saberEnt->r.contents = CONTENTS_LIGHTSABER;
	saberEnt->think = saberBackToOwner;
	saberEnt->nextthink = level.time;
	G_RunObject(saberEnt);
}

Link to comment
Share on other sites

Fixed the bug with using alt fire and then hitting use holdable to hold your charge.

 

in bg_pmove.c in the function PmoveSingle:

 

after:

pm = pmove;

add:

if (pm->cmd.buttons & BUTTON_ATTACK && pm->cmd.buttons & BUTTON_USE_HOLDABLE)
{	pm->cmd.buttons &= ~BUTTON_ATTACK;
	pm->cmd.buttons &= ~BUTTON_USE_HOLDABLE;}
if (pm->cmd.buttons & BUTTON_ALT_ATTACK && pm->cmd.buttons & BUTTON_USE_HOLDABLE)
{	pm->cmd.buttons &= ~BUTTON_ALT_ATTACK;
	pm->cmd.buttons &= ~BUTTON_USE_HOLDABLE;}

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.


×
×
  • Create New...