SpaceCadetPinball/SpaceCadetPinball/control.cpp

4604 lines
147 KiB
C++
Raw Normal View History

2020-12-19 15:49:31 +01:00
#include "pch.h"
#include "control.h"
2020-12-25 14:46:06 +01:00
#include "midi.h"
#include "pb.h"
#include "TBall.h"
2021-01-20 15:28:48 +01:00
#include "TBlocker.h"
#include "TBumper.h"
2021-01-22 10:53:16 +01:00
#include "TComponentGroup.h"
#include "TFlagSpinner.h"
2021-01-07 17:00:38 +01:00
#include "TLight.h"
2021-01-22 10:53:16 +01:00
#include "TLightBargraph.h"
#include "TLightGroup.h"
2021-01-22 10:53:16 +01:00
#include "TLightRollover.h"
2020-12-19 15:49:31 +01:00
#include "TPinballTable.h"
2021-01-22 10:53:16 +01:00
#include "TPopupTarget.h"
2021-01-20 15:28:48 +01:00
#include "TSink.h"
2021-01-22 10:53:16 +01:00
#include "TSoloTarget.h"
#include "TSound.h"
2021-01-22 10:53:16 +01:00
#include "TTripwire.h"
#include "TDrain.h"
#include "TFlipper.h"
#include "TGate.h"
#include "THole.h"
#include "TKickback.h"
#include "TKickout.h"
#include "TOneway.h"
#include "TRamp.h"
#include "TPlunger.h"
#include "TWall.h"
#include "TTextBox.h"
#include "translations.h"
2020-12-19 15:49:31 +01:00
int control_bump_scores1[] = {500, 1000, 1500, 2000};
int control_roll_scores1[] = {2000};
int control_bump_scores2[] = {1500, 2500, 3500, 4500};
int control_roll_scores2[] = {500};
int control_rebo_score1[] = {500};
int control_oneway4_score1[6] = {15000, 30000, 75000, 30000, 15000, 7500};
int control_ramp_score1[1] = {5000};
int control_roll_score1[1] = {20000};
int control_roll_score2[2] = {5000, 25000};
int control_roll_score3[1] = {10000};
int control_roll_score4[1] = {500};
int control_flag_score1[2] = {500, 2500};
int control_kickout_score1[5] = {10000, 0, 20000, 50000, 150000};
int control_sink_score1[3] = {2500, 5000, 7500};
int control_target_score1[2] = {500, 5000};
int control_target_score2[3] = {1500, 10000, 50000};
int control_target_score3[2] = {500, 1500};
int control_target_score4[1] = {750};
int control_target_score5[1] = {1000};
int control_target_score6[1] = {750};
int control_target_score7[1] = {750};
int control_roll_score5[1] = {10000};
int control_kickout_score2[1] = {20000};
int control_kickout_score3[1] = {50000};
component_tag<TComponentGroup> control_attack_bump_tag = {"attack_bumpers"};
component_tag<TComponentGroup> control_launch_bump_tag = {"launch_bumpers"};
component_tag<TBlocker> control_block1_tag = {"v_bloc1"};
component_tag<TBumper> control_bump1_tag = {"a_bump1"};
component_tag<TBumper> control_bump2_tag = {"a_bump2"};
component_tag<TBumper> control_bump3_tag = {"a_bump3"};
component_tag<TBumper> control_bump4_tag = {"a_bump4"};
component_tag<TBumper> control_bump5_tag = {"a_bump5"};
component_tag<TBumper> control_bump6_tag = {"a_bump6"};
component_tag<TBumper> control_bump7_tag = {"a_bump7"};
component_tag<TDrain> control_drain_tag = {"drain"};
component_tag<TFlagSpinner> control_flag1_tag = {"a_flag1"};
component_tag<TFlagSpinner> control_flag2_tag = {"a_flag2"};
component_tag<TFlipper> control_flip1_tag = {"a_flip1"};
component_tag<TFlipper> control_flip2_tag = {"a_flip2"};
component_tag<TLightBargraph> control_fuel_bargraph_tag = {"fuel_bargraph"};
component_tag<TGate> control_gate1_tag = {"v_gate1"};
component_tag<TGate> control_gate2_tag = {"v_gate2"};
component_tag<TTextBox> control_info_text_box_tag = {"info_text_box"};
component_tag<TKickback> control_kicker1_tag = {"a_kick1"};
component_tag<TKickback> control_kicker2_tag = {"a_kick2"};
component_tag<TKickout> control_kickout1_tag = {"a_kout1"};
component_tag<TKickout> control_kickout2_tag = {"a_kout2"};
component_tag<TKickout> control_kickout3_tag = {"a_kout3"};
component_tag<TLight> control_lite1_tag = {"lite1"};
component_tag<TLight> control_lite2_tag = {"lite2"};
component_tag<TLight> control_lite3_tag = {"lite3"};
component_tag<TLight> control_lite4_tag = {"lite4"};
component_tag<TLight> control_lite5_tag = {"lite5"};
component_tag<TLight> control_lite6_tag = {"lite6"};
component_tag<TLight> control_lite7_tag = {"lite7"};
component_tag<TLight> control_lite8_tag = {"lite8"};
component_tag<TLight> control_lite9_tag = {"lite9"};
component_tag<TLight> control_lite10_tag = {"lite10"};
component_tag<TLight> control_lite11_tag = {"lite11"};
component_tag<TLight> control_lite12_tag = {"lite12"};
component_tag<TLight> control_lite13_tag = {"lite13"};
component_tag<TLight> control_lite16_tag = {"lite16"};
component_tag<TLight> control_lite17_tag = {"lite17"};
component_tag<TLight> control_lite18_tag = {"lite18"};
component_tag<TLight> control_lite19_tag = {"lite19"};
component_tag<TLight> control_lite20_tag = {"lite20"};
component_tag<TLight> control_lite21_tag = {"lite21"};
component_tag<TLight> control_lite22_tag = {"lite22"};
component_tag<TLight> control_lite23_tag = {"lite23"};
component_tag<TLight> control_lite24_tag = {"lite24"};
component_tag<TLight> control_lite25_tag = {"lite25"};
component_tag<TLight> control_lite26_tag = {"lite26"};
component_tag<TLight> control_lite27_tag = {"lite27"};
component_tag<TLight> control_lite28_tag = {"lite28"};
component_tag<TLight> control_lite29_tag = {"lite29"};
component_tag<TLight> control_lite30_tag = {"lite30"};
component_tag<TLight> control_lite38_tag = {"lite38"};
component_tag<TLight> control_lite39_tag = {"lite39"};
component_tag<TLight> control_lite40_tag = {"lite40"};
component_tag<TLight> control_lite54_tag = {"lite54"};
component_tag<TLight> control_lite55_tag = {"lite55"};
component_tag<TLight> control_lite56_tag = {"lite56"};
component_tag<TLight> control_lite58_tag = {"lite58"};
component_tag<TLight> control_lite59_tag = {"lite59"};
component_tag<TLight> control_lite60_tag = {"lite60"};
component_tag<TLight> control_lite61_tag = {"lite61"};
component_tag<TLight> control_lite62_tag = {"lite62"};
component_tag<TLight> control_lite67_tag = {"lite67"};
component_tag<TLight> control_lite68_tag = {"lite68"};
component_tag<TLight> control_lite69_tag = {"lite69"};
component_tag<TLight> control_lite70_tag = {"lite70"};
component_tag<TLight> control_lite71_tag = {"lite71"};
component_tag<TLight> control_lite72_tag = {"lite72"};
component_tag<TLight> control_lite77_tag = {"lite77"};
component_tag<TLight> control_lite84_tag = {"lite84"};
component_tag<TLight> control_lite85_tag = {"lite85"};
component_tag<TLight> control_lite101_tag = {"lite101"};
component_tag<TLight> control_lite102_tag = {"lite102"};
component_tag<TLight> control_lite103_tag = {"lite103"};
component_tag<TLight> control_lite104_tag = {"lite104"};
component_tag<TLight> control_lite105_tag = {"lite105"};
component_tag<TLight> control_lite106_tag = {"lite106"};
component_tag<TLight> control_lite107_tag = {"lite107"};
component_tag<TLight> control_lite108_tag = {"lite108"};
component_tag<TLight> control_lite109_tag = {"lite109"};
component_tag<TLight> control_lite110_tag = {"lite110"};
component_tag<TLight> control_lite130_tag = {"lite130"};
component_tag<TLight> control_lite131_tag = {"lite131"};
component_tag<TLight> control_lite132_tag = {"lite132"};
component_tag<TLight> control_lite133_tag = {"lite133"};
component_tag<TLight> control_lite169_tag = {"lite169"};
component_tag<TLight> control_lite170_tag = {"lite170"};
component_tag<TLight> control_lite171_tag = {"lite171"};
component_tag<TLight> control_lite195_tag = {"lite195"};
component_tag<TLight> control_lite196_tag = {"lite196"};
component_tag<TLight> control_lite198_tag = {"lite198"};
component_tag<TLight> control_lite199_tag = {"lite199"};
component_tag<TLight> control_lite200_tag = {"lite200"};
component_tag<TLight> control_lite300_tag = {"lite300"};
component_tag<TLight> control_lite301_tag = {"lite301"};
component_tag<TLight> control_lite302_tag = {"lite302"};
component_tag<TLight> control_lite303_tag = {"lite303"};
component_tag<TLight> control_lite304_tag = {"lite304"};
component_tag<TLight> control_lite305_tag = {"lite305"};
component_tag<TLight> control_lite306_tag = {"lite306"};
component_tag<TLight> control_lite307_tag = {"lite307"};
component_tag<TLight> control_lite308_tag = {"lite308"};
component_tag<TLight> control_lite309_tag = {"lite309"};
component_tag<TLight> control_lite310_tag = {"lite310"};
component_tag<TLight> control_lite311_tag = {"lite311"};
component_tag<TLight> control_lite312_tag = {"lite312"};
component_tag<TLight> control_lite313_tag = {"lite313"};
component_tag<TLight> control_lite314_tag = {"lite314"};
component_tag<TLight> control_lite315_tag = {"lite315"};
component_tag<TLight> control_lite316_tag = {"lite316"};
component_tag<TLight> control_lite317_tag = {"lite317"};
component_tag<TLight> control_lite318_tag = {"lite318"};
component_tag<TLight> control_lite319_tag = {"lite319"};
component_tag<TLight> control_lite320_tag = {"lite320"};
component_tag<TLight> control_lite321_tag = {"lite321"};
component_tag<TLight> control_lite322_tag = {"lite322"};
component_tag<TLight> control_literoll179_tag = {"literoll179"};
component_tag<TLight> control_literoll180_tag = {"literoll180"};
component_tag<TLight> control_literoll181_tag = {"literoll181"};
component_tag<TLight> control_literoll182_tag = {"literoll182"};
component_tag<TLight> control_literoll183_tag = {"literoll183"};
component_tag<TLight> control_literoll184_tag = {"literoll184"};
component_tag<TLightGroup> control_middle_circle_tag = {"middle_circle"};
component_tag<TLightGroup> control_lchute_tgt_lights_tag = {"lchute_tgt_lights"};
component_tag<TLightGroup> control_l_trek_lights_tag = {"l_trek_lights"};
component_tag<TLightGroup> control_goal_lights_tag = {"goal_lights"};
component_tag<TLightGroup> control_hyper_lights_tag = {"hyperspace_lights"};
component_tag<TLightGroup> control_bmpr_inc_lights_tag = {"bmpr_inc_lights"};
component_tag<TLightGroup> control_bpr_solotgt_lights_tag = {"bpr_solotgt_lights"};
component_tag<TLightGroup> control_bsink_arrow_lights_tag = {"bsink_arrow_lights"};
component_tag<TLightGroup> control_bumber_target_lights_tag = {"bumper_target_lights"};
component_tag<TLightGroup> control_outer_circle_tag = {"outer_circle"};
component_tag<TLightGroup> control_r_trek_lights_tag = {"r_trek_lights"};
component_tag<TLightGroup> control_ramp_bmpr_inc_lights_tag = {"ramp_bmpr_inc_lights"};
component_tag<TLightGroup> control_ramp_tgt_lights_tag = {"ramp_tgt_lights"};
component_tag<TLightGroup> control_skill_shot_lights_tag = {"skill_shot_lights"};
component_tag<TLightGroup> control_top_circle_tgt_lights_tag = {"top_circle_tgt_lights"};
component_tag<TLightGroup> control_top_target_lights_tag = {"top_target_lights"};
component_tag<TLightGroup> control_worm_hole_lights_tag = {"worm_hole_lights"};
component_tag<TTextBox> control_mission_text_box_tag = {"mission_text_box"};
component_tag<TOneway> control_oneway1_tag = {"s_onewy1"};
component_tag<TOneway> control_oneway4_tag = {"s_onewy4"};
component_tag<TOneway> control_oneway10_tag = {"s_onewy10"};
component_tag<TPlunger> control_plunger_tag = {"plunger"};
component_tag<THole> control_ramp_hole_tag = {"ramp_hole"};
component_tag<TRamp> control_ramp_tag = {"ramp"};
component_tag<TWall> control_rebo1_tag = {"v_rebo1"};
component_tag<TWall> control_rebo2_tag = {"v_rebo2"};
component_tag<TWall> control_rebo3_tag = {"v_rebo3"};
component_tag<TWall> control_rebo4_tag = {"v_rebo4"};
component_tag<TRollover> control_roll1_tag = {"a_roll1"};
component_tag<TRollover> control_roll2_tag = {"a_roll2"};
component_tag<TRollover> control_roll3_tag = {"a_roll3"};
component_tag<TRollover> control_roll4_tag = {"a_roll4"};
component_tag<TRollover> control_roll5_tag = {"a_roll5"};
component_tag<TRollover> control_roll6_tag = {"a_roll6"};
component_tag<TRollover> control_roll7_tag = {"a_roll7"};
component_tag<TRollover> control_roll8_tag = {"a_roll8"};
component_tag<TLightRollover> control_roll9_tag = {"a_roll9"};
component_tag<TRollover> control_roll110_tag = {"a_roll110"};
component_tag<TRollover> control_roll111_tag = {"a_roll111"};
component_tag<TRollover> control_roll112_tag = {"a_roll112"};
component_tag<TRollover> control_roll179_tag = {"a_roll179"};
component_tag<TRollover> control_roll180_tag = {"a_roll180"};
component_tag<TRollover> control_roll181_tag = {"a_roll181"};
component_tag<TRollover> control_roll182_tag = {"a_roll182"};
component_tag<TRollover> control_roll183_tag = {"a_roll183"};
component_tag<TRollover> control_roll184_tag = {"a_roll184"};
component_tag<TSink> control_sink1_tag = {"v_sink1"};
component_tag<TSink> control_sink2_tag = {"v_sink2"};
component_tag<TSink> control_sink3_tag = {"v_sink3"};
component_tag<TSink> control_sink7_tag = {"v_sink7"};
component_tag<TSound> control_soundwave3_tag = {"soundwave3"};
component_tag<TSound> control_soundwave7_tag = {"soundwave7"};
component_tag<TSound> control_soundwave8_tag = {"soundwave8"};
component_tag<TSound> control_soundwave9_tag = {"soundwave9"};
component_tag<TSound> control_soundwave10_tag = {"soundwave10"};
component_tag<TSound> control_soundwave14_1_tag = {"soundwave14"};
component_tag<TSound> control_soundwave14_2_tag = {"soundwave14"};
component_tag<TSound> control_soundwave21_tag = {"soundwave21"};
component_tag<TSound> control_soundwave23_tag = {"soundwave23"};
component_tag<TSound> control_soundwave24_tag = {"soundwave24"};
component_tag<TSound> control_soundwave25_tag = {"soundwave25"};
component_tag<TSound> control_soundwave26_tag = {"soundwave26"};
component_tag<TSound> control_soundwave27_tag = {"soundwave27"};
component_tag<TSound> control_soundwave28_tag = {"soundwave28"};
component_tag<TSound> control_soundwave30_tag = {"soundwave30"};
component_tag<TSound> control_soundwave35_1_tag = {"soundwave35"};
component_tag<TSound> control_soundwave35_2_tag = {"soundwave35"};
component_tag<TSound> control_soundwave36_1_tag = {"soundwave36"};
component_tag<TSound> control_soundwave36_2_tag = {"soundwave36"};
component_tag<TSound> control_soundwave38_tag = {"soundwave38"};
component_tag<TSound> control_soundwave39_tag = {"soundwave39"};
component_tag<TSound> control_soundwave40_tag = {"soundwave40"};
component_tag<TSound> control_soundwave41_tag = {"soundwave41"};
component_tag<TSound> control_soundwave44_tag = {"soundwave44"};
component_tag<TSound> control_soundwave45_tag = {"soundwave45"};
component_tag<TSound> control_soundwave46_tag = {"soundwave46"};
component_tag<TSound> control_soundwave47_tag = {"soundwave47"};
component_tag<TSound> control_soundwave48_tag = {"soundwave48"};
component_tag<TSound> control_soundwave49D_tag = {"soundwave49D"};
component_tag<TSound> control_soundwave50_1_tag = {"soundwave50"};
component_tag<TSound> control_soundwave50_2_tag = {"soundwave50"};
component_tag<TSound> control_soundwave52_tag = {"soundwave52"};
component_tag<TSound> control_soundwave59_tag = {"soundwave59"};
component_tag<TPopupTarget> control_target1_tag = {"a_targ1"};
component_tag<TPopupTarget> control_target2_tag = {"a_targ2"};
component_tag<TPopupTarget> control_target3_tag = {"a_targ3"};
component_tag<TPopupTarget> control_target4_tag = {"a_targ4"};
component_tag<TPopupTarget> control_target5_tag = {"a_targ5"};
component_tag<TPopupTarget> control_target6_tag = {"a_targ6"};
component_tag<TPopupTarget> control_target7_tag = {"a_targ7"};
component_tag<TPopupTarget> control_target8_tag = {"a_targ8"};
component_tag<TPopupTarget> control_target9_tag = {"a_targ9"};
component_tag<TSoloTarget> control_target10_tag = {"a_targ10"};
component_tag<TSoloTarget> control_target11_tag = {"a_targ11"};
component_tag<TSoloTarget> control_target12_tag = {"a_targ12"};
component_tag<TSoloTarget> control_target13_tag = {"a_targ13"};
component_tag<TSoloTarget> control_target14_tag = {"a_targ14"};
component_tag<TSoloTarget> control_target15_tag = {"a_targ15"};
component_tag<TSoloTarget> control_target16_tag = {"a_targ16"};
component_tag<TSoloTarget> control_target17_tag = {"a_targ17"};
component_tag<TSoloTarget> control_target18_tag = {"a_targ18"};
component_tag<TSoloTarget> control_target19_tag = {"a_targ19"};
component_tag<TSoloTarget> control_target20_tag = {"a_targ20"};
component_tag<TSoloTarget> control_target21_tag = {"a_targ21"};
component_tag<TSoloTarget> control_target22_tag = {"a_targ22"};
component_tag<TTripwire> control_trip1_tag = {"s_trip1"};
component_tag<TTripwire> control_trip2_tag = {"s_trip2"};
component_tag<TTripwire> control_trip3_tag = {"s_trip3"};
component_tag<TTripwire> control_trip4_tag = {"s_trip4"};
component_tag<TTripwire> control_trip5_tag = {"s_trip5"};
// Component shortcuts for easier access without indirection through tags
TComponentGroup*& attack_bump = control_attack_bump_tag.Component;
TComponentGroup*& launch_bump = control_launch_bump_tag.Component;
TBlocker*& block1 = control_block1_tag.Component;
TBumper*& bump1 = control_bump1_tag.Component;
TBumper*& bump2 = control_bump2_tag.Component;
TBumper*& bump3 = control_bump3_tag.Component;
TBumper*& bump4 = control_bump4_tag.Component;
TBumper*& bump5 = control_bump5_tag.Component;
TBumper*& bump6 = control_bump6_tag.Component;
TBumper*& bump7 = control_bump7_tag.Component;
TDrain*& drain = control_drain_tag.Component;
TFlagSpinner*& flag1 = control_flag1_tag.Component;
TFlagSpinner*& flag2 = control_flag2_tag.Component;
TFlipper*& flip1 = control_flip1_tag.Component;
TFlipper*& flip2 = control_flip2_tag.Component;
TLightBargraph*& fuel_bargraph = control_fuel_bargraph_tag.Component;
TGate*& gate1 = control_gate1_tag.Component;
TGate*& gate2 = control_gate2_tag.Component;
TTextBox*& info_text_box = control_info_text_box_tag.Component;
TKickback*& kicker1 = control_kicker1_tag.Component;
TKickback*& kicker2 = control_kicker2_tag.Component;
TKickout*& kickout1 = control_kickout1_tag.Component;
TKickout*& kickout2 = control_kickout2_tag.Component;
TKickout*& kickout3 = control_kickout3_tag.Component;
TLight*& lite1 = control_lite1_tag.Component;
TLight*& lite2 = control_lite2_tag.Component;
TLight*& lite3 = control_lite3_tag.Component;
TLight*& lite4 = control_lite4_tag.Component;
TLight*& lite5 = control_lite5_tag.Component;
TLight*& lite6 = control_lite6_tag.Component;
TLight*& lite7 = control_lite7_tag.Component;
TLight*& lite8 = control_lite8_tag.Component;
TLight*& lite9 = control_lite9_tag.Component;
TLight*& lite10 = control_lite10_tag.Component;
TLight*& lite11 = control_lite11_tag.Component;
TLight*& lite12 = control_lite12_tag.Component;
TLight*& lite13 = control_lite13_tag.Component;
TLight*& lite16 = control_lite16_tag.Component;
TLight*& lite17 = control_lite17_tag.Component;
TLight*& lite18 = control_lite18_tag.Component;
TLight*& lite19 = control_lite19_tag.Component;
TLight*& lite20 = control_lite20_tag.Component;
TLight*& lite21 = control_lite21_tag.Component;
TLight*& lite22 = control_lite22_tag.Component;
TLight*& lite23 = control_lite23_tag.Component;
TLight*& lite24 = control_lite24_tag.Component;
TLight*& lite25 = control_lite25_tag.Component;
TLight*& lite26 = control_lite26_tag.Component;
TLight*& lite27 = control_lite27_tag.Component;
TLight*& lite28 = control_lite28_tag.Component;
TLight*& lite29 = control_lite29_tag.Component;
TLight*& lite30 = control_lite30_tag.Component;
TLight*& lite38 = control_lite38_tag.Component;
TLight*& lite39 = control_lite39_tag.Component;
TLight*& lite40 = control_lite40_tag.Component;
TLight*& lite54 = control_lite54_tag.Component;
TLight*& lite55 = control_lite55_tag.Component;
TLight*& lite56 = control_lite56_tag.Component;
TLight*& lite58 = control_lite58_tag.Component;
TLight*& lite59 = control_lite59_tag.Component;
TLight*& lite60 = control_lite60_tag.Component;
TLight*& lite61 = control_lite61_tag.Component;
TLight*& lite62 = control_lite62_tag.Component;
TLight*& lite67 = control_lite67_tag.Component;
TLight*& lite68 = control_lite68_tag.Component;
TLight*& lite69 = control_lite69_tag.Component;
TLight*& lite70 = control_lite70_tag.Component;
TLight*& lite71 = control_lite71_tag.Component;
TLight*& lite72 = control_lite72_tag.Component;
TLight*& lite77 = control_lite77_tag.Component;
TLight*& lite84 = control_lite84_tag.Component;
TLight*& lite85 = control_lite85_tag.Component;
TLight*& lite101 = control_lite101_tag.Component;
TLight*& lite102 = control_lite102_tag.Component;
TLight*& lite103 = control_lite103_tag.Component;
TLight*& lite104 = control_lite104_tag.Component;
TLight*& lite105 = control_lite105_tag.Component;
TLight*& lite106 = control_lite106_tag.Component;
TLight*& lite107 = control_lite107_tag.Component;
TLight*& lite108 = control_lite108_tag.Component;
TLight*& lite109 = control_lite109_tag.Component;
TLight*& lite110 = control_lite110_tag.Component;
TLight*& lite130 = control_lite130_tag.Component;
TLight*& lite131 = control_lite131_tag.Component;
TLight*& lite132 = control_lite132_tag.Component;
TLight*& lite133 = control_lite133_tag.Component;
TLight*& lite169 = control_lite169_tag.Component;
TLight*& lite170 = control_lite170_tag.Component;
TLight*& lite171 = control_lite171_tag.Component;
TLight*& lite195 = control_lite195_tag.Component;
TLight*& lite196 = control_lite196_tag.Component;
TLight*& lite198 = control_lite198_tag.Component;
TLight*& lite199 = control_lite199_tag.Component;
TLight*& lite200 = control_lite200_tag.Component;
TLight*& lite300 = control_lite300_tag.Component;
TLight*& lite301 = control_lite301_tag.Component;
TLight*& lite302 = control_lite302_tag.Component;
TLight*& lite303 = control_lite303_tag.Component;
TLight*& lite304 = control_lite304_tag.Component;
TLight*& lite305 = control_lite305_tag.Component;
TLight*& lite306 = control_lite306_tag.Component;
TLight*& lite307 = control_lite307_tag.Component;
TLight*& lite308 = control_lite308_tag.Component;
TLight*& lite309 = control_lite309_tag.Component;
TLight*& lite310 = control_lite310_tag.Component;
TLight*& lite311 = control_lite311_tag.Component;
TLight*& lite312 = control_lite312_tag.Component;
TLight*& lite313 = control_lite313_tag.Component;
TLight*& lite314 = control_lite314_tag.Component;
TLight*& lite315 = control_lite315_tag.Component;
TLight*& lite316 = control_lite316_tag.Component;
TLight*& lite317 = control_lite317_tag.Component;
TLight*& lite318 = control_lite318_tag.Component;
TLight*& lite319 = control_lite319_tag.Component;
TLight*& lite320 = control_lite320_tag.Component;
TLight*& lite321 = control_lite321_tag.Component;
TLight*& lite322 = control_lite322_tag.Component;
TLight*& literoll179 = control_literoll179_tag.Component;
TLight*& literoll180 = control_literoll180_tag.Component;
TLight*& literoll181 = control_literoll181_tag.Component;
TLight*& literoll182 = control_literoll182_tag.Component;
TLight*& literoll183 = control_literoll183_tag.Component;
TLight*& literoll184 = control_literoll184_tag.Component;
TLightGroup*& middle_circle = control_middle_circle_tag.Component;
TLightGroup*& lchute_tgt_lights = control_lchute_tgt_lights_tag.Component;
TLightGroup*& l_trek_lights = control_l_trek_lights_tag.Component;
TLightGroup*& goal_lights = control_goal_lights_tag.Component;
TLightGroup*& hyper_lights = control_hyper_lights_tag.Component;
TLightGroup*& bmpr_inc_lights = control_bmpr_inc_lights_tag.Component;
TLightGroup*& bpr_solotgt_lights = control_bpr_solotgt_lights_tag.Component;
TLightGroup*& bsink_arrow_lights = control_bsink_arrow_lights_tag.Component;
TLightGroup*& bumber_target_lights = control_bumber_target_lights_tag.Component;
TLightGroup*& outer_circle = control_outer_circle_tag.Component;
TLightGroup*& r_trek_lights = control_r_trek_lights_tag.Component;
TLightGroup*& ramp_bmpr_inc_lights = control_ramp_bmpr_inc_lights_tag.Component;
TLightGroup*& ramp_tgt_lights = control_ramp_tgt_lights_tag.Component;
TLightGroup*& skill_shot_lights = control_skill_shot_lights_tag.Component;
TLightGroup*& top_circle_tgt_lights = control_top_circle_tgt_lights_tag.Component;
TLightGroup*& top_target_lights = control_top_target_lights_tag.Component;
TLightGroup*& worm_hole_lights = control_worm_hole_lights_tag.Component;
TTextBox*& mission_text_box = control_mission_text_box_tag.Component;
TOneway*& oneway1 = control_oneway1_tag.Component;
TOneway*& oneway4 = control_oneway4_tag.Component;
TOneway*& oneway10 = control_oneway10_tag.Component;
TPlunger*& plunger = control_plunger_tag.Component;
THole*& ramp_hole = control_ramp_hole_tag.Component;
TRamp*& ramp = control_ramp_tag.Component;
TWall*& rebo1 = control_rebo1_tag.Component;
TWall*& rebo2 = control_rebo2_tag.Component;
TWall*& rebo3 = control_rebo3_tag.Component;
TWall*& rebo4 = control_rebo4_tag.Component;
TRollover*& roll1 = control_roll1_tag.Component;
TRollover*& roll2 = control_roll2_tag.Component;
TRollover*& roll3 = control_roll3_tag.Component;
TRollover*& roll4 = control_roll4_tag.Component;
TRollover*& roll5 = control_roll5_tag.Component;
TRollover*& roll6 = control_roll6_tag.Component;
TRollover*& roll7 = control_roll7_tag.Component;
TRollover*& roll8 = control_roll8_tag.Component;
TLightRollover*& roll9 = control_roll9_tag.Component;
TRollover*& roll110 = control_roll110_tag.Component;
TRollover*& roll111 = control_roll111_tag.Component;
TRollover*& roll112 = control_roll112_tag.Component;
TRollover*& roll179 = control_roll179_tag.Component;
TRollover*& roll180 = control_roll180_tag.Component;
TRollover*& roll181 = control_roll181_tag.Component;
TRollover*& roll182 = control_roll182_tag.Component;
TRollover*& roll183 = control_roll183_tag.Component;
TRollover*& roll184 = control_roll184_tag.Component;
TSink*& sink1 = control_sink1_tag.Component;
TSink*& sink2 = control_sink2_tag.Component;
TSink*& sink3 = control_sink3_tag.Component;
TSink*& sink7 = control_sink7_tag.Component;
TSound*& soundwave3 = control_soundwave3_tag.Component;
TSound*& soundwave7 = control_soundwave7_tag.Component;
TSound*& soundwave8 = control_soundwave8_tag.Component;
TSound*& soundwave9 = control_soundwave9_tag.Component;
TSound*& soundwave10 = control_soundwave10_tag.Component;
TSound*& soundwave14_1 = control_soundwave14_1_tag.Component;
TSound*& soundwave14_2 = control_soundwave14_2_tag.Component;
TSound*& soundwave21 = control_soundwave21_tag.Component;
TSound*& soundwave23 = control_soundwave23_tag.Component;
TSound*& soundwave24 = control_soundwave24_tag.Component;
TSound*& soundwave25 = control_soundwave25_tag.Component;
TSound*& soundwave26 = control_soundwave26_tag.Component;
TSound*& soundwave27 = control_soundwave27_tag.Component;
TSound*& soundwave28 = control_soundwave28_tag.Component;
TSound*& soundwave30 = control_soundwave30_tag.Component;
TSound*& soundwave35_1 = control_soundwave35_1_tag.Component;
TSound*& soundwave35_2 = control_soundwave35_2_tag.Component;
TSound*& soundwave36_1 = control_soundwave36_1_tag.Component;
TSound*& soundwave36_2 = control_soundwave36_2_tag.Component;
TSound*& soundwave38 = control_soundwave38_tag.Component;
TSound*& soundwave39 = control_soundwave39_tag.Component;
TSound*& soundwave40 = control_soundwave40_tag.Component;
TSound*& soundwave41 = control_soundwave41_tag.Component;
TSound*& soundwave44 = control_soundwave44_tag.Component;
TSound*& soundwave45 = control_soundwave45_tag.Component;
TSound*& soundwave46 = control_soundwave46_tag.Component;
TSound*& soundwave47 = control_soundwave47_tag.Component;
TSound*& soundwave48 = control_soundwave48_tag.Component;
TSound*& soundwave49D = control_soundwave49D_tag.Component;
TSound*& soundwave50_1 = control_soundwave50_1_tag.Component;
TSound*& soundwave50_2 = control_soundwave50_2_tag.Component;
TSound*& soundwave52 = control_soundwave52_tag.Component;
TSound*& soundwave59 = control_soundwave59_tag.Component;
TPopupTarget*& target1 = control_target1_tag.Component;
TPopupTarget*& target2 = control_target2_tag.Component;
TPopupTarget*& target3 = control_target3_tag.Component;
TPopupTarget*& target4 = control_target4_tag.Component;
TPopupTarget*& target5 = control_target5_tag.Component;
TPopupTarget*& target6 = control_target6_tag.Component;
TPopupTarget*& target7 = control_target7_tag.Component;
TPopupTarget*& target8 = control_target8_tag.Component;
TPopupTarget*& target9 = control_target9_tag.Component;
TSoloTarget*& target10 = control_target10_tag.Component;
TSoloTarget*& target11 = control_target11_tag.Component;
TSoloTarget*& target12 = control_target12_tag.Component;
TSoloTarget*& target13 = control_target13_tag.Component;
TSoloTarget*& target14 = control_target14_tag.Component;
TSoloTarget*& target15 = control_target15_tag.Component;
TSoloTarget*& target16 = control_target16_tag.Component;
TSoloTarget*& target17 = control_target17_tag.Component;
TSoloTarget*& target18 = control_target18_tag.Component;
TSoloTarget*& target19 = control_target19_tag.Component;
TSoloTarget*& target20 = control_target20_tag.Component;
TSoloTarget*& target21 = control_target21_tag.Component;
TSoloTarget*& target22 = control_target22_tag.Component;
TTripwire*& trip1 = control_trip1_tag.Component;
TTripwire*& trip2 = control_trip2_tag.Component;
TTripwire*& trip3 = control_trip3_tag.Component;
TTripwire*& trip4 = control_trip4_tag.Component;
TTripwire*& trip5 = control_trip5_tag.Component;
2020-12-19 15:49:31 +01:00
TPinballTable* control::TableG;
component_info control::score_components[88]
{
component_info{control_bump1_tag, {BumperControl, 4, control_bump_scores1}},
component_info{control_bump2_tag, {BumperControl, 4, control_bump_scores1}},
component_info{control_bump3_tag, {BumperControl, 4, control_bump_scores1}},
component_info{control_bump4_tag, {BumperControl, 4, control_bump_scores1}},
component_info{control_roll3_tag, {ReentryLanesRolloverControl, 1, control_roll_scores1}},
component_info{control_roll2_tag, {ReentryLanesRolloverControl, 1, control_roll_scores1}},
component_info{control_roll1_tag, {ReentryLanesRolloverControl, 1, control_roll_scores1}},
component_info{control_attack_bump_tag, {BumperGroupControl, 0, nullptr}},
component_info{control_bump5_tag, {BumperControl, 4, control_bump_scores2}},
component_info{control_bump6_tag, {BumperControl, 4, control_bump_scores2}},
component_info{control_bump7_tag, {BumperControl, 4, control_bump_scores2}},
component_info{control_roll112_tag, {LaunchLanesRolloverControl, 1, control_roll_scores2}},
component_info{control_roll111_tag, {LaunchLanesRolloverControl, 1, control_roll_scores2}},
component_info{control_roll110_tag, {LaunchLanesRolloverControl, 1, control_roll_scores2}},
component_info{control_launch_bump_tag, {BumperGroupControl, 0, nullptr}},
component_info{control_rebo1_tag, {FlipperRebounderControl1, 1, control_rebo_score1}},
component_info{control_rebo2_tag, {FlipperRebounderControl2, 1, control_rebo_score1}},
component_info{control_rebo3_tag, {RebounderControl, 1, control_rebo_score1}},
component_info{control_rebo4_tag, {RebounderControl, 1, control_rebo_score1}},
component_info{control_kicker1_tag, {LeftKickerControl, 0, nullptr}},
component_info{control_kicker2_tag, {RightKickerControl, 0, nullptr}},
component_info{control_gate1_tag, {LeftKickerGateControl, 0, nullptr}},
component_info{control_gate2_tag, {RightKickerGateControl, 0, nullptr}},
component_info{control_oneway4_tag, {DeploymentChuteToEscapeChuteOneWayControl, 6, control_oneway4_score1}},
component_info{control_oneway10_tag, {DeploymentChuteToTableOneWayControl, 0, nullptr}},
component_info{control_block1_tag, {DrainBallBlockerControl, 0, nullptr}},
component_info{control_ramp_tag, {LaunchRampControl, 1, control_ramp_score1}},
component_info{control_ramp_hole_tag, {LaunchRampHoleControl, 0, nullptr}},
component_info{control_roll4_tag, {OutLaneRolloverControl, 1, control_roll_score1}},
component_info{control_roll8_tag, {OutLaneRolloverControl, 1, control_roll_score1}},
component_info{control_lite17_tag, {ExtraBallLightControl, 0, nullptr}},
component_info{control_roll6_tag, {ReturnLaneRolloverControl, 2, control_roll_score2}},
component_info{control_roll7_tag, {ReturnLaneRolloverControl, 2, control_roll_score2}},
component_info{control_roll5_tag, {BonusLaneRolloverControl, 1, control_roll_score3}},
component_info{control_roll179_tag, {FuelRollover1Control, 1, control_roll_score4}},
component_info{control_roll180_tag, {FuelRollover2Control, 1, control_roll_score4}},
component_info{control_roll181_tag, {FuelRollover3Control, 1, control_roll_score4}},
component_info{control_roll182_tag, {FuelRollover4Control, 1, control_roll_score4}},
component_info{control_roll183_tag, {FuelRollover5Control, 1, control_roll_score4}},
component_info{control_roll184_tag, {FuelRollover6Control, 1, control_roll_score4}},
component_info{control_flag1_tag, {FlagControl, 2, control_flag_score1}},
component_info{control_kickout2_tag, {HyperspaceKickOutControl, 5, control_kickout_score1}},
component_info{control_hyper_lights_tag, {HyperspaceLightGroupControl, 0, nullptr}},
component_info{control_flag2_tag, {FlagControl, 2, control_flag_score1}},
component_info{control_sink1_tag, {WormHoleControl, 3, control_sink_score1}},
component_info{control_sink2_tag, {WormHoleControl, 3, control_sink_score1}},
component_info{control_sink3_tag, {WormHoleControl, 3, control_sink_score1}},
component_info{control_flip1_tag, {LeftFlipperControl, 0, nullptr}},
component_info{control_flip2_tag, {RightFlipperControl, 0, nullptr}},
component_info{control_plunger_tag, {PlungerControl, 0, nullptr}},
component_info{control_target1_tag, {BoosterTargetControl, 2, control_target_score1}},
component_info{control_target2_tag, {BoosterTargetControl, 2, control_target_score1}},
component_info{control_target3_tag, {BoosterTargetControl, 2, control_target_score1}},
component_info{control_lite60_tag, {JackpotLightControl, 0, nullptr}},
component_info{control_lite59_tag, {BonusLightControl, 0, nullptr}},
component_info{control_target6_tag, {MedalTargetControl, 3, control_target_score2}},
component_info{control_target5_tag, {MedalTargetControl, 3, control_target_score2}},
component_info{control_target4_tag, {MedalTargetControl, 3, control_target_score2}},
component_info{control_bumber_target_lights_tag, {MedalLightGroupControl, 0, nullptr}},
component_info{control_target9_tag, {MultiplierTargetControl, 2, control_target_score3}},
component_info{control_target8_tag, {MultiplierTargetControl, 2, control_target_score3}},
component_info{control_target7_tag, {MultiplierTargetControl, 2, control_target_score3}},
component_info{control_top_target_lights_tag, {MultiplierLightGroupControl, 0, nullptr}},
component_info{control_target10_tag, {FuelSpotTargetControl, 1, control_target_score4}},
component_info{control_target11_tag, {FuelSpotTargetControl, 1, control_target_score4}},
component_info{control_target12_tag, {FuelSpotTargetControl, 1, control_target_score4}},
component_info{control_target13_tag, {MissionSpotTargetControl, 1, control_target_score5}},
component_info{control_target14_tag, {MissionSpotTargetControl, 1, control_target_score5}},
component_info{control_target15_tag, {MissionSpotTargetControl, 1, control_target_score5}},
component_info{control_target16_tag, {LeftHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target17_tag, {LeftHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target18_tag, {LeftHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target19_tag, {RightHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target20_tag, {RightHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target21_tag, {RightHazardSpotTargetControl, 1, control_target_score6}},
component_info{control_target22_tag, {WormHoleDestinationControl, 1, control_target_score7}},
component_info{control_roll9_tag, {SpaceWarpRolloverControl, 1, control_roll_score5}},
component_info{control_kickout3_tag, {BlackHoleKickoutControl, 1, control_kickout_score2}},
component_info{control_kickout1_tag, {GravityWellKickoutControl, 1, control_kickout_score3}},
component_info{control_drain_tag, {BallDrainControl, 0, nullptr}},
component_info{control_oneway1_tag, {SkillShotGate1Control, 0, nullptr}},
component_info{control_trip1_tag, {SkillShotGate2Control, 0, nullptr}},
component_info{control_trip2_tag, {SkillShotGate3Control, 0, nullptr}},
component_info{control_trip3_tag, {SkillShotGate4Control, 0, nullptr}},
component_info{control_trip4_tag, {SkillShotGate5Control, 0, nullptr}},
component_info{control_trip5_tag, {SkillShotGate6Control, 0, nullptr}},
component_info{control_lite200_tag, {ShootAgainLightControl, 0, nullptr}},
component_info{control_sink7_tag, {EscapeChuteSinkControl, 0, nullptr}},
2020-12-19 15:49:31 +01:00
};
component_tag_base* control::simple_components[145]
2020-12-19 15:49:31 +01:00
{
&control_lite8_tag,
&control_lite9_tag,
&control_lite10_tag,
&control_bmpr_inc_lights_tag,
&control_lite171_tag,
&control_lite170_tag,
&control_lite169_tag,
&control_ramp_bmpr_inc_lights_tag,
&control_lite30_tag,
&control_lite29_tag,
&control_lite1_tag,
&control_lite54_tag,
&control_lite55_tag,
&control_lite56_tag,
&control_lite18_tag,
&control_lite27_tag,
&control_lite28_tag,
&control_lite16_tag,
&control_lite21_tag,
&control_lite22_tag,
&control_lite23_tag,
&control_lite24_tag,
&control_lite25_tag,
&control_lite26_tag,
&control_lite130_tag,
&control_lite5_tag,
&control_lite6_tag,
&control_lite7_tag,
&control_worm_hole_lights_tag,
&control_lite4_tag,
&control_lite2_tag,
&control_lite3_tag,
&control_bsink_arrow_lights_tag,
&control_l_trek_lights_tag,
&control_r_trek_lights_tag,
&control_literoll179_tag,
&control_literoll180_tag,
&control_literoll181_tag,
&control_literoll182_tag,
&control_literoll183_tag,
&control_literoll184_tag,
&control_fuel_bargraph_tag,
&control_lite20_tag,
&control_lite19_tag,
&control_lite61_tag,
&control_lite58_tag,
&control_lite11_tag,
&control_lite12_tag,
&control_lite13_tag,
&control_lite70_tag,
&control_lite71_tag,
&control_lite72_tag,
&control_top_circle_tgt_lights_tag,
&control_lite101_tag,
&control_lite102_tag,
&control_lite103_tag,
&control_ramp_tgt_lights_tag,
&control_lite104_tag,
&control_lite105_tag,
&control_lite106_tag,
&control_lite107_tag,
&control_lite108_tag,
&control_lite109_tag,
&control_lchute_tgt_lights_tag,
&control_bpr_solotgt_lights_tag,
&control_lite110_tag,
&control_lite62_tag,
&control_lite67_tag,
&control_lite68_tag,
&control_lite69_tag,
&control_lite131_tag,
&control_lite132_tag,
&control_lite133_tag,
&control_skill_shot_lights_tag,
&control_lite77_tag,
&control_lite198_tag,
&control_middle_circle_tag,
&control_outer_circle_tag,
&control_soundwave9_tag,
&control_soundwave10_tag,
&control_soundwave21_tag,
&control_soundwave23_tag,
&control_soundwave24_tag,
&control_soundwave30_tag,
&control_soundwave28_tag,
&control_soundwave50_1_tag,
&control_soundwave8_tag,
&control_soundwave40_tag,
&control_soundwave41_tag,
&control_soundwave36_1_tag,
&control_soundwave50_2_tag,
&control_soundwave35_1_tag,
&control_soundwave36_2_tag,
&control_soundwave35_2_tag,
&control_soundwave38_tag,
&control_soundwave39_tag,
&control_soundwave44_tag,
&control_soundwave45_tag,
&control_soundwave46_tag,
&control_soundwave47_tag,
&control_soundwave48_tag,
&control_soundwave52_tag,
&control_soundwave14_1_tag,
&control_soundwave59_tag,
&control_lite199_tag,
&control_lite196_tag,
&control_lite195_tag,
&control_info_text_box_tag,
&control_mission_text_box_tag,
&control_soundwave27_tag,
&control_lite84_tag,
&control_lite85_tag,
&control_soundwave14_2_tag,
&control_soundwave3_tag,
&control_soundwave26_tag,
&control_soundwave49D_tag,
&control_lite300_tag,
&control_lite301_tag,
&control_lite302_tag,
&control_lite303_tag,
&control_lite304_tag,
&control_lite305_tag,
&control_lite306_tag,
&control_lite307_tag,
&control_lite308_tag,
&control_lite309_tag,
&control_lite310_tag,
&control_lite311_tag,
&control_lite312_tag,
&control_lite313_tag,
&control_lite314_tag,
&control_lite315_tag,
&control_lite316_tag,
&control_lite317_tag,
&control_lite318_tag,
&control_lite319_tag,
&control_lite320_tag,
&control_lite321_tag,
&control_lite322_tag,
&control_goal_lights_tag,
&control_soundwave25_tag,
&control_soundwave7_tag,
&control_lite38_tag,
&control_lite39_tag,
&control_lite40_tag,
2020-12-19 15:49:31 +01:00
};
int control::waiting_deployment_flag;
bool control::table_unlimited_balls = false, control::easyMode = false;
2021-01-20 15:28:48 +01:00
int control::extraball_light_flag;
Msg control::RankRcArray[9] =
{
Msg::STRING185,
Msg::STRING186,
Msg::STRING187,
Msg::STRING188,
Msg::STRING189,
Msg::STRING190,
Msg::STRING191,
Msg::STRING192,
Msg::STRING193
};
Msg control::MissionRcArray[17] =
{
Msg::STRING161,
Msg::STRING162,
Msg::STRING163,
Msg::STRING164,
Msg::STRING165,
Msg::STRING166,
Msg::STRING167,
Msg::STRING168,
Msg::STRING169,
Msg::STRING170,
Msg::STRING171,
Msg::STRING172,
Msg::STRING173,
Msg::STRING174,
Msg::STRING175,
Msg::STRING176,
Msg::STRING177
};
2021-01-23 07:57:16 +01:00
int control::mission_select_scores[17] =
{
10000,
10000,
10000,
10000,
20000,
20000,
20000,
20000,
20000,
20000,
20000,
20000,
20000,
30000,
30000,
30000,
30000
};
std::reference_wrapper<TSink*> control::WormholeSinkArray[3] =
2021-01-23 07:57:16 +01:00
{
sink1, sink2, sink3
2021-01-23 07:57:16 +01:00
};
std::reference_wrapper<TLight*> control::WormholeLightArray1[3] =
2021-01-23 07:57:16 +01:00
{
lite5, lite6, lite7
2021-01-23 07:57:16 +01:00
};
std::reference_wrapper<TLight*> control::WormholeLightArray2[3] =
2021-01-23 07:57:16 +01:00
{
lite4, lite2, lite3
2021-01-23 07:57:16 +01:00
};
2020-12-19 15:49:31 +01:00
void control::make_links(TPinballTable* table)
{
TableG = table;
for (auto& score_component : score_components)
2020-12-19 15:49:31 +01:00
{
auto linkedComp = make_component_link(score_component.Tag);
if (linkedComp)
2020-12-19 15:49:31 +01:00
{
linkedComp->Control = &score_component.Control;
2020-12-19 15:49:31 +01:00
}
}
for (auto& simple_component : simple_components)
make_component_link(*simple_component);
2020-12-19 15:49:31 +01:00
}
void control::ClearLinks()
{
TableG = nullptr;
for (auto& component : score_components)
component.Tag.SetComponent(nullptr);
for (auto& component : simple_components)
component->SetComponent(nullptr);
}
2020-12-19 15:49:31 +01:00
TPinballComponent* control::make_component_link(component_tag_base& tag)
2020-12-19 15:49:31 +01:00
{
if (tag.GetComponent())
return tag.GetComponent();
2020-12-19 15:49:31 +01:00
for (auto component: TableG->ComponentList)
2020-12-19 15:49:31 +01:00
{
if (component->GroupName)
2020-12-19 15:49:31 +01:00
{
if (!strcmp(component->GroupName, tag.Name))
2020-12-19 15:49:31 +01:00
{
tag.SetComponent(component);
return component;
2020-12-19 15:49:31 +01:00
}
}
}
return nullptr;
}
void control::handler(MessageCode code, TPinballComponent* cmp)
2020-12-19 15:49:31 +01:00
{
component_control* control = cmp->Control;
2020-12-19 15:49:31 +01:00
if (control)
{
control->ControlFunc(code, cmp);
}
MissionControl(code, cmp);
}
void control::pbctrl_bdoor_controller(char key)
{
// Buffer large enough for longest cheat + null
static char cheatBuffer[11 + 1]{};
static const char* bufferEnd = &cheatBuffer[11];
static const char* quotes[8]
{
"Hey, is that a screen saver?",
"I guess it has been a good week",
"She may already be a glue bottle",
"If you don't come in Saturday,\n...\n",
"don't even bother coming in Sunday.",
"Tomorrow already sucks",
"I knew it worked too good to be right.",
"World's most expensive flippers"
};
static const char* credits[35]
{
"Full Tilt! was created by Cinematronics",
"for Maxis.",
"Cinematronics Team:",
"Programming\nMichael Sandige\nJohn Taylor",
"Art\nJohn Frantz Jr.\nRyan Medeiros",
"Design\nKevin Gliner",
"Sound Effects\nMatt Ridgeway",
"Donald S. Griffin",
"Design Consultant\nMark Sprenger",
"Music\nMatt Ridgeway",
"Producer\nKevin Gliner",
"Voices\nMike McGeary\nWilliam Rice",
"Grand Poobah\nDavid Stafford",
"Special Thanks\nPaula Sandige\nAlex St. John",
"Brad Silverberg\nJeff Camp",
"Danny Thorpe\nGreg Hospelhorn",
"Maxis Team:",
"Producer\nJohn Csicsery",
"Product Manager\nLarry Lee",
"Lead Tester\nMichael Gilmartin",
"QA Manager\nAlan Barton",
"Additional Testing\nJoe Longworth\nScott Shicoff",
"Owen Nelson\nJohn \"Jussi\" Ylinen",
"John Landes\nMarc Meyer",
"Cathy Castro\nKeith Meyer",
"Additional Art\nOcean Quigley",
"Rick Macaraeg\nCharlie Aquilina",
"Art Director\nSharon Barr",
"Install Program\nKevin O'Hare",
"Intro Music",
"Brian Conrad",
"John Csicsery",
"Special Thanks\nSam Poole\nJoe Scirica",
"Jeff Braun\nBob Derber\nAshley Csicsery",
"Tom Forge\nWill \"Burr\" Wright",
};
// Original allowed to enter cheats only before the first launch.
std::memmove(&cheatBuffer[0], &cheatBuffer[1], 10);
cheatBuffer[10] = key;
if (strcmp(bufferEnd - 11, "hidden test") == 0 ||
strcmp(bufferEnd - 11, "hidden\ttest") == 0)
{
pb::cheat_mode ^= true;
}
else if (strcmp(bufferEnd - 4, "gmax") == 0)
{
GravityWellKickoutControl(MessageCode::ControlEnableMultiplier, 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)
{
// Developer easter egg type 'cheat' from Full Tilt
float time = 0;
for (auto quote : quotes)
mission_text_box->Display(quote, time += 3, true);
return;
}
else if (pb::FullTiltMode && strcmp(bufferEnd - 7, "credits") == 0)
{
// Full Tilt in-game credits, shown when idle for 60sec
float time = 0;
for (auto line : credits)
mission_text_box->Display(line, time += 2, true);
pb::CreditsActive = true;
return;
}
else if (strcmp(bufferEnd - 9, "easy mode") == 0)
{
easyMode ^= true;
if (easyMode)
{
DrainBallBlockerControl(MessageCode::TBlockerEnable, block1);
gate1->Message(MessageCode::TGateDisable, 0.0);
gate2->Message(MessageCode::TGateDisable, 0.0);
}
else
DrainBallBlockerControl(MessageCode::ControlTimerExpired, block1);
}
else
{
return;
}
TableG->CheatsUsed = 1;
}
void control::table_add_extra_ball(float count)
{
++TableG->ExtraBalls;
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave28->Play(nullptr, "table_add_extra_ball");
info_text_box->Display(pb::get_rc_string(Msg::STRING110), count);
}
2021-01-20 15:28:48 +01:00
void control::table_set_bonus_hold()
{
lite58->Message(MessageCode::TLightResetAndTurnOn, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING153), 2.0);
2021-01-20 15:28:48 +01:00
}
void control::table_set_bonus()
{
TableG->BonusScoreFlag = true;
lite59->Message(MessageCode::TLightTurnOnTimed, 60.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING105), 2.0);
2021-01-20 15:28:48 +01:00
}
void control::table_set_jackpot()
{
TableG->JackpotScoreFlag = true;
lite60->Message(MessageCode::TLightTurnOnTimed, 60.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING116), 2.0);
2021-01-20 15:28:48 +01:00
}
void control::table_set_flag_lights()
{
lite20->Message(MessageCode::TLightTurnOnTimed, 60.0);
lite19->Message(MessageCode::TLightTurnOnTimed, 60.0);
lite61->Message(MessageCode::TLightTurnOnTimed, 60.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING152), 2.0);
2021-01-20 15:28:48 +01:00
}
void control::table_set_multiball(float time)
2021-01-21 15:58:05 +01:00
{
if (TableG->MultiballCount <= 1)
{
TableG->MultiballCount += 3;
sink1->Message(MessageCode::TSinkResetTimer, time);
sink2->Message(MessageCode::TSinkResetTimer, time);
sink3->Message(MessageCode::TSinkResetTimer, time);
lite38->Message(MessageCode::TLightFlasherStartTimed, -1.0f);
lite39->Message(MessageCode::TLightFlasherStartTimed, -1.0f);
lite40->Message(MessageCode::TLightFlasherStartTimed, -1.0f);
info_text_box->Display(pb::get_rc_string(Msg::STRING117), 2.0);
midi::play_track(MidiTracks::Track3, true);
}
2021-01-21 15:58:05 +01:00
}
2021-01-23 07:57:16 +01:00
void control::table_bump_ball_sink_lock()
{
if (TableG->MultiballCount <= 1)
2021-01-23 07:57:16 +01:00
{
TableG->MultiballCount--;
if (TableG->BallLockedCounter == 2)
{
soundwave41->Play(nullptr, "table_bump_ball_sink_lock_set_multiball");
table_set_multiball(2.0);
TableG->BallLockedCounter = 0;
}
else
{
TableG->BallLockedCounter = TableG->BallLockedCounter + 1;
soundwave44->Play(nullptr, "table_bump_ball_sink_lock");
info_text_box->Display(pb::get_rc_string(Msg::STRING102), 2.0);
TableG->Plunger->Message(MessageCode::PlungerRelaunchBall, 2.0f);
}
2021-01-23 07:57:16 +01:00
}
}
void control::table_set_replay(float value)
{
lite199->Message(MessageCode::TLightResetAndTurnOn, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING101), value);
2021-01-23 07:57:16 +01:00
}
void control::cheat_bump_rank()
{
char Buffer[64]{};
auto rank = middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
if (rank < 9)
{
middle_circle->Message(MessageCode::TLightGroupResetAndTurnOn, 2.0f);
auto rankText = pb::get_rc_string(RankRcArray[rank]);
snprintf(Buffer,sizeof Buffer, pb::get_rc_string(Msg::STRING184), rankText);
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave10->Play(nullptr, "cheat_bump_rank");
}
}
2023-03-05 12:16:07 +01:00
void control::UnstuckBall(TBall& ball, int dt)
{
if (!CheckBallInControlBounds(ball, *flip1) &&
!CheckBallInControlBounds(ball, *flip2) &&
!CheckBallInControlBounds(ball, *plunger))
{
2023-03-05 12:16:07 +01:00
if (ball.StuckCounter <= 20)
{
vector3 throwDir{0.0f, -1.0f, 0.0f};
ball.throw_ball(&throwDir, 90.0f, 1.0f, 0.0f);
}
else
{
ball.Disable();
TableG->MultiballCount--;
plunger->Message(MessageCode::PlungerRelaunchBall, 0);
}
}
}
bool control::CheckBallInControlBounds(const TBall& ball, const TCollisionComponent& cmp)
{
auto offset = TableG->CollisionCompOffset / 2.0f;
return ball.ActiveFlag &&
ball.Position.X >= cmp.AABB.XMin - offset &&
ball.Position.X <= cmp.AABB.XMax + offset &&
ball.Position.Y >= cmp.AABB.YMin - offset &&
ball.Position.Y <= cmp.AABB.YMax + offset;
}
int control::SpecialAddScore(int score, bool mission)
{
// FT: mission completion applies current jackpot
if (mission && pb::FullTiltMode)
score += TableG->JackpotScore;
const auto bonus = TableG->BonusScoreFlag;
const auto jackpot = TableG->JackpotScoreFlag;
const auto scoreMult = TableG->ScoreMultiplier;
TableG->BonusScoreFlag = false;
TableG->JackpotScoreFlag = false;
TableG->ScoreMultiplier = 0;
const auto addedScore = TableG->AddScore(score);
TableG->BonusScoreFlag = bonus;
TableG->JackpotScoreFlag = jackpot;
TableG->ScoreMultiplier = scoreMult;
// FT: each mission starts with jackpot set to 5e5
if (mission && pb::FullTiltMode)
TableG->JackpotScore = 500000;
return addedScore;
}
2021-01-20 15:28:48 +01:00
int control::AddRankProgress(int rank)
{
char Buffer[64];
int result = 0;
lite16->Message(MessageCode::TLightResetAndTurnOn, 0.0);
2021-01-20 15:28:48 +01:00
for (int index = rank; index; --index)
{
outer_circle->Message(MessageCode::TLightGroupResetAndTurnOn, 2.0);
2021-01-20 15:28:48 +01:00
}
int activeCount = outer_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
int totalCount = outer_circle->Message(MessageCode::TLightGroupGetLightCount, 0.0);
2021-01-20 15:28:48 +01:00
if (activeCount == totalCount)
{
result = 1;
outer_circle->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 5.0);
middle_circle->Message(MessageCode::TLightGroupReset, 0.0);
int midActiveCount = middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
2021-01-20 15:28:48 +01:00
if (midActiveCount < 9)
{
middle_circle->Message(MessageCode::TLightGroupResetAndTurnOn, 5.0);
auto rankText = pb::get_rc_string(RankRcArray[midActiveCount]);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING184), rankText);
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave10->Play(nullptr, "AddRankProgress");
2021-01-20 15:28:48 +01:00
}
}
else if (activeCount >= 3 * totalCount / 4)
{
middle_circle->Message(MessageCode::TLightGroupAnimationForward, -1.0);
2021-01-20 15:28:48 +01:00
}
return result;
}
void control::AdvanceWormHoleDestination(int flag)
{
int lite198Msg = lite198->MessageField;
2021-01-20 15:28:48 +01:00
if (lite198Msg != 16 && lite198Msg != 22 && lite198Msg != 23)
{
int lite4Msg = lite4->MessageField;
2021-01-20 15:28:48 +01:00
if (flag || lite4Msg)
{
int val1 = lite4Msg + 1;
int val2 = val1;
if (val1 == 4)
{
val1 = 1;
val2 = 1;
}
bsink_arrow_lights->Message(MessageCode::TLightSetMessageField, static_cast<float>(val2));
bsink_arrow_lights->Message(MessageCode::TLightSetOnStateBmpIndex, static_cast<float>(3 - val1));
if (!lite4->light_on())
2021-01-20 15:28:48 +01:00
{
worm_hole_lights->Message(MessageCode::TLightResetAndTurnOn, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightResetAndTurnOn, 0.0);
2021-01-20 15:28:48 +01:00
}
}
}
}
void control::FlipperRebounderControl1(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
lite84->Message(MessageCode::TLightTurnOnTimed, 0.1f);
2021-01-20 15:28:48 +01:00
auto score = caller->get_scoring(0);
TableG->AddScore(score);
}
2020-12-19 15:49:31 +01:00
}
void control::FlipperRebounderControl2(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
lite85->Message(MessageCode::TLightTurnOnTimed, 0.1f);
2021-01-20 15:28:48 +01:00
int score = caller->get_scoring(0);
TableG->AddScore(score);
}
2020-12-19 15:49:31 +01:00
}
void control::RebounderControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::BumperControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
TableG->AddScore(caller->get_scoring(static_cast<TBumper*>(caller)->BmpIndex));
}
2020-12-19 15:49:31 +01:00
}
void control::LeftKickerControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlTimerExpired && !easyMode)
gate1->Message(MessageCode::TGateEnable, 0.0);
2020-12-19 15:49:31 +01:00
}
void control::RightKickerControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlTimerExpired && !easyMode)
gate2->Message(MessageCode::TGateEnable, 0.0);
2020-12-19 15:49:31 +01:00
}
void control::LeftKickerGateControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::TGateDisable)
2021-01-21 15:58:05 +01:00
{
lite30->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 5.0);
lite196->Message(MessageCode::TLightFlasherStartTimed, 5.0);
2021-01-21 15:58:05 +01:00
}
else if (code == MessageCode::TGateEnable)
2021-01-21 15:58:05 +01:00
{
lite30->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite196->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::RightKickerGateControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::TGateDisable)
2021-01-23 07:57:16 +01:00
{
lite29->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 5.0);
lite195->Message(MessageCode::TLightFlasherStartTimed, 5.0);
2021-01-23 07:57:16 +01:00
}
else if (code == MessageCode::TGateEnable)
2021-01-23 07:57:16 +01:00
{
lite29->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite195->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-23 07:57:16 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::DeploymentChuteToEscapeChuteOneWayControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
char Buffer[64];
if (code == MessageCode::ControlCollision)
{
int count = skill_shot_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0);
if (count)
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave3->Play(nullptr, "DeploymentChuteToEscapeChuteOneWayControl");
int score = TableG->AddScore(caller->get_scoring(count - 1));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING122), score);
info_text_box->Display(Buffer, 2.0);
if (!lite56->light_on())
{
l_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
}
skill_shot_lights->Message(MessageCode::TLightGroupFlashWhenOn, 1.0);
}
}
2020-12-19 15:49:31 +01:00
}
void control::DeploymentChuteToTableOneWayControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
skill_shot_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2020-12-19 15:49:31 +01:00
}
void control::DrainBallBlockerControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-20 15:28:48 +01:00
auto block = static_cast<TBlocker*>(caller);
switch (code)
2021-01-20 15:28:48 +01:00
{
case MessageCode::TBlockerEnable:
2021-01-20 15:28:48 +01:00
{
block->MessageField = 1;
auto blockerDuration = !easyMode ? static_cast<float>(block->InitialDuration) : -1;
block->Message(MessageCode::TBlockerEnable, blockerDuration);
lite1->Message(MessageCode::TLightTurnOnTimed, blockerDuration);
break;
}
case MessageCode::ControlTimerExpired:
{
if (block->MessageField == 1)
{
block->MessageField = 2;
auto blockerDuration = static_cast<float>(block->ExtendedDuration);
block->Message(MessageCode::TBlockerRestartTimeout, blockerDuration);
lite1->Message(MessageCode::TLightFlasherStartTimed, blockerDuration);
break;
}
else
{
block->MessageField = 0;
block->Message(MessageCode::TBlockerDisable, 0.0);
break;
}
2021-01-20 15:28:48 +01:00
}
default: break;
2021-01-20 15:28:48 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::LaunchRampControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-22 10:53:16 +01:00
TSound* sound;
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
int someFlag = 0;
if (lite54->light_on())
2021-01-21 15:58:05 +01:00
{
someFlag = 1;
int addedScore = SpecialAddScore(TableG->ReflexShotScore);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING111), addedScore);
info_text_box->Display(Buffer, 2.0);
2021-01-21 15:58:05 +01:00
}
if (lite55->light_on())
2021-01-21 15:58:05 +01:00
someFlag |= 2u;
if (lite56->light_on())
2021-01-21 15:58:05 +01:00
someFlag |= 4u;
if (someFlag)
{
if (someFlag == 1)
{
sound = soundwave21;
2021-01-21 15:58:05 +01:00
}
2021-10-18 08:31:47 +02:00
else if (someFlag < 1 || someFlag > 3)
2021-01-21 15:58:05 +01:00
{
sound = soundwave24;
2021-01-21 15:58:05 +01:00
}
else
{
sound = soundwave23;
2021-01-21 15:58:05 +01:00
}
}
else
{
TableG->AddScore(caller->get_scoring(0));
sound = soundwave30;
2021-01-21 15:58:05 +01:00
}
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
sound->Play(lite198, "LaunchRampControl");
2021-01-21 15:58:05 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::LaunchRampHoleControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlBallReleased)
lite54->Message(MessageCode::TLightFlasherStartTimed, 5.0);
2020-12-19 15:49:31 +01:00
}
void control::SpaceWarpRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
lite27->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite28->Message(MessageCode::TLightResetAndTurnOn, 0.0);
2021-01-23 07:57:16 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::ReentryLanesRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (!lite56->light_on() && l_trek_lights->Message(MessageCode::TLightGroupGetMessage2, 0.0))
2021-01-21 15:58:05 +01:00
{
l_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
}
TLight* light;
if (roll3 == caller)
2021-01-21 15:58:05 +01:00
{
light = lite8;
2021-01-21 15:58:05 +01:00
}
else if (roll2 == caller)
2021-01-21 15:58:05 +01:00
{
light = lite9;
}
else
{
light = lite10;
2021-01-21 15:58:05 +01:00
}
if (!light->FlasherOnFlag)
2021-01-21 15:58:05 +01:00
{
if (light->LightOnFlag)
2021-01-21 15:58:05 +01:00
{
if (!pb::FullTiltMode)
{
light->Message(MessageCode::TLightResetAndTurnOff, 0.0);
}
2021-01-21 15:58:05 +01:00
}
else
{
light->Message(MessageCode::TLightResetAndTurnOn, 0.0);
int activeCount = bmpr_inc_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0);
if (activeCount == bmpr_inc_lights->Message(MessageCode::TLightGroupGetLightCount, 0.0))
2021-01-21 15:58:05 +01:00
{
bmpr_inc_lights->Message(MessageCode::TLightFlasherStartTimed, 5.0);
bmpr_inc_lights->Message(MessageCode::TLightTurnOff, 0.0);
if (bump1->BmpIndex < 3)
2021-01-21 15:58:05 +01:00
{
attack_bump->Message(MessageCode::TBumperIncBmpIndex, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING106), 2.0);
2021-01-21 15:58:05 +01:00
}
attack_bump->Message(MessageCode::TComponentGroupResetNotifyTimer, 60.0);
2021-01-21 15:58:05 +01:00
}
}
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::BumperGroupControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlNotifyTimerExpired)
2021-01-20 15:28:48 +01:00
{
caller->Message(MessageCode::TComponentGroupResetNotifyTimer, 60.0);
caller->Message(MessageCode::TBumperDecBmpIndex, 0.0);
2021-01-20 15:28:48 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::LaunchLanesRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
TLight* light;
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (roll112 == caller)
2021-01-21 15:58:05 +01:00
{
light = lite171;
2021-01-21 15:58:05 +01:00
}
else
{
light = lite170;
if (roll111 != caller)
light = lite169;
2021-01-21 15:58:05 +01:00
}
if (!light->FlasherOnFlag)
2021-01-21 15:58:05 +01:00
{
if (light->LightOnFlag)
2021-01-21 15:58:05 +01:00
{
if (!pb::FullTiltMode)
{
light->Message(MessageCode::TLightResetAndTurnOff, 0.0);
}
2021-01-21 15:58:05 +01:00
}
else
{
light->Message(MessageCode::TLightResetAndTurnOn, 0.0);
int msg1 = ramp_bmpr_inc_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0);
if (msg1 == ramp_bmpr_inc_lights->Message(MessageCode::TLightGroupGetLightCount, 0.0))
2021-01-21 15:58:05 +01:00
{
ramp_bmpr_inc_lights->Message(MessageCode::TLightFlasherStartTimed, 5.0);
ramp_bmpr_inc_lights->Message(MessageCode::TLightTurnOff, 0.0);
if (bump5->BmpIndex < 3)
2021-01-21 15:58:05 +01:00
{
launch_bump->Message(MessageCode::TBumperIncBmpIndex, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING107), 2.0);
2021-01-21 15:58:05 +01:00
}
launch_bump->Message(MessageCode::TComponentGroupResetNotifyTimer, 60.0);
2021-01-21 15:58:05 +01:00
}
}
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::OutLaneRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (lite17->light_on() || lite18->light_on())
2021-01-21 15:58:05 +01:00
{
table_add_extra_ball(2.0);
lite17->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite18->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
}
else
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave26->Play(caller, "OutLaneRolloverControl");
2021-01-21 15:58:05 +01:00
}
if (roll4 == caller)
2021-01-21 15:58:05 +01:00
{
if (lite30->light_on())
2021-01-21 15:58:05 +01:00
{
lite30->Message(MessageCode::TLightFlasherStart, 0.0);
lite196->Message(MessageCode::TLightFlasherStart, 0.0);
2021-01-21 15:58:05 +01:00
}
}
else if (lite29->light_on())
2021-01-21 15:58:05 +01:00
{
lite29->Message(MessageCode::TLightFlasherStart, 0.0);
lite195->Message(MessageCode::TLightFlasherStart, 0.0);
2021-01-21 15:58:05 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::ExtraBallLightControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::TLightResetAndTurnOn)
2021-01-20 15:28:48 +01:00
{
lite17->Message(MessageCode::TLightTurnOnTimed, 55.0);
lite18->Message(MessageCode::TLightTurnOnTimed, 55.0);
2021-01-20 15:28:48 +01:00
extraball_light_flag = 1;
}
else if (code == MessageCode::ControlTimerExpired)
2021-01-20 15:28:48 +01:00
{
if (extraball_light_flag)
{
lite17->Message(MessageCode::TLightFlasherStartTimed, 5.0);
lite18->Message(MessageCode::TLightFlasherStartTimed, 5.0);
2021-01-20 15:28:48 +01:00
extraball_light_flag = 0;
}
}
2020-12-19 15:49:31 +01:00
}
void control::ReturnLaneRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (roll6 == caller)
2021-01-23 07:57:16 +01:00
{
if (lite27->light_on())
2021-01-23 07:57:16 +01:00
{
lite59->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite27->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-23 07:57:16 +01:00
TableG->AddScore(caller->get_scoring(1));
}
else
TableG->AddScore(caller->get_scoring(0));
}
else if (roll7 == caller)
2021-01-23 07:57:16 +01:00
{
if (lite28->light_on())
2021-01-23 07:57:16 +01:00
{
lite59->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite28->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-23 07:57:16 +01:00
TableG->AddScore(caller->get_scoring(1));
}
else
TableG->AddScore(caller->get_scoring(0));
}
}
2020-12-19 15:49:31 +01:00
}
void control::BonusLaneRolloverControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-20 15:28:48 +01:00
char Buffer[64];
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (lite16->light_on())
2021-01-20 15:28:48 +01:00
{
int addedScore = SpecialAddScore(TableG->BonusScore);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING104), addedScore);
info_text_box->Display(Buffer, 2.0);
lite16->Message(MessageCode::TLightResetAndTurnOff, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave50_1->Play(caller, "BonusLaneRolloverControl1");
2021-01-20 15:28:48 +01:00
}
else
{
TableG->AddScore(caller->get_scoring(0));
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave25->Play(caller, "BonusLaneRolloverControl2");
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 11.0);
2021-01-20 15:28:48 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover1Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 1)
2021-01-20 15:28:48 +01:00
{
literoll179->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 1.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover2Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 3)
2021-01-20 15:28:48 +01:00
{
literoll180->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 3.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover3Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 5)
2021-01-20 15:28:48 +01:00
{
literoll181->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 5.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover4Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 7)
2021-01-20 15:28:48 +01:00
{
literoll182->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 7.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover5Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 9)
2021-01-20 15:28:48 +01:00
{
literoll183->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 9.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::FuelRollover6Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 11)
2021-01-20 15:28:48 +01:00
{
literoll184->Message(MessageCode::TLightTurnOffTimed, 0.05f);
2021-01-20 15:28:48 +01:00
}
else
{
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 11.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::HyperspaceLightGroupControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
switch (code)
{
case MessageCode::TLightGroupNull:
caller->Message(MessageCode::TLightTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::TLightGroupResetAndTurnOn:
caller->Message(MessageCode::TLightGroupResetAndTurnOn, 2.0);
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 60.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::ControlNotifyTimerExpired:
caller->Message(MessageCode::TLightGroupOffsetAnimationBackward, 0.0);
if (caller->Message(MessageCode::TLightGroupGetOnCount, 0.0))
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 60.0);
2021-01-21 15:58:05 +01:00
break;
default: break;
}
2020-12-19 15:49:31 +01:00
}
void control::WormHoleControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-23 07:57:16 +01:00
int sinkFlag2;
TSink* sink = static_cast<TSink*>(caller);
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
int sinkFlag = 0;
if (sink1 != sink)
2021-01-23 07:57:16 +01:00
{
sinkFlag = sink2 != sink;
2021-01-23 07:57:16 +01:00
++sinkFlag;
}
int lite4Msg = lite4->MessageField;
2021-01-23 07:57:16 +01:00
if (lite4Msg)
{
lite4->MessageField = 0;
worm_hole_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite110->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-23 07:57:16 +01:00
if (lite4Msg == sinkFlag + 1)
{
if (TableG->MultiballFlag)
{
if (TableG->MultiballCount == 1)
{
table_bump_ball_sink_lock();
TableG->AddScore(10000);
return;
}
else
{
table_set_replay(4.0);
TableG->AddScore(50000);
}
2021-01-23 07:57:16 +01:00
}
else
{
2021-01-23 07:57:16 +01:00
table_set_replay(4.0);
TableG->AddScore(sink->get_scoring(1));
}
info_text_box->Display(pb::get_rc_string(Msg::STRING150), 2.0);
WormholeLightArray1[sinkFlag].get()->Message(MessageCode::TLightFlasherStartTimedThenStayOff, sink->TimerTime);
WormholeLightArray2[sinkFlag].get()->Message(MessageCode::TLightSetOnStateBmpIndex, static_cast<float>(2 - sinkFlag));
WormholeLightArray2[sinkFlag].get()->Message(MessageCode::TLightFlasherStartTimedThenStayOff, sink->TimerTime);
WormholeSinkArray[sinkFlag].get()->Message(MessageCode::TSinkResetTimer, sink->TimerTime);
2021-01-23 07:57:16 +01:00
return;
}
TableG->AddScore(sink->get_scoring(2));
sinkFlag2 = lite4Msg - 1;
}
else
{
TableG->AddScore(sink->get_scoring(0));
sinkFlag2 = sinkFlag;
}
WormholeLightArray1[sinkFlag2].get()->Message(MessageCode::TLightFlasherStartTimedThenStayOff, sink->TimerTime);
WormholeLightArray2[sinkFlag2].get()->Message(MessageCode::TLightSetOnStateBmpIndex, static_cast<float>(2 - sinkFlag2));
WormholeLightArray2[sinkFlag2].get()->Message(MessageCode::TLightFlasherStartTimedThenStayOff, sink->TimerTime);
WormholeSinkArray[sinkFlag2].get()->Message(MessageCode::TSinkResetTimer, sink->TimerTime);
info_text_box->Display(pb::get_rc_string(Msg::STRING150), 2.0);
2021-01-23 07:57:16 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::LeftFlipperControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::TLightTurnOn)
2021-01-21 15:58:05 +01:00
{
bmpr_inc_lights->Message(MessageCode::TLightGroupStepBackward, 0.0);
ramp_bmpr_inc_lights->Message(MessageCode::TLightGroupStepBackward, 0.0);
2021-01-21 15:58:05 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::RightFlipperControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::TLightTurnOn)
2021-01-23 07:57:16 +01:00
{
bmpr_inc_lights->Message(MessageCode::TLightGroupStepForward, 0.0);
ramp_bmpr_inc_lights->Message(MessageCode::TLightGroupStepForward, 0.0);
2021-01-23 07:57:16 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::JackpotLightControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlTimerExpired)
TableG->JackpotScoreFlag = false;
2020-12-19 15:49:31 +01:00
}
void control::BonusLightControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlTimerExpired)
TableG->BonusScoreFlag = false;
2020-12-19 15:49:31 +01:00
}
void control::BoosterTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-22 10:53:16 +01:00
TSound* sound = nullptr;
2021-01-20 15:28:48 +01:00
if (code == MessageCode::ControlCollision && !caller->MessageField)
2021-01-20 15:28:48 +01:00
{
caller->MessageField = 1;
if (target1->MessageField
+ target2->MessageField
+ target3->MessageField != 3)
2021-01-20 15:28:48 +01:00
{
TableG->AddScore(caller->get_scoring(0));
return;
}
if (lite61->light_on())
2021-01-20 15:28:48 +01:00
{
if (lite60->light_on())
2021-01-20 15:28:48 +01:00
{
if (lite59->light_on())
2021-01-20 15:28:48 +01:00
{
if (lite58->light_on())
2021-01-20 15:28:48 +01:00
{
TableG->AddScore(caller->get_scoring(1));
}
else
{
table_set_bonus_hold();
}
sound = soundwave48;
2021-01-20 15:28:48 +01:00
}
else
{
table_set_bonus();
sound = soundwave46;
2021-01-20 15:28:48 +01:00
}
}
else
{
table_set_jackpot();
sound = soundwave45;
2021-01-20 15:28:48 +01:00
}
}
else
{
int msg = lite198->MessageField;
2021-01-20 15:28:48 +01:00
if (msg != 15 && msg != 29)
{
table_set_flag_lights();
sound = soundwave47;
2021-01-20 15:28:48 +01:00
}
}
if (sound)
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
sound->Play(caller, "BoosterTargetControl");
2021-01-20 15:28:48 +01:00
target1->MessageField = 0;
target1->Message(MessageCode::TPopupTargetEnable, 0.0);
target2->MessageField = 0;
target2->Message(MessageCode::TPopupTargetEnable, 0.0);
target3->MessageField = 0;
target3->Message(MessageCode::TPopupTargetEnable, 0.0);
2021-01-20 15:28:48 +01:00
TableG->AddScore(caller->get_scoring(1));
}
2020-12-19 15:49:31 +01:00
}
void control::MedalLightGroupControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
switch (code)
{
case MessageCode::TLightGroupNull:
caller->Message(MessageCode::TLightTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::TLightGroupResetAndTurnOn:
caller->Message(MessageCode::TLightGroupResetAndTurnOn, 2.0);
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 30.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::ControlNotifyTimerExpired:
caller->Message(MessageCode::TLightGroupOffsetAnimationBackward, 0.0);
if (caller->Message(MessageCode::TLightGroupGetOnCount, 0.0))
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 30.0);
2021-01-21 15:58:05 +01:00
break;
default: break;
}
2020-12-19 15:49:31 +01:00
}
void control::MultiplierLightGroupControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
switch (code)
{
case MessageCode::TLightGroupNull:
caller->Message(MessageCode::TLightTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::TLightGroupResetAndTurnOn:
caller->Message(MessageCode::TLightGroupResetAndTurnOn, 2.0);
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 30.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::ControlNotifyTimerExpired:
2021-01-21 15:58:05 +01:00
if (TableG->ScoreMultiplier)
TableG->ScoreMultiplier = TableG->ScoreMultiplier - 1;
caller->Message(MessageCode::TLightGroupOffsetAnimationBackward, 0.0);
if (caller->Message(MessageCode::TLightGroupGetOnCount, 0.0))
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 30.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::ControlEnableMultiplier:
2021-01-21 15:58:05 +01:00
TableG->ScoreMultiplier = 4;
caller->Message(MessageCode::TLightResetAndTurnOn, 0.0);
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, 30.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING160), 2.0);
2021-01-21 15:58:05 +01:00
break;
case MessageCode::ControlDisableMultiplier:
2021-01-21 15:58:05 +01:00
TableG->ScoreMultiplier = 0;
caller->Message(MessageCode::TLightResetAndTurnOff, 0.0);
caller->Message(MessageCode::TLightGroupRestartNotifyTimer, -1.0);
2021-01-21 15:58:05 +01:00
break;
default:
break;
}
2020-12-19 15:49:31 +01:00
}
void control::FuelSpotTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-20 15:28:48 +01:00
TPinballComponent* liteComp;
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (target10 == caller)
2021-01-20 15:28:48 +01:00
{
liteComp = lite70;
2021-01-20 15:28:48 +01:00
}
else
{
liteComp = lite71;
if (target11 != caller)
liteComp = lite72;
2021-01-20 15:28:48 +01:00
}
liteComp->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 2.0);
2021-01-20 15:28:48 +01:00
TableG->AddScore(caller->get_scoring(0));
if (top_circle_tgt_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0) == 3)
2021-01-20 15:28:48 +01:00
{
top_circle_tgt_lights->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 2.0);
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 11.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave25->Play(caller, "FuelSpotTargetControl1");
info_text_box->Display(pb::get_rc_string(Msg::STRING145), 2.0);
2021-01-20 15:28:48 +01:00
}
else
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave49D->Play(caller, "FuelSpotTargetControl2");
2021-01-20 15:28:48 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::MissionSpotTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
TPinballComponent* lite;
if (target13 == caller)
2021-01-21 15:58:05 +01:00
{
lite101->MessageField |= 1u;
lite = lite101;
2021-01-21 15:58:05 +01:00
}
else if (target14 == caller)
2021-01-21 15:58:05 +01:00
{
lite101->MessageField |= 2u;
lite = lite102;
2021-01-21 15:58:05 +01:00
}
else
{
lite101->MessageField |= 4u;
lite = lite103;
2021-01-21 15:58:05 +01:00
}
lite->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 2.0);
2021-01-21 15:58:05 +01:00
2021-01-22 10:53:16 +01:00
TSound* sound;
if (!lite198->light_on() || lite198->FlasherOnFlag)
2021-01-21 15:58:05 +01:00
{
sound = soundwave52;
2021-01-21 15:58:05 +01:00
}
else
sound = soundwave49D;
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
sound->Play(caller, "MissionSpotTargetControl");
2021-01-21 15:58:05 +01:00
TableG->AddScore(caller->get_scoring(0));
if (ramp_tgt_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0) == 3)
ramp_tgt_lights->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 2.0);
2021-01-21 15:58:05 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::LeftHazardSpotTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
TPinballComponent* lite;
if (code == MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (target16 == caller)
2021-01-21 15:58:05 +01:00
{
lite104->MessageField |= 1u;
lite = lite104;
2021-01-21 15:58:05 +01:00
}
else if (target17 == caller)
2021-01-21 15:58:05 +01:00
{
lite104->MessageField |= 2u;
lite = lite105;
2021-01-21 15:58:05 +01:00
}
else
{
lite104->MessageField |= 4u;
lite = lite106;
2021-01-21 15:58:05 +01:00
}
lite->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 2.0);
2021-01-21 15:58:05 +01:00
TableG->AddScore(caller->get_scoring(0));
if (lchute_tgt_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0) == 3)
2021-01-21 15:58:05 +01:00
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_1->Play(caller, "LeftHazardSpotTargetControl1");
gate1->Message(MessageCode::TGateDisable, 0.0);
lchute_tgt_lights->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 2.0);
2021-01-21 15:58:05 +01:00
}
else
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave49D->Play(caller, "LeftHazardSpotTargetControl2");
2021-01-21 15:58:05 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::RightHazardSpotTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-23 07:57:16 +01:00
TPinballComponent* light;
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (target19 == caller)
2021-01-23 07:57:16 +01:00
{
lite107->MessageField |= 1u;
light = lite107;
2021-01-23 07:57:16 +01:00
}
else if (target20 == caller)
2021-01-23 07:57:16 +01:00
{
lite107->MessageField |= 2u;
light = lite108;
2021-01-23 07:57:16 +01:00
}
else
{
lite107->MessageField |= 4u;
light = lite109;
2021-01-23 07:57:16 +01:00
}
light->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 2.0);
2021-01-23 07:57:16 +01:00
TableG->AddScore(caller->get_scoring(0));
if (bpr_solotgt_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0) == 3)
2021-01-23 07:57:16 +01:00
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_1->Play(caller, "RightHazardSpotTargetControl1");
gate2->Message(MessageCode::TGateDisable, 0.0);
bpr_solotgt_lights->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 2.0);
2021-01-23 07:57:16 +01:00
}
else
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave49D->Play(caller, "RightHazardSpotTargetControl2");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::WormHoleDestinationControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (!lite110->light_on())
2021-01-23 07:57:16 +01:00
{
lite110->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 3.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING194), 2.0);
2021-01-23 07:57:16 +01:00
}
TableG->AddScore(caller->get_scoring(0));
AdvanceWormHoleDestination(1);
}
2020-12-19 15:49:31 +01:00
}
void control::BlackHoleKickoutControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-20 15:28:48 +01:00
char Buffer[64];
if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
int addedScore = TableG->AddScore(caller->get_scoring(0));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING181), addedScore);
info_text_box->Display(Buffer, 2.0);
caller->Message(MessageCode::TKickoutRestartTimer, -1.0);
2021-01-20 15:28:48 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::FlagControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlSpinnerLoopReset)
2021-01-20 15:28:48 +01:00
{
AdvanceWormHoleDestination(0);
}
else if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
int score = caller->get_scoring(lite20->light_on());
2021-01-20 15:28:48 +01:00
TableG->AddScore(score);
}
2020-12-19 15:49:31 +01:00
}
void control::GravityWellKickoutControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
switch (code)
{
case MessageCode::ControlCollision:
2021-01-21 15:58:05 +01:00
{
auto addedScore = TableG->AddScore(caller->get_scoring(0));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING182), addedScore);
info_text_box->Display(Buffer, 2.0);
lite62->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-28 16:01:26 +01:00
caller->ActiveFlag = 0;
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
auto duration = soundwave7->Play(lite62, "GravityWellKickoutControl");
caller->Message(MessageCode::TKickoutRestartTimer, duration);
2021-01-21 15:58:05 +01:00
break;
}
case MessageCode::ControlEnableMultiplier:
2021-01-21 15:58:05 +01:00
{
auto score = reinterpret_cast<size_t>(caller);
2021-01-21 15:58:05 +01:00
if (score)
{
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING183), score);
2021-01-21 15:58:05 +01:00
}
else
{
snprintf(Buffer, sizeof Buffer, "%s", pb::get_rc_string(Msg::STRING146));
2021-01-21 15:58:05 +01:00
}
info_text_box->Display(Buffer, 2.0);
lite62->Message(MessageCode::TLightFlasherStart, 0.0);
kickout1->ActiveFlag = 1;
2021-01-21 15:58:05 +01:00
break;
}
case MessageCode::Reset:
kickout1->ActiveFlag = 0;
2021-01-21 15:58:05 +01:00
break;
default: break;
2021-01-21 15:58:05 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate1Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
lite200->Message(MessageCode::TLightTurnOnTimed, 5.0);
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
skill_shot_lights->Message(MessageCode::TLightGroupReset, 0.0);
skill_shot_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite67->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite54->Message(MessageCode::TLightFlasherStartTimed, 5.0);
lite25->Message(MessageCode::TLightFlasherStartTimed, 5.0);
fuel_bargraph->Message(MessageCode::TLightGroupToggleSplitIndex, 11.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite67, "SkillShotGate1Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate2Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
lite68->Message(MessageCode::TLightResetAndTurnOn, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite68, "SkillShotGate2Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate3Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
lite69->Message(MessageCode::TLightResetAndTurnOn, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite69, "SkillShotGate3Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate4Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
lite131->Message(MessageCode::TLightResetAndTurnOn, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite131, "SkillShotGate4Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate5Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
lite132->Message(MessageCode::TLightResetAndTurnOn, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite132, "SkillShotGate5Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::SkillShotGate6Control(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (lite67->light_on())
2021-01-23 07:57:16 +01:00
{
lite133->Message(MessageCode::TLightResetAndTurnOn, 0.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave14_2->Play(lite133, "SkillShotGate6Control");
2021-01-23 07:57:16 +01:00
}
}
2020-12-19 15:49:31 +01:00
}
void control::ShootAgainLightControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlTimerExpired)
2021-01-23 07:57:16 +01:00
{
if (caller->MessageField)
{
caller->MessageField = 0;
}
else
{
caller->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 5.0);
2021-01-23 07:57:16 +01:00
caller->MessageField = 1;
}
}
2020-12-19 15:49:31 +01:00
}
void control::EscapeChuteSinkControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision)
{
caller->Message(MessageCode::TSinkResetTimer, -1.0f);
}
2020-12-19 15:49:31 +01:00
}
void control::MissionControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (!lite198)
2021-01-21 15:58:05 +01:00
return;
int lite198Msg = lite198->MessageField;
2021-01-21 15:58:05 +01:00
switch (code)
{
case MessageCode::TLightGroupCountdownEnded:
if (fuel_bargraph == caller && lite198Msg > 1)
{
l_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
mission_text_box->Display(pb::get_rc_string(Msg::STRING210), 4.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
break;
case MessageCode::ControlTimerExpired:
if (fuel_bargraph == caller && lite198Msg)
2021-01-21 15:58:05 +01:00
{
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0) == 1)
2021-01-21 15:58:05 +01:00
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING217), 4.0);
2021-01-21 15:58:05 +01:00
}
break;
}
if (mission_text_box == caller)
code = MessageCode::ControlMissionStarted;
2021-01-21 15:58:05 +01:00
break;
case MessageCode::Resume:
code = MessageCode::ControlMissionStarted;
2021-01-21 15:58:05 +01:00
break;
default:
break;
}
switch (lite198Msg)
{
case 0:
WaitingDeploymentController(code, caller);
break;
case 1:
SelectMissionController(code, caller);
break;
case 2:
PracticeMissionController(code, caller);
break;
case 3:
LaunchTrainingController(code, caller);
break;
case 4:
ReentryTrainingController(code, caller);
break;
case 5:
ScienceMissionController(code, caller);
break;
case 6:
StrayCometController(code, caller);
break;
case 7:
BlackHoleThreatController(code, caller);
break;
case 8:
SpaceRadiationController(code, caller);
break;
case 9:
BugHuntController(code, caller);
break;
case 10:
AlienMenaceController(code, caller);
break;
case 11:
RescueMissionController(code, caller);
break;
case 12:
SatelliteController(code, caller);
break;
case 13:
ReconnaissanceController(code, caller);
break;
case 14:
DoomsdayMachineController(code, caller);
break;
case 15:
CosmicPlagueController(code, caller);
break;
case 16:
SecretMissionYellowController(code, caller);
break;
case 17:
TimeWarpController(code, caller);
break;
case 18:
MaelstromController(code, caller);
break;
/*case 19: QuoteController*/
2021-01-21 15:58:05 +01:00
case 20:
AlienMenacePartTwoController(code, caller);
break;
case 21:
CosmicPlaguePartTwoController(code, caller);
break;
case 22:
SecretMissionRedController(code, caller);
break;
case 23:
SecretMissionGreenController(code, caller);
break;
case 24:
TimeWarpPartTwoController(code, caller);
break;
case 25:
MaelstromPartTwoController(code, caller);
break;
case 26:
MaelstromPartThreeController(code, caller);
break;
case 27:
MaelstromPartFourController(code, caller);
break;
case 28:
MaelstromPartFiveController(code, caller);
break;
case 29:
MaelstromPartSixController(code, caller);
break;
case 30:
MaelstromPartSevenController(code, caller);
break;
case 31:
MaelstromPartEightController(code, caller);
break;
case 32:
GameoverController(code, caller);
break;
default:
UnselectMissionController(code, caller);
break;
}
2020-12-19 15:49:31 +01:00
}
void control::HyperspaceKickOutControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
return;
auto activeCount = hyper_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0);
HyperspaceLightGroupControl(MessageCode::TLightGroupResetAndTurnOn, hyper_lights);
2021-01-21 15:58:05 +01:00
switch (activeCount)
{
case 0:
{
auto addedScore = TableG->AddScore(caller->get_scoring(0));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING113), addedScore);
info_text_box->Display(Buffer, 2.0);
2021-01-21 15:58:05 +01:00
break;
}
case 1:
{
if (!pb::FullTiltMode)
{
auto addedScore = SpecialAddScore(TableG->JackpotScore);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING115), addedScore);
info_text_box->Display(Buffer, 2.0);
TableG->JackpotScore = 20000;
}
else
{
TableG->JackpotScore *= 2;
if (TableG->JackpotScore > 10000000)
TableG->JackpotScore = 10000000;
info_text_box->Display(pb::get_rc_string(Msg::ControlJackpotDoubled), 2.0);
}
2021-01-21 15:58:05 +01:00
break;
}
case 2:
{
DrainBallBlockerControl(MessageCode::TBlockerEnable, block1);
2021-01-21 15:58:05 +01:00
auto addedScore = TableG->AddScore(caller->get_scoring(2));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING103), addedScore);
info_text_box->Display(Buffer, 2.0);
2021-01-21 15:58:05 +01:00
break;
}
case 3:
{
ExtraBallLightControl(MessageCode::TLightResetAndTurnOn, nullptr);
2021-01-21 15:58:05 +01:00
auto addedScore = TableG->AddScore(caller->get_scoring(3));
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING109), addedScore);
info_text_box->Display(Buffer, 2.0);
2021-01-21 15:58:05 +01:00
break;
}
case 4:
{
hyper_lights->Message(MessageCode::TLightTurnOff, 0.0);
size_t addedScore = TableG->AddScore(caller->get_scoring(4));
GravityWellKickoutControl(MessageCode::ControlEnableMultiplier, reinterpret_cast<TPinballComponent*>(addedScore));
2021-01-21 15:58:05 +01:00
break;
}
default:
break;
}
int someFlag = 0;
if (lite25->light_on())
2021-01-21 15:58:05 +01:00
{
someFlag = 1;
auto addedScore = SpecialAddScore(TableG->ReflexShotScore);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING111), addedScore);
info_text_box->Display(Buffer, 2.0);
2021-01-21 15:58:05 +01:00
}
if (lite26->light_on())
2021-01-21 15:58:05 +01:00
someFlag |= 2u;
if (lite130->light_on())
2021-01-21 15:58:05 +01:00
{
someFlag |= 4u;
lite130->Message(MessageCode::TLightResetAndTurnOff, 0.0);
MultiplierLightGroupControl(MessageCode::ControlEnableMultiplier, top_target_lights);
bumber_target_lights->Message(MessageCode::TLightResetAndTurnOn, 0.0);
2021-01-21 15:58:05 +01:00
table_set_jackpot();
table_set_bonus();
table_set_flag_lights();
table_set_bonus_hold();
lite27->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite28->Message(MessageCode::TLightResetAndTurnOn, 0.0);
ExtraBallLightControl(MessageCode::TLightResetAndTurnOn, nullptr);
DrainBallBlockerControl(MessageCode::TBlockerEnable, block1);
2021-01-21 15:58:05 +01:00
if (TableG->MultiballFlag)
{
auto duration = soundwave41->Play(nullptr, "HyperspaceKickOutControl_setMultiball");
table_set_multiball(duration);
2021-01-21 15:58:05 +01:00
}
if (TableG->JackpotScore < 100000)
TableG->JackpotScore = 100000;
if (TableG->BonusScore < 100000)
TableG->BonusScore = 100000;
GravityWellKickoutControl(MessageCode::ControlEnableMultiplier, nullptr);
2021-01-21 15:58:05 +01:00
}
2021-01-22 10:53:16 +01:00
TSound* sound;
2021-01-21 15:58:05 +01:00
if (someFlag)
{
if (someFlag == 1)
{
sound = soundwave21;
2021-01-21 15:58:05 +01:00
}
else
{
if (someFlag < (!pb::FullTiltMode ? 1 : 2) || someFlag > 3)
2021-01-21 15:58:05 +01:00
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
auto duration = soundwave41->Play(lite24, "HyperspaceKickOutControl1");
soundwave36_1->Play(lite24, "HyperspaceKickOutControl2");
soundwave50_2->Play(lite24, "HyperspaceKickOutControl3");
lite25->Message(MessageCode::TLightFlasherStartTimed, duration + 5.0f);
caller->Message(MessageCode::TKickoutRestartTimer, duration);
2021-01-21 15:58:05 +01:00
return;
}
sound = soundwave40;
2021-01-21 15:58:05 +01:00
}
}
else
{
switch (activeCount)
{
case 1:
sound = soundwave36_2;
2021-01-21 15:58:05 +01:00
break;
case 2:
sound = soundwave35_2;
2021-01-21 15:58:05 +01:00
break;
case 3:
sound = soundwave38;
2021-01-21 15:58:05 +01:00
break;
case 4:
sound = soundwave39;
2021-01-21 15:58:05 +01:00
break;
default:
sound = soundwave35_1;
2021-01-21 15:58:05 +01:00
break;
}
}
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
auto duration = sound->Play(lite24, "HyperspaceKickOutControl4");
lite25->Message(MessageCode::TLightFlasherStartTimed, 5.0);
caller->Message(MessageCode::TKickoutRestartTimer, duration);
2020-12-19 15:49:31 +01:00
}
void control::PlungerControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::PlungerFeedBall)
2021-01-07 17:00:38 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, nullptr);
if (easyMode && !block1->ActiveFlag)
DrainBallBlockerControl(MessageCode::TBlockerEnable, block1);
2021-01-07 17:00:38 +01:00
}
else if (code == MessageCode::PlungerStartFeedTimer)
2021-01-07 17:00:38 +01:00
{
table_unlimited_balls = false;
if (!middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0))
middle_circle->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.0);
if (!lite200->light_on())
2021-01-07 17:00:38 +01:00
{
skill_shot_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite67->Message(MessageCode::TLightResetAndTurnOn, 0.0);
skill_shot_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.25f);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
l_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
l_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
r_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
TableG->ReflexShotScore = 25000;
MultiplierLightGroupControl(MessageCode::ControlDisableMultiplier, top_target_lights);
fuel_bargraph->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite200->Message(MessageCode::TLightResetAndTurnOn, 0.0);
gate1->Message(MessageCode::TGateDisable, 0.0);
gate2->Message(MessageCode::TGateDisable, 0.0);
2021-01-07 17:00:38 +01:00
}
lite200->MessageField = 0;
2021-01-07 17:00:38 +01:00
}
2020-12-19 15:49:31 +01:00
}
void control::MedalTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision && !caller->MessageField)
2021-01-21 15:58:05 +01:00
{
caller->MessageField = 1;
if (target6->MessageField
+ target5->MessageField
+ target4->MessageField == 3)
2021-01-21 15:58:05 +01:00
{
MedalLightGroupControl(MessageCode::TLightGroupResetAndTurnOn, bumber_target_lights);
int activeCount = bumber_target_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0) - 1;
const char* text;
2021-01-21 15:58:05 +01:00
switch (activeCount)
{
case 0:
TableG->AddScore(caller->get_scoring(1));
text = pb::get_rc_string(Msg::STRING154);
2021-01-21 15:58:05 +01:00
break;
case 1:
TableG->AddScore(caller->get_scoring(2));
text = pb::get_rc_string(Msg::STRING155);
2021-01-21 15:58:05 +01:00
break;
default:
table_add_extra_ball(4.0);
text = pb::get_rc_string(Msg::STRING156);
2021-01-21 15:58:05 +01:00
break;
}
info_text_box->Display(text, 2.0);
target6->MessageField = 0;
target6->Message(MessageCode::TPopupTargetEnable, 0.0);
target5->MessageField = 0;
target5->Message(MessageCode::TPopupTargetEnable, 0.0);
target4->MessageField = 0;
target4->Message(MessageCode::TPopupTargetEnable, 0.0);
2021-01-21 15:58:05 +01:00
return;
}
TableG->AddScore(caller->get_scoring(0));
}
2020-12-19 15:49:31 +01:00
}
void control::MultiplierTargetControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
if (code == MessageCode::ControlCollision && !caller->MessageField)
2021-01-21 15:58:05 +01:00
{
caller->MessageField = 1;
if (target9->MessageField + target8->MessageField + target7->MessageField == 3)
2021-01-21 15:58:05 +01:00
{
TableG->AddScore(caller->get_scoring(1));
MultiplierLightGroupControl(MessageCode::TLightGroupResetAndTurnOn, top_target_lights);
int activeCount = top_target_lights->Message(MessageCode::TLightGroupGetOnCount, 0.0);
const char* text;
2021-01-21 15:58:05 +01:00
switch (activeCount)
{
case 1:
TableG->ScoreMultiplier = 1;
text = pb::get_rc_string(Msg::STRING157);
2021-01-21 15:58:05 +01:00
break;
case 2:
TableG->ScoreMultiplier = 2;
text = pb::get_rc_string(Msg::STRING158);
2021-01-21 15:58:05 +01:00
break;
case 3:
TableG->ScoreMultiplier = 3;
text = pb::get_rc_string(Msg::STRING159);
2021-01-21 15:58:05 +01:00
break;
default:
TableG->ScoreMultiplier = 4;
text = pb::get_rc_string(Msg::STRING160);
2021-01-21 15:58:05 +01:00
break;
}
info_text_box->Display(text, 2.0);
target9->MessageField = 0;
target9->Message(MessageCode::TPopupTargetEnable, 0.0);
target8->MessageField = 0;
target8->Message(MessageCode::TPopupTargetEnable, 0.0);
target7->MessageField = 0;
target7->Message(MessageCode::TPopupTargetEnable, 0.0);
2021-01-21 15:58:05 +01:00
}
else
{
TableG->AddScore(caller->get_scoring(0));
}
}
}
void control::BallDrainControl(MessageCode code, TPinballComponent* caller)
2020-12-19 15:49:31 +01:00
{
char Buffer[64];
if (code == MessageCode::ControlTimerExpired)
{
if (lite199->MessageField)
{
TableG->Message(MessageCode::GameOver, 0.0);
if (pb::chk_highscore())
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave3->Play(nullptr, "BallDrainControl1");
TableG->LightGroup->Message(MessageCode::TLightFlasherStartTimedThenStayOff, 3.0);
mission_text_box->Display(pb::get_rc_string(Msg::STRING277), -1.0);
}
}
else
{
plunger->Message(MessageCode::PlungerStartFeedTimer, 0.0);
}
}
else if (code == MessageCode::ControlCollision)
{
if (table_unlimited_balls)
{
drain->Message(MessageCode::Reset, 0.0);
sink3->Message(MessageCode::TSinkResetTimer, 0.0);
}
else
{
if (TableG->TiltLockFlag)
{
lite200->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite199->Message(MessageCode::TLightResetAndTurnOff, 0.0);
midi::play_track(MidiTracks::Track1, false);
}
if (lite200->light_on())
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave27->Play(nullptr, "BallDrainControl2");
lite200->Message(MessageCode::TLightResetAndTurnOn, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING197), -1.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave59->Play(nullptr, "BallDrainControl3");
}
else if (lite199->light_on())
{
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave27->Play(nullptr, "BallDrainControl4");
lite199->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite200->Message(MessageCode::TLightResetAndTurnOn, 0.0);
info_text_box->Display(pb::get_rc_string(Msg::STRING196), 2.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave59->Play(nullptr, "BallDrainControl5");
--TableG->UnknownP78;
}
else if (TableG->MultiballCount)
{
if (TableG->MultiballCount == 1)
{
lite38->Message(MessageCode::TLightResetAndTurnOff, 0.0f);
lite39->Message(MessageCode::TLightResetAndTurnOff, 0.0f);
midi::play_track(MidiTracks::Track1, false);
}
else if (TableG->MultiballCount == 2)
{
lite40->Message(MessageCode::TLightResetAndTurnOff, 0.0f);
}
}
else
{
if (!TableG->TiltLockFlag)
{
int time = SpecialAddScore(TableG->BonusScore);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING195), time);
info_text_box->Display(Buffer, 2.0);
}
if (TableG->ExtraBalls)
{
TableG->ExtraBalls--;
const char* shootAgainText;
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave59->Play(nullptr, "BallDrainControl7");
switch (TableG->CurrentPlayer)
{
case 0:
shootAgainText = pb::get_rc_string(Msg::STRING198);
break;
case 1:
shootAgainText = pb::get_rc_string(Msg::STRING199);
break;
case 2:
shootAgainText = pb::get_rc_string(Msg::STRING200);
break;
default:
case 3:
shootAgainText = pb::get_rc_string(Msg::STRING201);
break;
}
info_text_box->Display(shootAgainText, -1.0);
}
else
{
TableG->ChangeBallCount(TableG->BallCount - 1);
if (TableG->CurrentPlayer + 1 != TableG->PlayerCount || TableG->BallCount)
{
TableG->Message(MessageCode::SwitchToNextPlayer, 0.0);
lite199->MessageField = 0;
}
else
{
lite199->MessageField = 1;
}
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave27->Play(nullptr, "BallDrainControl8");
}
bmpr_inc_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
ramp_bmpr_inc_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite30->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite29->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite1->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite54->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite55->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite56->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite17->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite18->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite27->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite28->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite16->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite20->Message(MessageCode::TLightResetAndTurnOff, 0.0);
hyper_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite25->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite26->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite130->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOff, 0.0);
worm_hole_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite60->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite59->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite61->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bumber_target_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
top_target_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
top_circle_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
ramp_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lchute_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bpr_solotgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite110->Message(MessageCode::TLightResetAndTurnOff, 0.0);
skill_shot_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite77->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite196->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite195->Message(MessageCode::TLightResetAndTurnOff, 0.0);
fuel_bargraph->Message(MessageCode::TLightResetAndTurnOff, 0.0);
fuel_bargraph->Message(MessageCode::Reset, 0.0);
GravityWellKickoutControl(MessageCode::Reset, nullptr);
lite62->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite4->MessageField = 0;
lite101->MessageField = 0;
lite102->MessageField = 0;
lite103->MessageField = 0;
ramp_tgt_lights->MessageField = 0;
outer_circle->Message(MessageCode::TLightGroupReset, 0.0);
middle_circle->Message(MessageCode::TLightGroupReset, 0.0);
attack_bump->Message(MessageCode::Reset, 0.0);
launch_bump->Message(MessageCode::Reset, 0.0);
gate1->Message(MessageCode::Reset, 0.0);
gate2->Message(MessageCode::Reset, 0.0);
block1->Message(MessageCode::Reset, 0.0);
target1->Message(MessageCode::Reset, 0.0);
target2->Message(MessageCode::Reset, 0.0);
target3->Message(MessageCode::Reset, 0.0);
target6->Message(MessageCode::Reset, 0.0);
target5->Message(MessageCode::Reset, 0.0);
target4->Message(MessageCode::Reset, 0.0);
target9->Message(MessageCode::Reset, 0.0);
target8->Message(MessageCode::Reset, 0.0);
target7->Message(MessageCode::Reset, 0.0);
if (lite199->MessageField)
lite198->MessageField = 32;
else
lite198->MessageField = 0;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
TableG->Message(MessageCode::ClearTiltLock, 0.0);
if (lite58->light_on())
lite58->Message(MessageCode::TLightResetAndTurnOff, 0.0);
else
TableG->BonusScore = 25000;
}
}
}
2020-12-19 15:49:31 +01:00
}
2020-12-25 14:46:06 +01:00
2021-01-20 15:28:48 +01:00
void control::table_control_handler(MessageCode code)
2020-12-25 14:46:06 +01:00
{
if (code == MessageCode::SetTiltLock)
2020-12-25 14:46:06 +01:00
{
table_unlimited_balls = false;
lite77->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2020-12-25 14:46:06 +01:00
}
}
2021-01-20 15:28:48 +01:00
void control::AlienMenaceController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
if (code != MessageCode::TBumperSetBmpIndex)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
attack_bump->Message(MessageCode::TBumperSetBmpIndex, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
l_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
l_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
r_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
lite307->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING275), -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (bump1 == caller)
2021-01-20 15:28:48 +01:00
{
if (bump1->BmpIndex)
2021-01-20 15:28:48 +01:00
{
lite307->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 20;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-20 15:28:48 +01:00
}
}
}
void control::AlienMenacePartTwoController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = 8;
l_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite308->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite311->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING208),
lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (bump1 == caller
|| bump2 == caller
|| bump3 == caller
|| bump4 == caller)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-20 15:28:48 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-20 15:28:48 +01:00
}
else
{
lite308->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite311->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING231), 4.0);
int addedScore = SpecialAddScore(750000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-20 15:28:48 +01:00
if (!AddRankProgress(7))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "AlienMenacePartTwoController");
2021-01-20 15:28:48 +01:00
}
}
}
}
void control::BlackHoleThreatController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code == MessageCode::TBumperSetBmpIndex)
2021-01-20 15:28:48 +01:00
{
if (bump5 == caller)
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-20 15:28:48 +01:00
}
else if (code == MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (kickout3 == caller
&& bump5->BmpIndex)
2021-01-20 15:28:48 +01:00
{
if (lite316->light_on())
lite316->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite314->light_on())
lite314->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING225), 4.0);
int addedScore = SpecialAddScore(1000000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-20 15:28:48 +01:00
if (!AddRankProgress(8))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "BlackHoleThreatController");
2021-01-20 15:28:48 +01:00
}
}
}
else
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
launch_bump->Message(MessageCode::TBumperSetBmpIndex, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
if (bump5->BmpIndex)
2021-01-20 15:28:48 +01:00
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING224), -1.0);
if (lite316->light_on())
lite316->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite314->light_on())
2021-01-20 15:28:48 +01:00
{
lite314->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
}
else
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING223), -1.0);
if (lite314->light_on())
lite314->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite316->light_on())
2021-01-20 15:28:48 +01:00
{
lite316->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
}
}
}
void control::BugHuntController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = 15;
target1->MessageField = 0;
target1->Message(MessageCode::TPopupTargetEnable, 0.0);
target2->MessageField = 0;
target2->Message(MessageCode::TPopupTargetEnable, 0.0);
target3->MessageField = 0;
target3->Message(MessageCode::TPopupTargetEnable, 0.0);
target6->MessageField = 0;
target6->Message(MessageCode::TPopupTargetEnable, 0.0);
target5->MessageField = 0;
target5->Message(MessageCode::TPopupTargetEnable, 0.0);
target4->MessageField = 0;
target4->Message(MessageCode::TPopupTargetEnable, 0.0);
target9->MessageField = 0;
target9->Message(MessageCode::TPopupTargetEnable, 0.0);
target8->MessageField = 0;
target8->Message(MessageCode::TPopupTargetEnable, 0.0);
target7->MessageField = 0;
target7->Message(MessageCode::TPopupTargetEnable, 0.0);
top_circle_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
ramp_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lchute_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bpr_solotgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite306->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite308->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite310->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite313->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite319->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING226), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (target1 == caller
|| target2 == caller
|| target3 == caller
|| target6 == caller
|| target5 == caller
|| target4 == caller
|| target9 == caller
|| target8 == caller
|| target7 == caller
|| target10 == caller
|| target11 == caller
|| target12 == caller
|| target13 == caller
|| target14 == caller
|| target15 == caller
|| target16 == caller
|| target17 == caller
|| target18 == caller
|| target19 == caller
|| target20 == caller
|| target21 == caller
|| target22 == caller)
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-20 15:28:48 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-20 15:28:48 +01:00
}
else
{
lite306->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite308->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite310->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite313->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite319->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING227), 4.0);
int addedScore = SpecialAddScore(750000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-20 15:28:48 +01:00
if (!AddRankProgress(7))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "BugHuntController");
2021-01-20 15:28:48 +01:00
}
}
}
}
void control::CosmicPlagueController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = 75;
lite20->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite305->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite312->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING240), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (flag1 == caller || flag2 == caller)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-20 15:28:48 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-20 15:28:48 +01:00
}
else
{
lite305->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite312->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 21;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
lite20->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-20 15:28:48 +01:00
}
}
}
void control::CosmicPlaguePartTwoController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
lite310->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING241), -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (roll9 == caller)
2021-01-20 15:28:48 +01:00
{
lite310->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING242), 4.0);
int addedScore = SpecialAddScore(1750000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-20 15:28:48 +01:00
if (!AddRankProgress(11))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "CosmicPlaguePartTwoController");
2021-01-20 15:28:48 +01:00
}
}
}
void control::DoomsdayMachineController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-20 15:28:48 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = 3;
lite301->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite320->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-20 15:28:48 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING238), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-20 15:28:48 +01:00
return;
}
if (roll4 == caller || roll8 == caller)
2021-01-20 15:28:48 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-20 15:28:48 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-20 15:28:48 +01:00
}
else
{
lite301->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite320->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING239), 4.0);
int addedScore = SpecialAddScore(1250000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-20 15:28:48 +01:00
if (!AddRankProgress(9))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "DoomsdayMachineController");
2021-01-20 15:28:48 +01:00
}
}
}
}
void control::GameoverController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
char Buffer[128];
if (code == MessageCode::ControlMissionComplete)
2021-01-20 15:28:48 +01:00
{
goal_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2022-01-05 09:38:50 +01:00
pb::mode_change(GameModes::GameOver);
flip1->Message(MessageCode::GameOver, 0.0);
flip2->Message(MessageCode::GameOver, 0.0);
mission_text_box->MessageField = 0;
midi::play_track(MidiTracks::Track1, false);
2021-01-20 15:28:48 +01:00
return;
}
if (code != MessageCode::ControlMissionStarted)
2021-01-20 15:28:48 +01:00
return;
int missionMsg = mission_text_box->MessageField;
2021-01-20 15:28:48 +01:00
if (missionMsg & 0x100)
{
int playerId = missionMsg % 4;
2021-01-20 15:28:48 +01:00
int playerScore = TableG->PlayerScores[playerId].ScoreStruct->Score;
auto nextPlayerId = playerId + 1;
if (playerScore >= 0)
{
const char* playerNScoreText = nullptr;
switch (nextPlayerId)
{
case 1:
playerNScoreText = pb::get_rc_string(Msg::STRING280);
2021-01-20 15:28:48 +01:00
break;
case 2:
playerNScoreText = pb::get_rc_string(Msg::STRING281);
2021-01-20 15:28:48 +01:00
break;
case 3:
playerNScoreText = pb::get_rc_string(Msg::STRING282);
2021-01-20 15:28:48 +01:00
break;
case 4:
playerNScoreText = pb::get_rc_string(Msg::STRING283);
2021-01-20 15:28:48 +01:00
break;
default:
break;
}
if (playerNScoreText != nullptr)
{
snprintf(Buffer, sizeof Buffer, playerNScoreText, playerScore);
mission_text_box->Display(Buffer, 3.0);
2021-01-20 15:28:48 +01:00
int msgField = nextPlayerId == TableG->PlayerCount ? 0x200 : nextPlayerId | 0x100;
mission_text_box->MessageField = msgField;
2021-01-20 15:28:48 +01:00
return;
}
}
mission_text_box->MessageField = 0x200;
2021-01-20 15:28:48 +01:00
}
if (missionMsg & 0x200)
{
2021-10-18 08:31:47 +02:00
int highscoreId = missionMsg % 5;
int highScore = high_score::highscore_table[highscoreId].Score;
2021-01-20 15:28:48 +01:00
auto nextHidhscoreId = highscoreId + 1;
if (highScore > 0)
{
const char* highScoreNText = nullptr;
switch (nextHidhscoreId)
{
case 1:
highScoreNText = pb::get_rc_string(Msg::STRING284);
2021-01-20 15:28:48 +01:00
break;
case 2:
highScoreNText = pb::get_rc_string(Msg::STRING285);
2021-01-20 15:28:48 +01:00
break;
case 3:
highScoreNText = pb::get_rc_string(Msg::STRING286);
2021-01-20 15:28:48 +01:00
break;
case 4:
highScoreNText = pb::get_rc_string(Msg::STRING287);
2021-01-20 15:28:48 +01:00
break;
case 5:
highScoreNText = pb::get_rc_string(Msg::STRING288);
2021-01-20 15:28:48 +01:00
break;
default:
break;
}
if (highScoreNText != nullptr)
{
snprintf(Buffer, sizeof Buffer, highScoreNText, highScore);
mission_text_box->Display(Buffer, 3.0);
2021-01-20 15:28:48 +01:00
int msgField = nextHidhscoreId == 5 ? 0 : nextHidhscoreId | 0x200;
mission_text_box->MessageField = msgField;
2021-01-20 15:28:48 +01:00
return;
}
}
}
2021-01-21 15:58:05 +01:00
mission_text_box->MessageField = 0x100;
mission_text_box->Display(pb::get_rc_string(Msg::STRING272), 10.0);
2021-01-20 15:28:48 +01:00
}
void control::LaunchTrainingController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite317->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite56->MessageField = 3;
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING211), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (ramp == caller)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-21 15:58:05 +01:00
}
else
{
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING212), 4.0);
int addedScore = SpecialAddScore(500000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-21 15:58:05 +01:00
if (!AddRankProgress(6))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "LaunchTrainingController");
2021-01-21 15:58:05 +01:00
}
}
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = 3;
lite303->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite309->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite315->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING249), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (target1 == caller
|| target2 == caller
|| target3 == caller
|| target6 == caller
|| target5 == caller
|| target4 == caller
|| target9 == caller
|| target8 == caller
|| target7 == caller)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-21 15:58:05 +01:00
}
else
{
lite303->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite309->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite315->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 25;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartEightController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite130->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite304->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING256), -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (kickout2 == caller)
2021-01-21 15:58:05 +01:00
{
lite304->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite130->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
int addedScore = SpecialAddScore(5000000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
info_text_box->Display(pb::get_rc_string(Msg::STRING149), 4.0);
2021-01-21 15:58:05 +01:00
if (!AddRankProgress(18))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "MaelstromPartEightController");
2021-01-21 15:58:05 +01:00
}
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartFiveController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite317->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING253), -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (ramp == caller)
2021-01-21 15:58:05 +01:00
{
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 29;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartFourController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = 0;
lite318->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING252), -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (roll184 == caller)
2021-01-21 15:58:05 +01:00
{
lite318->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 28;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartSevenController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
AdvanceWormHoleDestination(1);
sink1->Message(MessageCode::TSinkUnknown7, 0.0);
sink2->Message(MessageCode::TSinkUnknown7, 0.0);
sink3->Message(MessageCode::TSinkUnknown7, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING255), -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (sink1 == caller
|| sink2 == caller
|| sink3 == caller)
2021-01-21 15:58:05 +01:00
{
lite198->MessageField = 31;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartSixController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite20->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite305->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite312->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING254), -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (flag1 == caller || flag2 == caller)
2021-01-21 15:58:05 +01:00
{
lite305->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite312->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 30;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
lite20->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-21 15:58:05 +01:00
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartThreeController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = 5;
lite301->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite302->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite307->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite316->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite320->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite321->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING251), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (roll3 == caller
|| roll2 == caller
|| roll1 == caller
|| roll112 == caller
|| roll111 == caller
|| roll110 == caller
|| roll4 == caller
|| roll8 == caller
|| roll6 == caller
|| roll7 == caller
|| roll5 == caller)
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-21 15:58:05 +01:00
}
else
{
lite301->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite302->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite307->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite316->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite320->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite321->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 27;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
}
2021-01-20 15:28:48 +01:00
}
void control::MaelstromPartTwoController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = 3;
lite306->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite308->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite310->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite313->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite319->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING250), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (target10 == caller
|| target11 == caller
|| target12 == caller
|| target13 == caller
|| target14 == caller
|| target15 == caller
|| target16 == caller
|| target17 == caller
|| target18 == caller
|| target19 == caller
|| target20 == caller
|| target21 == caller
|| target22 == caller)
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-21 15:58:05 +01:00
}
else
{
lite306->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite308->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite310->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite313->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite319->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 26;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-21 15:58:05 +01:00
}
}
2021-01-20 15:28:48 +01:00
}
void control::PracticeMissionController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite308->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite311->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite56->MessageField = 8;
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING208), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (bump1 == caller
|| bump2 == caller
|| bump3 == caller
|| bump4 == caller)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-21 15:58:05 +01:00
}
else
{
lite308->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite311->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING209), 4.0);
int addedScore = SpecialAddScore(500000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-21 15:58:05 +01:00
if (!AddRankProgress(6))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "PracticeMissionController");
2021-01-21 15:58:05 +01:00
}
}
}
2021-01-20 15:28:48 +01:00
}
void control::ReconnaissanceController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-21 15:58:05 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-21 15:58:05 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-21 15:58:05 +01:00
{
lite56->MessageField = 15;
lite301->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite302->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite307->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite316->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite320->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite321->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-21 15:58:05 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-21 15:58:05 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING235), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-21 15:58:05 +01:00
return;
}
if (roll3 == caller
|| roll2 == caller
|| roll1 == caller
|| roll112 == caller
|| roll111 == caller
|| roll110 == caller
|| roll4 == caller
|| roll8 == caller
|| roll6 == caller
|| roll7 == caller
|| roll5 == caller)
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-21 15:58:05 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, nullptr);
2021-01-21 15:58:05 +01:00
}
else
{
lite301->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite302->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite307->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite316->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite320->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite321->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING237), 4.0);
int addedScore = SpecialAddScore(1250000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-21 15:58:05 +01:00
if (!AddRankProgress(9))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "ReconnaissanceController");
2021-01-21 15:58:05 +01:00
}
}
}
2021-01-20 15:28:48 +01:00
}
void control::ReentryTrainingController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
char Buffer[64];
2021-01-20 15:28:48 +01:00
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = 3;
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
l_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
l_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupOffsetAnimationForward, 0.2f);
r_trek_lights->Message(MessageCode::TLightGroupAnimationBackward, 0.2f);
lite307->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING213), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (roll3 == caller
|| roll2 == caller
|| roll1 == caller)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
}
else
{
lite307->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING214), 4.0);
int addedScore = SpecialAddScore(500000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(6))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "ReentryTrainingController");
2021-01-23 07:57:16 +01:00
}
}
}
2021-01-20 15:28:48 +01:00
}
void control::RescueMissionController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
char Buffer[64];
2021-01-20 15:28:48 +01:00
2021-01-23 07:57:16 +01:00
switch (code)
{
case MessageCode::ControlCollision:
2021-01-23 07:57:16 +01:00
{
if (target1 == caller
|| target2 == caller
|| target3 == caller)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
return;
}
if (kickout2 != caller || !lite20->light_on())
2021-01-23 07:57:16 +01:00
return;
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
return;
}
if (lite303->light_on())
lite303->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite304->light_on())
lite304->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING230), 4.0);
int addedScore = SpecialAddScore(750000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(7))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "RescueMissionController");
2021-01-23 07:57:16 +01:00
}
break;
}
case MessageCode::ControlMissionComplete:
lite20->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite19->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite56->MessageField = 1;
2021-01-23 07:57:16 +01:00
break;
case MessageCode::ControlMissionStarted:
if (lite20->light_on())
2021-01-23 07:57:16 +01:00
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING229), -1.0);
if (lite303->light_on())
lite303->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite304->light_on())
2021-01-23 07:57:16 +01:00
{
lite304->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
}
else
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING228), -1.0);
if (lite304->light_on())
lite304->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite303->light_on())
2021-01-23 07:57:16 +01:00
{
lite303->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
}
break;
default:
break;
}
2021-01-20 15:28:48 +01:00
}
void control::SatelliteController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
char Buffer[64];
2021-01-20 15:28:48 +01:00
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = 3;
lite308->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING233), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (bump4 == caller)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
}
else
{
lite308->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING234), 4.0);
int addedScore = SpecialAddScore(1250000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(9))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "SatelliteController");
2021-01-23 07:57:16 +01:00
}
}
}
}
void control::ScienceMissionController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = 9;
target1->MessageField = 0;
target1->Message(MessageCode::TPopupTargetEnable, 0.0);
target2->MessageField = 0;
target2->Message(MessageCode::TPopupTargetEnable, 0.0);
target3->MessageField = 0;
target3->Message(MessageCode::TPopupTargetEnable, 0.0);
target6->MessageField = 0;
target6->Message(MessageCode::TPopupTargetEnable, 0.0);
target5->MessageField = 0;
target5->Message(MessageCode::TPopupTargetEnable, 0.0);
target4->MessageField = 0;
target4->Message(MessageCode::TPopupTargetEnable, 0.0);
target9->MessageField = 0;
target9->Message(MessageCode::TPopupTargetEnable, 0.0);
target8->MessageField = 0;
target8->Message(MessageCode::TPopupTargetEnable, 0.0);
target7->MessageField = 0;
target7->Message(MessageCode::TPopupTargetEnable, 0.0);
lite303->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite309->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite315->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING215), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (target1 == caller
|| target2 == caller
|| target3 == caller
|| target6 == caller
|| target5 == caller
|| target4 == caller
|| target9 == caller
|| target8 == caller
|| target7 == caller)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
}
else
{
lite303->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite309->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite315->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING216), 4.0);
int addedScore = SpecialAddScore(750000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(9))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "ScienceMissionController");
2021-01-23 07:57:16 +01:00
}
}
}
}
void control::SecretMissionGreenController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite6->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite2->Message(MessageCode::TLightSetOnStateBmpIndex, 1.0);
lite2->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite2->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
const char* v2 = pb::get_rc_string(Msg::STRING245);
mission_text_box->Display(v2, -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (sink2 == caller)
2021-01-23 07:57:16 +01:00
{
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING246), 4.0);
int addedScore = SpecialAddScore(1500000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(10))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "SecretMissionGreenController");
2021-01-23 07:57:16 +01:00
}
}
}
void control::SecretMissionRedController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite5->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite4->Message(MessageCode::TLightSetOnStateBmpIndex, 2.0);
lite4->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite4->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING244), -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (sink1 == caller)
2021-01-23 07:57:16 +01:00
{
lite198->MessageField = 23;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-23 07:57:16 +01:00
}
}
void control::SecretMissionYellowController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
worm_hole_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightSetMessageField, 0.0);
lite110->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite7->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite3->Message(MessageCode::TLightSetOnStateBmpIndex, 0.0);
lite3->Message(MessageCode::TLightResetAndTurnOn, 0.0);
lite3->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING243), -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (sink3 == caller)
2021-01-23 07:57:16 +01:00
{
lite198->MessageField = 22;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-23 07:57:16 +01:00
}
}
void control::SelectMissionController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
char Buffer[64];
switch (code)
{
case MessageCode::TLightGroupToggleSplitIndex:
case MessageCode::TLightGroupCountdownEnded:
if (fuel_bargraph != caller)
2021-01-23 07:57:16 +01:00
return;
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
return;
case MessageCode::ControlCollision:
2021-01-23 07:57:16 +01:00
{
int missionLevel = 0;
if (target13 == caller)
2021-01-23 07:57:16 +01:00
missionLevel = 1;
if (target14 == caller)
2021-01-23 07:57:16 +01:00
missionLevel = 2;
if (target15 == caller)
2021-01-23 07:57:16 +01:00
missionLevel = 3;
if (!missionLevel)
{
if (ramp == caller
&& lite56->light_on()
&& fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0))
2021-01-23 07:57:16 +01:00
{
lite56->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->Message(MessageCode::TLightResetAndTurnOn, 0.0);
outer_circle->Message(MessageCode::TLightGroupAnimationBackward, -1.0);
if (lite317->light_on())
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite318->light_on())
lite318->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite319->light_on())
lite319->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = lite56->MessageField;
auto scoreId = lite56->MessageField - 2;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
auto score = !pb::FullTiltMode ? mission_select_scores[scoreId] : 100000;
int addedScore = SpecialAddScore(score);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING178), addedScore);
mission_text_box->Display(Buffer, 4.0);
midi::play_track(MidiTracks::Track2, true);
2021-01-23 07:57:16 +01:00
}
return;
}
if (lite101->MessageField == 7)
2021-01-23 07:57:16 +01:00
{
lite101->MessageField = 0;
2021-01-23 07:57:16 +01:00
missionLevel = 4;
}
int missionId;
auto activeCount = middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
2021-01-23 07:57:16 +01:00
switch (activeCount)
{
case 1:
switch (missionLevel)
{
case 1:
missionId = 3;
break;
case 2:
missionId = 4;
break;
case 3:
missionId = 2;
break;
default:
missionId = 5;
break;
}
break;
case 2:
case 3:
switch (missionLevel)
{
case 1:
missionId = 9;
break;
case 2:
missionId = 11;
break;
case 3:
missionId = 10;
break;
default:
missionId = 16;
break;
}
break;
case 4:
case 5:
switch (missionLevel)
{
case 1:
missionId = 6;
break;
case 2:
missionId = 8;
break;
case 3:
missionId = 7;
break;
default:
missionId = 15;
break;
}
break;
case 6:
case 7:
switch (missionLevel)
{
case 1:
missionId = 12;
break;
case 2:
missionId = 13;
break;
case 3:
missionId = 14;
break;
default:
missionId = 17;
break;
}
break;
case 8:
case 9:
switch (missionLevel)
{
case 1:
missionId = 15;
break;
case 2:
missionId = 16;
break;
case 3:
missionId = 17;
break;
default:
missionId = 18;
break;
}
break;
default:
return;
}
lite56->MessageField = missionId;
lite56->Message(MessageCode::TLightFlasherStartTimedThenStayOn, 2.0);
lite198->Message(MessageCode::TLightFlasherStart, 0.0);
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
return;
}
case MessageCode::ControlMissionComplete:
midi::play_track(MidiTracks::Track1, false);
lite198->Message(MessageCode::TLightResetAndTurnOff, 0.0);
outer_circle->Message(MessageCode::TLightGroupReset, 0.0);
ramp_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite56->MessageField = 0;
lite101->MessageField = 0;
l_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
l_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
r_trek_lights->Message(MessageCode::TLightGroupReset, 0.0);
r_trek_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
goal_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
worm_hole_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
bsink_arrow_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
2021-01-23 07:57:16 +01:00
break;
case MessageCode::ControlMissionStarted:
2021-01-23 07:57:16 +01:00
break;
default:
return;
}
if (fuel_bargraph->Message(MessageCode::TLightGroupGetOnCount, 0.0))
2021-01-23 07:57:16 +01:00
{
if (lite56->light_on() && lite56->MessageField >= 2)
2021-01-23 07:57:16 +01:00
{
auto missionText = pb::get_rc_string(MissionRcArray[lite56->MessageField - 2]);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING207), missionText);
mission_text_box->Display(Buffer, -1.0);
if (lite318->light_on())
lite318->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite319->light_on())
lite319->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite317->light_on())
lite317->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING205), -1.0);
if (lite317->light_on())
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite318->light_on())
lite318->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite319->light_on())
2021-01-23 07:57:16 +01:00
{
lite319->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
}
}
else
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING206), -1.0);
if (lite317->light_on())
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (lite319->light_on())
lite319->Message(MessageCode::TLightResetAndTurnOff, 0.0);
if (!lite318->light_on())
2021-01-23 07:57:16 +01:00
{
lite318->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
}
}
void control::SpaceRadiationController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
char Buffer[64];
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (target16 == caller
|| target17 == caller
|| target18 == caller)
2021-01-23 07:57:16 +01:00
{
if (lite104->MessageField == 7)
2021-01-23 07:57:16 +01:00
{
lite104->MessageField = 15;
bsink_arrow_lights->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite313->Message(MessageCode::TLightResetAndTurnOff, 0.0);
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
AdvanceWormHoleDestination(1);
}
}
else if ((sink1 == caller
|| sink2 == caller
|| sink3 == caller)
&& lite104->MessageField == 15)
2021-01-23 07:57:16 +01:00
{
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING222), 4.0);
int addedScore = SpecialAddScore(1000000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(8))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "SpaceRadiationController");
2021-01-23 07:57:16 +01:00
}
}
}
else
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lchute_tgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite104->MessageField = 0;
lite313->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code == MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
const char* text;
if (lite104->MessageField == 15)
text = pb::get_rc_string(Msg::STRING221);
2021-01-23 07:57:16 +01:00
else
text = pb::get_rc_string(Msg::STRING276);
mission_text_box->Display(text, -1.0);
2021-01-23 07:57:16 +01:00
}
}
}
void control::StrayCometController(MessageCode code, TPinballComponent* caller)
2021-01-23 07:57:16 +01:00
{
char Buffer[64];
if (code == MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (target19 == caller
|| target20 == caller
|| target21 == caller)
2021-01-23 07:57:16 +01:00
{
if (lite107->MessageField == 7)
2021-01-23 07:57:16 +01:00
{
lite306->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite304->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite107->MessageField = 15;
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
}
}
else if (kickout2 == caller && lite107->MessageField == 15)
2021-01-23 07:57:16 +01:00
{
lite304->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
mission_text_box->Display(pb::get_rc_string(Msg::STRING220), 4.0);
int addedScore = SpecialAddScore(1000000, true);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING179), addedScore);
2021-01-23 07:57:16 +01:00
if (!AddRankProgress(8))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave9->Play(nullptr, "StrayCometController");
2021-01-23 07:57:16 +01:00
}
}
}
else
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
bpr_solotgt_lights->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite107->MessageField = 0;
lite306->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code == MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
const char* text;
if (lite107->MessageField == 15)
text = pb::get_rc_string(Msg::STRING219);
2021-01-23 07:57:16 +01:00
else
text = pb::get_rc_string(Msg::STRING218);
mission_text_box->Display(text, -1.0);
2021-01-23 07:57:16 +01:00
}
}
}
void control::TimeWarpController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = 25;
lite300->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite322->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING247), lite56->MessageField);
mission_text_box->Display(Buffer, -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (rebo1 == caller
|| rebo2 == caller
|| rebo3 == caller
|| rebo4 == caller)
2021-01-23 07:57:16 +01:00
{
lite56->MessageField = lite56->MessageField - 1;
if (lite56->MessageField)
2021-01-23 07:57:16 +01:00
{
MissionControl(MessageCode::ControlMissionStarted, caller);
2021-01-23 07:57:16 +01:00
}
else
{
lite300->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite322->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 24;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-23 07:57:16 +01:00
}
}
2021-01-20 15:28:48 +01:00
}
void control::TimeWarpPartTwoController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
char Buffer[64];
if (code != MessageCode::ControlCollision)
2021-01-23 07:57:16 +01:00
{
if (code == MessageCode::ControlMissionComplete)
2021-01-23 07:57:16 +01:00
{
lite55->Message(MessageCode::TLightFlasherStartTimed, -1.0);
lite26->Message(MessageCode::TLightFlasherStartTimed, -1.0);
lite304->Message(MessageCode::TLightFlasherStartTimed, 0.0);
lite317->Message(MessageCode::TLightFlasherStartTimed, 0.0);
2021-01-23 07:57:16 +01:00
}
else if (code != MessageCode::ControlMissionStarted)
2021-01-23 07:57:16 +01:00
{
return;
}
mission_text_box->Display(pb::get_rc_string(Msg::STRING248), -1.0);
2021-01-23 07:57:16 +01:00
return;
}
if (kickout2 == caller)
2021-01-23 07:57:16 +01:00
{
mission_text_box->Display(pb::get_rc_string(Msg::STRING148), 4.0);
if (middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0) > 1)
2021-01-23 07:57:16 +01:00
{
middle_circle->Message(MessageCode::TLightGroupOffsetAnimationBackward, 5.0);
int rank = middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING274), pb::get_rc_string(RankRcArray[rank - 1]));
mission_text_box->Display(Buffer, 8.0);
2021-01-23 07:57:16 +01:00
}
}
else
{
if (ramp != caller)
2021-01-23 07:57:16 +01:00
return;
mission_text_box->Display(pb::get_rc_string(Msg::STRING147), 4.0);
if (middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0) < 9)
2021-01-23 07:57:16 +01:00
{
int rank = middle_circle->Message(MessageCode::TLightGroupGetOnCount, 0.0);
middle_circle->Message(MessageCode::TLightGroupResetAndTurnOn, 5.0);
snprintf(Buffer, sizeof Buffer, pb::get_rc_string(Msg::STRING273), pb::get_rc_string(RankRcArray[rank]));
2021-01-23 07:57:16 +01:00
}
if (!AddRankProgress(12))
{
mission_text_box->Display(Buffer, 8.0);
Implement stereo sound. (#138) * Implement stereo sound. Original Space Cadet has mono sound. To achieve stereo, the following steps were accomplished: - Add a game option to turn on/off stereo sound. Default is on. - TPinballComponent objects were extended with a method called get_coordinates() that returns a single 2D point, approximating the on-screen position of the object, re-mapped between 0 and 1 vertically and horizontally, {0, 0} being at the top-left. - For static objects like bumpers and lights, the coordinate refers to the geometric center of the corresponding graphic sprite, and is precalculated at initialization. - For ball objects, the coordinate refers to the geometric center of the ball, calculated during play when requested. - Extend all calls to sound-playing methods so that they include a TPinballComponent* argument that refers to the sound source, e.g. where the sound comes from. For instance, when a flipper is activated, its method call to emit a sound now includes a reference to the flipper object; when a ball goes under a SkillShotGate, its method call to emit a sound now includes a reference to the corresponding light; and so on. For some cases, like light rollovers, the sound source is taken from the ball that triggered the light rollover. For other cases, like holes, flags and targets, the sound source is taken from the object itself. For some special cases like ramp activation, sound source is taken from the nearest light position that makes sense. For all game-progress sounds, like mission completion sounds or ball drain sounds, the sound source is undefined (set to nullptr), and the Sound::PlaySound() method takes care of positioning them at a default location, where speakers on a pinball machine normally are. - Make the Sound::PlaySound() method accept a new argument, a TPinballComponent reference, as described above. If the stereo option is turned on, the Sound::PlaySound() method calls the get_coordinates() method of the TPinballComponent reference to get the sound position. This project uses SDL_mixer and there is a function called Mix_SetPosition() that allows placing a sound in the stereo field, by giving it a distance and an angle. We arbitrarily place the player's ears at the bottom of the table; we set the ears' height to half a table's length. Intensity of the stereo effect is directly related to this value; the farther the player's ears from the table, the narrowest the stereo picture gets, and vice-versa. From there we have all we need to calculate distance and angle; we do just that and position all the sounds. * Copy-paste typo fix.
2022-05-30 09:35:29 +02:00
soundwave10->Play(nullptr, "TimeWarpPartTwoController");
2021-01-23 07:57:16 +01:00
}
}
SpecialAddScore(2000000);
lite55->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite26->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite304->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite317->Message(MessageCode::TLightResetAndTurnOff, 0.0);
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
// SpecialAddScore sets the score dirty flag. So next tick it will be redrawn.
2021-01-20 15:28:48 +01:00
}
void control::UnselectMissionController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-20 15:28:48 +01:00
}
void control::WaitingDeploymentController(MessageCode code, TPinballComponent* caller)
2021-01-20 15:28:48 +01:00
{
2021-01-23 07:57:16 +01:00
switch (code)
{
case MessageCode::ControlCollision:
if (oneway4 == caller || oneway10 == caller)
2021-01-23 07:57:16 +01:00
{
lite198->MessageField = 1;
MissionControl(MessageCode::ControlMissionComplete, nullptr);
2021-01-23 07:57:16 +01:00
}
break;
case MessageCode::ControlMissionComplete:
mission_text_box->Clear();
2021-01-23 07:57:16 +01:00
waiting_deployment_flag = 0;
midi::play_track(MidiTracks::Track1, false);
2021-01-23 07:57:16 +01:00
break;
case MessageCode::ControlMissionStarted:
mission_text_box->Display(pb::get_rc_string(Msg::STRING151), -1.0);
2021-01-23 07:57:16 +01:00
break;
default:
break;
}
2021-01-20 15:28:48 +01:00
}