There are numerous ways of using the SCM hook, when I was playing around with it last night, as I believe I mentioned in my previous post, I merely threw all the script commands (opcodes) into a function in Custom.cpp, which contains much of the data that is used for the interface, i.e. CustomRender(...). All I did was threw in a call to my custom function in this function, since this function is executed quite frequently (whenever drawing routines are required) so it would execute any of the opcodes that need constant updating. Here's essentially what I mean:
|void CustomRender(IDirect3DDevice8* pDevice)|
if ((pSpeedoSprite) && (pSpeedoTex) && (pNeedleSprite) && (pNeedleTex)) // If we have the goods...
if ((*dwCanPlayRadio) && (!*bInMenu)) // If we're in the game (not in the menu)...
Why can't we use just (!*bInMenu)?
Well, bInMenu is 1 while in the menu and 0 while in-game,
BUT as the value isn't initalized until we reach the main
menu, it's 0 when this function first gets executed.
Theres bound to be a better "InGame" variable about,
but until I go looking for it, this'll do.
if (ScriptCommand(&player_in_car, PLAYER_CHAR)) // Is the player in a car?...
float fCurrentSpeed = 0.0;
DWORD dwPlayerCar = 0;
ScriptCommand(&get_player_car, PLAYER_CHAR, &dwPlayerCar); // Get the player's car.
ScriptCommand(&make_car_heavy, &dwPlayerCar, 1); // Make the vehicle heavy.
if (!ScriptCommand(&car_stopped, &dwPlayerCar)) // Is the car moving?...
ScriptCommand(&get_car_speed, &dwPlayerCar, &fCurrentSpeed); // Get the car speed :)
fCurrentSpeed *= fSpeedoMultiplier; // (m/s * 2.24) = mph
pSpeedoTex->GetLevelDesc(0, &Desc); // Get the primary texture level description.
if (Desc.Format == D3DFMT_A8R8G8B8) // This should always be true, but blah.
pSpeedoTex->LockRect(0, &Rect, NULL, 0); // Lock the texture. Error checking here maybe? :s
DWORD* pTexData = (DWORD*)Rect.pBits; // Pointer to the raw texture data.
int PixRow = Rect.Pitch / 4; // Pitch of the texture in pixels.
finit // Initialize FPU
fld fCurrentSpeed // Load speed from float
fistp nCurrentSpeed // Store speed in int
if (nCurrentSpeed > 999) nCurrentSpeed = 999; // Maybe they're driving the bat mobile!
if (fCurrentSpeed > 200.0f) fCurrentSpeed = 200.0f; // We don't want the needle looping.
int nDigit = nCurrentSpeed / 100; // How many hundreds of miles per hour are we going?
DrawDigit(pTexData, PixRow, 91, 149, nDigit); // Draw first speed digit
nCurrentSpeed -= (nDigit * 100); // Subtract the hundreds
nDigit = nCurrentSpeed / 10; // Get tenths
DrawDigit(pTexData, PixRow, 101, 149, nDigit); // Draw second speed digit
nDigit = nCurrentSpeed - (nDigit * 10); // Subtract the tens
DrawDigit(pTexData, PixRow, 111, 149, nDigit); // Draw third speed digit
BYTE* nGear = (BYTE*)GameGetVehicle(dwPlayerCar); // Get currently driven car's structure.
nGear += 520; // VEHICLE_STRUCT+520 = Gear
DrawDigit(pTexData, PixRow, 72, 149, *nGear); // Draw gear digit
pSpeedoTex->UnlockRect(0); // Unlock the texture.
pSpeedoSprite->Begin(); // This sets up render states and stuff. See the SDK dox.
// Draw the speedometer sprite.
pSpeedoSprite->Draw(pSpeedoTex, NULL, &vScaling, NULL, 0.0f, &vTranslation, 0xFFFFFFFF);
// Draw the needle sprite.
pNeedleSprite->Draw(pNeedleTex, NULL, &vScaling, &vRotCenter, fNeedleZero-(fNeedleUnit*fCurrentSpeed), &vNeedleTranslation, 0xFFFFFFFF);
pSpeedoSprite->End(); // Cleanup. Reset render states etc. See SDK dox.
ScriptCommand(&set_current_time, 0, 0);
if (ScriptCommand(&is_key_pressed, 0, 14))
else if (ScriptCommand(&is_key_pressed, 0, 6))
else if (ScriptCommand(&is_key_pressed, 0, 16))
Now I realize most people will tell you this is quite inefficient since opcodes such as set_weather and set_current_time (the clock remains at 00:00 during gameplay) only need to be called once, I believe the is_key_pressed opcodes must be embedded in a thread, which means that each time CustomRender(...) is called both set_weather and set_current_time are called which is improper use of CPU; but I was just messing around, so sue me.
The above CustomScript() function contains the simple, as can be seen, idea I mentioned previously, using the game's is_key_pressed function, which I added to the GameScripting.h (see my previous post), to check and see if a key is being pressed, and if it is modify the gamespeed to the appropriate float value, 1 being normal in a range of 0 - 2, 0 being nearly stopped and 2 being double the normal speed. Simple enough I hope.
Here you can see that in slow motion you can get some nice clips of carnage:
Ocram88, I believe you are referring to a .cfg file that contains opcodes that you want executed at runtime. You could possibly try adding a runtime interpreter to the code so anything within that configuration file is read by the script hook. Just a thought.