Bug fixes from master:

Demangled and simplified cheat controller.
TKickout temp Z in FT mode.
Flipper animation frame advance.
Fuel bar graph light states.
This commit is contained in:
Muzychenko Andrey 2021-10-09 08:14:47 +03:00
parent b995b02fd1
commit de76557325
16 changed files with 145 additions and 306 deletions

3
.gitignore vendored
View file

@ -21,6 +21,9 @@ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
ARM/
ARM64/
win32/
# Visual Studio 2015 cache/options directory # Visual Studio 2015 cache/options directory
.vs/ .vs/

View file

@ -22,14 +22,14 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Smoothness = visual.Smoothness; Smoothness = visual.Smoothness;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805); auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805);
auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804); auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804);
/*Full tilt hack: different flipper speed*/ /*Full tilt hack: different flipper speed*/
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
bmpCoef2 = 0.08f; retractTime = 0.08f;
bmpCoef1 = 0.04f; extendTime = 0.04f;
} }
auto vecT2 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT2 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 802));
auto vecT1 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 801)); auto vecT1 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 801));
@ -42,8 +42,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
origin, origin,
vecT1, vecT1,
vecT2, vecT2,
bmpCoef1, extendTime,
bmpCoef2, retractTime,
collMult, collMult,
Elasticity, Elasticity,
Smoothness); Smoothness);
@ -51,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
FlipperEdge = flipperEdge; FlipperEdge = flipperEdge;
if (flipperEdge) if (flipperEdge)
{ {
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->GetCount() - 1); ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->GetCount() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->GetCount() - 1); RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->GetCount() - 1);
} }
BmpIndex = 0; BmpIndex = 0;
InputTime = 0.0; InputTime = 0.0;
@ -68,35 +68,30 @@ int TFlipper::Message(int code, float value)
if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022) if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022)
{ {
float timerTime; float timerTime;
int soundIndex = 0, code2 = code; int command = code;
if (code == 1) if (code == 1)
{ {
control::handler(1, this); control::handler(1, this);
TimerTime = BmpCoef1; TimerTime = ExtendAnimationFrameTime;
soundIndex = HardHitSoundId; loader::play_sound(HardHitSoundId);
} }
else if (code == 2) else if (code == 2)
{ {
TimerTime = BmpCoef2; TimerTime = RetractAnimationFrameTime;
soundIndex = SoftHitSoundId; loader::play_sound(SoftHitSoundId);
} }
else else
{ {
code2 = 2; // Retract for all non-input messages
TimerTime = BmpCoef2; command = 2;
TimerTime = RetractAnimationFrameTime;
} }
if (soundIndex)
loader::play_sound(soundIndex);
if (Timer)
{
timer::kill(Timer);
Timer = 0;
}
if (MessageField) if (MessageField)
{ {
auto v10 = value - FlipperEdge->InputTime; // Message arrived before animation is finished
timerTime = v10 - floor(v10 / TimerTime) * TimerTime; auto inputDt = value - FlipperEdge->InputTime;
timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime;
if (timerTime < 0.0f) if (timerTime < 0.0f)
timerTime = 0.0; timerTime = 0.0;
} }
@ -104,10 +99,13 @@ int TFlipper::Message(int code, float value)
{ {
timerTime = TimerTime; timerTime = TimerTime;
} }
MessageField = code2;
MessageField = command;
InputTime = value; InputTime = value;
if (Timer)
timer::kill(Timer);
Timer = timer::set(timerTime, this, TimerExpired); Timer = timer::set(timerTime, this, TimerExpired);
FlipperEdge->SetMotion(code2, value); FlipperEdge->SetMotion(command, value);
} }
if (code == 1020 || code == 1024) if (code == 1020 || code == 1024)
@ -137,49 +135,43 @@ void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* di
void TFlipper::TimerExpired(int timerId, void* caller) void TFlipper::TimerExpired(int timerId, void* caller)
{ {
auto flip = static_cast<TFlipper*>(caller); auto flip = static_cast<TFlipper*>(caller);
int timer; // eax int bmpCountSub1 = flip->ListBitmap->GetCount() - 1;
auto newBmpIndex = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime));
if (newBmpIndex > bmpCountSub1)
newBmpIndex = bmpCountSub1;
if (newBmpIndex < 0)
newBmpIndex = 0;
bool bmpIndexOutOfBounds = false; bool bmpIndexOutOfBounds = false;
auto bmpIndexAdvance = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f));
int bmpCount = flip->ListBitmap->GetCount();
if (bmpIndexAdvance > bmpCount)
bmpIndexAdvance = bmpCount;
if (bmpIndexAdvance < 0)
bmpIndexAdvance = 0;
if (!bmpIndexAdvance)
bmpIndexAdvance = 1;
if (flip->MessageField == 1) if (flip->MessageField == 1)
{ {
flip->BmpIndex += bmpIndexAdvance; flip->BmpIndex = newBmpIndex;
int countSub1 = flip->ListBitmap->GetCount() - 1; if (flip->BmpIndex >= bmpCountSub1)
if (flip->BmpIndex >= countSub1)
{ {
flip->BmpIndex = countSub1; flip->BmpIndex = bmpCountSub1;
bmpIndexOutOfBounds = true; bmpIndexOutOfBounds = true;
} }
} }
if (flip->MessageField == 2) if (flip->MessageField == 2)
{ {
flip->BmpIndex -= bmpIndexAdvance; flip->BmpIndex = bmpCountSub1 - newBmpIndex;
timer = 0;
if (flip->BmpIndex <= 0) if (flip->BmpIndex <= 0)
{ {
flip->BmpIndex = 0; flip->BmpIndex = 0;
bmpIndexOutOfBounds = true; bmpIndexOutOfBounds = true;
} }
} }
else
{
timer = 0;
}
if (bmpIndexOutOfBounds) if (bmpIndexOutOfBounds)
{
flip->MessageField = 0; flip->MessageField = 0;
flip->Timer = 0;
}
else else
timer = timer::set(flip->TimerTime, flip, TimerExpired); {
flip->Timer = timer; flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired);
}
auto bmp = flip->ListBitmap->Get(flip->BmpIndex); auto bmp = flip->ListBitmap->Get(flip->BmpIndex);
auto zMap = flip->ListZMap->Get(flip->BmpIndex); auto zMap = flip->ListZMap->Get(flip->BmpIndex);

View file

@ -19,8 +19,8 @@ public:
int BmpIndex; int BmpIndex;
TFlipperEdge* FlipperEdge; TFlipperEdge* FlipperEdge;
int Timer; int Timer;
float BmpCoef1; float ExtendAnimationFrameTime;
float BmpCoef2; float RetractAnimationFrameTime;
float TimerTime; float TimerTime;
float InputTime; float InputTime;
}; };

View file

@ -12,15 +12,15 @@ line_type TFlipperEdge::lineA, TFlipperEdge::lineB;
circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1;
TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table,
vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime,
float collMult, float elasticity, float smoothness): TEdgeSegment(collComp, activeFlag, collisionGroup) float collMult, float elasticity, float smoothness): TEdgeSegment(collComp, activeFlag, collisionGroup)
{ {
vector_type crossProd{}, vecDir1{}, vecDir2{}; vector_type crossProd{}, vecDir1{}, vecDir2{};
Elasticity = elasticity; Elasticity = elasticity;
Smoothness = smoothness; Smoothness = smoothness;
BmpCoef1 = bmpCoef1; ExtendTime = extendTime;
BmpCoef2 = bmpCoef2; RetractTime = retractTime;
CollisionMult = collMult; CollisionMult = collMult;
T1Src = *vecT1; T1Src = *vecT1;
@ -78,9 +78,9 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z; auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
DistanceDivSq = distance1 * distance1; DistanceDivSq = distance1 * distance1;
float bmpCoef = min(BmpCoef1, BmpCoef2); float minMoveTime = min(ExtendTime, RetractTime);
auto distance = maths::Distance(vecT1, vecT2); auto distance = maths::Distance(vecT1, vecT2);
CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius); CollisionTimeAdvance = minMoveTime / (distance / CircleT1Radius + distance / CircleT1Radius);
TFlipperEdge::place_in_grid(); TFlipperEdge::place_in_grid();
EdgeCollisionFlag = 0; EdgeCollisionFlag = 0;
@ -469,12 +469,12 @@ void TFlipperEdge::SetMotion(int code, float value)
case 1: case 1:
Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
Angle1 = AngleMax; Angle1 = AngleMax;
AngleMult = BmpCoef1; AngleMult = ExtendTime;
break; break;
case 2: case 2:
Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
Angle1 = 0.0; Angle1 = 0.0;
AngleMult = BmpCoef2; AngleMult = RetractTime;
break; break;
case 1024: case 1024:
FlipperFlag = 0; FlipperFlag = 0;

View file

@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment
{ {
public: public:
TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table,
vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, float collMult, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime, float collMult,
float elasticity, float smoothness); float elasticity, float smoothness);
void port_draw() override; void port_draw() override;
float FindCollisionDistance(ray_type* ray) override; float FindCollisionDistance(ray_type* ray) override;
@ -50,8 +50,8 @@ public:
float InputTime; float InputTime;
float AngleStopTime; float AngleStopTime;
float AngleMult; float AngleMult;
float BmpCoef1; float ExtendTime;
float BmpCoef2; float RetractTime;
vector_type NextBallPosition; vector_type NextBallPosition;
static float flipper_sin_angle, flipper_cos_angle; static float flipper_sin_angle, flipper_cos_angle;

View file

@ -5,6 +5,7 @@
#include "control.h" #include "control.h"
#include "loader.h" #include "loader.h"
#include "objlist_class.h" #include "objlist_class.h"
#include "pb.h"
#include "TBall.h" #include "TBall.h"
#include "TCircle.h" #include "TCircle.h"
#include "timer.h" #include "timer.h"
@ -44,7 +45,8 @@ TKickout::TKickout(TPinballTable* table, int groupIndex, bool someFlag): TCollis
} }
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
CollisionBallSetZ = loader::query_float_attribute(groupIndex, 0, 408)[2]; auto zAttr = loader::query_float_attribute(groupIndex, 0, 408);
CollisionBallSetZ = pb::FullTiltMode ? zAttr[3] : zAttr[2];
ThrowSpeedMult2 = visual.Kicker.ThrowBallMult * 0.01f; ThrowSpeedMult2 = visual.Kicker.ThrowBallMult * 0.01f;
BallAcceleration = visual.Kicker.ThrowBallAcceleration; BallAcceleration = visual.Kicker.ThrowBallAcceleration;
ThrowAngleMult = visual.Kicker.ThrowBallAngleMult; ThrowAngleMult = visual.Kicker.ThrowBallAngleMult;

View file

@ -57,9 +57,8 @@ int TLightBargraph::Message(int code, float value)
TLightGroup::Message(45, static_cast<float>(timeIndex / 2)); TLightGroup::Message(45, static_cast<float>(timeIndex / 2));
if (!(timeIndex & 1)) if (!(timeIndex & 1))
TLightGroup::Message(46, 0.0); TLightGroup::Message(46, 0.0);
float* timeArray = TimerTimeArray; if (TimerTimeArray)
if (timeArray) TimerBargraph = timer::set(TimerTimeArray[timeIndex], this, BargraphTimerExpired);
TimerBargraph = timer::set(timeArray[timeIndex], this, BargraphTimerExpired);
TimeIndex = timeIndex; TimeIndex = timeIndex;
} }
else else

View file

@ -374,31 +374,21 @@ int TLightGroup::Message(int code, float value)
} }
case 45: case 45:
{ {
auto count = List->GetCount();
control::handler(code, this); control::handler(code, this);
auto index = static_cast<int>(floor(value)); auto index = static_cast<int>(floor(value));
if (index >= 0) if (index >= 0 && index < count)
{ {
auto count = List->GetCount(); // Turn off lights (index, end]
if (index <= count) for (auto i = count - 1; i > index; i--)
{ {
auto countSub1 = count - 1; List->Get(i)->Message(20, 0.0);
if (countSub1 > index) }
{
countSub1 = index; // Turn on lights [begin, index]
for (auto i = countSub1, k = countSub1 - index; k != 0; i--, k--) for (auto i = index; i >= 0; i--)
{ {
auto light = List->Get(i); List->Get(i)->Message(19, 0.0);
light->Message(20, 0.0);
}
}
if (countSub1 >= 0)
{
for (auto i = countSub1; i != 0; i--)
{
auto light = List->Get(i);
light->Message(19, 0.0);
}
}
} }
} }
break; break;
@ -477,7 +467,7 @@ int TLightGroup::next_light_down()
{ {
for (int index = List->GetCount() - 1; index >= 0; --index) for (int index = List->GetCount() - 1; index >= 0; --index)
{ {
if (!List->Get(index)->BmpIndex1) if (List->Get(index)->BmpIndex1)
return index; return index;
} }
return -1; return -1;

View file

@ -109,7 +109,7 @@ void TTextBox::Clear()
} }
} }
void TTextBox::Display(char* text, float time) void TTextBox::Display(const char* text, float time)
{ {
if (!text) if (!text)
return; return;

View file

@ -21,7 +21,7 @@ public:
~TTextBox() override; ~TTextBox() override;
int Message(int code, float value) override; int Message(int code, float value) override;
void Clear(); void Clear();
void Display(char* text, float time); void Display(const char* text, float time);
void Draw(); void Draw();
static void TimerExpired(int timerId, void* tb); static void TimerExpired(int timerId, void* tb);

View file

@ -3,7 +3,7 @@
#include "memory.h" #include "memory.h"
#include "pb.h" #include "pb.h"
TTextBoxMessage::TTextBoxMessage(char* text, float time) TTextBoxMessage::TTextBoxMessage(const char* text, float time)
{ {
NextMessage = nullptr; NextMessage = nullptr;
Time = time; Time = time;

View file

@ -7,7 +7,7 @@ public:
float Time; float Time;
int EndTicks; int EndTicks;
TTextBoxMessage(char* text, float time); TTextBoxMessage(const char* text, float time);
~TTextBoxMessage(); ~TTextBoxMessage();
float TimeLeft() const; float TimeLeft() const;
void Refresh(float time); void Refresh(float time);

View file

@ -28,8 +28,6 @@
#include "TPlunger.h" #include "TPlunger.h"
#include "TWall.h" #include "TWall.h"
int control::pbctrl_state;
int control_bump_scores1[] = {500, 1000, 1500, 2000}; int control_bump_scores1[] = {500, 1000, 1500, 2000};
int control_roll_scores1[] = {2000}; int control_roll_scores1[] = {2000};
int control_bump_scores2[] = {1500, 2500, 3500, 4500}; int control_bump_scores2[] = {1500, 2500, 3500, 4500};
@ -528,7 +526,8 @@ component_tag_base* control::simple_components[142]
&control_soundwave7_tag &control_soundwave7_tag
}; };
int control::table_unlimited_balls, control::waiting_deployment_flag; int control::waiting_deployment_flag;
bool control::table_unlimited_balls = false;
int control::extraball_light_flag; int control::extraball_light_flag;
int control::RankRcArray[9] = {84, 85, 86, 87, 88, 89, 90, 91, 92}; int control::RankRcArray[9] = {84, 85, 86, 87, 88, 89, 90, 91, 92};
int control::MissionRcArray[17] = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76}; int control::MissionRcArray[17] = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76};
@ -631,212 +630,65 @@ void control::handler(int code, TPinballComponent* cmp)
MissionControl(code, cmp); MissionControl(code, cmp);
} }
void control::pbctrl_bdoor_controller(int key) void control::pbctrl_bdoor_controller(char key)
{ {
int v1; // eax // Buffer large enough for longest cheat + null
int v2; // eax static char cheatBuffer[11 + 1]{};
bool v3; // zf static char* bufferEnd = &cheatBuffer[11];
static const char* quotes[8]
if (!control_lite198_tag.Component->MessageField)
{ {
if (key <= 'M') "Hey, is that a screen saver?",
{ "I guess it has been a good week",
if (key == 'M') "She may already be a glue bottle",
{ "If you don't come in Saturday,\n...\n",
v2 = pbctrl_state; "don't even bother coming in Sunday.",
if (pbctrl_state == 4 || pbctrl_state == 61 || pbctrl_state == 81 || pbctrl_state == 101) "Tomorrow already sucks",
goto LABEL_87; "I knew it worked too good to be right.",
v3 = pbctrl_state == 121; "World's most expensive flippers"
} };
else
{ if (control_lite198_tag.Component->MessageField)
if (key <= 'D') {
{ return;
if (key != 'D')
{
if (key == ' ')
{
if (pbctrl_state == 26)
{
pbctrl_state = 27;
return;
}
goto LABEL_77;
}
if (key != '1')
{
if (key != 'A')
{
if (key != 'B')
{
if (key == 'C')
{
if (!pbctrl_state)
{
pbctrl_state = 1;
return;
}
if (pbctrl_state == 11)
{
pbctrl_state = 12;
return;
}
}
goto LABEL_77;
}
v1 = pbctrl_state != 0 ? 0 : 81;
goto LABEL_88;
}
v2 = pbctrl_state;
if (pbctrl_state == 5 || pbctrl_state == 62 || pbctrl_state == 82 || pbctrl_state == 102)
goto LABEL_87;
v3 = pbctrl_state == 122;
goto LABEL_86;
}
v1 = pbctrl_state != 0 ? 0 : 61;
LABEL_88:
pbctrl_state = v1;
return;
}
if (pbctrl_state != 22 && pbctrl_state != 23)
goto LABEL_77;
LABEL_58:
++pbctrl_state;
return;
}
if (key != 'E')
{
switch (key)
{
case 'G':
v1 = pbctrl_state != 0 ? 0 : 101;
break;
case 'H':
v1 = pbctrl_state != 0 ? 0 : 21;
break;
case 'I':
v2 = pbctrl_state;
if (pbctrl_state == 1 || pbctrl_state == 10)
goto LABEL_87;
v3 = pbctrl_state == 21;
goto LABEL_86;
default:
goto LABEL_77;
}
goto LABEL_88;
}
v2 = pbctrl_state;
if (pbctrl_state == 3 || pbctrl_state == 24 || pbctrl_state == 28)
goto LABEL_87;
v3 = pbctrl_state == 44;
}
goto LABEL_86;
}
if (key <= 'S')
{
if (key == 'S')
{
v2 = pbctrl_state;
if (pbctrl_state == 12 || pbctrl_state == 29)
goto LABEL_87;
v3 = pbctrl_state == 45;
}
else
{
if (key != 'N')
{
if (key != 'O')
{
if (key != 'Q')
{
if (key == 'R')
{
if (!pbctrl_state)
{
pbctrl_state = 121;
return;
}
if (pbctrl_state == 7)
{
pbctrl_state = 8;
return;
}
}
goto LABEL_77;
}
v1 = pbctrl_state != 0 ? 0 : 41;
goto LABEL_88;
}
if (pbctrl_state != 8 && pbctrl_state != 42)
goto LABEL_77;
goto LABEL_58;
}
v2 = pbctrl_state;
if (pbctrl_state == 2 || pbctrl_state == 9)
goto LABEL_87;
v3 = pbctrl_state == 25;
}
LABEL_86:
if (v3)
{
LABEL_87:
v1 = v2 + 1;
goto LABEL_88;
}
LABEL_77:
pbctrl_state = 0;
return;
}
switch (key)
{
case 'T':
v2 = pbctrl_state;
if (pbctrl_state != 30)
{
if (pbctrl_state == 27 || pbctrl_state == 6)
goto LABEL_87;
v3 = pbctrl_state == 43;
goto LABEL_86;
}
pb::cheat_mode = 1;
break;
case 'U':
if (pbctrl_state == 41)
{
pbctrl_state = 42;
return;
}
goto LABEL_77;
case 'X':
if (pbctrl_state == 63)
{
table_add_extra_ball(2.0);
goto LABEL_76;
}
if (pbctrl_state != 83)
{
if (pbctrl_state == 103)
{
GravityWellKickoutControl(64, nullptr);
}
else
{
if (pbctrl_state != 123)
goto LABEL_77;
cheat_bump_rank();
}
LABEL_76:
TableG->CheatsUsed = 1;
goto LABEL_77;
}
table_unlimited_balls = 1;
break;
default:
goto LABEL_77;
}
TableG->CheatsUsed = 1;
goto LABEL_77;
} }
std::memmove(&cheatBuffer[0], &cheatBuffer[1], 10);
cheatBuffer[10] = key;
if (strcmp(bufferEnd - 11, "HIDDEN TEST") == 0)
{
pb::cheat_mode ^= true;
}
else if (strcmp(bufferEnd - 4, "GMAX") == 0)
{
GravityWellKickoutControl(64, nullptr);
}
else if (strcmp(bufferEnd - 4, "1MAX") == 0)
{
table_add_extra_ball(2.0);
}
else if (strcmp(bufferEnd - 4, "BMAX") == 0)
{
table_unlimited_balls ^= true;
}
else if (strcmp(bufferEnd - 4, "RMAX") == 0)
{
cheat_bump_rank();
}
else if (pb::FullTiltMode && strcmp(bufferEnd - 5, "QUOTE") == 0)
{
// A sad developer easter egg type 'cheat' from Full Tilt
float time = 0;
for (auto quote : quotes)
control_mission_text_box_tag.Component->Display(quote, time += 3);
return;
}
else
{
return;
}
TableG->CheatsUsed = 1;
} }
void control::table_add_extra_ball(float count) void control::table_add_extra_ball(float count)
@ -2339,7 +2191,7 @@ void control::PlungerControl(int code, TPinballComponent* caller)
} }
else if (code == 1016) else if (code == 1016)
{ {
table_unlimited_balls = 0; table_unlimited_balls = false;
if (!control_middle_circle_tag.Component->Message(37, 0.0)) if (!control_middle_circle_tag.Component->Message(37, 0.0))
control_middle_circle_tag.Component->Message(32, 0.0); control_middle_circle_tag.Component->Message(32, 0.0);
if (!light_on(&control_lite200_tag)) if (!light_on(&control_lite200_tag))
@ -2638,7 +2490,7 @@ void control::table_control_handler(int code)
{ {
if (code == 1011) if (code == 1011)
{ {
table_unlimited_balls = 0; table_unlimited_balls = false;
control_lite77_tag.Component->Message(7, 0.0); control_lite77_tag.Component->Message(7, 0.0);
} }
} }

View file

@ -65,14 +65,15 @@ public:
static TPinballTable* TableG; static TPinballTable* TableG;
static component_info score_components[88]; static component_info score_components[88];
static component_tag_base* simple_components[142]; static component_tag_base* simple_components[142];
static int table_unlimited_balls, waiting_deployment_flag; static int waiting_deployment_flag;
static bool table_unlimited_balls;
static int RankRcArray[9], MissionRcArray[17], mission_select_scores[17]; static int RankRcArray[9], MissionRcArray[17], mission_select_scores[17];
static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3]; static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
static void make_links(TPinballTable* table); static void make_links(TPinballTable* table);
static TPinballComponent* make_component_link(component_tag_base* tag); static TPinballComponent* make_component_link(component_tag_base* tag);
static void handler(int code, TPinballComponent* cmp); static void handler(int code, TPinballComponent* cmp);
static void pbctrl_bdoor_controller(int key); static void pbctrl_bdoor_controller(char key);
static void table_add_extra_ball(float count); static void table_add_extra_ball(float count);
static void table_set_bonus_hold(); static void table_set_bonus_hold();
static void table_set_bonus(); static void table_set_bonus();
@ -182,6 +183,5 @@ public:
static void UnselectMissionController(int code, TPinballComponent* caller); static void UnselectMissionController(int code, TPinballComponent* caller);
static void WaitingDeploymentController(int code, TPinballComponent* caller); static void WaitingDeploymentController(int code, TPinballComponent* caller);
private: private:
static int pbctrl_state;
static int extraball_light_flag; static int extraball_light_flag;
}; };

View file

@ -26,10 +26,10 @@
TPinballTable* pb::MainTable = nullptr; TPinballTable* pb::MainTable = nullptr;
datFileStruct* pb::record_table = nullptr; datFileStruct* pb::record_table = nullptr;
int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::state; int pb::time_ticks = 0, pb::demo_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::state;
float pb::time_now, pb::time_next, pb::ball_speed_limit; float pb::time_now, pb::time_next, pb::ball_speed_limit;
high_score_struct pb::highscore_table[5]; high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = false; bool pb::FullTiltMode = false, pb::cheat_mode = false;
int pb::init() int pb::init()
@ -404,7 +404,7 @@ void pb::keydown(int key)
mode_countdown(-1); mode_countdown(-1);
return; return;
} }
control::pbctrl_bdoor_controller(key); control::pbctrl_bdoor_controller(static_cast<char>(key));
if (key == options::Options.LeftFlipperKey) if (key == options::Options.LeftFlipperKey)
{ {
MainTable->Message(1000, time_now); MainTable->Message(1000, time_now);

View file

@ -10,7 +10,8 @@ class pb
public: public:
static int time_ticks; static int time_ticks;
static float ball_speed_limit, time_now, time_next; static float ball_speed_limit, time_now, time_next;
static int cheat_mode, game_mode; static int game_mode;
static bool cheat_mode;
static datFileStruct* record_table; static datFileStruct* record_table;
static TPinballTable* MainTable; static TPinballTable* MainTable;
static high_score_struct highscore_table[5]; static high_score_struct highscore_table[5];