Crossfire Server, Branch 1.12  R12190
plugins.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_plugins_c =
00003  *   "$Id: plugins.c 11578 2009-02-23 22:02:27Z lalo $";
00004  */
00005 
00006 /*****************************************************************************/
00007 /*  CrossFire, A Multiplayer game for X-windows                              */
00008 /*                                                                           */
00009 /*  Copyright (C) 2000-2006 Mark Wedel & Crossfire Development Team          */
00010 /*  Copyright (C) 1992 Frank Tore Johansen                                   */
00011 /*                                                                           */
00012 /*  This program is free software; you can redistribute it and/or modify     */
00013 /*  it under the terms of the GNU General Public License as published by     */
00014 /*  the Free Software Foundation; either version 2 of the License, or        */
00015 /*  (at your option) any later version.                                      */
00016 /*                                                                           */
00017 /*  This program is distributed in the hope that it will be useful,          */
00018 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
00019 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
00020 /*  GNU General Public License for more details.                             */
00021 /*                                                                           */
00022 /*  You should have received a copy of the GNU General Public License        */
00023 /*  along with this program; if not, write to the Free Software              */
00024 /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
00025 /*                                                                           */
00026 /*  The authors can be reached via e-mail to crossfire-devel@real-time.com   */
00027 /*****************************************************************************/
00028 /* This is the server-side plugin management part.                           */
00029 /*****************************************************************************/
00030 /* Original code by Yann Chachkoff (yann.chachkoff@mailandnews.com).         */
00031 /* Special thanks to:                                                        */
00032 /* David Delbecq                   (david.delbecq@mailandnews.com);          */
00033 /* Joris Bontje                    (jbontje@suespammers.org);                */
00034 /* Philip Currlin                  (?);                                      */
00035 /*****************************************************************************/
00036 
00045 #if 0
00046 
00047 #define PLUGIN_DEBUG
00048 #endif
00049 
00050 /*****************************************************************************/
00051 /* First, the headers. We only include plugin.h, because all other includes  */
00052 /* are done into it, and plugproto.h (which is used only by this file).      */
00053 /*****************************************************************************/
00054 #include <plugin.h>
00055 
00056 #ifndef __CEXTRACT__
00057 #include <sproto.h>
00058 #include <timers.h>
00059 #endif
00060 
00061 #define NR_OF_HOOKS 89
00062 
00063 static const hook_entry plug_hooks[NR_OF_HOOKS] = {
00064     { cfapi_system_add_string,       0, "cfapi_system_add_string" },
00065     { cfapi_system_register_global_event,   1, "cfapi_system_register_global_event" },
00066     { cfapi_system_remove_string,    2, "cfapi_system_remove_string" },
00067     { cfapi_system_unregister_global_event, 3, "cfapi_system_unregister_global_event" },
00068     { cfapi_system_check_path,       4, "cfapi_system_check_path" },
00069     { cfapi_system_re_cmp,           5, "cfapi_system_re_cmp" },
00070     { cfapi_system_strdup_local,     6, "cfapi_system_strdup_local" },
00071     { cfapi_system_directory,        7, "cfapi_system_directory" },
00072     { cfapi_system_find_animation,   8, "cfapi_system_find_animation" },
00073     { cfapi_object_clean_object,     9, "cfapi_object_clean_object" },
00074     { cfapi_object_on_same_map,      10, "cfapi_object_on_same_map" },
00075     { cfapi_object_get_key,          11, "cfapi_object_get_key" },
00076     { cfapi_object_set_key,          12, "cfapi_object_set_key" },
00077     { cfapi_object_get_property,     13, "cfapi_object_get_property" },
00078     { cfapi_object_set_property,     14, "cfapi_object_set_property" },
00079     { cfapi_object_apply,            15, "cfapi_object_apply" },
00080     { cfapi_object_identify,         16, "cfapi_object_identify" },
00081     { cfapi_object_describe,         17, "cfapi_object_describe" },
00082     { cfapi_object_drain,            18, "cfapi_object_drain" },
00083     { cfapi_object_fix,              19, "cfapi_object_fix" },
00084     { cfapi_object_give_skill,       20, "cfapi_object_give_skill" },
00085     { cfapi_object_transmute,        21, "cfapi_object_transmute" },
00086     { cfapi_object_remove,           22, "cfapi_object_remove" },
00087     { cfapi_object_delete,           23, "cfapi_object_delete" },
00088     { cfapi_object_clone,            24, "cfapi_object_clone" },
00089     { cfapi_object_find,             25, "cfapi_object_find" },
00090     { cfapi_object_create,           26, "cfapi_object_create" },
00091     { cfapi_object_insert,           27, "cfapi_object_insert" },
00092     { cfapi_object_split,            28, "cfapi_object_split" },
00093     { cfapi_object_merge,            29, "cfapi_object_merge" },
00094     { cfapi_object_distance,         30, "cfapi_object_distance" },
00095     { cfapi_object_update,           31, "cfapi_object_update" },
00096     { cfapi_object_clear,            32, "cfapi_object_clear" },
00097     { cfapi_object_reset,            33, "cfapi_object_reset" },
00098     { cfapi_object_check_inventory,  34, "cfapi_object_check_inventory" },
00099     { cfapi_object_spring_trap,      35, "cfapi_object_spring_trap" },
00100     { cfapi_object_check_trigger,    36, "cfapi_object_check_trigger" },
00101     { cfapi_object_query_cost,       37, "cfapi_object_query_cost" },
00102     { cfapi_object_query_money,      38, "cfapi_object_query_money" },
00103     { cfapi_object_cast,             39, "cfapi_object_cast" },
00104     { cfapi_object_learn_spell,      40, "cfapi_object_learn_spell" },
00105     { cfapi_object_forget_spell,     41, "cfapi_object_forget_spell" },
00106     { cfapi_object_check_spell,      42, "cfapi_object_check_spell" },
00107     { cfapi_object_pay_amount,       43, "cfapi_object_pay_amount" },
00108     { cfapi_object_pay_item,         44, "cfapi_object_pay_item" },
00109     { cfapi_object_transfer,         45, "cfapi_object_transfer" },
00110     { cfapi_object_drop,             46, "cfapi_object_drop" },
00111     { cfapi_object_change_abil,      47, "cfapi_object_change_abil" },
00112     { cfapi_object_find_archetype_inside, 48, "cfapi_object_find_archetype_inside" },
00113     { cfapi_object_say,              49, "cfapi_object_say" },
00114     { cfapi_map_get_map,             50, "cfapi_map_get_map" },
00115     { cfapi_map_has_been_loaded,     51, "cfapi_map_has_been_loaded" },
00116     { cfapi_map_create_path,         52, "cfapi_map_create_path" },
00117     { cfapi_map_get_map_property,    53, "cfapi_map_get_property" },
00118     { cfapi_map_set_map_property,    54, "cfapi_map_set_property" },
00119     { cfapi_map_out_of_map,          55, "cfapi_map_out_of_map" },
00120     { cfapi_map_update_position,     56, "cfapi_map_update_position" },
00121     { cfapi_map_delete_map,          57, "cfapi_map_delete_map" },
00122     { cfapi_map_message,             58, "cfapi_map_message" },
00123     { cfapi_map_get_object_at,       59, "cfapi_map_get_object_at" },
00124     { cfapi_map_change_light,        60, "cfapi_map_change_light" },
00125     { cfapi_map_present_arch_by_name, 61, "cfapi_map_present_arch_by_name" },
00126     { cfapi_player_find,             62, "cfapi_player_find" },
00127     { cfapi_player_message,          63, "cfapi_player_message" },
00128     { cfapi_object_change_exp,       64, "cfapi_object_change_exp" },
00129     { cfapi_object_teleport,         65, "cfapi_object_teleport" },
00130     { cfapi_object_pickup,           67, "cfapi_object_pickup" },
00131     { cfapi_object_move,             68, "cfapi_object_move" },
00132     { cfapi_object_apply_below,      69, "cfapi_object_apply_below" },
00133     { cfapi_generate_random_map,     70, "cfapi_generate_random_map" },
00134     { cfapi_archetype_get_property,  71, "cfapi_archetype_get_property" },
00135     { cfapi_party_get_property,      72, "cfapi_party_get_property" },
00136     { cfapi_region_get_property,     73, "cfapi_region_get_property" },
00137     { cfapi_player_can_pay,          74, "cfapi_player_can_pay" },
00138     { cfapi_log,                     75, "cfapi_log" },
00139     { cfapi_get_time,                76, "cfapi_system_get_time" },
00140     { cfapi_timer_create,            77, "cfapi_system_timer_create" },
00141     { cfapi_timer_destroy,           78, "cfapi_system_timer_destroy" },
00142     { cfapi_friendlylist_get_next,   79, "cfapi_friendlylist_get_next" },
00143     { cfapi_set_random_map_variable, 80, "cfapi_set_random_map_variable" },
00144     { cfapi_system_find_face,        81, "cfapi_system_find_face" },
00145     { cfapi_get_season_name,         82, "cfapi_system_get_season_name" },
00146     { cfapi_get_month_name,          83, "cfapi_system_get_month_name" },
00147     { cfapi_get_weekday_name,        84, "cfapi_system_get_weekday_name" },
00148     { cfapi_get_periodofday_name,    85, "cfapi_system_get_periodofday_name" },
00149     { cfapi_map_trigger_connected,   86, "cfapi_map_trigger_connected" },
00150     { cfapi_object_user_event,       87, "cfapi_object_user_event" },
00151     { cfapi_system_find_string,      88, "cfapi_system_find_string" }
00152 };
00153 
00154 int plugin_number = 0;
00155 
00156 crossfire_plugin *plugins_list = NULL;
00157 
00158 /*****************************************************************************/
00159 /* NEW PLUGIN STUFF STARTS HERE                                              */
00160 /*****************************************************************************/
00161 
00162 #ifdef WIN32
00163 static const char *plugins_dlerror(void) {
00164     static char buf[256];
00165     DWORD err;
00166     char *p;
00167 
00168     err = GetLastError();
00169     if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, sizeof(buf), NULL) == 0)
00170         snprintf(buf, sizeof(buf), "error %lu", err);
00171     p = strchr(buf, '\0');
00172     while (p > buf && (p[-1] == '\r' || p[-1] == '\n'))
00173         p--;
00174     *p = '\0';
00175     return buf;
00176 }
00177 #endif /* WIN32 */
00178 
00184 static void send_changed_object(object *op) {
00185     object *tmp;
00186     player *pl;
00187 
00188     if (op->env != NULL) {
00189         tmp = get_player_container(op->env);
00190         if (!tmp) {
00191             for (pl = first_player; pl; pl = pl->next)
00192                 if (pl->ob->container == op->env)
00193                     break;
00194             if (pl)
00195                 tmp = pl->ob;
00196             else
00197                 tmp = NULL;
00198         }
00199         if (tmp)
00200             /* We don't know what changed, so we send everything. */
00201             esrv_update_item(UPD_ALL, tmp, op);
00202     } else {
00203         for (tmp = op->above; tmp != NULL; tmp = tmp->above)
00204             if (tmp->type == PLAYER)
00205                 tmp->contr->socket.update_look = 1;
00206     }
00207 }
00208 
00209 int user_event(object *op, object *activator, object *third, const char *message, int fix) {
00210     return execute_event(op, EVENT_USER, activator, third, message, fix);
00211 }
00212 
00213 int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
00214     object *tmp, *next;
00215     crossfire_plugin *plugin;
00216     int rv = 0;
00217 
00218     for (tmp = op->inv; tmp != NULL; tmp = next) {
00219         next = tmp->below;
00220         if (tmp->type == EVENT_CONNECTOR && tmp->subtype == eventcode) {
00221 #ifdef PLUGIN_DEBUG
00222             LOG(llevDebug, "********** EVENT HANDLER **********\n");
00223             LOG(llevDebug, " - Who am I      :%s\n", op->name);
00224             if (activator != NULL)
00225                 LOG(llevDebug, " - Activator     :%s\n", activator->name);
00226             if (third != NULL)
00227                 LOG(llevDebug, " - Other object  :%s\n", third->name);
00228             LOG(llevDebug, " - Event code    :%d\n", tmp->subtype);
00229             if (tmp->title != NULL)
00230                 LOG(llevDebug, " - Event plugin  :%s\n", tmp->title);
00231             if (tmp->slaying != NULL)
00232                 LOG(llevDebug, " - Event hook    :%s\n", tmp->slaying);
00233             if (tmp->name != NULL)
00234                 LOG(llevDebug, " - Event options :%s\n", tmp->name);
00235 #endif
00236 
00237             if (tmp->title == NULL) {
00238                 object *env = object_get_env_recursive(tmp);
00239                 LOG(llevError, "Event object without title at %d/%d in map %s\n", env->x, env->y, env->map->name);
00240                 remove_ob(tmp);
00241                 free_object(tmp);
00242             } else if (tmp->slaying == NULL) {
00243                 object *env = object_get_env_recursive(tmp);
00244                 LOG(llevError, "Event object without slaying at %d/%d in map %s\n", env->x, env->y, env->map->name);
00245                 remove_ob(tmp);
00246                 free_object(tmp);
00247             } else {
00248                 plugin = plugins_find_plugin(tmp->title);
00249                 if (plugin == NULL) {
00250                     object *env = object_get_env_recursive(tmp);
00251                     LOG(llevError, "The requested plugin doesn't exit: %s at %d/%d in map %s\n", tmp->title, env->x, env->y, env->map->name);
00252                     remove_ob(tmp);
00253                     free_object(tmp);
00254                 } else {
00255                     int rvt = 0;
00256                     int *rv;
00257 
00258                     rv = plugin->eventfunc(&rvt, op, /*eventcode, */ activator, third, message, fix, /*tmp->slaying, tmp->name*/ tmp);
00259                     if (QUERY_FLAG(tmp, FLAG_UNIQUE)) {
00260 #ifdef PLUGIN_DEBUG
00261                         LOG(llevDebug, "Removing unique event %s\n", tmp->slaying);
00262 #endif
00263                         remove_ob(tmp);
00264                         free_object(tmp);
00265                     }
00266                     return *rv;
00267                 }
00268             }
00269         }
00270     }
00271     return rv;
00272 }
00273 
00274 int execute_global_event(int eventcode, ...) {
00275     va_list args;
00276     mapstruct *map;
00277     object *op;
00278     object *op2;
00279     player *pl;
00280     const char *buf;
00281     int i, rt;
00282     crossfire_plugin *cp;
00283 
00284     if (plugins_list == NULL)
00285         return -1;
00286 
00287     va_start(args, eventcode);
00288 
00289     switch (eventcode) {
00290     case EVENT_BORN:
00291         /*BORN: op*/
00292         op = va_arg(args, object *);
00293         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00294             if (cp->gevent[eventcode] != NULL)
00295                 cp->gevent[eventcode](&rt, eventcode, op);
00296         }
00297         break;
00298 
00299     case EVENT_CLOCK:
00300         /*CLOCK: -*/
00301         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00302             if (cp->gevent[eventcode] != NULL)
00303                 cp->gevent[eventcode](&rt, eventcode);
00304         }
00305         break;
00306 
00307     case EVENT_CRASH:
00308         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00309             if (cp->gevent[eventcode] != NULL)
00310                 cp->gevent[eventcode](&rt, eventcode);
00311         }
00312         break;
00313 
00314     case EVENT_PLAYER_DEATH:
00315         /*PLAYER_DEATH: op*/
00316         op = va_arg(args, object *);
00317         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00318             if (cp->gevent[eventcode] != NULL)
00319                 cp->gevent[eventcode](&rt, eventcode, op);
00320         }
00321         break;
00322 
00323     case EVENT_GKILL:
00324         /*GKILL: op, hitter*/
00325         op = va_arg(args, object *);
00326         op2 = va_arg(args, object *);
00327         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00328             if (cp->gevent[eventcode] != NULL)
00329                 cp->gevent[eventcode](&rt, eventcode, op, op2);
00330         }
00331         break;
00332 
00333     case EVENT_LOGIN:
00334         /*LOGIN: pl, pl->socket.host*/
00335         pl = va_arg(args, player *);
00336         buf = va_arg(args, char *);
00337         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00338             if (cp->gevent[eventcode] != NULL)
00339                 cp->gevent[eventcode](&rt, eventcode, pl, buf);
00340         }
00341         break;
00342 
00343     case EVENT_LOGOUT:
00344         /*LOGOUT: pl, pl->socket.host*/
00345         pl = va_arg(args, player *);
00346         buf = va_arg(args, char *);
00347         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00348             if (cp->gevent[eventcode] != NULL)
00349                 cp->gevent[eventcode](&rt, eventcode, pl, buf);
00350         }
00351         break;
00352 
00353     case EVENT_MAPENTER:
00354         /*MAPENTER: op, map*/
00355         op = va_arg(args, object *);
00356         map = va_arg(args, mapstruct *);
00357         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00358             if (cp->gevent[eventcode] != NULL)
00359                 cp->gevent[eventcode](&rt, eventcode, op, map);
00360         }
00361         break;
00362 
00363     case EVENT_MAPLEAVE:
00364         /*MAPLEAVE: op, map*/
00365         op = va_arg(args, object *);
00366         map = va_arg(args, mapstruct *);
00367         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00368             if (cp->gevent[eventcode] != NULL)
00369                 cp->gevent[eventcode](&rt, eventcode, op, map);
00370         }
00371         break;
00372 
00373     case EVENT_MAPRESET:
00374         /*MAPRESET: map*/
00375         map = va_arg(args, mapstruct *);
00376         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00377             if (cp->gevent[eventcode] != NULL)
00378                 cp->gevent[eventcode](&rt, eventcode, map);
00379         }
00380         break;
00381 
00382     case EVENT_REMOVE:
00383         /*REMOVE: op*/
00384         op = va_arg(args, object *);
00385         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00386             if (cp->gevent[eventcode] != NULL)
00387                 cp->gevent[eventcode](&rt, eventcode, op);
00388         }
00389         break;
00390 
00391     case EVENT_SHOUT:
00392         /*SHOUT: op, parms, priority*/
00393         op = va_arg(args, object *);
00394         buf = va_arg(args, char *);
00395         i = va_arg(args, int);
00396         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00397             if (cp->gevent[eventcode] != NULL)
00398                 cp->gevent[eventcode](&rt, eventcode, op, buf, i);
00399         }
00400         break;
00401 
00402     case EVENT_TELL:
00403         /* Tell: who, what, to who */
00404         op = va_arg(args, object *);
00405         buf = va_arg(args, const char *);
00406         op2 = va_arg(args, object *);
00407         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00408             if (cp->gevent[eventcode] != NULL)
00409                 cp->gevent[eventcode](&rt, eventcode, op, buf, op2);
00410         }
00411         break;
00412 
00413     case EVENT_MUZZLE:
00414         /*MUZZLE: op, parms*/
00415         op = va_arg(args, object *);
00416         buf = va_arg(args, char *);
00417         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00418             if (cp->gevent[eventcode] != NULL)
00419                 cp->gevent[eventcode](&rt, eventcode, op, buf);
00420         }
00421         break;
00422 
00423     case EVENT_KICK:
00424         /*KICK: op, parms*/
00425         op = va_arg(args, object *);
00426         buf = va_arg(args, char *);
00427         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00428             if (cp->gevent[eventcode] != NULL)
00429                 cp->gevent[eventcode](&rt, eventcode, op, buf);
00430         }
00431         break;
00432 
00433     case EVENT_MAPUNLOAD:
00434         /*MAPUNLOAD: map*/
00435         map = va_arg(args, mapstruct *);
00436         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00437             if (cp->gevent[eventcode] != NULL)
00438                 cp->gevent[eventcode](&rt, eventcode, map);
00439         }
00440         break;
00441 
00442     case EVENT_MAPLOAD:
00443         /*MAPLOAD: map*/
00444         map = va_arg(args, mapstruct *);
00445         for (cp = plugins_list; cp != NULL; cp = cp->next) {
00446             if (cp->gevent[eventcode] != NULL)
00447                 cp->gevent[eventcode](&rt, eventcode, map);
00448         }
00449         break;
00450     }
00451     va_end(args);
00452     return 0;
00453 }
00454 
00455 int plugins_init_plugin(const char *libfile) {
00456     LIBPTRTYPE ptr;
00457     f_plug_init initfunc;
00458     f_plug_api propfunc;
00459     f_plug_api eventfunc;
00460     f_plug_postinit postfunc;
00461     f_plug_postinit closefunc;
00462     int i;
00463     crossfire_plugin *cp;
00464     crossfire_plugin *ccp;
00465 
00466     /* Open the plugin lib and load the required functions */
00467     ptr = plugins_dlopen(libfile);
00468     if (ptr == NULL) {
00469         LOG(llevError, "Error trying to load %s: %s\n", libfile, plugins_dlerror());
00470         return -1;
00471     }
00472     initfunc = (f_plug_init)plugins_dlsym(ptr, "initPlugin");
00473     if (initfunc == NULL) {
00474         LOG(llevError, "Plugin error while requesting %s.initPlugin: %s\n", libfile, plugins_dlerror());
00475         plugins_dlclose(ptr);
00476         return -1;
00477     }
00478     propfunc = (f_plug_api)plugins_dlsym(ptr, "getPluginProperty");
00479     if (propfunc == NULL) {
00480         LOG(llevError, "Plugin error while requesting %s.getPluginProperty: %s\n", libfile, plugins_dlerror());
00481         plugins_dlclose(ptr);
00482         return -1;
00483     }
00484     eventfunc = (f_plug_api)plugins_dlsym(ptr, "eventListener");
00485     if (eventfunc == NULL) {
00486         LOG(llevError, "Plugin error while requesting %s.eventListener: %s\n", libfile, plugins_dlerror());
00487         plugins_dlclose(ptr);
00488         return -1;
00489     }
00490     postfunc = (f_plug_postinit)plugins_dlsym(ptr, "postInitPlugin");
00491     if (postfunc == NULL) {
00492         LOG(llevError, "Plugin error while requesting %s.postInitPlugin: %s\n", libfile, plugins_dlerror());
00493         plugins_dlclose(ptr);
00494         return -1;
00495     }
00496     closefunc = (f_plug_postinit)plugins_dlsym(ptr, "closePlugin");
00497     if (closefunc == NULL) {
00498         LOG(llevError, "Plugin error while requesting %s.closePlugin: %s\n", libfile, plugins_dlerror());
00499         plugins_dlclose(ptr);
00500         return -1;
00501     }
00502     i = initfunc("2.0", cfapi_get_hooks);
00503     cp = malloc(sizeof(crossfire_plugin));
00504     for (i = 0; i < NR_EVENTS; i++)
00505         cp->gevent[i] = NULL;
00506     cp->eventfunc = eventfunc;
00507     cp->propfunc = propfunc;
00508     cp->closefunc = closefunc;
00509     cp->libptr = ptr;
00510     propfunc(&i, "Identification", cp->id, sizeof(cp->id));
00511     propfunc(&i, "FullName", cp->fullname, sizeof(cp->fullname));
00512     cp->next = NULL;
00513     cp->prev = NULL;
00514     if (plugins_list == NULL) {
00515         plugins_list = cp;
00516     } else {
00517         for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
00518             ;
00519         ccp->next = cp;
00520         cp->prev = ccp;
00521     }
00522     postfunc();
00523     plugin_number++;
00524     return 0;
00525 }
00526 
00527 void *cfapi_get_hooks(int *type, ...) {
00528     va_list args;
00529     int request_type;
00530     char *buf;
00531     int fid;
00532     f_plug_api *rapi;
00533     int i;
00534 
00535     *type = CFAPI_NONE;
00536 
00537     va_start(args, type);
00538     request_type = va_arg(args, int);
00539     if (request_type == 0) { /* By nr */
00540         fid = va_arg(args, int);
00541         rapi = va_arg(args, f_plug_api *);
00542         if (fid < 0 || fid >= NR_OF_HOOKS) {
00543             *rapi = NULL;
00544             *type = CFAPI_NONE;
00545         } else {
00546             *rapi = plug_hooks[fid].func;
00547             *type = CFAPI_FUNC;
00548         }
00549     } else { /* by name */
00550         buf = va_arg(args, char *);
00551         rapi = va_arg(args, f_plug_api *);
00552         *rapi = NULL;
00553         *type = CFAPI_NONE;
00554         for (i = 0; i < NR_OF_HOOKS; i++) {
00555             if (!strcmp(buf, plug_hooks[i].fname)) {
00556                 *rapi = plug_hooks[i].func;
00557                 *type = CFAPI_FUNC;
00558                 break;
00559             }
00560         }
00561     }
00562     va_end(args);
00563     return NULL;
00564 }
00565 
00566 int plugins_remove_plugin(const char *id) {
00567     crossfire_plugin *cp;
00568 
00569     if (plugins_list == NULL)
00570         return -1;
00571 
00572     for (cp = plugins_list; cp != NULL; cp = cp->next) {
00573         if (!strcmp(id, cp->id)) {
00574             crossfire_plugin *n;
00575             crossfire_plugin *p;
00576 
00577             n = cp->next;
00578             p = cp->prev;
00579             if (cp->closefunc)
00580                 cp->closefunc();
00581             plugins_dlclose(cp->libptr);
00582             if (n != NULL) {
00583                 if (p != NULL) {
00584                     n->prev = p;
00585                     p->next = n;
00586                 } else {
00587                     n->prev = NULL;
00588                     plugins_list = n;
00589                 }
00590             } else {
00591                 if (p != NULL)
00592                     p->next = NULL;
00593                 else
00594                     plugins_list = NULL;
00595             }
00596             free(cp);
00597             plugin_number--;
00598             return 0;
00599         }
00600     }
00601     return -1;
00602 }
00603 
00604 crossfire_plugin *plugins_find_plugin(const char *id) {
00605     crossfire_plugin *cp;
00606 
00607     if (plugins_list == NULL)
00608         return NULL;
00609 
00610     for (cp = plugins_list; cp != NULL; cp = cp->next) {
00611         if (!strcmp(id, cp->id)) {
00612             return cp;
00613         }
00614     }
00615     return NULL;
00616 }
00617 
00618 /*****************************************************************************/
00619 /* Displays a list of loaded plugins (keystrings and description) in the     */
00620 /* game log window.                                                          */
00621 /*****************************************************************************/
00622 void plugins_display_list(object *op) {
00623     crossfire_plugin *cp;
00624 
00625     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00626                   "List of loaded plugins:\n-----------------------", NULL);
00627 
00628     if (plugins_list == NULL)
00629         return;
00630 
00631     for (cp = plugins_list; cp != NULL; cp = cp->next) {
00632         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00633                              "%s, %s",
00634                              "%s, %s",
00635                              cp->id, cp->fullname);
00636     }
00637 }
00638 
00639 /* SYSTEM-RELATED HOOKS */
00640 
00648 void *cfapi_system_find_animation(int *type, ...) {
00649     va_list args;
00650     const char *anim;
00651     int *num;
00652 
00653     va_start(args, type);
00654     anim = va_arg(args, const char *);
00655     num = va_arg(args, int *);
00656     va_end(args);
00657 
00658     *num = find_animation(anim);
00659     *type = CFAPI_INT;
00660     return NULL;
00661 }
00662 
00670 void *cfapi_system_find_face(int *type, ...) {
00671     va_list args;
00672     const char *face;
00673     int error;
00674     int *num;
00675 
00676     va_start(args, type);
00677     face = va_arg(args, const char *);
00678     error = va_arg(args, int);
00679     num = va_arg(args, int *);
00680     va_end(args);
00681 
00682     *num = find_face(face, error);
00683     *type = CFAPI_INT;
00684     return NULL;
00685 }
00686 
00694 void *cfapi_system_strdup_local(int *type, ...) {
00695     va_list args;
00696     const char *txt;
00697     char **ret;
00698 
00699     va_start(args, type);
00700     txt = va_arg(args, const char *);
00701     ret = va_arg(args, char **);
00702     va_end(args);
00703 
00704     *ret = strdup_local(txt);
00705     *type = CFAPI_STRING;
00706     return NULL;
00707 }
00708 
00709 void *cfapi_system_register_global_event(int *type, ...) {
00710     va_list args;
00711     int eventcode;
00712     char *pname;
00713     f_plug_api hook;
00714     crossfire_plugin *cp;
00715 
00716     va_start(args, type);
00717     eventcode = va_arg(args, int);
00718     pname     = va_arg(args, char *);
00719     hook      = va_arg(args, f_plug_api);
00720     va_end(args);
00721 
00722     *type = CFAPI_NONE;
00723 
00724     cp = plugins_find_plugin(pname);
00725     cp->gevent[eventcode] = hook;
00726     return NULL;
00727 }
00728 
00729 void *cfapi_system_unregister_global_event(int *type, ...) {
00730     va_list args;
00731     int eventcode;
00732     char *pname;
00733     crossfire_plugin *cp;
00734 
00735     va_start(args, type);
00736     eventcode = va_arg(args, int);
00737     pname = va_arg(args, char *);
00738     va_end(args);
00739 
00740     *type = CFAPI_NONE;
00741 
00742     cp = plugins_find_plugin(pname);
00743     cp->gevent[eventcode] = NULL;
00744 
00745     return NULL;
00746 }
00747 
00756 void *cfapi_system_add_string(int *type, ...) {
00757     va_list args;
00758     const char *str;
00759     sstring *rv;
00760 
00761     va_start(args, type);
00762     str = va_arg(args, const char *);
00763     rv = va_arg(args, sstring *);
00764     va_end(args);
00765 
00766     *rv = add_string(str);
00767     *type = CFAPI_SSTRING;
00768     return NULL;
00769 }
00770 
00779 void *cfapi_system_remove_string(int *type, ...) {
00780     va_list args;
00781     sstring str;
00782 
00783     va_start(args, type);
00784     str = va_arg(args, sstring);
00785     va_end(args);
00786 
00787     free_string(str);
00788     *type = CFAPI_NONE;
00789     return NULL;
00790 }
00791 
00800 void *cfapi_system_find_string(int *type, ...) {
00801     va_list args;
00802     const char *str;
00803     sstring *rv;
00804 
00805     va_start(args, type);
00806     str = va_arg(args, const char *);
00807     rv = va_arg(args, sstring *);
00808     va_end(args);
00809 
00810     *rv = find_string(str);
00811     *type = CFAPI_SSTRING;
00812     return NULL;
00813 }
00814 
00822 void *cfapi_system_check_path(int *type, ...) {
00823     va_list args;
00824     const char *name;
00825     int prepend_dir;
00826     int *ret;
00827 
00828     va_start(args, type);
00829 
00830     name = va_arg(args, char *);
00831     prepend_dir = va_arg(args, int);
00832     ret = va_arg(args, int *);
00833 
00834     *ret = check_path(name, prepend_dir);
00835 
00836     va_end(args);
00837     *type = CFAPI_INT;
00838     return NULL;
00839 }
00840 
00848 void *cfapi_system_re_cmp(int *type, ...) {
00849     va_list args;
00850     const char *str;
00851     const char *regexp;
00852     const char **rv;
00853 
00854     va_start(args, type);
00855 
00856     str = va_arg(args, char *);
00857     regexp = va_arg(args, char *);
00858     rv = va_arg(args, const char **);
00859 
00860     *rv = re_cmp(str, regexp);
00861 
00862     va_end(args);
00863     *type = CFAPI_STRING;
00864     return NULL;
00865 }
00866 
00867 void *cfapi_system_directory(int *type, ...) {
00868     va_list args;
00869     int dirtype;
00870     const char **str;
00871 
00872     va_start(args, type);
00873 
00874     dirtype = va_arg(args, int);
00875     str = va_arg(args, const char **);
00876     va_end(args);
00877 
00878     *type = CFAPI_STRING;
00879 
00880     switch (dirtype) {
00881     case 0:
00882         *str = settings.mapdir;
00883         break;
00884 
00885     case 1:
00886         *str = settings.uniquedir;
00887         break;
00888 
00889     case 2:
00890         *str = settings.tmpdir;
00891         break;
00892 
00893     case 3:
00894         *str = settings.confdir;
00895         break;
00896 
00897     case 4:
00898         *str = settings.localdir;
00899         break;
00900 
00901     case 5:
00902         *str = settings.playerdir;
00903         break;
00904 
00905     case 6:
00906         *str = settings.datadir;
00907         break;
00908 
00909     default:
00910         *str = NULL;
00911     }
00912 
00913     return NULL;
00914 }
00915 
00924 void *cfapi_get_time(int *type, ...) {
00925     va_list args;
00926     timeofday_t *tod;
00927 
00928     va_start(args, type);
00929     tod = va_arg(args, timeofday_t *);
00930     va_end(args);
00931 
00932     get_tod(tod);
00933     *type = CFAPI_NONE;
00934     return NULL;
00935 }
00936 
00937 #define string_get_int(name)            \
00938     va_list args;                       \
00939     int index;                          \
00940     const char **str;                   \
00941     va_start(args, type);               \
00942     index = va_arg(args, int);          \
00943     str = va_arg(args, const char **);  \
00944     va_end(args);                       \
00945     *str = name(index);                 \
00946     *type = CFAPI_STRING;               \
00947     return NULL;                        \
00948 
00949 
00957 void *cfapi_get_season_name(int *type, ...) {
00958     string_get_int(get_season_name)
00959 }
00960 
00969 void *cfapi_get_weekday_name(int *type, ...) {
00970     string_get_int(get_weekday)
00971 }
00972 
00981 void *cfapi_get_month_name(int *type, ...) {
00982     string_get_int(get_month_name)
00983 }
00984 
00993 void *cfapi_get_periodofday_name(int *type, ...) {
00994     string_get_int(get_periodofday)
00995 }
00996 
01010 void *cfapi_timer_create(int *type, ...) {
01011     va_list args;
01012     int res;
01013     object *ob;
01014     long delay;
01015     int mode;
01016     int *timer;
01017 
01018     va_start(args, type);
01019     ob = va_arg(args, object *);
01020     delay = va_arg(args, long);
01021     mode = va_arg(args, int);
01022     timer = va_arg(args, int *);
01023     va_end(args);
01024     *type = CFAPI_INT;
01025 
01026     *timer = cftimer_find_free_id();
01027     if (*timer != TIMER_ERR_ID) {
01028         res = cftimer_create(*timer, delay, ob, mode);
01029         if (res != TIMER_ERR_NONE)
01030             *timer = res;
01031     }
01032     return NULL;
01033 }
01034 
01046 void *cfapi_timer_destroy(int *type, ...) {
01047     va_list args;
01048     int id;
01049     int *err;
01050 
01051     va_start(args, type);
01052     id = va_arg(args, int);
01053     err = va_arg(args, int *);
01054     va_end(args);
01055     *type = CFAPI_INT;
01056 
01057     *err = cftimer_destroy(id);
01058 
01059     return NULL;
01060 }
01061 
01069 void *cfapi_log(int *type, ...) {
01070     va_list args;
01071     LogLevel logLevel;
01072     const char *message;
01073 
01074     va_start(args, type);
01075     logLevel = va_arg(args, LogLevel);
01076     message = va_arg(args, const char *);
01077     LOG(logLevel, "%s", message);
01078     va_end(args);
01079 
01080     *type = CFAPI_NONE;
01081 
01082     return NULL;
01083 }
01084 
01085 /* MAP RELATED HOOKS */
01086 
01095 void *cfapi_map_get_map(int *type, ...) {
01096     va_list args;
01097     mapstruct **ret;
01098     int ctype;
01099     int x, y;
01100     sint16 nx, ny;
01101     const char *name;
01102     mapstruct *m;
01103 
01104     va_start(args, type);
01105 
01106     ctype = va_arg(args, int);
01107 
01108     switch (ctype) {
01109     case 0:
01110         x = va_arg(args, int);
01111         y = va_arg(args, int);
01112         ret = va_arg(args, mapstruct **);
01113         *ret = get_empty_map(x, y);
01114         break;
01115 
01116     case 1:
01117         name = va_arg(args, const char *);
01118         x = va_arg(args, int);
01119         ret = va_arg(args, mapstruct **);
01120         *ret = ready_map_name(name, x);
01121         break;
01122 
01123     case 2:
01124         m = va_arg(args, mapstruct *);
01125         nx = va_arg(args, int);
01126         ny = va_arg(args, int);
01127         ret = va_arg(args, mapstruct **);
01128         *ret = get_map_from_coord(m, &nx, &ny);
01129         break;
01130 
01131     default:
01132         *type = CFAPI_NONE;
01133         va_end(args);
01134         return NULL;
01135         break;
01136     }
01137     va_end(args);
01138     *type = CFAPI_PMAP;
01139     return NULL;
01140 }
01141 
01149 void *cfapi_map_has_been_loaded(int *type, ...) {
01150     va_list args;
01151     mapstruct **map;
01152     char *string;
01153 
01154     va_start(args, type);
01155     string = va_arg(args, char *);
01156     map = va_arg(args, mapstruct **);
01157     *map = has_been_loaded(string);
01158     va_end(args);
01159     *type = CFAPI_PMAP;
01160     return NULL;
01161 }
01162 
01170 void *cfapi_map_create_path(int *type, ...) {
01171     va_list args;
01172     int ctype, size;
01173     const char *str;
01174     char *name;
01175 
01176     va_start(args, type);
01177 
01178     ctype = va_arg(args, int);
01179     str = va_arg(args, const char *);
01180     name = va_arg(args, char *);
01181     size = va_arg(args, int);
01182     *type = CFAPI_STRING;
01183 
01184     switch (ctype) {
01185     case 0:
01186         create_pathname(str, name, size);
01187         break;
01188 
01189     case 1:
01190         create_overlay_pathname(str, name, MAX_BUF);
01191         break;
01192 
01193 /*  case 2:
01194         rv = create_items_path(str);
01195         break;*/
01196 
01197     default:
01198         *type = CFAPI_NONE;
01199         break;
01200     }
01201     va_end(args);
01202     return NULL;
01203 }
01204 
01205 void *cfapi_map_get_map_property(int *type, ...) {
01206     va_list args;
01207     mapstruct *map;
01208     int property;
01209 
01210     int *rint;
01211     mapstruct **rmap;
01212     sstring *rstr;
01213     region **rreg;
01214     sint16 *nx, *ny;
01215     int x, y;
01216 
01217     va_start(args, type);
01218 
01219     map = va_arg(args, mapstruct *);
01220     property = va_arg(args, int);
01221 
01222     switch (property) {
01223     case CFAPI_MAP_PROP_FLAGS:
01224         rmap = va_arg(args, mapstruct **);
01225         x = va_arg(args, int);
01226         y = va_arg(args, int);
01227         nx = va_arg(args, sint16 *);
01228         ny = va_arg(args, sint16 *);
01229         rint = va_arg(args, int *);
01230         *rint = get_map_flags(map, rmap, x, y, nx, ny);
01231         *type = CFAPI_INT;
01232         break;
01233 
01234     case CFAPI_MAP_PROP_DIFFICULTY:
01235         rint = va_arg(args, int *);
01236         *rint = calculate_difficulty(map);
01237         *type = CFAPI_INT;
01238         break;
01239 
01240     case CFAPI_MAP_PROP_PATH:
01241         rstr = va_arg(args, sstring *);
01242         *rstr = map->path;
01243         *type = CFAPI_SSTRING;
01244         break;
01245 
01246     case CFAPI_MAP_PROP_TMPNAME:
01247         rstr = va_arg(args, sstring *);
01248         *rstr = map->tmpname;
01249         *type = CFAPI_SSTRING;
01250         break;
01251 
01252     case CFAPI_MAP_PROP_NAME:
01253         rstr = va_arg(args, sstring *);
01254         *rstr = map->name;
01255         *type = CFAPI_SSTRING;
01256         break;
01257 
01258     case CFAPI_MAP_PROP_RESET_TIME:
01259         rint = va_arg(args, int *);
01260         *rint = map->reset_time;
01261         *type = CFAPI_INT;
01262         break;
01263 
01264     case CFAPI_MAP_PROP_RESET_TIMEOUT:
01265         rint = va_arg(args, int *);
01266         *rint = map->reset_timeout;
01267         *type = CFAPI_INT;
01268         break;
01269 
01270     case CFAPI_MAP_PROP_PLAYERS:
01271         rint = va_arg(args, int *);
01272         *rint = map->players;
01273         *type = CFAPI_INT;
01274         break;
01275 
01276     case CFAPI_MAP_PROP_DARKNESS:
01277         rint = va_arg(args, int *);
01278         *rint = map->darkness;
01279         *type = CFAPI_INT;
01280         break;
01281 
01282     case CFAPI_MAP_PROP_WIDTH:
01283         rint = va_arg(args, int *);
01284         *rint = map->width;
01285         *type = CFAPI_INT;
01286         break;
01287 
01288     case CFAPI_MAP_PROP_HEIGHT:
01289         rint = va_arg(args, int *);
01290         *rint = map->height;
01291         *type = CFAPI_INT;
01292         break;
01293 
01294     case CFAPI_MAP_PROP_ENTER_X:
01295         rint = va_arg(args, int *);
01296         *rint = map->enter_x;
01297         *type = CFAPI_INT;
01298         break;
01299 
01300     case CFAPI_MAP_PROP_ENTER_Y:
01301         rint = va_arg(args, int *);
01302         *rint = map->enter_y;
01303         *type = CFAPI_INT;
01304         break;
01305 
01306     case CFAPI_MAP_PROP_MESSAGE:
01307         rstr = va_arg(args, sstring *);
01308         *rstr = map->msg;
01309         *type = CFAPI_SSTRING;
01310         break;
01311 
01312     case CFAPI_MAP_PROP_NEXT:
01313         rmap = va_arg(args, mapstruct **);
01314         *rmap = map ? map->next : first_map;
01315         *type = CFAPI_PMAP;
01316         break;
01317 
01318     case CFAPI_MAP_PROP_REGION:
01319         rreg = va_arg(args, region **);
01320         *rreg = get_region_by_map(map);
01321         *type = CFAPI_PREGION;
01322         break;
01323 
01324     case CFAPI_MAP_PROP_UNIQUE:
01325         rint = va_arg(args, int *);
01326         *rint = map->unique;
01327         *type = CFAPI_INT;
01328         break;
01329 
01330     default:
01331         *type = CFAPI_NONE;
01332         break;
01333     }
01334     va_end(args);
01335     return NULL;
01336 }
01337 
01338 void *cfapi_map_set_map_property(int *type, ...) {
01339     va_list args;
01340     mapstruct *map;
01341     int property;
01342     const char *buf;
01343 
01344     va_start(args, type);
01345 
01346     map = va_arg(args, mapstruct *);
01347     property = va_arg(args, int);
01348 
01349     switch (property) {
01350     case CFAPI_MAP_PROP_PATH:
01351         buf = va_arg(args, const char *);
01352         snprintf(map->path, sizeof(map->path), "%s", buf);
01353         *type = CFAPI_STRING;
01354         break;
01355 
01356     default:
01357         *type = CFAPI_NONE;
01358         break;
01359     }
01360     va_end(args);
01361     return NULL;
01362 }
01363 
01371 void *cfapi_map_out_of_map(int *type, ...) {
01372     va_list args;
01373     mapstruct *map;
01374     int x, y;
01375     int *rint;
01376 
01377     va_start(args, type);
01378     map = va_arg(args, mapstruct *);
01379     x = va_arg(args, int);
01380     y = va_arg(args, int);
01381     rint = va_arg(args, int *);
01382 
01383     *rint = out_of_map(map, x, y);
01384     va_end(args);
01385     *type = CFAPI_INT;
01386     return NULL;
01387 }
01388 
01396 void *cfapi_map_update_position(int *type, ...) {
01397     va_list args;
01398     mapstruct *map;
01399     int x, y;
01400 
01401     va_start(args, type);
01402 
01403     map = va_arg(args, mapstruct *);
01404     x = va_arg(args, int);
01405     y = va_arg(args, int);
01406 
01407     update_position(map, x, y);
01408     va_end(args);
01409     *type = CFAPI_NONE;
01410     return NULL;
01411 }
01412 
01413 void *cfapi_map_delete_map(int *type, ...) {
01414     va_list args;
01415     mapstruct *map;
01416     va_start(args, type);
01417 
01418     map = va_arg(args, mapstruct *);
01419 
01420     delete_map(map);
01421 
01422     va_end(args);
01423     *type = CFAPI_NONE;
01424     return NULL;
01425 }
01426 void *cfapi_map_message(int *type, ...) {
01427     va_list args;
01428     mapstruct *map;
01429     const char *string;
01430     int color;
01431 
01432     va_start(args, type);
01433     map = va_arg(args, mapstruct *);
01434     string = va_arg(args, const char *);
01435     color = va_arg(args, int);
01436     va_end(args);
01437 
01438     /* function should be extended to take message types probably */
01439     ext_info_map(color, map, MSG_TYPE_MISC, MSG_SUBTYPE_NONE, string, string);
01440     *type = CFAPI_NONE;
01441     return NULL;
01442 }
01443 
01451 void *cfapi_map_get_object_at(int *type, ...) {
01452     va_list args;
01453     mapstruct *map;
01454     int x, y;
01455     sint16 sx, sy;
01456     object **robj;
01457 
01458     va_start(args, type);
01459     map = va_arg(args, mapstruct *);
01460     x = va_arg(args, int);
01461     y = va_arg(args, int);
01462     robj = va_arg(args, object **);
01463     va_end(args);
01464 
01465     sx = x;
01466     sy = y;
01467     if (get_map_flags(map, &map, x, y, &sx, &sy)&P_OUT_OF_MAP)
01468         *robj = NULL;
01469     else
01470         *robj = GET_MAP_OB(map, sx, sy);
01471     *type = CFAPI_POBJECT;
01472     return NULL;
01473 }
01474 
01483 void *cfapi_map_present_arch_by_name(int *type, ...) {
01484     va_list args;
01485     int x, y;
01486     mapstruct *map;
01487     char *msg;
01488     object **robj;
01489 
01490     va_start(args, type);
01491 
01492     msg = va_arg(args, char *);
01493     map = va_arg(args, mapstruct *);
01494     x = va_arg(args, int);
01495     y = va_arg(args, int);
01496     robj = va_arg(args, object **);
01497 
01498     va_end(args);
01499 
01500     *robj = present_arch(try_find_archetype(msg), map, x, y);
01501     *type = CFAPI_POBJECT;
01502     return NULL;
01503 }
01504 
01512 void *cfapi_map_change_light(int *type, ...) {
01513     va_list args;
01514     int change;
01515     mapstruct *map;
01516     int *rint;
01517 
01518     va_start(args, type);
01519     map = va_arg(args, mapstruct *);
01520     change = va_arg(args, int);
01521     rint = va_arg(args, int *);
01522     va_end(args);
01523 
01524     *type = CFAPI_INT;
01525     *rint = change_map_light(map, change);
01526 
01527     return NULL;
01528 }
01529 
01530 /* OBJECT-RELATED HOOKS */
01531 
01546 void *cfapi_object_move(int *type, ...) {
01547     va_list args;
01548     int kind;
01549     object *op;
01550     object *activator;
01551     player *pl;
01552     int direction;
01553     int *ret;
01554 
01555     va_start(args, type);
01556     kind = va_arg(args, int);
01557     switch (kind) {
01558     case 0:
01559         op = va_arg(args, object *);
01560         direction = va_arg(args, int);
01561         activator = va_arg(args, object *);
01562         ret = va_arg(args, int *);
01563         va_end(args);
01564         *ret = move_ob(op, direction, activator);
01565         break;
01566 
01567     case 1:
01568         pl = va_arg(args, player *);
01569         direction = va_arg(args, int);
01570         ret = va_arg(args, int *);
01571         va_end(args);
01572         *ret = move_player(pl->ob, direction);
01573         break;
01574     }
01575     *type = CFAPI_INT;
01576     return NULL;
01577 }
01578 
01588 void *cfapi_object_get_key(int *type, ...) {
01589     va_list args;
01590     const char *keyname;
01591     const char **value;
01592     object *op;
01593 
01594     va_start(args, type);
01595     op = va_arg(args, object *);
01596     keyname = va_arg(args, const char *);
01597     value = va_arg(args, const char **);
01598     va_end(args);
01599 
01600     *value = get_ob_key_value(op, keyname);
01601     *type = CFAPI_SSTRING;
01602     return NULL;
01603 }
01604 
01613 void *cfapi_object_set_key(int *type, ...) {
01614     va_list args;
01615     const char *keyname;
01616     const char *value;
01617     int *ret;
01618     object *op;
01619     int add_key;
01620 
01621     va_start(args, type);
01622     op = va_arg(args, object *);
01623     keyname = va_arg(args, char *);
01624     value = va_arg(args, char *);
01625     add_key = va_arg(args, int);
01626     ret = va_arg(args, int *);
01627     va_end(args);
01628 
01629     *ret = set_ob_key_value(op, keyname, value, add_key);
01630     *type = CFAPI_INT;
01631     return NULL;
01632 }
01633 
01637 void *cfapi_object_get_property(int *type, ...) {
01638     va_list args;
01639     int property;
01640     object *op;
01641     int *rint;
01642     object **robject;
01643     mapstruct **rmap;
01644     float *rfloat;
01645     archetype **rarch;
01646     sstring *rsstring;
01647     char *rbuffer;
01648     int rbufsize;
01649     MoveType *rmove;
01650     sint64 *rint64;
01651     partylist **rparty;
01652     double *rdouble;
01653     long *rlong;
01654 
01655     va_start(args, type);
01656 
01657     op = va_arg(args, object *);
01658     property = va_arg(args, int);
01659     switch (property) {
01660     case CFAPI_OBJECT_PROP_OB_ABOVE:
01661         robject = va_arg(args, object **);
01662         *robject = op->above;
01663         *type = CFAPI_POBJECT;
01664         break;
01665 
01666     case CFAPI_OBJECT_PROP_OB_BELOW:
01667         robject = va_arg(args, object **);
01668         *robject = op->below;
01669         *type = CFAPI_POBJECT;
01670         break;
01671 
01672     case CFAPI_OBJECT_PROP_NEXT_ACTIVE_OB:
01673         robject = va_arg(args, object **);
01674         *robject = op->active_next;
01675         *type = CFAPI_POBJECT;
01676         break;
01677 
01678     case CFAPI_OBJECT_PROP_PREV_ACTIVE_OB:
01679         robject = va_arg(args, object **);
01680         *robject = op->active_prev;
01681         *type = CFAPI_POBJECT;
01682         break;
01683 
01684     case CFAPI_OBJECT_PROP_INVENTORY:
01685         robject = va_arg(args, object **);
01686         *robject = op->inv;
01687         *type = CFAPI_POBJECT;
01688         break;
01689 
01690     case CFAPI_OBJECT_PROP_ENVIRONMENT:
01691         robject = va_arg(args, object **);
01692         *robject = op->env;
01693         *type = CFAPI_POBJECT;
01694         break;
01695 
01696     case CFAPI_OBJECT_PROP_HEAD:
01697         robject = va_arg(args, object **);
01698         *robject = op->head;
01699         *type = CFAPI_POBJECT;
01700         break;
01701 
01702     case CFAPI_OBJECT_PROP_CONTAINER:
01703         robject = va_arg(args, object **);
01704         *robject = op->container;
01705         *type = CFAPI_POBJECT;
01706         break;
01707 
01708     case CFAPI_OBJECT_PROP_MAP:
01709         rmap = va_arg(args, mapstruct **);
01710         *rmap = op->map;
01711         *type = CFAPI_PMAP;
01712         break;
01713 
01714     case CFAPI_OBJECT_PROP_COUNT:
01715         rint = va_arg(args, int *);
01716         *rint = op->count;
01717         *type = CFAPI_INT;
01718         break;
01719 
01720     case CFAPI_OBJECT_PROP_NAME:
01721         rbuffer = va_arg(args, char *);
01722         rbufsize = va_arg(args, int);
01723         query_name(op, rbuffer, rbufsize);
01724         *type = CFAPI_STRING;
01725         break;
01726 
01727     case CFAPI_OBJECT_PROP_NAME_PLURAL:
01728         rsstring = va_arg(args, sstring *);
01729         *rsstring = op->name_pl;
01730         *type = CFAPI_SSTRING;
01731         break;
01732 
01733     case CFAPI_OBJECT_PROP_TITLE:
01734         rsstring = va_arg(args, sstring *);
01735         *rsstring = op->title;
01736         *type = CFAPI_SSTRING;
01737         break;
01738 
01739     case CFAPI_OBJECT_PROP_RACE:
01740         rsstring = va_arg(args, sstring *);
01741         *rsstring = op->race;
01742         *type = CFAPI_SSTRING;
01743         break;
01744 
01745     case CFAPI_OBJECT_PROP_SLAYING:
01746         rsstring = va_arg(args, sstring *);
01747         *rsstring = op->slaying;
01748         *type = CFAPI_SSTRING;
01749         break;
01750 
01751     case CFAPI_OBJECT_PROP_SKILL:
01752         rsstring = va_arg(args, sstring *);
01753         *rsstring = op->skill;
01754         *type = CFAPI_SSTRING;
01755         break;
01756 
01757     case CFAPI_OBJECT_PROP_MESSAGE:
01758         rsstring = va_arg(args, sstring *);
01759         *rsstring = op->msg;
01760         *type = CFAPI_SSTRING;
01761         break;
01762 
01763     case CFAPI_OBJECT_PROP_LORE:
01764         rsstring = va_arg(args, sstring *);
01765         *rsstring = op->lore;
01766         *type = CFAPI_SSTRING;
01767         break;
01768 
01769     case CFAPI_OBJECT_PROP_X:
01770         rint = va_arg(args, int *);
01771         *rint = op->x;
01772         *type = CFAPI_INT;
01773         break;
01774 
01775     case CFAPI_OBJECT_PROP_Y:
01776         rint = va_arg(args, int *);
01777         *rint = op->y;
01778         *type = CFAPI_INT;
01779         break;
01780 
01781     case CFAPI_OBJECT_PROP_SPEED:
01782         rfloat = va_arg(args, float *);
01783         *rfloat = op->speed;
01784         *type = CFAPI_FLOAT;
01785         break;
01786 
01787     case CFAPI_OBJECT_PROP_SPEED_LEFT:
01788         rfloat = va_arg(args, float *);
01789         *rfloat = op->speed_left;
01790         *type = CFAPI_FLOAT;
01791         break;
01792 
01793     case CFAPI_OBJECT_PROP_NROF:
01794         rint = va_arg(args, int *);
01795         *rint = op->nrof;
01796         *type = CFAPI_INT;
01797         break;
01798 
01799     case CFAPI_OBJECT_PROP_DIRECTION:
01800         rint = va_arg(args, int *);
01801         *rint = op->direction;
01802         *type = CFAPI_INT;
01803         break;
01804 
01805     case CFAPI_OBJECT_PROP_FACING:
01806         rint = va_arg(args, int *);
01807         *rint = op->facing;
01808         *type = CFAPI_INT;
01809         break;
01810 
01811     case CFAPI_OBJECT_PROP_TYPE:
01812         rint = va_arg(args, int *);
01813         *rint = op->type;
01814         *type = CFAPI_INT;
01815         break;
01816 
01817     case CFAPI_OBJECT_PROP_SUBTYPE:
01818         rint = va_arg(args, int *);
01819         *rint = op->subtype;
01820         *type = CFAPI_INT;
01821         break;
01822 
01823     case CFAPI_OBJECT_PROP_CLIENT_TYPE:
01824         rint = va_arg(args, int *);
01825         *rint = op->client_type;
01826         *type = CFAPI_INT;
01827         break;
01828 
01829     case CFAPI_OBJECT_PROP_RESIST: {
01830             int idx;
01831             sint16 *resist;
01832 
01833             idx = va_arg(args, int);
01834             resist = va_arg(args, sint16 *);
01835             *resist = op->resist[idx];
01836         }
01837         *type = CFAPI_INT16;
01838         break;
01839 
01840     case CFAPI_OBJECT_PROP_ATTACK_TYPE:
01841         rint = va_arg(args, int *);
01842         *rint = op->attacktype;
01843         *type = CFAPI_INT;
01844         break;
01845 
01846     case CFAPI_OBJECT_PROP_PATH_ATTUNED:
01847         rint = va_arg(args, int *);
01848         *rint = op->path_attuned;
01849         *type = CFAPI_INT;
01850         break;
01851 
01852     case CFAPI_OBJECT_PROP_PATH_REPELLED:
01853         rint = va_arg(args, int *);
01854         *rint = op->path_repelled;
01855         *type = CFAPI_INT;
01856         break;
01857 
01858     case CFAPI_OBJECT_PROP_PATH_DENIED:
01859         rint = va_arg(args, int *);
01860         *rint = op->path_denied;
01861         *type = CFAPI_INT;
01862         break;
01863 
01864     case CFAPI_OBJECT_PROP_MATERIAL:
01865         rint = va_arg(args, int *);
01866         *rint = op->material;
01867         *type = CFAPI_INT;
01868         break;
01869 
01870     case CFAPI_OBJECT_PROP_MATERIAL_NAME:
01871         rsstring = va_arg(args, sstring *);
01872         *rsstring = op->materialname;
01873         *type = CFAPI_SSTRING;
01874         break;
01875 
01876     case CFAPI_OBJECT_PROP_MAGIC:
01877         rint = va_arg(args, int *);
01878         *rint = op->magic;
01879         *type = CFAPI_INT;
01880         break;
01881 
01882     case CFAPI_OBJECT_PROP_VALUE:
01883         rlong = va_arg(args, long *);
01884         *rlong = op->value;
01885         *type = CFAPI_LONG;
01886         break;
01887 
01888     case CFAPI_OBJECT_PROP_LEVEL:
01889         rint = va_arg(args, int *);
01890         *rint = op->level;
01891         *type = CFAPI_INT;
01892         break;
01893 
01894     case CFAPI_OBJECT_PROP_LAST_HEAL:
01895         rint = va_arg(args, int *);
01896         *rint = op->last_heal;
01897         *type = CFAPI_INT;
01898         break;
01899 
01900     case CFAPI_OBJECT_PROP_LAST_SP:
01901         rint = va_arg(args, int *);
01902         *rint = op->last_sp;
01903         *type = CFAPI_INT;
01904         break;
01905 
01906     case CFAPI_OBJECT_PROP_LAST_GRACE:
01907         rint = va_arg(args, int *);
01908         *rint = op->last_grace;
01909         *type = CFAPI_INT;
01910         break;
01911 
01912     case CFAPI_OBJECT_PROP_LAST_EAT:
01913         rint = va_arg(args, int *);
01914         *rint = op->last_eat;
01915         *type = CFAPI_INT;
01916         break;
01917 
01918     case CFAPI_OBJECT_PROP_INVISIBLE_TIME:
01919         rint = va_arg(args, int *);
01920         *rint = op->invisible;
01921         *type = CFAPI_INT;
01922         break;
01923 
01924     case CFAPI_OBJECT_PROP_PICK_UP:
01925         rint = va_arg(args, int *);
01926         *rint = op->pick_up;
01927         *type = CFAPI_INT;
01928         break;
01929 
01930     case CFAPI_OBJECT_PROP_ITEM_POWER:
01931         rint = va_arg(args, int *);
01932         *rint = op->item_power;
01933         *type = CFAPI_INT;
01934         break;
01935 
01936     case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR:
01937         rint = va_arg(args, int *);
01938         *rint = op->gen_sp_armour;
01939         *type = CFAPI_INT;
01940         break;
01941 
01942     case CFAPI_OBJECT_PROP_WEIGHT:
01943         rint = va_arg(args, int *);
01944         *rint = op->weight;
01945         *type = CFAPI_INT;
01946         break;
01947 
01948     case CFAPI_OBJECT_PROP_WEIGHT_LIMIT:
01949         rint = va_arg(args, int *);
01950         *rint = op->weight_limit;
01951         *type = CFAPI_INT;
01952         break;
01953 
01954     case CFAPI_OBJECT_PROP_CARRYING:
01955         rint = va_arg(args, int *);
01956         *rint = op->carrying;
01957         *type = CFAPI_INT;
01958         break;
01959 
01960     case CFAPI_OBJECT_PROP_GLOW_RADIUS:
01961         rint = va_arg(args, int *);
01962         *rint = op->glow_radius;
01963         *type = CFAPI_INT;
01964         break;
01965 
01966     case CFAPI_OBJECT_PROP_PERM_EXP:
01967         rint64 = va_arg(args, sint64 *);
01968         *rint64 = op->perm_exp;
01969         *type = CFAPI_SINT64;
01970         break;
01971 
01972     case CFAPI_OBJECT_PROP_CURRENT_WEAPON:
01973         robject = va_arg(args, object **);
01974         *robject = op->current_weapon;
01975         *type = CFAPI_POBJECT;
01976         break;
01977 
01978     case CFAPI_OBJECT_PROP_ENEMY:
01979         robject = va_arg(args, object **);
01980         *robject = op->enemy;
01981         *type = CFAPI_POBJECT;
01982         break;
01983 
01984     case CFAPI_OBJECT_PROP_ATTACKED_BY:
01985         robject = va_arg(args, object **);
01986         *robject = op->attacked_by;
01987         *type = CFAPI_POBJECT;
01988         break;
01989 
01990     case CFAPI_OBJECT_PROP_RUN_AWAY:
01991         rint = va_arg(args, int *);
01992         *rint = op->run_away;
01993         *type = CFAPI_INT;
01994         break;
01995 
01996     case CFAPI_OBJECT_PROP_CHOSEN_SKILL:
01997         robject = va_arg(args, object **);
01998         *robject = op->chosen_skill;
01999         *type = CFAPI_POBJECT;
02000         break;
02001 
02002     case CFAPI_OBJECT_PROP_HIDDEN:
02003         rint = va_arg(args, int *);
02004         *rint = op->hide;
02005         *type = CFAPI_INT;
02006         break;
02007 
02008     case CFAPI_OBJECT_PROP_MOVE_STATUS:
02009         rint = va_arg(args, int *);
02010         *rint = op->move_status;
02011         *type = CFAPI_INT;
02012         break;
02013 
02014     case CFAPI_OBJECT_PROP_ATTACK_MOVEMENT:
02015         rint = va_arg(args, int *);
02016         *rint = op->attack_movement;
02017         *type = CFAPI_INT;
02018         break;
02019 
02020     case CFAPI_OBJECT_PROP_SPELL_ITEM:
02021         robject = va_arg(args, object **);
02022         *robject = op->spellitem;
02023         *type = CFAPI_POBJECT;
02024         break;
02025 
02026     case CFAPI_OBJECT_PROP_EXP_MULTIPLIER:
02027         rdouble = va_arg(args, double *);
02028         *rdouble = op->expmul;
02029         *type = CFAPI_DOUBLE;
02030         break;
02031 
02032     case CFAPI_OBJECT_PROP_ARCHETYPE:
02033         rarch = va_arg(args, archetype **);
02034         *rarch = op->arch;
02035         *type = CFAPI_PARCH;
02036         break;
02037 
02038     case CFAPI_OBJECT_PROP_OTHER_ARCH:
02039         rarch = va_arg(args, archetype **);
02040         *rarch = op->other_arch;
02041         *type = CFAPI_PARCH;
02042         break;
02043 
02044     case CFAPI_OBJECT_PROP_CUSTOM_NAME:
02045         rsstring = va_arg(args, sstring *);
02046         *rsstring = (char *)op->custom_name;
02047         *type = CFAPI_SSTRING;
02048         break;
02049 
02050     case CFAPI_OBJECT_PROP_ANIM_SPEED:
02051         rint = va_arg(args, int *);
02052         *rint = op->anim_speed;
02053         *type = CFAPI_INT;
02054         break;
02055 
02056     case CFAPI_OBJECT_PROP_FRIENDLY:
02057         rint = va_arg(args, int *);
02058         *rint = is_friendly(op);
02059         *type = CFAPI_INT;
02060         break;
02061 
02062     case CFAPI_OBJECT_PROP_SHORT_NAME:
02063         rbuffer = va_arg(args, char *);
02064         rbufsize = va_arg(args, int);
02065         query_short_name(op, rbuffer, rbufsize);
02066         *type = CFAPI_STRING;
02067         break;
02068 
02069     case CFAPI_OBJECT_PROP_BASE_NAME: {
02070             int i;
02071 
02072             i = va_arg(args, int);
02073             rbuffer = va_arg(args, char *);
02074             rbufsize = va_arg(args, int);
02075             query_base_name(op, i, rbuffer, rbufsize);
02076             *type = CFAPI_STRING;
02077         }
02078         break;
02079 
02080     case CFAPI_OBJECT_PROP_MAGICAL:
02081         rint = va_arg(args, int *);
02082         *rint = is_magical(op);
02083         *type = CFAPI_INT;
02084         break;
02085 
02086     case CFAPI_OBJECT_PROP_LUCK:
02087         rint = va_arg(args, int *);
02088         *rint = op->stats.luck;
02089         *type = CFAPI_INT;
02090         break;
02091 
02092     case CFAPI_OBJECT_PROP_EXP:
02093         rint64 = va_arg(args, sint64 *);
02094         *rint64 = op->stats.exp;
02095         *type = CFAPI_SINT64;
02096         break;
02097 
02098     case CFAPI_OBJECT_PROP_OWNER:
02099         robject = va_arg(args, object **);
02100         *robject = get_owner(op);
02101         *type = CFAPI_POBJECT;
02102         break;
02103 
02104     case CFAPI_OBJECT_PROP_PRESENT: {
02105             int stype;
02106 
02107             stype = va_arg(args, int);
02108             switch (stype) {
02109                 unsigned char ptype;
02110                 char *buf;
02111                 archetype *at;
02112 
02113             case 0: /* present_in_ob */
02114                 ptype = (unsigned char)(va_arg(args, int));
02115                 robject = va_arg(args, object **);
02116                 *robject = present_in_ob(ptype, op);
02117                 break;
02118 
02119             case 1: /* present_in_ob_by_name */
02120                 ptype = (unsigned char)(va_arg(args, int));
02121                 buf = va_arg(args, char *);
02122                 robject = va_arg(args, object **);
02123                 *robject = present_in_ob_by_name(ptype, buf, op);
02124                 break;
02125 
02126             case 2: /* present_arch_in_ob */
02127                 at = va_arg(args, archetype *);
02128                 robject = va_arg(args, object **);
02129                 *robject = present_arch_in_ob(at, op);
02130                 break;
02131             }
02132         }
02133         *type = CFAPI_POBJECT;
02134         break;
02135 
02136     case CFAPI_OBJECT_PROP_CHEATER:
02137         rint = va_arg(args, int *);
02138         *rint = (QUERY_FLAG(op, FLAG_WAS_WIZ));
02139         *type = CFAPI_INT;
02140         break;
02141 
02142     case CFAPI_OBJECT_PROP_MERGEABLE: {
02143             object *op2;
02144 
02145             op2 = va_arg(args, object *);
02146             rint = va_arg(args, int *);
02147             *rint = can_merge(op, op2);
02148         }
02149         *type = CFAPI_INT;
02150         break;
02151 
02152     case CFAPI_OBJECT_PROP_PICKABLE: {
02153             object *op2;
02154 
02155             op2 = va_arg(args, object *);
02156             rint = va_arg(args, int *);
02157             *rint = can_pick(op2, op);
02158         }
02159         *type = CFAPI_INT;
02160         break;
02161 
02162     case CFAPI_OBJECT_PROP_FLAGS: {
02163             int fl;
02164 
02165             fl = va_arg(args, int);
02166             rint = va_arg(args, int *);
02167             *rint = QUERY_FLAG(op, fl);
02168         }
02169         *type = CFAPI_INT;
02170         break;
02171 
02172     case CFAPI_OBJECT_PROP_STR:
02173         rint = va_arg(args, int *);
02174         *rint = op->stats.Str;
02175         *type = CFAPI_INT;
02176         break;
02177 
02178     case CFAPI_OBJECT_PROP_DEX:
02179         rint = va_arg(args, int *);
02180         *rint = op->stats.Dex;
02181         *type = CFAPI_INT;
02182         break;
02183 
02184     case CFAPI_OBJECT_PROP_CON:
02185         rint = va_arg(args, int *);
02186         *rint = op->stats.Con;
02187         *type = CFAPI_INT;
02188         break;
02189 
02190     case CFAPI_OBJECT_PROP_WIS:
02191         rint = va_arg(args, int *);
02192         *rint = op->stats.Wis;
02193         *type = CFAPI_INT;
02194         break;
02195 
02196     case CFAPI_OBJECT_PROP_INT:
02197         rint = va_arg(args, int *);
02198         *rint = op->stats.Int;
02199         *type = CFAPI_INT;
02200         break;
02201 
02202     case CFAPI_OBJECT_PROP_POW:
02203         rint = va_arg(args, int *);
02204         *rint = op->stats.Pow;
02205         *type = CFAPI_INT;
02206         break;
02207 
02208     case CFAPI_OBJECT_PROP_CHA:
02209         rint = va_arg(args, int *);
02210         *rint = op->stats.Cha;
02211         *type = CFAPI_INT;
02212         break;
02213 
02214     case CFAPI_OBJECT_PROP_WC:
02215         rint = va_arg(args, int *);
02216         *rint = op->stats.wc;
02217         *type = CFAPI_INT;
02218         break;
02219 
02220     case CFAPI_OBJECT_PROP_AC:
02221         rint = va_arg(args, int *);
02222         *rint = op->stats.ac;
02223         *type = CFAPI_INT;
02224         break;
02225 
02226     case CFAPI_OBJECT_PROP_HP:
02227         rint = va_arg(args, int *);
02228         *rint = op->stats.hp;
02229         *type = CFAPI_INT;
02230         break;
02231 
02232     case CFAPI_OBJECT_PROP_SP:
02233         rint = va_arg(args, int *);
02234         *rint = op->stats.sp;
02235         *type = CFAPI_INT;
02236         break;
02237 
02238     case CFAPI_OBJECT_PROP_GP:
02239         rint = va_arg(args, int *);
02240         *rint = op->stats.grace;
02241         *type = CFAPI_INT;
02242         break;
02243 
02244     case CFAPI_OBJECT_PROP_FP:
02245         rint = va_arg(args, int *);
02246         *rint = op->stats.food;
02247         *type = CFAPI_INT;
02248         break;
02249 
02250     case CFAPI_OBJECT_PROP_MAXHP:
02251         rint = va_arg(args, int *);
02252         *rint = op->stats.maxhp;
02253         *type = CFAPI_INT;
02254         break;
02255 
02256     case CFAPI_OBJECT_PROP_MAXSP:
02257         rint = va_arg(args, int *);
02258         *rint = op->stats.maxsp;
02259         *type = CFAPI_INT;
02260         break;
02261 
02262     case CFAPI_OBJECT_PROP_MAXGP:
02263         rint = va_arg(args, int *);
02264         *rint = op->stats.maxgrace;
02265         *type = CFAPI_INT;
02266         break;
02267 
02268     case CFAPI_OBJECT_PROP_DAM:
02269         rint = va_arg(args, int *);
02270         *rint = op->stats.dam;
02271         *type = CFAPI_INT;
02272         break;
02273 
02274     case CFAPI_OBJECT_PROP_GOD:
02275         rsstring = va_arg(args, sstring *);
02276         *rsstring = determine_god(op);
02277         *type = CFAPI_SSTRING;
02278         break;
02279 
02280     case CFAPI_OBJECT_PROP_ARCH_NAME:
02281         rsstring = va_arg(args, sstring *);
02282         *rsstring = op->arch->name;
02283         *type = CFAPI_SSTRING;
02284         break;
02285 
02286     case CFAPI_OBJECT_PROP_INVISIBLE:
02287         rint = va_arg(args, int *);
02288         *rint = op->invisible;
02289         *type = CFAPI_INT;
02290         break;
02291 
02292     case CFAPI_OBJECT_PROP_FACE:
02293         rint = va_arg(args, int *);
02294         *rint = op->face->number;
02295         *type = CFAPI_INT;
02296         break;
02297 
02298     case CFAPI_OBJECT_PROP_ANIMATION:
02299         rint = va_arg(args, int *);
02300         *rint = op->animation_id;
02301         *type = CFAPI_INT;
02302         break;
02303 
02304     case CFAPI_PLAYER_PROP_IP:
02305         rsstring = va_arg(args, sstring *);
02306         *rsstring = op->contr->socket.host;
02307         *type = CFAPI_SSTRING;
02308         break;
02309 
02310     case CFAPI_PLAYER_PROP_MARKED_ITEM:
02311         robject = va_arg(args, object **);
02312         *robject = find_marked_object(op);
02313         *type = CFAPI_POBJECT;
02314         break;
02315 
02316     case CFAPI_PLAYER_PROP_PARTY:
02317         rparty = va_arg(args, partylist **);
02318         *rparty = (op->contr ? op->contr->party : NULL);
02319         *type = CFAPI_PPARTY;
02320         break;
02321 
02322     case CFAPI_PLAYER_PROP_NEXT:
02323         robject = va_arg(args, object **);
02324         if (op)
02325             *robject = op->contr->next ? op->contr->next->ob : NULL;
02326         else
02327             /* This can be called when there is no player. */
02328             *robject = first_player ? first_player->ob : NULL;
02329         *type = CFAPI_POBJECT;
02330         break;
02331 
02332     case CFAPI_PLAYER_PROP_TITLE:
02333         rsstring = va_arg(args, sstring *);
02334         *rsstring = op->contr->title;
02335         *type = CFAPI_SSTRING;
02336         break;
02337 
02338     case CFAPI_OBJECT_PROP_NO_SAVE:
02339         rint = va_arg(args, int *);
02340         *rint = op->no_save;
02341         *type = CFAPI_INT;
02342         break;
02343 
02344     case CFAPI_OBJECT_PROP_MOVE_TYPE:
02345         rmove = va_arg(args, MoveType *);
02346         *rmove = op->move_type;
02347         *type = CFAPI_MOVETYPE;
02348         break;
02349 
02350     case CFAPI_OBJECT_PROP_MOVE_BLOCK:
02351         rmove = va_arg(args, MoveType *);
02352         *rmove = op->move_block;
02353         *type = CFAPI_MOVETYPE;
02354         break;
02355 
02356     case CFAPI_OBJECT_PROP_MOVE_ALLOW:
02357         rmove = va_arg(args, MoveType *);
02358         *rmove = op->move_allow;
02359         *type = CFAPI_MOVETYPE;
02360         break;
02361 
02362     case CFAPI_OBJECT_PROP_MOVE_ON:
02363         rmove = va_arg(args, MoveType *);
02364         *rmove = op->move_on;
02365         *type = CFAPI_MOVETYPE;
02366         break;
02367 
02368     case CFAPI_OBJECT_PROP_MOVE_OFF:
02369         rmove = va_arg(args, MoveType *);
02370         *rmove = op->move_off;
02371         *type = CFAPI_MOVETYPE;
02372         break;
02373 
02374     case CFAPI_OBJECT_PROP_MOVE_SLOW:
02375         rmove = va_arg(args, MoveType *);
02376         *rmove = op->move_type;
02377         *type = CFAPI_MOVETYPE;
02378         break;
02379 
02380     case CFAPI_OBJECT_PROP_MOVE_SLOW_PENALTY:
02381         rfloat = va_arg(args, float *);
02382         *rfloat = op->move_slow_penalty;
02383         *type = CFAPI_FLOAT;
02384         break;
02385 
02386     case CFAPI_PLAYER_PROP_BED_MAP:
02387         rbuffer = va_arg(args, char *);
02388         rbufsize = va_arg(args, int);
02389         snprintf(rbuffer, rbufsize, "%s", op->contr->savebed_map);
02390         *type = CFAPI_STRING;
02391         break;
02392 
02393     case CFAPI_PLAYER_PROP_BED_X:
02394         rint = va_arg(args, int *);
02395         *rint = op->contr->bed_x;
02396         *type = CFAPI_INT;
02397         break;
02398 
02399     case CFAPI_PLAYER_PROP_BED_Y:
02400         rint = va_arg(args, int *);
02401         *rint = op->contr->bed_y;
02402         *type = CFAPI_INT;
02403         break;
02404 
02405     case CFAPI_OBJECT_PROP_DURATION:
02406         rint = va_arg(args, int *);
02407         *rint = op->duration;
02408         *type = CFAPI_INT;
02409         break;
02410 
02411     default:
02412         *type = CFAPI_NONE;
02413         break;
02414     }
02415     va_end(args);
02416     return NULL;
02417 }
02418 
02427 static void copy_message(object *op, const char *msg) {
02428     char *temp;
02429     int size;
02430 
02431     if (!msg)
02432         return;
02433 
02434     size = strlen(msg);
02435 
02436     if (msg[0] != 0 && msg[size-1] == '\n') {
02437         FREE_AND_COPY(op->msg, msg);
02438         return;
02439     }
02440 
02441     temp = malloc(size+2);
02442     if (!temp)
02443         fatal(OUT_OF_MEMORY);
02444     snprintf(temp, size+2, "%s\n", msg);
02445     FREE_AND_COPY(op->msg, temp);
02446     free(temp);
02447 }
02448 
02459 void *cfapi_object_set_property(int *type, ...) {
02460     va_list args;
02461     int iarg;
02462     long larg;
02463     char *sarg;
02464     double darg;
02465     object *oparg;
02466     object *op;
02467     int property;
02468     sint64 s64arg;
02469     partylist *partyarg;
02470     float farg;
02471 
02472     va_start(args, type);
02473     op = va_arg(args, object *);
02474     property = va_arg(args, int);
02475     *type = CFAPI_NONE;
02476 
02477     if (op != NULL && (!op->arch || (op != &op->arch->clone))) {
02478         switch (property) {
02479         case CFAPI_OBJECT_PROP_NAME:
02480             sarg = va_arg(args, char *);
02481             *type = CFAPI_STRING;
02482             FREE_AND_COPY(op->name, sarg);
02483             send_changed_object(op);
02484             break;
02485 
02486         case CFAPI_OBJECT_PROP_NAME_PLURAL:
02487             sarg = va_arg(args, char *);
02488             *type = CFAPI_STRING;
02489             FREE_AND_COPY(op->name_pl, sarg);
02490             send_changed_object(op);
02491             break;
02492 
02493         case CFAPI_OBJECT_PROP_TITLE:
02494             sarg = va_arg(args, char *);
02495             *type = CFAPI_STRING;
02496             FREE_AND_COPY(op->title, sarg);
02497             break;
02498 
02499         case CFAPI_OBJECT_PROP_RACE:
02500             sarg = va_arg(args, char *);
02501             *type = CFAPI_STRING;
02502             FREE_AND_COPY(op->race, sarg);
02503             break;
02504 
02505         case CFAPI_OBJECT_PROP_SLAYING:
02506             sarg = va_arg(args, char *);
02507             *type = CFAPI_STRING;
02508             FREE_AND_COPY(op->slaying, sarg);
02509             break;
02510 
02511         case CFAPI_OBJECT_PROP_SKILL:
02512             sarg = va_arg(args, char *);
02513             *type = CFAPI_STRING;
02514             FREE_AND_COPY(op->skill, sarg);
02515             break;
02516 
02517         case CFAPI_OBJECT_PROP_MESSAGE:
02518             sarg = va_arg(args, char *);
02519             *type = CFAPI_STRING;
02520             copy_message(op, sarg);
02521             break;
02522 
02523         case CFAPI_OBJECT_PROP_LORE:
02524             sarg = va_arg(args, char *);
02525             *type = CFAPI_STRING;
02526             FREE_AND_COPY(op->lore, sarg);
02527             break;
02528 
02529         case CFAPI_OBJECT_PROP_SPEED:
02530             farg = va_arg(args, double);
02531             *type = CFAPI_FLOAT;
02532             if (farg != op->speed) {
02533                 op->speed = farg;
02534                 update_ob_speed(op);
02535             }
02536             break;
02537 
02538         case CFAPI_OBJECT_PROP_SPEED_LEFT:
02539             farg = va_arg(args, double);
02540             *type = CFAPI_FLOAT;
02541             op->speed_left = farg;
02542             break;
02543 
02544         case CFAPI_OBJECT_PROP_NROF:
02545             iarg = va_arg(args, int);
02546             *type = CFAPI_INT;
02547             if (iarg < 0)
02548                 iarg = 0;
02549             if (op->nrof > (uint32)iarg)
02550                 decrease_ob_nr(op, op->nrof-iarg);
02551             else if (op->nrof < (uint32)iarg) {
02552                 object *tmp;
02553                 player *pl;
02554 
02555                 op->nrof = iarg;
02556                 if (op->env != NULL) {
02557                     tmp = get_player_container(op->env);
02558                     if (!tmp) {
02559                         for (pl = first_player; pl; pl = pl->next)
02560                             if (pl->ob->container == op->env)
02561                                 break;
02562                         if (pl)
02563                             tmp = pl->ob;
02564                         else
02565                             tmp = NULL;
02566                     } else {
02567                         sum_weight(tmp);
02568                         fix_object(tmp);
02569                     }
02570                     if (tmp)
02571                         esrv_update_item(UPD_NROF, tmp, op);
02572                 } else {
02573                     object *above = op->above;
02574 
02575                     for (tmp = above; tmp != NULL; tmp = tmp->above)
02576                         if (tmp->type == PLAYER)
02577                             tmp->contr->socket.update_look = 1;
02578                 }
02579             }
02580             break;
02581 
02582         case CFAPI_OBJECT_PROP_DIRECTION:
02583             iarg = va_arg(args, int);
02584             *type = CFAPI_INT;
02585             op->direction = iarg;
02586             break;
02587 
02588         case CFAPI_OBJECT_PROP_FACING:
02589             iarg = va_arg(args, int);
02590             *type = CFAPI_INT;
02591             op->facing = iarg;
02592             break;
02593 
02594         case CFAPI_OBJECT_PROP_RESIST: {
02595             int iargbis = va_arg(args, int);
02596 
02597             *type = CFAPI_INT16;
02598             iarg = va_arg(args, int);
02599             op->resist[iargbis] = iarg;
02600         }
02601             break;
02602 
02603         case CFAPI_OBJECT_PROP_ATTACK_TYPE:
02604             iarg = va_arg(args, int);
02605             *type = CFAPI_INT;
02606             op->attacktype = iarg;
02607             break;
02608 
02609         case CFAPI_OBJECT_PROP_PATH_ATTUNED:
02610             iarg = va_arg(args, int);
02611             *type = CFAPI_INT;
02612             op->path_attuned = iarg;
02613             break;
02614 
02615         case CFAPI_OBJECT_PROP_PATH_REPELLED:
02616             iarg = va_arg(args, int);
02617             *type = CFAPI_INT;
02618             op->path_repelled = iarg;
02619             break;
02620 
02621         case CFAPI_OBJECT_PROP_PATH_DENIED:
02622             iarg = va_arg(args, int);
02623             *type = CFAPI_INT;
02624             op->path_denied = iarg;
02625             break;
02626 
02627         case CFAPI_OBJECT_PROP_MATERIAL:
02628             iarg = va_arg(args, int);
02629             *type = CFAPI_INT;
02630             op->material = iarg;
02631             break;
02632 
02633         case CFAPI_OBJECT_PROP_MATERIAL_NAME:
02634             break;
02635 
02636         case CFAPI_OBJECT_PROP_MAGIC:
02637             iarg = va_arg(args, int);
02638             *type = CFAPI_INT;
02639             op->magic = iarg;
02640             break;
02641 
02642         case CFAPI_OBJECT_PROP_VALUE:
02643             larg = va_arg(args, long);
02644             *type = CFAPI_LONG;
02645             op->value = larg;
02646             break;
02647 
02648         case CFAPI_OBJECT_PROP_LEVEL:
02649             iarg = va_arg(args, int);
02650             *type = CFAPI_INT;
02651             op->level = iarg;
02652             break;
02653 
02654         case CFAPI_OBJECT_PROP_LAST_HEAL:
02655             iarg = va_arg(args, int);
02656             *type = CFAPI_INT;
02657             op->last_heal = iarg;
02658             break;
02659 
02660         case CFAPI_OBJECT_PROP_LAST_SP:
02661             iarg = va_arg(args, int);
02662             *type = CFAPI_INT;
02663             op->last_sp = iarg;
02664             break;
02665 
02666         case CFAPI_OBJECT_PROP_LAST_GRACE:
02667             iarg = va_arg(args, int);
02668             *type = CFAPI_INT;
02669             op->last_grace = iarg;
02670             break;
02671 
02672         case CFAPI_OBJECT_PROP_LAST_EAT:
02673             iarg = va_arg(args, int);
02674             *type = CFAPI_INT;
02675             op->last_eat = iarg;
02676             break;
02677 
02678         case CFAPI_OBJECT_PROP_INVISIBLE_TIME:
02679             iarg = va_arg(args, int);
02680             *type = CFAPI_INT;
02681             op->invisible = iarg;
02682             break;
02683 
02684         case CFAPI_OBJECT_PROP_PICK_UP:
02685             iarg = va_arg(args, int);
02686             *type = CFAPI_INT;
02687             op->pick_up = iarg;
02688             break;
02689 
02690         case CFAPI_OBJECT_PROP_ITEM_POWER:
02691             iarg = va_arg(args, int);
02692             *type = CFAPI_INT;
02693             op->item_power = iarg;
02694             break;
02695 
02696         case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR:
02697             iarg = va_arg(args, int);
02698             *type = CFAPI_INT;
02699             op->gen_sp_armour = iarg;
02700             break;
02701 
02702         case CFAPI_OBJECT_PROP_WEIGHT:
02703             iarg = va_arg(args, int);
02704             *type = CFAPI_INT;
02705             if (op->weight != iarg) {
02706                 object *tmp;
02707                 player *pl;
02708 
02709                 op->weight = iarg;
02710                 if (op->env != NULL) {
02711                     tmp = get_player_container(op->env);
02712                     if (!tmp) {
02713                         for (pl = first_player; pl; pl = pl->next)
02714                             if (pl->ob->container == op->env)
02715                                 break;
02716                         if (pl)
02717                             tmp = pl->ob;
02718                         else
02719                             tmp = NULL;
02720                     } else {
02721                         sum_weight(tmp);
02722                         fix_object(tmp);
02723                     }
02724                     if (tmp)
02725                         esrv_update_item(UPD_WEIGHT, tmp, op);
02726                 } else {
02727                     object *above = op->above;
02728 
02729                     for (tmp = above; tmp != NULL; tmp = tmp->above)
02730                         if (tmp->type == PLAYER)
02731                             esrv_update_item(UPD_WEIGHT, tmp, op);
02732                 }
02733             }
02734             break;
02735 
02736         case CFAPI_OBJECT_PROP_WEIGHT_LIMIT:
02737             iarg = va_arg(args, int);
02738             *type = CFAPI_INT;
02739             op->weight_limit = iarg;
02740             break;
02741 
02742         case CFAPI_OBJECT_PROP_GLOW_RADIUS:
02743             iarg = va_arg(args, int);
02744             *type = CFAPI_INT;
02745             if (op->glow_radius != iarg) {
02746                 object *tmp;
02747 
02748                 op->glow_radius = iarg;
02749                 tmp = object_get_env_recursive(op);
02750                 if (tmp->map != NULL) {
02751                     SET_MAP_FLAGS(tmp->map, tmp->x, tmp->y,  P_NEED_UPDATE);
02752                     update_position(tmp->map, tmp->x, tmp->y);
02753                     update_all_los(tmp->map, tmp->x, tmp->y);
02754                 }
02755             }
02756             break;
02757 
02758         case CFAPI_OBJECT_PROP_PERM_EXP:
02759             s64arg = va_arg(args, sint64);
02760             *type = CFAPI_SINT64;
02761             op->perm_exp = s64arg;
02762             break;
02763 
02764         case CFAPI_OBJECT_PROP_ENEMY:
02765             oparg = va_arg(args, object *);
02766             *type = CFAPI_POBJECT;
02767             op->enemy = oparg;
02768             break;
02769 
02770         case CFAPI_OBJECT_PROP_RUN_AWAY:
02771             iarg = va_arg(args, int);
02772             *type = CFAPI_INT;
02773             op->run_away = iarg;
02774             break;
02775 
02776         case CFAPI_OBJECT_PROP_CHOSEN_SKILL:
02777             oparg = va_arg(args, object *);
02778             *type = CFAPI_POBJECT;
02779             op->chosen_skill = oparg;
02780             break;
02781 
02782         case CFAPI_OBJECT_PROP_HIDDEN:
02783             iarg = va_arg(args, int);
02784             *type = CFAPI_INT;
02785             op->hide = iarg;
02786             break;
02787 
02788         case CFAPI_OBJECT_PROP_MOVE_STATUS:
02789             iarg = va_arg(args, int);
02790             *type = CFAPI_INT;
02791             op->move_status = iarg;
02792             break;
02793 
02794         case CFAPI_OBJECT_PROP_ATTACK_MOVEMENT:
02795             iarg = va_arg(args, int);
02796             *type = CFAPI_INT;
02797             op->attack_movement = iarg;
02798             break;
02799 
02800         case CFAPI_OBJECT_PROP_SPELL_ITEM:
02801             oparg = va_arg(args, object *);
02802             *type = CFAPI_POBJECT;
02803             op->spellitem = oparg;
02804             break;
02805 
02806         case CFAPI_OBJECT_PROP_EXP_MULTIPLIER:
02807             darg = va_arg(args, double);
02808             *type = CFAPI_DOUBLE;
02809             op->expmul = darg;
02810             break;
02811 
02812         case CFAPI_OBJECT_PROP_CUSTOM_NAME:
02813             sarg = va_arg(args, char *);
02814             *type = CFAPI_STRING;
02815             FREE_AND_COPY(op->custom_name, sarg);
02816             send_changed_object(op);
02817             break;
02818 
02819         case CFAPI_OBJECT_PROP_ANIM_SPEED:
02820             iarg = va_arg(args, int);
02821             *type = CFAPI_INT;
02822             op->anim_speed = iarg;
02823             break;
02824 
02825         case CFAPI_OBJECT_PROP_FRIENDLY:
02826             iarg = va_arg(args, int);
02827             *type = CFAPI_INT;
02828             if (iarg == 1 && is_friendly(op) == 0)
02829                 add_friendly_object(op);
02830             else if (iarg == 0 && is_friendly(op) == 1)
02831                 remove_friendly_object(op);
02832             break;
02833 
02834         case CFAPI_OBJECT_PROP_LUCK:
02835             iarg = va_arg(args, int);
02836             *type = CFAPI_INT;
02837             op->stats.luck = iarg;
02838             break;
02839 
02840         case CFAPI_OBJECT_PROP_EXP:
02841             s64arg = va_arg(args, sint64);
02842             *type = CFAPI_SINT64;
02843             op->stats.exp = s64arg;
02844             break;
02845 
02846         case CFAPI_OBJECT_PROP_OWNER:
02847             oparg = va_arg(args, object *);
02848             *type = CFAPI_POBJECT;
02849             set_owner(op, oparg);
02850             break;
02851 
02852         case CFAPI_OBJECT_PROP_CHEATER:
02853             set_cheat(op);
02854             *type = CFAPI_NONE;
02855             break;
02856 
02857         case CFAPI_OBJECT_PROP_FLAGS: {
02858                 int iargbis;
02859 
02860                 iarg = va_arg(args, int);
02861                 iargbis = va_arg(args, int);
02862                 *type = CFAPI_INT;
02863 
02864                 if (iargbis == 1)
02865                     SET_FLAG(op, iarg);
02866                 else
02867                     CLEAR_FLAG(op, iarg);
02868             }
02869             break;
02870 
02871         case CFAPI_OBJECT_PROP_STR:
02872             iarg = va_arg(args, int);
02873             *type = CFAPI_INT;
02874             op->stats.Str = iarg;
02875             break;
02876 
02877         case CFAPI_OBJECT_PROP_DEX:
02878             iarg = va_arg(args, int);
02879             *type = CFAPI_INT;
02880             op->stats.Dex = iarg;
02881             break;
02882 
02883         case CFAPI_OBJECT_PROP_CON:
02884             iarg = va_arg(args, int);
02885             *type = CFAPI_INT;
02886             op->stats.Con = iarg;
02887             break;
02888 
02889         case CFAPI_OBJECT_PROP_WIS:
02890             iarg = va_arg(args, int);
02891             *type = CFAPI_INT;
02892             op->stats.Wis = iarg;
02893             break;
02894 
02895         case CFAPI_OBJECT_PROP_INT:
02896             iarg = va_arg(args, int);
02897             *type = CFAPI_INT;
02898             op->stats.Int = iarg;
02899             break;
02900 
02901         case CFAPI_OBJECT_PROP_POW:
02902             iarg = va_arg(args, int);
02903             *type = CFAPI_INT;
02904             op->stats.Pow = iarg;
02905             break;
02906 
02907         case CFAPI_OBJECT_PROP_CHA:
02908             iarg = va_arg(args, int);
02909             *type = CFAPI_INT;
02910             op->stats.Cha = iarg;
02911             break;
02912 
02913         case CFAPI_OBJECT_PROP_WC:
02914             iarg = va_arg(args, int);
02915             *type = CFAPI_INT;
02916             op->stats.wc = iarg;
02917             break;
02918 
02919         case CFAPI_OBJECT_PROP_AC:
02920             iarg = va_arg(args, int);
02921             *type = CFAPI_INT;
02922             op->stats.ac = iarg;
02923             break;
02924 
02925         case CFAPI_OBJECT_PROP_HP:
02926             iarg = va_arg(args, int);
02927             *type = CFAPI_INT;
02928             op->stats.hp = iarg;
02929             break;
02930 
02931         case CFAPI_OBJECT_PROP_SP:
02932             iarg = va_arg(args, int);
02933             *type = CFAPI_INT;
02934             op->stats.sp = iarg;
02935             break;
02936 
02937         case CFAPI_OBJECT_PROP_GP:
02938             iarg = va_arg(args, int);
02939             *type = CFAPI_INT;
02940             op->stats.grace = iarg;
02941             break;
02942 
02943         case CFAPI_OBJECT_PROP_FP:
02944             iarg = va_arg(args, int);
02945             *type = CFAPI_INT;
02946             op->stats.food = iarg;
02947             break;
02948 
02949         case CFAPI_OBJECT_PROP_MAXHP:
02950             iarg = va_arg(args, int);
02951             *type = CFAPI_INT;
02952             op->stats.maxhp = iarg;
02953             break;
02954 
02955         case CFAPI_OBJECT_PROP_MAXSP:
02956             iarg = va_arg(args, int);
02957             *type = CFAPI_INT;
02958             op->stats.maxsp = iarg;
02959             break;
02960 
02961         case CFAPI_OBJECT_PROP_MAXGP:
02962             iarg = va_arg(args, int);
02963             *type = CFAPI_INT;
02964             op->stats.maxgrace = iarg;
02965             break;
02966 
02967         case CFAPI_OBJECT_PROP_DAM:
02968             iarg = va_arg(args, int);
02969             *type = CFAPI_INT;
02970             op->stats.dam = iarg;
02971             break;
02972 
02973         case CFAPI_OBJECT_PROP_FACE:
02974             iarg = va_arg(args, int);
02975             *type = CFAPI_INT;
02976             op->face = &new_faces[iarg];
02977             op->state = 0;
02978             update_object(op, UP_OBJ_FACE);
02979             break;
02980 
02981         case CFAPI_OBJECT_PROP_ANIMATION:
02982             iarg = va_arg(args, int);
02983             *type = CFAPI_INT;
02984             op->animation_id = iarg;
02985             SET_ANIMATION(op, 0);
02986             update_object(op, UP_OBJ_FACE);
02987             break;
02988 
02989         case CFAPI_OBJECT_PROP_DURATION:
02990             iarg = va_arg(args, int);
02991             *type = CFAPI_INT;
02992             op->duration = iarg;
02993             break;
02994 
02995         case CFAPI_PLAYER_PROP_MARKED_ITEM:
02996             if (op->contr) {
02997                 oparg = va_arg(args, object *);
02998                 *type = CFAPI_POBJECT;
02999                 op->contr->mark = oparg;
03000                 if (oparg)
03001                     op->contr->mark_count = oparg->count;
03002             }
03003             break;
03004 
03005         case CFAPI_PLAYER_PROP_PARTY:
03006             if (op->contr) {
03007                 partyarg = va_arg(args, partylist *);
03008                 *type = CFAPI_PPARTY;
03009                 op->contr->party = partyarg;
03010             }
03011             break;
03012 
03013         case CFAPI_OBJECT_PROP_NO_SAVE:
03014             iarg = va_arg(args, int);
03015             *type = CFAPI_INT;
03016             op->no_save = iarg;
03017             break;
03018 
03019         case CFAPI_PLAYER_PROP_BED_MAP:
03020             sarg = va_arg(args, char *);
03021             *type = CFAPI_STRING;
03022             strncpy(op->contr->savebed_map, sarg, MAX_BUF);
03023             break;
03024 
03025         case CFAPI_PLAYER_PROP_BED_X:
03026             iarg = va_arg(args, int);
03027             *type = CFAPI_INT;
03028             op->contr->bed_x = iarg;
03029             break;
03030 
03031         case CFAPI_PLAYER_PROP_BED_Y:
03032             iarg = va_arg(args, int);
03033             *type = CFAPI_INT;
03034             op->contr->bed_y = iarg;
03035             break;
03036 
03037         case CFAPI_PLAYER_PROP_TITLE:
03038             sarg = va_arg(args, char *);
03039             *type = CFAPI_STRING;
03040             strncpy(op->contr->title, sarg, sizeof(op->contr->title));
03041             op->contr->title[sizeof(op->contr->title) - 1]= '\0';
03042             break;
03043 
03044         default:
03045             break;
03046         }
03047     }
03048     va_end(args);
03049 
03050     return NULL;
03051 }
03052 
03061 void *cfapi_object_apply_below(int *type, ...) {
03062     va_list args;
03063     object *applier;
03064 
03065     va_start(args, type);
03066 
03067     applier = va_arg(args, object *);
03068 
03069     va_end(args);
03070 
03071     player_apply_below(applier);
03072     *type = CFAPI_NONE;
03073     return NULL;
03074 }
03075 
03084 void *cfapi_object_apply(int *type, ...) {
03085     va_list args;
03086     object *applied;
03087     object *applier;
03088     int aflags;
03089     int *ret;
03090 
03091     va_start(args, type);
03092 
03093     applier = va_arg(args, object *);
03094     applied = va_arg(args, object *);
03095     aflags = va_arg(args, int);
03096     ret = va_arg(args, int *);
03097 
03098     va_end(args);
03099 
03100     *type = CFAPI_INT;
03101     *ret = manual_apply(applier, applied, aflags);
03102     return NULL;
03103 }
03104 
03112 void *cfapi_object_identify(int *type, ...) {
03113     va_list args;
03114     object *op;
03115 
03116     va_start(args, type);
03117 
03118     op = va_arg(args, object *);
03119 
03120     va_end(args);
03121 
03122     identify(op);
03123     *type = CFAPI_NONE;
03124     return NULL;
03125 }
03126 
03134 void *cfapi_object_describe(int *type, ...) {
03135     va_list args;
03136     object *op;
03137     object *owner;
03138     char *desc;
03139     int size;
03140 
03141     va_start(args, type);
03142 
03143     op = va_arg(args, object *);
03144     owner = va_arg(args, object *);
03145     desc = va_arg(args, char *);
03146     size = va_arg(args, int);
03147     va_end(args);
03148 
03149     *type = CFAPI_STRING;
03150     describe_item(op, owner, desc, size);
03151     return NULL;
03152 }
03153 
03154 void *cfapi_object_drain(int *type, ...) {
03155     va_list args;
03156 
03157     object *op;
03158     int ds;
03159 
03160     va_start(args, type);
03161 
03162     op = va_arg(args, object *);
03163     ds = va_arg(args, int);
03164 
03165     va_end(args);
03166 
03167     drain_specific_stat(op, ds);
03168 
03169     *type = CFAPI_NONE;
03170     return NULL;
03171 }
03172 
03173 void *cfapi_object_fix(int *type, ...) {
03174     va_list args;
03175     object *op;
03176 
03177     va_start(args, type);
03178 
03179     op = va_arg(args, object *);
03180 
03181     va_end(args);
03182 
03183     fix_object(op);
03184 
03185     *type = CFAPI_NONE;
03186     return NULL;
03187 }
03188 
03189 void *cfapi_object_give_skill(int *type, ...) {
03190     va_list args;
03191 
03192     object *op;
03193     char *skillname;
03194 
03195     va_start(args, type);
03196 
03197     op = va_arg(args, object *);
03198     skillname = va_arg(args, char *);
03199 
03200     va_end(args);
03201 
03202     *type = CFAPI_POBJECT;
03203     return give_skill_by_name(op, skillname);
03204 }
03205 
03206 void *cfapi_object_transmute(int *type, ...) {
03207     va_list args;
03208 
03209     object *op;
03210     object *chg;
03211 
03212     va_start(args, type);
03213 
03214     op = va_arg(args, object *);
03215     chg = va_arg(args, object *);
03216 
03217     va_end(args);
03218 
03219     transmute_materialname(op, chg);
03220     *type = CFAPI_NONE;
03221     return NULL;
03222 }
03223 
03224 void *cfapi_object_remove(int *type, ...) {
03225     va_list args;
03226     object *op;
03227 
03228     va_start(args, type);
03229 
03230     op = va_arg(args, object *);
03231 
03232     if (QUERY_FLAG(op, FLAG_REMOVED)) {
03233         LOG(llevError, "Plugin trying to remove removed object %s\n", op->name);
03234         *type = CFAPI_NONE;
03235         return NULL;
03236     }
03237 
03238     va_end(args);
03239 
03240     remove_ob(op);
03241     *type = CFAPI_NONE;
03242     return NULL;
03243 }
03244 
03245 void *cfapi_object_delete(int *type, ...) {
03246     va_list args;
03247     object *op;
03248 
03249     va_start(args, type);
03250 
03251     op = va_arg(args, object *);
03252 
03253     if (QUERY_FLAG(op, FLAG_FREED) || !QUERY_FLAG(op, FLAG_REMOVED)) {
03254         LOG(llevError, "Plugin trying to free freed/non removed object %s\n", op->name);
03255         *type = CFAPI_NONE;
03256         return NULL;
03257     }
03258 
03259     va_end(args);
03260 
03261     free_object(op);
03262 
03263     *type = CFAPI_NONE;
03264     return NULL;
03265 }
03266 
03274 void *cfapi_object_clone(int *type, ...) {
03275     va_list args;
03276     object *op;
03277     int kind;
03278     object **robj;
03279 
03280     va_start(args, type);
03281 
03282     op = va_arg(args, object *);
03283     kind = va_arg(args, int);
03284     robj = va_arg(args, object **);
03285 
03286     va_end(args);
03287 
03288     if (kind == 0) {
03289         *type = CFAPI_POBJECT;
03290         *robj = object_create_clone(op);
03291     } else {
03292         object *tmp;
03293         tmp = get_object();
03294         copy_object(op, tmp);
03295         *type = CFAPI_POBJECT;
03296         *robj = tmp;
03297     }
03298     return NULL;
03299 }
03300 
03301 void *cfapi_object_find(int *type, ...) {
03302     va_list args;
03303     int ftype;
03304     void *rv;
03305     int ival;
03306     int ival2;
03307     char *sval;
03308     object *op;
03309 
03310     va_start(args, type);
03311 
03312     *type = CFAPI_POBJECT;
03313     ftype = va_arg(args, int);
03314     switch (ftype) {
03315     case 0:
03316         ival = va_arg(args, int);
03317         rv = find_object(ival);
03318         break;
03319 
03320     case 1:
03321         sval = va_arg(args, char *);
03322         rv = find_object_name(sval);
03323         break;
03324 
03325     case 2:
03326         op = va_arg(args, object *);
03327         ival = va_arg(args, int);
03328         ival2 = va_arg(args, int);
03329         rv = find_obj_by_type_subtype(op, ival, ival2);
03330         break;
03331 
03332     case 3:
03333         op = va_arg(args, object *);
03334         rv = get_player_container(op);
03335         break;
03336 
03337     default:
03338         rv = NULL;
03339         *type = CFAPI_NONE;
03340         break;
03341     }
03342 
03343     va_end(args);
03344 
03345     return rv;
03346 }
03347 
03355 void *cfapi_object_create(int *type, ...) {
03356     va_list args;
03357     int ival;
03358     object **robj;
03359     va_start(args, type);
03360     ival = va_arg(args, int);
03361 
03362     *type = CFAPI_POBJECT;
03363     switch (ival) {
03364     case 0:
03365         robj = va_arg(args, object **);
03366         *robj = get_object();
03367         break;
03368 
03369     case 1: { /* Named object. Nearly the old plugin behavior, but we don't add artifact suffixes */
03370             const char *sval;
03371             archetype *at;
03372 
03373             sval = va_arg(args, const char *);
03374             robj = va_arg(args, object **);
03375             va_end(args);
03376 
03377             at = try_find_archetype(sval);
03378             if (!at)
03379                 at = find_archetype_by_object_name(sval);
03380             if (at) {
03381                 *robj = object_create_arch(at);
03382             } else
03383                 *robj = NULL;
03384         }
03385         break;
03386 
03387     default:
03388         *type = CFAPI_NONE;
03389         break;
03390     }
03391     va_end(args);
03392     return NULL;
03393 }
03394 void *cfapi_object_insert(int *type, ...) {
03395     va_list args;
03396     object *op;
03397     object *orig;
03398     mapstruct *map;
03399     int flag, x, y;
03400     int itype;
03401     object **robj;
03402 
03403     va_start(args, type);
03404 
03405     op = va_arg(args, object *);
03406     if (!op) {
03407         LOG(llevError, "cfapi_object_insert: called with NULL object!\n");
03408         va_end(args);
03409         return NULL;
03410     }
03411     if (QUERY_FLAG(op, FLAG_FREED)) {
03412         LOG(llevError, "cfapi_object_insert: called with FREED object!\n");
03413         va_end(args);
03414         return NULL;
03415     }
03416     if (!QUERY_FLAG(op, FLAG_REMOVED)) {
03417         LOG(llevError, "cfapi_object_insert: called with not removed object %s!\n", op->name);
03418         remove_ob(op);
03419     }
03420     itype = va_arg(args, int);
03421 
03422     switch (itype) {
03423     case 0:
03424         map = va_arg(args, mapstruct *);
03425         orig = va_arg(args, object *);
03426         flag = va_arg(args, int);
03427         x = va_arg(args, int);
03428         y = va_arg(args, int);
03429         robj = va_arg(args, object **);
03430         if (!map) {
03431             LOG(llevError, "cfapi_object_insert (0): called with NULL map, object %s!\n", op->name);
03432             free_object(op);
03433             *robj = NULL;
03434         } else
03435             *robj = insert_ob_in_map_at(op, map, orig, flag, x, y);
03436         *type = CFAPI_POBJECT;
03437         break;
03438 
03439     case 1:
03440         map = va_arg(args, mapstruct *);
03441         orig = va_arg(args, object *);
03442         flag = va_arg(args, int);
03443         robj = va_arg(args, object **);
03444         if (!map) {
03445             LOG(llevError, "cfapi_object_insert (1): called with NULL map, object %s!\n", op->name);
03446             free_object(op);
03447             *robj = NULL;
03448         } else
03449             *robj = insert_ob_in_map(op, map, orig, flag);
03450         *type = CFAPI_POBJECT;
03451         break;
03452 
03453     case 3:
03454         orig = va_arg(args, object *);
03455         robj = va_arg(args, object **);
03456         if (!orig) {
03457             LOG(llevError, "cfapi_object_insert (3): called with NULL orig, object %s!\n", op->name);
03458             free_object(op);
03459             *robj = NULL;
03460         } else
03461             *robj = insert_ob_in_ob(op, orig);
03462         *type = CFAPI_POBJECT;
03463         break;
03464 
03465     default:
03466         LOG(llevError, "cfapi_object_insert (1): called with itype %d which is not valid, object %s!\n", itype, op->name);
03467         free_object(op);
03468         *type = CFAPI_NONE;
03469         break;
03470     }
03471 
03472     va_end(args);
03473 
03474     return NULL;
03475 }
03483 void *cfapi_object_split(int *type, ...) {
03484     va_list args;
03485 
03486     int nr, size;
03487     object *op;
03488     char *buf;
03489     object **split;
03490 
03491     va_start(args, type);
03492 
03493     op = va_arg(args, object *);
03494     nr = va_arg(args, int);
03495     buf = va_arg(args, char *);
03496     size = va_arg(args, int);
03497     split = va_arg(args, object **);
03498     va_end(args);
03499 
03500     *type = CFAPI_POBJECT;
03501     *split = get_split_ob(op, nr, buf, size);
03502     return NULL;
03503 }
03504 
03512 void *cfapi_object_merge(int *type, ...) {
03513     va_list args;
03514     object *op;
03515     object *op2;
03516     object **merge;
03517 
03518     va_start(args, type);
03519 
03520     op = va_arg(args, object *);
03521     op2 = va_arg(args, object *);
03522     merge = va_arg(args, object **);
03523 
03524     va_end(args);
03525 
03526     *type = CFAPI_POBJECT;
03527     *merge = merge_ob(op, op2);
03528     return NULL;
03529 }
03530 
03538 void *cfapi_object_distance(int *type, ...) {
03539     va_list args;
03540     object *op;
03541     object *op2;
03542     int *rint;
03543     va_start(args, type);
03544 
03545     op = va_arg(args, object *);
03546     op2 = va_arg(args, object *);
03547     rint = va_arg(args, int *);
03548 
03549     va_end(args);
03550 
03551     *type = CFAPI_INT;
03552     *rint = distance(op, op2);
03553     return NULL;
03554 }
03562 void *cfapi_object_update(int *type, ...) {
03563     va_list args;
03564     int action;
03565     object *op;
03566     va_start(args, type);
03567 
03568     op = va_arg(args, object *);
03569     action = va_arg(args, int);
03570 
03571     va_end(args);
03572 
03573     update_object(op, action);
03574     *type = CFAPI_NONE;
03575     return NULL;
03576 }
03577 
03585 void *cfapi_object_clear(int *type, ...) {
03586     va_list args;
03587     object *op;
03588     va_start(args, type);
03589 
03590     op = va_arg(args, object *);
03591 
03592     va_end(args);
03593 
03594     clear_object(op);
03595     *type = CFAPI_NONE;
03596     return NULL;
03597 }
03598 
03606 void *cfapi_object_reset(int *type, ...) {
03607     va_list args;
03608     object *op;
03609 
03610     va_start(args, type);
03611 
03612     op = va_arg(args, object *);
03613 
03614     va_end(args);
03615 
03616     reset_object(op);
03617     *type = CFAPI_NONE;
03618     return NULL;
03619 }
03620 
03621 void *cfapi_object_check_inventory(int *type, ...) {
03622     va_list args;
03623     object *op;
03624     object *op2;
03625     int checktype;
03626     object *ret = NULL;
03627 
03628     va_start(args, type);
03629 
03630     op = va_arg(args, object *);
03631     op2 = va_arg(args, object *);
03632     checktype = va_arg(args, int);
03633 
03634     if (checktype == 0) {
03635         check_inv(op, op2);
03636         *type = CFAPI_NONE;
03637     } else {
03638         ret = check_inv_recursive(op, op2);
03639         *type = CFAPI_POBJECT;
03640     }
03641 
03642     va_end(args);
03643 
03644     return ret;
03645 }
03646 
03647 void *cfapi_object_clean_object(int *type, ...) {
03648     va_list args;
03649     object *op;
03650 
03651     va_start(args, type);
03652     op = va_arg(args, object *);
03653     clean_object(op);
03654     va_end(args);
03655     *type = CFAPI_NONE;
03656     return NULL;
03657 }
03658 
03659 void *cfapi_object_on_same_map(int *type, ...) {
03660     va_list args;
03661     object *op1;
03662     object *op2;
03663     int *rint;
03664 
03665     va_start(args, type);
03666     op1 = va_arg(args, object *);
03667     op2 = va_arg(args, object *);
03668     rint = va_arg(args, int *);
03669     va_end(args);
03670 
03671     *type = CFAPI_INT;
03672     *rint = on_same_map(op1, op2);
03673 
03674     return NULL;
03675 }
03676 
03677 void *cfapi_object_spring_trap(int *type, ...) {
03678     object *trap;
03679     object *victim;
03680     va_list args;
03681 
03682     va_start(args, type);
03683     trap = va_arg(args, object *);
03684     victim = va_arg(args, object *);
03685     va_end(args);
03686 
03687     spring_trap(trap, victim);
03688     *type = CFAPI_NONE;
03689     return NULL;
03690 }
03691 
03699 void *cfapi_object_check_trigger(int *type, ...) {
03700     object *op;
03701     object *cause;
03702     va_list args;
03703     int *rint;
03704 
03705     va_start(args, type);
03706     op = va_arg(args, object *);
03707     cause = va_arg(args, object *);
03708     rint = va_arg(args, int *);
03709     va_end(args);
03710 
03711     *rint = check_trigger(op, cause);
03712     *type = CFAPI_INT;
03713     return NULL;
03714 }
03715 
03729 void *cfapi_map_trigger_connected(int *type, ...) {
03730     objectlink *ol;
03731     object *cause;
03732     int state;
03733     va_list args;
03734 
03735     va_start(args, type);
03736     ol = va_arg(args, objectlink *);
03737     cause = va_arg(args, object *);
03738     state = va_arg(args, int);
03739     va_end(args);
03740     trigger_connected(ol, cause, state);
03741     *type = CFAPI_NONE;
03742     return NULL;
03743 }
03744 
03752 void *cfapi_object_query_cost(int *type, ...) {
03753     object *op;
03754     object *who;
03755     int flags;
03756     va_list args;
03757     int *rint;
03758 
03759     va_start(args, type);
03760     op = va_arg(args, object *);
03761     who = va_arg(args, object *);
03762     flags = va_arg(args, int);
03763     rint = va_arg(args, int *);
03764     va_end(args);
03765 
03766     *rint = query_cost(op, who, flags);
03767     *type = CFAPI_INT;
03768     return NULL;
03769 }
03770 
03778 void *cfapi_object_query_money(int *type, ...) {
03779     object *op;
03780     va_list args;
03781     int *rint;
03782 
03783     va_start(args, type);
03784     op = va_arg(args, object *);
03785     rint = va_arg(args, int *);
03786     va_end(args);
03787 
03788     *rint = query_money(op);
03789     *type = CFAPI_INT;
03790     return NULL;
03791 }
03792 
03800 void *cfapi_object_cast(int *type, ...) {
03801     object *op;
03802     object *sp;
03803     int dir;
03804     char *str;
03805     object *caster;
03806     va_list args;
03807     int *rint;
03808 
03809     va_start(args, type);
03810     op = va_arg(args, object *);
03811     caster = va_arg(args, object *);
03812     dir = va_arg(args, int);
03813     sp = va_arg(args, object *);
03814     str = va_arg(args, char *);
03815     rint = va_arg(args, int *);
03816     va_end(args);
03817 
03818     *type = CFAPI_INT;
03819 
03820     if (!op->map) {
03821         *rint = -1;
03822         return NULL;
03823     }
03824 
03825     *rint = cast_spell(op, caster, dir, sp, str);
03826     return NULL;
03827 }
03828 
03829 void *cfapi_object_learn_spell(int *type, ...) {
03830     object *op;
03831     object *sp;
03832     int prayer;
03833     va_list args;
03834 
03835     va_start(args, type);
03836     op = va_arg(args, object *);
03837     sp = va_arg(args, object *);
03838     prayer = va_arg(args, int);
03839     va_end(args);
03840     do_learn_spell(op, sp, prayer);
03841     *type = CFAPI_NONE;
03842     return NULL;
03843 }
03844 
03845 void *cfapi_object_forget_spell(int *type, ...) {
03846     object *op;
03847     object *sp;
03848     va_list args;
03849     char name[MAX_BUF];
03850 
03851     va_start(args, type);
03852     op = va_arg(args, object *);
03853     sp = va_arg(args, object *);
03854     va_end(args);
03855     query_name(sp, name, MAX_BUF);
03856     do_forget_spell(op, name);
03857     *type = CFAPI_NONE;
03858     return NULL;
03859 }
03860 
03868 void *cfapi_object_check_spell(int *type, ...) {
03869     object *op;
03870     char *spellname;
03871     va_list args;
03872     object **robj;
03873 
03874     va_start(args, type);
03875     op = va_arg(args, object *);
03876     spellname = va_arg(args, char *);
03877     robj = va_arg(args, object **);
03878     va_end(args);
03879     *robj = check_spell_known(op, spellname);
03880     *type = CFAPI_POBJECT;
03881     return NULL;
03882 }
03883 
03891 void *cfapi_object_pay_amount(int *type, ...) {
03892     object *op;
03893     uint64 amount;
03894     va_list args;
03895     int *rint;
03896 
03897     va_start(args, type);
03898     op = va_arg(args, object *);
03899     amount = va_arg(args, uint64);
03900     rint = va_arg(args, int *);
03901     va_end(args);
03902 
03903     *rint = pay_for_amount(amount, op);
03904     *type = CFAPI_INT;
03905     return NULL;
03906 }
03914 void *cfapi_object_pay_item(int *type, ...) {
03915     object *op;
03916     object *tobuy;
03917     int *rint;
03918 
03919     va_list args;
03920 
03921     va_start(args, type);
03922     tobuy = va_arg(args, object *);
03923     op = va_arg(args, object *);
03924     rint = va_arg(args, int *);
03925     va_end(args);
03926 
03927     *rint = pay_for_item(tobuy, op);
03928     *type = CFAPI_INT;
03929     return NULL;
03930 }
03931 
03941 void *cfapi_object_transfer(int *type, ...) {
03942     object *op;
03943     object *originator;
03944     int x, y, randompos, ttype, flag;
03945     va_list args;
03946     mapstruct *map;
03947     int *rint;
03948     object **robj;
03949 
03950     va_start(args, type);
03951     op = va_arg(args, object *);
03952     ttype = va_arg(args, int);
03953     switch (ttype) {
03954     case 0:
03955         x = va_arg(args, int);
03956         y = va_arg(args, int);
03957         randompos = va_arg(args, int);
03958         originator = va_arg(args, object *);
03959         rint = va_arg(args, int *);
03960         va_end(args);
03961 
03962         *rint = transfer_ob(op, x, y, randompos, originator);
03963         *type = CFAPI_INT;
03964         return NULL;
03965         break;
03966 
03967     case 1:
03968         map = va_arg(args, mapstruct *);
03969         originator = va_arg(args, object *);
03970         flag = va_arg(args, int);
03971         x = va_arg(args, int);
03972         y = va_arg(args, int);
03973         robj = va_arg(args, object **);
03974         va_end(args);
03975         if (x < 0 || y < 0) {
03976             x = map->enter_x;
03977             y = map->enter_y;
03978         }
03979         *robj = insert_ob_in_map_at(op, map, originator, flag, x, y);
03980         *type = CFAPI_POBJECT;
03981         return NULL;
03982         break;
03983 
03984     case 2:
03985         x = va_arg(args, int);
03986         y = va_arg(args, int);
03987         rint = va_arg(args, int *);
03988         va_end(args);
03989 
03990         *rint = move_to(op, x, y);
03991         *type = CFAPI_INT;
03992         return NULL;
03993 
03994     default:
03995         *type = CFAPI_NONE;
03996         return NULL;
03997         break;
03998     }
03999 }
04000 
04004 void *cfapi_object_find_archetype_inside(int *type, ...) {
04005     object *op;
04006     char *str;
04007     va_list args;
04008     object **robj;
04009 
04010     *type = CFAPI_POBJECT;
04011     va_start(args, type);
04012     op = va_arg(args, object *);
04013 
04014     str = va_arg(args, char *);
04015     robj = va_arg(args, object **);
04016     *robj = present_arch_in_ob(try_find_archetype(str), op);
04017     if (*robj == NULL) {
04018         object *tmp;
04019         char name[MAX_BUF];
04020 
04021         /* Search by query_name instead */
04022         for (tmp = op->inv; tmp; tmp = tmp->below) {
04023             query_name(tmp, name, MAX_BUF);
04024             if (!strncmp(name, str, strlen(str)))
04025                 *robj = tmp;
04026             if (!strncmp(tmp->name, str, strlen(str)))
04027                 *robj = tmp;
04028             if (*robj != NULL)
04029                 break;
04030         }
04031     }
04032     va_end(args);
04033 
04034     return NULL;
04035 }
04036 
04044 void *cfapi_object_drop(int *type, ...) {
04045     object *op;
04046     object *author;
04047     va_list args;
04048 
04049     va_start(args, type);
04050     op = va_arg(args, object *);
04051     author = va_arg(args, object *);
04052     va_end(args);
04053     *type = CFAPI_NONE;
04054 
04055     if (QUERY_FLAG(op, FLAG_NO_DROP))
04056         return NULL;
04057     drop(author, op);
04058 
04059     if (author->type == PLAYER) {
04060         author->contr->count = 0;
04061         author->contr->socket.update_look = 1;
04062     }
04063 
04064     return NULL;
04065 }
04066 
04070 void *cfapi_object_change_abil(int *type, ...) {
04071     object *op, *tmp;
04072     int *rint;
04073     va_list args;
04074 
04075     va_start(args, type);
04076     op = va_arg(args, object *);
04077     tmp = va_arg(args, object *);
04078     rint = va_arg(args, int *);
04079     va_end(args);
04080 
04081     *type = CFAPI_INT;
04082     *rint = change_abil(op, tmp);
04083 
04084     return NULL;
04085 }
04086 
04087 void *cfapi_object_say(int *type, ...) {
04088     object *op;
04089     char *msg;
04090     va_list args;
04091     int *rint;
04092 
04093     va_start(args, type);
04094     op = va_arg(args, object *);
04095     msg = va_arg(args, char *);
04096     rint = va_arg(args, int *);
04097     va_end(args);
04098 
04099     if (op->type == PLAYER) {
04100         *rint = command_say(op, msg);
04101     } else {
04102         npc_say(op, msg);
04103         *rint = 0;
04104     }
04105     *type = CFAPI_INT;
04106     return NULL;
04107 }
04108 
04109 /* PLAYER SUBCLASS */
04110 
04118 void *cfapi_player_find(int *type, ...) {
04119     va_list args;
04120     char *sval;
04121     player **rpl;
04122     va_start(args, type);
04123 
04124     sval = va_arg(args, char *);
04125     rpl = va_arg(args, player **);
04126     va_end(args);
04127 
04128     *rpl = find_player_partial_name(sval);
04129 
04130     *type = CFAPI_PPLAYER;
04131     return NULL;
04132 }
04133 
04134 void *cfapi_player_message(int *type, ...) {
04135     va_list args;
04136     int flags;
04137     int pri;
04138     object *pl;
04139     char *buf;
04140 
04141     va_start(args, type);
04142 
04143     flags = va_arg(args, int);
04144     pri = va_arg(args, int);
04145     pl = va_arg(args, object *);
04146     buf = va_arg(args, char *);
04147     va_end(args);
04148 
04149     draw_ext_info(flags, pri, pl, MSG_TYPE_MISC, MSG_SUBTYPE_NONE,
04150                   buf, buf);
04151     *type = CFAPI_NONE;
04152     return NULL;
04153 }
04154 
04162 void *cfapi_object_change_exp(int *type, ...) {
04163     va_list(args);
04164     int flag;
04165     object *ob;
04166     const char *skill;
04167     sint64 exp;
04168 
04169     va_start(args, type);
04170     ob = va_arg(args, object *);
04171     exp = va_arg(args, sint64);
04172     skill = va_arg(args, const char *);
04173     flag = va_arg(args, int);
04174     va_end(args);
04175 
04176     *type = CFAPI_NONE;
04177     change_exp(ob, exp, skill, flag);
04178     return NULL;
04179 }
04180 
04188 void *cfapi_player_can_pay(int *type, ...) {
04189     va_list args;
04190     object *pl;
04191     int *rint;
04192 
04193     va_start(args, type);
04194     pl = va_arg(args, object *);
04195     rint = va_arg(args, int *);
04196     va_end(args);
04197 
04198     *rint = can_pay(pl);
04199     *type = CFAPI_INT;
04200     return NULL;
04201 }
04202 
04210 void *cfapi_object_teleport(int *type, ...) {
04211     mapstruct *map;
04212     int x, y;
04213     object *who;
04214     int *res;
04215     va_list args;
04216 
04217     va_start(args, type);
04218     who = va_arg(args, object *);
04219     map = va_arg(args, mapstruct *);
04220     x = va_arg(args, int);
04221     y = va_arg(args, int);
04222     res = va_arg(args, int *);
04223     *type = CFAPI_INT;
04224 
04225     if (!out_of_map(map, x, y)) {
04226         int k;
04227         k = find_first_free_spot(who, map, x, y);
04228         if (k == -1) {
04229             *res = 1;
04230             return NULL;
04231         }
04232 
04233         if (!QUERY_FLAG(who, FLAG_REMOVED)) {
04234             remove_ob(who);
04235         }
04236 
04237         insert_ob_in_map_at(who, map, NULL, 0, x, y);
04238         if (who->type == PLAYER)
04239             map_newmap_cmd(&who->contr->socket);
04240         *res = 0;
04241     }
04242 
04243     return NULL;
04244 }
04245 
04246 void *cfapi_object_pickup(int *type, ...) {
04247     object *who;
04248     object *what;
04249     va_list args;
04250 
04251     va_start(args, type);
04252     who = va_arg(args, object *);
04253     what = va_arg(args, object *);
04254     va_end(args);
04255 
04256     pick_up(who, what);
04257     *type = CFAPI_NONE;
04258     return NULL;
04259 }
04260 
04261 /* Archetype-related functions */
04262 void *cfapi_archetype_get_property(int *type, ...) {
04263     int prop;
04264     archetype *arch;
04265     va_list args;
04266     sstring *rsstring;
04267     archetype **rarch;
04268     object **robject;
04269 
04270     va_start(args, type);
04271     arch = va_arg(args, archetype *);
04272     prop = va_arg(args, int);
04273     switch (prop) {
04274     case CFAPI_ARCH_PROP_NAME:
04275         *type = CFAPI_SSTRING;
04276         rsstring = va_arg(args, sstring *);
04277         *rsstring = arch->name;
04278         break;
04279 
04280     case CFAPI_ARCH_PROP_NEXT:
04281         *type = CFAPI_PARCH;
04282         rarch = va_arg(args, archetype **);
04283         *rarch = arch ? arch->next : first_archetype;
04284         break;
04285 
04286     case CFAPI_ARCH_PROP_HEAD:
04287         *type = CFAPI_PARCH;
04288         rarch = va_arg(args, archetype **);
04289         *rarch = arch->head;
04290         break;
04291 
04292     case CFAPI_ARCH_PROP_MORE:
04293         *type = CFAPI_PARCH;
04294         rarch = va_arg(args, archetype **);
04295         *rarch = arch->more;
04296         break;
04297 
04298     case CFAPI_ARCH_PROP_CLONE:
04299         *type = CFAPI_POBJECT;
04300         robject = va_arg(args, object **);
04301         *robject = &arch->clone;
04302         break;
04303 
04304     default:
04305         *type = CFAPI_NONE;
04306         break;
04307     }
04308     va_end(args);
04309     return NULL;
04310 }
04311 
04320 void *cfapi_party_get_property(int *type, ...) {
04321     partylist *party;
04322     int prop;
04323     va_list args;
04324     object *obarg;
04325     sstring *rsstring;
04326     player **rplayer;
04327     partylist **rparty;
04328 
04329     va_start(args, type);
04330     party = va_arg(args, partylist *);
04331     prop = va_arg(args, int);
04332     switch (prop) {
04333     case CFAPI_PARTY_PROP_NAME:
04334         rsstring = va_arg(args, sstring *);
04335         *rsstring = party->partyname;
04336         *type = CFAPI_SSTRING;
04337         break;
04338 
04339     case CFAPI_PARTY_PROP_NEXT:
04340         rparty = va_arg(args, partylist **);
04341         *rparty = (party ? party->next : get_firstparty());
04342         *type = CFAPI_PPARTY;
04343         break;
04344 
04345     case CFAPI_PARTY_PROP_PASSWORD:
04346         rsstring = va_arg(args, sstring *);
04347         *rsstring = party->passwd;
04348         *type = CFAPI_SSTRING;
04349         break;
04350 
04351     case CFAPI_PARTY_PROP_PLAYER:
04352         *type = CFAPI_PPLAYER;
04353         obarg = va_arg(args, object *);
04354         rplayer = va_arg(args, player **);
04355         *rplayer = (obarg ? obarg->contr : first_player);
04356         for (; *rplayer != NULL; (*rplayer) = (*rplayer)->next)
04357             if ((*rplayer)->ob->contr->party == party) {
04358                 break;
04359             }
04360         break;
04361 
04362     default:
04363         *type = CFAPI_NONE;
04364         break;
04365     }
04366     va_end(args);
04367     return NULL;
04368 }
04369 
04378 void *cfapi_region_get_property(int *type, ...) {
04379     region *reg;
04380     int prop;
04381     va_list args;
04383     sstring *rsstring;
04384     region **rregion;
04385 
04386     va_start(args, type);
04387     reg = va_arg(args, region *);
04388     prop = va_arg(args, int);
04389     switch (prop) {
04390     case CFAPI_REGION_PROP_NAME:
04391         rsstring = va_arg(args, sstring *);
04392         *rsstring = reg->name;
04393         *type = CFAPI_SSTRING;
04394         break;
04395 
04396     case CFAPI_REGION_PROP_NEXT:
04397         rregion = va_arg(args, region **);
04398         *rregion = (reg ? reg->next : first_region);
04399         *type = CFAPI_PREGION;
04400         break;
04401 
04402     case CFAPI_REGION_PROP_PARENT:
04403         rregion = va_arg(args, region **);
04404         *rregion = reg->parent;
04405         *type = CFAPI_PREGION;
04406         break;
04407 
04408     case CFAPI_REGION_PROP_LONGNAME:
04409         rsstring = va_arg(args, sstring *);
04410         *rsstring = reg->longname;
04411         *type = CFAPI_SSTRING;
04412         break;
04413 
04414     case CFAPI_REGION_PROP_MESSAGE:
04415         rsstring = va_arg(args, sstring *);
04416         *rsstring = reg->msg;
04417         *type = CFAPI_SSTRING;
04418         break;
04419 
04420     default:
04421         *type = CFAPI_NONE;
04422         break;
04423     }
04424     va_end(args);
04425     return NULL;
04426 }
04427 
04439 void *cfapi_friendlylist_get_next(int *type, ...) {
04440     object *ob;
04441     va_list args;
04442     objectlink *link;
04443     object **robject;
04444 
04445     va_start(args, type);
04446     ob = va_arg(args, object *);
04447     robject = va_arg(args, object **);
04448     va_end(args);
04449 
04450     *type = CFAPI_POBJECT;
04451     *robject = NULL;
04452 
04453     if (ob) {
04454         for (link = first_friendly_object; link; link = link->next) {
04455             if (ob == link->ob) {
04456                 if (link->next) {
04457                     *robject = link->next->ob;
04458                     return NULL;
04459                 } else {
04460                     return NULL;
04461                 }
04462             }
04463         }
04464         return NULL;
04465     }
04466 
04467     if (first_friendly_object)
04468         *robject = first_friendly_object->ob;
04469 
04470     return NULL;
04471 }
04472 
04473 /*
04474  * Random-map related stuff.
04475  */
04476 
04485 void *cfapi_set_random_map_variable(int *type, ...) {
04486     va_list args;
04487     RMParms *rp;
04488     const char *buf;
04489     int *ret;
04490 
04491     va_start(args, type);
04492     rp = va_arg(args, RMParms *);
04493     buf = va_arg(args, const char *);
04494     ret = va_arg(args, int *);
04495     va_end(args);
04496 
04497     *ret = set_random_map_variable(rp, buf);
04498     *type = CFAPI_INT;
04499 
04500     return NULL;
04501 }
04502 
04511 void *cfapi_generate_random_map(int *type, ...) {
04512     va_list args;
04513     const char *name;
04514     RMParms *rp;
04515     char **use_layout;
04516     mapstruct **ret;
04517 
04518     va_start(args, type);
04519     name = va_arg(args, const char *);
04520     rp = va_arg(args, RMParms *);
04521     use_layout = va_arg(args, char **);
04522     ret = va_arg(args, mapstruct **);
04523     va_end(args);
04524 
04525     *ret = generate_random_map(name, rp, use_layout);
04526 
04527     return NULL;
04528 }
04529 
04530 void *cfapi_object_user_event(int *type, ...) {
04531     object *op;
04532     object *activator;
04533     object *third;
04534     const char *message;
04535     int fix;
04536     int *ret;
04537     va_list args;
04538 
04539     va_start(args, type);
04540     op = va_arg(args, object *);
04541     activator = va_arg(args, object *);
04542     third = va_arg(args, object *);
04543     message = va_arg(args, const char *);
04544     fix = va_arg(args, int);
04545     ret = va_arg(args, int *);
04546     va_end(args);
04547 
04548     *ret = user_event(op, activator, third, message, fix);
04549     *type = CFAPI_INT;
04550 
04551     return NULL;
04552 }
04553 
04554 /*****************************************************************************/
04555 /* NEW PLUGIN STUFF ENDS HERE                                                */
04556 /*****************************************************************************/
04557 
04558 
04559 /*****************************************************************************/
04560 /* Tries to find if a given command is handled by a plugin.                  */
04561 /* Note that find_plugin_command is called *before *the internal commands are*/
04562 /* checked, meaning that you can "overwrite" them.                           */
04563 /*****************************************************************************/
04568 command_array_struct *find_plugin_command(char *cmd, object *op) {
04569     int i;
04570     crossfire_plugin *cp;
04571     static command_array_struct rtn_cmd;
04572 
04573     if (plugins_list == NULL)
04574         return NULL;
04575 
04576     for (cp = plugins_list; cp != NULL; cp = cp->next) {
04577         if (cp->propfunc(&i, "command?", cmd, &rtn_cmd) != NULL)
04578             return &rtn_cmd;
04579     }
04580     return NULL;
04581 }
04582 
04583 /*****************************************************************************/
04584 /* Plugins initialization. Browses the plugins directory and call            */
04585 /* initOnePlugin for each file found.                                        */
04586 /* Returns 0 if at least one plugin was successfully loaded, -1 if not       */
04587 /*****************************************************************************/
04588 int initPlugins(void) {
04589     struct dirent *currentfile;
04590     DIR *plugdir;
04591     size_t l;
04592     char buf[MAX_BUF];
04593     int result;
04594 
04595     LOG(llevInfo, "Initializing plugins\n");
04596     snprintf(buf, sizeof(buf), "%s/plugins/", LIBDIR);
04597     LOG(llevInfo, "Plugins directory is %s\n", buf);
04598 
04599     plugdir = opendir(buf);
04600     if (plugdir == NULL)
04601         return -1;
04602 
04603     result = -1;
04604     while ((currentfile = readdir(plugdir)) != NULL) {
04605         l = strlen(currentfile->d_name);
04606         if (l > strlen(PLUGIN_SUFFIX)) {
04607             if (strcmp(currentfile->d_name+l-strlen(PLUGIN_SUFFIX), PLUGIN_SUFFIX) == 0) {
04608                 snprintf(buf, sizeof(buf), "%s/plugins/%s", LIBDIR, currentfile->d_name);
04609                 LOG(llevInfo, " -> Loading plugin : %s\n", currentfile->d_name);
04610                 if (plugins_init_plugin(buf) == 0)
04611                     result = 0;
04612             }
04613         }
04614     }
04615 
04616     closedir(plugdir);
04617     return result;
04618 }
04619 
04623 void cleanupPlugins(void) {
04624     crossfire_plugin *cp;
04625 
04626     if (!plugins_list)
04627         return;
04628 
04629     for (cp = plugins_list; cp != NULL; ) {
04630         crossfire_plugin *next = cp->next;
04631         if (cp->closefunc)
04632             cp->closefunc();
04633         /* Don't actually unload plugins, it makes backtraces for memory
04634          * debugging (printed at exit) messed up. And it doesn't matter if we
04635          * don't free it here. The OS will do it for us.
04636          */
04637         /* plugins_dlclose(cp->libptr); */
04638         free(cp);
04639         plugin_number--;
04640         cp = next;
04641     }
04642     plugins_list = NULL;
04643 }