ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/plugins.C
Revision: 1.2
Committed: Tue Aug 15 17:10:46 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +56 -8 lines
Log Message:
converted perl to a mandatory / non-dynamic plug-in, firts step to put it fully in-core

File Contents

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