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);
}
}
}