mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-22 11:56:24 +01:00
TDrain, TKickout, TLightBargraph, TPopupTarget, TSoloTarget ready.
This commit is contained in:
parent
ffd626fbc1
commit
7e8f52c156
21 changed files with 840 additions and 29 deletions
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
int SoundIndex1;
|
||||
int SoundIndex2;
|
||||
int SoundIndex3;
|
||||
int UnknownP10;
|
||||
int BallInSink;
|
||||
int CurScore;
|
||||
int CurScoreE9;
|
||||
int LightShowTimer;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue