dribeas said:
That is, in the scope of main, neither pa nor fuptr are defined. They are defined in the class scope and you must access them through a class instance. Change the lines in main to:
62: printf("a as pointer = %d\n", *(xobject.pa));
65: (xobject.*(xobject.fuptr))(199);
Then again, the important question is what is the rationale that has lead you into trying to write this overly complex solution. If you provide a small description of what you are trying to achieve I am sure others can comment on better more simpler designs. Unless, of course, what you want to achieve is understanding of member to pointers.
First: many thanks for this perfect answer. That was very very useful.
62: printf("a as pointer = %d\n", *(xobject.pa)); I think i understand line 62, that's my fault, i guess - stupid one, i confused the simple pointer with the member function pointer.
65: (xobject.*(xobject.fuptr))(199); Now with line 65 I have some difficulties. I guessed it was something like this, but why again the xobject??? in the constructor i can call the pointer via (this->*fuptr), which is what i would expect. Why do i suddenly need a this->*(this->fuptr)? I did not create a class in a class, or did I?
Well, I think I'm not sure about the syntax rules, because i also had a problem with:
void (X::*fuptr)(int b) ;
Why does it need a X::? I'd have assumed that i just need a void (*fuptr)(int b); since it is in the class declaration, not the implementation outside the declaration... I'd have assumed that it is like when you define functions. In the class X you don't write void X::function(int argument), that you write in the implementation outside the class declaration, but inside???
As to the rest: i posted before i saw dwitney's post. Well, I'd certainly like to see whether i did it overly complex, so I'll explain what I'm doing:
I'm reimplementing OGC in C++, in a way that it doesn't need function detours. Now that's a really interesting thing, because instead of detouring functions (overwriting them in RAM), you can instead use threads that work across platform, and then modify some quake/openarena/CoD/EnemyTerritory pointers to direct the program execution to your shared library ;-)) (=cheating)
now there are various mods/extensions of quake3, like openarena, enemy territory and urban terror (and many more).
Now, to support all these mods in one hack, you first need to know what game/mod is running, and then use your hack's functions to cheat.
Now, unfortunately not all engines work the same, so you need adapt some functions to one mod specifically.
So you implement, for example: void AimAtPlayersHead_Quake3(int clientID) void AimAtPlayersHead_OpenArena(int clientID) void AimAtPlayersHead_UrbanTerror(int clientID) void AimAtPlayersHead_CoD(int clientID) void AimAtPlayersHead_ET(int clientID)
Now instead of writing 5 programs for each game, you write one program for all games. The way you do that, is you set a functionpointer in your bot, which you set to the appropriate function for the appropriate mod.
Then, another thing to know is that there are most probably more than one function which is different in each game, and also the weapons, their speed, names and accuracy can vary...
So you load all the mod specific data in one struct, from which you take the mod specific data.
So you can do the following: determine the mod at startup, get a number for it: int MOD = identify_Mod(); // returns a number, for exampel 2 if openarena then later functionpointer_for_aimatplayershead = modTable[MOD].AimAtPlayersHead with modTable being an array of ogcMod_t.
typedef struct ogcWeapon_s { char name[32] ; float speed ; vec3_t v ; } ogcWeapon_t ;
typedef struct ogcMod_s { char name[64] ; ogcWeapon_t* weapons ; int numweapons ; int playerinfo ; int unlagged ; int deadflag ; int clientinfo_distortion ; int (*VerifyTarget)(centity_t* ent) ; void (*AddGlowShell)(refEntity_t* ent) ; int (*AddTarget)(centity_t* targ, centity_t* ent) ; int (*DrawEsp)(centity_t* ent, float *color, int* force) ; } ogcMod_t ;
Now the first problem is, OGC was programmed in C.
Now one statement in C is:
ogcWeapon_t weapons_UT4[20]= { // char name[32] float speed vec3_t v {"NONE" , 0.0f, { 0.0f, 0.0f, 0.0f } }, {"KNIFE" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"BERETTA" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"DESERT EAGLE" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"SPAS-12" , 0.0f, { 0.0f, 0.0f, 5.0f } }, {"MPK5" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UMP-45" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"HK-69" , 1000.0f, { 0.0f, 0.0f, 30.0f } }, {"LR-300" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"G-36" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"PSG-1" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"GRENADE" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"FLASH" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"SMOKE" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"SR-8" , 0.0f, { 0.0f, 0.0f, 5.0f } }, {"AK-103" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"NEGEV" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"M4" , 0.0f, { 4.0f, 0.0f, 26.0f } } };
Now in C++ i have classes, and I made one class for MOD. There I put all mod specific things, for example the table with the weapons data above.
class Cmods { public: Cmods() ; ~Cmods() ; int VerifyTarget_BQ3(centity_t *ent) ; void AddGlowShell_BQ3(refEntity_t *ref) ; int AddTarget_BQ3(centity_t *targ,centity_t * cent) ; int DrawEsp_BQ3(centity_t *ent,float *color,int *force) ; int VerifyTarget_FRZ(centity_t * ent) ; void AddGlowShell_FRZ(refEntity_t * ref) ; int AddTarget_FRZ(centity_t * targ, centity_t * cent) ; int DrawEsp_FRZ(centity_t * ent, float *color, int *force) ;
typedef struct modWeapon_s
{
char name[32] ;
float speed ;
vec3_t v ;
} modWeapon_t ;
typedef struct modSupport_s { char name[64] ; modWeapon_t* weapons ; int numweapons ; int playerinfo ; int unlagged ; int deadflag ; int clientinfo_distortion ; int (*VerifyTarget)(centity_t* ent) ; void (*AddGlowShell)(refEntity_t* ent) ; int (*AddTarget)(centity_t* targ, centity_t* ent) ; int (*DrawEsp)(centity_t* ent, float *color, int* force) ; } modSupport_t ;
modWeapon_t weapons_UT4[] = { // char name[32] float speed vec3_t v {"NONE" , 0.0f, { 0.0f, 0.0f, 0.0f } }, {"KNIFE" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"BERETTA" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"DESERT EAGLE" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"SPAS-12" , 0.0f, { 0.0f, 0.0f, 5.0f } }, {"MPK5" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UMP-45" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"HK-69" , 1000.0f, { 0.0f, 0.0f, 30.0f } }, {"LR-300" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"G-36" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"PSG-1" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"GRENADE" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"FLASH" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"SMOKE" , 500.0f, { 0.0f, 0.0f, 30.0f } }, {"SR-8" , 0.0f, { 0.0f, 0.0f, 5.0f } }, {"AK-103" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"NEGEV" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } }, {"M4" , 0.0f, { 4.0f, 0.0f, 26.0f } } };
Now the problem is that this doesn't compile, since you cannot initialize data that is in a class....
so i thougt, OK, well, if I cannot initialize it in the declaration, then OK, I'm gonna initialize it in the constructor.
But the bad thing is, i cannot initialize this table in the constructor with a simple =, when i initialized the data in the in the class header...
so what i do is I create a new variable in the constructor, and then memcopy it's contents to the variable in the class... which works perfectly...
I define a too large array in the class header, so i can grow my array in the constructor without having to adapt the header. Therefore in the header i write: #define UT4_MAX_WEAPONS 30 #define BQ3_MAX_WEAPONS 20 modWeapon_t weapons_UT4[UT4_MAX_WEAPONS] ; modWeapon_t weapons_BQ3[BQ3_MAX_WEAPONS] ;
then in the constructor i do:
// f*** C++ ISO forbidds allocating this in class declaration
modWeapon_t temporary_weapons_UT4[UT4_MAX_WEAPONS] =
{
// char name[32] float speed vec3_t v
{"NONE" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"KNIFE" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"BERETTA" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"DESERT EAGLE" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"SPAS-12" , 0.0f, { 0.0f, 0.0f, 5.0f } },
{"MPK5" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"UMP-45" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"HK-69" , 1000.0f, { 0.0f, 0.0f, 30.0f } },
{"LR-300" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"G-36" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"PSG-1" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"GRENADE" , 500.0f, { 0.0f, 0.0f, 30.0f } },
{"FLASH" , 500.0f, { 0.0f, 0.0f, 30.0f } },
{"SMOKE" , 500.0f, { 0.0f, 0.0f, 30.0f } },
{"SR-8" , 0.0f, { 0.0f, 0.0f, 5.0f } },
{"AK-103" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"NEGEV" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"UNKNOWN" , 0.0f, { 4.0f, 0.0f, 26.0f } },
{"M4" , 0.0f, { 4.0f, 0.0f, 26.0f } }
};
memcpy(&weapons_UT4, &temporary_weapons_UT4, sizeof(modWeapon_t) * UT4_MAX_WEAPONS) ;
modWeapon_t temporary_weapons_BQ3[BQ3_MAX_WEAPONS] =
{
{"none" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"gauntlet" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"machine" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"shotgun" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"grenade" , 700.0f, { 0.0f, 0.0f, 20.0f } },
{"rocket" , 900.0f, { 0.0f, 0.0f, -20.0f } },
{"light" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"railgun" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"plasma" , 2000.0f, { 0.0f, 0.0f, 0.0f } },
{"bfg" , 2000.0f, { 0.0f, 0.0f, -20.0f } },
{"" , 0.0f, { 0.0f, 0.0f, 0.0f } },
{"grapple" , 0.0f, { 0.0f, 0.0f, 0.0f } }
};
memcpy(&weapons_BQ3, &temporary_weapons_BQ3, sizeof(modWeapon_t) * BQ3_MAX_WEAPONS) ;
Then i thought here i'm gonna do just the same with the modtable
#define MOD_FUNCS(MOD) VerifyTarget_##MOD , AddGlowShell_##MOD , AddTarget_##MOD , DrawEsp_##MOD
modSupport_t temporary_modTable[] = { //{ "baseq3" , weapons_BQ3, 10, 0, 0, EF_DEAD, 0, MOD_FUNCS(BQ3) }, //{ "cpma" , weapons_BQ3, 10, 0, 0, EF_DEAD, 0, MOD_FUNCS(BQ3) }, //{ "q3ut4" , weapons_UT4, 15, 0, 1, EF_DEAD, -4, MOD_FUNCS(FRZ) }, //{ "freeze" , weapons_BQ3, 10, 0, 0, EF_DEAD, 0, MOD_FUNCS(FRZ) }, //{ "ufreeze" , weapons_BQ3, 10, 0, 1, 0x100, 0, MOD_FUNCS(FRZ) }, //{ "arena" , weapons_BQ3, 10, 0, 0, EF_DEAD, 0, MOD_FUNCS(FRZ) }, //{ "threewave" , weapons_BQ3, 12, 17, 0, EF_DEAD, 0, MOD_FUNCS(FRZ) } }; modTableSize = sizeof(temporary_modTable)/sizeof(temporary_modTable[0]) ; memcpy(&modTable, &temporary_modTable, sizeof(modSupport_t) * modTableSize) ;
Now of course, since I putted data and functions in my mod class, the functions VerifyTarget, AddGlowShell, AddTarget, DrawEsp have become member functions... aaaaaaaaaaaaaargh well, i don't want to put them in a extern "C"{} of course, since I want it in proper C++...
You understand now? Probably not too god. I'm gonna attach the sourcecode for the entire bot. Compilation is broken at the moment, since it requries the mod data in some other classes, but i haven't yet finished implementing my mod class...
But you can read the source and critique it ;-)