Best way to lock and unlock secret characters with script?

Perfect timing! Thank youuuuuuu

You know what I was trying to do? During "waiting" anim, check if player is pressing left or right, and check if flag for that char is on or off, then make the system press left or right again if the char hadn't been unlocked yet, thus moving to the next character in the roster.

That was the theory of course, in practice it failed SO BAD
 
Let me see if I understand this. At the end of Forrest 3, the Unlock entity is spawned. This entity causes the savestate "test" to be activated... and that savestate has Paladin as a playable character.

Something tells me this won't do for what I'm trying to do, which is to unlock characters at different times depending of which levels players complete
 
Well, it depends. If what you meant by unlocking at different times is permanent, then you need this write to text method
But if it's not permanent i.e relocked when going to main menu, then you'll have to use other method. I know the method and it's not using write to text at all
 
Thanks for the clarification. For my game I had originally planed that the unlocking wouldn't be permanent, as in chars become locked again if you start a new game. But I will give your method a try as any other has not worked for me.
 
I'll show how I 'lock' Paladin

This is the update.c

Code:
void main()
{// Update script for locking certain player
//    drawstring(220,130,3, getindexedvar(0));
//    drawstring(220,150,3, getindexedvar(1));

    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      int i = 0;
      int C = getglobalvar("Load");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "Paladin" && C != 39 ) {
            changemodelproperty(i,4,0);
            return;
        }
      }
    } else if(openborvariant("in_menuscreen")==1){
      setindexedvar(0, NULL());
    }
}

void oncreate()
{
    int C = fileskim("Rise");
    setglobalvar("Load", C);

    setindexedvar(1, 0);
}

void fileskim(char Line)
{
      void file = openfilestream("Test.txt", 1);
      void vLoad;

      if(file != -1){
        setfilestreamposition(file, 0);
        vLoad = getfilestreamargument(file, 0, "string");

        while(vLoad != Line && vLoad != "#End"){
          filestreamnextline(file);
          vLoad = getfilestreamargument(file, 0, "string");          
        }
        if( vLoad == Line ){
          filestreamnextline(file);
          vLoad = getfilestreamargument(file, 0, "int");
          return vLoad;

          closefilestream(file);
        } else if(vLoad == "#End"){
          closefilestream(file);
          return 0;
        }
      } else {
        return 0;
      }
}

This line does the check work

Code:
 if( model == "Paladin" && C != 39 ) {
    changemodelproperty(i,4,0);

There's iteration before this but to make it simple, if C whose value is gained from global variable by name of load has value other than 39, Paladin will be unselectable

In this update.c, that global variable takes value from reading file in oncreate below. oncreate is only run once BTW
If you remove the file reading stuffs, you can unlock Paladin by setting that global variable elsewhere either in level or in an entity. That's how to modify this script for your purpose ;)
 
It works perfectly... when there's only one unlockable character.

I have been tweaking the script to allow for more than one unlockable char, and no luck. Could it be that I need multiple update.c files?
 
For multiple characters you only need modified update.c not multiple update script
Here's an example:

Code:
...

    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      int i = 0;
      int C = getglobalvar("Lock1");
      int D = getglobalvar("Lock2");
      int E = getglobalvar("Lock3");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "Paladin" && C != 39 ) {
            changemodelproperty(i,4,0);
        } else if( model == "Rogue" && D != 47 ) {
            changemodelproperty(i,4,0);
        } else if( model == "Bard" && E != 18 ) {
            changemodelproperty(i,4,0);
        }
      }
...

Each locked character has corresponding global variable to unlock
 
Thank you my friend, I knew you wouldn't disappoint!

Edit: I see now that my mistake was that I didn't erase "return;"
 
Ok, major Bump here guys, but given I've never been good at script and it's taken me hours of figuring things out and much trial and error, I need to do this.

Now, I've made a few changes to Update and fileEd to correspond with the changes made to what Bloodbane posted last after I tested the script as is, and the characters names are only examples. I made these changes because while all 3 characters get unlocked during the boss death I specified, the first character is the only one STAYING unlocked after I close and open the game up:
Update.C
Code:
void main()
{// Update script for locking certain player
//    drawstring(220,130,3, getindexedvar(0));
//    drawstring(220,150,3, getindexedvar(1));

    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      int i = 0;
      int C = getglobalvar("Lock1");
      int D = getglobalvar("Lock2");
      int E = getglobalvar("Lock3");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "1" && C != 38 ) {
            changemodelproperty(i,4,0);
        } else if( model == "2" && D != 48 ) {
            changemodelproperty(i,4,0);
        } else if( model == "3" && E != 58 ) {
            changemodelproperty(i,4,0);
        }
      }
    } else if(openborvariant("in_menuscreen")==1){
      setindexedvar(0, NULL());
    }
}

void oncreate()
{
    int C = fileskim("Rise");
    setglobalvar("Lock1", C);
    int D = fileskim("Rise2");
    setglobalvar("Lock2", D);
    int E = fileskim("Rise3");
    setglobalvar("Lock3", E);

    setindexedvar(1, 0);
}

FileEd.c
Code:
void writedefault(void Path)
{// Writes file by name Path with default values
// Used when there's no file to start with
      void file = createfilestream();
      filestreamappend(file, 11, 1);
      filestreamappend(file, 22, 0);
      filestreamappend(file, 33, 0);
      filestreamappend(file, 44, 0);
      filestreamappend(file, "Lock1", 0);
      filestreamappend(file, "Lock2", 0);
      filestreamappend(file, "Lock3", 0);
      filestreamappend(file, 8, 0);
      filestreamappend(file, 55, 0);
      filestreamappend(file, "Rise", 0);
      filestreamappend(file, "Rise2", 0);
      filestreamappend(file, "Rise3", 0);
      filestreamappend(file, 77, 0);
      filestreamappend(file, "#End", 0);

      savefilestream(file, Path);
      closefilestream(file);
}
Code:
void Unlock(int Flag, void Path)
{ // Unlocks certain character based on flag and write the status on file named Path
// 1: Unlocks 1
    void file = openfilestream(Path, 1);
    char Code;
    int Value;
    void file = openfilestream(Path, 2);
    char Code;
    int Value;
    void file = openfilestream(Path, 3);
    char Code;
    int Value;

    if(Flag == 1){
      Code = "Rise";
      Value = 38;
    } else if(Flag == 2){
      Code = "Rise2";
      Value = 48;
    } else if(Flag == 3){
      Code = "Rise3";
      Value = 58;
    }

Boss death
Code:
anim	death
@script
    if(frame==1){
      setglobalvar("Lock1", 38);
    } else if(frame==2){
      setglobalvar("Lock2", 48);
    } else if(frame==3){
      setglobalvar("Lock3", 58);
    }
@end_script
	loop	0
	offset	90 192
	delay	1
	frame	data/chars/x/pain.gif
	@cmd	Unlock 1 "Test.txt"
	frame	data/chars/x/pain.gif
	@cmd	Unlock 2 "Test.txt"
	frame	data/chars/x/pain.gif
	@cmd	Unlock 3 "Test.txt"
	frame	data/chars/x/pain.gif

If anyone can tell me what I screwed up, I'd appreciated it.

x)
 
I've seen couple errors:
1. You edited Unlock function with wrong way
Expanding the code and value part is correct but not this one:
Code:
    void file = openfilestream(Path, 1);
    char Code;
    int Value;
    void file = openfilestream(Path, 2);
    char Code;
    int Value;
    void file = openfilestream(Path, 3);
    char Code;
    int Value;

you should just leave it like this:
Code:
    void file = openfilestream(Path, 1);
    char Code;
    int Value;

2. The writedefault function is wrongly edited, it's supposed tobe like this:

Code:
void writedefault(void Path)
{// Writes file by name Path with default values
// Used when there's no file to start with
      void file = createfilestream();
      filestreamappend(file, 11, 1);
      filestreamappend(file, 22, 0);
      filestreamappend(file, 33, 0);
      filestreamappend(file, 44, 0);
      filestreamappend(file, "Lock", 0);
      filestreamappend(file, 8, 0);
      filestreamappend(file, 55, 0);
      filestreamappend(file, "Rise", 0);
      filestreamappend(file, 127, 0);
      filestreamappend(file, "Rise2", 0);
      filestreamappend(file, 85, 0);
      filestreamappend(file, "Rise3", 0);
      filestreamappend(file, 77, 0);
      filestreamappend(file, "#End", 0);

      savefilestream(file, Path);
      closefilestream(file);
}

And although changing name of global variable isn't wrong, I need to tell you that global variable name in update.c is completely unrelated to texts written in saved file
That's why I simply use "Load"
 
I made the specified fixed Blood, but still getting the same results. I'll paste the entire script here and maybe you can find something aside from the changes I made that's preventing the other 2 characters from staying unlocked. After hours of trial and error again, the only thing I'm getting from this is that the first model has something being changed or saved after the script executes, that the other two models aren't.
Update
Code:
void main()
{// Update script for locking certain player
//    drawstring(220,130,3, getindexedvar(0));
//    drawstring(220,150,3, getindexedvar(1));

    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      int i = 0;
      int C = getglobalvar("Lock1");
      int D = getglobalvar("Lock2");
      int E = getglobalvar("Lock3");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "1" && C != 39 ) {
            changemodelproperty(i,4,0);
        } else if( model == "2" && D != 49 ) {
            changemodelproperty(i,4,0);
        } else if( model == "3" && E != 59 ) {
            changemodelproperty(i,4,0);
        }
      }
    } else if(openborvariant("in_menuscreen")==1){
      setindexedvar(0, NULL());
    }
}

void oncreate()
{
    int C = fileskim("Rise");
    setglobalvar("Lock1", C);
    int D = fileskim("Rise2");
    setglobalvar("Lock2", D);
    int E = fileskim("Rise3");
    setglobalvar("Lock3", E);

    setindexedvar(1, 0);
}

void fileskim(char Line)
{
      void file = openfilestream("Test.txt", 1);
      void vLoad;

      if(file != -1){
        setfilestreamposition(file, 0);
        vLoad = getfilestreamargument(file, 0, "string");

        while(vLoad != Line && vLoad != "#End"){
          filestreamnextline(file);
          vLoad = getfilestreamargument(file, 0, "string");          
        }
        if( vLoad == Line ){
          filestreamnextline(file);
          vLoad = getfilestreamargument(file, 0, "int");
          return vLoad;

          closefilestream(file);
        } else if(vLoad == "#End"){
          closefilestream(file);
          return 0;
        }
      } else {
        return 0;
      }
}

FileED
Code:
void fileread(void Path)
{// Read values from file defined with Path then store each value in each entity variable
      void self = getlocalvar("self");
      void file = openfilestream(Path, 1);
      void vLoad;
      int i = 0;

      if( file != -1 ){
        setfilestreamposition(file, 0);
        vLoad = getfilestreamargument(file, 0, "string");

        while(vLoad != "#End"){
          setentityvar(self, i, vLoad);
          i = i + 1;
          filestreamnextline(file);
          vLoad = getfilestreamargument(file, 0, "string");
        }

        if(vLoad == "#End"){
          setentityvar(self, i, vLoad);
          closefilestream(file);
        }
        return 1;
      } else {
        return -1;
      }
}

void fileedit(void Path, char Name, void Value)
{// Read values from entity variables, find the one matching with Name then change the value in next line
      void self = getlocalvar("self");
      int Check = fileread(Path);
      int i;
      void vLoad;

      if(Check==1){
        i = 0;
        vLoad = getentityvar(self, i);

        while(vLoad != Name && vLoad != "#End" && vLoad != NULL()){
          i = i + 1;
          vLoad = getentityvar(self, i);
        }

        if(vLoad == Name){
          i = i + 1;
          vLoad = getentityvar(self, i);
          setentityvar(self, i, Value);
        }
      }
}

void filewrite(void Path)
{// Read values from entity variables then write them to a file by name Path
// Must use fileread function first
      void self = getlocalvar("self");
      int i = 0;
      void vLoad = getentityvar(self, i);

      if(vLoad){
        void file = createfilestream();
        filestreamappend(file, vLoad, 1);

        while(vLoad != "#End" && vLoad != NULL()){
          i = i + 1;
          vLoad = getentityvar(self, i);
          filestreamappend(file, vLoad, 0);
        }

        savefilestream(file, Path);
        closefilestream(file);
      }
}

void writedefault(void Path)
{// Writes file by name Path with default values
// Used when there's no file to start with
      void file = createfilestream();
      filestreamappend(file, 11, 1);
      filestreamappend(file, 22, 0);
      filestreamappend(file, 33, 0);
      filestreamappend(file, 44, 0);
      filestreamappend(file, "Lock1", 0);
      filestreamappend(file, 8, 0);
      filestreamappend(file, 55, 0);
      filestreamappend(file, "Rise", 0);
      filestreamappend(file, 127, 0);
      filestreamappend(file, "Rise2", 0);
      filestreamappend(file, 85, 0);
      filestreamappend(file, "Rise3", 0);
      filestreamappend(file, 77, 0);
      filestreamappend(file, "#End", 0);

      savefilestream(file, Path);
      closefilestream(file);
}

int load_unlocked_model(char modelname)
{
    int models_cached = openborvariant("models_cached");
    int i = 0;

    for ( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if ( model == modelname ) {
	    if (getmodelproperty(i,4)!=1) {
	      loadmodel(modelname);
	      changemodelproperty(i,4,1);
	    }
            return;
        }
    }
}

void Unlock(int Flag, void Path)
{ // Unlocks certain character based on flag and write the status on file named Path
// 1: Unlocks 1
    void file = openfilestream(Path, 1);
    char Code;
    int Value;

    if(Flag == 1){
      Code = "Rise";
      Value = 39;
    } else if(Flag == 2){
      Code = "Rise2";
      Value = 49;
    } else if(Flag == 3){
      Code = "Rise3";
      Value = 59;
    }

    if(file == -1){
      writedefault(Path);
    }

    fileedit(Path, Code, Value);
    filewrite(Path);
}

And although changing name of global variable isn't wrong, I need to tell you that global variable name in update.c is completely unrelated to texts written in saved file
That's why I simply use "Load"
I see, but the thing is that I noticed you changed "Load" to "Lock1,2,3" in your last example, so I simply followed what you did there.

x)
 
There doesn't seem to be anything wrong with the script
You sure you have loaded 2 and 3? (the other 2 models)
 
It's not convoluted workarounds FYI. Also if you learn this script, the saved data can be used for other purposes aside of unlocking characters
And OTOH as I've posted in previous page, the method of locking a character isn't connected to saving data to text file at all, allowing modder to lock/unlock characters just by playing with global variable :)

can anyone make this work

It does work here
 
Yo guys, I finally got the script working.  ;D
I tried to come up with another way to do this, but when that didn't work, I went back to the drawing board and pasted the original coding from Bloodbane's loaded mod, when I saw a mistake on my part: that Blood used "Load" in Update.C, and "Lock" in "void writedefault" within FileEd.c, and not the same in both files like I had did.  :o
After testing the script multiple times, I can confirm that this script works.

Update.C
Code:
void main()
{// Update script for locking certain player
//    drawstring(220,130,3, getindexedvar(0));
//    drawstring(220,150,3, getindexedvar(1));

    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      int i = 0;
      int C = getglobalvar("Load");
      int D = getglobalvar("Load2");
      int E = getglobalvar("Load3");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "1" && C != 39 ) {
            changemodelproperty(i,4,0);
        } else if( model == "2" && D != 49 ) {
            changemodelproperty(i,4,0);
        } else if( model == "3" && E != 59 ) {
            changemodelproperty(i,4,0);
        }
      }
    } else if(openborvariant("in_menuscreen")==1){
      setindexedvar(0, NULL());
    }
}

void oncreate()
{
    int C = fileskim("Rise");
    setglobalvar("Load", C);
    int D = fileskim("Rise2");
    setglobalvar("Load2", D);
    int E = fileskim("Rise3");
    setglobalvar("Load3", E);

    setindexedvar(1, 0);
}

fileEd.C
Code:
void writedefault(void Path)
{// Writes file by name Path with default values
// Used when there's no file to start with
      void file = createfilestream();
      filestreamappend(file, 11, 1);
      filestreamappend(file, 22, 0);
      filestreamappend(file, 33, 0);
      filestreamappend(file, 44, 0);
      filestreamappend(file, "Lock", 0);
      filestreamappend(file, 8, 0);
      filestreamappend(file, 55, 0);
      filestreamappend(file, "Rise", 0);
      filestreamappend(file, 127, 0);
      filestreamappend(file, "Rise2", 0);
      filestreamappend(file, 85, 0);
      filestreamappend(file, "Rise3", 0);
      filestreamappend(file, 77, 0);
      filestreamappend(file, "#End", 0);

      savefilestream(file, Path);
      closefilestream(file);
}
Code:
void Unlock(int Flag, void Path)
{ // Unlocks certain character based on flag and write the status on file named Path
// 1: Unlocks 1
// 2: Unlocks 2
// 3: Unlocks 3
    void file = openfilestream(Path, 1);
    char Code;
    int Value;


    if(Flag == 1){
      Code = "Rise";
      Value = 39;
    } else if(Flag == 2){
      Code = "Rise2";
      Value = 49;
    } else if(Flag == 3){
      Code = "Rise3";
      Value = 59;
    }

    if(file == -1){
      writedefault(Path);
    }

    fileedit(Path, Code, Value);
    filewrite(Path);
}

Boss death: animationscript data/scripts/fileEd.c
Code:
anim	death
@script
    if(frame==1){
      setglobalvar("Load", 39);
    } else if(frame==2){
      setglobalvar("Load2", 49);
    } else if(frame==3){
      setglobalvar("Load3", 59);
    }
@end_script
	loop	0
	offset	90 192
	delay	1
	frame	data/chars/x/pain.gif
	@cmd	Unlock 1 "Test.txt"
	frame	data/chars/x/pain.gif
	@cmd	Unlock 2 "Test.txt"
	frame	data/chars/x/pain.gif
	@cmd	Unlock 3 "Test.txt"
	frame	data/charsx/pain.gif

Lasty, sorry for screwing up your script Bloodbane. This proves how slow I am at scripting.  8)

x)
 
nsw25 said:
why cant this be fixed and hardcoded to the openbor engine instead of convoluted workarounds.

skipselect and custom select menus should give this effect but the save games do not load.

can anyone make this work

Because as has been explained to you at least a dozen times - nothing is broken! Those features were not designed for what you want, nor can they be. A custom menu is just that, custom. We cannot hard code for everyone's taste and will not bloat up the engine trying. That is exactly why we have script in the first place.

The save feature was also never intended for custom use and has several disclaimers saying as much. It is only there for basic modules to have a base line saving capability. If you want more than that, you are again going beyond what is reasonable for hard coding. That too, is covered by script - specifically using persistent global variables and/or the built in text based database.

DC
 
DC, I don't want to fan the flames here, but NSW has a valid point about the unlock system.
This is something very common on beat 'em up games, and the load game can yes lead you to bugs and/or unwanted behaviours (there are several exemples across the forum).

We all area aware that the engine is coded for free, all the coders are busy and etc. But this is something someone could take a look someday. If not to OpenBOR, to at least ChronoCrash engine.

Just my two cents.
 
Just a little but useful update
You can update this character locking script to allow locked characters to be available in certain modes
Here's an example:
Code:
...
    if(openborvariant("in_selectscreen")==1){
      int models_cached = openborvariant("models_cached");
      void Set = openborvariant("current_set");
      int i = 0;
      int C = getglobalvar("Lock1");
      int D = getglobalvar("Lock2");
      int E = getglobalvar("Lock3");

      for( i = 0; i < models_cached; ++i ) {
        char model = getmodelproperty(i,2);

        if( model == "Paladin" && C != 39 ) {
            changemodelproperty(i,4,0);
        } else if( model == "Rogue" && D != 47 && Set != 2) {
            changemodelproperty(i,4,0);
        } else if( model == "Bard" && E != 18 && Set != 2) {
            changemodelproperty(i,4,0);
        }
      }
...

In this example, Rogue and Bard are immediately playable in level set 3 even though they are locked in other level sets
 
Back
Top Bottom