TDrain, TKickout, TLightBargraph, TPopupTarget, TSoloTarget ready.

This commit is contained in:
oz 2021-01-17 18:26:03 +03:00
parent ffd626fbc1
commit 7e8f52c156
21 changed files with 840 additions and 29 deletions

Binary file not shown.

View file

@ -126,3 +126,15 @@ int TBall::Message(int code, float value)
}
return 0;
}
void TBall::throw_ball(TBall* ball, vector_type* acceleration, float angleMult, float speedMult1, float speedMult2)
{
ball->CollisionComp = nullptr;
ball->Acceleration = *acceleration;
float rnd = static_cast<float>(rand());
float angle = (1.0f - (rnd * 0.00003051850947599719f + rnd * 0.00003051850947599719f)) * angleMult;
maths::RotateVector(&ball->Acceleration, angle);
rnd = static_cast<float>(rand());
ball->Speed = (1.0f - (rnd * 0.00003051850947599719f + rnd * 0.00003051850947599719f)) * (speedMult1 *
speedMult2) + speedMult1;
}

View file

@ -14,13 +14,16 @@ public :
bool already_hit(TEdgeSegment* edge);
int Message(int code, float value) override;
static void throw_ball(TBall* ball, struct vector_type* acceleration, float angleMult, float speedMult1,
float speedMult2);
vector_type Position;
vector_type Acceleration;
float Speed;
float RayMaxDistance;
float TimeDelta;
float TimeNow;
vector_type InvAcceleration;
vector_type InvAcceleration;
int Unknown13;
int Unknown14;
int Unknown15;
@ -32,5 +35,5 @@ public :
int CollisionFlag;
float Offset;
int Unknown29;
float VisualZArray[50];
float VisualZArray[50];
};

View file

@ -1,2 +1,43 @@
#include "pch.h"
#include "TDrain.h"
#include "control.h"
#include "loader.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
TDrain::TDrain(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
Timer = 0;
TimerTime = *loader::query_float_attribute(groupIndex, 0, 407);
}
int TDrain::Message(int code, float value)
{
if (code == 1024)
{
if (Timer)
{
timer::kill(Timer);
Timer = 0;
}
PinballTable->BallInSink = 0;
}
return 0;
}
void TDrain::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
ball->Message(1024, 0.0);
PinballTable->BallInSink = 1;
Timer = timer::set(TimerTime, this, TimerCallback);
control::handler(63, this);
}
void TDrain::TimerCallback(int timerId, void* caller)
{
auto drain = static_cast<TDrain*>(caller);
control::handler(60, drain);
}

View file

@ -5,7 +5,13 @@ class TDrain :
public TCollisionComponent
{
public:
TDrain(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
}
TDrain(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 TimerCallback(int timerId, void* caller);
float TimerTime;
int Timer;
};

View file

@ -1,2 +1,174 @@
#include "pch.h"
#include "TKickout.h"
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "TBall.h"
#include "TCircle.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TTableLayer.h"
TKickout::TKickout(TPinballTable* table, int groupIndex, bool someFlag): TCollisionComponent(
table, groupIndex, false)
{
visualStruct visual{};
circle_type circle{};
NotSomeFlag = !someFlag;
if (!someFlag)
UnknownBaseFlag2 = 0;
TimerTime1 = 1.5;
TimerTime2 = 0.05f;
MessageField = 0;
Timer = 0;
KickFlag1 = 0;
FieldMult = *loader::query_float_attribute(groupIndex, 0, 305);
loader::query_visual(groupIndex, 0, &visual);
SoundIndex2 = visual.SoundIndex2;
SoundIndex1 = visual.Kicker.SoundIndex;
Circle.Center.X = *visual.FloatArr;
Circle.Center.Y = visual.FloatArr[1];
Circle.RadiusSq = *loader::query_float_attribute(groupIndex, 0, 306) * visual.FloatArr[2];
if (Circle.RadiusSq == 0.0)
Circle.RadiusSq = 0.001f;
auto tCircle = new TCircle(this, &UnknownBaseFlag2, visual.Flag,
reinterpret_cast<vector_type*>(visual.FloatArr), Circle.RadiusSq);
if (tCircle)
{
tCircle->place_in_grid();
EdgeList->Add(tCircle);
}
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
CollisionBallSetZ = loader::query_float_attribute(groupIndex, 0, 408)[2];
ThrowSpeedMult2 = visual.Kicker.Unknown3F * 0.01f;
BallAcceleration.X = visual.Kicker.Unknown4F;
BallAcceleration.Y = visual.Kicker.Unknown5F;
BallAcceleration.Z = visual.Kicker.Unknown6F;
ThrowAngleMult = visual.Kicker.Unknown7F;
ThrowSpeedMult1 = visual.Kicker.Unknown2F;
circle.RadiusSq = Circle.RadiusSq;
circle.Center.X = Circle.Center.X;
circle.Center.Y = Circle.Center.Y;
circle.Center.Z = Circle.Center.Z;
Field.Flag2Ptr = &UnknownBaseFlag2;
Field.CollisionComp = this;
Field.Mask = visual.Flag;
TTableLayer::edges_insert_circle(&circle, nullptr, &Field);
}
int TKickout::Message(int code, float value)
{
switch (code)
{
case 55:
if (KickFlag1)
{
if (value < 0.0)
value = TimerTime1;
Timer = timer::set(value, this, TimerExpired);
}
break;
case 1011:
if (NotSomeFlag)
UnknownBaseFlag2 = 0;
break;
case 1024:
if (KickFlag1)
{
if (Timer)
timer::kill(Timer);
TimerExpired(0, this);
}
if (NotSomeFlag)
UnknownBaseFlag2 = 0;
break;
default:
break;
}
return 0;
}
void TKickout::put_scoring(int index, int score)
{
if (index < 5)
Scores[index] = score;
}
int TKickout::get_scoring(int index)
{
return index < 5 ? Scores[index] : 0;
}
void TKickout::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef, TEdgeSegment* edge)
{
if (!KickFlag1)
{
Ball = ball;
MaxCollisionSpeed = 1000000000.0;
KickFlag1 = 1;
ball->CollisionComp = this;
ball->Position.X = Circle.Center.X;
ball->Position.Y = Circle.Center.Y;
ball->Position.Z = CollisionBallSetZ;
FieldBallZSet = ball->Position.Z;
if (PinballTable->TiltLockFlag)
{
Message(55, 0.1f);
}
else
{
loader::play_sound(SoundIndex2);
control::handler(63, this);
}
}
}
int TKickout::FieldEffect(TBall* ball, vector_type* dstVec)
{
vector_type direction{};
if (KickFlag1)
return 0;
direction.X = Circle.Center.X - ball->Position.X;
direction.Y = Circle.Center.Y - ball->Position.Y;
if (direction.Y * direction.Y + direction.X * direction.X > Circle.RadiusSq)
return 0;
maths::normalize_2d(&direction);
dstVec->X = direction.X * FieldMult - ball->Acceleration.X * ball->Speed;
dstVec->Y = direction.Y * FieldMult - ball->Acceleration.Y * ball->Speed;
return 1;
}
void TKickout::TimerExpired(int timerId, void* caller)
{
auto kick = static_cast<TKickout*>(caller);
if (kick->KickFlag1)
{
kick->KickFlag1 = 0;
kick->Timer = timer::set(kick->TimerTime2, kick, ResetTimerExpired);
if (kick->Ball)
{
kick->Ball->Position.Z = kick->FieldBallZSet;
TBall::throw_ball(kick->Ball, &kick->BallAcceleration, kick->ThrowAngleMult, kick->ThrowSpeedMult1,
kick->ThrowSpeedMult2);
kick->UnknownBaseFlag2 = 0;
kick->Ball = nullptr;
loader::play_sound(kick->SoundIndex1);
}
}
}
void TKickout::ResetTimerExpired(int timerId, void* caller)
{
auto kick = static_cast<TKickout*>(caller);
if (!kick->NotSomeFlag)
kick->UnknownBaseFlag2 = 1;
kick->Timer = 0;
}

View file

@ -1,11 +1,37 @@
#pragma once
#include "maths.h"
#include "TCollisionComponent.h"
#include "TEdgeManager.h"
class TKickout :
public TCollisionComponent
{
public:
TKickout(TPinballTable* table, int groupIndex, int vectorType) : TCollisionComponent(table, groupIndex, false)
{
}
TKickout(TPinballTable* table, int groupIndex, bool someFlag);
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;
int FieldEffect(TBall* ball, vector_type* vecDst) override;
static void TimerExpired(int timerId, void* caller);
static void ResetTimerExpired(int timerId, void* caller);
int KickFlag1;
int NotSomeFlag;
int Timer;
float TimerTime1;
float TimerTime2;
float CollisionBallSetZ;
TBall* Ball;
float FieldMult;
circle_type Circle;
float FieldBallZSet;
vector_type BallAcceleration;
float ThrowAngleMult;
float ThrowSpeedMult1;
float ThrowSpeedMult2;
field_effect_type Field;
int Scores[5];
};

View file

@ -1,2 +1,134 @@
#include "pch.h"
#include "TLightBargraph.h"
#include "control.h"
#include "loader.h"
#include "memory.h"
#include "objlist_class.h"
#include "timer.h"
#include "TPinballTable.h"
TLightBargraph::TLightBargraph(TPinballTable* table, int groupIndex) : TLightGroup(table, groupIndex)
{
TimerTimeArray = nullptr;
TLightBargraph::Reset();
if (groupIndex > 0)
{
float* floatArr = loader::query_float_attribute(groupIndex, 0, 904);
if (floatArr)
{
int count = 2 * List->Count();
TimerTimeArray = reinterpret_cast<float*>(memory::allocate(count * sizeof(float)));
if (TimerTimeArray)
{
for (int i = 0; i < count; ++floatArr)
TimerTimeArray[i++] = *floatArr;
}
}
}
}
TLightBargraph::~TLightBargraph()
{
if (TimerTimeArray)
memory::free(TimerTimeArray);
}
int TLightBargraph::Message(int code, float value)
{
switch (code)
{
case 37:
return TimeIndex;
case 45:
{
if (TimerBargraph)
{
timer::kill(TimerBargraph);
TimerBargraph = 0;
}
auto timeIndex = static_cast<int>(floor(value));
auto maxCount = 2 * List->Count();
if (timeIndex >= maxCount)
timeIndex = maxCount - 1;
if (timeIndex >= 0)
{
TLightGroup::Message(45, static_cast<float>(timeIndex / 2));
if (!(timeIndex & 1))
TLightGroup::Message(46, 0.0);
float* timeArray = TimerTimeArray;
if (timeArray)
TimerBargraph = timer::set(timeArray[timeIndex], this, BargraphTimerExpired);
TimeIndex = timeIndex;
}
else
{
TLightGroup::Message(20, 0.0);
TimeIndex = 0;
}
break;
}
case 1011:
Reset();
break;
case 1020:
if (TimerBargraph)
{
timer::kill(TimerBargraph);
TimerBargraph = 0;
}
PlayerTimerIndexBackup[PinballTable->CurrentPlayer] = TimeIndex;
Reset();
TimeIndex = PlayerTimerIndexBackup[static_cast<int>(floor(value))];
if (TimeIndex)
{
TLightBargraph::Message(45, static_cast<float>(TimeIndex));
}
break;
case 1024:
{
Reset();
int* playerPtr = PlayerTimerIndexBackup;
for (auto index = 0; index < PinballTable->PlayerCount; ++index)
{
*playerPtr = TimeIndex;
++playerPtr;
}
TLightGroup::Message(1024, value);
break;
}
default:
TLightGroup::Message(code, value);
break;
}
return 0;
}
void TLightBargraph::Reset()
{
if (TimerBargraph)
{
timer::kill(TimerBargraph);
TimerBargraph = 0;
}
TimeIndex = 0;
TLightGroup::Reset();
}
void TLightBargraph::BargraphTimerExpired(int timerId, void* caller)
{
auto bar = static_cast<TLightBargraph*>(caller);
bar->TimerBargraph = 0;
if (bar->TimeIndex)
{
bar->Message(45, static_cast<float>(bar->TimeIndex - 1));
control::handler(60, bar);
}
else
{
bar->Message(20, 0.0);
control::handler(47, bar);
}
}

View file

@ -5,7 +5,15 @@ class TLightBargraph :
public TLightGroup
{
public:
TLightBargraph(TPinballTable* table, int groupIndex) : TLightGroup(table, groupIndex)
{
}
TLightBargraph(TPinballTable* table, int groupIndex);
~TLightBargraph() override;
int Message(int code, float value) override;
void Reset() override;
static void BargraphTimerExpired(int timerId, void* caller);
float* TimerTimeArray;
int TimerBargraph;
int TimeIndex;
int PlayerTimerIndexBackup[4];
};

View file

@ -18,7 +18,7 @@ public:
TLightGroup(TPinballTable* table, int groupIndex);
~TLightGroup() override;
int Message(int code, float value) override;
void Reset();
virtual void Reset();
void reschedule_animation(float time);
void start_animation();
int next_light_up();

View file

@ -53,7 +53,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
CurScoreStruct = nullptr;
ScoreBallcount = nullptr;
ScorePlayerNumber1 = nullptr;
UnknownP10 = 0;
BallInSink = 0;
UnknownBaseFlag2 = 1;
TiltLockFlag = 0;
EndGameTimeoutTimer = 0;
@ -124,7 +124,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
new TBlocker(this, groupIndex);
break;
case 1012:
new TKickout(this, groupIndex, 1);
new TKickout(this, groupIndex, true);
break;
case 1013:
new TGate(this, groupIndex);
@ -169,7 +169,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
new TComponentGroup(this, groupIndex);
break;
case 1029:
new TKickout(this, groupIndex, 0);
new TKickout(this, groupIndex, false);
break;
case 1030:
new TLightBargraph(this, groupIndex);
@ -299,7 +299,7 @@ void TPinballTable::ChangeBallCount(int count)
void TPinballTable::tilt(float time)
{
if (!TiltLockFlag && !UnknownP10)
if (!TiltLockFlag && !BallInSink)
{
pinball::InfoTextBox->Clear();
pinball::MissTextBox->Clear();

View file

@ -49,7 +49,7 @@ public:
int SoundIndex1;
int SoundIndex2;
int SoundIndex3;
int UnknownP10;
int BallInSink;
int CurScore;
int CurScoreE9;
int LightShowTimer;

View file

@ -84,7 +84,7 @@ int TPlunger::Message(int code, float value)
ball->Position.X = PinballTable->PlungerPositionX;
ball->Position.Y = PinballTable->PlungerPositionY;
ball->UnknownBaseFlag2 = 1;
PinballTable->UnknownP10 = 0;
PinballTable->BallInSink = 0;
pb::tilt_no_more();
control::handler(code, this);
return 0;

View file

@ -1,2 +1,100 @@
#include "pch.h"
#include "TPopupTarget.h"
#include "control.h"
#include "loader.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TPopupTarget::TPopupTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
this->Timer = 0;
this->TimerTime = *loader::query_float_attribute(groupIndex, 0, 407);
}
int TPopupTarget::Message(int code, float value)
{
switch (code)
{
case 49:
this->UnknownBaseFlag2 = 0;
render::sprite_set_bitmap(this->RenderSprite, nullptr);
break;
case 50:
this->Timer = timer::set(this->TimerTime, this, TimerExpired);
break;
case 1020:
this->PlayerMessagefieldBackup[this->PinballTable->CurrentPlayer] = this->MessageField;
this->MessageField = this->PlayerMessagefieldBackup[static_cast<int>(floor(value))];
TPopupTarget::Message(50 - (MessageField != 0), 0.0);
break;
case 1024:
{
this->MessageField = 0;
int* playerPtr = this->PlayerMessagefieldBackup;
for (auto index = 0; index < this->PinballTable->PlayerCount; ++index)
{
*playerPtr = 0;
++playerPtr;
}
if (this->Timer)
timer::kill(this->Timer);
TimerExpired(0, this);
break;
}
default:
break;
}
return 0;
}
void TPopupTarget::put_scoring(int index, int score)
{
if (index < 3)
Scores[index] = score;
}
int TPopupTarget::get_scoring(int index)
{
return index < 3 ? Scores[index] : 0;
}
void TPopupTarget::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge)
{
if (this->PinballTable->TiltLockFlag)
{
maths::basic_collision(ball, nextPosition, direction, this->UnknownC4F, this->UnknownC5F, 1000000000.0, 0.0);
}
else if (maths::basic_collision(
ball,
nextPosition,
direction,
this->UnknownC4F,
this->UnknownC5F,
this->MaxCollisionSpeed,
this->CollisionMultiplier) > this->MaxCollisionSpeed)
{
if (this->SoundIndex1)
loader::play_sound(this->SoundIndex1);
this->Message(49, 0.0);
control::handler(63, this);
}
}
void TPopupTarget::TimerExpired(int timerId, void* caller)
{
auto target = static_cast<TPopupTarget*>(caller);
target->Timer = 0;
target->UnknownBaseFlag2 = 1;
render::sprite_set_bitmap(target->RenderSprite, static_cast<gdrv_bitmap8*>(target->ListBitmap->Get(0)));
if (timerId)
{
if (target->SoundIndex2)
loader::play_sound(target->SoundIndex2);
}
}

View file

@ -5,7 +5,17 @@ class TPopupTarget :
public TCollisionComponent
{
public:
TPopupTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
}
TPopupTarget(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;
int Scores[3];
int PlayerMessagefieldBackup[4];
};

View file

@ -1,2 +1,84 @@
#include "pch.h"
#include "TSoloTarget.h"
#include "control.h"
#include "loader.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TSoloTarget::TSoloTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
visualStruct visual{};
Timer = 0;
TimerTime = 0.1f;
loader::query_visual(groupIndex, 0, &visual);
SoundIndex4 = visual.SoundIndex4;
TSoloTarget::Message(50, 0.0);
}
int TSoloTarget::Message(int code, float value)
{
switch (code)
{
case 49:
case 50:
UnknownBaseFlag2 = code == 50;
break;
case 1024:
if (Timer)
timer::kill(Timer);
Timer = 0;
UnknownBaseFlag2 = 1;
break;
default:
return 0;
}
if (ListBitmap)
{
auto index = 1 - UnknownBaseFlag2;
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(index));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(index));
render::sprite_set(
RenderSprite,
bmp,
zMap,
bmp->XPosition - PinballTable->XOffset,
bmp->YPosition - PinballTable->YOffset);
}
return 0;
}
void TSoloTarget::put_scoring(int index, int score)
{
if (index < 1)
Scores[index] = score;
}
int TSoloTarget::get_scoring(int index)
{
return index < 1 ? Scores[index] : 0;
}
void TSoloTarget::Collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float coef,
TEdgeSegment* edge)
{
if (DefaultCollision(ball, nextPosition, direction))
{
Message(49, 0.0);
Timer = timer::set(TimerTime, this, TimerExpired);
control::handler(63, this);
}
}
void TSoloTarget::TimerExpired(int timerId, void* caller)
{
auto target = static_cast<TSoloTarget*>(caller);
target->Message(50, 0.0);
target->Timer = 0;
}

View file

@ -5,7 +5,18 @@ class TSoloTarget :
public TCollisionComponent
{
public:
TSoloTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
}
TSoloTarget(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 Unknown0;
int Timer;
float TimerTime;
int SoundIndex4;
int Scores[1];
};

View file

@ -4,6 +4,7 @@
#include "objlist_class.h"
#include "pb.h"
#include "TLight.h"
#include "TLightGroup.h"
#include "TPinballTable.h"
#include "TSound.h"
@ -786,9 +787,9 @@ void control::pbctrl_bdoor_controller(int key)
void control::table_add_extra_ball(float count)
{
++TableG->ExtraBalls;
static_cast<TSound*>(control_soundwave28_tag.Component)->Play();
dynamic_cast<TSound*>(control_soundwave28_tag.Component)->Play();
auto msg = pinball::get_rc_string(9, 0);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(msg, count);
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(msg, count);
}
int control::cheat_bump_rank()
@ -798,10 +799,26 @@ int control::cheat_bump_rank()
BOOL control::light_on(component_tag* tag)
{
auto light = static_cast<TLight*>(tag->Component);
auto light = dynamic_cast<TLight*>(tag->Component);
return light->BmpIndex1 || light->FlasherFlag2 || light->FlasherActive;
}
int control::SpecialAddScore(int score)
{
int prevFlag1 = TableG->ScoreSpecial3Flag;
TableG->ScoreSpecial3Flag = 0;
int prevFlag2 = TableG->ScoreSpecial2Flag;
TableG->ScoreSpecial2Flag = 0;
int prevMult = TableG->ScoreMultiplier;
TableG->ScoreMultiplier = 0;
int addedScore = TableG->AddScore(score);
TableG->ScoreSpecial2Flag = prevFlag2;
TableG->ScoreMultiplier = prevMult;
TableG->ScoreSpecial3Flag = prevFlag1;
return addedScore;
}
void control::FlipperRebounderControl1(int code, TPinballComponent* caller)
{
}
@ -842,10 +859,10 @@ void control::DeploymentChuteToEscapeChuteOneWayControl(int code, TPinballCompon
int count = control_skill_shot_lights_tag.Component->Message(37, 0.0);
if (count)
{
static_cast<TSound*>(control_soundwave3_tag.Component)->Play();
dynamic_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);
static_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(Buffer, 2.0);
dynamic_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);
@ -1083,6 +1100,185 @@ void control::MultiplierTargetControl(int code, TPinballComponent* caller)
void control::BallDrainControl(int code, TPinballComponent* caller)
{
char Buffer[64];
if (code == 60)
{
if (control_lite199_tag.Component->MessageField)
{
TableG->Message(1022, 0.0);
if (pb::chk_highscore())
{
dynamic_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);
}
}
else
{
control_plunger_tag.Component->Message(1016, 0.0);
}
}
else if (code == 63)
{
if (table_unlimited_balls)
{
control_drain_tag.Component->Message(1024, 0.0);
control_sink3_tag.Component->Message(56, 0.0);
}
else
{
if (TableG->TiltLockFlag)
{
control_lite200_tag.Component->Message(20, 0.0);
control_lite199_tag.Component->Message(20, 0.0);
}
if (light_on(&control_lite200_tag))
{
dynamic_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(
pinball::get_rc_string(96, 0), -1.0);
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
}
else if (light_on(&control_lite199_tag))
{
dynamic_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)->
Display(pinball::get_rc_string(95, 0), 2.0);
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
--TableG->UnknownP78;
}
else if (TableG->UnknownP75)
{
dynamic_cast<TSound*>(control_soundwave27_tag.Component)->Play();
--TableG->UnknownP75;
}
else
{
if (!TableG->TiltLockFlag)
{
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);
}
if (TableG->ExtraBalls)
{
TableG->ExtraBalls--;
char* shootAgainText;
dynamic_cast<TSound*>(control_soundwave59_tag.Component)->Play();
switch (TableG->CurrentPlayer)
{
case 0:
shootAgainText = pinball::get_rc_string(97, 0);
break;
case 1:
shootAgainText = pinball::get_rc_string(98, 0);
break;
case 2:
shootAgainText = pinball::get_rc_string(99, 0);
break;
default:
case 3:
shootAgainText = pinball::get_rc_string(100, 0);
break;
}
dynamic_cast<TTextBox*>(control_info_text_box_tag.Component)->Display(shootAgainText, -1.0);
}
else
{
TableG->ChangeBallCount(TableG->BallCount - 1);
if (TableG->CurrentPlayer + 1 != TableG->PlayerCount || TableG->BallCount)
{
TableG->Message(1021, 0.0);
control_lite199_tag.Component->MessageField = 0;
}
else
{
control_lite199_tag.Component->MessageField = 1;
}
dynamic_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);
control_lite30_tag.Component->Message(20, 0.0);
control_lite29_tag.Component->Message(20, 0.0);
control_lite1_tag.Component->Message(20, 0.0);
control_lite54_tag.Component->Message(20, 0.0);
control_lite55_tag.Component->Message(20, 0.0);
control_lite56_tag.Component->Message(20, 0.0);
control_lite17_tag.Component->Message(20, 0.0);
control_lite18_tag.Component->Message(20, 0.0);
control_lite27_tag.Component->Message(20, 0.0);
control_lite28_tag.Component->Message(20, 0.0);
control_lite16_tag.Component->Message(20, 0.0);
control_lite20_tag.Component->Message(20, 0.0);
control_hyper_lights_tag.Component->Message(20, 0.0);
control_lite25_tag.Component->Message(20, 0.0);
control_lite26_tag.Component->Message(20, 0.0);
control_lite130_tag.Component->Message(20, 0.0);
control_lite19_tag.Component->Message(20, 0.0);
control_worm_hole_lights_tag.Component->Message(20, 0.0);
control_bsink_arrow_lights_tag.Component->Message(20, 0.0);
control_l_trek_lights_tag.Component->Message(20, 0.0);
control_r_trek_lights_tag.Component->Message(20, 0.0);
control_lite60_tag.Component->Message(20, 0.0);
control_lite59_tag.Component->Message(20, 0.0);
control_lite61_tag.Component->Message(20, 0.0);
control_bumber_target_lights_tag.Component->Message(20, 0.0);
control_top_target_lights_tag.Component->Message(20, 0.0);
control_top_circle_tgt_lights_tag.Component->Message(20, 0.0);
control_ramp_tgt_lights_tag.Component->Message(20, 0.0);
control_lchute_tgt_lights_tag.Component->Message(20, 0.0);
control_bpr_solotgt_lights_tag.Component->Message(20, 0.0);
control_lite110_tag.Component->Message(20, 0.0);
control_skill_shot_lights_tag.Component->Message(20, 0.0);
control_lite77_tag.Component->Message(20, 0.0);
control_lite198_tag.Component->Message(20, 0.0);
control_lite196_tag.Component->Message(20, 0.0);
control_lite195_tag.Component->Message(20, 0.0);
control_fuel_bargraph_tag.Component->Message(20, 0.0);
control_fuel_bargraph_tag.Component->Message(1024, 0.0);
GravityWellKickoutControl(1024, nullptr);
control_lite62_tag.Component->Message(20, 0.0);
control_lite4_tag.Component->MessageField = 0;
control_lite101_tag.Component->MessageField = 0;
control_lite102_tag.Component->MessageField = 0;
control_lite103_tag.Component->MessageField = 0;
control_ramp_tgt_lights_tag.Component->MessageField = 0;
control_outer_circle_tag.Component->Message(34, 0.0);
control_middle_circle_tag.Component->Message(34, 0.0);
control_attack_bump_tag.Component->Message(1024, 0.0);
control_launch_bump_tag.Component->Message(1024, 0.0);
control_gate1_tag.Component->Message(1024, 0.0);
control_gate2_tag.Component->Message(1024, 0.0);
control_block1_tag.Component->Message(1024, 0.0);
control_target1_tag.Component->Message(1024, 0.0);
control_target2_tag.Component->Message(1024, 0.0);
control_target3_tag.Component->Message(1024, 0.0);
control_target6_tag.Component->Message(1024, 0.0);
control_target5_tag.Component->Message(1024, 0.0);
control_target4_tag.Component->Message(1024, 0.0);
control_target9_tag.Component->Message(1024, 0.0);
control_target8_tag.Component->Message(1024, 0.0);
control_target7_tag.Component->Message(1024, 0.0);
if (control_lite199_tag.Component->MessageField)
control_lite198_tag.Component->MessageField = 32;
else
control_lite198_tag.Component->MessageField = 0;
MissionControl(66, nullptr);
TableG->Message(1012, 0.0);
if (light_on(&control_lite58_tag))
control_lite58_tag.Component->Message(20, 0.0);
else
TableG->ScoreSpecial2 = 25000;
}
}
}
}
void control::table_control_handler(int code)

View file

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

View file

@ -408,3 +408,15 @@ float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
}
return 1000000000.0;
}
void maths::RotateVector(vector_type* vec, float angle)
{
float s = sin(angle), c = cos(angle);
vec->X = c * vec->X - s * vec->Y;
vec->Y = s * vec->X + c * vec->Y;
/* Error in the original, should be:
* tmp = c * vec->X - s * vec->Y;
* vec->Y = s * vec->X + c * vec->Y;
* vec->X = tmp
*/
}

View file

@ -68,4 +68,5 @@ public:
static void SinCos(float angle, float* sinOut, float* cosOut);
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);
};