Jump to content

Home

Q3 Engine Game Bugs / JA bugs


ensiform

Recommended Posts

There's an infinite loop in Cmd_FollowCycle_f (g_cmds.c) that can easily be used to attack an unpatched server.

 

To reproduce the infinite loop:

  • Join a server (Preferrably FFA?) where there are no in-game players (Spectators are fine)
  • /team follow1
  • Click to cycle through clients

 

Replace it with this version, also containing this fix

 

void Cmd_FollowCycle_f( gentity_t *ent, int dir ) {
int		clientnum;
int		original;
qboolean	looped = qfalse;

// if they are playing a tournement game, count as a loss
if ( (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
	&& ent->client->sess.sessionTeam == TEAM_FREE ) {\
	//WTF???
	ent->client->sess.losses++;
}
// first set them to spectator
if ( ent->client->sess.spectatorState == SPECTATOR_NOT ) {
	SetTeam( ent, "spectator" );
}

if ( dir != 1 && dir != -1 ) {
	G_Error( "Cmd_FollowCycle_f: bad dir %i", dir );
}

clientnum = ent->client->sess.spectatorClient;
original = clientnum;

do {
	clientnum += dir;
	if ( clientnum >= level.maxclients )
	{
		//Raz: Avoid /team follow1 crash
		if ( looped )
		{
			clientnum = original;
			break;
		}
		else
		{
			clientnum = 0;
			looped = qtrue;
		}
	}
	if ( clientnum < 0 ) {
		if ( looped )
		{
			clientnum = original;
			break;
		}
		else
		{
			clientnum = level.maxclients - 1;
			looped = qtrue;
		}
	}

	// can only follow connected clients
	if ( level.clients[ clientnum ].pers.connected != CON_CONNECTED ) {
		continue;
	}

	// can't follow another spectator
	if ( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) {
		continue;
	}

	//ensiform's fix
	// can't follow another spectator
	if ( level.clients[ clientnum ].tempSpectate >= level.time ) {
		return;
	}

	// this is good, we can use it
	ent->client->sess.spectatorClient = clientnum;
	ent->client->sess.spectatorState = SPECTATOR_FOLLOW;
	return;
} while ( clientnum != original );

// leave it where it was
}

 

I'm sure the loop could be written more elegantly, but this will suffice.

Link to comment
Share on other sites

  • Replies 229
  • Created
  • Last Reply

Prediction error after spectating somebody who is on an ET_MOVER then switching to roaming mode.

 

Modify the start of CG_AdjustPositionForMover (cg_ents.c) to match:

 

void CG_AdjustPositionForMover( const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out ) {
centity_t	*cent;
vec3_t	oldOrigin, origin, deltaOrigin;
vec3_t	oldAngles, angles, deltaAngles;

if ( cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_SPECTATOR )
{//Don't bother if we're a spectator
	VectorCopy( in, out );
	return;
}

Link to comment
Share on other sites

  • 7 months later...

Weird behaviour in UI code causes onOpen {} events to be triggered on the parent item of the item you're closing (via out-of-bounds click)

Example: Ingame menu -> click "About" -> Click "Setup" -> the onOpen event of the "ingame" menu would be fired.

This is only an issue if you have your own menus that use these events. Personally I'm using transitions in all my menus, which were being triggered at the wrong time.

 

In ui_shared.c -> Menus_HandleOOBClick

 

Comment out "Menus_Activate(&Menus);" in the for loop.

 

		for (i = 0; i < menuCount; i++) {
		if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) {
			Menu_RunCloseScript(menu);
			menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
		//	Menus_Activate(&Menus[i]);
			Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
			Menu_HandleKey(&Menus[i], key, down);
		}
	}

Link to comment
Share on other sites

JA's font width calculation is horrible broken, especially when using abnormal (anything but 1.0) scales.

The issue is in the engine, RE_Font_StrLenPixels uses integer precision for the return value, causing visible data loss.

 

The way I'm currently working around this is by replacing trap_R_Font_StrLenPixels with:

float trap_R_Font_StrLenPixels(const char *text, const int iFontIndex, const float scale)
{
//Raz: HACK! RE_Font_StrLenPixels only works semi-correctly with 1.0f scale
float width = (float)syscall( CG_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f));
return width * scale;
}

 

Note I'm using a float return value - you'll have to adjust function prototypes and usage all around the code to use floats for best results.

I also use a large custom font to help with scaling.

 

This is not a fix, but it does help tremendously when trying to center-align text in both cgame and ui

 

Theoretically you could replace all text rendering with your own OpenGL code and use the bmfont library. If you wanted to D:

Link to comment
Share on other sites

  • 3 months later...
There is a bug in jamp.exe where connecting to an invalid hostname or IP whilst ingame will shove you out to a black screen, unable to do anything (including open your console). A very ugly situation.

 

The function in question is CL_Connect_f (0x41D990)

The code in question is:

	//Taken from q3
if (!NET_StringToAdr( cls.servername, &clc.serverAddress) ) {
	Com_Printf ("Bad server address\n");
	cls.state = CA_DISCONNECTED;
	return;
}

At the very least, it should be setting your connection state to CA_CONNECTING

 

Ideally, you would rewrite this function to have a different code path if you attempt to connect to a bad hostname or IP whilst ingame.

Another solution, is to patch the opcode setting cls.state to CA_DISCONNECTED

 

You will have to unlock the code page with VirtualProtect or mprotect

I suggest writing a wrapper.

 

UnlockMemory( 0x41DACB, 1 );
*(unsigned char *)0x41DACB = (unsigned char)0x03;
LockMemory( 0x41DACB, 1 );

 

At the moment this fix is only for Windows, but it is possible to fix on Mac with the right addresses.

 

With this fix, you will be sent to the "Connecting to someinvalidhostname...1" screen and things will carry on as normal. Not ideal, but it works.

 

This fix is actually wrong.

 

The problem is raven fail coding in the UI:

 

(Main menu is never actually loaded because you were in the server last which will tell UI_Init to be (qtrue) on ingameload so it will only load ingame related menus. (This is fine however)

 

When it goes to try to revert back to main menu with setactivemenu UIMENU_MAIN:

 

 

			if (uiInfo.inGameLoad) 
		{
//				UI_LoadNonIngame();
		}

 

because of this, it fails to actually "activate" main.

Link to comment
Share on other sites

Archived

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


×
×
  • Create New...