diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index 31388c3..bd26638 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/TCircle.cpp b/SpaceCadetPinball/TCircle.cpp index 8800cdc..3d51e94 100644 --- a/SpaceCadetPinball/TCircle.cpp +++ b/SpaceCadetPinball/TCircle.cpp @@ -1,6 +1,10 @@ #include "pch.h" #include "TCircle.h" +#include "TBall.h" +#include "TCollisionComponent.h" +#include "TTableLayer.h" + TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, vector_type* center, float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag) { @@ -24,3 +28,8 @@ void TCircle::EdgeCollision(TBall* ball, float coef) maths::normalize_2d(&direction); CollisionComponent->Collision(ball, &nextPosition, &direction, coef, this); } + +void TCircle::place_in_grid() +{ + TTableLayer::edges_insert_circle(&Circle, this, nullptr); +} diff --git a/SpaceCadetPinball/TCircle.h b/SpaceCadetPinball/TCircle.h index 779128c..a919a77 100644 --- a/SpaceCadetPinball/TCircle.h +++ b/SpaceCadetPinball/TCircle.h @@ -12,8 +12,5 @@ public: float radius); float FindCollisionDistance(ray_type* ray) override; void EdgeCollision(TBall* ball, float coef) override; - - void place_in_grid() override - { - } + void place_in_grid() override; }; diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp index efb9aff..b4f2156 100644 --- a/SpaceCadetPinball/TCollisionComponent.cpp +++ b/SpaceCadetPinball/TCollisionComponent.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "TCollisionComponent.h" #include "loader.h" +#include "maths.h" +#include "objlist_class.h" #include "TEdgeSegment.h" #include "TPinballTable.h" diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h index ba097e7..db891ad 100644 --- a/SpaceCadetPinball/TCollisionComponent.h +++ b/SpaceCadetPinball/TCollisionComponent.h @@ -1,7 +1,7 @@ #pragma once -#include "objlist_class.h" #include "TPinballComponent.h" +class objlist_class; struct vector_type; class TEdgeSegment; class TBall; @@ -20,7 +20,7 @@ public: int SoundIndex1; TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall); - ~TCollisionComponent(); + ~TCollisionComponent() override; void port_draw() override; virtual void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge); diff --git a/SpaceCadetPinball/TEdgeManager.cpp b/SpaceCadetPinball/TEdgeManager.cpp index 0d98a37..a0353e7 100644 --- a/SpaceCadetPinball/TEdgeManager.cpp +++ b/SpaceCadetPinball/TEdgeManager.cpp @@ -1,7 +1,12 @@ #include "pch.h" #include "TEdgeManager.h" + +#include "maths.h" +#include "objlist_class.h" +#include "TBall.h" #include "TEdgeBox.h" +#include "TEdgeSegment.h" #include "TTableLayer.h" TEdgeManager::TEdgeManager(float posX, float posY, float width, float height) @@ -137,129 +142,126 @@ float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegme } } } - else + else if (rayBoxX == rayEndBoxX) { - if (rayBoxX == rayEndBoxX) + if (rayDirY == 1) { - if (rayDirY == 1) + for (auto indexY = rayBoxY; indexY <= rayEndBoxY; indexY++) { - for (auto indexY = rayBoxY; indexY <= rayEndBoxY; indexY++) - { - edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex); - } - } - else - { - for (auto indexY = rayBoxY; indexY >= rayEndBoxY; indexY--) - { - edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex); - } + edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex); } } else { - auto rayDyDX = (rayY - rayEndY) / (rayX - rayEndX); - auto indexX = rayBoxX; - auto indexY = rayBoxY; - auto bresIndexX = rayBoxX + 1; - auto bresIndexY = rayBoxY + 1; - auto bresXAdd = rayY - rayDyDX * rayX; - edgeIndex = TestGridBox(rayBoxX, rayBoxY, &distance, edge, ray, ball, 0); - if (rayDirX == 1) + for (auto indexY = rayBoxY; indexY >= rayEndBoxY; indexY--) { - if (rayDirY == 1) - { - do - { - auto yCoord = bresIndexY * AdvanceY + Y; - auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd; - if (xCoord >= yCoord) - { - if (xCoord == yCoord) - { - ++indexX; - ++bresIndexX; - } - ++indexY; - ++bresIndexY; - } - else - { - ++indexX; - ++bresIndexX; - } - edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); - } - while (indexX < rayEndBoxX || indexY < rayEndBoxY); - } - else + edgeIndex = TestGridBox(rayBoxX, indexY, &distance, edge, ray, ball, edgeIndex); + } + } + } + else + { + auto rayDyDX = (rayY - rayEndY) / (rayX - rayEndX); + auto indexX = rayBoxX; + auto indexY = rayBoxY; + auto bresIndexX = rayBoxX + 1; + auto bresIndexY = rayBoxY + 1; + auto bresXAdd = rayY - rayDyDX * rayX; + edgeIndex = TestGridBox(rayBoxX, rayBoxY, &distance, edge, ray, ball, 0); + if (rayDirX == 1) + { + if (rayDirY == 1) + { + do { - do + auto yCoord = bresIndexY * AdvanceY + Y; + auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd; + if (xCoord >= yCoord) { - auto yCoord = indexY * AdvanceY + Y; - auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd; - if (xCoord <= yCoord) - { - if (xCoord == yCoord) - { - ++indexX; - ++bresIndexX; - } - --indexY; - } - else + if (xCoord == yCoord) { ++indexX; ++bresIndexX; } - edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); + ++indexY; + ++bresIndexY; } - while (indexX < rayEndBoxX || indexY > rayEndBoxY); + else + { + ++indexX; + ++bresIndexX; + } + edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); } + while (indexX < rayEndBoxX || indexY < rayEndBoxY); } else { - if (rayDirY == 1) + do { - do + auto yCoord = indexY * AdvanceY + Y; + auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd; + if (xCoord <= yCoord) { - auto yCoord = bresIndexY * AdvanceY + Y; - auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd; - if (xCoord >= yCoord) + if (xCoord == yCoord) { - if (xCoord == yCoord) - --indexX; - ++indexY; - ++bresIndexY; + ++indexX; + ++bresIndexX; } - else - { - --indexX; - } - edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); + --indexY; } - while (indexX > rayEndBoxX || indexY < rayEndBoxY); + else + { + ++indexX; + ++bresIndexX; + } + edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); } - else + while (indexX < rayEndBoxX || indexY > rayEndBoxY); + } + } + else + { + if (rayDirY == 1) + { + do { - do + auto yCoord = bresIndexY * AdvanceY + Y; + auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd; + if (xCoord >= yCoord) { - auto yCoord = indexY * AdvanceY + Y; - auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd; - if (xCoord <= yCoord) - { - if (xCoord == yCoord) - --indexX; - --indexY; - } - else - { + if (xCoord == yCoord) --indexX; - } - edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); + ++indexY; + ++bresIndexY; } - while (indexX > rayEndBoxX || indexY > rayEndBoxY); + else + { + --indexX; + } + edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); } + while (indexX > rayEndBoxX || indexY < rayEndBoxY); + } + else + { + do + { + auto yCoord = indexY * AdvanceY + Y; + auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd; + if (xCoord <= yCoord) + { + if (xCoord == yCoord) + --indexX; + --indexY; + } + else + { + --indexX; + } + edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex); + } + while (indexX > rayEndBoxX || indexY > rayEndBoxY); } } } diff --git a/SpaceCadetPinball/TEdgeManager.h b/SpaceCadetPinball/TEdgeManager.h index d203862..00fb1b2 100644 --- a/SpaceCadetPinball/TEdgeManager.h +++ b/SpaceCadetPinball/TEdgeManager.h @@ -1,7 +1,7 @@ #pragma once #include "TCollisionComponent.h" -#include "TEdgeSegment.h" +struct ray_type; class TEdgeBox; struct field_effect_type diff --git a/SpaceCadetPinball/TEdgeSegment.cpp b/SpaceCadetPinball/TEdgeSegment.cpp index 2ab031a..da1cfbf 100644 --- a/SpaceCadetPinball/TEdgeSegment.cpp +++ b/SpaceCadetPinball/TEdgeSegment.cpp @@ -1,14 +1,17 @@ #include "pch.h" #include "TEdgeSegment.h" + +#include "objlist_class.h" #include "TCircle.h" +#include "TCollisionComponent.h" #include "TLine.h" TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag) { - this->CollisionComponent = collComp; - this->PinbCompFlag2Ptr = someFlag; - this->VisualFlag = visualFlag; - this->ProcessedFlag = 0; + CollisionComponent = collComp; + PinbCompFlag2Ptr = someFlag; + VisualFlag = visualFlag; + ProcessedFlag = 0; } void TEdgeSegment::port_draw() diff --git a/SpaceCadetPinball/TEdgeSegment.h b/SpaceCadetPinball/TEdgeSegment.h index cf2ac91..4cec022 100644 --- a/SpaceCadetPinball/TEdgeSegment.h +++ b/SpaceCadetPinball/TEdgeSegment.h @@ -1,7 +1,8 @@ #pragma once -#include "TCollisionComponent.h" -#include "maths.h" -#include "TBall.h" + +class TBall; +class TCollisionComponent; +struct ray_type; enum class wall_type : int { diff --git a/SpaceCadetPinball/TLightRollover.cpp b/SpaceCadetPinball/TLightRollover.cpp index 71e40f3..1b2cbe9 100644 --- a/SpaceCadetPinball/TLightRollover.cpp +++ b/SpaceCadetPinball/TLightRollover.cpp @@ -1,2 +1,71 @@ #include "pch.h" #include "TLightRollover.h" + + +#include "control.h" +#include "loader.h" +#include "render.h" +#include "TBall.h" +#include "timer.h" +#include "TPinballTable.h" +#include "TZmapList.h" + +TLightRollover::TLightRollover(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, false) +{ + RolloverFlag = 0; + Timer = 0; + if (ListBitmap != nullptr) + render::sprite_set_bitmap(RenderSprite, nullptr); + build_walls(groupIndex); + FloatArr = *loader::query_float_attribute(groupIndex, 0, 407); +} + +int TLightRollover::Message(int code, float value) +{ + if (code == 1024) + { + UnknownBaseFlag2 = 1; + RolloverFlag = 0; + if (Timer) + timer::kill(Timer); + Timer = 0; + if (ListBitmap) + render::sprite_set_bitmap(RenderSprite, nullptr); + } + return 0; +} + +void TLightRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) +{ + ball->Position.X = nextPosition->X; + ball->Position.Y = nextPosition->Y; + ball->RayMaxDistance -= coef; + ball->not_again(edge); + if (!PinballTable->TiltLockFlag) + { + if (RolloverFlag) + { + timer::set(0.1f, this, TimerExpired); + UnknownBaseFlag2 = 0; + RolloverFlag = RolloverFlag == 0; + if (Timer == 0) + Timer = timer::set(FloatArr, this, delay_expired); + } + else + { + loader::play_sound(SoundIndex2); + control::handler(63, this); + RolloverFlag = RolloverFlag == 0; + if (ListBitmap) + render::sprite_set_bitmap(RenderSprite, static_cast(ListBitmap->Get(0))); + } + } +} + +void TLightRollover::delay_expired(int timerId, void* caller) +{ + auto roll = static_cast(caller); + render::sprite_set_bitmap(roll->RenderSprite, nullptr); + roll->Timer = 0; +} diff --git a/SpaceCadetPinball/TLightRollover.h b/SpaceCadetPinball/TLightRollover.h index 886e1ac..52a8d5b 100644 --- a/SpaceCadetPinball/TLightRollover.h +++ b/SpaceCadetPinball/TLightRollover.h @@ -5,7 +5,14 @@ class TLightRollover : public TRollover { public: - TLightRollover(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex) - { - } + TLightRollover(TPinballTable* table, int groupIndex); + ~TLightRollover() override = default; + int Message(int code, float value) override; + void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) override; + + static void delay_expired(int timerId, void* caller); + + float FloatArr; + int Timer; }; diff --git a/SpaceCadetPinball/TLine.cpp b/SpaceCadetPinball/TLine.cpp index e67707b..71f45e9 100644 --- a/SpaceCadetPinball/TLine.cpp +++ b/SpaceCadetPinball/TLine.cpp @@ -53,10 +53,11 @@ void TLine::EdgeCollision(TBall* ball, float coef) void TLine::place_in_grid() { - auto xBox0 = TTableLayer::edge_manager->box_x(X0); - auto yBox0 = TTableLayer::edge_manager->box_y(Y0); - auto xBox1 = TTableLayer::edge_manager->box_x(X1); - auto yBox1 = TTableLayer::edge_manager->box_y(Y1); + auto edgeMan = TTableLayer::edge_manager; + auto xBox0 = edgeMan->box_x(X0); + auto yBox0 = edgeMan->box_y(Y0); + auto xBox1 = edgeMan->box_x(X1); + auto yBox1 = edgeMan->box_y(Y1); int dirX = X0 >= X1 ? -1 : 1; int dirY = Y0 >= Y1 ? -1 : 1; @@ -66,12 +67,12 @@ void TLine::place_in_grid() if (dirX == 1) { while (xBox0 <= xBox1) - TTableLayer::edge_manager->add_edge_to_box(xBox0++, yBox0, this); + edgeMan->add_edge_to_box(xBox0++, yBox0, this); } else { while (xBox0 >= xBox1) - TTableLayer::edge_manager->add_edge_to_box(xBox0--, yBox0, this); + edgeMan->add_edge_to_box(xBox0--, yBox0, this); } } else if (xBox0 == xBox1) @@ -81,14 +82,14 @@ void TLine::place_in_grid() if (yBox0 <= yBox1) { do - TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0++, this); + edgeMan->add_edge_to_box(xBox0, yBox0++, this); while (yBox0 <= yBox1); } } else if (yBox0 >= yBox1) { do - TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0--, this); + edgeMan->add_edge_to_box(xBox0, yBox0--, this); while (yBox0 >= yBox1); } } @@ -99,16 +100,15 @@ void TLine::place_in_grid() int bresIndexX = xBox0 + 1, bresIndexY = yBox0 + 1; auto bresDyDx = (Y0 - Y1) / (X0 - X1); auto bresXAdd = Y0 - bresDyDx * X0; - TTableLayer::edge_manager->add_edge_to_box(xBox0, yBox0, this); + edgeMan->add_edge_to_box(xBox0, yBox0, this); if (dirX == 1) { if (dirY == 1) { do { - yCoord = bresIndexY * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; - xCoord = (bresIndexX * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * - bresDyDx + bresXAdd; + yCoord = bresIndexY * edgeMan->AdvanceY + edgeMan->Y; + xCoord = (bresIndexX * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd; if (xCoord >= yCoord) { if (xCoord == yCoord) @@ -124,7 +124,7 @@ void TLine::place_in_grid() ++indexX1; ++bresIndexX; } - TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); + edgeMan->add_edge_to_box(indexX1, indexY1, this); } while (indexX1 != xBox1 || indexY1 != yBox1); } @@ -132,9 +132,8 @@ void TLine::place_in_grid() { do { - yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; - xCoord = (bresIndexX * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * - bresDyDx + bresXAdd; + yCoord = indexY1 * edgeMan->AdvanceY + edgeMan->Y; + xCoord = (bresIndexX * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd; if (xCoord <= yCoord) { if (xCoord == yCoord) @@ -149,7 +148,7 @@ void TLine::place_in_grid() ++indexX1; ++bresIndexX; } - TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); + edgeMan->add_edge_to_box(indexX1, indexY1, this); } while (indexX1 != xBox1 || indexY1 != yBox1); } @@ -160,9 +159,8 @@ void TLine::place_in_grid() { do { - xCoord = bresIndexY * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; - yCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * - bresDyDx + bresXAdd; + xCoord = bresIndexY * edgeMan->AdvanceY + edgeMan->Y; + yCoord = (indexX1 * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd; if (yCoord >= xCoord) { if (yCoord == xCoord) @@ -174,7 +172,7 @@ void TLine::place_in_grid() { --indexX1; } - TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); + edgeMan->add_edge_to_box(indexX1, indexY1, this); } while (indexX1 != xBox1 || indexY1 != yBox1); } @@ -182,9 +180,8 @@ void TLine::place_in_grid() { do { - yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y; - xCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) * - bresDyDx + bresXAdd; + yCoord = indexY1 * edgeMan->AdvanceY + edgeMan->Y; + xCoord = (indexX1 * edgeMan->AdvanceX + edgeMan->X) * bresDyDx + bresXAdd; if (xCoord <= yCoord) { if (xCoord == yCoord) @@ -195,7 +192,7 @@ void TLine::place_in_grid() { --indexX1; } - TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this); + edgeMan->add_edge_to_box(indexX1, indexY1, this); } while (indexX1 != xBox1 || indexY1 != yBox1); } diff --git a/SpaceCadetPinball/TOneway.cpp b/SpaceCadetPinball/TOneway.cpp index 6ead957..5454756 100644 --- a/SpaceCadetPinball/TOneway.cpp +++ b/SpaceCadetPinball/TOneway.cpp @@ -1,2 +1,86 @@ #include "pch.h" #include "TOneway.h" + + +#include "control.h" +#include "loader.h" +#include "objlist_class.h" +#include "TBall.h" +#include "TLine.h" +#include "TPinballTable.h" + +TOneway::TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) +{ + visualStruct visual{}; + vector_type linePt1{}, linePt2{}; + + loader::query_visual(groupIndex, 0, &visual); + if (visual.FloatArrCount == 2) + { + linePt2.X = visual.FloatArr[0]; + linePt2.Y = visual.FloatArr[1]; + linePt1.X = visual.FloatArr[2]; + linePt1.Y = visual.FloatArr[3]; + + auto line = new TLine(this, &UnknownBaseFlag2, visual.Flag, &linePt2, &linePt1); + if (line) + { + line->Offset(table->CollisionCompOffset); + line->place_in_grid(); + EdgeList->Add(line); + } + + line = new TLine(this, &UnknownBaseFlag2, visual.Flag, &linePt1, &linePt2); + Line = line; + if (line) + { + line->Offset(-table->CollisionCompOffset * 0.8f); + Line->place_in_grid(); + EdgeList->Add(Line); + } + } +} + +void TOneway::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge) +{ + if (edge == Line) + { + ball->not_again(edge); + ball->Position.X = nextPosition->X; + ball->Position.Y = nextPosition->Y; + ball->RayMaxDistance -= coef; + if (!PinballTable->TiltLockFlag) + { + if (SoundIndex1) + loader::play_sound(SoundIndex1); + control::handler(63, this); + } + } + else if (PinballTable->TiltLockFlag) + { + maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, 1000000000.0, 0.0); + } + else if (maths::basic_collision( + ball, + nextPosition, + direction, + UnknownC4F, + UnknownC5F, + MaxCollisionSpeed, + CollisionMultiplier) > 0.2) + { + if (SoundIndex2) + loader::play_sound(SoundIndex2); + } +} + +void TOneway::put_scoring(int index, int score) +{ + if (index < 6) + Scores[index] = score; +} + +int TOneway::get_scoring(int index) +{ + return index < 6 ? Scores[index] : 0; +} diff --git a/SpaceCadetPinball/TOneway.h b/SpaceCadetPinball/TOneway.h index fa20778..ea9f316 100644 --- a/SpaceCadetPinball/TOneway.h +++ b/SpaceCadetPinball/TOneway.h @@ -1,11 +1,18 @@ #pragma once #include "TCollisionComponent.h" -class TOneway : - public TCollisionComponent +class TLine; + +class TOneway : public TCollisionComponent { public: - TOneway(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) - { - } + TOneway(TPinballTable* table, int groupIndex); + ~TOneway() override = default; + void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) override; + void put_scoring(int index, int score) override; + int get_scoring(int index) override; + + TLine* Line; + int Scores[6]; }; diff --git a/SpaceCadetPinball/TPinballComponent.cpp b/SpaceCadetPinball/TPinballComponent.cpp index 9ceb066..e312144 100644 --- a/SpaceCadetPinball/TPinballComponent.cpp +++ b/SpaceCadetPinball/TPinballComponent.cpp @@ -101,11 +101,11 @@ void TPinballComponent::port_draw() { } -void TPinballComponent::put_scoring(int scoreId, int value) +void TPinballComponent::put_scoring(int index, int score) { } -int TPinballComponent::get_scoring(int score1) +int TPinballComponent::get_scoring(int index) { return 0; } diff --git a/SpaceCadetPinball/TPinballComponent.h b/SpaceCadetPinball/TPinballComponent.h index c5db926..25daaa5 100644 --- a/SpaceCadetPinball/TPinballComponent.h +++ b/SpaceCadetPinball/TPinballComponent.h @@ -17,8 +17,8 @@ public: virtual ~TPinballComponent(); virtual int Message(int code, float value); virtual void port_draw(); - virtual void put_scoring(int scoreId, int value); - virtual int get_scoring(int score1); + virtual void put_scoring(int index, int score); + virtual int get_scoring(int index); __int8 UnknownBaseFlag1; __int8 UnknownBaseFlag2; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index aebcbc5..1805ff8 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -5,6 +5,7 @@ #include "control.h" #include "loader.h" #include "memory.h" +#include "objlist_class.h" #include "pb.h" #include "pinball.h" #include "render.h" diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index 1b538b3..11d4bbf 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -26,7 +26,7 @@ class TPinballTable : public TPinballComponent { public: TPinballTable(); - ~TPinballTable(); + ~TPinballTable() override; TPinballComponent* find_component(LPCSTR componentName); TPinballComponent* find_component(int groupIndex); int AddScore(int score); diff --git a/SpaceCadetPinball/TPlunger.h b/SpaceCadetPinball/TPlunger.h index 5ce1bdc..9419239 100644 --- a/SpaceCadetPinball/TPlunger.h +++ b/SpaceCadetPinball/TPlunger.h @@ -6,6 +6,7 @@ class TPlunger : { public: TPlunger(TPinballTable* table, int groupIndex); + ~TPlunger() override = default; void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge) override; int Message(int code, float value) override; diff --git a/SpaceCadetPinball/TRollover.cpp b/SpaceCadetPinball/TRollover.cpp index 2dd2273..f1f3faa 100644 --- a/SpaceCadetPinball/TRollover.cpp +++ b/SpaceCadetPinball/TRollover.cpp @@ -1,2 +1,99 @@ #include "pch.h" #include "TRollover.h" + + +#include "control.h" +#include "gdrv.h" +#include "loader.h" +#include "render.h" +#include "TBall.h" +#include "TEdgeSegment.h" +#include "timer.h" +#include "TPinballTable.h" +#include "TZmapList.h" + +TRollover::TRollover(TPinballTable* table, int groupIndex, bool createWall) : TCollisionComponent( + table, groupIndex, createWall) +{ +} + + +TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) +{ + RolloverFlag = 0; + if (ListBitmap) + render::sprite_set_bitmap(RenderSprite, static_cast(ListBitmap->Get(0))); + build_walls(groupIndex); +} + + +int TRollover::Message(int code, float value) +{ + if (code == 1024) + { + this->UnknownBaseFlag2 = 1; + this->RolloverFlag = 0; + if (this->ListBitmap) + render::sprite_set_bitmap(this->RenderSprite, static_cast(this->ListBitmap->Get(0))); + } + return 0; +} + +void TRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) +{ + ball->Position.X = nextPosition->X; + ball->Position.Y = nextPosition->Y; + ball->RayMaxDistance -= coef; + ball->not_again(edge); + gdrv_bitmap8* bmp = nullptr; + if (!PinballTable->TiltLockFlag) + { + if (RolloverFlag) + { + timer::set(0.1f, this, TimerExpired); + UnknownBaseFlag2 = 0; + } + else + { + loader::play_sound(SoundIndex2); + control::handler(63, this); + } + RolloverFlag = RolloverFlag == 0; + if (ListBitmap) + { + if (!RolloverFlag) + bmp = static_cast(ListBitmap->Get(0)); + render::sprite_set_bitmap(RenderSprite, bmp); + } + } +} + +void TRollover::put_scoring(int index, int score) +{ + if (index < 2) + Scores[index] = score; +} + +int TRollover::get_scoring(int index) +{ + return index < 2 ? Scores[index] : 0; +} + + +void TRollover::build_walls(int groupIndex) +{ + visualStruct visual{}; + + loader::query_visual(groupIndex, 0, &visual); + float* arr1 = loader::query_float_attribute(groupIndex, 0, 600); + TEdgeSegment::install_wall(arr1, this, &UnknownBaseFlag2, visual.Flag, 0.0, 600); + float* arr2 = loader::query_float_attribute(groupIndex, 0, 603); + TEdgeSegment::install_wall(arr2, this, &RolloverFlag, visual.Flag, 0.0, 603); +} + +void TRollover::TimerExpired(int timerId, void* caller) +{ + auto roll = static_cast(caller); + roll->UnknownBaseFlag2 = 1; +} diff --git a/SpaceCadetPinball/TRollover.h b/SpaceCadetPinball/TRollover.h index cf993a5..b6ac262 100644 --- a/SpaceCadetPinball/TRollover.h +++ b/SpaceCadetPinball/TRollover.h @@ -4,8 +4,20 @@ class TRollover : public TCollisionComponent { +protected: + TRollover(TPinballTable* table, int groupIndex, bool createWall); public: - TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true) - { - } + TRollover(TPinballTable* table, int groupIndex); + ~TRollover() override = default; + int Message(int code, float value) override; + void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) override; + void put_scoring(int index, int score) override; + int get_scoring(int index) override; + void build_walls(int groupIndex); + + static void TimerExpired(int timerId, void* caller); + + char RolloverFlag; + int Scores[2]; }; diff --git a/SpaceCadetPinball/TTableLayer.cpp b/SpaceCadetPinball/TTableLayer.cpp index f3bd644..ce0b8ff 100644 --- a/SpaceCadetPinball/TTableLayer.cpp +++ b/SpaceCadetPinball/TTableLayer.cpp @@ -2,8 +2,10 @@ #include "TTableLayer.h" #include "loader.h" +#include "objlist_class.h" #include "proj.h" #include "render.h" +#include "TBall.h" #include "TLine.h" #include "TPinballTable.h" @@ -114,8 +116,8 @@ int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst) void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge, field_effect_type* field) { - float widthM = edge_manager->AdvanceX * 0.001f; - float heightM = edge_manager->AdvanceY * 0.001f; + float widthM = static_cast(static_cast(edge_manager->AdvanceX * 0.001f)); // Sic + float heightM = static_cast(static_cast(edge_manager->AdvanceY * 0.001f)); float xMin = x0 - widthM; float xMax = x1 + widthM; float yMin = y0 - heightM; @@ -127,10 +129,9 @@ void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TE int yMaxBox = edge_manager->box_y(yMax); float boxX = static_cast(xMinBox) * edge_manager->AdvanceX + edge_manager->X; - float boxY = static_cast(yMinBox) * edge_manager->AdvanceY + edge_manager->Y; - for (int indexX = xMinBox; indexX <= xMaxBox; ++indexX) { + float boxY = static_cast(yMinBox) * edge_manager->AdvanceY + edge_manager->Y; for (int indexY = yMinBox; indexY <= yMaxBox; ++indexY) { if (xMax >= boxX && xMin <= boxX + edge_manager->AdvanceX && @@ -150,3 +151,127 @@ void TTableLayer::edges_insert_square(float y0, float x0, float y1, float x1, TE boxX += edge_manager->AdvanceX; } } + +void TTableLayer::edges_insert_circle(circle_type* circle, TEdgeSegment* edge, field_effect_type* field) +{ + ray_type ray{}; + vector_type vec1{}; + + auto radiusM = sqrt(circle->RadiusSq) + edge_manager->AdvanceX * 0.001f; + auto radiusMSq = radiusM * radiusM; + + auto xMin = circle->Center.X - radiusM; + auto yMin = circle->Center.Y - radiusM; + auto xMax = radiusM + circle->Center.X; + auto yMax = radiusM + circle->Center.Y; + + auto xMinBox = edge_manager->box_x(xMin); + auto yMinBox = edge_manager->box_y(yMin); + auto xMaxBox = edge_manager->box_x(xMax); + auto yMaxBox = edge_manager->box_y(yMax); + + auto dirX = xMinBox - 1 <= 0 ? 0 : xMinBox - 1; + auto dirY = yMinBox - 1 <= 0 ? 0 : yMinBox - 1; + + xMaxBox = edge_manager->increment_box_x(xMaxBox); + yMaxBox = edge_manager->increment_box_y(yMaxBox); + + vec1.X = static_cast(dirX) * edge_manager->AdvanceX + edge_manager->X; + for (auto indexX = dirX; indexX <= xMaxBox; ++indexX) + { + vec1.Y = static_cast(dirY) * edge_manager->AdvanceY + edge_manager->Y; + for (int indexY = dirY; indexY <= yMaxBox; ++indexY) + { + auto vec1XAdv = vec1.X + edge_manager->AdvanceX; + auto vec1YAdv = vec1.Y + edge_manager->AdvanceY; + if (xMax >= vec1.X && xMin <= vec1XAdv && + yMax >= vec1.Y && yMin <= vec1YAdv) + { + bool collision = true; + do + { + if (circle->Center.X <= vec1XAdv && circle->Center.X >= vec1.X && + circle->Center.Y <= vec1YAdv && circle->Center.Y >= vec1.Y) + break; + + auto vec2 = vec1; + if (maths::Distance_Squared(vec1, circle->Center) <= radiusMSq) + break; + + vec2.X = vec2.X + edge_manager->AdvanceX; + if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq) + break; + + vec2.Y = vec2.Y + edge_manager->AdvanceY; + if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq) + break; + + vec2.X = vec2.X - edge_manager->AdvanceX; + if (maths::Distance_Squared(vec2, circle->Center) <= radiusMSq) + break; + + ray.Origin = vec1; + ray.Direction.X = 1.0; + ray.Direction.Y = 0.0; + ray.MaxDistance = edge_manager->AdvanceX; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.X = -1.0; + ray.Origin.X = ray.Origin.X + edge_manager->AdvanceX; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.X = 0.0; + ray.Direction.Y = 1.0; + ray.MaxDistance = edge_manager->AdvanceY; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.Y = -1.0; + ray.Origin.Y = ray.Origin.Y + edge_manager->AdvanceY; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.Y = 0.0; + ray.Direction.X = -1.0; + ray.MaxDistance = edge_manager->AdvanceX; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.X = 1.0; + ray.Origin.X = ray.Origin.X - edge_manager->AdvanceX; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.X = 0.0; + ray.Direction.Y = -1.0; + ray.MaxDistance = edge_manager->AdvanceY; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + ray.Direction.Y = 1.0; + ray.Origin.Y = ray.Origin.Y - edge_manager->AdvanceY; + if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) + break; + + collision = false; + } + while (false); + if (collision) + { + if (edge) + { + edge_manager->add_edge_to_box(indexX, indexY, edge); + } + if (field) + { + edge_manager->add_field_to_box(indexX, indexY, field); + } + } + } + vec1.Y += edge_manager->AdvanceY; + } + vec1.X += edge_manager->AdvanceX; + } +} diff --git a/SpaceCadetPinball/TTableLayer.h b/SpaceCadetPinball/TTableLayer.h index d8bf9a9..d858ab0 100644 --- a/SpaceCadetPinball/TTableLayer.h +++ b/SpaceCadetPinball/TTableLayer.h @@ -3,6 +3,7 @@ #include "TEdgeManager.h" +struct circle_type; class TPinballTable; class TEdgeManager; struct gdrv_bitmap8; @@ -10,14 +11,15 @@ struct gdrv_bitmap8; class TTableLayer : public TCollisionComponent { -public: +public: TTableLayer(TPinballTable* table); ~TTableLayer() override; int FieldEffect(TBall* ball, vector_type* vecDst) override; static void edges_insert_square(float y0, float x0, float y1, float x1, TEdgeSegment* edge, - field_effect_type* field); - + field_effect_type* field); + static void edges_insert_circle(circle_type* circle, TEdgeSegment* edge, field_effect_type* field); + gdrv_bitmap8* VisBmp; float Unknown1F; float Unknown2F; diff --git a/SpaceCadetPinball/TTripwire.cpp b/SpaceCadetPinball/TTripwire.cpp index ae80677..0e4dfc0 100644 --- a/SpaceCadetPinball/TTripwire.cpp +++ b/SpaceCadetPinball/TTripwire.cpp @@ -1,2 +1,25 @@ #include "pch.h" #include "TTripwire.h" + +#include "control.h" +#include "loader.h" +#include "TBall.h" +#include "TPinballTable.h" + +TTripwire::TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, 1) +{ +} + +void TTripwire::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) +{ + ball->Position.X = nextPosition->X; + ball->Position.Y = nextPosition->Y; + ball->RayMaxDistance -= coef; + ball->not_again(edge); + if (!PinballTable->TiltLockFlag) + { + loader::play_sound(SoundIndex2); + control::handler(63, this); + } +} diff --git a/SpaceCadetPinball/TTripwire.h b/SpaceCadetPinball/TTripwire.h index 3b156e3..d886ec8 100644 --- a/SpaceCadetPinball/TTripwire.h +++ b/SpaceCadetPinball/TTripwire.h @@ -5,7 +5,8 @@ class TTripwire : public TRollover { public: - TTripwire(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex) - { - } + TTripwire(TPinballTable* table, int groupIndex); + ~TTripwire() override = default; + void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, + TEdgeSegment* edge) override; }; diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index d6735df..26ad38d 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -836,10 +836,32 @@ void control::RightKickerGateControl(int code, TPinballComponent* caller) void control::DeploymentChuteToEscapeChuteOneWayControl(int code, TPinballComponent* caller) { + char Buffer[64]; + if (code == 63) + { + int count = control_skill_shot_lights_tag.Component->Message(37, 0.0); + if (count) + { + static_cast(control_soundwave3_tag.Component)->Play(); + int score = TableG->AddScore(caller->get_scoring(count - 1)); + sprintf_s(Buffer, pinball::get_rc_string(21, 0), score); + static_cast(control_info_text_box_tag.Component)->Display(Buffer, 2.0); + if (!light_on(&control_lite56_tag)) + { + control_l_trek_lights_tag.Component->Message(34, 0.0); + control_l_trek_lights_tag.Component->Message(20, 0.0); + control_r_trek_lights_tag.Component->Message(34, 0.0); + control_r_trek_lights_tag.Component->Message(20, 0.0); + } + control_skill_shot_lights_tag.Component->Message(44, 1.0); + } + } } void control::DeploymentChuteToTableOneWayControl(int code, TPinballComponent* caller) { + if (code == 63) + control_skill_shot_lights_tag.Component->Message(20, 0.0); } void control::DrainBallBlockerControl(int code, TPinballComponent* caller) diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 317eb0f..3591832 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -299,3 +299,8 @@ float maths::basic_collision(TBall* ball, vector_type* nextPosition, vector_type } return projSpeed; } + +float maths::Distance_Squared(vector_type vec1, vector_type vec2) +{ + return (vec1.Y - vec2.Y) * (vec1.Y - vec2.Y) + (vec1.X - vec2.X) * (vec1.X - vec2.X); +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index ed5752f..a1fd4a1 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -42,7 +42,7 @@ struct __declspec(align(4)) line_type float PreComp1; float OriginX; float OriginY; - vector_type RayIntersect; + vector_type RayIntersect; }; @@ -59,5 +59,7 @@ public: static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec); static float magnitude(vector_type* vec); static void vector_add(vector_type* vec1Dst, vector_type* vec2); - static float basic_collision(TBall* ball, struct vector_type* nextPosition, struct vector_type* direction, float a4, float a5, float maxSpeed, float multiplier); + static float basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5, + float maxSpeed, float multiplier); + static float Distance_Squared(vector_type vec1, vector_type vec2); }; diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 371e460..1bcb665 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -11,12 +11,14 @@ #include "loader.h" #include "midi.h" #include "nudge.h" +#include "objlist_class.h" #include "options.h" #include "timer.h" #include "winmain.h" #include "resource.h" #include "TBall.h" #include "TDemo.h" +#include "TEdgeSegment.h" #include "TLightGroup.h" #include "TPlunger.h" #include "TTableLayer.h" @@ -623,6 +625,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball) TEdgeSegment* edge = nullptr; auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); + ball->EdgeCollisionCount = 0; if (distance >= 1000000000.0) { maxDistance = timeDelta * ball->Speed;