Dave Voyles
Dave Voyles

Reputation: 4605

Check for next highest / lowest value in list and select that item

UPDATE: I should have been more clear. I am attemtping to sort a list in ascending order, and then getting the first weapon that has a greater value than the currently select weapon.

My NextWeapon() function doesn't do anything at this point (it was simply there to show things that I have tried), but in the past I was simply iterating to the next item in the list, however an item may not be there.

The enum F3DFXType are the weapons my character could possible pick up, but there is no sense in looping through those if they are not actually in the inventory. Therefore, I tried creating a list of type int, and looping through that. As the character picks up a new weapon, it would be added to the list as an int, and then when I switched to that int, I would check for that same int in the F3DFXType enum.

For example, in a pickup I would check for a collision event, then use: weaponList.Add(5); thinking it would add the integer 5 to my inventory. The 5th item in the F3DFXType is "Seeker". When I tried to loop through my inventory, it wouldn't actually add the 5th F3DFXType, it would simply add the NEXT item in the F3DFXType. (Ex: I already have Vulcan, and this would simply add SoloGun, which is the 2nd item in the enum)


I am trying to loop through items in a list.

The issue I run into is that if Ito iterate to the next item in the list, that item may not actually be there. So how do I advance to the next item that DOES exist in the list?

I'm not necessarily looking for an answer using the code below, I just wanted to give some context, so that you could see my current approach.

// Possible weapon types
public enum F3DFXType
{
    Vulcan = 1,
    SoloGun,
    Sniper,
    ShotGun,
    Seeker,
    RailGun,
    PlasmaGun,
    PlasmaBeam,
    PlasmaBeamHeavy,
    LightningGun,
    FlameRed,
    LaserImpulse
}


 // List of weapons currently avaialable
public List<int> weaponList;
public int currentIndex = 1;


void NextWeapon()
    {
        // Keep within bounds of list
        if (currentIndex < weaponList.Count)
        {
            currentIndex++;

            // Check if a higher value exists
            var higherVal = weaponList.Any(item => item < currentIndex);

            // create a new list to store current weapons in inventory
            var newWeapList = new List<int>();
            foreach (var weap in weaponList)
            {
                newWeapList.Add(weap);
            }
            weaponList = newWeapList;

            // If a higher value exists....
            if (higherVal)
            {
                //  currentIndex = SOMEHIGHERVALUE
            }
        }        
    }



    void PrevWeapon()
    {
        if (currentIndex > 1)
        {
            currentIndex--;
        }
    }



  // Fire turret weapon
    public void Fire()
    {
        switch (currentIndex)
        {
            case 1:
                // Fire vulcan at specified rate until canceled
                timerID = F3DTime.time.AddTimer(0.05f, Vulcan);
                Vulcan();
                break;
            case 2:
                timerID = F3DTime.time.AddTimer(0.2f, SoloGun);
                SoloGun();
                break;
            case 3:
                timerID = F3DTime.time.AddTimer(0.3f, Sniper);
                Sniper();
                break;
            case 4:
                ShotGun();
                break;
            case 5:
                timerID = F3DTime.time.AddTimer(0.2f, Seeker);
                Seeker();
                break
           default:
                break;
        }
    }

Upvotes: 1

Views: 1054

Answers (2)

Dave Voyles
Dave Voyles

Reputation: 4605

I found a solution. No idea why this took me so long to figure out. Anyway, I have it working now.

I start off with 2 guns in my inventory. I can only switch between those two for now. (Items 0 & 4 in my array).

When I collide with a pickup, I can add another item to this inventory (item 11 in the array).

Now when I hit Previous or Advance, it knows to stay within the array's bounds, and if a higher weapon is not found, then default back to the one we are currently using.

// Weapon types
public enum F3DFXType
{
    Vulcan          = 0,
    SoloGun         = 1,
    Sniper          = 2,
    ShotGun         = 3,
    Seeker          = 4,
    RailGun         = 5,
    PlasmaGun       = 6,
    PlasmaBeam      = 7,
    PlasmaBeamHeavy = 8,
    LightningGun    = 9,
    FlameRed        = 10,
    LaserImpulse    = 11,
    MAX_WEAPONS     = 12
}


    public bool[] aWeaponsHave = new bool[(int)F3DFXType.MAX_WEAPONS];
    int iWeaponsCurrent;


public Constructor() 
{

       .....
     // Start at first weapon (VULCAN)
        iWeaponsCurrent = 0;
        aWeaponsHave[0] = true;

        // DEBUG: Add weapon to inventory
        aWeaponsHave[1] = true;
         .....
}



 private void GoNextWeapon()
    {
        // If there isn't a higher value found, then default back to the original one
        var originalVal = iWeaponsCurrent;

        do
        {
            iWeaponsCurrent++;
            // Went to the end of array & didn't find a new weapon. Set it to the original one. 
            if (iWeaponsCurrent == 12)
            {
                iWeaponsCurrent = originalVal;
                return;
            }
        } while (aWeaponsHave[iWeaponsCurrent] == false);
    }


    void GoPrevWeapon()
{
    do
    {
        iWeaponsCurrent--;

        // Prevent from spilling over
        if (iWeaponsCurrent < 0)
        {
            // Went to end of array. Set weapon to lowest value and get out of here
            iWeaponsCurrent = 0;
            return;
        }
    } while (!aWeaponsHave[iWeaponsCurrent]);
}



// Fire turret weapon
    public void Fire()
    {
        switch (iWeaponsCurrent)
        {
            //case F3DFXType.Vulcan:
            case 0:
                // Fire vulcan at specified rate until canceled
                timerID = F3DTime.time.AddTimer(0.05f, Vulcan);
                // Invoke manually before the timer ticked to avoid initial delay
                Vulcan();
                break;

            //case F3DFXType.SoloGun:
            case 1:
                timerID = F3DTime.time.AddTimer(0.2f, SoloGun);
                Debug.Log("Solo");
                SoloGun();
                break;

            //case F3DFXType.Sniper:
            case 2:
                timerID = F3DTime.time.AddTimer(0.3f, Sniper);
                Debug.Log("Sniper");
                Sniper();
                break;

            //case F3DFXType.ShotGun:
            case 3:
                timerID = F3DTime.time.AddTimer(0.3f, ShotGun);
                ShotGun();
                break;

            //case F3DFXType.Seeker:
            case 4:
                timerID = F3DTime.time.AddTimer(0.2f, Seeker);
                Seeker();
                break;

            //case F3DFXType.RailGun:
            case 5:
                timerID = F3DTime.time.AddTimer(0.2f, RailGun);
                Debug.Log("railgun");
                RailGun();
                break;
            //case F3DFXType.PlasmaGun:
            case 6:
                timerID = F3DTime.time.AddTimer(0.2f, PlasmaGun);
                PlasmaGun();
                break;

            //case F3DFXType.PlasmaBeam:
            case 7:
                // Beams has no timer requirement
                PlasmaBeam();
                break;

            //case F3DFXType.PlasmaBeamHeavy:
            case 8:
                // Beams has no timer requirement
                PlasmaBeamHeavy();
                break;

            //case F3DFXType.LightningGun:
            case 9:
                // Beams has no timer requirement
                LightningGun();
                break;

            //case F3DFXType.FlameRed:
            case 10:
                // Flames has no timer requirement
                FlameRed();
                break;

            //case F3DFXType.LaserImpulse:
            case 11:
                timerID = F3DTime.time.AddTimer(0.15f, LaserImpulse);
                LaserImpulse();
                break;
            default:
                break;
        }
    }

Upvotes: 0

sauceboat
sauceboat

Reputation: 43

If I'm understanding the question correctly, I think you could simply do this by sorting the list in ascending order, and then getting the first weapon that has a greater value than the currently select weapon.

For example:

void Next()
{
    var nextWeapon = weaponList
        .OrderBy(w => w)                         // Sort the weapon list
        .FirstOrDefault(w => w > currentIndex);  // Get the next highest weapon

    // If nextWeapon is 0, there was no higher weapon found
    currentIndex = nextWeapon > 0 ? nextWeapon : currentIndex;
}

EDIT:

You can also reverse this to get the previous weapon:

void PrevWeapon()
{
    if (currentIndex > 1)
    {
        var previousWeapon = weaponList
            .OrderByDescending(w => w)               // Sort the weapon list
            .FirstOrDefault(w => w < currentIndex);  // Get the next lowest weapon

        // If previousWeapon is 0, there is no next lowest weapon
        currentIndex = previousWeapon > 0 ? previousWeapon : currentIndex;
    }
}

Upvotes: 3

Related Questions