ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/plugins.c
Revision: 1.11
Committed: Sun Jun 11 15:02:16 2006 UTC (18 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.10: +11 -0 lines
Log Message:
implement 'ext' packet for extensions to hook directly into the protocol

File Contents

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