1
0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-25 04:02:30 +01:00

TPlunger ready. TEdgeManager v1.

This commit is contained in:
oz 2021-01-07 19:00:38 +03:00
parent 1ea247e185
commit 9bd064bf15
28 changed files with 866 additions and 118 deletions

Binary file not shown.

View File

@ -184,6 +184,7 @@
<ClInclude Include="TComponentGroup.h" />
<ClInclude Include="TDemo.h" />
<ClInclude Include="TDrain.h" />
<ClInclude Include="TEdgeBox.h" />
<ClInclude Include="TEdgeManager.h" />
<ClInclude Include="TEdgeSegment.h" />
<ClInclude Include="TFlagSpinner.h" />
@ -252,6 +253,7 @@
<ClCompile Include="TComponentGroup.cpp" />
<ClCompile Include="TDemo.cpp" />
<ClCompile Include="TDrain.cpp" />
<ClCompile Include="TEdgeBox.cpp" />
<ClCompile Include="TEdgeManager.cpp" />
<ClCompile Include="TEdgeSegment.cpp" />
<ClCompile Include="TFlagSpinner.cpp" />

View File

@ -216,6 +216,9 @@
<ClInclude Include="TEdgeManager.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TEdgeBox.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
@ -398,6 +401,9 @@
<ClCompile Include="TEdgeManager.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TEdgeBox.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="NatvisFile.natvis" />

View File

@ -20,7 +20,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
CollisionComp = nullptr;
EdgeCollisionCount = 0;
TimeDelta = 0.0;
Unknown17F = 1;
FieldFlag = 1;
CollisionFlag = 0;
Speed = 0.0;
Acceleration.Y = 0.0;
@ -83,8 +83,8 @@ void TBall::Repaint()
RenderSprite,
bmp,
zDepth,
bmp->Width / 2 - pos2D[0],
bmp->Height / 2 - pos2D[1]);
pos2D[0] - bmp->Width / 2,
pos2D[1] - bmp->Height / 2);
}
void TBall::not_again(TEdgeSegment* edge)
@ -117,7 +117,7 @@ int TBall::Message(int code, float value)
Position.Y = 0.0;
UnknownBaseFlag2 = 0;
CollisionFlag = 0;
Unknown17F = 1;
FieldFlag = 1;
Acceleration.Y = 0.0;
Position.Z = Offset;
Acceleration.X = 0.0;

View File

@ -25,7 +25,7 @@ public :
int Unknown14;
int Unknown15;
TCollisionComponent* CollisionComp;
float Unknown17F;
int FieldFlag;
TEdgeSegment* Collisions[5];
int EdgeCollisionCount;
vector_type CollisionOffset;

View File

@ -8,7 +8,19 @@ TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visu
Circle.Center = *center;
}
double TCircle::FindCollisionDistance(ray_type* ray)
float TCircle::FindCollisionDistance(ray_type* ray)
{
return maths::ray_intersect_circle(ray, &Circle);
}
void TCircle::EdgeCollision(TBall* ball, float coef)
{
vector_type direction{}, nextPosition{};
nextPosition.X = coef * ball->Acceleration.X + ball->Position.X;
nextPosition.Y = coef * ball->Acceleration.Y + ball->Position.Y;
direction.X = nextPosition.X - Circle.Center.X;
direction.Y = nextPosition.Y - Circle.Center.Y;
maths::normalize_2d(&direction);
CollisionComponent->Collision(ball, &nextPosition, &direction, coef, this);
}

View File

@ -10,11 +10,8 @@ public:
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
{
}
float FindCollisionDistance(ray_type* ray) override;
void EdgeCollision(TBall* ball, float coef) override;
void place_in_grid() override
{

View File

@ -29,10 +29,10 @@ TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, b
}
}
UnknownC7F = visual.Kicker.Unknown1F;
MaxCollisionSpeed = visual.Kicker.Unknown1F;
UnknownC4F = visual.Unknown2F;
UnknownC5F = visual.Unknown1F;
UnknownC6F = visual.Kicker.Unknown2F;
CollisionMultiplier = visual.Kicker.Unknown2F;
SoundIndex1 = visual.Kicker.SoundIndex;
SoundIndex2 = visual.SoundIndex2;
GroupIndex = groupIndex;
@ -58,17 +58,17 @@ void TCollisionComponent::port_draw()
}
}
int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* ballPosition, vector_type* vec2)
int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* nextPosition, vector_type* direction)
{
if (PinballTable->TiltLockFlag)
{
maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
return 0;
}
auto projSpeed = maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F,
UnknownC7F,
UnknownC6F);
if (projSpeed <= UnknownC7F)
auto projSpeed = maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F,
MaxCollisionSpeed,
CollisionMultiplier);
if (projSpeed <= MaxCollisionSpeed)
{
if (projSpeed > 0.2)
{
@ -82,25 +82,25 @@ int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* ballPosition
return 1;
}
void TCollisionComponent::Collision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2,
float someVal, TEdgeSegment* edge)
void TCollisionComponent::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction,
float coef, TEdgeSegment* edge)
{
int soundIndex;
if (PinballTable->TiltLockFlag)
{
maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
return;
}
double projSpeed = maths::basic_collision(
ball,
ballPosition,
vec2,
nextPosition,
direction,
UnknownC4F,
UnknownC5F,
UnknownC7F,
UnknownC6F);
if (projSpeed <= UnknownC7F)
MaxCollisionSpeed,
CollisionMultiplier);
if (projSpeed <= MaxCollisionSpeed)
{
if (projSpeed <= 0.2)
return;

View File

@ -2,6 +2,7 @@
#include "objlist_class.h"
#include "TPinballComponent.h"
struct vector_type;
class TEdgeSegment;
class TBall;
@ -13,16 +14,16 @@ public:
__int16 UnknownC3;
float UnknownC4F;
float UnknownC5F;
float UnknownC6F;
float UnknownC7F;
float CollisionMultiplier;
float MaxCollisionSpeed;
int SoundIndex2;
int SoundIndex1;
TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall);
~TCollisionComponent();
void port_draw() override;
virtual void Collision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2, float someVal,
virtual void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge);
virtual int FieldEffect(TBall* ball, struct vector_type* vecDst);
int DefaultCollision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2);
virtual int FieldEffect(TBall* ball, vector_type* vecDst);
int DefaultCollision(TBall* ball, vector_type* nextPosition, vector_type* direction);
};

View File

@ -0,0 +1,16 @@
#include "pch.h"
#include "TEdgeBox.h"
#include "objlist_class.h"
TEdgeBox::TEdgeBox()
{
EdgeList = new objlist_class(0, 4);
FieldList = new objlist_class(0, 1);
}
TEdgeBox::~TEdgeBox()
{
delete EdgeList;
delete FieldList;
}

View File

@ -0,0 +1,13 @@
#pragma once
class objlist_class;
class TEdgeBox
{
public:
TEdgeBox();
~TEdgeBox();
objlist_class* EdgeList;
objlist_class* FieldList;
};

View File

@ -1,16 +1,274 @@
#include "pch.h"
#include "TEdgeManager.h"
int TEdgeManager::FieldEffects(TBall* ball, vector_type* vecDst)
#include "TEdgeBox.h"
#include "TTableLayer.h"
TEdgeManager::TEdgeManager(float posX, float posY, float width, float height)
{
return 0;
X = posX;
Y = posY;
MaxBoxX = 10;
MaxBoxY = 15;
AdvanceX = width / 10.0f;
AdvanceY = height / 15.0f;
AdvanceXInv = 1.0f / AdvanceX;
AdvanceYInv = 1.0f / AdvanceY;
BoxArray = new TEdgeBox[150];
}
void TEdgeManager::edges_insert_square(float a1, float a2, float a3, float a4, TEdgeSegment* a5, field_effect_type* a6)
TEdgeManager::~TEdgeManager()
{
delete[] BoxArray;
}
int TEdgeManager::box_x(float x)
{
return static_cast<int>((max(0, min(floor((x - X) * AdvanceXInv), (MaxBoxX - 1)))));
}
int TEdgeManager::box_y(float y)
{
return static_cast<int>((max(0, min(floor((y - Y) * AdvanceYInv), (MaxBoxY - 1)))));
}
int TEdgeManager::increment_box_x(int x)
{
return min(x + 1, MaxBoxX - 1);
}
int TEdgeManager::increment_box_y(int y)
{
return min(y + 1, MaxBoxY - 1);
}
void TEdgeManager::add_edge_to_box(int x, int y, TEdgeSegment* edge)
{
BoxArray[x + y * MaxBoxX].EdgeList->Add(edge);
}
void TEdgeManager::add_field_to_box(int x, int y, field_effect_type* field)
{
BoxArray[x + y * MaxBoxX].FieldList->Add(field);
}
int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeDst, ray_type* ray, TBall* ball,
int edgeIndex)
{
if (x >= 0 && x < 10 && y >= 0 && y < 15)
{
TEdgeBox* edgeBox = &BoxArray[x + y * MaxBoxX];
TEdgeSegment** edgePtr = &EdgeArray[edgeIndex];
for (auto index = edgeBox->EdgeList->Count() - 1; index >= 0; --index)
{
auto edge = static_cast<TEdgeSegment*>(edgeBox->EdgeList->Get(index));
if (!edge->ProcessedFlag && *edge->PinbCompFlag2Ptr && (edge->VisualFlag & ray->FieldFlag))
{
if (!ball->already_hit(edge))
{
++edgeIndex;
*edgePtr = edge;
++edgePtr;
edge->ProcessedFlag = 1;
auto dist = edge->FindCollisionDistance(ray);
if (dist < *distPtr)
{
*distPtr = dist;
*edgeDst = edge;
}
}
}
}
}
return edgeIndex;
}
void TEdgeManager::FieldEffects(TBall* ball, vector_type* dstVec)
{
vector_type vec{};
TEdgeBox* edgeBox = &BoxArray[box_x(ball->Position.X) + box_y(ball->Position.Y) *
MaxBoxX];
for (int index = edgeBox->FieldList->Count() - 1; index >= 0; --index)
{
auto field = static_cast<field_effect_type*>(edgeBox->FieldList->Get(index));
if (*field->Flag2Ptr && ball->FieldFlag & field->Mask)
{
if (field->CollisionComp->FieldEffect(ball, &vec))
{
maths::vector_add(dstVec, &vec);
}
}
}
}
float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegment** edge)
{
return 1000000000.0;
auto distance = 1000000000.0f;
auto edgeIndex = 0;
auto rayX = ray->Origin.X;
auto rayY = ray->Origin.Y;
auto rayBoxX = box_x(rayX);
auto rayBoxY = box_y(rayY);
auto rayEndX = ray->Direction.X * ray->MaxDistance + ray->Origin.X;
auto rayEndY = ray->Direction.Y * ray->MaxDistance + ray->Origin.Y;
auto rayEndBoxX = box_x(rayEndX);
auto rayEndBoxY = box_y(rayEndY);
auto rayDirX = rayX >= rayEndX ? -1 : 1;
auto rayDirY = rayY >= rayEndY ? -1 : 1;
if (rayBoxY == rayEndBoxY)
{
if (rayDirX == 1)
{
for (auto indexX = rayBoxX; indexX <= rayEndBoxX; indexX++)
{
edgeIndex = TestGridBox(indexX, rayBoxY, &distance, edge, ray, ball, edgeIndex);
}
}
else
{
for (auto indexX = rayBoxX; indexX >= rayEndBoxX; indexX--)
{
edgeIndex = TestGridBox(indexX, rayBoxY, &distance, edge, ray, ball, edgeIndex);
}
}
}
else
{
if (rayBoxX == rayEndBoxX)
{
if (rayDirY == 1)
{
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);
}
}
}
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
{
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
{
do
{
auto yCoord = indexY * AdvanceY + Y;
auto xCoord = (bresIndexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
{
++indexX;
++bresIndexX;
}
--indexY;
}
else
{
++indexX;
++bresIndexX;
}
edgeIndex = TestGridBox(indexX, indexY, &distance, edge, ray, ball, edgeIndex);
}
while (indexX < rayEndBoxX || indexY > rayEndBoxY);
}
}
else
{
if (rayDirY == 1)
{
do
{
auto yCoord = bresIndexY * AdvanceY + Y;
auto xCoord = (indexX * AdvanceX + X) * rayDyDX + bresXAdd;
if (xCoord >= yCoord)
{
if (xCoord == yCoord)
--indexX;
++indexY;
++bresIndexY;
}
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);
}
}
}
}
for (auto edgePtr = EdgeArray; edgeIndex > 0; --edgeIndex, ++edgePtr)
{
(*edgePtr)->ProcessedFlag = 0;
}
return distance;
}

View File

@ -2,22 +2,38 @@
#include "TCollisionComponent.h"
#include "TEdgeSegment.h"
class TEdgeBox;
struct field_effect_type
{
char* Flag2Ptr;
int Unknown1;
int Mask;
TCollisionComponent* CollisionComp;
};
class TEdgeManager
{
public:
TEdgeManager(float a2, float a3, float a4, float a5)
{
}
int FieldEffects(TBall* ball, struct vector_type* vecDst);
static void edges_insert_square(float a1, float a2, float a3, float a4, TEdgeSegment* a5, field_effect_type* a6);
TEdgeManager(float posX, float posY, float width, float height);
~TEdgeManager();
void FieldEffects(TBall* ball, struct vector_type* dstVec);
int box_x(float x);
int box_y(float y);
int increment_box_x(int x);
int increment_box_y(int y);
void add_edge_to_box(int x, int y, TEdgeSegment* edge);
void add_field_to_box(int x, int y, field_effect_type* field);
int TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeDst, ray_type* ray, TBall* ball, int edgeIndex);
float FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegment** edge);
float AdvanceX;
float AdvanceY;
float AdvanceXInv;
float AdvanceYInv;
int MaxBoxX;
int MaxBoxY;
float X;
float Y;
TEdgeBox* BoxArray;
TEdgeSegment* EdgeArray[1000];
};

View File

@ -8,7 +8,7 @@ TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsign
this->CollisionComponent = collComp;
this->PinbCompFlag2Ptr = someFlag;
this->VisualFlag = visualFlag;
this->Unknown3_0 = 0;
this->ProcessedFlag = 0;
}
void TEdgeSegment::port_draw()

View File

@ -14,7 +14,7 @@ class TEdgeSegment
public:
TCollisionComponent* CollisionComponent;
char* PinbCompFlag2Ptr;
char Unknown3_0;
char ProcessedFlag;
int WallValue;
int VisualFlag;
@ -24,7 +24,7 @@ public:
virtual void EdgeCollision(TBall* ball, float coef) = 0;
virtual void port_draw();
virtual void place_in_grid() = 0;
virtual double FindCollisionDistance(ray_type* ray) = 0;
virtual float FindCollisionDistance(ray_type* ray) = 0;
static TEdgeSegment* install_wall(float* floatArr, TCollisionComponent* collComp, char* flagPtr,
unsigned int visual_flag, float offset, int someValue);

View File

@ -9,7 +9,7 @@
#include "TLight.h"
#include "TPinballTable.h"
TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, -1, false)
TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
{
List = new objlist_class(4, 4);
Timer = 0;

View File

@ -1,24 +1,26 @@
#include "pch.h"
#include "TLine.h"
#include "TTableLayer.h"
TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1,
float y1): TEdgeSegment(collCmp, flagPtr, visualFlag)
{
this->X0 = x0;
this->Y0 = y0;
this->X1 = x1;
this->Y1 = y1;
X0 = x0;
Y0 = y0;
X1 = x1;
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)
{
this->X0 = start->X;
this->Y0 = start->Y;
this->X1 = end->X;
this->Y1 = end->Y;
X0 = start->X;
Y0 = start->Y;
X1 = end->X;
Y1 = end->Y;
maths::line_init(&Line, X0, Y0, X1, Y1);
}
@ -34,7 +36,169 @@ void TLine::Offset(float offset)
maths::line_init(&Line, X0, Y0, X1, Y1);
}
double TLine::FindCollisionDistance(ray_type* ray)
float TLine::FindCollisionDistance(ray_type* ray)
{
return maths::ray_intersect_line(ray, &Line);
}
void TLine::EdgeCollision(TBall* ball, float coef)
{
CollisionComponent->Collision(
ball,
&Line.RayIntersect,
&Line.PerpendicularL,
coef,
this);
}
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);
int dirX = X0 >= X1 ? -1 : 1;
int dirY = Y0 >= Y1 ? -1 : 1;
if (yBox0 == yBox1)
{
if (dirX == 1)
{
while (xBox0 <= xBox1)
TTableLayer::edge_manager->add_edge_to_box(xBox0++, yBox0, this);
}
else
{
while (xBox0 >= xBox1)
TTableLayer::edge_manager->add_edge_to_box(xBox0--, yBox0, this);
}
}
else if (xBox0 == xBox1)
{
if (dirY == 1)
{
if (yBox0 <= yBox1)
{
do
TTableLayer::edge_manager->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);
while (yBox0 >= yBox1);
}
}
else
{
float yCoord, xCoord;
int indexX1 = xBox0, indexY1 = yBox0;
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);
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;
if (xCoord >= yCoord)
{
if (xCoord == yCoord)
{
++indexX1;
++bresIndexX;
}
++indexY1;
++bresIndexY;
}
else
{
++indexX1;
++bresIndexX;
}
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this);
}
while (indexX1 != xBox1 || indexY1 != yBox1);
}
else
{
do
{
yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y;
xCoord = (bresIndexX * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) *
bresDyDx + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
{
++indexX1;
++bresIndexX;
}
--indexY1;
}
else
{
++indexX1;
++bresIndexX;
}
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this);
}
while (indexX1 != xBox1 || indexY1 != yBox1);
}
}
else
{
if (dirY == 1)
{
do
{
xCoord = bresIndexY * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y;
yCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) *
bresDyDx + bresXAdd;
if (yCoord >= xCoord)
{
if (yCoord == xCoord)
--indexX1;
++indexY1;
++bresIndexY;
}
else
{
--indexX1;
}
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this);
}
while (indexX1 != xBox1 || indexY1 != yBox1);
}
else
{
do
{
yCoord = indexY1 * TTableLayer::edge_manager->AdvanceY + TTableLayer::edge_manager->Y;
xCoord = (indexX1 * TTableLayer::edge_manager->AdvanceX + TTableLayer::edge_manager->X) *
bresDyDx + bresXAdd;
if (xCoord <= yCoord)
{
if (xCoord == yCoord)
--indexX1;
--indexY1;
}
else
{
--indexX1;
}
TTableLayer::edge_manager->add_edge_to_box(indexX1, indexY1, this);
}
while (indexX1 != xBox1 || indexY1 != yBox1);
}
}
}
}

View File

@ -12,13 +12,7 @@ public:
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
{
}
float FindCollisionDistance(ray_type* ray) override;
void EdgeCollision(TBall* ball, float coef) override;
void place_in_grid() override;
};

View File

@ -68,12 +68,12 @@ public:
objlist_class* ComponentList;
objlist_class* BallList;
TLightGroup* LightGroup;
float TableAngleMult;
float TableAngle1;
float TableAngle2;
float GravityDirVectMult;
float GravityAngleX;
float GravityAnglY;
float CollisionCompOffset;
int UnknownP62;
int UnknownP63;
float PlungerPositionX;
float PlungerPositionY;
int ScoreMultiplier;
int ScoreAdded;
int ScoreSpecial1;

View File

@ -1,2 +1,171 @@
#include "pch.h"
#include "TPlunger.h"
#include "control.h"
#include "loader.h"
#include "maths.h"
#include "pb.h"
#include "render.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
visualStruct visual{};
loader::query_visual(groupIndex, 0, &visual);
CollisionMultiplier = 0.0;
BallFeedTimer_ = 0;
PullbackTimer_ = 0;
SoundIndexP1 = visual.SoundIndex4;
SoundIndexP2 = visual.SoundIndex3;
SoundIndex1 = visual.Kicker.SoundIndex;
MaxCollisionSpeed = 1000000000.0;
MaxPullback = 100;
UnknownC4F = 0.5f;
UnknownC5F = 0.5f;
PullbackIncrement = static_cast<int>(100.0 / (ListBitmap->Count() * 8.0));
Unknown4F = 0.025f;
float* floatArr = loader::query_float_attribute(groupIndex, 0, 601);
table->PlungerPositionX = floatArr[0];
table->PlungerPositionY = floatArr[1];
}
void TPlunger::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
if (PinballTable->TiltLockFlag)
Message(1017, 0.0);
coef = static_cast<float>(rand()) * 0.00003051850947599719f * CollisionMultiplier * 0.1f + CollisionMultiplier;
maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, MaxCollisionSpeed, coef);
}
int TPlunger::Message(int code, float value)
{
switch (code)
{
case 1004:
if (!PullbackTimer_)
{
CollisionMultiplier = 0.0;
MaxCollisionSpeed = 1000000000.0;
loader::play_sound(SoundIndex1);
PullbackTimer(0, this);
}
return 0;
case 1005:
case 1009:
case 1010:
{
MaxCollisionSpeed = 0.0;
if (PullbackTimer_)
timer::kill(PullbackTimer_);
PullbackTimer_ = 0;
if (code == 1005)
loader::play_sound(SoundIndexP2);
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
render::sprite_set(
RenderSprite,
bmp,
zMap,
bmp->XPosition - PinballTable->XOffset,
bmp->YPosition - PinballTable->YOffset);
timer::set(Unknown4F, this, PlungerReleasedTimer);
break;
}
case 1015:
{
auto ball = static_cast<TBall*>(PinballTable->ComponentList->Get(0));
ball->Message(1024, 0.0);
ball->Position.X = PinballTable->PlungerPositionX;
ball->Position.Y = PinballTable->PlungerPositionY;
ball->UnknownBaseFlag2 = 1;
PinballTable->UnknownP10 = 0;
pb::tilt_no_more();
control::handler(code, this);
return 0;
}
case 1016:
if (BallFeedTimer_)
timer::kill(BallFeedTimer_);
BallFeedTimer_ = timer::set(0.95999998f, this, BallFeedTimer);
loader::play_sound(SoundIndexP1);
control::handler(code, this);
return 0;
case 1017:
MaxCollisionSpeed = 0.0;
CollisionMultiplier = static_cast<float>(MaxPullback);
timer::set(0.2f, this, PlungerReleasedTimer);
break;
case 1024:
{
if (BallFeedTimer_)
timer::kill(BallFeedTimer_);
BallFeedTimer_ = 0;
MaxCollisionSpeed = 0.0;
if (PullbackTimer_)
timer::kill(PullbackTimer_);
PullbackTimer_ = 0;
if (code == 1005)
loader::play_sound(SoundIndexP2);
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
render::sprite_set(
RenderSprite,
bmp,
zMap,
bmp->XPosition - PinballTable->XOffset,
bmp->YPosition - PinballTable->YOffset);
timer::set(Unknown4F, this, PlungerReleasedTimer);
break;
}
default:
break;
}
return 0;
}
void TPlunger::BallFeedTimer(int timerId, void* caller)
{
auto plunger = static_cast<TPlunger*>(caller);
plunger->PullbackTimer_ = 0;
plunger->Message(1015, 0.0);
}
void TPlunger::PullbackTimer(int timerId, void* caller)
{
auto plunger = static_cast<TPlunger*>(caller);
plunger->CollisionMultiplier += static_cast<float>(plunger->PullbackIncrement);
if (plunger->CollisionMultiplier <= static_cast<float>(plunger->MaxPullback))
{
plunger->PullbackTimer_ = timer::set(plunger->Unknown4F, plunger, PullbackTimer);
}
else
{
plunger->PullbackTimer_ = 0;
plunger->CollisionMultiplier = static_cast<float>(plunger->MaxPullback);
}
int index = static_cast<int>(floor(
static_cast<float>(plunger->ListBitmap->Count() - 1) *
(plunger->CollisionMultiplier / static_cast<float>(plunger->MaxPullback))));
auto bmp = static_cast<gdrv_bitmap8*>(plunger->ListBitmap->Get(index));
auto zMap = static_cast<zmap_header_type*>(plunger->ListZMap->Get(index));
render::sprite_set(
plunger->RenderSprite,
bmp,
zMap,
bmp->XPosition - plunger->PinballTable->XOffset,
bmp->YPosition - plunger->PinballTable->YOffset);
}
void TPlunger::PlungerReleasedTimer(int timerId, void* caller)
{
auto plunger = static_cast<TPlunger*>(caller);
plunger->MaxCollisionSpeed = 1000000000.0;
plunger->CollisionMultiplier = 0.0;
}

View File

@ -5,7 +5,20 @@ class TPlunger :
public TCollisionComponent
{
public:
TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
}
TPlunger(TPinballTable* table, int groupIndex);
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
int Message(int code, float value) override;
static void BallFeedTimer(int timerId, void* caller);
static void PullbackTimer(int timerId, void* caller);
static void PlungerReleasedTimer(int timerId, void* caller);
int PullbackTimer_;
int BallFeedTimer_;
int MaxPullback;
int PullbackIncrement;
float Unknown4F;
int SoundIndexP1;
int SoundIndexP2;
};

View File

@ -36,32 +36,32 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
auto tableAngleArr = loader::query_float_attribute(groupIndex, 0, 305);
if (tableAngleArr)
{
PinballTable->TableAngleMult = tableAngleArr[0];
PinballTable->TableAngle1 = tableAngleArr[1];
PinballTable->TableAngle2 = tableAngleArr[2];
PinballTable->GravityDirVectMult = tableAngleArr[0];
PinballTable->GravityAngleX = tableAngleArr[1];
PinballTable->GravityAnglY = tableAngleArr[2];
}
else
{
PinballTable->TableAngleMult = 25.0f;
PinballTable->TableAngle1 = 0.5f;
PinballTable->TableAngle2 = 1.570796f;
PinballTable->GravityDirVectMult = 25.0f;
PinballTable->GravityAngleX = 0.5f;
PinballTable->GravityAnglY = 1.570796f;
}
auto table3 = PinballTable;
Angle1 = cos(table3->TableAngle2) * sin(table3->TableAngle1) * table3->TableAngleMult;
Angle2 = sin(table3->TableAngle2) * sin(table3->TableAngle1) * table3->TableAngleMult;
GraityDirX = cos(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult;
GraityDiY = sin(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult;
auto angleMultArr = loader::query_float_attribute(groupIndex, 0, 701);
if (angleMultArr)
AngleMult = *angleMultArr;
GraityMult = *angleMultArr;
else
AngleMult = 0.2f;
GraityMult = 0.2f;
table->XOffset = bmp->XPosition;
table->YOffset = bmp->YPosition;
table->Width = bmp->Width;
table->Height = bmp->Height;
UnknownC7F = visual.Kicker.Unknown1F;
UnknownC6F = 15.0f;
MaxCollisionSpeed = visual.Kicker.Unknown1F;
CollisionMultiplier = 15.0f;
auto visArrPtr = visual.FloatArr;
Unknown1F = min(visArrPtr[0], min(visArrPtr[2], visArrPtr[4]));
@ -90,10 +90,10 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
visArrPtr += 2;
}
Field.Unknown1 = -1;
Field.Mask = -1;
Field.Flag2Ptr = &UnknownBaseFlag2;
Field.CollisionComp = this;
TEdgeManager::edges_insert_square(Unknown2F, Unknown1F, Unknown4F, Unknown3F, nullptr,
edges_insert_square(Unknown2F, Unknown1F, Unknown4F, Unknown3F, nullptr,
&Field);
}
@ -102,3 +102,51 @@ TTableLayer::~TTableLayer()
if (edge_manager)
delete edge_manager;
}
int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst)
{
vecDst->X = GraityDirX - (0.5f - static_cast<float>(rand()) * 0.00003051850947599719f + ball->Acceleration.X) *
ball->Speed * GraityMult;
vecDst->Y = GraityDiY - ball->Acceleration.Y * ball->Speed * GraityMult;
return 1;
}
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 xMin = x0 - widthM;
float xMax = x1 + widthM;
float yMin = y0 - heightM;
float yMax = y1 + heightM;
int xMinBox = edge_manager->box_x(xMin);
int yMinBox = edge_manager->box_y(yMin);
int xMaxBox = edge_manager->box_x(xMax);
int yMaxBox = edge_manager->box_y(yMax);
float boxX = static_cast<float>(xMinBox) * edge_manager->AdvanceX + edge_manager->X;
float boxY = static_cast<float>(yMinBox) * edge_manager->AdvanceY + edge_manager->Y;
for (int indexX = xMinBox; indexX <= xMaxBox; ++indexX)
{
for (int indexY = yMinBox; indexY <= yMaxBox; ++indexY)
{
if (xMax >= boxX && xMin <= boxX + edge_manager->AdvanceX &&
yMax >= boxY && yMin <= boxY + edge_manager->AdvanceY)
{
if (edge)
{
edge_manager->add_edge_to_box(indexX, indexY, edge);
}
if (field)
{
edge_manager->add_field_to_box(indexX, indexY, field);
}
}
boxY += edge_manager->AdvanceY;
}
boxX += edge_manager->AdvanceX;
}
}

View File

@ -11,19 +11,23 @@ class TTableLayer :
public TCollisionComponent
{
public:
static TEdgeManager* edge_manager;
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);
gdrv_bitmap8* VisBmp;
float Unknown1F;
float Unknown2F;
float Unknown3F;
float Unknown4F;
float Angle1;
float Angle2;
float GraityDirX;
float GraityDiY;
int Unknown7;
float AngleMult;
float GraityMult;
field_effect_type Field;
static TEdgeManager* edge_manager;
};

View File

@ -3,6 +3,7 @@
#include "objlist_class.h"
#include "pb.h"
#include "TLight.h"
#include "TPinballTable.h"
#include "TSound.h"
@ -795,6 +796,12 @@ int control::cheat_bump_rank()
return 0;
}
BOOL control::light_on(component_tag* tag)
{
auto light = static_cast<TLight*>(tag->Component);
return light->BmpIndex1 || light->FlasherFlag2 || light->FlasherActive;
}
void control::FlipperRebounderControl1(int code, TPinballComponent* caller)
{
}
@ -1013,6 +1020,35 @@ void control::HyperspaceKickOutControl(int code, TPinballComponent* caller)
void control::PlungerControl(int code, TPinballComponent* caller)
{
if (code == 1015)
{
MissionControl(67, nullptr);
}
else if (code == 1016)
{
table_unlimited_balls = 0;
if (!control_middle_circle_tag.Component->Message(37, 0.0))
control_middle_circle_tag.Component->Message(32, 0.0);
if (!light_on(&control_lite200_tag))
{
control_skill_shot_lights_tag.Component->Message(20, 0.0);
control_lite67_tag.Component->Message(19, 0.0);
control_skill_shot_lights_tag.Component->Message(26, 0.25f);
control_l_trek_lights_tag.Component->Message(20, 0.0);
control_l_trek_lights_tag.Component->Message(32, 0.2f);
control_l_trek_lights_tag.Component->Message(26, 0.2f);
control_r_trek_lights_tag.Component->Message(20, 0.0);
control_r_trek_lights_tag.Component->Message(32, 0.2f);
control_r_trek_lights_tag.Component->Message(26, 0.2f);
TableG->ScoreSpecial1 = 25000;
MultiplierLightGroupControl(65, control_top_target_lights_tag.Component);
control_fuel_bargraph_tag.Component->Message(19, 0.0);
control_lite200_tag.Component->Message(19, 0.0);
control_gate1_tag.Component->Message(53, 0.0);
control_gate2_tag.Component->Message(53, 0.0);
}
control_lite200_tag.Component->MessageField = 0;
}
}
void control::MedalTargetControl(int code, TPinballComponent* caller)

View File

@ -38,6 +38,7 @@ public:
static void pbctrl_bdoor_controller(int key);
static void table_add_extra_ball(float count);
static int cheat_bump_rank();
static BOOL light_on(struct component_tag* tag);
static void FlipperRebounderControl1(int code, TPinballComponent* caller);
static void FlipperRebounderControl2(int code, TPinballComponent* caller);

View File

@ -216,9 +216,9 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line)
/ perpDot);
if (result >= -ray->MinDistance && result <= ray->MaxDistance)
{
line->CompTmp1 = result * ray->Direction.X + ray->Origin.X;
line->RayIntersect.X = result * ray->Direction.X + ray->Origin.X;
float v4 = result * ray->Direction.Y + ray->Origin.Y;
line->Unknown10 = v4;
line->RayIntersect.Y = v4;
if (0.0 == line->Direction.X)
{
if (v4 >= line->OriginX)
@ -230,9 +230,9 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line)
return 1000000000.0;
}
}
else if (line->OriginX <= line->CompTmp1)
else if (line->OriginX <= line->RayIntersect.X)
{
float v7 = line->CompTmp1;
float v7 = line->RayIntersect.X;
v5 = v7 < line->OriginY;
v6 = v7 == line->OriginY;
if (v5 || v6)
@ -268,20 +268,20 @@ void maths::vector_add(vector_type* vec1Dst, vector_type* vec2)
vec1Dst->Y += vec2->Y;
}
float maths::basic_collision(TBall* ball, vector_type* ballPosition, vector_type* vec2, float a4, float a5, float a6,
float a7)
float maths::basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5, float maxSpeed,
float multiplier)
{
ball->Position.X = ballPosition->X;
ball->Position.Y = ballPosition->Y;
float proj = -(vec2->Y * ball->Acceleration.Y + vec2->X * ball->Acceleration.X);
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
float proj = -(direction->Y * ball->Acceleration.Y + direction->X * ball->Acceleration.X);
if (proj < 0)
{
proj = -proj;
}
else
{
float dx1 = proj * vec2->X;
float dy1 = proj * vec2->Y;
float dx1 = proj * direction->X;
float dy1 = proj * direction->Y;
float v17 = dx1 + ball->Acceleration.X;
float v18 = dy1 + ball->Acceleration.Y;
ball->Acceleration.X = v17 * a5 + dx1 * a4;
@ -291,10 +291,10 @@ float maths::basic_collision(TBall* ball, vector_type* ballPosition, vector_type
float projSpeed = proj * ball->Speed;
float newSpeed = ball->Speed - (1.0f - a4) * projSpeed;
ball->Speed = newSpeed;
if (projSpeed >= a6)
if (projSpeed >= maxSpeed)
{
ball->Acceleration.X = newSpeed * ball->Acceleration.X + vec2->X * a7;
ball->Acceleration.Y = newSpeed * ball->Acceleration.Y + vec2->Y * a7;
ball->Acceleration.X = newSpeed * ball->Acceleration.X + direction->X * multiplier;
ball->Acceleration.Y = newSpeed * ball->Acceleration.Y + direction->Y * multiplier;
ball->Speed = normalize_2d(&ball->Acceleration);
}
return projSpeed;

View File

@ -32,7 +32,7 @@ struct __declspec(align(4)) ray_type
float MinDistance;
float TimeNow;
float TimeDelta;
float Unknown2;
int FieldFlag;
};
struct __declspec(align(4)) line_type
@ -42,9 +42,7 @@ struct __declspec(align(4)) line_type
float PreComp1;
float OriginX;
float OriginY;
float CompTmp1;
float Unknown10;
float Unknown11;
vector_type RayIntersect;
};
@ -61,5 +59,5 @@ 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* ballPosition, struct vector_type* vec2, float a4, float a5, float a6, float a7);
static float basic_collision(TBall* ball, struct vector_type* nextPosition, struct vector_type* direction, float a4, float a5, float maxSpeed, float multiplier);
};

View File

@ -518,8 +518,8 @@ void pb::launch_ball()
void pb::end_game()
{
int scores[4];
int scoreIndex[4];
int scores[4]{};
int scoreIndex[4]{};
char String1[200];
mode_change(2);
@ -616,7 +616,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
ray.Direction.Y = ball->Acceleration.Y;
ray.Direction.Z = ball->Acceleration.Z;
ray.MaxDistance = maxDistance;
ray.Unknown2 = ball->Unknown17F;
ray.FieldFlag = ball->FieldFlag;
ray.TimeNow = timeNow;
ray.TimeDelta = timeDelta;
ray.MinDistance = 0.0020000001f;