175 lines
4.9 KiB
C
175 lines
4.9 KiB
C
|
|
||
|
class action_c;
|
||
|
class decision_c;
|
||
|
class sense_c;
|
||
|
class body_c;
|
||
|
class ai_public_c;
|
||
|
class ggOinstC;
|
||
|
class ggBinstC;
|
||
|
class ggObjC;
|
||
|
|
||
|
class scripted_decision;
|
||
|
|
||
|
void DynListWrite();
|
||
|
void DynListRead();
|
||
|
|
||
|
typedef struct classcode_s
|
||
|
{
|
||
|
int uuid;
|
||
|
int code;
|
||
|
} classcode_t;
|
||
|
|
||
|
//couldn't make this a static in a template class.
|
||
|
extern int ptListTCNextUUID;
|
||
|
|
||
|
template <class T>
|
||
|
class ptListTC
|
||
|
{
|
||
|
private:
|
||
|
int NewUUID() {return ptListTCNextUUID++;}
|
||
|
void LoadUUID(int uuid) {if (ptListTCNextUUID<=uuid) ptListTCNextUUID=uuid+1;} // prevent new thing from conflicting with loaded things.
|
||
|
|
||
|
map<T *,int> Index;
|
||
|
map<int,T *> Pointer;
|
||
|
public:
|
||
|
int GetIndexFromPointer(T *thing)
|
||
|
{
|
||
|
map<T *,int>::iterator f;
|
||
|
|
||
|
if (!thing)
|
||
|
{
|
||
|
return(0);
|
||
|
}
|
||
|
f = Index.find(thing);
|
||
|
if (f == Index.end())
|
||
|
{
|
||
|
return(0);
|
||
|
}
|
||
|
return((*f).second);
|
||
|
}
|
||
|
T *GetPointerFromIndex(int index)
|
||
|
{
|
||
|
map<int,T *>::iterator f;
|
||
|
|
||
|
if (!index)
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
f = Pointer.find(index);
|
||
|
if (f == Pointer.end())
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
return((*f).second);
|
||
|
}
|
||
|
void AddElement(T *thing)
|
||
|
{
|
||
|
map<T *,int>::iterator f;
|
||
|
int idx;
|
||
|
|
||
|
if (!thing)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
f = Index.find(thing);
|
||
|
if (f == Index.end())
|
||
|
{
|
||
|
idx = NewUUID();
|
||
|
Index[thing] = idx;
|
||
|
Pointer[idx] = thing;
|
||
|
}
|
||
|
}
|
||
|
void RemoveElement(T *thing)
|
||
|
{
|
||
|
map<T *,int>::iterator f;
|
||
|
map<int,T *>::iterator ff;
|
||
|
|
||
|
if (!thing)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
f = Index.find(thing);
|
||
|
if (f == Index.end())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
ff = Pointer.find((*f).second);
|
||
|
assert(ff != Pointer.end()); // maps are corrupted, they should always correspond.
|
||
|
Pointer.erase(ff);
|
||
|
Index.erase(f);
|
||
|
delete thing;
|
||
|
}
|
||
|
|
||
|
void Write1();
|
||
|
void Write2();
|
||
|
void Read1();
|
||
|
void Read2();
|
||
|
};
|
||
|
|
||
|
extern ptListTC<action_c> actionL;
|
||
|
extern ptListTC<decision_c> decisionL;
|
||
|
extern ptListTC<sense_c> senseL;
|
||
|
extern ptListTC<body_c> bodyL;
|
||
|
extern ptListTC<ai_public_c> aiL;
|
||
|
|
||
|
//ghoul stuff:
|
||
|
extern ptListTC<ggOinstC> instL;
|
||
|
extern ptListTC<ggBinstC> binstL;
|
||
|
extern ptListTC<ggObjC> objL;
|
||
|
|
||
|
//use these wherever you need a pointer and you need to keep track of what's pointed to. they should be used to maintain a list for savegame stuff.
|
||
|
|
||
|
// requirements for a class being able to used by ptrTC as T:
|
||
|
// needs to have member functions int GetClassCode(void) and T* NewClassForCode(int);
|
||
|
// --they allow saving and loading child classes. if no child classes exist, it doesn't matter
|
||
|
// what getclasscode returns, newclassforcode should always return the base class.
|
||
|
// if there are children, the parent and all the children should return a unique class
|
||
|
// code, and newclassforcode should allocate a new parent, or child, class based on that.
|
||
|
//
|
||
|
// also need Save and Load funcs
|
||
|
//
|
||
|
// then, need to make a content list of the class, and define your ptrTC
|
||
|
// and add the list to the list saving and loading in listpointer.cpp
|
||
|
|
||
|
template <class T, ptListTC<T> *ptlist>
|
||
|
class ptrTC
|
||
|
{
|
||
|
protected:
|
||
|
T *this_pointed;
|
||
|
public:
|
||
|
//constructors are for initialization, and for conversion, so you can use action_c_ptr as an argument, and it'll work just like a normal pointer--can pass in NULL, or &<some action_c>
|
||
|
ptrTC(void){this_pointed = NULL;}
|
||
|
//update list on this constructor
|
||
|
ptrTC(const T *a_pointer){this_pointed = (T *)a_pointer; ptlist->AddElement((T *)this_pointed);}
|
||
|
|
||
|
//assignments--again, works just like a pointer--update list here
|
||
|
const ptrTC &operator= (const T* new_action) {this_pointed = (T *)new_action; ptlist->AddElement((T *)this_pointed); return *this;}
|
||
|
|
||
|
//so you can access this like, uh, a pointer...
|
||
|
T *operator-> () {return this_pointed;}
|
||
|
|
||
|
//this is a better way to make me work in logic statements--just treat me exactly like a pointer!
|
||
|
operator T*() {return this_pointed;}
|
||
|
|
||
|
//this used in place of delete for getting rid of what the pointer is pointing to. update list
|
||
|
void Destroy(void){if (this_pointed) ptlist->RemoveElement(this_pointed); this_pointed = NULL;}
|
||
|
|
||
|
void MakeIndex(T *orig) { *(int *)&this_pointed = ptlist->GetIndexFromPointer(orig); }
|
||
|
void MakeIndex() { *(int *)&this_pointed = ptlist->GetIndexFromPointer(this_pointed); }
|
||
|
int GetIndex() { return(ptlist->GetIndexFromPointer(this_pointed)); }
|
||
|
// void MakePtr() { this_pointed = ptlist->GetPointerFromIndex((int)this_pointed); }
|
||
|
void MakePtr(int idx) { this_pointed = ptlist->GetPointerFromIndex(idx); }
|
||
|
T *GetPtr(int i) { ptlist->GetPointerFromIndex(i); }
|
||
|
};
|
||
|
|
||
|
#define sense_c_ptr ptrTC<sense_c,&senseL>
|
||
|
#define decision_c_ptr ptrTC<decision_c,&decisionL>
|
||
|
#define action_c_ptr ptrTC<action_c,&actionL>
|
||
|
#define ai_c_ptr ptrTC<ai_public_c,&aiL>
|
||
|
|
||
|
#define gg_inst_c_ptr ptrTC<ggOinstC,&instL>
|
||
|
#define gg_binst_c_ptr ptrTC<ggBinstC,&binstL>
|
||
|
#define gg_obj_c_ptr ptrTC<ggObjC,&objL>
|
||
|
|
||
|
#define body_c_ptr ptrTC<body_c,&bodyL>
|