Game; Monster Drops, most efficient way

I would like some assistance on how best to go about a drop list for a monster in a console application. Assume I have a Goblin object, and it drops 11 things at various chances, stats and effects. It seems really inefficient to keep those in memory the entire time the program is running. Is there some file format like an .ini file that can quickly read multilevel simplistic data?

Example:
// Format: Weapon Name; Weapon Type; Stats; Rate; Rarity(common(c), uncommon(u), rare(r), exotic(e), Legend(l))

Long Sword; Weapon; 2; 50; c
Silver Axe; Weapon; 3; 25; u;
// .. etc.

If not, what would be the best way to go about this?

Or, would it be best to have each weapon have its own class? I'm not really sure.
Last edited on
If you're making a console application on today's machines, it's unlikely you're going to have any problems with memory (not without storing huge wads of data or performing some crazy calculations, neither of which you're likely to be doing).

Classes are a great way to store weapon data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CWeapon
{
   public:
      CWeapon();
      int Init();
      int GetDamage();
      // etc. etc.

   private:
      int damage;
      int value;
      int weight;
      bool is_blunt;
      // etc, etc
      
}
We're talking about a few bytes per possible drop, there's nothing inefficient about that. Now reading from a file every time something is dropped, that would be inefficient.
It's best to have a drop class and then initialize the drops as follows:

1
2
3
goblinDrops={{"Long Sword",WEAPON,2,50,COMMON}, //note: requires C++11
             {"Silver Axe",WEAPON,3,25,UNCOMMON},
             {...}};


Or, would it be best to have each weapon have its own class?

Its own class? Probably not. However, a WeaponStats class grouping the stats for a weapon certainly makes sense and can then be used to look up the stats of a weapon via name or another ID.
Lacking that, imagine you want to change the stats of a weapon - then you'd have to edit all drop lists where it appears. That would be most inefficient.
Thank you for the fast response.

I know, but my current knowledge testing out concepts I may later expand upon, what would be the best way of doing this?

I'll try creating classes for this project. I've seen it done in ways like in Terraria, each weapon has its own ini file for basic stats, an image file to go with it, and a unique .cs file for special effects. I can see the .ini file being effective in this situation. How do I read from files like an .ini?
Sorry, I meant, a class for weapons in which all would fit. Then how would that work when I initialize the goblin, would I create a vector array to store each weapon object and apply that within the constructor?

Also, should items like healing potions group together in an all-encompassing class for weapons/armors/items or keep each class unique to its unique type.
Last edited on

Sorry, I meant, a class for weapons in which all would fit. Then how would that work when I initialize the goblin, would I create a vector array to store each weapon object and apply that within the constructor?


There are so many ways to do this, I suggest going with you feel most comfortable with. If you are trying to learn new things then you can try out an idea that you aren't familiar with. Sure you can init the weapon drop info in a constructor, but you could also create an interface for drops that your Goblin would implement (or any monster type). You could even have a default implementation for drops and only override it when you see fit.

You could have a drop be part of a base class that all monsters inherit from. Drops themselves could be there own object, that could be passed into a constructor for that monster type etc. (as said before).

With each abstraction and or granularity comes its advantages and disadvantages. You could create a mediator object which could then manage an assortment of objects that have different responsibilities. I'll give you an example.
Lets say you have a weapon class, armor class, item class. From these classes you can derive your swords, axes, crossbows, cloth, leather, plate, healing, mana, food etc. Neither of these classes need to know about the other, however, the mediator class (the glue) can bring all of them together and loosely couple. Now this mediator's sole purpose could be handling drops (or any number of things), what this buys you is the goblin need not know anything about weapon, item types etc and vice versa. This decoupling allows you to be flexible. Like I said this is just one way to implement what you are trying to do there are hundreds of ways to accomplish this.


Also, should items like healing potions group together in an all-encompassing class for weapons/armors/items or keep each class unique to its unique type.


This is entirely up to how you want to implement. Personally I probably would create an abstract base class 'item' (or whatever suites your naming) that all weapons/armor/misc things would be derived from. Why? Because now I have a common abstraction that I can pass around to different interfaces and let that interface decide on how it is implemented. Here is an example of this.

Item.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//... includes ...

class Item
{
   public:
       //For simplicity this will be the only public interface in the base class...
       virtual int GetKind()=0;

       //Notice virtual deconstructor, it is implemented here
       virtual ~Item(){}
   protected:
       //Derived classes can now call the default constructor
       Item(){}

}


Yes that base class is very simple, you would probably want to add some more to the interface. Maybe something like virtual int GetItemLevel()=0;, you get the idea.

Now you can derive from this class...

Armor.h
1
2
3
4
5
6
7
8
9
10
//... includes....

class Armor : public Item
{
    public:
      //.... implementation details....
      virtual int GetKind();
     
      //.... more details ....
}


Armor.cpp
1
2
3
4
5
int Armor::GetKind()
{
     return 42; //Meaning of life right?  You will have to decide what the interface does...
    //Maybe you don't return an int, maybe it's a const char *, or maybe its an object itself..
}


Now what is the point of showing you those? So that I can show you how they can be passed through other interfaces. Imagine now that Armor is a base class for hundreds of different derived armor classes. Suppose you also have weapons and healing potions and random pieces of material... but they all have one thing in common, Item.

You can now pass Item to any interface, figure out what kind of item it is and have it handle it appropriately...

1
2
3
4
//You could also pass the item as a pointer.
void BossDrop(const Item &Item);
void MonsterDrop(const Item &Item);
Item MonsterDrop(const Item &Item);


Ok how does this help you with the Goblin object? Well you could still have a vector, but now it would be a vector whos elements are a pointer to an Item...

This is probably a lot more than you wanted but since your having fun with this I figured I'd throw out some other concepts.
Last edited on
Your first idea is good but consider grouping all weapons in a file weapons.ini and add another field, the identifier which is unique for each weapon:
LongSword, Long Sword; Weapon; 2; 50; c
LongSword is the identifier and Long Sword is the name in-game.
It is better to separate the identifier from the name in-game, for example if you want to localize the game.
Then for each monster(in a file monsters.ini for example), give a list of available drops with the weapon identifier, for example:
...
Gobelin:
hp: 12
...
Drops: LongSword, Potion
...

You can also add drop rate:
Drops: LongSword(20%), Potion(50%)
Thank you, all. You have given me quite a bit to think about. I'll have to experiment a bit and see which way I like.
Topic archived. No new replies allowed.