TSink, TDemo ready.

This commit is contained in:
oz 2021-01-18 18:30:19 +03:00
parent 7e8f52c156
commit f22077d8c8
11 changed files with 453 additions and 24 deletions

Binary file not shown.

View File

@ -1,10 +1,205 @@
#include "pch.h"
#include "TDemo.h"
#include "loader.h"
#include "pb.h"
#include "TEdgeSegment.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TBall.h"
TDemo::TDemo(TPinballTable* table, int groupIndex)
: TCollisionComponent(table, groupIndex, false)
{
visualStruct visual{};
RestartGameTimer = 0;
PlungerFlag = 0;
FlipLeftTimer = 0;
FlipRightTimer = 0;
MessageField = 0;
UnknownBaseFlag1 = 0;
UnknownBaseFlag2 = 0;
FlipRightFlag = 0;
FlipLeftFlag = 0;
table->Demo = this;
auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 407);
if (floatArr1)
{
FlipTimerTime1 = floatArr1[0];
FlipTimerTime2 = floatArr1[1];
UnFlipTimerTime1 = floatArr1[2];
UnFlipTimerTime2 = floatArr1[3];
}
else
{
FlipTimerTime1 = 0.2f;
FlipTimerTime2 = 0.1f;
UnFlipTimerTime1 = 0.2f;
UnFlipTimerTime2 = 0.1f;
}
loader::query_visual(groupIndex, 0, &visual);
auto v5 = loader::query_float_attribute(groupIndex, 0, 1400);
Edge1 = TEdgeSegment::install_wall(v5, this, &UnknownBaseFlag2, visual.Flag, 0.0, 1400);
auto v6 = loader::query_float_attribute(groupIndex, 0, 1401);
TEdgeSegment::install_wall(v6, this, &UnknownBaseFlag2, visual.Flag, 0.0, 1401);
auto v7 = loader::query_float_attribute(groupIndex, 0, 1402);
Edge2 = TEdgeSegment::install_wall(v7, this, &UnknownBaseFlag2, visual.Flag, 0.0, 1402);
auto v8 = loader::query_float_attribute(groupIndex, 0, 1403);
TEdgeSegment::install_wall(v8, this, &UnknownBaseFlag2, visual.Flag, 0.0, 1403);
auto v9 = loader::query_float_attribute(groupIndex, 0, 1404);
Edge3 = TEdgeSegment::install_wall(v9, this, &UnknownBaseFlag2, visual.Flag, table->CollisionCompOffset, 1404);
}
int TDemo::Message(int code, float value)
{
switch (code)
{
case 1014:
if (RestartGameTimer)
timer::kill(RestartGameTimer);
RestartGameTimer = 0;
break;
case 1022:
if (RestartGameTimer)
timer::kill(RestartGameTimer);
RestartGameTimer = 0;
if (UnknownBaseFlag2 != 0)
RestartGameTimer = timer::set(5.0, this, NewGameRestartTimer);
break;
case 1024:
if (FlipLeftTimer)
timer::kill(FlipLeftTimer);
FlipLeftTimer = 0;
if (FlipRightTimer)
timer::kill(FlipRightTimer);
FlipRightTimer = 0;
if (FlipLeftFlag != 0)
UnFlipLeft(0, this);
if (FlipRightFlag)
UnFlipRight(0, this);
if (PlungerFlag)
PlungerRelease(0, this);
break;
default:
break;
}
return 0;
}
void TDemo::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
ball->not_again(edge);
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
switch (edge->WallValue)
{
case 1400:
if (!FlipLeftTimer && !FlipLeftFlag)
{
float time = FlipTimerTime1 + FlipTimerTime2 - static_cast<float>(rand()) *
0.00003051850947599719f * (FlipTimerTime2 + FlipTimerTime2);
FlipLeftTimer = timer::set(time, this, FlipLeft);
}
break;
case 1401:
FlipLeft(0, this);
break;
case 1402:
if (!FlipRightTimer && !FlipRightFlag)
{
float time = FlipTimerTime1 + FlipTimerTime2 - static_cast<float>(rand()) *
0.00003051850947599719f * (FlipTimerTime2 + FlipTimerTime2);
FlipRightTimer = timer::set(time, this, FlipRight);
}
break;
case 1403:
FlipRight(0, this);
break;
case 1404:
if (!PlungerFlag)
{
PinballTable->Message(1004, ball->TimeNow);
float time = static_cast<float>(rand()) * 0.00003051850947599719f + 2.0f;
PlungerFlag = timer::set(time, this, PlungerRelease);
}
break;
default:
break;
}
}
void TDemo::PlungerRelease(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
demo->PlungerFlag = 0;
demo->PinballTable->Message(1005, pb::time_next);
}
void TDemo::UnFlipRight(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
if (demo->FlipRightFlag)
demo->PinballTable->Message(1003, pb::time_next);
demo->FlipRightFlag = 0;
}
void TDemo::UnFlipLeft(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
if (demo->FlipLeftFlag)
demo->PinballTable->Message(1001, pb::time_next);
demo->FlipLeftFlag = 0;
}
void TDemo::FlipRight(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
if (!demo->FlipRightFlag)
{
if (demo->FlipRightTimer)
{
timer::kill(demo->FlipRightTimer);
demo->FlipRightTimer = 0;
}
demo->PinballTable->Message(1002, pb::time_next);
demo->FlipRightFlag = 1;
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - static_cast<float>(rand()) *
0.00003051850947599719f * (demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
timer::set(time, demo, UnFlipRight);
}
}
void TDemo::FlipLeft(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
if (!demo->FlipLeftFlag)
{
if (demo->FlipLeftTimer)
{
timer::kill(demo->FlipLeftTimer);
demo->FlipLeftTimer = 0;
}
demo->PinballTable->Message(1000, pb::time_next);
demo->FlipLeftFlag = 1;
float time = demo->UnFlipTimerTime1 + demo->UnFlipTimerTime2 - static_cast<float>(rand()) *
0.00003051850947599719f * (demo->UnFlipTimerTime2 + demo->UnFlipTimerTime2);
timer::set(time, demo, UnFlipLeft);
}
}
void TDemo::NewGameRestartTimer(int timerId, void* caller)
{
auto demo = static_cast<TDemo*>(caller);
pb::replay_level(1);
demo->PinballTable->Message(1014, static_cast<float>(demo->PinballTable->PlayerCount));
demo->RestartGameTimer = 0;
}

View File

@ -6,4 +6,28 @@ class TDemo :
{
public:
TDemo(TPinballTable* table, int groupIndex);
int Message(int code, float value) override;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
static void PlungerRelease(int timerId, void* caller);
static void UnFlipRight(int timerId, void* caller);
static void UnFlipLeft(int timerId, void* caller);
static void FlipRight(int timerId, void* caller);
static void FlipLeft(int timerId, void* caller);
static void NewGameRestartTimer(int timerId, void* caller);
float FlipTimerTime1;
float FlipTimerTime2;
float UnFlipTimerTime1;
float UnFlipTimerTime2;
int FlipLeftFlag;
int FlipRightFlag;
int FlipLeftTimer;
int FlipRightTimer;
int PlungerFlag;
int RestartGameTimer;
TEdgeSegment* Edge1;
TEdgeSegment* Edge2;
TEdgeSegment* Edge3;
};

View File

@ -109,3 +109,13 @@ int TPinballComponent::get_scoring(int index)
{
return 0;
}
void* TPinballComponent::operator new(size_t Size)
{
return calloc(1u, Size);
}
void TPinballComponent::operator delete(void* p)
{
free(p); /*Original does not have this*/
}

View File

@ -20,6 +20,9 @@ public:
virtual void put_scoring(int index, int score);
virtual int get_scoring(int index);
void* operator new(size_t Size);
void operator delete(void* p);
__int8 UnknownBaseFlag1;
__int8 UnknownBaseFlag2;
int MessageField;

View File

@ -1,2 +1,110 @@
#include "pch.h"
#include "TSink.h"
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "TPinballTable.h"
#include "TBall.h"
#include "timer.h"
TSink::TSink(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
visualStruct visual{};
MessageField = 0;
Timer = 0;
loader::query_visual(groupIndex, 0, &visual);
BallAcceleration.X = visual.Kicker.Unknown4F;
BallAcceleration.Y = visual.Kicker.Unknown5F;
BallAcceleration.Z = visual.Kicker.Unknown6F;
ThrowAngleMult = visual.Kicker.Unknown7F;
ThrowSpeedMult1 = visual.Kicker.Unknown2F;
ThrowSpeedMult2 = visual.Kicker.Unknown3F * 0.01f;
SoundIndex4 = visual.SoundIndex4;
SoundIndex3 = visual.SoundIndex3;
auto floatArr = loader::query_float_attribute(groupIndex, 0, 601);
BallPosition.X = floatArr[0];
BallPosition.Y = floatArr[1];
TimerTime = *loader::query_float_attribute(groupIndex, 0, 407);
}
int TSink::Message(int code, float value)
{
switch (code)
{
case 56:
if (value < 0.0)
value = TimerTime;
Timer = timer::set(value, this, TimerExpired);
break;
case 1020:
PlayerMessagefieldBackup[PinballTable->CurrentPlayer] = MessageField;
MessageField = PlayerMessagefieldBackup[static_cast<int>(floor(value))];
break;
case 1024:
{
if (Timer)
timer::kill(Timer);
Timer = 0;
MessageField = 0;
auto playerPtr = PlayerMessagefieldBackup;
for (auto index = 0; index < PinballTable->PlayerCount; ++index)
{
*playerPtr = 0;
++playerPtr;
}
break;
}
default:
break;
}
return 0;
}
void TSink::put_scoring(int index, int score)
{
if (index < 3)
Scores[index] = score;
}
int TSink::get_scoring(int index)
{
return index < 3 ? Scores[index] : 0;
}
void TSink::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
Timer = 0;
if (PinballTable->TiltLockFlag)
{
maths::basic_collision(ball, nextPosition, direction, UnknownC4F, UnknownC5F, 1000000000.0, 0.0);
}
else
{
ball->UnknownBaseFlag2 = 0;
render::sprite_set_bitmap(ball->RenderSprite, nullptr);
loader::play_sound(SoundIndex4);
control::handler(63, this);
}
}
void TSink::TimerExpired(int timerId, void* caller)
{
auto sink = static_cast<TSink*>(caller);
auto ball = static_cast<TBall*>(sink->PinballTable->BallList->Get(0));
ball->CollisionComp = nullptr;
ball->UnknownBaseFlag2 = 1;
ball->Position.X = sink->BallPosition.X;
ball->Position.Y = sink->BallPosition.Y;
TBall::throw_ball(ball, &sink->BallAcceleration, sink->ThrowAngleMult, sink->ThrowSpeedMult1,
sink->ThrowSpeedMult2);
if (sink->SoundIndex3)
loader::play_sound(sink->SoundIndex3);
sink->Timer = 0;
}

View File

@ -1,11 +1,29 @@
#pragma once
#include "maths.h"
#include "TCollisionComponent.h"
class TSink :
public TCollisionComponent
{
public:
TSink(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
}
TSink(TPinballTable* table, int groupIndex);
int Message(int code, float value) override;
void put_scoring(int index, int score) override;
int get_scoring(int index) override;
void Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge) override;
static void TimerExpired(int timerId, void* caller);
int Timer;
float TimerTime;
vector_type BallPosition;
vector_type BallAcceleration;
float ThrowAngleMult;
float ThrowSpeedMult1;
float ThrowSpeedMult2;
int SoundIndex4;
int SoundIndex3;
int Scores[3];
int PlayerMessagefieldBackup[4];
};

View File

@ -787,9 +787,9 @@ void control::pbctrl_bdoor_controller(int key)
void control::table_add_extra_ball(float count)
{
++TableG->ExtraBalls;
dynamic_cast<TSound*>(control_soundwave28_tag.Component)->Play();
static_cast<TSound*>(control_soundwave28_tag.Component)->Play();
auto msg = pinball::get_rc_string(9, 0);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(msg, count);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(msg, count);
}
int control::cheat_bump_rank()
@ -799,7 +799,7 @@ int control::cheat_bump_rank()
BOOL control::light_on(component_tag* tag)
{
auto light = dynamic_cast<TLight*>(tag->Component);
auto light = static_cast<TLight*>(tag->Component);
return light->BmpIndex1 || light->FlasherFlag2 || light->FlasherActive;
}
@ -859,10 +859,10 @@ void control::DeploymentChuteToEscapeChuteOneWayControl(int code, TPinballCompon
int count = control_skill_shot_lights_tag.Component->Message(37, 0.0);
if (count)
{
dynamic_cast<TSound*>(control_soundwave3_tag.Component)->Play();
static_cast<TSound*>(control_soundwave3_tag.Component)->Play();
int score = TableG->AddScore(caller->get_scoring(count - 1));
sprintf_s(Buffer, pinball::get_rc_string(21, 0), score);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(Buffer, 2.0);
static_cast<TTextBox*>(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);
@ -1109,10 +1109,10 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
TableG->Message(1022, 0.0);
if (pb::chk_highscore())
{
dynamic_cast<TSound*>(control_soundwave3_tag.Component)->Play();
static_cast<TSound*>(control_soundwave3_tag.Component)->Play();
TableG->LightGroup->Message(16, 3.0);
char* v11 = pinball::get_rc_string(177, 0);
dynamic_cast<TTextBox*>(control_mission_text_box_tag.Component)->Display(v11, -1.0);
static_cast<TTextBox*>(control_mission_text_box_tag.Component)->Display(v11, -1.0);
}
}
else
@ -1136,25 +1136,25 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
}
if (light_on(&control_lite200_tag))
{
dynamic_cast<TSound*>(control_soundwave27_tag.Component)->Play();
static_cast<TSound*>(control_soundwave27_tag.Component)->Play();
control_lite200_tag.Component->Message(19, 0.0);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(
pinball::get_rc_string(96, 0), -1.0);
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
static_cast<TSound*>(control_soundwave59_tag.Component)->Play();
}
else if (light_on(&control_lite199_tag))
{
dynamic_cast<TSound*>(control_soundwave27_tag.Component)->Play();
static_cast<TSound*>(control_soundwave27_tag.Component)->Play();
control_lite199_tag.Component->Message(20, 0.0);
control_lite200_tag.Component->Message(19, 0.0);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->
static_cast<TTextBox*>(control_info_text_box_tag.Component)->
Display(pinball::get_rc_string(95, 0), 2.0);
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
static_cast<TSound*>(control_soundwave59_tag.Component)->Play();
--TableG->UnknownP78;
}
else if (TableG->UnknownP75)
{
dynamic_cast<TSound*>(control_soundwave27_tag.Component)->Play();
static_cast<TSound*>(control_soundwave27_tag.Component)->Play();
--TableG->UnknownP75;
}
else
@ -1163,14 +1163,14 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
{
int time = SpecialAddScore(TableG->ScoreSpecial2);
sprintf_s(Buffer, pinball::get_rc_string(94, 0), time);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(Buffer, 2.0);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(Buffer, 2.0);
}
if (TableG->ExtraBalls)
{
TableG->ExtraBalls--;
char* shootAgainText;
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
static_cast<TSound*>(control_soundwave59_tag.Component)->Play();
switch (TableG->CurrentPlayer)
{
case 0:
@ -1187,7 +1187,7 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
shootAgainText = pinball::get_rc_string(100, 0);
break;
}
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(shootAgainText, -1.0);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(shootAgainText, -1.0);
}
else
{
@ -1201,7 +1201,7 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
{
control_lite199_tag.Component->MessageField = 1;
}
dynamic_cast<TSound*>(control_soundwave27_tag.Component)->Play();
static_cast<TSound*>(control_soundwave27_tag.Component)->Play();
}
control_bmpr_inc_lights_tag.Component->Message(20, 0.0);
control_ramp_bmpr_inc_lights_tag.Component->Message(20, 0.0);

View File

@ -178,7 +178,7 @@ void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
normalize_2d(&line->Direction);
line->PerpendicularL.X = line->Direction.Y;
line->PerpendicularL.Y = -line->Direction.X;
line->PreComp1 = -(line->Direction.Y * x0) + (line->Direction.X * y0);
line->PreComp1 = -(line->Direction.Y * x0) + line->Direction.X * y0;
if (line->Direction.X >= 0.000000001 || line->Direction.X <= -0.000000001)
{
v9 = x1;
@ -420,3 +420,47 @@ void maths::RotateVector(vector_type* vec, float angle)
* vec->X = tmp
*/
}
void maths::find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector_type** lineEnd,
vector_type** lineStart)
{
vector_type wallEnd{}, wallStart{};
wallStart.X = wall->X0;
wallStart.Y = wall->Y0;
wallEnd.Y = wall->Y1;
wallEnd.X = wall->X1;
float maxDistance = 1000000000.0f;
ramp_plane_type* planePtr = plane;
for (auto index = 0; index < planeCount; index++)
{
auto vec1 = reinterpret_cast<vector_type*>(&planePtr->V1),
vec2 = reinterpret_cast<vector_type*>(&planePtr->V2),
vec3 = reinterpret_cast<vector_type*>(&planePtr->V3);
auto distance = Distance(&wallStart, vec1) + Distance(&wallEnd, vec2);
if (distance < maxDistance)
{
maxDistance = distance;
*lineEnd = vec1;
*lineStart = vec2;
}
distance = Distance(&wallStart, vec2) + Distance(&wallEnd, vec3);
if (distance < maxDistance)
{
maxDistance = distance;
*lineEnd = vec2;
*lineStart = vec3;
}
distance = Distance(&wallStart, vec3) + Distance(&wallEnd, vec1);
if (distance < maxDistance)
{
maxDistance = distance;
*lineEnd = vec3;
*lineStart = vec1;
}
++planePtr;
}
}

View File

@ -45,6 +45,32 @@ struct __declspec(align(4)) line_type
vector_type RayIntersect;
};
struct vector_type2
{
int X;
int Y;
};
struct wall_point_type
{
float X0;
float Y0;
float X1;
float Y1;
};
struct __declspec(align(4)) ramp_plane_type
{
float Unknown12;
vector_type2 V0;
vector_type2 V1;
vector_type2 V2;
vector_type2 V3;
float GravityAngle1;
float GravityAngle2;
vector_type2 V5_Zero;
};
class maths
{
@ -69,4 +95,6 @@ public:
static void RotatePt(vector_type* point, float sin, float cos, vector_type* origin);
static float distance_to_flipper(ray_type* ray1, ray_type* ray2);
static void RotateVector(vector_type* vec, float angle);
static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector_type** lineEnd,
vector_type** lineStart);
};

View File

@ -9,7 +9,7 @@ class pb
{
public:
static int time_ticks;
static float ball_speed_limit, time_now;
static float ball_speed_limit, time_now, time_next;
static int cheat_mode, game_mode;
static datFileStruct* record_table;
static TPinballTable* MainTable;
@ -39,7 +39,6 @@ public:
static float collide(float timeNow, float timeDelta, TBall* ball);
private :
static int demo_mode, mode_countdown_;
static float time_next;
static high_score_struct highscore_table[5];
static int state;
};