Jump to content

Photo

Rage script

global active

  • Please log in to reply
8 replies to this topic

#1 Smiles the Death Bringer

Smiles the Death Bringer

    The smiling demon!

  • Members
  • Real Name:William
  • Location:Dream Land

Posted 11 August 2019 - 03:39 PM

I'm attempting to implement a script that is akin to Spartan Rage from God of War. I have a counter that is supposed to increment each time you take damage, then once it reaches 100, it ticks down until it reaches 0 again. Whenever I get hit, the counter just ticks all the way up to 99 and then freezes there.

import "std.zh"

global script Active
{
	void run()
	{
		bool rage = false;
		int lasthp = Link->HP;
		while (true)
		{
			moblinRage(rage, lasthp);
			Waitframe();
		}
	}
}

void moblinRage(bool rage, int lasthp){

	if(Link->HP < lasthp)
	{
		Game->Counter[CR_SCRIPT1] += (lasthp - Link->HP)/2;
		lasthp = Link->HP;
	}

	if(Game->Counter[CR_SCRIPT1] > 100)
	{
		Game->Counter[CR_SCRIPT1] = 100;
	}


	if(Game->Counter[CR_SCRIPT1] < 0)  
	{
		Game->Counter[CR_SCRIPT1] = 0;
	}

	if(Game->Counter[CR_SCRIPT1] == 0)
	{
		rage = false;
	}

	if(Game->Counter[CR_SCRIPT1] == 100)
   	{	
		rage = true;
	}

	if(rage == true)
	{
		Game->Counter[CR_SCRIPT1]--;
	}	
}


Edited by Smiles the Death Bringer, 11 August 2019 - 04:02 PM.


#2 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 11 August 2019 - 04:47 PM

When you pass the variables into moblinRage(), you're actually giving it copies. When you set them in that function, it only affects those copies; the variables in run() never change. The easiest way to fix that is to make them global.

When the counter reaches 100, rage is set to true, then the next block decrements the counter to 99. Since the variables don't stay set, in the next frame, either nothing will happen or the counter will just increment and decrement again.

#3 Smiles the Death Bringer

Smiles the Death Bringer

    The smiling demon!

  • Members
  • Real Name:William
  • Location:Dream Land

Posted 11 August 2019 - 06:31 PM

How would I do that? I tried to put the variables in the scope of the script, void run, and outside of everything and I get errors.
I'm using 2.53.


Edited by Smiles the Death Bringer, 11 August 2019 - 06:37 PM.


#4 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 11 August 2019 - 06:40 PM

Declare them outside of everything, but initialize them in the script. That is:
 
bool rage;
int lasthp;

global script Active
{
	void run()
	{
		rage = false;
		lasthp = Link->HP;
		while (true)
		{
			moblinRage();
			Waitframe();
		}
	}
}

Global variables can be initialized in place, but not with values that aren't known until the game is running (like Link's HP). But if you do that, they're only set when the quest is first started, not after each continue.

#5 Smiles the Death Bringer

Smiles the Death Bringer

    The smiling demon!

  • Members
  • Real Name:William
  • Location:Dream Land

Posted 11 August 2019 - 06:42 PM

Thank you. I've only ever worked in Java, so C++ is weird to me.



#6 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 11 August 2019 - 08:58 PM

I'm attempting to implement a script that is akin to Spartan Rage from God of War. I have a counter that is supposed to increment each time you take damage, then once it reaches 100, it ticks down until it reaches 0 again. Whenever I get hit, the counter just ticks all the way up to 99 and then freezes there.

import "std.zh"

global script Active
{
	void run()
	{
		bool rage = false;
		int lasthp = Link->HP;
		while (true)
		{
			moblinRage(rage, lasthp);
			Waitframe();
		}
	}
}

void moblinRage(bool rage, int lasthp){

	if(Link->HP < lasthp)
	{
		Game->Counter[CR_SCRIPT1] += (lasthp - Link->HP)/2;
		lasthp = Link->HP;
	}

	if(Game->Counter[CR_SCRIPT1] > 100)
	{
		Game->Counter[CR_SCRIPT1] = 100;
	}


	if(Game->Counter[CR_SCRIPT1] < 0)  
	{
		Game->Counter[CR_SCRIPT1] = 0;
	}

	if(Game->Counter[CR_SCRIPT1] == 0)
	{
		rage = false;
	}

	if(Game->Counter[CR_SCRIPT1] == 100)
   	{	
		rage = true;
	}

	if(rage == true)
	{
		Game->Counter[CR_SCRIPT1]--;
	}	
}

 
The other option here, is to use a script-local array. The array remains accessible as long as the script is active, so you can pass its pointer by reference and use it, thus:
 
 
const int RAGE_ACTIVE = 0; 
const int RAGE_LASTHP = 1; 

global script Active
{
	void run()
	{
		int rageinfo[2] = {0,(Link->HP*0.5)}; //active, lasthp
		
		while (true)
		{
			moblinRage(rageinfo);
			Waitframe();
		}
	}
}

bool moblinRage(int ptr)
{

	if(Link->HP < ptr[RAGE_LASTHP] ) 
	{
		if ( !ptr[RAGE_ACTIVE] ) //might want this, too
			//Game->Counter[CR_SCRIPT1] += (ptr[RAGE_LASTHP] - Link->HP)/2; //might want to rethink this calc
			Game->Counter[CR_SCRIPT1] = (Link->HP*0.5) * 60; //Half of his HP in seconds
	}
	if(Game->Counter[CR_SCRIPT1] > 99 )
	{
		if (!ptr[RAGE_ACTIVE]) 
		{
			ptr[RAGE_ACTIVE] = 1;
			return true;
		}
		else 
		{
			Game->Counter[CR_SCRIPT1] = 99;
		}
		
	}
	if ( ptr[RAGE_ACTIVE] )
	{
		if ( Game->Counter[CR_SCRIPT1] ) //reduce if > 0
		{
			--Game->Counter[CR_SCRIPT1];
		}
		else 
		{
			ptr[RAGE_ACTIVE] = 0; //ran out of rage bonus, so clear
			ptr[RAGE_LASTHP] = (Link->HP*0.5); //reset min HP
		}		
	}
	return (ptr[RAGE_ACTIVE]);
}
 
I also condensed and optimised your if chain, but I see a possible flaw logic. See my code comments.

#7 Smiles the Death Bringer

Smiles the Death Bringer

    The smiling demon!

  • Members
  • Real Name:William
  • Location:Dream Land

Posted 12 August 2019 - 12:27 PM

 
The other option here, is to use a script-local array. The array remains accessible as long as the script is active, so you can pass its pointer by reference and use it, thus:
 
 

const int RAGE_ACTIVE = 0; 
const int RAGE_LASTHP = 1; 

global script Active
{
	void run()
	{
		int rageinfo[2] = {0,(Link->HP*0.5)}; //active, lasthp
		
		while (true)
		{
			moblinRage(rageinfo);
			Waitframe();
		}
	}
}

bool moblinRage(int ptr)
{

	if(Link->HP < ptr[RAGE_LASTHP] ) 
	{
		if ( !ptr[RAGE_ACTIVE] ) //might want this, too
			//Game->Counter[CR_SCRIPT1] += (ptr[RAGE_LASTHP] - Link->HP)/2; //might want to rethink this calc
			Game->Counter[CR_SCRIPT1] = (Link->HP*0.5) * 60; //Half of his HP in seconds
	}
	if(Game->Counter[CR_SCRIPT1] > 99 )
	{
		if (!ptr[RAGE_ACTIVE]) 
		{
			ptr[RAGE_ACTIVE] = 1;
			return true;
		}
		else 
		{
			Game->Counter[CR_SCRIPT1] = 99;
		}
		
	}
	if ( ptr[RAGE_ACTIVE] )
	{
		if ( Game->Counter[CR_SCRIPT1] ) //reduce if > 0
		{
			--Game->Counter[CR_SCRIPT1];
		}
		else 
		{
			ptr[RAGE_ACTIVE] = 0; //ran out of rage bonus, so clear
			ptr[RAGE_LASTHP] = (Link->HP*0.5); //reset min HP
		}		
	}
	return (ptr[RAGE_ACTIVE]);
}
 
I also condensed and optimised your if chain, but I see a possible flaw logic. See my code comments.

 

 

Your script doesn't tick up the counter when Link takes damage. I've modified saffith's script to keep the counter from ticking down too fast.

 

void moblinRage(){

	if(Link->HP < lasthp && rage == false)
	{
		Game->Counter[CR_SCRIPT1] += (lasthp - Link->HP)/2;
	}

	if(Game->Counter[CR_SCRIPT1] > 100)
	{
		Game->Counter[CR_SCRIPT1] = 100;
	}
 
	if(Game->Counter[CR_SCRIPT1] < 0)  
	{
		Game->Counter[CR_SCRIPT1] = 0;
	}

	if(Game->Counter[CR_SCRIPT1] <= 0)
	{
		rage = false;
	}

	if(Game->Counter[CR_SCRIPT1] >= 100)
	{	
		rage = true;
	}

	if(rage == true)
	{
		countdown--;
		if(countdown % 4 == 0)
		{
			Game->Counter[CR_SCRIPT1]--;
		}
	}	

	if(rage == false)
	{
		countdown = 5000;
	}
	
	lasthp = Link->HP;

}


#8 Emily

Emily

    Scripter / Dev

  • ZC Developers

Posted 12 August 2019 - 02:11 PM

Here, I fixed that for both of you. Zoria had the better idea with using a ptr, and optimizing the number of checks, but he got the basic functionality of the script wrong entirely. Saffith just gave you the quick-and-dirty fix (just make the var global), without any optimizations.

This should:

1. Be more optimized than the original script

2. Actually do what you intend it to

3. Not use global variables (you only get so many for your entire quest, so, using local/arrays is preferable)

import "std.zh"

const int RAGE_ACTIVE = 0;
const int RAGE_LASTHP = 1;

global script Active
{
	void run()
	{
		int ragedata[2] = {0, Link->HP};
		while (true)
		{
			moblinRage(ragedata);
			Waitframe();
		}
	}
}

void moblinRage(int data)
{
	if(data[RAGE_ACTIVE])
	{
		--Game->Counter[CR_SCRIPT1];
		if(!Game->Counter[CR_SCRIPT1])
		{
			data[RAGE_ACTIVE] = 0;
		}
	}
	else if(Link->HP < data[RAGE_LASTHP])
	{
		Game->Counter[CR_SCRIPT1] += (data[RAGE_LASTHP] - Link->HP)/2;
		if(Game->Counter[CR_SCRIPT1] >= 100)
		{
			data[RAGE_ACTIVE] = 1;
			Game->Counter[CR_SCRIPT1] = 100;
		}
	}
        data[RAGE_LASTHP] = Link->HP;
}


#9 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 12 August 2019 - 06:26 PM

I misunderstood the original intent. I thought that the rage duration was meant to be variable, and that you intended it to trigger every time Link's HP dropped below 1/2 of its last recorded value.. As-is, it lasts exactly 1.6 seconds, which seems too short.

The script also needs a constant update of [lasthp].



Also tagged with one or more of these keywords: global, active

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users