c++ array of an object resets, after it gets changed in a method

126 Views Asked by At

im new to c++, i learned java at the university. I was trying to start with a small beginner project. A console rpg. i made a GameEntity class, a player class that inherits the GameEntity class and some enums: GameType, Stats

int main(){

    GameEntity *opponent = new GameEntity("enemy", 20, 3, 4);
    Player *player = new Player("player", 40, 4, 4);

    //initialize combatStats
    player->prepareForCombat();
    opponent->prepareForCombat();

    int r = 0;
    while(!player->isDead() && !opponent->isDead()){
        player->chooseMove(*opponent, r);
        opponent->chooseMove(*player, r);
        r++;
    }
    if(!player->isDead()){
        cout << "you won!";
    }else{
        cout << "you lost!";
    }

    return 0;
}

My Problem: i have an array for all the Stats, including hp. int combatStats[7]; and a method to decrease the hp in GameEntity:

void decreaseHp(int damage)
    {
        if(damage <= 0)return;
        combatStats[Hp] = combatStats[Hp] - damage;
        cout << name << ": gets "<< damage << " damage." << '\n';
        cout << name << ": current health: " << getHp() << '\n';
        if(combatStats[Hp] <= 0){
            die();
        }
    }

the method changes the hp to its correct value and prints it out, but it changes back to its initial state, after the method stops.

i expected that an array doesn't, resets its value itself.

it had a private access modifyer, so i tried changing it to public, it did nothing.

here is the whole code:

//#include "GameEntity.cpp";
//#include "Player.cpp";
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::string;

enum Stats{
    Hp = 0,Mind = 1,Str = 2,Dex = 3,End = 4,Int = 5,Wis = 6
};
enum GameType{
    thrust,slash,bludgeon,light,dark,heat,cold, mind, arcane
};

class GameEntity{
    protected:
        int baseStats[7];
        string name;
        bool isAllive = true;
        int blockVal = 0;
        
    public:
        GameEntity(string name, int hp, int pVal, int mVal){
            this->name = name;
            baseStats[Hp] = hp;
            baseStats[Mind] = 100;
            baseStats[Str] = pVal;
            baseStats[Dex] = pVal;
            baseStats[End] = hp/10;
            baseStats[Int] = mVal;
            baseStats[Wis] = mVal;
        }
        int combatStats[7];
        string getName(){return name;}
        int getHp(){return combatStats[Hp];}
        int getDex(){return combatStats[Dex];}
        int getInt(){return combatStats[Int];}
        int getEnd(){return combatStats[End];}
        int getStr(){return combatStats[Str];}
        int getWis(){return combatStats[Wis];}
        int getMind(){return combatStats[Mind];}
        void incrementDex(int i){combatStats[Dex] += i;}
        void incrementInt(int i){combatStats[Int]+= i;}
        void incrementEnd(int i){combatStats[End]+= i;}
        void incrementStr(int i){combatStats[Str]+= i;}
        void incrementWis(int i){combatStats[Wis]+= i;}
        void decrementDex(int d){combatStats[Dex]-= d;}
        void decrementInt(int d){combatStats[Int]-= d;}
        void decrementEnd(int d){combatStats[End]-= d;}
        void decrementStr(int d){combatStats[Str]-= d;}
        void decrementWis(int d){combatStats[Wis]-= d;}

    void chooseMove(GameEntity target, int round){
        cout << name << " health: " << combatStats[Hp] << '\n';
        blockVal = 0;
        if(round%2 == 0){
            cout << name << ": does a slash attack." << '\n';
            target.damage(10 , GameType::slash);
        }
        else if(round == 5 || round == 12){
            heal(5, GameType::light);
        }
        else{
            block(8);
        }
    }
    void damage(int damage, GameType type){
        if(blockVal > damage){
            blockVal -= damage;
            cout << name << ": blocked "<< damage << " damage." << '\n';
            damage = 0;
        }else if(blockVal < damage){
            damage -= blockVal;
            cout << name << ": blocked "<< blockVal << " damage." << '\n';
            blockVal = 0;
        }else{
            cout << name << ": blocked all damage. ("<< blockVal << ")" << '\n';
            damage = 0;
            blockVal = damage;
        }

        switch(type){
            case GameType::arcane: 
                decreaseHp(damage);
                break;
            default:
                cout << name << ": endured "<< combatStats[End] << " damage." << '\n';
                decreaseHp(damage-combatStats[End]);
                break;
        }
    }
    
    void heal(int healing, GameType type){
        if(type == GameType::light){
            combatStats[Hp] += healing;
            cout << name << ": healed by "<< healing << '\n';
        }
        if(combatStats[Hp] > baseStats[Hp]){
            combatStats[Hp] = baseStats[Hp];
        }
    }
    void block(int block){
        blockVal = block;
        cout << name << ": prepares to block." << '\n';
    }

    bool isDead(){
        return !isAllive;
    }

    void prepareForCombat(){
        combatStats[Hp] = baseStats[Hp];
        combatStats[Mind] = baseStats[Mind];
        combatStats[Str] = baseStats[Str];
        combatStats[Dex] = baseStats[Dex];
        combatStats[End] = baseStats[End];
        combatStats[Int] = baseStats[Int];
        combatStats[Wis] = baseStats[Wis];
    }
    
    void decreaseHp(int damage)
    {
        if(damage <= 0)return;
        combatStats[Hp] = combatStats[Hp] - damage;
        cout << name << ": gets "<< damage << " damage." << '\n';
        cout << name << ": current health: " << getHp() << '\n';
        if(combatStats[Hp] <= 0){
            die();
        }
    }

    void die(){
        cout << name << ": died" << '\n';
        isAllive = false;
    }
};
class Player : public GameEntity
{
    public:
        using GameEntity::GameEntity;
        //using GameEntity::isDead;
        void chooseMove(GameEntity target, int round){
            cout << name << " health: " << combatStats[Hp] << '\n';
            blockVal = 0;
            cout <<"System: what do you want to do?" << '\n';
            cout <<"1) slash attack" << '\n';
            cout <<"2) punch" << '\n';
            cout <<"3) riposte" << '\n';
            cout <<"4) heal" << '\n';
            cout <<"5) block" << '\n';
            string input;
            cin >> input;
            switch (stoi(input))
            {
            case 1:
                cout << name << ": does a slash attack." << '\n';
                target.damage(10 , GameType::slash);
                break;
            case 2:
                cout << name << ": punches " << target.getName() << " really hard"<< '\n';
                target.damage(4 , GameType::bludgeon);
                block(2);
                break;
            case 3:
                cout << name << ": hits " << target.getName() << " and retracts, really fast"<< '\n';
                target.damage(7, GameType::thrust);
                block(5);
                break;
            case 4:
                cout << name << ": channels the light element"<< '\n';
                target.damage(7, GameType::thrust);
                heal(4, GameType::light);
                break;
            case 5:
                block(12);
            
            default:
                break;
            }
        }
};

int main(){

    GameEntity *opponent = new GameEntity("enemy", 20, 3, 4);
    Player *player = new Player("player", 40, 4, 4);

    player->prepareForCombat();
    opponent->prepareForCombat();

    int r = 0;
    while(!player->isDead() && !opponent->isDead()){
        player->chooseMove(*opponent, r);
        opponent->chooseMove(*player, r);
        r++;
    }
    if(!player->isDead()){
        cout << "you won!";
    }else{
        cout << "you lost!";
    }

    return 0;
}

1

There are 1 best solutions below

0
john On

Here's the problem

void chooseMove(GameEntity target, int round){

As suspected you are changing target which is a copy of the object you actually want to change. Just change your code to use a reference

void chooseMove(GameEntity& target, int round){

In Java all object variables are references automatically. This is not true in C++. Here is the first clue that learning C++ means unlearning Java.

And a free piece of advice, don't use new here, just

GameEntity opponent("enemy", 20, 3, 4);
Player player("player", 40, 4, 4);

(and consequent changes in the rest of main).