Copy to Clipboard Test

Hot Room w/ Palette Change [2.55] Code

namespace HeatedRoom
{
	// Misc screen flag used for hot rooms
	CONFIG SFM_HOTROOM = SFM_SCRIPT1; 
	
	// General settings
	CONFIG HEATEDROOM_DAMAGE_FREQ = 8; // How often damage ticks when out of time
	CONFIG HEATEDROOM_FADE_FRAMES = 30; // Frames it takes to fade between palettes
	CONFIG HEATEDROOM_TIMER_HEART_MULT = 480; // If timer is 0, timer is set to Link's hearts * this
	CONFIG HEATEDROOM_DIRE_FRAMES = 600; // If timer is less than this draw timer in red
	CONFIG HEATEDROOM_PAL_UPDATE_FREQ = 10; // How frequently the palette should update
	
	CONFIGB HEATEDROOM_NO_COUNTDOWN_SCROLL = true; // If true, timer does not count down when scrolling
	CONFIGB HEATEDROOM_DRAW_TIMER = true; // If true, the timer is visible
	CONFIGB HEADEDROOM_DRAW_TIMER_ZERO = true; // If true, the timer is still drawn at 0:00
	
	// Minimum and maximum interpolation for palettes
	CONFIG HEATEDROOM_PALETTE_INTERPOLATE_MIN = 0.8;
	CONFIG HEATEDROOM_PALETTE_INTERPOLATE_MAX = 1.0;
	
	// Flicker period for palettes
	CONFIG HEATEDROOM_PALETTE_FLICKER_FRAMES = 120;

	// Layer to draw the timer to
	CONFIG LAYER_TIMER = 7;
	
	// Tile and CSet for timer icon
	CONFIG TIL_TIMER_ICON = 80;
	CONFIG CS_TIMER_ICON = 8;

	// Colors for the timer 
	CONFIG C_HEATEDROOM_TIMER = 0x01;
	CONFIG C_HEATEDROOM_TIMER_OUTLINE = 0x0F;
	CONFIG C_HEATEDROOM_TIMER_DIRE = 0x82;
	
	// Particles
	CONFIG HEATEDROOM_PARTICLE_MAX = 32; // Max number that can ever draw
	CONFIG HEATEDROOM_PARTICLE_FREQ = 8; // How often to create new particles
	
	// Sounds
	CONFIG SFX_HEATEDROOM_DAMAGE = SFX_OUCH; // Sound when taking damage from heated rooms

	// Sounds for the countdown in increasing intensity
	CONFIG SFX_COUNTDOWN1 = 70; // Normal
	CONFIG SFX_COUNTDOWN2 = 71; // Dire
	CONFIG SFX_COUNTDOWN3 = 72; // Last Second
	
	// Timing for countdown sfx
	CONFIG FREQ_SFX_COUNTDOWN1 = 120; // Normal
	CONFIG FREQ_SFX_COUNTDOWN2 = 60; // Dire
	
	class HeatedRoomParticle
	{
		int X,Y;
		int Timer;
		int InitTimer;
		int ATimer;
		int StartColor,EndColor;
		int W;
		bool Valid;
		
		HeatedRoomParticle(int cStart, int cEnd)
		{
			StartColor = cStart;
			EndColor = cEnd;
			Init();
		}
		
		void Init()
		{
			X = Rand(256);
			Y = Rand(176);
			Timer = Rand(64, 128);
			InitTimer = Timer;
			ATimer = Rand(360);
			W = Choose(-16, -8, 8, 16);
			Valid = true;
		}
		
		void Update()
		{
			ATimer += 3;
			Y -= 0.5;
			int x = X+W*Sin(ATimer);
			int c = Round(Lerp(EndColor, StartColor, Timer/InitTimer));
			Screen->PutPixel(6, x, Y, c, 0, 0, 0, OP_OPAQUE);
			--Timer;
			if(Timer<=0)
				Valid = false;
		}
	}

	@InitD0("Timer"),
	@InitDHelp0("The timer for the hot rooms in frames. If 0, will be based on Link's current HP"),
	@InitD1("Palette"),
	@InitDHelp1("Which level palette to fade to for the hot room. If 0, skips the palette effect"),
	@InitD2("Immunity Item"),
	@InitDHelp2("Which item gives immunity to the hot room's effect. 0 for none."),
	@InitD3("Damage"),
	@InitDHelp3("How much damage to deal per damage tick when the timer runs out. If 0, kills Link instantly"),
	@InitD4("Particle Color (Start)"),
	@InitDHelp4("Color particles start out as. If 0, no particles are drawn"),
	@InitD5("Particle Color (End)"),
	@InitDHelp5("Color particles end as. If 0, same as start"),
	@InitD6("Wavy"),
	@InitDHelp6("How much to make the screen wavy")
	dmapdata script HeatedRooms
	{
		void run(int maxTimer, int pal, int immunityItem, int damage, int particleColorStart, int particleColorEnd, int wavy)
		{
			bool doParticles = particleColorStart;
			if(doParticles&&!particleColorEnd)
				particleColorEnd = particleColorStart;
		
			paldata pdold = Graphics->CreatePalData();
			pdold->Own();
			pdold->LoadLevelPalette(Game->DMapPalette[Game->GetCurDMap()]);
		
			paldata pdnew = Graphics->CreatePalData();
			pdnew->Own();
			pdnew->LoadLevelPalette(pal);
			
			paldata pd = Graphics->CreatePalData(Graphics->CreateRGB(0));
			pd->Own();
			pdold->Copy(pd);
			for(int i=0; i<15; ++i)
			{
				if(i<2||i>4)
				{
					pd->ClearCSet(i);
				}
			}
			if(pal)
				pd->WriteMainPalette();
			
			HeatedRoomParticle hrp[HEATEDROOM_PARTICLE_MAX];
			for(int i=0; i<HEATEDROOM_PARTICLE_MAX; ++i)
			{
				hrp[i] = new HeatedRoomParticle(particleColorStart, particleColorEnd);
				hrp[i]->Valid = false;
			}
			int hrpTimer;
		
			int aSpeed = 360/HEATEDROOM_PALETTE_FLICKER_FRAMES;
			if(maxTimer==0&&HEATEDROOM_TIMER_HEART_MULT)
				maxTimer = Ceiling(Link->HP/16)*HEATEDROOM_TIMER_HEART_MULT;
			if(damage==0)
				damage = 99999;
				
			int t;
			int fadeTimer;
			int palTimer;
			int damageTimer;
			
			int timer = maxTimer;
			while(true)
			{
				bool palUpdate;
				bool forceUpdate;
				int fadepct;

				if(ScreenFlag(SF_MISC, SFM_HOTROOM))
				{
					if(doParticles)
					{
						++hrpTimer;
						for(int i=0; i<HEATEDROOM_PARTICLE_MAX; ++i)
						{
							if(hrp[i]->Valid)
							{
								hrp[i]->Update();
							}
							else
							{
								if(hrpTimer>=HEATEDROOM_PARTICLE_FREQ)
								{
									hrp[i]->Init();
									hrpTimer = 0;
								}
							}
						}
					}
				
					if(wavy)
						Screen->Wavy = wavy;
						
					palUpdate = true;
					if(immunityItem==0||!Link->Item[immunityItem])
					{
						if(Link->Action!=LA_SCROLLING||!HEATEDROOM_NO_COUNTDOWN_SCROLL)
						{
							if(timer)
								--timer;
							else
							{
								if(Link->Action!=LA_SCROLLING&&damage)
								{
									++damageTimer;
									if(damageTimer>=HEATEDROOM_DAMAGE_FREQ)
									{
										Game->PlaySound(SFX_HEATEDROOM_DAMAGE);
										Link->HP -= damage;
										damageTimer = 0;
									}
								}
							}
						}
						
						if(timer)
						{
							if(SFX_COUNTDOWN2&&timer<HEATEDROOM_DIRE_FRAMES)
							{
								if(timer%FREQ_SFX_COUNTDOWN2==FREQ_SFX_COUNTDOWN2-1)
								{
									if(SFX_COUNTDOWN3&&timer<=FREQ_SFX_COUNTDOWN2)
										Game->PlaySound(SFX_COUNTDOWN3);
									else
										Game->PlaySound(SFX_COUNTDOWN2);
								}
							}
							else if(SFX_COUNTDOWN1)
							{
								if((timer-HEATEDROOM_DIRE_FRAMES)%FREQ_SFX_COUNTDOWN1==FREQ_SFX_COUNTDOWN1-1)
								{
									Game->PlaySound(SFX_COUNTDOWN1);
								}
							}
						}
						
						DrawTimer(timer);
					}
					if(fadeTimer<HEATEDROOM_FADE_FRAMES)
						++fadeTimer;
				}
				else
				{
					if(wavy&&timer>0)
						Screen->Wavy = 0;
					
					palUpdate = true;
					timer = maxTimer;
					if(fadeTimer>0)
					{
						palUpdate = true;
						--fadeTimer;
						if(fadeTimer==0)
							forceUpdate = true;
					}
					if(!fadeTimer)
						palTimer = 0;
				}
				
				fadepct = fadeTimer/HEATEDROOM_FADE_FRAMES;
				t = WrapDegrees(t+aSpeed);
				
				if(pal&&palUpdate)
				{
					++palTimer;
					if(forceUpdate||palTimer>=HEATEDROOM_PAL_UPDATE_FREQ)
					{
						int p = Lerp(HEATEDROOM_PALETTE_INTERPOLATE_MIN, HEATEDROOM_PALETTE_INTERPOLATE_MAX, 0.5+0.5*Sin(t))*fadepct;
						pd->Mix(pdold, pdnew, p, CSPACE_LAB);
						pd->WriteMainPalette();
						palTimer = 0;
					}
				}
				
				Waitframe();
			}
		}
		void DrawTimer(int timer)
		{
			if(!HEATEDROOM_DRAW_TIMER)
				return;
			if(!HEADEDROOM_DRAW_TIMER_ZERO&&timer<=0)
				return;
			int buf[32];
			sprintf(buf, "%d:%02d", Floor(timer/3600), Floor((timer%3600)/60));
			int x = 8;
			int y = 8;
			if(TIL_TIMER_ICON)
			{
				Screen->FastTile(7, x, y, TIL_TIMER_ICON, CS_TIMER_ICON, OP_OPAQUE);
				x += 10;
				y += 2;
			}
			Screen->DrawString(7, x, y, FONT_Z3SMALL, timer<HEATEDROOM_DIRE_FRAMES?C_HEATEDROOM_TIMER_DIRE:C_HEATEDROOM_TIMER, -1, TF_NORMAL, buf, OP_OPAQUE, SHD_OUTLINED8, C_HEATEDROOM_TIMER_OUTLINE);
		}
	}
}