Switch FireMode if Available

So, I have a script with booleans that show what fire modes a weapon has. And switch between them when I press “H”.

public bool Semi;
public bool Auto;
public bool Burst;
public enum FireModeS{
	Semi,
	Auto,
	Burst,
}
public FireModeS FireMode;

  void Update () {
if(Input.GetButtonDown("ChangeFireMode")){
			switch(FireMode){
			case FireModeS.Auto:
				FireMode = FireModeS.Semi;
				break;
			case FireModeS.Semi:
				FireMode = FireModeS.Burst;
				break;
			case FireModeS.Burst:
				FireMode = FireModeS.Auto;
				break;
			}
		} 
                 }

But I want to know how could I skip a FireMode, and use the remaining ones

e.g. I have Auto and Semi or Auto and Burst or just Semi… and when I press “H” I want to switch between those two FireModes, and/or do not switch if there is just one FireMode. How Can I do it?

You can use flags:

#region Private Fields

[SerializeField]
[BitMask(typeof(FireMode))]
private FireMode availableFireModes;

[SerializeField]
private FireMode fireMode;

#endregion Private Fields

#region Public Enums

[Flags]
public enum FireMode
{
    Semi = 1 << 0,
    Auto = 1 << 1,
    Burst = 1 << 2
}

#endregion Public Enums

#region Private Methods

// This function is called when the script is loaded or a value is changed in the inspector
// (Called in the editor only)
private void OnValidate()
{
    if (this.fireMode == 0)
    {
        this.SwitchToNextFireMode();
    }
}

private void SwitchToNextFireMode()
{
    Debug.Log("Switch!");
    if ((this.availableFireModes & ~this.fireMode) != 0)
    {
        // We don't need to change FireMode if there are no available FireModes
        int fireModeCount = Enum.GetNames(typeof(FireMode)).Length;
        int fireMode = (int)this.fireMode;
        for (int i = 0; i < fireModeCount; i++)
        {
            fireMode = fireMode < (1 << (fireModeCount - 1)) ? fireMode << 1 : 1;
            if ((fireMode & (int)this.availableFireModes) != 0)
            {
                Debug.Log("Setting FireMode!");
                this.fireMode = (FireMode)fireMode;
                break;
            }
        }
    }
}

private void Update()
{
    if (Input.GetButtonDown("ChangeFireMode"))
    {
        this.SwitchToNextFireMode();
    }
}

#endregion Private Methods

If you want to be able to edit the enum in the editor, this guy has got your back:

I’ve attached the files you’ll need to get the BitMask to work. Reply if you have any further problems.

EDIT: I forgot the files. :stuck_out_tongue:
[72417-bitmask.zip|72417]

EDIT: ARGH, I BROKE IT. Wait a moment.

EDIT: Finally found the bug… Sorry about that.

Well, one way is to simply switch the mode and after that check if the mode is available. If not simply switch to the next until it’s a valid mode:

void NextFireMode()
{
    for(int i = 0; i < 3; i++)
    {
        // select next fire mode
        int mode = (int)FireMode + 1;
        if (mode > 2) // wrap around after last mode
            mode = 0;
        FireMode = (FireModeS)mode;
        
        switch(FireMode){
            case FireModeS.Semi:
                if (Semi)
                    return;  // valid mode --> exit method
            break; // mode not valid.
            case FireModeS.Auto:
                if (Auto)
                    return;  // valid mode --> exit method
            break; // mode not valid.
            case FireModeS.Burst:
                if (Burst)
                    return;  // valid mode --> exit method
            break; // mode not valid.
        }
    }
} 

I used a for loop instead of a while(true) loop just in case all 3 booleans are false in which case it would never exit. The first part inside the loop simply selects the next fire mode in the enum. After that the switch statement checks if the mode is valid. If it is, it uses “return” to quite the method and the firemode has been changed. If the mode is not valid the for loop will do another iteration and once more increases the fire mode. This repeats until a valid mode has been found or the max iteration count is reached. The second case should never happen as you should have at least one mode available.