Copy to Clipboard Test

Jumping Pushblock Code

const int CMB_JUMP_PUSHBLOCK_SOLID = 1; //ID of combo used to mimic solidity. It must be fully solid and fully transparent.



const int SFX_JUMP_PUSHBLOCK_MOVE = 50; //Sound to play when moving a block.

const int SFX_JUMP_PUSHBLOCK_STUCK = 16;//Sound to play when pushblock gets stuck.

const int SFX_JUMP_PUSHBLOCK_BOUNCE = 16;//Sound to play when pushblock bounces off wall in midair



const int CMB_JUMP_PUSHBLOCK_SHADOW = 1011;//Combo used to render shadow.

const int CSET_JUMP_PUSHBLOCK_SHADOW = 7;//CSet used to render shadow.



//Pushblock that jumps certain amount of space when pushed. Bounces off walls, can crush Link, if land on top of him.

//Requires LinkMovement.zh and SolidFFCs.zh

//Set up solid combo with blank tile for CMB_JUMP_PUSHBLOCK_SOLID constant.

//Effect Width and Height used. If TileHeight is greater than EffectHeight / 16, then the script calls JumpPush Renderer, so FFC sprite rendering is aligned to bottom edge of FFC`s hitbox.

//D0 - bracelet level requirement.

//D1 - allowed push directions. Add together - 1-up, 2-down, 4-left, 8-right. 0 for all directions.

//D2 - add together: 1 - gets stuck after 1 push, 2 - gets stuck when landing on trigger, 4 - unused, 8 - ignore triggers, 16 - require triggers with same CSet as FFC`s Cset, 32 - animation on push (uses next combo in list)

//D3 - jumping distance per push, in combos.

//If you want for support for combo-related puzzles, like Matrix Password Puzzle, place exactly similar-looking FFC with script on top of solid puzzle combos, such as blocks with letters inscribed on them.

//JumpPushRender

//Renderer for JumpPush blocks

//Place, gridsnap, and align on bottom with large pushblock.

//D0 - ID of pushblock FFC



ffc script JumpPushBlock{

	void run (int weight, int dirs, int flags, int speed){

		if (speed==0)speed=1;

		int origdata= this->Data;

		int cmb=origdata;

		int str[] = "JumpPushRender";

		int scr = Game->GetFFCScript(str);

		if (this->TileHeight>(this->EffectHeight/16)){

			int args[2] = {FFCNum(this),0};

			ffc r = RunFFCScriptOrQuit(scr, args);

			r->Data = cmb;

			r->X = this->X;

			r->TileWidth = this->TileWidth;

			r->TileHeight=this->TileHeight;

			r->CSet = this->CSet;

			r->Y = this->Y + this->EffectHeight - this->TileHeight*16;

			this->Data = FFCS_INVISIBLE_COMBO;

		}	

		int pos = ComboAt (this->X+1, this->Y+1);

		if (dirs==0) dirs=15;

		int ucmb[16];

		int ucset[16];

		int posx = this->X;

		int posy = this->Y;

		if (Screen->isSolid(this->X+1, this->Y+1)){

			for (int i=0;i<16;i++){

				ucmb[i] = Screen->UnderCombo;

				ucset[i] = Screen->UnderCSet;

			}

		}

		else{

			for (int i=0;i<16;i++){

				ucmb[i] = CMB_JUMP_PUSHBLOCK_SOLID;

				ucset[i] = this->CSet;

			}

			JumpPushReplaceCombosUnderFFC(this, ucmb, ucset);

		}		

		int pushcounter = 0;

		this->InitD[7] = -1;

		int movecounter = 0;

		int jumpz = 0;

		for (int i=0;i<176;i++){

			if (ComboFI(i, CF_BLOCKTRIGGER))Screen->ComboF[i] = CF_BLOCKTRIGGER;

		}

		while(true){

			if (this->InitD[7]<0){

				if (JumpPushBlockIsPushed(this,Link->Dir, 6))pushcounter++;

				else pushcounter = 0;

				if (pushcounter>=12){

					if (JumpPushBlockCanBePushed(posx,posy,this->EffectWidth, this->EffectHeight, Link->Dir, weight, dirs)){

						this->InitD[7] = Link->Dir;

						Game->PlaySound(SFX_JUMP_PUSHBLOCK_MOVE);

						movecounter = 16;

						JumpPushReplaceCombosUnderFFC(this, ucmb, ucset);

					}

					else pushcounter = 0;

				}

			}

			else{

				NoAction();	

				if (movecounter>12) jumpz+=4;

				else if (movecounter>8) jumpz+=1;

				else if (movecounter>4) jumpz-=1;

				else jumpz-=4;

				if (this->InitD[7]==DIR_UP){

					for (int i=0;i<speed; i++){						

						if (!JumpPushBlockCanBePushed(posx,posy,this->EffectWidth, this->EffectHeight, DIR_UP, 0, 15)){

							this->InitD[7] = DIR_DOWN;

							//posy=GridY(posy+3);

							Game->PlaySound(SFX_JUMP_PUSHBLOCK_BOUNCE);

						}

						if (this->InitD[7]==DIR_UP) posy--;

						else posy ++;

						//Trace(posy);

					}

				}

				else if (this->InitD[7]==DIR_DOWN){

					for (int i=0;i<speed; i++){

						

						if (!JumpPushBlockCanBePushed(posx,posy,this->EffectWidth, this->EffectHeight, DIR_DOWN, 0, 15)){

							this->InitD[7] = DIR_UP;

							//posy=GridY(posy+3);

							Game->PlaySound(SFX_JUMP_PUSHBLOCK_BOUNCE);

						}

						if (this->InitD[7]==DIR_DOWN) posy++;

						else posy --;

						//Trace(posy);

					}

				}

				if (this->InitD[7]==DIR_LEFT){

					for (int i=0;i<speed; i++){

						

						if (!JumpPushBlockCanBePushed(posx,posy,this->EffectWidth, this->EffectHeight, DIR_LEFT, 0, 15)){

							this->InitD[7] = DIR_RIGHT;

							//posx=GridX(posx+3);

							Game->PlaySound(SFX_JUMP_PUSHBLOCK_BOUNCE);

						}

						if (this->InitD[7]==DIR_LEFT) posx--;

						else posx ++;

						//Trace(posx);

					}

				}

				 else if (this->InitD[7]==DIR_RIGHT){

					for (int i=0;i<speed; i++){

						

						if (!JumpPushBlockCanBePushed(posx,posy,this->EffectWidth, this->EffectHeight, DIR_RIGHT, 0, 15)){

							this->InitD[7] = DIR_LEFT;

							//posx=GridX(posx+3);

							Game->PlaySound(SFX_JUMP_PUSHBLOCK_BOUNCE);

						}

						if (this->InitD[7]==DIR_RIGHT) posx++;

						else posx --;

						//Trace(posx);

					}

				}

				this->X=posx;

				this->Y=posy-jumpz;

				//TraceNL();

				movecounter--;

				if (movecounter==0){

					pushcounter = 0;

					this->X=GridX(this->X+8);

					this->Y=GridY(this->Y+8);

					posx = this->X;

					posy = this->Y;

					if ((flags&1)>0){

						Game->PlaySound(SFX_JUMP_PUSHBLOCK_STUCK);

						dirs=0;

					}

					SolidObjects_Add(FFCNum(this), this->X, this->Y, this->EffectWidth, this->EffectHeight, 0, 0, 2);

					JumpPushReplaceCombosUnderFFC(this, ucmb, ucset);

					this->InitD[7]=-1;

					if ((flags&8)==0)JumpPushTriggerUpdate(this, ucset);

					if ((flags&2)>0 && this->InitD[6]>0){

						Game->PlaySound(SFX_JUMP_PUSHBLOCK_STUCK);

						dirs=0;

					}

				}

			}

			if (this->Data!=FFCS_INVISIBLE_COMBO && (flags&32)>0){

				if (this->InitD[7]>=0)this->Data=origdata+1;

				else this->Data=origdata;

			}

			if ((CMB_JUMP_PUSHBLOCK_SHADOW>0) && (jumpz>0))Screen->FastCombo(1, posx+(this->TileWidth-1)*8, posy+(this->TileHeight-1)*16, CMB_JUMP_PUSHBLOCK_SHADOW, CSET_JUMP_PUSHBLOCK_SHADOW, OP_TRANS);

			Waitframe();

		}

	}

}



//returns true, if Link tries to push this block

bool JumpPushBlockIsPushed(ffc this, int dir, int margin){

	if((Link->X == this->X - 16 && (CenterLinkY() < this->Y+this->EffectHeight - 8+margin && CenterLinkY() > this->Y - margin) && Link->InputRight && dir == DIR_RIGHT) || // Right

	(Link->X == this->X + this->EffectWidth && (CenterLinkY() < this->Y+this->EffectHeight - 8+margin && CenterLinkY() > this->Y - margin) && Link->InputLeft && dir == DIR_LEFT) || // Left

	(Link->Y == this->Y - 16 && (Link->X < (this->X + this->EffectWidth-16+margin) && Link->X > this->X - margin) && Link->InputDown && dir == DIR_DOWN) || // Down

	(Link->Y == this->Y + this->EffectHeight-8 && (Link->X < (this->X + this->EffectWidth-16+margin) && Link->X > this->X - margin) && Link->InputUp && dir == DIR_UP)) { // Up

		return true;

	}

	return false;

}



//Returns true, if block can be pushed in the given direction

bool JumpPushBlockCanBePushed(int x, int y, int sizex, int sizey, int dir, int weight, int dirs){

	if (dir==DIR_UP){

		if ((dirs&1)==0) return false;

	}

	if (dir==DIR_DOWN){

		if ((dirs&2)==0) return false;

	}

	if (dir==DIR_LEFT){

		if ((dirs&4)==0) return false;

	}

	if (dir==DIR_RIGHT){

		if ((dirs&8)==0) return false;

	}

	int br = GetHighestLevelItemOwned(IC_BRACELET);

	int power = 0;

	if (br>=0){

		itemdata it = Game->LoadItemData(br);

		power = it->Power;

	}

	if (power<weight) return false;

	int x1 = 0;

	int y1 = 0;

	int x2 = 0;

	int y2 = 0;

	if (dir==DIR_UP){

		x1 = x;

		y1 = y-1;

		x2 = x+sizex-1;

		y2 = y1;

	}

	if (dir==DIR_DOWN){

		x1 = x;

		y1 = y+sizey;

		x2 = x+sizex-1;

		y2 = y1;

	}

	if (dir==DIR_LEFT){

		x1 = x-1;

		y1 = y;

		x2 = x-1;

		y2 = y1+sizey-1;

	}

	if (dir==DIR_RIGHT){

		x1 = x+sizex;

		y1 = y;

		x2 = x1;

		y2 = y1+sizey-1;

	}

	for (int i=0;i<176;i++){

		int cx1 = ComboX(i);

		int cy1 = ComboY(i);

		int cx2 = cx1+15;

		int cy2 = cy1+15;

		if (!RectCollision(x1,y1,x2,y2,cx1,cy1,cx2,cy2))continue;

		if (ComboFI(i, CF_NOBLOCKS)) return false;

		if (Screen->ComboS[i]>0)return false;

		int comboS=0;

		if(Screen->LayerMap(1)>0) comboS |= GetLayerComboS(1, i);

		if(Screen->LayerMap(2)>0) comboS |= GetLayerComboS(2, i);

		if(comboS>0)return false;

	}

	return true;

}



//Stores and replaces combos under FFC to mimic solidity.

void JumpPushReplaceCombosUnderFFC(ffc this, int ucmb, int ucset){

	int x1 = this->X+1;

	int y1 = this->Y+1;

	int x2 = x1+this->EffectWidth-2;

	int y2 = y1+this->EffectHeight-2;

	int arr=0;

	for (int i=0;i<176;i++){

		int cx1 = ComboX(i);

		int cy1 = ComboY(i);

		int cx2 = cx1+15;

		int cy2 = cy1+15;

		if (!RectCollision(x1,y1,x2,y2,cx1,cy1,cx2,cy2))continue;

		int rcmb = Screen->ComboD[i];

		int rcset = Screen->ComboC[i];

		Screen->ComboD[i] = ucmb[arr];

		Screen->ComboC[i] = ucset[arr];

		ucmb[arr] = rcmb;

		ucset[arr]=rcset;

		arr++;

	}

}



//Checks, if all pushblocks are on triggers and triggers secrets, if it`s true;

void JumpPushTriggerUpdate(ffc f, int ucset){

	f->InitD[6]=1;

	for (int i=0;i<16;i++){

		int x = f->X+(i%4)*16;

		if (x>(f->X+f->EffectWidth-1)) continue;

		int y = f->Y+Floor(i/4)*16;

		if (y>(f->Y+f->EffectHeight-1)) continue;

		int cmb = ComboAt(x+1,y+1);

		if (!ComboFI(cmb, CF_BLOCKTRIGGER)) f->InitD[6]=0;

		if ((f->InitD[2]&16)>0 && ucset[i]!=f->CSet)f->InitD[6]=0;

	}

	int str[] = "JumpPushBlock";

	int scr = Game->GetFFCScript(str);

	for(int i=1;i<=33;i++){

		if (Screen->State[ST_SECRET]) break;

		if (i==33){

			Game->PlaySound(SFX_SECRET);

			Screen->TriggerSecrets();

			Screen->State[ST_SECRET]=true;

			break;

		}

		ffc n = Screen->LoadFFC(i);

		if (n->Script!=scr)continue;

		if ((n->InitD[2]&8)>0) continue;

		if (n->InitD[6] == 0) break;

	}

}



//Renderer for JumpPush blocks

//D0 - ID of pushblock FFC

ffc script JumpPushRender{

	void run (int ID){

		int origdata = this->Data;

		ffc f = Screen->LoadFFC(ID);

		while(true){

			if (Link->Y>=f->Y)this->Flags[FFCF_OVERLAY] =false;

			else this->Flags[FFCF_OVERLAY] =true;

			this->X = f->X;

			this->Y = f->Y + f->EffectHeight - f->TileHeight*16;

			if (((f->InitD[2])&32)>0 && f->InitD[7]>=0)this->Data = origdata+1;

			else this->Data = origdata;

			Waitframe();

		}

	}

}



global script DemonWallActive{

	void run(){

		StartGhostZH();

		Tango_Start();

		__classic_zh_InitScreenUpdating();

		LinkMovement_Init();

		SolidObjects_Init();

		while(true)	{

			SolidObjects_Update1();

			LinkMovement_Update1();

			UpdateGhostZH1();

			__classic_zh_UpdateScreenChange1();

			Tango_Update1();

			__classic_zh_do_z2_lantern();

			if ( __classic_zc_internal[__classic_zh_SCREENCHANGED] )

			{

				__classic_zh_CompassBeep();

				__classic_zh_ResetScreenChange();

			}

			Waitdraw();

			SolidObjects_Update2();

			LinkMovement_Update2();

			UpdateGhostZH2();

			Tango_Update2();

			Waitframe();

		}

	}

}