I'm going to resurrect this. |
No worries, I'm always interested in new ideas.
Just some reference info:
The simple model: Damage is subtracted from Health.
Complex model: There are different behaviours for Weapon / Attacked object scenarios.
1 2 3
|
CPlayer Hero; //derived from CActor because of common attributes like Health
CEnemy Troll; //derived from CActor
CSword HeroSword; //Derived from CWeapon
|
or this instead:
1 2 3
|
CPlayer *pHero = new CPlayer ; //derived from CActor because of common attributes like Health
CEnemy *pTroll = new CEnemy ; //derived from CActor
CSword *pHeroSword = new CSword; //Derived from CWeapon
|
So, How to do this problem:
1. The worlds easiest, but somewhat bad solution
Have a getDamage function in CWeapon, and getHealth, setHealth in CEnemy.
Immediate problem - uses getter & setters which we are trying avoid, especially the public setHealth which is nonsense.
2. Have a virtual Attack & RecvAttack functions in CActor.
This is a initiate & handler scenario. An Attack is initiated by one object with the Attack function, and this handled by the object being attacked, with the RecvAttack function.
1 2 3 4
|
virtual bool Attack(CActor *pAttacker, CActor *pAttackee, CWeapon *pAWeapon){
return true; //so we can return some kind of success status - might use a status enum to be more fancy
}
|
The call to it would look like this:
|
pHero->Attack(this, pTroll, pHeroSword);
|
The Attacking object is included so the object being attacked can mount a counter attack.
Weapon could have a virtual Use function, which for the simple model just returns the damage. It is a getter in disguise. Can be redefined to carry out more complex behaviour.
Actor objects could have a virtual RecvAttack function, for the simple model subtracts the damage from health. It is a setter in disguise. Can be redefined to carry out more complex behaviour.
Although these function are getters /setters, they are virtual and in the base class, so they form an interface.
Problem - this implies a free for all, Player vs Player & Enemy vs Enemy - not what we want. Also want to avoid the situation with cheater objects ne555 just pointed out.
Possible partial solution - use RTTI to check whether it's a valid attack - that is, the the typeid's aren't equal.
3. Have a virtual Attack & RecvAttack functions in CPlayer & CEnemy
I tried doing this, but had problem with circular #includes. Tried forward declaration of classes, but couldn't get it to work for both situations. The code compiles, but I can't do any thing with a Player object in CEnemy.
In CEnemy.h
1 2 3 4 5
|
class CPlayer; //fwd declaration to avoid circular includes
// cannot do anything with a Player object
virtual bool Attack(CEnemy *, CPlayer *, CWeapon *);
virtual bool RecvAttack(CPlayer * , CWeapon * ) ;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
#include "/home/david/projects/RGP/CActor.h"
#include "/home/david/projects/RGP/weapon/CWeapon.h"
#include "/home/david/projects/RGP/enemy/CEnemy.h"
class CPlayer : public CActor
{
public:
CPlayer();
virtual ~CPlayer();
virtual bool Attack(CPlayer *, CEnemy *, CWeapon *);
virtual bool RecvAttack(CEnemy * , CWeapon * ) ;
};
|
4. Have a virtual RecvAttack function in CActor - no Attack function
The arguments would be the attacking object & the weapon. Would need RTTI to check validity of the attacking object. Is simpler because there is 1 function not 2. Doesn't solve the cheater problem
OK, so those are my ideas so far. Am interested to hear how to solve the cheater problem.