#include<iostream>
#include<string>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<ctime>
#include"functions.h"
#include"PLAYER.h"
#include"MONSTER.h"
using namespace std;
//split everything in main up into loops/functions/declarations/etc.
//include inventory system, random loot generation, shopkeepers
//make initiative rolls, random number generation for attacks, and armour class
//this way, who goes first is random, whether an attack hits is random, and it is based off AC and bonuses.
//for this, we need to add initiative members to MONSTER.cpp/h, and PLAYER.cpp/h,
//we also need AC for both of them, and a method to generate random numbers for attacks to each of them.
//once we have initiative and can determine who goes first, we can implement MONSTER::attack(int playerLevel, int monsterNum),
//we can have combat, and thus find out what is causing the error with spawns.
//also make weaponry for the player, and attacks for the player. probably check the if statements on doesSpawn.cpp over again.
int main()
{
srand(time(0));
string enviroDesc[64];
fstream inData; inData.open("environments.txt");//inData takes all 64 environment descriptions from environments.txt.
for(int i = 0; i < 64; i++) { getline(inData,enviroDesc[i]); }
int mapArray[8][8];
int currentLocation = 1;
for(int j = 0; j < 8; j++)
{
for(int k = 0; k < 8; k++) { mapArray[j][k] = (k+1)+(j*8); }
} //see array demonstration file at: https://onlinegdb.com/Hkss7xJo7
printInfo();
PLAYER mainCharacter;
char begin = beginAdventure();
bool playing = true;
if(begin == 'b')
{
bool inCombat = false; //we will use RNG to determine whether a monster spawns. if one does, inCombat = true, and another while loop executes. we want
int monsterInt = 0; //0 returns no monster, 1, 2, 3, 4 construct monsters to fight.
adventureText();
int spawnInt;
int MTYPE;
while(playing == true)
{
cout << "Map Coordinate: " << currentLocation << endl;
cout << enviroDesc[(currentLocation - 1)] << endl;
currentLocation +=movementReturn(currentLocation);
spawnInt = rand() % 100 + 1;
MTYPE = getMTYPE(currentLocation,spawnInt);//getMTYPE(); takes spawnInt and currentLocation, and ultimately returns the monsterType.
//returns 0 if no monster should spawn, so if statement evaluating whether or not it is 0 is necessary.
if(MTYPE == 0)
{
cout << "No monsters are currently present\n";
}
else if(MTYPE > 0)
{ //perhaps try making this a vector, which pushes back another new monster each time the loop executes in case the values still fuck up.
MONSTER theMonster(mainCharacter.level,MTYPE);
mainCharacter.initiative = mainCharacter.initiativeBonus + (rand() % 20 + 1);
//, if constructor value fucks up, uncomment and remove this text. theMonster.initiative = theMonster.initiativeBonus + (rand() % 20 + 1);
while(theMonster.health > 0)
{
if(theMonster.initiative > mainCharacter.initiative)
{
mainCharacter.health -= theMonster.attack();
//get player's action.
cout << "Test phase" << endl;
cin >> theMonster.health;
}
else if(mainCharacter.initiative >= theMonster.initiative)
{
cout << "Test phase" << endl;
cin >> theMonster.health;
mainCharacter.health -= theMonster.attack();
}
}
} //monster destructs, should reward player experience.
//monster needs to reach end of scope so it is reconstructed each time loop is executed.
//MONSTER theMonster(mainCharacter.level, monsterNum);
/*while(theMonster.health > 0 and mainCharacter.health > 0)
{
cout << "Test phase!" << endl;
cin >> theMonster.health;
if(theMonster.initative > mainCharacter.initiative)
{
mainCharacter.health -= theMonster.attack();//mainCharacter.health = mainCharacter.health - theMonster.attack(mainCharacter.playerLevel, )//make it so it doesn't take playerLevel, constructor should set mosnter level to be the same as player level regardless anyways.
mainWeapon.attack(); //we need a weapon class, that has damage, names, types, and is determined by class, RNG and ETC.
}
//outputOptions(//numHealthPotions), implement numhealthPotions later.
//returns int, determing what the player's action is.
//player.takeTurn()
//ask user what they want to do function, if 1, monsterHealth -= weapon.damage.
//if 2, player can use health potion from store.
//implement stores and stuff later though, that's too complex for now.
}
}
else
{
cout << "\nNo monsters seem to be present currently.\n";
//getAction(weaponDamage,numPotions,player.health,player.maxHealth,classNum),
//returns 1, 2, or 3, 1 being attack, 2 being heal if less than max hp and
}*/
//weapons need to be generated here, and there needs to be a weapon currentWeapon, as well as backPackWeapon[0,1,2]
//if the weapons reach the end of the scope, they're deallocated, so they have to exist within the initial while loop.
//doesSpawn checkSpawn(currentLocation);
//WE NEED TO ADD CHECKS AND TRYS TO STOP ERRORS AND PROGRAM TERMINATION.
//struct doesSpawn() has two members, spawnTF, and monsterNum.
//checkSpawn(int spawnInt); returns these variables, if spawnTF == 1, MONSTER monster1(playerLevel,monsterNum);
//inCombat = checkSpawn(currentLocation); checkSpawn takes location to determine spawn.
//getMonsterType(currentLocation); returns the monsterInt.
//create MONSTER of type monsterInt. constructor should display monster info.
//roll initiative, whoever has it higher goes first. player class determines bonus.
//while(inCombat == true)
//{
//if(monsterInitiative > playerInitiative)
//{ monster.attack(); }
//player.takeTurn.
//after player's action, monster attacks/takes an action.
}
}
else { return 1; }
//we need to make an inventory system, including gold, weapon types, weapons, and armour.
return 0;
}
#ifndef functions_H
#define functions_H
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
void printInfo();
char beginAdventure();
void adventureText();
int movementReturn(int currentPos);
int getMTYPE(int currentLocation,int spawnInt);
//int checkSpawn
#endif
#ifndef PLAYER_H
#define PLAYER_H
#include<iostream>
#include<string>
using namespace std;
struct PLAYER
{
public:
int initiative;
int initiativeBonus;
float health;
float maxHealth;
int AC;
int attackBonus;
int level; //level automatically set to 1 by constructor.
string className; //returned by getClass();
string charName;
float experience; //float because exponents will inevitably be involved.
float experienceNeeded;
void getClass(); //getClass runs with constructor
void getCharName();
void charInfo(); //charInfo() outputs stats, level, etc, whenever player asks for it.
PLAYER();//constructor sets health, level, experience points, etc.
void levelUp();
};
#endif
#include<iostream>
#include<string>
#include<iomanip>
#include"PLAYER.h"
using namespace std;
void PLAYER::getClass()
{
int classNum;
cout << "Pick class using the number corresponding to the class: ";
cin >> classNum;
if(classNum == 1)
{//fighter
PLAYER::className = "Fighter";
PLAYER::health = 20;
PLAYER::maxHealth = 20;
PLAYER::AC = 15;
PLAYER::attackBonus = 3;
PLAYER::level = 1;
PLAYER::initiativeBonus = 3;
PLAYER::experience = 0.0;
PLAYER::experienceNeeded = 30;
}
else if(classNum == 2)
{//wizard
PLAYER::className = "Wizard";
PLAYER::health = 10;
PLAYER::maxHealth = 10;
PLAYER::AC = 10;
PLAYER::attackBonus = 7;
PLAYER::level = 1;
PLAYER::initiativeBonus = 5;
PLAYER::experience = 0.0;
PLAYER::experienceNeeded = 30;
}
else if(classNum == 3)
{//ranger
PLAYER::className = "Ranger";
PLAYER::health = 15;
PLAYER::maxHealth = 15;
PLAYER::AC = 13;
PLAYER::attackBonus = 5;
PLAYER::initiativeBonus = 7;
PLAYER::level = 1;
PLAYER::experience = 0.0;
PLAYER::experienceNeeded = 30;
}
}
void PLAYER::getCharName()
{
cout << "Enter a name for your character: ";
cin.ignore();
getline(cin,charName,'\n');
}
void PLAYER::charInfo()
{
cout << charName << ", Level " << level << " " << className << endl;
cout << "Max health: " << maxHealth << endl;
cout << "Current Health: " << health << endl;
cout << "Experience: " << experience << endl;
cout << "Experience until level up: " << experienceNeeded << endl;
}
PLAYER::PLAYER()
{
PLAYER::getClass(); //When PLAYER types are created, constructor runs setting class of character.
PLAYER::getCharName();
PLAYER::charInfo();
}
void PLAYER::levelUp() //we need to check to see if exp >= expNeeded everytime exp is gained. If true, run this.
{
cout << "You leveled up! Displaying character information: " << endl;
PLAYER::level++;
PLAYER::maxHealth = maxHealth * 1.5;
PLAYER::health = maxHealth;
PLAYER::experienceNeeded = level * (level * 0.8) * 20; //monsters need to increase the experience gained at the same rate. monsterLevel * monsterLevel * 15, so that it slows.
PLAYER::charInfo();
}
#include"functions.h"
void printInfo() //prints basic information.
{
cout << "Welcome to Ryxaar's Dungeon Delver! Pick your class: " << endl;
cout << "1. Fighter, Close range jack of all trades\n";
cout << "2. Wizard, High damage but low defense, magical expert\n";
cout << "3. Ranger, Medium range sustained damage, ranged weapons expert\n";
}
char beginAdventure() //main takes char and uses if statements to evaluate next action.
{
cout << "To begin your adventure type ''b''\n";
cout << "To quit ''q''" << endl;
char begin;
cin >> begin;
return begin;
}
void adventureText()
{
cout << "Your adventure begins here. You descend into Ryxaar's dungeon. " << endl;
cout << "Walking down the steps, you see a large open room, with two paths, ";
cout << "one forwards, the other to the right." << endl;
}
int movementReturn(int currentPos)
{
int moveInput;
if((currentPos + 8) < 65) { cout << "Type 1 to move downwards. "; } //this one is good.
if((currentPos - 8) > 0) { cout << "Type 2 to move upwards. "; } //these work this way because I was a moron and programmed one of the variables wrong.
if(currentPos % 8 != 0 and (currentPos + 1) < 65) { cout << "Type 3 to move rightwards. "; } //basically up is down and down is up which is like
if((currentPos-1) % 8 != 0 and (currentPos - 1) > 0) { cout << "Type 4 to move leftwards. "; } //unfortunate, but nonetheless it works and runs, and doesn't really need changing.
cin >> moveInput;
if(moveInput == 1 and ( (currentPos +8) < 65) ) { return 8; } //we need to make the if statements stop the increase to stop segfaulting in case the user types something they shouldn't.
else if(moveInput == 2 and ( (currentPos -8) > 0) ) { return -8; }
else if(currentPos % 8 != 0 and moveInput == 3 and ( (currentPos +1) < 65) ){ return 1; }
else if((currentPos-1) % 8 != 0 and moveInput == 4 and ( (currentPos -1) > 0) ) { return -1; } //now the player can't move back once they reach an area divisible by 8.
else { cout << "You can't go that way " << endl; return 0; }
}
int getMTYPE(int currentLocation,int spawnInt)
{
//returns 0 if none of the if statements are met.
if(currentLocation > 1 and currentLocation <= 8)
{
if(spawnInt >= 80)
{ return 1; }
}
else if(currentLocation > 8 and currentLocation <= 16)
{
if(spawnInt >= 75 and spawnInt < 90)
{ return 1; }
else if(spawnInt >= 90)
{ return 2; }
}
else if(currentLocation > 16 and currentLocation <= 24)
{
if(spawnInt >= 70 and spawnInt < 85)
{ return 1; }
else if(spawnInt >= 85 and spawnInt < 95)
{ return 2; }
else if(spawnInt >= 95)
{ return 3; }
}
else if(currentLocation > 24 and currentLocation <= 32)
{
if(spawnInt >= 65 and spawnInt < 75)
{ return 1; }
else if(spawnInt >= 75 and spawnInt < 90)
{ return 2; }
else if(spawnInt >= 90)
{ return 3; }
}
else if(currentLocation > 32 and currentLocation <= 40)
{
if(spawnInt >= 65 and spawnInt < 70)
{ return 1; }
else if(spawnInt >= 70 and spawnInt < 85)
{ return 2; }
else if(spawnInt >= 85)
{ return 3; }
}
else if(currentLocation > 40 and currentLocation <= 48)
{
if(spawnInt >= 65 and spawnInt < 70)
{ return 2; }
else if(spawnInt >= 70 and spawnInt < 95)
{ return 3; }
else if(spawnInt >= 95)
{ return 4; }
}
else if(currentLocation > 48 and currentLocation <= 56)
{
if(spawnInt >= 65 and spawnInt < 90)
{ return 3; }
else if(spawnInt >= 90)
{ return 4; }
}
else if(currentLocation > 56 and currentLocation <= 64)
{
if(spawnInt >= 70 and spawnInt < 80)
{ return 3; }
else if(spawnInt >= 80)
{ return 4; }
}
return 0;
}
Environment 1
Environment 2
Environment 3
Environment 4
Environment 5
Environment 6
Environment 7
Environment 8
Big lad land
Environment 10
Environment 11
Environment 12
Environment 13
Environment 14
Environment 15
Environment 16
Environment 17
Environment 18
Environment 19
Environment 20
Environment 21
Environment 22
Environment 23
Environment 24
Environment 25
Environment 26
Environment 27
Environment 28
Environment 29
Environment 30
Environment 31
Environment 32
Environment 33
Environment 34
Environment 35
Environment 36
Environment 37
Environment 38
Environment 39
Environment 40
Environment 41
Environment 42
Environment 43
Environment 44
Environment 45
Environment 46
Environment 47
Environment 48
Environment 49
Environment 50
Environment 51
Environment 52
Environment 53
Environment 54
Environment 55
Environment 56
Environment 57
Environment 58
Environment 59
Environment 60
Environment 61
Environment 62
Environment 63
Environment 64
#ifndef MONSTER_H
#define MONSTER_H
using namespace std;
//we will probably need to turn a lot of these into floats.
struct MONSTER
{ //eventually try to use inheritance to simplify this code. using PLAYER.h
int monsterType; //determines basically everything during construction and destruction.
float health; //also determines when the destructor is called.
float maxHealth; //may not be necessary unless they regain health like PLAYERs do.
int level; // helps to determine attack, health, expReward, etc.
string monsterName; //returned by MONSTER::MONSTER(), based off of location. using equalities <, >, <=, >=.
int initiativeBonus;
int initiative; //determines who attacks first during combat.
int AC;
float expReward; //float because exponents will inevitably be involved.
float damage; //Determines how much damage will be dealt with attack(); Set by constructor.
float attack(); //returns amount of damage dealt to PLAYER.
float deathNote();
MONSTER();
MONSTER(int playerLevel, int monsterInt);
~MONSTER();
};
#endif
#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime>
#include"MONSTER.h"
using namespace std;
float MONSTER::attack()
{
srand(time(0));
int randomNum = 0;
//output attack, random generator to determine the attack
//utilizes monsterType and attackNum, randomly generated during constructor, to subtract health from the PLAYER.
//uses MONSTER::damage as int.
if(MONSTER::monsterType == 1)
{
randomNum = rand() % 1 + 1;
if(randomNum == 1)
{
cout << "The Baron scratches at you with his claws!" << endl;
}
else if (randomNum == 2)
{
cout << "From the Baron's hand flies a green ball of fire!" << endl;
}
}
else if(MONSTER::monsterType == 2)
{
if(randomNum == 1)
{
cout << "The heshefiend charges at you!" << endl;
}
else if(randomNum == 2)
{
cout << "The heshefiend bites you!" << endl;
}
}
else if(MONSTER::monsterType == 3)
{
if(randomNum == 1)
{
cout << "The Greater Baron's grapnels lacerate you!" << endl;
}
else if(randomNum == 2)
{
cout << "The Greater Baron throws a blazing ball of cursed flame!" << endl;
}
else if(randomNum == 3)
{
cout << "The Greater Baron jumps at you, leaving a shockwave!" << endl;
}
}
else if(MONSTER::monsterType == 4)
{
if(randomNum == 1)
{
cout << "The Eldritch Horror casts decay!" << endl;
}
else if(randomNum == 2)
{
cout << "The Eldritch Horror tosses a death tome!" << endl;
}
else if(randomNum == 3)
{
cout << "The Eldritch Horror dissapears!" << endl;
//ac bonus of 3 for three rounds.
}
}
}
float MONSTER::deathNote()
{
if(MONSTER::monsterType == 1)
{
cout << "You gain " << MONSTER::expReward << " experience" << endl;
return MONSTER::expReward;
}
}
MONSTER::MONSTER(int playerLevel, int monsterInt) //whenever constructor runs, it needs the player's level.
{
srand(time(0));
//monster is constructed, sets monsterType, which sets level, monsterName, health, maxhealth, then while(playerHealth >= 1) it attacks.
//should set monsterType, name, health, attack damage, etc. USE RNG to get monsterType.
MONSTER::monsterType = monsterInt;
if(MONSTER::monsterType == 1)
{
MONSTER::monsterName = "Baron";
cout << "A baron appears!" << endl;
MONSTER::level = playerLevel;
MONSTER::initiativeBonus = 2;
MONSTER::initiative = rand() % 20 + 1 + MONSTER::initiativeBonus;
MONSTER::AC = 12;
MONSTER::maxHealth = 15 * 1.2 * playerLevel;
MONSTER::health = MONSTER::maxHealth;
MONSTER::expReward = MONSTER::maxHealth/2;
}
else if(MONSTER::monsterType == 2)
{
MONSTER::monsterName = "Heshefiend";
cout << "A heshefiend appears!" << endl;
MONSTER::level = playerLevel;
MONSTER::initiativeBonus = -2;
MONSTER::initiative = rand() % 20 + 1 + MONSTER::initiativeBonus;
MONSTER::AC = 14;
MONSTER::maxHealth = 30 * 0.8 * playerLevel;
MONSTER::health = MONSTER::maxHealth;
MONSTER::expReward = MONSTER::maxHealth/1.5;
}
else if(MONSTER::monsterType == 3)
{
MONSTER::monsterName = "Greater Baron";
cout << "A Greater Baron appears!" << endl;
MONSTER::level = playerLevel;
MONSTER::initiativeBonus = 4;
MONSTER::initiative = rand() % 20 + 1 + MONSTER::initiativeBonus;
MONSTER::AC = 15;
MONSTER::maxHealth = 30 * 1.2 * playerLevel;
MONSTER::health = MONSTER::maxHealth;
MONSTER::expReward = MONSTER::maxHealth/1.3;
}
else if(MONSTER::monsterType == 4)
{
MONSTER::monsterName = "Eldritch Horror";
cout << "An Eldritch Horror appears!" << endl;
MONSTER::level = playerLevel;
MONSTER::initiativeBonus = 7;
MONSTER::initiative = rand() % 20 + 1 + MONSTER::initiativeBonus;
MONSTER::AC = 20;
MONSTER::maxHealth = 20 * playerLevel;
MONSTER::health = MONSTER::maxHealth;
MONSTER::expReward = MONSTER::maxHealth*2;
}
MONSTER::initiative = MONSTER::initiativeBonus + (rand() % 20 + 1);
}
MONSTER::~MONSTER()
{
cout << "You slayed the " << MONSTER::monsterName << "!" << endl;
}
#ifndef weapon_h
#define weapon_h
#include<string>
using namespace std;
struct weapon
{
int weaponType; //determines whether player can use the weapon or not depending on class.
float weaponTypeMult; //if weaponType matches classNum, mult = 1, else 0.5;
string weaponName; //determines name of weapon.
int rarity; //determines stat bonuses.
float rarityMultiplier; //determined by rarity.
float damage; //determines return value of weapon.attack(); when getAction(); is 1.
weapon(int playerLevel, int classNum); //when constructed, takes playerlevel and classNum to determine damage, halved if classNum != weaponType.
//also sets damage and weaponName based off rarity.
void getRarity(int rarityRand);
void getWeaponType(int typeRand, int classNum);
};
#endif
#include<iostream>
#include<string>
#include<cstdlib>
#include"weapon.h"
void weapon::getRarity(int rarityRand)
{
if(rarityRand < 30)
{
weapon::rarityMultiplier = 0.8;
weapon::rarity = 1;
}
else if(rarityRand >= 30 and rarityRand < 50)
{
weapon::rarityMultiplier = 1.0;
weapon::rarity = 2;
}
else if(rarityRand >= 50 and rarityRand < 75)
{
weapon::rarityMultiplier = 1.2;
weapon::rarity = 3;
}
else if(rarityRand >= 75 and rarityRand < 85)
{
weapon::rarityMultiplier = 1.4;
weapon::rarity = 4;
}
else if(rarityRand >= 85 and rarityRand < 95)
{
weapon::rarityMultiplier = 1.6;
weapon::rarity = 5;
}
else if(rarityRand >= 95 and rarityRand <= 100)
{
weapon::rarityMultiplier = 2.0;
weapon::rarity = 6;
}
else if(rarityRand == 0)
{
cout << "Either you're a developer and testing monsters and weapons out, or a serious error occured!" << endl;
weapon::rarity = 0;
weapon::damage = 10000;
weapon::rarityMultiplier = 5;
}
}
void weapon::getWeaponType(int typeRand, int classNum)
{
weapon::weaponType = typeRand;
if(classNum != typeRand) { weapon::weaponTypeMult = 0.75; }
else { weapon::weaponTypeMult = 1.0; }
switch(typeRand)
{
case 1: weapon::weaponName = "Sword"; break;
case 2: weapon::weaponName = "Staff"; break;
case 3: weapon::weaponName = "Bow"; break;
}
}
weapon::weapon(int playerLevel, int classNum)
{
srand(time(0));
int rarityRand = rand() % 100 + 1;
int typeRand = rand() % 3 + 1;
getRarity(rarityRand);
getWeaponType(typeRand, classNum);
weapon::damage = weapon::rarityMultiplier * (playerLevel * (playerLevel * .85)) * weapon::weaponTypeMult;
cout << "You found a Rarity " << weapon::rarity << " " << weapon::weaponName << ", and it deals " << weapon::damage << " damage! " << endl;
//ultimate goal is to return damage
}