mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			241 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// DR. ROBOTNIK'S RING RACERS
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// Copyright (C) 2024 by Vivian "toastergrl" Grannell
 | 
						|
// Copyright (C) 2024 by Kart Krew
 | 
						|
//
 | 
						|
// This program is free software distributed under the
 | 
						|
// terms of the GNU General Public License, version 2.
 | 
						|
// See the 'LICENSE' file for more details.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
/// \file  k_boss.c
 | 
						|
/// \brief Boss battle game logic
 | 
						|
 | 
						|
#include "k_boss.h"
 | 
						|
#include "doomdef.h"
 | 
						|
#include "d_player.h"
 | 
						|
#include "g_game.h"
 | 
						|
#include "p_local.h"
 | 
						|
#include "k_kart.h"
 | 
						|
#include "s_sound.h"
 | 
						|
#include "st_stuff.h"
 | 
						|
#include "z_zone.h"
 | 
						|
 | 
						|
struct bossinfo bossinfo;
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	void K_ResetBossInfo(void)
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
void K_ResetBossInfo(void)
 | 
						|
{
 | 
						|
	Z_Free(bossinfo.enemyname);
 | 
						|
	Z_Free(bossinfo.subtitle);
 | 
						|
	memset(&bossinfo, 0, sizeof(struct bossinfo));
 | 
						|
	bossinfo.barlen = BOSSHEALTHBARLEN;
 | 
						|
	bossinfo.titlesound = sfx_typri1;
 | 
						|
}
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	void K_BossInfoTicker(void)
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
void K_BossInfoTicker(void)
 | 
						|
{
 | 
						|
	UINT8 i;
 | 
						|
 | 
						|
	if (bossinfo.valid == false)
 | 
						|
		return;
 | 
						|
 | 
						|
	// Update healthbar data. (only if the hud is visible)
 | 
						|
	if (leveltime > (TICRATE/2)+3)
 | 
						|
	{
 | 
						|
		// Greater than the actual health?
 | 
						|
		if (bossinfo.visualbar > bossinfo.healthbar)
 | 
						|
		{
 | 
						|
			bossinfo.visualbar--;
 | 
						|
			// If the boss is dying, start shrinking the healthbar.
 | 
						|
			if (bossinfo.visualbar == 0)
 | 
						|
				bossinfo.barlen -= 2;
 | 
						|
		}
 | 
						|
		// Less than the actual health?
 | 
						|
		else if (bossinfo.visualbar < bossinfo.healthbar)
 | 
						|
			bossinfo.visualbar++;
 | 
						|
		// Continue to shrink the healthbar.
 | 
						|
		else if (bossinfo.barlen > 1  && bossinfo.barlen < BOSSHEALTHBARLEN)
 | 
						|
			bossinfo.barlen -= 2;
 | 
						|
 | 
						|
		// Jitter timer.
 | 
						|
		if (bossinfo.visualbarimpact)
 | 
						|
			bossinfo.visualbarimpact--;
 | 
						|
	}
 | 
						|
 | 
						|
	if (bossinfo.doweakspotsound != SPOT_NONE)
 | 
						|
	{
 | 
						|
		S_StartSound(NULL, sfx_mbs55); // may change for bump option
 | 
						|
		bossinfo.doweakspotsound = SPOT_NONE;
 | 
						|
	}
 | 
						|
 | 
						|
	// Update weakspot data.
 | 
						|
	for (i = 0; i < NUMWEAKSPOTS; i++)
 | 
						|
	{
 | 
						|
		// Clean out invalid references.
 | 
						|
		if ((bossinfo.weakspots[i].spot && P_MobjWasRemoved(bossinfo.weakspots[i].spot)))
 | 
						|
			P_SetTarget(&bossinfo.weakspots[i].spot, NULL);
 | 
						|
 | 
						|
		if (bossinfo.weakspots[i].spot == NULL)
 | 
						|
			continue;
 | 
						|
 | 
						|
		// Damaged quickly? Make it disappear immediately (making sure to match the flashing).
 | 
						|
		if ((bossinfo.weakspots[i].spot->hitlag > 0) && (bossinfo.weakspots[i].time > TICRATE/2))
 | 
						|
			bossinfo.weakspots[i].time = (TICRATE/2) & ~(bossinfo.weakspots[i].time & 1);
 | 
						|
 | 
						|
		// Handle counter.
 | 
						|
		if (!bossinfo.weakspots[i].time)
 | 
						|
			continue;
 | 
						|
		bossinfo.weakspots[i].time--;
 | 
						|
 | 
						|
		// Get rid of concluded spots.
 | 
						|
		if (!bossinfo.weakspots[i].time && !bossinfo.weakspots[i].minimap)
 | 
						|
			P_SetTarget(&bossinfo.weakspots[i].spot, NULL);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	void K_InitBossHealthBar(const char *enemyname, const char *subtitle, sfxenum_t titlesound, fixed_t pinchmagnitude, UINT8 divisions)
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
 | 
						|
void K_InitBossHealthBar(const char *enemyname, const char *subtitle, sfxenum_t titlesound, fixed_t pinchmagnitude, UINT8 divisions)
 | 
						|
{
 | 
						|
	if (!(gametyperules & GTR_BOSS))
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	bossinfo.valid = true;
 | 
						|
 | 
						|
	if (!leveltime)
 | 
						|
	{
 | 
						|
		bossinfo.coolintro = true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (enemyname && enemyname[0])
 | 
						|
	{
 | 
						|
		Z_Free(bossinfo.enemyname);
 | 
						|
		bossinfo.enemyname = Z_StrDup(enemyname);
 | 
						|
	}
 | 
						|
 | 
						|
	if (subtitle && subtitle[0])
 | 
						|
	{
 | 
						|
		Z_Free(bossinfo.subtitle);
 | 
						|
		bossinfo.subtitle = Z_StrDup(subtitle);
 | 
						|
	}
 | 
						|
 | 
						|
	if (titlesound)
 | 
						|
	{
 | 
						|
		bossinfo.titlesound = titlesound;
 | 
						|
	}
 | 
						|
 | 
						|
	bossinfo.barlen = BOSSHEALTHBARLEN;
 | 
						|
	K_UpdateBossHealthBar(FRACUNIT, 0);
 | 
						|
 | 
						|
	if (pinchmagnitude > FRACUNIT)
 | 
						|
		pinchmagnitude = FRACUNIT;
 | 
						|
	else if (pinchmagnitude < 0)
 | 
						|
		pinchmagnitude = 0;
 | 
						|
 | 
						|
	bossinfo.healthbarpinch = FixedMul(pinchmagnitude, BOSSHEALTHBARLEN*FRACUNIT)>>FRACBITS;
 | 
						|
 | 
						|
	// we do this here so we can fudge our working a bit
 | 
						|
	if (divisions > 0)
 | 
						|
	{
 | 
						|
		if (divisions > (BOSSHEALTHBARLEN/2)) // megamanification
 | 
						|
		{
 | 
						|
			divisions = (BOSSHEALTHBARLEN/2);
 | 
						|
		}
 | 
						|
		bossinfo.visualdiv = FixedDiv(BOSSHEALTHBARLEN*FRACUNIT, divisions*FRACUNIT);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		bossinfo.visualdiv = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	void K_UpdateBossHealthBar(fixed_t magnitude, tic_t jitterlen)
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
 | 
						|
void K_UpdateBossHealthBar(fixed_t magnitude, tic_t jitterlen)
 | 
						|
{
 | 
						|
	if (bossinfo.valid == false)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (magnitude > FRACUNIT)
 | 
						|
		magnitude = FRACUNIT;
 | 
						|
	else if (magnitude < 0)
 | 
						|
		magnitude = 0;
 | 
						|
 | 
						|
	if (jitterlen > bossinfo.visualbarimpact)
 | 
						|
		bossinfo.visualbarimpact = jitterlen;
 | 
						|
	bossinfo.healthbar = FixedMul(magnitude, BOSSHEALTHBARLEN);
 | 
						|
}
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	void K_DeclareWeakspot(mobj_t *weakspot, spottype_t spottype, boolean minimap)
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
void K_DeclareWeakspot(mobj_t *spot, spottype_t spottype, UINT16 color, boolean minimap)
 | 
						|
{
 | 
						|
	UINT8 i;
 | 
						|
 | 
						|
	if (bossinfo.valid == false)
 | 
						|
		return;
 | 
						|
 | 
						|
	// First check whether the spot is already in the list and simply redeclaring weakness (for example, a vulnerable moment in the pattern).
 | 
						|
	for (i = 0; i < NUMWEAKSPOTS; i++)
 | 
						|
		if (bossinfo.weakspots[i].spot == spot)
 | 
						|
			break;
 | 
						|
 | 
						|
	// If it's not redeclaring, check for an empty spot.
 | 
						|
	if (i == NUMWEAKSPOTS)
 | 
						|
	{
 | 
						|
		for (i = 0; i < NUMWEAKSPOTS; i++)
 | 
						|
			if (!bossinfo.weakspots[i].spot || P_MobjWasRemoved(bossinfo.weakspots[i].spot))
 | 
						|
				break;
 | 
						|
	}
 | 
						|
 | 
						|
	// If you've crammed up the list with minimap entries (the only ones that will persist), give up.
 | 
						|
	if (i == NUMWEAKSPOTS)
 | 
						|
		return;
 | 
						|
 | 
						|
	// OK, now we can slot in the weakspot data...
 | 
						|
	P_SetTarget(&bossinfo.weakspots[i].spot, spot);
 | 
						|
	bossinfo.weakspots[i].type = spottype;
 | 
						|
	bossinfo.weakspots[i].time = WEAKSPOTANIMTIME;
 | 
						|
	bossinfo.weakspots[i].color = color;
 | 
						|
	bossinfo.weakspots[i].minimap = minimap;
 | 
						|
 | 
						|
	if (spottype && bossinfo.doweakspotsound != SPOT_WEAK)
 | 
						|
	{
 | 
						|
		bossinfo.doweakspotsound = spottype;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*--------------------------------------------------
 | 
						|
	boolean K_CheckBossIntro(void);
 | 
						|
 | 
						|
		See header file for description.
 | 
						|
--------------------------------------------------*/
 | 
						|
 | 
						|
boolean K_CheckBossIntro(void)
 | 
						|
{
 | 
						|
	if (bossinfo.valid == false)
 | 
						|
		return false;
 | 
						|
	return bossinfo.coolintro;
 | 
						|
}
 |