diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index c18f505..c6cb10b 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/TComponentGroup.cpp b/SpaceCadetPinball/TComponentGroup.cpp index eda558b..e94a19d 100644 --- a/SpaceCadetPinball/TComponentGroup.cpp +++ b/SpaceCadetPinball/TComponentGroup.cpp @@ -1,2 +1,66 @@ #include "pch.h" #include "TComponentGroup.h" + + +#include "control.h" +#include "loader.h" +#include "objlist_class.h" +#include "timer.h" +#include "TPinballTable.h" + +TComponentGroup::TComponentGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false) +{ + List = new objlist_class(4, 4); + Timer = 0; + if (groupIndex > 0) + { + int attrCount; + auto shortArr = loader::query_iattribute(groupIndex, 1027, &attrCount); + auto shortArrPtr = shortArr; + for (auto index = 0; index < attrCount; ++index, ++shortArrPtr) + { + auto component = table->find_component(*shortArrPtr); + if (component) + List->Add(component); + } + } +} + +TComponentGroup::~TComponentGroup() +{ + if (Timer) + { + timer::kill(Timer); + Timer = 0; + } + delete List; +} + +int TComponentGroup::Message(int code, float value) +{ + if (code == 48) + { + if (this->Timer) + { + timer::kill(this->Timer); + this->Timer = 0; + } + if (value > 0.0) + this->Timer = timer::set(value, this, NotifyTimerExpired); + } + else if (code <= 1007 || code > 1011 && code != 1020 && code != 1022) + { + for (int i = 0; i < List->Count(); i++) + { + static_cast(List->Get(i))->Message(code, value); + } + } + return 0; +} + +void TComponentGroup::NotifyTimerExpired(int timerId, void* caller) +{ + auto compGroup = static_cast(caller); + compGroup->Timer = 0; + control::handler(61, compGroup); +} diff --git a/SpaceCadetPinball/TComponentGroup.h b/SpaceCadetPinball/TComponentGroup.h index 7e7ba81..ec44329 100644 --- a/SpaceCadetPinball/TComponentGroup.h +++ b/SpaceCadetPinball/TComponentGroup.h @@ -1,11 +1,17 @@ #pragma once #include "TPinballComponent.h" + +class objlist_class; + class TComponentGroup : - public TPinballComponent + public TPinballComponent { public: - TComponentGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false) - { - } -}; + TComponentGroup(TPinballTable* table, int groupIndex); + ~TComponentGroup() override; + int Message(int code, float value) override; + static void NotifyTimerExpired(int timerId, void* caller); + objlist_class* List; + int Timer; +}; diff --git a/SpaceCadetPinball/TLight.cpp b/SpaceCadetPinball/TLight.cpp index 9e0ecdd..81494db 100644 --- a/SpaceCadetPinball/TLight.cpp +++ b/SpaceCadetPinball/TLight.cpp @@ -1,2 +1,327 @@ #include "pch.h" #include "TLight.h" + + +#include "control.h" +#include "loader.h" +#include "render.h" +#include "timer.h" +#include "TPinballTable.h" +#include "TZmapList.h" + +TLight::TLight(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) +{ + Timer1 = 0; + FlasherActive = 0; + Timer2 = 0; + Flasher.Timer = 0; + Reset(); + float* floatArr1 = loader::query_float_attribute(groupIndex, 0, 900); + Flasher.TimerDelay[0] = *floatArr1; + FlasherDelay[0] = *floatArr1; + float* floatArr2 = loader::query_float_attribute(groupIndex, 0, 901); + Flasher.TimerDelay[1] = *floatArr2; + FlasherDelay[1] = *floatArr2; +} + +int TLight::Message(int code, float value) +{ + int bmpIndex; + auto this2 = this; + if (code > 1020) + { + if (code == 1024) + { + Reset(); + for (auto index = 0; index < this2->PinballTable->PlayerCount; ++index) + { + auto playerPtr = &this2->PlayerData[index]; + playerPtr->FlasherActive = this2->FlasherActive; + playerPtr->BmpIndex2 = this2->BmpIndex2; + playerPtr->BmpIndex1 = this2->BmpIndex1; + playerPtr->MessageField = this2->MessageField; + } + } + return 0; + } + if (code == 1020) + { + auto playerPtr = &this2->PlayerData[PinballTable->CurrentPlayer]; + playerPtr->FlasherActive = this2->FlasherActive; + playerPtr->BmpIndex2 = this2->BmpIndex2; + playerPtr->BmpIndex1 = this2->BmpIndex1; + playerPtr->MessageField = this2->MessageField; + + Reset(); + + playerPtr = &this2->PlayerData[static_cast(floor(value))]; + this2->FlasherActive = playerPtr->FlasherActive; + this2->BmpIndex2 = playerPtr->BmpIndex2; + this2->BmpIndex1 = playerPtr->BmpIndex1; + this2->MessageField = playerPtr->MessageField; + if (this2->BmpIndex2) + { + this2->Message(11, static_cast(this2->BmpIndex2)); + } + if (this2->BmpIndex1) + this2->Message(1, 0.0); + if (this2->FlasherActive) + this2->Message(4, 0.0); + return 0; + } + switch (code) + { + case 0: + this->BmpIndex1 = 0; + if (this->FlasherActive == 0 && !this->FlasherFlag1 && !this->FlasherFlag2) + render::sprite_set_bitmap(this->RenderSprite, this->Flasher.BmpArr[0]); + return 0; + case 1: + this->BmpIndex1 = 1; + if (this->FlasherActive == 0 && !this->FlasherFlag1 && !this->FlasherFlag2) + render::sprite_set_bitmap(this->RenderSprite, this->Flasher.BmpArr[1]); + return 0; + case 2: + break; + case 3: + return this->FlasherActive; + case 4: + schedule_timeout(0.0); + if (!this2->FlasherActive || !this2->Flasher.Timer) + { + this2->FlasherActive = 1; + this2->FlasherFlag2 = 0; + this2->FlasherFlag1 = 0; + this2->Unknown13 = 0; + flasher_start(&this2->Flasher, this2->BmpIndex1); + } + return 0; + case 5: + this->Flasher.TimerDelay[0] = value * this->FlasherDelay[0]; + this->Flasher.TimerDelay[1] = value * this->FlasherDelay[1]; + return 0; + case 6: + this->Flasher.TimerDelay[0] = this->FlasherDelay[0]; + this->Flasher.TimerDelay[1] = this->FlasherDelay[1]; + return 0; + case 7: + if (!this->FlasherActive) + flasher_start(&this->Flasher, this->BmpIndex1); + this2->FlasherActive = 1; + this2->FlasherFlag2 = 0; + this2->Unknown13 = 0; + this2->FlasherFlag1 = 0; + schedule_timeout(value); + return 0; + case 8: + if (!this->FlasherFlag1) + { + if (this->FlasherActive) + { + flasher_stop(&this->Flasher, 0); + this2->FlasherActive = 0; + } + else + { + render::sprite_set_bitmap(this->RenderSprite, this->Flasher.BmpArr[0]); + } + this2->FlasherFlag1 = 1; + this2->FlasherFlag2 = 0; + } + schedule_timeout(value); + return 0; + case 9: + if (!this->FlasherFlag2) + { + if (this->FlasherActive) + { + flasher_stop(&this->Flasher, 1); + this2->FlasherActive = 0; + } + else + { + render::sprite_set_bitmap(this->RenderSprite, this->Flasher.BmpArr[1]); + } + this2->FlasherFlag2 = 1; + this2->FlasherFlag1 = 0; + } + schedule_timeout(value); + return 0; + case 11: + this2->BmpIndex2 = static_cast(floor(value)); + if (this2->BmpIndex2 > this2->ListBitmap->Count()) + this2->BmpIndex2 = this2->ListBitmap->Count(); + bmpIndex = 0; + if (this2->BmpIndex2 < 0) + this2->BmpIndex2 = 0; + this2->Flasher.BmpArr[0] = nullptr; + this2->Flasher.BmpArr[1] = static_cast(this2->ListBitmap->Get(this2->BmpIndex2)); + if (this2->FlasherActive == 0) + { + if (!this2->FlasherFlag1) + { + if (this2->FlasherFlag2) + bmpIndex = 1; + else + bmpIndex = this2->BmpIndex1; + } + } + else + { + bmpIndex = this2->Flasher.BmpIndex; + } + render::sprite_set_bitmap(this2->RenderSprite, this2->Flasher.BmpArr[bmpIndex]); + return 0; + case 12: + bmpIndex = this->BmpIndex2 + 1; + if (bmpIndex > this->ListBitmap->Count()) + bmpIndex = this->ListBitmap->Count(); + Message(11, static_cast(bmpIndex)); + return 0; + case 13: + bmpIndex = this->BmpIndex2 - 1; + if (bmpIndex < 0) + bmpIndex = 0; + Message(11, static_cast(bmpIndex)); + return 0; + case 14: + if (this->Timer1) + timer::kill(this->Timer1); + this2->Timer1 = 0; + if (this2->FlasherActive != 0) + flasher_stop(&this2->Flasher, -1); + this2->FlasherActive = 0; + this2->FlasherFlag1 = 0; + this2->FlasherFlag2 = 0; + render::sprite_set_bitmap(this2->RenderSprite, this2->Flasher.BmpArr[this2->BmpIndex1]); + return 0; + case 15: + this->Unknown13 = 0; + if (this->Timer2) + timer::kill(this->Timer2); + this2->Timer2 = 0; + Message(1, 0.0); + Message(7, value); + return 0; + case 16: + if (this->Timer2) + timer::kill(this->Timer2); + this2->Timer2 = 0; + Message(7, value); + this2->Unknown13 = 1; + return 0; + case 17: + Message(static_cast(floor(value)) != 0, 0.0); + break; + case 18: + Message(17, value); + Message(14, 0.0); + break; + case 19: + Message(1, 0.0); + Message(14, 0.0); + return 0; + case 20: + Message(0, 0.0); + Message(14, 0.0); + return 0; + case 21: + Message(17, static_cast(this->BmpIndex1 == 0)); + break; + case 22: + Message(18, static_cast(this->BmpIndex1 == 0)); + break; + case 23: + this->MessageField = static_cast(floor(value)); + return 0; + default: + return 0; + } + + return this2->BmpIndex1; +} + +void TLight::Reset() +{ + if (Timer1) + timer::kill(Timer1); + if (Timer2) + timer::kill(Timer2); + if (FlasherActive) + flasher_stop(&Flasher, -1); + Unknown20F = 1.0; + Timer1 = 0; + Timer2 = 0; + BmpIndex1 = 0; + BmpIndex2 = 0; + FlasherFlag1 = 0; + FlasherFlag2 = 0; + FlasherActive = 0; + Unknown13 = 0; + render::sprite_set_bitmap(RenderSprite, nullptr); + Flasher.Sprite = RenderSprite; + Flasher.BmpArr[0] = nullptr; + if (ListBitmap) + Flasher.BmpArr[1] = static_cast(ListBitmap->Get(0)); + Flasher.Unknown4 = 0; + Flasher.Unknown3 = 0; + MessageField = 0; +} + +void TLight::schedule_timeout(float time) +{ + Flasher.TimerDelay[0] = FlasherDelay[0]; + Flasher.TimerDelay[1] = FlasherDelay[1]; + if (Timer1) + timer::kill(Timer1); + Timer1 = 0; + if (time > 0.0) + Timer1 = timer::set(time, this, TimerExpired); +} + +void TLight::TimerExpired(int timerId, void* caller) +{ + auto light = static_cast(caller); + if (light->FlasherActive) + flasher_stop(&light->Flasher, -1); + render::sprite_set_bitmap(light->RenderSprite, light->Flasher.BmpArr[light->BmpIndex1]); + light->FlasherFlag1 = 0; + light->FlasherFlag2 = 0; + light->FlasherActive = 0; + light->Timer1 = 0; + if (light->Unknown13 != 0) + { + light->Unknown13 = 0; + light->Message(20, 0.0); + } + if (light->Control) + control::handler(60, light); +} + + +void TLight::flasher_stop(flasher_type* flash, int bmpIndex) +{ + if (flash->Timer) + timer::kill(flash->Timer); + flash->Timer = 0; + if (bmpIndex >= 0) + { + flash->BmpIndex = bmpIndex; + render::sprite_set_bitmap(flash->Sprite, flash->BmpArr[bmpIndex]); + } +} + +void TLight::flasher_start(flasher_type* flash, int bmpIndex) +{ + flash->BmpIndex = bmpIndex; + flasher_callback(0, flash); +} + +void TLight::flasher_callback(int timerId, void* caller) +{ + auto flash = static_cast(caller); + auto index = 1 - flash->BmpIndex; + flash->BmpIndex = index; + render::sprite_set_bitmap(flash->Sprite, flash->BmpArr[index]); + flash->Timer = timer::set(flash->TimerDelay[flash->BmpIndex], flash, flasher_callback); +} diff --git a/SpaceCadetPinball/TLight.h b/SpaceCadetPinball/TLight.h index e60d80b..cdb9cbd 100644 --- a/SpaceCadetPinball/TLight.h +++ b/SpaceCadetPinball/TLight.h @@ -1,11 +1,56 @@ #pragma once #include "TPinballComponent.h" -class TLight : - public TPinballComponent + +struct gdrv_bitmap8; + +struct __declspec(align(4)) flasher_type { -public: - TLight(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) - { - } + render_sprite_type_struct* Sprite; + gdrv_bitmap8* BmpArr[2]; + int Unknown3; + int Unknown4; + float TimerDelay[2]; + int Timer; + int BmpIndex; }; + +struct __declspec(align(4)) TLight_player_backup +{ + int MessageField; + int BmpIndex1; + int FlasherActive; + int Unknown3; + int Unknown4; + int BmpIndex2; +}; + + +class TLight : + public TPinballComponent +{ +public: + TLight(TPinballTable* table, int groupIndex); + int Message(int code, float value) override; + void Reset(); + void schedule_timeout(float time); + + static void TimerExpired(int timerId, void* caller); + static void flasher_stop(flasher_type* flash, int bmpIndex); + static void flasher_start(struct flasher_type* flash, int bmpIndex); + static void flasher_callback(int timerId, void* caller); + + flasher_type Flasher; + int BmpIndex1; + int FlasherActive; + int FlasherFlag1; + int FlasherFlag2; + int Unknown13; + int BmpIndex2; + float FlasherDelay[2]; + int Timer1; + int Timer2; + int Unknown19; + float Unknown20F; + TLight_player_backup PlayerData[4]; +}; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 5efc507..c5ca725 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -241,7 +241,7 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName) TPinballComponent* TPinballTable::find_component(int groupIndex) { - char Buffer[33]; + char Buffer[40]; int objCount = ComponentList->Count(); if (objCount > 0) { diff --git a/SpaceCadetPinball/TSound.cpp b/SpaceCadetPinball/TSound.cpp index 5c30db5..9e835c8 100644 --- a/SpaceCadetPinball/TSound.cpp +++ b/SpaceCadetPinball/TSound.cpp @@ -1,2 +1,16 @@ #include "pch.h" #include "TSound.h" + +#include "loader.h" + +TSound::TSound(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) +{ + visualStruct visual{}; + loader::query_visual(groupIndex, 0, &visual); + this->SoundIndex = visual.SoundIndex4; +} + +float TSound::Play() +{ + return loader::play_sound(this->SoundIndex); +} diff --git a/SpaceCadetPinball/TSound.h b/SpaceCadetPinball/TSound.h index 3a3a3fe..aef92eb 100644 --- a/SpaceCadetPinball/TSound.h +++ b/SpaceCadetPinball/TSound.h @@ -1,11 +1,12 @@ #pragma once #include "TPinballComponent.h" + class TSound : - public TPinballComponent + public TPinballComponent { public: - TSound(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) - { - } -}; + TSound(TPinballTable* table, int groupIndex); + float Play(); + int SoundIndex; +}; diff --git a/SpaceCadetPinball/TTimer.cpp b/SpaceCadetPinball/TTimer.cpp index 6821d49..56f9dc5 100644 --- a/SpaceCadetPinball/TTimer.cpp +++ b/SpaceCadetPinball/TTimer.cpp @@ -1,2 +1,37 @@ #include "pch.h" #include "TTimer.h" + +#include "control.h" +#include "timer.h" + +TTimer::TTimer(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) +{ + Timer = 0; +} + +int TTimer::Message(int code, float value) +{ + if (code == 59) + { + if (Timer) + timer::kill(Timer); + Timer = timer::set(value, this, TimerExpired); + } + else if (code == 1011 || code == 1022 || code == 1024) + { + if (Timer) + { + timer::kill(Timer); + Timer = 0; + } + } + return 0; +} + + +void TTimer::TimerExpired(int timerId, void* caller) +{ + auto timer = static_cast(caller); + timer->Timer = 0; + control::handler(60, timer); +} diff --git a/SpaceCadetPinball/TTimer.h b/SpaceCadetPinball/TTimer.h index 6ed87a1..175627b 100644 --- a/SpaceCadetPinball/TTimer.h +++ b/SpaceCadetPinball/TTimer.h @@ -1,11 +1,13 @@ #pragma once #include "TPinballComponent.h" + class TTimer : - public TPinballComponent + public TPinballComponent { public: - TTimer(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true) - { - } -}; + TTimer(TPinballTable* table, int groupIndex); + int Message(int code, float value) override; + static void TimerExpired(int timerId, void* caller); + int Timer; +}; diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index d86940f..b539b45 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -11,7 +11,7 @@ rectangle_type fullscrn::WHRect; int fullscrn::fullscrn_flag1; int fullscrn::display_changed; int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2; -int fullscrn::trick; +int fullscrn::trick = 1; int fullscrn::MenuEnabled; HMENU fullscrn::MenuHandle;