Blaster_Baldusi

@profezzorn On a separate note: couldn’t we put some registry code in the ButtonBase creator so that it registers on some general variable the presence of such button? Some very simple object with just two methods:

class ButtonRegistry {

private uint32_t buttonRegistry=0;

void RegisterButton (uint32_t button) {
  buttonRegistry |= button;
}

boolean IsRegistered (uint32_t button) {
    if (button &= buttonRegistry ) {
      return true;
   } else {
      return false;
   }
}

I’m horrible at bitwise operations, but this is the pseudo code, if you will.

We can initialize the ButtonRegistry object and then add the register function to the BaseButton constructor. That should allow us to know if any button is present, right?

I would just do:

if (SFX_range) {
  SFX_range.Select(current_range * SFX_range.files_found() / MAX_RANGE);
  hybrid_font.Play(&SFX_range);
}

Or possibly:

if (SFX_range.files_found() == MAX_RANGE) {
  SFX_range.Select(current_range_);
  hybrid_font.Play(&SFX_range);
}

You don’t have to worry about the “alt” directories. Each alt directory MUST have the same filenames in it.

That would in fact be fairly easy to do.
We already have something similar in the “current_modifiers” which is used to keep track of which buttons are currently pressed.

I’m not sure I follow. The range files might be more or less than MAX_RANGE. If my current_range_ is 5, I need range05.wav (or a variation) but can’t get range04 nor range06. So, if there are rangeXX wavs 01 to 16, but I only have 6 defined ranges, unless I’m misreading your code, I would be getting bigger numbers than what I want.
Conversely, if I had less than MAX_RANGE I would be getting lower numbers. The way I’m writing my code, is that if the user is increasing range and there’s not the specific range wav, I will try to use a rangeup.wav and if that’s missing, then I will use talkie.

So if MAX_RANGE is 10, but you have 6 files, then what do you do?
I think you should make sure it works for all the ranges rather than just the current one so that it’s consistent.

Maybe what you want is:

if (SFX_range.files_found() >= MAX_RANGE) {
   SFX_range.Select(current_range_);
  hybrid_font.Play(&SFX_range);
}

?

Well, the idea is that the range/power level is defined by the config, probably because it is a multiple of the PLI pixel number. So I want to let the installer determine the range maximum levels and try to do the sanest thing given whatever the soundfont offers. I’m settling for this code. Please tell me if you like it:

void SayRange() {
    if (SFX_range.files_found() >=current_range_) {
        SFX_range.Select(current_range_);
        hybrid_font.PlayCommon(&SFX_range);
    } else if (current_range_ == BLASTER_RANGE_LEVELS) {
        if (SFX_rangemax) {
          hybrid_font.PlayCommon(&SFX_rangemax);
        } else {
          talkie.Say(spRANGE);
          talkie.Say(spSTOP);
        }
    } else if (current_range_ == 1) {
        if (SFX_rangemin) {
          hybrid_font.PlayCommon(&SFX_rangemin);
        } else {
          talkie.Say(spRANGE);
          talkie.Say(spSTOP);
        }
    } else if (previous_range_>current_range_) {
        if (SFX_rangeup) {
          hybrid_font.PlayCommon(&SFX_rangeup);
        } else {
          talkie.Say(spRANGE);
          talkie.Say(spUP);
        }
    } else {
        if (SFX_rangedwn) {
          hybrid_font.PlayCommon(&SFX_rangedwn);
        } else {
          talkie.Say(spRANGE);
          talkie.Say(spDOWN);
      }
    }
  };

If there is the rangeXX.wav, it will use it. If there isn’t, then we fall back to telling if it is at max, at min, going up or down. And if those are not there either, then use talkie for that info. Or could use talkie with the digits, too. Either is fine with me. But it has enough fallbacks to do something reasonable.

I tested it, and it works. I was off-by-one because SFF_range.Select() counts from 0 and I count from 1 (both of us have good reasons). And I had to swap a sign so up actually falls back to UP and not vice versa. But seems to be working nice.

I think the code should either use rangeXX.wav for all the ranges, or none of them, not switch in the middle.

Well, I’m in the process of offering the BLASTER_RANGE_LEVELS_BY_FONT. But I’m stuck at initialization.

class Blaster_Baldusi : public PROP_INHERIT_PREFIX PropBase {
public:
  Blaster_Baldusi() : PropBase() {}
  const char* name() override { return "Blaster_Baldusi"; }
[...]

  int previous_range_ = 1;
  int current_range_ = 1;
  #ifdef BLASTER_RANGE_LEVELS_BY_FONT
    int maximum_range_ = max(1, SFX_range.files_found());
  #else
    int maximum_range_ = BLASTER_RANGE_LEVELS;
  #endif
  bool stun_mode_ = true;
  

And I always get a 0. Clearly I’m not initializing SFX_range like it’s supposed too.

On the issue of using all the font or none at all, I can rewrite it.

Why not just do:

#define BLASTER_RANGE_LEVELS SFX_range.files_found()

?

The prop is is initialized ONCE, and that happens before we decide which font to use, so the number of files isn’t known at that time. Also, it will change if/when we change font.

I have the problem of bootstrapping that value. Because for changing fonts it makes use of the next_preset() and previous_preset() methods that I assume are inherited from PropBase. I can put that line after that call. What I don’t know is how to get to define it at instantiation time.

Oh! You mean to just put the define in the IF statement. Duh! thanks for the tip.

Ok, I’ve done the define and it works pretty nicely. But when there is no rangexx.wav in the font, I get a No sounds found: range error and my handling code does not seems to work.

Well what do you want to happen if range isn’t found?
How does your code actually implement that?

Never mind, I’ve rewritten in a more traditional way taking the values at preset initialization. Now I simply do:

  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();
        } else {
          maximum_range_ = 1;
        }
      #endif
(...)

At initialization and:

  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_);
    }  
  };

This way, I use range only if it covers the full amount of levels, or handle it by other means otherwise.
Obviously, if you let it be handled by the fonts and there is none, you have a single range. Hope all of this seems like a sane thing.

@profezzorn I’ve updated the first post with a TODO list. Please tell me if you find anything in that list outside the scope of the basic blaster.h. I think it should be feature complete (handle all buttons, use all sound options) but offer no bells and whistles like menus, style edition and all that stuff.

@profezzorn Sorry that I’m a bother by now. But I’ve found out the following situation:

We have defined a reload sound, plus a full sound. But blaster.h does not makes use of it. So, I tried to do:

  virtual void Reload() {
    shots_fired_ = 0;
    SaberBase::DoEffect(EFFECT_RELOAD, 0);
    SaberBase::DoEffect(EFFECT_FULL, 0);
  }

Which obviously made them go in parallel. So I was wondering if:

  1. Is there a way to define a queue of effects and push it?
  2. Is there a way to register for the end of a DoEffect?
  3. And getting ahead of myself. Is there a way to register on a lockup so you can add more than a condition to end it? This is not exactly the same as above, but for having clip capacity while doing auto I want either condition to end the lockup. And probably have a different endlckup sound.

Aaaand, sorry to keep asking. I’m trying to communicate most actions. And am currently using STDOUT.println("Action Description");. Should I encapsulate between an #ifdef DISABLE_DIAGNOSTIC_COMMANDS or is there some other preferred way of defining the verbosity of a prop?

I think it depends more on how they are implemented than what the features are actually.
There are a few things that are important to keep in mind:

  • it needs to be backwards compatible, that means that all existing blaster config files should still work, and behave more or less the same. (Unless we strongly believe the new behavior is an improvement.)
  • In most cases, new features should be optional, and thus enabled by a define (it could also be enabled by having a particular button, or having a particular sound effect, or something else.) Note that any features which is on by default will need to be relatively lean and not use up too much memory.

That also means that some bells and whistles are ok, as long as they are off by default.

Why wouldn’t a font maker just put the “full” effect at the end of the “reload” sound then?
I don’t understand the point of “full” I guess.

Yes, but nothing pre-made exists, so you would have to implement it yourself.

A DoEffect does not have a length, but if it triggers a sound effect, we can find out how long that sound effect is. (This is what Wavlen<> does.)

It can be done. I did it it for the ARMED lockup state.
Currently there is no way to do it in a way that doesn’t take up memory for everybody though, so I would try to find another solution if possible. (Like just using your own state instead of lockup.)

There are no bad questions.
I won’t get annoyed until I have to explain the same thing multiple times… :slight_smile:

There isn’t a standardized way, but maybe there should be.
Using DISABLE_DIAGNOSTIC_COMMANDS is not the right way though.
We might want to create a new define for this, something like:

#define VERBOSITY 0  /* range 0 - 5 */

Then in the code we would do:

#if VERBOSITY - 0 >= 1
   STDOUT.println("debug printout");
#endif

We would need to define what the VERBOSITY levels mean though, like maybe something like:
0: no printouts
1: essential printouts
2: good-to-know printouts
3: debug printouts
4: verbose printouts
5: spammy printouts

1 Like

That’s exactly why I’m creating so many defines: any change in behavior to OS7 blaster.h is only enabled by new code.
For know I think I grew the code 2%, (61% to 62%) but I’m enabling a lot of features.

I’m not quite sure myself. I’m going by current documentation. May be @NoSloppy knows de difference? I could imagine that if you had an energy weapon that charges continuously it would use the sound. But I think enably the queue or some sort of callback is a better long term option. I will think about it a bit and bring some concept forward.