Obstacle count entity

dantedevil

Well-known member
I try to create an obstacle count for the bonus stages, but not work.
Then when you destroy all the obstacles, the entity change the animation and spawn the PERFECT text. And finally end the stage.

Here my try:
Code:
#BONUS - OBSTACLE COUNT
anim follow1
@script
    void self = getlocalvar("self");
    int Obstacle = openborvariant("count_obstacles");

    if(Obstacle == 0){
      changeentityproperty(self, "velocity", 0, 0, 0); 
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
@end_script
	loop	1
	delay	1
        offset 1 1
        frame data/chars/misc/empty.png
        frame data/chars/misc/empty.png


#BONUS - ALL OBSTACLES DESTROY
anim follow2
	loop	0
	delay	1
        offset 1 1
        @cmd    spawnAniEdge "textlist" 0 18 0 "ANI_FOLLOW3" 0
        frame data/chars/misc/empty.png
	delay	20
        frame data/chars/misc/empty.png
	delay	1
	@cmd	finishlevel 
        frame data/chars/misc/empty.png

I can't use the script to change the type of the obstacles to enemies, to avoid all the script check grab of the hero's.
I don't want make a can't grab exception for all obstacles in the bonus stages.
I think the obstale count entity is the best solution.
 
Solution
@O Ilusionista fixed xD thanks for the assist brother
ill post the whole animation here in case anyone else might need this.. remember to put an endlevel behind the door and also i used a platform to block its path.
that delay -1 is key tho.. if you dont put it there it will revert to idle animation that has the platform blocking the way.

fixed code same as below
Code:
name    door
health    1
type    obstacle
setlayer -9


anim idle
    loop 1
    delay 500
@script
    void self = getlocalvar("self");
    int C = openborvariant("count_enemies"); // Get count of enemies.
    int follow_played = getlocalvar("follow_played"); // Flag to track if follow animation was played.

    // Initialize follow_played flag if not set...
try adding this line to check if the engine is picking up any obstacles.

Code:
settextobj(0, 110,  180, 3, 9999999999, openborvariant("count_obstacles"));


also instead of making a entity to handle this script a level update file might have been a better option and you could reuse it for other bonus stages.
 
msmalik681 said:
try adding this line to check if the engine is picking up any obstacles.

Code:
settextobj(0, 110,  180, 3, 9999999999, openborvariant("count_obstacles"));


also instead of making a entity to handle this script a level update file might have been a better option and you could reuse it for other bonus stages.

Could you explain to me how that line works and where should I add it?

If you have a better idea, do not hesitate to show it to me.
You help me a lot with your new system of fatalities.
I trust in your good judgment.
 
It will display what value that openborvariant("count_obstacles") holds just add it at the start of your script like a check to see if it finds and counts the obstacles.


I often use this method to make sure my scripts hold the expected values and debug any crashes.


It might crash asking for a string value so try this.


Code:
settextobj(0, 110,  180, 3, 9999999999, "_"+openborvariant("count_obstacles"));
 
msmalik681 said:
also instead of making a entity to handle this script a level update file might have been a better option and you could reuse it for other bonus stages.

not really. Level update fires in every tick (every engine update) and can lead to waste of resources. I am strongly against using update scripts unless you really need to.  Using an entity, you can reduce the resource usage a lot.

@Dante check what I did on my game. Turning the obstacles to enemies is easy and my grab codes already check for those names.

About your code, you can use log function to sent to the OpenBor log the result of that count and check if it is counting it right.
 
O Ilusionista said:
msmalik681 said:
also instead of making a entity to handle this script a level update file might have been a better option and you could reuse it for other bonus stages.

not really. Level update fires in every tick (every engine update) and can lead to waste of resources. I am strongly against using update scripts unless you really need to.  Using an entity, you can reduce the resource usage a lot.

@Dante check what I did on my game. Turning the obstacles to enemies is easy and my grab codes already check for those names.

About your code, you can use log function to sent to the OpenBor log the result of that count and check if it is counting it right.

Here the log:


Code:
-- LOG: Game proper ---------------------------

Level Loading:   'data/levels/bonus02.txt'
Total Ram: 4294967295 Bytes
 Free Ram: 4294967295 Bytes
 Used Ram: 140374016 Bytes

Loading 'textlist' from data/chars/misc/dialogue/textlist.txt
openborvariant: System variable name not found: 'count_obstacles'

Script compile error in 'timer': openborvariant line 36, column 19

********** An Error Occurred **********
*            Shutting Down            *

Can't compile script 'timer' data/chars/misc/bonus/timer.txt
Total Ram: 4294967295 Bytes
 Free Ram: 4294967295 Bytes
 Used Ram: 141225984 Bytes
 
You are not crazy and there is no such thing as "count_obstacle"  !

Another option is to do the exact same thing you are but change all obstacles to enemies with no move option and use the real option "count_enemies".
 
If you change them to enemies, you can just use "group" to... Group them and spawn the text animation after that.

It's exactly what I did in my game. No need for and update script, since the engine already does it :)
 
I coded simple script to count number of obstacles. I've updated FOLLOW1 animation above into this:

Code:
#BONUS - OBSTACLE COUNT
anim follow1
@script
    void self = getlocalvar("self");
    void vEntity;                                       //Target entity placeholder.
    int  iEntity;                                       //Entity enumeration holder.
    char iType;                                         //Entity type.
    int  iMax      = openborvariant("ent_max");         //Entity count.
    int C = 0;

    //Enumerate and loop through entity collection.
    for(iEntity=0; iEntity<iMax; iEntity++){
      vEntity = getentity(iEntity);                 //Get target entity from current loop.
      iType   = getentityproperty(vEntity, "type"); //Get target type.

      if(iType == openborconstant("TYPE_OBSTACLE")){
        C = C + 1;
      }
    }

    if(C == 0){
      changeentityproperty(self, "velocity", 0, 0, 0);
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
@end_script
	loop	1
	delay	10
        offset 1 1
        frame data/chars/misc/empty.png
        frame data/chars/misc/empty.png

The script will count number of active obstacles and if it remains 0, if it change animation into FOLLOW2
 
I coded simple script to count number of obstacles. I've updated FOLLOW1 animation above into this:

Code:
#BONUS - OBSTACLE COUNT
anim follow1
@script
    void self = getlocalvar("self");
    void vEntity;                                       //Target entity placeholder.
    int  iEntity;                                       //Entity enumeration holder.
    char iType;                                         //Entity type.
    int  iMax      = openborvariant("ent_max");         //Entity count.
    int C = 0;

    //Enumerate and loop through entity collection.
    for(iEntity=0; iEntity<iMax; iEntity++){
      vEntity = getentity(iEntity);                 //Get target entity from current loop.
      iType   = getentityproperty(vEntity, "type"); //Get target type.

      if(iType == openborconstant("TYPE_OBSTACLE")){
        C = C + 1;
      }
    }

    if(C == 0){
      changeentityproperty(self, "velocity", 0, 0, 0);
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
@end_script
    loop    1
    delay    10
        offset 1 1
        frame data/chars/misc/empty.png
        frame data/chars/misc/empty.png

The script will count number of active obstacles and if it remains 0, if it change animation into FOLLOW2
this script is perfect for what i need..only problem is that i cant stop ani_follow to stop looping... even setting loop 0 or removing loop line..just keeps looping lol
thanks
 
this script is perfect for what i need..only problem is that i cant stop ani_follow to stop looping... even setting loop 0 or removing loop line..just keeps looping lol
thanks
Just change the line "performattack..." with "executeanimation".

C-like:
executeanimation(self, openborconstant("ANI_FOLLOW2"));

executeanimation(entity, int anim, int resetable)

  • it works like performattack() but just you play an animation without animation loop.
  • This function is useful to avoid changeentityproperty(entity,"animation",value) loop issue!
 
Just change the line "performattack..." with "executeanimation".

C-like:
executeanimation(self, openborconstant("ANI_FOLLOW2"));

executeanimation(entity, int anim, int resetable)

  • it works like performattack() but just you play an animation without animation loop.
  • This function is useful to avoid changeentityproperty(entity,"animation",value) loop issue!
just changing this executeanimation doesnt do anything..keeps looping sadly

EDIT: also took your advise on enemy count and this is what am using and it works the same s above... but i did try your suggestion with both this one and the og one from bloodbane
Code:
@script
    void self = getlocalvar("self");
    int C = openborvariant("count_enemies");                 // Get count of enemies.

    // If no enemies are present, perform the follow animation.
    // Execute the animation directly.
    if(C == 0){
        executeanimation(self, openborconstant("ANI_FOLLOW1"));  // Perform follow animation.
    }
@end_script
 
Last edited:
@O Ilusionista is weird it seems like the whole idle and follow animations play right away once no matter what,then them the enemies are defeated it plays the follow 1 animation in loop tho.. also i couldnt get your door script you shared... i tried but no dice sadly :(
this is the whole animation. also adding a long delay on last frame is a no go since it cycles once right away so itl show the door open till that delay is done.

Code:
name    door1
health    1
type    obstacle
setlayer -9


anim idle
    loop 1
@script
    void self = getlocalvar("self");
    int C = openborvariant("count_enemies"); // Get count of enemies.

    // If no enemies are present, perform the follow animation.
    // Execute the animation directly.
    if(C == 0){
        executeanimation(self, openborconstant("ANI_FOLLOW1")); // Perform follow animation.
    }
@end_script
    delay 15
    offset 0 161
    platform 43 160 -64 -64 176 176 210 1100
    frame data/BGS/level8/L8/door1.png

anim follow1
    loop 0
    delay 15
    offset 0 161
    frame data/BGS/level8/L8/door/1.png
    frame data/BGS/level8/L8/door/2.png
    frame data/BGS/level8/L8/door/3.png
    frame data/BGS/level8/L8/door/4.png
    frame data/BGS/level8/L8/door/5.png
    frame data/BGS/level8/L8/door/6.png
    frame data/BGS/level8/L8/door/7.png
 
then them the enemies are defeated it plays the follow 1 animation in loop tho.. also i couldnt get your door script you shared... i tried but no dice sadly :(
Your code is checking it there is any enemy and if there is 1 enemy, it will play the follow1 animation.
Once you reach follow1, if there is no loop, the entity will revert back to IDLE.
But if you have one enemy when you revert back to idle, it will play FOLLOW1 again. The engine is doing exactly you are telling it to do :)

If you don't want a loop, try setting the delay of the last frame in follow1 animation to -1
 
Last edited:
Your code is checking it there is any enemy and if there is 1 enemy, it will play the follow1 animation.
Once you reach follow1, if there is no loop, the entity will revert back to IDLE.
But if you have one enemy when you revert back to idle, it will play FOLLOW1 again. The engine is doing exactly you are telling it to do :)

If you don't want a loop, try setting the delay of the last frame in follow1 animation to -1
i changed the 1 to 0 as that was just me not knowing wtf am doing trying stuff... also changed loop to -1 and it plays follow1 in a loop right away lol
EDIT- the delay now that i read again... leaves the door open right from the get go sdly
 
Last edited:
@O Ilusionista fixed xD thanks for the assist brother
ill post the whole animation here in case anyone else might need this.. remember to put an endlevel behind the door and also i used a platform to block its path.
that delay -1 is key tho.. if you dont put it there it will revert to idle animation that has the platform blocking the way.

fixed code same as below
Code:
name    door
health    1
type    obstacle
setlayer -9


anim idle
    loop 1
    delay 500
@script
    void self = getlocalvar("self");
    int C = openborvariant("count_enemies"); // Get count of enemies.
    int follow_played = getlocalvar("follow_played"); // Flag to track if follow animation was played.

    // Initialize follow_played flag if not set
    if(follow_played == NULL()){
        setlocalvar("follow_played", 0); // Initialize flag
    }

    // If enemies are 0 and follow animation has not been played
    if(C == 0 && follow_played == 0){
        setlocalvar("follow_played", 1); // Mark as played to prevent re-triggering
        executeanimation(self, openborconstant("ANI_FOLLOW1")); // Play follow1 animation
    }
@end_script
    offset 0 161
    platform 43 160 -64 -64 176 176 210 1100
    frame data/BGS/level8/L8/door/1.png

anim follow1
    loop 0
    delay 15
    offset 0 161
    frame data/BGS/level8/L8/door/1.png
    frame data/BGS/level8/L8/door/2.png
    frame data/BGS/level8/L8/door/3.png
    frame data/BGS/level8/L8/door/4.png
    frame data/BGS/level8/L8/door/5.png
    frame data/BGS/level8/L8/door/6.png
    frame data/BGS/level8/L8/door/7.png
    frame data/BGS/level8/L8/door/8.png
    frame data/BGS/level8/L8/door/9.png
    frame data/BGS/level8/L8/door/10.png
    frame data/BGS/level8/L8/door/11.png
    frame data/BGS/level8/L8/door/12.png
    frame data/BGS/level8/L8/door/14.png
    frame data/BGS/level8/L8/door/15.png
    frame data/BGS/level8/L8/door/16.png
    delay -1                            // This stops the follow1 animation from looping back to idle
    frame data/BGS/level8/L8/door/17.png
@end_script
 
Last edited:
Solution
grrr.. update..since the door am using is in the middle of the stage.. i set it so the player spawns near it and with an enemy right away... all for testing so i didnt have to run there every time.. now that i spawn at the begining it seems like its thinking theres no enemies and the door is already opened... so now even spawning enemies right away wont work as you have to move for them to come out... back to square 1.. this i dont know how to fix :(
apologies....i may end up spawning in the middle to solve this issue since the level is direction both... but it wouldnt work to great for others.



EDIT: fixed it by adding the anim idle delay to before the script and gave it a 500 which is enough to encounter the first enemy which will then have the door work as intended... that was close lol

Code:
name    door
health    1
type    obstacle
setlayer -9


anim idle
    loop 1
    delay 500
@script
    void self = getlocalvar("self");
    int C = openborvariant("count_enemies"); // Get count of enemies.
    int follow_played = getlocalvar("follow_played"); // Flag to track if follow animation was played.

    // Initialize follow_played flag if not set
    if(follow_played == NULL()){
        setlocalvar("follow_played", 0); // Initialize flag
    }

    // If enemies are 0 and follow animation has not been played
    if(C == 0 && follow_played == 0){
        setlocalvar("follow_played", 1); // Mark as played to prevent re-triggering
        executeanimation(self, openborconstant("ANI_FOLLOW1")); // Play follow1 animation
    }
@end_script
    offset 0 161
    platform 43 160 -64 -64 176 176 210 1100
    frame data/BGS/level8/L8/door/1.png

anim follow1
    loop 0
    delay 15
    offset 0 161
    frame data/BGS/level8/L8/door/1.png
    frame data/BGS/level8/L8/door/2.png
    frame data/BGS/level8/L8/door/3.png
    frame data/BGS/level8/L8/door/4.png
    frame data/BGS/level8/L8/door/5.png
    frame data/BGS/level8/L8/door/6.png
    frame data/BGS/level8/L8/door/7.png
    frame data/BGS/level8/L8/door/8.png
    frame data/BGS/level8/L8/door/9.png
    frame data/BGS/level8/L8/door/10.png
    frame data/BGS/level8/L8/door/11.png
    frame data/BGS/level8/L8/door/12.png
    frame data/BGS/level8/L8/door/14.png
    frame data/BGS/level8/L8/door/15.png
    frame data/BGS/level8/L8/door/16.png
    delay -1                            // This stops the follow1 animation from looping back to idle
    frame data/BGS/level8/L8/door/17.png
@end_script
 
Last edited:
Back
Top Bottom