-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCharacter.cc
232 lines (210 loc) · 6.87 KB
/
Character.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include "Character.h"
#include <string>
#include <math.h>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <iostream>
#include "floor.h"
using namespace std;
std::pair<int,int> Character::radius[8] = {std::make_pair(-1,0), std::make_pair(1,0), std::make_pair(0,1), std::make_pair(0,-1),
std::make_pair(1,-1), std::make_pair(-1,1), std::make_pair(1,1), std::make_pair(-1,-1)};
// Character Constructor, has the cell's location, the symbol, a pointer to the floor, the characteristics, and the amount of gold carried.
Character::Character(int x, int y, char symbol, int health, int attack, int defense, std::string race, int gold):
GameObject(x,y,symbol),
health(health),
attack(attack),
defense(defense),
race(race),
gold(gold)
{}
// Character Destructor:
Character::~Character() {}
int Character::getHP() {
return health;
}
int Character::getAtk() {
return attack;
}
int Character::getDef() {
return defense;
}
int Character::getGold(){
return gold;
}
std::string Character::getRace() {
return race;
}
void Character::setHP(int hp){
health = hp;
}
void Character::setAtk(int at){
attack = at;
}
void Character::setDef(int def){
defense = def;
}
void Character::setGold(int g){
gold = g;
}
std::string translation(std::string dir){
if(dir == "no") return "North";
else if(dir == "so") return "South";
else if(dir == "ea") return "East";
else if(dir == "we") return "West";
else if(dir == "ne") return "NorthEast";
else if(dir == "nw") return "NorthWest";
else if(dir == "se") return "SouthEast";
else if(dir == "sw") return "SouthWest";
else { return "Invalid Coordinate"; }
}
// This function, moves/shifts the character in the specific direction.
void Character::shift(std::string dir, Floor *g){
int old_x = getx();
int old_y = gety();
int new_x,new_y;
if(dir == "no"){
new_x = getx()-1;
new_y = gety();
}
else if(dir == "so"){
new_x = getx()+1;
new_y = gety();
}
else if(dir == "ea"){
new_x = getx();
new_y = gety()+1;
}
else if(dir == "we"){
new_x = getx();
new_y = gety()-1;
}
else if(dir == "ne"){
new_x = getx()-1;
new_y = gety()+1;
}
else if(dir == "nw"){
new_x = getx()-1;
new_y = gety()-1;
}
else if(dir == "se"){
new_x = getx()+1;
new_y = gety()+1;
}
else if(dir == "sw"){
new_x = getx()+1;
new_y = gety()-1;
}
else {
new_x = getx();
new_y = gety();
}
// A floor point to the grid the character is on. First checks, if the new cell where the player is trying to move is valid for player to move or not. If it is valid, and if the new cell has gold object on it, then it creates a GameObject pointer to store the gold. Now if the gold is pickable (i.e. not the dragon gold), then the gold value get's added to the gold carried by the player. The player is shifted to the new cells and removed from the old location.
// Floor *g = this->getGrid();
bool isPlayer = false;
if(getSymbol() == '@'){
isPlayer = true;
}
bool valid = g->isCellValid(new_x, new_y, isPlayer);
if(isPlayer && g->getSymbol(new_x, new_y) == '\\') setLevel(getLevel() + 1);
std::ostringstream ss;
if (valid) {
if(this->getRace() == "Troll"){ //Every time troll moves, gets 5 points.
if(((this->getHP()) + 5) > 120){
this->setHP(120);
}
else{
this->setHP((this->getHP()) + 5);
}
}
if((g->getSymbol(new_x, new_y)) == 'G'){
GameObject *gold = g->getObj(new_x, new_y);
if(gold->getPickable()){
ss << "PC picks up " << gold->getGold() << " gold. ";
std::string s = ss.str();
setGold(gold->getGold()+this->getGold());
}
delete gold;
}
setx(new_x);
sety(new_y);
g->objectAdd(new_x, new_y,this);
g->objectRemove(old_x, old_y);
if(getSymbol() == '@'){
callAction(g);
}
if(isPlayer){
ss << "PC moves " << translation(dir);
std::string s = ss.str();
setMessage(s);
}
}
}
// The strike function calculates the damage when one character attacks the other, and it manipulates the health points.
void Character::strike(GameObject *c, Floor *g){
// Troll gains 5 HP every turn; Capped at Max Health
if(this->getRace() == "Troll"){
if(((this->getHP()) + 5) > 120){
this->setHP(120);
}
else{
this->setHP((this->getHP()) + 5);
}
}
// Vampire gains 5 HP for every attack but loses 5HP for every attack on dwarf
if(this->getRace() == "Vampire"){
if (c->getSymbol() != 'W')
this->setHP(this->getHP() + 5);
else
this->setHP(this->getHP() - 5);
}
// Calculate damage
double temp = c->getDef();
double damage = ceil((100/(100+temp))*(this->getAtk()));
// Orcs do 50% more damage to goblins
if ((this->getSymbol() == 'O') && (c->getRace() == "Goblin"))
damage *= 1.5;
// If enemy dies call their death function.
if((c->getHP() - damage) <= 0){
c->setHP(0);
if (c->getSymbol() != '@'){
c->enemyDeath(*this,g);
delete c;
return;
}
}
else{
c->setHP(c->getHP() - damage);
}
if(this->getSymbol() == '@'){
//double oppDamage = ceil((100/(100+getDef()))*(c.getAtk()));
std::ostringstream ss;
ss << "PC deals " << damage << " to " << c->getRace() << ". HP left: " << c->getHP();
std::string s = ss.str();
setMessage(s);
}
}
// BeStruckBY function means Character A is struck by Character B. So, B strikes A, hence it calls the strike function.
void Character::beStruckBy(GameObject *c, Floor *g){
int hit = 1; // If 1 then hit; if 0 then miss
std::srand(time(0));
// Enemies have a 50% chance of striking the player (ie if player is being struck by an enemy, there is a 50% chance of calling strike(player).Players have a 50% chance of striking a halfling, i.e if halfing is being struck by player, there is a 50% chance of calling strike(halfling)
if((this->getSymbol() == '@') || (this->getSymbol() == 'L')){
hit = std::rand() % 2;
}
if(hit == 1){
c->strike(this,g);
// If a Merchant is attacked for the first time; set merchantHostile to true
if(this->getSymbol() == 'M'){
c->setMerchantHostile();
}
// Elf can strike each race except Drow twice (it still has 50% chance of hitting)
else if((c->getSymbol()) == 'E'){
hit = std::rand() % 2;
if(!(this->getRace() == "Drow") && (hit == 1)){
if(c) c->strike(this,g);
}
}
}
c->callAction(g);
}