/*Adam Obenauf, ml224/17/11project2.cppText based rpg game based on the combat system of eve online*///Preprocessor directives#include<iostream>#include<iomanip>#include<cmath>#include<string>#include<fstream>#include <stdio.h>#include <stdlib.h>#include <time.h>#include "prompts.h"#include "attributecalc.h"#include "display.h"using namespace std;//Structuresstruct ship{ int size; int velocity; int damageBonusShield; int damageBonusArmor; int damage; int shieldHitPoints; int armorHitPoints; int hullHitPoints; int accuracyFalloff; int optimalRange; float trackingSpeed;};//Function prototypes//CalculateShipAttributes//Return type: ship//Parameters: int specialization, int size, int primaryWeaponChoice, int ammoChoice//This function calculates the attributes of a ship based on specialization/size/weapon choice/ammo choice and returns that shipship CalculateShipAttributes (int specialization, int size, int primaryWeaponChoice, int ammoChoice);//WriteShipFile//Return type: void//Parameters: ship myShip, string shipName//This function is passed a ship and the name of the file and writes the data to that file void WriteShipFile (ship myShip, string shipName);//LoadShip//Return type: ship//Parameters: string shipName//This function is passed the name of a file, it reads the data from that file and returns it as a shipship LoadShip(string shipName);//DoesFileExist//Return type: bool//Parameters: string shipName//This function is passed the name of a file and checks if the file exists, it returns true/false based on whether it exists or notbool DoesFileExist(string shipName);//RandomNum//Return type: int//Parameters: int lo, int hi//This function is passed two numbers and returns a random number between them (inclusive)int RandomNum(int lo, int hi);//DisplayShipAttributes//Return type: void//Parameters: ship playerShip//This function is passed a ship and displays the attributes of that shipvoid DisplayShipAttributes(ship playerShip);//IsHit//Return type: bool//Parameters: float accuracyFalloff, float optimalRange, float currentRange, float velocity, float trackingSpeed//This function is passed a bunch of attributes and returns whether or not the person attacking hit the targetbool IsHit(float accuracyFalloff, float optimalRange, float currentRange, float velocity, float trackingSpeed);//UpdateShipWeapon//Return type: void//Parameters: int size, int weaponChoice, int ammoChoice, ship myShip passed by reference//This function updates some of a ships's attributes when a weapon change occursvoid UpdateShipWeapon(int size, int weaponChoice, int ammoChoice, ship& myShip);//PercHealth//Return type: float//Parameters: int current, string shipName, int healthType//This function calculates the percentage of health remaining by using current health, originalHealth (reads this from a file), and health typefloat PercHealth (int current, string shipName, int healthType);//PlayerAttacksEnemy//Return type: void//Parameters: ship playerShip passed by reference, ship enemyShip passed by reference, int currentRange//This function updates the enemyShips shield/armor/hull hitpoints based on damage inflicted by the player from a hit (if the hit is successful), it displays a message about whether you hit the enemy or not and how much damage you inflicted to shields/armor/hull void PlayerAttacksEnemy(ship playerShip, ship& enemyShip, int currentRange);//EnemyAttacksPlayer//Return type: void//Parameters: ship playerShip passed by reference, ship enemyShip passed by reference, int currentRange//This function updates the playerShips shield/armor/hull hitpoints based on damage inflicted by the enemy from a hit (if the hit is successful), it displays a message about whether the enemy hit you or not and how much damage it inflicted to your shields/armor/hull void EnemyAttacksPlayer(ship& playerShip, ship enemyShip, int currentRange);//DisplayCombatStats//Return type: void//Parameters: ship playerShip, ship enemyShip//This function displays current range, and everybody's healthvoid DisplayCombatStats(ship playerShip, ship enemyShip, int currentRange);//Main functionint main(){ srand((unsigned)time(0)); //Declare variables int menuChoice = 0; ship playerShip; ship enemyShip; string shipName = ""; bool fileExists; int shipMenu = 0; int specialization = 0; int size = 0; int weaponChoice = 0; int ammoChoice = 0; int currentRange = 0; int combatChoice = 0; cout<<endl<<"Welcome to blah blah blah"; do { cout<<endl; menuChoice = MainMenu(); //Instructions if(menuChoice==1) { cout<<endl<<"Instructions go here"; } //Actual game else if(menuChoice==2) { shipName="PlayerShip.txt"; fileExists=DoesFileExist(shipName); if(fileExists==true) { playerShip=LoadShip(shipName); //actual game begins here //Generate enemy vessel //Make it the same size as the player vessel, everything else is random shipName="EnemyShip.txt"; size=RandomNum(1,3); specialization=RandomNum(1,3); weaponChoice=RandomNum(1,4); ammoChoice=RandomNum(1,4); enemyShip=CalculateShipAttributes (specialization, size, weaponChoice, ammoChoice); WriteShipFile (enemyShip, shipName); cout<<endl<<"The enemy has the following attributes:"<<endl; DisplayShipAttributes (enemyShip); //Nested for loops go here //Combat do while loop do { //If the player is faster than the enemy they set the range if(playerShip.velocity>=enemyShip.velocity) { currentRange=playerShip.optimalRange; } else { currentRange=enemyShip.optimalRange; } DisplayCombatStats(playerShip, enemyShip, currentRange); combatChoice = PromptCombatChoice(); //Player attacks enemy if(combatChoice==1) { PlayerAttacksEnemy(playerShip, enemyShip, currentRange); } //Player switches weapon/ammo else if(combatChoice==2) { weaponChoice = PromptWeaponChoice(); ammoChoice = PromptAmmoChoice(); UpdateShipWeapon(playerShip.size, weaponChoice, ammoChoice, playerShip); } //Player attempts escape, only succesfull if they are faster than the enemy else if(combatChoice==3) { if(playerShip.velocity>enemyShip.velocity) { cout<<endl<<endl<<"You escaped!"; } else { cout<<endl<<endl<<"You are not fast enough to escape."; } } EnemyAttacksPlayer(playerShip, enemyShip, currentRange); //Set anything that is negative to 0 if(playerShip.shieldHitPoints<0) { playerShip.shieldHitPoints=0; } if(playerShip.armorHitPoints<0) { playerShip.armorHitPoints=0; } if(playerShip.hullHitPoints<0) { playerShip.hullHitPoints=0; } if(enemyShip.shieldHitPoints<0) { enemyShip.shieldHitPoints=0; } if(enemyShip.armorHitPoints<0) { enemyShip.armorHitPoints=0; } if(enemyShip.hullHitPoints<0) { enemyShip.hullHitPoints=0; } } while(enemyShip.hullHitPoints>0 && playerShip.hullHitPoints>0); //Either the enemy or player has died if(enemyShip.hullHitPoints==0) { cout<<endl<<endl<<"Congradulations! You have defeated the enemy!"; } else if(playerShip.hullHitPoints==0) { cout<<endl<<endl<<"Your enemy has destroyed you. Please try again."; } } else { cout<<endl<<"Error. File does not exist. Please create a ship first."; } } //Create else if(menuChoice==3) { shipName="PlayerShip.txt"; specialization = PromptSpecialization(); size = PromptSize(); weaponChoice = PromptWeaponChoice(); ammoChoice = PromptAmmoChoice(); playerShip=CalculateShipAttributes (specialization, size, weaponChoice, ammoChoice); playerShip.size=size; WriteShipFile (playerShip, shipName); //Go ahead and automatically load the ship they just created in case they forget cout<<endl<<"Your ship has the following attributes:"<<endl; DisplayShipAttributes (playerShip); } //Display else if(menuChoice==4) { shipName="PlayerShip.txt"; fileExists=DoesFileExist(shipName); if(fileExists==true) { playerShip=LoadShip(shipName); cout<<endl<<"Your ship has the following attributes:"<<endl; DisplayShipAttributes (playerShip); } else { cout<<endl<<"Error. File does not exist. Please create a ship first."; } } //View high scores else if(menuChoice==5) { cout<<"Unavailible at the moment."<<endl; } //Quit else if(menuChoice==6) { cout<<endl<<"Have a nice day!"; } } while(menuChoice!=6); cout<<endl; return 0;}ship CalculateShipAttributes (int specialization, int size, int primaryWeaponChoice, int ammoChoice){ ship myShip; //Calculate the attributes myShip.velocity = CalcVelocity(size); myShip.damage = CalcDamage (size, primaryWeaponChoice); myShip.shieldHitPoints = CalcShields (size); myShip.armorHitPoints = CalcArmor (size); myShip.hullHitPoints = CalcHull (size); myShip.accuracyFalloff = CalcAccuracyFalloff (size, primaryWeaponChoice); myShip.optimalRange = CalcOptimalRange (size, primaryWeaponChoice); myShip.trackingSpeed = CalcTrackingSpeed (size, primaryWeaponChoice); CalcDamageBonuses (myShip.damageBonusShield, myShip.damageBonusArmor, ammoChoice, myShip.damage); //Specializations if(specialization==1) { myShip.velocity = myShip.velocity * 2; } else if(specialization==2) { myShip.shieldHitPoints=myShip.shieldHitPoints * 2; } else if(specialization==3) { myShip.armorHitPoints=myShip.armorHitPoints * 2; } return myShip;}void UpdateShipWeapon(int size, int weaponChoice, int ammoChoice, ship& myShip){ myShip.damage = CalcDamage (size, weaponChoice); myShip.accuracyFalloff = CalcAccuracyFalloff (size, weaponChoice); myShip.optimalRange = CalcOptimalRange (size, weaponChoice); myShip.trackingSpeed = CalcTrackingSpeed (size, weaponChoice); CalcDamageBonuses (myShip.damageBonusShield, myShip.damageBonusArmor, ammoChoice, myShip.damage);}void WriteShipFile (ship myShip, string shipName){ //Write it to a file ofstream outputFile; outputFile.open(shipName.c_str()); outputFile<<myShip.size<<endl; outputFile<<myShip.velocity<<endl; outputFile<<myShip.damageBonusShield<<endl; outputFile<<myShip.damageBonusArmor<<endl; outputFile<<myShip.damage<<endl; outputFile<<myShip.shieldHitPoints<<endl; outputFile<<myShip.armorHitPoints<<endl; outputFile<<myShip.hullHitPoints<<endl; outputFile<<myShip.accuracyFalloff<<endl; outputFile<<myShip.optimalRange<<endl; outputFile<<myShip.trackingSpeed<<endl; outputFile.close();}bool IsHit(float accuracyFalloff, float optimalRange, float currentRange, float velocity, float trackingSpeed){ float hitChance = 0.0; int randomNum = 0; //in radians/s float angularVelocity = velocity/currentRange; //angular speed of the enemy is greater than tracking speed of the turret if(angularVelocity>trackingSpeed) { return false; } //Extremely close range else if (currentRange < accuracyFalloff) { return true; } else if (currentRange >= accuracyFalloff) { //calculate hitChance hitChance = 1.f - abs(optimalRange - currentRange) / accuracyFalloff * 0.5f; //If we have 1/6 chance for example that's 0.15. 0.15 times 1000 is 150, we pick a random number between 0 and 1000 and we'll have a 1/6th chance of it being less than or equal to 150 randomNum=RandomNum(0,1000); if (hitChance*1000 <= randomNum) { return true; } else if(hitChance*1000 > randomNum) { return false; } }}int RandomNum(int lo, int hi) { // note: floor() really only needed if hi < 0 int range = (hi - lo+1); return rand()%range+lo;}ship LoadShip(string shipName){ ship Ship1; ifstream inputFile; inputFile.open(shipName.c_str()); inputFile>>Ship1.size; inputFile>>Ship1.velocity; inputFile>>Ship1.damageBonusShield; inputFile>>Ship1.damageBonusArmor; inputFile>>Ship1.damage; inputFile>>Ship1.shieldHitPoints; inputFile>>Ship1.armorHitPoints; inputFile>>Ship1.hullHitPoints; inputFile>>Ship1.accuracyFalloff; inputFile>>Ship1.optimalRange; inputFile>>Ship1.trackingSpeed; inputFile.close(); return Ship1;}bool DoesFileExist(string shipName){ ifstream inputFile; inputFile.open(shipName.c_str()); if(inputFile.fail()) { return false; } else { return true; }}void DisplayShipAttributes (ship playerShip){ //Display everything cout<<"Velocity: \t\t\t"<<playerShip.velocity<<" meters per second"<<endl; cout<<"Base damage: \t\t\t"<<playerShip.damage<<" hitpoints"<<endl; cout<<"Bonus damage against shields: \t"<<playerShip.damageBonusShield<<" hitpoints"<<endl; cout<<"Bonus damage against armor: \t"<<playerShip.damageBonusArmor<<" hitpoints"<<endl; cout<<"Shields: \t\t\t"<<playerShip.shieldHitPoints<<" hitpoints"<<endl; cout<<"Armor: \t\t\t"<<playerShip.armorHitPoints<<" hitpoints"<<endl; cout<<"Hull: \t\t\t\t"<<playerShip.hullHitPoints<<" hitpoints"<<endl; cout<<"Accuracy falloff: \t\t"<<playerShip.accuracyFalloff<<" meters"<<endl; cout<<"Optimal range: \t\t"<<playerShip.optimalRange<<" meters"<<endl; cout<<"Tracking speed: \t\t"<<playerShip.trackingSpeed<<" radians per second"<<endl;}//Make a function to get the percentage remaining health, but use 50 instead of 100float PercHealth (int current, string shipName, int healthType){ ship myShip=LoadShip(shipName); float fcurrent = current; float fpoints; if(healthType==1) { fpoints = myShip.shieldHitPoints; } else if(healthType==2) { fpoints = myShip.armorHitPoints; } else if(healthType==3) { fpoints = myShip.hullHitPoints; } return (fcurrent/fpoints) * 100;}void PlayerAttacksEnemy(ship playerShip, ship& enemyShip, int currentRange){ if (IsHit(playerShip.accuracyFalloff, playerShip.optimalRange, currentRange, enemyShip.velocity, playerShip.trackingSpeed)==true) { //Player deals damage cout<<endl<<endl<<"You hit the enemy!"; if(enemyShip.shieldHitPoints>0) { enemyShip.shieldHitPoints=enemyShip.shieldHitPoints-(playerShip.damage + playerShip.damageBonusShield); cout<<endl<<"You dealt "<<playerShip.damage + playerShip.damageBonusShield<<" damage to the enemy's shields."; } else if(enemyShip.armorHitPoints>0) { enemyShip.armorHitPoints=enemyShip.armorHitPoints-(playerShip.damage + playerShip.damageBonusArmor); cout<<endl<<"You dealt "<<playerShip.damage + playerShip.damageBonusArmor<<" damage to the enemy's armor."; } else if (enemyShip.armorHitPoints<=0) { enemyShip.hullHitPoints=enemyShip.hullHitPoints-playerShip.damage; cout<<endl<<"You dealt "<<playerShip.damage<<" damage to the enemy's hull"; } } else { //Player misses the enemy cout<<endl<<endl<<"You missed!"; }}void EnemyAttacksPlayer(ship& playerShip, ship enemyShip, int currentRange){ //Enemy attacks player if (IsHit(enemyShip.accuracyFalloff, enemyShip.optimalRange, currentRange, playerShip.velocity, enemyShip.trackingSpeed)==true) { //enemy hits cout<<endl<<endl<<"The enemy hit you!"; if(playerShip.shieldHitPoints>0) { playerShip.shieldHitPoints=playerShip.shieldHitPoints-(enemyShip.damage + enemyShip.damageBonusShield); cout<<endl<<"The enemy dealt "<<enemyShip.damage + enemyShip.damageBonusShield<<" damage to your shields."; } else if(playerShip.armorHitPoints>0) { playerShip.armorHitPoints=playerShip.armorHitPoints-(enemyShip.damage + enemyShip.damageBonusArmor); cout<<endl<<"The enemy dealt "<<enemyShip.damage + enemyShip.damageBonusArmor<<" damage to your armor."; } else if(playerShip.armorHitPoints<=0) { enemyShip.hullHitPoints=enemyShip.hullHitPoints-playerShip.damage; cout<<endl<<"The enemy dealt "<<enemyShip.damage<<" damage to your hull."; } } else { //Enemy misses cout<<endl<<endl<<"The enemy missed you!"; }}void DisplayCombatStats(ship playerShip, ship enemyShip, int currentRange){ float percHealth = 0.0; //Display current range and everyone's health cout<<endl<<endl<<"Current Range: "<<currentRange<<"km"; cout<<fixed<<setprecision(0); cout<<endl<<"Your shields: "; percHealth = PercHealth (playerShip.shieldHitPoints, "PlayerShip.txt", 1); cout<<percHealth<<"%"; /* DisplayHealthBar(percHealth); */ cout<<endl<<"Your armor: "; percHealth = PercHealth (playerShip.armorHitPoints, "PlayerShip.txt", 2); cout<<percHealth<<"%"; cout<<endl<<"Your hull: "; percHealth = PercHealth (playerShip.hullHitPoints, "PlayerShip.txt", 3); cout<<percHealth<<"%"; cout<<endl; cout<<endl<<"Enemy shields: "; percHealth = PercHealth (enemyShip.shieldHitPoints, "EnemyShip.txt", 1); cout<<percHealth<<"%"; cout<<endl<<"Enemy armor: "; percHealth = PercHealth (enemyShip.armorHitPoints, "EnemyShip.txt", 2); cout<<percHealth<<"%"; cout<<endl<<"Enemy hull: "; percHealth = PercHealth (enemyShip.hullHitPoints, "EnemyShip.txt", 3); cout<<percHealth<<"%";}