Advertisement
Guest User

Untitled

a guest
Aug 31st, 2022
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.64 KB | None | 0 0
  1. // sa22c props file, includes 1,2 and 3 button modes. Incorporates multi-blast,
  2. // battle mode and gesture ignitions from fett263 plus on-the-fly volume
  3. // controls and full access to all features with 1,2 or 3 button sabers
  4. //
  5. // New #define SA22C_NO_LOCKUP_HOLD
  6. // reverts to lockup being triggered only by clash + aux in 2-button mode
  7. // Also sets multi-blast to trigger while holding aux and swinging, rather than
  8. // double click and hold
  9. //
  10. // Gesture Controls
  11. // There are four gesture types: swing, stab, twist and thrust. For simplicity,
  12. // using gesture ignition will automatically skip the preon effect.
  13. // Below are the options to add to the config to enable
  14. // the various gestures
  15. //
  16. // #define SA22C_STAB_ON
  17. // #define SA22C_SWING_ON
  18. // #define SA22C_TWIST_ON
  19. // #define SA22C_THRUST_ON
  20. // #define SA22C_TWIST_OFF
  21. // #define SA22C_FORCE_PUSH
  22. //
  23. // #define SA22C_FORCE_PUSH_LENGTH 5
  24. // Allows for adjustment to Push gesture length in millis needed to trigger Force Push
  25. // Recommended range 1 ~ 10, 1 = shortest, easiest to trigger, 10 = longest
  26. //
  27. // If you want the gesture ignition to ALSO enter battle mode automatically
  28. // on ignition, add this define
  29. //
  30. // #define GESTURE_AUTO_BATTLE_MODE
  31. //
  32. // Battle mode by fett263
  33. //
  34. // Once you enter battle mode, button functions will be disabled for lockup
  35. // stab, melt, etc. Blaster blocks and lightning block will continue to be
  36. // triggered by button controls. Automatic lockup/clash detection works
  37. // by measuring delay of the saber blade pulling back from the clash.
  38. // If you clash the blade and it does not pull back during the delay period,
  39. // it is assumed to be a lockup and the lockup effect will show on the blade.
  40. // If you clash the blade and pull away, only the bgn/end lockup effects will show.
  41. //
  42. // You can adjust the threshold of this detection by using
  43. // #define SA22C_LOCKUP_DELAY (insert number here)
  44. // Default value is 200
  45. //
  46. // Battle mode features automatic clash and lockup detection plus a new
  47. // force push mode that will play a force or force push sound with a controlled
  48. // pushing gesture. Automatic clash/lockup uses the pre and post lock effects
  49. // so your blade style and font MUST have those capabilities to support
  50. // battle mode. Kudos to fett263 for his very impressive additions for OS 5
  51. //
  52. // Tightened click timings
  53. // I've shortened the timeout for short and double click detection from 500ms
  54. // to 300ms. I think it feels more responsive this way but still gives enough
  55. // timeout to ensure all button actions can be achieved consistently
  56. // I've included all button timings so they can be easily tweaked to suit
  57. // individual tastes.
  58. //
  59. // Button configs:
  60. //
  61. // 1 Button:
  62. // Activate Muted - double click and hold while OFF
  63. // Activate - short click while OFF
  64. // Play/Stop Music - double click while OFF
  65. // Turn off blade - hold and wait till blade is off while ON
  66. // Next Preset - hold and release while OFF
  67. // Prev Preset - hold and wait while OFF
  68. // Lockup - hold + hit clash while ON
  69. // Stab - thrust forward clash while ON
  70. // Lightning Block - double click and hold while ON
  71. // Melt - hold + thust forward clash while ON
  72. // Drag - hold + hit clash while ON pointing the blade tip down
  73. // Blaster Blocks - short click/double click/triple click while on
  74. // Multi-Blast - hold while swinging for one second and release
  75. // to trigger blaster block, swing saber while in multi-blast mode
  76. // to exit, hold while swinging for one second and release
  77. // Battle Mode - triple-click and hold while on
  78. // Force Effects - hold + twist the hilt while ON (while pointing up)
  79. // Color Change mode - hold + twist the hilt while ON (pointing down)
  80. // Enter Volume - Menu hold + clash while OFF
  81. // Volume UP - hold and release while in Volume Menu
  82. // Volume DOWN - click while in Volume Menu
  83. // Exit Volume Menu - Menu hold + clash while OFF
  84. // Battery Level - triple click while OFF
  85. //
  86. //
  87. // 2 Button:
  88. // POWER
  89. // Activate Muted - double click and hold while OFF
  90. // Activate - short click while OFF
  91. // Play/Stop Music - hold and release while OFF
  92. // Turn off blade - hold and wait till blade is off while ON
  93. // Force Effects - double click while ON
  94. // Volume UP - short click while OFF and in VOLUME MENU
  95. // Prev Preset - hold and wait while OFF
  96. // Color Change mode - hold + toggle AUX while ON
  97. // Lightning Block - double click and hold while ON
  98. // Melt - hold while stabbing (clash with forward motion, horizontal)
  99. // Battle Mode - triple-click and hold for half a second while on
  100. // AUX
  101. // Blaster blocks - short click/double click/triple click while ON
  102. // Multi-Blast - double-click and hold for half a second
  103. // to trigger blaster block, swing saber while in multi-blast mode
  104. // to exit, double-click and hold for half a second
  105. // Next Preset - short click while OFF
  106. // Lockup - hold while ON
  107. // Drag - hold while ON pointing the blade tip down
  108. // Enter VOLUME MENU - long click while OFF
  109. // Volume down - short click while OFF and in VOLUME MENU
  110. // Battery level - hold while off
  111. //
  112. // 3 Button: Same as two button except for the following
  113. //
  114. // AUX2
  115. // Lightning Block - hold while ON
  116. // Battle Mode - double-click and hold while on
  117. // Previous Preset - short click while OFF
  118.  
  119.  
  120. #ifndef PROPS_SABER_SA22C_BUTTONS_H
  121. #define PROPS_SABER_SA22C_BUTTONS_H
  122.  
  123. #include "prop_base.h"
  124. #include "../sound/hybrid_font.h"
  125.  
  126. #undef PROP_TYPE
  127. #define PROP_TYPE SaberSA22CButtons
  128.  
  129. #ifndef MOTION_TIMEOUT
  130. #define MOTION_TIMEOUT 60 * 15 * 1000
  131. #endif
  132.  
  133. #ifndef SA22C_SWING_ON_SPEED
  134. #define SA22C_SWING_ON_SPEED 250
  135. #endif
  136.  
  137. #ifndef SA22C_LOCKUP_DELAY
  138. #define SA22C_LOCKUP_DELAY 200
  139. #endif
  140.  
  141. #ifndef SA22C_FORCE_PUSH_LENGTH
  142. #define SA22C_FORCE_PUSH_LENGTH 5
  143. #endif
  144.  
  145. #ifndef BUTTON_DOUBLE_CLICK_TIMEOUT
  146. #define BUTTON_DOUBLE_CLICK_TIMEOUT 300
  147. #endif
  148.  
  149. #ifndef BUTTON_SHORT_CLICK_TIMEOUT
  150. #define BUTTON_SHORT_CLICK_TIMEOUT 300
  151. #endif
  152.  
  153. #ifndef BUTTON_HELD_TIMEOUT
  154. #define BUTTON_HELD_TIMEOUT 300
  155. #endif
  156.  
  157. #ifndef BUTTON_HELD_MEDIUM_TIMEOUT
  158. #define BUTTON_HELD_MEDIUM_TIMEOUT 1000
  159. #endif
  160.  
  161. #ifndef BUTTON_HELD_LONG_TIMEOUT
  162. #define BUTTON_HELD_LONG_TIMEOUT 2000
  163. #endif
  164.  
  165. #ifdef SA22C_SWING_ON
  166. #define SWING_GESTURE
  167. #endif
  168.  
  169. #ifdef SA22C_STAB_ON
  170. #define STAB_GESTURE
  171. #endif
  172.  
  173. #ifdef SA22C_TWIST_ON
  174. #define TWIST_GESTURE
  175. #endif
  176.  
  177. #ifdef SA22C_THRUST_ON
  178. #define THRUST_GESTURE
  179. #endif
  180.  
  181. #define FORCE_PUSH_CONDITION battle_mode_
  182.  
  183. EFFECT(dim); // for EFFECT_POWERSAVE
  184. EFFECT(battery); // for EFFECT_BATTERY_LEVEL
  185. EFFECT(bmbegin); // for Begin Battle Mode
  186. EFFECT(bmend); // for End Battle Mode
  187. EFFECT(vmbegin); // for Begin Volume Menu
  188. EFFECT(vmend); // for End Volume Menu
  189. EFFECT(volup); // for increse volume
  190. EFFECT(voldown); // for decrease volume
  191. EFFECT(volmin); // for minimum volume reached
  192. EFFECT(volmax); // for maximum volume reached
  193. EFFECT(faston); // for EFFECT_FAST_ON
  194. EFFECT(blstbgn); // for Begin Multi-Blast
  195. EFFECT(blstend); // for End Multi-Blast
  196. EFFECT(push); // for Force Push gesture in Battle Mode
  197.  
  198. // The Saber class implements the basic states and actions
  199. // for the saber.
  200. class SaberSA22CButtons : public PropBase {
  201. public:
  202. SaberSA22CButtons() : PropBase() {}
  203. const char* name() override { return "SaberSA22CButtons"; }
  204.  
  205. void Loop() override {
  206. PropBase::Loop();
  207. DetectTwist();
  208. Vec3 mss = fusor.mss();
  209. if (SaberBase::IsOn()) {
  210. DetectSwing();
  211. if (auto_lockup_on_ &&
  212. !swinging_ &&
  213. fusor.swing_speed() > 120 &&
  214. millis() - clash_impact_millis_ > SA22C_LOCKUP_DELAY &&
  215. SaberBase::Lockup()) {
  216. SaberBase::DoEndLockup();
  217. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  218. auto_lockup_on_ = false;
  219. }
  220. if (auto_melt_on_ &&
  221. !swinging_ &&
  222. fusor.swing_speed() > 60 &&
  223. millis() - clash_impact_millis_ > SA22C_LOCKUP_DELAY &&
  224. SaberBase::Lockup()) {
  225. SaberBase::DoEndLockup();
  226. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  227. auto_melt_on_ = false;
  228. }
  229.  
  230. // EVENT_PUSH
  231. if (fabs(mss.x) < 3.0 &&
  232. mss.y * mss.y + mss.z * mss.z > 70 &&
  233. fusor.swing_speed() < 30 &&
  234. fabs(fusor.gyro().x) < 10) {
  235. if (millis() - push_begin_millis_ > SA22C_FORCE_PUSH_LENGTH) {
  236. Event(BUTTON_NONE, EVENT_PUSH);
  237. push_begin_millis_ = millis();
  238. }
  239. } else {
  240. push_begin_millis_ = millis();
  241. }
  242.  
  243. } else {
  244. // EVENT_SWING - Swing On gesture control to allow fine tuning of speed needed to ignite
  245. if (millis() - saber_off_time_ < MOTION_TIMEOUT) {
  246. SaberBase::RequestMotion();
  247. if (swinging_ && fusor.swing_speed() < 90) {
  248. swinging_ = false;
  249. }
  250. if (!swinging_ && fusor.swing_speed() > SA22C_SWING_ON_SPEED) {
  251. swinging_ = true;
  252. Event(BUTTON_NONE, EVENT_SWING);
  253. }
  254. }
  255. // EVENT_THRUST
  256. if (mss.y * mss.y + mss.z * mss.z < 16.0 &&
  257. mss.x > 14 &&
  258. fusor.swing_speed() < 150) {
  259. if (millis() - thrust_begin_millis_ > 15) {
  260. Event(BUTTON_NONE, EVENT_THRUST);
  261. thrust_begin_millis_ = millis();
  262. }
  263. } else {
  264. thrust_begin_millis_ = millis();
  265. }
  266. }
  267. }
  268.  
  269. // Fast On Gesture Ignition
  270. virtual void FastOn() {
  271. if (IsOn()) return;
  272. if (current_style() && current_style()->NoOnOff())
  273. return;
  274. activated_ = millis();
  275. STDOUT.println("Ignition.");
  276. MountSDCard();
  277. EnableAmplifier();
  278. SaberBase::RequestMotion();
  279. // Avoid clashes a little bit while turning on.
  280. // It might be a "clicky" power button...
  281. IgnoreClash(500);
  282. SaberBase::TurnOn();
  283. // Optional effects
  284. SaberBase::DoEffect(EFFECT_FAST_ON, 0);
  285. }
  286.  
  287. // SA22C Volume Menu
  288. void VolumeUp() {
  289. if (dynamic_mixer.get_volume() < VOLUME) {
  290. dynamic_mixer.set_volume(std::min<int>(VOLUME + VOLUME * 0.1,
  291. dynamic_mixer.get_volume() + VOLUME * 0.10));
  292. if (SFX_volup) {
  293. hybrid_font.PlayCommon(&SFX_volup);
  294. } else {
  295. beeper.Beep(0.5, 2000);
  296. }
  297. STDOUT.print("Volume Up - Current Volume: ");
  298. STDOUT.println(dynamic_mixer.get_volume());
  299. } else {
  300. // Cycle through Volume Menu option
  301. #ifdef VOLUME_MENU_CYCLE
  302. if (!max_vol_reached_) {
  303. if (SFX_volmax) {
  304. hybrid_font.PlayCommon(&SFX_volmax);
  305. } else {
  306. beeper.Beep(0.5, 3000);
  307. }
  308. STDOUT.print("Maximum Volume \n");
  309. max_vol_reached_ = true;
  310. } else {
  311. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  312. dynamic_mixer.get_volume() - VOLUME * 0.90));
  313. if (SFX_volmin) {
  314. hybrid_font.PlayCommon(&SFX_volmin);
  315. } else {
  316. beeper.Beep(0.5, 1000);
  317. }
  318. STDOUT.print("Minimum Volume \n");
  319. max_vol_reached_ = false;
  320. }
  321. #else
  322. if (SFX_volmax) {
  323. hybrid_font.PlayCommon(&SFX_volmax);
  324. } else {
  325. beeper.Beep(0.5, 3000);
  326. }
  327. STDOUT.print("Maximum Volume \n");
  328. #endif
  329. }
  330. }
  331.  
  332. void VolumeDown() {
  333. if (dynamic_mixer.get_volume() > (0.10 * VOLUME)) {
  334. dynamic_mixer.set_volume(std::max<int>(VOLUME * 0.1,
  335. dynamic_mixer.get_volume() - VOLUME * 0.10));
  336. if (SFX_voldown) {
  337. hybrid_font.PlayCommon(&SFX_voldown);
  338. } else {
  339. beeper.Beep(0.5, 2000);
  340. }
  341. STDOUT.print("Volume Down - Current Volume: ");
  342. STDOUT.println(dynamic_mixer.get_volume());
  343. } else {
  344. #ifdef VOLUME_MENU_CYCLE
  345. if (!min_vol_reached_) {
  346. if (SFX_volmin) {
  347. hybrid_font.PlayCommon(&SFX_volmin);
  348. } else {
  349. beeper.Beep(0.5, 1000);
  350. }
  351. STDOUT.print("Minimum Volume \n");
  352. min_vol_reached_ = true;
  353. } else {
  354. dynamic_mixer.set_volume(VOLUME);
  355. if (SFX_volmax) {
  356. hybrid_font.PlayCommon(&SFX_volmax);
  357. } else {
  358. beeper.Beep(0.5, 3000);
  359. }
  360. STDOUT.print("Maximum Volume \n");
  361. min_vol_reached_ = false;
  362. }
  363. #else
  364. if (SFX_volmin) {
  365. hybrid_font.PlayCommon(&SFX_volmin);
  366. } else {
  367. beeper.Beep(0.5, 1000);
  368. }
  369. STDOUT.print("Minimum Volume \n");
  370. #endif
  371.  
  372. }
  373. }
  374.  
  375.  
  376.  
  377. // *******************************************************************************
  378. // Scavenger Button Mod Part 1:
  379. void PlaySound(const char* sound) {
  380. RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
  381. if (player) {
  382. if (!player->PlayInCurrentDir(sound))
  383. player->Play(spimd);
  384. }
  385. }
  386. // *******************************************************************************
  387.  
  388.  
  389.  
  390. bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override {
  391. switch (EVENTID(button, event, modifiers)) {
  392. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ON):
  393. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ON):
  394. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON):
  395. if (accel_.x < -0.15) {
  396. pointing_down_ = true;
  397. } else {
  398. pointing_down_ = false;
  399. }
  400. return true;
  401.  
  402.  
  403.  
  404. // *******************************************************************************
  405. // Scavenger Button Mod Part 2:
  406. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY):
  407. PlaySound("press.wav");
  408. return false;
  409. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY):
  410. PlaySound("release.wav");
  411. return false;
  412. // *******************************************************************************
  413.  
  414.  
  415. // Battle Mode
  416. #if NUM_BUTTONS == 3
  417. case EVENTID(BUTTON_AUX2, EVENT_SECOND_HELD, MODE_ON):
  418. #else
  419. case EVENTID(BUTTON_POWER, EVENT_THIRD_HELD, MODE_ON):
  420. #endif
  421. if (!battle_mode_) {
  422. STDOUT.println("Entering Battle Mode");
  423. battle_mode_ = true;
  424. if (SFX_bmbegin) {
  425. hybrid_font.PlayCommon(&SFX_bmbegin);
  426. } else {
  427. hybrid_font.DoEffect(EFFECT_FORCE, 0);
  428. }
  429. } else {
  430. STDOUT.println("Exiting Battle Mode");
  431. battle_mode_ = false;
  432. if (SFX_bmend) {
  433. hybrid_font.PlayCommon(&SFX_bmend);
  434. } else {
  435. beeper.Beep(0.5, 3000);
  436. }
  437. }
  438. return true;
  439.  
  440. // Auto Lockup Mode
  441. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON):
  442. if (!battle_mode_) return false;
  443. clash_impact_millis_ = millis();
  444. swing_blast_ = false;
  445. if (swinging_) return false;
  446. SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL);
  447. auto_lockup_on_ = true;
  448. SaberBase::DoBeginLockup();
  449. return true;
  450.  
  451. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON):
  452. if (!battle_mode_) return false;
  453. clash_impact_millis_ = millis();
  454. swing_blast_ = false;
  455. if (!swinging_) {
  456. if (fusor.angle1() < - M_PI / 4) {
  457. SaberBase::SetLockup(SaberBase::LOCKUP_DRAG);
  458. } else {
  459. SaberBase::SetLockup(SaberBase::LOCKUP_MELT);
  460. }
  461. auto_melt_on_ = true;
  462. SaberBase::DoBeginLockup();
  463. }
  464. return true;
  465.  
  466. // Gesture Controls
  467. #ifdef SA22C_SWING_ON
  468. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_OFF):
  469. // Due to motion chip startup on boot creating false ignition we delay Swing On at boot for 3000ms
  470. if (millis() > 3000) {
  471. FastOn();
  472. #ifdef GESTURE_AUTO_BATTLE_MODE
  473. STDOUT.println("Entering Battle Mode");
  474. battle_mode_ = true;
  475. #endif
  476. }
  477. return true;
  478. #endif
  479.  
  480. #ifdef SA22C_TWIST_ON
  481. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_OFF):
  482. // Delay twist events to prevent false trigger from over twisting
  483. if (millis() - last_twist_ > 2000 &&
  484. millis() - saber_off_time_ > 1000) {
  485. FastOn();
  486. #ifdef GESTURE_AUTO_BATTLE_MODE
  487. STDOUT.println("Entering Battle Mode");
  488. battle_mode_ = true;
  489. #endif
  490. last_twist_ = millis();
  491. }
  492. return true;
  493. #endif
  494.  
  495. #ifdef SA22C_TWIST_OFF
  496. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON):
  497. // Delay twist events to prevent false trigger from over twisting
  498. if (millis() - last_twist_ > 3000) {
  499. Off();
  500. last_twist_ = millis();
  501. saber_off_time_ = millis();
  502. battle_mode_ = false;
  503. }
  504. return true;
  505. #endif
  506.  
  507. #ifdef SA22C_STAB_ON
  508. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_OFF):
  509. if (millis() - saber_off_time_ > 1000) {
  510. FastOn();
  511. #ifdef GESTURE_AUTO_BATTLE_MODE
  512. STDOUT.println("Entering Battle Mode");
  513. battle_mode_ = true;
  514. #endif
  515. }
  516. return true;
  517. #endif
  518.  
  519. #ifdef SA22C_THRUST_ON
  520. case EVENTID(BUTTON_NONE, EVENT_THRUST, MODE_OFF):
  521. if (millis() - saber_off_time_ > 1000) {
  522. FastOn();
  523. #ifdef GESTURE_AUTO_BATTLE_MODE
  524. STDOUT.println("Entering Battle Mode");
  525. battle_mode_ = true;
  526. #endif
  527. }
  528. return true;
  529. #endif
  530.  
  531. #ifdef SA22C_FORCE_PUSH
  532. case EVENTID(BUTTON_NONE, EVENT_PUSH, MODE_ON):
  533. if (FORCE_PUSH_CONDITION &&
  534. millis() - last_push_ > 2000) {
  535. if (SFX_push) {
  536. hybrid_font.PlayCommon(&SFX_push);
  537. } else {
  538. hybrid_font.DoEffect(EFFECT_FORCE, 0);
  539. }
  540. last_push_ = millis();
  541. }
  542. return true;
  543.  
  544. #endif
  545.  
  546. // Saber ON AND Volume Up
  547. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF):
  548. if (!mode_volume_) {
  549. On();
  550. } else {
  551. VolumeUp();
  552. }
  553. return true;
  554.  
  555. case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  556. // 1-button: Next Preset AND Volume Down
  557. #if NUM_BUTTONS == 1
  558. if (!mode_volume_) {
  559. next_preset();
  560. } else {
  561. VolumeDown();
  562. }
  563. return true;
  564. #else
  565. // 2 and 3 button: Start or Stop Track
  566. StartOrStopTrack();
  567. return true;
  568. #endif
  569.  
  570. // 2 and 3 button: Next Preset and Volume Down
  571. case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_SHORT, MODE_OFF):
  572. if (!mode_volume_) {
  573. next_preset();
  574. } else {
  575. VolumeDown();
  576. }
  577. return true;
  578.  
  579. #if NUM_BUTTONS == 3
  580. // 3 button: Previous Preset
  581. case EVENTID(BUTTON_AUX2, EVENT_FIRST_CLICK_SHORT, MODE_OFF):
  582. #else
  583. // 1 and 2 button: Previous Preset
  584. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_OFF):
  585. #endif
  586. if (!mode_volume_) {
  587. previous_preset();
  588. }
  589. return true;
  590.  
  591. // Activate Muted
  592. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF):
  593. if (SetMute(true)) {
  594. unmute_on_deactivation_ = true;
  595. On();
  596. }
  597. return true;
  598.  
  599. // Turn Blade OFF
  600. #if NUM_BUTTONS > 1
  601. // 2 and 3 button
  602. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_MEDIUM, MODE_ON):
  603. #else
  604. // 1 button
  605. case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_ON):
  606. #endif
  607. if (!SaberBase::Lockup()) {
  608. #ifndef DISABLE_COLOR_CHANGE
  609. if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) {
  610. // Just exit color change mode.
  611. // Don't turn saber off.
  612. ToggleColorChangeMode();
  613. return true;
  614. }
  615. #endif
  616. if (!battle_mode_) {
  617. Off();
  618. }
  619. }
  620. saber_off_time_ = millis();
  621. battle_mode_ = false;
  622. swing_blast_ = false;
  623. return true;
  624.  
  625. // 1 button Force and Color Change mode
  626. #if NUM_BUTTONS == 1
  627. case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON | BUTTON_POWER):
  628. #ifndef DISABLE_COLOR_CHANGE
  629. if (accel_.x < -0.15) {
  630. ToggleColorChangeMode();
  631. } else {
  632. SaberBase::DoForce();
  633. }
  634. #else
  635. SaberBase::DoForce();
  636. #endif
  637. return true;
  638. #else
  639. // 2 and 3 button Force effect
  640. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON):
  641. SaberBase::DoForce();
  642. return true;
  643. // 2 and 3 button color change
  644. #ifndef DISABLE_COLOR_CHANGE
  645. case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_SHORT, MODE_ON | BUTTON_POWER):
  646. ToggleColorChangeMode();
  647. return true;
  648. #endif
  649. #endif
  650.  
  651. // Blaster Deflection
  652. #if NUM_BUTTONS == 1
  653. // 1 button
  654. case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  655. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON):
  656. case EVENTID(BUTTON_POWER, EVENT_THIRD_CLICK_SHORT, MODE_ON):
  657. #else
  658. // 2 and 3 button
  659. case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
  660. case EVENTID(BUTTON_AUX, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON):
  661. case EVENTID(BUTTON_AUX, EVENT_THIRD_CLICK_SHORT, MODE_ON):
  662. #endif
  663. swing_blast_ = false;
  664. SaberBase::DoBlast();
  665. return true;
  666.  
  667. // Multi-Blaster Deflection mode
  668. #if NUM_BUTTONS == 1
  669. // 1 button
  670. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER):
  671. #else
  672. // 2 and 3 button
  673. #ifndef SA22C_NO_LOCKUP_HOLD
  674. case EVENTID(BUTTON_AUX, EVENT_SECOND_HELD, MODE_ON):
  675. #else
  676. // in SA22C_NO_LOCKUP_HOLD mode, multi-blaster is triggered by holding aux
  677. // while swinging
  678. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_AUX):
  679. #endif
  680. #endif
  681. swing_blast_ = !swing_blast_;
  682. if (swing_blast_) {
  683. if (SFX_blstbgn) {
  684. hybrid_font.PlayCommon(&SFX_blstbgn);
  685. } else {
  686. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  687. }
  688. } else {
  689. if (SFX_blstend) {
  690. hybrid_font.PlayCommon(&SFX_blstend);
  691. } else {
  692. hybrid_font.SB_Effect(EFFECT_BLAST, 0);
  693. }
  694. }
  695. return true;
  696.  
  697. case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON):
  698. if (swing_blast_) {
  699. SaberBase::DoBlast();
  700. }
  701. return true;
  702.  
  703. // Lockup
  704. #if NUM_BUTTONS == 1
  705. // 1 button lockup
  706. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER):
  707. #else
  708. #ifndef SA22C_NO_LOCKUP_HOLD
  709. // 2 and 3 button lockup
  710. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD, MODE_ON):
  711. #else
  712. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX):
  713. #endif
  714. #endif
  715. if (!SaberBase::Lockup() && !battle_mode_) {
  716. if (pointing_down_) {
  717. SaberBase::SetLockup(SaberBase::LOCKUP_DRAG);
  718. } else {
  719. SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL);
  720. }
  721. swing_blast_ = false;
  722. SaberBase::DoBeginLockup();
  723. return true;
  724. }
  725. break;
  726.  
  727. // Lightning Block
  728. #if NUM_BUTTONS < 3
  729. // 1 and 2 button
  730. case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_ON):
  731. #else
  732. // 3 button
  733. case EVENTID(BUTTON_AUX2, EVENT_FIRST_HELD, MODE_ON):
  734. #endif
  735. if (!battle_mode_) {
  736. SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK);
  737. swing_blast_ = false;
  738. SaberBase::DoBeginLockup();
  739. return true;
  740. }
  741. break;
  742.  
  743. // Melt
  744. case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER):
  745. if (!SaberBase::Lockup() && !battle_mode_) {
  746. SaberBase::SetLockup(SaberBase::LOCKUP_MELT);
  747. swing_blast_ = false;
  748. SaberBase::DoBeginLockup();
  749. return true;
  750. }
  751. break;
  752.  
  753. // Start or Stop Track
  754. #if NUM_BUTTONS == 1
  755. // 1 button
  756. case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF):
  757. StartOrStopTrack();
  758. return true;
  759. #endif
  760.  
  761. case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF):
  762. case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_OFF):
  763. case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_OFF):
  764. SaberBase::RequestMotion();
  765. return true;
  766.  
  767. // Enter Volume MENU
  768. #if NUM_BUTTONS == 1
  769. // 1 button
  770. case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER):
  771. #else
  772. // 2 and 3 button
  773. case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_LONG, MODE_OFF):
  774. #endif
  775. if (!mode_volume_) {
  776. mode_volume_ = true;
  777. if (SFX_vmbegin) {
  778. hybrid_font.PlayCommon(&SFX_vmbegin);
  779. } else {
  780. beeper.Beep(0.5, 3000);
  781. }
  782. STDOUT.println("Enter Volume Menu");
  783. } else {
  784. mode_volume_ = false;
  785. if (SFX_vmend) {
  786. hybrid_font.PlayCommon(&SFX_vmend);
  787. } else {
  788. beeper.Beep(0.5, 3000);
  789. }
  790. STDOUT.println("Exit Volume Menu");
  791. }
  792. return true;
  793.  
  794. // Battery level
  795. #if NUM_BUTTONS == 1
  796. // 1 button
  797. case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
  798. #else
  799. // 2 and 3 button
  800. case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD_LONG, MODE_OFF):
  801. #endif
  802. talkie.SayDigit((int)floorf(battery_monitor.battery()));
  803. talkie.Say(spPOINT);
  804. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 10)) % 10);
  805. talkie.SayDigit(((int)floorf(battery_monitor.battery() * 100)) % 10);
  806. talkie.Say(spVOLTS);
  807. return true;
  808.  
  809. #ifdef BLADE_DETECT_PIN
  810. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_ON):
  811. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_OFF):
  812. // Might need to do something cleaner, but let's try this for now.
  813. blade_detected_ = true;
  814. FindBladeAgain();
  815. SaberBase::DoBladeDetect(true);
  816. return true;
  817.  
  818. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_ON):
  819. case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_OFF):
  820. // Might need to do something cleaner, but let's try this for now.
  821. blade_detected_ = false;
  822. FindBladeAgain();
  823. SaberBase::DoBladeDetect(false);
  824. return true;
  825. #endif
  826.  
  827. // Events that needs to be handled regardless of what other buttons
  828. // are pressed.
  829. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  830. case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  831. case EVENTID(BUTTON_AUX2, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
  832. if (SaberBase::Lockup()) {
  833. SaberBase::DoEndLockup();
  834. SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
  835. return true;
  836. }
  837. }
  838. return false;
  839. }
  840.  
  841. void SB_Effect(EffectType effect, float location) override {
  842. switch (effect) {
  843. case EFFECT_POWERSAVE:
  844. if (SFX_dim) {
  845. hybrid_font.PlayCommon(&SFX_dim);
  846. } else {
  847. beeper.Beep(0.5, 3000);
  848. }
  849. return;
  850. case EFFECT_BATTERY_LEVEL:
  851. if (SFX_battery) {
  852. hybrid_font.PlayCommon(&SFX_battery);
  853. } else {
  854. beeper.Beep(0.5, 3000);
  855. }
  856. return;
  857. case EFFECT_FAST_ON:
  858. if (SFX_faston) {
  859. hybrid_font.PlayCommon(&SFX_faston);
  860. }
  861. return;
  862.  
  863. default: break; // avoids compiler warning
  864. }
  865. }
  866.  
  867. private:
  868. bool pointing_down_ = false;
  869. bool swing_blast_ = false;
  870. bool mode_volume_ = false;
  871. bool auto_lockup_on_ = false;
  872. bool auto_melt_on_ = false;
  873. bool battle_mode_ = false;
  874. bool max_vol_reached_ = false;
  875. bool min_vol_reached_ = false;
  876. uint32_t thrust_begin_millis_ = millis();
  877. uint32_t push_begin_millis_ = millis();
  878. uint32_t clash_impact_millis_ = millis();
  879. uint32_t last_twist_ = millis();
  880. uint32_t last_push_ = millis();
  881. uint32_t saber_off_time_ = millis();
  882. };
  883.  
  884. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement