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. The Criminal Enterprises
      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. Grand Theft Auto Series

      1. Bugs*
      2. 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. Classic GTA SA
      2. Guides & Strategies
      3. Help & Support
    6. GTA Vice City

      1. Classic GTA VC
      2. Guides & Strategies
      3. Help & Support
    7. GTA III

      1. Classic GTA III
      2. Guides & Strategies
      3. 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. Red Dead Redemption 2

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

    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

    2. Support

    3. Suggestions

[SA] Simple Menu-Driven Vehicle Spawner


pdescobar
 Share

Recommended Posts

I wanted to spawn some vehicles to do some testing and I wanted to learn about creating in-game menus, so I looked up Patrick's menu tutorial in the Google cache and created the following simple vehicle spawner. Too lazy to wrap it up nice and polish it for a full-blown release but it's small enough I thought I'd post it here for general discussion and in case someone would find it useful.

 

This is a menu-driven vehicle spawner based on vehicle IDs implemented as a MAIN thread. Although if you have installed Xieon's memory access patch I hacked in display of in-game names for those vehicles which have them. The source is Sanny Builder syntax although aside from a couple for loops it should be fairly easily translatable to SAMB.

 

Some in-game screens showing the 3 levels of menu and the resulting spawned vehicle:

user posted image user posted image user posted image user posted image

 

As mentioned in the opening comment block, I'm aware that the "help text" only partially makes sense due to my not bothering to make custom GXT entries; I also know the menu size and position could stand some tweaking. Any sort of C&C is welcome; I'm particularly interested in things like better understanding whether the player defined check is absolutely necessary, thoughts on the 50 ms wait time, handling of the actual spawn, and efficiency issues.

 

 

// ======================================//  Simple Vehicle Spawner by PD Escobar// ======================================// A simple menu-driven ID-based vehicle spawner for GTA:SA. Activated by// pressing ACTION + SPRINT when on foot. Menus then pop up allowing the// player to fairly quickly pick the ID of the vehicle to spawn. The// vehicle will appear 5m in front of CJ. Optionally will display the// in-game name of the vehicles on the final menu if Xieon's memory access// patch is installed. Memory addresses probably specific to US v 1.0.// Also, menu help text doesn't completely make sense in order to use// existing GXT entries. Feel free to use it however you wish; if used in// a released mod, mention in the credits would be appreciated. // ======================================// Important Variables// [email protected]@ : Temporary use// [email protected] : Selection from panel 1 (row)// [email protected] : Selection from panel 2 (row)// [email protected] : Selection from panel 3 (row)// [email protected] : Selection from panel 1 (value)// [email protected] : Selection from panel 2 (value)// [email protected] : Selection from panel 3 (value)// [email protected] : Highest allowed ID// [email protected] : Selection from current panel (row)// [email protected] : Current panel handle:MenuSpawnerthread 'SPAWN01'[email protected] = 611 // Highest allowed ID:MenuSpawnerMainLoopwait 50// I'm referencing the player later, so I guess I need this checkif   Player.Defined($PLAYER_CHAR)jf @MenuSpawnerMainLoop// Only check for keypresses if outside of a vehicleif NOT Actor.Driving($PLAYER_ACTOR)jf @MenuSpawnerMainLoopif  00E1: key_pressed_on_pad 0 button 4  // Actionjf @MenuSpawnerMainLoopif  00E1: key_pressed_on_pad 0 button 16 // Sprintjf @MenuSpawnerMainLoop:MenuSpawnerKeyReleasewait 0if and  80E1: NOT key_pressed_on_pad 0 button 4  // Action  80E1: NOT key_pressed_on_pad 0 button 16 // Sprintjf @MenuSpawnerKeyRelease01B4: set_player $PLAYER_CHAR can_move 0 // Init row select [email protected] = [email protected] = [email protected] = 0:MenuSpawnerLevel10512: permanent text box 'CLOTHA'08D4: [email protected] = create_panel title 'DUMMY' position 29.0 145.0 col_width 90.0 columns 1 interactive 1 bg 1 align 1// Hardcoded; smaller than a for loop since only 3 values08EF: set_panel [email protected] column 0 row 0 text_2numbers 'TIME' 400 499  // ~1~:~1~08EF: set_panel [email protected] column 0 row 1 text_2numbers 'TIME' 500 599  // ~1~:~1~08EF: set_panel [email protected] column 0 row 2 text_2numbers 'TIME' 600 699  // ~1~:~1~090E: set_panel [email protected] active_row [email protected] gosub @MenuSpawnerKeyCheckif  [email protected] > -1jf @MenuSpawnerEnd0085: [email protected] = [email protected]: [email protected] = [email protected]@ += [email protected] *= 100:MenuSpawnerLevel20512: permanent_text_box 'CLOTHB'08D4: [email protected] = create_panel title 'DUMMY' position 29.0 145.0 col_width 90.0 columns 1 interactive 1 bg 1 align 10085: [email protected] = [email protected] [email protected] = 0 to 9  if     001D: [email protected] >= [email protected]  jf break  0085: [email protected] = [email protected]  [email protected] += 9  08EF: set_panel [email protected] column 0 row [email protected] text_2numbers 'TIME' [email protected] [email protected]  // ~1~:~1~  [email protected] += 10end090E: set_panel [email protected] active_row [email protected] gosub @MenuSpawnerKeyCheckif  [email protected] > -1jf @MenuSpawnerLevel10085: [email protected] = [email protected]: [email protected] = [email protected]@ *= 10005A: [email protected] += [email protected]:MenuSpawnerLevel30512: permanent_text_box 'IE21'08D4: [email protected] = create_panel title 'DUMMY' position 29.0 145.0 col_width 100.0 columns 2 interactive 1 bg 1 align 109DB: set_panel [email protected] column 0 width 50   09DB: set_panel [email protected] column 1 width 150   0085: [email protected] = [email protected]@s = 'DUMMY'// Comment out this section if Xieon's memory access patch is not installed// START of memory access setup0085: [email protected] = [email protected]@ -= [email protected] *= [email protected] += 11662982 // Adjust this address for exe's other than US v1.0// END of memory access setupfor [email protected] = 0 to 9  if     001D: [email protected] >= [email protected]  jf break  08EE: set_panel [email protected] column 0 row [email protected] text_1number 'NUMBER' [email protected]  // ~1~  // Comment out this section if Xieon's memory access patch is not installed  // START of memory access  00C3: read_mem_address [email protected] words 2 store_to [email protected]  [email protected] += 4  00C3: read_mem_address [email protected] words 2 store_to [email protected]  [email protected] += 772  // END of memory access  08EE: set_panel [email protected] column 1 row [email protected] text_1number [email protected] 0  // Vehicle Name  [email protected] += 1end090E: set_panel [email protected] active_row [email protected] gosub @MenuSpawnerKeyCheckif  [email protected] > -1jf @MenuSpawnerLevel20085: [email protected] = [email protected]: [email protected] = [email protected]: [email protected] += [email protected]: request_model [email protected] :MenuSpawnerModelWaitif 8248: not model [email protected] available jf @MenuSpawnerDoSpawnwait 0jump @MenuSpawnerModelWait:MenuSpawnerDoSpawn04C4: create_coordinate [email protected] [email protected] [email protected] from_actor $PLAYER_ACTOR offset 0.0 5.0 -1.10674: set_vehicle_model [email protected] numberplate "__GTAF__" // unnecessary silliness 00A5: [email protected] = create_vehicle [email protected] at [email protected] [email protected] [email protected]: [email protected] = actor $PLAYER_ACTOR [email protected] += 90.00175: set_vehicle [email protected] z_angle_to [email protected]: set_car [email protected] door_status_to 1 // make sure it's unlocked; damned police...   0249: release_model [email protected] 01C3: remove_references_to_car [email protected] // Like turning a car into any random car :MenuSpawnerEnd01B4: set_player $PLAYER_CHAR can_move 1jump @MenuSpawnerMainLoop// Menu key processing subroutine// Assumes [email protected] is menu handle, saves selection to [email protected]:MenuSpawnerKeyCheckwait 0if  00E1: key_pressed_on_pad 0 button 15 // EXITjf @MenuSpawnerKeyCheck2:MenuSpawnerKeyCheckReleasewait 0if   80E1: NOT key_pressed_on_pad 0 button 15 // EXITjf @[email protected] = -1jump @MenuSpawnerKeyCheckEnd:MenuSpawnerKeyCheck2if  00E1: key_pressed_on_pad 0 button 16 // Selectjf @MenuSpawnerKeyCheck:MenuSpawnerKeyCheck2Releasewait 0if   80E1: NOT key_pressed_on_pad 0 button 16 // Selectjf @MenuSpawnerKeyCheck2Release08D7: [email protected] = panel [email protected] active_row :MenuSpawnerKeyCheckEnd08DA: remove_panel [email protected]: remove_text_boxreturn

 

Link to comment
Share on other sites

I'll give it the usual once over. I'll lay it on thick too because I've wanted to make a Car Spawn for SA and just never got around to it tounge2.gif

 

In your keypress release loop, you've referenced the player and a wait has elapsed since the last if defined check. So you'll need another one there with a JF that bounces back to the beginning. When you go to spawn the car, you again start talking about the player. You should have another if defined check there with a JF that will lead to releasing the loaded model and then bouncing back to the beginning.

 

I found your code hard to read. For one, it's Sanny which I'm not accustomed to (no biggie). Secondly, it's heavily noted, sometimes on separate lines. Also no biggie. And while the next point is also no biggie, it's more than aesthetics and think it should be heeded. You say if player not driving if key pressed 4 if key pressed 16. They all have the same JF address and none of them are required to preceed the others (like the player defined check). So there's no reason not to clump them. You'll save 22 bytes doing this and since it's a MAIN thread, this will add up for SA users.

 

If you care to, you could also flip the MenuSpawnerModelWait loop to save another 7 bytes.

 

Otherwise, all good. I didn't pay too much attention to the nitty gritty as I think I grasp the concept anyways, having done 3 versions of the Car Spawn mod myself. You might want to look into it. I like your code for the sake of simplicity. However, I think it was v3 where I specifically wrote it out in longhand to make it easily editable by novice coders. Or for the progression mode option even.

Link to comment
Share on other sites

 

I'll give it the usual once over. I'll lay it on thick too because I've wanted to make a Car Spawn for SA and just never got around to it tounge2.gif

Thanks for the feedback smile.gif Laying it on thick is good as I'm still quite new at this and don't know a lot of the subtleties.

 

 

In your keypress release loop, you've referenced the player and a wait has elapsed since the last if defined check. So you'll need another one there with a JF that bounces back to the beginning. When you go to spawn the car, you again start talking about the player. You should have another if defined check there with a JF that will lead to releasing the loaded model and then bouncing back to the beginning.

OK, so every time a wait has passed, the player may become undefined? Is it then sometimes better to use a subroutine to run the if defined check if you have to do it multiple times? EDIT: Actually, now that I think about this, a subroutine may not help...

 

 

I found your code hard to read. For one, it's Sanny which I'm not accustomed to (no biggie). Secondly, it's heavily noted, sometimes on separate lines. Also no biggie. And while the next point is also no biggie, it's more than aesthetics and think it should be heeded. You say if player not driving if key pressed 4 if key pressed 16. They all have the same JF address and none of them  are required to preceed the others (like the player defined check). So there's no reason not to clump them. You'll save 22 bytes doing this and since it's a MAIN thread, this will add up for SA users.

Heavy commenting is a habit of mine, and the less experienced I am with a language, the heavier it gets. wink.gif Thanks for the tip on the if checks. For some reason, in the past I had real trouble with clumped keypress checks, but that must have been due to some other problem because the following worked just fine in a quick test.

 

if and  NOT Actor.Driving($PLAYER_ACTOR)  00E1: key_pressed_on_pad 0 button 4  // Action  00E1: key_pressed_on_pad 0 button 16 // Sprintjf @MenuSpawnerMainLoop

 

 

 

If you care to, you could also flip the MenuSpawnerModelWait loop to save another 7 bytes.

 

Otherwise, all good. I didn't pay too much attention to the nitty gritty as I think I grasp the concept anyways, having done 3 versions of the Car Spawn mod myself. You might want to look into it. I like your code for the sake of simplicity. However, I think it was v3 where I specifically wrote it out in longhand to make it easily editable by novice coders. Or for the progression mode option even.

Thanks, I may take a look at other car spawners such as yours now that the forum is back up and supposedly searchable again. The progression sounded interesting when I read about it in a google cached copy of space's all-in-one mod, but it was beyond my initial simple needs.

Edited by pdescobar
Link to comment
Share on other sites

Nice. Thinking about releasing it? I can't see any problems other than the minor ones Dem indicated. To answer some of your questions:

 

 

OK, so every time a wait has passed, the player may become undefined?

 

Yes. Dem would expand more on this; when the script 'waits', of course the game goes on, so the player can die, etc. If you have a loop with no waits, the script keeps on running the game simply freezes. Wait 0 means (I assume R* made this like other programming languages, and this is most likely true) to wait for the shortest time possible (by "definition": to stop waiting as soon as other pending events have finished. OR something to that extent monocle.gif ). The game EXE itself doesn't continue running while the script is running (to avoid problems) so the player doesn't simply die between this opcode and that one, for example. It continues on wait commands. If you have a lot of threads running with low wait numbers the game will run slowly. The wait time is in milliseconds, so 1000 is one second, 500 is a half etc. You ask what waiting time you should use. That depends on the "urgently-ness" of that loop. For example, if you have a loop in the middle of your code it should have relatively lower waiting time since the code is in the middle of running and obviously you want it to continue. But in the first loop (this is how it is in 90% of mod threads) you have something like this (psuedo-MB format):

 

:ModName_keycheckwait NUMif 2;;three conditionals  player $player_char defined  key_pressed X  key_pressed Yjump_if_false ModName_keycheck

 

(Note that key_pressed does not "count" as referencing the player, understandable, as it simply checks the keyboard/controller status, not dealing with the player at all)

 

OK, so this is the beginning of our mod, it isn't very urgent. Most people use a wait time of 250 to 500. I usually use 'overdone' numbers like 1000. The penalty of a big delay in these kind of loops decide is pretty much how long (the maximum possible time) the player will need to hold the button down. IMO no player would even tell the difference between holding the button for quarter a second or a whole second so this isn't a real penalty for these kind of loops and you can safely make them relatively big and not worry about the game freezing because you have a lot of running threads with low delays (people can count this as overly-careful indeed since crashing of that is VERY rare but again there's no real penalty).

Deeper in your mod you can have something like this, also a very standard label:

 

:ModName_loadedwait 0if 0;;one conditionalmodel #M loadedjf ModName_loaded

 

 

Now here you should always use wait 0. Models usually load very fast since typically you would request a (relatively) tiny model of a car or bike or ped or weapon, not a building or road and a lot of time the loop isnt necessary and the model loads almost instantly. However as known loops are the failproof method and are even more required on PCs since you can have heavy background processes slowing the system down like anti-viruses etc (note that in SA you now do have the AT400 as well that model mods can be made huge like other big planes and ferrys) so it's best to DO use loops. If you use a wait of one second you pretty much waste time since again usually models load "instantly". However if you do use a wait 0 AND you happen to be loading some huge models you don't fear taking a toll on the game since it's only one thread and very temporary (unlike keypress check loops that continue to directly jump to themselves until the keys are pressed).

 

Right, I think I should stop now since I wrote too much on such a tiny subject (hope it doesnt just confuse you blush.gif ) more than necessary. I probably drank too much [cola], cough. So er, good luck, I'm off, thankfully [people like] Dem are here to fix any mistakes in this post if needed. ph34r.gif

Link to comment
Share on other sites

Just to confirm as Bigun didn't seem entirely convinced, wait 0 does wait for one game itteration (technically any wait less then the time needed for one itteration will). Also, cars and bikes etc are higher poly than most map models as they're used more and need to be and are thus bigger files, actual physical ingame size has little to no bearing on file size.

 

You may also want to consider using a local variable to set wether the memory patch is used or not to jf past it and not worry about people making sure they comment everything out.

Link to comment
Share on other sites

OK, so every time a wait has passed, the player may become undefined? Is it then sometimes better to use a subroutine to run the if defined check if you have to do it multiple times? EDIT: Actually, now that I think about this, a subroutine may not help...
If it's a mock subroutine, maybe. Depends on the mod and what comes from the differences. More often than not though, there's no benefit in farming it out. It varies from situation to situation. It also depends on how you plan on consolidating. If your goal is streamlined-looking code, then it's more likely to have SOME uses. If it's for the sake of compressing footprint, hardly ever will it be a viable option.

 

 

Heavy commenting is a habit of mine, and the less experienced I am with a language, the heavier it gets. wink.gif
And I would never get down on somebody for that. As a rule, I tend to comment not enough, but I'm getting much better. I was referring more to the way you have comments on their own lines sometimes. Don't worry about me though. I've gotten in the habit of not spacing out code that I feel is finished/tested/solidified. Example:
:AUI_WEAPONSRELOAD00D6: if  182D8:   NOT  actor $PLAYER_ACTOR currentweapon ==  082D8:   NOT  actor $PLAYER_ACTOR currentweapon ==  1004D: jump_if_false ££AUI_WEAPONSRELOADTRICK:AUI_WEAPONSRELOAD20006: @18 =  00002: jump ££AUI_WEAPONSRELOADRESET:AUI_WEAPONSRELOADTRICK0085: @31 = @200006: @17 =  10002: jump ££AUI_WEAPONDRAW:AUI_WEAPONSCALCPOSTDETONATOR2

Not very readable, but that's the point (for me). Once I'm finished with a section like that, I take out all the extra carriage returns so that that section no longer catches my eye as "current" when I'm scrolling. If I posted it though, I'd probably expand it to the more traditional display for ease of those reading it.

 

 

Thanks, I may take a look at other car spawners such as yours now that the forum is back up and supposedly searchable again. The progression sounded interesting when I read about it in a google cached copy of space's all-in-one mod, but it was beyond my initial simple needs.
Can't speak for others, but you're likely to have an easier time researching mine by just going to my site. You'll have to peek into the GTA3 codes for the full progression of examples. On to waits...

 

Waits are an acquired taste as well as a sign of experience. The latter means that you can always tell when somebody's new to coding as they'll riddle their code with waits or choose values that aren't necessary. One common example is keypresses. Some newer people are forethoughtful enough to consider (sometimes by falling first) waiting for a release. A good coder will program a release loop. A newer coder will rely on a wait. At least with published code. I'm sure everybody throws in the occassional wait for testing purposes.

 

Wait selection is important though as it impacts various things. As Bigun pointed out, an is loaded check should always be wait 0. He was also right to differentiate main waits and loop waits, though I disagree with their position dictating how it should go. I've had mods with lax waits that "speed up" when they're "active". And I've had high-priority threads switch to a more dormant state say for example when you're arrested or busted. This will return is player defined false for a good 5 second. No thread looping waiting for player to be defined again needs to be high priority here.

 

My understanding of this psuedo multi-thread environment is that threads sort of form a line. When they encounter a wait, they fall back in line based on the length of wait. wait 0 is a way of saying this thread really shouldn't relinquish focus, but it has to. When a wait 0 is encountered, it will probably jump back in line to just after all the other wait 0's. Unless of course there's a longer wait that has reached it's time and gets ahead as well. The way I understand it, when a thread encounters a wait, an address then stores the value that the internal timer must reach before that thread needs focus again. In GTA3/VC, this was [email protected], which was cool because it meant that if you set [email protected] and read it before your next wait, it was like a free local.

Link to comment
Share on other sites

 

Nice. Thinking about releasing it? I can't see any problems other than the minor ones Dem indicated. To answer some of your questions...

I might release it eventually, but it has too many little "sloppiness" annoyances in its current form. I'm a bit of a perfectionist, so I hate releasing stuff that's not really complete. wink.gif Thanks for the feedback on the waits, as well.

 

--

 

 

You may also want to consider using a local variable to set wether the memory patch is used or not to jf past it and not worry about people making sure they comment everything out.

Yeah, that's a good idea for a source release, although it would still make sense for someone to comment out those sections if they don't use the patch to keep from bloating up the code unnecessarily. I had actually been trying to think of a way to automatically detect if the patch was installed, perhaps by setting a var to zero, reading a known location (with non-zero value) and seeing if the var changed. But that's probably overkill for something like this; the fact that the memory address is exe-specific means it'll never be completely idiotproof anyhow.

 

--

 

 

Heavy commenting is a habit of mine, and the less experienced I am with a language, the heavier it gets. wink.gif
And I would never get down on somebody for that. As a rule, I tend to comment not enough, but I'm getting much better. I was referring more to the way you have comments on their own lines sometimes. Don't worry about me though. I've gotten in the habit of not spacing out code that I feel is finished/tested/solidified.

Another stylistic convention. Basically, if my comment applies to a single statement, I'll put it at the end of that line. However, if my comment applies to multiple lines of code (or I think it is especially important,) I will put it on its own before that code section because I'm much more likely to notice it there. We all have our own little coding habits. biggrin.gif

 

 

Waits are an acquired taste as well as a sign of experience. The latter means that you can always tell when somebody's new to coding as they'll riddle their code with waits or choose values that aren't necessary. One common example is keypresses. Some newer people are forethoughtful enough to consider (sometimes by falling first) waiting for a release. A good coder will program a release loop. A newer coder will rely on a wait. At least with published code. I'm sure everybody throws in the occassional wait for testing purposes.

Thanks for the further details on waits. I've actually found uses for both types of keypress processing. For something like this, where I'm always trapping a single keypress, it makes sense to loop until key release. However, there are situations where a wait can be useful. For example, when testing stats, I had a little stat displayer which put the values of 25 stats on screen at a time and a keypress would page up to the next (or previous) set of 25. In that situation, using a wait allowed me to hold down the paging key in order to scroll through multiple pages rather than having to press and release each time.

Link to comment
Share on other sites

Thanks for the further details on waits. I've actually found uses for both types of keypress processing. For something like this, where I'm always trapping a single keypress, it makes sense to loop until key release. However, there are situations where a wait can be useful. For example, when testing stats, I had a little stat displayer which put the values of 25 stats on screen at a time and a keypress would page up to the next (or previous) set of 25. In that situation, using a wait allowed me to hold down the paging key in order to scroll through multiple pages rather than having to press and release each time.

Ah, but that's you using rules and exceptions to the rules as your applications call for them. Proof of conscious thought. The wait slopiness I was referring to actually indicates a general lakc of conscious thought. Like rich people that throw money at a problem instead of addressing it, newer coders might crash one time and riddle the damn thing with waits. Which I'm finding out more and more is far from what's necessary. For all intents and purposes, Windshield is some 800-900 lines of code with a single wait. AND it was meant to exist in the original code where there's already tons going on.

Link to comment
Share on other sites

 

I had actually been trying to think of a way to automatically detect if the patch was installed

IMO, the only way to detect it is if the compiler will check some of the EXE bytes and compile the code in accordance with the returning values. Maybe it sounds non-understadable, so I'll try to give an example.

 

When a code is compiled the game EXE is available for any checks, so the coder (scripter) is able to make the compiler read the bytes at specific address of the file and remember it as a constant. I had already said that the constants support will be one of the SB3 feature.

 

So, an example (without comments)

 

constPatchByte = ReadFile(GTA_SA_EXE, 0xFFFFFF)end{$IF PatchByte == 0xFF}ReadMem([email protected], [email protected]){$END}

 

 

 

(with comments)

 

constPatchByte = ReadFile(GTA_SA_EXE, 0xFFFFFF){ ReadFile is the internal function with the following syntax: ReadFile(FileName: String; FileAddress: Integer const) GTA_SA_EXE is the internal constant, the compiler replace it with actual game path }end{$IF PatchByte == 0xFF} // just an example. this expression returns True or False{ Expression is true specific exe byte was changed, so the patch was installed >> here memory access routine goes the compiler skip another lines until $END}{$ELSE}{ Expression is False specific exe byte was not equal to needed value, something wrong >> here goes a code which does not use the memory access routines, if necessary.} {$END}

 

 

Such feature should also allow to write multiversion scripts (for both SA 1.0, SA 2.0; VC 1.0, VC 1.1) with reading of the specific addresses.

Also, as I can see, it will allow to make the config files for the hardcoded scripts (forget about changing the source)

 

 

Just the thoughts, but maybe it's interesting for someone smile.gif

Edited by Seemann
Link to comment
Share on other sites

In theory you could use the stats hack as a basic memory reader to test if the patch is installed then execute code accordingly. Not sure of the details yet but worth a look. Or, if the codes are only NOPED, not crashing prior to patching, run the mem read one at an address known to be non zero (possibly different in each EXE but constant in both) into a variable initialised to zero then use the new value of the variable (0, 1.0 EXE value or 1.1/2.0 EXE value) to execute code accordingly.

Link to comment
Share on other sites

@Y_Less: Yes, nice non-compiler-controlled idea. But the fact its just that means you will waste additional space in MAIN for checks that could be compiler-controlled. Your way(s) does still have its advantages though.

 

@Seemann: Can you also add more advanced pre-proccessor functions? Like something as this:

 

#IF COMPILER_VERSION < 3.2#CRASH(or #ERROR) "Compiler is outdated. Please upgrade to the latest version to use this {insert_mod/code_name_here}."#ENDIF

 

 

Note: #CRASH/ERROR directive cancels compiling and displays the msg after it in an error box. It doesnt crash the program. tounge.gif

Also you should have a function that "hardcodedly" auto-checks mempatch installation for mods that REQUIRE it (this menu spawner doesnt) as an easy "one-line" check for the compiler, as this (also another function and syntax for CRASH, the one above should still be accepted) directive:

 

 

#IF MEMPATCH_INSTALLED != 1#CRASH("The compiler didn't detect the SA Memory Patch!",ASK=1)#ENDIF

 

If SB didn't detect the mempatch installed, it will pause compiling and display an alert box with the text "The compiler didn't detect the SA Memory Patch!", and under it "Do you want to continue?" with Yes and No buttons which obviously decide if the compilation will halt or not. Note that you might as well have this check hardcoded into SB if mempatch not detected and it's opcodes are used.

 

In addition to COMPILER_VERSION and MEMPATCH_INSTALLED, how about these constants as well: GAME_VERSION, ("SA","VC,"GTA3") INI_VERSION (as you supported extra info in INIs), INI_AUTHOR. They'd be useful as well.

 

And these extra preproccessor commands too:

 

#ELSE(IF_FALSE) (used after #IF and before #ENDIF)#IDE c:\mods\modded_vehicles.ide (used only on top of file OR pretty much anywhere...can be used to load custom IDEs for this file. they will be used in addition with orig one to replace model names),#UNLOAD_ORIG_IDE (will make SB only use custom ides loaded with previous directive),#DEFINE Name value (to make custom constants for use with other preproccessor commands AND are replaced in code itself with associated value(I think the last bit was requested already)),#COMPILE (used to conditionally compile code. used between #IF and #ENDIF. normal SCM SB code goes after this and ends with #ENDCOMPILE. That code is only compiled if the #IF was true and otherwise SB skips it).

 

Note: Yes, this IS "stolen" from other programming langs. Some are my ideas though.

 

I hope all of this can be done, it can get very useful.

Not meaning to "highjack" this topic and could've posted this at SB topic but it was mostly inspired by Seemann's reply here and this suggestion could also be useful with the mempatch.

Edited by Bigun
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.