SpaceCadetPinball/SpaceCadetPinball/TLight.cpp

346 lines
7.6 KiB
C++

#include "pch.h"
#include "TLight.h"
#include "control.h"
#include "loader.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
TLight::TLight(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true)
{
TimeoutTimer = 0;
FlasherOnFlag = false;
UndoOverrideTimer = 0;
FlashTimer = 0;
Reset();
float* floatArr1 = loader::query_float_attribute(groupIndex, 0, 900);
FlashDelay[0] = *floatArr1;
SourceDelay[0] = *floatArr1;
float* floatArr2 = loader::query_float_attribute(groupIndex, 0, 901);
FlashDelay[1] = *floatArr2;
SourceDelay[1] = *floatArr2;
}
int TLight::Message(int code, float value)
{
int bmpIndex;
switch (code)
{
case ~MessageCode::Reset:
Reset();
for (auto index = 0; index < PinballTable->PlayerCount; ++index)
{
auto playerPtr = &PlayerData[index];
playerPtr->FlasherOnFlag = FlasherOnFlag;
playerPtr->LightOnBmpIndex = LightOnBmpIndex;
playerPtr->LightOnFlag = LightOnFlag;
playerPtr->MessageField = MessageField;
}
break;
case ~MessageCode::PlayerChanged:
{
auto playerPtr = &PlayerData[PinballTable->CurrentPlayer];
playerPtr->FlasherOnFlag = FlasherOnFlag;
playerPtr->LightOnBmpIndex = LightOnBmpIndex;
playerPtr->LightOnFlag = LightOnFlag;
playerPtr->MessageField = MessageField;
Reset();
playerPtr = &PlayerData[static_cast<int>(floor(value))];
FlasherOnFlag = playerPtr->FlasherOnFlag;
LightOnBmpIndex = playerPtr->LightOnBmpIndex;
LightOnFlag = playerPtr->LightOnFlag;
MessageField = playerPtr->MessageField;
if (LightOnBmpIndex)
{
Message(11, static_cast<float>(LightOnBmpIndex));
}
if (LightOnFlag)
Message(1, 0.0);
if (FlasherOnFlag)
Message(4, 0.0);
break;
}
case 0:
LightOnFlag = false;
if (!FlasherOnFlag && !ToggledOffFlag && !ToggledOnFlag)
SetSpriteBmp(BmpArr[0]);
break;
case 1:
LightOnFlag = true;
if (!FlasherOnFlag && !ToggledOffFlag && !ToggledOnFlag)
SetSpriteBmp(BmpArr[1]);
break;
case 2:
return LightOnFlag;
case 3:
return FlasherOnFlag;
case 4:
schedule_timeout(0.0);
if (!FlasherOnFlag || !FlashTimer)
{
FlasherOnFlag = true;
ToggledOnFlag = false;
ToggledOffFlag = false;
TurnOffAfterFlashingFg = false;
flasher_start(LightOnFlag);
}
break;
case 5:
FlashDelay[0] = value * SourceDelay[0];
FlashDelay[1] = value * SourceDelay[1];
break;
case 6:
FlashDelay[0] = SourceDelay[0];
FlashDelay[1] = SourceDelay[1];
break;
case 7:
if (!FlasherOnFlag)
flasher_start(LightOnFlag);
FlasherOnFlag = true;
ToggledOnFlag = false;
TurnOffAfterFlashingFg = false;
ToggledOffFlag = false;
schedule_timeout(value);
break;
case 8:
if (!ToggledOffFlag)
{
if (FlasherOnFlag)
{
flasher_stop(0);
FlasherOnFlag = false;
}
else
{
SetSpriteBmp(BmpArr[0]);
}
ToggledOffFlag = true;
ToggledOnFlag = false;
}
schedule_timeout(value);
break;
case 9:
if (!ToggledOnFlag)
{
if (FlasherOnFlag)
{
flasher_stop(1);
FlasherOnFlag = false;
}
else
{
SetSpriteBmp(BmpArr[1]);
}
ToggledOnFlag = true;
ToggledOffFlag = false;
}
schedule_timeout(value);
break;
case 11:
LightOnBmpIndex = Clamp(static_cast<int>(floor(value)), 0, static_cast<int>(ListBitmap->size()) - 1);
BmpArr[0] = nullptr;
BmpArr[1] = ListBitmap->at(LightOnBmpIndex);
if (!FlasherOnFlag)
{
if (ToggledOffFlag)
bmpIndex = 0;
else if (ToggledOnFlag)
bmpIndex = 1;
else
bmpIndex = LightOnFlag;
}
else
{
bmpIndex = FlashLightOnFlag;
}
SetSpriteBmp(BmpArr[bmpIndex]);
break;
case 12:
bmpIndex = LightOnBmpIndex + 1;
if (bmpIndex >= static_cast<int>(ListBitmap->size()))
bmpIndex = static_cast<int>(ListBitmap->size()) - 1;
Message(11, static_cast<float>(bmpIndex));
break;
case 13:
bmpIndex = LightOnBmpIndex - 1;
if (bmpIndex < 0)
bmpIndex = 0;
Message(11, static_cast<float>(bmpIndex));
break;
case 14:
if (TimeoutTimer)
timer::kill(TimeoutTimer);
TimeoutTimer = 0;
if (FlasherOnFlag)
flasher_stop(-1);
FlasherOnFlag = false;
ToggledOffFlag = false;
ToggledOnFlag = false;
SetSpriteBmp(BmpArr[LightOnFlag]);
break;
case 15:
TurnOffAfterFlashingFg = false;
if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0;
Message(1, 0.0);
Message(7, value);
break;
case 16:
if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0;
Message(7, value);
TurnOffAfterFlashingFg = true;
break;
case 17:
Message(static_cast<int>(floor(value)) != 0, 0.0);
return LightOnFlag;
case 18:
Message(17, value);
Message(14, 0.0);
return LightOnFlag;
case 19:
Message(1, 0.0);
Message(14, 0.0);
break;
case 20:
Message(0, 0.0);
Message(14, 0.0);
break;
case 21:
Message(17, !LightOnFlag);
return LightOnFlag;
case 22:
Message(18, !LightOnFlag);
return LightOnFlag;
case 23:
MessageField = static_cast<int>(floor(value));
break;
case -24:
case -25:
// FT codes in negative to avoid overlap with 3DPB TLightGroup codes
render::sprite_set_bitmap(RenderSprite, BmpArr[code == -24]);
if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0;
if (value > 0)
{
TemporaryOverrideFlag = true;
UndoOverrideTimer = timer::set(value, this, UndoTmpOverride);
}
break;
case -26:
if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0;
TemporaryOverrideFlag = false;
render::sprite_set_bitmap(RenderSprite, PreviousBitmap);
break;
default:
break;
}
return 0;
}
void TLight::Reset()
{
if (TimeoutTimer)
timer::kill(TimeoutTimer);
if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer);
if (FlasherOnFlag)
flasher_stop(-1);
TimeoutTimer = 0;
UndoOverrideTimer = 0;
LightOnFlag = false;
LightOnBmpIndex = 0;
ToggledOffFlag = false;
ToggledOnFlag = false;
FlasherOnFlag = false;
TemporaryOverrideFlag = false;
TurnOffAfterFlashingFg = false;
PreviousBitmap = nullptr;
render::sprite_set_bitmap(RenderSprite, nullptr);
BmpArr[0] = nullptr;
if (ListBitmap)
BmpArr[1] = ListBitmap->at(0);
MessageField = 0;
}
void TLight::schedule_timeout(float time)
{
FlashDelay[0] = SourceDelay[0];
FlashDelay[1] = SourceDelay[1];
if (TimeoutTimer)
timer::kill(TimeoutTimer);
TimeoutTimer = 0;
if (time > 0.0f)
TimeoutTimer = timer::set(time, this, TimerExpired);
}
void TLight::TimerExpired(int timerId, void* caller)
{
auto light = static_cast<TLight*>(caller);
if (light->FlasherOnFlag)
light->flasher_stop(-1);
light->SetSpriteBmp(light->BmpArr[light->LightOnFlag]);
light->ToggledOffFlag = false;
light->ToggledOnFlag = false;
light->FlasherOnFlag = false;
light->TimeoutTimer = 0;
if (light->TurnOffAfterFlashingFg)
{
light->TurnOffAfterFlashingFg = false;
light->Message(20, 0.0);
}
if (light->Control)
control::handler(60, light);
}
void TLight::flasher_stop(int bmpIndex)
{
if (FlashTimer)
timer::kill(FlashTimer);
FlashTimer = 0;
if (bmpIndex >= 0)
{
FlashLightOnFlag = bmpIndex;
SetSpriteBmp(BmpArr[FlashLightOnFlag]);
}
}
void TLight::flasher_start(bool bmpIndex)
{
FlashLightOnFlag = bmpIndex;
flasher_callback(0, this);
}
void TLight::SetSpriteBmp(gdrv_bitmap8* bmp)
{
PreviousBitmap = bmp;
if (!TemporaryOverrideFlag)
render::sprite_set_bitmap(RenderSprite, bmp);
}
void TLight::flasher_callback(int timerId, void* caller)
{
auto light = static_cast<TLight*>(caller);
light->FlashLightOnFlag ^= true;
light->SetSpriteBmp(light->BmpArr[light->FlashLightOnFlag]);
light->FlashTimer = timer::set(light->FlashDelay[light->FlashLightOnFlag], light, flasher_callback);
}
void TLight::UndoTmpOverride(int timerId, void* caller)
{
auto light = static_cast<TLight*>(caller);
light->Message(-26, 0.0f);
}