ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/plugins.C
Revision: 1.1
Committed: Sun Aug 13 17:16:04 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_plugins_c =
3     * "$Id$";
4     */
5    
6     /*****************************************************************************/
7     /* CrossFire, A Multiplayer game for X-windows */
8     /* */
9     /* Copyright (C) 2000 Mark Wedel */
10     /* Copyright (C) 1992 Frank Tore Johansen */
11     /* */
12     /* This program is free software; you can redistribute it and/or modify */
13     /* it under the terms of the GNU General Public License as published by */
14     /* the Free Software Foundation; either version 2 of the License, or */
15     /* (at your option) any later version. */
16     /* */
17     /* This program is distributed in the hope that it will be useful, */
18     /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19     /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20     /* GNU General Public License for more details. */
21     /* */
22     /* You should have received a copy of the GNU General Public License */
23     /* along with this program; if not, write to the Free Software */
24     /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
25     /* */
26     /*****************************************************************************/
27     /* This is the server-side plugin management part. */
28     /*****************************************************************************/
29     /* Original code by Yann Chachkoff (yann.chachkoff@mailandnews.com). */
30     /* Special thanks to: */
31     /* David Delbecq (david.delbecq@mailandnews.com); */
32     /* Joris Bontje (jbontje@suespammers.org); */
33     /* Philip Currlin (?); */
34     /*****************************************************************************/
35    
36     /*****************************************************************************/
37     /* First, the headers. We only include plugin.h, because all other includes */
38     /* are done into it, and plugproto.h (which is used only by this file). */
39     /*****************************************************************************/
40     #include <plugin.h>
41    
42     #ifndef __CEXTRACT__
43     #include <sproto.h>
44     #endif
45    
46     #define NR_OF_HOOKS 74
47    
48     static const hook_entry plug_hooks[NR_OF_HOOKS] =
49     {
50     {cfapi_system_add_string, 0, "cfapi_system_add_string"},
51     {cfapi_system_register_global_event, 1, "cfapi_system_register_global_event"},
52     {cfapi_system_remove_string, 2, "cfapi_system_remove_string"},
53     {cfapi_system_unregister_global_event, 3, "cfapi_system_unregister_global_event"},
54     {cfapi_system_check_path, 4, "cfapi_system_check_path"},
55     {cfapi_system_re_cmp, 5, "cfapi_system_re_cmp"},
56     {cfapi_system_strdup_local, 6, "cfapi_system_strdup_local"},
57     {cfapi_system_directory, 7, "cfapi_system_directory"},
58     {cfapi_system_find_animation, 8, "cfapi_system_find_animation"},
59     {cfapi_object_clean_object, 9, "cfapi_object_clean_object"},
60     {cfapi_object_on_same_map, 10, "cfapi_object_on_same_map"},
61     {cfapi_object_get_key, 11, "cfapi_object_get_key"},
62     {cfapi_object_set_key, 12, "cfapi_object_set_key"},
63     {cfapi_object_get_property, 13, "cfapi_object_get_property"},
64     {cfapi_object_set_property, 14,"cfapi_object_set_property"},
65     {cfapi_object_apply, 15, "cfapi_object_apply"},
66     {cfapi_object_identify, 16, "cfapi_object_identify"},
67     {cfapi_object_describe, 17, "cfapi_object_describe"},
68     {cfapi_object_drain, 18, "cfapi_object_drain"},
69     {cfapi_object_fix, 19, "cfapi_object_fix"},
70     {cfapi_object_give_skill, 20, "cfapi_object_give_skill"},
71     {cfapi_object_transmute, 21, "cfapi_object_transmute"},
72     {cfapi_object_remove, 22, "cfapi_object_remove"},
73     {cfapi_object_delete, 23, "cfapi_object_delete"},
74     {cfapi_object_clone, 24, "cfapi_object_clone"},
75     {cfapi_object_find, 25, "cfapi_object_find"},
76     {cfapi_object_create, 26, "cfapi_object_create"},
77     {cfapi_object_insert, 27, "cfapi_object_insert"},
78     {cfapi_object_split, 28, "cfapi_object_split"},
79     {cfapi_object_merge, 29, "cfapi_object_merge"},
80     {cfapi_object_distance, 30, "cfapi_object_distance"},
81     {cfapi_object_update, 31, "cfapi_object_update"},
82     {cfapi_object_clear, 32, "cfapi_object_clear"},
83     {cfapi_object_reset, 33, "cfapi_object_reset"},
84     {cfapi_object_check_inventory, 34, "cfapi_object_check_inventory"},
85     {cfapi_object_spring_trap, 35, "cfapi_object_spring_trap"},
86     {cfapi_object_check_trigger, 36, "cfapi_object_check_trigger"},
87     {cfapi_object_query_cost, 37, "cfapi_object_query_cost"},
88     {cfapi_object_query_money, 38, "cfapi_object_query_money"},
89     {cfapi_object_cast, 39, "cfapi_object_cast"},
90     {cfapi_object_learn_spell, 40, "cfapi_object_learn_spell"},
91     {cfapi_object_forget_spell, 41, "cfapi_object_forget_spell"},
92     {cfapi_object_check_spell, 42, "cfapi_object_check_spell"},
93     {cfapi_object_pay_amount, 43, "cfapi_object_pay_amount"},
94     {cfapi_object_pay_item, 44, "cfapi_object_pay_item"},
95     {cfapi_object_transfer, 45, "cfapi_object_transfer"},
96     {cfapi_object_drop, 46, "cfapi_object_drop"},
97     {cfapi_object_take, 47, "cfapi_object_take"},
98     {cfapi_object_find_archetype_inside, 48, "cfapi_object_find_archetype_inside"},
99     {cfapi_object_say, 49, "cfapi_object_say"},
100     {cfapi_map_get_map, 50, "cfapi_map_get_map"},
101     {cfapi_map_has_been_loaded, 51, "cfapi_map_has_been_loaded"},
102     {cfapi_map_create_path, 52, "cfapi_map_create_path"},
103     {cfapi_map_get_map_property, 53, "cfapi_map_get_property"},
104     {cfapi_map_set_map_property, 54, "cfapi_map_set_property"},
105     {cfapi_map_out_of_map, 55, "cfapi_map_out_of_map"},
106     {cfapi_map_update_position, 56, "cfapi_map_update_position"},
107     {cfapi_map_delete_map, 57, "cfapi_map_delete_map"},
108     {cfapi_map_message, 58, "cfapi_map_message"},
109     {cfapi_map_get_object_at, 59, "cfapi_map_get_object_at"},
110     {cfapi_map_get_flags, 60, "cfapi_map_get_flags"},
111     {cfapi_map_present_arch_by_name,61, "cfapi_map_present_arch_by_name"},
112     {cfapi_player_find, 62, "cfapi_player_find"},
113     {cfapi_player_message, 63, "cfapi_player_message"},
114     {cfapi_player_send_inventory, 64, "cfapi_player_send_inventory"},
115     {cfapi_object_teleport, 65, "cfapi_object_teleport"},
116     {cfapi_object_speak, 66, "cfapi_object_speak"},
117     {cfapi_object_pickup, 67, "cfapi_object_pickup"},
118     {cfapi_object_move, 68, "cfapi_object_move"},
119     {cfapi_object_apply_below, 69, "cfapi_object_apply_below"},
120     {cfapi_archetype_get_first, 70, "cfapi_archetype_get_first"},
121     {cfapi_archetype_get_property, 71, "cfapi_archetype_get_property"},
122     {cfapi_party_get_property, 72, "cfapi_party_get_property"},
123     {cfapi_region_get_property, 73, "cfapi_region_get_property"},
124     };
125     int plugin_number = 0;
126     crossfire_plugin* plugins_list = NULL;
127    
128     /*****************************************************************************/
129     /* NEW PLUGIN STUFF STARTS HERE */
130     /*****************************************************************************/
131    
132     static void plugin_load_original_map(mapstruct *map)
133     {
134     execute_global_event (EVENT_MAPLOAD, map);
135     }
136    
137     static void plugin_load_temporary_map(mapstruct *map)
138     {
139     execute_global_event (EVENT_MAPIN, map);
140     }
141    
142     static void plugin_clean_temporary_map(mapstruct *map)
143     {
144     execute_global_event (EVENT_MAPCLEAN, map);
145     }
146    
147     static void plugin_object_free(object *ob)
148     {
149     execute_global_event (EVENT_FREE_OB, ob);
150     }
151    
152     #ifdef WIN32
153     static const char *plugins_dlerror(void)
154     {
155     static char buf[256];
156     DWORD err;
157     char* p;
158     err = GetLastError();
159     if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, sizeof(buf), NULL) == 0)
160     snprintf(buf, sizeof(buf), "error %lu", err);
161     p = strchr(buf, '\0');
162     while (p > buf && (p[-1] == '\r' || p[-1] == '\n'))
163     p--;
164     *p = '\0';
165     return buf;
166     }
167     #endif /* WIN32 */
168    
169     /**
170     * Notify clients about a changed object.
171     *
172     * @param op the object that has changed
173     */
174     static void send_changed_object(object *op)
175     {
176     object* tmp;
177     player *pl;
178    
179     if (op->env != NULL) {
180     tmp = is_player_inv(op->env);
181     if (!tmp) {
182     for (pl = first_player; pl; pl = pl->next)
183     if (pl->ob->container == op->env)
184     break;
185     if (pl)
186     tmp = pl->ob;
187     else
188     tmp = NULL;
189     }
190     if (tmp)
191     esrv_send_item(tmp, op);
192     } else {
193     for (tmp = op->above; tmp != NULL; tmp = tmp->above)
194     if (tmp->type == PLAYER)
195     esrv_send_item(tmp, op);
196     }
197     }
198    
199     /**
200     * Notify clients about a removed object.
201     *
202     * @param op the object about to be removed from its environment; it must still
203     * be present in its environment
204     */
205     static void send_removed_object(object *op)
206     {
207     object* tmp;
208     player *pl;
209    
210     if (op->env == NULL) {
211     /* no action necessary: remove_ob() notifies the client */
212     return;
213     }
214    
215     tmp = is_player_inv(op->env);
216     if (!tmp) {
217     for (pl = first_player; pl; pl = pl->next)
218     if (pl->ob->container == op->env)
219     break;
220     if (pl)
221     tmp = pl->ob;
222     else
223     tmp = NULL;
224     }
225     if (tmp)
226     esrv_del_item(tmp->contr, op->count);
227     }
228    
229     int execute_event(object* op, int eventcode, object* activator, object* third, const char* message, int fix)
230     {
231     object *tmp, *next;
232     crossfire_plugin* plugin;
233     int rv = 0;
234     for (tmp = op->inv; tmp != NULL; tmp = next) {
235     next = tmp->below;
236     if (tmp->type == EVENT_CONNECTOR && tmp->subtype == eventcode) {
237     #if 0
238     LOG(llevDebug, "********** EVENT HANDLER **********\n");
239     LOG(llevDebug, " - Who am I :%s\n", op->name);
240     if (activator != NULL)
241     LOG(llevDebug, " - Activator :%s\n", activator->name);
242     if (third != NULL)
243     LOG(llevDebug, " - Other object :%s\n", third->name);
244     LOG(llevDebug, " - Event code :%d\n", tmp->subtype);
245     if (tmp->title != NULL)
246     LOG(llevDebug, " - Event plugin :%s\n", tmp->title);
247     if (tmp->slaying != NULL)
248     LOG(llevDebug, " - Event hook :%s\n", tmp->slaying);
249     if (tmp->name != NULL)
250     LOG(llevDebug, " - Event options :%s\n", tmp->name);
251     #endif
252    
253     if (tmp->title == NULL) {
254     object *env = object_get_env_recursive(tmp);
255     LOG(llevError, "Event object without title at %d/%d in map %s\n", env->x, env->y, env->map->name);
256     send_removed_object(tmp);
257     remove_ob(tmp);
258     free_object(tmp);
259     } else if (tmp->slaying == NULL) {
260     object *env = object_get_env_recursive(tmp);
261     LOG(llevError, "Event object without slaying at %d/%d in map %s\n", env->x, env->y, env->map->name);
262     send_removed_object(tmp);
263     remove_ob(tmp);
264     free_object(tmp);
265     } else {
266     plugin = plugins_find_plugin(tmp->title);
267     if (plugin == NULL) {
268     object *env = object_get_env_recursive(tmp);
269     LOG(llevError, "The requested plugin doesn't exist: %s at %d/%d in map %s\n", tmp->title, env->x, env->y, env->map->name);
270     send_removed_object(tmp);
271     remove_ob(tmp);
272     free_object(tmp);
273     } else {
274     int rvt = 0;
275     int *rv;
276    
277     rv = (int*) plugin->eventfunc(&rvt, op, eventcode, activator, third, message, fix, tmp->slaying, tmp->name, tmp);
278     return *rv;
279     }
280     }
281     }
282     }
283     return rv;
284     }
285    
286     int execute_global_event(int eventcode, ...)
287     {
288     va_list args;
289     object* op;
290     object* op2;
291     object* op3;
292     mapstruct *map;
293     player* pl;
294     char* buf;
295     int i, rt, retval = 0, *tmpretval = NULL, fix;
296     crossfire_plugin* cp;
297     if (plugins_list == NULL)
298     return -1;
299    
300     va_start(args, eventcode);
301    
302     switch (eventcode) {
303    
304     case EVENT_CLOCK:
305     case EVENT_CRASH:
306     case EVENT_TELL:
307     /* no additional arguments */
308     for (cp = plugins_list; cp != NULL; cp = cp->next) {
309     if (cp->gevent[eventcode] != NULL)
310     cp->gevent[eventcode](&rt, eventcode);
311     }
312     break;
313    
314     case EVENT_PLAYER_LOAD:
315     case EVENT_PLAYER_SAVE:
316     /* object, filename */
317     op = va_arg(args, object*);
318     buf = va_arg(args, char*);
319     for (cp = plugins_list; cp != NULL; cp = cp->next) {
320     if (cp->gevent[eventcode] != NULL)
321     cp->gevent[eventcode](&rt, eventcode, op, buf);
322     }
323     break;
324    
325     case EVENT_MAPLOAD:
326     case EVENT_MAPOUT:
327     case EVENT_MAPIN:
328     case EVENT_MAPCLEAN:
329     /* map argument */
330     map = va_arg(args, mapstruct*);
331     for (cp = plugins_list; cp != NULL; cp = cp->next) {
332     if (cp->gevent[eventcode] != NULL)
333     cp->gevent[eventcode](&rt, eventcode, map);
334     }
335     break;
336    
337     case EVENT_REMOVE:
338     case EVENT_MAPENTER:
339     case EVENT_MAPLEAVE:
340     case EVENT_BORN:
341     case EVENT_PLAYER_DEATH:
342     case EVENT_FREE_OB:
343     /* op argument */
344     op = va_arg(args, object*);
345     for (cp = plugins_list; cp != NULL; cp = cp->next) {
346     if (cp->gevent[eventcode] != NULL)
347     cp->gevent[eventcode](&rt, eventcode, op);
348     }
349     break;
350    
351     case EVENT_GKILL:
352     /*GKILL: op, hitter*/
353     op = va_arg(args, object*);
354     op2 = va_arg(args, object*);
355     for (cp = plugins_list; cp != NULL; cp = cp->next) {
356     if (cp->gevent[eventcode] != NULL)
357     cp->gevent[eventcode](&rt, eventcode, op, op2);
358     }
359     break;
360    
361     case EVENT_LOGIN:
362     /*LOGIN: pl, pl->socket.host*/
363     pl = va_arg(args, player*);
364     buf = va_arg(args, char*);
365     for (cp = plugins_list; cp != NULL; cp = cp->next) {
366     if (cp->gevent[eventcode] != NULL)
367     cp->gevent[eventcode](&rt, eventcode, pl, buf);
368     }
369     break;
370    
371     case EVENT_LOGOUT:
372     /*LOGOUT: pl, pl->socket.host*/
373     pl = va_arg(args, player*);
374     buf = va_arg(args, char*);
375     for (cp = plugins_list; cp != NULL; cp = cp->next) {
376     if (cp->gevent[eventcode] != NULL)
377     cp->gevent[eventcode](&rt, eventcode, pl, buf);
378     }
379     break;
380    
381     case EVENT_MAPRESET:
382     /*MAPRESET: map->path*/
383     buf = va_arg(args, char*);
384     for (cp = plugins_list; cp != NULL; cp = cp->next) {
385     if (cp->gevent[eventcode] != NULL)
386     cp->gevent[eventcode](&rt, eventcode, buf);
387     }
388     break;
389    
390     case EVENT_SHOUT:
391     /*SHOUT: op, parms, priority*/
392     op = va_arg(args, object*);
393     buf = va_arg(args, char*);
394     i = va_arg(args, int);
395     for (cp = plugins_list; cp != NULL; cp = cp->next) {
396     if (cp->gevent[eventcode] != NULL)
397     cp->gevent[eventcode](&rt, eventcode, op, buf, i);
398     }
399     break;
400    
401     case EVENT_MUZZLE:
402     /*MUZZLE: op, parms*/
403     op = va_arg(args, object*);
404     buf = va_arg(args, char*);
405     for (cp = plugins_list; cp != NULL; cp = cp->next) {
406     if (cp->gevent[eventcode] != NULL)
407     cp->gevent[eventcode](&rt, eventcode, op, buf);
408     }
409     break;
410    
411     case EVENT_KICK:
412     /*KICK: op, parms*/
413     op = va_arg(args, object*);
414     buf = va_arg(args, char*);
415     for (cp = plugins_list; cp != NULL; cp = cp->next) {
416     if (cp->gevent[eventcode] != NULL)
417     cp->gevent[eventcode](&rt, eventcode, op, buf);
418     }
419     break;
420    
421     case EVENT_FIND_UNARMED_SKILL:
422     op = va_arg(args, object*);
423     for (cp = plugins_list; cp != NULL; cp = cp->next) {
424     if (cp->gevent[eventcode] != NULL)
425     if ((tmpretval = (int*) cp->gevent[eventcode](&rt, eventcode, op)) && *tmpretval > 0) {
426     retval = *tmpretval;
427     }
428     }
429     break;
430    
431     case EVENT_PLAYER_USE_SKILL:
432     case EVENT_MONSTER_USE_SKILL:
433     op = va_arg(args, object*);
434     op2 = va_arg(args, object*);
435     op3 = va_arg(args, object*);
436     fix = va_arg(args, int);
437     buf = va_arg(args, char*);
438     for (cp = plugins_list; cp != NULL; cp = cp->next) {
439     if (cp->gevent[eventcode] != NULL)
440     if ((tmpretval = (int*) cp->gevent[eventcode](&rt, eventcode, op, op2, op3, fix, buf)) && *tmpretval != 0) {
441     retval = *tmpretval;
442     }
443     }
444     break;
445    
446     case EVENT_CAST_SPELL:
447     op = va_arg(args, object*);
448     op2 = va_arg(args, object*);
449     op3 = va_arg(args, object*);
450     fix = va_arg(args, int);
451     buf = va_arg(args, char*);
452     for (cp = plugins_list; cp != NULL; cp = cp->next) {
453     if (cp->gevent[eventcode] != NULL)
454     if ((tmpretval = (int*) cp->gevent[eventcode](&rt, eventcode, op, op2, op3, fix, buf)) && *tmpretval != 0) {
455     retval = *tmpretval;
456     break; /* The first who did something wins! */
457     }
458     }
459     break;
460    
461     case EVENT_EXTCMD:
462     /*KICK: op, parms*/
463     pl = va_arg (args, player *);
464     buf = va_arg (args, char *);
465     i = va_arg (args, int);
466     for (cp = plugins_list; cp != NULL; cp = cp->next) {
467     if (cp->gevent[eventcode] != NULL)
468     cp->gevent[eventcode](&rt, eventcode, pl, buf, i, buf);
469     }
470     break;
471     }
472     va_end(args);
473    
474     return retval;
475     }
476    
477     int plugins_init_plugin(const char* libfile)
478     {
479     LIBPTRTYPE ptr;
480     f_plug_init initfunc;
481     f_plug_api propfunc;
482     f_plug_api eventfunc;
483     f_plug_postinit postfunc;
484     f_plug_postinit closefunc;
485     int i;
486     crossfire_plugin* cp;
487     crossfire_plugin* ccp;
488    
489     load_original_map_callback = plugin_load_original_map;
490     load_temporary_map_callback = plugin_load_temporary_map;
491     clean_temporary_map_callback = plugin_clean_temporary_map;
492     object_free_callback = plugin_object_free;
493    
494     /* Open the plugin lib and load the required functions */
495     ptr = plugins_dlopen(libfile);
496     if (ptr == NULL) {
497     LOG(llevError, "Error trying to load %s: %s\n", libfile, plugins_dlerror());
498     return -1;
499     }
500     initfunc = (f_plug_init)plugins_dlsym(ptr, "initPlugin");
501     if (initfunc == NULL) {
502     LOG(llevError, "Plugin error while requesting %s.initPlugin: %s\n",
503     libfile, plugins_dlerror());
504     plugins_dlclose(ptr);
505     return -1;
506     }
507     propfunc = (f_plug_api)plugins_dlsym(ptr, "getPluginProperty");
508     if (propfunc == NULL) {
509     LOG(llevError, "Plugin error while requesting %s.getPluginProperty: %s\n",
510     libfile, plugins_dlerror());
511     plugins_dlclose(ptr);
512     return -1;
513     }
514     eventfunc = (f_plug_api)plugins_dlsym(ptr, "eventListener");
515     if (eventfunc == NULL) {
516     LOG(llevError, "Plugin error while requesting %s.eventListener: %s\n",
517     libfile, plugins_dlerror());
518     plugins_dlclose(ptr);
519     return -1;
520     }
521     postfunc = (f_plug_postinit)plugins_dlsym(ptr, "postInitPlugin");
522     if (postfunc == NULL) {
523     LOG(llevError, "Plugin error while requesting %s.postInitPlugin: %s\n",
524     libfile, plugins_dlerror());
525     plugins_dlclose(ptr);
526     return -1;
527     }
528     closefunc = (f_plug_postinit)plugins_dlsym(ptr, "closePlugin");
529     if (postfunc == NULL) {
530     LOG(llevError, "Plugin error while requesting %s.closePlugin: %s\n",
531     libfile, plugins_dlerror());
532     plugins_dlclose(ptr);
533     return -1;
534     }
535     if (postfunc == NULL) {
536     LOG(llevError, "Plugin error while requesting %s.closePlugin: %s\n",
537     libfile, plugins_dlerror());
538     plugins_dlclose(ptr);
539     return -1;
540     }
541     i = initfunc("2.0", cfapi_get_hooks);
542     cp = (crossfire_plugin*) malloc(sizeof(crossfire_plugin));
543     for (i = 0; i < NR_EVENTS; i++)
544     cp->gevent[i] = NULL;
545     cp->eventfunc = eventfunc;
546     cp->propfunc = propfunc;
547     cp->closefunc = closefunc;
548     cp->libptr = ptr;
549     strcpy(cp->id, (const char*) propfunc(&i, "Identification"));
550     strcpy(cp->fullname, (const char*) propfunc(&i, "FullName"));
551     cp->next = NULL;
552     cp->prev = NULL;
553     if (plugins_list == NULL) {
554     plugins_list = cp;
555     } else {
556     for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
557     ;
558     ccp->next = cp;
559     cp->prev = ccp;
560     }
561     postfunc();
562     plugin_number++;
563     return 0;
564     }
565    
566     void* cfapi_get_hooks(int* type, ...)
567     {
568     va_list args;
569     int request_type;
570     char* buf;
571     int fid;
572     f_plug_api rv;
573     int i;
574    
575     va_start(args, type);
576     request_type = va_arg(args, int);
577     if (request_type == 0) { /* By nr */
578     fid = va_arg(args, int);
579     if (fid < 0 || fid >= NR_OF_HOOKS) {
580     rv = NULL;
581     *type = CFAPI_NONE;
582     } else {
583     rv = plug_hooks[fid].func;
584     *type = CFAPI_FUNC;
585     }
586     } else { /* by name */
587     buf = va_arg(args, char*);
588     rv = NULL;
589     for (i = 0; i < NR_OF_HOOKS; i++) {
590     if (!strcmp(buf, plug_hooks[i].fname)) {
591     rv = plug_hooks[i].func;
592     *type = CFAPI_FUNC;
593     break;
594     }
595     }
596     if (rv == NULL) {
597     *type = CFAPI_NONE;
598     }
599     }
600     va_end(args);
601     return (void*)rv;
602     }
603    
604     int plugins_remove_plugin(const char* id)
605     {
606     crossfire_plugin* cp;
607    
608     if (plugins_list == NULL)
609     return -1;
610    
611     for (cp = plugins_list; cp != NULL; cp = cp->next) {
612     if (!strcmp(id, cp->id)) {
613     crossfire_plugin* n;
614     crossfire_plugin* p;
615     n = cp->next;
616     p = cp->prev;
617     plugins_dlclose(cp->libptr);
618     if (n != NULL) {
619     if (p != NULL) {
620     n->prev = p;
621     p->next = n;
622     } else {
623     n->prev = NULL;
624     plugins_list = n;
625     }
626     } else {
627     if (p != NULL)
628     p->next = NULL;
629     else
630     plugins_list = NULL;
631     }
632     free(cp);
633     plugin_number --;
634     return 0;
635     }
636     }
637     return -1;
638     }
639    
640     crossfire_plugin* plugins_find_plugin(const char* id)
641     {
642     crossfire_plugin* cp;
643    
644     if (plugins_list == NULL)
645     return NULL;
646    
647     for (cp = plugins_list; cp != NULL; cp = cp->next) {
648     if (!strcmp(id, cp->id)) {
649     return cp;
650     }
651     }
652     return NULL;
653     }
654    
655     /*****************************************************************************/
656     /* Displays a list of loaded plugins (keystrings and description) in the */
657     /* game log window. */
658     /*****************************************************************************/
659     void plugins_display_list(object *op)
660     {
661     crossfire_plugin* cp;
662    
663     new_draw_info(NDI_UNIQUE, 0, op, "List of loaded plugins:");
664     new_draw_info(NDI_UNIQUE, 0, op, "-----------------------");
665    
666     if (plugins_list == NULL)
667     return;
668    
669     for (cp = plugins_list; cp != NULL; cp = cp->next) {
670     new_draw_info_format(NDI_UNIQUE, 0, op, "%s, %s", cp->id, cp->fullname);
671     }
672     }
673    
674     /* SYSTEM-RELATED HOOKS */
675    
676     void* cfapi_system_find_animation(int *type, ...)
677     {
678     va_list args;
679     static int rv;
680     char* anim;
681     va_start(args, type);
682     anim = va_arg(args, char*);
683     va_end(args);
684    
685     rv = find_animation(anim);
686     *type = CFAPI_INT;
687     return &rv;
688     }
689    
690     void* cfapi_system_strdup_local(int *type, ...)
691     {
692     va_list args;
693     char* txt;
694     va_start(args, type);
695     txt = va_arg(args, char*);
696     va_end(args);
697     *type = CFAPI_STRING;
698     return strdup_local(txt);
699     }
700    
701     void* cfapi_system_register_global_event(int *type, ...)
702     {
703     va_list args;
704     int eventcode;
705     char* pname;
706     f_plug_api hook;
707     crossfire_plugin* cp;
708    
709     va_start(args, type);
710     eventcode = va_arg(args, int);
711     pname = va_arg(args, char*);
712     hook = va_arg(args, f_plug_api);
713    
714     va_end(args);
715     cp = plugins_find_plugin(pname);
716     cp->gevent[eventcode] = hook;
717     return NULL;
718     }
719    
720     void* cfapi_system_unregister_global_event(int *type, ...)
721     {
722     va_list args;
723     int eventcode;
724     char* pname;
725     crossfire_plugin* cp;
726    
727     va_start(args, type);
728     eventcode = va_arg(args, int);
729     pname = va_arg(args, char*);
730    
731     cp = plugins_find_plugin(pname);
732     cp->gevent[eventcode] = NULL;
733    
734     va_end(args);
735     return NULL;
736     }
737    
738     void* cfapi_system_add_string(int *type, ...)
739     {
740     va_list args;
741     const char* str;
742     char* rv;
743    
744     va_start(args, type);
745     str = va_arg(args, char*);
746     va_end(args);
747    
748     rv = (char*)add_string(str);
749     *type = CFAPI_STRING;
750     return rv;
751     }
752    
753     void* cfapi_system_remove_string(int *type, ...)
754     {
755     va_list args;
756     char* str;
757    
758     va_start(args, type);
759     str = va_arg(args, char*);
760     va_end(args);
761    
762     free_string(str);
763     *type = CFAPI_NONE;
764     return NULL;
765     }
766     void* cfapi_system_check_path(int* type, ...)
767     {
768     va_list args;
769     static int rv;
770     char* name;
771     int prepend_dir;
772    
773     va_start(args, type);
774    
775     name = va_arg(args, char*);
776     prepend_dir = va_arg(args, int);
777    
778     rv = check_path(name, prepend_dir);
779    
780     va_end(args);
781     *type = CFAPI_INT;
782     return &rv;
783     }
784    
785     void* cfapi_system_re_cmp(int* type, ...)
786     {
787     va_list args;
788     char* rv;
789     const char* str;
790     const char* regexp;
791    
792     va_start(args, type);
793    
794     str = va_arg(args, char*);
795     regexp = va_arg(args, char*);
796    
797     rv = (char*)re_cmp(str, regexp);
798    
799     va_end(args);
800     *type = CFAPI_STRING;
801     return rv;
802     }
803    
804     void* cfapi_system_directory(int* type, ...)
805     {
806     va_list args;
807     int dirtype;
808    
809     va_start(args, type);
810    
811     dirtype = va_arg(args, int);
812     va_end(args);
813    
814     *type = CFAPI_STRING;
815    
816     switch (dirtype)
817     {
818     case 0:
819     return settings.mapdir;
820     break;
821    
822     case 1:
823     return settings.uniquedir;
824     break;
825    
826     case 2:
827     return settings.tmpdir;
828     break;
829    
830     case 3:
831     return settings.confdir;
832     break;
833    
834     case 4:
835     return settings.localdir;
836     break;
837    
838     case 5:
839     return settings.playerdir;
840     break;
841    
842     case 6:
843     return settings.datadir;
844     break;
845     }
846    
847     *type = CFAPI_NONE;
848     return NULL;
849     }
850    
851    
852     /* MAP RELATED HOOKS */
853    
854     void* cfapi_map_get_map(int* type, ...)
855     {
856     va_list args;
857     mapstruct* rv;
858     int ctype;
859     int x, y;
860     sint16 nx, ny;
861     char* name;
862     mapstruct* m;
863    
864     va_start(args, type);
865    
866     ctype = va_arg(args, int);
867    
868     switch (ctype)
869     {
870     case 0:
871     x = va_arg(args, int);
872     y = va_arg(args, int);
873     rv = get_empty_map(x, y);
874     break;
875    
876     case 1:
877     name = va_arg(args, char*);
878     x = va_arg(args, int);
879     rv = ready_map_name(name, x);
880     break;
881    
882     case 2:
883     m = va_arg(args, mapstruct*);
884     nx = va_arg(args, int);
885     ny = va_arg(args, int);
886     rv = get_map_from_coord(m, &nx, &ny);
887     break;
888    
889     case 3:
890     rv = first_map;
891     break;
892    
893     default:
894     *type = CFAPI_NONE;
895     va_end(args);
896     return NULL;
897     break;
898     }
899     va_end(args);
900     *type = CFAPI_PMAP;
901     return rv;
902     }
903     void* cfapi_map_has_been_loaded(int* type, ...)
904     {
905     va_list args;
906     mapstruct* map;
907     char* string;
908    
909     va_start(args, type);
910     string = va_arg(args, char*);
911     map = has_been_loaded(string);
912     va_end(args);
913     *type = CFAPI_PMAP;
914     return map;
915     }
916     void* cfapi_map_create_path(int* type, ...)
917     {
918     va_list args;
919     int ctype;
920     const char* str;
921     char* rv;
922     va_start(args, type);
923    
924     ctype = va_arg(args, int);
925     str = va_arg(args, char*);
926     *type = CFAPI_STRING;
927    
928     switch (ctype)
929     {
930     case 0:
931     rv = (char*)create_pathname(str);
932     break;
933    
934     case 1:
935     rv = (char*)create_overlay_pathname(str);
936     break;
937    
938     /*case 2:
939     rv = create_items_path(str);
940     break;*/
941    
942     default:
943     rv = NULL;
944     *type = CFAPI_NONE;
945     break;
946     }
947     va_end(args);
948     return rv;
949     }
950     void* cfapi_map_get_map_property(int* type, ...)
951     {
952     va_list args;
953     int x, y;
954     sint16 nx, ny;
955     mapstruct* map;
956     mapstruct* newmap;
957     static int rv;
958     int property;
959     char* buf;
960    
961     va_start(args, type);
962    
963     property = va_arg(args, int);
964     switch (property)
965     {
966     case CFAPI_MAP_PROP_FLAGS:
967     map = va_arg(args, mapstruct*);
968     newmap = va_arg(args, mapstruct*);
969     x = va_arg(args, int);
970     y = va_arg(args, int);
971     nx = va_arg(args, int);
972     ny = va_arg(args, int);
973     rv = get_map_flags(map, &newmap, x, y, &nx, &ny);
974     va_end(args);
975     *type = CFAPI_INT;
976     return &rv;
977     break;
978    
979     case CFAPI_MAP_PROP_DIFFICULTY:
980     map = va_arg(args, mapstruct*);
981     rv = calculate_difficulty(map);
982     va_end(args);
983     *type = CFAPI_INT;
984     return &rv;
985     break;
986    
987     case CFAPI_MAP_PROP_PATH:
988     map = va_arg(args, mapstruct*);
989     buf = map->path;
990     *type = CFAPI_STRING;
991     va_end(args);
992     return buf;
993     break;
994    
995     case CFAPI_MAP_PROP_TMPNAME:
996     map = va_arg(args, mapstruct*);
997     buf = map->tmpname;
998     *type = CFAPI_STRING;
999     va_end(args);
1000     return buf;
1001     break;
1002    
1003     case CFAPI_MAP_PROP_NAME:
1004     map = va_arg(args, mapstruct*);
1005     buf = map->name;
1006     *type = CFAPI_STRING;
1007     va_end(args);
1008     return buf;
1009     break;
1010    
1011     case CFAPI_MAP_PROP_RESET_TIME:
1012     map = va_arg(args, mapstruct*);
1013     rv = map->reset_time;
1014     *type = CFAPI_INT;
1015     va_end(args);
1016     return &rv;
1017     break;
1018    
1019     case CFAPI_MAP_PROP_RESET_TIMEOUT:
1020     map = va_arg(args, mapstruct*);
1021     rv = map->reset_timeout;
1022     *type = CFAPI_INT;
1023     va_end(args);
1024     return &rv;
1025     break;
1026    
1027     case CFAPI_MAP_PROP_PLAYERS:
1028     map = va_arg(args, mapstruct*);
1029     rv = map->players;
1030     *type = CFAPI_INT;
1031     va_end(args);
1032     return &rv;
1033     break;
1034    
1035     case CFAPI_MAP_PROP_DARKNESS:
1036     map = va_arg(args, mapstruct*);
1037     rv = map->darkness;
1038     *type = CFAPI_INT;
1039     va_end(args);
1040     return &rv;
1041     break;
1042    
1043     case CFAPI_MAP_PROP_WIDTH:
1044     map = va_arg(args, mapstruct*);
1045     rv = map->width;
1046     *type = CFAPI_INT;
1047     va_end(args);
1048     return &rv;
1049     break;
1050    
1051     case CFAPI_MAP_PROP_HEIGHT:
1052     map = va_arg(args, mapstruct*);
1053     rv = map->height;
1054     *type = CFAPI_INT;
1055     va_end(args);
1056     return &rv;
1057     break;
1058    
1059     case CFAPI_MAP_PROP_ENTER_X:
1060     map = va_arg(args, mapstruct*);
1061     rv = map->enter_x;
1062     *type = CFAPI_INT;
1063     va_end(args);
1064     return &rv;
1065     break;
1066    
1067     case CFAPI_MAP_PROP_ENTER_Y:
1068     map = va_arg(args, mapstruct*);
1069     rv = map->enter_y;
1070     *type = CFAPI_INT;
1071     va_end(args);
1072     return &rv;
1073     break;
1074    
1075     case CFAPI_MAP_PROP_TEMPERATURE:
1076     map = va_arg(args, mapstruct*);
1077     rv = map->temp;
1078     *type = CFAPI_INT;
1079     va_end(args);
1080     return &rv;
1081     break;
1082    
1083     case CFAPI_MAP_PROP_PRESSURE:
1084     map = va_arg(args, mapstruct*);
1085     rv = map->pressure;
1086     *type = CFAPI_INT;
1087     va_end(args);
1088     return &rv;
1089     break;
1090    
1091     case CFAPI_MAP_PROP_HUMIDITY:
1092     map = va_arg(args, mapstruct*);
1093     rv = map->humid;
1094     *type = CFAPI_INT;
1095     va_end(args);
1096     return &rv;
1097     break;
1098    
1099     case CFAPI_MAP_PROP_WINDSPEED:
1100     map = va_arg(args, mapstruct*);
1101     rv = map->windspeed;
1102     *type = CFAPI_INT;
1103     va_end(args);
1104     return &rv;
1105     break;
1106    
1107     case CFAPI_MAP_PROP_WINDDIR:
1108     map = va_arg(args, mapstruct*);
1109     rv = map->winddir;
1110     *type = CFAPI_INT;
1111     va_end(args);
1112     return &rv;
1113     break;
1114    
1115     case CFAPI_MAP_PROP_SKY:
1116     map = va_arg(args, mapstruct*);
1117     rv = map->sky;
1118     *type = CFAPI_INT;
1119     va_end(args);
1120     return &rv;
1121     break;
1122    
1123     case CFAPI_MAP_PROP_WPARTX:
1124     map = va_arg(args, mapstruct*);
1125     rv = map->wpartx;
1126     *type = CFAPI_INT;
1127     va_end(args);
1128     return &rv;
1129     break;
1130    
1131     case CFAPI_MAP_PROP_WPARTY:
1132     map = va_arg(args, mapstruct*);
1133     rv = map->wparty;
1134     *type = CFAPI_INT;
1135     va_end(args);
1136     return &rv;
1137     break;
1138    
1139     case CFAPI_MAP_PROP_MESSAGE:
1140     map = va_arg(args, mapstruct*);
1141     buf = map->msg;
1142     *type = CFAPI_STRING;
1143     va_end(args);
1144     return buf;
1145     break;
1146    
1147     case CFAPI_MAP_PROP_NEXT:
1148     map = va_arg(args, mapstruct*);
1149     *type = CFAPI_PMAP;
1150     va_end(args);
1151     return map->next;
1152     break;
1153    
1154     case CFAPI_MAP_PROP_REGION:
1155     map = va_arg(args, mapstruct*);
1156     *type = CFAPI_PREGION;
1157     va_end(args);
1158     return get_region_by_map(map);
1159     break;
1160    
1161     default:
1162     *type = CFAPI_NONE;
1163     va_end(args);
1164     return NULL;
1165     break;
1166     }
1167     }
1168    
1169     void* cfapi_map_set_map_property(int* type, ...)
1170     {
1171     va_list args;
1172     static int rv;
1173     mapstruct* map;
1174     int val;
1175     int property;
1176    
1177     va_start(args, type);
1178    
1179     property = va_arg(args, int);
1180    
1181     switch (property)
1182     {
1183     case CFAPI_MAP_PROP_LIGHT:
1184     map = va_arg(args, mapstruct*);
1185     val = va_arg(args, int);
1186     rv = change_map_light(map, val);
1187     *type = CFAPI_INT;
1188     va_end(args);
1189     return &rv;
1190     break;
1191    
1192     case CFAPI_MAP_PROP_RESET_TIME:
1193     map = va_arg(args, mapstruct*);
1194     *type = CFAPI_NONE;
1195     va_end(args);
1196     return NULL;
1197     break;
1198    
1199     default:
1200     *type = CFAPI_NONE;
1201     va_end(args);
1202     return NULL;
1203     break;
1204     }
1205     }
1206     void* cfapi_map_out_of_map(int* type, ...)
1207     {
1208     va_list args;
1209     static int rv;
1210     mapstruct* map;
1211     int x, y;
1212    
1213     va_start(args, type);
1214     map = va_arg(args, mapstruct*);
1215     x = va_arg(args, int);
1216     y = va_arg(args, int);
1217    
1218     rv = out_of_map(map, x, y);
1219     va_end(args);
1220     *type = CFAPI_INT;
1221     return &rv;
1222     }
1223     void* cfapi_map_update_position(int* type, ...)
1224     {
1225     va_list args;
1226     mapstruct* map;
1227     int x, y;
1228    
1229     va_start(args, type);
1230    
1231     map = va_arg(args, mapstruct*);
1232     x = va_arg(args, int);
1233     y = va_arg(args, int);
1234    
1235     update_position(map, x, y);
1236     va_end(args);
1237     *type = CFAPI_NONE;
1238     return NULL;
1239     }
1240     void* cfapi_map_delete_map(int* type, ...)
1241     {
1242     va_list args;
1243     mapstruct* map;
1244     va_start(args, type);
1245    
1246     map = va_arg(args, mapstruct*);
1247    
1248     delete_map(map);
1249    
1250     va_end(args);
1251     *type = CFAPI_NONE;
1252     return NULL;
1253     }
1254     void* cfapi_map_message(int* type, ...)
1255     {
1256     va_list args;
1257     mapstruct* map;
1258     char* string;
1259     int color;
1260    
1261     va_start(args, type);
1262     map = va_arg(args, mapstruct*);
1263     string = va_arg(args, char*);
1264     color = va_arg(args, int);
1265     va_end(args);
1266    
1267     new_info_map(color, map, string);
1268     *type = CFAPI_NONE;
1269     return NULL;
1270     }
1271     void* cfapi_map_get_object_at(int* type, ...)
1272     {
1273     va_list args;
1274     mapstruct* map;
1275     int x, y;
1276     object* rv;
1277    
1278     va_start(args, type);
1279     map = va_arg(args, mapstruct*);
1280     x = va_arg(args, int);
1281     y = va_arg(args, int);
1282     va_end(args);
1283    
1284     rv = get_map_ob(map, x, y);
1285     *type = CFAPI_POBJECT;
1286     return rv;
1287     }
1288     void* cfapi_map_get_flags(int* type, ...)
1289     {
1290     va_list args;
1291     sint16 x, y;
1292     sint16 *nx, *ny;
1293     static mapstruct* map;
1294     mapstruct** newmap;
1295     static int rv;
1296    
1297     va_start(args, type);
1298    
1299     map = va_arg(args, mapstruct*);
1300     newmap = va_arg(args, mapstruct**);
1301     x = va_arg(args, int);
1302     y = va_arg(args, int);
1303     nx = va_arg(args, sint16*);
1304     ny = va_arg(args, sint16*);
1305     va_end(args);
1306    
1307     rv = get_map_flags(map, newmap, x, y, nx, ny);
1308    
1309     *type = CFAPI_INT;
1310     return &rv;
1311     }
1312     void* cfapi_map_present_arch_by_name(int* type, ...)
1313     {
1314     va_list args;
1315     object* rv;
1316     int x, y;
1317     mapstruct* map;
1318     char* msg;
1319    
1320     va_start(args, type);
1321    
1322     msg = va_arg(args, char*);
1323     map = va_arg(args, mapstruct*);
1324     x = va_arg(args, int);
1325     y = va_arg(args, int);
1326    
1327     va_end(args);
1328    
1329     rv = present_arch(find_archetype(msg), map, x, y);
1330     *type = CFAPI_POBJECT;
1331     return rv;
1332     }
1333    
1334     /* OBJECT-RELATED HOOKS */
1335    
1336     void* cfapi_object_move(int* type, ...)
1337     {
1338     va_list args;
1339     int kind;
1340     object* op;
1341     object* activator;
1342     player* pl;
1343     int direction;
1344     static int rv=0;
1345    
1346     va_start(args, type);
1347     kind = va_arg(args, int);
1348     switch (kind)
1349     {
1350     case 0:
1351     op = va_arg(args, object*);
1352     direction = va_arg(args, int);
1353     activator = va_arg(args, object*);
1354     va_end(args);
1355     rv = move_ob(op, direction, activator);
1356     break;
1357    
1358     case 1:
1359     pl = va_arg(args, player*);
1360     direction = va_arg(args, int);
1361     va_end(args);
1362     rv = move_player(pl->ob, direction);
1363     break;
1364     }
1365     *type = CFAPI_INT;
1366     return &rv;
1367     }
1368    
1369     void* cfapi_object_get_key(int* type, ...)
1370     {
1371     va_list args;
1372     char* rv;
1373     char* keyname;
1374     object* op;
1375    
1376     va_start(args, type);
1377     op = va_arg(args, object*);
1378     keyname = va_arg(args, char*);
1379     va_end(args);
1380    
1381     rv = (char*)get_ob_key_value(op, keyname);
1382     *type = CFAPI_STRING;
1383     return rv;
1384     }
1385     void* cfapi_object_set_key(int* type, ...)
1386     {
1387     va_list args;
1388     char* keyname;
1389     char* value;
1390     object* op;
1391    
1392     va_start(args, type);
1393     op = va_arg(args, object*);
1394     keyname = va_arg(args, char*);
1395     value = va_arg(args, char*);
1396     va_end(args);
1397    
1398     set_ob_key_value(op, keyname, value, 0);
1399     *type = CFAPI_NONE;
1400     return NULL;
1401     }
1402     void* cfapi_object_get_property(int* type, ...)
1403     {
1404     va_list args;
1405     int property;
1406     object* op;
1407     void* rv;
1408     static int ri;
1409    
1410     va_start(args, type);
1411    
1412     op = va_arg(args, object*);
1413     property = va_arg(args, int);
1414     rv = NULL;
1415     if (op != NULL) {
1416     switch (property)
1417     {
1418     case CFAPI_OBJECT_PROP_OB_ABOVE:
1419     rv = op->above;
1420     *type = CFAPI_POBJECT;
1421     break;
1422    
1423     case CFAPI_OBJECT_PROP_OB_BELOW:
1424     rv = op->below;
1425     *type = CFAPI_POBJECT;
1426     break;
1427    
1428     case CFAPI_OBJECT_PROP_NEXT_ACTIVE_OB:
1429     rv = op->active_next;
1430     *type = CFAPI_POBJECT;
1431     break;
1432    
1433     case CFAPI_OBJECT_PROP_PREV_ACTIVE_OB:
1434     rv = op->active_prev;
1435     *type = CFAPI_POBJECT;
1436     break;
1437    
1438     case CFAPI_OBJECT_PROP_INVENTORY:
1439     rv = op->inv;
1440     *type = CFAPI_POBJECT;
1441     break;
1442    
1443     case CFAPI_OBJECT_PROP_ENVIRONMENT:
1444     rv = op->env;
1445     *type = CFAPI_POBJECT;
1446     break;
1447    
1448     case CFAPI_OBJECT_PROP_HEAD:
1449     rv = op->head;
1450     *type = CFAPI_POBJECT;
1451     break;
1452    
1453     case CFAPI_OBJECT_PROP_CONTAINER:
1454     rv = op->container;
1455     *type = CFAPI_POBJECT;
1456     break;
1457    
1458     case CFAPI_OBJECT_PROP_MAP:
1459     rv = op->map;
1460     *type = CFAPI_PMAP;
1461     break;
1462    
1463     case CFAPI_OBJECT_PROP_COUNT:
1464     ri = op->count; rv = &ri;
1465     *type = CFAPI_INT;
1466     break;
1467    
1468     case CFAPI_OBJECT_PROP_REFCOUNT:
1469     ri = op->refcount; rv = &ri;
1470     *type = CFAPI_INT;
1471     break;
1472    
1473     case CFAPI_OBJECT_PROP_NAME:
1474     rv = query_name(op);
1475     *type = CFAPI_STRING;
1476     break;
1477    
1478     case CFAPI_OBJECT_PROP_NAME_PLURAL:
1479     rv = (char*)op->name_pl;
1480     *type = CFAPI_STRING;
1481     break;
1482    
1483     case CFAPI_OBJECT_PROP_TITLE:
1484     rv = (char*)op->title;
1485     *type = CFAPI_STRING;
1486     break;
1487    
1488     case CFAPI_OBJECT_PROP_RACE:
1489     rv = (char*)op->race;
1490     *type = CFAPI_STRING;
1491     break;
1492    
1493     case CFAPI_OBJECT_PROP_SLAYING:
1494     rv = (char*)op->slaying;
1495     *type = CFAPI_STRING;
1496     break;
1497    
1498     case CFAPI_OBJECT_PROP_SKILL:
1499     rv = (char*)op->skill;
1500     *type = CFAPI_STRING;
1501     break;
1502    
1503     case CFAPI_OBJECT_PROP_MESSAGE:
1504     rv = (char*)op->msg;
1505     if (rv == NULL)
1506     rv = (void*)"";
1507     *type = CFAPI_STRING;
1508     break;
1509    
1510     case CFAPI_OBJECT_PROP_LORE:
1511     rv = (char*)op->lore;
1512     *type = CFAPI_STRING;
1513     break;
1514    
1515     case CFAPI_OBJECT_PROP_X:
1516     ri = op->x;
1517     rv = &ri;
1518     *type = CFAPI_INT;
1519     break;
1520    
1521     case CFAPI_OBJECT_PROP_Y:
1522     ri = op->y;
1523     rv = &ri;
1524     *type = CFAPI_INT;
1525     break;
1526    
1527     case CFAPI_OBJECT_PROP_SPEED:
1528     rv = &op->speed;
1529     *type = CFAPI_DOUBLE;
1530     break;
1531    
1532     case CFAPI_OBJECT_PROP_SPEED_LEFT:
1533     rv = &op->speed_left;
1534     *type = CFAPI_DOUBLE;
1535     break;
1536    
1537     case CFAPI_OBJECT_PROP_NROF:
1538     ri = op->nrof; rv = &ri;
1539     *type = CFAPI_INT;
1540     break;
1541    
1542     case CFAPI_OBJECT_PROP_DIRECTION:
1543     ri = op->direction; rv = &ri;
1544     *type = CFAPI_INT;
1545     break;
1546    
1547     case CFAPI_OBJECT_PROP_FACING:
1548     ri = op->facing; rv = &ri;
1549     *type = CFAPI_INT;
1550     break;
1551    
1552     case CFAPI_OBJECT_PROP_TYPE:
1553     ri = op->type; rv = &ri;
1554     *type = CFAPI_INT;
1555     break;
1556    
1557     case CFAPI_OBJECT_PROP_SUBTYPE:
1558     ri = op->subtype; rv = &ri;
1559     *type = CFAPI_INT;
1560     break;
1561    
1562     case CFAPI_OBJECT_PROP_CLIENT_TYPE:
1563     ri = op->client_type; rv = &ri;
1564     *type = CFAPI_INT;
1565     break;
1566    
1567     case CFAPI_OBJECT_PROP_RESIST:
1568     {
1569     int idx;
1570     idx = va_arg(args, int);
1571     ri = op->resist[idx]; rv = &ri;
1572     }
1573     *type = CFAPI_INT;
1574     break;
1575    
1576     case CFAPI_OBJECT_PROP_ATTACK_TYPE:
1577     ri = op->attacktype; rv = &ri;
1578     *type = CFAPI_INT;
1579     break;
1580    
1581     case CFAPI_OBJECT_PROP_PATH_ATTUNED:
1582     ri = op->path_attuned; rv = &ri;
1583     *type = CFAPI_INT;
1584     break;
1585    
1586     case CFAPI_OBJECT_PROP_PATH_REPELLED:
1587     ri = op->path_repelled; rv = &ri;
1588     *type = CFAPI_INT;
1589     break;
1590    
1591     case CFAPI_OBJECT_PROP_PATH_DENIED:
1592     ri = op->path_denied; rv = &ri;
1593     *type = CFAPI_INT;
1594     break;
1595    
1596     case CFAPI_OBJECT_PROP_MATERIAL:
1597     ri = op->material; rv = &ri;
1598     *type = CFAPI_INT;
1599     break;
1600    
1601     case CFAPI_OBJECT_PROP_MATERIAL_NAME:
1602     rv = (char*)op->materialname;
1603     *type = CFAPI_STRING;
1604     break;
1605    
1606     case CFAPI_OBJECT_PROP_MAGIC:
1607     ri = op->magic; rv = &ri;
1608     *type = CFAPI_INT;
1609     break;
1610    
1611     case CFAPI_OBJECT_PROP_VALUE:
1612     ri = op->value; rv = &ri;
1613     *type = CFAPI_INT;
1614     break;
1615    
1616     case CFAPI_OBJECT_PROP_LEVEL:
1617     ri = op->level; rv = &ri;
1618     *type = CFAPI_INT;
1619     break;
1620    
1621     case CFAPI_OBJECT_PROP_LAST_HEAL:
1622     ri = op->last_heal; rv = &ri;
1623     *type = CFAPI_INT;
1624     break;
1625    
1626     case CFAPI_OBJECT_PROP_LAST_SP:
1627     ri = op->last_sp; rv = &ri;
1628     *type = CFAPI_INT;
1629     break;
1630    
1631     case CFAPI_OBJECT_PROP_LAST_GRACE:
1632     ri = op->last_grace; rv = &ri;
1633     *type = CFAPI_INT;
1634     break;
1635    
1636     case CFAPI_OBJECT_PROP_LAST_EAT:
1637     ri = op->last_eat; rv = &ri;
1638     *type = CFAPI_INT;
1639     break;
1640    
1641     case CFAPI_OBJECT_PROP_INVISIBLE_TIME:
1642     ri = op->invisible; rv = &ri;
1643     *type = CFAPI_INT;
1644     break;
1645    
1646     case CFAPI_OBJECT_PROP_PICK_UP:
1647     ri = op->pick_up; rv = &ri;
1648     *type = CFAPI_INT;
1649     break;
1650    
1651     case CFAPI_OBJECT_PROP_ITEM_POWER:
1652     ri = op->item_power; rv = &ri;
1653     *type = CFAPI_INT;
1654     break;
1655    
1656     case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR:
1657     ri = op->gen_sp_armour; rv = &ri;
1658     *type = CFAPI_INT;
1659     break;
1660    
1661     case CFAPI_OBJECT_PROP_WEIGHT:
1662     ri = op->weight; rv = &ri;
1663     *type = CFAPI_INT;
1664     break;
1665    
1666     case CFAPI_OBJECT_PROP_WEIGHT_LIMIT:
1667     ri = op->weight_limit; rv = &ri;
1668     *type = CFAPI_INT;
1669     break;
1670    
1671     case CFAPI_OBJECT_PROP_CARRYING:
1672     ri = op->carrying; rv = &ri;
1673     *type = CFAPI_INT;
1674     break;
1675    
1676     case CFAPI_OBJECT_PROP_GLOW_RADIUS:
1677     ri = op->glow_radius; rv = &ri;
1678     *type = CFAPI_INT;
1679     break;
1680    
1681     case CFAPI_OBJECT_PROP_PERM_EXP:
1682     rv = &op->perm_exp;
1683     *type = CFAPI_LONG;
1684     break;
1685    
1686     case CFAPI_OBJECT_PROP_CURRENT_WEAPON:
1687     rv = op->current_weapon;
1688     *type = CFAPI_POBJECT;
1689     break;
1690    
1691     case CFAPI_OBJECT_PROP_ENEMY:
1692     rv = op->enemy;
1693     *type = CFAPI_POBJECT;
1694     break;
1695    
1696     case CFAPI_OBJECT_PROP_ATTACKED_BY:
1697     rv = op->attacked_by;
1698     *type = CFAPI_POBJECT;
1699     break;
1700    
1701     case CFAPI_OBJECT_PROP_RUN_AWAY:
1702     ri = op->run_away; rv = &ri;
1703     *type = CFAPI_INT;
1704     break;
1705    
1706     case CFAPI_OBJECT_PROP_CHOSEN_SKILL:
1707     rv = op->chosen_skill;
1708     *type = CFAPI_POBJECT;
1709     break;
1710    
1711     case CFAPI_OBJECT_PROP_HIDDEN:
1712     ri = op->hide; rv = &ri;
1713     *type = CFAPI_INT;
1714     break;
1715    
1716     case CFAPI_OBJECT_PROP_MOVE_STATUS:
1717     ri = op->move_status; rv = &ri;
1718     *type = CFAPI_INT;
1719     break;
1720    
1721     case CFAPI_OBJECT_PROP_MOVE_TYPE:
1722     ri = op->attack_movement; rv = &ri;
1723     *type = CFAPI_INT;
1724     break;
1725    
1726     case CFAPI_OBJECT_PROP_SPELL_ITEM:
1727     rv = op->spellitem;
1728     *type = CFAPI_POBJECT;
1729     break;
1730    
1731     case CFAPI_OBJECT_PROP_EXP_MULTIPLIER:
1732     rv = &op->expmul;
1733     *type = CFAPI_DOUBLE;
1734     break;
1735    
1736     case CFAPI_OBJECT_PROP_ARCHETYPE:
1737     rv = op->arch;
1738     *type = CFAPI_PARCH;
1739     break;
1740    
1741     case CFAPI_OBJECT_PROP_OTHER_ARCH:
1742     rv = op->other_arch;
1743     *type = CFAPI_PARCH;
1744     break;
1745    
1746     case CFAPI_OBJECT_PROP_CUSTOM_NAME:
1747     rv = (char*)op->custom_name;
1748     *type = CFAPI_STRING;
1749     break;
1750    
1751     case CFAPI_OBJECT_PROP_ANIM_SPEED:
1752     ri = op->anim_speed; rv = &ri;
1753     *type = CFAPI_INT;
1754     break;
1755    
1756     case CFAPI_OBJECT_PROP_FRIENDLY:
1757     ri = is_friendly(op);
1758     rv = &ri;
1759     *type = CFAPI_INT;
1760     break;
1761    
1762     case CFAPI_OBJECT_PROP_SHORT_NAME:
1763     rv = (char*)query_short_name(op);
1764     *type = CFAPI_STRING;
1765     break;
1766    
1767     case CFAPI_OBJECT_PROP_BASE_NAME:
1768     {
1769     int i;
1770     i = va_arg(args, int);
1771     rv = (char*)query_base_name(op, i);
1772     *type = CFAPI_STRING;
1773     }
1774     break;
1775    
1776     case CFAPI_OBJECT_PROP_MAGICAL:
1777     ri = is_magical(op);
1778     rv = &ri;
1779     *type = CFAPI_INT;
1780     break;
1781    
1782     case CFAPI_OBJECT_PROP_LUCK:
1783     ri = op->stats.luck; rv = &ri;
1784     *type = CFAPI_INT;
1785     break;
1786    
1787     case CFAPI_OBJECT_PROP_EXP:
1788     rv = &op->stats.exp;
1789     *type = CFAPI_LONG;
1790     break;
1791    
1792     case CFAPI_OBJECT_PROP_OWNER:
1793     rv = get_owner(op);
1794     *type = CFAPI_POBJECT;
1795     break;
1796    
1797     case CFAPI_OBJECT_PROP_PRESENT:
1798     {
1799     int stype;
1800     rv = 0;
1801     stype = va_arg(args, int);
1802     switch (stype) {
1803    
1804     unsigned char ptype;
1805     char* buf;
1806     archetype* at;
1807    
1808     case 0: /* present_in_ob */
1809     ptype = (unsigned char)(va_arg(args, int));
1810     rv = present_in_ob(ptype, op);
1811     break;
1812    
1813     case 1: /* present_in_ob_by_name */
1814     ptype = (unsigned char)(va_arg(args, int));
1815     buf = va_arg(args, char*);
1816     rv = present_in_ob_by_name(ptype, buf, op);
1817     break;
1818    
1819     case 2: /* present_arch_in_ob */
1820     at = va_arg(args, archetype*);
1821     rv = present_arch_in_ob(at, op);
1822     break;
1823     }
1824     }
1825     *type = CFAPI_POBJECT;
1826     break;
1827    
1828     case CFAPI_OBJECT_PROP_CHEATER:
1829     ri = (QUERY_FLAG(op, FLAG_WAS_WIZ));
1830     rv = &ri;
1831     *type = CFAPI_INT;
1832     break;
1833    
1834     case CFAPI_OBJECT_PROP_MERGEABLE:
1835     {
1836     object* op2;
1837     op2 = va_arg(args, object*);
1838     ri = CAN_MERGE(op, op2);
1839     rv = &ri;
1840     }
1841     *type = CFAPI_INT;
1842     break;
1843    
1844     case CFAPI_OBJECT_PROP_PICKABLE:
1845     {
1846     object* op2;
1847     rv = 0;
1848     op2 = va_arg(args, object*);
1849     ri = can_pick(op2, op);
1850     rv = &ri;
1851     }
1852     *type = CFAPI_INT;
1853     break;
1854    
1855     case CFAPI_OBJECT_PROP_FLAGS:
1856     {
1857     int fl;
1858     ri = 0;
1859     fl = va_arg(args, int);
1860     ri = QUERY_FLAG(op, fl);
1861     rv = &ri;
1862     }
1863     *type = CFAPI_INT;
1864     break;
1865    
1866     case CFAPI_OBJECT_PROP_STR:
1867     ri = op->stats.Str;
1868     rv = &ri;
1869     *type = CFAPI_INT;
1870     break;
1871    
1872     case CFAPI_OBJECT_PROP_DEX:
1873     ri = op->stats.Dex;
1874     rv = &ri;
1875     *type = CFAPI_INT;
1876     break;
1877    
1878     case CFAPI_OBJECT_PROP_CON:
1879     ri = op->stats.Con;
1880     rv = &ri;
1881     *type = CFAPI_INT;
1882     break;
1883    
1884     case CFAPI_OBJECT_PROP_WIS:
1885     ri = op->stats.Wis;
1886     rv = &ri;
1887     *type = CFAPI_INT;
1888     break;
1889    
1890     case CFAPI_OBJECT_PROP_INT:
1891     ri = op->stats.Int;
1892     rv = &ri;
1893     *type = CFAPI_INT;
1894     break;
1895    
1896     case CFAPI_OBJECT_PROP_POW:
1897     ri = op->stats.Pow;
1898     rv = &ri;
1899     *type = CFAPI_INT;
1900     break;
1901    
1902     case CFAPI_OBJECT_PROP_CHA:
1903     ri = op->stats.Cha;
1904     rv = &ri;
1905     *type = CFAPI_INT;
1906     break;
1907    
1908     case CFAPI_OBJECT_PROP_WC:
1909     ri = op->stats.wc;
1910     rv = &ri;
1911     *type = CFAPI_INT;
1912     break;
1913    
1914     case CFAPI_OBJECT_PROP_AC:
1915     ri = op->stats.ac;
1916     rv = &ri;
1917     *type = CFAPI_INT;
1918     break;
1919    
1920     case CFAPI_OBJECT_PROP_HP:
1921     ri = op->stats.hp;
1922     rv = &ri;
1923     *type = CFAPI_INT;
1924     break;
1925    
1926     case CFAPI_OBJECT_PROP_SP:
1927     ri = op->stats.sp;
1928     rv = &ri;
1929     *type = CFAPI_INT;
1930     break;
1931    
1932     case CFAPI_OBJECT_PROP_GP:
1933     ri = op->stats.grace;
1934     rv = &ri;
1935     *type = CFAPI_INT;
1936     break;
1937    
1938     case CFAPI_OBJECT_PROP_FP:
1939     ri = op->stats.food;
1940     rv = &ri;
1941     *type = CFAPI_INT;
1942     break;
1943    
1944     case CFAPI_OBJECT_PROP_MAXHP:
1945     ri = op->stats.maxhp;
1946     rv = &ri;
1947     *type = CFAPI_INT;
1948     break;
1949    
1950     case CFAPI_OBJECT_PROP_MAXSP:
1951     ri = op->stats.maxsp;
1952     rv = &ri;
1953     *type = CFAPI_INT;
1954     break;
1955    
1956     case CFAPI_OBJECT_PROP_MAXGP:
1957     ri = op->stats.maxgrace;
1958     rv = &ri;
1959     *type = CFAPI_INT;
1960     break;
1961    
1962     case CFAPI_OBJECT_PROP_DAM:
1963     ri = op->stats.dam;
1964     rv = &ri;
1965     *type = CFAPI_INT;
1966     break;
1967    
1968     case CFAPI_OBJECT_PROP_GOD:
1969     rv = (char*)determine_god(op);
1970     *type = CFAPI_STRING;
1971     break;
1972    
1973     case CFAPI_OBJECT_PROP_ARCH_NAME:
1974     rv = (char*)op->arch->name;
1975     *type = CFAPI_STRING;
1976     break;
1977    
1978     case CFAPI_OBJECT_PROP_INVISIBLE:
1979     ri = op->invisible;
1980     rv = &ri;
1981     *type = CFAPI_INT;
1982     break;
1983    
1984     case CFAPI_OBJECT_PROP_FACE:
1985     ri = op->animation_id;
1986     rv = &ri;
1987     *type = CFAPI_INT;
1988     break;
1989    
1990     case CFAPI_PLAYER_PROP_IP:
1991     rv = op->contr->socket.host;
1992     *type = CFAPI_STRING;
1993     break;
1994    
1995     case CFAPI_PLAYER_PROP_MARKED_ITEM:
1996     rv = find_marked_object(op);
1997     *type = CFAPI_POBJECT;
1998     break;
1999    
2000     case CFAPI_PLAYER_PROP_PARTY:
2001     rv = (op->contr ? op->contr->party : NULL);
2002     *type = CFAPI_PPARTY;
2003     break;
2004     default:
2005     *type = CFAPI_NONE;
2006     break;
2007     }
2008     }
2009     va_end(args);
2010     return rv;
2011     }
2012    
2013     void* cfapi_object_set_property(int* type, ...)
2014     {
2015     va_list args;
2016     int iarg;
2017     long larg;
2018     char* sarg;
2019     double darg;
2020     object* oparg;
2021     object* op;
2022     int property;
2023     void* rv;
2024     partylist* partyarg;
2025     va_start(args, type);
2026    
2027     op = va_arg(args, object*);
2028     property = va_arg(args, int);
2029     rv = NULL;
2030    
2031     if (op != NULL && (!op->arch || (op != &op->arch->clone))) {
2032     switch (property)
2033     {
2034     case CFAPI_OBJECT_PROP_NAME:
2035     sarg = va_arg(args, char*);
2036     FREE_AND_COPY(op->name, sarg);
2037     send_changed_object(op);
2038     break;
2039    
2040     case CFAPI_OBJECT_PROP_NAME_PLURAL:
2041     sarg = va_arg(args, char*);
2042     FREE_AND_COPY(op->name_pl, sarg);
2043     send_changed_object(op);
2044     break;
2045    
2046     case CFAPI_OBJECT_PROP_TITLE:
2047     sarg = va_arg(args, char*);
2048     FREE_AND_COPY(op->title, sarg);
2049     break;
2050    
2051     case CFAPI_OBJECT_PROP_RACE:
2052     sarg = va_arg(args, char*);
2053     FREE_AND_COPY(op->race, sarg);
2054     break;
2055    
2056     case CFAPI_OBJECT_PROP_SLAYING:
2057     sarg = va_arg(args, char*);
2058     FREE_AND_COPY(op->slaying, sarg);
2059     break;
2060    
2061     case CFAPI_OBJECT_PROP_SKILL:
2062     sarg = va_arg(args, char*);
2063     FREE_AND_COPY(op->skill, sarg);
2064     break;
2065    
2066     case CFAPI_OBJECT_PROP_MESSAGE:
2067     sarg = va_arg(args, char*);
2068     FREE_AND_COPY(op->msg, sarg);
2069     break;
2070    
2071     case CFAPI_OBJECT_PROP_LORE:
2072     sarg = va_arg(args, char*);
2073     FREE_AND_COPY(op->lore, sarg);
2074     break;
2075    
2076     case CFAPI_OBJECT_PROP_SPEED:
2077     darg = va_arg(args, double);
2078     op->speed = darg;
2079     break;
2080    
2081     case CFAPI_OBJECT_PROP_SPEED_LEFT:
2082     darg = va_arg(args, double);
2083     op->speed_left = darg;
2084     break;
2085    
2086     case CFAPI_OBJECT_PROP_NROF:
2087     iarg = va_arg(args, int);
2088     if (iarg < 0)
2089     iarg = 0;
2090     if (op->nrof > (uint32)iarg)
2091     decrease_ob_nr(op, op->nrof-iarg);
2092     else if (op->nrof < (uint32)iarg) {
2093     object* tmp;
2094     player *pl;
2095     op->nrof = iarg;
2096     if (op->env != NULL) {
2097     tmp = is_player_inv(op->env);
2098     if (!tmp) {
2099     for (pl = first_player; pl; pl = pl->next)
2100     if (pl->ob->container == op->env)
2101     break;
2102     if (pl)
2103     tmp = pl->ob;
2104     else
2105     tmp = NULL;
2106     }
2107     else {
2108     sum_weight(tmp);
2109     fix_player(tmp);
2110     }
2111     if (tmp)
2112     esrv_send_item(tmp, op);
2113     }
2114     else
2115     {
2116     object *above = op->above;
2117    
2118     for (tmp = above; tmp != NULL; tmp = tmp->above)
2119     if (tmp->type == PLAYER)
2120     esrv_send_item(tmp, op);
2121     }
2122     }
2123     break;
2124    
2125     case CFAPI_OBJECT_PROP_DIRECTION:
2126     iarg = va_arg(args, int);
2127     op->direction = iarg;
2128     break;
2129    
2130     case CFAPI_OBJECT_PROP_FACING:
2131     iarg = va_arg(args, int);
2132     op->facing = iarg;
2133     break;
2134    
2135     case CFAPI_OBJECT_PROP_RESIST:
2136     {
2137     int iargbis = va_arg(args, int);
2138     iarg = va_arg(args, int);
2139     op->resist[iargbis] = iarg;
2140     }
2141     break;
2142    
2143     case CFAPI_OBJECT_PROP_ATTACK_TYPE:
2144     iarg = va_arg(args, int);
2145     op->attacktype = iarg;
2146     break;
2147    
2148     case CFAPI_OBJECT_PROP_PATH_ATTUNED:
2149     iarg = va_arg(args, int);
2150     op->path_attuned = iarg;
2151     break;
2152    
2153     case CFAPI_OBJECT_PROP_PATH_REPELLED:
2154     iarg = va_arg(args, int);
2155     op->path_repelled = iarg;
2156     break;
2157    
2158     case CFAPI_OBJECT_PROP_PATH_DENIED:
2159     iarg = va_arg(args, int);
2160     op->path_denied = iarg;
2161     break;
2162    
2163     case CFAPI_OBJECT_PROP_MATERIAL:
2164     iarg = va_arg(args, int);
2165     op->material = iarg;
2166     break;
2167    
2168     case CFAPI_OBJECT_PROP_MATERIAL_NAME:
2169     break;
2170    
2171     case CFAPI_OBJECT_PROP_MAGIC:
2172     iarg = va_arg(args, int);
2173     op->magic = iarg;
2174     break;
2175    
2176     case CFAPI_OBJECT_PROP_VALUE:
2177     iarg = va_arg(args, int);
2178     op->value = iarg;
2179     break;
2180    
2181     case CFAPI_OBJECT_PROP_LEVEL:
2182     iarg = va_arg(args, int);
2183     op->level = iarg;
2184     break;
2185    
2186     case CFAPI_OBJECT_PROP_LAST_HEAL:
2187     iarg = va_arg(args, int);
2188     op->last_heal = iarg;
2189     break;
2190    
2191     case CFAPI_OBJECT_PROP_LAST_SP:
2192     iarg = va_arg(args, int);
2193     op->last_sp = iarg;
2194     break;
2195    
2196     case CFAPI_OBJECT_PROP_LAST_GRACE:
2197     iarg = va_arg(args, int);
2198     op->last_grace = iarg;
2199     break;
2200    
2201     case CFAPI_OBJECT_PROP_LAST_EAT:
2202     iarg = va_arg(args, int);
2203     op->last_eat = iarg;
2204     break;
2205    
2206     case CFAPI_OBJECT_PROP_INVISIBLE_TIME:
2207     iarg = va_arg(args, int);
2208     op->invisible = iarg;
2209     break;
2210    
2211     case CFAPI_OBJECT_PROP_PICK_UP:
2212     iarg = va_arg(args, int);
2213     op->pick_up = iarg;
2214     break;
2215    
2216     case CFAPI_OBJECT_PROP_ITEM_POWER:
2217     iarg = va_arg(args, int);
2218     op->item_power = iarg;
2219     break;
2220    
2221     case CFAPI_OBJECT_PROP_GEN_SP_ARMOUR:
2222     iarg = va_arg(args, int);
2223     op->gen_sp_armour = iarg;
2224     break;
2225    
2226     case CFAPI_OBJECT_PROP_WEIGHT:
2227     iarg = va_arg(args, int);
2228     if (op->weight != iarg) {
2229     object* tmp;
2230     player *pl;
2231     op->weight = iarg;
2232     if (op->env != NULL) {
2233     tmp = is_player_inv(op->env);
2234     if (!tmp) {
2235     for (pl = first_player; pl; pl = pl->next)
2236     if (pl->ob->container == op->env)
2237     break;
2238     if (pl)
2239     tmp = pl->ob;
2240     else
2241     tmp = NULL;
2242     } else {
2243     sum_weight(tmp);
2244     fix_player(tmp);
2245     }
2246     if (tmp)
2247     esrv_send_item(tmp, op);
2248     }
2249     else
2250     {
2251     object *above = op->above;
2252    
2253     for (tmp = above; tmp != NULL; tmp = tmp->above)
2254     if (tmp->type == PLAYER)
2255     esrv_send_item(tmp, op);
2256     }
2257     }
2258     break;
2259    
2260     case CFAPI_OBJECT_PROP_WEIGHT_LIMIT:
2261     iarg = va_arg(args, int);
2262     op->weight_limit = iarg;
2263     break;
2264    
2265     case CFAPI_OBJECT_PROP_GLOW_RADIUS:
2266     iarg = va_arg(args, int);
2267     op->glow_radius = iarg;
2268     break;
2269    
2270     case CFAPI_OBJECT_PROP_PERM_EXP:
2271     larg = va_arg(args, long);
2272     op->perm_exp = larg;
2273     break;
2274    
2275     case CFAPI_OBJECT_PROP_ENEMY:
2276     oparg = va_arg(args, object*);
2277     op->enemy = oparg;
2278     break;
2279    
2280     case CFAPI_OBJECT_PROP_RUN_AWAY:
2281     iarg = va_arg(args, int);
2282     op->run_away = iarg;
2283     break;
2284    
2285     case CFAPI_OBJECT_PROP_CHOSEN_SKILL:
2286     oparg = va_arg(args, object*);
2287     op->chosen_skill = oparg;
2288     break;
2289    
2290     case CFAPI_OBJECT_PROP_HIDDEN:
2291     iarg = va_arg(args, int);
2292     op->hide = iarg;
2293     break;
2294    
2295     case CFAPI_OBJECT_PROP_MOVE_STATUS:
2296     iarg = va_arg(args, int);
2297     op->move_status = iarg;
2298     break;
2299    
2300     case CFAPI_OBJECT_PROP_MOVE_TYPE:
2301     iarg = va_arg(args, int);
2302     op->attack_movement = iarg;
2303     break;
2304    
2305     case CFAPI_OBJECT_PROP_SPELL_ITEM:
2306     oparg = va_arg(args, object*);
2307     op->spellitem = oparg;
2308     break;
2309    
2310     case CFAPI_OBJECT_PROP_EXP_MULTIPLIER:
2311     darg = va_arg(args, double);
2312     op->expmul = darg;
2313     break;
2314    
2315     case CFAPI_OBJECT_PROP_CUSTOM_NAME:
2316     sarg = va_arg(args, char*);
2317     FREE_AND_COPY(op->custom_name, sarg);
2318     send_changed_object(op);
2319     break;
2320    
2321     case CFAPI_OBJECT_PROP_ANIM_SPEED:
2322     iarg = va_arg(args, int);
2323     op->anim_speed = iarg;
2324     break;
2325    
2326     case CFAPI_OBJECT_PROP_FRIENDLY:
2327     iarg = va_arg(args, int);
2328     if (iarg == 1 && is_friendly(op) == 0)
2329     add_friendly_object(op);
2330     else if (iarg == 0 && is_friendly(op) == 1)
2331     remove_friendly_object(op);
2332     break;
2333    
2334     case CFAPI_OBJECT_PROP_LUCK:
2335     iarg = va_arg(args, int);
2336     op->stats.luck = iarg;
2337     break;
2338    
2339     case CFAPI_OBJECT_PROP_EXP:
2340     {
2341     char* skillname;
2342    
2343     larg = va_arg(args, long);
2344     skillname = va_arg(args, char*);
2345     iarg = va_arg(args, int);
2346     change_exp(op, larg, skillname, iarg);
2347     }
2348     break;
2349    
2350     case CFAPI_OBJECT_PROP_OWNER:
2351     oparg = va_arg(args, object*);
2352     set_owner(op, oparg);
2353     break;
2354    
2355     case CFAPI_OBJECT_PROP_CHEATER:
2356     set_cheat(op);
2357     break;
2358    
2359     case CFAPI_OBJECT_PROP_FLAGS:
2360     {
2361     int iargbis;
2362     iarg = va_arg(args, int);
2363     iargbis = va_arg(args, int);
2364     if (iargbis == 1)
2365     SET_FLAG(op, iarg);
2366     else
2367     CLEAR_FLAG(op, iarg);
2368     }
2369     break;
2370    
2371     case CFAPI_OBJECT_PROP_STR:
2372     iarg = va_arg(args, int);
2373     op->stats.Str=iarg;
2374     break;
2375    
2376     case CFAPI_OBJECT_PROP_DEX:
2377     iarg = va_arg(args, int);
2378     op->stats.Dex=iarg;
2379     break;
2380    
2381     case CFAPI_OBJECT_PROP_CON:
2382     iarg = va_arg(args, int);
2383     op->stats.Con=iarg;
2384     break;
2385    
2386     case CFAPI_OBJECT_PROP_WIS:
2387     iarg = va_arg(args, int);
2388     op->stats.Wis=iarg;
2389     break;
2390    
2391     case CFAPI_OBJECT_PROP_INT:
2392     iarg = va_arg(args, int);
2393     op->stats.Int=iarg;
2394     break;
2395    
2396     case CFAPI_OBJECT_PROP_POW:
2397     iarg = va_arg(args, int);
2398     op->stats.Pow=iarg;
2399     break;
2400    
2401     case CFAPI_OBJECT_PROP_CHA:
2402     iarg = va_arg(args, int);
2403     op->stats.Cha=iarg;
2404     break;
2405    
2406     case CFAPI_OBJECT_PROP_WC:
2407     iarg = va_arg(args, int);
2408     op->stats.wc=iarg;
2409     break;
2410    
2411     case CFAPI_OBJECT_PROP_AC:
2412     iarg = va_arg(args, int);
2413     op->stats.ac=iarg;
2414     break;
2415    
2416     case CFAPI_OBJECT_PROP_HP:
2417     iarg = va_arg(args, int);
2418     op->stats.hp=iarg;
2419     break;
2420    
2421     case CFAPI_OBJECT_PROP_SP:
2422     iarg = va_arg(args, int);
2423     op->stats.sp=iarg;
2424     break;
2425    
2426     case CFAPI_OBJECT_PROP_GP:
2427     iarg = va_arg(args, int);
2428     op->stats.grace=iarg;
2429     break;
2430    
2431     case CFAPI_OBJECT_PROP_FP:
2432     iarg = va_arg(args, int);
2433     op->stats.food=iarg;
2434     break;
2435    
2436     case CFAPI_OBJECT_PROP_MAXHP:
2437     iarg = va_arg(args, int);
2438     op->stats.maxhp=iarg;
2439     break;
2440    
2441     case CFAPI_OBJECT_PROP_MAXSP:
2442     iarg = va_arg(args, int);
2443     op->stats.maxsp=iarg;
2444     break;
2445    
2446     case CFAPI_OBJECT_PROP_MAXGP:
2447     iarg = va_arg(args, int);
2448     op->stats.maxgrace=iarg;
2449     break;
2450    
2451     case CFAPI_OBJECT_PROP_DAM:
2452     iarg = va_arg(args, int);
2453     op->stats.dam=iarg;
2454     break;
2455    
2456     case CFAPI_OBJECT_PROP_FACE:
2457     iarg = va_arg(args, int);
2458     op->animation_id = iarg;
2459     update_object(op, UP_OBJ_FACE);
2460     break;
2461    
2462     case CFAPI_OBJECT_ANIMATION:
2463     iarg = va_arg(args, int);
2464     if (iarg != -1) {
2465     SET_ANIMATION(op, iarg);
2466     }
2467     update_object(op, UP_OBJ_FACE);
2468     break;
2469    
2470     case CFAPI_PLAYER_PROP_MARKED_ITEM:
2471     if (op->contr) {
2472     oparg = va_arg(args, object*);
2473     op->contr->mark = oparg;
2474     if (oparg)
2475     op->contr->mark_count = oparg->count;
2476     }
2477     break;
2478    
2479     case CFAPI_PLAYER_PROP_PARTY:
2480     if (op->contr) {
2481     partyarg = va_arg(args, partylist*);
2482     op->contr->party = partyarg;
2483     }
2484     break;
2485    
2486     default:
2487     *type = CFAPI_NONE;
2488     break;
2489     }
2490     }
2491     va_end(args);
2492    
2493     *type = CFAPI_NONE;
2494     return NULL;
2495     }
2496    
2497     void* cfapi_object_apply_below(int* type, ...)
2498     {
2499     va_list args;
2500     object* applier;
2501    
2502     va_start(args, type);
2503    
2504     applier = va_arg(args, object*);
2505    
2506     va_end(args);
2507    
2508     player_apply_below(applier);
2509     *type = CFAPI_NONE;
2510     return NULL;
2511     }
2512    
2513     void* cfapi_object_apply(int* type, ...)
2514     {
2515     va_list args;
2516     object* applied;
2517     object* applier;
2518     int aflags;
2519     static int rv;
2520    
2521     va_start(args, type);
2522    
2523     applied = va_arg(args, object*);
2524     applier = va_arg(args, object*);
2525     aflags = va_arg(args, int);
2526    
2527     va_end(args);
2528    
2529     *type = CFAPI_INT;
2530     rv = manual_apply(applier, applied, aflags);
2531     return &rv;
2532     }
2533     void* cfapi_object_identify(int* type, ...)
2534     {
2535     va_list args;
2536     object* op;
2537    
2538     va_start(args, type);
2539    
2540     op = va_arg(args, object*);
2541    
2542     va_end(args);
2543    
2544     identify(op);
2545     *type = CFAPI_NONE;
2546     return NULL;
2547     }
2548     void* cfapi_object_describe(int* type, ...)
2549     {
2550     va_list args;
2551     object* op;
2552     object* owner;
2553    
2554     va_start(args, type);
2555    
2556     op = va_arg(args, object*);
2557     owner = va_arg(args, object*);
2558     va_end(args);
2559    
2560     *type = CFAPI_STRING;
2561     return describe_item(op, owner);
2562     }
2563     void* cfapi_object_drain(int* type, ...)
2564     {
2565     va_list args;
2566    
2567     object* op;
2568     int ds;
2569    
2570     va_start(args, type);
2571    
2572     op = va_arg(args, object*);
2573     ds = va_arg(args, int);
2574    
2575     va_end(args);
2576    
2577     drain_specific_stat(op, ds);
2578    
2579     *type = CFAPI_NONE;
2580     return NULL;
2581     }
2582     void* cfapi_object_fix(int* type, ...)
2583     {
2584     va_list args;
2585     object* op;
2586    
2587     va_start(args, type);
2588    
2589     op = va_arg(args, object*);
2590    
2591     va_end(args);
2592    
2593     fix_player(op);
2594    
2595     *type = CFAPI_NONE;
2596     return NULL;
2597     }
2598     void* cfapi_object_give_skill(int* type, ...)
2599     {
2600     va_list args;
2601    
2602     object* op;
2603     char* skillname;
2604    
2605     va_start(args, type);
2606    
2607     op = va_arg(args, object*);
2608     skillname = va_arg(args, char*);
2609    
2610     va_end(args);
2611    
2612     *type = CFAPI_POBJECT;
2613     return give_skill_by_name(op, skillname);
2614     }
2615     void* cfapi_object_transmute(int* type, ...)
2616     {
2617     va_list args;
2618    
2619     object* op;
2620     object* chg;
2621    
2622     va_start(args, type);
2623    
2624     op = va_arg(args, object*);
2625     chg = va_arg(args, object*);
2626    
2627     va_end(args);
2628    
2629     transmute_materialname(op, chg);
2630     *type = CFAPI_NONE;
2631     return NULL;
2632     }
2633     void* cfapi_object_remove(int* type, ...)
2634     {
2635     va_list args;
2636     object* op;
2637    
2638     va_start(args, type);
2639    
2640     op = va_arg(args, object*);
2641    
2642     va_end(args);
2643    
2644     send_removed_object(op);
2645     remove_ob(op);
2646     *type = CFAPI_NONE;
2647     return NULL;
2648     }
2649     void* cfapi_object_delete(int* type, ...)
2650     {
2651     va_list args;
2652     object* op;
2653    
2654     va_start(args, type);
2655    
2656     op = va_arg(args, object*);
2657    
2658     va_end(args);
2659    
2660     free_object(op);
2661    
2662     *type = CFAPI_NONE;
2663     return NULL;
2664     }
2665     void* cfapi_object_clone(int* type, ...)
2666     {
2667     va_list args;
2668     object* op;
2669     int kind;
2670    
2671     va_start(args, type);
2672    
2673     op = va_arg(args, object*);
2674     kind = va_arg(args, int);
2675    
2676     va_end(args);
2677    
2678     if (kind == 0) {
2679     *type = CFAPI_POBJECT;
2680     return object_create_clone(op);
2681     } else {
2682     object* tmp;
2683     tmp = get_object();
2684     copy_object(op, tmp);
2685     *type = CFAPI_POBJECT;
2686     return tmp;
2687     }
2688     }
2689     void* cfapi_object_find(int* type, ...)
2690     {
2691     va_list args;
2692     int ftype;
2693     void* rv;
2694     int ival;
2695     int ival2;
2696     char* sval;
2697     object* op;
2698     va_start(args, type);
2699    
2700     *type = CFAPI_POBJECT;
2701     ftype = va_arg(args, int);
2702     switch (ftype)
2703     {
2704     case 0:
2705     ival = va_arg(args, int);
2706     rv = find_object(ival);
2707     break;
2708    
2709     case 1:
2710     sval = va_arg(args, char*);
2711     rv = find_object_name(sval);
2712     break;
2713    
2714     case 2:
2715     op = va_arg(args, object*);
2716     ival = va_arg(args, int);
2717     ival2 = va_arg(args, int);
2718     rv = find_obj_by_type_subtype(op, ival, ival2);
2719     break;
2720    
2721     case 3:
2722     op = va_arg(args, object*);
2723     rv = is_player_inv(op);
2724     break;
2725    
2726     default:
2727     rv = NULL;
2728     *type = CFAPI_NONE;
2729     break;
2730     }
2731    
2732     va_end(args);
2733    
2734     return rv;
2735     }
2736     void* cfapi_object_create(int* type, ...)
2737     {
2738     va_list args;
2739     int ival;
2740     va_start(args, type);
2741     ival = va_arg(args, int);
2742    
2743     *type = CFAPI_POBJECT;
2744     switch (ival)
2745     {
2746     case 0:
2747     va_end(args);
2748     return get_object();
2749     break;
2750    
2751     case 1: /* Named object. Nearly the old plugin behavior, but we don't add artifact suffixes */
2752     {
2753     char* sval;
2754     object* op;
2755     sval = va_arg(args, char*);
2756    
2757     op = get_archetype_by_object_name(sval);
2758    
2759     if (strncmp(query_name(op), ARCH_SINGULARITY, ARCH_SINGULARITY_LEN) == 0) {
2760     free_object(op);
2761     /* Try with archetype names... */
2762     op = get_archetype(sval);
2763     if (strncmp(query_name(op), ARCH_SINGULARITY, ARCH_SINGULARITY_LEN) == 0) {
2764     free_object(op);
2765     *type = CFAPI_NONE;
2766     va_end(args);
2767     return NULL;
2768     }
2769     }
2770     va_end(args);
2771     return op;
2772     }
2773     break;
2774    
2775     default:
2776     *type = CFAPI_NONE;
2777     va_end(args);
2778     return NULL;
2779     break;
2780     }
2781     }
2782     void* cfapi_object_insert(int* type, ...)
2783     {
2784     va_list args;
2785     object* op;
2786     object* orig;
2787     mapstruct* map;
2788     int flag, x, y;
2789     int itype;
2790     char* arch_string;
2791     void* rv = NULL;
2792    
2793     va_start(args, type);
2794    
2795     op = va_arg(args, object*);
2796     itype = va_arg(args, int);
2797    
2798     switch (itype) {
2799     case 0:
2800     map = va_arg(args, mapstruct*);
2801     orig = va_arg(args, object*);
2802     flag = va_arg(args, int);
2803     x = va_arg(args, int);
2804     y = va_arg(args, int);
2805     rv = insert_ob_in_map_at(op, map, orig, flag, x, y);
2806     *type = CFAPI_POBJECT;
2807     break;
2808    
2809     case 1:
2810     map = va_arg(args, mapstruct*);
2811     orig = va_arg(args, object*);
2812     flag = va_arg(args, int);
2813     rv = insert_ob_in_map(op, map, orig, flag);
2814     *type = CFAPI_POBJECT;
2815     break;
2816    
2817     case 2:
2818     arch_string = va_arg(args, char*);
2819     replace_insert_ob_in_map(arch_string, op);
2820     *type = CFAPI_NONE;
2821     break;
2822    
2823     case 3:
2824     orig = va_arg(args, object*);
2825     rv = insert_ob_in_ob(op, orig);
2826     if (orig->type == PLAYER) {
2827     esrv_send_item(orig, op);
2828     }
2829     *type = CFAPI_POBJECT;
2830     break;
2831     }
2832    
2833     va_end(args);
2834    
2835     return rv;
2836     }
2837     void* cfapi_object_split(int* type, ...)
2838     {
2839     va_list args;
2840    
2841     int nr;
2842     object* op;
2843     va_start(args, type);
2844    
2845     op = va_arg(args, object*);
2846     nr = va_arg(args, int);
2847    
2848     va_end(args);
2849     *type = CFAPI_POBJECT;
2850     return get_split_ob(op, nr);
2851     }
2852     void* cfapi_object_merge(int* type, ...)
2853     {
2854     va_list args;
2855     object* op;
2856     object* op2;
2857    
2858     va_start(args, type);
2859    
2860     op = va_arg(args, object*);
2861     op2 = va_arg(args, object*);
2862    
2863     va_end(args);
2864    
2865    
2866     *type = CFAPI_POBJECT;
2867     return merge_ob(op, op2);
2868     }
2869     void* cfapi_object_distance(int* type, ...)
2870     {
2871     va_list args;
2872     static int rv;
2873     object* op;
2874     object* op2;
2875     va_start(args, type);
2876    
2877     op = va_arg(args, object*);
2878     op2 = va_arg(args, object*);
2879    
2880     va_end(args);
2881    
2882     *type = CFAPI_INT;
2883     rv = distance(op, op2);
2884     return &rv;
2885     }
2886     void* cfapi_object_update(int* type, ...)
2887     {
2888     va_list args;
2889     int action;
2890     object* op;
2891     va_start(args, type);
2892    
2893     op = va_arg(args, object*);
2894     action = va_arg(args, int);
2895    
2896     va_end(args);
2897    
2898     update_object(op, action);
2899     *type = CFAPI_NONE;
2900     return NULL;
2901     }
2902     void* cfapi_object_clear(int* type, ...)
2903     {
2904     va_list args;
2905     object* op;
2906     va_start(args, type);
2907    
2908     op = va_arg(args, object*);
2909    
2910     va_end(args);
2911    
2912     clear_object(op);
2913     *type = CFAPI_NONE;
2914     return NULL;
2915     }
2916     void* cfapi_object_reset(int* type, ...)
2917     {
2918     va_list args;
2919     object* op;
2920    
2921     va_start(args, type);
2922    
2923     op = va_arg(args, object*);
2924    
2925     va_end(args);
2926    
2927     reset_object(op);
2928     *type = CFAPI_NONE;
2929     return NULL;
2930     }
2931    
2932     void* cfapi_object_check_inventory(int* type, ...)
2933     {
2934     va_list args;
2935     object* op;
2936     object* op2;
2937     int checktype;
2938     object* ret = NULL;
2939    
2940     va_start(args, type);
2941    
2942     op = va_arg(args, object*);
2943     op2 = va_arg(args, object*);
2944     checktype = va_arg(args, int);
2945    
2946     if (checktype == 0) {
2947     check_inv(op, op2);
2948     *type = CFAPI_NONE;
2949     } else {
2950     ret = check_inv_recursive(op, op2);
2951     *type = CFAPI_POBJECT;
2952     }
2953    
2954     va_end(args);
2955    
2956     return ret;
2957     }
2958    
2959     void* cfapi_object_clean_object(int* type, ...)
2960     {
2961     va_list args;
2962     object* op;
2963     va_start(args, type);
2964     op = va_arg(args, object*);
2965     clean_object(op);
2966     va_end(args);
2967     *type = CFAPI_NONE;
2968     return NULL;
2969     }
2970     void* cfapi_object_on_same_map(int* type, ...)
2971     {
2972     va_list args;
2973     static int rv;
2974     object* op1;
2975     object* op2;
2976    
2977     va_start(args, type);
2978     op1 = va_arg(args, object*);
2979     op2 = va_arg(args, object*);
2980    
2981     rv = on_same_map(op1, op2);
2982     va_end(args);
2983    
2984     *type = CFAPI_INT;
2985     return &rv;
2986     }
2987    
2988     void* cfapi_object_spring_trap(int* type, ...)
2989     {
2990     object* trap;
2991     object* victim;
2992     va_list args;
2993    
2994     va_start(args, type);
2995     trap = va_arg(args, object*);
2996     victim = va_arg(args, object*);
2997     va_end(args);
2998    
2999     spring_trap(trap, victim);
3000     *type = CFAPI_NONE;
3001     return NULL;
3002     }
3003    
3004     void* cfapi_object_check_trigger(int* type, ...)
3005     {
3006     object* op;
3007     object* cause;
3008     va_list args;
3009     static int rv;
3010    
3011     va_start(args, type);
3012     op = va_arg(args, object*);
3013     cause = va_arg(args, object*);
3014     va_end(args);
3015    
3016     rv = check_trigger(op, cause);
3017     *type = CFAPI_INT;
3018     return &rv;
3019     }
3020    
3021     void* cfapi_object_query_cost(int* type, ...)
3022     {
3023     object* op;
3024     object* who;
3025     int flags;
3026     va_list args;
3027     static int rv;
3028    
3029     va_start(args, type);
3030     op = va_arg(args, object*);
3031     who = va_arg(args, object*);
3032     flags = va_arg(args, int);
3033     va_end(args);
3034    
3035     rv = query_cost(op, who, flags);
3036     *type = CFAPI_INT;
3037     return &rv;
3038     }
3039    
3040     void* cfapi_object_query_money(int* type, ...)
3041     {
3042     object* op;
3043     va_list args;
3044     static int rv;
3045    
3046     va_start(args, type);
3047     op = va_arg(args, object*);
3048     va_end(args);
3049    
3050     rv = query_money(op);
3051     *type = CFAPI_INT;
3052     return &rv;
3053     }
3054     void* cfapi_object_cast(int* type, ...)
3055     {
3056     object* op;
3057     object* sp;
3058     int dir;
3059     char* str;
3060     object* caster;
3061     va_list args;
3062     static int rv;
3063     va_start(args, type);
3064     op = va_arg(args, object*);
3065     caster = va_arg(args, object*);
3066     dir = va_arg(args, int);
3067     sp = va_arg(args, object*);
3068     str = va_arg(args, char*);
3069     va_end(args);
3070     rv = cast_spell(op, caster, dir, sp, str);
3071     *type = CFAPI_INT;
3072     return &rv;
3073     }
3074     void* cfapi_object_learn_spell(int* type, ...)
3075     {
3076     object* op;
3077     object* sp;
3078     int prayer;
3079     va_list args;
3080    
3081     va_start(args, type);
3082     op = va_arg(args, object*);
3083     sp = va_arg(args, object*);
3084     prayer = va_arg(args, int);
3085     va_end(args);
3086     do_learn_spell(op, sp, prayer);
3087     *type = CFAPI_NONE;
3088     return NULL;
3089     }
3090     void* cfapi_object_forget_spell(int* type, ...)
3091     {
3092     object* op;
3093     object* sp;
3094     va_list args;
3095    
3096     va_start(args, type);
3097     op = va_arg(args, object*);
3098     sp = va_arg(args, object*);
3099     va_end(args);
3100     do_forget_spell(op, query_name(sp));
3101     *type = CFAPI_NONE;
3102     return NULL;
3103     }
3104     void* cfapi_object_check_spell(int* type, ...)
3105     {
3106     object* op;
3107     char* spellname;
3108     va_list args;
3109     object* rv;
3110    
3111     va_start(args, type);
3112     op = va_arg(args, object*);
3113     spellname = va_arg(args, char*);
3114     va_end(args);
3115     rv = check_spell_known(op, spellname);
3116     *type = CFAPI_POBJECT;
3117     return rv;
3118     }
3119     void* cfapi_object_pay_amount(int* type, ...)
3120     {
3121     object* op;
3122     uint64 amount;
3123     va_list args;
3124     static int rv;
3125    
3126     va_start(args, type);
3127     op = va_arg(args, object*);
3128     amount = va_arg(args, uint64);
3129     va_end(args);
3130    
3131     rv = pay_for_amount(amount, op);
3132     *type = CFAPI_INT;
3133     return &rv;
3134     }
3135     void* cfapi_object_pay_item(int* type, ...)
3136     {
3137     object* op;
3138     object* tobuy;
3139    
3140     va_list args;
3141     static int rv;
3142    
3143     va_start(args, type);
3144     tobuy = va_arg(args, object*);
3145     op = va_arg(args, object*);
3146     va_end(args);
3147    
3148     rv = pay_for_item(tobuy, op);
3149     *type = CFAPI_INT;
3150     return &rv;
3151     }
3152     void* cfapi_object_transfer(int* type, ...)
3153     {
3154     object* op;
3155     object* originator;
3156     int x, y, randompos, ttype;
3157     va_list args;
3158     static int rv=0;
3159     mapstruct* map;
3160    
3161     va_start(args, type);
3162     op = va_arg(args, object*);
3163     ttype = va_arg(args, int);
3164     switch (ttype)
3165     {
3166     case 0:
3167     x = va_arg(args, int);
3168     y = va_arg(args, int);
3169     randompos = va_arg(args, int);
3170     originator = va_arg(args, object*);
3171     va_end(args);
3172    
3173     rv = transfer_ob(op, x, y, randompos, originator);
3174     *type = CFAPI_INT;
3175     return &rv;
3176     break;
3177    
3178     case 1:
3179     x = va_arg(args, int);
3180     y = va_arg(args, int);
3181     map = va_arg(args, mapstruct*);
3182     va_end(args);
3183     if (x < 0 || y < 0) {
3184     x = map->enter_x;
3185     y = map->enter_y;
3186     }
3187     /*
3188     originator = get_object();
3189     EXIT_PATH(originator) = add_string(map->path);
3190     EXIT_X(originator) = x;
3191     EXIT_Y(originator) = y;
3192     printf("B Transfer: X=%d, Y=%d, OP=%s\n", x, y, op->name);*/
3193     /*enter_exit(op, originator);*/
3194     insert_ob_in_map_at(op, map, NULL, 0, x, y);
3195     /*printf("A Transfer: X=%d, Y=%d, MAP=%s\n", x, y, op->map->name);
3196     free_object(originator);
3197     */
3198     *type = CFAPI_INT;
3199     return &rv;
3200     break;
3201    
3202     default:
3203     *type = CFAPI_NONE;
3204     return NULL;
3205     break;
3206     }
3207     }
3208    
3209     void* cfapi_object_find_archetype_inside(int* type, ...)
3210     {
3211     object* op;
3212     int critera;
3213     char* str;
3214     va_list args;
3215     object* rv;
3216    
3217     *type = CFAPI_POBJECT;
3218     va_start(args, type);
3219     op = va_arg(args, object*);
3220     critera = va_arg(args, int);
3221    
3222     switch(critera)
3223     {
3224     case 0: /* By name, either exact or from query_name */
3225     str = va_arg(args, char*);
3226     rv = present_arch_in_ob(find_archetype(str), op);
3227     if (rv == NULL) {
3228     object* tmp;
3229     /* Search by query_name instead */
3230     for (tmp = op->inv; tmp; tmp = tmp->below) {
3231     if (!strncmp(query_name(tmp), str, strlen(str)))
3232     rv = tmp;
3233     if (!strncmp(tmp->name, str, strlen(str)))
3234     rv = tmp;
3235     if (rv != NULL)
3236     break;
3237     }
3238     }
3239     break;
3240    
3241     default:
3242     rv = NULL;
3243     break;
3244     }
3245     va_end(args);
3246    
3247     if (rv == NULL) {
3248     *type = CFAPI_NONE;
3249     }
3250     return rv;
3251     }
3252    
3253     void* cfapi_object_drop(int* type, ...)
3254     {
3255     object* op;
3256     object* author;
3257     va_list args;
3258    
3259     va_start(args, type);
3260     op = va_arg(args, object*);
3261     author = va_arg(args, object*);
3262     va_end(args);
3263    
3264     if (QUERY_FLAG(op, FLAG_NO_DROP))
3265     return NULL;
3266     drop(author, op);
3267    
3268     if (author->type == PLAYER) {
3269     author->contr->count = 0;
3270     author->contr->socket.update_look = 1;
3271     }
3272    
3273     *type = CFAPI_NONE;
3274     return NULL;
3275     }
3276    
3277     void* cfapi_object_take(int* type, ...)
3278     {
3279     object *op;
3280     object *author;
3281     va_list args;
3282    
3283     va_start(args, type);
3284     op = va_arg(args, object*);
3285     author = va_arg(args, object*);
3286     va_end(args);
3287     pick_up(author, op);
3288    
3289     *type = CFAPI_NONE;
3290     return NULL;
3291     }
3292    
3293     void* cfapi_object_say(int* type, ...)
3294     {
3295     static int rv;
3296     object* op;
3297     char* msg;
3298     va_list args;
3299    
3300     va_start(args, type);
3301     op = va_arg(args, object*);
3302     msg = va_arg(args, char*);
3303     va_end(args);
3304    
3305     rv = command_say(op, msg);
3306     *type = CFAPI_INT;
3307     return &rv;
3308     }
3309     void* cfapi_object_speak(int* type, ...)
3310     {
3311     object* op;
3312     char* msg;
3313     va_list args;
3314     static char buf[MAX_BUF];
3315    
3316     va_start(args, type);
3317     op = va_arg(args, object*);
3318     msg = va_arg(args, char*);
3319     va_end(args);
3320    
3321     if (!op || !msg)
3322     return NULL;
3323     sprintf(buf, "%s says: ", op->name);
3324     strncat(buf, msg, MAX_BUF-strlen(buf)-1);
3325     buf[MAX_BUF-1]=0;
3326     new_info_map(NDI_WHITE, op->map, buf);
3327     communicate(op, msg);
3328     *type = CFAPI_NONE;
3329     return NULL;
3330     }
3331     /* PLAYER SUBCLASS */
3332     void* cfapi_player_find(int* type, ...)
3333     {
3334     va_list args;
3335     void* rv;
3336     char* sval;
3337     va_start(args, type);
3338    
3339     sval = va_arg(args, char*);
3340     va_end(args);
3341    
3342     rv = find_player(sval);
3343    
3344     *type = CFAPI_PPLAYER;
3345     return rv;
3346     }
3347     void* cfapi_player_message(int* type, ...)
3348     {
3349     va_list args;
3350     int flags;
3351     int pri;
3352     object* pl;
3353     char* buf;
3354    
3355     va_start(args, type);
3356    
3357     flags = va_arg(args, int);
3358     pri = va_arg(args, int);
3359     pl = va_arg(args, object*);
3360     buf = va_arg(args, char*);
3361     va_end(args);
3362    
3363     new_draw_info(flags, pri, pl, buf);
3364     *type = CFAPI_NONE;
3365     return NULL;
3366     }
3367     void *cfapi_player_send_inventory(int *type, ...)
3368     {
3369     /* Currently a stub. Do we really need this anymore ? */
3370     *type = CFAPI_NONE;
3371     return NULL;
3372     }
3373    
3374     void* cfapi_object_teleport(int *type, ...)
3375     {
3376     mapstruct* map;
3377     int x, y;
3378     object* who;
3379     static int result;
3380     va_list args;
3381    
3382     va_start(args, type);
3383     who = va_arg(args, object*);
3384     map = va_arg(args, mapstruct*);
3385     x = va_arg(args, int);
3386     y = va_arg(args, int);
3387    
3388     if (!out_of_map(map, x, y)) {
3389     int k;
3390     object *tmp;
3391     k = find_first_free_spot(who, map, x, y);
3392     if (k == -1) {
3393     result = 1;
3394     return &result;
3395     }
3396    
3397     send_removed_object(who);
3398     remove_ob(who);
3399    
3400     for (tmp = who; tmp != NULL; tmp = tmp->more)
3401     tmp->x = x+freearr_x[k]+(tmp->arch == NULL ? 0 : tmp->arch->clone.x),
3402     tmp->y = y+freearr_y[k]+(tmp->arch == NULL ? 0 : tmp->arch->clone.y);
3403    
3404     insert_ob_in_map(who, map, NULL, 0);
3405     result = 0;
3406     }
3407    
3408     return &result;
3409     }
3410     void* cfapi_object_pickup(int *type, ...)
3411     {
3412     object* who;
3413     object* what;
3414     va_list args;
3415    
3416     va_start(args, type);
3417     who = va_arg(args, object*);
3418     what = va_arg(args, object*);
3419     va_end(args);
3420    
3421     pick_up(who, what);
3422     *type = CFAPI_NONE;
3423     return NULL;
3424     }
3425    
3426     /* Archetype-related functions */
3427     void* cfapi_archetype_get_first(int* type, ...)
3428     {
3429     va_list args;
3430     va_start(args, type);
3431     va_end(args);
3432     *type = CFAPI_PARCH;
3433     return first_archetype;
3434     }
3435    
3436     void* cfapi_archetype_get_property(int* type, ...)
3437     {
3438     archetype* arch;
3439     int prop;
3440     va_list args;
3441     void* rv;
3442    
3443     va_start(args, type);
3444     arch = va_arg(args, archetype*);
3445     prop = va_arg(args, int);
3446     switch (prop) {
3447     case CFAPI_ARCH_PROP_NAME:
3448     *type = CFAPI_STRING;
3449     rv = (void*)arch->name;
3450     break;
3451    
3452     case CFAPI_ARCH_PROP_NEXT:
3453     *type = CFAPI_PARCH;
3454     rv = arch->next;
3455     break;
3456    
3457     case CFAPI_ARCH_PROP_HEAD:
3458     *type = CFAPI_PARCH;
3459     rv = arch->head;
3460     break;
3461    
3462     case CFAPI_ARCH_PROP_MORE:
3463     *type = CFAPI_PARCH;
3464     rv = arch->more;
3465     break;
3466    
3467     case CFAPI_ARCH_PROP_CLONE:
3468     *type = CFAPI_POBJECT;
3469     rv = &arch->clone;
3470     break;
3471    
3472     default:
3473     *type = CFAPI_NONE;
3474     rv = NULL;
3475     break;
3476     }
3477     va_end(args);
3478     return rv;
3479     }
3480    
3481     /* Party-related functions */
3482     void* cfapi_party_get_property(int* type, ...)
3483     {
3484     partylist* party;
3485     int prop;
3486     va_list args;
3487     void* rv;
3488     object* obarg;
3489     player* pl;
3490    
3491     va_start(args, type);
3492     party = va_arg(args, partylist*);
3493     prop = va_arg(args, int);
3494     switch (prop)
3495     {
3496     case CFAPI_PARTY_PROP_NAME:
3497     *type = CFAPI_STRING;
3498     rv = (void*)party->partyname;
3499     break;
3500    
3501     case CFAPI_PARTY_PROP_NEXT:
3502     *type = CFAPI_PPARTY;
3503     rv = (party ? party->next : get_firstparty());
3504     break;
3505    
3506     case CFAPI_PARTY_PROP_PASSWORD:
3507     *type = CFAPI_STRING;
3508     rv = (void*)party->passwd;
3509     break;
3510    
3511     case CFAPI_PARTY_PROP_PLAYER:
3512     *type = CFAPI_PPLAYER;
3513     obarg = va_arg(args, object*);
3514     pl = (obarg ? obarg->contr : first_player);
3515     rv = NULL;
3516     for (; pl != NULL; pl = pl->next)
3517     if (pl->ob->contr->party == party) {
3518     rv = (void*)pl;
3519     break;
3520     }
3521     break;
3522    
3523     default:
3524     *type = CFAPI_NONE;
3525     rv = NULL;
3526     break;
3527     }
3528     va_end(args);
3529     return rv;
3530     }
3531    
3532     /* Regions-related functions */
3533     void* cfapi_region_get_property(int* type, ...)
3534     {
3535     region* reg;
3536     int prop;
3537     va_list args;
3538     void* rv;
3539    
3540     va_start(args, type);
3541     reg = va_arg(args, region*);
3542     prop = va_arg(args, int);
3543     switch (prop) {
3544     case CFAPI_REGION_PROP_NAME:
3545     *type = CFAPI_STRING;
3546     rv = (void*)reg->name;
3547     break;
3548    
3549     case CFAPI_REGION_PROP_NEXT:
3550     *type = CFAPI_PREGION;
3551     rv = (reg?reg->next:first_region);
3552     break;
3553    
3554     case CFAPI_REGION_PROP_PARENT:
3555     *type = CFAPI_PREGION;
3556     rv = (void*)reg->parent;
3557     break;
3558    
3559     case CFAPI_REGION_PROP_LONGNAME:
3560     *type = CFAPI_STRING;
3561     rv = (void*)reg->longname;
3562     break;
3563    
3564     case CFAPI_REGION_PROP_MESSAGE:
3565     *type = CFAPI_STRING;
3566     rv = (void*)reg->msg;
3567     break;
3568    
3569     default:
3570     *type = CFAPI_NONE;
3571     rv = NULL;
3572     break;
3573     }
3574     va_end(args);
3575     return rv;
3576     }
3577    
3578     /*****************************************************************************/
3579     /* NEW PLUGIN STUFF ENDS HERE */
3580     /*****************************************************************************/
3581    
3582    
3583     /*****************************************************************************/
3584     /* Tries to find if a given command is handled by a plugin. */
3585     /* Note that find_plugin_command is called *before* the internal commands are*/
3586     /* checked, meaning that you can "overwrite" them. */
3587     /*****************************************************************************/
3588     CommArray_s *find_plugin_command(char *cmd, object *op)
3589     {
3590     int i;
3591     crossfire_plugin* cp;
3592     CommArray_s* rtn_cmd;
3593    
3594     if (plugins_list == NULL)
3595     return NULL;
3596    
3597     for (cp = plugins_list; cp != NULL; cp = cp->next) {
3598     rtn_cmd = (CommArray_s*) cp->propfunc(&i, "command?", cmd);
3599     if (rtn_cmd)
3600     return rtn_cmd;
3601     }
3602     return NULL;
3603     }
3604    
3605     /*****************************************************************************/
3606     /* Plugins initialization. Browses the plugins directory and call */
3607     /* initOnePlugin for each file found. */
3608     /* Returns 0 if at least one plugin was successfully loaded, -1 if not */
3609     /*****************************************************************************/
3610     int initPlugins(void)
3611     {
3612     struct dirent *currentfile;
3613     DIR *plugdir;
3614     size_t l;
3615     char buf[MAX_BUF];
3616     char buf2[MAX_BUF];
3617     int result;
3618    
3619     LOG(llevInfo, "Initializing plugins\n");
3620     strcpy(buf, LIBDIR);
3621     strcat(buf, "/plugins/");
3622     LOG(llevInfo, "Plugins directory is %s\n", buf);
3623    
3624     plugdir = opendir(buf);
3625     if (plugdir == NULL)
3626     return -1;
3627    
3628     result = -1;
3629     while ((currentfile = readdir(plugdir)) != NULL) {
3630     l = strlen(currentfile->d_name);
3631     if (l > strlen(PLUGIN_SUFFIX)) {
3632     if (strcmp(currentfile->d_name+l-strlen(PLUGIN_SUFFIX), PLUGIN_SUFFIX) == 0) {
3633     strcpy(buf2, buf);
3634     strcat(buf2, currentfile->d_name);
3635     LOG(llevInfo, " -> Loading plugin : %s\n", currentfile->d_name);
3636     if (plugins_init_plugin(buf2) == 0)
3637     result = 0;
3638     }
3639     }
3640     }
3641    
3642     closedir(plugdir);
3643     return result;
3644     }