Sign in to follow this  
cyberspahn

C++ crpg style combat system help

Recommended Posts

I'm creating an CRPG type game(similar to Bardstale2, Might-n-Magic, Wizards) in which several 'players' face off against a random sized number of monsters. This will be a turn-based DnD type of game. A combat round is a time frame where all players/monsters have a chance to do at least 1 action(eg- attack with a sword, shoot an arrow, use a spell of healing etc.) In combat, I need to find a way to determine which player or monster will be able to attack first. Following that which player/monster will attack next, and so on and so forth. my idea so far... Ive created a class that holds both the players and monsters under one roof. As the USER creates a new player, a player object is created and placed within an array. Take the number of characters/players (including monsters) and create a list. eg- 10 characters (4 players and say 6 monsters) Each character rolls d20 to get initiative. At this point any ability modifiers are added that may effect the roll. Eg- "cloak of haste" might bring the initiative up to 17 from a roll of 16 Now take all those values and "use" the highest roll down to the lowest roll while retaining the "owner" of each initiative roll. An Action queue is created which can be dynamically altered. What it is, is basically a list with all the characters and all their intended actions. The game will follow the Action queue from start to finish or until an action dictates a change in the queue. Usually something will die for this to change. each player will go through their attack sequence, whether its a melee attack, a spell, or other appropriate action during the combat round. If their action is successful then that effect will complete before the next character in the sequence has a chance to use their action. In other words, if a character whose higher initiative successfully kills another character with a "lower" initiative roll then the target character dies without chance of retaliation and is removed from the action queue. THE PROBLEM: How do I create this list? It must be "used" from the Highest to Lowest roll, the value(initiative roll) must also associate the character who made the roll in order to utilize that character's intended action, and the list needs to be updated if a character is killed without losing the data of the rolls( or at least until all characters have used up that "combat round"). so I can only guess at some sort of array for all the characters used but I would have to change the size of the array for each combat encounter. (So that each encounter will show a random number of monsters) Perhaps this is a multiple step process instead of a single "container" such as Map or multimap or stack.(to be honest, Im such a noob that STL confuses the hell out of me) If this is not a good way to accomplish what I need then what would be a better approach? I suppose someone may suggest studying STL(and I am trying), however I am hoping for a code example, or a thoughtful response that will steer me in the right direction. Also, I'm convinced that other fresh programmers out there who are thinking of an rpg project might run into this kind of complex problem and like me, would appreciate the answers greatly. Thank you.

Share this post


Link to post
Share on other sites
You might find the concept of a vector useful :) A vector, as a data structure, is simply a resizable array. Before you look at the STL to see how to use a vector, google "vector data structure". You should be able to find plenty of resources explaining what it is.

Share this post


Link to post
Share on other sites
This should help you get started :)


// Assuming:
#include <queue>
#include <algorithm>

using namespace std;

class Actor {
public:
virtual ~Actor() = 0;
virtual bool isAlly() const = 0;
virtual bool isEnemy() const = 0;
virtual Action makeDecision( vector<Actor*>& allies, vector<Actor*>& enemies ) = 0;
};

class EnemyActor : public Actor { /* ... */ };
class PlayerActor : public Actor { /* ... */ };

unsigned rolld20() {
return rand()%20 + 1;
}

vector<Actor*> party, monsters;


// First, build the queue to decide the turn order:
// ActorPriority.first decides the initiative, while
// ActorPriority.second is the pointer to the Actor who owns this initiative
typedef pair<int, Actor*> ActorPriority;
vector<ActorPriority> theQueue;

// Add the player's party first:
for ( unsigned i = 0; i < party.size(); ++i ) {
theQueue.push_back(
ActorPriority(
rolld20() + party[i].initaitiveModifier
, party[i]
)
);
}

// Then the monsters
for ( unsigned i = 0; i < monsters.size(); ++i ) {
theQueue.push_back(
ActorPriority(
rolld20()
, monsters[i]
)
);
}

// Sort by ActorPriority.first, descending
// Note the use of rbegin and rend to reverse the order of the sorting
sort( theQueue.rbegin(), theQueue.rend() );


// Next, the battle loop:
while ( party.size() && monsters.size() ) { // Loop until either the monsters are dead or the player's party is dead
// Perform actions:
vector<ActorPriority>::iterator it = theQueue.begin();
while ( it != theQueue.end() ) {
Actor* current = (*it).second;
if ( current->isDead() ) { // Don't perform an action for this Actor; it's dead!
( current->isAlly() ? party : monsters ).remove( current ); // Remove "current" from either the "party" or "monsters" list, depending on if the current Actor is an ally or monster
it = theQueue.erase( it ); // Remove the Actor from the turn order
} else {
Action act = (*it).second->makeDecision( party, monsters );
switch ( act.type ) {
case ATTACK: /* ... */; break;
case SPELL: /* ... */; break;
}

// Next Actor's turn!
++ it;
}
}
}



*Not tested

If you have any questions about the use of std::vector, just go to the C++ reference page!

Share this post


Link to post
Share on other sites
Thank you _Fastcall this appears to be exactly what I've been searching for (for a few months) -I'm a slow learner. I had suspected this to be a multi step process which for me made it difficult to encompass.

// ActorPriority.first decides the initiative, while
// ActorPriority.second is the pointer to the Actor who owns this initiative

I figured out the first step initially but never thought of using a pointer to reference the elements prior to sorting. I feel like a D2D now but its worth it cause I've racked my brain on this for far too long. Thanks again.

Oh and Thanks Grafalgar for your reply as well. Hopefully others with this problem will benefit like me.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this