/*****************************************************************************/ /* CrossFire, A Multiplayer game for X-windows */ /* */ /* Copyright (C) 2000 Mark Wedel */ /* Copyright (C) 1992 Frank Tore Johansen */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /*****************************************************************************/ /* This is the server-side plugin management part. */ /*****************************************************************************/ /* Original code by Yann Chachkoff (yann.chachkoff@mailandnews.com). */ /* Special thanks to: */ /* David Delbecq (david.delbecq@mailandnews.com); */ /* Joris Bontje (jbontje@suespammers.org); */ /* Philip Currlin (?); */ /*****************************************************************************/ /*****************************************************************************/ /* First, the headers. We only include plugin.h, because all other includes */ /* are done into it, and plugproto.h (which is used only by this file). */ /*****************************************************************************/ #include #ifndef __CEXTRACT__ # include #endif #define NR_OF_HOOKS 74 static const hook_entry plug_hooks[NR_OF_HOOKS] = { {cfapi_system_register_global_event, 1, "cfapi_system_register_global_event"}, {cfapi_system_unregister_global_event, 3, "cfapi_system_unregister_global_event"}, {cfapi_system_check_path, 4, "cfapi_system_check_path"}, {NULL, 5, "cfapi_system_re_cmp"}, {cfapi_system_strdup_local, 6, "cfapi_system_strdup_local"}, {cfapi_system_directory, 7, "cfapi_system_directory"}, {cfapi_system_find_animation, 8, "cfapi_system_find_animation"}, {cfapi_object_clean_object, 9, "cfapi_object_clean_object"}, {cfapi_object_on_same_map, 10, "cfapi_object_on_same_map"}, {cfapi_object_get_key, 11, "cfapi_object_get_key"}, {cfapi_object_set_key, 12, "cfapi_object_set_key"}, {cfapi_object_get_property, 13, "cfapi_object_get_property"}, {cfapi_object_set_property, 14, "cfapi_object_set_property"}, {cfapi_object_apply, 15, "cfapi_object_apply"}, {cfapi_object_identify, 16, "cfapi_object_identify"}, {cfapi_object_describe, 17, "cfapi_object_describe"}, {cfapi_object_drain, 18, "cfapi_object_drain"}, {cfapi_object_fix, 19, "cfapi_object_fix"}, {cfapi_object_give_skill, 20, "cfapi_object_give_skill"}, {cfapi_object_transmute, 21, "cfapi_object_transmute"}, {cfapi_object_remove, 22, "cfapi_object_remove"}, {cfapi_object_delete, 23, "cfapi_object_delete"}, {cfapi_object_clone, 24, "cfapi_object_clone"}, {cfapi_object_find, 25, "cfapi_object_find"}, {cfapi_object_create, 26, "cfapi_object_create"}, {cfapi_object_insert, 27, "cfapi_object_insert"}, {cfapi_object_split, 28, "cfapi_object_split"}, {cfapi_object_merge, 29, "cfapi_object_merge"}, {cfapi_object_distance, 30, "cfapi_object_distance"}, {cfapi_object_update, 31, "cfapi_object_update"}, {cfapi_object_clear, 32, "cfapi_object_clear"}, {cfapi_object_reset, 33, "cfapi_object_reset"}, {cfapi_object_check_inventory, 34, "cfapi_object_check_inventory"}, {cfapi_object_spring_trap, 35, "cfapi_object_spring_trap"}, {cfapi_object_check_trigger, 36, "cfapi_object_check_trigger"}, {cfapi_object_query_cost, 37, "cfapi_object_query_cost"}, {cfapi_object_query_money, 38, "cfapi_object_query_money"}, {cfapi_object_cast, 39, "cfapi_object_cast"}, {cfapi_object_learn_spell, 40, "cfapi_object_learn_spell"}, {cfapi_object_forget_spell, 41, "cfapi_object_forget_spell"}, {cfapi_object_check_spell, 42, "cfapi_object_check_spell"}, {cfapi_object_pay_amount, 43, "cfapi_object_pay_amount"}, {cfapi_object_pay_item, 44, "cfapi_object_pay_item"}, {cfapi_object_transfer, 45, "cfapi_object_transfer"}, {cfapi_object_drop, 46, "cfapi_object_drop"}, {cfapi_object_take, 47, "cfapi_object_take"}, {cfapi_object_find_archetype_inside, 48, "cfapi_object_find_archetype_inside"}, {cfapi_object_say, 49, "cfapi_object_say"}, {cfapi_map_get_map, 50, "cfapi_map_get_map"}, {cfapi_map_has_been_loaded, 51, "cfapi_map_has_been_loaded"}, {cfapi_map_create_path, 52, "cfapi_map_create_path"}, {cfapi_map_get_map_property, 53, "cfapi_map_get_property"}, {cfapi_map_set_map_property, 54, "cfapi_map_set_property"}, {cfapi_map_out_of_map, 55, "cfapi_map_out_of_map"}, {cfapi_map_update_position, 56, "cfapi_map_update_position"}, {cfapi_map_delete_map, 57, "cfapi_map_delete_map"}, {cfapi_map_message, 58, "cfapi_map_message"}, {cfapi_map_get_object_at, 59, "cfapi_map_get_object_at"}, {cfapi_map_get_flags, 60, "cfapi_map_get_flags"}, {cfapi_map_present_arch_by_name, 61, "cfapi_map_present_arch_by_name"}, {cfapi_player_find, 62, "cfapi_player_find"}, {cfapi_player_message, 63, "cfapi_player_message"}, {cfapi_player_send_inventory, 64, "cfapi_player_send_inventory"}, {cfapi_object_teleport, 65, "cfapi_object_teleport"}, {cfapi_object_speak, 66, "cfapi_object_speak"}, {cfapi_object_pickup, 67, "cfapi_object_pickup"}, {cfapi_object_move, 68, "cfapi_object_move"}, {cfapi_object_apply_below, 69, "cfapi_object_apply_below"}, {cfapi_archetype_get_first, 70, "cfapi_archetype_get_first"}, {cfapi_archetype_get_property, 71, "cfapi_archetype_get_property"}, {cfapi_party_get_property, 72, "cfapi_party_get_property"}, {cfapi_region_get_property, 73, "cfapi_region_get_property"}, }; int plugin_number = 0; crossfire_plugin *plugins_list = NULL; /*****************************************************************************/ /* NEW PLUGIN STUFF STARTS HERE */ /*****************************************************************************/ /** * Notify clients about a changed object. * * @param op the object that has changed */ static void send_changed_object (object *op) { object *tmp; player *pl; if (op->env != NULL) { tmp = is_player_inv (op->env); if (!tmp) { for (pl = first_player; pl; pl = pl->next) if (pl->ob->container == op->env) break; if (pl) tmp = pl->ob; else tmp = NULL; } if (tmp) esrv_send_item (tmp, op); } else { for (tmp = op->above; tmp != NULL; tmp = tmp->above) if (tmp->type == PLAYER) esrv_send_item (tmp, op); } } /** * Notify clients about a removed object. * * @param op the object about to be removed from its environment; it must still * be present in its environment */ static void send_removed_object (object *op) { object *tmp; player *pl; if (op->env == NULL) { /* no action necessary: remove_ob() notifies the client */ return; } tmp = is_player_inv (op->env); if (!tmp) { for (pl = first_player; pl; pl = pl->next) if (pl->ob->container == op->env) break; if (pl) tmp = pl->ob; else tmp = NULL; } if (tmp) esrv_del_item (tmp->contr, op->count); } extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr); extern "C" void *cfperl_getPluginProperty (int *type, ...); extern "C" int cfperl_postInitPlugin (); extern "C" int cfperl_closePlugin (); // this is a temporary hack till the old plugin stuff is removed int plugins_init_perl () { f_plug_init initfunc; f_plug_api propfunc; f_plug_postinit postfunc; f_plug_postinit closefunc; int i; crossfire_plugin *cp; crossfire_plugin *ccp; initfunc = (f_plug_init) cfperl_initPlugin; propfunc = (f_plug_api) cfperl_getPluginProperty; postfunc = (f_plug_postinit) cfperl_postInitPlugin; closefunc = (f_plug_postinit) cfperl_closePlugin; i = initfunc ("2.0", cfapi_get_hooks); cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin)); for (i = 0; i < NR_EVENTS; i++) cp->gevent[i] = NULL; cp->eventfunc = 0; cp->propfunc = propfunc; cp->closefunc = closefunc; cp->libptr = 0; strcpy (cp->id, (const char *) propfunc (&i, "Identification")); strcpy (cp->fullname, (const char *) propfunc (&i, "FullName")); cp->next = NULL; cp->prev = NULL; if (plugins_list == NULL) { plugins_list = cp; } else { for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next) ; ccp->next = cp; cp->prev = ccp; } postfunc (); plugin_number++; return 0; } int plugins_init_plugin (const char *libfile) { return 0; LIBPTRTYPE ptr; f_plug_init initfunc; f_plug_api propfunc; f_plug_api eventfunc; f_plug_postinit postfunc; f_plug_postinit closefunc; int i; crossfire_plugin *cp; crossfire_plugin *ccp; /* Open the plugin lib and load the required functions */ ptr = plugins_dlopen (libfile); if (ptr == NULL) { LOG (llevError, "Error trying to load %s: %s\n", libfile, plugins_dlerror ()); return -1; } initfunc = (f_plug_init) plugins_dlsym (ptr, "initPlugin"); if (initfunc == NULL) { LOG (llevError, "Plugin error while requesting %s.initPlugin: %s\n", libfile, plugins_dlerror ()); plugins_dlclose (ptr); return -1; } propfunc = (f_plug_api) plugins_dlsym (ptr, "getPluginProperty"); if (propfunc == NULL) { LOG (llevError, "Plugin error while requesting %s.getPluginProperty: %s\n", libfile, plugins_dlerror ()); plugins_dlclose (ptr); return -1; } eventfunc = (f_plug_api) plugins_dlsym (ptr, "eventListener"); if (eventfunc == NULL) { LOG (llevError, "Plugin error while requesting %s.eventListener: %s\n", libfile, plugins_dlerror ()); plugins_dlclose (ptr); return -1; } postfunc = (f_plug_postinit) plugins_dlsym (ptr, "postInitPlugin"); if (postfunc == NULL) { LOG (llevError, "Plugin error while requesting %s.postInitPlugin: %s\n", libfile, plugins_dlerror ()); plugins_dlclose (ptr); return -1; } closefunc = (f_plug_postinit) plugins_dlsym (ptr, "closePlugin"); if (postfunc == NULL) { LOG (llevError, "Plugin error while requesting %s.closePlugin: %s\n", libfile, plugins_dlerror ()); plugins_dlclose (ptr); return -1; } i = initfunc ("2.0", cfapi_get_hooks); cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin)); for (i = 0; i < NR_EVENTS; i++) cp->gevent[i] = NULL; cp->eventfunc = eventfunc; cp->propfunc = propfunc; cp->closefunc = closefunc; cp->libptr = ptr; strcpy (cp->id, (const char *) propfunc (&i, "Identification")); strcpy (cp->fullname, (const char *) propfunc (&i, "FullName")); cp->next = NULL; cp->prev = NULL; if (plugins_list == NULL) { plugins_list = cp; } else { for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next) ; ccp->next = cp; cp->prev = ccp; } postfunc (); plugin_number++; return 0; } void * cfapi_get_hooks (int *type, ...) { va_list args; int request_type; char *buf; int fid; f_plug_api rv; int i; va_start (args, type); request_type = va_arg (args, int); if (request_type == 0) { /* By nr */ fid = va_arg (args, int); if (fid < 0 || fid >= NR_OF_HOOKS) { rv = NULL; *type = CFAPI_NONE; } else { rv = plug_hooks[fid].func; *type = CFAPI_FUNC; } } else { /* by name */ buf = va_arg (args, char *); rv = NULL; for (i = 0; i < NR_OF_HOOKS; i++) { if (!strcmp (buf, plug_hooks[i].fname)) { rv = plug_hooks[i].func; *type = CFAPI_FUNC; break; } } if (rv == NULL) { *type = CFAPI_NONE; } } va_end (args); return (void *) rv; } int plugins_remove_plugin (const char *id) { crossfire_plugin *cp; if (plugins_list == NULL) return -1; for (cp = plugins_list; cp != NULL; cp = cp->next) { if (!strcmp (id, cp->id) && cp->libptr) { crossfire_plugin *n; crossfire_plugin *p; n = cp->next; p = cp->prev; plugins_dlclose (cp->libptr); if (n != NULL) { if (p != NULL) { n->prev = p; p->next = n; } else { n->prev = NULL; plugins_list = n; } } else { if (p != NULL) p->next = NULL; else plugins_list = NULL; } free (cp); plugin_number--; return 0; } } return -1; } crossfire_plugin * plugins_find_plugin (const char *id) { crossfire_plugin *cp; if (plugins_list == NULL) return NULL; for (cp = plugins_list; cp != NULL; cp = cp->next) { if (!strcmp (id, cp->id)) { return cp; } } return NULL; } /*****************************************************************************/ /* Displays a list of loaded plugins (keystrings and description) in the */ /* game log window. */ /*****************************************************************************/ void plugins_display_list (object *op) { crossfire_plugin *cp; new_draw_info (NDI_UNIQUE, 0, op, "List of loaded plugins:"); new_draw_info (NDI_UNIQUE, 0, op, "-----------------------"); if (plugins_list == NULL) return; for (cp = plugins_list; cp != NULL; cp = cp->next) { new_draw_info_format (NDI_UNIQUE, 0, op, "%s, %s", cp->id, cp->fullname); } } /* SYSTEM-RELATED HOOKS */ void * cfapi_system_find_animation (int *type, ...) { va_list args; static int rv; char *anim; va_start (args, type); anim = va_arg (args, char *); va_end (args); rv = find_animation (anim); *type = CFAPI_INT; return &rv; } void * cfapi_system_strdup_local (int *type, ...) { va_list args; char *txt; va_start (args, type); txt = va_arg (args, char *); va_end (args); *type = CFAPI_STRING; return strdup_local (txt); } void * cfapi_system_register_global_event (int *type, ...) { va_list args; int eventcode; char *pname; f_plug_api hook; crossfire_plugin *cp; va_start (args, type); eventcode = va_arg (args, int); pname = va_arg (args, char *); hook = va_arg (args, f_plug_api); va_end (args); cp = plugins_find_plugin (pname); cp->gevent[eventcode] = hook; return NULL; } void * cfapi_system_unregister_global_event (int *type, ...) { va_list args; int eventcode; char *pname; crossfire_plugin *cp; va_start (args, type); eventcode = va_arg (args, int); pname = va_arg (args, char *); cp = plugins_find_plugin (pname); cp->gevent[eventcode] = NULL; va_end (args); return NULL; } void * cfapi_system_check_path (int *type, ...) { va_list args; static int rv; char *name; int prepend_dir; va_start (args, type); name = va_arg (args, char *); prepend_dir = va_arg (args, int); rv = check_path (name, prepend_dir); va_end (args); *type = CFAPI_INT; return &rv; } void * cfapi_system_directory (int *type, ...) { va_list args; int dirtype; va_start (args, type); dirtype = va_arg (args, int); va_end (args); *type = CFAPI_STRING; switch (dirtype) { case 0: return settings.mapdir; break; case 1: return settings.uniquedir; break; case 2: return settings.tmpdir; break; case 3: return settings.confdir; break; case 4: return settings.localdir; break; case 5: return settings.playerdir; break; case 6: return settings.datadir; break; } *type = CFAPI_NONE; return NULL; } /* MAP RELATED HOOKS */ void * cfapi_map_get_map (int *type, ...) { va_list args; maptile *rv; int ctype; int x, y; sint16 nx, ny; char *name; maptile *m; va_start (args, type); ctype = va_arg (args, int); switch (ctype) { case 0: x = va_arg (args, int); y = va_arg (args, int); rv = get_empty_map (x, y); break; case 1: name = va_arg (args, char *); x = va_arg (args, int); rv = ready_map_name (name, x); break; case 2: m = va_arg (args, maptile *); nx = va_arg (args, int); ny = va_arg (args, int); rv = get_map_from_coord (m, &nx, &ny); break; case 3: rv = first_map; break; default: *type = CFAPI_NONE; va_end (args); return NULL; break; } va_end (args); *type = CFAPI_PMAP; return rv; } void * cfapi_map_has_been_loaded (int *type, ...) { va_list args; maptile *map; char *string; va_start (args, type); string = va_arg (args, char *); map = has_been_loaded (string); va_end (args); *type = CFAPI_PMAP; return map; } void * cfapi_map_create_path (int *type, ...) { va_list args; int ctype; const char *str; char *rv; va_start (args, type); ctype = va_arg (args, int); str = va_arg (args, char *); *type = CFAPI_STRING; switch (ctype) { case 0: rv = (char *) create_pathname (str); break; case 1: rv = (char *) create_overlay_pathname (str); break; /*case 2: rv = create_items_path(str); break; */ default: rv = NULL; *type = CFAPI_NONE; break; } va_end (args); return rv; } void * cfapi_map_get_map_property (int *type, ...) { va_list args; int x, y; sint16 nx, ny; maptile *map; maptile *newmap; static int rv; int property; char *buf; va_start (args, type); property = va_arg (args, int); switch (property) { case CFAPI_MAP_PROP_FLAGS: map = va_arg (args, maptile *); newmap = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); nx = va_arg (args, int); ny = va_arg (args, int); rv = get_map_flags (map, &newmap, x, y, &nx, &ny); va_end (args); *type = CFAPI_INT; return &rv; break; case CFAPI_MAP_PROP_DIFFICULTY: map = va_arg (args, maptile *); rv = calculate_difficulty (map); va_end (args); *type = CFAPI_INT; return &rv; break; case CFAPI_MAP_PROP_PATH: map = va_arg (args, maptile *); buf = map->path; *type = CFAPI_STRING; va_end (args); return buf; break; case CFAPI_MAP_PROP_TMPNAME: map = va_arg (args, maptile *); buf = map->tmpname; *type = CFAPI_STRING; va_end (args); return buf; break; case CFAPI_MAP_PROP_NAME: map = va_arg (args, maptile *); buf = map->name; *type = CFAPI_STRING; va_end (args); return buf; break; case CFAPI_MAP_PROP_RESET_TIME: map = va_arg (args, maptile *); rv = map->reset_time; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_RESET_TIMEOUT: map = va_arg (args, maptile *); rv = map->reset_timeout; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_PLAYERS: map = va_arg (args, maptile *); rv = map->players; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_DARKNESS: map = va_arg (args, maptile *); rv = map->darkness; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_WIDTH: map = va_arg (args, maptile *); rv = map->width; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_HEIGHT: map = va_arg (args, maptile *); rv = map->height; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_ENTER_X: map = va_arg (args, maptile *); rv = map->enter_x; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_ENTER_Y: map = va_arg (args, maptile *); rv = map->enter_y; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_TEMPERATURE: map = va_arg (args, maptile *); rv = map->temp; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_PRESSURE: map = va_arg (args, maptile *); rv = map->pressure; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_HUMIDITY: map = va_arg (args, maptile *); rv = map->humid; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_WINDSPEED: map = va_arg (args, maptile *); rv = map->windspeed; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_WINDDIR: map = va_arg (args, maptile *); rv = map->winddir; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_SKY: map = va_arg (args, maptile *); rv = map->sky; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_WPARTX: map = va_arg (args, maptile *); rv = map->wpartx; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_WPARTY: map = va_arg (args, maptile *); rv = map->wparty; *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_MESSAGE: map = va_arg (args, maptile *); buf = map->msg; *type = CFAPI_STRING; va_end (args); return buf; break; case CFAPI_MAP_PROP_NEXT: map = va_arg (args, maptile *); *type = CFAPI_PMAP; va_end (args); return map->next; break; case CFAPI_MAP_PROP_REGION: map = va_arg (args, maptile *); *type = CFAPI_PREGION; va_end (args); return get_region_by_map (map); break; default: *type = CFAPI_NONE; va_end (args); return NULL; break; } } void * cfapi_map_set_map_property (int *type, ...) { va_list args; static int rv; maptile *map; int val; int property; va_start (args, type); property = va_arg (args, int); switch (property) { case CFAPI_MAP_PROP_LIGHT: map = va_arg (args, maptile *); val = va_arg (args, int); rv = change_map_light (map, val); *type = CFAPI_INT; va_end (args); return &rv; break; case CFAPI_MAP_PROP_RESET_TIME: map = va_arg (args, maptile *); *type = CFAPI_NONE; va_end (args); return NULL; break; default: *type = CFAPI_NONE; va_end (args); return NULL; break; } } void * cfapi_map_out_of_map (int *type, ...) { va_list args; static int rv; maptile *map; int x, y; va_start (args, type); map = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); rv = out_of_map (map, x, y); va_end (args); *type = CFAPI_INT; return &rv; } void * cfapi_map_update_position (int *type, ...) { va_list args; maptile *map; int x, y; va_start (args, type); map = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); update_position (map, x, y); va_end (args); *type = CFAPI_NONE; return NULL; } void * cfapi_map_delete_map (int *type, ...) { va_list args; maptile *map; va_start (args, type); map = va_arg (args, maptile *); delete_map (map); va_end (args); *type = CFAPI_NONE; return NULL; } void * cfapi_map_message (int *type, ...) { va_list args; maptile *map; char *string; int color; va_start (args, type); map = va_arg (args, maptile *); string = va_arg (args, char *); color = va_arg (args, int); va_end (args); new_info_map (color, map, string); *type = CFAPI_NONE; return NULL; } void * cfapi_map_get_object_at (int *type, ...) { va_list args; maptile *map; int x, y; object *rv; va_start (args, type); map = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); va_end (args); rv = get_map_ob (map, x, y); *type = CFAPI_POBJECT; return rv; } void * cfapi_map_get_flags (int *type, ...) { va_list args; sint16 x, y; sint16 *nx, *ny; static maptile *map; maptile **newmap; static int rv; va_start (args, type); map = va_arg (args, maptile *); newmap = va_arg (args, maptile **); x = va_arg (args, int); y = va_arg (args, int); nx = va_arg (args, sint16 *); ny = va_arg (args, sint16 *); va_end (args); rv = get_map_flags (map, newmap, x, y, nx, ny); *type = CFAPI_INT; return &rv; } void * cfapi_map_present_arch_by_name (int *type, ...) { va_list args; object *rv; int x, y; maptile *map; char *msg; va_start (args, type); msg = va_arg (args, char *); map = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); va_end (args); rv = present_arch (archetype::find (msg), map, x, y); *type = CFAPI_POBJECT; return rv; } /* OBJECT-RELATED HOOKS */ void * cfapi_object_move (int *type, ...) { va_list args; int kind; object *op; object *activator; player *pl; int direction; static int rv = 0; va_start (args, type); kind = va_arg (args, int); switch (kind) { case 0: op = va_arg (args, object *); direction = va_arg (args, int); activator = va_arg (args, object *); va_end (args); rv = move_ob (op, direction, activator); break; case 1: pl = va_arg (args, player *); direction = va_arg (args, int); va_end (args); rv = move_player (pl->ob, direction); break; } *type = CFAPI_INT; return &rv; } void * cfapi_object_get_key (int *type, ...) { va_list args; char *rv; char *keyname; object *op; va_start (args, type); op = va_arg (args, object *); keyname = va_arg (args, char *); va_end (args); rv = (char *) get_ob_key_value (op, keyname); *type = CFAPI_STRING; return rv; } void * cfapi_object_set_key (int *type, ...) { va_list args; char *keyname; char *value; object *op; va_start (args, type); op = va_arg (args, object *); keyname = va_arg (args, char *); value = va_arg (args, char *); va_end (args); set_ob_key_value (op, keyname, value, 0); *type = CFAPI_NONE; return NULL; } void * cfapi_object_get_property (int *type, ...) { va_list args; int property; object *op; void *rv; static int ri; va_start (args, type); op = va_arg (args, object *); property = va_arg (args, int); rv = NULL; if (op != NULL) { switch (property) { case CFAPI_OBJECT_PROP_OB_ABOVE: rv = op->above; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_OB_BELOW: rv = op->below; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_NEXT_ACTIVE_OB: rv = op->active_next; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_PREV_ACTIVE_OB: rv = op->active_prev; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_INVENTORY: rv = op->inv; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_ENVIRONMENT: rv = op->env; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_HEAD: rv = op->head; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_CONTAINER: rv = op->container; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_MAP: rv = op->map; *type = CFAPI_PMAP; break; case CFAPI_OBJECT_PROP_COUNT: ri = op->count; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_REFCOUNT: abort (); break; case CFAPI_OBJECT_PROP_NAME: rv = query_name (op); *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_NAME_PLURAL: rv = (char *) &op->name_pl; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_TITLE: rv = (char *) &op->title; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_RACE: rv = (char *) &op->race; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_SLAYING: rv = (char *) &op->slaying; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_SKILL: rv = (char *) &op->skill; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_MESSAGE: rv = (char *) &op->msg; if (rv == NULL) rv = (void *) ""; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_LORE: rv = (char *) &op->lore; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_X: ri = op->x; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_Y: ri = op->y; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_SPEED: rv = &op->speed; *type = CFAPI_DOUBLE; break; case CFAPI_OBJECT_PROP_SPEED_LEFT: rv = &op->speed_left; *type = CFAPI_DOUBLE; break; case CFAPI_OBJECT_PROP_NROF: ri = op->nrof; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_DIRECTION: ri = op->direction; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_FACING: ri = op->facing; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_TYPE: ri = op->type; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_SUBTYPE: ri = op->subtype; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_CLIENT_TYPE: ri = op->client_type; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_RESIST: { int idx; idx = va_arg (args, int); ri = op->resist[idx]; rv = &ri; } *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_ATTACK_TYPE: ri = op->attacktype; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PATH_ATTUNED: ri = op->path_attuned; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PATH_REPELLED: ri = op->path_repelled; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PATH_DENIED: ri = op->path_denied; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MATERIAL: ri = op->material; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MAGIC: ri = op->magic; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_VALUE: ri = op->value; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LEVEL: ri = op->level; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LAST_HEAL: ri = op->last_heal; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LAST_SP: ri = op->last_sp; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LAST_GRACE: ri = op->last_grace; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LAST_EAT: ri = op->last_eat; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_INVISIBLE_TIME: ri = op->invisible; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PICK_UP: ri = op->pick_up; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_ITEM_POWER: ri = op->item_power; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR: ri = op->gen_sp_armour; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_WEIGHT: ri = op->weight; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_WEIGHT_LIMIT: ri = op->weight_limit; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_CARRYING: ri = op->carrying; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_GLOW_RADIUS: ri = op->glow_radius; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PERM_EXP: rv = &op->perm_exp; *type = CFAPI_LONG; break; case CFAPI_OBJECT_PROP_CURRENT_WEAPON: rv = op->current_weapon; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_ENEMY: rv = op->enemy; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_ATTACKED_BY: rv = op->attacked_by; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_RUN_AWAY: ri = op->run_away; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_CHOSEN_SKILL: rv = op->chosen_skill; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_HIDDEN: ri = op->hide; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MOVE_STATUS: ri = op->move_status; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MOVE_TYPE: ri = op->attack_movement; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_SPELL_ITEM: rv = op->spellitem; *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_EXP_MULTIPLIER: rv = &op->expmul; *type = CFAPI_DOUBLE; break; case CFAPI_OBJECT_PROP_ARCHETYPE: rv = op->arch; *type = CFAPI_PARCH; break; case CFAPI_OBJECT_PROP_OTHER_ARCH: rv = op->other_arch; *type = CFAPI_PARCH; break; case CFAPI_OBJECT_PROP_ANIM_SPEED: ri = op->anim_speed; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_FRIENDLY: ri = is_friendly (op); rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_BASE_NAME: { int i; i = va_arg (args, int); rv = (char *) query_base_name (op, i); *type = CFAPI_STRING; } break; case CFAPI_OBJECT_PROP_MAGICAL: ri = is_magical (op); rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_LUCK: ri = op->stats.luck; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_EXP: rv = &op->stats.exp; *type = CFAPI_LONG; break; case CFAPI_OBJECT_PROP_OWNER: rv = get_owner (op); *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_PRESENT: { int stype; rv = 0; stype = va_arg (args, int); switch (stype) { unsigned char ptype; char *buf; archetype *at; case 0: /* present_in_ob */ ptype = (unsigned char) (va_arg (args, int)); rv = present_in_ob (ptype, op); break; case 1: /* present_in_ob_by_name */ ptype = (unsigned char) (va_arg (args, int)); buf = va_arg (args, char *); rv = present_in_ob_by_name (ptype, buf, op); break; case 2: /* present_arch_in_ob */ at = va_arg (args, archetype *); rv = present_arch_in_ob (at, op); break; } } *type = CFAPI_POBJECT; break; case CFAPI_OBJECT_PROP_CHEATER: ri = (QUERY_FLAG (op, FLAG_WAS_WIZ)); rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MERGEABLE: { object *op2; op2 = va_arg (args, object *); ri = CAN_MERGE (op, op2); rv = &ri; } *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_PICKABLE: { object *op2; rv = 0; op2 = va_arg (args, object *); ri = can_pick (op2, op); rv = &ri; } *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_FLAGS: { int fl; ri = 0; fl = va_arg (args, int); ri = QUERY_FLAG (op, fl); rv = &ri; } *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_STR: ri = op->stats.Str; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_DEX: ri = op->stats.Dex; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_CON: ri = op->stats.Con; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_WIS: ri = op->stats.Wis; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_INT: ri = op->stats.Int; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_POW: ri = op->stats.Pow; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_CHA: ri = op->stats.Cha; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_WC: ri = op->stats.wc; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_AC: ri = op->stats.ac; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_HP: ri = op->stats.hp; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_SP: ri = op->stats.sp; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_GP: ri = op->stats.grace; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_FP: ri = op->stats.food; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MAXHP: ri = op->stats.maxhp; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MAXSP: ri = op->stats.maxsp; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_MAXGP: ri = op->stats.maxgrace; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_DAM: ri = op->stats.dam; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_GOD: rv = (char *) determine_god (op); *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_ARCH_NAME: rv = (char *) &op->arch->name; *type = CFAPI_STRING; break; case CFAPI_OBJECT_PROP_INVISIBLE: ri = op->invisible; rv = &ri; *type = CFAPI_INT; break; case CFAPI_OBJECT_PROP_FACE: ri = op->animation_id; rv = &ri; *type = CFAPI_INT; break; case CFAPI_PLAYER_PROP_IP: rv = op->contr->socket.host; *type = CFAPI_STRING; break; case CFAPI_PLAYER_PROP_MARKED_ITEM: rv = find_marked_object (op); *type = CFAPI_POBJECT; break; case CFAPI_PLAYER_PROP_PARTY: rv = (op->contr ? op->contr->party : NULL); *type = CFAPI_PPARTY; break; default: *type = CFAPI_NONE; break; } } va_end (args); return rv; } void * cfapi_object_set_property (int *type, ...) { va_list args; int iarg; long larg; char *sarg; double darg; object *oparg; object *op; int property; void *rv; partylist *partyarg; va_start (args, type); op = va_arg (args, object *); property = va_arg (args, int); rv = NULL; if (op != NULL && (!op->arch || (op != &op->arch->clone))) { switch (property) { case CFAPI_OBJECT_PROP_NAME: sarg = va_arg (args, char *); #define FREE_AND_COPY(a,b) (a) = (b) // TODO: remove, but plugins.C is considered zombie code FREE_AND_COPY (op->name, sarg); send_changed_object (op); break; case CFAPI_OBJECT_PROP_NAME_PLURAL: sarg = va_arg (args, char *); FREE_AND_COPY (op->name_pl, sarg); send_changed_object (op); break; case CFAPI_OBJECT_PROP_TITLE: sarg = va_arg (args, char *); FREE_AND_COPY (op->title, sarg); break; case CFAPI_OBJECT_PROP_RACE: sarg = va_arg (args, char *); FREE_AND_COPY (op->race, sarg); break; case CFAPI_OBJECT_PROP_SLAYING: sarg = va_arg (args, char *); FREE_AND_COPY (op->slaying, sarg); break; case CFAPI_OBJECT_PROP_SKILL: sarg = va_arg (args, char *); FREE_AND_COPY (op->skill, sarg); break; case CFAPI_OBJECT_PROP_MESSAGE: sarg = va_arg (args, char *); FREE_AND_COPY (op->msg, sarg); break; case CFAPI_OBJECT_PROP_LORE: sarg = va_arg (args, char *); FREE_AND_COPY (op->lore, sarg); break; case CFAPI_OBJECT_PROP_SPEED: darg = va_arg (args, double); op->speed = darg; break; case CFAPI_OBJECT_PROP_SPEED_LEFT: darg = va_arg (args, double); op->speed_left = darg; break; case CFAPI_OBJECT_PROP_NROF: iarg = va_arg (args, int); if (iarg < 0) iarg = 0; if (op->nrof > (uint32) iarg) decrease_ob_nr (op, op->nrof - iarg); else if (op->nrof < (uint32) iarg) { object *tmp; player *pl; op->nrof = iarg; if (op->env != NULL) { tmp = is_player_inv (op->env); if (!tmp) { for (pl = first_player; pl; pl = pl->next) if (pl->ob->container == op->env) break; if (pl) tmp = pl->ob; else tmp = NULL; } else { sum_weight (tmp); fix_player (tmp); } if (tmp) esrv_send_item (tmp, op); } else { object *above = op->above; for (tmp = above; tmp != NULL; tmp = tmp->above) if (tmp->type == PLAYER) esrv_send_item (tmp, op); } } break; case CFAPI_OBJECT_PROP_DIRECTION: iarg = va_arg (args, int); op->direction = iarg; break; case CFAPI_OBJECT_PROP_FACING: iarg = va_arg (args, int); op->facing = iarg; break; case CFAPI_OBJECT_PROP_RESIST: { int iargbis = va_arg (args, int); iarg = va_arg (args, int); op->resist[iargbis] = iarg; } break; case CFAPI_OBJECT_PROP_ATTACK_TYPE: iarg = va_arg (args, int); op->attacktype = iarg; break; case CFAPI_OBJECT_PROP_PATH_ATTUNED: iarg = va_arg (args, int); op->path_attuned = iarg; break; case CFAPI_OBJECT_PROP_PATH_REPELLED: iarg = va_arg (args, int); op->path_repelled = iarg; break; case CFAPI_OBJECT_PROP_PATH_DENIED: iarg = va_arg (args, int); op->path_denied = iarg; break; case CFAPI_OBJECT_PROP_MATERIAL: iarg = va_arg (args, int); op->material = iarg; break; case CFAPI_OBJECT_PROP_MATERIAL_NAME: break; case CFAPI_OBJECT_PROP_MAGIC: iarg = va_arg (args, int); op->magic = iarg; break; case CFAPI_OBJECT_PROP_VALUE: iarg = va_arg (args, int); op->value = iarg; break; case CFAPI_OBJECT_PROP_LEVEL: iarg = va_arg (args, int); op->level = iarg; break; case CFAPI_OBJECT_PROP_LAST_HEAL: iarg = va_arg (args, int); op->last_heal = iarg; break; case CFAPI_OBJECT_PROP_LAST_SP: iarg = va_arg (args, int); op->last_sp = iarg; break; case CFAPI_OBJECT_PROP_LAST_GRACE: iarg = va_arg (args, int); op->last_grace = iarg; break; case CFAPI_OBJECT_PROP_LAST_EAT: iarg = va_arg (args, int); op->last_eat = iarg; break; case CFAPI_OBJECT_PROP_INVISIBLE_TIME: iarg = va_arg (args, int); op->invisible = iarg; break; case CFAPI_OBJECT_PROP_PICK_UP: iarg = va_arg (args, int); op->pick_up = iarg; break; case CFAPI_OBJECT_PROP_ITEM_POWER: iarg = va_arg (args, int); op->item_power = iarg; break; case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR: iarg = va_arg (args, int); op->gen_sp_armour = iarg; break; case CFAPI_OBJECT_PROP_WEIGHT: iarg = va_arg (args, int); if (op->weight != iarg) { object *tmp; player *pl; op->weight = iarg; if (op->env != NULL) { tmp = is_player_inv (op->env); if (!tmp) { for (pl = first_player; pl; pl = pl->next) if (pl->ob->container == op->env) break; if (pl) tmp = pl->ob; else tmp = NULL; } else { sum_weight (tmp); fix_player (tmp); } if (tmp) esrv_send_item (tmp, op); } else { object *above = op->above; for (tmp = above; tmp != NULL; tmp = tmp->above) if (tmp->type == PLAYER) esrv_send_item (tmp, op); } } break; case CFAPI_OBJECT_PROP_WEIGHT_LIMIT: iarg = va_arg (args, int); op->weight_limit = iarg; break; case CFAPI_OBJECT_PROP_GLOW_RADIUS: iarg = va_arg (args, int); op->glow_radius = iarg; break; case CFAPI_OBJECT_PROP_PERM_EXP: larg = va_arg (args, long); op->perm_exp = larg; break; case CFAPI_OBJECT_PROP_ENEMY: oparg = va_arg (args, object *); op->enemy = oparg; break; case CFAPI_OBJECT_PROP_RUN_AWAY: iarg = va_arg (args, int); op->run_away = iarg; break; case CFAPI_OBJECT_PROP_CHOSEN_SKILL: oparg = va_arg (args, object *); op->chosen_skill = oparg; break; case CFAPI_OBJECT_PROP_HIDDEN: iarg = va_arg (args, int); op->hide = iarg; break; case CFAPI_OBJECT_PROP_MOVE_STATUS: iarg = va_arg (args, int); op->move_status = iarg; break; case CFAPI_OBJECT_PROP_MOVE_TYPE: iarg = va_arg (args, int); op->attack_movement = iarg; break; case CFAPI_OBJECT_PROP_SPELL_ITEM: oparg = va_arg (args, object *); op->spellitem = oparg; break; case CFAPI_OBJECT_PROP_EXP_MULTIPLIER: darg = va_arg (args, double); op->expmul = darg; break; case CFAPI_OBJECT_PROP_CUSTOM_NAME: sarg = va_arg (args, char *); FREE_AND_COPY (op->custom_name, sarg); send_changed_object (op); break; case CFAPI_OBJECT_PROP_ANIM_SPEED: iarg = va_arg (args, int); op->anim_speed = iarg; break; case CFAPI_OBJECT_PROP_FRIENDLY: iarg = va_arg (args, int); if (iarg == 1 && is_friendly (op) == 0) add_friendly_object (op); else if (iarg == 0 && is_friendly (op) == 1) remove_friendly_object (op); break; case CFAPI_OBJECT_PROP_LUCK: iarg = va_arg (args, int); op->stats.luck = iarg; break; case CFAPI_OBJECT_PROP_EXP: { char *skillname; larg = va_arg (args, long); skillname = va_arg (args, char *); iarg = va_arg (args, int); change_exp (op, larg, skillname, iarg); } break; case CFAPI_OBJECT_PROP_OWNER: oparg = va_arg (args, object *); set_owner (op, oparg); break; case CFAPI_OBJECT_PROP_CHEATER: set_cheat (op); break; case CFAPI_OBJECT_PROP_FLAGS: { int iargbis; iarg = va_arg (args, int); iargbis = va_arg (args, int); if (iargbis == 1) SET_FLAG (op, iarg); else CLEAR_FLAG (op, iarg); } break; case CFAPI_OBJECT_PROP_STR: iarg = va_arg (args, int); op->stats.Str = iarg; break; case CFAPI_OBJECT_PROP_DEX: iarg = va_arg (args, int); op->stats.Dex = iarg; break; case CFAPI_OBJECT_PROP_CON: iarg = va_arg (args, int); op->stats.Con = iarg; break; case CFAPI_OBJECT_PROP_WIS: iarg = va_arg (args, int); op->stats.Wis = iarg; break; case CFAPI_OBJECT_PROP_INT: iarg = va_arg (args, int); op->stats.Int = iarg; break; case CFAPI_OBJECT_PROP_POW: iarg = va_arg (args, int); op->stats.Pow = iarg; break; case CFAPI_OBJECT_PROP_CHA: iarg = va_arg (args, int); op->stats.Cha = iarg; break; case CFAPI_OBJECT_PROP_WC: iarg = va_arg (args, int); op->stats.wc = iarg; break; case CFAPI_OBJECT_PROP_AC: iarg = va_arg (args, int); op->stats.ac = iarg; break; case CFAPI_OBJECT_PROP_HP: iarg = va_arg (args, int); op->stats.hp = iarg; break; case CFAPI_OBJECT_PROP_SP: iarg = va_arg (args, int); op->stats.sp = iarg; break; case CFAPI_OBJECT_PROP_GP: iarg = va_arg (args, int); op->stats.grace = iarg; break; case CFAPI_OBJECT_PROP_FP: iarg = va_arg (args, int); op->stats.food = iarg; break; case CFAPI_OBJECT_PROP_MAXHP: iarg = va_arg (args, int); op->stats.maxhp = iarg; break; case CFAPI_OBJECT_PROP_MAXSP: iarg = va_arg (args, int); op->stats.maxsp = iarg; break; case CFAPI_OBJECT_PROP_MAXGP: iarg = va_arg (args, int); op->stats.maxgrace = iarg; break; case CFAPI_OBJECT_PROP_DAM: iarg = va_arg (args, int); op->stats.dam = iarg; break; case CFAPI_OBJECT_PROP_FACE: iarg = va_arg (args, int); op->animation_id = iarg; update_object (op, UP_OBJ_FACE); break; case CFAPI_OBJECT_ANIMATION: iarg = va_arg (args, int); if (iarg != -1) { SET_ANIMATION (op, iarg); } update_object (op, UP_OBJ_FACE); break; case CFAPI_PLAYER_PROP_MARKED_ITEM: if (op->contr) { oparg = va_arg (args, object *); op->contr->mark = oparg; } break; case CFAPI_PLAYER_PROP_PARTY: if (op->contr) { partyarg = va_arg (args, partylist *); op->contr->party = partyarg; } break; default: *type = CFAPI_NONE; break; } } va_end (args); *type = CFAPI_NONE; return NULL; } void * cfapi_object_apply_below (int *type, ...) { va_list args; object *applier; va_start (args, type); applier = va_arg (args, object *); va_end (args); player_apply_below (applier); *type = CFAPI_NONE; return NULL; } void * cfapi_object_apply (int *type, ...) { va_list args; object *applied; object *applier; int aflags; static int rv; va_start (args, type); applied = va_arg (args, object *); applier = va_arg (args, object *); aflags = va_arg (args, int); va_end (args); *type = CFAPI_INT; rv = manual_apply (applier, applied, aflags); return &rv; } void * cfapi_object_identify (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); va_end (args); identify (op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_describe (int *type, ...) { va_list args; object *op; object *owner; va_start (args, type); op = va_arg (args, object *); owner = va_arg (args, object *); va_end (args); *type = CFAPI_STRING; return describe_item (op, owner); } void * cfapi_object_drain (int *type, ...) { va_list args; object *op; int ds; va_start (args, type); op = va_arg (args, object *); ds = va_arg (args, int); va_end (args); drain_specific_stat (op, ds); *type = CFAPI_NONE; return NULL; } void * cfapi_object_fix (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); va_end (args); fix_player (op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_give_skill (int *type, ...) { va_list args; object *op; char *skillname; va_start (args, type); op = va_arg (args, object *); skillname = va_arg (args, char *); va_end (args); *type = CFAPI_POBJECT; return give_skill_by_name (op, skillname); } void * cfapi_object_transmute (int *type, ...) { va_list args; object *op; object *chg; va_start (args, type); op = va_arg (args, object *); chg = va_arg (args, object *); va_end (args); transmute_materialname (op, chg); *type = CFAPI_NONE; return NULL; } void * cfapi_object_remove (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); va_end (args); send_removed_object (op); remove_ob (op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_delete (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); va_end (args); free_object (op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_clone (int *type, ...) { va_list args; object *op; int kind; va_start (args, type); op = va_arg (args, object *); kind = va_arg (args, int); va_end (args); if (kind == 0) { *type = CFAPI_POBJECT; return object_create_clone (op); } else { object *tmp; tmp = get_object (); copy_object (op, tmp); *type = CFAPI_POBJECT; return tmp; } } void * cfapi_object_find (int *type, ...) { va_list args; int ftype; void *rv; int ival; int ival2; char *sval; object *op; va_start (args, type); *type = CFAPI_POBJECT; ftype = va_arg (args, int); switch (ftype) { case 0: ival = va_arg (args, int); rv = find_object (ival); break; case 1: sval = va_arg (args, char *); rv = find_object_name (sval); break; case 2: op = va_arg (args, object *); ival = va_arg (args, int); ival2 = va_arg (args, int); rv = find_obj_by_type_subtype (op, ival, ival2); break; case 3: op = va_arg (args, object *); rv = is_player_inv (op); break; default: rv = NULL; *type = CFAPI_NONE; break; } va_end (args); return rv; } void * cfapi_object_create (int *type, ...) { va_list args; int ival; va_start (args, type); ival = va_arg (args, int); *type = CFAPI_POBJECT; switch (ival) { case 0: va_end (args); return get_object (); break; case 1: /* Named object. Nearly the old plugin behavior, but we don't add artifact suffixes */ { char *sval; object *op; sval = va_arg (args, char *); op = get_archetype_by_object_name (sval); if (strncmp (query_name (op), ARCH_SINGULARITY, ARCH_SINGULARITY_LEN) == 0) { free_object (op); /* Try with archetype names... */ op = get_archetype (sval); if (strncmp (query_name (op), ARCH_SINGULARITY, ARCH_SINGULARITY_LEN) == 0) { free_object (op); *type = CFAPI_NONE; va_end (args); return NULL; } } va_end (args); return op; } break; default: *type = CFAPI_NONE; va_end (args); return NULL; break; } } void * cfapi_object_insert (int *type, ...) { va_list args; object *op; object *orig; maptile *map; int flag, x, y; int itype; char *arch_string; void *rv = NULL; va_start (args, type); op = va_arg (args, object *); itype = va_arg (args, int); switch (itype) { case 0: map = va_arg (args, maptile *); orig = va_arg (args, object *); flag = va_arg (args, int); x = va_arg (args, int); y = va_arg (args, int); rv = insert_ob_in_map_at (op, map, orig, flag, x, y); *type = CFAPI_POBJECT; break; case 1: map = va_arg (args, maptile *); orig = va_arg (args, object *); flag = va_arg (args, int); rv = insert_ob_in_map (op, map, orig, flag); *type = CFAPI_POBJECT; break; case 2: arch_string = va_arg (args, char *); replace_insert_ob_in_map (arch_string, op); *type = CFAPI_NONE; break; case 3: orig = va_arg (args, object *); rv = insert_ob_in_ob (op, orig); if (orig->type == PLAYER) { esrv_send_item (orig, op); } *type = CFAPI_POBJECT; break; } va_end (args); return rv; } void * cfapi_object_split (int *type, ...) { va_list args; int nr; object *op; va_start (args, type); op = va_arg (args, object *); nr = va_arg (args, int); va_end (args); *type = CFAPI_POBJECT; return get_split_ob (op, nr); } void * cfapi_object_merge (int *type, ...) { va_list args; object *op; object *op2; va_start (args, type); op = va_arg (args, object *); op2 = va_arg (args, object *); va_end (args); *type = CFAPI_POBJECT; return merge_ob (op, op2); } void * cfapi_object_distance (int *type, ...) { va_list args; static int rv; object *op; object *op2; va_start (args, type); op = va_arg (args, object *); op2 = va_arg (args, object *); va_end (args); *type = CFAPI_INT; rv = distance (op, op2); return &rv; } void * cfapi_object_update (int *type, ...) { va_list args; int action; object *op; va_start (args, type); op = va_arg (args, object *); action = va_arg (args, int); va_end (args); update_object (op, action); *type = CFAPI_NONE; return NULL; } void * cfapi_object_clear (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); va_end (args); clear_object (op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_reset (int *type, ...) { abort (); } void * cfapi_object_check_inventory (int *type, ...) { va_list args; object *op; object *op2; int checktype; object *ret = NULL; va_start (args, type); op = va_arg (args, object *); op2 = va_arg (args, object *); checktype = va_arg (args, int); if (checktype == 0) { check_inv (op, op2); *type = CFAPI_NONE; } else { ret = check_inv_recursive (op, op2); *type = CFAPI_POBJECT; } va_end (args); return ret; } void * cfapi_object_clean_object (int *type, ...) { va_list args; object *op; va_start (args, type); op = va_arg (args, object *); clean_object (op); va_end (args); *type = CFAPI_NONE; return NULL; } void * cfapi_object_on_same_map (int *type, ...) { va_list args; static int rv; object *op1; object *op2; va_start (args, type); op1 = va_arg (args, object *); op2 = va_arg (args, object *); rv = on_same_map (op1, op2); va_end (args); *type = CFAPI_INT; return &rv; } void * cfapi_object_spring_trap (int *type, ...) { object *trap; object *victim; va_list args; va_start (args, type); trap = va_arg (args, object *); victim = va_arg (args, object *); va_end (args); spring_trap (trap, victim); *type = CFAPI_NONE; return NULL; } void * cfapi_object_check_trigger (int *type, ...) { object *op; object *cause; va_list args; static int rv; va_start (args, type); op = va_arg (args, object *); cause = va_arg (args, object *); va_end (args); rv = check_trigger (op, cause); *type = CFAPI_INT; return &rv; } void * cfapi_object_query_cost (int *type, ...) { object *op; object *who; int flags; va_list args; static int rv; va_start (args, type); op = va_arg (args, object *); who = va_arg (args, object *); flags = va_arg (args, int); va_end (args); rv = query_cost (op, who, flags); *type = CFAPI_INT; return &rv; } void * cfapi_object_query_money (int *type, ...) { object *op; va_list args; static int rv; va_start (args, type); op = va_arg (args, object *); va_end (args); rv = query_money (op); *type = CFAPI_INT; return &rv; } void * cfapi_object_cast (int *type, ...) { object *op; object *sp; int dir; char *str; object *caster; va_list args; static int rv; va_start (args, type); op = va_arg (args, object *); caster = va_arg (args, object *); dir = va_arg (args, int); sp = va_arg (args, object *); str = va_arg (args, char *); va_end (args); rv = cast_spell (op, caster, dir, sp, str); *type = CFAPI_INT; return &rv; } void * cfapi_object_learn_spell (int *type, ...) { object *op; object *sp; int prayer; va_list args; va_start (args, type); op = va_arg (args, object *); sp = va_arg (args, object *); prayer = va_arg (args, int); va_end (args); do_learn_spell (op, sp, prayer); *type = CFAPI_NONE; return NULL; } void * cfapi_object_forget_spell (int *type, ...) { object *op; object *sp; va_list args; va_start (args, type); op = va_arg (args, object *); sp = va_arg (args, object *); va_end (args); do_forget_spell (op, query_name (sp)); *type = CFAPI_NONE; return NULL; } void * cfapi_object_check_spell (int *type, ...) { object *op; char *spellname; va_list args; object *rv; va_start (args, type); op = va_arg (args, object *); spellname = va_arg (args, char *); va_end (args); rv = check_spell_known (op, spellname); *type = CFAPI_POBJECT; return rv; } void * cfapi_object_pay_amount (int *type, ...) { object *op; uint64 amount; va_list args; static int rv; va_start (args, type); op = va_arg (args, object *); amount = va_arg (args, uint64); va_end (args); rv = pay_for_amount (amount, op); *type = CFAPI_INT; return &rv; } void * cfapi_object_pay_item (int *type, ...) { object *op; object *tobuy; va_list args; static int rv; va_start (args, type); tobuy = va_arg (args, object *); op = va_arg (args, object *); va_end (args); rv = pay_for_item (tobuy, op); *type = CFAPI_INT; return &rv; } void * cfapi_object_transfer (int *type, ...) { object *op; object *originator; int x, y, randompos, ttype; va_list args; static int rv = 0; maptile *map; va_start (args, type); op = va_arg (args, object *); ttype = va_arg (args, int); switch (ttype) { case 0: x = va_arg (args, int); y = va_arg (args, int); randompos = va_arg (args, int); originator = va_arg (args, object *); va_end (args); rv = transfer_ob (op, x, y, randompos, originator); *type = CFAPI_INT; return &rv; break; case 1: x = va_arg (args, int); y = va_arg (args, int); map = va_arg (args, maptile *); va_end (args); if (x < 0 || y < 0) { x = map->enter_x; y = map->enter_y; } /* originator = get_object(); EXIT_PATH(originator) = add_string(map->path); EXIT_X(originator) = x; EXIT_Y(originator) = y; printf("B Transfer: X=%d, Y=%d, OP=%s\n", x, y, op->name);*/ /*enter_exit(op, originator); */ insert_ob_in_map_at (op, map, NULL, 0, x, y); /*printf("A Transfer: X=%d, Y=%d, MAP=%s\n", x, y, op->map->name); free_object(originator); */ *type = CFAPI_INT; return &rv; break; default: *type = CFAPI_NONE; return NULL; break; } } void * cfapi_object_find_archetype_inside (int *type, ...) { object *op; int critera; char *str; va_list args; object *rv; *type = CFAPI_POBJECT; va_start (args, type); op = va_arg (args, object *); critera = va_arg (args, int); switch (critera) { case 0: /* By name, either exact or from query_name */ str = va_arg (args, char *); rv = present_arch_in_ob (archetype::find (str), op); if (rv == NULL) { object *tmp; /* Search by query_name instead */ for (tmp = op->inv; tmp; tmp = tmp->below) { if (!strncmp (query_name (tmp), str, strlen (str))) rv = tmp; if (!strncmp (tmp->name, str, strlen (str))) rv = tmp; if (rv != NULL) break; } } break; default: rv = NULL; break; } va_end (args); if (rv == NULL) { *type = CFAPI_NONE; } return rv; } void * cfapi_object_drop (int *type, ...) { object *op; object *author; va_list args; va_start (args, type); op = va_arg (args, object *); author = va_arg (args, object *); va_end (args); if (QUERY_FLAG (op, FLAG_NO_DROP)) return NULL; drop (author, op); if (author->type == PLAYER) { author->contr->count = 0; author->contr->socket.update_look = 1; } *type = CFAPI_NONE; return NULL; } void * cfapi_object_take (int *type, ...) { object *op; object *author; va_list args; va_start (args, type); op = va_arg (args, object *); author = va_arg (args, object *); va_end (args); pick_up (author, op); *type = CFAPI_NONE; return NULL; } void * cfapi_object_say (int *type, ...) { abort (); } void * cfapi_object_speak (int *type, ...) { abort (); } /* PLAYER SUBCLASS */ void * cfapi_player_find (int *type, ...) { va_list args; void *rv; char *sval; va_start (args, type); sval = va_arg (args, char *); va_end (args); rv = find_player (sval); *type = CFAPI_PPLAYER; return rv; } void * cfapi_player_message (int *type, ...) { va_list args; int flags; int pri; object *pl; char *buf; va_start (args, type); flags = va_arg (args, int); pri = va_arg (args, int); pl = va_arg (args, object *); buf = va_arg (args, char *); va_end (args); new_draw_info (flags, pri, pl, buf); *type = CFAPI_NONE; return NULL; } void * cfapi_player_send_inventory (int *type, ...) { /* Currently a stub. Do we really need this anymore ? */ *type = CFAPI_NONE; return NULL; } void * cfapi_object_teleport (int *type, ...) { maptile *map; int x, y; object *who; static int result; va_list args; va_start (args, type); who = va_arg (args, object *); map = va_arg (args, maptile *); x = va_arg (args, int); y = va_arg (args, int); if (!out_of_map (map, x, y)) { int k; object *tmp; k = find_first_free_spot (who, map, x, y); if (k == -1) { result = 1; return &result; } send_removed_object (who); remove_ob (who); for (tmp = who; tmp != NULL; tmp = tmp->more) tmp->x = x + freearr_x[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x), tmp->y = y + freearr_y[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y); insert_ob_in_map (who, map, NULL, 0); result = 0; } return &result; } void * cfapi_object_pickup (int *type, ...) { object *who; object *what; va_list args; va_start (args, type); who = va_arg (args, object *); what = va_arg (args, object *); va_end (args); pick_up (who, what); *type = CFAPI_NONE; return NULL; } /* Archetype-related functions */ void * cfapi_archetype_get_first (int *type, ...) { va_list args; va_start (args, type); va_end (args); *type = CFAPI_PARCH; return first_archetype; } void * cfapi_archetype_get_property (int *type, ...) { archetype *arch; int prop; va_list args; void *rv; va_start (args, type); arch = va_arg (args, archetype *); prop = va_arg (args, int); switch (prop) { case CFAPI_ARCH_PROP_NAME: *type = CFAPI_STRING; rv = (void *) &arch->name; break; case CFAPI_ARCH_PROP_NEXT: *type = CFAPI_PARCH; rv = arch->next; break; case CFAPI_ARCH_PROP_HEAD: *type = CFAPI_PARCH; rv = arch->head; break; case CFAPI_ARCH_PROP_MORE: *type = CFAPI_PARCH; rv = arch->more; break; case CFAPI_ARCH_PROP_CLONE: *type = CFAPI_POBJECT; rv = &arch->clone; break; default: *type = CFAPI_NONE; rv = NULL; break; } va_end (args); return rv; } /* Party-related functions */ void * cfapi_party_get_property (int *type, ...) { partylist *party; int prop; va_list args; void *rv; object *obarg; player *pl; va_start (args, type); party = va_arg (args, partylist *); prop = va_arg (args, int); switch (prop) { case CFAPI_PARTY_PROP_NAME: *type = CFAPI_STRING; rv = (void *) party->partyname; break; case CFAPI_PARTY_PROP_NEXT: *type = CFAPI_PPARTY; rv = (party ? party->next : get_firstparty ()); break; case CFAPI_PARTY_PROP_PASSWORD: *type = CFAPI_STRING; rv = (void *) party->passwd; break; case CFAPI_PARTY_PROP_PLAYER: *type = CFAPI_PPLAYER; obarg = va_arg (args, object *); pl = (obarg ? obarg->contr : first_player); rv = NULL; for (; pl != NULL; pl = pl->next) if (pl->ob->contr->party == party) { rv = (void *) pl; break; } break; default: *type = CFAPI_NONE; rv = NULL; break; } va_end (args); return rv; } /* Regions-related functions */ void * cfapi_region_get_property (int *type, ...) { region *reg; int prop; va_list args; void *rv; va_start (args, type); reg = va_arg (args, region *); prop = va_arg (args, int); switch (prop) { case CFAPI_REGION_PROP_NAME: *type = CFAPI_STRING; rv = (void *) reg->name; break; case CFAPI_REGION_PROP_NEXT: *type = CFAPI_PREGION; rv = (reg ? reg->next : first_region); break; case CFAPI_REGION_PROP_PARENT: *type = CFAPI_PREGION; rv = (void *) reg->parent; break; case CFAPI_REGION_PROP_LONGNAME: *type = CFAPI_STRING; rv = (void *) reg->longname; break; case CFAPI_REGION_PROP_MESSAGE: *type = CFAPI_STRING; rv = (void *) reg->msg; break; default: *type = CFAPI_NONE; rv = NULL; break; } va_end (args); return rv; } /*****************************************************************************/ /* NEW PLUGIN STUFF ENDS HERE */ /*****************************************************************************/ /*****************************************************************************/ /* Tries to find if a given command is handled by a plugin. */ /* Note that find_plugin_command is called *before* the internal commands are*/ /* checked, meaning that you can "overwrite" them. */ /*****************************************************************************/ CommArray_s * find_plugin_command (char *cmd, object *op) { int i; crossfire_plugin *cp; CommArray_s *rtn_cmd; if (plugins_list == NULL) return NULL; for (cp = plugins_list; cp != NULL; cp = cp->next) { rtn_cmd = (CommArray_s *) cp->propfunc (&i, "command?", cmd); if (rtn_cmd) return rtn_cmd; } return NULL; } /*****************************************************************************/ /* Plugins initialization. Browses the plugins directory and call */ /* initOnePlugin for each file found. */ /* Returns 0 if at least one plugin was successfully loaded, -1 if not */ /*****************************************************************************/ int initPlugins (void) { struct dirent *currentfile; DIR *plugdir; size_t l; char buf[MAX_BUF]; char buf2[MAX_BUF]; int result; LOG (llevInfo, "Initializing plugins\n"); strcpy (buf, LIBDIR); strcat (buf, "/plugins/"); LOG (llevInfo, "Plugins directory is %s\n", buf); plugins_init_perl (); plugdir = opendir (buf); if (plugdir == NULL) return -1; result = -1; while ((currentfile = readdir (plugdir)) != NULL) { l = strlen (currentfile->d_name); if (l > strlen (PLUGIN_SUFFIX)) { if (strcmp (currentfile->d_name + l - strlen (PLUGIN_SUFFIX), PLUGIN_SUFFIX) == 0) { strcpy (buf2, buf); strcat (buf2, currentfile->d_name); LOG (llevInfo, " -> Loading plugin : %s\n", currentfile->d_name); if (plugins_init_plugin (buf2) == 0) result = 0; } } } closedir (plugdir); return result; }