I'm a novice programmer but I have completed a pre-university in web prog so I am not a total noob. I'm using Unity, but this is just C# for now.
This is my first big project and I need some professional insight to make sure the design is not flawed. Currently working on abilities in an turn based rpg game.
What you might need to know: Abilities need to be learned/chosen, they may have requirements(levels, weapontype, more/etc.) New abilities will be added to the game with updates.
This is still the primitive stage, but very important to me because this project is more about learning to do it right rather than just getting it done.
Here are the following classes where we create abilities:
public abstract class Ability {
public readonly int id, multi, manaCost;
public Ability(int id, int multi, int manaCost) {
this.id = id;
this.multi = multi;
this.manaCost = manaCost;
}
public virtual void resolve(Actor user, Actor target){}
//Would create more methods with different parameters based on different abilities
//Example for multi target ability
public virtual void resolve(Actor user, Actor[] targets){}
}
Pretty simple stuff, Actor is just a in-game character. resolve is where the ability effects will be coded
using UnityEngine;
public class Freeze : Ability {
public Freeze() : base(0, 0, 3) { }
public override void resolve(Actor user, Actor target) {
int damage = 2 * user.attribute[2];
Debug.Log (damage);
target.damage(damage);
/*System.Random rnd = new System.Random();
if(rnd.Next(100) <= 35)
target.state = new Frozen();*/
}
}
the way I was planning to use abilities is, in the main script of the battle system there would be an array that has all the abilities such as this:
Ability[] all_ability;
public void createAbilities(){
all_ability = new Ability[2]; //size increased as we create more abilities
all_ability[0] = new Freeze();
all_ability[1] = new FirstStrike(); //and so on as we create more
}
The index of the array is also the id of the ability which allows us to easily access abilities.
So if an Actor wanted to use freeze, the id of freeze would be stored in Actor i.e. p1.actors[0].ability_ids array
so let's say i've got what ability the player chose, it would be something like this
int aId = p1.actors[i].ability_ids[j]; //would return 0 assuming he chose freeze
all_ability[aId].resolve(p1.actors[i], p2.actors[k]);
Everything works so far, no errors, and damage gets calculated correctly but this is a very simple ability and still much more to add like damage counters, animations, status effects etc.
What should I look out for? is there a much easier way to do this I dont know about? I guess my main concern is, as we learn in web programming, it is said to be very bad to hard code values and everything should come from databases, but, is that also true for a game since each ability can be quite different? As you can see, everything is hard coded here. I guess I just want tips on things I may have done wrong/if there is a clear better way to do this. Thanks for any and all replies!
Answer
You sound like you're off to a good start! However, you asked a pretty general question, so I can only really offer some general pointers that might help!
To start with, I'd use a List instead of an array ( using System.Collections.Generic
). You can still do abilityList[index]
like with arrays, but you get the added benefit of not having to handle resizing if you run out of rooms (since it's handled by the List
class), and LINQ queries, if you're into that!
After that, you should make sure your Actor has an "AddAbilities" method. Then, on load (or creation), you can simply go down the list, adding the abilities appropriately (instead of hardcoding them). For instance, if your character load data for Darth Vader is:
Force Lightning, Force Choke
(Not knowing how you intend to store stuff, let's just assume you somehow parse out a list of strings)
foreach(string abil in savedCharAbilities)
{
//You can use reflection or an AbilityFactory that takes a string parameter to create
// an instnace of the class based on it's name.
// If you have an enumeration of all of the possible abilities
// (only do this if you have a small total amount!), you could set up a switch statement
// to get your new Ability instead.
character.AddAbility(createdAbility);
}
Finally, you may also want to look into making your abilities MonoBehaviors that implement an Ability
Interface instead of inheriting from an abstract class - that way you can make use of Unity's built in Enable
properties (for toggle-able abilties), it's Update
method (for quickly changing effects), and Unity's Invoke
call (which calls the passed method X seconds later, or every X seconds if you call InvokePeriodic
).
No comments:
Post a Comment