mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-14 19:25:18 -05:00
169 lines
4.4 KiB
C++
169 lines
4.4 KiB
C++
#include "pch.h"
|
|
#include "TKickout.h"
|
|
|
|
|
|
#include "control.h"
|
|
#include "loader.h"
|
|
#include "pb.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)
|
|
ActiveFlag = 0;
|
|
TimerTime1 = 1.5;
|
|
TimerTime2 = 0.05f;
|
|
MessageField = 0;
|
|
Timer = 0;
|
|
BallCaputeredFlag = 0;
|
|
FieldMult = *loader::query_float_attribute(groupIndex, 0, 305);
|
|
loader::query_visual(groupIndex, 0, &visual);
|
|
SoftHitSoundId = visual.SoftHitSoundId;
|
|
HardHitSoundId = visual.Kicker.HardHitSoundId;
|
|
|
|
Circle.Center.X = visual.FloatArr[0];
|
|
Circle.Center.Y = visual.FloatArr[1];
|
|
Circle.RadiusSq = *loader::query_float_attribute(groupIndex, 0, 306) * visual.FloatArr[2];
|
|
if (Circle.RadiusSq == 0.0f)
|
|
Circle.RadiusSq = 0.001f;
|
|
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup,
|
|
reinterpret_cast<vector3*>(visual.FloatArr), Circle.RadiusSq);
|
|
if (tCircle)
|
|
{
|
|
tCircle->place_in_grid(&AABB);
|
|
EdgeList.push_back(tCircle);
|
|
}
|
|
|
|
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
|
|
auto zAttr = loader::query_float_attribute(groupIndex, 0, 408);
|
|
CollisionBallSetZ = pb::FullTiltMode && !pb::FullTiltDemoMode ? zAttr[3] : zAttr[2];
|
|
ThrowSpeedMult2 = visual.Kicker.ThrowBallMult * 0.01f;
|
|
BallThrowDirection = visual.Kicker.ThrowBallDirection;
|
|
ThrowAngleMult = visual.Kicker.ThrowBallAngleMult;
|
|
ThrowSpeedMult1 = visual.Kicker.Boost;
|
|
|
|
circle.RadiusSq = Circle.RadiusSq;
|
|
circle.Center.X = Circle.Center.X;
|
|
circle.Center.Y = Circle.Center.Y;
|
|
Field.ActiveFlag = &ActiveFlag;
|
|
Field.CollisionComp = this;
|
|
Field.CollisionGroup = visual.CollisionGroup;
|
|
TTableLayer::edges_insert_circle(&circle, nullptr, &Field);
|
|
}
|
|
|
|
int TKickout::Message(MessageCode code, float value)
|
|
{
|
|
switch (code)
|
|
{
|
|
case MessageCode::TKickoutRestartTimer:
|
|
if (BallCaputeredFlag)
|
|
{
|
|
if (value < 0.0f)
|
|
value = TimerTime1;
|
|
Timer = timer::set(value, this, TimerExpired);
|
|
}
|
|
break;
|
|
case MessageCode::SetTiltLock:
|
|
if (NotSomeFlag)
|
|
ActiveFlag = 0;
|
|
break;
|
|
case MessageCode::Reset:
|
|
if (BallCaputeredFlag)
|
|
{
|
|
if (Timer)
|
|
timer::kill(Timer);
|
|
TimerExpired(0, this);
|
|
}
|
|
if (NotSomeFlag)
|
|
ActiveFlag = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void TKickout::Collision(TBall* ball, vector2* nextPosition, vector2* direction, float distance, TEdgeSegment* edge)
|
|
{
|
|
if (!BallCaputeredFlag)
|
|
{
|
|
Ball = ball;
|
|
Threshold = 1000000000.0;
|
|
BallCaputeredFlag = 1;
|
|
ball->CollisionComp = this;
|
|
ball->Position.X = Circle.Center.X;
|
|
ball->Position.Y = Circle.Center.Y;
|
|
OriginalBallZ = ball->Position.Z;
|
|
ball->Position.Z = CollisionBallSetZ;
|
|
ball->CollisionDisabledFlag = true;
|
|
if (PinballTable->TiltLockFlag)
|
|
{
|
|
Message(MessageCode::TKickoutRestartTimer, 0.1f);
|
|
}
|
|
else
|
|
{
|
|
loader::play_sound(SoftHitSoundId, ball, "TKickout1");
|
|
control::handler(MessageCode::ControlCollision, this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ball->Position.X = nextPosition->X;
|
|
ball->Position.Y = nextPosition->Y;
|
|
ball->RayMaxDistance -= distance;
|
|
ball->not_again(edge);
|
|
}
|
|
}
|
|
|
|
int TKickout::FieldEffect(TBall* ball, vector2* dstVec)
|
|
{
|
|
vector2 direction{};
|
|
|
|
if (BallCaputeredFlag)
|
|
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->Direction.X * ball->Speed;
|
|
dstVec->Y = direction.Y * FieldMult - ball->Direction.Y * ball->Speed;
|
|
return 1;
|
|
}
|
|
|
|
void TKickout::TimerExpired(int timerId, void* caller)
|
|
{
|
|
auto kick = static_cast<TKickout*>(caller);
|
|
if (kick->BallCaputeredFlag)
|
|
{
|
|
kick->BallCaputeredFlag = 0;
|
|
kick->Timer = timer::set(kick->TimerTime2, kick, ResetTimerExpired);
|
|
if (kick->Ball)
|
|
{
|
|
loader::play_sound(kick->HardHitSoundId, kick->Ball, "TKickout2");
|
|
kick->Ball->Position.Z = kick->OriginalBallZ;
|
|
kick->Ball->throw_ball(&kick->BallThrowDirection, kick->ThrowAngleMult, kick->ThrowSpeedMult1,
|
|
kick->ThrowSpeedMult2);
|
|
kick->ActiveFlag = 0;
|
|
kick->Ball = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TKickout::ResetTimerExpired(int timerId, void* caller)
|
|
{
|
|
auto kick = static_cast<TKickout*>(caller);
|
|
if (!kick->NotSomeFlag)
|
|
kick->ActiveFlag = 1;
|
|
kick->Timer = 0;
|
|
}
|