Jump to content
  • Advertisement
Sign in to follow this  
DiscountVisionary

Creating "Equipable" Items That Have Unique Functions

This topic is 882 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello for the first time. I am still very new to C++ but understand the basics. I am taking on a larger project for the first time. I'm aiming to make turn based battle game (like FF1). The most important goal i have is to make items, that have multiple individually scripted functions, that can then be equiped in a set of slots for the player.

Originally I was planning to make an inheritance based system but my original idea didn't pan out.

I'm looking for any ideas on how I can create items that have unique functions and how i could allow the player to equip and use those items and their functions.

Share this post


Link to post
Share on other sites
Advertisement

A unique item can make available a list of commands/actions that it supports, so you could just use them as a way to interact with each unique item.

 

For example:

class Action
{
public:
    std::string id;
    std::string actionType;
}

class Item
{
public:
    virtual std::string GetItemName();
    virtual std::string GetItemType();
    virtual std::vector<Action> GetSupportedActions();
    virtual void DoAction(std::string actionId);
}

class EquipableItem : public Item
{
public:
// add anything specific to EquipableItems
}

class ItemA : public EquipableItem
{
public:
    std::vector<Action> GetSupportedActions() override;
    void DoAction(std::string actionId) override;
}

class ItemB : public EquipableItem
{
public:
    std::vector<Action> GetSupportedActions() override;
    void DoAction(std::string actionId) override;
}

class ItemSlot
{
public:
    virtual std::string GetSlotId();
    virtual std::vector<std::string> GetSupportedItemTypes(); // What kind of items can we equip in this slot
    virtual void EquipItem(EquipableItem* item);

private:
    EquipableItem* equipedItem;
}

class Player
{
public:
    std::vector<Item> Inventory;
    std::vector<ItemSlot> ItemSlots;
}

Share this post


Link to post
Share on other sites

It's a nitpick but it might introduce something new to the OP:

 

Instead of Action being a class that is only public, make it a struct.  Less typing and just as clear.  Could also do that for Item honestly since it's pure virtual.

 

You can also look, but you're new and it's a fairly large concept, at ECS or Entity Component System.  Sometimes called a Component System or an Entity System.

Share this post


Link to post
Share on other sites
Thanks for the replies!

@RH101
Okay, thats just about all new to me. I'll go ahead and put this project on pause and go learn about vectors, then come back. The question I have right now is about all those get functions. What would the {} be filled with when it comes time to override them in the ItemA class?

@Mike2343
I have heard about entity component systems before and its something down the pipeline for me. For now I'd be working with no more than 5 or so specific classes of items (ItemA, ItemB, Itemc...) but I can see that a better system would be needed if i was working with like 100.

Share this post


Link to post
Share on other sites

It's a nitpick but it might introduce something new to the OP: Instead of Action being a class that is only public, make it a struct. Less typing and just as clear. Could also do that for Item honestly since it's pure virtual.

 

Fair point regarding Action, since it's really just data and not much else. 

 

With the Item class, I'm almost certain there will be a lot more in there (public/private members) than what I've quickly typed up, so probably best to keep it as a class, even if it is a pure virtual/abstract class.  Personal preference to an extent, using structs primarily for plain old data encapsulation and classes for anything more complex than that.

Share this post


Link to post
Share on other sites

@RH101
Okay, thats just about all new to me. I'll go ahead and put this project on pause and go learn about vectors, then come back. The question I have right now is about all those get functions. What would the {} be filled with when it comes time to override them in the ItemA class?

 

Think of a C++ std::vector as a dynamic array, or a container that holds a list of data in a sequence. Oversimplification, but I'm sure if you do an online search you'll figure it out very quickly.

 

As for an example of an Item, let's try this:

class ShieldItem : public EquipableItem
{
public:
    ShieldItem(std::string itemName, std::string itemType)
        : itemName(itemName), itemType(itemType)
    {
        Action raiseShieldAction;
        raiseShieldAction.id = "Raise Shield";
        raiseShieldAction.actionType = "movement";
        actionListpush_back(raiseShieldAction);

        Action lowerShieldAction;
        lowerShieldAction.id = "Lower Shield";
        lowerShieldAction.actionType = "movement";
        actionList.push_back(lowerShieldAction);

        Action dropShieldAction;
        dropShieldAction.id = "Drop Shield";
        dropShieldAction.actionType = "movement";
        actionList.push_back(dropShieldAction);
    }

    std::vector<Action> GetSupportedActions() override
    {
        return actionList;
    }
    
    void DoAction(std::string actionId) override
    {
        auto& action = std::find_if(actionList.begin(), actionList.end(), [actionId](const Action& action) {
            return action->id == actionId;
        });
        
        if (action != actionList.end())
        {
            HandleAction(action, this);  // send the action along with the item to some code that handles it
        }
    }

private:
    std::vector<std::string> actionList;
    std::string itemName;
    std::string itemType;
}

This is really not the best way to implement it by any means, but it's just an example to show you what may go between the { }, and how to add items to a list (the actionList vector), and it's not guaranteed to compile.  Also, the ECS method is a great way to deal with what you want, as Mike2343 mentioned.  As an example, Unity3D uses the component system to do what it does very well, if you want to see how such a system works.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!