Jump to content

Photo

EctoGoggles, Lives System, and More (Proof of Concept)

ghostbusters ffc script slow game fix

  • Please log in to reply
6 replies to this topic

#1 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 06 September 2013 - 05:04 AM

I have been working on some projects in the background, that may amuse some of you, and in the process learned some oddities in ZScript, which I will outline below.

Item One: A Lives & Points System: While not yet perfect, I have it semi-functional in two games. There are a few bugs remaining, but I am certain that I can find a way around both of the big ones.

One is that the game is set to deplete a life and respawn Link when he is below 16HP (1-heart), but sometimes if Link takes enough damage to go from 30-40HP to -HP, instead of removing a life and respawning, the engine kills him.

The other has to do with some conflicts in my onContinue and onExit scripts, as the points and life count do not always reset as I desire.

Item Two: EctoGoggles!: This is an item, a new spin based on the bool item concept that MoscowModder used in his OneRing script, that enables or disables the amulet item via an item that Link must use. That is, to see invisible enemies, Link must activate his EctoGoggles, which drain MP (or Energy, as in the demo below).

(Using scripts like this, it is possible to enable any passive item only when using an active item, should you desire; the amulet seemed the most natural (initial) choice for the science-fiction themed games that I am making.)

I included some nice visual effects, including an initial screen wave, and a blue overlay, plus sound effects, etc..

Most Important...

What I learned, that may be crucial to anyone wanting to do this sort of thing: If you set up a global script to set an item to false, ZC slows to a crawl. (It dropped from 60FPS to about 25FPS on my system.)

There is a way around this, and I figured it out on my own, by a combination of experimentation and (for a change), actual understanding of the language. I thought to post the script and ask for help, but as soon as I saw that it was only happening when the passive item was set to false, but not when it was set to true, I had a suspicion that it was a waitframe category issue. I tried a simple return function first, but of course, that broke the script.

Waitframes(1), however, works like a charm, and the bottom line is that if you want to use a while loop to set an item to true, this does not seem to slow down ZC, but if you set it to false, it does. What I did, was add a Waitframes(1) to the else if statements and if statements that made the item false, and amazingly, that fixed it.

I will be posting scripts to the database, with the EctoGoggles being my next entry, and the Lives System once I debug some of the flaws. For the time being, here is a demo of EctoGoggles rev.7. (The sound files make it a tad bloated at 5.7MB for such a tiny demo, and it includes an original score of music.)

It is a mere six-screen arena, and includes some other things that I have not implemented, such as a guns and ammunition system (from a previous demo that I posted) and the lives & points system, plus a modification of jsm116's whip concept, somewhat streamlined, and turned into a proton pack/

I expect to be drawing some 'Ghostbusters' sprites--I would rip the ones from NGBII, but they are slightly larger than 16x16, and I don't want to push too hard to make an oversized player sprite just yet--to add into the game, plus ghosts, and nasties. Some will be visible only via the goggles, and my mate suggested that I set up puzzles that the player can only solve via the goggles... More on that in the future.

I am uploading this now, so it may take 5-10 minutes to be ready to download.

I will of course be posting the scripts to the database, particularly when I get the bugs out of the lives system. I will likely post the EctoGoggles scripts into the forums this evening, while I prepare a proper DB template for them.

I would appreciate any feedback, suggestions, or assistance in getting the Lives system fully-operational. The main crux is interupting the normal game engine death sequence. I am doing this:



The flaw occurs if Link dies because of zero HP, and the game does not interrupt the death with this:

if ((Game->Counter[CR_LIVES] >= 1) && (Link->HP < 17))
I'm not sure if there is a better way to handle this. Perhaps something similar to HP_DEAD for NPCs would work? I'm open to any ideas or suggestions and any feedback.

#2 MoscowModder

MoscowModder

    Sometimes lurking. Rarely posting.

  • Members
  • Location:Wisconsin

Posted 06 September 2013 - 10:34 AM

For some reason, setting Link->Item[x] to true or false every frame slows down ZC. To get around this, do:

 

bool value; //Figure out what this is however you want
if(Link->Item[id] != value)
    Link->Item[id] = value;


#3 Alucard648

Alucard648

    Wizard

  • Members
  • Location:castle Dracula

Posted 06 September 2013 - 12:02 PM

 

While not yet perfect, I have it semi-functional in two games. There are a few bugs remaining, but I am certain that I can find a way around both of the big ones.

One is that the game is set to deplete a life and respawn Link when he is below 16HP (1-heart), but sometimes if Link takes enough damage to go from 30-40HP to -HP, instead of removing a life and respawning, the engine kills him.

The other has to do with some conflicts in my onContinue and onExit scripts, as the points and life count do not always reset as I desire.

I am suggesting another completely different way to handle lives:

When Link uses Continue after death, OnContinue global script reduces Lives counter by 1 and then checks if that counter is reduced to 1 (which means Link is down to last life) and if that check returns true turn on "Skip Continue screen" rule. Any event that raises Lives counter above 1 (like 1UP item) turns "Skip continue screen" rule off. 

Did You tried this?



#4 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 06 September 2013 - 09:02 PM

I want to avoid the continue screen entirely, unless Link runs out of Lives, and replace it with a custom display via visual effects. Using the continue screen in the way that you suggest would also break part of the ultimate goal

There is nothing wrong with the continue process. The flaw lies in how the game engine handles Link's HP and death, and how to resolve proper interruption.

I found that it is only a problem when setting an item to false... I tried reversing the ordering, and it was only slow when setting it to false. Adding a Waitframes() after the else solved it. I think Waitframes(0) might even work, as it only needs some interruption.

Edited by ZoriaRPG, 06 September 2013 - 09:20 PM.


#5 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 06 September 2013 - 09:52 PM

The goggles do not reveal other hidden things, only Invisible (spectral) enemies; whereas the Lens shows all secrets and flags.

I want to avoid the continue screen entirely, unless Link runs out of Lives, and replace it with a custom display via visual effects. Using the continue screen in the way that you suggest would also break part of the ultimate goal

There is nothing wrong with the continue process. The flaw lies in how the game engine handles Link's HP and death, and how to resolve proper interruption.

I found that it is only a problem when setting an item to false... I tried reversing the ordering, and it was only slow when setting it to false. Adding a Waitframes() after the else solved it. I think Waitframes(0) might even work, as it only needs some interruption.

Would this work (using DCounter) better than what I am doing above?

void LivesUpdate(){
	int continuedmap = Game->LastEntranceDMap;
	int entScreen = Game->LastEntranceScreen;
	if ( Game-DCounter[CR_LIFE] >= Game->Counter[CR_LIFE] ){
		Game->Counter[CR_LIVES] -= 1;
		Link->Invisible = false;
		Link->HP += 999;
		SkipContinue = true;
		closingWipe(30);
		Waitframes(10);
		Link->Warp(continuedmap, entScreen);
		openingWipe(30);
		}
	else if ((Game->Counter[CR_LIVES] == 0) && (Link->HP <= 0 )){
	return;
	}
}
I also need to put this on all damaging FFCs, seemingly, as they execute before global code.

I know that I also have the option of making every enemy ghosted or otherwise scripted, and setting them to lower a different counter on collision, other than doing standard damage, and displaying that false counter as a Life gauge to bypass the internal life system, but I would prefer a solution that doesn't need that level of extra work.

#6 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 09 September 2013 - 10:31 PM

For some reason, setting Link->Item[x] to true or false every frame slows down ZC. To get around this, do:
 

bool value; //Figure out what this is however you want
if(Link->Item[id] != value)
    Link->Item[id] = value;


This seems as if it would set up a perpetual loop...?

How do I use your for this situation, to turn the amulet on and off with the bool GogglesOn (scroll to '//Take off goggles.'):

[hidden]
bool isValid;
const int TIME_PER_MP = 15; //How many frames 1 unit of MP lasts items.
bool gogglesOn;
int gogglesTimer;

global script active{
    void run(){
    int whipCooldownTimer = 0;
	LinkX = Link->X;
    LinkY = Link->Y;
	int fastWalkTimer;
    int lastScreen = Game->GetCurDMapScreen();
    int lastDMap = Game->GetCurDMap();
	Game->MCounter[CR_LIVES] = 99;
	Game->MCounter[CR_POINTS] = 999999;
	
        while(true){
		
		
		if ( LinkSeen ){
			Link->Invisible = false;
			}
		else if ( !LinkSeen ){
			Link->Invisible = true;
			}
		
		//Whip Cooldown Timer
            if ( whipCooldownTimer > 0 )
                whipCooldownTimer--;
			
            if ( gogglesOn && Link->MP ){                
                //Decrement magic
                gogglesTimer = (gogglesTimer+1) % TIME_PER_MP;
                if ( !gogglesTimer ) Link->MP--;
				Screen->Rectangle(6, 0, 0, 256, 172, 4, 1, 0, 0, 0, true, 64);
                
                if ( Link->MP <= 0 //If magic ran out
               
                ){ //Take off goggles.
				
                    gogglesOn = false;
					if(Link->Item[I_AMULET1] != IsValid){
					Link->Item[I_AMULET1] = IsValid;
					}
                    Link->Item[I_AMULET1] = false;
                }

            }
            else if ( !gogglesOn ){ //Disable Goggles
                Link->Item[I_AMULET1] = false;
				Waitframes(1);
            }
			
			
	
        
            //Exp gain and level up
            if ( Game->Counter[CR_LEVEL] < EXP_MAX_LEVEL ){ //Disable if level is maxed
                setMaxHP();
                checkEnemiesKilled();
            }
		lastScreen = Game->GetCurDMapScreen(); //Update last screen/DMap
		lastDMap = Game->GetCurDMap();
            
            //Fast walk
            if ( Link->Item[I_FASTWALK] ){
                fastWalkTimer++;
                fastWalkTimer %= EXP_FASTWALKRATE;
                if ( fastWalkTimer == 0 )
                    fastWalk(1);
            }
            
            //Treasure Hunter
            if ( Link->Item[I_TREASUREHUNTER] //If skill learned
                && (lastScreen != Game->GetCurDMapScreen() || lastDMap != Game->GetCurDMap()) //If new screen
                && checkScreenFlag(SF_TREASURE) //And flag active
                && !Screen->State[ST_ITEM] //And item not taken
                && !Screen->State[ST_CHEST]
                && !Screen->State[ST_LOCKEDCHEST]
                && !Screen->State[ST_BOSSCHEST]
            ){
                Game->PlaySound(SFX_TREASURESCREEN); //Play SFX
            }
            lastScreen = Game->GetCurDMapScreen(); //Update last screen/DMap
            lastDMap = Game->GetCurDMap();
			
			UpdateEWeapons();
			CleanUpGhostFFCs(); // Only needed if __GH_USE_DRAWCOMBO is 0
			UpdateGhostZHData();
			Cooldown_Update();
			
	  
			Game->Counter[CR_SCRIPT2] = Link->HP;
			Game->Counter[CR_SCRIPT3] = Link->MP;
			Game->Counter[CR_SCRIPT4] = Link->MaxHP;
			Game->Counter[CR_SCRIPT5] = Link->MaxMP;
			Game->Counter[CR_LIVES] = Game->Counter[16];
			Game->Counter[CR_POINTS] =%2


#7 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 09 September 2013 - 11:49 PM

For some reason, setting Link->Item[x] to true or false every frame slows down ZC.

Update: Solved: The reason for the game engine slowing was that in declaring Link->Item[I_AMULET] false every frame, while it is already false, the game is constantly resetting it. Adding one statement (essentially, if that item is not false, so that it only sets it false if it is already true) suggested by MM fixed it , and now it runs at full-speed.

New Global



Edited by ZoriaRPG, 10 September 2013 - 04:02 AM.




Also tagged with one or more of these keywords: ghostbusters, ffc script, slow game, fix

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users