diff options
Diffstat (limited to '')
| -rw-r--r-- | bossCaptainBowser.yaml | 11 | ||||
| -rw-r--r-- | kamek_pal.x | 4 | ||||
| -rw-r--r-- | src/bossCaptainBowser.cpp | 554 | ||||
| -rw-r--r-- | src/bossKoopaThrow.cpp | 31 | ||||
| -rw-r--r-- | src/bossPlayerClown.S | 46 | ||||
| -rw-r--r-- | src/bossPlayerClown.cpp | 59 | 
6 files changed, 514 insertions, 191 deletions
| diff --git a/bossCaptainBowser.yaml b/bossCaptainBowser.yaml index 14c09fa..354d0dd 100644 --- a/bossCaptainBowser.yaml +++ b/bossCaptainBowser.yaml @@ -4,7 +4,7 @@  # KoopaThrow = WM_ANCHOR  # FlameThrower = WM_ANTLION -source_files: [../src/bossPlayerClown.cpp, ../src/bossCaptainBowser.cpp, ../src/bossKoopaThrow.cpp, ../src/bossFlameThrower.cpp] +source_files: [../src/bossPlayerClown.cpp, ../src/bossPlayerClown.S, ../src/bossCaptainBowser.cpp, ../src/bossKoopaThrow.cpp, ../src/bossFlameThrower.cpp]  hooks: @@ -144,7 +144,16 @@ hooks:    #   src_addr_pal: 0x8095FFDC    #   target_func: 'CCSpriteCollision(dEn_c *, ActivePhysics *, ActivePhysics *)' +  - name: ClownCarDetectAdjacents +    type: branch_insn +    branch_type: b +    src_addr_pal: 0x80812100 +    target_func: 'ClownCarDetectAdjacents' +  - name: ClownCarPlayAccelSound +    type: add_func_pointer +    src_addr_pal: 0x80960298 +    target_func: 'JrClownForPlayer_playAccelSound' diff --git a/kamek_pal.x b/kamek_pal.x index 7e91ce8..a60f608 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -98,6 +98,7 @@ SECTIONS {  	PClownCarAfterCreate = 0x800951D0;  	PClownCarDraw = 0x80810B90;  	PClownCarMove = 0x80811E70; +	ContinueFromClownCarDetectAdjacent = 0x80812104;  	sAllocatorFunc__FrmHeap = 0x8042E5B0; @@ -1706,6 +1707,9 @@ SECTIONS {  	instance__7StageE4 = 0x8042A020;  	killAllEnemiesAtLevelEnd__7StageE4Fi = 0x80066A40; +	JrClownEndDemoState = 0x80999988; +	JrClownDemoWaitState = 0x80999884; +	ClownDemoWaitState = 0x803580DC;  	.text : {  		FILL (0) diff --git a/src/bossCaptainBowser.cpp b/src/bossCaptainBowser.cpp index cb076c6..5eb8ac7 100644 --- a/src/bossCaptainBowser.cpp +++ b/src/bossCaptainBowser.cpp @@ -45,6 +45,7 @@ public:  	int onDelete();  	int onExecute();  	int onDraw(); +	int afterExecute(int param);  	mHeapAllocator_c allocator;  	nw4r::g3d::ResFile resFile; @@ -56,9 +57,10 @@ public:  	m3d::anmChr_c chrAnimation;  	m3d::anmChr_c shipAnm; -	static const int SHIP_COLL_COUNT = 7; -	ActivePhysics shipCollisions[SHIP_COLL_COUNT]; -	ActivePhysics Roar; +	nw4r::snd::SoundHandle prplSound; + +	static const int SHIP_SCOLL_COUNT = 7; +	Physics shipSColls[SHIP_SCOLL_COUNT];  	mEf::es2 effect;  	mEf::es2 shipDmgA; @@ -67,23 +69,49 @@ public:  	mEf::es2 shipDmgD;  	mEf::es2 shipDmgE; +	mEf::es2 flamethrowerEffect; +	mEf::es2 flamethrowerEffectInd; + +	nw4r::g3d::ResFile flamethrowerRF; +	m3d::mdl_c flamethrowerModel; +	m3d::anmTexSrt_c flamethrowerAnim; +	bool renderFlamethrowerModel; +	ActivePhysics flameCollision; + +#define flameOffsetX -160.0f +#define flameOffsetY 150.0f +#define flameZ 1900.0f +	Vec flameScale; +  	char isAngry;  	char isInvulnerable;  	char isIntro; -	float scaleIncreaser; -	int homingBillCountdown; -	int homingBillSlot;  	int maxDamage;  	int playerCount; -	float sinTimer;  	float roarLen; +	float bowserX, bowserY; +	s16 bowserRotX, bowserRotY; +	float bowserXSpeed, bowserYSpeed, bowserMaxYSpeed, bowserYAccel; + +	s16 shipRotY; +	float sinTimerX; +	float sinTimerY; +	bool sinTimerXRunning, sinTimerYRunning, stopMoving; + +	bool wereEntirelyDone; +	float explosionBottomBound; + +	bool deathSequenceRunning; +	void initiateDeathSequence(); +  	static daCaptainBowser *build();  	void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate);  	void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);  	void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther); +	bool collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);  	void addScoreWhenHit(void *other); @@ -96,6 +124,7 @@ public:  	DECLARE_STATE(Damage);  	DECLARE_STATE(Intro); +	DECLARE_STATE(FinalAttack);  	DECLARE_STATE(Outro);  }; @@ -118,6 +147,7 @@ daCaptainBowser *daCaptainBowser::build() {  	CREATE_STATE(daCaptainBowser, Damage);  	CREATE_STATE(daCaptainBowser, Intro); +	CREATE_STATE(daCaptainBowser, FinalAttack);  	CREATE_STATE(daCaptainBowser, Outro); @@ -125,50 +155,37 @@ daCaptainBowser *daCaptainBowser::build() {  ////////////////////////  // Collision Functions  //////////////////////// -	void daCaptainBowser::addScoreWhenHit(void *other) { }; +void daCaptainBowser::addScoreWhenHit(void *other) { }; -	void daCaptainBowser::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { -		if (apOther->owner->name == 657) { //time to get hurt -			if (this->isInvulnerable) { -				return; -			} -			this->damage -= 1; - -			spawnHitEffectAtPosition((Vec2){apOther->owner->pos.x, apOther->owner->pos.y});		 -				 -			SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); -			PlaySound(apOther->owner, SE_BOSS_CMN_STOMPED); -			apOther->owner->Delete(1); +bool daCaptainBowser::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { +	apOther->owner->kill(); +	SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); +	apThis->someFlagByte |= 2; +	return true; +} -			if (this->damage == this->maxDamage/2) 	{ doStateChange(&StateID_Roar); } -			else if (this->damage < 0)  			{ doStateChange(&StateID_Outro); } -			else 									{ doStateChange(&StateID_Damage); } +void daCaptainBowser::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { +	if (apOther->owner->name == WM_PAKKUN) { //time to get hurt +		if (this->isInvulnerable) { +			return;  		} -	} +		this->damage -= 1; -	void ShipAPhysicsCallback(ActivePhysics *apThis, ActivePhysics *apOther) { -		daCaptainBowser *self = (daCaptainBowser*)apThis->owner; -		if (apOther->owner->name == 657) { -			OSReport("CANNON COLLISION"); -			if (self->isInvulnerable) { -				return; -			} -			self->damage -= 1; +		spawnHitEffectAtPosition((Vec2){apOther->owner->pos.x, apOther->owner->pos.y});		 -			SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); -			PlaySound(apOther->owner, SE_OBJ_TARU_BREAK); -			apOther->owner->Delete(1); +		SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); +		PlaySound(apOther->owner, SE_BOSS_CMN_STOMPED); +		apOther->owner->Delete(1); -			if (self->damage == self->maxDamage/2) 	{ self->doStateChange(&daCaptainBowser::StateID_Roar); } -			else if (self->damage < 0) 				{ self->doStateChange(&daCaptainBowser::StateID_Outro); } -			 -			apThis->someFlagByte |= 2; -		} +		if (this->damage == this->maxDamage/2) 	{ doStateChange(&StateID_Roar); } +		else if (this->damage < 0)  			{ initiateDeathSequence(); } +		else 									{ doStateChange(&StateID_Damage); }  	} +} -	void daCaptainBowser::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { -		DamagePlayer(this, apThis, apOther); -	} +void daCaptainBowser::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { +	DamagePlayer(this, apThis, apOther); +} @@ -180,6 +197,13 @@ void daCaptainBowser::bindAnimChr_and_setUpdateRate(const char* name, int unk, f  }  int daCaptainBowser::onCreate() { +	bowserX = -148.0f; +	bowserY = 122.0f; +	bowserRotY = 0xD800; + +	shipRotY = 0x4000; +	sinTimerXRunning = true; +	sinTimerYRunning = true;  	// Model creation	  	allocator.link(-1, GameHeaps[0], 0, 0x20); @@ -206,6 +230,20 @@ int daCaptainBowser::onCreate() {  	this->shipModel.bindAnim(&this->shipAnm, 0.0);  	this->shipAnm.setUpdateRate(1.0); +	// Flamethrower +	flamethrowerRF.data = getResource("fire_cannon", "g3d/flame_koopa.brres"); + +	nw4r::g3d::ResMdl ftResMdl = flamethrowerRF.GetResMdl("fire_effect1x6_right"); +	nw4r::g3d::ResAnmTexSrt ftResAnm = flamethrowerRF.GetResAnmTexSrt("fire_effect1x6_right"); + +	flamethrowerModel.setup(ftResMdl, &allocator, 0x224, 1, 0); +	SetupTextures_MapObj(&flamethrowerModel, 0); + +	flamethrowerAnim.setup(ftResMdl, ftResAnm, &allocator, 0, 1); +	flamethrowerAnim.bindEntry(&flamethrowerModel, ftResAnm, 0, 0); +	flamethrowerModel.bindAnim(&flamethrowerAnim, 0.0f); +	flamethrowerAnim.setFrameForEntry(0.0f, 0); +	flamethrowerAnim.setUpdateRate(1.0f);  	allocator.unlink(); @@ -215,47 +253,20 @@ int daCaptainBowser::onCreate() {  	pos.z = 8000.0;  	this->scale = (Vec){0.57, 0.57, 0.57}; -	this->homingBillCountdown = 270; -	this->homingBillSlot = 0;	  	this->damage = this->maxDamage; - -	for (int i = 0; i < SHIP_COLL_COUNT; i++) { -		shipCollisions[i].owner = this; -		shipCollisions[i].info.category1 = 3; -		shipCollisions[i].info.category2 = 0; -		shipCollisions[i].info.bitfield1 = 0x4F; -		shipCollisions[i].info.bitfield2 = 0x8028E; -		shipCollisions[i].info.unkShort1C = 0; -		shipCollisions[i].info.callback = &ShipAPhysicsCallback; -	} - -	static const float xToCentres[] = {-56.541185, 161.824968, 106.258581}; -	static const float yToCentres[] = {-91.176745, -66.957921, 57.935231}; -	static const float xToEdges[] = {39.481380, 11.698187, 24.371222}; -	static const float yToEdges[] = {37.040555, 12.821730, 21.844430}; -	static const float trpValues0[] = {-39.481380, -11.698187, -24.371222}; -	static const float trpValues1[] = {-39.481380, -11.698187, 24.371222}; -	static const float trpValues2[] = {-39.481380, -11.698187, -24.371222}; -	static const float trpValues3[] = {39.481380, 11.698187, -24.371222}; -	static const float scX1[] = {-176.447600, 64.340078, -157.925471, -157.925471}; -	static const float scY1[] = {-128.217300, 112.570378, -109.695171, -109.695171}; -	static const float scX2[] = {-176.447600, 64.340078, -157.925471, -157.925471}; -	static const float scY2[] = {-128.217300, 112.570378, -109.695171, -109.695171}; - -	for (int i = 0; i < SHIP_COLL_COUNT; i++) { -		shipCollisions[i].info.xDistToCenter = xToCentres[i]; -		shipCollisions[i].info.yDistToCenter = yToCentres[i]; -		shipCollisions[i].info.xDistToEdge = xToEdges[i]; -		shipCollisions[i].info.yDistToEdge = yToEdges[i]; -		if (i >= 4) { -			int xi = i - 4; -			shipCollisions[i].trpValue0 = trpValues0[xi]; -			shipCollisions[i].trpValue1 = trpValues1[xi]; -			shipCollisions[i].trpValue2 = trpValues2[xi]; -			shipCollisions[i].trpValue3 = trpValues3[xi]; -			shipCollisions[i].collisionCheckType = 3; -		} +	static const float scX1[] = {-176.447600, 64.340078, -157.925471, -157.925471, -158.561530, 49.742932, 48.957043}; +	static const float scY1[] = {128.217300, 86.427956, 54.136191, -36.090801, 22.765115, 162.568398, 66.849169}; +	static const float scX2[] = {-96.022566, 150.126781, 173.523155, 81.887358, -50.343171, 84.419332, 117.889270}; +	static const float scY2[] = {54.136191, 54.136191, -36.090801, -79.779661, -26.166291, 142.846802, -2.083058}; +	static s16 sRots[] = {-8192, -8192, -8192}; + +	for (int i = 0; i < SHIP_SCOLL_COUNT; i++) { +		shipSColls[i].setup(this, +				scX1[i], scY1[i], scX2[i], scY2[i], +				0, 0, 0, 1, 0); +		if (i >= 4) +			shipSColls[i].setPtrToRotation(&sRots[i - 4]);  	}  	// Bowser Physics! @@ -263,8 +274,8 @@ int daCaptainBowser::onCreate() {  	BowserPhysics.xDistToCenter = -152.0;  	BowserPhysics.yDistToCenter = 152.0; -	BowserPhysics.xDistToEdge = 38.0; -	BowserPhysics.yDistToEdge = 38.0; +	BowserPhysics.xDistToEdge = 28.0; +	BowserPhysics.yDistToEdge = 26.0;  	BowserPhysics.category1 = 0x3;  	BowserPhysics.category2 = 0x0; @@ -277,90 +288,64 @@ int daCaptainBowser::onCreate() { -	// Roar Physics! -	ActivePhysics::Info RoarStruct; -	RoarStruct.xDistToCenter = -186.0; -	RoarStruct.yDistToCenter = 138.0; - -	RoarStruct.xDistToEdge = 20.0; -	RoarStruct.yDistToEdge = 20.0; - -	RoarStruct.category1 = 0x3; -	RoarStruct.category2 = 0x0; -	RoarStruct.bitfield1 = 0x4F; -	RoarStruct.bitfield2 = 0x8028E; -	RoarStruct.unkShort1C = 0; -	RoarStruct.callback = &dEn_c::collisionCallback; - -	this->Roar.initWithStruct(this, &RoarStruct); - -  	// State Changers  	this->isIntro = 3;  	doStateChange(&StateID_Intro); +	// THIS IS FOR TESTING!!! +	damage = 0; +  	return true;  }  int daCaptainBowser::onDelete() { +	prplSound.Stop(0);  	return true;  } +int daCaptainBowser::afterExecute(int param) { +	return dEn_c::afterExecute(param); +} +  int daCaptainBowser::onExecute() {  	acState.execute(); -	PlaySound(this, SE_BOSS_SHIP_PRPL); +	if (!prplSound.Exists() && acState.getCurrentState() != &StateID_Outro) { +		PlaySoundWithFunctionB4(SoundRelatedClass, &prplSound, SE_BOSS_SHIP_PRPL, 1); +	} + +	aPhysics.info.xDistToCenter = bowserX; +	aPhysics.info.yDistToCenter = bowserY + 28.0f;  	bodyModel._vf1C();  	shipModel._vf1C(); -	if(this->isIntro == 0) { +	for (int i = 0; i < SHIP_SCOLL_COUNT; i++) +		shipSColls[i].update(); -		float xmod = sin(this->sinTimer * 3.14 / 180.0) * 60.0; -		float ymod = sin(this->sinTimer * 3.14 / 130.0) * 84.0; +	float xmod = sinTimerXRunning ? (sin(this->sinTimerX * 3.14 / 180.0) * 60.0) : 0.0f; +	float ymod = sin(this->sinTimerY * 3.14 / 130.0) * (sinTimerYRunning ? 84.0 : 10.0); +	if(this->isIntro == 0) {  		pos.x = ClassWithCameraInfo::instance->screenCentreX + 200.0 + xmod;  		pos.y = ClassWithCameraInfo::instance->screenCentreY - 180.0 + ymod; -		this->sinTimer++; +		sinTimerX++; +		if (sinTimerX >= 360) { +			sinTimerX = 0; +			if (stopMoving) +				sinTimerXRunning = false; +		} + +		sinTimerY++; +		if (sinTimerY >= 260) { +			sinTimerY = 0; +			if (stopMoving) +				sinTimerYRunning = false; +		}  	} -		// this->homingBillCountdown--; -		 -		// if (this->homingBillCountdown == 0) { -			 -		// 	Vec tempPos; - -		// 	switch (this->homingBillSlot) { -		// 		case 0: -		// 			this->homingBillSlot++;	 -		// 			tempPos.x = this->pos.x - 26.0; -		// 			tempPos.y = this->pos.y + 40.0; -		// 			tempPos.z = this->pos.z + 2000.0; -		// 			break; - -		// 		case 1: -		// 			this->homingBillSlot++;	 -		// 			tempPos.x = this->pos.x + 22.0; -		// 			tempPos.y = this->pos.y + 40.0; -		// 			tempPos.z = this->pos.z + 2000.0; -		// 			break; - -		// 		case 2: -		// 	 		this->homingBillSlot = 0;	 -		// 			tempPos.x = this->pos.x + 70.0; -		// 			tempPos.y = this->pos.y + 40.0; -		// 			tempPos.z = this->pos.z + 2000.0; -		// 			break; -		// 	} - -		// 	SpawnEffect("Wm_en_killervanish", 0, &tempPos, &(S16Vec){0,0,0}, &(Vec){0.1, 0.1, 0.1}); -		// 	PlaySoundAsync(this, SE_EMY_SR_KILLER_SHOT); -		// 	CreateActor(EN_SEARCH_KILLER, 0, tempPos, 0, 0); - -		// 	this->homingBillCountdown = (isAngry) ? 90: 180; -		// } - -	if(this->shipAnm.isAnimationDone()) { + +	if(this->shipAnm.isAnimationDone() && acState.getCurrentState() != &StateID_Outro) {  		this->shipAnm.setCurrentFrame(0.0);  	} @@ -371,9 +356,8 @@ int daCaptainBowser::onDraw() {  	if(this->isIntro > 2) { return false; } -	matrix.translation(pos.x-146.0, pos.y+122.0, pos.z-200.0); // 136.0 is the bottom of the platform footing -	short newrot = rot.y + 0xD800; -	matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z); +	matrix.translation(pos.x+bowserX, pos.y+bowserY, pos.z-200.0); // 136.0 is the bottom of the platform footing +	matrix.applyRotationYXZ(&bowserRotX, &bowserRotY, &rot.z);  	bodyModel.setDrawMatrix(matrix);  	bodyModel.setScale(&(Vec){1.0, 1.0, 1.0}); @@ -383,8 +367,7 @@ int daCaptainBowser::onDraw() {  	matrix.translation(pos.x, pos.y, pos.z); -	newrot = rot.y + 0x4000; -	matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z); +	matrix.applyRotationYXZ(&rot.x, &shipRotY, &rot.z);  	shipModel.setDrawMatrix(matrix);  	shipModel.setScale(&scale); @@ -392,6 +375,18 @@ int daCaptainBowser::onDraw() {  	shipModel.scheduleForDrawing(); +	if (renderFlamethrowerModel) { +		matrix.translation(pos.x + flameOffsetX, pos.y + flameOffsetY, flameZ); +		s16 thing = 0x8000; +		matrix.applyRotationZ(&thing); + +		flamethrowerModel.setDrawMatrix(matrix); +		flamethrowerModel.setScale(&flameScale); +		flamethrowerModel.calcWorld(false); + +		flamethrowerModel.scheduleForDrawing(); +	} +  	return true;  } @@ -430,10 +425,17 @@ int daCaptainBowser::onDraw() {  		}  		// Bowser Flies In -		if (this->timer == 422) { this->isIntro = 2; } -		if ((this->timer > 420) && (this->timer < (420 + roarLen))) { -			pos.x = ClassWithCameraInfo::instance->screenCentreX + ((this->timer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0); -			pos.y = ClassWithCameraInfo::instance->screenCentreY - 380.0 + ((this->timer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0); +		if (this->timer == 422) { +			this->isIntro = 2; + +			for (int i = 0; i < SHIP_SCOLL_COUNT; i++) +				shipSColls[i].addToList(); +		} + +		if (this->timer > 420) { +			int effectiveTimer = min(timer, 719U); +			pos.x = ClassWithCameraInfo::instance->screenCentreX + ((effectiveTimer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0); +			pos.y = ClassWithCameraInfo::instance->screenCentreY - 380.0 + ((effectiveTimer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0);  		}  		// Bowser does a shitty roar @@ -457,8 +459,6 @@ int daCaptainBowser::onDraw() {  	}  	void daCaptainBowser::endState_Intro() {  -		for (int i = 0; i < SHIP_COLL_COUNT; i++) -			shipCollisions[i].addToList();  		this->aPhysics.addToList();	  		this->isInvulnerable = 0; @@ -507,12 +507,12 @@ int daCaptainBowser::onDraw() {  		if (this->chrAnimation.getCurrentFrame() == 60.0) { // throw back  			int num = GenerateRandomNumber(4); -			CreateActor(0x29F, 0x101 + ((num + 1) * 0x10), (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0); +			CreateActor(0x29F, 0x101 + ((num + 1) * 0x10), (Vec){pos.x+bowserX, pos.y+bowserY, pos.z}, 0, 0);  		}  		if (this->chrAnimation.getCurrentFrame() == 126.0) { // throw front  			int num = GenerateRandomNumber(4); -			CreateActor(0x29F, ((num + 1) * 0x10) + 1, (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0); +			CreateActor(0x29F, ((num + 1) * 0x10) + 1, (Vec){pos.x+bowserX, pos.y+bowserY, pos.z}, 0, 0);  		}  		if (this->chrAnimation.isAnimationDone()) {  @@ -573,39 +573,26 @@ int daCaptainBowser::onDraw() {  		bindAnimChr_and_setUpdateRate("kp_roar3", 1, 0.0, 1.0);   		this->isInvulnerable = 1;  		this->timer = 0; -		this->scaleIncreaser = 0.5; - -		// this->Roar.info.xDistToEdge = 70.0 * scaleIncreaser; -		// this->Roar.info.yDistToEdge = 70.0 * scaleIncreaser; - -		// this->Roar.addToList();	  	}  	void daCaptainBowser::executeState_Roar() {   		if (this->chrAnimation.getCurrentFrame() == 53.0) { // This is where the smackdown starts -			PlaySound(this, SE_VOC_KP_L_SHOUT); +			nw4r::snd::SoundHandle handle; +			PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_L_SHOUT, 1);  		}  		if (this->chrAnimation.getCurrentFrame() > 53.0) { // This is where the smackdown starts -			scaleIncreaser += 0.014285; -			effect.spawn("Wm_ko_shout", 0, &(Vec){pos.x-186.0+(scaleIncreaser*16.0), pos.y+138.0+(scaleIncreaser*16.0), pos.z}, &(S16Vec){0,0,0x7000}, &(Vec){scaleIncreaser, scaleIncreaser, scaleIncreaser}); - -			// this->Roar.info.xDistToEdge = 70.0 * scaleIncreaser; -			// this->Roar.info.yDistToEdge = 70.0 * scaleIncreaser; +			effect.spawn("Wm_ko_shout", 0, &(Vec){pos.x-174.0, pos.y+140.0, pos.z}, &(S16Vec){0,0,0x7000}, &(Vec){1.0, 1.0, 1.0});  		} -		// if (this->chrAnimation.getCurrentFrame() == 197.0) { // This is where the smackdown ends -		// 	this->Roar.removeFromList();	 -		// } -  		if (this->chrAnimation.isAnimationDone()) {  -			doStateChange(&StateID_Wait);  +			doStateChange(deathSequenceRunning ? &StateID_FinalAttack : &StateID_Wait);   		}  	}  	void daCaptainBowser::endState_Roar() {   		this->isInvulnerable = 0; -		this->isAngry = 1;		 +		this->isAngry = 1;  	} @@ -633,10 +620,221 @@ int daCaptainBowser::onDraw() {  //////////////////  // State Outro  ////////////////// -	void daCaptainBowser::beginState_Outro() { +void daCaptainBowser::initiateDeathSequence() { +	deathSequenceRunning = true; +	stopMoving = true; + +	StopBGMMusic(); +	dFlagMgr_c::instance->set(31, 0, false, false, false); +	*((u32*)(((char*)dBgGm_c::instance) + 0x900F0)) = 999; + +	doStateChange(&StateID_Roar); +} + +void daCaptainBowser::beginState_FinalAttack() { +	isInvulnerable = true; + +	bindAnimChr_and_setUpdateRate("mastfail", 1, 0.0, 1.0f);  + +	timer = 0; +	flameScale.x = flameScale.y = flameScale.z = 0.0f; +} + +void daCaptainBowser::executeState_FinalAttack() { +	timer++; + +	if (timer == 56) { +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_JR_CHARGE, 1); +		handle.SetPitch(0.25f); +	} else if (timer == 185) { +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_SHOUT, 1); +	} else if (timer == 348) { +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_EMY_BIG_PAKKUN_DAMAGE_1, 1); +	} + +	if (timer > 204 && timer < 315) { +		if (timer == 205) { +			// First thing +			renderFlamethrowerModel = true; + +			static const ActivePhysics::Info fcInfo = { +				0.0f, 0.0f, 0.0f, 0.0f, // placeholder +				3, 0, 0x4F, 0x8028E, 0, +				&dEn_c::collisionCallback +			}; +			flameCollision.initWithStruct(this, &fcInfo); +			flameCollision.addToList(); +		} +		if (timer < 289) { +			if (flameScale.y < 2.0f) { +				flameScale.y = flameScale.y = flameScale.z = flameScale.y + 0.1f; +			} else { +				flameScale.y = flameScale.y = flameScale.z = 2.5f; +			} +		} +		flameScale.x = flameScale.y * 1.5f; + +		flameCollision.info.xDistToCenter = flameOffsetX - (48.0f * flameScale.x); +		flameCollision.info.yDistToCenter = flameOffsetY; +		flameCollision.info.xDistToEdge = 48.0f * flameScale.x; +		flameCollision.info.yDistToEdge = 7.0f * flameScale.y; + +		Vec efPos = {pos.x + flameOffsetX, pos.y + flameOffsetY, flameZ}; +		S16Vec efRot = {-0x4000, 0, 0}; +		//flamethrowerEffect.spawn("Wm_en_fireburner", 0, &efPos, &efRot, &flameScale); +		flamethrowerEffectInd.spawn("Wm_en_fireburner6ind", 0, &efPos, &efRot, &flameScale); +		flamethrowerModel._vf1C(); +		flamethrowerAnim.process(); +	} else if (timer == 315) { +		renderFlamethrowerModel = false; +		flameCollision.removeFromList(); +		aPhysics.removeFromList(); + +		Vec efPos = {pos.x + flameOffsetX - 6.0f, pos.y + flameOffsetY + 1.0f, pos.z}; +		float offsets[] = {0.0f, 3.0f, 0.0f, -3.0f}; +		for (int i = 0; i < 20; i++) { +			efPos.y = pos.y + flameOffsetY + offsets[i & 3]; +			SpawnEffect("Wm_mr_fireball_hit01", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){1.5f, 1.5f, 1.5f}); +			efPos.x -= 12.0f; +		} + +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_OBJ_PAIPO, 1); +	} else if (timer == 348) { +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_DEMO_ED_BALLOON_LAND, 1); + +		Vec efPos = {pos.x - 72.0f, pos.y + 170.0f, pos.z}; +		SpawnEffect("Wm_mr_wallkick_l", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}); +	} + +	if (chrAnimation.isAnimationDone()) { +		doStateChange(&StateID_Outro); +	} +} + +void daCaptainBowser::endState_FinalAttack() { +} + +void daCaptainBowser::beginState_Outro() { +	WLClass::instance->_4 = 5; +	WLClass::instance->_8 = 0; +	dStage32C_c::instance->freezeMarioBossFlag = 1; + +	bowserX += 56.0f; +	bindAnimChr_and_setUpdateRate("kp_death1", 1, 0.0, 1.0f);  + +	//shipRotY = -0x4000; +	shipAnm.bind(&shipModel, shipFile.GetResAnmChr("mastfail_after"), 1); +	shipModel.bindAnim(&shipAnm, 0.0); +	shipAnm.setUpdateRate(0.5f); + +	bowserXSpeed = -3.5f; +	bowserYSpeed = 8.9f; +	bowserMaxYSpeed = -4.0f; +	bowserYAccel = -0.24375f; + +	nw4r::snd::SoundHandle handle; +	PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_L_FALL, 1); + +	explosionBottomBound = 0.0f; + +	timer = 0; +} + +extern dStateBase_c JrClownEndDemoState; +void daCaptainBowser::executeState_Outro() {  +	if (wereEntirelyDone) +		return; + +	timer++; + +	float frame = shipAnm.getCurrentFrame(); + +	// nuke the things! +	if (frame == 35.0f) { +		dActor_c *iter = 0; + +		while (iter = (dActor_c*)dActor_c::searchByBaseType(2, iter)) { +			dStageActor_c *sa = (dStageActor_c*)iter; + +			if (sa->name == EN_BIRIKYU_MAKER || sa->name == KAZAN_MGR) { +				sa->Delete(1); +			} + +			if (sa->name == EN_LINE_BIRIKYU || +					sa->name == EN_STAR_COIN || +					sa->name == EN_HATENA_BALLOON || +					sa->name == EN_ITEM || +					sa->name == EN_TARZANROPE || // Meteor +					sa->name == WM_ANCHOR) { // Koopa Throw +				sa->killedByLevelClear(); +				sa->Delete(1); +			} +		} + +		// freeze ye olde clowne +		dEn_c *clownIter = 0; +		while (clownIter = (dEn_c*)dEn_c::search(JR_CLOWN_FOR_PLAYER, clownIter)) { +			clownIter->doStateChange(&JrClownEndDemoState); +		} + +		// remove all ship collisions +		for (int i = 0; i < SHIP_SCOLL_COUNT; i++) +			shipSColls[i].removeFromList(); + +	} else if (frame == 150.0f) { +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_BOSS_KOOPA_CRASH, 1); +		prplSound.Stop(10); + +		ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance; +		Vec efPos = {cwci->screenCentreX+168.0f, cwci->screenTop-cwci->screenHeight, pos.z}; +		SpawnEffect("Wm_bg_volcano", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){4.0, 4.0, 4.0}); + +		ShakeScreen(StageScreen, 17, 7, 0, 0); + +	} else if (shipAnm.isAnimationDone()) { +		wereEntirelyDone = true;  	} -	void daCaptainBowser::executeState_Outro() {  +	if (frame > 30.0f) { +		if (timer & 4 && explosionBottomBound > -249.0f) { +			static const char *efs[] = {"Wm_en_explosion", "Wm_ob_cmnboxpiece"}; + +			int id = MakeRandomNumber(2); +			Vec efPos = { +				pos.x - 150.0f + MakeRandomNumber(300), +				pos.y + explosionBottomBound + MakeRandomNumber(250 + explosionBottomBound), +				pos.z + 200.0f +			}; +			float efScale = (float(MakeRandomNumber(30)) / 20.0f); + +			SpawnEffect(efs[id], 0, &efPos, &(S16Vec){0,0,0}, &(Vec){efScale,efScale,efScale}); +		} + +		if ((timer % 12) == 0 && (frame < 150.0f)) { +			nw4r::snd::SoundHandle handle; +			PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_DEMO_OP_CAKE_CLASH_1210f, 1); +		} + +		explosionBottomBound -= 0.85f;  	} -	void daCaptainBowser::endState_Outro() {  } + +	// handleYSpeed(): +	bowserYSpeed += bowserYAccel; +	if (bowserYSpeed < bowserMaxYSpeed) +		bowserYSpeed = bowserMaxYSpeed; + +	// doMovement() +	bowserX += bowserXSpeed; +	bowserY += bowserYSpeed; + +	bowserRotX -= 0xC00; +	bowserRotY -= 0x100; +} +void daCaptainBowser::endState_Outro() {  } diff --git a/src/bossKoopaThrow.cpp b/src/bossKoopaThrow.cpp index 3b07d98..d330651 100644 --- a/src/bossKoopaThrow.cpp +++ b/src/bossKoopaThrow.cpp @@ -21,10 +21,10 @@ struct TypeInfo {  static const TypeInfo types[6] = {  	{"choropoo", 			"g3d/choropoo.brres", 			"spanner", 				"Wm_en_hit", 		0, 						SE_BOSS_JR_FLOOR_BREAK, 0, 							8.0f, 	2.0f, 0, 		0, 		0x1000}, -	{"choropoo", 			"g3d/choropoo.brres", 			"spanner", 				"Wm_en_burst_s", 	0, 						SE_BOSS_JR_BOMB_BURST, 	0, 							8.0f, 	2.0f, 0, 		0, 		0x1000}, +	{"choropoo", 			"g3d/choropoo.brres", 			"spanner", 				"Wm_en_burst_s", 	0, 						SE_BOSS_JR_BOMB_BURST, 	0, 							12.0f, 	2.0f, 0, 		0, 		0x1000},  	{"koopa_clown_bomb", 	"g3d/koopa_clown_bomb.brres", 	"koopa_clown_bomb", 	"Wm_en_burst_s", 	SE_EMY_ELCJ_THROW, 		SE_BOSS_JR_BOMB_BURST, 	0, 							16.0f, 	0.8f, 0x200, 	0x800, 	0x1000},  	{"bros", 				"g3d/t00.brres", 				"bros_hammer", 			"Wm_en_hit", 		0, 						SE_OBJ_HAMMER_HIT_BOTH, SE_EMY_MEGA_BROS_HAMMER, 	16.0f, 	2.0f, 0, 		0, 		0x1000}, -	{"dossun",				"g3d/t00.brres", 				"dossun", 				"Wm_en_hit", 		SE_EMY_DOSSUN, 			SE_EMY_DOSSUN_DEAD, 	0, 							16.0f, 	1.0f, 0x100,  	0x100, 	0x100}, +	{"dossun",				"g3d/t02.brres", 				"dossun", 				"Wm_en_hit", 		SE_EMY_DOSSUN, 			SE_EMY_DOSSUN_DEAD, 	0, 							14.0f, 	1.0f, 0,		0,		0},  	{"KoopaShip",			"g3d/present.brres", 			"PresentBox_penguin", 	"Wm_dm_presentopen",SE_DEMO_OP_PRESENT_THROW_2400f, SE_DEMO_OP_PRESENT_BOX_BURST, 	0, 			20.0f, 	1.0f, 0x20, 	0x40, 	0x200}  }; @@ -55,6 +55,9 @@ class daKoopaThrow : public dEn_c {  	int lifespan;  	u32 cmgr_returnValue; +	bool playsAnim; +	m3d::anmChr_c chrAnim; +  	const TypeInfo *currentInfo;  	static daKoopaThrow *build(); @@ -181,16 +184,29 @@ int daKoopaThrow::onCreate() {  	allocator.link(-1, GameHeaps[0], 0, 0x20);  	nw4r::g3d::ResFile rf(getResource(currentInfo->arcName, currentInfo->brresName)); -	bodyModel.setup(rf.GetResMdl(currentInfo->modelName), &allocator, 0x224, 1, 0); +	nw4r::g3d::ResMdl resMdl = rf.GetResMdl(currentInfo->modelName); + +	bodyModel.setup(resMdl, &allocator, (Type == 4 ? 0x224 : 0), 1, 0);  	SetupTextures_Enemy(&bodyModel, 0); +	if (Type == 4) { +		// Thwomp +		playsAnim = true; + +		nw4r::g3d::ResAnmChr anmChr = rf.GetResAnmChr("boss_throw"); +		chrAnim.setup(resMdl, anmChr, &allocator, 0); +		chrAnim.bind(&bodyModel, anmChr, 1); +		bodyModel.bindAnim(&chrAnim, 0.0); +		chrAnim.setUpdateRate(1.0); +	} +  	allocator.unlink();  	ActivePhysics::Info KoopaJunk; -	KoopaJunk.xDistToCenter = -currentInfo->size; -	KoopaJunk.yDistToCenter = 0.0; +	KoopaJunk.xDistToCenter = 0.0f; +	KoopaJunk.yDistToCenter = (Type == 4) ? currentInfo->size : 0.0;  	KoopaJunk.xDistToEdge = currentInfo->size;  	KoopaJunk.yDistToEdge = currentInfo->size; @@ -273,6 +289,11 @@ void daKoopaThrow::updateModelMatrices() {  int daKoopaThrow::onExecute() {  	acState.execute();  	updateModelMatrices(); +	if (playsAnim) { +		if (chrAnim.isAnimationDone()) +			chrAnim.setCurrentFrame(0.0f); +		bodyModel._vf1C(); +	}  	float rect[] = {this->_320, this->_324, this->spriteSomeRectX, this->spriteSomeRectY};  	int ret = this->outOfZone(this->pos, (float*)&rect, this->currentZoneID); diff --git a/src/bossPlayerClown.S b/src/bossPlayerClown.S new file mode 100644 index 0000000..b1d00a5 --- /dev/null +++ b/src/bossPlayerClown.S @@ -0,0 +1,46 @@ +.text +.align 4 +.extern ContinueFromClownCarDetectAdjacent +.extern calculateAdjacentCollision__14collisionMgr_cFPf +.global ClownCarDetectAdjacents +ClownCarDetectAdjacents: +	addi r3, r30, 0x1EC +	li r4, 0 +	bl calculateAdjacentCollision__14collisionMgr_cFPf +	cmpwi r3, 0 +	beq notAdjacent + +	# what direction are we in? +	lfs f1, 0xE8(r30) # x speed +	lis r4, zeroFloat@h +	ori r4, r4, zeroFloat@l +	lfs f2, 0(r4) + +	lbz r4, 0x348(r30) + +	cmpwi r4, 1 +	beq isLeft + +	# RIGHT +	fcmpo cr0, f1, f2 # xspeed > 0 +	blt notAdjacent +	stfs f2, 0xE8(r30) +	b notAdjacent + +isLeft: +	# LEFT +	fcmpo cr0, f1, f2 # xspeed < 0 +	bgt notAdjacent +	stfs f2, 0xE8(r30) + +notAdjacent: +	# END HERE + +	mr r3, r30 +	b ContinueFromClownCarDetectAdjacent + + +.data +.align 4 +zeroFloat: .float 0.0 + diff --git a/src/bossPlayerClown.cpp b/src/bossPlayerClown.cpp index 3bf1119..0095b6b 100644 --- a/src/bossPlayerClown.cpp +++ b/src/bossPlayerClown.cpp @@ -53,9 +53,24 @@ int CConDraw(dEn_c *clown) {  	return PClownCarDraw(clown);  	// run normal clown function  } +extern dStateBase_c JrClownEndDemoState; +extern dStateBase_c JrClownDemoWaitState; +extern dStateBase_c ClownDemoWaitState;  int CConExecute(dEn_c *clown) { -	return PClownCarExecute(clown); +	// A REALLY TERRIBLE HACK. +	float saveX = clown->pos.x; +	float saveY = clown->pos.y; + +	int ret = PClownCarExecute(clown); + +	dStateBase_c *state = clown->acState.getCurrentState(); +	if (state == &JrClownEndDemoState || state == &JrClownDemoWaitState || state == &ClownDemoWaitState) { +		clown->pos.x = saveX; +		clown->pos.y = saveY; +		clown->speed.x = 0.0f; +		clown->speed.y = 0.0f; +	}  }  void CCafterCreate(dEn_c *clown, u32 param) { @@ -78,6 +93,17 @@ void CCafterCreate(dEn_c *clown, u32 param) {  	// Original AfterCreate  	PClownCarAfterCreate(clown, param); + +	int playerCount = 0; +	for (int i = 0; i < 4; i++) +		if (Player_Active[i]) +			playerCount++; + +	if ((clown->settings & 0xF) != 0) { +		int playerID = (clown->settings & 0xF) - 1; +		if (playerID >= playerCount) +			clown->Delete(1); +	}  }  void CConExecuteMove(dEn_c *clown) { @@ -104,7 +130,8 @@ void CConExecuteMove(dEn_c *clown) {  			}  			SpawnEffect("Wm_en_killervanish", 0, &tempPos, &(S16Vec){0,0,0}, &(Vec){0.1, 0.1, 0.1}); -			PlaySoundAsync(clown, SE_OBJ_HOUDAI_S_SHOT); +			nw4r::snd::SoundHandle handle; +			PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_OBJ_HOUDAI_S_SHOT, 1);  		cTimer = 0;  		} @@ -112,9 +139,13 @@ void CConExecuteMove(dEn_c *clown) {  	cTimer++; -	float leftBound = ClassWithCameraInfo::instance->screenLeft + 12.0f; +	ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance; +	float leftBound = cwci->screenLeft + 12.0f; +	float rightBound = (cwci->screenLeft + cwci->screenWidth) - 12.0f;  	if (clown->pos.x < leftBound)  		clown->pos.x = leftBound; +	if (clown->pos.x > rightBound) +		clown->pos.x = rightBound;  	// run normal move  	PClownCarMove(clown); @@ -151,6 +182,10 @@ void newClownDtor(dEn_c *clown, u32 willDelete) {  	__dt__20daJrClownForPlayer_cFv(clown, willDelete);  } +extern "C" void JrClownForPlayer_playAccelSound() { +	nw4r::snd::SoundHandle handle; +	PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_PLY_CROWN_ACC, 1); +} @@ -214,10 +249,10 @@ int daClownShot::onCreate() {  	_320 = 0.0f;  	_324 = 0.0f; -	// These structs tell stupid collider what to collide with - these are from koopa troopa -	static const lineSensor_s below(SENSOR_BREAK_BRICK | SENSOR_BREAK_BLOCK, 12<<12, 4<<12, 0<<12); -	static const pointSensor_s above(SENSOR_BREAK_BRICK | SENSOR_BREAK_BLOCK, 0<<12, 12<<12); -	static const lineSensor_s adjacent(SENSOR_BREAK_BRICK | SENSOR_BREAK_BLOCK, 6<<12, 9<<12, 6<<12); +	u32 flags = SENSOR_BREAK_BRICK | SENSOR_BREAK_BLOCK | SENSOR_80000000; +	static const lineSensor_s below(flags, 12<<12, 4<<12, 0<<12); +	static const pointSensor_s above(flags, 0<<12, 12<<12); +	static const lineSensor_s adjacent(flags, 6<<12, 9<<12, 6<<12);  	collMgr.init(this, &below, &above, &adjacent);  	collMgr.calculateBelowCollisionWithSmokeEffect(); @@ -248,7 +283,17 @@ int daClownShot::onExecute() {  	HandleXSpeed();  	HandleYSpeed();  	doSpriteMovement(); +  	collMgr.calculateBelowCollisionWithSmokeEffect(); +	collMgr.calculateAboveCollision(0); +	collMgr.calculateAdjacentCollision(); +	if (collMgr.outputMaybe) { +		SpawnEffect("Wm_en_burst_m", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); +		nw4r::snd::SoundHandle handle; +		PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_OBJ_TARU_BREAK, 1); +		Delete(1); +		return true; +	}  	effect.spawn("Wm_en_killersmoke", 0, &(Vec){pos.x, pos.y, pos.z}, &(S16Vec){0,0,0}, &(Vec){0.7, 0.7, 0.7}); | 
