Coding Question

Sadge

Sexy Shoeless God of War
Joined
Nov 2, 2007
Messages
567
Reaction score
0
Points
16
Location
Washington, DC area
Is there a way to call a function based off of class? Here's what I'm after (note this is obviously not code):

Code:
void Warrior(VOID) {
     dostuff}

void Monk(VOID)
     dostuff}

PLUGIN_API VOID SetGameState(DWORD GameState)
{
    if (GameState==GAMESTATE_INGAME)
        sprintf(ClassIs, "%s", GetClassDesc(GetCharInfo2()->Class));
        ClassIs();
}

Can something like that be done?
 
I should say that I do realize I could do something like:

Code:
if ClassIs=Warrior Warrior();
if ClassIs=Monk Monk();
etc.
But I'm looking for something more efficient.
 
The world is currently crashed...so no promises this would work, but:
Code:
/varset varNameDamnit $(Target.Class.Name)
...many line later
/call something_[$(varNameDamnit)]
Something along those lines should work. You'd have to tweak it some obviously, but I think it should be functional...

BC
 
The world is currently crashed...so no promises this would work, but:
Code:
/varset varNameDamnit $(Target.Class.Name)
...many line later
/call something_[$(varNameDamnit)]
Something along those lines should work. You'd have to tweak it some obviously, but I think it should be functional...

BC

Thanks for the reply, Bearcub.

It looks like the code you posted might work for a macro, but in this case, I'm working on a plugin and I don't think it'll work the same way.
Code:
GetClassDesc(GetCharInfo2()->Class)
will return the correct class (Warrior, Monk, Magician, etc.), but in string format. What I need is something that will convert that string to an actual function call.
 
goto is my only other thought then. Check class and have 15 (or whatever we're at now) different subs.
Code:
classCheck
function shit('class') {
     goto class
}
warrior
     do warrior shit
cleric
     do cleric shit
shaman
     do shaman shit[code]No promises.
 
Well I dont know if there is anything like this in C++ .net.. but in visual basic you can create new threads based on functions like this:

Code:
Dim newThread as System.Threading.Thread

newThread = New Threading.Thread(DirectCast(Function() SomeFunctionName(abc, def), Threading.ThreadStart))
newThread.Start

Function SomeFunctionName(var1, var2)
'function code
End Function

I think if you dont need to pass any vars you can call it without the DirectCast and just do something like New Threading.Thread(AddressOf SubName)

I imagine c++ .net has access to the System.Threading.Thread the same as Visual Basic .Net, so you might want to look into this.

If that dosn't work for you, you can also look at this:
http://publib.boulder.ibm.com/infoc.../com.ibm.xlcpp8a.doc/language/ref/cplr139.htm

It's dealing with using Structures and virtual functions in the structures as pointers. Not sure if you can get that to do what you need or not.
 
This is the only way I could think of without researching it. The downside is that the functions in the map have to have the same parameter types, i.e. all void, all "(char*, int)", etc.

Code:
void Warrior()
{
    printf("Warrior\n");
}

void Monk()
{
    printf("Monk\n");
}

typedef void (*functionPtr)();

functionPtr fWarPtr = &Warrior;
functionPtr fMonkPtr = &Monk;

map<string, functionPtr> functionMap;

int main(int argc, char* argv[])
{
    // initialize, associating names with pointers to functions
    functionMap["Warrior"] = fWarPtr;
    functionMap["Monk"] = fMonkPtr;

    // call functions by name
    functionMap["Monk"]();
    functionMap["Warrior"]();

    return 0;
}


Using args:
Code:
void Test(char *text)
{
    printf("%s\n", text[0] ? text : "NULL");
}

typedef void (*functionPtr)(char*);

functionPtr fTestPtr = &Test;

map<string, functionPtr> functionMap;

int main(int argc, char* argv[])
{
    // initialize it
    functionMap["Test"] = fTestPtr;

    // call with string arg
    functionMap["Test"]("this is a test");

    return 0;
}
 
The real solution to your problem would be solved by reflection. However, though my knowledge of C++ reflection is limited, it would seem that in your use case reflection would be over kill. One suggestion above is to just use an if or a case statement around the class name and call the function directly. Since you have a limited number of possible class names which is also static (won't change very often) you would be better off with a more explicit implementation than try to come up with something dynamic.

My two cents, :)
 
The real solution to your problem would be solved by reflection. However, though my knowledge of C++ reflection is limited, it would seem that in your use case reflection would be over kill. One suggestion above is to just use an if or a case statement around the class name and call the function directly. Since you have a limited number of possible class names which is also static (won't change very often) you would be better off with a more explicit implementation than try to come up with something dynamic.

My two cents, :)

Yeah, I'm thinking that that is the best option. I thought about using the pointers, but it's just easier to do it with an /if statement.

Thanks everyone for the help!
 
I guess you could always do a lookup table, if you wanted it looking easy to read.

Untested.

Code:
const char* tblclass[] = {
"monk",
"paladin",
"cleric",
"druid",
"ranger"
};  // add others

enum {
CLASS_MONK,
CLASS_PALADIN,
CLASS_CLERIC,
CLASS_DRUID,
CLASS_RANGER,
CLASS_NONE
};  // add others from table before NONE


int ClassIndex(char MyClass[])
{
  const int total_classes = sizeof tblclass / sizeof *tblclass;
  for(int z=0; z!=total_classes; z++)
    if(!stricmp(MyClass, tblclass[z]))
      return z;
  return CLASS_NONE;
}

void MyFunc()
{
  if(gGameState != GAMESTATE_INGAME)
    return;
  switch(ClassIndex(GetClassDesc(GetCharInfo2()->Class)))
  {
     case CLASS_CLERIC:
         // do cleric stuff
         break;
     case CLASS_DRUID:
         // do druid stuff
         break;
     case CLASS_NONE:
     default:
         // do error stuff
  }
}

htw