[ET] Manipulate loadingscreen (ETPro)

mowl

Coders
Well hello.

I don't think anyone else has showed how this can be done. Anyways, I've looked in ETSDK where it draws the loading screen. This function took my attention: 'CG_DrawConnectScreen'. So I loaded up the ETPro module in IDA, since it contains a few text strings, it wasn't very hard to find it.

Code:
CG_Text_Paint_Centred_Ext( 540, y, 0.2f, 0.2f, colorWhite, str && *str ? str : [b]"ETHost"[/b], 0, 26, 0, &bg_loadscreenfont2 );

Code:
.text:30066835 loc_30066835:   ; CODE XREF: sub_30066080+437j
.text:30066835                 ; sub_30066080+440j
.text:30066835                 mov     eax, offset aEthost ; "ETHost"
.text:3006683A                 jmp     loc_300664C6

The function where it is called is then (in pseudocode)
Code:
void __cdecl sub_30066080(int a1, int a2)

Looking a little further, I found the function where it processes the 'loading bar': 'void CG_LoadPanel_RenderLoadingBar'.
The only line that caught my attention there was the trap function: 'trap_GetHunkData( &hunkUsed, &hunkExpected );'.

Now lets hook the call and block it, so we can overwrite it with our own loadingscreen.

Code:
[b]CHooks class:[/b]
typedef void (WINAPIV			*cg_loadingScreen_t)(qboolean a1, qboolean a2);
static void h_CG_LoadingScreen(qboolean a1, qboolean a2);
cg_loadingScreen_t o_CG_LoadingScreen;

[b]Hooking:[/b]
hooks.o_CG_LoadingScreen = (cg_loadingScreen_t) Detour((BYTE *)main.hCgame + 0x066080, h_CG_LoadingScreen);

[b]Hooked function:[/b]
void CHooks::h_CG_LoadingScreen(qboolean valid, qboolean refresh)
{
	//engine.h_LoadingScreen(refresh, 1);

	if (!valid)
		return;

	hooks.o_CG_LoadingScreen(valid, refresh);

}

When we draw where snap ain't set yet, we will draw in the loadingscreen.
Code:
void CEngine::h_DrawActiveFrame_Pre(int serverTime, int stereoView, int demoPlayback)
{
	if (!loading)
		this->drawAtLoading();

	if (!engine.cg_snap)
		return;
	
	loading = true;
}

And finally, where we draw the loading bar and some text:
Code:
void CEngine::drawAtLoading()
{
	char print[1024];
	// Background
	draw.drawFillRect(0, 0, 640, 480, colorBlack);

	// Loading bar
	float loadPercent;
	int hunkUsed, hunkNeeded;

	hooks.o_syscall(CG_GETHUNKDATA, &hunkUsed, &hunkNeeded);

	if ( hunkNeeded <= 0 )
		return;

	loadPercent = hunkUsed / (float)hunkNeeded;
	if ( loadPercent < 0.f ) loadPercent = 0.f;
	if ( loadPercent > 1.f ) loadPercent = 1.f;

	vec4_t loadclr = {1, 0, 0, 0.5};
	draw.drawFillRect(0, 0, 640*loadPercent, 5, loadclr);
	draw.drawFillRect(0, 480-5, 640*loadPercent, 5, loadclr);

	// Draw title and loading percentage
	draw.drawTextCenterScreen(50, 0.17, "^7ET^1:^7ProtoType", false, colorWhite);

	float percent = (float)(loadPercent * 100);
	sprintf_s(print, sizeof(print), "^7Loading: %1.1f percent", percent);

	draw.drawTextCenterScreen(60, 0.15, print, false, colorWhite);
}

This is very close to copy/pasting. But credit whenever you use :)
Shout: sp00f, King Horny and ETSDK

Uploading a screenshot in the attachment. The red bar on the top shows the loading progress.

Regards,
mOwl
 

Attachments

  • loading.png
    loading.png
    5.6 KB · Views: 114
too bad you didn't set a naked girl instead of the plain black background, you wouldn't be allowed to upload the pic here though
 

mowl

Coders
too bad you didn't set a naked girl instead of the plain black background, you wouldn't be allowed to upload the pic here though

Then I should load my own pk3 file, and I want to stay away from pk3's since pb checks the names. Thats why I create all the chams dynamicly.
But if you really want, I'll draw it through OpenGL, so you could add your favorite 'naked girls' pictures whenever you want. I bet you would be playing ET day and night! :)
 
Then I should load my own pk3 file, and I want to stay away from pk3's since pb checks the names. Thats why I create all the chams dynamicly.
But if you really want, I'll draw it through OpenGL, so you could add your favorite 'naked girls' pictures whenever you want. I bet you would be playing ET day and night! :)
I'd enter vid_restart over and over again ;)
 

learn_more

Semi-Coder
hook createfile, and redirect "c:\game\model.xxx" to "c:\hack\modelhack.xxx" ;)

optionally you might need to hook find[first/next]file to make it appear to ET as if there was an extra pk3/model in the directory :)
(and don't forget to check the return address, if PB calls you don't want to have it show that extra pk3)
 

mowl

Coders
hook createfile, and redirect "c:\game\model.xxx" to "c:\hack\modelhack.xxx" ;)

optionally you might need to hook find[first/next]file to make it appear to ET as if there was an extra pk3/model in the directory :)
(and don't forget to check the return address, if PB calls you don't want to have it show that extra pk3)

I prefer hooking 'FS_PureServerSetLoadedPaks' instead. Since you got paknames passed there.
And you can get packname through looping 'searchpath' from ETSDK. I guess 99% of the ET coders do it this way.
Seems more logic, and easier :)
Code:
.text:00412F4C                 call    sub_429620
.text:00412F51                 push    offset aSv_referencedp ; "sv_referencedPaks"
.text:00412F56                 push    esi
.text:00412F57                 call    sub_4317A0 <=== 'FS_PureServerSetLoadedPaks'
.text:00412F5C                 push    offset aSv_reference_0 ; "sv_referencedPakNames"
 

Larz

New member
If I'm not mistaking 0x037E80 is the etmain offset.. Sorry for bump if it pisses anyone off.
Code:
hooks.o_CG_LoadingScreen = (cg_loadingScreen_t) Detour((BYTE *)main.hCgame + [B]0x037E80[/B], h_CG_LoadingScreen);
 
Top