Crossfire Server, Trunk
cfpython.cpp
Go to the documentation of this file.
1 /*****************************************************************************/
2 /* CFPython - A Python module for Crossfire RPG. */
3 /*****************************************************************************/
4 /* This is the third version of the Crossfire Scripting Engine. */
5 /* The first version used Guile. It was directly integrated in the server */
6 /* code, but since Guile wasn't perceived as an easy-to-learn, easy-to-use */
7 /* language by many, it was dropped in favor of Python. */
8 /* The second version, CFPython 1.0, was included as a plugin and provided */
9 /* just about the same level of functionality the current version has. But */
10 /* it used a rather counter-intuitive, procedural way of presenting things. */
11 /* */
12 /* CFPython 2.0 aims at correcting many of the design flaws crippling the */
13 /* older version. It is also the first plugin to be implemented using the */
14 /* new interface, that doesn't need awkward stuff like the horrible CFParm */
15 /* structure. For the Python writer, things should probably be easier and */
16 /* lead to more readable code: instead of writing "CFPython.getObjectXPos(ob)*/
17 /* he/she now can simply write "ob.X". */
18 /* */
19 /*****************************************************************************/
20 /* Please note that it is still very beta - some of the functions may not */
21 /* work as expected and could even cause the server to crash. */
22 /*****************************************************************************/
23 /* Version history: */
24 /* 0.1 "Ophiuchus" - Initial Alpha release */
25 /* 0.5 "Stalingrad" - Message length overflow corrected. */
26 /* 0.6 "Kharkov" - Message and Write correctly redefined. */
27 /* 0.7 "Koursk" - Setting informations implemented. */
28 /* 1.0a "Petersburg" - Last "old-fashioned" version, never submitted to CVS.*/
29 /* 2.0 "Arkangelsk" - First release of the 2.x series. */
30 /*****************************************************************************/
31 /* Version: 2.0beta8 (also known as "Alexander") */
32 /* Contact: yann.chachkoff@myrealbox.com */
33 /*****************************************************************************/
34 /* That code is placed under the GNU General Public Licence (GPL) */
35 /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */
36 /*****************************************************************************/
37 /* CrossFire, A Multiplayer game for X-windows */
38 /* */
39 /* Copyright (C) 2000 Mark Wedel */
40 /* Copyright (C) 1992 Frank Tore Johansen */
41 /* */
42 /* This program is free software; you can redistribute it and/or modify */
43 /* it under the terms of the GNU General Public License as published by */
44 /* the Free Software Foundation; either version 2 of the License, or */
45 /* (at your option) any later version. */
46 /* */
47 /* This program is distributed in the hope that it will be useful, */
48 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
49 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
50 /* GNU General Public License for more details. */
51 /* */
52 /* You should have received a copy of the GNU General Public License */
53 /* along with this program; if not, write to the Free Software */
54 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
55 /* */
56 /*****************************************************************************/
57 
58 /* First let's include the header file needed */
59 
60 #include <cfpython.h>
61 #include <fcntl.h>
62 #include <stdarg.h>
63 // node.h is deprecated in python 3.9, and removed in 3.10 due to a new parser for Python.
64 #ifndef IS_PY3K10
65 #include <node.h>
66 #endif
67 #include <svnversion.h>
68 
70 
71 #define PYTHON_DEBUG
72 #define PYTHON_CACHE_SIZE 256
77 typedef struct {
79  PyCodeObject *code;
80  time_t cached_time,
83 
84 #define MAX_COMMANDS 1024
86 
89 
90 static PyObject *CFPythonError;
91 
93 static void set_exception(const char *fmt, ...) {
94  char buf[1024];
95  va_list arg;
96 
97  va_start(arg, fmt);
98  vsnprintf(buf, sizeof(buf), fmt, arg);
99  va_end(arg);
100 
101  PyErr_SetString(PyExc_ValueError, buf);
102 }
103 
105 
107 
108 static PyObject *shared_data = NULL;
109 
110 static PyObject *private_data = NULL;
111 
112 static CFPContext *popContext(void);
113 static void freeContext(CFPContext *context);
114 static int do_script(CFPContext *context);
115 
116 static PyObject *registerGEvent(PyObject *self, PyObject *args) {
117  int eventcode;
118  (void)self;
119 
120  if (!PyArg_ParseTuple(args, "i", &eventcode))
121  return NULL;
122 
124 
125  Py_INCREF(Py_None);
126  return Py_None;
127 }
128 
129 static PyObject *unregisterGEvent(PyObject *self, PyObject *args) {
130  int eventcode;
131  (void)self;
132 
133  if (!PyArg_ParseTuple(args, "i", &eventcode))
134  return NULL;
135 
137 
138  Py_INCREF(Py_None);
139  return Py_None;
140 }
141 
142 static PyObject *createCFObject(PyObject *self, PyObject *args) {
143  object *op;
144  (void)self;
145  (void)args;
146 
147  op = cf_create_object();
148 
149  return Crossfire_Object_wrap(op);
150 }
151 
152 static PyObject *createCFObjectByName(PyObject *self, PyObject *args) {
153  char *obname;
154  object *op;
155  (void)self;
156 
157  if (!PyArg_ParseTuple(args, "s", &obname))
158  return NULL;
159 
160  op = cf_create_object_by_name(obname);
161 
162  return Crossfire_Object_wrap(op);
163 }
164 
165 static PyObject *getCFPythonVersion(PyObject *self, PyObject *args) {
166  int i = 2044;
167  (void)self;
168  (void)args;
169 
170  return Py_BuildValue("i", i);
171 }
172 
173 static PyObject *getReturnValue(PyObject *self, PyObject *args) {
174  (void)self;
175  (void)args;
176  return Py_BuildValue("i", current_context->returnvalue);
177 }
178 
179 static PyObject *setReturnValue(PyObject *self, PyObject *args) {
180  int i;
181  (void)self;
182 
183  if (!PyArg_ParseTuple(args, "i", &i))
184  return NULL;
186  Py_INCREF(Py_None);
187  return Py_None;
188 }
189 
190 static PyObject *matchString(PyObject *self, PyObject *args) {
191  char *premiere;
192  char *seconde;
193  const char *result;
194  (void)self;
195 
196  if (!PyArg_ParseTuple(args, "ss", &premiere, &seconde))
197  return NULL;
198 
199  result = cf_re_cmp(premiere, seconde);
200  if (result != NULL)
201  return Py_BuildValue("i", 1);
202  else
203  return Py_BuildValue("i", 0);
204 }
205 
206 static PyObject *findPlayer(PyObject *self, PyObject *args) {
207  player *foundpl;
208  char *txt;
209  (void)self;
210 
211  if (!PyArg_ParseTuple(args, "s", &txt))
212  return NULL;
213 
214  foundpl = cf_player_find(txt);
215 
216  if (foundpl != NULL)
217  return Py_BuildValue("O", Crossfire_Object_wrap(foundpl->ob));
218  else {
219  Py_INCREF(Py_None);
220  return Py_None;
221  }
222 }
223 
224 static PyObject *readyMap(PyObject *self, PyObject *args) {
225  char *mapname;
226  mapstruct *map;
227  int flags = 0;
228  (void)self;
229 
230  if (!PyArg_ParseTuple(args, "s|i", &mapname, &flags))
231  return NULL;
232 
234 
235  return Crossfire_Map_wrap(map);
236 }
237 
238 static PyObject *createMap(PyObject *self, PyObject *args) {
239  int sizex, sizey;
240  mapstruct *map;
241  (void)self;
242 
243  if (!PyArg_ParseTuple(args, "ii", &sizex, &sizey))
244  return NULL;
245 
246  map = cf_get_empty_map(sizex, sizey);
247 
248  return Crossfire_Map_wrap(map);
249 }
250 
251 static PyObject *getMapDirectory(PyObject *self, PyObject *args) {
252  (void)self;
253  (void)args;
254  return Py_BuildValue("s", cf_get_directory(0));
255 }
256 
257 static PyObject *getUniqueDirectory(PyObject *self, PyObject *args) {
258  (void)self;
259  (void)args;
260  return Py_BuildValue("s", cf_get_directory(1));
261 }
262 
263 static PyObject *getTempDirectory(PyObject *self, PyObject *args) {
264  (void)self;
265  (void)args;
266  return Py_BuildValue("s", cf_get_directory(2));
267 }
268 
269 static PyObject *getConfigDirectory(PyObject *self, PyObject *args) {
270  (void)self;
271  (void)args;
272  return Py_BuildValue("s", cf_get_directory(3));
273 }
274 
275 static PyObject *getLocalDirectory(PyObject *self, PyObject *args) {
276  (void)self;
277  (void)args;
278  return Py_BuildValue("s", cf_get_directory(4));
279 }
280 
281 static PyObject *getPlayerDirectory(PyObject *self, PyObject *args) {
282  (void)self;
283  (void)args;
284  return Py_BuildValue("s", cf_get_directory(5));
285 }
286 
287 static PyObject *getDataDirectory(PyObject *self, PyObject *args) {
288  (void)self;
289  (void)args;
290  return Py_BuildValue("s", cf_get_directory(6));
291 }
292 
293 static PyObject *getWhoAmI(PyObject *self, PyObject *args) {
294  (void)self;
295  (void)args;
296  if (!current_context->who) {
297  Py_INCREF(Py_None);
298  return Py_None;
299  }
300  Py_INCREF(current_context->who);
301  return current_context->who;
302 }
303 
304 static PyObject *getWhoIsActivator(PyObject *self, PyObject *args) {
305  (void)self;
306  (void)args;
307  if (!current_context->activator) {
308  Py_INCREF(Py_None);
309  return Py_None;
310  }
311  Py_INCREF(current_context->activator);
312  return current_context->activator;
313 }
314 
315 static PyObject *getWhoIsThird(PyObject *self, PyObject *args) {
316  (void)self;
317  (void)args;
318  if (!current_context->third) {
319  Py_INCREF(Py_None);
320  return Py_None;
321  }
322  Py_INCREF(current_context->third);
323  return current_context->third;
324 }
325 
326 static PyObject *getWhatIsMessage(PyObject *self, PyObject *args) {
327  (void)self;
328  (void)args;
329  if (*current_context->message == '\0')
330  return Py_BuildValue("");
331  else
332  return Py_BuildValue("s", current_context->message);
333 }
334 
335 static PyObject *getScriptName(PyObject *self, PyObject *args) {
336  (void)self;
337  (void)args;
338  return Py_BuildValue("s", current_context->script);
339 }
340 
341 static PyObject *getScriptParameters(PyObject *self, PyObject *args) {
342  (void)self;
343  (void)args;
344  if (!*current_context->options) {
345  Py_INCREF(Py_None);
346  return Py_None;
347  }
348  return Py_BuildValue("s", current_context->options);
349 }
350 
351 static PyObject *getEvent(PyObject *self, PyObject *args) {
352  (void)self;
353  (void)args;
354  if (!current_context->event) {
355  Py_INCREF(Py_None);
356  return Py_None;
357  }
358  Py_INCREF(current_context->event);
359  return current_context->event;
360 }
361 
362 static PyObject *getPrivateDictionary(PyObject *self, PyObject *args) {
363  PyObject *data;
364  (void)self;
365  (void)args;
366 
367  data = PyDict_GetItemString(private_data, current_context->script);
368  if (!data) {
369  data = PyDict_New();
370  PyDict_SetItemString(private_data, current_context->script, data);
371  Py_DECREF(data);
372  }
373  Py_INCREF(data);
374  return data;
375 }
376 
377 static PyObject *getSharedDictionary(PyObject *self, PyObject *args) {
378  (void)self;
379  (void)args;
380  Py_INCREF(shared_data);
381  return shared_data;
382 }
383 
384 static PyObject *getArchetypes(PyObject *self, PyObject *args) {
385  PyObject *list;
386  archetype *arch;
387  (void)self;
388  (void)args;
389 
390  list = PyList_New(0);
392  while (arch) {
393  PyList_Append(list, Crossfire_Archetype_wrap(arch));
395  }
396  return list;
397 }
398 
399 static PyObject *getPlayers(PyObject *self, PyObject *args) {
400  PyObject *list;
401  object *pl;
402  (void)self;
403  (void)args;
404 
405  list = PyList_New(0);
407  while (pl) {
408  PyList_Append(list, Crossfire_Object_wrap(pl));
410  }
411  return list;
412 }
413 
414 static PyObject *getMaps(PyObject *self, PyObject *args) {
415  PyObject *list;
416  mapstruct *map;
417  (void)self;
418  (void)args;
419 
420  list = PyList_New(0);
421  map = cf_map_get_first();
422  while (map) {
423  PyList_Append(list, Crossfire_Map_wrap(map));
425  }
426  return list;
427 }
428 
429 static PyObject *getParties(PyObject *self, PyObject *args) {
430  PyObject *list;
431  partylist *party;
432  (void)self;
433  (void)args;
434 
435  list = PyList_New(0);
436  party = cf_party_get_first();
437  while (party) {
438  PyList_Append(list, Crossfire_Party_wrap(party));
439  party = cf_party_get_next(party);
440  }
441  return list;
442 }
443 
444 static PyObject *getRegions(PyObject *self, PyObject *args) {
445  PyObject *list;
446  region *reg;
447  (void)self;
448  (void)args;
449 
450  list = PyList_New(0);
451  reg = cf_region_get_first();
452  while (reg) {
453  PyList_Append(list, Crossfire_Region_wrap(reg));
454  reg = cf_region_get_next(reg);
455  }
456  return list;
457 }
458 
459 static PyObject *getFriendlyList(PyObject *self, PyObject *args) {
460  PyObject *list;
461  object *ob;
462  (void)self;
463  (void)args;
464 
465  list = PyList_New(0);
467  while (ob) {
468  PyList_Append(list, Crossfire_Object_wrap(ob));
470  }
471  return list;
472 }
473 
474 static void python_command_function(object *op, const char *params, const char *script) {
475  char buf[1024], path[1024];
476  CFPContext *context;
477 
478  snprintf(buf, sizeof(buf), "%s.py", cf_get_maps_directory(script, path, sizeof(path)));
479 
480  context = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
481  context->message[0] = 0;
482 
483  context->who = Crossfire_Object_wrap(op);
484  context->activator = NULL;
485  context->third = NULL;
486  /* We are not running from an event, so set it to NULL to avoid segfaults. */
487  context->event = NULL;
488  snprintf(context->script, sizeof(context->script), "%s", buf);
489  if (params)
490  snprintf(context->options, sizeof(context->options), "%s", params);
491  else
492  context->options[0] = 0;
493  context->returnvalue = 1; /* Default is "command successful" */
494 
495  if (!do_script(context)) {
496  freeContext(context);
497  return;
498  }
499 
500  context = popContext();
501  freeContext(context);
502 }
503 
504 static PyObject *registerCommand(PyObject *self, PyObject *args) {
505  char *cmdname;
506  char *scriptname;
507  double cmdspeed;
509  (void)self;
510 
511  if (!PyArg_ParseTuple(args, "ssd|i", &cmdname, &scriptname, &cmdspeed, &type))
512  return NULL;
513 
514  if (cmdspeed < 0) {
515  set_exception("speed must not be negative");
516  return NULL;
517  }
518 
519  if (type < 0 || type > COMMAND_TYPE_WIZARD) {
520  set_exception("type must be between 0 and 2");
521  return NULL;
522  }
523 
524  for (index = 0; index < MAX_COMMANDS; index++) {
525  if (registered_commands[index] == 0) {
526  break;
527  }
528  }
529  if (index == MAX_COMMANDS) {
530  set_exception("too many registered commands");
531  return NULL;
532  }
533 
535  if (registered_commands[index] == 0) {
536  set_exception("failed to register command (overriding an existing one with a different type?)");
537  return NULL;
538  }
539 
540  Py_INCREF(Py_None);
541  return Py_None;
542 }
543 
544 static PyObject *getTime(PyObject *self, PyObject *args) {
545  PyObject *list;
546  timeofday_t tod;
547  (void)self;
548  (void)args;
549 
550  cf_get_time(&tod);
551 
552  list = PyList_New(0);
553  PyList_Append(list, Py_BuildValue("i", tod.year));
554  PyList_Append(list, Py_BuildValue("i", tod.month));
555  PyList_Append(list, Py_BuildValue("i", tod.day));
556  PyList_Append(list, Py_BuildValue("i", tod.hour));
557  PyList_Append(list, Py_BuildValue("i", tod.minute));
558  PyList_Append(list, Py_BuildValue("i", tod.dayofweek));
559  PyList_Append(list, Py_BuildValue("i", tod.weekofmonth));
560  PyList_Append(list, Py_BuildValue("i", tod.season));
561  PyList_Append(list, Py_BuildValue("i", tod.periodofday));
562 
563  return list;
564 }
565 
566 static PyObject *destroyTimer(PyObject *self, PyObject *args) {
567  int id;
568  (void)self;
569 
570  if (!PyArg_ParseTuple(args, "i", &id))
571  return NULL;
572  return Py_BuildValue("i", cf_timer_destroy(id));
573 }
574 
575 static PyObject *getMapHasBeenLoaded(PyObject *self, PyObject *args) {
576  char *name;
577  (void)self;
578 
579  if (!PyArg_ParseTuple(args, "s", &name))
580  return NULL;
582 }
583 
584 static PyObject *findFace(PyObject *self, PyObject *args) {
585  char *name;
586  (void)self;
587 
588  if (!PyArg_ParseTuple(args, "s", &name))
589  return NULL;
590  return Py_BuildValue("i", cf_find_face(name, 0));
591 }
592 
593 static PyObject *log_message(PyObject *self, PyObject *args) {
594  LogLevel level;
595  int intLevel;
596  char *message;
597  (void)self;
598 
599  if (!PyArg_ParseTuple(args, "is", &intLevel, &message))
600  return NULL;
601 
602  switch (intLevel) {
603  case llevError:
604  level = llevError;
605  break;
606 
607  case llevInfo:
608  level = llevInfo;
609  break;
610 
611  case llevDebug:
612  level = llevDebug;
613  break;
614 
615  case llevMonster:
616  level = llevMonster;
617  break;
618 
619  default:
620  return NULL;
621  }
622  if ((message != NULL) && (message[strlen(message)] == '\n'))
623  cf_log(level, "CFPython: %s", message);
624  else
625  cf_log(level, "CFPython: %s\n", message);
626  Py_INCREF(Py_None);
627  return Py_None;
628 }
629 
630 static PyObject *findAnimation(PyObject *self, PyObject *args) {
631  char *name;
632  (void)self;
633 
634  if (!PyArg_ParseTuple(args, "s", &name))
635  return NULL;
636  return Py_BuildValue("i", cf_find_animation(name));
637 }
638 
639 static PyObject *getSeasonName(PyObject *self, PyObject *args) {
640  int i;
641  (void)self;
642 
643  if (!PyArg_ParseTuple(args, "i", &i))
644  return NULL;
645  return Py_BuildValue("s", cf_get_season_name(i));
646 }
647 
648 static PyObject *getMonthName(PyObject *self, PyObject *args) {
649  int i;
650  (void)self;
651 
652  if (!PyArg_ParseTuple(args, "i", &i))
653  return NULL;
654  return Py_BuildValue("s", cf_get_month_name(i));
655 }
656 
657 static PyObject *getWeekdayName(PyObject *self, PyObject *args) {
658  int i;
659  (void)self;
660 
661  if (!PyArg_ParseTuple(args, "i", &i))
662  return NULL;
663  return Py_BuildValue("s", cf_get_weekday_name(i));
664 }
665 
666 static PyObject *getPeriodofdayName(PyObject *self, PyObject *args) {
667  int i;
668  (void)self;
669 
670  if (!PyArg_ParseTuple(args, "i", &i))
671  return NULL;
672  return Py_BuildValue("s", cf_get_periodofday_name(i));
673 }
674 
675 static PyObject *addReply(PyObject *self, PyObject *args) {
676  char *word, *reply;
677  talk_info *talk;
678  (void)self;
679 
680  if (current_context->talk == NULL) {
681  set_exception("not in a dialog context");
682  return NULL;
683  }
684  talk = current_context->talk;
685 
686  if (!PyArg_ParseTuple(args, "ss", &word, &reply)) {
687  return NULL;
688  }
689 
690  if (talk->replies_count == MAX_REPLIES) {
691  set_exception("too many replies");
692  return NULL;
693  }
694 
695  talk->replies_words[talk->replies_count] = cf_add_string(word);
696  talk->replies[talk->replies_count] = cf_add_string(reply);
697  talk->replies_count++;
698  Py_INCREF(Py_None);
699  return Py_None;
700 
701 }
702 
703 static PyObject *setPlayerMessage(PyObject *self, PyObject *args) {
704  char *message;
705  int type = rt_reply;
706  (void)self;
707 
708  if (current_context->talk == NULL) {
709  set_exception("not in a dialog context");
710  return NULL;
711  }
712 
713  if (!PyArg_ParseTuple(args, "s|i", &message, &type)) {
714  return NULL;
715  }
716 
717  if (current_context->talk->message != NULL)
720  current_context->talk->message_type = static_cast<reply_type>(type);
721 
722  Py_INCREF(Py_None);
723  return Py_None;
724 }
725 
726 static PyObject *npcSay(PyObject *self, PyObject *args) {
727  Crossfire_Object *npc = NULL;
728  char *message, buf[2048];
729  (void)self;
730 
731  if (!PyArg_ParseTuple(args, "O!s", &Crossfire_ObjectType, &npc, &message))
732  return NULL;
733 
734  if (current_context->talk == NULL) {
735  set_exception("not in a dialog context");
736  return NULL;
737  }
738 
740  set_exception("too many NPCs");
741  return NULL;
742  }
743 
744  if (strlen(message) >= sizeof(buf) - 1)
745  cf_log(llevError, "CFPython: warning, too long message in npcSay, will be truncated");
747  snprintf(buf, sizeof(buf), "%s says: %s", npc->obj->name, message);
748 
751 
752  Py_INCREF(Py_None);
753  return Py_None;
754 }
755 
756 static PyObject *costStringFromValue(PyObject *self, PyObject *args) {
757  uint64_t value;
758  char buf[2048];
759  int largest_coin = 0;
760  (void)self;
761 
762  if (!PyArg_ParseTuple(args, "L|i", &value, &largest_coin))
763  return NULL;
764 
765  cf_cost_string_from_value(value, largest_coin, buf, sizeof(buf));
766  return Py_BuildValue("s", buf);
767 }
768 
769 PyMethodDef CFPythonMethods[] = {
770  { "WhoAmI", getWhoAmI, METH_NOARGS, NULL },
771  { "WhoIsActivator", getWhoIsActivator, METH_NOARGS, NULL },
772  { "WhoIsOther", getWhoIsThird, METH_NOARGS, NULL },
773  { "WhatIsMessage", getWhatIsMessage, METH_NOARGS, NULL },
774  { "ScriptName", getScriptName, METH_NOARGS, NULL },
775  { "ScriptParameters", getScriptParameters, METH_NOARGS, NULL },
776  { "WhatIsEvent", getEvent, METH_NOARGS, NULL },
777  { "MapDirectory", getMapDirectory, METH_NOARGS, NULL },
778  { "UniqueDirectory", getUniqueDirectory, METH_NOARGS, NULL },
779  { "TempDirectory", getTempDirectory, METH_NOARGS, NULL },
780  { "ConfigDirectory", getConfigDirectory, METH_NOARGS, NULL },
781  { "LocalDirectory", getLocalDirectory, METH_NOARGS, NULL },
782  { "PlayerDirectory", getPlayerDirectory, METH_NOARGS, NULL },
783  { "DataDirectory", getDataDirectory, METH_NOARGS, NULL },
784  { "ReadyMap", readyMap, METH_VARARGS, NULL },
785  { "CreateMap", createMap, METH_VARARGS, NULL },
786  { "FindPlayer", findPlayer, METH_VARARGS, NULL },
787  { "MatchString", matchString, METH_VARARGS, NULL },
788  { "GetReturnValue", getReturnValue, METH_NOARGS, NULL },
789  { "SetReturnValue", setReturnValue, METH_VARARGS, NULL },
790  { "PluginVersion", getCFPythonVersion, METH_NOARGS, NULL },
791  { "CreateObject", createCFObject, METH_NOARGS, NULL },
792  { "CreateObjectByName", createCFObjectByName, METH_VARARGS, NULL },
793  { "GetPrivateDictionary", getPrivateDictionary, METH_NOARGS, NULL },
794  { "GetSharedDictionary", getSharedDictionary, METH_NOARGS, NULL },
795  { "GetPlayers", getPlayers, METH_NOARGS, NULL },
796  { "GetArchetypes", getArchetypes, METH_NOARGS, NULL },
797  { "GetMaps", getMaps, METH_NOARGS, NULL },
798  { "GetParties", getParties, METH_NOARGS, NULL },
799  { "GetRegions", getRegions, METH_NOARGS, NULL },
800  { "GetFriendlyList", getFriendlyList, METH_NOARGS, NULL },
801  { "RegisterCommand", registerCommand, METH_VARARGS, NULL },
802  { "RegisterGlobalEvent", registerGEvent, METH_VARARGS, NULL },
803  { "UnregisterGlobalEvent", unregisterGEvent, METH_VARARGS, NULL },
804  { "GetTime", getTime, METH_NOARGS, NULL },
805  { "DestroyTimer", destroyTimer, METH_VARARGS, NULL },
806  { "MapHasBeenLoaded", getMapHasBeenLoaded, METH_VARARGS, NULL },
807  { "Log", log_message, METH_VARARGS, NULL },
808  { "FindFace", findFace, METH_VARARGS, NULL },
809  { "FindAnimation", findAnimation, METH_VARARGS, NULL },
810  { "GetSeasonName", getSeasonName, METH_VARARGS, NULL },
811  { "GetMonthName", getMonthName, METH_VARARGS, NULL },
812  { "GetWeekdayName", getWeekdayName, METH_VARARGS, NULL },
813  { "GetPeriodofdayName", getPeriodofdayName, METH_VARARGS, NULL },
814  { "AddReply", addReply, METH_VARARGS, NULL },
815  { "SetPlayerMessage", setPlayerMessage, METH_VARARGS, NULL },
816  { "NPCSay", npcSay, METH_VARARGS, NULL },
817  { "CostStringFromValue", costStringFromValue, METH_VARARGS, NULL },
818  { NULL, NULL, 0, NULL }
819 };
820 
821 static void initContextStack(void) {
822  current_context = NULL;
823  context_stack = NULL;
824 }
825 
826 static void pushContext(CFPContext *context) {
827  if (current_context == NULL) {
828  context_stack = context;
829  context->down = NULL;
830  } else {
831  context->down = current_context;
832  }
833  current_context = context;
834 }
835 
836 static CFPContext *popContext(void) {
837  CFPContext *oldcontext;
838 
839  if (current_context != NULL) {
840  oldcontext = current_context;
842  return oldcontext;
843  }
844  else
845  return NULL;
846 }
847 
848 static void freeContext(CFPContext *context) {
849  Py_XDECREF(context->event);
850  Py_XDECREF(context->third);
851  Py_XDECREF(context->who);
852  Py_XDECREF(context->activator);
853  free(context);
854 }
855 
859 static PyObject* cfpython_openpyfile(char *filename) {
860  PyObject *scriptfile;
861  int fd;
862  fd = open(filename, O_RDONLY);
863  if (fd == -1)
864  return NULL;
865  scriptfile = PyFile_FromFd(fd, filename, "r", -1, NULL, NULL, NULL, 1);
866  return scriptfile;
867 }
868 
873 static FILE* cfpython_pyfile_asfile(PyObject* obj) {
874  return fdopen(PyObject_AsFileDescriptor(obj), "r");
875 }
876 
881 static PyObject *catcher = NULL;
882 
883 #ifdef IS_PY3K10
884 
888 static PyObject *io_module = NULL;
889 #endif
890 
897 static void log_python_error(void) {
898 
899  PyErr_Print();
900 
901  if (catcher != NULL) {
902  PyObject *output = PyObject_GetAttrString(catcher, "value"); //get the stdout and stderr from our catchOutErr object
903  PyObject* empty = PyUnicode_FromString("");
904 
905  cf_log_plain(llevError, PyUnicode_AsUTF8(output));
906  Py_DECREF(output);
907 
908  PyObject_SetAttrString(catcher, "value", empty);
909  Py_DECREF(empty);
910  }
911 
912  return;
913 }
914 
915 
917 static PyCodeObject *compilePython(char *filename) {
918  PyObject *scriptfile = NULL;
919  sstring sh_path;
920  struct stat stat_buf;
921  struct _node *n;
922  int i;
923  pycode_cache_entry *replace = NULL, *run = NULL;
924 
925  if (stat(filename, &stat_buf)) {
926  cf_log(llevError, "CFPython: script file %s can't be stat'ed\n", filename);
927  return NULL;
928  }
929 
930  sh_path = cf_add_string(filename);
931 
932  /* Search through cache. Four cases:
933  * 1) script in cache, but older than file -> replace cached
934  * 2) script in cache and up to date -> use cached
935  * 3) script not in cache, cache not full -> add to end of cache
936  * 4) script not in cache, cache full -> replace least recently used
937  */
938  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
939  if (pycode_cache[i].file == NULL) { /* script not in cache, cache not full */
940  replace = &pycode_cache[i]; /* add to end of cache */
941  break;
942  } else if (pycode_cache[i].file == sh_path) {
943  /* script in cache */
944  if (pycode_cache[i].code == NULL || (pycode_cache[i].cached_time < stat_buf.st_mtime)) {
945  /* cache older than file, replace cached */
946  replace = &pycode_cache[i];
947  } else {
948  /* cache uptodate, use cached*/
949  replace = NULL;
950  run = &pycode_cache[i];
951  }
952  break;
953  } else if (replace == NULL || pycode_cache[i].used_time < replace->used_time)
954  /* if we haven't found it yet, set replace to the oldest cache */
955  replace = &pycode_cache[i];
956  }
957 
958  /* replace a specific cache index with the file */
959  if (replace) {
960  Py_XDECREF(replace->code); /* safe to call on NULL */
961  replace->code = NULL;
962 
963  /* Need to replace path string? */
964  if (replace->file != sh_path) {
965  if (replace->file) {
966  cf_free_string(replace->file);
967  }
968  replace->file = cf_add_string(sh_path);
969  }
970 #ifdef IS_PY3K10
971  /* With the new parser in 3.10, we need to read the file contents into a buffer, and then pass that string to compile it.
972  * The new parser removes the PyNode functions as well as PyParser_SimpleParseFile,
973  * so the code needed to be completely rewritten to work.
974  *
975  * Python's solution to these changes is to import the io module and use Python's read method to read in the file,
976  * and then convert the bytes object into a c-string for Py_CompileString
977  *
978  * Though, if it is more performant than the previous code, Py_CompileString is
979  * available for all Python 3, so it is possible to simplify all of them to this if we need to.
980  */
981  if (!io_module)
982  io_module = PyImport_ImportModule("io");
983  scriptfile = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
984  if (!scriptfile) {
985  cf_log(llevDebug, "CFPython: script file %s can't be opened\n", filename);
986  cf_free_string(sh_path);
987  return NULL;
988  }
989  PyObject *source_bytes = PyObject_CallMethod(scriptfile, "read", "");
990  (void)PyObject_CallMethod(scriptfile, "close", "");
991  PyObject *code = Py_CompileString(PyBytes_AsString(source_bytes), filename, Py_file_input);
992  if (code) {
993  replace->code = (PyCodeObject *)code;
994  }
995  if (PyErr_Occurred())
997  else
998  replace->cached_time = stat_buf.st_mtime;
999  run = replace;
1000 #else
1001  /* Load, parse and compile. Note: because Pyhon may have been built with a
1002  * different library than Crossfire, the FILE* it uses may be incompatible.
1003  * Therefore we use PyFile to open the file, then convert to FILE* and get
1004  * Python's own structure. Messy, but can't be helped... */
1005  if (!(scriptfile = cfpython_openpyfile(filename))) {
1006  cf_log(llevDebug, "CFPython: script file %s can't be opened\n", filename);
1007  cf_free_string(sh_path);
1008  return NULL;
1009  } else {
1010  /* Note: FILE* being opaque, it works, but the actual structure may be different! */
1011  FILE* pyfile = cfpython_pyfile_asfile(scriptfile);
1012  if ((n = PyParser_SimpleParseFile(pyfile, filename, Py_file_input))) {
1013  replace->code = PyNode_Compile(n, filename);
1014  PyNode_Free(n);
1015  }
1016  if (PyErr_Occurred())
1017  log_python_error();
1018  else
1019  replace->cached_time = stat_buf.st_mtime;
1020  run = replace;
1021  }
1022 #endif
1023  }
1024 
1025  cf_free_string(sh_path);
1026 
1027  if (scriptfile) {
1028  Py_DECREF(scriptfile);
1029  }
1030 
1031  assert(run != NULL);
1032  run->used_time = time(NULL);
1033  return run->code;
1034 }
1035 
1036 static int do_script(CFPContext *context) {
1037  PyCodeObject *pycode;
1038  PyObject *dict;
1039  PyObject *ret;
1040 
1041  cf_log(llevDebug, "CFPython: running script %s\n", context->script);
1042 
1043  pycode = compilePython(context->script);
1044  if (pycode) {
1045  pushContext(context);
1046  dict = PyDict_New();
1047  PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
1048  ret = PyEval_EvalCode((PyObject *)pycode, dict, NULL);
1049  if (PyErr_Occurred()) {
1050  log_python_error();
1051  }
1052  Py_XDECREF(ret);
1053  Py_DECREF(dict);
1054  return 1;
1055  } else
1056  return 0;
1057 }
1058 
1066 static void addConstants(PyObject *module, const char *name, const CFConstant *constants) {
1067  int i = 0;
1068  char tmp[1024];
1069  PyObject *cst;
1070  PyObject *dict;
1071 
1072  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1073 
1074  cst = PyModule_New(tmp);
1075  dict = PyDict_New();
1076 
1077  while (constants[i].name != NULL) {
1078  PyModule_AddIntConstant(cst, (char *)constants[i].name, constants[i].value);
1079  PyDict_SetItem(dict, PyLong_FromLong(constants[i].value), PyUnicode_FromString(constants[i].name));
1080  i++;
1081  }
1082  PyDict_SetItemString(PyModule_GetDict(module), name, cst);
1083 
1084  snprintf(tmp, sizeof(tmp), "%sName", name);
1085  PyDict_SetItemString(PyModule_GetDict(module), tmp, dict);
1086  Py_DECREF(dict);
1087 }
1088 
1098 static void addSimpleConstants(PyObject *module, const char *name, const CFConstant *constants) {
1099  int i = 0;
1100  char tmp[1024];
1101  PyObject *cst;
1102 
1103  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1104 
1105  cst = PyModule_New(tmp);
1106 
1107  while (constants[i].name != NULL) {
1108  PyModule_AddIntConstant(cst, (char *)constants[i].name, constants[i].value);
1109  i++;
1110  }
1111  PyDict_SetItemString(PyModule_GetDict(module), name, cst);
1112 }
1113 
1115  { "NORTH", 1 },
1116  { "NORTHEAST", 2 },
1117  { "EAST", 3 },
1118  { "SOUTHEAST", 4 },
1119  { "SOUTH", 5 },
1120  { "SOUTHWEST", 6 },
1121  { "WEST", 7 },
1122  { "NORTHWEST", 8 },
1123  { NULL, 0 }
1124 };
1125 
1126 const CFConstant cstType[] = {
1127  { "PLAYER", PLAYER },
1128  { "TRANSPORT", TRANSPORT },
1129  { "ROD", ROD },
1130  { "TREASURE", TREASURE },
1131  { "POTION", POTION },
1132  { "FOOD", FOOD },
1133  { "POISON", POISON },
1134  { "BOOK", BOOK },
1135  { "CLOCK", CLOCK },
1136  { "DRAGON_FOCUS", DRAGON_FOCUS },
1137  { "ARROW", ARROW },
1138  { "BOW", BOW },
1139  { "WEAPON", WEAPON },
1140  { "ARMOUR", ARMOUR },
1141  { "PEDESTAL", PEDESTAL },
1142  { "ALTAR", ALTAR },
1143  { "LOCKED_DOOR", LOCKED_DOOR },
1144  { "SPECIAL_KEY", SPECIAL_KEY },
1145  { "MAP", MAP },
1146  { "DOOR", DOOR },
1147  { "KEY", KEY },
1148  { "TIMED_GATE", TIMED_GATE },
1149  { "TRIGGER", TRIGGER },
1150  { "GRIMREAPER", GRIMREAPER },
1151  { "MAGIC_EAR", MAGIC_EAR },
1152  { "TRIGGER_BUTTON", TRIGGER_BUTTON },
1153  { "TRIGGER_ALTAR", TRIGGER_ALTAR },
1154  { "TRIGGER_PEDESTAL", TRIGGER_PEDESTAL },
1155  { "SHIELD", SHIELD },
1156  { "HELMET", HELMET },
1157  { "MONEY", MONEY },
1158  { "CLASS", CLASS },
1159  { "AMULET", AMULET },
1160  { "PLAYERMOVER", PLAYERMOVER },
1161  { "TELEPORTER", TELEPORTER },
1162  { "CREATOR", CREATOR },
1163  { "SKILL", SKILL },
1164  { "EARTHWALL", EARTHWALL },
1165  { "GOLEM", GOLEM },
1166  { "THROWN_OBJ", THROWN_OBJ },
1167  { "BLINDNESS", BLINDNESS },
1168  { "GOD", GOD },
1169  { "DETECTOR", DETECTOR },
1170  { "TRIGGER_MARKER", TRIGGER_MARKER },
1171  { "DEAD_OBJECT", DEAD_OBJECT },
1172  { "DRINK", DRINK },
1173  { "MARKER", MARKER },
1174  { "HOLY_ALTAR", HOLY_ALTAR },
1175  { "PLAYER_CHANGER", PLAYER_CHANGER },
1176  { "BATTLEGROUND", BATTLEGROUND },
1177  { "PEACEMAKER", PEACEMAKER },
1178  { "GEM", GEM },
1179  { "FIREWALL", FIREWALL },
1180  { "CHECK_INV", CHECK_INV },
1181  { "MOOD_FLOOR", MOOD_FLOOR },
1182  { "EXIT", EXIT },
1183  { "ENCOUNTER", ENCOUNTER },
1184  { "SHOP_FLOOR", SHOP_FLOOR },
1185  { "SHOP_MAT", SHOP_MAT },
1186  { "RING", RING },
1187  { "FLOOR", FLOOR },
1188  { "FLESH", FLESH },
1189  { "INORGANIC", INORGANIC },
1190  { "SKILL_TOOL", SKILL_TOOL },
1191  { "LIGHTER", LIGHTER },
1192  { "WALL", WALL },
1193  { "MISC_OBJECT", MISC_OBJECT },
1194  { "MONSTER", MONSTER },
1195  { "LAMP", LAMP },
1196  { "DUPLICATOR", DUPLICATOR },
1197  { "SPELLBOOK", SPELLBOOK },
1198  { "CLOAK", CLOAK },
1199  { "SPINNER", SPINNER },
1200  { "GATE", GATE },
1201  { "BUTTON", BUTTON },
1202  { "CF_HANDLE", CF_HANDLE },
1203  { "HOLE", HOLE },
1204  { "TRAPDOOR", TRAPDOOR },
1205  { "SIGN", SIGN },
1206  { "BOOTS", BOOTS },
1207  { "GLOVES", GLOVES },
1208  { "SPELL", SPELL },
1209  { "SPELL_EFFECT", SPELL_EFFECT },
1210  { "CONVERTER", CONVERTER },
1211  { "BRACERS", BRACERS },
1212  { "POISONING", POISONING },
1213  { "SAVEBED", SAVEBED },
1214  { "WAND", WAND },
1215  { "SCROLL", SCROLL },
1216  { "DIRECTOR", DIRECTOR },
1217  { "GIRDLE", GIRDLE },
1218  { "FORCE", FORCE },
1219  { "POTION_RESIST_EFFECT", POTION_RESIST_EFFECT },
1220  { "EVENT_CONNECTOR", EVENT_CONNECTOR },
1221  { "CLOSE_CON", CLOSE_CON },
1222  { "CONTAINER", CONTAINER },
1223  { "ARMOUR_IMPROVER", ARMOUR_IMPROVER },
1224  { "WEAPON_IMPROVER", WEAPON_IMPROVER },
1225  { "SKILLSCROLL", SKILLSCROLL },
1226  { "DEEP_SWAMP", DEEP_SWAMP },
1227  { "IDENTIFY_ALTAR", IDENTIFY_ALTAR },
1228  { "SHOP_INVENTORY", SHOP_INVENTORY },
1229  { "RUNE", RUNE },
1230  { "TRAP", TRAP },
1231  { "POWER_CRYSTAL", POWER_CRYSTAL },
1232  { "CORPSE", CORPSE },
1233  { "DISEASE", DISEASE },
1234  { "SYMPTOM", SYMPTOM },
1235  { "BUILDER", BUILDER },
1236  { "MATERIAL", MATERIAL },
1237  { "MIMIC", MIMIC },
1238  { "LIGHTABLE", LIGHTABLE },
1239  { NULL, 0 }
1240 };
1241 
1242 const CFConstant cstMove[] = {
1243  { "WALK", MOVE_WALK },
1244  { "FLY_LOW", MOVE_FLY_LOW },
1245  { "FLY_HIGH", MOVE_FLY_HIGH },
1246  { "FLYING", MOVE_FLYING },
1247  { "SWIM", MOVE_SWIM },
1248  { "BOAT", MOVE_BOAT },
1249  { "ALL", MOVE_ALL },
1250  { NULL, 0 }
1251 };
1252 
1254  { "NDI_BLACK", NDI_BLACK },
1255  { "NDI_WHITE", NDI_WHITE },
1256  { "NDI_NAVY", NDI_NAVY },
1257  { "NDI_RED", NDI_RED },
1258  { "NDI_ORANGE", NDI_ORANGE },
1259  { "NDI_BLUE", NDI_BLUE },
1260  { "NDI_DK_ORANGE", NDI_DK_ORANGE },
1261  { "NDI_GREEN", NDI_GREEN },
1262  { "NDI_LT_GREEN", NDI_LT_GREEN },
1263  { "NDI_GREY", NDI_GREY },
1264  { "NDI_BROWN", NDI_BROWN },
1265  { "NDI_GOLD", NDI_GOLD },
1266  { "NDI_TAN", NDI_TAN },
1267  { "NDI_UNIQUE", NDI_UNIQUE },
1268  { "NDI_ALL", NDI_ALL },
1269  { "NDI_ALL_DMS", NDI_ALL_DMS },
1270  { NULL, 0 }
1271 };
1272 
1274  { "PHYSICAL", AT_PHYSICAL },
1275  { "MAGIC", AT_MAGIC },
1276  { "FIRE", AT_FIRE },
1277  { "ELECTRICITY", AT_ELECTRICITY },
1278  { "COLD", AT_COLD },
1279  { "CONFUSION", AT_CONFUSION },
1280  { "ACID", AT_ACID },
1281  { "DRAIN", AT_DRAIN },
1282  { "WEAPONMAGIC", AT_WEAPONMAGIC },
1283  { "GHOSTHIT", AT_GHOSTHIT },
1284  { "POISON", AT_POISON },
1285  { "SLOW", AT_SLOW },
1286  { "PARALYZE", AT_PARALYZE },
1287  { "TURN_UNDEAD", AT_TURN_UNDEAD },
1288  { "FEAR", AT_FEAR },
1289  { "CANCELLATION", AT_CANCELLATION },
1290  { "DEPLETE", AT_DEPLETE },
1291  { "DEATH", AT_DEATH },
1292  { "CHAOS", AT_CHAOS },
1293  { "COUNTERSPELL", AT_COUNTERSPELL },
1294  { "GODPOWER", AT_GODPOWER },
1295  { "HOLYWORD", AT_HOLYWORD },
1296  { "BLIND", AT_BLIND },
1297  { "INTERNAL", AT_INTERNAL },
1298  { "LIFE_STEALING", AT_LIFE_STEALING },
1299  { "DISEASE", AT_DISEASE },
1300  { NULL, 0 }
1301 };
1302 
1304  { "PHYSICAL", ATNR_PHYSICAL },
1305  { "MAGIC", ATNR_MAGIC },
1306  { "FIRE", ATNR_FIRE },
1307  { "ELECTRICITY", ATNR_ELECTRICITY },
1308  { "COLD", ATNR_COLD },
1309  { "CONFUSION", ATNR_CONFUSION },
1310  { "ACID", ATNR_ACID },
1311  { "DRAIN", ATNR_DRAIN },
1312  { "WEAPONMAGIC", ATNR_WEAPONMAGIC },
1313  { "GHOSTHIT", ATNR_GHOSTHIT },
1314  { "POISON", ATNR_POISON },
1315  { "SLOW", ATNR_SLOW },
1316  { "PARALYZE", ATNR_PARALYZE },
1317  { "TURN_UNDEAD", ATNR_TURN_UNDEAD },
1318  { "FEAR", ATNR_FEAR },
1319  { "CANCELLATION", ATNR_CANCELLATION },
1320  { "DEPLETE", ATNR_DEPLETE },
1321  { "DEATH", ATNR_DEATH },
1322  { "CHAOS", ATNR_CHAOS },
1323  { "COUNTERSPELL", ATNR_COUNTERSPELL },
1324  { "GODPOWER", ATNR_GODPOWER },
1325  { "HOLYWORD", ATNR_HOLYWORD },
1326  { "BLIND", ATNR_BLIND },
1327  { "INTERNAL", ATNR_INTERNAL },
1328  { "LIFE_STEALING", ATNR_LIFE_STEALING },
1329  { "DISEASE", ATNR_DISEASE },
1330  { NULL, 0 }
1331 };
1332 
1335  { "APPLY", EVENT_APPLY },
1336  { "ATTACK", EVENT_ATTACKED },
1337  { "ATTACKS", EVENT_ATTACKS },
1338  { "BOUGHT", EVENT_BOUGHT },
1339  { "CLOSE", EVENT_CLOSE },
1340  { "DEATH", EVENT_DEATH },
1341  { "DESTROY", EVENT_DESTROY },
1342  { "DROP", EVENT_DROP },
1343  { "PICKUP", EVENT_PICKUP },
1344  { "SAY", EVENT_SAY },
1345  { "SELLING", EVENT_SELLING },
1346  { "STOP", EVENT_STOP },
1347  { "TIME", EVENT_TIME },
1348  { "THROW", EVENT_THROW },
1349  { "TRIGGER", EVENT_TRIGGER },
1350  { "TIMER", EVENT_TIMER },
1351  { "USER", EVENT_USER },
1352 
1354  { "BORN", EVENT_BORN },
1355  { "CLOCK", EVENT_CLOCK },
1356  { "CRASH", EVENT_CRASH },
1357  { "GKILL", EVENT_GKILL },
1358  { "KICK", EVENT_KICK },
1359  { "LOGIN", EVENT_LOGIN },
1360  { "LOGOUT", EVENT_LOGOUT },
1361  { "MAPENTER", EVENT_MAPENTER },
1362  { "MAPLEAVE", EVENT_MAPLEAVE },
1363  { "MAPLOAD", EVENT_MAPLOAD },
1364  { "MAPREADY", EVENT_MAPREADY },
1365  { "MAPRESET", EVENT_MAPRESET },
1366  { "MAPUNLOAD", EVENT_MAPUNLOAD },
1367  { "MUZZLE", EVENT_MUZZLE },
1368  { "PLAYER_DEATH", EVENT_PLAYER_DEATH },
1369  { "REMOVE", EVENT_REMOVE },
1370  { "SHOUT", EVENT_SHOUT },
1371  { "TELL", EVENT_TELL },
1372  { NULL, 0 }
1373 };
1374 
1375 const CFConstant cstTime[] = {
1376  { "HOURS_PER_DAY", HOURS_PER_DAY },
1377  { "DAYS_PER_WEEK", DAYS_PER_WEEK },
1378  { "WEEKS_PER_MONTH", WEEKS_PER_MONTH },
1379  { "MONTHS_PER_YEAR", MONTHS_PER_YEAR },
1380  { "SEASONS_PER_YEAR", SEASONS_PER_YEAR },
1381  { "PERIODS_PER_DAY", PERIODS_PER_DAY },
1382  { NULL, 0 }
1383 };
1384 
1386  { "SAY", rt_say },
1387  { "REPLY", rt_reply },
1388  { "QUESTION", rt_question },
1389  { NULL, 0 }
1390 };
1391 
1393  { "DISTATT", DISTATT },
1394  { "RUNATT", RUNATT },
1395  { "HITRUN", HITRUN },
1396  { "WAITATT", WAITATT },
1397  { "RUSH", RUSH },
1398  { "ALLRUN", ALLRUN },
1399  { "DISTHIT", DISTHIT },
1400  { "WAIT2", WAIT2 },
1401  { "PETMOVE", PETMOVE },
1402  { "CIRCLE1", CIRCLE1 },
1403  { "CIRCLE2", CIRCLE2 },
1404  { "PACEH", PACEH },
1405  { "PACEH2", PACEH2 },
1406  { "RANDO", RANDO },
1407  { "RANDO2", RANDO2 },
1408  { "PACEV", PACEV },
1409  { "PACEV2", PACEV2 },
1410  { NULL, 0 }
1411 };
1412 
1413 static void initConstants(PyObject *module) {
1414  addConstants(module, "Direction", cstDirection);
1415  addConstants(module, "Type", cstType);
1416  addConstants(module, "Move", cstMove);
1417  addConstants(module, "MessageFlag", cstMessageFlag);
1418  addConstants(module, "AttackType", cstAttackType);
1419  addConstants(module, "AttackTypeNumber", cstAttackTypeNumber);
1420  addConstants(module, "EventType", cstEventType);
1421  addSimpleConstants(module, "Time", cstTime);
1422  addSimpleConstants(module, "ReplyType", cstReplyTypes);
1423  addSimpleConstants(module, "AttackMovement", cstAttackMovement);
1424 }
1425 
1426 /*
1427  * Set up the main module and handle misc plugin loading stuff and such.
1428  */
1429 
1434 static void cfpython_init_types(PyObject* m) {
1435  PyObject *d = PyModule_GetDict(m);
1436 
1437  Crossfire_ObjectType.tp_new = PyType_GenericNew;
1438  Crossfire_MapType.tp_new = PyType_GenericNew;
1439  Crossfire_PlayerType.tp_new = PyType_GenericNew;
1440  Crossfire_ArchetypeType.tp_new = PyType_GenericNew;
1441  Crossfire_PartyType.tp_new = PyType_GenericNew;
1442  Crossfire_RegionType.tp_new = PyType_GenericNew;
1443  PyType_Ready(&Crossfire_ObjectType);
1444  PyType_Ready(&Crossfire_MapType);
1445  PyType_Ready(&Crossfire_PlayerType);
1446  PyType_Ready(&Crossfire_ArchetypeType);
1447  PyType_Ready(&Crossfire_PartyType);
1448  PyType_Ready(&Crossfire_RegionType);
1449 
1450  Py_INCREF(&Crossfire_ObjectType);
1451  Py_INCREF(&Crossfire_MapType);
1452  Py_INCREF(&Crossfire_PlayerType);
1453  Py_INCREF(&Crossfire_ArchetypeType);
1454  Py_INCREF(&Crossfire_PartyType);
1455  Py_INCREF(&Crossfire_RegionType);
1456 
1457  PyModule_AddObject(m, "Object", (PyObject *)&Crossfire_ObjectType);
1458  PyModule_AddObject(m, "Map", (PyObject *)&Crossfire_MapType);
1459  PyModule_AddObject(m, "Player", (PyObject *)&Crossfire_PlayerType);
1460  PyModule_AddObject(m, "Archetype", (PyObject *)&Crossfire_ArchetypeType);
1461  PyModule_AddObject(m, "Party", (PyObject *)&Crossfire_PartyType);
1462  PyModule_AddObject(m, "Region", (PyObject *)&Crossfire_RegionType);
1463 
1464  PyModule_AddObject(m, "LogError", Py_BuildValue("i", llevError));
1465  PyModule_AddObject(m, "LogInfo", Py_BuildValue("i", llevInfo));
1466  PyModule_AddObject(m, "LogDebug", Py_BuildValue("i", llevDebug));
1467  PyModule_AddObject(m, "LogMonster", Py_BuildValue("i", llevMonster));
1468 
1469  CFPythonError = PyErr_NewException("Crossfire.error", NULL, NULL);
1470  PyDict_SetItemString(d, "error", CFPythonError);
1471 }
1472 
1473 extern PyObject* PyInit_cjson(void);
1474 
1475 static PyModuleDef CrossfireModule = {
1476  PyModuleDef_HEAD_INIT,
1477  "Crossfire", /* m_name */
1478  NULL, /* m_doc */
1479  -1, /* m_size */
1480  CFPythonMethods, /* m_methods */
1481  NULL, /* m_reload */
1482  NULL, /* m_traverse */
1483  NULL, /* m_clear */
1484  NULL /* m_free */
1485 };
1486 
1487 static PyObject* PyInit_Crossfire(void)
1488 {
1489  PyObject *m = PyModule_Create(&CrossfireModule);
1490  Py_INCREF(m);
1491  return m;
1492 }
1493 
1494 extern "C"
1495 int initPlugin(const char *iversion, f_plug_api gethooksptr) {
1496  PyObject *m;
1497  /* Python code to redirect stdouts/stderr. */
1498  const char *stdOutErr =
1499 "import sys\n\
1500 class CatchOutErr:\n\
1501  def __init__(self):\n\
1502  self.value = ''\n\
1503  def write(self, txt):\n\
1504  self.value += txt\n\
1505 catchOutErr = CatchOutErr()\n\
1506 sys.stdout = catchOutErr\n\
1507 sys.stderr = catchOutErr\n\
1508 ";
1509  (void)iversion;
1510 
1511  for (int c = 0; c < MAX_COMMANDS; c++) {
1512  registered_commands[c] = 0;
1513  }
1514 
1515  cf_init_plugin(gethooksptr);
1516  cf_log(llevDebug, "CFPython 2.0a init\n");
1517 
1520 
1521  PyImport_AppendInittab("Crossfire", &PyInit_Crossfire);
1522  PyImport_AppendInittab("cjson", &PyInit_cjson);
1523 
1524  Py_Initialize();
1525 
1526  m = PyImport_ImportModule("Crossfire");
1527 
1529 
1530  initConstants(m);
1531  private_data = PyDict_New();
1532  shared_data = PyDict_New();
1533 
1534  /* Redirect Python's stderr to a special object so it can be put to
1535  * the Crossfire log. */
1536  m = PyImport_AddModule("__main__");
1537  PyRun_SimpleString(stdOutErr);
1538  catcher = PyObject_GetAttrString(m, "catchOutErr");
1539  return 0;
1540 }
1541 
1543  va_list args;
1544  const char *propname;
1545  int size;
1546  char *buf;
1547 
1548  va_start(args, type);
1549  propname = va_arg(args, const char *);
1550  if (!strcmp(propname, "Identification")) {
1551  buf = va_arg(args, char *);
1552  size = va_arg(args, int);
1553  va_end(args);
1554  snprintf(buf, size, PLUGIN_NAME);
1555  return NULL;
1556  } else if (!strcmp(propname, "FullName")) {
1557  buf = va_arg(args, char *);
1558  size = va_arg(args, int);
1559  va_end(args);
1560  snprintf(buf, size, PLUGIN_VERSION);
1561  return NULL;
1562  }
1563  va_end(args);
1564  return NULL;
1565 }
1566 
1567 static int GECodes[] = {
1568  EVENT_BORN,
1569  EVENT_CLOCK,
1571  EVENT_GKILL,
1572  EVENT_LOGIN,
1573  EVENT_LOGOUT,
1577  EVENT_REMOVE,
1578  EVENT_SHOUT,
1579  EVENT_TELL,
1580  EVENT_MUZZLE,
1581  EVENT_KICK,
1583  EVENT_MAPLOAD,
1585  0
1586 };
1587 
1588 static const char* GEPaths[] = {
1589  "born",
1590  "clock",
1591  "death",
1592  "gkill",
1593  "login",
1594  "logout",
1595  "mapenter",
1596  "mapleave",
1597  "mapreset",
1598  "remove",
1599  "shout",
1600  "tell",
1601  "muzzle",
1602  "kick",
1603  "mapunload",
1604  "mapload",
1605  "mapready",
1606  NULL
1607 };
1608 
1614 static void freeEventFiles(char **eventFiles) {
1615  assert(eventFiles);
1616  for (int e = 0; eventFiles[e] != NULL; e++) {
1617  free(eventFiles[e]);
1618  }
1619  free(eventFiles);
1620 }
1621 
1627 static char **getEventFiles(CFPContext *context) {
1628  char **eventFiles = NULL;
1629  char name[NAME_MAX+1], path[NAME_MAX + 1];
1630 
1631  int allocated = 0, current = 0;
1632  DIR *dp;
1633  struct dirent *d;
1634  struct stat sb;
1635 
1636  snprintf(name, sizeof(name), "python/events/%s/", context->options);
1637  cf_get_maps_directory(name, path, sizeof(path));
1638 
1639  dp = opendir(path);
1640  if (dp == NULL) {
1641  eventFiles = static_cast<char **>(calloc(1, sizeof(eventFiles[0])));
1642  eventFiles[0] = NULL;
1643  return eventFiles;
1644  }
1645 
1646  while ((d = readdir(dp)) != NULL) {
1647  snprintf(name, sizeof(name), "%s%s", path, d->d_name);
1648  stat(name, &sb);
1649  if (S_ISDIR(sb.st_mode)) {
1650  continue;
1651  }
1652  if (strcmp(d->d_name + strlen(d->d_name) - 3, ".py")) {
1653  continue;
1654  }
1655 
1656  if (allocated == current) {
1657  allocated += 10;
1658  eventFiles = static_cast<char **>(realloc(eventFiles, sizeof(char *) * (allocated + 1)));
1659  for (int i = current; i < allocated + 1; i++) {
1660  eventFiles[i] = NULL;
1661  }
1662  }
1663  eventFiles[current] = strdup(name);
1664  current++;
1665  }
1666  (void)closedir(dp);
1667  return eventFiles;
1668 }
1669 
1671  PyObject *scriptfile;
1672  char path[1024];
1673  int i;
1674 
1675  cf_log(llevDebug, "CFPython 2.0a post init\n");
1676  initContextStack();
1677  for (i = 0; GECodes[i] != 0; i++)
1679 
1680  scriptfile = cfpython_openpyfile(cf_get_maps_directory("python/events/python_init.py", path, sizeof(path)));
1681  if (scriptfile != NULL) {
1682  FILE* pyfile = cfpython_pyfile_asfile(scriptfile);
1683  PyRun_SimpleFile(pyfile, cf_get_maps_directory("python/events/python_init.py", path, sizeof(path)));
1684  Py_DECREF(scriptfile);
1685  }
1686 
1687  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
1688  pycode_cache[i].code = NULL;
1689  pycode_cache[i].file = NULL;
1690  pycode_cache[i].cached_time = 0;
1691  pycode_cache[i].used_time = 0;
1692  }
1693 
1694  return 0;
1695 }
1696 
1697 static const char *getGlobalEventPath(int code) {
1698  for (int i = 0; GECodes[i] != 0; i++) {
1699  if (GECodes[i] == code)
1700  return GEPaths[i];
1701  }
1702  return "";
1703 }
1704 
1706  va_list args;
1707  int rv = 0;
1708  CFPContext *context;
1709  char *buf;
1710  player *pl;
1711  object *op;
1712  context = static_cast<CFPContext *>(calloc(1, sizeof(CFPContext)));
1713  char **files;
1714 
1715  va_start(args, type);
1716  context->event_code = va_arg(args, int);
1717 
1718  context->message[0] = 0;
1719 
1720  rv = context->returnvalue = 0;
1721  switch (context->event_code) {
1722  case EVENT_CRASH:
1723  cf_log(llevDebug, "CFPython: event_crash unimplemented for now\n");
1724  break;
1725 
1726  case EVENT_BORN:
1727  op = va_arg(args, object *);
1728  context->activator = Crossfire_Object_wrap(op);
1729  break;
1730 
1731  case EVENT_PLAYER_DEATH:
1732  op = va_arg(args, object *);
1733  context->who = Crossfire_Object_wrap(op);
1734  op = va_arg(args, object *);
1735  context->activator = Crossfire_Object_wrap(op);
1736  break;
1737 
1738  case EVENT_GKILL:
1739  {
1740  op = va_arg(args, object *);
1741  object* hitter = va_arg(args, object *);
1742  context->who = Crossfire_Object_wrap(op);
1744  break;
1745  }
1746 
1747  case EVENT_LOGIN:
1748  pl = va_arg(args, player *);
1749  context->activator = Crossfire_Object_wrap(pl->ob);
1750  buf = va_arg(args, char *);
1751  if (buf != NULL)
1752  snprintf(context->message, sizeof(context->message), "%s", buf);
1753  break;
1754 
1755  case EVENT_LOGOUT:
1756  pl = va_arg(args, player *);
1757  context->activator = Crossfire_Object_wrap(pl->ob);
1758  buf = va_arg(args, char *);
1759  if (buf != NULL)
1760  snprintf(context->message, sizeof(context->message), "%s", buf);
1761  break;
1762 
1763  case EVENT_REMOVE:
1764  op = va_arg(args, object *);
1765  context->activator = Crossfire_Object_wrap(op);
1766  break;
1767 
1768  case EVENT_SHOUT:
1769  op = va_arg(args, object *);
1770  context->activator = Crossfire_Object_wrap(op);
1771  buf = va_arg(args, char *);
1772  if (buf != NULL)
1773  snprintf(context->message, sizeof(context->message), "%s", buf);
1774  break;
1775 
1776  case EVENT_MUZZLE:
1777  op = va_arg(args, object *);
1778  context->activator = Crossfire_Object_wrap(op);
1779  buf = va_arg(args, char *);
1780  if (buf != NULL)
1781  snprintf(context->message, sizeof(context->message), "%s", buf);
1782  break;
1783 
1784  case EVENT_KICK:
1785  op = va_arg(args, object *);
1786  context->activator = Crossfire_Object_wrap(op);
1787  buf = va_arg(args, char *);
1788  if (buf != NULL)
1789  snprintf(context->message, sizeof(context->message), "%s", buf);
1790  break;
1791 
1792  case EVENT_MAPENTER:
1793  op = va_arg(args, object *);
1794  context->activator = Crossfire_Object_wrap(op);
1795  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1796  break;
1797 
1798  case EVENT_MAPLEAVE:
1799  op = va_arg(args, object *);
1800  context->activator = Crossfire_Object_wrap(op);
1801  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1802  break;
1803 
1804  case EVENT_CLOCK:
1805  break;
1806 
1807  case EVENT_MAPRESET:
1808  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1809  break;
1810 
1811  case EVENT_TELL:
1812  op = va_arg(args, object *);
1813  buf = va_arg(args, char *);
1814  context->activator = Crossfire_Object_wrap(op);
1815  if (buf != NULL)
1816  snprintf(context->message, sizeof(context->message), "%s", buf);
1817  op = va_arg(args, object *);
1818  context->third = Crossfire_Object_wrap(op);
1819  break;
1820 
1821  case EVENT_MAPUNLOAD:
1822  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1823  break;
1824 
1825  case EVENT_MAPLOAD:
1826  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1827  break;
1828  }
1829  va_end(args);
1830  context->returnvalue = 0;
1831 
1832  if (context->event_code == EVENT_CLOCK) {
1833  // Ignore EVENT_CLOCK. It is not being used in maps, but nevertheless
1834  // runs python_init.py several times per second even while idling.
1835  freeContext(context);
1836  return rv;
1837  }
1838 
1839  snprintf(context->options, sizeof(context->options), "%s", getGlobalEventPath(context->event_code));
1840  files = getEventFiles(context);
1841  for (int file = 0; files[file] != NULL; file++)
1842  {
1843  CFPContext *copy = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
1844  (*copy) = (*context);
1845  Py_XINCREF(copy->activator);
1846  Py_XINCREF(copy->event);
1847  Py_XINCREF(copy->third);
1848  Py_XINCREF(copy->who);
1849  strncpy(copy->script, files[file], sizeof(copy->script));
1850 
1851  if (!do_script(copy)) {
1852  freeContext(copy);
1853  freeEventFiles(files);
1854  return rv;
1855  }
1856 
1857  copy = popContext();
1858  rv = copy->returnvalue;
1859 
1860  freeContext(copy);
1861  }
1862  freeEventFiles(files);
1863 
1864  /* Invalidate freed map wrapper. */
1865  if (context->event_code == EVENT_MAPUNLOAD)
1867 
1868  free(context);
1869 
1870  return rv;
1871 }
1872 
1873 CF_PLUGIN int eventListener(int *type, ...) {
1874  int rv = 0;
1875  va_list args;
1876  char *buf;
1877  CFPContext *context;
1878  object *event;
1879 
1880  context = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
1881 
1882  context->message[0] = 0;
1883 
1884  va_start(args, type);
1885 
1886  context->who = Crossfire_Object_wrap(va_arg(args, object *));
1887  context->activator = Crossfire_Object_wrap(va_arg(args, object *));
1888  context->third = Crossfire_Object_wrap(va_arg(args, object *));
1889  buf = va_arg(args, char *);
1890  if (buf != NULL)
1891  snprintf(context->message, sizeof(context->message), "%s", buf);
1892  /* fix = */va_arg(args, int);
1893  event = va_arg(args, object *);
1894  context->talk = va_arg(args, talk_info *);
1895  context->event_code = event->subtype;
1896  context->event = Crossfire_Object_wrap(event);
1897  cf_get_maps_directory(event->slaying, context->script, sizeof(context->script));
1898  snprintf(context->options, sizeof(context->options), "%s", event->name);
1899  context->returnvalue = 0;
1900 
1901  va_end(args);
1902 
1903  if (!do_script(context)) {
1904  freeContext(context);
1905  return rv;
1906  }
1907 
1908  context = popContext();
1909  rv = context->returnvalue;
1910  freeContext(context);
1911  return rv;
1912 }
1913 
1915  int i;
1916 
1917  cf_log(llevDebug, "CFPython 2.0a closing\n");
1918 
1919  for (int c = 0; c < MAX_COMMANDS; c++) {
1920  if (registered_commands[c]) {
1922  }
1923  }
1924 
1925  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
1926  Py_XDECREF(pycode_cache[i].code);
1927  if (pycode_cache[i].file != NULL)
1929  }
1930 
1931  Py_Finalize();
1932 
1933  return 0;
1934 }
cf_cost_string_from_value
void cf_cost_string_from_value(uint64_t cost, int largest_coin, char *buffer, int length)
Definition: plugin_common.cpp:984
CLASS
@ CLASS
Definition: object.h:141
findPlayer
static PyObject * findPlayer(PyObject *self, PyObject *args)
Definition: cfpython.cpp:206
getMonthName
static PyObject * getMonthName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:648
TRIGGER
@ TRIGGER
Definition: object.h:132
_timeofday::month
int month
Definition: tod.h:40
_cfpcontext::message
char message[1024]
Definition: cfpython.h:97
MIMIC
@ MIMIC
Definition: object.h:252
PLAYER
@ PLAYER
Definition: object.h:110
cf_log
void cf_log(LogLevel logLevel, const char *format,...)
Definition: plugin_common.cpp:1512
ATNR_PARALYZE
#define ATNR_PARALYZE
Definition: attack.h:61
_cfpcontext::third
PyObject * third
Definition: cfpython.h:95
cstMove
const CFConstant cstMove[]
Definition: cfpython.cpp:1242
pycode_cache_entry::used_time
time_t used_time
Definition: cfpython.cpp:81
DAYS_PER_WEEK
#define DAYS_PER_WEEK
Definition: tod.h:16
ATNR_CANCELLATION
#define ATNR_CANCELLATION
Definition: attack.h:64
getCFPythonVersion
static PyObject * getCFPythonVersion(PyObject *self, PyObject *args)
Definition: cfpython.cpp:165
shared_data
static PyObject * shared_data
Definition: cfpython.cpp:108
CF_HANDLE
@ CF_HANDLE
Definition: object.h:211
cf_get_weekday_name
const char * cf_get_weekday_name(int index)
Definition: plugin_common.cpp:1564
cf_add_string
sstring cf_add_string(const char *str)
Definition: plugin_common.cpp:1157
talk_info::replies
sstring replies[MAX_REPLIES]
Definition: dialog.h:59
MAP
@ MAP
Definition: object.h:128
cf_map_get_first
mapstruct * cf_map_get_first(void)
Definition: plugin_common.cpp:965
getSeasonName
static PyObject * getSeasonName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:639
cf_get_directory
const char * cf_get_directory(int id)
Definition: plugin_common.cpp:1120
getLocalDirectory
static PyObject * getLocalDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:275
AT_POISON
#define AT_POISON
Definition: attack.h:86
ATNR_INTERNAL
#define ATNR_INTERNAL
Definition: attack.h:72
AT_MAGIC
#define AT_MAGIC
Definition: attack.h:77
MONSTER
@ MONSTER
Definition: object.h:203
BOW
@ BOW
Definition: object.h:121
BRACERS
@ BRACERS
Definition: object.h:220
CLOSE_CON
@ CLOSE_CON
Definition: object.h:232
WAITATT
#define WAITATT
Definition: define.h:495
llevError
@ llevError
Definition: logger.h:11
ARMOUR_IMPROVER
@ ARMOUR_IMPROVER
Definition: object.h:235
EVENT_CONNECTOR
@ EVENT_CONNECTOR
Definition: object.h:230
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
SYMPTOM
@ SYMPTOM
Definition: object.h:248
WAND
@ WAND
Definition: object.h:223
cf_get_season_name
const char * cf_get_season_name(int index)
Definition: plugin_common.cpp:1546
ALLRUN
#define ALLRUN
Definition: define.h:497
talk_info::replies_words
sstring replies_words[MAX_REPLIES]
Definition: dialog.h:58
talk_info::npc_msg_count
int npc_msg_count
Definition: dialog.h:60
FLESH
@ FLESH
Definition: object.h:190
ENCOUNTER
@ ENCOUNTER
Definition: object.h:185
GLOVES
@ GLOVES
Definition: object.h:216
GIRDLE
@ GIRDLE
Definition: object.h:226
compilePython
static PyCodeObject * compilePython(char *filename)
Definition: cfpython.cpp:917
ATNR_ACID
#define ATNR_ACID
Definition: attack.h:55
BUTTON
@ BUTTON
Definition: object.h:210
_cfpcontext::event_code
int event_code
Definition: cfpython.h:98
cf_archetype_get_first
archetype * cf_archetype_get_first(void)
Definition: plugin_common.cpp:1676
RUNATT
#define RUNATT
Definition: define.h:493
AT_ELECTRICITY
#define AT_ELECTRICITY
Definition: attack.h:79
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
PACEV2
#define PACEV2
Definition: define.h:526
cf_object_get_object_property
object * cf_object_get_object_property(object *op, int propcode)
Definition: plugin_common.cpp:355
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:137
CFAPI_MAP_PROP_NEXT
#define CFAPI_MAP_PROP_NEXT
Definition: plugin.h:264
_timeofday::day
int day
Definition: tod.h:41
NDI_GREEN
#define NDI_GREEN
Definition: newclient.h:249
KEY
@ KEY
Definition: object.h:130
CFBank.open
def open()
Definition: CFBank.py:70
Crossfire_Object
Definition: cfpython_object.h:32
c
static event_registration c
Definition: citylife.cpp:425
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
postInitPlugin
CF_PLUGIN int postInitPlugin(void)
Definition: cfpython.cpp:1670
eventListener
CF_PLUGIN int eventListener(int *type,...)
Definition: cfpython.cpp:1873
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:186
GEM
@ GEM
Definition: object.h:170
pl
Definition: player.h:105
cf_create_object_by_name
object * cf_create_object_by_name(const char *name)
Definition: plugin_common.cpp:1083
HITRUN
#define HITRUN
Definition: define.h:494
HOURS_PER_DAY
#define HOURS_PER_DAY
Definition: tod.h:15
TRAP
@ TRAP
Definition: object.h:244
setPlayerMessage
static PyObject * setPlayerMessage(PyObject *self, PyObject *args)
Definition: cfpython.cpp:703
CFPythonError
static PyObject * CFPythonError
Definition: cfpython.cpp:90
ARMOUR
@ ARMOUR
Definition: object.h:123
guildoracle.list
list
Definition: guildoracle.py:87
SVN_REV
#define SVN_REV
Definition: svnversion.h:2
popContext
static CFPContext * popContext(void)
Definition: cfpython.cpp:836
WEAPON
@ WEAPON
Definition: object.h:122
TIMED_GATE
@ TIMED_GATE
Definition: object.h:131
guildjoin.ob
ob
Definition: guildjoin.py:42
EVENT_TIMER
#define EVENT_TIMER
Definition: events.h:35
say.reply
string reply
Definition: say.py:77
getPrivateDictionary
static PyObject * getPrivateDictionary(PyObject *self, PyObject *args)
Definition: cfpython.cpp:362
cf_timer_destroy
int cf_timer_destroy(int id)
Definition: plugin_common.cpp:1610
_timeofday::year
int year
Definition: tod.h:39
ATNR_SLOW
#define ATNR_SLOW
Definition: attack.h:60
AMULET
@ AMULET
Definition: object.h:142
CHECK_INV
@ CHECK_INV
Definition: object.h:172
getConfigDirectory
static PyObject * getConfigDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:269
mad_mage_user.file
file
Definition: mad_mage_user.py:15
initPlugin
int initPlugin(const char *iversion, f_plug_api gethooksptr)
Definition: cfpython.cpp:1495
pl::ob
object * ob
Definition: player.h:176
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:113
cf_region_get_next
region * cf_region_get_next(region *reg)
Definition: plugin_common.cpp:1900
EVENT_MAPLOAD
#define EVENT_MAPLOAD
Definition: events.h:48
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:264
Crossfire_Party_wrap
PyObject * Crossfire_Party_wrap(partylist *what)
Definition: cfpython_party.cpp:61
SKILL
@ SKILL
Definition: object.h:146
RUNE
@ RUNE
Definition: object.h:243
createCFObject
static PyObject * createCFObject(PyObject *self, PyObject *args)
Definition: cfpython.cpp:142
ATNR_DISEASE
#define ATNR_DISEASE
Definition: attack.h:74
registerCommand
static PyObject * registerCommand(PyObject *self, PyObject *args)
Definition: cfpython.cpp:504
pycode_cache
static pycode_cache_entry pycode_cache[PYTHON_CACHE_SIZE]
Definition: cfpython.cpp:88
Ice.tmp
int tmp
Definition: Ice.py:207
AT_INTERNAL
#define AT_INTERNAL
Definition: attack.h:99
NDI_RED
#define NDI_RED
Definition: newclient.h:245
CREATOR
@ CREATOR
Definition: object.h:145
EVENT_LOGOUT
#define EVENT_LOGOUT
Definition: events.h:45
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:244
RANDO
#define RANDO
Definition: define.h:520
pushContext
static void pushContext(CFPContext *context)
Definition: cfpython.cpp:826
COMMAND_TYPE_NORMAL
#define COMMAND_TYPE_NORMAL
Definition: commands.h:35
_cfpcontext::returnvalue
int returnvalue
Definition: cfpython.h:101
llevMonster
@ llevMonster
Definition: logger.h:14
EVENT_SAY
#define EVENT_SAY
Definition: events.h:29
_timeofday::periodofday
int periodofday
Definition: tod.h:47
TRANSPORT
@ TRANSPORT
Definition: object.h:111
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
POTION_RESIST_EFFECT
@ POTION_RESIST_EFFECT
Definition: object.h:228
FLOOR
@ FLOOR
Definition: object.h:189
_cfpcontext::event
PyObject * event
Definition: cfpython.h:96
SIGN
@ SIGN
Definition: object.h:214
NAME_MAX
#define NAME_MAX
Definition: define.h:30
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.c:101
cf_party_get_next
partylist * cf_party_get_next(partylist *party)
Definition: plugin_common.cpp:1804
ATNR_TURN_UNDEAD
#define ATNR_TURN_UNDEAD
Definition: attack.h:62
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:135
getEventFiles
static char ** getEventFiles(CFPContext *context)
Definition: cfpython.cpp:1627
npc_dialog.filename
filename
Definition: npc_dialog.py:99
Handle_Map_Unload_Hook
void Handle_Map_Unload_Hook(Crossfire_Map *map)
Definition: cfpython_map.cpp:434
NDI_BLUE
#define NDI_BLUE
Definition: newclient.h:247
current_context
CFPContext * current_context
Definition: cfpython.cpp:106
_timeofday::dayofweek
int dayofweek
Definition: tod.h:42
POWER_CRYSTAL
@ POWER_CRYSTAL
Definition: object.h:245
WEEKS_PER_MONTH
#define WEEKS_PER_MONTH
Definition: tod.h:17
AT_LIFE_STEALING
#define AT_LIFE_STEALING
Definition: attack.h:100
buf
StringBuffer * buf
Definition: readable.cpp:1611
_timeofday
Definition: tod.h:38
PACEH
#define PACEH
Definition: define.h:514
POISONING
@ POISONING
Definition: object.h:221
AT_DEATH
#define AT_DEATH
Definition: attack.h:93
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
Crossfire_Object_wrap
PyObject * Crossfire_Object_wrap(object *what)
Definition: cfpython_object.cpp:1609
cstMessageFlag
const CFConstant cstMessageFlag[]
Definition: cfpython.cpp:1253
ATNR_HOLYWORD
#define ATNR_HOLYWORD
Definition: attack.h:70
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
talk_info::message
sstring message
Definition: dialog.h:55
talk_info::replies_count
int replies_count
Definition: dialog.h:57
archt
Definition: object.h:472
obj
Definition: object.h:280
getDataDirectory
static PyObject * getDataDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:287
TRIGGER_MARKER
@ TRIGGER_MARKER
Definition: object.h:156
Crossfire_PlayerType
PyTypeObject Crossfire_PlayerType
ATNR_BLIND
#define ATNR_BLIND
Definition: attack.h:71
m
static event_registration m
Definition: citylife.cpp:425
getPluginProperty
CF_PLUGIN void * getPluginProperty(int *type,...)
Definition: cfpython.cpp:1542
AT_CHAOS
#define AT_CHAOS
Definition: attack.h:94
CLOAK
@ CLOAK
Definition: object.h:207
pycode_cache_entry::cached_time
time_t cached_time
Definition: cfpython.cpp:80
_timeofday::season
int season
Definition: tod.h:46
opendir
DIR * opendir(const char *)
EVENT_LOGIN
#define EVENT_LOGIN
Definition: events.h:44
HELMET
@ HELMET
Definition: object.h:139
disinfect.map
map
Definition: disinfect.py:4
POISON
@ POISON
Definition: object.h:116
setReturnValue
static PyObject * setReturnValue(PyObject *self, PyObject *args)
Definition: cfpython.cpp:179
cf_log_plain
void cf_log_plain(LogLevel logLevel, const char *message)
Definition: plugin_common.cpp:1532
EVENT_STOP
#define EVENT_STOP
Definition: events.h:31
cf_party_get_first
partylist * cf_party_get_first(void)
Definition: plugin_common.cpp:1773
EVENT_CLOCK
#define EVENT_CLOCK
Definition: events.h:40
getArchetypes
static PyObject * getArchetypes(PyObject *self, PyObject *args)
Definition: cfpython.cpp:384
DEEP_SWAMP
@ DEEP_SWAMP
Definition: object.h:239
make_face_from_files.args
args
Definition: make_face_from_files.py:31
MARKER
@ MARKER
Definition: object.h:161
rotate-tower.result
bool result
Definition: rotate-tower.py:13
getMapHasBeenLoaded
static PyObject * getMapHasBeenLoaded(PyObject *self, PyObject *args)
Definition: cfpython.cpp:575
GEPaths
static const char * GEPaths[]
Definition: cfpython.cpp:1588
EVENT_PICKUP
#define EVENT_PICKUP
Definition: events.h:28
EVENT_CRASH
#define EVENT_CRASH
Definition: events.h:41
getMapDirectory
static PyObject * getMapDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:251
SAVEBED
@ SAVEBED
Definition: object.h:222
EVENT_SELLING
#define EVENT_SELLING
Definition: events.h:30
AT_COLD
#define AT_COLD
Definition: attack.h:80
CF_PLUGIN
#define CF_PLUGIN
Definition: plugin_common.h:38
SEASONS_PER_YEAR
#define SEASONS_PER_YEAR
Definition: tod.h:19
LIGHTABLE
@ LIGHTABLE
Definition: object.h:253
POTION
@ POTION
Definition: object.h:114
_cfpcontext::down
struct _cfpcontext * down
Definition: cfpython.h:92
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
cf_find_face
int cf_find_face(const char *name, int error)
Definition: plugin_common.cpp:1500
BUILDER
@ BUILDER
Definition: object.h:249
EVENT_DROP
#define EVENT_DROP
Definition: events.h:27
_cfpcontext::who
PyObject * who
Definition: cfpython.h:93
findFace
static PyObject * findFace(PyObject *self, PyObject *args)
Definition: cfpython.cpp:584
EVENT_TRIGGER
#define EVENT_TRIGGER
Definition: events.h:34
f_plug_api
void(* f_plug_api)(int *type,...)
Definition: plugin.h:81
EVENT_MAPENTER
#define EVENT_MAPENTER
Definition: events.h:46
cstDirection
const CFConstant cstDirection[]
Definition: cfpython.cpp:1114
npcSay
static PyObject * npcSay(PyObject *self, PyObject *args)
Definition: cfpython.cpp:726
cf_system_unregister_global_event
void cf_system_unregister_global_event(int event, const char *name)
Definition: plugin_common.cpp:1099
cf_get_month_name
const char * cf_get_month_name(int index)
Definition: plugin_common.cpp:1555
cf_init_plugin
int cf_init_plugin(f_plug_api getHooks)
Definition: plugin_common.cpp:141
ROD
@ ROD
Definition: object.h:112
CONTAINER
@ CONTAINER
Definition: object.h:234
INORGANIC
@ INORGANIC
Definition: object.h:191
_timeofday::weekofmonth
int weekofmonth
Definition: tod.h:45
readdir
struct dirent * readdir(DIR *)
python_init.path
path
Definition: python_init.py:8
cf_get_empty_map
mapstruct * cf_get_empty_map(int sizex, int sizey)
Definition: plugin_common.cpp:938
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:126
PLAYERMOVER
@ PLAYERMOVER
Definition: object.h:143
PLUGIN_NAME
#define PLUGIN_NAME
Definition: cfanim.h:32
cf_region_get_first
region * cf_region_get_first(void)
Definition: plugin_common.cpp:1868
unregisterGEvent
static PyObject * unregisterGEvent(PyObject *self, PyObject *args)
Definition: cfpython.cpp:129
EVENT_MAPRESET
#define EVENT_MAPRESET
Definition: events.h:50
cfpython.h
pycode_cache_entry::code
PyCodeObject * code
Definition: cfpython.cpp:79
addSimpleConstants
static void addSimpleConstants(PyObject *module, const char *name, const CFConstant *constants)
Definition: cfpython.cpp:1098
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:127
MOVE_FLYING
#define MOVE_FLYING
Definition: define.h:395
HOLE
@ HOLE
Definition: object.h:212
costStringFromValue
static PyObject * costStringFromValue(PyObject *self, PyObject *args)
Definition: cfpython.cpp:756
PEACEMAKER
@ PEACEMAKER
Definition: object.h:167
MAX_NPC
#define MAX_NPC
Definition: dialog.h:47
CIRCLE2
#define CIRCLE2
Definition: define.h:513
SvnRevPlugin
CF_PLUGIN char SvnRevPlugin[]
Definition: cfpython.cpp:69
do_script
static int do_script(CFPContext *context)
Definition: cfpython.cpp:1036
getSharedDictionary
static PyObject * getSharedDictionary(PyObject *self, PyObject *args)
Definition: cfpython.cpp:377
EVENT_BORN
#define EVENT_BORN
Definition: events.h:39
guild_questpoints_apply.mapname
mapname
Definition: guild_questpoints_apply.py:8
CONVERTER
@ CONVERTER
Definition: object.h:219
GECodes
static int GECodes[]
Definition: cfpython.cpp:1567
EVENT_MAPUNLOAD
#define EVENT_MAPUNLOAD
Definition: events.h:51
SKILLSCROLL
@ SKILLSCROLL
Definition: object.h:237
createMap
static PyObject * createMap(PyObject *self, PyObject *args)
Definition: cfpython.cpp:238
set_exception
static void set_exception(const char *fmt,...)
Definition: cfpython.cpp:93
ATNR_DRAIN
#define ATNR_DRAIN
Definition: attack.h:56
catcher
static PyObject * catcher
Definition: cfpython.cpp:881
navar-midane_time.data
data
Definition: navar-midane_time.py:11
NDI_GOLD
#define NDI_GOLD
Definition: newclient.h:254
Crossfire_Archetype_wrap
PyObject * Crossfire_Archetype_wrap(archetype *what)
Definition: cfpython_archetype.cpp:62
DRAGON_FOCUS
@ DRAGON_FOCUS
Definition: object.h:119
rt_say
@ rt_say
Definition: dialog.h:10
LAMP
@ LAMP
Definition: object.h:204
getFriendlyList
static PyObject * getFriendlyList(PyObject *self, PyObject *args)
Definition: cfpython.cpp:459
GOLEM
@ GOLEM
Definition: object.h:148
init_object_assoc_table
void init_object_assoc_table(void)
Definition: cfpython_object.cpp:60
registered_commands
static command_registration registered_commands[MAX_COMMANDS]
Definition: cfpython.cpp:85
sstring
const typedef char * sstring
Definition: global.h:43
ATNR_COUNTERSPELL
#define ATNR_COUNTERSPELL
Definition: attack.h:68
closePlugin
CF_PLUGIN int closePlugin(void)
Definition: cfpython.cpp:1914
getPlayers
static PyObject * getPlayers(PyObject *self, PyObject *args)
Definition: cfpython.cpp:399
EVENT_USER
#define EVENT_USER
Definition: events.h:36
MOOD_FLOOR
@ MOOD_FLOOR
Definition: object.h:173
ATNR_POISON
#define ATNR_POISON
Definition: attack.h:59
ARROW
@ ARROW
Definition: object.h:120
EVENT_THROW
#define EVENT_THROW
Definition: events.h:33
ATNR_DEATH
#define ATNR_DEATH
Definition: attack.h:66
rt_reply
@ rt_reply
Definition: dialog.h:11
PACEV
#define PACEV
Definition: define.h:524
mapdef
Definition: map.h:317
BOOK
@ BOOK
Definition: object.h:117
empty
const char * empty[]
Definition: check_treasure.cpp:107
Crossfire_Region_wrap
PyObject * Crossfire_Region_wrap(region *what)
Definition: cfpython_region.cpp:72
RING
@ RING
Definition: object.h:188
EVENT_SHOUT
#define EVENT_SHOUT
Definition: events.h:55
BLINDNESS
@ BLINDNESS
Definition: object.h:150
replace
Definition: replace.py:1
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
cf_map_get_map_property
mapstruct * cf_map_get_map_property(mapstruct *map, int propcode)
Definition: plugin_common.cpp:269
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
getUniqueDirectory
static PyObject * getUniqueDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:257
party_struct
Definition: party.h:10
matchString
static PyObject * matchString(PyObject *self, PyObject *args)
Definition: cfpython.cpp:190
CLOCK
@ CLOCK
Definition: object.h:118
cf_free_string
void cf_free_string(sstring str)
Definition: plugin_common.cpp:1172
cstTime
const CFConstant cstTime[]
Definition: cfpython.cpp:1375
SHOP_MAT
@ SHOP_MAT
Definition: object.h:187
EVENT_BOUGHT
#define EVENT_BOUGHT
Definition: events.h:23
COMMAND_TYPE_WIZARD
#define COMMAND_TYPE_WIZARD
Definition: commands.h:39
_cfpcontext::script
char script[1024]
Definition: cfpython.h:99
destroyTimer
static PyObject * destroyTimer(PyObject *self, PyObject *args)
Definition: cfpython.cpp:566
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Definition: define.h:393
EVENT_PLAYER_DEATH
#define EVENT_PLAYER_DEATH
Definition: events.h:53
ATNR_FIRE
#define ATNR_FIRE
Definition: attack.h:51
cfpython_pyfile_asfile
static FILE * cfpython_pyfile_asfile(PyObject *obj)
Definition: cfpython.cpp:873
_cfpcontext::talk
struct talk_info * talk
Definition: cfpython.h:102
cstType
const CFConstant cstType[]
Definition: cfpython.cpp:1126
cf_system_register_command_extra
command_registration cf_system_register_command_extra(const char *name, const char *extra, command_function_extra func, uint8_t command_type, float time)
Definition: plugin_common.cpp:2093
EXIT
@ EXIT
Definition: object.h:184
getPlayerDirectory
static PyObject * getPlayerDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:281
MAGIC_EAR
@ MAGIC_EAR
Definition: object.h:134
MONTHS_PER_YEAR
#define MONTHS_PER_YEAR
Definition: tod.h:18
getWeekdayName
static PyObject * getWeekdayName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:657
PLUGIN_VERSION
#define PLUGIN_VERSION
Definition: cfanim.h:33
getMaps
static PyObject * getMaps(PyObject *self, PyObject *args)
Definition: cfpython.cpp:414
cstReplyTypes
const CFConstant cstReplyTypes[]
Definition: cfpython.cpp:1385
diamondslots.message
string message
Definition: diamondslots.py:57
replace
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Definition: utils.cpp:337
reply_type
reply_type
Definition: dialog.h:9
cf_system_register_global_event
void cf_system_register_global_event(int event, const char *name, f_plug_event hook)
Definition: plugin_common.cpp:1092
llevInfo
@ llevInfo
Definition: logger.h:12
dirent
#define dirent
Definition: xdir.h:12
talk_info::message_type
reply_type message_type
Definition: dialog.h:56
autojail.dict
dict
Definition: autojail.py:7
cfpython_openpyfile
static PyObject * cfpython_openpyfile(char *filename)
Definition: cfpython.cpp:859
getTempDirectory
static PyObject * getTempDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:263
pycode_cache_entry::file
sstring file
Definition: cfpython.cpp:78
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:52
cf_find_animation
int cf_find_animation(const char *txt)
Definition: plugin_common.cpp:1488
MAX_COMMANDS
#define MAX_COMMANDS
Definition: cfpython.cpp:84
AT_BLIND
#define AT_BLIND
Definition: attack.h:98
getReturnValue
static PyObject * getReturnValue(PyObject *self, PyObject *args)
Definition: cfpython.cpp:173
CFPythonMethods
PyMethodDef CFPythonMethods[]
Definition: cfpython.cpp:769
EVENT_TELL
#define EVENT_TELL
Definition: events.h:56
ATNR_CHAOS
#define ATNR_CHAOS
Definition: attack.h:67
EVENT_DEATH
#define EVENT_DEATH
Definition: events.h:25
BATTLEGROUND
@ BATTLEGROUND
Definition: object.h:166
Crossfire_PartyType
PyTypeObject Crossfire_PartyType
cf_archetype_get_next
archetype * cf_archetype_get_next(archetype *arch)
Definition: plugin_common.cpp:1709
AT_SLOW
#define AT_SLOW
Definition: attack.h:87
CFConstant
Definition: cfpython.h:105
MAX_REPLIES
#define MAX_REPLIES
Definition: dialog.h:45
AT_TURN_UNDEAD
#define AT_TURN_UNDEAD
Definition: attack.h:89
cf_get_periodofday_name
const char * cf_get_periodofday_name(int index)
Definition: plugin_common.cpp:1573
getWhatIsMessage
static PyObject * getWhatIsMessage(PyObject *self, PyObject *args)
Definition: cfpython.cpp:326
GRIMREAPER
@ GRIMREAPER
Definition: object.h:133
getScriptName
static PyObject * getScriptName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:335
ATNR_DEPLETE
#define ATNR_DEPLETE
Definition: attack.h:65
CrossfireModule
static PyModuleDef CrossfireModule
Definition: cfpython.cpp:1475
EARTHWALL
@ EARTHWALL
Definition: object.h:147
python_command_function
static void python_command_function(object *op, const char *params, const char *script)
Definition: cfpython.cpp:474
DUPLICATOR
@ DUPLICATOR
Definition: object.h:205
DISEASE
@ DISEASE
Definition: object.h:247
FIREWALL
@ FIREWALL
Definition: object.h:171
TRIGGER_ALTAR
@ TRIGGER_ALTAR
Definition: object.h:136
getGlobalEventPath
static const char * getGlobalEventPath(int code)
Definition: cfpython.cpp:1697
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:165
createCFObjectByName
static PyObject * createCFObjectByName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:152
cstAttackType
const CFConstant cstAttackType[]
Definition: cfpython.cpp:1273
LIGHTER
@ LIGHTER
Definition: object.h:193
rt_question
@ rt_question
Definition: dialog.h:12
PERIODS_PER_DAY
#define PERIODS_PER_DAY
Definition: tod.h:20
give.op
op
Definition: give.py:33
NDI_ALL
#define NDI_ALL
Definition: newclient.h:263
_cfpcontext::activator
PyObject * activator
Definition: cfpython.h:94
cstAttackTypeNumber
const CFConstant cstAttackTypeNumber[]
Definition: cfpython.cpp:1303
autojail.value
value
Definition: autojail.py:6
AT_DEPLETE
#define AT_DEPLETE
Definition: attack.h:92
Crossfire_ArchetypeType
PyTypeObject Crossfire_ArchetypeType
cf_map_has_been_loaded
mapstruct * cf_map_has_been_loaded(const char *name)
Definition: plugin_common.cpp:951
MATERIAL
@ MATERIAL
Definition: object.h:251
EVENT_TIME
#define EVENT_TIME
Definition: events.h:32
cf_re_cmp
const char * cf_re_cmp(const char *str, const char *regexp)
Definition: plugin_common.cpp:1133
EVENT_MAPLEAVE
#define EVENT_MAPLEAVE
Definition: events.h:47
SPINNER
@ SPINNER
Definition: object.h:208
getRegions
static PyObject * getRegions(PyObject *self, PyObject *args)
Definition: cfpython.cpp:444
AT_WEAPONMAGIC
#define AT_WEAPONMAGIC
Definition: attack.h:84
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:218
readyMap
static PyObject * readyMap(PyObject *self, PyObject *args)
Definition: cfpython.cpp:224
SKILL_TOOL
@ SKILL_TOOL
Definition: object.h:192
getParties
static PyObject * getParties(PyObject *self, PyObject *args)
Definition: cfpython.cpp:429
ATNR_MAGIC
#define ATNR_MAGIC
Definition: attack.h:50
roll-o-matic.params
params
Definition: roll-o-matic.py:193
SHOP_INVENTORY
@ SHOP_INVENTORY
Definition: object.h:241
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:243
PEDESTAL
@ PEDESTAL
Definition: object.h:124
cf_create_object
object * cf_create_object(void)
Definition: plugin_common.cpp:1071
cf_get_maps_directory
char * cf_get_maps_directory(const char *name, char *buf, int size)
Definition: plugin_common.cpp:1059
npc_dialog.index
int index
Definition: npc_dialog.py:102
NDI_BROWN
#define NDI_BROWN
Definition: newclient.h:253
talk_info
Definition: dialog.h:52
NDI_TAN
#define NDI_TAN
Definition: newclient.h:255
EVENT_REMOVE
#define EVENT_REMOVE
Definition: events.h:54
init_map_assoc_table
void init_map_assoc_table(void)
Definition: cfpython_map.cpp:37
freeEventFiles
static void freeEventFiles(char **eventFiles)
Definition: cfpython.cpp:1614
cfpython_init_types
static void cfpython_init_types(PyObject *m)
Definition: cfpython.cpp:1434
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:248
addReply
static PyObject * addReply(PyObject *self, PyObject *args)
Definition: cfpython.cpp:675
level
int level
Definition: readable.cpp:1609
pycode_cache_entry
Definition: cfpython.cpp:77
initConstants
static void initConstants(PyObject *module)
Definition: cfpython.cpp:1413
DEAD_OBJECT
@ DEAD_OBJECT
Definition: object.h:159
ATNR_WEAPONMAGIC
#define ATNR_WEAPONMAGIC
Definition: attack.h:57
DIRECTOR
@ DIRECTOR
Definition: object.h:225
getWhoIsThird
static PyObject * getWhoIsThird(PyObject *self, PyObject *args)
Definition: cfpython.cpp:315
CORPSE
@ CORPSE
Definition: object.h:246
getScriptParameters
static PyObject * getScriptParameters(PyObject *self, PyObject *args)
Definition: cfpython.cpp:341
talk_info::npc_msgs
sstring npc_msgs[MAX_NPC]
Definition: dialog.h:61
npc_dialog.npc
npc
Definition: npc_dialog.py:95
Crossfire_RegionType
PyTypeObject Crossfire_RegionType
cf_player_find
player * cf_player_find(const char *plname)
Definition: plugin_common.cpp:815
cf_friendlylist_get_next
object * cf_friendlylist_get_next(object *ob)
Definition: plugin_common.cpp:2026
_cfpcontext
Definition: cfpython.h:91
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
AT_DISEASE
#define AT_DISEASE
Definition: attack.h:102
AT_ACID
#define AT_ACID
Definition: attack.h:82
cf_system_unregister_command
void cf_system_unregister_command(command_registration command)
Definition: plugin_common.cpp:2101
AT_FEAR
#define AT_FEAR
Definition: attack.h:90
FOOD
@ FOOD
Definition: object.h:115
AT_GODPOWER
#define AT_GODPOWER
Definition: attack.h:96
PYTHON_CACHE_SIZE
#define PYTHON_CACHE_SIZE
Definition: cfpython.cpp:72
MOVE_BOAT
#define MOVE_BOAT
Definition: define.h:397
MOVE_FLY_HIGH
#define MOVE_FLY_HIGH
Definition: define.h:394
context_stack
CFPContext * context_stack
Definition: cfpython.cpp:104
EVENT_ATTACKED
#define EVENT_ATTACKED
Definition: events.h:21
EVENT_MAPREADY
#define EVENT_MAPREADY
Definition: events.h:49
ALTAR
@ ALTAR
Definition: object.h:125
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
DOOR
@ DOOR
Definition: object.h:129
EVENT_CLOSE
#define EVENT_CLOSE
Definition: events.h:24
command_registration
uint64_t command_registration
Definition: commands.h:32
AT_CONFUSION
#define AT_CONFUSION
Definition: attack.h:81
cf_map_get_map
mapstruct * cf_map_get_map(const char *name, int flags)
Definition: plugin_common.cpp:925
WAIT2
#define WAIT2
Definition: define.h:499
DRINK
@ DRINK
Definition: object.h:160
ATNR_GHOSTHIT
#define ATNR_GHOSTHIT
Definition: attack.h:58
WALL
@ WALL
Definition: object.h:194
ATNR_COLD
#define ATNR_COLD
Definition: attack.h:53
WEAPON_IMPROVER
@ WEAPON_IMPROVER
Definition: object.h:236
SCROLL
@ SCROLL
Definition: object.h:224
AT_CANCELLATION
#define AT_CANCELLATION
Definition: attack.h:91
DISTHIT
#define DISTHIT
Definition: define.h:498
RUSH
#define RUSH
Definition: define.h:496
PETMOVE
#define PETMOVE
Definition: define.h:501
registerGEvent
static PyObject * registerGEvent(PyObject *self, PyObject *args)
Definition: cfpython.cpp:116
death_message.hitter
hitter
Definition: death_message.py:33
cstAttackMovement
const CFConstant cstAttackMovement[]
Definition: cfpython.cpp:1392
LogLevel
LogLevel
Definition: logger.h:10
MOVE_SWIM
#define MOVE_SWIM
Definition: define.h:396
DISTATT
#define DISTATT
Definition: define.h:491
cf_friendlylist_get_first
object * cf_friendlylist_get_first(void)
Definition: plugin_common.cpp:2010
log_message
static PyObject * log_message(PyObject *self, PyObject *args)
Definition: cfpython.cpp:593
_timeofday::minute
int minute
Definition: tod.h:44
EVENT_ATTACKS
#define EVENT_ATTACKS
Definition: events.h:22
svnversion.h
BOOTS
@ BOOTS
Definition: object.h:215
AT_PARALYZE
#define AT_PARALYZE
Definition: attack.h:88
ATNR_ELECTRICITY
#define ATNR_ELECTRICITY
Definition: attack.h:52
AT_HOLYWORD
#define AT_HOLYWORD
Definition: attack.h:97
IDENTIFY_ALTAR
@ IDENTIFY_ALTAR
Definition: object.h:240
SPELL
@ SPELL
Definition: object.h:217
AT_GHOSTHIT
#define AT_GHOSTHIT
Definition: attack.h:85
EVENT_DESTROY
#define EVENT_DESTROY
Definition: events.h:26
replace.current
current
Definition: replace.py:64
getWhoAmI
static PyObject * getWhoAmI(PyObject *self, PyObject *args)
Definition: cfpython.cpp:293
closedir
int closedir(DIR *)
log_python_error
static void log_python_error(void)
Definition: cfpython.cpp:897
getTime
static PyObject * getTime(PyObject *self, PyObject *args)
Definition: cfpython.cpp:544
EVENT_GKILL
#define EVENT_GKILL
Definition: events.h:42
addConstants
static void addConstants(PyObject *module, const char *name, const CFConstant *constants)
Definition: cfpython.cpp:1066
SHIELD
@ SHIELD
Definition: object.h:138
CIRCLE1
#define CIRCLE1
Definition: define.h:509
TELEPORTER
@ TELEPORTER
Definition: object.h:144
Crossfire_Map_wrap
PyObject * Crossfire_Map_wrap(mapstruct *what)
Definition: cfpython_map.cpp:439
private_data
static PyObject * private_data
Definition: cfpython.cpp:110
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
ATNR_LIFE_STEALING
#define ATNR_LIFE_STEALING
Definition: attack.h:73
PACEH2
#define PACEH2
Definition: define.h:516
Crossfire_Map
Definition: cfpython_map.h:32
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:149
NDI_GREY
#define NDI_GREY
Definition: newclient.h:252
SPELLBOOK
@ SPELLBOOK
Definition: object.h:206
Crossfire_ObjectType
PyTypeObject Crossfire_ObjectType
getPeriodofdayName
static PyObject * getPeriodofdayName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:666
EVENT_KICK
#define EVENT_KICK
Definition: events.h:43
cstEventType
const CFConstant cstEventType[]
Definition: cfpython.cpp:1333
PyInit_cjson
PyObject * PyInit_cjson(void)
Definition: cjson.cpp:1185
cfpython_globalEventListener
CF_PLUGIN int cfpython_globalEventListener(int *type,...)
Definition: cfpython.cpp:1705
FORCE
@ FORCE
Definition: object.h:227
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:164
TRAPDOOR
@ TRAPDOOR
Definition: object.h:213
AT_DRAIN
#define AT_DRAIN
Definition: attack.h:83
getWhoIsActivator
static PyObject * getWhoIsActivator(PyObject *self, PyObject *args)
Definition: cfpython.cpp:304
DETECTOR
@ DETECTOR
Definition: object.h:152
NDI_LT_GREEN
#define NDI_LT_GREEN
Definition: newclient.h:250
CFAPI_PLAYER_PROP_NEXT
#define CFAPI_PLAYER_PROP_NEXT
Definition: plugin.h:240
PyInit_Crossfire
static PyObject * PyInit_Crossfire(void)
Definition: cfpython.cpp:1487
initContextStack
static void initContextStack(void)
Definition: cfpython.cpp:821
_cfpcontext::options
char options[1024]
Definition: cfpython.h:100
cf_get_time
void cf_get_time(timeofday_t *tod)
Definition: plugin_common.cpp:1539
GOD
@ GOD
Definition: object.h:151
_timeofday::hour
int hour
Definition: tod.h:43
llevDebug
@ llevDebug
Definition: logger.h:13
MISC_OBJECT
@ MISC_OBJECT
Definition: object.h:196
MONEY
@ MONEY
Definition: object.h:140
findAnimation
static PyObject * findAnimation(PyObject *self, PyObject *args)
Definition: cfpython.cpp:630
RANDO2
#define RANDO2
Definition: define.h:523
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
GATE
@ GATE
Definition: object.h:209
give.name
name
Definition: give.py:27
EVENT_APPLY
#define EVENT_APPLY
Definition: events.h:20
getEvent
static PyObject * getEvent(PyObject *self, PyObject *args)
Definition: cfpython.cpp:351
freeContext
static void freeContext(CFPContext *context)
Definition: cfpython.cpp:848
ATNR_FEAR
#define ATNR_FEAR
Definition: attack.h:63
Crossfire_MapType
PyTypeObject Crossfire_MapType
AT_FIRE
#define AT_FIRE
Definition: attack.h:78
level
Definition: level.py:1
diamondslots.id
id
Definition: diamondslots.py:53
regiondef
Definition: map.h:275