Quantcast
Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. Los Santos Tuners
      2. Updates
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Red Dead Online

      1. Blood Money
      2. Frontier Pursuits
      3. Find Lobbies & Outlaws
      4. Help & Support
    3. Crews

    1. Red Dead Redemption 2

      1. PC
      2. Help & Support
    2. Red Dead Redemption

    1. Grand Theft Auto Series

      1. St. Andrews Cathedral
    2. GTA VI

    3. GTA V

      1. Guides & Strategies
      2. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
    6. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
    7. GTA III

      1. Guides & Strategies
      2. Help & Support
    8. Portable Games

      1. GTA Chinatown Wars
      2. GTA Vice City Stories
      3. GTA Liberty City Stories
    9. Top-Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. Design Your Own Mission
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Announcements

      1. GTANet 20th Anniversary
    2. Support

    3. Suggestions

[SRC|REL] SCM Hook for Vice City


Spooky
 Share

Recommended Posts

random_download

 

int __declspec(naked) ExecuteScriptBuf(){__asm{ mov eax, OFFSET ScriptBuf	// Move our script buffer base into eax. sub eax, SCRIPT_BASE  // Subtract usual script base from eax. mov ecx, gst    // Move GAME_SCRIPT_THREAD structure into ecx. mov [ecx+0x10], eax  	// Move eax into the gst->dwScriptIP. call ProcessOneCommand  // Call the game's script opcode processor. xor eax, eax    // eax = 0. mov ecx, gst    // Move game script thread into ecx again. mov al, [ecx+0x79]  	// Move the jumpflag into al (return value). ret      	// return.}}int Main(){ScriptBuf[1] = 0x01;ScriptBuf[2] = 0x00;ScriptBuf[3] = 0x04;ScriptBuf[4] = 0x00;int result = ExecuteScriptBuf();	// Execute script stub.}

 

That code should call a "wait 0 ms" command. To call basic commands such as this that is really the only code you need (as well as declaring the vars and structures like gst). ScriptBuf contains the compiled scm code you want to execute. Format is:

Opcode(Word), ParamType(Byte), Parameter, ParamType(Byte), Parameter, etc.

Parameter types are:

01: 32bit int

02: Global var

03: Local var

04: 8bit int

05: 16bit int

06: float (4 byte)

 

For a string eg. in name_thread or gxt references miss out the parameter type.

01 00 04 00 = 0001: wait 0 ms, as "0" can be stored in an 8bit int and so parmeter type 04 is used.

 

Link to comment
Share on other sites

Ahhhh, things are getting clearer now, but I still don't get a couple of things:

 

A) Opcode(Word)

 

How does the program (or dll in this case) know what opcode is what? From what I can gather, you say

 

01 00 04 00 = 0001: wait 0 ms

 

So to me, it look like this:

 

ScriptBuf[1] = 0x01; - The "wait" opcodeScriptBuf[2] = 0x00; - ? Or is this the first half of the opcode, and it's read in reverse?ScriptBuf[3] = 0x04; - The parameter type, in this case 8bitScriptBuf[4] = 0x00; - The parameter for the previous type, in this case 00 ms

 

 

Does this mean I need to define the opcodes I will be using? For example, it seems that somewhere it needs to be defined that 0x01 becomes the opcode 0001. So that would mean that I would need to define somewhere that 0x02 = 0372 (actor wait state). Or does it work in reverse like I said, becoming this:

 

ScriptBuf[1] = 0x72; Second half of wait_state opcodeScriptBuf[2] = 0x03; first half of wait_state opcodeScriptBuf[3] = 0x02; Param type is a globalScriptBuf[4] = 0x01; Not sure how I should get around this... should I rename my globals to numbers? If so, that would make my first ped = 1 ScriptBuf[5] = 0x04; Param type is 8bitScriptBuf[6] = 0x31; Wait state 31 (guestures 2, I think)ScriptBuf[7] = 0x04; Param type is 8bitScriptBuf[8] = 0x20; 20ms, although how would I get higher numbers, like 2000 ms or more?

 

So that would give the game: 0372: 1 31 20ms

 

Is this close, or am I totally off the mark. If it's a byte conversion thing, I'll learn it, but I'm not sure where to start. Does it need to be converted to hex? That would make more sense to me, I think...

 

B) Obviously, I'd like a bunch of these sitting around. I noticed this:

 

int Main()

 

Is the Main() a label? For different opcodes, would I just change this to a different name? For example:

 

int WaitState1()

code follows

 

int WaitState2()

code follows

 

etc.

 

So when I call it from my WM_CHAR (the Windows I/O KeyPress), would I do this?

 

bool KeyPresses = false;  for (;    if (case WM_CHAR:        switch(wParam)           {              case 'Q'   // Shift + qint WaitState1()code followsint result = ExecuteScriptBuf(); // Execute script stub.}            {              case 'W'   // Shift + wint WaitState2()code followsint result = ExecuteScriptBuf(); // Execute script stub.}etc....

 

C) (as well as declaring the vars and structures like gst).

 

What does Canadian Tax have to do with it? wink.gif

 

I'll assume that was a typo and you meant gxt (text stuff). But I don't need text stuff. Does this relate to A) above when declaring what the opcode is, which ped is who, etc?

 

Thanks a bunch man, I think I'm getting closer...

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Alot of this I don't know, but some I can answer from the earlier days of mission coding.

 

Yes, the OpCodes are defined backwards - 0001 is 01 00 in the SCM or in this case in your code. Yes your numbers need to be in hex so a wait 20 ms command would be 01 00 04 14 (14 being 20 in HEX). For larger numbers, you would need a bigger space to store the number in (e.g. 16 bits - 05), so wait 2000 ms would be 01 00 05 07 D0 (7D0 is 2000 in HEX and the numbers are not reversed, but they require a preceding 0 to pad it out).

 

Finally, referencing your actors. When you define an actor as $myactor1, that variable is only used as a marker in your builder. As you may know, these are only references to the actor, but the game does not read them as this, it reads them as memory offsets from the start of the SCM memory block, $myactor1 is not an offset, but 352?? or any other multiple of 4 (or possibly 8) is (when you decompile an SCM, you will see al the default variables as $1 $2 $3 etc, these are the offset divided multiple (4 or 8). Unfortunately, you cannot use Direct Memory Access in the latest builders, even though it was useful, you will need an old builder such as 0.22, which I still use a bit. To get the offset of you actor, you will need to compile then in a hex editor, track down the create_actor you used, and look at the 2 bytes after the 02 variable type, this is the actors ACTUAL variable, and is what you would need to use to reference it.

 

I know this is a fairly basic explanation of what goes on, but its the best I can do at the moment, I'm a bit rusty on DMA.

Link to comment
Share on other sites

You sir, are WONDERFUL!

 

That really helps alot!

EDIT: I got the old MB; I just slugged this into the original MAIN.SCM

 

009A:  $Grp1Ped1?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp2Ped1?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp2Ped2?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp3Ped1?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp3Ped2?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp3Ped3?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp4Ped1?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp4Ped2?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp4Ped3?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]:  $Grp4Ped4?? = create_actor  4? #PGA at  [email protected]  [email protected]  [email protected]

 

Except I'm not entirely sure WHERE to look in the hex editor for what I'm looking for. Again, the code above doesn't need to "work" per say; it's just so I can find the offsets you are talking about. So where WOULD I find this?

 

Would this be the same for my car creation routine, since I'll need to put a ped in a car on occasion (see Just A Short - Getaway for that usage)?

 

EDIT 2: And just so I'm clear, the actor_wait_state code from my above post would now be:

 

int WaitState1(){ScriptBuf[1] = 0x72; //Second half of wait_state opcodeScriptBuf[2] = 0x03; //first half of wait_state opcodeScriptBuf[3] = 0x02; //Param type is a globalScriptBuf[4] = 0x??; //Need to find actor offsetScriptBuf[5] = 0x04; //Param type is 8 bitScriptBuf[6] = 0x1F; //Wait state 31 (guestures 2)ScriptBuf[7] = 0x05; //Param type is 16 bitScriptBuf[8] = 0x07; //First half of 2000 msScriptBuf[9] = 0xD0; //Second half of 2000 msint result = ExecuteScriptBuf(); // Execute script stub.}int ClearObj1(){ScriptBuf[1] = 0x1C; //Second half of clear_objective opcodeScriptBuf[2] = 0x01; //first half of clear_objective opcodeScriptBuf[3] = 0x02; //Param type is a globalScriptBuf[4] = 0x??; //Need to find actor offsetint result = ExecuteScriptBuf(); // Execute script stub.}

 

 

Which SHOULD give me

 

0372: ?? 31 2000m

011C: ??

 

Correct?

 

Again, many thanks! Getting closer still... rah.gif

 

EDIT 3: I was playing around with Delfi's Devloper Console, and found the pointers for my created peds. They remain the same, no matter how many times I change them, so this must reference my peds creation routine (I used the No Peds/Vehicles option to eliminate other peds so I could get the right numbers). Here's what I got:

 

 

1 pedPointer - 29875600Type - 68883642 pedsped1Pointer - 29854400Type - 6888364ped2Pointer - 29861408Type - 68883644 pedsped1Pointer - 29857904Type - 6888364ped2Pointer - 29863160Type - 6888364ped3Pointer - 29870168Type - 6888364ped4Pointer - 29878928Type - 6888364

 

 

Converting the first number to hex gives me 1C7DD90. Since to make this a mutiple of 4 or 8, I'd have to add a leading 0 to pad it out, giving me this:

 

01C7DD90

 

So, in int WaitState1(), my ScriptBuf becomes:

 

int WaitState1(){ScriptBuf[1] = 0x72; //Second half of wait_state opcodeScriptBuf[2] = 0x03; //first half of wait_state opcodeScriptBuf[3] = 0x01; //Param type is 32 bit then addScriptBuf[4] = 0x01; //Ped ID part 1ScriptBuf[5] = 0xC7; //Ped ID part 2ScriptBuf[6] = 0xDD; //Ped ID part 3ScriptBuf[7] = 0x90; //Ped ID part 4ScriptBuf[8] = 0x04; //Param type is 8 bitScriptBuf[9] = 0x1F; //Wait state 31 (guestures 2)ScriptBuf[10] = 0x05; //Param type is 16 bitScriptBuf[11] = 0x07; //First half of 2000 msScriptBuf[12] = 0xD0; //Second half of 2000 msint result = ExecuteScriptBuf(); // Execute script stub.}

 

 

OR do I just do this:

 

int WaitState1(){ScriptBuf[1] = 0x72; //Second half of wait_state opcodeScriptBuf[2] = 0x03; //first half of wait_state opcodeScriptBuf[3] = 0x01; //Param type is 32 bitScriptBuf[4] = 0x1C7DD90; //Actor IDScriptBuf[5] = 0x04; //Param type is 8 bitScriptBuf[6] = 0x1F; //Wait state 31 (guestures 2)ScriptBuf[7] = 0x05; //Param type is 16 bitScriptBuf[8] = 0x07; //First half of 2000 msScriptBuf[9] = 0xD0; //Second half of 2000 msint result = ExecuteScriptBuf(); // Execute script stub.}

 

 

and forget about adding the leading 0?

 

Will this help me at all? Or am I completely wrong?

Edited by ceedj

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

random_download

To find the actor in a hex editor search for:

 

9A 00 04 04 05 95 00 03 0A 00 03 0B 00 03 0C 00 02 <here is the global var>

 

You should find a chunk like that, just like in your code.

int Main() is not a label. It is how a function is declared in C++, so to call it you would do:

 

int Result = Main();

 

The function Main() is executed once the program starts however, so you should not need to call it.

Sorry, I forgot to mention, global and local vars are Words, ie. 2 bytes long. Whenever you read a word, dword etc. it is read in "reverse". So 0x20000000 would be 00 00 00 20, and 03A7 would be A7 03

so:

 

int WaitState1(){ScriptBuf[1] = 0x72; //Second half of wait_state opcodeScriptBuf[2] = 0x03; //first half of wait_state opcodeScriptBuf[3] = 0x02; //Param type is a globalScriptBuf[4] = 0x??; //Need to find actor offsetScriptBuf[5] = 0x??; //Need to find actor offsetScriptBuf[6] = 0x04; //Param type is 8 bitScriptBuf[7] = 0x1F; //Wait state 31 (guestures 2)ScriptBuf[8] = 0x05; //Param type is 16 bitScriptBuf[9] = 0xD0; //First half of 2000 msScriptBuf[10] = 0x07; //Second half of 2000 msint result = ExecuteScriptBuf(); // Execute script stub.}int ClearObj1(){ScriptBuf[1] = 0x1C; //Second half of clear_objective opcodeScriptBuf[2] = 0x01; //first half of clear_objective opcodeScriptBuf[3] = 0x02; //Param type is a globalScriptBuf[4] = 0x??; //Need to find actor offsetScriptBuf[5] = 0x??; //Need to find actor offsetint result = ExecuteScriptBuf(); // Execute script stub.}

 

You could also have more developed function eg.:

 

int Wait(int Time){ScriptBuf[1] = 0x01;ScriptBuf[2] = 0x00; if (Time >= -128) and (Time <= 127) {ScriptBuf[3] = 0x04;memcpy(&ScriptBuf[4], &Time, 1);        } else if (Time >= -32768) and (Time <= 32767) {ScriptBuf[3] = 0x05;memcpy(&ScriptBuf[4], &Time, 2);        } else {ScriptBuf[3] = 0x01;memcpy(&ScriptBuf[4], &Time, 4);        }int result = ExecuteScriptBuf(); // Execute script stub.}

 

Then you would just go:

Wait(1000); // 0001: wait 1000 ms

 

ScriptBuf is an array of BYTE, each part of it is 1 byte long so

ScriptBuf[4] = 0x1C7DD90; //Actor ID

won't work as you are trying to put 4 bytes into a memory of 1 byte.

 

@Y_Less:

so wait 2000 ms would be 01 00 05 07 D0 (7D0 is 2000 in HEX and the numbers are not reversed, but they require a preceding 0 to pad it out).

Are you sure? I thought that parameters were written the normal way if they are > 1 byte ie. "reversed".

Link to comment
Share on other sites

Very good, this is starting to actually make SENSE.

 

Awesome with the help. Thanks!

 

I have much to play with now...

 

EDIT: This is what HexWorkshopFree spits out for me:

 

/*00D459:*/ 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x64, /*00D46A:*/ 0x03, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xF0, /*00D47C:*/ 0x03, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x18, /*00D48E:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x1C, /*00D4A0:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x20, /*00D4B2:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xD0, /*00D4C4:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x98, /*00D4D6:*/ 0x0F, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xBC, /*00D4E8:*/ 0x10, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x48, /*00D4FA:*/ 0x11, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xE4, /*00D50C:*/ 0x13, 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 64 03 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 F0 03 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 18 0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 1C 0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 20 0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 D0 0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 98 0F 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 BC 10 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 48 11 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 E4 13 

 

 

The top section is C++ formated (very handy, yes?), the bottom is regular hex. So that I am clear, I am looking for the number immediately following the 02. In the first case it's 64, followed by 03. Now in my code (and the code random posted after) I have two spaces for the actor; do I need to use both the 64 and the 03, or is it just one or the other? Either way, I will play with both and see what happens...

 

I had a feeling about the int Main() thing; as I was looking over some sample code, I noticed that I can build all of the opcodes in Main() and call them with my OnKeyDown from another file. Silly of me perhaps, but I'm battling not only learning the syntax of C++, but also how to integrate that with all of the MB coding that I use now. I greatly appreciate the help in figuring this out though.

 

This is starting to remind me of the minor GameShark hacking I used to do with WWF No Mercy.

 

cool.gif

Edited by ceedj

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 64 03

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 F0 03

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 18 0D

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 1C 0D

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 20 0D

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 D0 0D

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 98 0F

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 BC 10

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 48 11

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 E4 13

 

Using this formatting, it is alot clearer to see what is going on, after all the 0C 00 02 are the ped references (64 03, F0 03, 18 0D ect), by the looks of things, they are backwards, so large waits probably are too.

 

Also, you variables: $Grp1Ped1?? are not valid $ indicates MB variable ?? indicates memory reference, for the first pe you could EITHER use $Grp1Ped1 or 0364??, but not both in the same SCM. If you use 0364?? the ped will definately be stored at 0364 (02 64 03), if you use $Grp1Ped1 it will be stored at the next availabe address assigned by MB, if you are going to be modifying your SCM alot and integrating it with C, I would suggest using the ?? variables so for every compile they are the same (as MTA do), just be careful you don't use an address used elsewhere, this is why we often advise against using numbered variables.

Link to comment
Share on other sites

random_download

 

I have two spaces for the actor; do I need to use both the 64 and the 03, or is it just one or the other? Either way, I will play with both and see what happens...

You use both. The actor is defined by the number "364", so in your code you will use this to reference the actor:

ScriptBuf[4] = 0x64;

ScriptBuf[5] = 0x03;

 

Or you could do:

int Actor = 0x0364;

memcpy(&ScriptBuf[4], &Actor, 2);

 

Which will do the same thing.

Edited by random_download
Link to comment
Share on other sites

I REALLY appreciate the help guys, and I don't want to piss anyone off...

 

But...

 

I'm recoding my scm into C++, using spooky's structures. Trying to do this memory crap and all that is more of a pain than I need to deal with right now. I got about half of it done (just finishing up the system-wide keyhook); just need to setup a few more structures and opcodes.

 

Thanks very much though; everything is VERY informative. colgate.gif

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Hy.

 

Sorry to bother you again, but isn't there still a version for San Andreas ? i would like to add some things to SA, but without modifying the MAIN.SCM.

 

Question, if i save a game witha "SCM Hooking MOD", can it be loaded with "normal" GTA ? or it's the same as if you would have modified the MAIN.SCM file ?

Link to comment
Share on other sites

  • 1 month later...
Spookie has made a San Andreas version, but from what I know the source hasn't been released

Like, OMG!

 

I hope he's not mad at me for using the Vice version. cryani.gif

 

I'd love to see that source though. Mostly so the 8 billion people can stop pestering me for San An Studios! blink.gif

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Question, if i save a game witha "SCM Hooking MOD", can it be loaded with "normal" GTA ? or it's the same as if you would have modified the MAIN.SCM file ?

As long as the scm hook doesn't call a create_thread command then you should be able to save and then load from an original scm file. If however any threads are created or destroyed, then you will not be able to load a game you make after doing this with an original scm.

Link to comment
Share on other sites

Spookie has made a San Andreas version, but from what I know the source hasn't been released

Like, OMG!

 

I hope he's not mad at me for using the Vice version. cryani.gif

 

I'd love to see that source though. Mostly so the 8 billion people can stop pestering me for San An Studios! blink.gif

I don't think he will be mad at you for it, as he released it to be used, and you have made some very good missions with it.

Link to comment
Share on other sites

  • 4 weeks later...

Excellent work, Spooky!

 

I've just gotten started with this GTA:SA modding malarky. all those funny cryptic numbers and the evil dreaded goto-style "jump" thingies in the script files were making my head ache! nervous.gif

 

Great to see there's a way to mod GTA in a language which I can actually understand and make sense of tounge.gifsmile.gif

 

Great job, thanks for the contribution biggrin.gif

Link to comment
Share on other sites

Um, you do know that this was meant for Vice City.. It'll not work with San Andreas, unless you can get Spookie to give you the SA version (rumor)

 

-Nipa

Link to comment
Share on other sites

  • 3 weeks later...

Here's an updated GAME_SCRIPT_THREAD for GTA:SA

 

 

struct GTASA_SCRIPT_THREAD	// 0xE0 bytes total.{      	//void* pNext;  	// 0x00void* pPrev;  	// 0x04char strName[8];  // 0x08DWORD dwBaseIP;  	// 0x10DWORD dwScriptIP;  // 0x14DWORD dwReturnStack[8];	// 0x18WORD dwStackPointer;	// 0x38DWORD dwLocalVar[34];	// 0x3CBYTE bStartNewScript;	// 0xC4BYTE bJumpFlag;  	// 0xC5BYTE bIsMissionThread;// 0xC6BYTE bIsExternalScript;// 0xC7BYTE bInMenu  	// 0xC8BYTE bUnknown;	// 0xC9DWORD dwWakeTime;  // 0xCCWORD wIfParam;  	// 0xD0BYTE bNotFlag;  	// 0xD2BYTE bWastedBustedCheck;// 0xD3BYTE bWastedBustedFlag;	// 0xD4DWORD dwSceneSkipIP;  // 0xD8BYTE bMissionThread;	// 0xDC};

 

 

Comments:

  • dwScriptIP contains an absolute address, not relative to script base.
  • For mission and external script threads, dwBaseIP contains the base address of the buffer at which the code is stored, since the code is not stored at the usual script base buffer. Jump targets with a negative value are relative to this address (the negative value is subtracted from dwBaseIP.) The buffer for mission threads is at address 0xA7A6A0. Buffers for external scripts are allocated dynmically since there can be many of them.
  • For non-mission threads (bMissionThread == 0), the thread's local vars are stored at offset 0x3C as above. For mission threads (bMissionThread != 0), the thread's local vars are stored in a buffer of length 4096 bytes at address 0xA48960 (right below the script base). There can only be 1 mission thread running, so there is no sharing problem for this buffer.
  • Local vars @32 and @33 are up-counting millisec timers. This holds true regardless of where the local vars are stored.
  • The flag bIsMissionThread appears to always have an identical value to bMissionThread, although it's tested for different purposes.
  • bWastedBustedCheck is set to 1 for all new threads. However an actual check is only performed if both bIsMissionThread and bWastedBustedCheck are non-zero.
  • dwSceneSkipIP is an IP to jump to if a cutscene is terminated by a keypress.
  • bInMenu indicates if the thread is in a game menu (the type used for buying food, clothes, ammunation, etc., not the main menu.)
  • bUnknown is initialized to 0xFF when a thread is created. It is used by external script threads where is can have a value of either 0xFF or 0-5.
Edited by op9080
Link to comment
Share on other sites

  • 2 months later...

I am a cheap basterd and am currently learning C++. I have "Microsoft Visual C++ 2005 Express Edition", since its the only on I can get directly from Microsoft. I also have DevC++ and Microsoft C++ 6. But when I load it up with 2005 Expr. Edit. I get this after its converts it to the new.

 

 

Project: SCMMod

Filename Status Errors Warnings

SCMMod.vcproj Converted 0 2

Conversion Issues - SCMMod.vcproj:

Visual C++ now supports a secure version of the C Runtime Library. Use of this library is turned on by default. You may see some warnings about deprecated functions when you build your project. It is advised that you correct these warnings, in order to make your code more secure.

The C/C++ compiler default settings have been modified to be more compliant with ISO Standard C++. Included in those changes are enforcing Standard C++ for loop scoping and supporting wchar_t as a native type. These changes may cause existing code to no longer compile without changes to the code or the compiler options with which it is built.

Project file successfully backed up as 'C:\Documents and Settings\Dustin\Desktop\SCMMod\src\SCMMod.vcproj.7.10.old'.

Project upgraded successfully.

Due to the requirement that Visual C++ projects produce an embedded (by default) Windows SxS manifest, manifest files in the project are automatically excluded from building with the Manifest Tool. It is recommended that the dependency information contained in any manifest files be converted to "#pragma comment(linker,"<insert dependency here>")" in a header file that is included from your source code. If your project already embeds a manifest in the RT_MANIFEST resource section through a resource (.rc) file, the line will need to be commented out before the project will build correctly.

Due to a conformance change in the C++ compiler, code change may be required before your project will build without errors. Previous versions of the C++ compiler allowed specification of member function pointers by member function name (e.g. MemberFunctionName). The C++ standard requires a fully qualified name with the use of the address-of operator (e.g. &ClassName::MemberFunctionName). If your project contains forms or controls used in the Windows Forms Designer, you may have to change code in InitializeComponent because the designer generated code used the non-conformant syntax in delegate construction (used in event handlers).

 

1 file  Converted: 1

Not converted 0

 

Is this some thing I should worry about and if so what should I do?

 

Also I don't know how to load it with VC6++, as it doesn't have a workstation.

 

Btw THIS MOD KICKS A$$

 

Edit:

I complied it in Express Edition and got this long list of errors, Log

 

Edit: Compiling in VC++6

 

--------------------Configuration: SCMMod - Win32 Debug--------------------

Compiling...

ScriptClasses.cpp

GameScripting.cpp

GxtHook.cpp

MissionHook.cpp

c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

MissionThreads.cpp

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

SCMMod.cpp

Error executing cl.exe.

 

SCMMod.dll - 4 error(s), 1 warning(s)

Edited by dustcrazy
Link to comment
Share on other sites

  • 3 months later...

 

Edit: Compiling in VC++6

 

--------------------Configuration: SCMMod - Win32 Debug--------------------

Compiling...

ScriptClasses.cpp

GameScripting.cpp

GxtHook.cpp

MissionHook.cpp

c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

MissionThreads.cpp

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'

        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'

SCMMod.cpp

Error executing cl.exe.

 

SCMMod.dll - 4 error(s), 1 warning(s)

Final edit(I hope):

Sorry for the bump, i had the same problem, and asked for help, but i figured it out:

 

I fixed the bBringMsg warning by moving

bool bBringMsg = false;

directly beneath

float fX, fY, fZ;

 

 

The

 

c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

 

warning is fixed by removing one = in the line.

 

But now, the mission wont start if i stand in the marker, the marker does disappear, but nothing happens..

Edited by grovespaz
Link to comment
Share on other sites

 

The

 

c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

 

warning is fixed by removing one = in the line.

 

But now, the mission wont start if i stand in the marker, the marker does disappear, but nothing happens..

Put the '=' sign back. You're changing a test for equality into an assignation. If you you want to remove the warning either change one of the data types or perform a cast.

Link to comment
Share on other sites

 

c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

 

 

This warning has ALWAYS shown up from day one. I think it's because it was written in 7.1, and we compile with 6.0. I've always ignored it, and never had any issues. But like Cowpat said, put the other = back in; that statement checks if a mission is running.

 

I also had an issue with bBringMsg at the very beginning, but it's been almost a year since I've done it that I can't quite remember what I did. If you're still having problems, post back and I'll compare my code with the original and we'll see what I can find.

 

smile.gif

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

  • 2 weeks later...

Ceedj, is there any chance you could give a c++ noob using dev-c++ 'a few tips' on how to compile this in dev-c++. I like the idea of coding missions with c++ syntax, but my knowledge of the language... and compilers in general, is somewhat limited.

Link to comment
Share on other sites

I don't think it will compile in dev c++, but I could be wrong. I've got MSVC++, so I never had a problem...

 

Anyone else have thoughts on this?

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

I don't think it will compile as some of the libaries will be different. If you want to write missions in C syntax, have a look at POINT, a mission compiler with C syntax.

Link to comment
Share on other sites

 

Ceedj, is there any chance you could give a c++ noob using dev-c++ 'a few tips' on how to compile this in dev-c++. I like the idea of coding missions with c++ syntax, but my knowledge of the language... and compilers in general, is somewhat limited.

It seems that dev-cpp and directx will work together, but a little work is required to set it up. From what I've read Dev-cpp won't read .lib files unless they are converted to it's own .a (or .as ?) format. A utilty which comes with the MinGW compiler called reimp does that job, though you might like to write a little Batch file to do it.

 

This link appears useful, also this link and this link

Link to comment
Share on other sites

thanks for the help but i'm afraid all that direct-x stuff is way over my head.

If anyone can give me a link for POINT i would be most grateful.

Link to comment
Share on other sites

  • 1 year later...

HUGE BUMP. YEAH!

 

Anyway, I'm having a problem, similar to the text issue I had using the SA hook (which CyQ was awesome enough to help fix). Same issue here; there are two animation headers in the game that I can't load because the strings are too long: playidles and sunbathe. Anyone wanna take a stab at how I can resolve this?

 

Thanks muchly! smile.gif

 

EDIT: This is related to this post if anyone wonders why I want to fix this. Thanks again.

Edited by ceedj

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.