is it possible for a switch to run through multiple cases at once for example.
void AgilityAbilities ()
{
switch (agilityCheck)
{
case 5:
dodgeChance = 5;
break;
case 10:
numAttacks = 2;
break;
case 15:
spacesCanJump = 2;
break;
case 20:
dodgeChance = 10;
break;
case 25:
numAttacks = 3;
break;
case 30:
spacesCanJump = 3;
break;
case 35:
dodgeChance = 15;
break;
case 40:
numAttacks = 4;
break;
case 45:
spacesCanJump = 4;
break;
case 50:
canSteal = true;
break;
case 55:
dodgeChance = 20;
break;
case 60:
numAttacks = 5;
break;
case 65:
spacesCanJump = 5;
break;
case 70:
dodgeChance = 25;
break;
case 75:
ignoreCoverAgility = true;
break;
case 80:
numAttacks = 6;
break;
case 85:
dodgeChance = 30;
break;
case 90:
numAttacks = 7;
break;
case 95:
dodgeChance = 35;
break;
case 100:
if (character.name == "player Character")
{
agilityMastered = true;
}
numAttacks = 8;
break;
if my characters agility was 50 I’d want all the cases before 50 to be active but currently only case 50 is active and my characters dodge chance and number of attacks are still zero. can this be changed and how?
The short answer is no. You can do this in some languages, like C++, but in C# case statements cannot fall through to the next unless there is no code for the case in question. For example:
switch(agility)
{
case 25:
case 50:
// this is valid
}
Which won’t do you any good. That being said, what you have looks like a poor design to begin with and doesn’t really follow good OOP principles. Maybe a better way to tackle it would be to break out your abilities into modifier classes and use something similar to the decorator pattern to chain them up. Here’s a simple mock-up:
// Class for holding player attributes. Implements INotifyPropertyChanged so that we can react when something changes.
public class Attributes: INotifyPropertyChanged
{
private int _agility;
public int Agility
{
get { return _agility; }
set
{
if (_agility != value)
{
_agility = value;
RaisePropertyChanged("Agility");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
}
// Class for holding abilities.
public class Abilities
{
public int NumberOfAttacks { get; set; }
public int DodgeChance { get; set; }
}
// Interface for the ability modifiers.
public interface IAbilityModifier
{
void CalculateAbilities(Player player);
}
// Base class for ability modifiers. Similar to a decorator.
public abstract class AbilityModifierBase: IAbilityModifier
{
protected AbilityModifierBase _modifier = null;
protected AbilityModifierBase(AbilityModifierBase modifier)
{
_modifier = modifier;
}
public virtual void CalculateAbilities(Player player)
{
if (_modifier != null)
_modifier.CalculateAbilities(player);
}
}
// The modifier for calculating the NumberOfAttacks ability.
public class NumberOfAttacksModifier : AbilityModifierBase
{
public NumberOfAttacksModifier(AbilityModifierBase modifier)
: base(modifier)
{ }
public override void CalculateAbilities(Player player)
{
base.CalculateAbilities(player);
if (player.Attributes.Agility > 40) player.Abilities.NumberOfAttacks = 4;
else if (player.Attributes.Agility > 25) player.Abilities.NumberOfAttacks = 3;
else if (player.Attributes.Agility > 10) player.Abilities.NumberOfAttacks = 2;
}
}
// Modifier for calculating the DodgeChance ability.
public class DodgeChanceModifier : AbilityModifierBase
{
public DodgeChanceModifier(AbilityModifierBase modifier)
: base(modifier)
{ }
public override void CalculateAbilities(Player player)
{
base.CalculateAbilities(player);
if (player.Attributes.Agility > 35) player.Abilities.DodgeChance = 15;
else if (player.Attributes.Agility > 20) player.Abilities.DodgeChance = 10;
else if (player.Attributes.Agility > 5) player.Abilities.DodgeChance = 5;
}
}
// Player class.
public class Player
{
private Attributes _attributes;
private Abilities _abilities;
private readonly IAbilityModifier _abilityModifier;
public Player()
{
_attributes = new Attributes();
_abilities = new Abilities();
_abilityModifier = new DodgeChanceModifier(new NumberOfAttacksModifier(null));
_attributes.PropertyChanged += Attributes_PropertyChanged;
}
private void Attributes_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_abilityModifier != null)
_abilityModifier.CalculateAbilities(this);
}
public Attributes Attributes { get { return _attributes; } }
public Abilities Abilities { get { return _abilities; } }
}
By doing it this way, you are isolating the logic of a particular modifier - e.g. all of the logic for dealing with the DodgeChance is in one place. By using a constructor chain to assign the various modifiers you want, you can easily add/remove them as needed, without breaking any other code.
Technically you can actually fall though with c# with the goto statement, most programmers agree that goto leads to spaghetti code and should be avoided, although it can be useful (like in the example in the docs) sometimes, and it doesn’t have to “spaghettify” your code if you’re sensible about the use, I mean loops use a sort-of goto statement after all.
Although in your case, adding 20 goto statements will probably be a bit of a disaster. You might want to consider redesigning how your attributes (I’m assuming you have agi, int, wis whatever) work. Most games be it D&D, rpg’s or whatever will have stats scale off the primary attribute, which avoids having all these set intervals in your switch statement, heres an example for you:
dodgeChange = 3 + Mathf.Round(agilityCheck / 3);
numAttacks = 1 + Mathf.Round(agilityCheck / 14);
spacesCanJump = 1 + Mathf.Round(agilityCheck / 15);
if(agilityCheck >= 50)
canSteal = true;
if(agilityCheck >= 75)
ignoreCoverAgility = true;
if(agilityCheck >= 100 && character.name == "player Character")
agilityMastered = true;
And if you check the maths:
5: dodgeChance = 5
10: numAttacks = 2
15: spacesCanJump = 2
55: dodgeChange = 21
60: numAttacks = 5
65: spacesCanJump = 5
As you can see this roughly fits what you had at set intervals, and these are numbers I just roughly guessed. And the advantage of this is your abilities like dodge will scale with every agi point you get, instead of suddenly jumping up when you hit a multiple of 5. So from a game design point of view thats what I would recommend, otherwise @NewPath made a great example for you if its not too confusing!
Why make this harder than it needs to be…simply set the variables from under 50 to be the same for 50
I think a far simpler answer for this would be to create an enum and a class for to hold the different attribute types and values for them. Example:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public enum AttributeType{dodgeChance, numAttacks};
public class Attribute
{
public Attribute(int check, int val, AttributeType type)
{
agilityCheck = check;
attributeValue = val;
attributeType = type;
}
public int agilityCheck;
public int attributeValue;
public AttributeType attributeType;
}
public class temp : MonoBehaviour
{
public Dictionary<AttributeType,int> Attributes = new Dictionary<AttributeType, int>();
public List<Attribute> attributeSetPoints = new List<Attribute>();
public int agilityCheck;
void Start ()
{
Attributes.Add (AttributeType.dodgeChance, 0);
Attributes.Add (AttributeType.numAttacks, 0);
attributeSetPoints.Add(new Attribute(5,5,AttributeType.dodgeChance));
attributeSetPoints.Add(new Attribute(20,10,AttributeType.dodgeChance));
}
public void AgilityAbilities()
{
foreach (Attribute attr in attributeSetPoints)
{
if (attr.agilityCheck > this.agilityCheck)
{
Attributes[attr.attributeType] = attr.attributeValue;
}
}
}
}
You can then easily add attribute types that need to change, etc; and no messy case statement.