From 1ea247e185c7fe12c3f8731768388e6b15bf2758 Mon Sep 17 00:00:00 2001 From: oz Date: Wed, 6 Jan 2021 17:06:13 +0300 Subject: [PATCH] pb, cheats ready. Collison v1, mouse fixed. --- Doc/FuncStats.xlsx | Bin 37904 -> 38023 bytes SpaceCadetPinball/TBall.cpp | 16 +- SpaceCadetPinball/TBall.h | 11 +- SpaceCadetPinball/TCollisionComponent.cpp | 63 ++- SpaceCadetPinball/TCollisionComponent.h | 7 + SpaceCadetPinball/TEdgeManager.cpp | 10 + SpaceCadetPinball/TEdgeManager.h | 3 + SpaceCadetPinball/TPinballTable.cpp | 2 +- SpaceCadetPinball/TPinballTable.h | 2 +- SpaceCadetPinball/control.cpp | 229 ++++++++++- SpaceCadetPinball/control.h | 10 +- SpaceCadetPinball/fullscrn.cpp | 2 +- SpaceCadetPinball/fullscrn.h | 2 +- SpaceCadetPinball/maths.cpp | 48 ++- SpaceCadetPinball/maths.h | 6 + SpaceCadetPinball/nudge.cpp | 2 +- SpaceCadetPinball/options.cpp | 4 +- SpaceCadetPinball/pb.cpp | 169 +++++++- SpaceCadetPinball/pb.h | 8 +- SpaceCadetPinball/winmain.cpp | 463 +++++++++++----------- 20 files changed, 773 insertions(+), 284 deletions(-) diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index c6cb10b640dc4cb9d1a602d94eed138b463f310c..ed22afb5506446b4d545dab2ddfa8f55a06c1ea3 100644 GIT binary patch delta 31210 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 delta 31057 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 diff --git a/SpaceCadetPinball/TBall.cpp b/SpaceCadetPinball/TBall.cpp index f866293..574873b 100644 --- a/SpaceCadetPinball/TBall.cpp +++ b/SpaceCadetPinball/TBall.cpp @@ -14,13 +14,13 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) { visualStruct visual{}; - Unknown9F = 0.0; - Unknown7F = 0.0; + TimeNow = 0.0; + RayMaxDistance = 0.0; UnknownBaseFlag2 = 1; - Unknown16 = 0; + CollisionComp = nullptr; EdgeCollisionCount = 0; - Unknown8F = 0.0; - Unknown17 = 1; + TimeDelta = 0.0; + Unknown17F = 1; CollisionFlag = 0; Speed = 0.0; Acceleration.Y = 0.0; @@ -113,16 +113,16 @@ int TBall::Message(int code, float value) { render::ball_set(RenderSprite, nullptr, 0.0, 0, 0); Position.X = 0.0; - Unknown16 = 0; + CollisionComp = nullptr; Position.Y = 0.0; UnknownBaseFlag2 = 0; CollisionFlag = 0; - Unknown17 = 1; + Unknown17F = 1; Acceleration.Y = 0.0; Position.Z = Offset; Acceleration.X = 0.0; Speed = 0.0; - Unknown7F = 0.0; + RayMaxDistance = 0.0; } return 0; } diff --git a/SpaceCadetPinball/TBall.h b/SpaceCadetPinball/TBall.h index e3ee29e..e7ef2a3 100644 --- a/SpaceCadetPinball/TBall.h +++ b/SpaceCadetPinball/TBall.h @@ -2,6 +2,7 @@ #include "maths.h" #include "TPinballComponent.h" +class TCollisionComponent; class TEdgeSegment; class TBall : public TPinballComponent @@ -16,15 +17,15 @@ public : vector_type Position; vector_type Acceleration; float Speed; - float Unknown7F; - float Unknown8F; - float Unknown9F; + float RayMaxDistance; + float TimeDelta; + float TimeNow; vector_type InvAcceleration; int Unknown13; int Unknown14; int Unknown15; - int Unknown16; - int Unknown17; + TCollisionComponent* CollisionComp; + float Unknown17F; TEdgeSegment* Collisions[5]; int EdgeCollisionCount; vector_type CollisionOffset; diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp index 5da51ae..762b136 100644 --- a/SpaceCadetPinball/TCollisionComponent.cpp +++ b/SpaceCadetPinball/TCollisionComponent.cpp @@ -46,7 +46,7 @@ TCollisionComponent::~TCollisionComponent() EdgeList->Delete(edge); delete edge; } - delete this->EdgeList; + delete EdgeList; } @@ -57,3 +57,64 @@ void TCollisionComponent::port_draw() static_cast(EdgeList->Get(index))->port_draw(); } } + +int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* ballPosition, vector_type* vec2) +{ + if (PinballTable->TiltLockFlag) + { + maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F, 1000000000.0, 0.0); + return 0; + } + auto projSpeed = maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F, + UnknownC7F, + UnknownC6F); + if (projSpeed <= UnknownC7F) + { + if (projSpeed > 0.2) + { + if (SoundIndex2) + loader::play_sound(SoundIndex2); + } + return 0; + } + if (SoundIndex1) + loader::play_sound(SoundIndex1); + return 1; +} + +void TCollisionComponent::Collision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2, + float someVal, TEdgeSegment* edge) +{ + int soundIndex; + + if (PinballTable->TiltLockFlag) + { + maths::basic_collision(ball, ballPosition, vec2, UnknownC4F, UnknownC5F, 1000000000.0, 0.0); + return; + } + double projSpeed = maths::basic_collision( + ball, + ballPosition, + vec2, + UnknownC4F, + UnknownC5F, + UnknownC7F, + UnknownC6F); + if (projSpeed <= UnknownC7F) + { + if (projSpeed <= 0.2) + return; + soundIndex = SoundIndex2; + } + else + { + soundIndex = SoundIndex1; + } + if (soundIndex) + loader::play_sound(soundIndex); +} + +int TCollisionComponent::FieldEffect(TBall* ball, vector_type* vecDst) +{ + return 0; +} diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h index 738c49f..dc66cd2 100644 --- a/SpaceCadetPinball/TCollisionComponent.h +++ b/SpaceCadetPinball/TCollisionComponent.h @@ -2,6 +2,9 @@ #include "objlist_class.h" #include "TPinballComponent.h" +class TEdgeSegment; +class TBall; + class TCollisionComponent : public TPinballComponent { public: @@ -18,4 +21,8 @@ public: TCollisionComponent(TPinballTable* table, int groupIndex, bool createWall); ~TCollisionComponent(); void port_draw() override; + virtual void Collision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2, float someVal, + TEdgeSegment* edge); + virtual int FieldEffect(TBall* ball, struct vector_type* vecDst); + int DefaultCollision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2); }; diff --git a/SpaceCadetPinball/TEdgeManager.cpp b/SpaceCadetPinball/TEdgeManager.cpp index 65e1609..b22c884 100644 --- a/SpaceCadetPinball/TEdgeManager.cpp +++ b/SpaceCadetPinball/TEdgeManager.cpp @@ -1,6 +1,16 @@ #include "pch.h" #include "TEdgeManager.h" +int TEdgeManager::FieldEffects(TBall* ball, vector_type* vecDst) +{ + return 0; +} + void TEdgeManager::edges_insert_square(float a1, float a2, float a3, float a4, TEdgeSegment* a5, field_effect_type* a6) { } + +float TEdgeManager::FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegment** edge) +{ + return 1000000000.0; +} diff --git a/SpaceCadetPinball/TEdgeManager.h b/SpaceCadetPinball/TEdgeManager.h index 9a92d3f..5e34342 100644 --- a/SpaceCadetPinball/TEdgeManager.h +++ b/SpaceCadetPinball/TEdgeManager.h @@ -16,5 +16,8 @@ public: { } + int FieldEffects(TBall* ball, struct vector_type* vecDst); + static void edges_insert_square(float a1, float a2, float a3, float a4, TEdgeSegment* a5, field_effect_type* a6); + float FindCollisionDistance(ray_type* ray, TBall* ball, TEdgeSegment** edge); }; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 7e2f713..aebcbc5 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -403,7 +403,7 @@ int TPinballTable::Message(int code, float value) } else { - UnknownP6 = 0; + CheatsUsed = 0; Message(1024, 0.0); auto ball = static_cast(BallList->Get(0)); ball->Position.Y = 0.0; diff --git a/SpaceCadetPinball/TPinballTable.h b/SpaceCadetPinball/TPinballTable.h index 31dbce7..39e7897 100644 --- a/SpaceCadetPinball/TPinballTable.h +++ b/SpaceCadetPinball/TPinballTable.h @@ -45,7 +45,7 @@ public: scoreStruct* CurScoreStruct; scoreStruct* ScoreBallcount; scoreStruct* ScorePlayerNumber1; - int UnknownP6; + int CheatsUsed; int SoundIndex1; int SoundIndex2; int SoundIndex3; diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index 5e15d4e..21d95fc 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -2,7 +2,11 @@ #include "control.h" #include "objlist_class.h" +#include "pb.h" #include "TPinballTable.h" +#include "TSound.h" + +int control::pbctrl_state; int control_bump_scores1[] = {500, 1000, 1500, 2000}; int control_roll_scores1[] = {2000}; @@ -502,7 +506,7 @@ component_tag* control::simple_components[142] &control_soundwave7_tag }; -int control::table_control_flag; +int control::table_unlimited_balls; void control::make_links(TPinballTable* table) @@ -570,6 +574,227 @@ void control::handler(int code, TPinballComponent* cmp) MissionControl(code, cmp); } +void control::pbctrl_bdoor_controller(int key) +{ + int v1; // eax + int v2; // eax + bool v3; // zf + + if (!control_lite198_tag.Component->MessageField) + { + if (key <= 'M') + { + if (key == 'M') + { + v2 = pbctrl_state; + if (pbctrl_state == 4 || pbctrl_state == 61 || pbctrl_state == 81 || pbctrl_state == 101) + goto LABEL_87; + v3 = pbctrl_state == 121; + } + else + { + if (key <= 'D') + { + 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; + } +} + +void control::table_add_extra_ball(float count) +{ + ++TableG->ExtraBalls; + static_cast(control_soundwave28_tag.Component)->Play(); + auto msg = pinball::get_rc_string(9, 0); + static_cast(control_info_text_box_tag.Component)->Display(msg, count); +} + +int control::cheat_bump_rank() +{ + return 0; +} + void control::FlipperRebounderControl1(int code, TPinballComponent* caller) { } @@ -806,7 +1031,7 @@ void control::table_control_handler(int code) { if (code == 1011) { - table_control_flag = 0; + table_unlimited_balls = 0; control_lite77_tag.Component->Message(7, 0.0); } } diff --git a/SpaceCadetPinball/control.h b/SpaceCadetPinball/control.h index fb6d8be..cf73b0b 100644 --- a/SpaceCadetPinball/control.h +++ b/SpaceCadetPinball/control.h @@ -30,11 +30,14 @@ public: static TPinballTable* TableG; static component_info score_components[88]; static component_tag* simple_components[142]; - static int table_control_flag; + static int table_unlimited_balls; static void make_links(TPinballTable* table); static TPinballComponent* make_component_link(component_tag* tag); static void handler(int code, TPinballComponent* cmp); + static void pbctrl_bdoor_controller(int key); + static void table_add_extra_ball(float count); + static int cheat_bump_rank(); static void FlipperRebounderControl1(int code, TPinballComponent* caller); static void FlipperRebounderControl2(int code, TPinballComponent* caller); @@ -95,5 +98,8 @@ public: static void MultiplierTargetControl(int code, TPinballComponent* caller); static void BallDrainControl(int code, TPinballComponent* caller); - static void table_control_handler(int code); + static void table_control_handler(int code); + +private: + static int pbctrl_state; }; diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index b539b45..7a858ce 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -320,7 +320,7 @@ void fullscrn::fillRect(int right, int bottom) } } -int fullscrn::convert_mouse_pos(unsigned int mouseXY) +unsigned fullscrn::convert_mouse_pos(unsigned int mouseXY) { unsigned __int16 x = mouseXY & 0xffFF - render::vscreen.XPosition; unsigned __int16 y = (mouseXY >> 16) - render::vscreen.YPosition; diff --git a/SpaceCadetPinball/fullscrn.h b/SpaceCadetPinball/fullscrn.h index bb1a9df..8ed0a87 100644 --- a/SpaceCadetPinball/fullscrn.h +++ b/SpaceCadetPinball/fullscrn.h @@ -25,7 +25,7 @@ public: static void center_in(HWND parent, HWND child); static int displaychange(); static void activate(int flag); - static int convert_mouse_pos(unsigned int mouseXY); + static unsigned convert_mouse_pos(unsigned int mouseXY); static void getminmaxinfo(MINMAXINFO* maxMin); static void paint(); static bool set_menu_mode(int menuEnabled); diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 66672ba..2532479 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "maths.h" +#include "TBall.h" + void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) { @@ -203,23 +205,19 @@ void maths::line_init(line_type* line, float x0, float y0, float x1, float y1) float maths::ray_intersect_line(ray_type* ray, line_type* line) { - // Similar to https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/ - float perpDot; - float result; - float v4; bool v5; bool v6; - float v7; - perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X; + float perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X; if (perpDot < 0.0) { - result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->PreComp1) + float result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line-> + PreComp1) / perpDot); if (result >= -ray->MinDistance && result <= ray->MaxDistance) { line->CompTmp1 = result * ray->Direction.X + ray->Origin.X; - v4 = result * ray->Direction.Y + ray->Origin.Y; + float v4 = result * ray->Direction.Y + ray->Origin.Y; line->Unknown10 = v4; if (0.0 == line->Direction.X) { @@ -234,7 +232,7 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line) } else if (line->OriginX <= line->CompTmp1) { - v7 = line->CompTmp1; + float v7 = line->CompTmp1; v5 = v7 < line->OriginY; v6 = v7 == line->OriginY; if (v5 || v6) @@ -269,3 +267,35 @@ void maths::vector_add(vector_type* vec1Dst, vector_type* vec2) vec1Dst->X += vec2->X; vec1Dst->Y += vec2->Y; } + +float maths::basic_collision(TBall* ball, vector_type* ballPosition, vector_type* vec2, float a4, float a5, float a6, + float a7) +{ + ball->Position.X = ballPosition->X; + ball->Position.Y = ballPosition->Y; + float proj = -(vec2->Y * ball->Acceleration.Y + vec2->X * ball->Acceleration.X); + if (proj < 0) + { + proj = -proj; + } + else + { + float dx1 = proj * vec2->X; + float dy1 = proj * vec2->Y; + float v17 = dx1 + ball->Acceleration.X; + float v18 = dy1 + ball->Acceleration.Y; + ball->Acceleration.X = v17 * a5 + dx1 * a4; + ball->Acceleration.Y = v18 * a5 + dy1 * a4; + normalize_2d(&ball->Acceleration); + } + float projSpeed = proj * ball->Speed; + float newSpeed = ball->Speed - (1.0f - a4) * projSpeed; + ball->Speed = newSpeed; + if (projSpeed >= a6) + { + ball->Acceleration.X = newSpeed * ball->Acceleration.X + vec2->X * a7; + ball->Acceleration.Y = newSpeed * ball->Acceleration.Y + vec2->Y * a7; + ball->Speed = normalize_2d(&ball->Acceleration); + } + return projSpeed; +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index b0b9b4c..3d93bff 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -1,5 +1,7 @@ #pragma once +class TBall; + struct vector_type { float X; @@ -28,6 +30,9 @@ struct __declspec(align(4)) ray_type vector_type Direction; float MaxDistance; float MinDistance; + float TimeNow; + float TimeDelta; + float Unknown2; }; struct __declspec(align(4)) line_type @@ -56,4 +61,5 @@ public: static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec); static float magnitude(vector_type* vec); static void vector_add(vector_type* vec1Dst, vector_type* vec2); + static float basic_collision(TBall* ball, struct vector_type* ballPosition, struct vector_type* vec2, float a4, float a5, float a6, float a7); }; diff --git a/SpaceCadetPinball/nudge.cpp b/SpaceCadetPinball/nudge.cpp index 6d9e3b1..0438522 100644 --- a/SpaceCadetPinball/nudge.cpp +++ b/SpaceCadetPinball/nudge.cpp @@ -74,7 +74,7 @@ void nudge::_nudge(float xDiff, float yDiff) for (auto index = 0; index < ballList->Count(); index++) { auto ball = static_cast(ballList->Get(index)); - if (ball->UnknownBaseFlag2 && !ball->Unknown16) + if (ball->UnknownBaseFlag2 && !ball->CollisionComp) { ball->Acceleration.X = ball->Acceleration.X * ball->Speed; ball->Acceleration.Y = ball->Acceleration.Y * ball->Speed; diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 1fbec02..ccb1798 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -37,9 +37,9 @@ winhelp_entry options::keymap_help[18] short options::vk_list[28] { - 0x8041, + -32703, 0x5A, - 0x8030, + -32720, 0x39, 0x402E, 0x402F, diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index d6a33cb..e78c12f 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "pb.h" + +#include "control.h" #include "high_score.h" #include "memory.h" #include "pinball.h" @@ -17,6 +19,7 @@ #include "TDemo.h" #include "TLightGroup.h" #include "TPlunger.h" +#include "TTableLayer.h" TPinballTable* pb::MainTable = nullptr; datFileStruct* pb::record_table = nullptr; @@ -218,7 +221,7 @@ int pb::frame(int time) if (!mode_countdown(time)) { time_next = time_now + timeMul; - //pb::timed_frame(time_now, timeMul, 1); + timed_frame(time_now, timeMul, true); time_now = time_next; time_ticks += time; if (nudge::nudged_left || nudge::nudged_right || nudge::nudged_up) @@ -248,6 +251,62 @@ int pb::frame(int time) return 1; } +void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) +{ + vector_type vec1{}, vec2{}; + + for (int i = 0; i < MainTable->BallList->Count(); i++) + { + auto ball = static_cast(MainTable->BallList->Get(i)); + if (ball->UnknownBaseFlag2 != 0) + { + auto collComp = ball->CollisionComp; + if (collComp) + { + ball->TimeDelta = timeDelta; + collComp->FieldEffect(ball, &vec1); + } + else + { + if (MainTable->UnknownBaseFlag2) + { + vec2.X = 0.0; + vec2.Y = 0.0; + vec2.Z = 0.0; + TTableLayer::edge_manager->FieldEffects(ball, &vec2); + vec2.X = vec2.X * timeDelta; + vec2.Y = vec2.Y * timeDelta; + ball->Acceleration.X = ball->Speed * ball->Acceleration.X; + ball->Acceleration.Y = ball->Speed * ball->Acceleration.Y; + maths::vector_add(&ball->Acceleration, &vec2); + ball->Speed = maths::normalize_2d(&ball->Acceleration); + ball->InvAcceleration.X = ball->Acceleration.X == 0.0 ? 1000000000.0f : 1.0f / ball->Acceleration.X; + ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0 ? 1000000000.0f : 1.0f / ball->Acceleration.Y; + } + + auto timeDelta2 = timeDelta; + auto timeNow2 = timeNow; + for (auto index = 10; timeDelta2 > 0.000001 && index; --index) + { + auto time = collide(timeNow2, timeDelta2, ball); + timeDelta2 -= time; + timeNow2 += time; + } + } + } + } + + if (drawBalls) + { + for (int i = 0; i < MainTable->BallList->Count(); i++) + { + auto ball = static_cast(MainTable->BallList->Get(i)); + if (ball->UnknownBaseFlag2) + ball->Repaint(); + } + } +} + void pb::window_size(int* width, int* height) { *width = 600; @@ -337,7 +396,7 @@ void pb::keydown(int key) mode_countdown(-1); return; } - ctrl_bdoor_controller(key); + control::pbctrl_bdoor_controller(key); if (key == options::Options.LeftFlipperKey) { MainTable->Message(1000, time_now); @@ -417,7 +476,7 @@ void pb::keydown(int key) MessageBoxA(winmain::hwnd_frame, buffer, "Mem:", 0x2000u); break; case 'R': - cheat_bump_rank(); + control::cheat_bump_rank(); break; case VK_F11: gdrv::get_focus(); @@ -429,10 +488,6 @@ void pb::keydown(int key) } } -void pb::ctrl_bdoor_controller(int key) -{ -} - int pb::mode_countdown(int time) { if (!game_mode || game_mode <= 0) @@ -456,19 +511,57 @@ int pb::mode_countdown(int time) return 0; } -int pb::cheat_bump_rank() -{ - return 0; -} - void pb::launch_ball() { MainTable->Plunger->Message(1017, 0.0f); } -int pb::end_game() +void pb::end_game() { - return 0; + int scores[4]; + int scoreIndex[4]; + char String1[200]; + + mode_change(2); + int playerCount = MainTable->PlayerCount; + + score_struct_super* scorePtr = MainTable->PlayerScores; + for (auto index = 0; index < playerCount; ++index) + { + scores[index] = scorePtr->ScoreStruct->Score; + scoreIndex[index] = index; + ++scorePtr; + } + + for (auto i = 0; i < playerCount; ++i) + { + for (auto j = i; j < playerCount; ++j) + { + if (scores[j] > scores[i]) + { + int score = scores[j]; + scores[j] = scores[i]; + scores[i] = score; + + int index = scoreIndex[j]; + scoreIndex[j] = scoreIndex[i]; + scoreIndex[i] = index; + } + } + } + + if (!demo_mode && !MainTable->CheatsUsed) + { + for (auto i = 0; i < playerCount; ++i) + { + int position = high_score::get_score_position(highscore_table, scores[i]); + if (position >= 0) + { + lstrcpyA(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0)); + high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1); + } + } + } } void pb::high_scores() @@ -500,3 +593,51 @@ bool pb::chk_highscore() } return true; } + +float pb::collide(float timeNow, float timeDelta, TBall* ball) +{ + ray_type ray{}; + vector_type positionMod{}; + + if (ball->UnknownBaseFlag2 && !ball->CollisionComp) + { + if (ball_speed_limit < ball->Speed) + ball->Speed = ball_speed_limit; + + auto maxDistance = timeDelta * ball->Speed; + ball->TimeDelta = timeDelta; + ball->RayMaxDistance = maxDistance; + ball->TimeNow = timeNow; + + ray.Origin.X = ball->Position.X; + ray.Origin.Y = ball->Position.Y; + ray.Origin.Z = ball->Position.Z; + ray.Direction.X = ball->Acceleration.X; + ray.Direction.Y = ball->Acceleration.Y; + ray.Direction.Z = ball->Acceleration.Z; + ray.MaxDistance = maxDistance; + ray.Unknown2 = ball->Unknown17F; + ray.TimeNow = timeNow; + ray.TimeDelta = timeDelta; + ray.MinDistance = 0.0020000001f; + + TEdgeSegment* edge = nullptr; + auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge); + if (distance >= 1000000000.0) + { + maxDistance = timeDelta * ball->Speed; + ball->RayMaxDistance = maxDistance; + positionMod.X = maxDistance * ball->Acceleration.X; + positionMod.Y = maxDistance * ball->Acceleration.Y; + positionMod.Z = 0.0; + maths::vector_add(&ball->Position, &positionMod); + } + else + { + edge->EdgeCollision(ball, distance); + if (ball->Speed > 0.000000001) + return fabs(distance / ball->Speed); + } + } + return timeDelta; +} diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index 7eb730e..beae935 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -3,6 +3,8 @@ #include "partman.h" #include "TPinballTable.h" +class TBall; + class pb { public: @@ -22,19 +24,19 @@ public: static void replay_level(int demoMode); static void ballset(int x, int y); static int frame(int time); + static void timed_frame(float timeNow, float timeDelta, bool drawBalls); static void window_size(int* width, int* height); static void pause_continue(); static void loose_focus(); static void keyup(int key); static void keydown(int key); - static void ctrl_bdoor_controller(int key); static int mode_countdown(int time); - static int cheat_bump_rank(); static void launch_ball(); - static int end_game(); + static void end_game(); static void high_scores(); static void tilt_no_more(); static bool chk_highscore(); + static float collide(float timeNow, float timeDelta, TBall* ball); private : static int demo_mode, mode_countdown_; static float time_now, time_next; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index eb4c27c..d9bcc59 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -312,7 +312,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP SetForegroundWindow(hWnd); return 0; } - + if (Msg <= WM_ACTIVATEAPP) { switch (Msg) @@ -410,250 +410,247 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP return 0; } - if (Msg <= WM_MENUSELECT) + switch (Msg) { - switch (Msg) + case WM_MENUSELECT: + if (lParam) + return DefWindowProcA(hWnd, Msg, wParam, lParam); + if (fullscrn::screen_mode) + fullscrn::set_menu_mode(0); + return 0; + case WM_SYSKEYDOWN: + no_time_loss = 1; + if (fullscrn::screen_mode) + fullscrn::set_menu_mode(1); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_GETMINMAXINFO: + fullscrn::getminmaxinfo((MINMAXINFO*)lParam); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_DISPLAYCHANGE: + if (fullscrn::displaychange()) { - case WM_MENUSELECT: - if (lParam) - return DefWindowProcA(hWnd, Msg, wParam, lParam); - if (fullscrn::screen_mode) - fullscrn::set_menu_mode(0); - return 0; - case WM_SYSKEYDOWN: - no_time_loss = 1; - if (fullscrn::screen_mode) - fullscrn::set_menu_mode(1); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_GETMINMAXINFO: - fullscrn::getminmaxinfo((MINMAXINFO*)lParam); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_DISPLAYCHANGE: - if (fullscrn::displaychange()) - { - options::Options.FullScreen = 0; - options::menu_check(Menu1_Full_Screen, 0); - } - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_KEYUP: - pb::keyup(wParam); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_KEYDOWN: - if (!(lParam & 0x40000000)) - pb::keydown(wParam); - switch (wParam) - { - case VK_ESCAPE: - if (options::Options.FullScreen) - options::toggle(0x193u); - SendMessageA(hwnd_frame, 0x112u, 0xF020u, 0); - break; - case VK_F1: - help_introduction(hinst, hWnd); - break; - case VK_F2: - new_game(); - break; - case VK_F3: - pause(); - break; - case VK_F4: + options::Options.FullScreen = 0; + options::menu_check(Menu1_Full_Screen, 0); + } + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_KEYUP: + pb::keyup(wParam); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_KEYDOWN: + if (!(lParam & 0x40000000)) + pb::keydown(wParam); + switch (wParam) + { + case VK_ESCAPE: + if (options::Options.FullScreen) options::toggle(0x193u); - break; - case VK_F8: - if (!single_step) - pause(); - options::keyboard(); - break; - } - if (!pb::cheat_mode) - return DefWindowProcA(hWnd, Msg, wParam, lParam); - switch (wParam) - { - case 'H': - DispGRhistory = 1; - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case 'Y': - SetWindowTextA(hWnd, "Pinball"); - DispFrameRate = DispFrameRate == 0; - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case VK_F1: - pb::frame(10); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case VK_F15: - single_step = single_step == 0; - if (single_step == 0) - no_time_loss = 1; - return DefWindowProcA(hWnd, Msg, wParam, lParam); - default: - return DefWindowProcA(hWnd, Msg, wParam, lParam); - } - case WM_SYSCOMMAND: - switch (wParam & 0xFFF0) - { - case SC_MOVE: - if (fullscrn::screen_mode) - return 0; - break; - case SC_MINIMIZE: - if (!single_step) - pause(); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case SC_SCREENSAVE: - fullscrn::activate(0); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - default: break; - } - end_pause(); - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_INITMENU: - no_time_loss = 1; - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_COMMAND: - no_time_loss = 1; - switch (wParam) - { - case Menu1_Launch_Ball: - end_pause(); - pb::launch_ball(); - break; - case Menu1_Pause_Resume_Game: + SendMessageA(hwnd_frame, 0x112u, 0xF020u, 0); + break; + case VK_F1: + help_introduction(hinst, hWnd); + break; + case VK_F2: + new_game(); + break; + case VK_F3: + pause(); + break; + case VK_F4: + options::toggle(0x193u); + break; + case VK_F8: + if (!single_step) pause(); - break; - case Menu1_Demo: - end_pause(); - pb::toggle_demo(); - break; - case Menu1_Select_Table: - { - if (!single_step) - pause(); - auto tmpBuf = memory::allocate(0x1F4u); - if (tmpBuf) - { - char cmdLine[0x1F4u]; - options::get_string(nullptr, "Shell Exe", tmpBuf, pinball::WindowName, 500); - sprintf_s( - cmdLine, - "%s %s%lX %s%lX", - tmpBuf, - "select=", - (int)hwnd_frame, - "confirm=", - (int)hwnd_frame - * (int)hwnd_frame - * (int)hwnd_frame - * (int)hwnd_frame - * (int)hwnd_frame - * (int)hwnd_frame - * (int)hwnd_frame); - if (static_cast(WinExec(cmdLine, 5u)) < 32) - { - auto caption = pinball::get_rc_string(170, 0); - auto text = pinball::get_rc_string(171, 0); - MessageBoxA(hwnd_frame, text, caption, 0x2010u); - } - memory::free(tmpBuf); - } - break; - } - case Menu1_1Player: - case Menu1_2Players: - case Menu1_3Players: - case Menu1_4Players: - options::toggle(wParam); - new_game(); - break; - case Menu1_Help_Topics: - if (!single_step) - pause(); - help_introduction(hinst, hWnd); - break; - case 106: // End game button? - pb::end_game(); - break; - case Menu1_Full_Screen: - case Menu1_Sounds: - case Menu1_Music: - if (!single_step) - pause(); - options::toggle(wParam); - break; - case Menu1_Player_Controls: - case 204: // Second controls button? - if (!single_step) - pause(); - options::keyboard(); - break; - case Menu1_Exit: - PostMessageA(hWnd, WM_QUIT, 0, 0); - break; - case Menu1_New_Game: - new_game(); - break; - case Menu1_About_Pinball: - if (!single_step) - pause(); - a_dialog(hinst, hWnd); - break; - case Menu1_High_Scores: - if (!single_step) - pause(); - pb::high_scores(); - break; - case 1: // Unknown button - midi::restart_midi_seq(lParam); - break; - default: - break; - } - return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_LBUTTONDOWN: - if (pb::game_mode) - { - if (pb::cheat_mode) - { - mouse_down = 1; - mouse_hsave = SetCursor(nullptr); - auto lParam2 = fullscrn::convert_mouse_pos(lParam); - last_mouse_x = static_cast(lParam2); - last_mouse_y = static_cast(lParam2) >> 16; - SetCapture(hWnd); - } - return DefWindowProcA(hWnd, Msg, wParam, lParam); - } + options::keyboard(); break; - case WM_LBUTTONUP: - if (mouse_down) - { - mouse_down = 0; - SetCursor(mouse_hsave); - ReleaseCapture(); - } + } + if (!pb::cheat_mode) return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - if (pb::game_mode) - return DefWindowProcA(hWnd, Msg, wParam, lParam); - break; - case WM_POWERBROADCAST: - if (wParam == 4 && options::Options.FullScreen) - { - options::Options.FullScreen = 0; - options::menu_check(Menu1_Full_Screen, 0); - fullscrn::set_screen_mode(options::Options.FullScreen); - } + switch (wParam) + { + case 'H': + DispGRhistory = 1; return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_PALETTECHANGED: - InvalidateRect(hWnd, nullptr, 0); + case 'Y': + SetWindowTextA(hWnd, "Pinball"); + DispFrameRate = DispFrameRate == 0; return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_POINTERDEVICEINRANGE | LB_ADDSTRING: - if (wParam == 1) - midi::restart_midi_seq(lParam); + case VK_F1: + pb::frame(10); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case VK_F15: + single_step = single_step == 0; + if (single_step == 0) + no_time_loss = 1; return DefWindowProcA(hWnd, Msg, wParam, lParam); default: return DefWindowProcA(hWnd, Msg, wParam, lParam); } + case WM_SYSCOMMAND: + switch (wParam & 0xFFF0) + { + case SC_MOVE: + if (fullscrn::screen_mode) + return 0; + break; + case SC_MINIMIZE: + if (!single_step) + pause(); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case SC_SCREENSAVE: + fullscrn::activate(0); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + default: break; + } + end_pause(); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_INITMENU: + no_time_loss = 1; + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_COMMAND: + no_time_loss = 1; + switch (wParam) + { + case Menu1_Launch_Ball: + end_pause(); + pb::launch_ball(); + break; + case Menu1_Pause_Resume_Game: + pause(); + break; + case Menu1_Demo: + end_pause(); + pb::toggle_demo(); + break; + case Menu1_Select_Table: + { + if (!single_step) + pause(); + auto tmpBuf = memory::allocate(0x1F4u); + if (tmpBuf) + { + char cmdLine[0x1F4u]; + options::get_string(nullptr, "Shell Exe", tmpBuf, pinball::WindowName, 500); + sprintf_s( + cmdLine, + "%s %s%lX %s%lX", + tmpBuf, + "select=", + (int)hwnd_frame, + "confirm=", + (int)hwnd_frame + * (int)hwnd_frame + * (int)hwnd_frame + * (int)hwnd_frame + * (int)hwnd_frame + * (int)hwnd_frame + * (int)hwnd_frame); + if (static_cast(WinExec(cmdLine, 5u)) < 32) + { + auto caption = pinball::get_rc_string(170, 0); + auto text = pinball::get_rc_string(171, 0); + MessageBoxA(hwnd_frame, text, caption, 0x2010u); + } + memory::free(tmpBuf); + } + break; + } + case Menu1_1Player: + case Menu1_2Players: + case Menu1_3Players: + case Menu1_4Players: + options::toggle(wParam); + new_game(); + break; + case Menu1_Help_Topics: + if (!single_step) + pause(); + help_introduction(hinst, hWnd); + break; + case 106: // End game button? + pb::end_game(); + break; + case Menu1_Full_Screen: + case Menu1_Sounds: + case Menu1_Music: + if (!single_step) + pause(); + options::toggle(wParam); + break; + case Menu1_Player_Controls: + case 204: // Second controls button? + if (!single_step) + pause(); + options::keyboard(); + break; + case Menu1_Exit: + PostMessageA(hWnd, WM_QUIT, 0, 0); + break; + case Menu1_New_Game: + new_game(); + break; + case Menu1_About_Pinball: + if (!single_step) + pause(); + a_dialog(hinst, hWnd); + break; + case Menu1_High_Scores: + if (!single_step) + pause(); + pb::high_scores(); + break; + case 1: // Unknown button + midi::restart_midi_seq(lParam); + break; + default: + break; + } + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_LBUTTONDOWN: + if (pb::game_mode) + { + if (pb::cheat_mode) + { + mouse_down = 1; + mouse_hsave = SetCursor(nullptr); + auto mouseXY = fullscrn::convert_mouse_pos(lParam); + last_mouse_x = mouseXY & 0xffFFu; + last_mouse_y = mouseXY >> 16; + SetCapture(hWnd); + } + return DefWindowProcA(hWnd, Msg, wParam, lParam); + } + break; + case WM_LBUTTONUP: + if (mouse_down) + { + mouse_down = 0; + SetCursor(mouse_hsave); + ReleaseCapture(); + } + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + if (pb::game_mode) + return DefWindowProcA(hWnd, Msg, wParam, lParam); + break; + case WM_POWERBROADCAST: + if (wParam == 4 && options::Options.FullScreen) + { + options::Options.FullScreen = 0; + options::menu_check(Menu1_Full_Screen, 0); + fullscrn::set_screen_mode(options::Options.FullScreen); + } + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_PALETTECHANGED: + InvalidateRect(hWnd, nullptr, 0); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + case WM_POINTERDEVICEINRANGE | LB_ADDSTRING: + if (wParam == 1) + midi::restart_midi_seq(lParam); + return DefWindowProcA(hWnd, Msg, wParam, lParam); + default: + return DefWindowProcA(hWnd, Msg, wParam, lParam); } pb::mode_countdown(-1);