#include <common.h>
#include <game.h>
#include <g3dhax.h>
#include <sfx.h>
#include <stage.h>
#include "effects.h"
#include "player.h"

class daDreidel : public dEn_c {
	int onCreate();
	int onDelete();
	int onExecute();
	int onDraw();

	mHeapAllocator_c allocator;
	nw4r::g3d::ResFile resFile;

	m3d::mdl_c bodyModel;

	m3d::anmChr_c chrAnimation;

	int timer;
	int damage;
	char isDown;
	float XSpeed;
	u32 cmgr_returnValue;
	bool isBouncing;
	char isInSpace;
	char fromBehind;

	float dying;

	dEn_c *Kameck;

	static daDreidel *build();

	void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate);
	void updateModelMatrices();
	bool calculateTileCollisions();

	void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
	void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
	void yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);

	void collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther);
	bool collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);
	void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther);


	USING_STATES(daDreidel);
	DECLARE_STATE(Walk);
	DECLARE_STATE(Turn);
	DECLARE_STATE(KnockBack);

	DECLARE_STATE(ChargePrep);
	DECLARE_STATE(Charge);
	DECLARE_STATE(ChargeRecover);
	DECLARE_STATE(Damage);

	DECLARE_STATE(Grow);
	DECLARE_STATE(Outro);

};

daDreidel *daDreidel::build() {
	void *buffer = AllocFromGameHeap1(sizeof(daDreidel));
	return new(buffer) daDreidel;
}

///////////////////////
// Externs and States
///////////////////////
	extern "C" void *PlaySound(dStageActor_c *, int soundID);
	extern "C" void *PlaySoundAsync(dStageActor_c *, int soundID);
	extern "C" void *EN_LandbarrelPlayerCollision(dEn_c* t, ActivePhysics *apThis, ActivePhysics *apOther);

	extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer);
	extern "C" u8 dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(daDreidel *, Vec pos);
	extern "C" dStageActor_c *GetSpecificPlayerActor(int num);
// CalculateDistanceFromActorsNextPosToFurthestPlayer

	//FIXME make this dEn_c->used...
	extern "C" char usedForDeterminingStatePress_or_playerCollision(dEn_c* t, ActivePhysics *apThis, ActivePhysics *apOther, int unk1);
	extern "C" int SmoothRotation(short* rot, u16 amt, int unk2);

	extern "C" void *StopBGMMusic();
	extern "C" void *StartBGMMusic();

	extern "C" void *MakeMarioEnterDemoMode();
	extern "C" void *MakeMarioExitDemoMode();
	extern "C" void *UpdateGameMgr();

	CREATE_STATE(daDreidel, Walk);
	CREATE_STATE(daDreidel, Turn);
	CREATE_STATE(daDreidel, KnockBack);

	CREATE_STATE(daDreidel, ChargePrep);
	CREATE_STATE(daDreidel, Charge);
	CREATE_STATE(daDreidel, ChargeRecover);
	CREATE_STATE(daDreidel, Damage);

	CREATE_STATE(daDreidel, Grow);
	CREATE_STATE(daDreidel, Outro);

	// 	begoman_attack2"	// wobble back and forth tilted forwards
	// 	begoman_attack3"	// Leaned forward, antennae extended
	// 	begoman_damage"		// Bounces back slightly
	// 	begoman_damage2"	// Stops spinning and wobbles to the ground like a top
	// 	begoman_stand"		// Stands still, waiting
	// 	begoman_wait"		// Dizzily Wobbles
	// 	begoman_wait2"		// spins around just slightly
	// 	begoman_attack"		// Rocks backwards, and then attacks to an upright position, pulsing out his antennae


////////////////////////
// Collision Functions
////////////////////////

	void daDreidel::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
		if (apOther->owner->name == 250) { //time to get hurt
			this->damage += 1;
			doStateChange(&StateID_Damage);

			if (this->damage > 2) { doStateChange(&StateID_Outro); }
		}
		else { dEn_c::spriteCollision(apThis, apOther); }
	}

	void daDreidel::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {

		char hitType;
		hitType = usedForDeterminingStatePress_or_playerCollision(this, apThis, apOther, 0);

		if(hitType == 1) {	// regular jump
			this->_vf220(apOther->owner);
		} 
		else if(hitType == 3) {	// spinning jump or whatever?
			this->_vf220(apOther->owner);
		} 
		else if(hitType == 0) {
			EN_LandbarrelPlayerCollision(this, apThis, apOther);
			if (this->pos.x > apOther->owner->pos.x) {
				this->direction = 1;
			}
			else {
				this->direction = 0;
			}
			doStateChange(&StateID_KnockBack);
		} 

		// fix multiple player collisions via megazig
		this->isDead = 0;
		this->flags_4FC |= (1<<(31-7));
		if(apOther->owner->which_player < 4) {
			this->counter_504[apOther->owner->which_player] = 0;
		}
	}

	void daDreidel::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
		this->playerCollision(apThis, apOther);
	}

	void daDreidel::collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) {
		this->dEn_c::playerCollision(apThis, apOther);
		this->_vf220(apOther->owner);

		this->isDead = 0;
		this->flags_4FC |= (1<<(31-7));
		if(apOther->owner->which_player < 4) {
			this->counter_504[apOther->owner->which_player] = 0;
		}
	}

	void daDreidel::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) {
		this->collisionCatD_GroundPound(apThis, apOther);
	}

	void daDreidel::collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther) {
		this->collisionCatD_GroundPound(apThis, apOther);
	}

	void daDreidel::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) {
		doStateChange(&StateID_KnockBack);
	}

	void daDreidel::collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther){	}

	void daDreidel::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { }

	void daDreidel::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther){
		doStateChange(&StateID_KnockBack);
	}

	void daDreidel::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther){ }

	void daDreidel::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { }

	bool daDreidel::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { return true; }


bool daDreidel::calculateTileCollisions() {
	// Returns true if sprite should turn, false if not.

	HandleXSpeed();
	HandleYSpeed();
	doSpriteMovement();

	cmgr_returnValue = collMgr.CollidedWithTile();
	collMgr.execute();

	if (isBouncing) {
		stuffRelatingToCollisions(0.1875f, 1.0f, 0.5f);
		if (speed.y != 0.0f)
			isBouncing = false;
	}

	float xDelta = pos.x - last_pos.x;
	if (xDelta >= 0.0f)
		direction = 0;
	else
		direction = 1;

	if (collMgr.CollidedWithTile()) {
		// Walking into a tile branch

		if (cmgr_returnValue == 0)
			isBouncing = true;

		if (speed.x != 0.0f) {
			//playWmEnIronEffect();
		}

		speed.y = 0.0f;

		// u32 blah = collMgr.s_80070760();
		// u8 one = (blah & 0xFF);
		// static const float incs[5] = {0.00390625f, 0.0078125f, 0.015625f, 0.0234375f, 0.03125f};
		// x_speed_inc = incs[one];
		max_speed.x = (direction == 1) ? -1.0f : 1.0f;
	} else {
		x_speed_inc = 0.0f;
	}

	// Bouncing checks
	if (_34A & 4) {
		Vec v = (Vec){0.0f, 1.0f, 0.0f};
		collMgr.parent_speed_ptr = &v;

		if (collMgr.SomethingSemiImportant(collMgr.bitfield_for_checks))
			speed.y = 0.0f;

		collMgr.parent_speed_ptr = &speed;

	} else {
		if (collMgr.SomethingSemiImportant(collMgr.bitfield_for_checks))
			speed.y = 0.0f;
	}

	collMgr.s_8006FA40(0);

	// Switch Direction
	if (collMgr.bitfield_for_checks & (0x15 << direction)) {
		if (collMgr.CollidedWithTile()) {
			isBouncing = true;
		}
		return true;
	}
	return false;
}

void daDreidel::bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate) {
	nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr(name);
	this->chrAnimation.bind(&this->bodyModel, anmChr, unk);
	this->bodyModel.bindAnim(&this->chrAnimation, unk2);
	this->chrAnimation.setUpdateRate(rate);
}

int daDreidel::onCreate() {
	
	// Model creation	
	allocator.link(-1, GameHeaps[0], 0, 0x20);

	this->resFile.data = getResource("ben", "g3d/begoman_spike.brres");
	nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("begoman");
	bodyModel.setup(mdl, &allocator, 0x224, 1, 0);
	SetupTextures_Map(&bodyModel, 0);


	// Animations start here
	nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("begoman_wait");
	this->chrAnimation.setup(mdl, anmChr, &this->allocator, 0);

	allocator.unlink();

	// Stuff I do understand
	this->scale = (Vec){0.2, 0.2, 0.2};

	// this->pos.y = this->pos.y + 30.0; // X is vertical axis
	this->rot.x = 0; // X is vertical axis
	this->rot.y = 0xD800; // Y is horizontal axis
	this->rot.z = 0; // Z is ... an axis >.>
	this->direction = 1; // Heading left.
	
	this->speed.x = 0.0;
	this->speed.y = 0.0;
	this->max_speed.x = 0.8;
	this->x_speed_inc = 0.0;
	this->XSpeed = 0.8;

	this->isInSpace = this->settings & 0xF;
	this->fromBehind = 0;

	ActivePhysics::Info HitMeBaby;

	HitMeBaby.xDistToCenter = 0.0;
	HitMeBaby.yDistToCenter = 12.0;

	HitMeBaby.xDistToEdge = 14.0;
	HitMeBaby.yDistToEdge = 12.0;		

	HitMeBaby.category1 = 0x3;
	HitMeBaby.category2 = 0x0;
	HitMeBaby.bitfield1 = 0x4F;
	HitMeBaby.bitfield2 = 0xffbafffe;
	HitMeBaby.unkShort1C = 0;
	HitMeBaby.callback = &dEn_c::collisionCallback;

	OSReport("Making the Physics Class and adding to the list\n");
	this->aPhysics.initWithStruct(this, &HitMeBaby);
	this->aPhysics.addToList();


	// Tile collider
	OSReport("Making the Tile collider Class\n");

	// These fucking rects do something for the tile rect
	spriteSomeRectX = 28.0f;
	spriteSomeRectY = 32.0f;
	_320 = 0.0f;
	_324 = 16.0f;

	// These structs tell stupid collider what to collide with - these are from koopa troopa
	static const u8 one[16] = {0,0,0,1, 0,0,0xC0,0, 0,0,0x40,0, 0,0,0,0};
	static const u8 two[12] = {0,0,0,0, 0,0,0,0, 0,0,0xC0,0};
	static const u8 three[16] = {0,0,0,1, 0,0,0x60,0, 0,0,0x90,0, 0,0,0x60,0};

	collMgr.Init(this, one, two, three);
	collMgr.execute();

	cmgr_returnValue = collMgr.CollidedWithTile();

	if (collMgr.CollidedWithTile())
		isBouncing = false;
	else
		isBouncing = true;


	// State Changers
	bindAnimChr_and_setUpdateRate("begoman_wait2", 1, 0.0, 1.0); 
	doStateChange(&StateID_Grow);

	this->onExecute();
	return true;
}

int daDreidel::onDelete() {
	return true;
}

int daDreidel::onExecute() {
	acState.execute();
	updateModelMatrices();
	
	return true;
}

int daDreidel::onDraw() {
	bodyModel.scheduleForDrawing();
	bodyModel._vf1C();

	return true;
}

void daDreidel::updateModelMatrices() {
	matrix.translation(pos.x, pos.y - 2.0, pos.z);
	matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z);

	bodyModel.setDrawMatrix(matrix);
	bodyModel.setScale(&scale);
	bodyModel.calcWorld(false);
}



///////////////
// Grow State
///////////////
	void daDreidel::beginState_Grow() { 
		bindAnimChr_and_setUpdateRate("begoman_wait2", 1, 0.0, 0.75); 

		this->timer = 0;

		// Stop the BGM Music
		StopBGMMusic();

		// Set the necessary Flags and make Mario enter Demo Mode
		dStage32C_c::instance->freezeMarioBossFlag = 1;
		WLClass::instance->_4 = 4;
		WLClass::instance->_8 = 0;

		MakeMarioEnterDemoMode();

		// Make sure to use the correct position
		Vec pos = (Vec){this->pos.x - 124.0, this->pos.y + 104.0, 3564.0};
		S16Vec rot = (S16Vec){0, 0, 0};

		// Create And use Kameck
		Kameck = (daKameckDemo*)createChild(KAMECK_FOR_CASTLE_DEMO, (dStageActor_c*)this, 0, &pos, &rot, 0);
		Kameck->doStateChange(&daKameckDemo::StateID_DemoWait);
	}

	void daDreidel::executeState_Grow() { 
		
		if(this->chrAnimation.isAnimationDone()) {
			this->chrAnimation.setCurrentFrame(0.0);
		}

		this->timer = this->timer + 1;
		
		float scaleSpeed, yPosScaling;

		
		if ((this->timer > 150) && (this->timer < 230)) {

			scaleSpeed = 0.005;
			yPosScaling = 18;
		
			float modifier;

			modifier = 0.2 + ((this->timer - 150) * scaleSpeed);
			
			this->scale = (Vec){modifier, modifier, modifier};
			// this->pos.y = this->pos.y + (yPosScaling/80);
			
		}
		if (this->timer > 420) { 
			PlaySound(this, SE_EMY_MECHAKOOPA_BOUND);
			doStateChange(&StateID_Walk); 
		}

		if (this->timer == 130) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt); }
		if (this->timer == 150) { PlaySound(this, SE_BOSS_IGGY_WANWAN_TO_L); }
		if (this->timer == 400) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt2); }
		if (this->timer == 360) { 
			Vec tempPos = (Vec){this->pos.x - 40.0, this->pos.y + 120.0, 3564.0};
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 175);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 400);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 401);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 564);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 583);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 754);  // 400 & 401 // 564 // 583 // 754 // 958
			CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 958);  // 400 & 401 // 564 // 583 // 754 // 958
		}
	}
	void daDreidel::endState_Grow() { 
		// Clean up the flags and Kameck
		dStage32C_c::instance->freezeMarioBossFlag = 0;
		WLClass::instance->_8 = 1;

		MakeMarioExitDemoMode();
		StartBGMMusic();

		Kameck->Delete(1);
	}


///////////////
// Walk State
///////////////
	void daDreidel::beginState_Walk() {
		this->max_speed.x = (this->direction) ? -this->XSpeed : this->XSpeed;
		this->speed.x = (direction) ? -0.8f : 0.8f;

		this->max_speed.y = (this->isInSpace) ? -2.0 : -4.0;
		this->speed.y = 	(this->isInSpace) ? -2.0 : -4.0;
		this->y_speed_inc = (this->isInSpace) ? -0.09375 : -0.1875;
	}
	void daDreidel::executeState_Walk() { 

		PlaySound(this, SE_BOSS_JR_CROWN_JR_RIDE); // 5
	
		bool ret = calculateTileCollisions();
		if (ret) {
			doStateChange(&StateID_Turn);
		}

		if(this->chrAnimation.isAnimationDone()) {
			this->chrAnimation.setCurrentFrame(0.0);
		}
	}
	void daDreidel::endState_Walk() { this->timer += 1; }


///////////////
// Turn State
///////////////
	void daDreidel::beginState_Turn() {
		this->direction ^= 1;
		this->speed.x = 0.0;
	}
	void daDreidel::executeState_Turn() { 

		if(this->chrAnimation.isAnimationDone()) {
			this->chrAnimation.setCurrentFrame(0.0);
		}

		u16 amt = (this->direction == 0) ? 0x2800 : 0xD800;
		int done = SmoothRotation(&this->rot.y, amt, 0x800);

		if(done) {
			this->doStateChange(&StateID_Walk);
		}
	}
	void daDreidel::endState_Turn() { }


///////////////
// Knockback State
///////////////
	void daDreidel::beginState_KnockBack() {
		bindAnimChr_and_setUpdateRate("begoman_damage", 1, 0.0, 0.75); 

		this->max_speed.x = (this->direction) ? this->XSpeed*5.0 : -this->XSpeed*5.0;
		this->speed.x = (this->direction) ? 4.0f : -4.0f;
	}
	void daDreidel::executeState_KnockBack() { 

		bool ret = calculateTileCollisions();
		this->speed.x = this->speed.x / 1.1;

		bodyModel._vf1C();
		if(this->chrAnimation.isAnimationDone()) {
			doStateChange(&StateID_Walk); 
		}

	}
	void daDreidel::endState_KnockBack() { 
		if (this->rot.y == 0x2800) {
			// CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 175);
			this->direction = 0; 
		}
		else {
			// CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 192);
			this->direction = 1; 
		}
		// OSReport("Rotation: %x", this->rot.y);
		// OSReport("Direction: %d", this->direction);
		// this->direction ^= 1;
		bindAnimChr_and_setUpdateRate("begoman_wait2", 1, 0.0, 1.0); 
	}


///////////////
// ChargePrep State
///////////////
	void daDreidel::beginState_ChargePrep() {
		bindAnimChr_and_setUpdateRate("begoman_attack", 1, 0.0, 1.0); 
	}
	void daDreidel::executeState_ChargePrep() { 
		if(this->chrAnimation.isAnimationDone()) {
			doStateChange(&StateID_Charge);
		}
	}
	void daDreidel::endState_ChargePrep() { }


///////////////
// Charge State
///////////////
	void daDreidel::beginState_Charge() {
		bindAnimChr_and_setUpdateRate("begoman_attack3", 1, 0.0, 1.0); 
	}
	void daDreidel::executeState_Charge() { 
		if(this->chrAnimation.isAnimationDone()) {
			this->chrAnimation.setCurrentFrame(0.0);
		}
	}
	void daDreidel::endState_Charge() { }


///////////////
// ChargeRecover State
///////////////
	void daDreidel::beginState_ChargeRecover() {
		bindAnimChr_and_setUpdateRate("begoman_stand", 1, 0.0, 1.0); 
	}
	void daDreidel::executeState_ChargeRecover() { 
		if(this->chrAnimation.isAnimationDone()) {
			doStateChange(&StateID_ChargePrep);
		}
	}
	void daDreidel::endState_ChargeRecover() { }


///////////////
// Damage State
///////////////
	void daDreidel::beginState_Damage() {
		bindAnimChr_and_setUpdateRate("begoman_wait", 1, 0.0, 1.0); 
	}
	void daDreidel::executeState_Damage() { 
		if(this->chrAnimation.isAnimationDone()) {
			this->chrAnimation.setCurrentFrame(0.0);
		}
	}
	void daDreidel::endState_Damage() { }


///////////////
// Outro State
///////////////
	void daDreidel::beginState_Outro() { 

		WLClass::instance->_4 = 5;
		WLClass::instance->_8 = 0;

		this->removeMyActivePhysics();
		this->timer = 0;
		StopBGMMusic();

		dStage32C_c::instance->freezeMarioBossFlag = 1;

	}
	void daDreidel::executeState_Outro() {

		if (this->dying == 1) { 
			if (this->timer > 180) {
				ExitStage(WORLD_MAP, 0, BEAT_LEVEL, MARIO_WIPE);
			}
			
			if (this->timer == 60) {
				
				UpdateGameMgr();

				if (GetSpecificPlayerActor(0) != 0) {
					PlaySound(this, SE_VOC_MA_CLEAR_BOSS);
					// Send PlBase into DemoGoal State here, kthxbai
				}
				
				if (GetSpecificPlayerActor(1) != 0) {
					PlaySound(this, SE_VOC_LU_CLEAR_BOSS);
					// Send PlBase into DemoGoal State here, kthxbai
				}

				if (GetSpecificPlayerActor(2) != 0) {
					PlaySound(this, SE_VOC_KO_CLEAR_BOSS);
					// Send PlBase into DemoGoal State here, kthxbai
				}

				if (GetSpecificPlayerActor(3) != 0) {
					PlaySound(this, SE_VOC_KO2_CLEAR_BOSS);
					// Send PlBase into DemoGoal State here, kthxbai
				}
			}	
			
			this->timer += 1;
			return; 
		}	

		if (this->scale.x > 0.1) {

			PlaySound(this, SE_EMY_BUBBLE_EXTINCT);

			// Adjust this to equal the scale of your boss / 80.
			this->scale.x -= 0.0075;
			this->scale.y -= 0.0075;
			this->scale.z -= 0.0075;

			if (this->timer == 30) {  
				CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 756); 
				CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 801); 
				CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 957); 
				this->timer = 0;
			}

			this->timer += 1;
		}
		else {
			this->scale.x = 0.0;
			this->scale.y = 0.0;
			this->scale.z = 0.0;
			
			CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 588);
			this->dying = 1;
			this->timer = 0;

			PlaySound(this, STRM_BGM_SHIRO_BOSS_CLEAR);
			MakeMarioEnterDemoMode();
		}
	}
	void daDreidel::endState_Outro() { }