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

    1. Red Dead Redemption 2

      1. Gameplay
      2. Missions
      3. Help & Support
    2. Red Dead Online

      1. Gameplay
      2. Find Lobbies & Outlaws
      3. Help & Support
    1. Crews & Posses

      1. Recruitment
    2. Events

    1. GTA Online

      1. Arena War
      2. After Hours
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Grand Theft Auto Series

    3. GTA Next

    4. GTA V

      1. PC
      2. Guides & Strategies
      3. Help & Support
    5. GTA IV

      1. Episodes from Liberty City
      2. Multiplayer
      3. Guides & Strategies
      4. Help & Support
      5. GTA Mods
    6. GTA Chinatown Wars

    7. GTA Vice City Stories

    8. GTA Liberty City Stories

    9. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    10. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    11. GTA III

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    12. Top Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    13. Wiki

      1. Merchandising
    1. GTA Modding

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Mod Showroom

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

      1. DYOM
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Red Dead Redemption

    2. Rockstar Games

    1. Off-Topic

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

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

    2. Forum Support

    3. Site Suggestions

ceedj

San An Studios rewrite

Recommended Posts

ceedj

Hi gang, I'm working on a rewrite of my filming mod, because as it is now, it's a giant mess. I'll be taking a more modular approach to all the parts, and I'm pretty sure I can figure out moving and converting my endless goto's to something a bit more modern and efficient. The main part of the mod, is the giant list of keypresses it needs to listen for (I haven't counted, but I'm sure it's over a hundred, though likely not more than 30 or so at once). I have 5 (or 6) threads that all run at the same time, and they all have their own key press trees. I guess I'm wondering if there is an easier way to check other than

if (KEYINSERT) && (KEY3)
do Create Ped(3)

else

move on to next check

etc.

 

Or is this really my only option? Not really an issue if that's the case; it's the nature of the mod that needs to listen for all of this. At least when I use it. :)

 

Thanks!

Share this post


Link to post
Share on other sites
uNi

I used something familiar, with way less options though, can't you use GetKeyboardState() for this?

Share this post


Link to post
Share on other sites
ceedj
4 hours ago, uNi said:

I used something familiar, with way less options though, can't you use GetKeyboardState() for this?

Good question, would I "get" the values, and then, slug it into a switch statement? I will need TWO checks for everything - one to check the modifier (Shift, Control, etc for the peds/cars, and Insert and Delete for creation) and one for the key it's modifiying (letters, numbers, etc). The trouble is, it just WORKS now, so if the way it is winds up being the best, who cares as long as it works, right?

 

Just spitballing here, no idea is dumb; bring them on!

 

Tonight I'm going to attempt to move the stuff in the threads to their own files to make sure all that works first. Something super simple, like the time/weather function. If that all goes well, then I can work cleaning up/optimizing the code while it's still in a (mostly) working state. 

 

Thanks uNi! :)

Edited by ceedj

Share this post


Link to post
Share on other sites
K^2

What are you writing this in? When you have massive tables of conditionals to handle, you're usually better off creating an actual lookup table and processing it programatically, rather than build giant switches. Although, switches are certainly preferable to if/else trees.

 

In modern C++, you can get pretty creative, using something like std::map<std::string, std::function<void()>>, which will map a string of key codes that have to be pressed to a function to be executed. And you can push lambdas into these if you have to get creative.

Quote

#include <map>

#include <algorithm>

#include <functional>

#include <windows.h>

 

std::map<std::string, std::function<void()>> actions;

actions["\x2D""3"] = std::move([](){SpawnPed(3);}); // INSERT + '3' -> call SpawnPed(3)

actions["\x2D""4"] = std::move([](){SpawnPed(4);}); // INSERT + '4' -> call SpawnPed(4)

//...

while (true) for (auto& action : actions) if (std::all_of(action.first.begin(), action.first.end(), [](const char c){ return GetKeyState(c) < 0; })) action.second();

This might be massive overkill, but it's the cleanest the code like this will get, allowing you to add each key combination as a single line, and with all of the logic of iterating through all commands also fitting onto a single line. (So long as you declare SpawnPed, the above code actually works. Although, I suggest replacing while(true) with something more sensible.)

 

If you don't want to mess with lambdas, or if they simply aren't an option with whatever you're writing the code in, you can do the same thing with callbacks. I would still strongly suggest creating a lookup table or an array, and storing key combinations and pointers to callback functions. You can do this in C, old style C++, C#, or VBS. The main advantage over switch is that it doesn't have to all live in one giant block of code. You can split it up into sections, each one handling specific category of key presses. Heck, you could edit what every key combination is doing depending on what's happening by simply adjusting data in the map/table/array.

Share this post


Link to post
Share on other sites
ceedj
12 hours ago, K^2 said:

What are you writing this in? When you have massive tables of conditionals to handle, you're usually better off creating an actual lookup table and processing it programatically, rather than build giant switches. Although, switches are certainly preferable to if/else trees.

 

In modern C++, you can get pretty creative, using something like std::map<std::string, std::function<void()>>, which will map a string of key codes that have to be pressed to a function to be executed. And you can push lambdas into these if you have to get creative.

This might be massive overkill, but it's the cleanest the code like this will get, allowing you to add each key combination as a single line, and with all of the logic of iterating through all commands also fitting onto a single line. (So long as you declare SpawnPed, the above code actually works. Although, I suggest replacing while(true) with something more sensible.)

 

If you don't want to mess with lambdas, or if they simply aren't an option with whatever you're writing the code in, you can do the same thing with callbacks. I would still strongly suggest creating a lookup table or an array, and storing key combinations and pointers to callback functions. You can do this in C, old style C++, C#, or VBS. The main advantage over switch is that it doesn't have to all live in one giant block of code. You can split it up into sections, each one handling specific category of key presses. Heck, you could edit what every key combination is doing depending on what's happening by simply adjusting data in the map/table/array.

I love everything about this. I am using VS 2005 (C++), because it gave me headaches trying to get it to work in 2010. But I get the concept you're pushing here, and I like it a bunch. Thanks for that!

 

Moar good news, I have successfully separated the environment stuff (weather, HUD, Particles, etc) and the Frozen Clock into their own pages while still being their own threads. This is a HUGE deal, because now I can split this mess into about 15 files that can be worked on by themselves without interfering with anything else. Condensing and placing several hundred variables ought to be interesting, but for now, I'm just gonna bask in this tiny victory for a minute or so. :panic:

Share this post


Link to post
Share on other sites
K^2

Neither 2005 nor 2010 will have C++11 features. You can still use std::map, if it makes your life easier, but you can also roll your own. You will not have lambdas, and you will not have std::all_of. The later is very easily replaced. The former you can replace with function pointers.

Quote

std::map<std::string, void(*)()> actions;
actions["\x2D""3"] = &SpawnPed3;

^ This should work even in 2005, so long as you have function void SpawnPed3() defined somewhere, which means you'll have to define a function for each key combination you want to use. And you'd have to use actions.begin() and actions.end() explicitly in the loop to iterate over all actions. It's not nearly as elegant, but it's effectively the same code.

Share this post


Link to post
Share on other sites
ceedj
On 2/6/2019 at 11:41 PM, K^2 said:

Neither 2005 nor 2010 will have C++11 features. You can still use std::map, if it makes your life easier, but you can also roll your own. You will not have lambdas, and you will not have std::all_of. The later is very easily replaced. The former you can replace with function pointers.

^ This should work even in 2005, so long as you have function void SpawnPed3() defined somewhere, which means you'll have to define a function for each key combination you want to use. And you'd have to use actions.begin() and actions.end() explicitly in the loop to iterate over all actions. It's not nearly as elegant, but it's effectively the same code.

Awesomesauce, thank you for that! 

 

The biggest challenge so far in separating everything is re-figuring where some of the inline converters need to go.

 

Hey concerning design, I have at least 4 (maybe more) different file I/O routines, would it be reasonable to put them all in their own file/space? Or is this taking it a bit too far? I feel like the hardest part is getting them all to talk to each other properly, but adding/updating individual parts of the I/O will be easier in the long run.

Edited by ceedj
because I damn well felt like it

Share this post


Link to post
Share on other sites
ceedj

So, separation is still going well, but one of the challenges I'm running into is how if I want to use "game" stuff, it has to be in an active thread. To wit, this is the HookStuff:

void startProgram()
{
	initializeAddresses();
	setupCriticalSection();
	setupHooks();
	setupGXTList();
	setupScriptThreads(); - Main....main? Original Spookie Script
	setupAnimation1Thread(); - I work here too
	setupFreezeThread(); - and here
	setupEnvironmentThread(); - here too! In fact there will be a few more threads as I convert
	disableSplashScreens();
	FILE* fHandle = fopen("SanAnStudios4\\pfscs.txd","r");
	if(fHandle != NULL)
	{customscreens();
	customscreens2();}
	resumeGameThread();
etc
...}

This is the main "control" portion of how my script gets started. I can use as many of these that the game can handle, and I think I can "function" some of the non-game code (I already have my "converters" moved into their own header/cpp set). But I feel like there are a few places where it really doesn't make sense to remove the goto labels, since it's the only way to break out of my loop without breaking other stuff, For example, here is my code that creates a ped selection to scroll through:

 

Spoiler

{ThePeds:
    BrowseOn = 1;
    PedSelect = 9;
    //CallOpcode(&get_active_interior, &Interior);
    goto ShowPed;

PedKeyUp:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_PRIOR))
    {goto PedCheckUp;
    } else {
        goto PedKeyDown;}

PedKeyDown:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_NEXT))
    {goto PedCheckDown;
    } else {
        goto PedKeyKeep;}

PedKeyKeep:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_BACK))
    {SpPed = 0;
        return;
    } else {
        goto PedKeyUp;}

PedCheckUp: //Because of the funky default.ide, we need to check for unused/bad models
    PedSelect++;
switch (PedSelect){
    case 42:
    PedSelect = 43;
    goto ShowPed;
    case 65:
    PedSelect = 66;
    goto ShowPed;
    case 74:
    PedSelect = 75;
    goto ShowPed;
    case 86:
    PedSelect = 87;
    goto ShowPed;
    case 119:
    PedSelect = 120;
    goto ShowPed;
    case 149:
    PedSelect = 150;
    goto ShowPed;
    case 208:
    PedSelect = 209;
    goto ShowPed;
    case 265:
    PedSelect = 274;
    goto ShowPed;
    case 289:
    SpPedSelect = 1;
    goto SpPedCheck; 
    default:
    goto ShowPed; } 

PedCheckDown: //Because of the funky default.ide, we need to check for unused/bad models
    PedSelect--;
switch (PedSelect){
    case 8:
    if (Peds == 1)
    {SpPedSelect = 39;
    goto SpPedCheck;}
    SpPedSelect = 29;
    goto SpPedCheck;
    case 273:
    PedSelect = 264;
    goto ShowPed;
    case 208:
    PedSelect = 207;
    goto ShowPed;
    case 149:
    PedSelect = 148;
    goto ShowPed;
    case 119:
    PedSelect = 118;
    goto ShowPed;
    case 86:
    PedSelect = 85;
    goto ShowPed;
    case 74:
    PedSelect = 73;
    goto ShowPed;
    case 65:
    PedSelect = 64;
    goto ShowPed;
    case 42:
    PedSelect = 41;
    goto ShowPed;
    default:
    goto ShowPed; }

ShowPed:
    pPlayerChar->WaitUntilDefined();
    pTempPed->DestroyActor();
    pPlayerActor->GetActorCoordOffset(0.0, 1.5, 0.0, &fX, &fY, &fZ);
    pPlayerActor->GetActorZ(&fPLZangle);
    pTempPed->Spawn(4, PedSelect, fX, fY, fZ);
    pTempPed->RotateToActor(pPlayerActor->GetActor());
    pGame->ReleaseModel(PedSelect);
    SCRIPT_WAIT(50);
    goto PedKeyUp;

SpPedKeyUp:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_PRIOR))
    {SpPedSelect ++;
        goto SpPedCheck;
    } else {
        goto SpPedKeyDown;}

SpPedKeyDown:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_NEXT))
    {SpPedSelect --;
        goto SpPedCheck;
    } else {
        goto SpPedKeyKeep;}

SpPedKeyKeep:
    SCRIPT_WAIT(0);
    if (KEYDOWN(VK_BACK))
    {SpPed = 1;
    if (ShootC == 1)
    {goto ShootKeep;}
        return;
    } else {
        goto SpPedKeyUp;}

SpPedCheck:
    if (Peds == 1 && SpPedSelect >= 30)
    {goto PEDSactors;}
    switch(SpPedSelect){
        case 1:
            pGame->LoadSpecialActor(1, "TENPEN");
            SpActorTemp = "TENPEN";
            goto SpShowPed;
        case 2:
            pGame->LoadSpecialActor(1, "PULASKI");
            SpActorTemp = "PULASKI";
            goto SpShowPed;
        case 3:
            pGame->LoadSpecialActor(1, "HERN");
            SpActorTemp = "HERN";
            goto SpShowPed;
        case 4:
            pGame->LoadSpecialActor(1, "SMOKE");
            SpActorTemp = "SMOKE";
            goto SpShowPed;
        case 5:
            pGame->LoadSpecialActor(1, "SWEET");
            SpActorTemp = "SWEET";
            goto SpShowPed;
        case 6:
            pGame->LoadSpecialActor(1, "RYDER2");
            SpActorTemp = "RYDER2";
            goto SpShowPed;
        case 7:
            pGame->LoadSpecialActor(1, "RYDER3");
            SpActorTemp = "RYDER3";
            goto SpShowPed;
        case 8:
            pGame->LoadSpecialActor(1, "EMMET");
            SpActorTemp = "EMMET";
            goto SpShowPed;
        case 9:
            pGame->LoadSpecialActor(1, "OGLOC");
            SpActorTemp = "OGLOC";
            goto SpShowPed;
        case 10:
            pGame->LoadSpecialActor(1, "CESAR");
            SpActorTemp = "CESAR";
            goto SpShowPed;
        case 11:
            pGame->LoadSpecialActor(1, "KENDL");
            SpActorTemp = "KENDL";
            goto SpShowPed;
        case 12:
            pGame->LoadSpecialActor(1, "WUZIMU");
            SpActorTemp = "WUZIMU";
            goto SpShowPed;
        case 13:
            pGame->LoadSpecialActor(1, "CAT");
            SpActorTemp = "CAT";
            goto SpShowPed;
        case 14:
            pGame->LoadSpecialActor(1, "TRUTH");
            SpActorTemp = "TRUTH";
            goto SpShowPed;
        case 15:
            pGame->LoadSpecialActor(1, "JETHRO");
            SpActorTemp = "JETHRO";
            goto SpShowPed;
        case 16:
            pGame->LoadSpecialActor(1, "DWAYNE");
            SpActorTemp = "DWAYNE";
            goto SpShowPed;
        case 17:
            pGame->LoadSpecialActor(Slot, "ZERO");
            SpActorTemp = "ZERO";
            goto SpShowPed;
        case 18:
            pGame->LoadSpecialActor(1, "TBONE");
            SpActorTemp = "TBONE";
            goto SpShowPed;
        case 19:
            pGame->LoadSpecialActor(1, "JIZZY");
            SpActorTemp = "JIZZY";
            goto SpShowPed;
        case 20:
            pGame->LoadSpecialActor(1, "TORINO");
            SpActorTemp = "TORINO";
            goto SpShowPed;
        case 21:
            pGame->LoadSpecialActor(1, "SINDACO");
            SpActorTemp = "SINDACO";
            goto SpShowPed;
        case 22:
            pGame->LoadSpecialActor(1, "MACCER");
            SpActorTemp = "MACCER";
            goto SpShowPed;
        case 23:
            pGame->LoadSpecialActor(1, "PAUL");
            SpActorTemp = "PAUL";
            goto SpShowPed;
        case 24:
            pGame->LoadSpecialActor(1, "ROSE");
            SpActorTemp = "ROSE";
            goto SpShowPed;
        case 25:
            pGame->LoadSpecialActor(1, "FORELLI");
            SpActorTemp = "FORELLI";
            goto SpShowPed;
        case 26:
            pGame->LoadSpecialActor(1, "MADDOGG");
            SpActorTemp = "MADDOGG";
            goto SpShowPed;
        case 27:
            pGame->LoadSpecialActor(1, "JANITOR");
            SpActorTemp = "JANITOR";
            goto SpShowPed;
        case 28:
            pGame->LoadSpecialActor(1, "BBTHIN");
            SpActorTemp = "BBTHIN";
            goto SpShowPed;
        case 29:
            pGame->LoadSpecialActor(1, "SMOKEV");
            SpActorTemp = "SMOKEV";
            goto SpShowPed;
        case 30:
            if (Peds == 1 && SpPedSelect >= 30)
            {goto PEDSactors;}
            SpPedSelect = 1;
            PedSelect = 9;
            goto ShowPed;
        case 0:
            if (SpPedSelect == 0)
            {SpPedSelect = 1;
            PedSelect = 288;
            goto ShowPed;
            } }

PEDSactors:
        switch (SpPedSelect){
            case 30:
            pGame->LoadSpecialActor(1, "BURT");
            SpActorTemp = "BURT";
            goto SpShowPed;
            case 31:
            pGame->LoadSpecialActor(1, "DANNY");
            SpActorTemp = "DANNY";
            goto SpShowPed;
            case 32:
            pGame->LoadSpecialActor(1, "MARY");
            SpActorTemp = "MARY";
            goto SpShowPed;
            case 33:
            pGame->LoadSpecialActor(1, "JESS");
            SpActorTemp = "JESS";
            goto SpShowPed;
            case 34:
            pGame->LoadSpecialActor(1, "SNIDELY");
            SpActorTemp = "SNIDELY";
            goto SpShowPed;
            case 35:
            pGame->LoadSpecialActor(1, "SHERMAN");
            SpActorTemp = "SHERMAN";
            goto SpShowPed;
            case 36:
            pGame->LoadSpecialActor(1, "BUM");
            SpActorTemp = "BUM";
            goto SpShowPed;
            case 37:
            pGame->LoadSpecialActor(1, "TOMMY");
            SpActorTemp = "TOMMY";
            goto SpShowPed;
            case 38:
            pGame->LoadSpecialActor(1, "BILL");
            SpActorTemp = "BILL";
            goto SpShowPed;
            case 39:
            pGame->LoadSpecialActor(1, "JESS2");
            SpActorTemp = "JESS2";
            goto SpShowPed;
            case 40:
            /*pGame->LoadSpecialActor(Slot, "DON");
            SpActorTemp = "DON";
            goto SpShowPed;
            case 41:*/
            SpPedSelect = 1;
            PedSelect = 9;
            goto ShowPed;
            }

SpShowPed:
    pPlayerChar->WaitUntilDefined();
    pTempPed->DestroyActor();
    pPlayerActor->GetActorCoordOffset(0.0, 1.5, 0.0, &fX, &fY, &fZ);
    pTempPed->Spawn(4, 290, fX, fY, fZ);
    pTempPed->RotateToActor(pPlayerActor->GetActor());            
    pGame->UnloadSpecialActor(1);
    SCRIPT_WAIT(50);
    goto SpPedKeyUp;
}

EDIT: Spoilered because it's BIG.

 

Again, I can convert most of this to a couple of do(while) or fors, with a nested switch to check pg up, pg dn and backspace. But it still leaves me out of scope on the game stuff, so I feel like keeping this but reusing it on the oher creation parts will be helpful.

Anyway, just posting this stuff so maybe someone can see something I'm missing. In the meantime, still separating the big stuff. Just for giggles, I looked last night, the Custom Script was around 25000 lines! I don't even want to check the script classes and opcode files.

 

Thanks for reading/helping/not pointing and laughing. Will continue to update, whether you want it or not. :D

Edited by ceedj

Share this post


Link to post
Share on other sites
K^2

Wow.

 

A LOT of it can be cleaned up with modern C++. The STL has gotten pretty fantastic, the thread library is great, and there is a lot you can do with functionals and algorithms. Is there any particular reason not to just jump straight to 2017? I imagine the solution files are probably beyond usable with a decade in between, but there shouldn't be all that much stuff in them. And the code itself ought to be easy enough to fix up.

 

Let me take a look at the C++ hooks and see if I can get the core library to run on 2017 (or if someone already did the legwork...). That ought to allow most mods to just compile under 2017.

Share this post


Link to post
Share on other sites
ceedj
4 hours ago, K^2 said:

Wow.

 

A LOT of it can be cleaned up with modern C++. The STL has gotten pretty fantastic, the thread library is great, and there is a lot you can do with functionals and algorithms. Is there any particular reason not to just jump straight to 2017? I imagine the solution files are probably beyond usable with a decade in between, but there shouldn't be all that much stuff in them. And the code itself ought to be easy enough to fix up.

 

Let me take a look at the C++ hooks and see if I can get the core library to run on 2017 (or if someone already did the legwork...). That ought to allow most mods to just compile under 2017.

Is that the free one, Visual Studio Community? I'll try and install it, I think I need to include some specific libs for this. More and more reading has shown that an update is probably going to make this significantly easier, so what the heck. Will post some results, thanks!

 

EDIT: Holy balls, after a ton of reconfiguring, I got it to work! Just built a new version, seems to work so far (just created and animated a ped). Basics to fix are to remove the DX Include (keep DX though, in case you need to test something in an older compiler), reverse the include and library settings, and use the XP Win 7 environment (need to download this). But so far, so good.

 

EDIT2: Wow, that is really cool, just having some trouble deciphering how it all works. I think I have an idea of how (and where) to implement it, but I'd like to test the small bit you provided first. Really neat stuff, thanks so much!

 

EDIT3: Tested. Wow. Just, wow. I am going to gush slightly and say I can't thank you enough for this. Geez, what a difference. Seriously, big ups, you just got added to the welcome screen. :)

 

Now, still some figuring to do on "how" this is all going to fit together. Building functions inside the game thread will be...tricky. But, I can use what you gave me to make a simple function that changes a var (that's how I tested it inside my existing loop), so one way or another, it will get sorted. 

 

More to come! I should be sleeping, but boy, this could be fun again!

Edited by ceedj
and the reason is you...

Share this post


Link to post
Share on other sites
ceedj

Ok, last post for a bit, did most of the creation routine. Sort of.

 

The way the hook works, I think it creates the instance of player char and player actor at the injection time, which is why I can see and use these in the "main" (CustomScript.cpp), and it doesn't see anything I do outside of it. Which is for the best really, but it creates a challenge trying to code something of this scale "like a real program." Since I'm stuck in using the "game space" for most of what I need to do, I have to adapt. So I'm still using the goto's, but I'm explicitly directing where they go, wrapping them in braces, and using them as kind of a "faux function."

Spoiler

{SkinReset:
            pPlayerChar->WaitUntilDefined();
            pPlayerChar->Freeze(true);
            pGame->Fade(500, 0);
            SCRIPT_WAIT(1000);
            pPlayerChar->SetPlayerSkin(0);
            pGame->ChangeStatFloat(21, Build);
            pGame->ChangeStatFloat(23, Muscle);
            pPlayerChar->WaitUntilDefined();
            pGame->Fade(500, 1);
            pPlayerChar->Freeze(false);
            goto CreatePed1; }

Here's a perfect example; I've got a bunch of these, mostly in order, but they always are run once and immediately go back, where it returns control (so to speak) to the "main" thread. Since there are a TON of these, I've setup a page (and thread) that is nothing but these mini functions, and I just jump in and out when I need to. The big help is getting it all separated into sections (individual code pages) and K^2's awesomelicous code, which really makes it a ton easier update and navigate.

 

Spoiler

void SpawnPed(int x)
{
    WonderTwinPowers = x;
}
void DeletePed(int x)
{
    WonderTwinPowers = x;
}


DWORD __stdcall CreateThings_Thread(SCMThread *threadDesc)    //Main Creation Routines, Save/Load Files

{
    THREAD_INIT();

    std::map<std::string, std::function<void()>> createKeys;
    createKeys["\x2D""1"] = std::move([]() {SpawnPed(1); });
    createKeys["\x2D""2"] = std::move([]() {SpawnPed(2); });
    createKeys["\x2D""3"] = std::move([]() {SpawnPed(3); });     // Peds 1-6, Cars 1-4
    createKeys["\x2D""4"] = std::move([]() {SpawnPed(4); });
    createKeys["\x2D""5"] = std::move([]() {SpawnPed(5); });
    createKeys["\x2D""6"] = std::move([]() {SpawnPed(6); });
    createKeys["\x2D""7"] = std::move([]() {SpawnPed(7); });
    createKeys["\x2D""8"] = std::move([]() {SpawnPed(8); });
    createKeys["\x2D""9"] = std::move([]() {SpawnPed(9); });
    createKeys["\x2D""0"] = std::move([]() {SpawnPed(10); });
    createKeys["\x2E""1"] = std::move([]() {DeletePed(101); });
    createKeys["\x2E""2"] = std::move([]() {DeletePed(102); });
    createKeys["\x2E""3"] = std::move([]() {DeletePed(103); });
    createKeys["\x2E""4"] = std::move([]() {DeletePed(104); });     // Peds 1-6, Cars 1-4
    createKeys["\x2E""5"] = std::move([]() {DeletePed(105); });
    createKeys["\x2E""6"] = std::move([]() {DeletePed(106); });
    createKeys["\x2E""7"] = std::move([]() {DeletePed(107); });
    createKeys["\x2E""8"] = std::move([]() {DeletePed(108); });
    createKeys["\x2E""9"] = std::move([]() {DeletePed(109); });
    createKeys["\x2E""0"] = std::move([]() {DeletePed(110); });
    createKeys["\x2D""S"] = std::move([]() {SpawnPed(13); });  //Skin
    createKeys["\x2E""S"] = std::move([]() {DeletePed(113); });
    createKeys["\x2D""G"] = std::move([]() {SpawnPed(12); }); //Orginization 12
    createKeys["\x2E""G"] = std::move([]() {DeletePed(112); });
    createKeys["\x2D""\x09"] = std::move([]() {SpawnPed(11); }); //Trio Group
    createKeys["\x2E""\x09"] = std::move([]() {DeletePed(115); });
    createKeys["\x2E""\x08"] = std::move([]() {DeletePed(111); });//Delete All (except Org 12)
    createKeys["U""G"] = std::move([]() {DeletePed(114); }); //Disarm Org 12
    //createKeys["\x2D""2"] = std::move([]() {TestingStuff1(); });

    
    SCRIPT_WAIT(500);


    for (;;) 
    {
        while (BrowseOn != 0) SCRIPT_WAIT(500); 
            SCRIPT_WAIT(100);
            for (auto& createPairs : createKeys)
                if (std::all_of(createPairs.first.begin(), createPairs.first.end(), [](const char c)
                { return GetKeyState(c) < 0; }))
                    createPairs.second(); 
    }


    THREAD_EXIT();
    return 0;
}
 

Yeah, that's much better. The best part is that I get to keep most of the work I've done on this over the years. I'd never code anything like this in the real world, but it's a hack of a hack of a 15 year old game. I think I did ok.

Yes, I know this is practically ancient by today's standards, and I'm likely talking to myself, but I'm glad this is getting done, and hopefully someone else can pick up a few nuggets of knowledge along the way,

 

Thanks again! :)

 

EDIT: Oh duh, I'm looking into it on my own, but if anyone could give some tips on integrating a small part of some MTA code (I'd like to experiment with some of the shaders), please pass it along!

Edited by ceedj

Share this post


Link to post
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

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

×

Important Information

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