If it is any help, this is what I was working on:
/*
blaster_BC_buttons.h prop file.
http://fredrik.hubbe.net/lightsaber/proffieos.html
Copyright (c) 2016-2023 Fredrik Hubinette
Fredrik Hubinette, Fernando da Rosa, Brian Conner, Matthew McGeary,
Scott Weber and Alejandro Belluscio.
Distributed under the terms of the GNU General Public License v3.
http://www.gnu.org/licenses/
This prop file makes full use soundfont and display specification, while keeping features to a minimum
TODO:
-Do Range change the fire sound.
-Add ammo limitation to auto.
-Teach prop about OLED: PLI, Shot counter, battery, etc.
Functionality:
-------------------------------------------------------------------------------
* PROP DEFINES *
Optional #defines that customize the blaster's behavior.
-------------------------------------------------------------------------------
General Defines:
#define PROFFIEOS_VERBOSITY 2 - 0-5 range. Sets the output verbosity.
0: no printouts
1: essential printouts
2: good-to-know printouts
3: debug printouts
4: verbose printouts
5: spammy printouts
Optional defines:
#define ENABLE_BLASTER_AUTO - DEPRECATED. Enable Autofire/rapid fire mode. Please replace with BLASTER_ENABLE_AUTO.
#define BLASTER_ENABLE_AUTO - Enable Autofire/rapid fire mode.
#define BLASTER_DEFAULT_MODE - Sets the mode at startup MODE_STUN|MODE_KILL|MODE_AUTO.
#define BLASTER_DEFAULT_POWER_STATE - Sets the state at startup as ON|OFF|SOUNDFONT (dependent on poweron.wav presence). Defaults to SOUNDFONT.
#define BLASTER_RANGE_LEVELS - Sets the steps of Range/Power levels, also used to define PLI steps. Should be 1 to 99. Defaults to 6.
#define BLASTER_RANGE_LEVELS_BY_FONT - Sets the steps of Range/Power levels according to each fonts number of rangexx.wavs.
#define BLASTER_SHOTS_UNTIL_EMPTY 15 - Whatever number, not defined = unlimited shots.
#define BLASTER_AUTO_LIMITED_ROUNDS - When enabled, AUTO mode respects the round limit set by BLASTER_SHOTS_UNTIL_EMPTY.
#define BLASTER_JAM_PERCENTAGE - Range 0-100 percent. If this is not defined, random from 0-100%.
#define BLASTER_SINGLE_POWER_BUTTON - Only Power Button will turn on/off the blaster.
#define BLASTER_SINGLE_RELOAD_BUTTON - Only Reload Button will reload the blaster. Mutually exclusive with BLASTER_RELOAD_THROUGH_CLIP.
#define BLASTER_RELOAD_THROUGH_CLIP - Only Clip Out then Clip In will reload the blaster. Mutually exclusive BLASTER_SINGLE_RELOAD_BUTTON.
#define BLASTER_CLIP_OUT_BLOCK - Clip Out will block blaster even without BLASTER_SHOTS_UNTIL_EMPTY.
-------------------------------------------------------------------------------
* PROP BUTTONS *
This prop manages up to six different buttons.
-------------------------------------------------------------------------------
*Single Button Mode*
-Buttons: FIRE
This case quite limited since you can only fire and reload. Weapon will always
be on the default mode (STUN is the defined in the prop, if you wish another
you will have to define BLASTER_DEFAULT_MODE). Blaster can be turned on or off.
And can be reloaded, which takes precedence over turning it on/off.
Default Mode: Fire or Stun
Fire - Click FIRE.
Power On / Off - Hold FIRE.
Reload - Hold FIRE until Reloaded. Takes priority over power on/off.
Unjam - Bang the blaster.
Default Mode: Auto *This mode is not compatible with clip capacity and really needs
an on/off switch on the power line.
Fire (Semi) - Click FIRE.
Fire (Auto) - Hold FIRE.
Power On - Hold FIRE. You can't power off.
Unjam - Bang the blaster.
*Dual Buttons Mode*
-Buttons: FIRE and MODE
This is the "stock" configuration.
-Weapon will always start on the default mode (define with BLASTER_DEFAULT_MODE,
STUN is default).
Default is to powered on if it finds poweron.wav file present or off otherwise.
Use BLASTER_DEFAULT_POWERON_STATE to define a different behavior.
Fire - Click FIRE.
Cycle Modes - Click MODE.
Next Preset - Long click and release MODE.
Previous Preset - Double click and hold MODE, release after a second.
Reload - Hold MODE until Reloaded.
Start/Stop Track - Double click MODE.
Unjam - Bang the blaster.
*Extra Buttons*
-Button: POWER
Power On / Off - Click POWER.
-Button: RELOAD
You can make this the only button to reload by defining BLASTER_SINGLE_RELOAD_BUTTON.
Reload - Hold RELOAD until Reloaded.
-Button: CLIP
You can make that shooting will be blocked when the clip is out by defining
define BLASTER_CLIP_OUT_BLOCK.
You can make that you only reload through the clip by defining
BLASTER_RELOAD_THROUGH_CLIP (takes precedence over BLASTER_SINGLE_RELOAD_BUTTON).
Clip In - Latch CLIP
Clip Out - Unlatch CLIP
-Button: RANGE
You have to define the number of levels by
Increase Range - Click RANGE.
Decrease Range - Long click RANGE.
-------------------------------------------------------------------------------
* PROP SOUNDS *
This prop manages the following sounds.
-------------------------------------------------------------------------------
bgnauto Played when auto fire starts.
auto Played while auto fire is going.
endauto Played when auto fire ends.
blast Is the semi-automatic fire sound. You can have as many as you want.
boot Played when ProffieOS boots up.
clipin Sound made when inserting a clip.
clipout Sound made when dropping a clip.
empty Sound when the weapon is out of rounds.
font Name of the preset.
full Sound made when the weapon is full of ammo.
hum Constant sound looping while not firing.
jam Sound made when the weapon jamed.
unjam Sound made when unjamming the blaster.
mode Sound made when switching mode (if mdkill, mdstun and/or mdauto not present).
plioff Played while retracting the PLI bargraph.
plion Played while extending the PLI bargraph.
poweron If this file is present, the blaster will start once it is turned on. If not, you will need a Power button to power it on.
range Sounds of increasing weapon range/power.
stun Firing sound for stun mode.
reload Reloading sound.
mdkill Sound made when switching to KILL mode
mdstun Sound made when switching to STUN mode
mdauto Sound made when switching to AUTO mode
-------------------------------------------------------------------------------
* PROP EFFECTS *
This prop enables the following EFFECTs for use in styles
-------------------------------------------------------------------------------
EFFECT_RANGE_MAXIMUM
EFFECT_RANGE_MINIMUM
EFFECT_RANGE_UP
EFFECT_RANGE_DOWN
Already defined in SaberBase
EFFECT_CLIP_IN
EFFECT_CLIP_OUT
EFFECT_RELOAD
EFFECT_JAM
EFFECT_UNJAM
EFFECT_NONE
EFFECT_BLAST
EFFECT_BOOT
EFFECT_LOCKUP_BEGIN
EFFECT_LOCKUP_END
EFFECT_PREON
EFFECT_POSTOFF
EFFECT_ON
EFFECT_FAST_ON
EFFECT_OFF
EFFECT_FAST_OFF
*/
#ifndef PROPS_BLASTER_BALDUSI_H
#define PROPS_BLASTER_BALDUSI_H
#ifndef PROFFIEOS_VERBOSITY
#define PROFFIEOS_VERBOSITY 2 /* range 0 - 5 */
#endif
#ifndef BLASTER_DEFAULT_MODE
#define BLASTER_DEFAULT_MODE MODE_STUN
#endif
#ifndef BLASTER_DEFAULT_POWER_STATE
#define BLASTER_DEFAULT_POWER_STATE SOUNDFONT
#endif
#ifndef BLASTER_RANGE_LEVELS
#define BLASTER_RANGE_LEVELS 6
#endif
#if NUM_BUTTONS < 1
#error /props/blaster_baldusi.h requires 1 or more Buttons for operation
#endif
#include "prop_base.h"
#include "../sound/sound_library.h"
#define PROP_TYPE Blaster_Baldusi
#define PROP_HAS_BULLET_COUNT
EFFECT(clipin);
EFFECT(clipins); // s for stun mode
EFFECT(clipout);
EFFECT(clipouts); // s for stun mode
EFFECT(empty);
EFFECT(full);
EFFECT(jam);
EFFECT(mode);
EFFECT(plioff);
EFFECT(plion);
EFFECT(range);
EFFECT(rangemax);
EFFECT(rangemin);
EFFECT(rangeup);
EFFECT(rangedwn);
EFFECT(reload);
EFFECT(reloads); // s for stun mode
EFFECT(stun);
EFFECT(unjam);
EFFECT(mdstun);
EFFECT(mdkill);
EFFECT(mdauto);
//Effects defined in SaberBase
//EFFECT(bgnauto)
//EFFECT(auto)
//EFFECT(endauto)
//EFFECT(hum)
//EFFECT()
//EFFECT()
//EFFECT()
//EFFECT()
//EFFECT()
/* Blaster effects defined in SaberBase
DEFINE_EFFECT(STUN)
DEFINE_EFFECT(FIRE)
DEFINE_EFFECT(CLIP_IN)
DEFINE_EFFECT(CLIP_OUT)
DEFINE_EFFECT(RELOAD)
DEFINE_EFFECT(MODE)
DEFINE_EFFECT(RANGE)
DEFINE_EFFECT(EMPTY)
DEFINE_EFFECT(FULL)
DEFINE_EFFECT(JAM)
DEFINE_EFFECT(UNJAM)
DEFINE_EFFECT(PLI_ON)
DEFINE_EFFECT(PLI_OFF)
*/
//EFFECT_RANGE_MAX
//EFFECT_RANGE_MIN
//EFFECT_RANGE_INCREASE
//EFFECT_RANGE_DECREASE
class Blaster_Baldusi : public PROP_INHERIT_PREFIX PropBase {
public:
Blaster_Baldusi() : PropBase() {}
const char* name() override { return "Blaster_Baldusi"; }
// Mode states to handle kill vs stun effects
enum BlasterMode {
MODE_STUN = 0,
MODE_KILL = 1,
MODE_AUTO = 2
};
// Set default power state.
enum BlasterInitialPowerState {
ON = 0,
OFF = 1,
SOUNDFONT=2
};
#if defined (BLASTER_SINGLE_RELOAD_BUTTON) && defined (BLASTER_RELOAD_THROUGH_CLIP)
#error "BLASTER_SINGLE_RELOAD_BUTTON and BLASTER_RELOAD_THROUGH_CLIP are mutually exclusive."
#endif
#if NUM_BUTTONS == 1 && !(defined (ENABLE_BLASTER_AUTO) || defined (BLASTER_ENABLE_AUTO))
static_assert(BLASTER_DEFAULT_MODE != MODE_AUTO,
"BLASTER_DEFAULT_MODE cannot be MODE_AUTO without BLASTER_ENABLE_AUTO in Single Button configuration.");
#endif
#if NUM_BUTTONS == 1 && (defined (BLASTER_ENABLE_AUTO) || defined (ENABLE_BLASTER_AUTO))
static_assert(BLASTER_DEFAULT_MODE == MODE_AUTO,
"Single Button Auto mode requires BLASTER_DEFAULT_MODE = MODE_AUTO");
#endif
BlasterMode blaster_mode = BLASTER_DEFAULT_MODE;
BlasterInitialPowerState initial_power_state = BLASTER_DEFAULT_POWER_STATE;
int shots_fired_ = 0;
bool auto_firing_ = false;
bool is_jammed_ = false;
bool empty_ = false;
bool clip_present_ = true;
int previous_range_ = 1;
int current_range_ = 1;
int maximum_range_ = BLASTER_RANGE_LEVELS;
bool stun_mode_ = true;
#ifdef BLASTER_SHOTS_UNTIL_EMPTY
const int max_shots_ = BLASTER_SHOTS_UNTIL_EMPTY;
#else
const int max_shots_ = -1;
#endif
virtual void SetBlasterMode(BlasterMode to_mode) {
if (!auto_firing_) {
blaster_mode = to_mode;
SaberBase::DoEffect(EFFECT_MODE, 0);
}
}
virtual void NextBlasterMode() {
switch(blaster_mode) {
case MODE_STUN:
stun_mode_ = false;
SetBlasterMode(MODE_KILL);
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Mode set to: MODE_KILL");
#endif
return;
case MODE_KILL:
#if defined (ENABLE_BLASTER_AUTO) || defined (BLASTER_ENABLE_AUTO)
stun_mode_ = false;
SetBlasterMode(MODE_AUTO);
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Mode set to: MODE_AUTO");
#endif
#else
stun_mode_ = true;
SetBlasterMode(MODE_STUN);
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Mode set to: MODE_STUN");
#endif
#endif
return;
case MODE_AUTO:
stun_mode_ = true;
SetBlasterMode(MODE_STUN);
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Mode set to: MODE_STUN");
#endif
return;
}
}
virtual int GetBulletCount() {
return max_shots_ - shots_fired_;
}
virtual bool CheckJam(int percent) {
int random = rand() % 100;
if (random < percent) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Effect: JAM");
#endif
return 1;
}
return 0;
//return random < percent;
}
virtual void Fire() {
#ifdef ENABLE_MOTION
#ifdef BLASTER_JAM_PERCENTAGE
// If we're already jammed then we don't need to recheck. If we're not jammed then check if we just jammed.
is_jammed_ = is_jammed_ ? true : CheckJam(BLASTER_JAM_PERCENTAGE);
if (is_jammed_) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Effect: JAMMED");
#endif
SaberBase::DoEffect(EFFECT_JAM, 0);
return;
}
#endif
#endif
#ifdef BLASTER_CLIP_OUT_BLOCK
if ((max_shots_ != -1 && shots_fired_ >= max_shots_)|| clip_present_ == false ) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Effect: EMPTY or CLIP OUT");
#endif
#else
if (max_shots_ != -1 && shots_fired_ >= max_shots_) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Effect: EMPTY");
#endif
#endif
SaberBase::DoEffect(EFFECT_EMPTY, 0);
return;
}
if (blaster_mode == MODE_AUTO) {
// !!!!!It would be desirable to have the option to limit the amount of total shots, even in auto!!!
SelectAutoFirePair(); // Set up the autofire pairing if the font suits it.
SaberBase::SetLockup(LOCKUP_AUTOFIRE);
#if PROFFIEOS_VERBOSITY - 0 >= 4
STDOUT.println("Action: AUTO Fire");
#endif
SaberBase::DoBeginLockup();
auto_firing_ = true;
} else {
if (blaster_mode == MODE_STUN) {
#if PROFFIEOS_VERBOSITY - 0 >= 4
STDOUT.println("Action: STUN");
#endif
SaberBase::DoEffect(EFFECT_STUN, 0);
} else {
#if PROFFIEOS_VERBOSITY - 0 >= 4
STDOUT.println("Action: FIRE");
#endif
SaberBase::DoEffect(EFFECT_FIRE, 0);
}
shots_fired_++;
}
}
virtual void SelectAutoFirePair() {
if (!SFX_auto.files_found() || !SFX_blast.files_found()) return;
int autoCount = SFX_auto.files_found();
int blastCount = SFX_blast.files_found();
int pairSelection;
// If we don't have a matched pair of autos and blasts, then don't override the sequence to get a matched pair.
if (autoCount == blastCount) {
pairSelection = rand() % autoCount;
SFX_auto.Select(pairSelection);
SFX_blast.Select(pairSelection);
}
}
virtual void Reload() {
shots_fired_ = 0;
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: RELOAD");
#endif
SaberBase::DoEffect(EFFECT_RELOAD, 0);
SaberBase::DoEffect(EFFECT_FULL, 0);
}
// !!! Should clip out prevent firing even when infinite rounds? I think yes.
virtual void ClipOut() {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: CLIP_OUT");
#endif
if (max_shots_ != -1) shots_fired_ = max_shots_;
clip_present_ = false;
SaberBase::DoEffect(EFFECT_CLIP_OUT, 0);
}
virtual void ClipIn() {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: CLIP_IN");
#endif
clip_present_ = true;
SaberBase::DoEffect(EFFECT_CLIP_IN, 0);
#if defined (BLASTER_RELOAD_THROUGH_CLIP)
if (max_shots_ != -1) shots_fired_ = 0;
SaberBase::DoEffect(EFFECT_FULL, 0);
#endif
}
virtual void IncreaseRange() {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Increase RANGE");
#endif
previous_range_ = current_range_;
if (current_range_ < maximum_range_ ) {
current_range_++;
}
SaberBase::DoEffect(EFFECT_RANGE, 0);
}
virtual void DecreaseRange() {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Decrease RANGE");
#endif
previous_range_ = current_range_;
if (current_range_ > 1) {
current_range_--;
}
SaberBase::DoEffect(EFFECT_RANGE, 0);
}
// Pull in parent's SetPreset, but turn the blaster on.
// Still keeping it to default off.
void SetPreset(int preset_num, bool announce) override {
PropBase::SetPreset(preset_num, announce);
#ifdef BLASTER_RANGE_LEVELS_BY_FONT
if (SFX_range) {
maximum_range_ = SFX_range.files_found();
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.print("Action: range.wav found. Setting MAX_RANGE as:");
STDOUT.println(maximum_range_);
#endif
} else {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: range.wav not found. Setting MAX_RANGE as 1");
#endif
maximum_range_ = 1;
}
#endif
switch (initial_power_state) {
case ON:
if (!SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Blaster ON.");
#endif
On();
}
case OFF:
if (SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Blaster OFF.");
#endif
Off();
}
case SOUNDFONT:
if (!SFX_poweron) {
if (!SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: poweron.wav found. Setting Blaster ON.");
#endif
On();
}
}
}
/* #if (defined BLASTER_DEFAULT_POWER && BLASTER_DEFAULT_POWER_STATE == ON)
if (!SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Blaster ON.");
#endif
On();
}
#elif (defined BLASTER_DEFAULT_POWER && BLASTER_DEFAULT_POWER_STATE == OFF)
if (SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Blaster OFF.");
#endif
Off();
}
#else
if (!SFX_poweron) {
if (!SaberBase::IsOn()) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: poweron.wav found. Setting Blaster ON.");
#endif
On();
}
#endif */
}
void LowBatteryOff() override {
if (SFX_poweron) {
PropBase::LowBatteryOff();
}
}
// Make clash do nothing except unjam if jammed.
void Clash(bool stab, float strength) override {
if (is_jammed_) {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: UNJAM\n");
#endif
is_jammed_ = false;
SaberBase::DoEffect(EFFECT_UNJAM, 0);
}
}
// Make swings do nothing
void DoMotion(const Vec3& motion, bool clear) override {
PropBase::DoMotion(Vec3(0), clear);
}
bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override {
switch (EVENTID(button, event, modifiers)) {
//-------------------------------------------------------------------------
// #### SINGLE BUTTON (FIRE) CASE
//-------------------------------------------------------------------------
#if NUM_BUTTONS == 1 && (defined (BLASTER_ENABLE_AUTO) || defined (ENABLE_BLASTER_AUTO))
case EVENTID(BUTTON_FIRE, EVENT_PRESSED, MODE_OFF):
On();
return true;
case EVENTID(BUTTON_FIRE, EVENT_PRESSED, MODE_ON):
Fire();
return true;
case EVENTID(BUTTON_FIRE, EVENT_RELEASED, MODE_ON):
if (blaster_mode == MODE_AUTO) {
if (SaberBase::Lockup()) {
SaberBase::DoEndLockup();
SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
auto_firing_ = false;
}
}
return true;
#elif (NUM_BUTTONS == 1)
case EVENTID(BUTTON_FIRE, EVENT_CLICK_SHORT, MODE_ON):
Fire();
return true;
case EVENTID(BUTTON_FIRE, EVENT_HELD, MODE_ON):
if(max_shots_ != -1 && shots_fired_ >= max_shots_) {
Reload();
} else {
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Power OFF");
#endif
Off();
};
return true;
case EVENTID(BUTTON_FIRE, EVENT_HELD, MODE_OFF):
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Power ON");
#endif
On();
return true;
//-------------------------------------------------------------------------
// #### MULTI BUTTON CASE
//-------------------------------------------------------------------------
#else
case EVENTID(BUTTON_MODE_SELECT, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON):
NextBlasterMode();
return true;
case EVENTID(BUTTON_MODE_SELECT, EVENT_FIRST_CLICK_LONG, MODE_ON):
next_preset();
return true;
case EVENTID(BUTTON_MODE_SELECT, EVENT_SECOND_CLICK_LONG, MODE_ON):
previous_preset();
return true;
#ifndef BLASTER_RELOAD_THROUGH_CLIP
case EVENTID(BUTTON_RELOAD, EVENT_PRESSED, MODE_ON):
#ifndef BLASTER_SINGLE_RELOAD_BUTTON
case EVENTID(BUTTON_MODE_SELECT, EVENT_HELD_MEDIUM, MODE_ON):
#endif
Reload();
return true;
#endif
case EVENTID(BUTTON_MODE_SELECT, EVENT_DOUBLE_CLICK, MODE_ON):
StartOrStopTrack();
return true;
case EVENTID(BUTTON_FIRE, EVENT_CLICK_SHORT, MODE_ON):
Fire();
return true;
case EVENTID(BUTTON_FIRE, EVENT_HELD, MODE_ON):
Fire();
return true;
case EVENTID(BUTTON_FIRE, EVENT_RELEASED, MODE_ON):
if (blaster_mode == MODE_AUTO) {
if (SaberBase::Lockup()) {
SaberBase::DoEndLockup();
SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
auto_firing_ = false;
}
}
return true;
//-----------------------------------------------------------------------
//POWER Button
//-----------------------------------------------------------------------
// In the event of the presence of a power button, let it control the power on events.
case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF):
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Power ON");
#endif
On();
return true;
case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ON):
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Action: Power OFF");
#endif
Off();
return true;
//-----------------------------------------------------------------------
//CLIP_DETECT Button
//-----------------------------------------------------------------------
case EVENTID(BUTTON_CLIP_DETECT, EVENT_PRESSED, MODE_ON):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_PRESSED, MODE_OFF):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_LATCH_ON, MODE_ON):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_LATCH_ON, MODE_OFF):
ClipIn();
return true;
case EVENTID(BUTTON_CLIP_DETECT, EVENT_RELEASED, MODE_ON):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_RELEASED, MODE_OFF):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_LATCH_OFF, MODE_ON):
case EVENTID(BUTTON_CLIP_DETECT, EVENT_LATCH_OFF, MODE_OFF):
ClipOut();
return true;
//-----------------------------------------------------------------------
//RANGE Button
//-----------------------------------------------------------------------
// In the event of the presence of a power button, let it control the power on events.
case EVENTID(BUTTON_RANGE, EVENT_CLICK_SHORT, MODE_ON):
IncreaseRange();
return true;
case EVENTID(BUTTON_RANGE, EVENT_CLICK_LONG, MODE_ON):
DecreaseRange();
return true;
#endif
#ifdef BLADE_DETECT_PIN
case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_OFF):
// Might need to do something cleaner, but let's try this for now.
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Event: Blade DETECT");
#endif
blade_detected_ = true;
FindBladeAgain();
SaberBase::DoBladeDetect(true);
return true;
case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_OFF):
// Might need to do something cleaner, but let's try this for now.
#if PROFFIEOS_VERBOSITY - 0 >= 3
STDOUT.println("Event: NO Blade");
#endif
blade_detected_ = false;
FindBladeAgain();
SaberBase::DoBladeDetect(false);
return true;
#endif
}
return false;
}
// Blaster effects, auto fire is handled by begin/end lockup
void SB_Effect(EffectType effect, float location) override {
switch (effect) {
default: return;
case EFFECT_STUN: hybrid_font.PlayCommon(&SFX_stun); return;
case EFFECT_FIRE: hybrid_font.PlayCommon(&SFX_blast); return;
case EFFECT_CLIP_IN:
if (stun_mode_ && SFX_clipins) {
hybrid_font.PlayCommon(&SFX_clipins); return;
} else {
hybrid_font.PlayCommon(&SFX_clipin); return;
}
case EFFECT_CLIP_OUT:
if (stun_mode_ && SFX_clipouts) {
hybrid_font.PlayCommon(&SFX_clipouts); return;
} else {
hybrid_font.PlayCommon(&SFX_clipout); return;
}
case EFFECT_RELOAD:
if (stun_mode_ && SFX_reloads) {
hybrid_font.PlayCommon(&SFX_reloads); return;
} else {
hybrid_font.PlayCommon(&SFX_reload); return;
}
case EFFECT_MODE: SayMode(); return;
case EFFECT_RANGE: SayRange(); return;
case EFFECT_EMPTY: hybrid_font.PlayCommon(&SFX_empty); return;
case EFFECT_FULL: hybrid_font.PlayCommon(&SFX_full); return;
case EFFECT_JAM: hybrid_font.PlayCommon(&SFX_jam); return;
case EFFECT_UNJAM: hybrid_font.PlayCommon(&SFX_unjam); return;
case EFFECT_PLI_ON: hybrid_font.PlayCommon(&SFX_plion); return;
case EFFECT_PLI_OFF: hybrid_font.PlayCommon(&SFX_plioff); return;
case EFFECT_RANGE_MAXIMUM: hybrid_font.PlayCommon(&SFX_rangemax); return;
case EFFECT_RANGE_MINIMUM: hybrid_font.PlayCommon(&SFX_rangemin); return;
case EFFECT_RANGE_UP: hybrid_font.PlayCommon(&SFX_rangeup); return;
case EFFECT_RANGE_DOWN: hybrid_font.PlayCommon(&SFX_rangedwn); return;
}
}
void SayMode() {
switch (blaster_mode) {
case MODE_STUN:
if (SFX_mdstun) {
hybrid_font.PlayCommon(&SFX_mdstun);
} else if (SFX_mode) {
hybrid_font.PlayCommon(&SFX_mode);
} else {
talkie.Say(spSTUN);
}
break;
case MODE_KILL:
if (SFX_mdkill) {
hybrid_font.PlayCommon(&SFX_mdkill);
} else if (SFX_mode) {
hybrid_font.PlayCommon(&SFX_mode);
} else {
talkie.Say(spKILL);
}
break;
case MODE_AUTO:
if (SFX_mdauto) {
hybrid_font.PlayCommon(&SFX_mdauto);
} else if (SFX_mode) {
hybrid_font.PlayCommon(&SFX_mode);
} else {
talkie.Say(spAUTOFIRE);
}
break;
}
}
void SayRange() {
if (SFX_range || SFX_range.files_found() >= maximum_range_) {
SFX_range.Select(current_range_ - 1);
hybrid_font.PlayCommon(&SFX_range);
} else if ( SFX_rangemax && SFX_rangemin && SFX_rangeup && SFX_rangedwn) {
if (current_range_ == maximum_range_) {
hybrid_font.PlayCommon(&SFX_rangemax);
} else if (current_range_ == 1) {
hybrid_font.PlayCommon(&SFX_rangemin);
} else if (previous_range_<current_range_) {
hybrid_font.PlayCommon(&SFX_rangeup);
} else {
hybrid_font.PlayCommon(&SFX_rangedwn);
}
} else {
talkie.Say(spRANGE);
talkie.SayNumber(current_range_);
}
};
};
#endif