Ejemplo n.º 1
0
void Battle::NextTurn()
{
	std::queue<BattleEvent> events;

	std::sort(combatants.begin(), combatants.end(),
		[](Creature* a, Creature* b) { return a->GetAgility() > b->GetAgility(); });

	for (auto com : combatants)
	{
		if (com->GetID() == "Player")
		{
			Dialogue targetSelection = Dialogue("Who?", {});
			for (auto target : combatants)
				if (target->GetID() != "Player")
					targetSelection.AddChoice(target->GetName());

			int choice = battleOptions.Activate();

			switch (choice)
			{
			default:
			case 1:
			{
				int position = targetSelection.Activate();
				for (int i = 0; i < position; i++)
					if (combatants[i]->GetID() == "Player")
						position++;

				Creature* target = combatants[position - 1];
				events.push(BattleEvent(com, target, BattleEventType::ATTACK));
				break;
			}
			case 2:
			{
				events.push(BattleEvent(com, nullptr, BattleEventType::DEFEND));
				break;
			}
			}
		}
		else
		{
			Creature* player = *std::find_if(combatants.begin(), combatants.end(),
				[](Creature* a) { return a->GetID() == "Player"; });
			events.push(BattleEvent(com, player, BattleEventType::ATTACK));
		}
	}

	while (!events.empty())
	{
		BattleEvent event = events.front();
		switch (event.GetType())
		{
		case BattleEventType::ATTACK:
		{
			auto a = combatants.begin();
			auto b = combatants.end();

			if (std::find(a, b, event.GetSource()) == b || std::find(a, b, event.GetTarget()) == b)
				break;

			std::cout << event.GetSource()->GetName() << " attacks " << event.GetTarget()->GetName() << " for "	<< event.Run() << " damage!" << std::endl;
			if (event.GetTarget()->GetHP() <= 0)
				Kill(event.GetTarget());

			break;
		}
		case BattleEventType::DEFEND:
			std::cout << event.GetSource()->GetName() << " defends!\n";
			break;
		default:
			break;
		}

		events.pop();
	}
}
Ejemplo n.º 2
0
void Battle::next_turn()
{
	// Queue of battle events. Fastest combatants will be
	// at the start of the queue, and so will go first,
	// whereas slower ones will be at the back
	std::queue<BattleEvent> events;

	// Sort the combatants in agility order
	std::sort(combatants.begin(), combatants.end(), [](Creature* a, Creature* b) { return a->agility < b->agility; });

	// Iterate over the combatants and decide what they should do,
	// before adding the action to the event queue.
	for(auto com : this->combatants)
	{
		if(com->id == "player")
		{
			// Create the target selection dialogue
			Dialogue targetSelection = Dialogue("Who?", {});
			// Created every turn because some combatants may die
			for(auto target : this->combatants)
			{
				if(target->id != "player")
				{
					targetSelection.addChoice(target->name);
				}
			}

			// Ask the player for their action (attack or defend)
			int choice = this->battleOptions.activate();

			switch(choice)
			{
				default:
				case 1:
				{
					// Player is attacking, so ask for the target.
					// Dialogue returns the number of the choice, but we
					// want the pointer that name corresponds to and so we
					// must look it up in the combatant vector
					Creature* target = this->combatants[targetSelection.activate()-1];
					// Add the attack command to the event queue
					events.push(BattleEvent(com, target, BattleEventType::ATTACK));
					break;
				}
				case 2:
				{
					// Player is defending, so do nothing
					events.push(BattleEvent(com, nullptr, BattleEventType::DEFEND));
					break;
				}
			}
		}
		else
		{
			// Simple enemy AI where enemy constantly attacks player
			Creature* player = *std::find_if(this->combatants.begin(), this->combatants.end(),
				[](Creature* a) { return a->id == "player"; });

			events.push(BattleEvent(com, player, BattleEventType::ATTACK));
		}
	}

	// Take each event from the queue in turn and process them,
	// displaying the results
	while(!events.empty())
	{
		// Take event from the front of the queue
		BattleEvent event = events.front();
		switch(event.type)
		{
			case BattleEventType::ATTACK:
			{
				// The event can't be run if either the source or the
				// target were slain previously in this turn, so we
				// must check that they're valid first
				auto a = this->combatants.begin();
				auto b = this->combatants.end();
				if(std::find(a, b, event.source) == b || std::find(a, b, event.target) == b)
				{
					break;
				}
				std::cout << event.source->name
					<< " attacks "
					<< event.target->name
					<< " for "
					<< event.run()
					<< " damage!\n";
				// Delete slain enemies
				if(event.target->hp <= 0)
				{
					this->kill(event.target);
				}
				break;
			}
			case BattleEventType::DEFEND:
				std::cout << event.source->name
					<< " defends!\n";
				break;
			default:
				break;
		}
		events.pop();
	}
}