//***************************************************************************** // // affect.c // // Affects are temporary changes to numericvalues assocciated with a character. // For instance, a character can have a +10 strength affect. Each affect has a // duration. Negative-duration affects are permenanant. // //***************************************************************************** #include "../mud.h" #include "../utils.h" #include "../storage.h" #include "../auxiliary.h" #include "../character.h" #include "../object.h" #include "../room.h" #include "../event.h" #include "../hooks.h" #include "affects.h" //***************************************************************************** // mandatory modules //***************************************************************************** #include "../scripts/scripts.h" #include "../scripts/pychar.h" #include "../scripts/pyroom.h" #include "../scripts/pyobj.h" #include "../scripts/pymudsys.h" #include "../scripts/pyplugs.h" //***************************************************************************** // local variables //***************************************************************************** // tables for holding mappings between affects and modifier functions HASHTABLE *aff_table = NULL; //***************************************************************************** // contains a function for setting affects, and a variable saying which type // of new value (int or double) it takes in. //***************************************************************************** typedef struct { void *func; int type; bool python; } AFF_FUNCTION; AFF_FUNCTION *newAffFunction(void *func, int type, bool python) { AFF_FUNCTION *data = malloc(sizeof(AFF_FUNCTION)); data->func = func; data->type = type; data->python = python; if(python == TRUE) Py_INCREF((PyObject *)func); return data; } // primarily needed for Python #define AFF_RECV_CHAR 0 #define AFF_RECV_ROOM 1 #define AFF_RECV_OBJ 2 // // execute the function void affFunctionExec(AFF_FUNCTION *func, void *data, int recv_type, const char *aff_type, double amnt) { if(func->python == FALSE) { if(func->type == AFFECT_VAR_INT) { void (* mod_func)(void *, const char *, int) = func->func; mod_func(data, aff_type, amnt); } else if(func->type == AFFECT_VAR_DOUBLE) { void (* mod_func)(void *, const char *, double) = func->func; mod_func(data, aff_type, amnt); } } else { // make our Python form PyObject *self = NULL; if(recv_type == AFF_RECV_CHAR) self = charGetPyFormBorrowed(data); else if(recv_type == AFF_RECV_OBJ) self = objGetPyFormBorrowed(data); else if(recv_type == AFF_RECV_ROOM) self = roomGetPyFormBorrowed(data); // didn't figure out what we are? if(self == NULL) return; // build our argument list as is appropriate PyObject *arglist = NULL; if(func->type == AFFECT_VAR_INT) arglist = Py_BuildValue("Osi", self, aff_type, (int)amnt); else arglist = Py_BuildValue("Osd", self, aff_type, amnt); // call our function PyObject *retval = PyEval_CallObject(func->func, arglist); // check for an error: if(retval == NULL) { char *tb = getPythonTraceback(); if(tb != NULL) { log_string("Error running python affect modifier, %s:\r\n%s\r\n", aff_type, tb); free(tb); } } // garbage collection Py_XDECREF(retval); Py_XDECREF(arglist); } } //***************************************************************************** // affect modifier data and functions //***************************************************************************** typedef struct affect_modifer { char *type; // the stat we modify double val; // where the modification is placed } AFF_MODIFIER; AFF_MODIFIER *newAffModifier(const char *type, double val) { AFF_MODIFIER *mod = malloc(sizeof(AFF_MODIFIER)); mod->type = strdupsafe(type); mod->val = val; return mod; } void deleteAffModifier(AFF_MODIFIER *mod) { if(mod->type) free(mod->type); free(mod); } STORAGE_SET *affModifierStore(AFF_MODIFIER *mod) { STORAGE_SET *set = new_storage_set(); store_string(set, "key", mod->type); store_double(set, "val", mod->val); return set; } AFF_MODIFIER *affModifierRead(STORAGE_SET *set) { return newAffModifier(read_string(set, "key"), read_double(set, "val")); } AFF_MODIFIER *affModifierCopy(AFF_MODIFIER *mod) { return newAffModifier(mod->type, mod->val); } void affModifierCopyTo(AFF_MODIFIER *from, AFF_MODIFIER *to) { if(to->type) free(to->type); to->type = strdupsafe(from->type); to->val = from->val; } void affectModApply(AFF_MODIFIER *mod, void *thing, int recv_type) { AFF_FUNCTION *func = hashGet(aff_table, mod->type); affFunctionExec(func, thing, recv_type, mod->type, mod->val); } void affectModRemove(AFF_MODIFIER *mod, void *thing, int recv_type) { AFF_FUNCTION *func = hashGet(aff_table, mod->type); affFunctionExec(func, thing, recv_type, mod->type, -mod->val); } //***************************************************************************** // affect data and functions //***************************************************************************** struct affect_data { char *name; char *type; // magic, physical, curse, etc... not neccessary but // usable if people want to make the differentiation int duration; LIST *modifiers; }; AFFECT_DATA *newAffect(const char *name, int duration) { AFFECT_DATA *aff = malloc(sizeof(AFFECT_DATA)); aff->name = strdupsafe(name); aff->type = strdupsafe(""); aff->duration = duration; aff->modifiers = newList(); return aff; } void deleteAffect(AFFECT_DATA *aff) { if(aff->name) free(aff->name); if(aff->type) free(aff->type); if(aff->modifiers) deleteListWith(aff->modifiers, deleteAffModifier); free(aff); } STORAGE_SET *affectStore(AFFECT_DATA *aff) { STORAGE_SET *set = new_storage_set(); store_string(set, "name", aff->name); store_string(set, "type", aff->type); store_int (set, "duration", aff->duration); store_list (set, "modifiers", gen_store_list(aff->modifiers, affModifierStore)); return set; } AFFECT_DATA *affectRead(STORAGE_SET *set) { AFFECT_DATA *aff = malloc(sizeof(AFFECT_DATA)); aff->name = strdupsafe(read_string(set, "name")); aff->type = strdupsafe(read_string(set, "type")); aff->duration = read_int(set, "duration"); aff->modifiers = gen_read_list(read_list(set,"modifiers"), affModifierRead); return aff; } void affectCopyTo(AFFECT_DATA *from, AFFECT_DATA *to) { if(to->name) free(to->name); if(to->type) free(to->type); if(to->modifiers) deleteListWith(to->modifiers, deleteAffModifier); to->name = strdupsafe(from->name); to->duration = from->duration; to->modifiers = listCopyWith(from->modifiers, affModifierCopy); } AFFECT_DATA *affectCopy(AFFECT_DATA *aff) { AFFECT_DATA *newaff = malloc(sizeof(AFFECT_DATA)); newaff->name = strdupsafe(aff->name); newaff->type = strdupsafe(aff->type); newaff->duration = aff->duration; newaff->modifiers = listCopyWith(aff->modifiers, affModifierCopy); return newaff; } const char *affectGetName(AFFECT_DATA *affect) { return affect->name; } const char *affectGetType(AFFECT_DATA *affect) { return affect->type; } int affectGetDuration(AFFECT_DATA *affect) { return affect->duration; } void affectAddModifier(AFFECT_DATA *affect, const char *affect_type, double amount) { listPut(affect->modifiers, newAffModifier(affect_type, amount)); } void affectSetType(AFFECT_DATA *affect, const char *type) { if(affect->type) free(affect->type); affect->type = strdupsafe(type); } void affectApply(AFFECT_DATA *affect, void *thing, int recv_type) { LIST_ITERATOR *mod_i = newListIterator(affect->modifiers); AFF_MODIFIER *mod = NULL; ITERATE_LIST(mod, mod_i) { affectModApply(mod, thing, recv_type); } deleteListIterator(mod_i); } void affectRemove(AFFECT_DATA *affect, void *thing, int recv_type) { LIST_ITERATOR *mod_i = newListIterator(affect->modifiers); AFF_MODIFIER *mod = NULL; ITERATE_LIST(mod, mod_i) { affectModRemove(mod, thing, recv_type); } deleteListIterator(mod_i); } int affectNameComp(const char *name, AFFECT_DATA *affect) { return strcasecmp(name, affect->name); } //***************************************************************************** // auxiliary data //***************************************************************************** typedef struct { LIST *affects; } AFFECT_AUX_DATA; AFFECT_AUX_DATA *newAffAuxData(void) { AFFECT_AUX_DATA *data = malloc(sizeof(AFFECT_AUX_DATA)); data->affects = newList(); return data; } void deleteAffAuxData(AFFECT_AUX_DATA *data) { if(data->affects) deleteListWith(data->affects, deleteAffect); free(data); } STORAGE_SET *affAuxDataStore(AFFECT_AUX_DATA *data) { STORAGE_SET *set = new_storage_set(); store_list(set, "affects", gen_store_list(data->affects, affectStore)); return set; } AFFECT_AUX_DATA *affAuxDataRead(STORAGE_SET *set) { AFFECT_AUX_DATA *data = malloc(sizeof(AFFECT_AUX_DATA)); data->affects = gen_read_list(read_list(set, "affects"), affectRead); return data; } void affAuxDataCopyTo(AFFECT_AUX_DATA *from, AFFECT_AUX_DATA *to) { if(to->affects) deleteListWith(to->affects, deleteAffect); to->affects = listCopyWith(from->affects, affectCopy); } AFFECT_AUX_DATA *affAuxDataCopy(AFFECT_AUX_DATA *affaux) { AFFECT_AUX_DATA *data = newAffAuxData(); affAuxDataCopyTo(affaux, data); return data; } //***************************************************************************** // local functions //***************************************************************************** // // iterate across all of our characters, objects, and rooms, updating affects void affect_update(void *self, void *nothing, char *arg) { LIST_ITERATOR *ch_i = newListIterator(mobile_list); BUFFER *buf = newBuffer(1); LIST_ITERATOR *aff_i = NULL; AFFECT_DATA *aff = NULL; CHAR_DATA *ch = NULL; AFFECT_AUX_DATA *data = NULL; ITERATE_LIST(ch, ch_i) { data = charGetAuxiliaryData(ch, "affect_data"); if(listSize(data->affects) > 0) { aff_i = newListIterator(data->affects); ITERATE_LIST(aff, aff_i) { // ignore permenant affects if(aff->duration < 0) continue; aff->duration--; if(aff->duration <= 0) { listRemove(data->affects, aff); affectRemove(aff, ch, AFF_RECV_CHAR); // run our cancel and then wearoff goes first, or else some of the // blanket resets that are tied to cancel hooks will wipe out // important wearoff information hookRun("affect_wearoff", hookBuildInfo("ch str", ch, aff->name)); if(*aff->type) { bufferClear(buf); bprintf(buf, "%s_wearoff", aff->type); hookRun(bufferString(buf), hookBuildInfo("ch str", ch, aff->name)); } hookRun("affect_cancel", hookBuildInfo("ch str", ch, aff->name)); if(*aff->type) { bufferClear(buf); bprintf(buf, "%s_cancel", aff->type); hookRun(bufferString(buf), hookBuildInfo("ch str", ch, aff->name)); } // delete the affect that was just removed deleteAffect(aff); } } deleteListIterator(aff_i); } } deleteListIterator(ch_i); // remove all affects for objects and rooms //*********** // FINISH ME //*********** // garbage collection deleteBuffer(buf); } // // for internal use only; quick lookup of affects AFFECT_DATA *charGetAffect(CHAR_DATA *ch, const char *affect) { LIST *affs = charGetAffects(ch); LIST_ITERATOR *aff_i = newListIterator(affs); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(!strcasecmp(affectGetName(aff), affect)) break; } deleteListIterator(aff_i); return aff; } //***************************************************************************** // character commands //***************************************************************************** // // shows one affect modifier to a character void show_affect_modifier(CHAR_DATA *ch, AFF_MODIFIER *mod) { // display the value differently if it's a double or int AFF_FUNCTION *func = hashGet(aff_table, mod->type); if(func->type == AFFECT_VAR_DOUBLE) send_to_char(ch, " %s by %.2lf\r\n", mod->type, mod->val); else if(func->type == AFFECT_VAR_INT) send_to_char(ch, " %s by %d\r\n", mod->type, (int)mod->val); } // // show one affect to a character void show_one_affect(CHAR_DATA *ch, AFFECT_DATA *affect) { // print the duration buffer perm. if time < 0. in hms otherwise char durbuf[SMALL_BUFFER]; if(affect->duration <= 0) sprintf(durbuf, "perm."); else { int sec = affect->duration % 60; int min = ((affect->duration - sec) / 60); sprintf(durbuf, "%3dm%2ds", min, sec); } // show time in minutes if it's more than 60 seconds. Seconds, otherwise send_to_char(ch, "%s) %s%s\r\n", durbuf, affect->name, (listSize(affect->modifiers) > 0 ? " affects:" : "")); if(listSize(affect->modifiers) > 0) { LIST_ITERATOR *mod_i = newListIterator(affect->modifiers); AFF_MODIFIER *mod = NULL; ITERATE_LIST(mod, mod_i) { show_affect_modifier(ch, mod); } deleteListIterator(mod_i); } } // // show all of the affects in the given list to the specified character void show_affects(CHAR_DATA *ch, LIST *affects) { LIST_ITERATOR *aff_i = newListIterator(affects); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { show_one_affect(ch, aff); } deleteListIterator(aff_i); } // // iterates over a character's affect list, and displays them all to him COMMAND(cmd_affect) { AFFECT_AUX_DATA *data = charGetAuxiliaryData(ch, "affect_data"); if(listSize(data->affects) == 0) send_to_char(ch, "You currently have no affects on you.\r\n"); else { send_to_char(ch, "{wCurrent affects:{g\r\n"); show_affects(ch, data->affects); send_to_char(ch, "{n"); } } //***************************************************************************** // python extentions //***************************************************************************** PyObject *PyChar_getaffects(PyObject *self, void *closure) { CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) return NULL; LIST_ITERATOR *aff_i = newListIterator(charGetAffects(ch)); AFFECT_DATA *aff = NULL; PyObject *list = PyList_New(0); ITERATE_LIST(aff, aff_i) { PyObject *affname = Py_BuildValue("s", affectGetName(aff)); PyList_Append(list, affname); Py_DECREF(affname); } deleteListIterator(aff_i); PyObject *retval = Py_BuildValue("O", list); Py_DECREF(list); return retval; } PyObject *PyChar_affected(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "affect name must be specified."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } return Py_BuildValue("i", charIsAffected(ch, name)); } PyObject *PyChar_add_affect(PyObject *self, PyObject *args) { char *name = NULL; char *type = NULL; int duration = 0; if(!PyArg_ParseTuple(args, "si|s", &name, &duration, &type)) { PyErr_Format(PyExc_TypeError, "affect name and duration must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // remove our old affect if(charIsAffected(ch, name)) charRemoveAffect(ch, name); // add our new affect AFFECT_DATA *affect = newAffect(name, duration); if(type != NULL) affectSetType(affect, type); charAddAffect(ch, affect); return Py_BuildValue("i", 1); } PyObject *PyChar_mod_affect(PyObject *self, PyObject *args) { char *name = NULL; char *mod = NULL; double amnt = 0; if(!PyArg_ParseTuple(args, "ssd", &name, &mod, &amnt)) { PyErr_Format(PyExc_TypeError, "affect name, mod, and amount must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // find our old affect LIST_ITERATOR *aff_i = newListIterator(charGetAffects(ch)); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(!strcasecmp(affectGetName(aff), name)) break; } deleteListIterator(aff_i); // see if the affect exists if(aff == NULL) return Py_BuildValue("i", 0); else { // copy the affect aff = affectCopy(aff); // remove the old affect charRemoveAffect(ch, name); // add our new modifier affectAddModifier(aff, mod, amnt); // add our new affect charAddAffect(ch, aff); return Py_BuildValue("i", 1); } } PyObject *PyChar_rem_affect(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "affect name must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // remove the affect and run the appropriate hooks if(charIsAffected(ch, name)) { AFFECT_DATA *aff = charGetAffect(ch, name); BUFFER *buf = newBuffer(1); hookRun("affect_cancel", hookBuildInfo("ch str", ch, name)); if(*aff->type) { bprintf(buf, "%s_cancel", aff->type); hookRun(bufferString(buf), hookBuildInfo("ch str", ch, name)); } charRemoveAffect(ch, name); // garbage collection deleteBuffer(buf); } return Py_BuildValue("i", 1); } PyObject *PyChar_aff_duration(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "affect name must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // find the affect LIST_ITERATOR *aff_i = newListIterator(charGetAffects(ch)); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(!strcasecmp(affectGetName(aff), name)) break; } deleteListIterator(aff_i); if(aff != NULL) return Py_BuildValue("i", affectGetDuration(aff)); return Py_BuildValue("i", 0); } PyObject *PyChar_aff_type(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "affect name must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // find the affect LIST_ITERATOR *aff_i = newListIterator(charGetAffects(ch)); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(!strcasecmp(affectGetName(aff), name)) break; } deleteListIterator(aff_i); if(aff != NULL) return Py_BuildValue("s", affectGetType(aff)); return Py_BuildValue("O", Py_None); } PyObject *PyChar_aff_refresh(PyObject *self, PyObject *args) { char *name = NULL; int duration = 0; if(!PyArg_ParseTuple(args, "si", &name, &duration)) { PyErr_Format(PyExc_TypeError, "affect name and duration must be supplied."); return NULL; } CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } if(!charIsAffected(ch, name)) return Py_BuildValue("i", 0); // find the affect LIST_ITERATOR *aff_i = newListIterator(charGetAffects(ch)); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(!strcasecmp(affectGetName(aff), name)) aff->duration = duration; } deleteListIterator(aff_i); return Py_BuildValue("i", 1); } PyObject *PyChar_aff_has_mod(PyObject *self, PyObject *args) { char *name = NULL; char *type = NULL; double amnt = 0; if(!PyArg_ParseTuple(args, "ss", &name, &type)) { PyErr_Format(PyExc_TypeError, "Affect name and mod type must be supplied."); return NULL; } // make sure we exist CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } // get the affect on the character AFFECT_DATA *aff = charGetAffect(ch, name); if(aff == NULL) return 0; LIST_ITERATOR *mod_i = newListIterator(aff->modifiers); AFF_MODIFIER *mod = NULL; ITERATE_LIST(mod, mod_i) { if(!strcasecmp(mod->type, type)) { amnt = mod->val; break; } } deleteListIterator(mod_i); return Py_BuildValue("i", (mod == 0 ? 0 : (mod < 0 ? -1 : 1))); } PyObject *PyChar_add_modifier(PyObject *self, PyObject *args) { char *type = NULL; double val = 0; if(!PyArg_ParseTuple(args, "sd", &type, &val)) { PyErr_Format(PyExc_TypeError, "Affect type and amount to modify must be supplied."); return NULL; } // make sure we exist CHAR_DATA *ch = PyChar_AsChar(self); if(ch == NULL) { PyErr_Format(PyExc_StandardError, "character does not exist."); return NULL; } charAddModifier(ch, type, val); return Py_BuildValue("i", 1); } PyObject *PyRoom_add_modifier(PyObject *self, PyObject *args) { char *type = NULL; double val = 0; if(!PyArg_ParseTuple(args, "sd", &type, &val)) { PyErr_Format(PyExc_TypeError, "Affect type and amount to modify must be supplied."); return NULL; } // make sure we exist ROOM_DATA *room = PyRoom_AsRoom(self); if(room == NULL) { PyErr_Format(PyExc_StandardError, "room does not exist."); return NULL; } roomAddModifier(room, type, val); return Py_BuildValue("i", 1); } PyObject *PyObj_add_modifier(PyObject *self, PyObject *args) { char *type = NULL; double val = 0; if(!PyArg_ParseTuple(args, "sd", &type, &val)) { PyErr_Format(PyExc_TypeError, "Affect type and amount to modify must be supplied."); return NULL; } // make sure we exist OBJ_DATA *obj = PyObj_AsObj(self); if(obj == NULL) { PyErr_Format(PyExc_StandardError, "object does not exist."); return NULL; } objAddModifier(obj, type, val); return Py_BuildValue("i", 1); } // // adds a new affect type via Python PyObject *PyMudSys_AddAffectType(PyObject *self, PyObject *args) { char *name = NULL; char *vartype = NULL; PyObject *func = NULL; int var_val = -1; if(!PyArg_ParseTuple(args, "ssO", &name, &vartype, &func)) { PyErr_Format(PyExc_TypeError, "Affect name, type, and add/remove function must be supplied."); return NULL; } if(!strcasecmp(vartype, "int")) var_val = AFFECT_VAR_INT; else if(!strcasecmp(vartype, "double")) var_val = AFFECT_VAR_DOUBLE; else { PyErr_Format(PyExc_TypeError, "affect type must be an 'int' or 'double'."); return NULL; } // hash our function add_py_affect_type(name, var_val, func); return Py_BuildValue("i", 1); } //***************************************************************************** // implementation of affect.h //***************************************************************************** void init_affects(void) { aff_table = newHashtable(); auxiliariesInstall("affect_data", newAuxiliaryFuncs(AUXILIARY_TYPE_CHAR| AUXILIARY_TYPE_ROOM| AUXILIARY_TYPE_OBJ, newAffAuxData, deleteAffAuxData, affAuxDataCopyTo, affAuxDataCopy, affAuxDataStore, affAuxDataRead)); // add python extentions PyChar_addGetSetter("affects", PyChar_getaffects, NULL, NULL); PyChar_addMethod("affected", PyChar_affected, METH_VARARGS, NULL); PyChar_addMethod("add_affect", PyChar_add_affect, METH_VARARGS, NULL); PyChar_addMethod("mod_affect", PyChar_mod_affect, METH_VARARGS, NULL); PyChar_addMethod("rem_affect", PyChar_rem_affect, METH_VARARGS, NULL); PyChar_addMethod("aff_duration", PyChar_aff_duration, METH_VARARGS, NULL); PyChar_addMethod("aff_type", PyChar_aff_type, METH_VARARGS, NULL); PyChar_addMethod("aff_refresh", PyChar_aff_refresh, METH_VARARGS, NULL); PyChar_addMethod("add_modifier", PyChar_add_modifier, METH_VARARGS, NULL); PyChar_addMethod("aff_has_mod", PyChar_aff_has_mod, METH_VARARGS, NULL); PyRoom_addMethod("add_modifier", PyRoom_add_modifier, METH_VARARGS, NULL); PyObj_addMethod ("add_modifier", PyObj_add_modifier, METH_VARARGS, NULL); PyMudSys_addMethod("add_affect_type", PyMudSys_AddAffectType, METH_VARARGS, NULL); add_cmd("affects", NULL, cmd_affect, "player", FALSE); start_update(NULL, 1 SECOND, affect_update, NULL, NULL, NULL); } void add_py_affect_type(const char *affect_type, int vartype, void *addremove) { hashPut(aff_table, affect_type, newAffFunction(addremove, vartype, TRUE)); } void add_affect_type(const char *affect_type, int vartype, void *addremove) { hashPut(aff_table, affect_type, newAffFunction(addremove, vartype, FALSE)); } void charAddAffect(CHAR_DATA *ch, AFFECT_DATA *affect) { AFFECT_AUX_DATA *data = charGetAuxiliaryData(ch, "affect_data"); listPut(data->affects, affect); affectApply(affect, ch, AFF_RECV_CHAR); } void roomAddAffect(ROOM_DATA *room, AFFECT_DATA *affect) { AFFECT_AUX_DATA *data = roomGetAuxiliaryData(room, "affect_data"); listPut(data->affects, affect); affectApply(affect, room, AFF_RECV_ROOM); } void objAddAffect(OBJ_DATA *obj, AFFECT_DATA *affect) { AFFECT_AUX_DATA *data = objGetAuxiliaryData(obj, "affect_data"); listPut(data->affects, affect); affectApply(affect, obj, AFF_RECV_OBJ); } void charRemoveAffect(CHAR_DATA *ch, const char *affect) { AFFECT_AUX_DATA *data = charGetAuxiliaryData(ch, "affect_data"); AFFECT_DATA *aff = listRemoveWith(data->affects, affect, affectNameComp); affectRemove(aff, ch, AFF_RECV_CHAR); deleteAffect(aff); } void roomRemoveAffect(ROOM_DATA *room, const char *affect) { AFFECT_AUX_DATA *data = roomGetAuxiliaryData(room, "affect_data"); AFFECT_DATA *aff = listRemoveWith(data->affects, affect, affectNameComp); affectRemove(aff, room, AFF_RECV_ROOM); deleteAffect(aff); } void objRemoveAffect(OBJ_DATA *obj, const char *affect) { AFFECT_AUX_DATA *data = objGetAuxiliaryData(obj, "affect_data"); AFFECT_DATA *aff = listRemoveWith(data->affects, affect, affectNameComp); affectRemove(aff, obj, AFF_RECV_OBJ); deleteAffect(aff); } bool charIsAffected(CHAR_DATA *ch, const char *affect) { AFFECT_AUX_DATA *data = charGetAuxiliaryData(ch, "affect_data"); return (listGetWith(data->affects, affect, affectNameComp) != NULL); } bool objIsAffected(OBJ_DATA *obj, const char *affect) { AFFECT_AUX_DATA *data = objGetAuxiliaryData(obj, "affect_data"); return (listGetWith(data->affects, affect, affectNameComp) != NULL); } bool roomIsAffected(ROOM_DATA *room, const char *affect) { AFFECT_AUX_DATA *data = roomGetAuxiliaryData(room, "affect_data"); return (listGetWith(data->affects, affect, affectNameComp) != NULL); } LIST *charGetAffects(CHAR_DATA *ch) { AFFECT_AUX_DATA *data = charGetAuxiliaryData(ch, "affect_data"); return data->affects; } LIST *roomGetAffects(ROOM_DATA *room) { AFFECT_AUX_DATA *data = roomGetAuxiliaryData(room, "affect_data"); return data->affects; } LIST *objGetAffects(OBJ_DATA *obj) { AFFECT_AUX_DATA *data = objGetAuxiliaryData(obj, "affect_data"); return data->affects; } void anyUnaffect(void *thing, int recv_type, AFFECT_AUX_DATA *data, bool remove_permenants) { LIST_ITERATOR *aff_i = newListIterator(data->affects); AFFECT_DATA *aff = NULL; ITERATE_LIST(aff, aff_i) { if(aff->duration < 0 && !remove_permenants) continue; listRemove(data->affects, aff); affectRemove(aff, thing, recv_type); deleteAffect(aff); } deleteListIterator(aff_i); } void charUnaffect(CHAR_DATA *ch, bool remove_permenants) { anyUnaffect(ch, AFF_RECV_CHAR, charGetAuxiliaryData(ch, "affect_data"), remove_permenants); } void roomUnaffect(ROOM_DATA *room, bool remove_permenants) { anyUnaffect(room, AFF_RECV_ROOM, roomGetAuxiliaryData(room,"affect_data"), remove_permenants); } void objUnaffect(OBJ_DATA *obj, bool remove_permenants) { anyUnaffect(obj, AFF_RECV_OBJ, objGetAuxiliaryData(obj, "affect_data"), remove_permenants); } void charAddModifier(CHAR_DATA *ch, const char *affect_type, double amount) { AFF_FUNCTION *func = hashGet(aff_table, affect_type); if(func != NULL) affFunctionExec(func, ch, AFF_RECV_CHAR,affect_type, amount); } void roomAddModifier(ROOM_DATA *room,const char *affect_type, double amount) { AFF_FUNCTION *func = hashGet(aff_table, affect_type); if(func != NULL) affFunctionExec(func, room,AFF_RECV_ROOM,affect_type,amount); } void objAddModifier (OBJ_DATA *obj, const char *affect_type, double amount) { AFF_FUNCTION *func = hashGet(aff_table, affect_type); if(func != NULL) affFunctionExec(func, obj, AFF_RECV_OBJ,affect_type, amount); }