Jump to content

Photo

Power Bomb


  • Please log in to reply
21 replies to this topic

#1 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 22 November 2021 - 02:08 PM

I need a script for a power bomb item that would damage all enemies on screen and trigger super bomb triggers and spend 1 super bomb and plays an animation, like the one from super metroid and metroid dread



#2 ywkls

ywkls

    Master

  • Members

Posted 22 November 2021 - 04:11 PM

I made this for my Metroid quest a while back.
I'm not sure how easy it would be to transfer to another project.
This hasn't been tested in any way.

const int POWER_BOMB_CENTER_X= 1;
const int POWER_BOMB_CENTER_Y= 2;
const int POWER_BOMB_RADIUS  = 3;

int GameVars[65536];

const int GEN_MISC_FLAGS			= 0;//Index used to set various flags. Shared by all objects.
const int NPC_F_PB			        = 00000000100b;//An enemy hit by a power bomb.
const int SPRITE_NULL				= 0;

item script PowerBomb{
	void run(int script_num, int damage)
		if(Game->Counter[CR_SBOMBS]>=1){
			Game->Counter[CR_SBOMBS]--;
			//Start power bomb wave.
			if(GameVars[POWER_BOMB_RADIUS]==0)
				GameVars[POWER_BOMB_RADIUS]=8;
			if(CountFFCsRunning(script_num)==0){
				int Args[8]= {damage};
				NewFFCScript(script_num, Args);
			}
		}
	}
}

ffc script PowerBombFX{
	void run(int damage)
		int i;
		npc n;
		while(true){
			//The wave hasn't been created yet.
			if(GameVars[POWER_BOMB_RADIUS]!=0){
				//If the wave hasn't reached it's edge yet.
				if(GameVars[POWER_BOMB_RADIUS]<200){
					Screen->Circle(4, GameVars[POWER_BOMB_CENTER_X], 
									GameVars[POWER_BOMB_CENTER_Y], GameVars[POWER_BOMB_RADIUS], 
									((GameVars[POWER_BOMB_RADIUS]/10)%16), 1, 0, 0, 0, true, 64);
					GameVars[POWER_BOMB_RADIUS]+=4;
				}
				//This power bomb has gone off.
				else{
					GameVars[POWER_BOMB_RADIUS]= 0;
					for(i = Screen->NumNPCs();i>0;i--){
						n = Screen->LoadNPC(i);
						if((n->Misc[GEN_MISC_FLAGS]&NPC_F_PB)!=0)
							n->Misc[GEN_MISC_FLAGS]&=~NPC_F_PB;
					}
				}
				//Mark and damage enemies in range.
				for(i = Screen->NumNPCs();i>0;i--){
					n = Screen->LoadNPC(i);
					if((n->Misc[GEN_MISC_FLAGS]&NPC_F_PB)==0  
						&& Between(n->X+(n->HitWidth/2),GameVars[POWER_BOMB_CENTER_X]-GameVars[POWER_BOMB_RADIUS],GameVars[POWER_BOMB_CENTER_X]+GameVars[POWER_BOMB_RADIUS])
						&& Between(n->Y+(n->HitHeight/2),GameVars[POWER_BOMB_CENTER_Y]-GameVars[POWER_BOMB_RADIUS],GameVars[POWER_BOMB_CENTER_Y]+GameVars[POWER_BOMB_RADIUS]) 
						&& n->Defense[NPCD_SBOMB]==NPCDT_NONE){
						lweapon w = CreateLWeaponAt(LW_SCRIPT3,n->X+(n->HitWidth/2),n->Y+(n->HitHeight/2));
						w->Damage = damage;
						w->UseSprite(SPRITE_NULL);
						n->Misc[GEN_MISC_FLAGS]|=NPC_F_PB;
					}
				}
				//Set off secrets if in range of blast.
				for(i = 0;i<175;i++){
					if(Abs(ComboX(i)-GameVars[POWER_BOMB_CENTER_X])<GameVars[POWER_BOMB_RADIUS]
						&& Abs(ComboY(i)-GameVars[POWER_BOMB_CENTER_Y])<GameVars[POWER_BOMB_RADIUS]){
						if(ComboFI(i,CF_SBOMB) && !Screen->State[ST_SECRET]){
							Screen->State[ST_SECRET]= true;
							Screen->TriggerSecrets();
						}
					}
				}
			}
			Waitframe();
		}
	}
}

Video of the script in action.


Edited by ywkls, 22 November 2021 - 04:13 PM.


#3 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 22 November 2021 - 05:05 PM

I made this for my Metroid quest a while back.
I'm not sure how easy it would be to transfer to another project.
This hasn't been tested in any way.

const int POWER_BOMB_CENTER_X= 1;
const int POWER_BOMB_CENTER_Y= 2;
const int POWER_BOMB_RADIUS  = 3;

int GameVars[65536];

const int GEN_MISC_FLAGS			= 0;//Index used to set various flags. Shared by all objects.
const int NPC_F_PB			        = 00000000100b;//An enemy hit by a power bomb.
const int SPRITE_NULL				= 0;

item script PowerBomb{
	void run(int script_num, int damage)
		if(Game->Counter[CR_SBOMBS]>=1){
			Game->Counter[CR_SBOMBS]--;
			//Start power bomb wave.
			if(GameVars[POWER_BOMB_RADIUS]==0)
				GameVars[POWER_BOMB_RADIUS]=8;
			if(CountFFCsRunning(script_num)==0){
				int Args[8]= {damage};
				NewFFCScript(script_num, Args);
			}
		}
	}
}

ffc script PowerBombFX{
	void run(int damage)
		int i;
		npc n;
		while(true){
			//The wave hasn't been created yet.
			if(GameVars[POWER_BOMB_RADIUS]!=0){
				//If the wave hasn't reached it's edge yet.
				if(GameVars[POWER_BOMB_RADIUS]<200){
					Screen->Circle(4, GameVars[POWER_BOMB_CENTER_X], 
									GameVars[POWER_BOMB_CENTER_Y], GameVars[POWER_BOMB_RADIUS], 
									((GameVars[POWER_BOMB_RADIUS]/10)%16), 1, 0, 0, 0, true, 64);
					GameVars[POWER_BOMB_RADIUS]+=4;
				}
				//This power bomb has gone off.
				else{
					GameVars[POWER_BOMB_RADIUS]= 0;
					for(i = Screen->NumNPCs();i>0;i--){
						n = Screen->LoadNPC(i);
						if((n->Misc[GEN_MISC_FLAGS]&NPC_F_PB)!=0)
							n->Misc[GEN_MISC_FLAGS]&=~NPC_F_PB;
					}
				}
				//Mark and damage enemies in range.
				for(i = Screen->NumNPCs();i>0;i--){
					n = Screen->LoadNPC(i);
					if((n->Misc[GEN_MISC_FLAGS]&NPC_F_PB)==0  
						&& Between(n->X+(n->HitWidth/2),GameVars[POWER_BOMB_CENTER_X]-GameVars[POWER_BOMB_RADIUS],GameVars[POWER_BOMB_CENTER_X]+GameVars[POWER_BOMB_RADIUS])
						&& Between(n->Y+(n->HitHeight/2),GameVars[POWER_BOMB_CENTER_Y]-GameVars[POWER_BOMB_RADIUS],GameVars[POWER_BOMB_CENTER_Y]+GameVars[POWER_BOMB_RADIUS]) 
						&& n->Defense[NPCD_SBOMB]==NPCDT_NONE){
						lweapon w = CreateLWeaponAt(LW_SCRIPT3,n->X+(n->HitWidth/2),n->Y+(n->HitHeight/2));
						w->Damage = damage;
						w->UseSprite(SPRITE_NULL);
						n->Misc[GEN_MISC_FLAGS]|=NPC_F_PB;
					}
				}
				//Set off secrets if in range of blast.
				for(i = 0;i<175;i++){
					if(Abs(ComboX(i)-GameVars[POWER_BOMB_CENTER_X])<GameVars[POWER_BOMB_RADIUS]
						&& Abs(ComboY(i)-GameVars[POWER_BOMB_CENTER_Y])<GameVars[POWER_BOMB_RADIUS]){
						if(ComboFI(i,CF_SBOMB) && !Screen->State[ST_SECRET]){
							Screen->State[ST_SECRET]= true;
							Screen->TriggerSecrets();
						}
					}
				}
			}
			Waitframe();
		}
	}
}

Video of the script in action.

right now it won't compile, it doesn't like line 13 



#4 Russ

Russ

    Caelan, the Encouraging

  • Administrators
  • Location:Washington

Posted 22 November 2021 - 05:48 PM

What's the specific error it's giving? The compiler will usually explain why it can't compile a particular line, and that info more often than not is necessary in troubleshooting.

 

Edit: Wait I see the issue myself. ywkls's script is missing an open parenthesis. Replace this bit:

 

void run(int script_num, int damage)

 

with this:

 

void run(int script_num, int damage){


#5 Moosh

Moosh

    Tiny Little Questmaker

  • ZC Developers

Posted 22 November 2021 - 05:49 PM

Just a heads up, it's handy to mention which specific version of ZC your quest is targetting when writing a request. Usually it doesn't matter and people can just assume the lowest version available, but there are situations where 2.55 makes a huge difference over 2.53.



#6 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 22 November 2021 - 06:45 PM

 

What's the specific error it's giving? The compiler will usually explain why it can't compile a particular line, and that info more often than not is necessary in troubleshooting.

 

Edit: Wait I see the issue myself. ywkls's script is missing an open parenthesis. Replace this bit:

void run(int script_num, int damage)

with this:

void run(int script_num, int damage){

EDIT now it says function newffcscript and function between are undeclared. is there any other scripts I need?


Edited by Blackpaintbowser, 22 November 2021 - 09:18 PM.


#7 ywkls

ywkls

    Master

  • Members

Posted 23 November 2021 - 08:27 AM

EDIT now it says function newffcscript and function between are undeclared. is there any other scripts I need?

Sorry, I forget that those are custom scripts sometimes.

int NewFFCScript(int scriptNum, float args){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc theFFC;
    
    // Find an FFC not already in use
    for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
        theFFC=Screen->LoadFFC(i);
        
        if(theFFC->Script!=0){
			if(theFFC->Script!=BLANK_SCRIPT)
				continue;
			if(theFFC->Data!=0){
				if(theFFC->Data!=FFCS_INVISIBLE_COMBO)
					continue;
			}
			if(theFFC->Flags[FFCF_CHANGER])
				continue;
        }
        // Found an unused one; set it up
        theFFC->Data=FFCS_INVISIBLE_COMBO;
		theFFC->TileWidth = 1;
		theFFC->TileHeight = 1;
        theFFC->Script=scriptNum;
        
        if(args!=NULL){
            for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
                theFFC->InitD[j]=args[j];
        }
        theFFC->Flags[FFCF_ETHEREAL]= true;
        return i;
    }
    
    // No FFCs available
    return 0;
}

//Test if one location is between two others.
//D0- Location to test
//D1- Lower bound
//D2- Higher bound

bool Between(int loc,int greaterthan, int lessthan){
	if(loc>=greaterthan && loc<=lessthan)return true;
	return false;
}

I don't think there are any others which were used but I could be wrong.



#8 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 23 November 2021 - 01:44 PM

Sorry, I forget that those are custom scripts sometimes.

int NewFFCScript(int scriptNum, float args){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc theFFC;
    
    // Find an FFC not already in use
    for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
        theFFC=Screen->LoadFFC(i);
        
        if(theFFC->Script!=0){
			if(theFFC->Script!=BLANK_SCRIPT)
				continue;
			if(theFFC->Data!=0){
				if(theFFC->Data!=FFCS_INVISIBLE_COMBO)
					continue;
			}
			if(theFFC->Flags[FFCF_CHANGER])
				continue;
        }
        // Found an unused one; set it up
        theFFC->Data=FFCS_INVISIBLE_COMBO;
		theFFC->TileWidth = 1;
		theFFC->TileHeight = 1;
        theFFC->Script=scriptNum;
        
        if(args!=NULL){
            for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
                theFFC->InitD[j]=args[j];
        }
        theFFC->Flags[FFCF_ETHEREAL]= true;
        return i;
    }
    
    // No FFCs available
    return 0;
}

//Test if one location is between two others.
//D0- Location to test
//D1- Lower bound
//D2- Higher bound

bool Between(int loc,int greaterthan, int lessthan){
	if(loc>=greaterthan && loc<=lessthan)return true;
	return false;
}

I don't think there are any others which were used but I could be wrong.

BLANK_SCRIPT this doesn't exist and also how do I set up the item?


Edited by Blackpaintbowser, 23 November 2021 - 09:38 PM.


#9 ywkls

ywkls

    Master

  • Members

Posted 23 November 2021 - 09:45 PM

BLANK_SCRIPT this doesn't exist and also how do I set up the item?

You can comment out those two lines.

I added them because of a bug which you probably won't have to deal with.

 

Set the item script as the Action Script for the item you want to use it.

Set the first argument as the ffc slot the ffc script uses.

Set the second argument as the amount of damage it does.

 

You will have to assign the ffc script to a script slot for it to work and change the item's arguments to reflect this.

I could have made this a constant but it's easier to use the item script to set this.

 

Once these two steps have been taken, equip and use the item while you have at least one super bomb ammo in inventory.

It doesn't have to be a super bomb to work.


Edited by ywkls, 23 November 2021 - 09:45 PM.


#10 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 23 November 2021 - 10:15 PM

right now the bomb just gets placed and then diserpears. is there anything I need to change in the script? and where am I supposed to put this:

int NewFFCScript(int scriptNum, float args){
// Invalid script
if(scriptNum<0 || scriptNum>511)
return 0;

ffc theFFC;

// Find an FFC not already in use
for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
theFFC=Screen->LoadFFC(i);

if(theFFC->Script!=0){
            if(theFFC->Script!=BLANK_SCRIPT)
                continue;
            if(theFFC->Data!=0){
                if(theFFC->Data!=FFCS_INVISIBLE_COMBO)
                    continue;
            }
            if(theFFC->Flags[FFCF_CHANGER])
                continue;
}
// Found an unused one; set it up
theFFC->Data=FFCS_INVISIBLE_COMBO;
        theFFC->TileWidth = 1;
        theFFC->TileHeight = 1;
theFFC->Script=scriptNum;

if(args!=NULL){
for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
theFFC->InitD[j]=args[j];
}
theFFC->Flags[FFCF_ETHEREAL]= true;
return i;
}

// No FFCs available
return 0;
}

//Test if one location is between two others.
//D0- Location to test
//D1- Lower bound
//D2- Higher bound

bool Between(int loc,int greaterthan, int lessthan){
    if(loc>=greaterthan && loc<=lessthan)return true;
    return false;
}


Edited by Blackpaintbowser, 23 November 2021 - 10:25 PM.


#11 Emily

Emily

    Scripter / Dev

  • ZC Developers

Posted 24 November 2021 - 12:20 AM

right now the bomb just gets placed and then diserpears. is there anything I need to change in the script? and where am I supposed to put this:

int NewFFCScript(int scriptNum, float args){
// Invalid script
if(scriptNum<0 || scriptNum>511)
return 0;

ffc theFFC;

// Find an FFC not already in use
for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
theFFC=Screen->LoadFFC(i);

if(theFFC->Script!=0){
            if(theFFC->Script!=BLANK_SCRIPT)
                continue;
            if(theFFC->Data!=0){
                if(theFFC->Data!=FFCS_INVISIBLE_COMBO)
                    continue;
            }
            if(theFFC->Flags[FFCF_CHANGER])
                continue;
}
// Found an unused one; set it up
theFFC->Data=FFCS_INVISIBLE_COMBO;
        theFFC->TileWidth = 1;
        theFFC->TileHeight = 1;
theFFC->Script=scriptNum;

if(args!=NULL){
for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
theFFC->InitD[j]=args[j];
}
theFFC->Flags[FFCF_ETHEREAL]= true;
return i;
}

// No FFCs available
return 0;
}

//Test if one location is between two others.
//D0- Location to test
//D1- Lower bound
//D2- Higher bound

bool Between(int loc,int greaterthan, int lessthan){
    if(loc>=greaterthan && loc<=lessthan)return true;
    return false;
}

those are just functions, so anywhere



#12 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 24 November 2021 - 10:16 PM

just found out the item is mostly working, but the explosion is coming from the top left, and is playing no sound


Edited by Blackpaintbowser, 24 November 2021 - 10:30 PM.


#13 ywkls

ywkls

    Master

  • Members

Posted 25 November 2021 - 09:35 AM

just found out the item is mostly working, but the explosion is coming from the top left, and is playing no sound

Add these lines to the ffc script before while(true).

this->X= Link->X+8;
this->Y= Link->Y+8;
GameVars[POWER_BOMB_CENTER_X]- this->X;
GameVars[POWER_BOMB_CENTER_Y]- this->Y;

This will cause the explosion to center on the player.

 

Change the item script as follows.

item script PowerBomb{
	void run(int script_num, int damage, int sfx)
		if(Game->Counter[CR_SBOMBS]>=1){
			Game->Counter[CR_SBOMBS]--;
			//Start power bomb wave.
			if(GameVars[POWER_BOMB_RADIUS]==0)
				GameVars[POWER_BOMB_RADIUS]=8;
                        Game->PlaySound(sfx);
			if(CountFFCsRunning(script_num)==0){
				int Args[8]= {damage};
				NewFFCScript(script_num, Args);
			}
		}
	}
}

Use the item scripts arguments to assign the sound of your choice.



#14 Blackpaintbowser

Blackpaintbowser

    Go Bowser Go

  • Members
  • Location:somewhere in the world

Posted 17 December 2021 - 09:19 PM

It still is coming from the top left



#15 ywkls

ywkls

    Master

  • Members

Posted 19 December 2021 - 12:28 PM

It still is coming from the top left

I would probably have to look at the script file to see what's going on.

The problem with working on it separately is the fact that I can't see anything which might be affecting it.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users