diff options
| -rw-r--r-- | bossTopman.yaml | 10 | ||||
| -rw-r--r-- | electricLine.yaml | 10 | ||||
| -rw-r--r-- | src/bossTopman.cpp | 708 | ||||
| -rw-r--r-- | src/electricLine.cpp | 144 | 
4 files changed, 872 insertions, 0 deletions
diff --git a/bossTopman.yaml b/bossTopman.yaml new file mode 100644 index 0000000..94ab3ac --- /dev/null +++ b/bossTopman.yaml @@ -0,0 +1,10 @@ +--- +# Replaces Slow_Quick_Tag + +source_files: [../src/bossTopman.cpp] +hooks: +  - name: BossTopmanBuild +    type: add_func_pointer +    src_addr_pal: 0x8095D018 +    target_func: 'daDreidel::build(void)' + diff --git a/electricLine.yaml b/electricLine.yaml new file mode 100644 index 0000000..3b9e856 --- /dev/null +++ b/electricLine.yaml @@ -0,0 +1,10 @@ +--- +# Replaces Ship_Window + +source_files: [../src/electricLine.cpp] +hooks: +  - name: electricLineBuild +    type: add_func_pointer +    src_addr_pal: 0x809622F8 +    target_func: 'daElectricLine::build(void)' + diff --git a/src/bossTopman.cpp b/src/bossTopman.cpp new file mode 100644 index 0000000..a52c66b --- /dev/null +++ b/src/bossTopman.cpp @@ -0,0 +1,708 @@ +#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() { } diff --git a/src/electricLine.cpp b/src/electricLine.cpp new file mode 100644 index 0000000..28822f1 --- /dev/null +++ b/src/electricLine.cpp @@ -0,0 +1,144 @@ +#include <common.h> +#include <game.h> +#include <g3dhax.h> +#include <sfx.h> +#include <stage.h> +#include "effects.h" +#include "player.h" + +class daElectricLine : public dEn_c { +	int onCreate(); +	int onDelete(); +	int onExecute(); +	int onDraw(); + +	mHeapAllocator_c allocator; +	nw4r::g3d::ResFile resFile; + +	dEn_c *Needles; +	u32 delay; +	u32 timer; +	char loops; + +	static daElectricLine *build(); + +	USING_STATES(daElectricLine); +	DECLARE_STATE(Activate); +	DECLARE_STATE(Deactivate); +	DECLARE_STATE(Die); +}; + +daElectricLine *daElectricLine::build() { +	void *buffer = AllocFromGameHeap1(sizeof(daElectricLine)); +	return new(buffer) daElectricLine; +} + +/////////////////////// +// Externs and States +/////////////////////// +	extern "C" void *PlaySound(dStageActor_c *, int soundID); +	extern "C" void *PlaySoundAsync(dStageActor_c *, int soundID); + +	extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer); + + +	CREATE_STATE(daElectricLine, Activate); +	CREATE_STATE(daElectricLine, Deactivate); +	CREATE_STATE(daElectricLine, Die); + + + +int daElectricLine::onCreate() { + +	Vec temppos = this->pos; +	temppos.x += 24.0; + +	// Settings for rotation: 0 = facing right, 1 = facing left, 2 = facing up, 3 = facing down +	char settings = 0; +	if (this->settings & 0x1) { +		settings = 1; +		temppos.x -= 32.0; +	} + + +	Needles = (daNeedles*)create(NEEDLE_FOR_KOOPA_JR_B, settings, &temppos, &this->rot, 0); +	Needles->doStateChange(&daNeedles::StateID_DemoWait); +	 +	// Delay in 1/6ths of a second +	this->delay = (this->settings >> 16) * 10; +	this->loops = (this->settings >> 4); + +	// State Changers +	doStateChange(&StateID_Activate); + +	this->onExecute(); +	return true; +} + +int daElectricLine::onDelete() { +	return true; +} + +int daElectricLine::onExecute() { +	acState.execute();	 +	return true; +} + +int daElectricLine::onDraw() { +	return true; +} + + +// States: +// +// DemoWait - all nullsubs, does nothing +// DemoAwake - moves the spikes in their respective directions +// Idle - Fires off an infinity of effects for some reason. +// Die - removes physics, then nullsubs + + +/////////////// +// Activate State +/////////////// +	void daElectricLine::beginState_Activate() {  +		this->timer = this->delay; +		Needles->doStateChange(&daNeedles::StateID_Idle); +	} +	void daElectricLine::executeState_Activate() {  +		if (this->loops) { +			this->timer--; +			if (this->timer == 0) { +				this->loops += 1; +				doStateChange(&StateID_Deactivate); +			} +		} +	} +	void daElectricLine::endState_Activate() { } + +/////////////// +// Deactivate State +/////////////// +	void daElectricLine::beginState_Deactivate() {  +		this->timer = this->delay;  +		Needles->removeMyActivePhysics(); +		Needles->doStateChange(&daNeedles::StateID_DemoWait); +	} +	void daElectricLine::executeState_Deactivate() {  + +		this->timer--; +		if (this->timer == 0) { +			doStateChange(&StateID_Activate); +		} +	} +	void daElectricLine::endState_Deactivate() {  +		Needles->addMyActivePhysics(); +	} + + +/////////////// +// Die State +/////////////// +	void daElectricLine::beginState_Die() { Needles->doStateChange(&daNeedles::StateID_Die); } +	void daElectricLine::executeState_Die() { } +	void daElectricLine::endState_Die() { } +  | 
