[SCRIPT] Identifying a stage

O Ilusionista

Captain 100K
Watching the discussion on another topic, I decided to share a solution I made to help me to indentify which stage the player is right now.

There are two other methods to achive something like this, but both has issues:
  • Getting "current_branch" > only gets the current branch, not the current stage. If you have a branch with 4 stages, all the stages will return the same value, since they are part of the same branch
  • Getting "stagenumber"  > as the manual explains, it can get inconsistent to real progress, because it only count the number of NEXTs used.

My solution uses a globalvar and check to achive this
It uses a levelscript (or you can paste as a spawnscript of a empty entity)

Code:
@script
void main()
{
     void stageName;
     if (!stageName){
     setglobalvar("stageName","My Stage"); // Put your stage name here. It's CASE SENSITIVE.
     }
}
@end_script

So, when I want to check for a stage name, i just paste this:
Code:
void stageName = getglobalvar("stageName");
if (stageName == "My Stage"){
*INSERT YOUR LOGIC HERE*
}

And just to avoid issues, I free the globalvar in endlevel.c
Code:
void main()
{
   setglobalvar("stageName",  NULL());
}

And I duplicate it into "ondestroy" at updated.c
Code:
void ondestroy()
{ 
   if(getglobalvar("stageName"))
    {
        //free(getglobalvar("stageName"));
        setglobalvar("stageName",  NULL());
    }
}

I tested and it works (I use it on my Avengers mod).
 
For the purpose of ...identifying a stage to check it later :)

Joking aside, it can be very useful. On my game, for example, I use an explosion effect which spawns little rocks. When those explosion happens on the air, I don't want those rocks, and when I am on a underwater stage, I want a different animation.

This is where I use this script, for example. Why creating another entity, when I can simply change its animation?
 
Isnt it just easier to have globalvar set in actual stage when you spawn first entity ?
Code:
spawn	crapper
@script void main() {
   setglobalvar("simplescriptinsteadofmultipletxtfilestodothesamething",NULL());
} @end_script
	coords  123  456 
	at  0
then just clear this variable when you acquire it
 
Your method is simpler to just set the global var. It's just a different way to do the same thing.
But the "simplescriptinsteadofmultipletxtfilestodothesamething" isn't quite that because you need to :

-get the value
-clean the value, in both places.

Plus, you are just setting the globarvariable without checking it first.
 
O Ilusionista said:
My solution uses a globalvar and check to achive this
It uses a levelscript

levelscript? As in levelscript.c and put it in the data/ folder /scripts?

O Ilusionista said:
So, when I want to check for a stage name, i just paste this:
Code:
void stageName = getglobalvar("stageName");
if (stageName == "My Stage"){
*INSERT YOUR LOGIC HERE*
}

where though? The Player spawn animation? The actual level?
could you please elaborate?

 
I've put this on a stage I recently created called "st2c"

Code:
spawn	ClimbSpot3
@script
void main()
{
     void stageName;
     if (!stageName){
     setglobalvar("stageName","st2c"); // Put your stage name here. It's CASE SENSITIVE.
     }
}
@end_script
health 234
flip	1
coords	145 759
at	0

And I put this piece of code on the player spawn animation so that he does not hurt NPC if he is playing on stage "st2c"  But it's not working and I'm still able to hit the NPC in that stage.

Code:
anim spawn
    @script
    void stageName = getglobalvar("stageName"); // Get stage name (global variable)
    void self = getlocalvar("self"); //Get calling entity.
    if (stageName == "st2c"){
    changeentityproperty(self, "candamage", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Change the can damage setting, excluding NPC
    }
    else {
    changeentityproperty(self, "candamage", "TYPE_NPC", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Revert to normal
    }

    void P1 = getplayerproperty(0, "entity");
    void P2 = getplayerproperty(1, "entity");
    int eTime = openborvariant("elapsed_time");

    if(P1){
      changeentityproperty(P1, "invincible", 1);
      changeentityproperty(P1, "invinctime", eTime + 340);
    }
    if(P2){
      changeentityproperty(P2, "invincible", 1);
      changeentityproperty(P2, "invinctime", eTime + 340);
    }


    @end_script
     loop 0
     delay 1
     offset 77 170
     frame data/chars/billy/idle.png
     frame data/chars/billy/idle.png
     @cmd    spawnbind2 "parrow" "parrow2" 0 1 0 0
     frame data/chars/billy/idle.png
     frame data/chars/billy/idle.png
     @cmd    stealth 0 2
     frame data/chars/billy/idle.png
     frame data/chars/billy/idle.png
 
only gets the current branch, not the current stage. If you have a branch with 4 stages, all the stages will return the same value, since they are part of the same branch

O Ilusionista
Yeah buddy, this problem can really happen. However, you can avoid this issue by adding a branch name to every level in the levels.txt file, like this:

Code:
#STAGE 1
branch			sor2_st1a
z				150 466
file			data/levels/sor2/st1a.txt 	#STREETS A

branch			sor2_st1b
z				220 270
file			data/levels/sor2/st1b.txt	#BAR

branch			sor2_st1c
z				220 270
file			data/levels/sor2/st1c.txt	#BAR EXIT BARBON
next

#STAGE 2
branch			sor2_st2a
z				216 270
file			data/levels/sor2/st2a.txt	#BRIDGE A

branch			sor2_st2b
z				220 270
file			data/levels/sor2/st2b.txt	#TRUCK

branch			sor2_st2c
z				216 270
file			data/levels/sor2/st2c.txt	#BRIDGE B JET
next
 
Kratus

How could Implement your branch idea into the code I'm trying to work out( as seen above your post),  where I'm trying to figure out how to make the player not hit NPC in a particular stage? Otherwise he is able to do so.
 
Just a small question because I have a similar structure in Street of Nightmare: once I kill all the enemies, the level ends after some seconds, teleporting to the next level of the list, even if I have a hidden object like this:
Code:
spawn		Bin
flip		1
coords		999 999 0
at		0

Should I change it to an enemy type with a
Code:
nomove 1
attribute or is there any way to stop being teleported to the next level of the list?
 
PS VITA
First you need to define a branch name to the desired level in the levels.txt file, like I posted before, and after that you can use the function "current_branch" like O Ilusionista said to detect the branch you are.

Code:
void branch = openborvariant("current_branch");

Also the Ilu's method is very good too and will work fine to rename and get the level name. You can choose the one that fits better to your project.

Once you can detect the level correctly, all you need to do is to changing the "candamage" property in the desired entities, like this:

Code:
if(branch == "desired_branch"){
       changeentityproperty(entity, "candamage", "type_player", "type_enemy");
}

Don't forget to rollback the "candamage" property to the default values after this specific level is finished. You can add this script in many events, choose the one that fits better for your game.

kimono
To avoid the current level finishes after beating all enemies, you need to place a hidden enemy in a place far from the player, like this "Bin" entity. And yes, need to be a "type enemy" entity, unless you change the level type to 1 inside the current level file and then you can use a "type obstacle" entity.

~{type} is a binary value which determines if the stage is a normal stage (0) or a bonus stage (1).
~Bonus stages end when all obstacles are destroyed, when there are no more items or when time runs out.
 
Kratus said:
PS VITA
First you need to define a branch name to the desired level in the levels.txt file, like I posted before, and after that you can use the function "current_branch" like O Ilusionista said to detect the branch you are.

Code:
void branch = openborvariant("current_branch");

Kratus
Yeah, that's the part that I was asking about - where does that piece of code go?

for example : in the animation spawn of the player?

Code:
anim spawn
    @script
    void branch = openborvariant("st2c");
    void self = getlocalvar("self"); //Get calling entity.
    if(branch == "st2c"){
    changeentityproperty(self, "candamage", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Change the can damage setting, excluding NPC
    }
    else {
    changeentityproperty(self, "candamage", "TYPE_NPC", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Revert to normal
    }
@end_script



EDIT: I just keep getting this error ... "openborvariant: System variable name not found: 'st2c'"
I need a little more help.
 
Bloodbane said:
It should be:
Code:
void branch = openborvariant"current_branch");

Kratus and Bloodbane
hey guys it's working!

except now I need to learn how to reset the variable  like 0 illusionista mentioned in endlevel.c but using the brach method.


"And just to avoid issues, I free the globalvar in endlevel.c
Code:"
Code:
void main()
{
   setglobalvar("stageName",  NULL());
}

So this code above how would that look like in the branch format?

 
PS VITA
Nice, it's good to know that it worked  :)

Bloodbane is right, the correct way is:
void branch = openborvariant("current_branch");

The "current_branch" is a variant that will detect the current branch.

About this:
except now I need to learn how to reset the variable  like 0 illusionista mentioned in endlevel.c but using the branch method
If you use the branch method directly in the levels.txt file, don't need to reset variables. But if you choose to use Ilu's scripted method, don't forget to reset the "stageName" variable at the endlevel.c event exactly as he said (will run when every level ends).
 
If you use the branch method directly in the levels.txt file, don't need to reset variables. But if you choose to use Ilu's scripted method, don't forget to reset the "stageName" variable at the endlevel.c event exactly as he said (will run when every level ends).

you are absolutley correct. One last question using your method - how would I add two stages to the current code instead of just one stage?

Here's the current code - but that I want to add stage called "st2d"

Code:
@script
    void branch = openborvariant("current_branch");
    void self = getlocalvar("self"); //Get calling entity.
   
 if(branch == "st2c")

{
    changeentityproperty(self, "candamage", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Change the can damage setting, excluding NPC
    }
    else {
    changeentityproperty(self, "candamage", "TYPE_NPC", "TYPE_ENEMY", "TYPE_PLAYER", "TYPE_OBSTACLE"); // Revert to normal
    }
@end_script

would this piece of code work?

Code:
if((branch == "st2c") || (branch == "std"))

Edit ah, and one more question if anyone knows - why after I pick up a weapon player one resets as if the branch == st2c does not matter anymore? anything I can do to prevent this?
 
PS VITA

Yes, you can apply it in multiple levels. The correct way is:
Code:
if(branch == "st2c" || branch == "st2d")
 
Kratus said:
PS VITA

Yes, you can apply it in multiple levels. The correct way is:
Code:
if(branch == "st2c" || branch == "st2d")

Awesome - I almost had it !

ah, and one more question if anyone knows - why after I pick up a weapon player one resets as if the branch == st2c does not matter anymore? anything I can do to prevent this?

I think what is happening is that whenever I pick a weapon that entity that has the weapon has a different set of variables
and in my case the branch == st2c sorta reverts back to normal for the player after he picks up the weapon.

I know it's a vague question, but any sorta hint or clue could really go along way.

EDIT: Do I need to add the code to the Player holding a weapon spawn animation as well?
 
PS VITA said:
Kratus said:
PS VITA

Yes, you can apply it in multiple levels. The correct way is:
Code:
if(branch == "st2c" || branch == "st2d")

Awesome - I almost had it !

ah, and one more question if anyone knows - why after I pick up a weapon player one resets as if the branch == st2c does not matter anymore? anything I can do to prevent this?

PS VITA
In this case you will need a script in the "onmodelcopy" event. Using this, you can copy all "candamage" properties when the model is changed to a weapon model.

STEP 1
First you need to call this event in the character header. For safe, I'm calling it in all my games in both original model and weapon model, like this:

Code:
onmodelcopyscript	data/scripts/your_file_name.c

STEP 2
Now you need to create the script inside your file:

Code:
void main()
{//Maintain default header config for alternative models (WEAPON MODELS)

	void self	= getlocalvar("self");
	void old	= getlocalvar("old");
	void vAlias	= getentityproperty(old,"name"); //GET OLD ALIAS.
	int  iMHealth	= getentityproperty(old,"maxhealth"); //GET OLD MAX HEALTH.
	int  iHealth	= getentityproperty(old,"health"); //GET OLD HEALTH.
	int  iMaxMP	= getentityproperty(old,"maxmp"); //GET OLD MAX MP.
	int  iMp	= getentityproperty(old,"mp"); //GET OLD MP.
	int  hostile	= getentityproperty(old,"hostile"); //GET OLD HOSTILE.
	int  candamage	= getentityproperty(old,"candamage"); //GET OLD CANDAMAGE.
	
	changeentityproperty(self, "name", vAlias); //SET ALIAS.
	changeentityproperty(self, "maxhealth", iMHealth); //SET MAX HEALTH.
	changeentityproperty(self, "health", iHealth); //SET HEALTH.
	changeentityproperty(self, "maxmp", iMaxMP); //SET MAX MP.
	changeentityproperty(self, "mp", iMp); //SET MP.
	changeentityproperty(self, "hostile", hostile); //SET HOSTILE'S FLAG.
	changeentityproperty(self, "candamage", candamage); //SET CANDAMAGE'S FLAG.
}

This is an example only, some games can have less or more properties depending on the developer's way.
 
Back
Top Bottom