Trying to fix "Beat em up ultimate alliance"

devshark

New member
prelude, for context:
i'm not playing openbor on a PC, i'm doing it on a powkiddy rgb20s device. so i dont really know which version of openbor it's running.

the actual problem:
i'm trying to fix one game, however it's crashing - i need help in figuring out why it's crashing so i can fix that too.
for what it's worth, i can't really update openbor on the device, since i'm using openbor on the powkiddy rgb20s device. the game in question is beat em up ultimate alliance (ᐈ Beat Em Up Ultimate Alliance OpenBOR - 【 OpenBOR Games 2023 】)

i figured out it's crashing on the device for two reasons:
1) too much rain which slows it down to a halt on data/levels/br_st2c.txt - i can fix that easily.
2) something else just makes it crash on that same level... and i don't know what. turning on logging in the and i dont know where to locate the log

it seems to work fine on PC, using openbor 3.0, built Jan 26, 2017 - the level is beatable. however the rgb20s device is much less powerful so it could be due to discrepancy of the openbor used, or the raw computing power necessary to process whatever happens shortly after first screen.


one way to figure out whats going on is by commenting out everything that goes on in the level, then uncommenting things one by one until i find what breaks it, however that doesn't sound very efficient.
 
I haven't reviewed most of this thread in detail, but I can give a definitive answer to this: Yes. OpenBOR Script is weak typed, but it can and does use pointers. Most of the time you're messing with native engine objects, but it's easy enough to let a NULL or some other invalid pointer slip through if you're not careful.

One of the more common mistakes is trying to reference an entity pointer that the engine has removed from play.

DC
Great, now i just need to find the logs so i can narrow down this nullpointer hunt and patch it away.

Or alternatively... is there some not-entirely-empty project template i can download so i can quickly try and rebuild this game. Like, not entirely from scratch, but from some common "empty project" template if such a thing exists.
 
or at least ends up creating br_st2c.txt that doesn't crash.
@devshark I'm curious to understand what's causing the crash, I made some changes in this Beat em Up Alliance mod.

About the changes, I replaced the multiple individual "drop" spawns with just 4 panel entities that show many drops at once using multiple sprites, it can save some hardware resources.
However, I saw that this mod is using more than 500mb of memory even before starting the game. As a comparison, my latest SORX build that contains years of additions and updates is currently using around 170mb, and I can safely say that it's already high (due to many menu options and scripts) once I see many high quality games using around 100-150mb.

Anyway, here's the link for the updated pak file, tested with OpenBOR build 6391. Please, it would be good to know if the crash still happens or not.

1690417673582.png

1690417685886.png
 
@devshark I'm curious to understand what's causing the crash, I made some changes in this Beat em Up Alliance mod.

About the changes, I replaced the multiple individual "drop" spawns with just 4 panel entities that show many drops at once using multiple sprites, it can save some hardware resources.
However, I saw that this mod is using more than 500mb of memory even before starting the game. As a comparison, my latest SORX build that contains years of additions and updates is currently using around 170mb, and I can safely say that it's already high (due to many menu options and scripts) once I see many high quality games using around 100-150mb.

Anyway, here's the link for the updated pak file, tested with OpenBOR build 6391. Please, it would be good to know if the crash still happens or not.

View attachment 4576

View attachment 4577
tested it, the crash is still there. actually, i unpacked your PAK, changed the first level to be br_st2c.txt and repacked it, then tested.

however, good news - the game no longer grinds to a halt (or severly chops) while playing while the rain is present, so you definitely fixed the rain :) the FPS is pretty solid, just like in the levels before.

punching certain enemies on this stage is when the crash happens. as far as i could see, all levels use *pretty much* the same enemies - donovan, gneiss, jack, mic, billy ...
so i suppose this *pretty much* part needs closer inspection because one of the enemies might be broken and is causing the crash. i barely played for less than 2 minutes.

so congratulations on making the rain run decently (y) when i head out soon, i'll have some time in the bus to play your version starting at real level1. then I expect the same behaviour as before - first 5 levels working fine, and crashing when stage2c is reached, after punching someone. i'll let you know how that goes too.
 
yep, just as i suspected. first five levels work fine, then comes stage2c, it runs great (FPS is consistent) but the crash problem is still there, though i have uncovered a new fact: you don't need to punch enemies. at some point, after *some* enemy spawns, you just need to hang around for 5 seconds and it'll crash. we're talking like second screen of the stage.
I'll need to sift through the enemies and pinpoint which one is problematic, or whether the problem persists if i just change them from the yellow-jackets to some other ones.

but the crash most definitely lies in one of the enemies (or it's AI), of that I am very much assured of now.

however, when i tried reproing on the computer - i couldn't repro the problem. so that also leads me to suspect openbor versions (and no, i don't know which openbor is on the device).

presuming that openbor version on teh device will remain the same, this level needs to be fixed. I'll also try testing the levels after this stage2c to see if they exhibit similar problems.

for now, the only problems I am aware of are:
- special tanks the FPS, i suspect too many red shadows showing up. applying the "rain fix" or getting rid of excess red shadow should fix the problem.
- stage1 boss, his (her) special also tanks the FPS, i expect the problem will be resolved after the first point is resolved
- stage2c has a enemy-related unknown problem. it's like either the memory running out, or hitting a nullpointer somewhere, even when standing still or just walking between enemies.

but first thing's first, give enemies individual different names, and try changing them all to some other enemy and see what happens. I have deduced that lowering the number of enemies doesn't exibit the crashing behaviour, but as i uncomment more of them - the problem comes back. So the problem is in the enemies, it was always in the enemies. The rain problem was just a deterrant from figuring it out as it was slowing down the game.

at least, thats my current analysis of the problem... or needle-in-haystack hunt.
 
however, good news - the game no longer grinds to a halt (or severly chops) while playing while the rain is present, so you definitely fixed the rain :) the FPS is pretty solid, just like in the levels before.
It's good to know that the rain is better. A minor fix in my previos post, I meant 4 panels for rain but indeed are 5.

- special tanks the FPS, i suspect too many red shadows showing up. applying the "rain fix" or getting rid of excess red shadow should fix the problem.
You're right, the red shadows are problematic in this version. You can improve it by reducing the spawn amount and rate, you will need to enter in every character update script (ex: axel.c) and follow the example below (they are in the path "data/scripts/updateentity/").

As a suggestion you can do an advanced search for the function rageS() in your editor. There's duplicated function with the same name in the "main.c" file but it does a totally different thing, you can ignore this one.

Before
C:
void rageS()
{//Shadow copy frame for Rage
    void self     = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame    = getentityproperty(self, "animpos");
    void vSpawn1;
    void vSpawn2;
    
    if(vAniID == openborconstant("ANI_FREESPECIAL"))
    {
        vSpawn1 = spawn01("AxelS", -2, 0, -1);
        vSpawn2 = spawn01("AxelS", 2, 0, -1);
        changeentityproperty(vSpawn1, "parent", self);
        changeentityproperty(vSpawn2, "parent", self);
        updateframe(vSpawn1, Frame);
        updateframe(vSpawn2, Frame);
    }
}

After
C:
void rageS()
{//Shadow copy frame for Rage
    void self   = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame   = getentityproperty(self, "animpos");
    int rate    = 4; //YOU CAN FREELY ADJUST THE RATE IF IT'S NECESSARY
    void vSpawn;
    
    if(openborvariant("elapsed_time")%rate == 0)
    {
        if(vAniID == openborconstant("ANI_FREESPECIAL"))
        {
            vSpawn = spawn01("AxelS", 0, 0, -1);
            changeentityproperty(vSpawn, "parent", self);
            updateframe(vSpawn, Frame);
        }
    }
}

- stage2c has a enemy-related unknown problem. it's like either the memory running out, or hitting a nullpointer somewhere, even when standing still or just walking between enemies.
As a suggestion you could remove some entities that were not present in the original SOR2X and see if the crash happens, maybe the author of this mod didn't adapt some scripts to work in the same way as originally developed. This way you can gradually isolate where the problem is until you find the problematic character.

They are:
- Rio
- gNEISS_Wait0, Gneiss
- Mic, miC
- Billy0, Billy1
- Rubby, Rubby1
- Elmer0, Elmer1
 
As a suggestion you could remove some entities that were not present in the original SOR2X and see if the crash happens, maybe the author of this mod didn't adapt some scripts to work in the same way as originally developed. This way you can gradually isolate where the problem is until you find the problematic character.

They are:
- Rio
- gNEISS_Wait0, Gneiss
- Mic, miC
- Billy0, Billy1
- Rubby, Rubby1
- Elmer0, Elmer1
initially i started commenting them out from the top (because they're listed in order where they spawn)
at some point (when there's like only 4-5 enemies left) on the "last screen" there were no crashes. then i started uncommenting more and more of them and the crash returned.

So i'm definatelly sure it's one of the enemies, and I'm definitelly sure it's got nothing with hurting him or killing him, because just standing or walking around him makes the game crash too.

However, today I have been dealing with something else so no time to mess with openbor :D I need to finish tasks before switching them or nothing will be done and i'll have dozen of started things on my plate... :D

But you're right. Instead of commenting them out one-by-one, i should remove them by their "type", which are Rio, Gness_Wait0, Gneiss, Mic, Billy0, Billy1, Rubby, Rubby1, Elmer0, Elmer1

I have also noticed that these names are case-insensitive. so gNEISS_Wait0 is the same as Gneiss_wait0 because that's how they're referenced in some later stage and the enemy definition as well.
 
It's good to know that the rain is better. A minor fix in my previos post, I meant 4 panels for rain but indeed are 5.


You're right, the red shadows are problematic in this version. You can improve it by reducing the spawn amount and rate, you will need to enter in every character update script (ex: axel.c) and follow the example below (they are in the path "data/scripts/updateentity/").

As a suggestion you can do an advanced search for the function rageS() in your editor. There's duplicated function with the same name in the "main.c" file but it does a totally different thing, you can ignore this one.

Before
C:
void rageS()
{//Shadow copy frame for Rage
    void self     = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame    = getentityproperty(self, "animpos");
    void vSpawn1;
    void vSpawn2;
   
    if(vAniID == openborconstant("ANI_FREESPECIAL"))
    {
        vSpawn1 = spawn01("AxelS", -2, 0, -1);
        vSpawn2 = spawn01("AxelS", 2, 0, -1);
        changeentityproperty(vSpawn1, "parent", self);
        changeentityproperty(vSpawn2, "parent", self);
        updateframe(vSpawn1, Frame);
        updateframe(vSpawn2, Frame);
    }
}

After
C:
void rageS()
{//Shadow copy frame for Rage
    void self   = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame   = getentityproperty(self, "animpos");
    int rate    = 4; //YOU CAN FREELY ADJUST THE RATE IF IT'S NECESSARY
    void vSpawn;
   
    if(openborvariant("elapsed_time")%rate == 0)
    {
        if(vAniID == openborconstant("ANI_FREESPECIAL"))
        {
            vSpawn = spawn01("AxelS", 0, 0, -1);
            changeentityproperty(vSpawn, "parent", self);
            updateframe(vSpawn, Frame);
        }
    }
}


As a suggestion you could remove some entities that were not present in the original SOR2X and see if the crash happens, maybe the author of this mod didn't adapt some scripts to work in the same way as originally developed. This way you can gradually isolate where the problem is until you find the problematic character.

They are:
- Rio
- gNEISS_Wait0, Gneiss
- Mic, miC
- Billy0, Billy1
- Rubby, Rubby1
- Elmer0, Elmer1
Since I'm finding time to deal with this, I've decided to streamline all of the `data/scripts/updateentity/<whatever>.c` files to look something like this:

Code:
#import "data/scripts/updateentity/main.c"
#define ANIMATION_NAME "captain_PipeS" //and i just keep changing this between the different files

void main()
{
    rageS();
}

void rageS()
{//Shadow copy frame for Rage
    void self   = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame   = getentityproperty(self, "animpos");
    int rate    = 4; //YOU CAN FREELY ADJUST THE RATE IF IT'S NECESSARY
    void vSpawn;
    
    if(openborvariant("elapsed_time")%rate == 0)
    {
        if(vAniID == openborconstant("ANI_FREESPECIAL"))
        {
            vSpawn = spawn01(ANIMATION_NAME, 0, 0, -1);
            changeentityproperty(vSpawn, "parent", self);
            updateframe(vSpawn, Frame);
        }
    }
}
 
@Kratus alright, getting rid of the excessive / multiple `spawn`, `changeentityproperty` and `updateframe` calls fixed the specials. thanks for the heads up.
i'm starting to dig into the enemies, and ... i'm finding multiple copies of same-files :/ like `donovan0.txt` is in data/chars/tiger, /chars/donovan, /chars/gneiss

how does this affect... everything? the last one to get loaded is the one that gets used or what?
obviously, i need to clean this up and keep individuals to just their own folders

EDIT:
an interesting question arises.

given the two following scripts:
/data/scripts/onspawn/donovan.c
Code:
void main()
{
    void self         = getlocalvar("self");
    void vRName     = getentityproperty(self,"defaultname"); // Get caller's real name.
    void vAlias        = getentityproperty(self,"name"); // Get caller's alias.
    int  iMHealth     = getentityproperty(self,"maxhealth"); // Get caller's maxhealth.
    int  iHealth     = getentityproperty(self,"health"); // Get caller's health.
    int  iSpeed     = getentityproperty(self,"speed"); // Get caller's speed.
    int  iAggre     = getentityproperty(self,"aggression"); // Get caller's aggression.
    int  iScore     = getentityproperty(self,"score"); // Get caller's score.
    int  iMap         = getentityproperty(self,"map"); // Get caller's map.
    int  pCount        = openborvariant("count_players"); // Count players alive.
    int  set        = openborvariant("current_set");
    
    if(set == 2 || set == 3)
    {
        changeentityproperty(self, "nodieblink", 3);
    }
    
    if(vRName == "Donovan0"){
        vAlias        = "Donovan";
        iMHealth    = 75;
        iHealth     = iMHealth;
        iSpeed         = 0.8;
        iAggre         = -400;
        iScore         = 200*pCount;
        iMap        = 0;
    }else if(vRName == "Donovan_Wait0"){
        vAlias        = "Donovan";
        iMHealth    = 75;
        iHealth     = iMHealth;
        iSpeed         = 0.8;
        iAggre         = -400;
        iScore         = 200*pCount;
        iMap        = 0;
    }else if(vRName == "Donovan1"){
        vAlias        = "Reid";
        iMHealth    = 100;
        iHealth     = iMHealth;
        iSpeed         = 1;
        iAggre         = -200;
        iScore         = 400*pCount;
        iMap        = 1;
    }else if(vRName == "Donovan_Manhole"){
        vAlias        = "Reid";
        iMHealth    = 100;
        iHealth     = iMHealth;
        iSpeed         = 1;
        iAggre         = -200;
        iScore         = 400*pCount;
        iMap        = 1;
    }else if(vRName == "Donovan2"){
        vAlias        = "Martin";
        iMHealth    = 150;
        iHealth     = iMHealth;
        iSpeed         = 1.2;
        iAggre         = 1;
        iScore         = 600*pCount;
        iMap        = 2;
    }else if(vRName == "Donovan_Wait2"){
        vAlias        = "Martin";
        iMHealth    = 150;
        iHealth     = iMHealth;
        iSpeed         = 1.2;
        iAggre         = 1;
        iScore         = 600*pCount;
        iMap        = 2;
    }else if(vRName == "Donovan3"){
        vAlias        = "Gudden";
        iMHealth    = 200;
        iHealth     = iMHealth;
        iSpeed         = 1.4;
        iAggre         = 200;
        iScore         = 800*pCount;
        iMap        = 3;
    }else if(vRName == "Donovan4"){
        vAlias        = "Altet";
        iMHealth    = 250;
        iHealth     = iMHealth;
        iSpeed         = 1.6;
        iAggre         = 400;
        iScore         = 1000*pCount;
        iMap        = 4;
    }else if(vRName == "Donovan_Wait4"){
        vAlias        = "Altet";
        iMHealth    = 250;
        iHealth     = iMHealth;
        iSpeed         = 1.6;
        iAggre         = 400;
        iScore         = 1000*pCount;
        iMap        = 4;   
    }
    
    changeentityproperty(self, "name", vAlias); //Set alias.
    changeentityproperty(self, "maxhealth", iMHealth); //Set maxhealth.
    changeentityproperty(self, "health", iHealth); //Set health.
    changeentityproperty(self, "speed", iSpeed); //Set speed.
    changeentityproperty(self, "aggression", iAggre); //Set aggression.
    changeentityproperty(self, "score", iScore); //Set score.
    changeentityproperty(self, "map", iMap); //Set map.
}

and this snippet from level script:
Code:
spawn        Donovan_Wait4
Alias        enemy1
flip        0
coords        500 270 0
at            301

spawn        Billy_wait0
Alias        enemy2
coords        500 240 0
at            301

#spawn        gNEISS_Wait0
#Alias        enemy2
#coords        500 240 0
#at            301


group        4 4
at            400

wait
at            400

spawn        Jack0
Alias        enemy3
flip        1
coords        -5 270 0
at            400


spawn        Mic
Alias        enemy4
Map            2
flip        1
coords        600 270 0
at            400


spawn        Billy1
#Alias        Billy
Alias        enemy5
map            1
flip        1
coords        600 270 0
at            400

Will this Donovan_wait4 enemy be called enemy1 or Altet? since i'm seeing Altet when ingame.
This whole mess of level script trying to do something only to get overridden by some other script looks like cabagge mess a little bit, what's the best way to organize this thing?

Apart from that, the good news seem to be - after replacing this Gneiss_wait0 with Billy_wait0, the level is completable.
I do still run into a crash here and there, but i have no clue where it stems from :/ something's triggering it, but if i just try to not kick their asses as fast as possible the crash doesn't happen. Will need to test more.
 
Last edited:
@Kratus alright, getting rid of the excessive / multiple `spawn`, `changeentityproperty` and `updateframe` calls fixed the specials. thanks for the heads up.
Great, glad it works :)

i'm starting to dig into the enemies, and ... i'm finding multiple copies of same-files :/ like `donovan0.txt` is in data/chars/tiger, /chars/donovan, /chars/gneiss
In the original SOR2X the donovan0.txt originally belongs to the Donovan's folder only.
Maybe the author of this modification added new characters using the donovan0.txt as base but forgot to change the file name, once entities are spawned by the names defined at the character header no matter what name is used by the files.
I think just renaming these files and updating their paths at the models.txt can fix the problem.
 
Hm, it looks like while i fixed the crash and the big problems, but i might have messed up Hannah's outfit somehow. Still need to verify between branches. Where would I look into fixing this?

I don't see how this could have possibly break it.
old hannah.c:
Code:
#import "data/scripts/updateentity/main.c"

void main()
{
    rageS();
}

void rageS()
{//Shadow copy frame for Rage
    void self     = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame    = getentityproperty(self, "animpos");
    void vSpawn1;
    void vSpawn2;
    
    if(vAniID == openborconstant("ANI_FREESPECIAL"))
    {
        vSpawn1 = spawn01("HannahS", -2, 0, -1);
        vSpawn2 = spawn01("HannahS", 2, 0, -1);
        changeentityproperty(vSpawn1, "parent", self);
        changeentityproperty(vSpawn2, "parent", self);
        updateframe(vSpawn1, Frame);
        updateframe(vSpawn2, Frame);
    }
}

new hannah.c:
Code:
#import "data/scripts/updateentity/main.c"
#define ANIMATION_NAME "HannahS"

void main()
{
    rageS();
}

void rageS()
{//Shadow copy frame for Rage
    void self   = getlocalvar("self");
    void vAniID = getentityproperty(self, "animationID");
    int Frame   = getentityproperty(self, "animpos");
    int rate    = 4; //YOU CAN FREELY ADJUST THE RATE IF IT'S NECESSARY
    void vSpawn;
    
    if(openborvariant("elapsed_time")%rate == 0)
    {
        if(vAniID == openborconstant("ANI_FREESPECIAL"))
        {
            vSpawn = spawn01(ANIMATION_NAME, 0, 0, -1);
            changeentityproperty(vSpawn, "parent", self);
            updateframe(vSpawn, Frame);
        }
    }
}

I'm asking since while testing the crash fix last night, i noticed her whole outfit was white/pale rather than red. After re-running the previously deployed version, it was red shirt with blue jeans.
The only things changed on this branch are data/levels.txt and data/levels/br_st2c.txt
 
vSpawn = spawn01(ANIMATION_NAME, 0, 0, -1);
Maybe the problem could be in this line, here we call the character's shadow entity name and not the animation's name.
For example, for Axel the shadow entity is AxelS, Blaze is BlazeS and so on same as the HannahS.
 
Maybe the problem could be in this line, here we call the character's shadow entity name and not the animation's name.
For example, for Axel the shadow entity is AxelS, Blaze is BlazeS and so on same as the HannahS.

That doesn't make much sense mate, to avoid potentially less polite words. While i get where you're coming from with this, please look at the following two snippets and tell me if it holds water.

new hannah.c:
Code:
#define ANIMATION_NAME="HannahS"

vSpawn = spawn01(ANIMATION_NAME, 0, 0, -1);

old hannah.c:
Code:
vSpawn = spawn01("HannahS", 0, 0, -1);

Of course, the ANIMATION_NAME define has a different value for every character.c file that matches their old name. Fix special code and streamline all files with a #define (#3) · RkShaRkz/openbor-beat-em-up-ultimate-alliance@5697da3
On top of that, yes, calling it ANIMATION_NAME is a poor choice as well, but that's the best i had at the time.

In any case, i reran the app again today/last night... hannah was red. While I don't quite get how i saw what i saw, i'll just repackage it again, deploy as new version, then pay attention whether the crash is fixed and whether everyone still looks how they're supposed to look like :D

and then look into the selection screen, i see some portraits seem to be "locked" ? i've read a bit about selection screen on the wiki Select Screen – OpenBOR Wiki however i don't get where the characters that are initially selectable are declared. I'm wondering whether the characters are just not hooked up to their portraits or they're completely not done. If they're done, i want to unlock them and have them selectable from the start. If they're not done - great. maybe I try implementing characters from scratch and putting them in this game :D
 
That doesn't make much sense mate, to avoid potentially less polite words. While i get where you're coming from with this, please look at the following two snippets and tell me if it holds water.

new hannah.c:
Code:
#define ANIMATION_NAME="HannahS"

vSpawn = spawn01(ANIMATION_NAME, 0, 0, -1);
old hannah.c:
Code:
vSpawn = spawn01("HannahS", 0, 0, -1);
I didn't see the #define line while writing my previous post, I thought you were just using the animation's name due to the constant name. The only problem I saw is the = operator, which will cause the engine to crash.

In any case, i reran the app again today/last night... hannah was red. While I don't quite get how i saw what i saw, i'll just repackage it again, deploy as new version, then pay attention whether the crash is fixed and whether everyone still looks how they're supposed to look like :D
Sorry, I don't know too much about the new characters the other author added in the SOR2X that may cause those crashes, I suggest taking a look at the log file.
About the red color, did you mean the "red shadows" used in rage moves or the main character itself is fully red? I don't remember exactly how I coded but maybe something may be wrong with the remap or drawmethod function.

and then look into the selection screen, i see some portraits seem to be "locked" ? i've read a bit about selection screen on the wiki Select Screen – OpenBOR Wiki however i don't get where the characters that are initially selectable are declared
The SOR2X uses a custom scripted select screen, some native engine methods may not work as intended. In case you are mentioning the "?" boxes, most of them do not have a character developed and they belong to "future" characters planned to be added.
 
Can confirm the last release doesn't have the weird coloring/pallete problem, and the crash is gone :) Now how do i go about fixing the number of available characters on the selection screen?
About the red color, did you mean the "red shadows" used in rage moves or the main character itself is fully red? I don't remember exactly how I coded but maybe something may be wrong with the remap or drawmethod function.
No, I noticed the weird problem of Hannah not being red shirt with blue pants but rather something beige and kinda colorless. I thought I broke something but looks like I'm safe :D Thats what i meant by "hannah was red".
 
Can confirm the last release doesn't have the weird coloring/pallete problem, and the crash is gone :) Now how do i go about fixing the number of available characters on the selection screen?

No, I noticed the weird problem of Hannah not being red shirt with blue pants but rather something beige and kinda colorless. I thought I broke something but looks like I'm safe :D Thats what i meant by "hannah was red".
Glad to know that the issues were solved :)
About the select screen, I don't know exactly what's changed in this mod but I suggest you search for all the instances that contain openborvariant("in_selectscreen") inside your scripts folder using your text editor. In OpenBOR you don't need to increase the limit for playable characters, just adding them in the models.txt is enough to make them available, but when using scripted select screen you need some extra steps.
 
Back
Top Bottom