diff --git a/SpaceCadetPinball/TCircle.cpp b/SpaceCadetPinball/TCircle.cpp index 2ae524b..c8d00b6 100644 --- a/SpaceCadetPinball/TCircle.cpp +++ b/SpaceCadetPinball/TCircle.cpp @@ -1,13 +1,11 @@ #include "pch.h" #include "TCircle.h" -TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, float* floatArr, +TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, vector_type* center, float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag) { Circle.RadiusSq = radius * radius; - Circle.X = *floatArr; - Circle.Y = floatArr[1]; - Circle.Unknown2 = floatArr[2]; + Circle.Center = *center; } double TCircle::FindCollisionDistance(ray_type* ray) diff --git a/SpaceCadetPinball/TCircle.h b/SpaceCadetPinball/TCircle.h index f675dc3..ce17f1a 100644 --- a/SpaceCadetPinball/TCircle.h +++ b/SpaceCadetPinball/TCircle.h @@ -5,8 +5,18 @@ class TCircle : public TEdgeSegment { +public: circle_type Circle; - TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned int visualFlag, float* floatArr, float radius); + TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned int visualFlag, vector_type* center, + float radius); double FindCollisionDistance(ray_type* ray) override; + + void EdgeCollision(TBall* ball, float coef) override + { + } + + void place_in_grid() override + { + } }; diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp index dae0a13..4115f0c 100644 --- a/SpaceCadetPinball/TCollisionComponent.cpp +++ b/SpaceCadetPinball/TCollisionComponent.cpp @@ -1,2 +1,50 @@ #include "pch.h" #include "TCollisionComponent.h" +#include "loader.h" +#include "TEdgeSegment.h" +#include "TPinballTable.h" + + +TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, int someFlag) : TPinballComponent( + table, groupIndex, true) +{ + visualStruct visual{}; + + EdgeList = new objlist_class(4, 4); + UnknownBaseFlag2 = 1; + if (GroupName != nullptr) + UnknownBaseFlag1 = 1; + if (groupIndex <= 0) + { + loader::default_vsi(&visual); + } + else + { + loader::query_visual(groupIndex, 0, &visual); + if (someFlag) + { + float offset = table->UnknownP61F; + float* floatArr = loader::query_float_attribute(groupIndex, 0, 600); + TEdgeSegment::install_wall(floatArr, this, &UnknownBaseFlag2, visual.Flag, offset, 0); + } + } + + UnknownC7F = visual.Kicker.Unknown1F; + UnknownC4F = visual.Unknown2F; + UnknownC5F = visual.Unknown1F; + UnknownC6F = visual.Kicker.Unknown2F; + SoundIndex1 = visual.Kicker.SoundIndex; + SoundIndex2 = visual.SoundIndex2; + GroupIndex = groupIndex; +} + +TCollisionComponent::~TCollisionComponent() +{ + for (TEdgeSegment* edge; EdgeList->Count() > 0;) + { + edge = static_cast(EdgeList->Get(0)); + EdgeList->Delete(edge); + delete edge; + } + delete this->EdgeList; +} diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h index 7175d95..77c4bd7 100644 --- a/SpaceCadetPinball/TCollisionComponent.h +++ b/SpaceCadetPinball/TCollisionComponent.h @@ -1,5 +1,20 @@ #pragma once -class TCollisionComponent -{ -}; +#include "objlist_class.h" +#include "TPinballComponent.h" +class TCollisionComponent : public TPinballComponent +{ +public: + objlist_class* EdgeList; + __int16 UnknownC2; + __int16 UnknownC3; + float UnknownC4F; + float UnknownC5F; + float UnknownC6F; + float UnknownC7F; + int SoundIndex2; + int SoundIndex1; + + TCollisionComponent(TPinballTable* table, int groupIndex, int someFlag); + ~TCollisionComponent(); +}; diff --git a/SpaceCadetPinball/TEdgeSegment.cpp b/SpaceCadetPinball/TEdgeSegment.cpp index 87234c2..6708d8a 100644 --- a/SpaceCadetPinball/TEdgeSegment.cpp +++ b/SpaceCadetPinball/TEdgeSegment.cpp @@ -1,5 +1,7 @@ #include "pch.h" #include "TEdgeSegment.h" +#include "TCircle.h" +#include "TLine.h" TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag) { @@ -8,3 +10,116 @@ TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsign this->VisualFlag = visualFlag; this->Unknown3_0 = 0; } + +TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* collComp, char* flagPtr, + unsigned int visual_flag, + float offset, int someValue) +{ + vector_type center{}, start{}, end{}, prevCenter{}, vec1{}, vec2{}, dstVec{}; + TEdgeSegment* edge1; + + wall_type wallType = static_cast(static_cast(floor(*floatArr) - 1.0)); + switch (wallType) + { + case wall_type::Circle: + { + center.X = floatArr[1]; + center.Y = floatArr[2]; + + auto radius = offset + floatArr[3]; + auto circle = new TCircle(collComp, flagPtr, visual_flag, ¢er, radius); + + if (circle) + { + circle->WallValue = someValue; + circle->place_in_grid(); + } + + collComp->EdgeList->Add(circle); + return circle; + } + case wall_type::Line: + { + start.X = floatArr[1]; + start.Y = floatArr[2]; + end.X = floatArr[3]; + end.Y = floatArr[4]; + + auto line = new TLine(collComp, flagPtr, visual_flag, &start, &end); + + if (line) + { + line->WallValue = someValue; + line->Offset(offset); + line->place_in_grid(); + collComp->EdgeList->Add(line); + } + return line; + } + default: + { + int wallTypeI = static_cast(wallType); + auto floatArrPtr = floatArr + 1; + prevCenter.X = floatArr[2 * wallTypeI - 1]; + prevCenter.Y = floatArr[2 * wallTypeI]; + + for (int index = 0; index < wallTypeI; index++, floatArrPtr += 2) + { + float centerX2, centerY2; + if (index >= wallTypeI - 1) + { + centerX2 = floatArr[1]; + centerY2 = floatArr[2]; + } + else + { + centerX2 = floatArrPtr[2]; + centerY2 = floatArrPtr[3]; + } + auto centerX1 = floatArrPtr[0]; + auto centerY1 = floatArrPtr[1]; + + center.X = centerX1; + center.Y = centerY1; + if (offset != 0.0) + { + vec1.X = centerX1 - prevCenter.X; + vec1.Y = center.Y - prevCenter.Y; + vec2.X = centerX2 - centerX1; + vec2.Y = centerY2 - center.Y; + maths::cross(&vec1, &vec2, &dstVec); + if (dstVec.Z > 0.0 && offset > 0.0 || + dstVec.Z < 0.0 && offset < 0.0) + { + auto radius = offset * 1.001; + auto circle = new TCircle(collComp, flagPtr, visual_flag, ¢er, radius); + + if (circle) + { + circle->WallValue = someValue; + circle->place_in_grid(); + collComp->EdgeList->Add(circle); + } + } + } + + start.X = floatArrPtr[0]; + start.Y = floatArrPtr[1]; + end.X = floatArrPtr[2]; + end.Y = floatArrPtr[3]; + auto line = new TLine(collComp, flagPtr, visual_flag, &start, &end); + if (line) + { + line->WallValue = someValue; + line->Offset(offset); + line->place_in_grid(); + collComp->EdgeList->Add(line); + } + + prevCenter = center; + } + } + } + + return nullptr; +} diff --git a/SpaceCadetPinball/TEdgeSegment.h b/SpaceCadetPinball/TEdgeSegment.h index 369b5f3..8d45078 100644 --- a/SpaceCadetPinball/TEdgeSegment.h +++ b/SpaceCadetPinball/TEdgeSegment.h @@ -3,21 +3,30 @@ #include "maths.h" #include "TBall.h" +enum class wall_type +{ + Circle = 0, + Line = 1, +}; + class TEdgeSegment { public: TCollisionComponent* CollisionComponent; char* PinbCompFlag2Ptr; char Unknown3_0; - char Unknown3_1; - char Unknown3_2; - char Unknown3_3; - char Unknown4; + int WallValue; int VisualFlag; TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag); - //virtual ~TEdgeSegment() = 0; + + virtual ~TEdgeSegment() + { + } + virtual void place_in_grid() = 0; virtual double FindCollisionDistance(ray_type* ray) = 0; virtual void EdgeCollision(TBall* ball, float coef) = 0; + static TEdgeSegment* install_wall(float* floatArr, TCollisionComponent* collComp, char* flagPtr, + unsigned int visual_flag, float offset, int someValue); }; diff --git a/SpaceCadetPinball/TFlipper.h b/SpaceCadetPinball/TFlipper.h index 067f285..ba53225 100644 --- a/SpaceCadetPinball/TFlipper.h +++ b/SpaceCadetPinball/TFlipper.h @@ -1,5 +1,6 @@ #pragma once #include "TPinballComponent.h" + class TFlipper : public TPinballComponent { diff --git a/SpaceCadetPinball/TLine.cpp b/SpaceCadetPinball/TLine.cpp index de2f452..66b5a7c 100644 --- a/SpaceCadetPinball/TLine.cpp +++ b/SpaceCadetPinball/TLine.cpp @@ -5,19 +5,21 @@ TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1, float y1): TEdgeSegment(collCmp, flagPtr, visualFlag) { - Start.X = x0; - Start.Y = y0; - End.X = x1; - End.Y = y1; + this->X0 = x0; + this->Y0 = y0; + this->X1 = x1; + this->Y1 = y1; maths::line_init(&Line, x0, y0, x1, y1); } TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start, struct vector_type* end) : TEdgeSegment(collCmp, flagPtr, visualFlag) { - Start = *start; - End = *end; - maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y); + this->X0 = start->X; + this->Y0 = start->Y; + this->X1 = end->X; + this->Y1 = end->Y; + maths::line_init(&Line, X0, Y0, X1, Y1); } void TLine::Offset(float offset) @@ -25,14 +27,14 @@ void TLine::Offset(float offset) float offX = offset * Line.PerpendicularL.X; float offY = offset * Line.PerpendicularL.Y; - Start.X += offX; - Start.Y += offY; - End.X += offX; - End.Y += offY; - maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y); + X0 += offX; + Y0 += offY; + X1 += offX; + Y1 += offY; + maths::line_init(&Line, X0, Y0, X1, Y1); } double TLine::FindCollisionDistance(ray_type* ray) { return maths::ray_intersect_line(ray, &Line); -} \ No newline at end of file +} diff --git a/SpaceCadetPinball/TLine.h b/SpaceCadetPinball/TLine.h index ebfc0cf..ffe88c4 100644 --- a/SpaceCadetPinball/TLine.h +++ b/SpaceCadetPinball/TLine.h @@ -7,11 +7,18 @@ class TLine : { public: line_type Line; - vector_type Start; - vector_type End; + float X0, Y0, X1, Y1; TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1, float y1); TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start, struct vector_type* end); void Offset(float offset); double FindCollisionDistance(ray_type* ray) override; + + void EdgeCollision(TBall* ball, float coef) override + { + } + + void place_in_grid() override + { + } }; diff --git a/SpaceCadetPinball/TPinballComponent.h b/SpaceCadetPinball/TPinballComponent.h index 42ded2f..5a26850 100644 --- a/SpaceCadetPinball/TPinballComponent.h +++ b/SpaceCadetPinball/TPinballComponent.h @@ -2,11 +2,12 @@ #include "render.h" #include "TZmapList.h" +class TPinballTable; class TPinballComponent { public: - TPinballComponent(class TPinballTable* table, int groupIndex, bool loadVisuals); + TPinballComponent(TPinballTable* table, int groupIndex, bool loadVisuals); virtual ~TPinballComponent(); virtual int Message(int message1, float message2); virtual void put_scoring(int score1, int score2); diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index b5304da..8b3cc74 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -73,7 +73,7 @@ public: int UnknownP58; int UnknownP59; int UnknownP60; - int UnknownP61; + float UnknownP61F; int UnknownP62; int UnknownP63; int UnknownP64; diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index 0daf74f..cb4eb14 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -83,7 +83,7 @@ int loader::error(int errorCode, int captionCode) void loader::default_vsi(visualStruct* visual) { - visual->Unknown14Flag = 0; + visual->Flag = 0; visual->Kicker.Unknown1F = 8.9999999e10f; visual->Kicker.SoundIndex = 0; visual->Unknown1F = 0.94999999f; @@ -509,7 +509,7 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vi shortValSub602 = shortVal - 602; if (!shortValSub602) { - visual2->Unknown14Flag |= 1 << *nextShortVal; + visual2->Flag |= 1 << *nextShortVal; goto LABEL_31; } shortValSub1100 = shortValSub602 - 498; @@ -537,8 +537,8 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vi } } LABEL_33: - if (!visual2->Unknown14Flag) - visual2->Unknown14Flag = 1; + if (!visual2->Flag) + visual2->Flag = 1; floatArr = (float*)partman::field(loader_table, groupIndexSum3, datFieldTypes::FloatArray); if (!floatArr) return 0; diff --git a/SpaceCadetPinball/loader.h b/SpaceCadetPinball/loader.h index aaadbbe..8fdd3af 100644 --- a/SpaceCadetPinball/loader.h +++ b/SpaceCadetPinball/loader.h @@ -41,7 +41,7 @@ struct __declspec(align(4)) visualStruct float* FloatArr; int SoundIndex2; visualKickerStruct Kicker; - int Unknown14Flag; + int Flag; int SoundIndex4; int SoundIndex3; gdrv_bitmap8* Bitmap; diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 47e5e57..a0b78b1 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -123,8 +123,8 @@ float maths::ray_intersect_circle(ray_type* ray, circle_type* circle) // C - circle center // R - circle radius // L, C - O, vector between O and C - float Lx = circle->X - ray->Origin.X; - float Ly = circle->Y - ray->Origin.Y; + float Lx = circle->Center.X - ray->Origin.X; + float Ly = circle->Center.Y - ray->Origin.Y; // Tca, L dot D, projection of L on D float Tca = Ly * ray->Direction.Y + Lx * ray->Direction.X; @@ -191,13 +191,13 @@ void maths::line_init(line_type* line, float x0, float y0, float x1, float y1) } if (lineDirection) { - line->Origin.X = v9; - line->Origin.Y = v11; + line->OriginX = v9; + line->OriginY = v11; } else { - line->Origin.Y = v9; - line->Origin.X = v11; + line->OriginY = v9; + line->OriginX = v11; } } @@ -216,27 +216,27 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line) { result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->PreComp1) / perpDot); - if (result >= -ray->Unknown7 && result <= ray->MaxDistance) + if (result >= -ray->MinDistance && result <= ray->MaxDistance) { - line->Unknown9 = result * ray->Direction.X + ray->Origin.X; + line->CompTmp1 = result * ray->Direction.X + ray->Origin.X; v4 = result * ray->Direction.Y + ray->Origin.Y; line->Unknown10 = v4; if (0.0 == line->Direction.X) { - if (v4 >= line->Origin.X) + if (v4 >= line->OriginX) { - v5 = v4 < line->Origin.Y; - v6 = v4 == line->Origin.Y; + v5 = v4 < line->OriginY; + v6 = v4 == line->OriginY; if (v5 || v6) return result; return 1000000000.0; } } - else if (line->Origin.X <= line->Unknown9) + else if (line->OriginX <= line->CompTmp1) { - v7 = line->Unknown9; - v5 = v7 < line->Origin.Y; - v6 = v7 == line->Origin.Y; + v7 = line->CompTmp1; + v5 = v7 < line->OriginY; + v6 = v7 == line->OriginY; if (v5 || v6) return result; return 1000000000.0; @@ -245,3 +245,10 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line) } return 1000000000.0; } + +void maths::cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec) +{ + dstVec->X = vec2->Z * vec1->Y - vec2->Y * vec1->Z; + dstVec->Y = vec2->X * vec1->Z - vec1->X * vec2->Z; + dstVec->Z = vec1->X * vec2->Y - vec2->X * vec1->Y; +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index bdd9b45..74f6d57 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -4,6 +4,7 @@ struct vector_type { float X; float Y; + float Z; }; @@ -17,31 +18,26 @@ struct __declspec(align(4)) rectangle_type struct circle_type { - float X; - float Y; - float Unknown2; + vector_type Center; float RadiusSq; }; struct __declspec(align(4)) ray_type { vector_type Origin; - float Unknown2; vector_type Direction; - float Unknown5; float MaxDistance; - float Unknown7; + float MinDistance; }; struct __declspec(align(4)) line_type { vector_type PerpendicularL; - float Unknown2; vector_type Direction; - float Unknown5; float PreComp1; - vector_type Origin; - float Unknown9; + float OriginX; + float OriginY; + float CompTmp1; float Unknown10; float Unknown11; }; @@ -57,4 +53,5 @@ public: static float normalize_2d(vector_type* vec); static void line_init(line_type* line, float x0, float y0, float x1, float y1); static float ray_intersect_line(ray_type* ray, line_type* line); + static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec); };