hey there Unity peeps. so i have come to a point in my game where i need to find a good solution to create logic for my stats.
this is one of the Base classes and all it does it that it allows me to hold values and reference when needed. for the Player Alone.
public class BasePlayer {
// Use this for initialization
public BasePlayer () {
tookDamage = false;
//DontDestroyOnLoad (this);
}
private string playerName;
private string playerDescription;
private float playerHealth;
private float playerMana;
private float playerCurrentHealth;
private float playerCurrentMana;
private float playerMaxHealth;
private float playerMaxMana;
private int playerPhysicalMinDamage;
private int playerPhysicalMaxDamage;
private float playerPhysicalCritChance;
private float playerPhysicalCritDamage;
private int playerMagicalMinDamage;
private int playerMagicalMaxDamage;
private float playerMagicalCritChance;
private float playerMagicalCritDamage;
private BaseCharacter.ClassType playerClass;
private int playerLevel;
//private int availbleAttributesPoints;
private float playerExp;
private float playerCurrentExp;
private int playerStrength;
private int playerIntellect;
private int playerAgility;
private int playerLuck;
private float playerAttackSpeed;
private float playerCastSpeed;
private float playerSpeed;
private Vector3 playerPosition;
private bool onDeath;
private bool isAlive;
private bool tookDamage;
private List<BasicSpells> playerSpellBook;
private List<PlayerInventory> playerInventory;
private int[] playerAttributes;
public string PlayerName { get { return playerName; } set { playerName = value; } }
public string PlayerDescription { get { return playerDescription; } set { playerDescription = value; } }
public float PlayerHealth { get { return playerHealth; } set { playerHealth = value; } }
public float PlayerMana { get { return playerMana; } set { playerMana = value; } }
public float PlayerCurrentHealth { get { return playerCurrentHealth; } set { playerCurrentHealth = value; } }
public float PlayerCurrentMana { get { return playerCurrentMana; } set { playerCurrentMana = value; } }
public float PlayerMaxHealth { get { return playerMaxHealth; } set { playerMaxHealth = value; } }
public float PlayerMaxMana { get { return playerMaxMana; } set { playerMaxMana = value; } }
public int PlayerPhysicalMinDamage { get { return playerPhysicalMinDamage; } set { playerPhysicalMinDamage = value; } }
public int PlayerPhysicalMaxDamage { get { return playerPhysicalMaxDamage; } set { playerPhysicalMaxDamage = value; } }
public float PlayerPhysicalCritChance { get { return playerPhysicalCritChance; } set { playerPhysicalCritChance = value; } }
public float PlayerPhysicalCritDamage { get { return playerPhysicalCritDamage; } set { playerPhysicalCritDamage = value; } }
public int PlayerMagicalMinDamage { get { return playerMagicalMinDamage; } set { playerMagicalMinDamage = value; } }
public int PlayerMagicalMaxDamage { get { return playerMagicalMaxDamage; } set { playerMagicalMaxDamage = value; } }
public float PlayerMagicalCritChance { get { return playerMagicalCritChance; } set { playerMagicalCritChance = value; } }
public float PlayerMagicalCritDamage { get { return playerMagicalCritDamage; } set { playerMagicalCritDamage = value; } }
public BaseCharacter.ClassType PlayerClass { get { return playerClass; } set { playerClass = value; } }
public int PlayerLevel { get { return playerLevel; } set { playerLevel = value; } }
//public int AvailbleAttributesPoints { get { return availbleAttributesPoints; } set { availbleAttributesPoints = value; } }
public float PlayerExp { get { return playerExp; } set { playerExp = value; } }
public float PlayerCurrentExp { get { return playerCurrentExp; } set { playerCurrentExp = value; } }
public int PlayerStrength { get { return playerStrength; } set { playerStrength = value; } }
public int PlayerIntellect { get { return playerIntellect; } set { playerIntellect = value; } }
public int PlayerAgility { get { return playerAgility; } set { playerAgility = value; } }
public int PlayerLuck { get { return playerLuck; } set { playerLuck = value; } }
public float PlayerAttackSpeed { get { return playerAttackSpeed; } set { playerAttackSpeed = value; } }
public float PlayerCastSpeed { get { return playerCastSpeed; } set { playerCastSpeed = value; } }
public float PlayerSpeed { get { return playerSpeed; } set { playerSpeed = value; } }
public bool OnDeath { get { return onDeath; } set { onDeath = value; } }
public bool IsAlive { get { return isAlive; } set { isAlive = value; } }
public bool TookDamage { get { return tookDamage; } set { tookDamage = value;} }
public List<BasicSpells> PlayerSpellBook {get { return playerSpellBook;} set { playerSpellBook = value;}}
public List<PlayerInventory> PlayerInventory {get { return playerInventory;} set { playerInventory = value;}}
public int[] AttributesPoints {get { return playerAttributes;} set {playerAttributes = value;}}
public Vector3 PlayerPosition { get { return playerPosition; } set { playerPosition = value;} }
}
right now i am using a class to provide my logic from but from what u can see i got kinda stuck in trying to find the one solution
public class BaseStatLogic {
public BaseStatLogic (){
}
public int playerPhysicalMinDamage (){
return GameManager._BasePlayer.PlayerPhysicalMinDamage += (((int)1.25f * GameManager._BasePlayer.PlayerStrength));
}
}
is there a easier and more manageable way to do Logic? some sort of structure?
and if u could suggest any good Formula that i might be able to build i am all ears. but what i am searching for is a Slow >>> Faster Progress formula.
Firstly, you’ll want to keep your base player class organized rather than chucking everything into that class, making it hard to read or keep organized. Plus, assuming you have classes (as in knights, cleric, etc.), you might have some custom stats for each class, your inventory might depend on what class/race you are, etc.
So here’s a more abstracted base player class (just to get started):
public enum DamageType
{
Physical,
Fire,
Water,
Lightning,
// etc
}
public abstract class BaseStats
{
public int health;
public int maxHealth;
public int mana;
public int maxMana;
}
public abstract class BasePlayer
{
public BaseStats stats;
public BaseInventory inventory;
public abstract void TakeDamage(int amount, DamageType type, BasePlayer source = null);
// etc
}
Of course, how exactly you want to organize this is up to you, but the key ideas are:
When attacking, calculate the amount of damage and damage type you want to inflict.
Pass these values along to enemy.TakeDamage(amount, type). This may mean running through your inventory to see if the amount should increase based on equipped items, etc.
Let the enemy figure out how the damage should be handled to account for immunity, resistances due to equipped items in inventory, race bonuses, class bonuses, etc. and respond accordingly.
Bottom line: Let each character (player, enemy, etc.) be responsible for themselves. Don’t assume anything about anyone else.
E.g. I know I’m about to attack you for 100hp worth of damage but I don’t actually know if you will actually receive the full 100hp due to your strengths or weaknesses. Only you can figure out how much you’ll actually take, and whether you’ll die from it (or counter attack or roid out or be stunned… etc.)
and i for some reason keep forgetting to include importent data.
Here is my Class that will have all BasicClasses in it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BasicClass : BaseCharacter {
public BasicClass Beginner()
{
CharacterClassType = ClassType.Beginner;
CharacterClassnName = "Beginner";
CharacterClassDescription = "New Adventure";
CharacterClassBaseHealthMulti = 1.0f;
CharacterClassBaseManaMulti = 1.0f;
return this;
}
public BasicClass Warrior()
{
CharacterClassType = ClassType.Warrior;
CharacterClassnName = "Warrior";
CharacterClassDescription = "The Most Basic of Basic Pawns";
CharacterClassBaseHealthMulti = 2.7f;
CharacterClassBaseManaMulti = 1.2f;
return this;
}
public BasicClass Mage ()
{
CharacterClassType = ClassType.Mage;
CharacterClassnName = "Mage";
CharacterClassDescription = "The Mage of books";
CharacterClassBaseHealthMulti = 1.35f;
CharacterClassBaseManaMulti = 2.8f;
return this;
}
public BasicClass Thief ()
{
CharacterClassType = ClassType.Thief;
CharacterClassnName = "Thief";
CharacterClassDescription = "The Shady Dealer";
CharacterClassBaseHealthMulti = 1.1f;
CharacterClassBaseManaMulti = 1.3f;
return this;
}
public BasicClass Bowman ()
{
CharacterClassType = ClassType.Bowman;
CharacterClassnName = "Bowman";
CharacterClassDescription = "The false Robinhood";
CharacterClassBaseHealthMulti = 1.15f;
CharacterClassBaseManaMulti = 1.3f;
return this;
}
}
and its parent.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseCharacter {
private string characterClassName;
private string characterClassDescription;
private ClassType characterClassType;
public enum ClassType
{
Beginner,
Warrior,
Mage,
Bowman,
Thief
}
private float characterClassBaseHealthMulti;
private float characterClassBaseManaMulti;
private int characterClassStrength;
private int characterClassIntellect;
private int characterClassAgility;
private int characterClassLuck;
public ClassType CharacterClassType { get { return characterClassType; } set { characterClassType = value; } }
public string CharacterClassnName { get { return characterClassName; } set { characterClassName = value; } }
public string CharacterClassDescription { get { return characterClassDescription; } set { characterClassDescription = value; } }
public float CharacterClassBaseHealthMulti { get { return characterClassBaseHealthMulti; } set { characterClassBaseHealthMulti = value; } }
public float CharacterClassBaseManaMulti { get { return characterClassBaseManaMulti; } set { characterClassBaseManaMulti = value; } }
public int CharacterClassStrength { get { return characterClassStrength; } set { characterClassStrength = value; } }
public int CharacterClassIntellect { get { return characterClassIntellect; } set { characterClassIntellect = value; } }
public int CharacterClassAgility { get { return characterClassAgility; } set { characterClassAgility = value; } }
public int CharacterClassLuck { get { return characterClassLuck; } set { characterClassLuck = value; } }
}
I would suggest using Scriptable Objects. You create one base class and give different characteristics by creating multiple assets from the same class.
To prevent you from creating an instance of BasePlayer, which by itself doesn’t make too much sense.
Or turn it into an interface if you can reorganize well enough.
Ultimately you want to use components, and let components dictate your logic.
Basically, you want to avoid doing this:
public int playerPhysicalMinDamage (){
return GameManager._BasePlayer.PlayerPhysicalMinDamage += (((int)1.25f * GameManager._BasePlayer.PlayerStrength));
}
Reasons:
Where’s the damage coming from? You have no counterattack target if you wanted to counterattack.
It doesn’t really allow you to specify a target, or set an AoE damage center, damage types, etc.
It doesn’t allow for the attacker’s inventory. Was it done using a sword? Gun? Spell?
Hardcoded 1.25 really should come from the attacker’s stats. In fact, it really should be the attacker that’s trying to deal the damage, not some outside logic handler. Keyword: Trying. The target/victim should be the one to handle the actual receiving of the damage, hit point loss, etc.
If it’s a turn based RPG, then your logic handler should be responsible for:
Turn order
Moving players and projectiles around
Apply some global rules of battle (due to environment type, if it’s dark, whatever that may affect damage modifiers)
Organizing combat into phases (movement, combat, resolution)
well i kinda misworded myself but that class will be used to calculate the stats of the player. not the actual Output of dmg etc.
like based on what armor,wep, etc player has and what each stat will do for the player. i will make another class that is will do the logic for calculating dmg i think