diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx
index 5aa3f46..8a91eb6 100644
Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ
diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
index 8a4faae..7317e0e 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
+++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
@@ -220,7 +220,7 @@
Header Files\TPinballComponent
- Header Files
+ Header Files\TEdgeSegment
@@ -408,7 +408,7 @@
Source Files\TPinballComponent
- Source Files
+ Source Files\TEdgeSegment
diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp
index d515cd4..690892d 100644
--- a/SpaceCadetPinball/TFlipper.cpp
+++ b/SpaceCadetPinball/TFlipper.cpp
@@ -1,2 +1,188 @@
#include "pch.h"
#include "TFlipper.h"
+
+
+#include "control.h"
+#include "loader.h"
+#include "pb.h"
+#include "render.h"
+#include "TFlipperEdge.h"
+#include "timer.h"
+#include "TZmapList.h"
+
+TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
+{
+ visualStruct visual{};
+
+ loader::query_visual(groupIndex, 0, &visual);
+ SoundIndex1 = visual.SoundIndex4;
+ SoundIndex2 = visual.SoundIndex3;
+ UnknownC4F = visual.Unknown2F;
+ Timer = 0;
+ UnknownC5F = visual.Unknown1F;
+
+ auto floatArr = loader::query_float_attribute(groupIndex, 0, 803);
+ auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 805);
+ auto floatArr3 = loader::query_float_attribute(groupIndex, 0, 804);
+ auto collMult = *floatArr;
+ auto bmpCoef2 = *floatArr2;
+ auto bmpCoef1 = *floatArr3;
+ auto vecT2 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 802));
+ auto vecT1 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 801));
+ auto origin = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 800));
+ auto flipperEdge = new TFlipperEdge(
+ this,
+ &UnknownBaseFlag2,
+ visual.Flag,
+ table,
+ origin,
+ vecT1,
+ vecT2,
+ bmpCoef1,
+ bmpCoef2,
+ collMult,
+ UnknownC4F,
+ UnknownC5F);
+
+ FlipperEdge = flipperEdge;
+ if (flipperEdge)
+ {
+ BmpCoef1 = flipperEdge->BmpCoef1 / static_cast(ListBitmap->Count() - 1);
+ BmpCoef2 = flipperEdge->BmpCoef2 / static_cast(ListBitmap->Count() - 1);
+ }
+ BmpIndex = 0;
+ InputTime = 0.0;
+}
+
+TFlipper::~TFlipper()
+{
+ delete FlipperEdge;
+}
+
+int TFlipper::Message(int code, float value)
+{
+ if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022)
+ {
+ float timerTime;
+ int soundIndex = 0, code2 = code;
+ if (code == 1)
+ {
+ control::handler(1, this);
+ TimerTime = BmpCoef1;
+ soundIndex = SoundIndex1;
+ }
+ else if (code == 2)
+ {
+ TimerTime = BmpCoef2;
+ soundIndex = SoundIndex2;
+ }
+ else
+ {
+ code2 = 2;
+ TimerTime = BmpCoef2;
+ }
+
+ if (soundIndex)
+ loader::play_sound(soundIndex);
+ if (Timer)
+ {
+ timer::kill(Timer);
+ Timer = 0;
+ }
+ if (MessageField)
+ {
+ auto v10 = value - FlipperEdge->InputTime;
+ timerTime = v10 - floor(v10 / TimerTime) * TimerTime;
+ if (timerTime < 0.0)
+ timerTime = 0.0;
+ }
+ else
+ {
+ timerTime = TimerTime;
+ }
+ MessageField = code2;
+ InputTime = value;
+ Timer = timer::set(timerTime, this, TimerExpired);
+ FlipperEdge->SetMotion(code2, value);
+ }
+
+ if (code == 1020 || code == 1024)
+ {
+ if (MessageField)
+ {
+ if (Timer)
+ timer::kill(Timer);
+ BmpIndex = -1;
+ MessageField = 2;
+ TimerExpired(Timer, this);
+ FlipperEdge->SetMotion(code, value);
+ }
+ }
+ return 0;
+}
+
+void TFlipper::port_draw()
+{
+ FlipperEdge->port_draw();
+}
+
+void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
+{
+}
+
+void TFlipper::TimerExpired(int timerId, void* caller)
+{
+ auto flip = static_cast(caller);
+ int timer; // eax
+
+ bool bmpIndexOutOfBounds = false;
+ auto bmpIndexAdvance = static_cast(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f));
+ int bmpCount = flip->ListBitmap->Count();
+ if (bmpIndexAdvance > bmpCount)
+ bmpIndexAdvance = bmpCount;
+ if (bmpIndexAdvance < 0)
+ bmpIndexAdvance = 0;
+
+ if (!bmpIndexAdvance)
+ bmpIndexAdvance = 1;
+
+ if (flip->MessageField == 1)
+ {
+ flip->BmpIndex += bmpIndexAdvance;
+ int countSub1 = flip->ListBitmap->Count() - 1;
+ if (flip->BmpIndex >= countSub1)
+ {
+ flip->BmpIndex = countSub1;
+ bmpIndexOutOfBounds = true;
+ }
+ }
+ if (flip->MessageField == 2)
+ {
+ flip->BmpIndex -= bmpIndexAdvance;
+ timer = 0;
+ if (flip->BmpIndex <= 0)
+ {
+ flip->BmpIndex = 0;
+ bmpIndexOutOfBounds = true;
+ }
+ }
+ else
+ {
+ timer = 0;
+ }
+
+ if (bmpIndexOutOfBounds)
+ flip->MessageField = 0;
+ else
+ timer = timer::set(flip->TimerTime, flip, TimerExpired);
+ flip->Timer = timer;
+
+ auto bmp = static_cast(flip->ListBitmap->Get(flip->BmpIndex));
+ auto zMap = static_cast(flip->ListZMap->Get(flip->BmpIndex));
+ render::sprite_set(
+ flip->RenderSprite,
+ bmp,
+ zMap,
+ bmp->XPosition - flip->PinballTable->XOffset,
+ bmp->YPosition - flip->PinballTable->YOffset);
+}
diff --git a/SpaceCadetPinball/TFlipper.h b/SpaceCadetPinball/TFlipper.h
index ebd59bd..1f830d2 100644
--- a/SpaceCadetPinball/TFlipper.h
+++ b/SpaceCadetPinball/TFlipper.h
@@ -1,11 +1,26 @@
#pragma once
#include "TCollisionComponent.h"
+class TFlipperEdge;
+
class TFlipper :
public TCollisionComponent
{
public:
- TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
- {
- }
+ TFlipper(TPinballTable* table, int groupIndex);
+ ~TFlipper() override;
+ int Message(int code, float value) override;
+ void port_draw() override;
+ void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
+ TEdgeSegment* edge) override;
+
+ static void TimerExpired(int timerId, void* caller);
+
+ int BmpIndex;
+ TFlipperEdge* FlipperEdge;
+ int Timer;
+ float BmpCoef1;
+ float BmpCoef2;
+ float TimerTime;
+ float InputTime;
};
diff --git a/SpaceCadetPinball/TFlipperEdge.cpp b/SpaceCadetPinball/TFlipperEdge.cpp
index a32f9d9..2187f5f 100644
--- a/SpaceCadetPinball/TFlipperEdge.cpp
+++ b/SpaceCadetPinball/TFlipperEdge.cpp
@@ -12,8 +12,8 @@ line_type TFlipperEdge::lineA, TFlipperEdge::lineB;
circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1;
TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table,
- vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2,
- float a11, float c4F, float c5F): TEdgeSegment(collComp, someFlag, visualFlag)
+ vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2,
+ float collMult, float c4F, float c5F): TEdgeSegment(collComp, someFlag, visualFlag)
{
vector_type crossProd{}, vecDir1{}, vecDir2{};
@@ -21,10 +21,10 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
CollisionC5F = c5F;
BmpCoef1 = bmpCoef1;
BmpCoef2 = bmpCoef2;
- Unknown32F = a11;
+ CollisionMult = collMult;
- T1Src = *vecT;
- Unknown36V = *vec3;
+ T1Src = *vecT1;
+ T2Src = *vecT2;
RotOrigin.X = origin->X;
RotOrigin.Y = origin->Y;
@@ -32,17 +32,17 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
CirclebaseRadiusMSq = CirclebaseRadius * 1.01f * (CirclebaseRadius * 1.01f);
CirclebaseRadiusSq = CirclebaseRadius * CirclebaseRadius;
- CircleT1Radius = vecT->Z + table->CollisionCompOffset;
+ CircleT1Radius = vecT1->Z + table->CollisionCompOffset;
CircleT1RadiusMSq = CircleT1Radius * 1.01f * (CircleT1Radius * 1.01f);
CircleT1RadiusSq = CircleT1Radius * CircleT1Radius;
- vecDir1.X = vecT->X - origin->X;
- vecDir1.Y = vecT->Y - origin->Y;
+ vecDir1.X = vecT1->X - origin->X;
+ vecDir1.Y = vecT1->Y - origin->Y;
vecDir1.Z = 0.0;
maths::normalize_2d(&vecDir1);
- vecDir2.X = vec3->X - origin->X;
- vecDir2.Y = vec3->Y - origin->Y;
+ vecDir2.X = vecT2->X - origin->X;
+ vecDir2.Y = vecT2->Y - origin->Y;
vecDir2.Z = 0.0;
maths::normalize_2d(&vecDir2);
@@ -57,15 +57,15 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
auto dirY1 = -vecDir1.Y;
A2Src.X = dirY1 * CirclebaseRadius + origin->X;
A2Src.Y = dirX1 * CirclebaseRadius + origin->Y;
- A1Src.X = dirY1 * CircleT1Radius + vecT->X;
- A1Src.Y = dirX1 * CircleT1Radius + vecT->Y;
+ A1Src.X = dirY1 * CircleT1Radius + vecT1->X;
+ A1Src.Y = dirX1 * CircleT1Radius + vecT1->Y;
dirX1 = -dirX1;
dirY1 = -dirY1;
B1Src.X = dirY1 * CirclebaseRadius + origin->X;
B1Src.Y = dirX1 * CirclebaseRadius + origin->Y;
- B2Src.X = dirY1 * CircleT1Radius + vecT->X;
- B2Src.Y = dirX1 * CircleT1Radius + vecT->Y;
+ B2Src.X = dirY1 * CircleT1Radius + vecT1->X;
+ B2Src.Y = dirX1 * CircleT1Radius + vecT1->Y;
if (AngleMax < 0.0)
{
@@ -73,261 +73,239 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsign
maths::vswap(&A2Src, &B2Src);
}
- auto dx = vecT->X - RotOrigin.X;
- auto dy = vecT->Y - RotOrigin.Y;
- auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT->Z;
+ auto dx = vecT1->X - RotOrigin.X;
+ auto dy = vecT1->Y - RotOrigin.Y;
+ auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
DistanceDivSq = distance1 * distance1;
float bmpCoef = min(BmpCoef1, BmpCoef2);
- auto distance = maths::Distance(vecT, vec3);
- Unknown40F = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius);
+ auto distance = maths::Distance(vecT1, vecT2);
+ CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius);
TFlipperEdge::place_in_grid();
- Unknown44 = 0;
- TimeAngle = 0.0;
- Unknown15 = 0;
- Unknown46F = 0.0;
+ EdgeCollisionFlag = 0;
+ InputTime = 0.0;
+ CollisionFlag1 = 0;
+ AngleStopTime = 0.0;
AngleMult = 0.0;
}
void TFlipperEdge::port_draw()
{
- set_control_points(TimeAngle);
+ set_control_points(InputTime);
build_edges_in_motion();
}
float TFlipperEdge::FindCollisionDistance(ray_type* ray)
{
auto ogRay = ray;
+ ray_type dstRay{}, srcRay{};
-
- float* pfVar2;
- short uVar3;
- int iVar4;
- int uVar5;
- vector_type* prVar6;
- vector_type* plVar6;
- vector_type* pvVar7;
- float fVar8;
- ray_type ray2;
- ray_type ray1;
- float local_1c;
- float local_18;
- float local_14;
- float local_10;
- float local_c;
- float local_8;
-
- if (ogRay->TimeNow > this->Unknown46F) {
- this->FlipperFlag = 0;
+ if (ogRay->TimeNow > AngleStopTime)
+ {
+ FlipperFlag = 0;
}
- if (this->Unknown44 == 0) {
- if (this->FlipperFlag == 0) {
- this->Unknown44 = 0;
- this->Unknown15 = 0;
- this->Unknown16 = 0;
- set_control_points( ogRay->TimeNow);
+ if (EdgeCollisionFlag == 0)
+ {
+ if (FlipperFlag == 0)
+ {
+ EdgeCollisionFlag = 0;
+ CollisionFlag1 = 0;
+ CollisionFlag2 = 0;
+ set_control_points(ogRay->TimeNow);
build_edges_in_motion();
- iVar4 = is_ball_inside( (ogRay->Origin).X, (ogRay->Origin).Y);
- ray1.MinDistance = ogRay->MinDistance;
- if (iVar4 == 0) {
- ray1.Direction.X = (ogRay->Direction).X;
- ray1.Direction.Y = (ogRay->Direction).Y;
- ray1.Direction.Z = (ogRay->Direction).Z;
- ray1.MaxDistance = ogRay->MaxDistance;
- ray1.Origin.X = (ogRay->Origin).X;
- ray1.Origin.Y = (ogRay->Origin).Y;
- ray1.Origin.Z = (ogRay->Origin).Z;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- plVar6 = &ray2.Origin;
- if (fVar8 == 0.0) {
- pvVar7 = &this->NextBallPosition;
- pvVar7->X = ray2.Origin.X;
- (this->NextBallPosition).Y = ray2.Origin.Y;
- (this->NextBallPosition).Z = ray2.Origin.Z;
- pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f;
- pfVar2 = &(this->NextBallPosition).Y;
- *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f;
+ auto ballInside = is_ball_inside(ogRay->Origin.X, ogRay->Origin.Y);
+ srcRay.MinDistance = ogRay->MinDistance;
+ if (ballInside == 0)
+ {
+ srcRay.Direction = ogRay->Direction;
+ srcRay.MaxDistance = ogRay->MaxDistance;
+ srcRay.Origin = ogRay->Origin;
+ auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
+ if (distance == 0.0)
+ {
+ NextBallPosition = dstRay.Origin;
+ NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
+ NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
}
- else {
- pvVar7 = &this->NextBallPosition;
- LAB_0101bab7:
- pvVar7->X = (plVar6)->X;
- pvVar7->Y = (plVar6)->Y;
- pvVar7->Z = (plVar6)->Z;
+ else
+ {
+ NextBallPosition = dstRay.Origin;
}
- (this->CollisionDirection).X = ray2.Direction.X;
- (this->CollisionDirection).Y = ray2.Direction.Y;
- (this->CollisionDirection).Z = ray2.Direction.Z;
- return fVar8;
+ CollisionDirection = dstRay.Direction;
+ return distance;
}
- fVar8 = maths::Distance_Squared(ogRay->Origin, this->RotOrigin);
- if (this->CirclebaseRadiusMSq <= fVar8) {
- fVar8 = maths::Distance_Squared(ogRay->Origin, T1);
- if (this->CircleT1RadiusMSq <= fVar8) {
- ray1.Direction.Y = lineB.PerpendicularL.Y;
- ray1.Direction.X = lineB.PerpendicularL.X;
- if (iVar4 == 4) {
- ray1.Direction.Y = lineA.PerpendicularL.Y;
- ray1.Direction.X = lineA.PerpendicularL.X;
+
+ if (maths::Distance_Squared(ogRay->Origin, RotOrigin) >= CirclebaseRadiusMSq)
+ {
+ if (maths::Distance_Squared(ogRay->Origin, T1) >= CircleT1RadiusMSq)
+ {
+ srcRay.Direction.Y = lineB.PerpendicularL.Y;
+ srcRay.Direction.X = lineB.PerpendicularL.X;
+ if (ballInside == 4)
+ {
+ srcRay.Direction.Y = lineA.PerpendicularL.Y;
+ srcRay.Direction.X = lineA.PerpendicularL.X;
}
- ray1.Direction.X = -ray1.Direction.X;
- ray1.Direction.Y = -ray1.Direction.Y;
+ srcRay.Direction.X = -srcRay.Direction.X;
+ srcRay.Direction.Y = -srcRay.Direction.Y;
}
- else {
- ray1.Direction.X = T1.X - (ogRay->Origin).X;
- ray1.Direction.Y = T1.Y - (ogRay->Origin).Y;
- maths::normalize_2d(&ray1.Direction);
+ else
+ {
+ srcRay.Direction.X = T1.X - ogRay->Origin.X;
+ srcRay.Direction.Y = T1.Y - ogRay->Origin.Y;
+ maths::normalize_2d(&srcRay.Direction);
}
}
- else {
- ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X;
- ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y;
- maths::normalize_2d(&ray1.Direction);
+ else
+ {
+ srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
+ srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
+ maths::normalize_2d(&srcRay.Direction);
}
- ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f;
- ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f;
- ray1.MaxDistance = ogRay->MaxDistance + 10.0f;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- if (1e+09 <= fVar8) {
- ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X;
- ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y;
- maths::normalize_2d(&ray1.Direction);
- ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f;
- ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- if (1e+09 <= fVar8) {
+
+ srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
+ srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
+ srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
+ if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
+ {
+ srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
+ srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
+ maths::normalize_2d(&srcRay.Direction);
+ srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
+ srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
+ if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
+ {
return 1e+09;
}
}
- LAB_0101ba1a:
- (this->NextBallPosition).X = ray2.Origin.X;
- (this->NextBallPosition).Y = ray2.Origin.Y;
- (this->NextBallPosition).Z = ray2.Origin.Z;
- pvVar7 = &this->CollisionDirection;
- prVar6 = &ray2.Direction;
- LAB_0101bc82:
- pvVar7->X = prVar6->X;
- pvVar7->Y = prVar6->Y;
- pvVar7->Z = prVar6->Z;
- (this->NextBallPosition).X = (this->NextBallPosition).X - ray1.Direction.X * 1e-05;
- pfVar2 = &(this->NextBallPosition).Y;
- *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05;
+
+ NextBallPosition = dstRay.Origin;
+ CollisionDirection = dstRay.Direction;
+ NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
+ NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
return 0.0;
}
- local_8 = (ogRay->Origin).X;
- local_14 = this->Unknown40F * ogRay->MaxDistance;
- local_c = (ogRay->Origin).Y;
- local_10 = ogRay->TimeNow;
- local_18 = this->Unknown40F * (ogRay->Direction).X;
- local_1c = (ogRay->Direction).Y * this->Unknown40F;
- fVar8 = ogRay->TimeDelta + ogRay->TimeNow;
- uVar3 = fVar8 <= local_10;// fp flag shift
- while (uVar3 == 0) {
- set_control_points( local_10);
+
+ auto posX = ogRay->Origin.X;
+ auto posY = ogRay->Origin.Y;
+ auto posXAdvance = ogRay->Direction.X * CollisionTimeAdvance;
+ auto posYAdvance = ogRay->Direction.Y * CollisionTimeAdvance;
+ auto rayMaxDistance = ogRay->MaxDistance * CollisionTimeAdvance;
+ auto timeNow = ogRay->TimeNow;
+ auto stopTime = ogRay->TimeDelta + ogRay->TimeNow;
+ while (timeNow < stopTime)
+ {
+ set_control_points(timeNow);
build_edges_in_motion();
- iVar4 = is_ball_inside( local_8, local_c);
- if (iVar4 != 0) {
- if ((this->FlipperFlag == 1) && (iVar4 != 5)) {
- plVar6 = &lineA.PerpendicularL;
- ray1.Direction.Y = lineA.PerpendicularL.Y;
- ray1.Direction.X = lineA.PerpendicularL.X;
+ auto ballInside = is_ball_inside(posX, posY);
+ if (ballInside != 0)
+ {
+ vector_type* linePtr;
+ if (FlipperFlag == 1 && ballInside != 5)
+ {
+ linePtr = &lineA.PerpendicularL;
+ srcRay.Direction.Y = lineA.PerpendicularL.Y;
+ srcRay.Direction.X = lineA.PerpendicularL.X;
}
- else {
- if ((this->FlipperFlag != 2) || (iVar4 == 4)) {
- ray1.Direction.X = (this->RotOrigin).X - local_8;
- this->Unknown15 = 0;
- this->Unknown16 = 1;
- ray1.Direction.Y = (this->RotOrigin).Y - local_c;
- maths::normalize_2d(&ray1.Direction);
- ray1.Origin.X = local_8 - ray1.Direction.X * 5.0f;
- ray1.Origin.Y = local_c - ray1.Direction.Y * 5.0f;
- ray1.MaxDistance = ogRay->MaxDistance + 10.0f;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- if (1e+09 <= fVar8) {
- (this->NextBallPosition).X = local_8;
- (this->CollisionDirection).X = -ray1.Direction.X;
- (this->NextBallPosition).Y = local_c;
- (this->CollisionDirection).Y = -ray1.Direction.Y;
+ else
+ {
+ if (FlipperFlag != 2 || ballInside == 4)
+ {
+ CollisionFlag1 = 0;
+ CollisionFlag2 = 1;
+ srcRay.Direction.X = RotOrigin.X - posX;
+ srcRay.Direction.Y = RotOrigin.Y - posY;
+ maths::normalize_2d(&srcRay.Direction);
+
+ srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
+ srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
+ srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
+ if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
+ {
+ NextBallPosition.X = posX;
+ NextBallPosition.Y = posY;
+ CollisionDirection.X = -srcRay.Direction.X;
+ CollisionDirection.Y = -srcRay.Direction.Y;
return 0.0;
}
- goto LAB_0101ba1a;
+
+ NextBallPosition = dstRay.Origin;
+ CollisionDirection = dstRay.Direction;
+ NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
+ NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
+ return 0.0;
}
- plVar6 = &lineB.PerpendicularL;
- ray1.Direction.Y = lineB.PerpendicularL.Y;
- ray1.Direction.X = lineB.PerpendicularL.X;
+ linePtr = &lineB.PerpendicularL;
+ srcRay.Direction.Y = lineB.PerpendicularL.Y;
+ srcRay.Direction.X = lineB.PerpendicularL.X;
}
- ray1.Direction.X = -ray1.Direction.X;
- ray1.Direction.Y = -ray1.Direction.Y;
- (this->Unknown17V).X = plVar6->X;
- (this->Unknown17V).Y = plVar6->Y;
- (this->Unknown17V).Z = plVar6->Z;
- this->Unknown16 = 0;
- this->Unknown15 = 1;
- ray1.MinDistance = 0.002;
- ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f;
- ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f;
- ray1.MaxDistance = ogRay->MaxDistance + 10.0f;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- (this->CollisionDirection).X = ray2.Direction.X;
- (this->CollisionDirection).Y = ray2.Direction.Y;
- (this->CollisionDirection).Z = ray2.Direction.Z;
- if (1e+09 <= fVar8) {
+
+ CollisionLinePerp = *linePtr;
+ CollisionFlag2 = 0;
+ CollisionFlag1 = 1;
+ srcRay.Direction.X = -srcRay.Direction.X;
+ srcRay.Direction.Y = -srcRay.Direction.Y;
+ srcRay.MinDistance = 0.002f;
+ srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
+ srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
+ srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
+ auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
+ CollisionDirection = dstRay.Direction;
+ if (distance >= 1e+09)
+ {
return 1e+09;
}
- pvVar7 = &this->NextBallPosition;
- prVar6 = &ray2.Origin;
- goto LAB_0101bc82;
+ NextBallPosition = dstRay.Origin;
+ NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
+ NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
+ return 0.0;
}
- ray1.Direction.X = (ogRay->Direction).X;
- ray1.Direction.Y = (ogRay->Direction).Y;
- ray1.Direction.Z = (ogRay->Direction).Z;
- ray1.MinDistance = ogRay->MinDistance;
- ray1.Origin.X = (ogRay->Origin).X;
- ray1.Origin.Y = (ogRay->Origin).Y;
- ray1.Origin.Z = (ogRay->Origin).Z;
- ray1.MaxDistance = local_14;
- fVar8 = maths::distance_to_flipper(&ray1, &ray2);
- if (fVar8 < 1e+09) {
- pvVar7 = &this->NextBallPosition;
- pvVar7->X = ray2.Origin.X;
- (this->NextBallPosition).Y = ray2.Origin.Y;
- (this->NextBallPosition).Z = ray2.Origin.Z;
- pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f;
- pfVar2 = &(this->NextBallPosition).Y;
- *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f;
- uVar5 = this->AngleMax > 0.0;
- pvVar7 = &this->Unknown17V;
- if (this->FlipperFlag == 2) {
- plVar6 = &lineB.PerpendicularL;
- this->Unknown15 = (uVar5 == 0);
+
+ srcRay.Direction = ogRay->Direction;
+ srcRay.MinDistance = ogRay->MinDistance;
+ srcRay.Origin = ogRay->Origin;
+ srcRay.MaxDistance = rayMaxDistance;
+ auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
+ if (distance < 1e+09)
+ {
+ NextBallPosition = dstRay.Origin;
+ NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
+ NextBallPosition.Y -= srcRay.Direction.Y * 1e-05f;
+ vector_type* linePtr;
+ if (FlipperFlag == 2)
+ {
+ linePtr = &lineB.PerpendicularL;
+ CollisionFlag1 = AngleMax <= 0.0;
}
- else {
- this->Unknown15 = uVar5;
- plVar6 = &lineA.PerpendicularL;
+ else
+ {
+ CollisionFlag1 = AngleMax > 0.0;
+ linePtr = &lineA.PerpendicularL;
}
- goto LAB_0101bab7;
+ CollisionLinePerp = *linePtr;
+ CollisionDirection = dstRay.Direction;
+ return distance;
}
- local_10 = local_10 + this->Unknown40F;
- local_8 = local_8 + local_18;
- local_c = local_c + local_1c;
- fVar8 = ogRay->TimeDelta + ogRay->TimeNow;
- uVar3 = fVar8 <= local_10;
+ timeNow = timeNow + CollisionTimeAdvance;
+ posX = posX + posXAdvance;
+ posY = posY + posYAdvance;
}
}
- else {
- this->Unknown44 = 0;
+ else
+ {
+ EdgeCollisionFlag = 0;
}
return 1e+09;
}
void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
{
- Unknown44 = 1;
- if (!FlipperFlag || !Unknown16 || Unknown15)
+ EdgeCollisionFlag = 1;
+ if (!FlipperFlag || !CollisionFlag2 || CollisionFlag1)
{
float collMult = 0.0;
- if (Unknown15)
+ if (CollisionFlag1)
{
float dx = NextBallPosition.X - RotOrigin.X;
float dy = NextBallPosition.Y - RotOrigin.Y;
@@ -336,12 +314,12 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
{
float v11;
float v20 = sqrt(distance / DistanceDivSq) * (fabs(AngleMax) / AngleMult);
- float dot1 = maths::DotProduct(&Unknown17V, &CollisionDirection);
+ float dot1 = maths::DotProduct(&CollisionLinePerp, &CollisionDirection);
if (dot1 >= 0.0)
v11 = dot1 * v20;
else
v11 = 0.0;
- collMult = v11 * Unknown32F;
+ collMult = v11 * CollisionMult;
}
}
@@ -372,9 +350,9 @@ void TFlipperEdge::place_in_grid()
{
float x0 = RotOrigin.X - CirclebaseRadius;
float y0 = RotOrigin.Y - CirclebaseRadius;
- float x1 = CirclebaseRadius + RotOrigin.X;
+ float x1 = RotOrigin.X + CirclebaseRadius;
+ float y1 = RotOrigin.Y + CirclebaseRadius;
- float v1 = RotOrigin.Y + CirclebaseRadius;
float v2 = T1Src.X - CircleT1Radius;
if (v2 < x0)
x0 = v2;
@@ -383,31 +361,30 @@ void TFlipperEdge::place_in_grid()
if (v3 < y0)
y0 = v3;
- float v4 = CircleT1Radius + T1Src.X;
+ float v4 = T1Src.X + CircleT1Radius;
if (v4 > x1)
x1 = v4;
float v5 = T1Src.Y + CircleT1Radius;
- if (v5 > v1)
- v1 = v5;
+ if (v5 > y1)
+ y1 = v5;
- float v6 = Unknown36V.X - CircleT1Radius;
+ float v6 = T2Src.X - CircleT1Radius;
if (v6 < x0)
x0 = v6;
- float v7 = Unknown36V.Y - CircleT1Radius;
+ float v7 = T2Src.Y - CircleT1Radius;
if (v7 < y0)
y0 = v7;
- float v8 = Unknown36V.X + CircleT1Radius;
+ float v8 = T2Src.X + CircleT1Radius;
if (v8 > x1)
x1 = v8;
- float v9 = CircleT1Radius + Unknown36V.Y;
- if (v9 > v1)
- v1 = v9;
+ float v9 = T2Src.Y + CircleT1Radius;
+ if (v9 > y1)
+ y1 = v9;
- float y1 = v1;
TTableLayer::edges_insert_square(y0, x0, y1, x1, this, nullptr);
}
@@ -447,7 +424,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
angle = -angle;
if (angle >= 0.0000001)
- angle = (timeNow - TimeAngle) / angle;
+ angle = (timeNow - InputTime) / angle;
else
angle = 1.0;
@@ -459,7 +436,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
int TFlipperEdge::is_ball_inside(float x, float y)
{
- vector_type ptTest{};
+ vector_type testPoint{};
float dx = RotOrigin.X - x;
float dy = RotOrigin.Y - y;
if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0 &&
@@ -469,15 +446,16 @@ int TFlipperEdge::is_ball_inside(float x, float y)
dy * dy + dx * dx <= CirclebaseRadiusSq ||
(T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq)
{
+ float flipperLR = AngleMax < 0.0 ? -1 : 1;
if (FlipperFlag == 1)
- ptTest = AngleMax < 0.0 ? B1 : B2;
+ testPoint = AngleMax < 0.0 ? B1 : B2;
else if (FlipperFlag == 2)
- ptTest = AngleMax < 0.0 ? A2 : A1;
+ testPoint = AngleMax < 0.0 ? A2 : A1;
else
- ptTest = T1;
+ testPoint = T1;
- if ((y - ptTest.Y) * (RotOrigin.X - ptTest.X) -
- (x - ptTest.X) * (RotOrigin.Y - ptTest.Y) >= 0.0f)
+ if (((y - testPoint.Y) * (RotOrigin.X - testPoint.X) -
+ (x - testPoint.X) * (RotOrigin.Y - testPoint.Y)) * flipperLR < 0.0)
return 4;
return 5;
}
@@ -489,24 +467,24 @@ void TFlipperEdge::SetMotion(int code, float value)
switch (code)
{
case 1:
- this->Angle2 = flipper_angle(value);
- this->Angle1 = this->AngleMax;
- this->AngleMult = this->BmpCoef1;
+ Angle2 = flipper_angle(value);
+ Angle1 = AngleMax;
+ AngleMult = BmpCoef1;
break;
case 2:
- this->Angle2 = flipper_angle(value);
- this->Angle1 = 0.0;
- this->AngleMult = this->BmpCoef2;
+ Angle2 = flipper_angle(value);
+ Angle1 = 0.0;
+ AngleMult = BmpCoef2;
break;
case 1024:
- this->FlipperFlag = 0;
- this->Angle1 = 0.0;
+ FlipperFlag = 0;
+ Angle1 = 0.0;
return;
default: break;
}
- if (!this->FlipperFlag)
- this->TimeAngle = value;
- this->FlipperFlag = code;
- this->Unknown46F = this->AngleMult + this->TimeAngle;
+ if (!FlipperFlag)
+ InputTime = value;
+ FlipperFlag = code;
+ AngleStopTime = AngleMult + InputTime;
}
diff --git a/SpaceCadetPinball/TFlipperEdge.h b/SpaceCadetPinball/TFlipperEdge.h
index c19f366..3d6dc69 100644
--- a/SpaceCadetPinball/TFlipperEdge.h
+++ b/SpaceCadetPinball/TFlipperEdge.h
@@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment
{
public:
TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table,
- vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2, float a11,
+ vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, float collMult,
float c4F, float c5F);
void port_draw() override;
float FindCollisionDistance(ray_type* ray) override;
@@ -33,22 +33,22 @@ public:
float AngleMax;
float Angle2;
float Angle1;
- int Unknown15;
- int Unknown16;
- vector_type Unknown17V;
+ int CollisionFlag1;
+ int CollisionFlag2;
+ vector_type CollisionLinePerp;
vector_type A1Src;
vector_type A2Src;
vector_type B1Src;
vector_type B2Src;
- float Unknown32F;
+ float CollisionMult;
vector_type T1Src;
- vector_type Unknown36V;
+ vector_type T2Src;
float DistanceDivSq;
- float Unknown40F;
+ float CollisionTimeAdvance;
vector_type CollisionDirection;
- int Unknown44;
- float TimeAngle;
- float Unknown46F;
+ int EdgeCollisionFlag;
+ float InputTime;
+ float AngleStopTime;
float AngleMult;
float BmpCoef1;
float BmpCoef2;
diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp
index 0623913..9aaf441 100644
--- a/SpaceCadetPinball/maths.cpp
+++ b/SpaceCadetPinball/maths.cpp
@@ -2,6 +2,7 @@
#include "maths.h"
#include "TBall.h"
+#include "TFlipperEdge.h"
void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect)
@@ -341,5 +342,69 @@ void maths::RotatePt(vector_type* point, float sin, float cos, vector_type* orig
float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
{
- return 0;
+ auto distance = 1000000000.0f;
+ auto distanceType = -1;
+ auto newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineA);
+ if (newDistance < 1000000000.0)
+ {
+ distance = newDistance;
+ distanceType = 0;
+ }
+ newDistance = ray_intersect_circle(ray1, &TFlipperEdge::circlebase);
+ if (newDistance < distance)
+ {
+ distance = newDistance;
+ distanceType = 2;
+ }
+ newDistance = ray_intersect_circle(ray1, &TFlipperEdge::circleT1);
+ if (newDistance < distance)
+ {
+ distance = newDistance;
+ distanceType = 3;
+ }
+ newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineB);
+ if (newDistance < distance)
+ {
+ distance = newDistance;
+ distanceType = 1;
+ }
+ if (!ray2 || distance >= 1000000000.0)
+ return distance;
+
+ if (distanceType != -1)
+ {
+ vector_type* nextOrigin;
+ if (distanceType)
+ {
+ if (distanceType != 1)
+ {
+ float dirY;
+ ray2->Origin.X = distance * ray1->Direction.X + ray1->Origin.X;
+ ray2->Origin.Y = distance * ray1->Direction.Y + ray1->Origin.Y;
+ if (distanceType == 2)
+ {
+ ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circlebase.Center.X;
+ dirY = ray2->Origin.Y - TFlipperEdge::circlebase.Center.Y;
+ }
+ else
+ {
+ ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circleT1.Center.X;
+ dirY = ray2->Origin.Y - TFlipperEdge::circleT1.Center.Y;
+ }
+ ray2->Direction.Y = dirY;
+ normalize_2d(&ray2->Direction);
+ return distance;
+ }
+ ray2->Direction = TFlipperEdge::lineB.PerpendicularL;
+ nextOrigin = &TFlipperEdge::lineB.RayIntersect;
+ }
+ else
+ {
+ ray2->Direction = TFlipperEdge::lineA.PerpendicularL;
+ nextOrigin = &TFlipperEdge::lineA.RayIntersect;
+ }
+ ray2->Origin = *nextOrigin;
+ return distance;
+ }
+ return 1000000000.0;
}
diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h
index beae935..35748e7 100644
--- a/SpaceCadetPinball/pb.h
+++ b/SpaceCadetPinball/pb.h
@@ -9,7 +9,7 @@ class pb
{
public:
static int time_ticks;
- static float ball_speed_limit;
+ static float ball_speed_limit, time_now;
static int cheat_mode, game_mode;
static datFileStruct* record_table;
static TPinballTable* MainTable;
@@ -39,7 +39,7 @@ public:
static float collide(float timeNow, float timeDelta, TBall* ball);
private :
static int demo_mode, mode_countdown_;
- static float time_now, time_next;
+ static float time_next;
static high_score_struct highscore_table[5];
static int state;
};