blog > Use preset cars in quickrace (2023 August 7)

Use preset cars in quickrace #

Well this didn't take long after last blogpost (Customizing preset cars). (you may want to read/skim that one first before going here, as this post is a continuation really)

Just chasing xrefs to profileData.player1.d4.currentCarSelectionSlotHash led me to the code that initializes the car stuff to use in game. I suspected that that field would lead me to there because, well, it's the "current selected car".


Reusing code from customizing preset cars #

I'm not gonna copy everything in here again, most of it is the same/similar to the code as in previous blog post.

See nfsu2-re-hooks/fun-use-preset-cars-in-quickrace.c for all the code together.

Though important implementation notes: because I also don't just wanna copy all code, I'm relying on the existing code from nfsu2-re-hooks/fun-car-customize-preset.c.

That means the hook for ChangeCategory in this new file will also call the old hook (because the new hook file relies on the old hook file and I don't want to break the functionality of the old hook file by including the new hook file, youwithme?)

Also we'll have to override CountAvailableCars_hook again, because we added something so it returns 0 if we're not in the customization menu. Of course it shouldn't do that anymore, we need a real count in the quickrace menu too now.


The only really important code #

So the game crashes if we select a preset car for quick race. The reason is still the same as we've seen so many times before; it tried to find a car based on its slot hash. Since the slot hash for our custom preset car entries does not resolve to a real slot in the car collection, the car will not be found.

The code skips over that and just doesn't call the ApplyTuning method then, but apparently that is vital because the game crashes... maybe it does more than ApplyTuning and it sets important things that are not solely tuning things. Maybe there's no car info at all and it just gets a very empty car instance...

Anyways, we just need to hook in there once more and return the inventory car instance for the preset cars we made before.

	_asm {
		cmp edi, [numPresetCars]
		jb its_preset
		// this is what we overwrote
		add edx, 0x9BD8 // sizeof(struct CarCollection)
		mov ecx, 0x525FC1
		jmp ecx

		dec edi
		imul edi, 0x1C // sizeof(SponsorCar)
		add edi, offset presetCarAsInventoryCar
		mov eax, 0x525FE6
		jmp eax

mkjmp(0x525FBB, fun_use_preset_cars_in_quickrace_FindPresetCarWhenTuningForIngameCar);

so simple!