//*****************************************************************************
//
// py_char.c
//
// A python extention to allow python scripts to treat MUD characters as an
// object within the script.
//
//*****************************************************************************
#include <Python.h>
#include <structmember.h>
#include "../mud.h"
#include "../world.h"
#include "../room.h"
#include "../character.h"
#include "../body.h"
#include "../object.h"
#include "../races.h"
#include "../handler.h"
#include "../utils.h"
#include "../action.h"
#include "../socket.h"
#include "../prototype.h"
#include "../save.h"
#include "pyplugs.h"
#include "scripts.h"
#include "pychar.h"
#include "pyroom.h"
#include "pyobj.h"
#include "pyexit.h"
#include "pyaccount.h"
#include "pyauxiliary.h"
//*****************************************************************************
// mandatory modules
//*****************************************************************************
#include "../char_vars/char_vars.h"
#include "../items/items.h"
#include "../items/worn.h"
//*****************************************************************************
// local structures and defines
//*****************************************************************************
// a list of the get/setters on the Char class
LIST *pychar_getsetters = NULL;
// a list of the methods on the Char class
LIST *pychar_methods = NULL;
typedef struct {
PyObject_HEAD
int uid;
} PyChar;
//*****************************************************************************
// allocation, deallocation, initialization, and comparison
//*****************************************************************************
void PyChar_dealloc(PyChar *self) {
self->ob_type->tp_free((PyObject*)self);
}
PyObject *PyChar_new(PyTypeObject *type, PyObject *args, PyObject *kwds){
PyChar *self;
self = (PyChar *)type->tp_alloc(type, 0);
self->uid = NOBODY;
return (PyObject *)self;
}
int PyChar_init(PyChar *self, PyObject *args, PyObject *kwds) {
static char *kwlist[] = {"uid", NULL};
int uid = NOBODY;
// get the universal id
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &uid)) {
PyErr_Format(PyExc_TypeError,
"Characters may only be created by uid");
return -1;
}
// make sure a character with the UID exists
if(!propertyTableGet(mob_table, uid)) {
PyErr_Format(PyExc_TypeError,
"Character with uid, %d, does not exist", uid);
return -1;
}
self->uid = uid;
return 0;
}
int PyChar_compare(PyChar *ch1, PyChar *ch2) {
if(ch1->uid == ch2->uid)
return 0;
else if(ch1->uid < ch2->uid)
return -1;
else
return 1;
}
//*****************************************************************************
// getters and setters for the Char class
//*****************************************************************************
PyObject *PyChar_getname(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetName(ch));
else return NULL;
}
PyObject *PyChar_getkeywords(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetKeywords(ch));
else return NULL;
}
PyObject *PyChar_getmname(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetMultiName(ch));
else return NULL;
}
PyObject *PyChar_getdesc(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetDesc(ch));
else return NULL;
}
PyObject *PyChar_getlookbuf(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", bufferString(charGetLookBuffer(ch)));
else return NULL;
}
PyObject *PyChar_getrdesc(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetRdesc(ch));
else return NULL;
}
PyObject *PyChar_getmdesc(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetMultiRdesc(ch));
else return NULL;
}
PyObject *PyChar_getrace(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetRace(ch));
else return NULL;
}
PyObject *PyChar_getsex(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", sexGetName(charGetSex(ch)));
else return NULL;
}
PyObject *PyChar_getposition(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", posGetName(charGetPos(ch)));
else return NULL;
}
PyObject *PyChar_getroom(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
else if(charGetRoom(ch) != NULL)
return Py_BuildValue("O", roomGetPyFormBorrowed(charGetRoom(ch)));
else {
Py_INCREF(Py_None);
return Py_BuildValue("O", Py_None);
}
}
PyObject *PyChar_getlastroom(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
else if(charGetLastRoom(ch) != NULL)
return Py_BuildValue("O", roomGetPyFormBorrowed(charGetLastRoom(ch)));
else {
Py_INCREF(Py_None);
return Py_BuildValue("O", Py_None);
}
}
PyObject *PyChar_getisnpc(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("i", charIsNPC(ch));
else return NULL;
}
PyObject *PyChar_getispc(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("i", !charIsNPC(ch));
else return NULL;
}
PyObject *PyChar_gethisher(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", HISHER(ch));
else return NULL;
}
PyObject *PyChar_gethimher(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", HIMHER(ch));
else return NULL;
}
PyObject *PyChar_getheshe(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", HESHE(ch));
else return NULL;
}
PyObject *PyChar_geton(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
else if(charGetFurniture(ch) == NULL)
return Py_BuildValue("O", Py_None);
else
return Py_BuildValue("O", objGetPyFormBorrowed(charGetFurniture(ch)));
}
PyObject *PyChar_getuid(PyChar *self, void *closure) {
return Py_BuildValue("i", self->uid);
}
PyObject *PyChar_getprototypes(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) return Py_BuildValue("s", charGetPrototypes(ch));
else return NULL;
}
PyObject *PyChar_getinv(PyChar *self, PyObject *args) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
LIST_ITERATOR *inv_i = newListIterator(charGetInventory(ch));
PyObject *list = PyList_New(0);
OBJ_DATA *obj;
// for each obj in the inventory, add it to the Python list
ITERATE_LIST(obj, inv_i)
PyList_Append(list, objGetPyFormBorrowed(obj));
deleteListIterator(inv_i);
PyObject *retval = Py_BuildValue("O", list);
Py_DECREF(list);
return retval;
}
PyObject *PyChar_geteq(PyChar *self, PyObject *args) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
PyObject *list = PyList_New(0);
LIST *equipped = bodyGetAllEq(charGetBody(ch));
LIST_ITERATOR *eq_i = newListIterator(equipped);
OBJ_DATA *eq = NULL;
ITERATE_LIST(eq, eq_i) {
PyList_Append(list, objGetPyFormBorrowed(eq));
} deleteListIterator(eq_i);
PyObject *retval = Py_BuildValue("O", list);
Py_DECREF(list);
return retval;
}
PyObject *PyChar_getbodyparts(PyChar *self, PyObject *args) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
PyObject *list = PyList_New(0);
int i, num_bodyparts;
const char **bodyparts = bodyGetParts(charGetBody(ch), TRUE, &num_bodyparts);
for(i = 0; i < num_bodyparts; i++) {
PyObject *str = Py_BuildValue("s", bodyparts[i]);
PyList_Append(list, str);
Py_DECREF(str);
}
free(bodyparts);
return list;
}
PyObject *PyChar_getusergroups(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL)
return Py_BuildValue("s", bitvectorGetBits(charGetUserGroups(ch)));
else
return NULL;
}
PyObject *PyChar_getsocket(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL)
return NULL;
else {
SOCKET_DATA *sock = charGetSocket(ch);
if(sock == NULL)
return Py_BuildValue("O", Py_None);
return Py_BuildValue("O", socketGetPyFormBorrowed(sock));
}
}
//
// Standard check to make sure the character exists when
// trying to set a value for it. If successful, assign the
// character to ch. Otherwise, return -1 (error)
#define PYCHAR_CHECK_CHAR_EXISTS(uid, ch) \
ch = propertyTableGet(mob_table, uid); \
if(ch == NULL) { \
PyErr_Format(PyExc_TypeError, \
"Tried to modify nonexistant character, %d", uid); \
return -1; \
}
int PyChar_setname(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's name");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character names must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetName(ch, PyString_AsString(value));
return 0;
}
int PyChar_setkeywords(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's keywords");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character keywords must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetKeywords(ch, PyString_AsString(value));
return 0;
}
int PyChar_setmname(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's multi-name");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character multi-names must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetMultiName(ch, PyString_AsString(value));
return 0;
}
int PyChar_setdesc(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's description");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character descriptions must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetDesc(ch, PyString_AsString(value));
return 0;
}
int PyChar_setlookbuf(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's look buffer");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Look bufers must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
bufferClear(charGetLookBuffer(ch));
bufferCat(charGetLookBuffer(ch), PyString_AsString(value));
return 0;
}
int PyChar_setrdesc(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's rdesc");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character rdescs must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetRdesc(ch, PyString_AsString(value));
return 0;
}
int PyChar_setmdesc(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete character's multi-rdesc");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character multi-rdescs must be strings");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetMultiRdesc(ch, PyString_AsString(value));
return 0;
}
int PyChar_setrace(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete a character's race");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError, "Character races must be strings");
return -1;
}
const char *race = PyString_AsString(value);
if(!isRace(race))
return -1;
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetRace(ch, race);
charResetBody(ch);
return 0;
}
int PyChar_seton(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete a character's furniture.");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
if (value == Py_None) {
char_from_furniture(ch);
return 0;
}
else if(PyObj_Check(value)) {
OBJ_DATA *obj = propertyTableGet(obj_table, PyObj_AsUid(value));
if(obj == NULL) {
PyErr_Format(PyExc_TypeError,
"Tried to %s's furniture to a nonexistant object.",
charGetName(ch));
return -1;
}
else if(objIsType(obj, "furniture")) {
if(charGetFurniture(ch))
char_from_furniture(ch);
char_to_furniture(ch, obj);
return 0;
}
}
PyErr_Format(PyExc_TypeError,
"A Character's furniture may only be set to None or a ."
"furniture object.");
return -1;
}
int PyChar_setsex(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete a character's sex");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError,
"Character sexes must be strings");
return -1;
}
int sex = sexGetNum(PyString_AsString(value));
if(sex == SEX_NONE) {
char buf[SMALL_BUFFER];
sprintf(buf, "%s is an invalid sex type", PyString_AsString(value));
PyErr_Format(PyExc_TypeError, buf);
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetSex(ch, sex);
return 0;
}
int PyChar_setposition(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete a character's position");
return -1;
}
if (!PyString_Check(value)) {
PyErr_Format(PyExc_TypeError,
"Character positions must be strings");
return -1;
}
int pos = posGetNum(PyString_AsString(value));
if(pos == POS_NONE) {
char buf[SMALL_BUFFER];
sprintf(buf, "%s is an invalid position type", PyString_AsString(value));
PyErr_Format(PyExc_TypeError, buf);
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
charSetPos(ch, pos);
// players can't be on furniture if they are standing or flying
if(poscmp(charGetPos(ch), POS_STANDING) >= 0 && charGetFurniture(ch))
char_from_furniture(ch);
return 0;
}
int PyChar_setroom(PyChar *self, PyObject *value, void *closure) {
if (value == NULL) {
PyErr_Format(PyExc_TypeError, "Cannot delete a character's room");
return -1;
}
ROOM_DATA *room = NULL;
if(PyRoom_Check(value))
room = PyRoom_AsRoom(value);
else if(PyString_Check(value))
room = worldGetRoom(gameworld, PyString_AsString(value));
else {
PyErr_Format(PyExc_TypeError,
"Character's room must be a string value or a "
"room object.");
return -1;
}
if(room == NULL) {
PyErr_Format(PyExc_TypeError,
"Attempting to move character to nonexistent room.");
return -1;
}
CHAR_DATA *ch;
PYCHAR_CHECK_CHAR_EXISTS(self->uid, ch);
// only move if we're not already here
if(charGetRoom(ch) != room) {
char_to_room(ch, room);
// if we were on furniture, make sure we dismount it
if(charGetFurniture(ch))
char_from_furniture(ch);
}
return 0;
}
//*****************************************************************************
// methods for the Char class
//*****************************************************************************
//
// pages a length of text to the character
PyObject *PyChar_page(PyChar *self, PyObject *value) {
char *mssg = NULL;
if (!PyArg_ParseTuple(value, "s", &mssg)) {
PyErr_Format(PyExc_TypeError, "Characters may only be paged strings");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) {
if(charGetSocket(ch))
page_string(charGetSocket(ch), mssg);
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_TypeError,
"Tried to page message to nonexistant character, %d.",
self->uid);
return NULL;
}
}
//
// sends text to the character
PyObject *PyChar_send_raw(PyChar *self, PyObject *value) {
char *mssg = NULL;
if (!PyArg_ParseTuple(value, "s", &mssg)) {
PyErr_Format(PyExc_TypeError,
"Characters may only be sent strings");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch) {
send_to_char(ch, "%s", mssg);
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_TypeError,
"Tried to send message to nonexistant character, %d.",
self->uid);
return NULL;
}
}
//
// sends a newline-tagged message to the character
PyObject *PyChar_send(PyChar *self, PyObject *value) {
PyObject *retval = PyChar_send_raw(self, value);
if(retval == NULL)
return NULL;
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
send_to_char(ch, "\r\n");
Py_DECREF(retval);
return Py_BuildValue("i", 1);
}
//
// Send a newline-tagged message to everyone around the character
PyObject *PyChar_sendaround(PyChar *self, PyObject *value) {
char *mssg = NULL;
if (!PyArg_ParseTuple(value, "s", &mssg)) {
PyErr_Format(PyExc_TypeError,
"Characters may only be sent strings");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch) {
send_around_char(ch, FALSE, "%s\r\n", mssg);
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_TypeError,
"Tried to send message to nonexistant character, %d.",
self->uid);
return NULL;
}
}
//
// make the character perform an action
PyObject *PyChar_act(PyChar *self, PyObject *value) {
char *act = NULL;
bool alias_ok = FALSE;
if (!PyArg_ParseTuple(value, "s|b", &act, &alias_ok)) {
PyErr_Format(PyExc_TypeError, "Characters actions must be strings.");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch) {
// do not send the actual act - if we edit it, things go awry
char *working_act = strdupsafe(act);
do_cmd(ch, working_act, alias_ok);
free(working_act);
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_TypeError,
"Nonexistant character, %d, tried to perform an action.",
self->uid);
return NULL;
}
}
//
// returns whether or not the character can see something
PyObject *PyChar_cansee(PyChar *self, PyObject *arg) {
PyObject *py_tgt = NULL;
if(!PyArg_ParseTuple(arg, "O", &py_tgt)) {
PyErr_Format(PyExc_TypeError, "Must supply obj, mob, or exit for cansee");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL) {
PyErr_Format(PyExc_TypeError, "Nonexistent character, %d, tried cansee",
self->uid);
return NULL;
}
else {
OBJ_DATA *obj = NULL;
CHAR_DATA *pers = NULL;
EXIT_DATA *ex = NULL;
if(PyChar_Check(py_tgt))
pers = PyChar_AsChar(py_tgt);
else if(PyObj_Check(py_tgt))
obj = PyObj_AsObj(py_tgt);
else if(PyExit_Check(py_tgt))
ex = PyExit_AsExit(py_tgt);
else {
PyErr_Format(PyExc_TypeError, "Must supply obj, mob, or exit to cansee");
return NULL;
}
if(obj != NULL)
return Py_BuildValue("b", can_see_obj(ch, obj));
else if(pers != NULL)
return Py_BuildValue("b", can_see_char(ch, pers));
else if(ex != NULL)
return Py_BuildValue("b", can_see_exit(ch, ex));
else {
PyErr_Format(PyExc_StandardError, "Target of cansee did not exist!");
return NULL;
}
}
}
//
// Returns TRUE if the character has the given variable set
PyObject *PyChar_hasvar(PyChar *self, PyObject *arg) {
char *var = NULL;
if (!PyArg_ParseTuple(arg, "s", &var)) {
PyErr_Format(PyExc_TypeError,
"Character variables must have string names.");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL)
return Py_BuildValue("b", charHasVar(ch, var));
PyErr_Format(PyExc_TypeError,
"Tried to get a variable value for nonexistant character, %d",
self->uid);
return NULL;
}
//
// Delete the variable set on the character with the specified name
PyObject *PyChar_deletevar(PyChar *self, PyObject *arg) {
char *var = NULL;
if (!PyArg_ParseTuple(arg, "s", &var)) {
PyErr_Format(PyExc_TypeError,
"Character variables must have string names.");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) {
charDeleteVar(ch, var);
return Py_BuildValue("i", 1);
}
PyErr_Format(PyExc_TypeError,
"Tried to get a variable value for nonexistant character, %d",
self->uid);
return NULL;
}
//
// Get the value of a variable stored on the character
PyObject *PyChar_getvar(PyChar *self, PyObject *arg) {
char *var = NULL;
if (!PyArg_ParseTuple(arg, "s", &var)) {
PyErr_Format(PyExc_TypeError,
"Character variables must have string names.");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) {
int vartype = charGetVarType(ch, var);
if(vartype == CHAR_VAR_INT)
return Py_BuildValue("i", charGetInt(ch, var));
else if(vartype == CHAR_VAR_LONG)
return Py_BuildValue("i", charGetLong(ch, var));
else if(vartype == CHAR_VAR_DOUBLE)
return Py_BuildValue("d", charGetDouble(ch, var));
else
return Py_BuildValue("s", charGetString(ch, var));
}
else {
PyErr_Format(PyExc_TypeError,
"Tried to get a variable value for nonexistant character, %d",
self->uid);
return NULL;
}
}
//
// Set the value of a variable assocciated with the character
PyObject *PyChar_setvar(PyChar *self, PyObject *args) {
char *var = NULL;
PyObject *val = NULL;
if (!PyArg_ParseTuple(args, "sO", &var, &val)) {
PyErr_Format(PyExc_TypeError,
"Character setvar must be supplied with a var name and integer value.");
return NULL;
}
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) {
if(PyInt_Check(val))
charSetInt(ch, var, (int)PyInt_AsLong(val));
else if(PyFloat_Check(val))
charSetDouble(ch, var, PyFloat_AsDouble(val));
else if(PyString_Check(val))
charSetString(ch, var, PyString_AsString(val));
else {
PyErr_Format(PyExc_TypeError,
"Tried to store a char_var of invalid type on char %d.",
self->uid);
return NULL;
}
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_TypeError,
"Tried to set a variable value for nonexistant character, %d",
self->uid);
return NULL;
}
}
PyObject *PyChar_getbodypct(PyChar *self, PyObject *args) {
char *parts = NULL;
CHAR_DATA *ch = NULL;
if (!PyArg_ParseTuple(args, "s", &parts)) {
PyErr_Format(PyExc_TypeError,"A comma-separated list of body parts needed");
return NULL;
}
ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to query body info for nonexistant character!");
return NULL;
}
return Py_BuildValue("d", bodyPartRatio(charGetBody(ch), parts));
}
//
// equips a character with an item
PyObject *PyChar_equip(PyChar *self, PyObject *args) {
OBJ_DATA *obj = NULL;
CHAR_DATA *ch = NULL;
PyObject *pobj = NULL;
char *pos = NULL;
// incase the equip fails, keep item in the original place.. here's the vars
CHAR_DATA *old_carrier = NULL;
CHAR_DATA *old_wearer = NULL;
const char *old_pos = NULL;
ROOM_DATA *old_room = NULL;
OBJ_DATA *old_cont = NULL;
if (!PyArg_ParseTuple(args, "O|z", &pobj, &pos)) {
PyErr_Format(PyExc_TypeError,
"Character equip must be supplied with an item to equip!");
return NULL;
}
if(!PyObj_Check(pobj)) {
PyErr_Format(PyExc_TypeError,
"Only objects may be equipped to characters!");
return NULL;
}
ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to equip nonexistant character!");
return NULL;
}
obj = PyObj_AsObj(pobj);
if(obj == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to equip character with existant object!");
return NULL;
}
// remove the object from whatever it's in/on currently
if((old_room = objGetRoom(obj)) != NULL)
obj_from_room(obj);
if((old_cont = objGetContainer(obj)) != NULL)
obj_from_obj(obj);
if((old_carrier = objGetCarrier(obj)) != NULL)
obj_from_char(obj);
if((old_wearer = objGetWearer(obj)) != NULL) {
old_pos = bodyEquippedWhere(charGetBody(old_wearer), obj);
try_unequip(old_wearer, obj);
}
// try equipping the object. If we fail, put it back wherever it came from
if(!objIsType(obj, "worn") || !try_equip(ch, obj, pos,wornGetPositions(obj))){
if(old_room != NULL)
obj_to_room(obj, old_room);
else if(old_cont != NULL)
obj_to_obj(obj, old_cont);
else if(old_carrier != NULL)
obj_to_char(obj, old_carrier);
else if(old_wearer != NULL)
try_equip(ch, obj, old_pos, NULL);
return Py_BuildValue("i", 0);
// PyErr_Format(PyExc_StandardError,
// "Character is already equipped in all possible positions!");
// return NULL;
}
// success
else
return Py_BuildValue("i", 1);
}
PyObject *PyChar_getequip(PyChar *self, PyObject *args) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
OBJ_DATA *obj = NULL;
char *pos = NULL;
if(ch == NULL) {
PyErr_Format(PyExc_StandardError, "Nonexistant character");
return NULL;
}
if(!PyArg_ParseTuple(args, "s", &pos)) {
PyErr_Format(PyExc_TypeError, "A position name must be supplied.");
return NULL;
}
obj = bodyGetEquipment(charGetBody(ch), pos);
if(obj == NULL)
return Py_BuildValue("O", Py_None);
else
return Py_BuildValue("O", objGetPyFormBorrowed(obj));
}
PyObject *PyChar_attach(PyChar *self, PyObject *args) {
char *key = NULL;
// make sure we're getting passed the right type of data
if (!PyArg_ParseTuple(args, "s", &key)) {
PyErr_Format(PyExc_TypeError,
"To attach a trigger, the trigger key must be suppplied.");
return NULL;
}
// pull out the character and do the attaching
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to attach trigger to nonexistant char, %d.", self->uid);
return NULL;
}
TRIGGER_DATA *trig =
worldGetType(gameworld, "trigger",
get_fullkey_relative(key, get_script_locale()));
if(trig != NULL) {
triggerListAdd(charGetTriggers(ch), triggerGetKey(trig));
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_StandardError,
"Tried to attach nonexistant trigger, %s, to character %s.",
key, charGetClass(ch));
return NULL;
}
}
PyObject *PyChar_detach(PyChar *self, PyObject *args) {
char *key = NULL;
// make sure we're getting passed the right type of data
if (!PyArg_ParseTuple(args, "s", &key)) {
PyErr_Format(PyExc_TypeError,
"To detach a trigger, the key must be supplied.");
return NULL;
}
// pull out the character and do the attaching
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL) {
const char *fkey = get_fullkey_relative(key, get_script_locale());
triggerListRemove(charGetTriggers(ch), fkey);
return Py_BuildValue("i", 1);
}
else {
PyErr_Format(PyExc_StandardError,
"Tried to detach trigger from nonexistant char, %d.",self->uid);
return NULL;
}
}
//
// handles the completion of an action queued up by Python
void PyAction_on_complete(CHAR_DATA *ch, PyObject *tuple, bitvector_t where,
const char *arg) {
PyObject *pychar = NULL; // the python representation of our ch
PyObject *cfunc = NULL; // the function called on completion
PyObject *ifunc = NULL; // the function called on interruption
PyObject *data = NULL; // the data we need to send back
// only run the action of our arguments parse properly
if(PyArg_ParseTuple(tuple, "OOOO", &pychar, &data, &cfunc, &ifunc)) {
if(cfunc != Py_None) {
PyObject *ret = PyObject_CallFunction(cfunc, "OOs", pychar, data, arg);
Py_XDECREF(ret);
}
}
Py_DECREF(tuple);
}
//
// handles the interruption of an action queued up by Python
void PyAction_on_interrupt(CHAR_DATA *ch, PyObject *tuple, bitvector_t where,
const char *arg) {
PyObject *pychar = NULL; // the python representation of our ch
PyObject *cfunc = NULL; // the function called on completion
PyObject *ifunc = NULL; // the function called on interruption
PyObject *data = NULL; // the data we need to send back
// only run the action of our arguments parse properly
if(PyArg_ParseTuple(tuple, "OOOO", &pychar, &data, &cfunc, &ifunc)) {
if(ifunc != Py_None) {
PyObject *ret = PyObject_CallFunction(ifunc, "OOs", pychar, data, arg);
Py_XDECREF(ret);
}
}
Py_DECREF(tuple);
}
//
// start a new action (and interrupt old ones)
PyObject *PyChar_start_action(PyChar *self, PyObject *args) {
CHAR_DATA *ch = NULL; // our normal character representation
PyObject *on_complete = Py_None; // func called when action is completed
PyObject *on_interrupt = Py_None; // func called when action is interrupted
PyObject *data = Py_None; // the function's data value
double delay = 0; // the delay of the action (seconds)
char *arg = NULL; // the action's string argument
// parse all of our values
if(!PyArg_ParseTuple(args, "dO|OOs", &delay, &on_complete, &on_interrupt,
&data, &arg)) {
PyErr_Format(PyExc_TypeError,
"startAction supplied with invalid arguments!");
return NULL;
}
// make sure we exist
if((ch = PyChar_AsChar((PyObject *)self)) == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to start action for nonexistant character!");
return NULL;
}
// now, queue up the action
start_action(ch, (int)(delay SECONDS), 1,
PyAction_on_complete, PyAction_on_interrupt,
Py_BuildValue("OOOO", self, data, on_complete, on_interrupt),
arg);
// success!
return Py_BuildValue("i", 1);
}
//
// check to see if a character currently has an action in progress
PyObject *PyChar_is_acting(PyChar *self, PyObject *args) {
// make sure we exist
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
// make sure the character exists
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to query action status for a nonexistant character.");
return NULL;
}
// return our value
return Py_BuildValue("i", is_acting(ch, 1));
}
//
// interrupt any actions the character is currently performing
PyObject *PyChar_interrupt_action(PyChar *self, PyObject *args) {
// make sure we exist
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
// make sure the character exists
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to interrupt actions for a nonexistant character.");
return NULL;
}
interrupt_action(ch, 1);
return Py_BuildValue("i", 1);
}
//
// returns the specified piece of auxiliary data from the character
// if it is a piece of python auxiliary data.
PyObject *PyChar_get_auxiliary(PyChar *self, PyObject *args) {
char *keyword = NULL;
if(!PyArg_ParseTuple(args, "s", &keyword)) {
PyErr_Format(PyExc_TypeError,
"getAuxiliary() must be supplied with the name that the "
"auxiliary data was installed under!");
return NULL;
}
// make sure we exist
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch == NULL) {
PyErr_Format(PyExc_StandardError,
"Tried to get auxiliary data for a nonexistant character.");
return NULL;
}
// make sure the auxiliary data exists
if(!pyAuxiliaryDataExists(keyword)) {
PyErr_Format(PyExc_StandardError,
"No auxiliary data named '%s' exists!", keyword);
return NULL;
}
PyObject *data = charGetAuxiliaryData(ch, keyword);
if(data == NULL)
data = Py_None;
PyObject *retval = Py_BuildValue("O", data);
// Py_DECREF(data);
return retval;
}
//
// returns whether or not the character is an instance of the prototype
PyObject *PyChar_isinstance(PyChar *self, PyObject *args) {
char *type = NULL;
// make sure we're getting passed the right type of data
if (!PyArg_ParseTuple(args, "s", &type)) {
PyErr_Format(PyExc_TypeError, "isinstance only accepts strings.");
return NULL;
}
// pull out the object and check the type
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL)
return Py_BuildValue("i",
charIsInstance(ch, get_fullkey_relative(type, get_script_locale())));
else {
PyErr_Format(PyExc_StandardError,
"Tried to check instances of nonexistent char, %d.", self->uid);
return NULL;
}
}
//
// returns whether or not the character belongs to one of the specified groups
PyObject *PyChar_is_in_groups(PyChar *self, PyObject *args) {
char *groups = NULL;
// make sure we're getting passed the right type of data
if (!PyArg_ParseTuple(args, "s", &groups)) {
PyErr_Format(PyExc_TypeError, "is_in_groups only accepts strings.");
return NULL;
}
// pull out the object and check the type
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
if(ch != NULL)
return Py_BuildValue("i", bitIsSet(charGetUserGroups(ch), groups));
else {
PyErr_Format(PyExc_StandardError,
"Tried to check user groups of nonexistent char, %d.", self->uid);
return NULL;
}
}
//*****************************************************************************
// comparators, getattr, setattr, and all that other class stuff
//*****************************************************************************
PyTypeObject PyChar_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"char.Char", /*tp_name*/
sizeof(PyChar), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)PyChar_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)PyChar_compare, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"Char/Mob objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyChar_init, /* tp_init */
0, /* tp_alloc */
PyChar_new, /* tp_new */
};
//*****************************************************************************
// methods in the char module
//*****************************************************************************
PyObject *PyChar_load_mob(PyObject *self, PyObject *args) {
char *mob_key = NULL;
PyObject *to = NULL;
ROOM_DATA *room = NULL;
OBJ_DATA *on = NULL;
char *posname = NULL;
if (!PyArg_ParseTuple(args, "sO|s", &mob_key, &to, &posname)) {
PyErr_Format(PyExc_TypeError,
"Load char failed - it needs prototype and destination.");
return NULL;
}
// see what we're trying to load to
if(PyString_Check(to))
room = worldGetRoom(gameworld, PyString_AsString(to));
else if(PyRoom_Check(to))
room = PyRoom_AsRoom(to);
else if(PyObj_Check(to))
on = propertyTableGet(obj_table, PyObj_AsUid(to));
else {
PyErr_Format(PyExc_TypeError,
"Load char failed: invalid load-to type.");
return NULL;
}
// see if we're loading onto something
if(on != NULL)
room = objGetRoom(on);
if(room == NULL) {
PyErr_Format(PyExc_TypeError, "Load char failed: room does not exist, or "
"furniture is not. in a room.");
return NULL;
}
// check the mob
PROTO_DATA *mob_proto =
worldGetType(gameworld, "mproto",
get_fullkey_relative(mob_key, get_script_locale()));
if(mob_proto == NULL) {
PyErr_Format(PyExc_TypeError,
"Load char failed: no mproto for %s exists",
get_fullkey_relative(mob_key, get_script_locale()));
return NULL;
}
// copy the mob, and put it into the game
CHAR_DATA *mob = protoMobRun(mob_proto);
if(mob == NULL) {
PyErr_Format(PyExc_TypeError,
"Load char failed: proto script terminated with an error.");
return NULL;
}
char_to_room(mob, room);
// now check if we need to put the char onto some furniture
// default position is POS_SITTING
if(on) {
int pos = POS_SITTING;
char_to_furniture(mob, on);
if(posname)
pos = posGetNum(posname);
// if the position is none, or greater
// than sitting, default to sitting.
if(pos == POS_NONE || poscmp(pos, POS_SITTING) > 0)
pos = POS_SITTING;
charSetPos(mob, pos);
}
else if(posname) {
int pos = posGetNum(posname);
// if it was an invalid name, set it to standing
if(pos == POS_NONE)
pos = POS_STANDING;
charSetPos(mob, pos);
}
// create a python object for the new char, and return it
return Py_BuildValue("O", charGetPyFormBorrowed(mob));
}
PyObject *PyChar_find_char_key(PyObject *self, PyObject *args) {
CHAR_DATA *ch = NULL;
PyObject *pych = NULL;
LIST *where = mobile_list;
PyObject *pywhere = NULL;
char *key = NULL;
bool must_see = TRUE;
bool multiple = FALSE;
ROOM_DATA *room = NULL;
// figure out our arguments
if(!PyArg_ParseTuple(args, "Os|Obb",&pych,&key,&pywhere,&must_see,&multiple)){
PyErr_Format(PyExc_TypeError, "Invalid arguments supplied to find_char");
return NULL;
}
// make sure ch exists, if we supplied one
if(pych == Py_None)
ch = NULL;
else if(PyChar_Check(pych)) {
ch = PyChar_AsChar(pych);
if(ch == NULL) {
PyErr_Format(PyExc_StandardError, "character does not exist");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError, "first arg must be a Char, or None");
return NULL;
}
// figoure out our room if we supply one
if(pywhere != NULL) {
if(PyRoom_Check(pywhere))
room = PyRoom_AsRoom(pywhere);
else if(PyString_Check(pywhere))
room = worldGetRoom(gameworld,
get_fullkey_relative(PyString_AsString(pywhere),
get_script_locale()));
else if(pywhere == Py_None)
room = NULL;
else {
PyErr_Format(PyExc_TypeError, "search scope must be a room or room key");
return NULL;
}
}
// if we've got a room, look in it
if(room != NULL)
where = roomGetCharacters(room);
// do the searching for a single thing
if(multiple == FALSE) {
CHAR_DATA *found = find_char(ch, where, 1, NULL,
get_fullkey_relative(key, get_script_locale()),
must_see);
return Py_BuildValue("O", (found ? charGetPyFormBorrowed(found) : Py_None));
}
// search for multiple occurences
else {
LIST *found = find_all_chars(ch, where, NULL,
get_fullkey_relative(key, get_script_locale()),
must_see);
PyObject *list = PyList_New(0);
LIST_ITERATOR *found_i = newListIterator(found);
CHAR_DATA *one_found = NULL;
ITERATE_LIST(one_found, found_i) {
PyList_Append(list, charGetPyFormBorrowed(one_found));
} deleteListIterator(found_i);
deleteList(found);
PyObject *retval = Py_BuildValue("O", list);
Py_DECREF(list);
return retval;
}
}
PyObject *PyChar_count_mobs(PyObject *self, PyObject *args) {
LIST *list = NULL;
char *tgt = NULL;
PyObject *in = NULL;
ROOM_DATA *room = NULL;
OBJ_DATA *furniture = NULL;
const char *prototype = NULL;
if (!PyArg_ParseTuple(args, "s|O", &tgt, &in)) {
PyErr_Format(PyExc_TypeError,
"count_mobs failed. No arguments supplied.");
return NULL;
}
// figure out the full key of our prototype
prototype = get_fullkey_relative(tgt, get_script_locale());
// if we didn't supply something to look in, assume it means the world
if(in == NULL)
return Py_BuildValue("i", count_chars(NULL, mobile_list, NULL, prototype,
FALSE));
// see what we're looking in
if(PyString_Check(in))
room = worldGetRoom(gameworld, PyString_AsString(in));
else if(PyRoom_Check(in))
room = PyRoom_AsRoom(in);
else if(PyObj_Check(in))
furniture = propertyTableGet(obj_table, PyObj_AsUid(in));
// now find the list we're dealing with
if(room) list = roomGetCharacters(room);
if(furniture) list = objGetUsers(furniture);
if(list == NULL) {
PyErr_Format(PyExc_TypeError,
"count_mobs failed. invalid argument supplied.");
return NULL;
}
return Py_BuildValue("i", count_chars(NULL, list, NULL, prototype, FALSE));
}
PyObject *PyChar_all_chars(PyObject *self) {
PyObject *list = PyList_New(0);
LIST_ITERATOR *ch_i = newListIterator(mobile_list);
CHAR_DATA *ch = NULL;
ITERATE_LIST(ch, ch_i)
PyList_Append(list, charGetPyFormBorrowed(ch));
deleteListIterator(ch_i);
PyObject *retval = Py_BuildValue("O", list);
Py_DECREF(list);
return retval;
}
PyMethodDef char_module_methods[] = {
{ "char_list", (PyCFunction)PyChar_all_chars, METH_NOARGS,
"Return a python list containing an entry for every character in game." },
{ "load_mob", PyChar_load_mob, METH_VARARGS,
"load a mobile with the specified prototype to a room." },
{ "count_mobs", PyChar_count_mobs, METH_VARARGS,
"count how many occurances of a mobile there are in the specified scope. "
"prototype or name can be used." },
{ "find_char_key", PyChar_find_char_key, METH_VARARGS,
"finds a character (or group of chars) by their prototype. Finding by "
"keywords is done with generic_find()" },
{NULL, NULL, 0, NULL} /* Sentinel */
};
//*****************************************************************************
// implementation of pychar.h
//*****************************************************************************
void PyChar_addGetSetter(const char *name, void *g, void *s, const char *doc) {
// make sure our list of get/setters is created
if(pychar_getsetters == NULL) pychar_getsetters = newList();
// make the GetSetter def
PyGetSetDef *def = calloc(1, sizeof(PyGetSetDef));
def->name = strdup(name);
def->get = (getter)g;
def->set = (setter)s;
def->doc = (doc ? strdup(doc) : NULL);
def->closure = NULL;
listPut(pychar_getsetters, def);
}
void PyChar_addMethod(const char *name, void *f, int flags, const char *doc) {
// make sure our list of methods is created
if(pychar_methods == NULL) pychar_methods = newList();
// make the Method def
PyMethodDef *def = calloc(1, sizeof(PyMethodDef));
def->ml_name = strdup(name);
def->ml_meth = (PyCFunction)f;
def->ml_flags = flags;
def->ml_doc = (doc ? strdup(doc) : NULL);
listPut(pychar_methods, def);
}
PyMODINIT_FUNC init_PyChar(void) {
PyObject* m;
// add in our setters and getters for the char class
PyChar_addGetSetter("inv", PyChar_getinv, NULL,
"returns a list of objects in the char's inventory");
PyChar_addGetSetter("objs", PyChar_getinv, NULL,
"returns a list of objects in the char's inventory");
PyChar_addGetSetter("eq", PyChar_geteq, NULL,
"returns a list of the character's equipment");
PyChar_addGetSetter("bodyparts", PyChar_getbodyparts, NULL,
"Returns a list of the character's bodyparts");
PyChar_addGetSetter("name", PyChar_getname, PyChar_setname,
"handle the character's name");
PyChar_addGetSetter("mname", PyChar_getmname, PyChar_setmname,
"handle the character's multi-name");
PyChar_addGetSetter("desc", PyChar_getdesc, PyChar_setdesc,
"handle the character's description");
PyChar_addGetSetter("look_buf", PyChar_getlookbuf, PyChar_setlookbuf,
"handle the character's look buffer");
PyChar_addGetSetter("rdesc", PyChar_getrdesc, PyChar_setrdesc,
"handle the character's room description");
PyChar_addGetSetter("mdesc", PyChar_getmdesc, PyChar_setmdesc,
"handle the character's multi room description");
PyChar_addGetSetter("keywords", PyChar_getkeywords, PyChar_setkeywords,
"comma-separated list of the character's keywords.");
PyChar_addGetSetter("sex", PyChar_getsex, PyChar_setsex,
"handle the character's gender");
PyChar_addGetSetter("gender", PyChar_getsex, PyChar_setsex,
"handle the character's gender");
PyChar_addGetSetter("race", PyChar_getrace, PyChar_setrace,
"handle the character's race");
PyChar_addGetSetter("pos", PyChar_getposition, PyChar_setposition,
"handle the character's position");
PyChar_addGetSetter("position", PyChar_getposition, PyChar_setposition,
"handle the character's position");
PyChar_addGetSetter("room", PyChar_getroom, PyChar_setroom,
"handle the character's room");
PyChar_addGetSetter("last_room", PyChar_getlastroom, NULL,
"the last room the character was in");
PyChar_addGetSetter("on", PyChar_geton, PyChar_seton,
"The furniture the character is sitting on/at. If the character is not "
"on furniture, None is returned. To remove a character from furniture, "
"then use None");
PyChar_addGetSetter("uid", PyChar_getuid, NULL,
"the character's unique identification number");
PyChar_addGetSetter("prototypes", PyChar_getprototypes, NULL,
"The prototypes for a mobile");
PyChar_addGetSetter("is_npc", PyChar_getisnpc, NULL,
"Returns 1 if the char is an NPC, and 0 otherwise.");
PyChar_addGetSetter("is_pc", PyChar_getispc, NULL,
"Returns 1 if the char is a PC, and 0 otherwise.");
PyChar_addGetSetter("hisher", PyChar_gethisher, NULL,
"Returns 'his' if the char is male, 'her' if female, and "
"'its' for neuters");
PyChar_addGetSetter("himher", PyChar_gethimher, NULL,
"Returns 'him' if the char is male, 'her' if female, and "
"'it' for neuters");
PyChar_addGetSetter("heshe", PyChar_getheshe, NULL,
"Returns 'he' if the char is male, 'she' if female, and "
"'it' for neuters");
PyChar_addGetSetter("user_groups", PyChar_getusergroups, NULL,
"Returns the character's user groups");
PyChar_addGetSetter("socket", PyChar_getsocket, NULL,
"Returns the character's socket if it exists.");
PyChar_addGetSetter("sock", PyChar_getsocket, NULL,
"Returns the character's socket if it exists.");
// add in all of our methods for the Char class
PyChar_addMethod("attach", PyChar_attach, METH_VARARGS,
"attach a new script to the character.");
PyChar_addMethod("detach", PyChar_detach, METH_VARARGS,
"detach an old script from the character.");
PyChar_addMethod("send", PyChar_send, METH_VARARGS,
"send a message to the character with appended newline.");
PyChar_addMethod("send_raw", PyChar_send_raw, METH_VARARGS,
"send a message to the character.");
PyChar_addMethod("sendaround", PyChar_sendaround, METH_VARARGS,
"send a message to everyone around the character.");
PyChar_addMethod("act", PyChar_act, METH_VARARGS,
"make the character perform an action.");
PyChar_addMethod("getvar", PyChar_getvar, METH_VARARGS,
"get the value of a special variable the character has.");
PyChar_addMethod("setvar", PyChar_setvar, METH_VARARGS,
"set the value of a special variable the character has.");
PyChar_addMethod("hasvar", PyChar_hasvar, METH_VARARGS,
"return whether or not the character has a given variable.");
PyChar_addMethod("deletevar", PyChar_deletevar, METH_VARARGS,
"delete a variable from the character's variable table.");
PyChar_addMethod("delvar", PyChar_deletevar, METH_VARARGS,
"delete a variable from the character's variable table.");
PyChar_addMethod("equip", PyChar_equip, METH_VARARGS,
"equips a character with the given item. Removes the item "
"from whatever it is currently in/on.");
PyChar_addMethod("get_equip", PyChar_getequip, METH_VARARGS,
"Returns the person's equipment in the specified slot.");
PyChar_addMethod("get_bodypct", PyChar_getbodypct, METH_VARARGS,
"Returns the percent mass of the character's body taken up "
"by the specified parts.");
PyChar_addMethod("isActing", PyChar_is_acting, METH_VARARGS,
"Returns True if the character is currently taking an "
"action, and False otherwise.");
PyChar_addMethod("startAction", PyChar_start_action, METH_VARARGS,
"Begins the character starting a new action");
PyChar_addMethod("interrupt", PyChar_interrupt_action, METH_VARARGS,
"Interrupts the character's current action.");
PyChar_addMethod("getAuxiliary", PyChar_get_auxiliary, METH_VARARGS,
"get's the specified piece of aux data from the char");
PyChar_addMethod("cansee", PyChar_cansee, METH_VARARGS,
"returns whether or not a char can see an obj or mob.");
PyChar_addMethod("page", PyChar_page, METH_VARARGS,
"page a bunch of text to the character.");
PyChar_addMethod("isinstance", PyChar_isinstance, METH_VARARGS,
"returns whether or not the char inherits from the proto");
PyChar_addMethod("isInGroup", PyChar_is_in_groups, METH_VARARGS,
"returns whether or not the character belongs to one of the groups");
// add in all the getsetters and methods
makePyType(&PyChar_Type, pychar_getsetters, pychar_methods);
deleteListWith(pychar_getsetters, free); pychar_getsetters = NULL;
deleteListWith(pychar_methods, free); pychar_methods = NULL;
// make sure the room class is ready to be made
if (PyType_Ready(&PyChar_Type) < 0)
return;
// load the module
m = Py_InitModule3("char", char_module_methods,
"The char module, for all char/mob-related MUD stuff.");
// make sure it loaded OK
if (m == NULL)
return;
// add the Char class to the module
PyTypeObject *type = &PyChar_Type;
Py_INCREF(&PyChar_Type);
PyModule_AddObject(m, "Char", (PyObject *)type);
}
int PyChar_Check(PyObject *value) {
return PyObject_TypeCheck(value, &PyChar_Type);
}
int PyChar_AsUid(PyObject *ch) {
return ((PyChar *)ch)->uid;
}
CHAR_DATA *PyChar_AsChar(PyObject *ch) {
return propertyTableGet(mob_table, PyChar_AsUid(ch));
}
PyObject *
newPyChar(CHAR_DATA *ch) {
PyChar *py_ch = (PyChar *)PyChar_new(&PyChar_Type, NULL, NULL);
py_ch->uid = charGetUID(ch);
return (PyObject *)py_ch;
}