Crossfire Server, Trunk
cfpython.c
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 = 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)
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 *new;
1070  PyObject *dict;
1071 
1072  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1073 
1074  new = PyModule_New(tmp);
1075  dict = PyDict_New();
1076 
1077  while (constants[i].name != NULL) {
1078  PyModule_AddIntConstant(new, (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, new);
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 *new;
1102 
1103  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1104 
1105  new = PyModule_New(tmp);
1106 
1107  while (constants[i].name != NULL) {
1108  PyModule_AddIntConstant(new, (char *)constants[i].name, constants[i].value);
1109  i++;
1110  }
1111  PyDict_SetItemString(PyModule_GetDict(module), name, new);
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 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) {
1495  PyObject *m;
1496  /* Python code to redirect stdouts/stderr. */
1497  const char *stdOutErr =
1498 "import sys\n\
1499 class CatchOutErr:\n\
1500  def __init__(self):\n\
1501  self.value = ''\n\
1502  def write(self, txt):\n\
1503  self.value += txt\n\
1504 catchOutErr = CatchOutErr()\n\
1505 sys.stdout = catchOutErr\n\
1506 sys.stderr = catchOutErr\n\
1507 ";
1508  (void)iversion;
1509 
1510  for (int c = 0; c < MAX_COMMANDS; c++) {
1511  registered_commands[c] = 0;
1512  }
1513 
1514  cf_init_plugin(gethooksptr);
1515  cf_log(llevDebug, "CFPython 2.0a init\n");
1516 
1519 
1520  PyImport_AppendInittab("Crossfire", &PyInit_Crossfire);
1521  PyImport_AppendInittab("cjson", &PyInit_cjson);
1522 
1523  Py_Initialize();
1524 
1525  m = PyImport_ImportModule("Crossfire");
1526 
1528 
1529  initConstants(m);
1530  private_data = PyDict_New();
1531  shared_data = PyDict_New();
1532 
1533  /* Redirect Python's stderr to a special object so it can be put to
1534  * the Crossfire log. */
1535  m = PyImport_AddModule("__main__");
1536  PyRun_SimpleString(stdOutErr);
1537  catcher = PyObject_GetAttrString(m, "catchOutErr");
1538  return 0;
1539 }
1540 
1542  va_list args;
1543  const char *propname;
1544  int size;
1545  char *buf;
1546 
1547  va_start(args, type);
1548  propname = va_arg(args, const char *);
1549  if (!strcmp(propname, "Identification")) {
1550  buf = va_arg(args, char *);
1551  size = va_arg(args, int);
1552  va_end(args);
1553  snprintf(buf, size, PLUGIN_NAME);
1554  return NULL;
1555  } else if (!strcmp(propname, "FullName")) {
1556  buf = va_arg(args, char *);
1557  size = va_arg(args, int);
1558  va_end(args);
1559  snprintf(buf, size, PLUGIN_VERSION);
1560  return NULL;
1561  }
1562  va_end(args);
1563  return NULL;
1564 }
1565 
1566 static int GECodes[] = {
1567  EVENT_BORN,
1568  EVENT_CLOCK,
1570  EVENT_GKILL,
1571  EVENT_LOGIN,
1572  EVENT_LOGOUT,
1576  EVENT_REMOVE,
1577  EVENT_SHOUT,
1578  EVENT_TELL,
1579  EVENT_MUZZLE,
1580  EVENT_KICK,
1582  EVENT_MAPLOAD,
1584  0
1585 };
1586 
1587 static const char* GEPaths[] = {
1588  "born",
1589  "clock",
1590  "death",
1591  "gkill",
1592  "login",
1593  "logout",
1594  "mapenter",
1595  "mapleave",
1596  "mapreset",
1597  "remove",
1598  "shout",
1599  "tell",
1600  "muzzle",
1601  "kick",
1602  "mapunload",
1603  "mapload",
1604  "mapready",
1605  NULL
1606 };
1607 
1613 static void freeEventFiles(char **eventFiles) {
1614  assert(eventFiles);
1615  for (int e = 0; eventFiles[e] != NULL; e++) {
1616  free(eventFiles[e]);
1617  }
1618  free(eventFiles);
1619 }
1620 
1626 static char **getEventFiles(CFPContext *context) {
1627  char **eventFiles = NULL;
1628  char name[NAME_MAX+1], path[NAME_MAX + 1];
1629 
1630  int allocated = 0, current = 0;
1631  DIR *dp;
1632  struct dirent *d;
1633  struct stat sb;
1634 
1635  snprintf(name, sizeof(name), "python/events/%s/", context->options);
1636  cf_get_maps_directory(name, path, sizeof(path));
1637 
1638  dp = opendir(path);
1639  if (dp == NULL) {
1640  cf_log(llevInfo, "CFPython: global event directory %s not found\n", context->options);
1641  eventFiles = 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 = 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 = malloc(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  context->who = NULL;
1721  context->activator = NULL;
1722  context->third = NULL;
1723  context->event = NULL;
1724  context->talk = NULL;
1725  rv = context->returnvalue = 0;
1726  switch (context->event_code) {
1727  case EVENT_CRASH:
1728  cf_log(llevDebug, "CFPython: event_crash unimplemented for now\n");
1729  break;
1730 
1731  case EVENT_BORN:
1732  op = va_arg(args, object *);
1733  context->activator = Crossfire_Object_wrap(op);
1734  break;
1735 
1736  case EVENT_PLAYER_DEATH:
1737  op = va_arg(args, object *);
1738  context->who = Crossfire_Object_wrap(op);
1739  op = va_arg(args, object *);
1740  context->activator = Crossfire_Object_wrap(op);
1741  break;
1742 
1743  case EVENT_GKILL:
1744  op = va_arg(args, object *);
1745  object* hitter = va_arg(args, object *);
1746  context->who = Crossfire_Object_wrap(op);
1748  break;
1749 
1750  case EVENT_LOGIN:
1751  pl = va_arg(args, player *);
1752  context->activator = Crossfire_Object_wrap(pl->ob);
1753  buf = va_arg(args, char *);
1754  if (buf != NULL)
1755  snprintf(context->message, sizeof(context->message), "%s", buf);
1756  break;
1757 
1758  case EVENT_LOGOUT:
1759  pl = va_arg(args, player *);
1760  context->activator = Crossfire_Object_wrap(pl->ob);
1761  buf = va_arg(args, char *);
1762  if (buf != NULL)
1763  snprintf(context->message, sizeof(context->message), "%s", buf);
1764  break;
1765 
1766  case EVENT_REMOVE:
1767  op = va_arg(args, object *);
1768  context->activator = Crossfire_Object_wrap(op);
1769  break;
1770 
1771  case EVENT_SHOUT:
1772  op = va_arg(args, object *);
1773  context->activator = Crossfire_Object_wrap(op);
1774  buf = va_arg(args, char *);
1775  if (buf != NULL)
1776  snprintf(context->message, sizeof(context->message), "%s", buf);
1777  break;
1778 
1779  case EVENT_MUZZLE:
1780  op = va_arg(args, object *);
1781  context->activator = Crossfire_Object_wrap(op);
1782  buf = va_arg(args, char *);
1783  if (buf != NULL)
1784  snprintf(context->message, sizeof(context->message), "%s", buf);
1785  break;
1786 
1787  case EVENT_KICK:
1788  op = va_arg(args, object *);
1789  context->activator = Crossfire_Object_wrap(op);
1790  buf = va_arg(args, char *);
1791  if (buf != NULL)
1792  snprintf(context->message, sizeof(context->message), "%s", buf);
1793  break;
1794 
1795  case EVENT_MAPENTER:
1796  op = va_arg(args, object *);
1797  context->activator = Crossfire_Object_wrap(op);
1798  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1799  break;
1800 
1801  case EVENT_MAPLEAVE:
1802  op = va_arg(args, object *);
1803  context->activator = Crossfire_Object_wrap(op);
1804  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1805  break;
1806 
1807  case EVENT_CLOCK:
1808  break;
1809 
1810  case EVENT_MAPRESET:
1811  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1812  break;
1813 
1814  case EVENT_TELL:
1815  op = va_arg(args, object *);
1816  buf = va_arg(args, char *);
1817  context->activator = Crossfire_Object_wrap(op);
1818  if (buf != NULL)
1819  snprintf(context->message, sizeof(context->message), "%s", buf);
1820  op = va_arg(args, object *);
1821  context->third = Crossfire_Object_wrap(op);
1822  break;
1823 
1824  case EVENT_MAPUNLOAD:
1825  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1826  break;
1827 
1828  case EVENT_MAPLOAD:
1829  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1830  break;
1831  }
1832  va_end(args);
1833  context->returnvalue = 0;
1834 
1835  if (context->event_code == EVENT_CLOCK) {
1836  // Ignore EVENT_CLOCK. It is not being used in maps, but nevertheless
1837  // runs python_init.py several times per second even while idling.
1838  freeContext(context);
1839  return rv;
1840  }
1841 
1842  snprintf(context->options, sizeof(context->options), "%s", getGlobalEventPath(context->event_code));
1843  files = getEventFiles(context);
1844  for (int file = 0; files[file] != NULL; file++)
1845  {
1846  CFPContext *copy = malloc(sizeof(CFPContext));
1847  (*copy) = (*context);
1848  Py_XINCREF(copy->activator);
1849  Py_XINCREF(copy->event);
1850  Py_XINCREF(copy->third);
1851  Py_XINCREF(copy->who);
1852  strncpy(copy->script, files[file], sizeof(copy->script));
1853 
1854  if (!do_script(copy)) {
1855  freeContext(copy);
1856  freeEventFiles(files);
1857  return rv;
1858  }
1859 
1860  copy = popContext();
1861  rv = copy->returnvalue;
1862 
1863  freeContext(copy);
1864  }
1865  freeEventFiles(files);
1866 
1867  /* Invalidate freed map wrapper. */
1868  if (context->event_code == EVENT_MAPUNLOAD)
1870 
1871  free(context);
1872 
1873  return rv;
1874 }
1875 
1876 CF_PLUGIN int eventListener(int *type, ...) {
1877  int rv = 0;
1878  va_list args;
1879  char *buf;
1880  CFPContext *context;
1881  object *event;
1882 
1883  context = malloc(sizeof(CFPContext));
1884 
1885  context->message[0] = 0;
1886 
1887  va_start(args, type);
1888 
1889  context->who = Crossfire_Object_wrap(va_arg(args, object *));
1890  context->activator = Crossfire_Object_wrap(va_arg(args, object *));
1891  context->third = Crossfire_Object_wrap(va_arg(args, object *));
1892  buf = va_arg(args, char *);
1893  if (buf != NULL)
1894  snprintf(context->message, sizeof(context->message), "%s", buf);
1895  /* fix = */va_arg(args, int);
1896  event = va_arg(args, object *);
1897  context->talk = va_arg(args, talk_info *);
1898  context->event_code = event->subtype;
1899  context->event = Crossfire_Object_wrap(event);
1900  cf_get_maps_directory(event->slaying, context->script, sizeof(context->script));
1901  snprintf(context->options, sizeof(context->options), "%s", event->name);
1902  context->returnvalue = 0;
1903 
1904  va_end(args);
1905 
1906  if (!do_script(context)) {
1907  freeContext(context);
1908  return rv;
1909  }
1910 
1911  context = popContext();
1912  rv = context->returnvalue;
1913  freeContext(context);
1914  return rv;
1915 }
1916 
1918  int i;
1919 
1920  cf_log(llevDebug, "CFPython 2.0a closing\n");
1921 
1922  for (int c = 0; c < MAX_COMMANDS; c++) {
1923  if (registered_commands[c]) {
1925  }
1926  }
1927 
1928  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
1929  Py_XDECREF(pycode_cache[i].code);
1930  if (pycode_cache[i].file != NULL)
1932  }
1933 
1934  Py_Finalize();
1935 
1936  return 0;
1937 }
cf_cost_string_from_value
void cf_cost_string_from_value(uint64_t cost, int largest_coin, char *buffer, int length)
Definition: plugin_common.c:984
compilePython
static PyCodeObject * compilePython(char *filename)
Definition: cfpython.c:917
CLASS
@ CLASS
Definition: object.h:138
getPlayerDirectory
static PyObject * getPlayerDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:281
CrossfireModule
static PyModuleDef CrossfireModule
Definition: cfpython.c:1475
findAnimation
static PyObject * findAnimation(PyObject *self, PyObject *args)
Definition: cfpython.c:630
TRIGGER
@ TRIGGER
Definition: object.h:129
_timeofday::month
int month
Definition: tod.h:40
_cfpcontext::message
char message[1024]
Definition: cfpython.h:97
MIMIC
@ MIMIC
Definition: object.h:249
getWhatIsMessage
static PyObject * getWhatIsMessage(PyObject *self, PyObject *args)
Definition: cfpython.c:326
PLAYER
@ PLAYER
Definition: object.h:107
cf_log
void cf_log(LogLevel logLevel, const char *format,...)
Definition: plugin_common.c:1512
ATNR_PARALYZE
#define ATNR_PARALYZE
Definition: attack.h:61
_cfpcontext::third
PyObject * third
Definition: cfpython.h:95
pycode_cache_entry::used_time
time_t used_time
Definition: cfpython.c:81
DAYS_PER_WEEK
#define DAYS_PER_WEEK
Definition: tod.h:16
ATNR_CANCELLATION
#define ATNR_CANCELLATION
Definition: attack.h:64
CF_HANDLE
@ CF_HANDLE
Definition: object.h:208
cf_get_weekday_name
const char * cf_get_weekday_name(int index)
Definition: plugin_common.c:1564
cf_add_string
sstring cf_add_string(const char *str)
Definition: plugin_common.c:1157
talk_info::replies
sstring replies[MAX_REPLIES]
Definition: dialog.h:58
MAP
@ MAP
Definition: object.h:125
cf_map_get_first
mapstruct * cf_map_get_first(void)
Definition: plugin_common.c:965
getFriendlyList
static PyObject * getFriendlyList(PyObject *self, PyObject *args)
Definition: cfpython.c:459
Crossfire_Map_wrap
PyObject * Crossfire_Map_wrap(mapstruct *what)
Definition: cfpython_map.c:439
cf_get_directory
const char * cf_get_directory(int id)
Definition: plugin_common.c:1120
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:200
BOW
@ BOW
Definition: object.h:118
BRACERS
@ BRACERS
Definition: object.h:217
cstAttackType
const CFConstant cstAttackType[]
Definition: cfpython.c:1273
CLOSE_CON
@ CLOSE_CON
Definition: object.h:229
WAITATT
#define WAITATT
Definition: define.h:495
llevError
@ llevError
Definition: logger.h:11
eventListener
CF_PLUGIN int eventListener(int *type,...)
Definition: cfpython.c:1876
ARMOUR_IMPROVER
@ ARMOUR_IMPROVER
Definition: object.h:232
EVENT_CONNECTOR
@ EVENT_CONNECTOR
Definition: object.h:227
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
SYMPTOM
@ SYMPTOM
Definition: object.h:245
WAND
@ WAND
Definition: object.h:220
do_script
static int do_script(CFPContext *context)
Definition: cfpython.c:1036
cf_get_season_name
const char * cf_get_season_name(int index)
Definition: plugin_common.c:1546
ALLRUN
#define ALLRUN
Definition: define.h:497
getMaps
static PyObject * getMaps(PyObject *self, PyObject *args)
Definition: cfpython.c:414
talk_info::replies_words
sstring replies_words[MAX_REPLIES]
Definition: dialog.h:57
talk_info::npc_msg_count
int npc_msg_count
Definition: dialog.h:59
FLESH
@ FLESH
Definition: object.h:187
ENCOUNTER
@ ENCOUNTER
Definition: object.h:182
closePlugin
CF_PLUGIN int closePlugin(void)
Definition: cfpython.c:1917
GLOVES
@ GLOVES
Definition: object.h:213
findFace
static PyObject * findFace(PyObject *self, PyObject *args)
Definition: cfpython.c:584
GIRDLE
@ GIRDLE
Definition: object.h:223
ATNR_ACID
#define ATNR_ACID
Definition: attack.h:55
BUTTON
@ BUTTON
Definition: object.h:207
_cfpcontext::event_code
int event_code
Definition: cfpython.h:98
cf_archetype_get_first
archetype * cf_archetype_get_first(void)
Definition: plugin_common.c:1676
RUNATT
#define RUNATT
Definition: define.h:493
AT_ELECTRICITY
#define AT_ELECTRICITY
Definition: attack.h:79
MAX_COMMANDS
#define MAX_COMMANDS
Definition: cfpython.c:84
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
PACEV2
#define PACEV2
Definition: define.h:526
Crossfire_Region_wrap
PyObject * Crossfire_Region_wrap(region *what)
Definition: cfpython_region.c:72
cf_object_get_object_property
object * cf_object_get_object_property(object *op, int propcode)
Definition: plugin_common.c:355
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:134
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:127
CFBank.open
def open()
Definition: CFBank.py:70
getWhoAmI
static PyObject * getWhoAmI(PyObject *self, PyObject *args)
Definition: cfpython.c:293
Crossfire_Object
Definition: cfpython_object.h:32
c
static event_registration c
Definition: citylife.cpp:427
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
getMonthName
static PyObject * getMonthName(PyObject *self, PyObject *args)
Definition: cfpython.c:648
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:183
GEM
@ GEM
Definition: object.h:167
getWeekdayName
static PyObject * getWeekdayName(PyObject *self, PyObject *args)
Definition: cfpython.c:657
pl
Definition: player.h:105
cf_create_object_by_name
object * cf_create_object_by_name(const char *name)
Definition: plugin_common.c:1083
HITRUN
#define HITRUN
Definition: define.h:494
HOURS_PER_DAY
#define HOURS_PER_DAY
Definition: tod.h:15
TRAP
@ TRAP
Definition: object.h:241
addReply
static PyObject * addReply(PyObject *self, PyObject *args)
Definition: cfpython.c:675
ARMOUR
@ ARMOUR
Definition: object.h:120
guildoracle.list
list
Definition: guildoracle.py:87
SVN_REV
#define SVN_REV
Definition: svnversion.h:2
WEAPON
@ WEAPON
Definition: object.h:119
TIMED_GATE
@ TIMED_GATE
Definition: object.h:128
guildjoin.ob
ob
Definition: guildjoin.py:42
Crossfire_Object_wrap
PyObject * Crossfire_Object_wrap(object *what)
Definition: cfpython_object.c:1609
EVENT_TIMER
#define EVENT_TIMER
Definition: events.h:34
say.reply
string reply
Definition: say.py:77
initPlugin
CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr)
Definition: cfpython.c:1494
cf_timer_destroy
int cf_timer_destroy(int id)
Definition: plugin_common.c:1610
_timeofday::year
int year
Definition: tod.h:39
ATNR_SLOW
#define ATNR_SLOW
Definition: attack.h:60
AMULET
@ AMULET
Definition: object.h:139
CHECK_INV
@ CHECK_INV
Definition: object.h:169
current_context
CFPContext * current_context
Definition: cfpython.c:106
getCFPythonVersion
static PyObject * getCFPythonVersion(PyObject *self, PyObject *args)
Definition: cfpython.c:165
mad_mage_user.file
file
Definition: mad_mage_user.py:15
getParties
static PyObject * getParties(PyObject *self, PyObject *args)
Definition: cfpython.c:429
pl::ob
object * ob
Definition: player.h:176
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
getScriptName
static PyObject * getScriptName(PyObject *self, PyObject *args)
Definition: cfpython.c:335
TREASURE
@ TREASURE
Definition: object.h:110
cf_region_get_next
region * cf_region_get_next(region *reg)
Definition: plugin_common.c:1900
EVENT_MAPLOAD
#define EVENT_MAPLOAD
Definition: events.h:47
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:264
SKILL
@ SKILL
Definition: object.h:143
RUNE
@ RUNE
Definition: object.h:240
ATNR_DISEASE
#define ATNR_DISEASE
Definition: attack.h:74
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:142
EVENT_LOGOUT
#define EVENT_LOGOUT
Definition: events.h:44
registered_commands
static command_registration registered_commands[MAX_COMMANDS]
Definition: cfpython.c:85
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:244
RANDO
#define RANDO
Definition: define.h:520
freeEventFiles
static void freeEventFiles(char **eventFiles)
Definition: cfpython.c:1613
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:28
_timeofday::periodofday
int periodofday
Definition: tod.h:47
TRANSPORT
@ TRANSPORT
Definition: object.h:108
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
POTION_RESIST_EFFECT
@ POTION_RESIST_EFFECT
Definition: object.h:225
FLOOR
@ FLOOR
Definition: object.h:186
_cfpcontext::event
PyObject * event
Definition: cfpython.h:96
setPlayerMessage
static PyObject * setPlayerMessage(PyObject *self, PyObject *args)
Definition: cfpython.c:703
SIGN
@ SIGN
Definition: object.h:211
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.c:1804
ATNR_TURN_UNDEAD
#define ATNR_TURN_UNDEAD
Definition: attack.h:62
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:132
npc_dialog.filename
filename
Definition: npc_dialog.py:99
Handle_Map_Unload_Hook
void Handle_Map_Unload_Hook(Crossfire_Map *map)
Definition: cfpython_map.c:434
NDI_BLUE
#define NDI_BLUE
Definition: newclient.h:247
talk_info::message_type
int message_type
Definition: dialog.h:55
_timeofday::dayofweek
int dayofweek
Definition: tod.h:42
POWER_CRYSTAL
@ POWER_CRYSTAL
Definition: object.h:242
WEEKS_PER_MONTH
#define WEEKS_PER_MONTH
Definition: tod.h:17
AT_LIFE_STEALING
#define AT_LIFE_STEALING
Definition: attack.h:100
_timeofday
Definition: tod.h:38
PACEH
#define PACEH
Definition: define.h:514
POISONING
@ POISONING
Definition: object.h:218
AT_DEATH
#define AT_DEATH
Definition: attack.h:93
PyInit_Crossfire
static PyObject * PyInit_Crossfire(void)
Definition: cfpython.c:1487
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
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:54
talk_info::replies_count
int replies_count
Definition: dialog.h:56
archt
Definition: object.h:469
obj
Definition: object.h:277
createCFObject
static PyObject * createCFObject(PyObject *self, PyObject *args)
Definition: cfpython.c:142
TRIGGER_MARKER
@ TRIGGER_MARKER
Definition: object.h:153
Crossfire_PlayerType
PyTypeObject Crossfire_PlayerType
getMapHasBeenLoaded
static PyObject * getMapHasBeenLoaded(PyObject *self, PyObject *args)
Definition: cfpython.c:575
ATNR_BLIND
#define ATNR_BLIND
Definition: attack.h:71
m
static event_registration m
Definition: citylife.cpp:427
AT_CHAOS
#define AT_CHAOS
Definition: attack.h:94
CLOAK
@ CLOAK
Definition: object.h:204
costStringFromValue
static PyObject * costStringFromValue(PyObject *self, PyObject *args)
Definition: cfpython.c:756
pycode_cache_entry::cached_time
time_t cached_time
Definition: cfpython.c:80
_timeofday::season
int season
Definition: tod.h:46
GECodes
static int GECodes[]
Definition: cfpython.c:1566
getEvent
static PyObject * getEvent(PyObject *self, PyObject *args)
Definition: cfpython.c:351
unregisterGEvent
static PyObject * unregisterGEvent(PyObject *self, PyObject *args)
Definition: cfpython.c:129
opendir
DIR * opendir(const char *)
EVENT_LOGIN
#define EVENT_LOGIN
Definition: events.h:43
HELMET
@ HELMET
Definition: object.h:136
getConfigDirectory
static PyObject * getConfigDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:269
disinfect.map
map
Definition: disinfect.py:4
POISON
@ POISON
Definition: object.h:113
getPluginProperty
CF_PLUGIN void * getPluginProperty(int *type,...)
Definition: cfpython.c:1541
initContextStack
static void initContextStack(void)
Definition: cfpython.c:821
cf_log_plain
void cf_log_plain(LogLevel logLevel, const char *message)
Definition: plugin_common.c:1532
EVENT_STOP
#define EVENT_STOP
Definition: events.h:30
cf_party_get_first
partylist * cf_party_get_first(void)
Definition: plugin_common.c:1773
EVENT_CLOCK
#define EVENT_CLOCK
Definition: events.h:39
DEEP_SWAMP
@ DEEP_SWAMP
Definition: object.h:236
make_face_from_files.args
args
Definition: make_face_from_files.py:31
shared_data
static PyObject * shared_data
Definition: cfpython.c:108
MARKER
@ MARKER
Definition: object.h:158
rotate-tower.result
bool result
Definition: rotate-tower.py:13
cstEventType
const CFConstant cstEventType[]
Definition: cfpython.c:1333
matchString
static PyObject * matchString(PyObject *self, PyObject *args)
Definition: cfpython.c:190
EVENT_PICKUP
#define EVENT_PICKUP
Definition: events.h:27
EVENT_CRASH
#define EVENT_CRASH
Definition: events.h:40
SAVEBED
@ SAVEBED
Definition: object.h:219
EVENT_SELLING
#define EVENT_SELLING
Definition: events.h:29
AT_COLD
#define AT_COLD
Definition: attack.h:80
init_map_assoc_table
void init_map_assoc_table(void)
Definition: cfpython_map.c:37
CF_PLUGIN
#define CF_PLUGIN
Definition: plugin_common.h:38
pushContext
static void pushContext(CFPContext *context)
Definition: cfpython.c:826
SEASONS_PER_YEAR
#define SEASONS_PER_YEAR
Definition: tod.h:19
LIGHTABLE
@ LIGHTABLE
Definition: object.h:250
POTION
@ POTION
Definition: object.h:111
_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.c:1500
BUILDER
@ BUILDER
Definition: object.h:246
EVENT_DROP
#define EVENT_DROP
Definition: events.h:26
_cfpcontext::who
PyObject * who
Definition: cfpython.h:93
EVENT_TRIGGER
#define EVENT_TRIGGER
Definition: events.h:33
f_plug_api
void(* f_plug_api)(int *type,...)
Definition: plugin.h:81
createCFObjectByName
static PyObject * createCFObjectByName(PyObject *self, PyObject *args)
Definition: cfpython.c:152
EVENT_MAPENTER
#define EVENT_MAPENTER
Definition: events.h:45
freeContext
static void freeContext(CFPContext *context)
Definition: cfpython.c:848
cf_system_unregister_global_event
void cf_system_unregister_global_event(int event, const char *name)
Definition: plugin_common.c:1099
cf_get_month_name
const char * cf_get_month_name(int index)
Definition: plugin_common.c:1555
cf_init_plugin
int cf_init_plugin(f_plug_api getHooks)
Definition: plugin_common.c:141
ROD
@ ROD
Definition: object.h:109
CONTAINER
@ CONTAINER
Definition: object.h:231
INORGANIC
@ INORGANIC
Definition: object.h:188
_timeofday::weekofmonth
int weekofmonth
Definition: tod.h:45
readdir
struct dirent * readdir(DIR *)
python_command_function
static void python_command_function(object *op, const char *params, const char *script)
Definition: cfpython.c:474
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.c:938
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:123
PLAYERMOVER
@ PLAYERMOVER
Definition: object.h:140
PLUGIN_NAME
#define PLUGIN_NAME
Definition: cfanim.h:32
cf_region_get_first
region * cf_region_get_first(void)
Definition: plugin_common.c:1868
cstTime
const CFConstant cstTime[]
Definition: cfpython.c:1375
EVENT_MAPRESET
#define EVENT_MAPRESET
Definition: events.h:49
cfpython.h
pycode_cache_entry::code
PyCodeObject * code
Definition: cfpython.c:79
getWhoIsThird
static PyObject * getWhoIsThird(PyObject *self, PyObject *args)
Definition: cfpython.c:315
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:124
MOVE_FLYING
#define MOVE_FLYING
Definition: define.h:395
HOLE
@ HOLE
Definition: object.h:209
cfpython_init_types
static void cfpython_init_types(PyObject *m)
Definition: cfpython.c:1434
PEACEMAKER
@ PEACEMAKER
Definition: object.h:164
MAX_NPC
#define MAX_NPC
Definition: dialog.h:46
CIRCLE2
#define CIRCLE2
Definition: define.h:513
getRegions
static PyObject * getRegions(PyObject *self, PyObject *args)
Definition: cfpython.c:444
readyMap
static PyObject * readyMap(PyObject *self, PyObject *args)
Definition: cfpython.c:224
EVENT_BORN
#define EVENT_BORN
Definition: events.h:38
guild_questpoints_apply.mapname
mapname
Definition: guild_questpoints_apply.py:8
CONVERTER
@ CONVERTER
Definition: object.h:216
EVENT_MAPUNLOAD
#define EVENT_MAPUNLOAD
Definition: events.h:50
SKILLSCROLL
@ SKILLSCROLL
Definition: object.h:234
ATNR_DRAIN
#define ATNR_DRAIN
Definition: attack.h:56
navar-midane_time.data
data
Definition: navar-midane_time.py:11
NDI_GOLD
#define NDI_GOLD
Definition: newclient.h:254
DRAGON_FOCUS
@ DRAGON_FOCUS
Definition: object.h:116
rt_say
@ rt_say
Definition: dialog.h:10
LAMP
@ LAMP
Definition: object.h:201
cstMove
const CFConstant cstMove[]
Definition: cfpython.c:1242
cfpython_openpyfile
static PyObject * cfpython_openpyfile(char *filename)
Definition: cfpython.c:859
GOLEM
@ GOLEM
Definition: object.h:145
sstring
const typedef char * sstring
Definition: global.h:40
ATNR_COUNTERSPELL
#define ATNR_COUNTERSPELL
Definition: attack.h:68
set_exception
static void set_exception(const char *fmt,...)
Definition: cfpython.c:93
postInitPlugin
CF_PLUGIN int postInitPlugin(void)
Definition: cfpython.c:1670
EVENT_USER
#define EVENT_USER
Definition: events.h:35
MOOD_FLOOR
@ MOOD_FLOOR
Definition: object.h:170
ATNR_POISON
#define ATNR_POISON
Definition: attack.h:59
ARROW
@ ARROW
Definition: object.h:117
EVENT_THROW
#define EVENT_THROW
Definition: events.h:32
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:114
SvnRevPlugin
CF_PLUGIN char SvnRevPlugin[]
Definition: cfpython.c:69
RING
@ RING
Definition: object.h:185
EVENT_SHOUT
#define EVENT_SHOUT
Definition: events.h:54
BLINDNESS
@ BLINDNESS
Definition: object.h:147
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.c:269
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
getLocalDirectory
static PyObject * getLocalDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:275
cstType
const CFConstant cstType[]
Definition: cfpython.c:1126
party_struct
Definition: party.h:10
CLOCK
@ CLOCK
Definition: object.h:115
cf_free_string
void cf_free_string(sstring str)
Definition: plugin_common.c:1172
log_python_error
static void log_python_error(void)
Definition: cfpython.c:897
SHOP_MAT
@ SHOP_MAT
Definition: object.h:184
EVENT_BOUGHT
#define EVENT_BOUGHT
Definition: events.h:22
COMMAND_TYPE_WIZARD
#define COMMAND_TYPE_WIZARD
Definition: commands.h:39
cstMessageFlag
const CFConstant cstMessageFlag[]
Definition: cfpython.c:1253
_cfpcontext::script
char script[1024]
Definition: cfpython.h:99
getReturnValue
static PyObject * getReturnValue(PyObject *self, PyObject *args)
Definition: cfpython.c:173
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Definition: define.h:393
EVENT_PLAYER_DEATH
#define EVENT_PLAYER_DEATH
Definition: events.h:52
ATNR_FIRE
#define ATNR_FIRE
Definition: attack.h:51
_cfpcontext::talk
struct talk_info * talk
Definition: cfpython.h:102
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.c:2093
EXIT
@ EXIT
Definition: object.h:181
cfpython_globalEventListener
CF_PLUGIN int cfpython_globalEventListener(int *type,...)
Definition: cfpython.c:1705
MAGIC_EAR
@ MAGIC_EAR
Definition: object.h:131
MONTHS_PER_YEAR
#define MONTHS_PER_YEAR
Definition: tod.h:18
PLUGIN_VERSION
#define PLUGIN_VERSION
Definition: cfanim.h:33
createMap
static PyObject * createMap(PyObject *self, PyObject *args)
Definition: cfpython.c:238
diamondslots.message
string message
Definition: diamondslots.py:57
cf_system_register_global_event
void cf_system_register_global_event(int event, const char *name, f_plug_event hook)
Definition: plugin_common.c:1092
log_message
static PyObject * log_message(PyObject *self, PyObject *args)
Definition: cfpython.c:593
GEPaths
static const char * GEPaths[]
Definition: cfpython.c:1587
llevInfo
@ llevInfo
Definition: logger.h:12
dirent
#define dirent
Definition: xdir.h:12
autojail.dict
dict
Definition: autojail.py:7
pycode_cache_entry::file
sstring file
Definition: cfpython.c:78
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:51
addSimpleConstants
static void addSimpleConstants(PyObject *module, const char *name, const CFConstant *constants)
Definition: cfpython.c:1098
cf_find_animation
int cf_find_animation(const char *txt)
Definition: plugin_common.c:1488
registerGEvent
static PyObject * registerGEvent(PyObject *self, PyObject *args)
Definition: cfpython.c:116
AT_BLIND
#define AT_BLIND
Definition: attack.h:98
CFPythonError
static PyObject * CFPythonError
Definition: cfpython.c:90
EVENT_TELL
#define EVENT_TELL
Definition: events.h:55
ATNR_CHAOS
#define ATNR_CHAOS
Definition: attack.h:67
EVENT_DEATH
#define EVENT_DEATH
Definition: events.h:24
getSharedDictionary
static PyObject * getSharedDictionary(PyObject *self, PyObject *args)
Definition: cfpython.c:377
BATTLEGROUND
@ BATTLEGROUND
Definition: object.h:163
Crossfire_PartyType
PyTypeObject Crossfire_PartyType
getSeasonName
static PyObject * getSeasonName(PyObject *self, PyObject *args)
Definition: cfpython.c:639
cf_archetype_get_next
archetype * cf_archetype_get_next(archetype *arch)
Definition: plugin_common.c:1709
AT_SLOW
#define AT_SLOW
Definition: attack.h:87
CFConstant
Definition: cfpython.h:105
MAX_REPLIES
#define MAX_REPLIES
Definition: dialog.h:44
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.c:1573
cfpython_pyfile_asfile
static FILE * cfpython_pyfile_asfile(PyObject *obj)
Definition: cfpython.c:873
GRIMREAPER
@ GRIMREAPER
Definition: object.h:130
ATNR_DEPLETE
#define ATNR_DEPLETE
Definition: attack.h:65
popContext
static CFPContext * popContext(void)
Definition: cfpython.c:836
getArchetypes
static PyObject * getArchetypes(PyObject *self, PyObject *args)
Definition: cfpython.c:384
EARTHWALL
@ EARTHWALL
Definition: object.h:144
Crossfire_Archetype_wrap
PyObject * Crossfire_Archetype_wrap(archetype *what)
Definition: cfpython_archetype.c:62
DUPLICATOR
@ DUPLICATOR
Definition: object.h:202
DISEASE
@ DISEASE
Definition: object.h:244
FIREWALL
@ FIREWALL
Definition: object.h:168
TRIGGER_ALTAR
@ TRIGGER_ALTAR
Definition: object.h:133
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:162
npcSay
static PyObject * npcSay(PyObject *self, PyObject *args)
Definition: cfpython.c:726
LIGHTER
@ LIGHTER
Definition: object.h:190
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
autojail.value
value
Definition: autojail.py:6
AT_DEPLETE
#define AT_DEPLETE
Definition: attack.h:92
getWhoIsActivator
static PyObject * getWhoIsActivator(PyObject *self, PyObject *args)
Definition: cfpython.c:304
Crossfire_ArchetypeType
PyTypeObject Crossfire_ArchetypeType
cf_map_has_been_loaded
mapstruct * cf_map_has_been_loaded(const char *name)
Definition: plugin_common.c:951
cstAttackTypeNumber
const CFConstant cstAttackTypeNumber[]
Definition: cfpython.c:1303
MATERIAL
@ MATERIAL
Definition: object.h:248
EVENT_TIME
#define EVENT_TIME
Definition: events.h:31
getPlayers
static PyObject * getPlayers(PyObject *self, PyObject *args)
Definition: cfpython.c:399
cf_re_cmp
const char * cf_re_cmp(const char *str, const char *regexp)
Definition: plugin_common.c:1133
destroyTimer
static PyObject * destroyTimer(PyObject *self, PyObject *args)
Definition: cfpython.c:566
EVENT_MAPLEAVE
#define EVENT_MAPLEAVE
Definition: events.h:46
initConstants
static void initConstants(PyObject *module)
Definition: cfpython.c:1413
Crossfire_Party_wrap
PyObject * Crossfire_Party_wrap(partylist *what)
Definition: cfpython_party.c:61
SPINNER
@ SPINNER
Definition: object.h:205
AT_WEAPONMAGIC
#define AT_WEAPONMAGIC
Definition: attack.h:84
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:215
SKILL_TOOL
@ SKILL_TOOL
Definition: object.h:189
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:238
catcher
static PyObject * catcher
Definition: cfpython.c:881
context_stack
CFPContext * context_stack
Definition: cfpython.c:104
NDI_WHITE
#define NDI_WHITE
Definition: newclient.h:243
PEDESTAL
@ PEDESTAL
Definition: object.h:121
cf_create_object
object * cf_create_object(void)
Definition: plugin_common.c:1071
cf_get_maps_directory
char * cf_get_maps_directory(const char *name, char *buf, int size)
Definition: plugin_common.c:1059
npc_dialog.index
int index
Definition: npc_dialog.py:102
NDI_BROWN
#define NDI_BROWN
Definition: newclient.h:253
buf
StringBuffer * buf
Definition: readable.c:1610
talk_info
Definition: dialog.h:51
NDI_TAN
#define NDI_TAN
Definition: newclient.h:255
EVENT_REMOVE
#define EVENT_REMOVE
Definition: events.h:53
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:248
cstAttackMovement
const CFConstant cstAttackMovement[]
Definition: cfpython.c:1392
pycode_cache_entry
Definition: cfpython.c:77
registerCommand
static PyObject * registerCommand(PyObject *self, PyObject *args)
Definition: cfpython.c:504
DEAD_OBJECT
@ DEAD_OBJECT
Definition: object.h:156
getGlobalEventPath
static const char * getGlobalEventPath(int code)
Definition: cfpython.c:1697
ATNR_WEAPONMAGIC
#define ATNR_WEAPONMAGIC
Definition: attack.h:57
DIRECTOR
@ DIRECTOR
Definition: object.h:222
CORPSE
@ CORPSE
Definition: object.h:243
talk_info::npc_msgs
sstring npc_msgs[MAX_NPC]
Definition: dialog.h:60
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.c:815
cstDirection
const CFConstant cstDirection[]
Definition: cfpython.c:1114
replace
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Definition: utils.c:337
cf_friendlylist_get_next
object * cf_friendlylist_get_next(object *ob)
Definition: plugin_common.c:2026
_cfpcontext
Definition: cfpython.h:91
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
getScriptParameters
static PyObject * getScriptParameters(PyObject *self, PyObject *args)
Definition: cfpython.c:341
getEventFiles
static char ** getEventFiles(CFPContext *context)
Definition: cfpython.c:1626
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.c:2101
AT_FEAR
#define AT_FEAR
Definition: attack.h:90
FOOD
@ FOOD
Definition: object.h:112
AT_GODPOWER
#define AT_GODPOWER
Definition: attack.h:96
findPlayer
static PyObject * findPlayer(PyObject *self, PyObject *args)
Definition: cfpython.c:206
pycode_cache
static pycode_cache_entry pycode_cache[PYTHON_CACHE_SIZE]
Definition: cfpython.c:88
MOVE_BOAT
#define MOVE_BOAT
Definition: define.h:397
MOVE_FLY_HIGH
#define MOVE_FLY_HIGH
Definition: define.h:394
EVENT_ATTACKED
#define EVENT_ATTACKED
Definition: events.h:20
EVENT_MAPREADY
#define EVENT_MAPREADY
Definition: events.h:48
PYTHON_CACHE_SIZE
#define PYTHON_CACHE_SIZE
Definition: cfpython.c:72
ALTAR
@ ALTAR
Definition: object.h:122
animate.event
event
DIALOGCHECK MINARGS 1 MAXARGS 2
Definition: animate.py:17
DOOR
@ DOOR
Definition: object.h:126
getPrivateDictionary
static PyObject * getPrivateDictionary(PyObject *self, PyObject *args)
Definition: cfpython.c:362
EVENT_CLOSE
#define EVENT_CLOSE
Definition: events.h:23
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.c:925
WAIT2
#define WAIT2
Definition: define.h:499
level
int level
Definition: readable.c:1608
PyInit_cjson
PyObject * PyInit_cjson(void)
Definition: cjson.c:1185
DRINK
@ DRINK
Definition: object.h:157
ATNR_GHOSTHIT
#define ATNR_GHOSTHIT
Definition: attack.h:58
WALL
@ WALL
Definition: object.h:191
setReturnValue
static PyObject * setReturnValue(PyObject *self, PyObject *args)
Definition: cfpython.c:179
ATNR_COLD
#define ATNR_COLD
Definition: attack.h:53
WEAPON_IMPROVER
@ WEAPON_IMPROVER
Definition: object.h:233
SCROLL
@ SCROLL
Definition: object.h:221
AT_CANCELLATION
#define AT_CANCELLATION
Definition: attack.h:91
getTempDirectory
static PyObject * getTempDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:263
CFPythonMethods
PyMethodDef CFPythonMethods[]
Definition: cfpython.c:769
DISTHIT
#define DISTHIT
Definition: define.h:498
RUSH
#define RUSH
Definition: define.h:496
PETMOVE
#define PETMOVE
Definition: define.h:501
death_message.hitter
hitter
Definition: death_message.py:33
LogLevel
LogLevel
Definition: logger.h:10
MOVE_SWIM
#define MOVE_SWIM
Definition: define.h:396
getMapDirectory
static PyObject * getMapDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:251
DISTATT
#define DISTATT
Definition: define.h:491
cf_friendlylist_get_first
object * cf_friendlylist_get_first(void)
Definition: plugin_common.c:2010
addConstants
static void addConstants(PyObject *module, const char *name, const CFConstant *constants)
Definition: cfpython.c:1066
_timeofday::minute
int minute
Definition: tod.h:44
EVENT_ATTACKS
#define EVENT_ATTACKS
Definition: events.h:21
svnversion.h
BOOTS
@ BOOTS
Definition: object.h:212
cstReplyTypes
const CFConstant cstReplyTypes[]
Definition: cfpython.c:1385
getDataDirectory
static PyObject * getDataDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:287
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:237
SPELL
@ SPELL
Definition: object.h:214
AT_GHOSTHIT
#define AT_GHOSTHIT
Definition: attack.h:85
EVENT_DESTROY
#define EVENT_DESTROY
Definition: events.h:25
replace.current
current
Definition: replace.py:64
closedir
int closedir(DIR *)
EVENT_GKILL
#define EVENT_GKILL
Definition: events.h:41
SHIELD
@ SHIELD
Definition: object.h:135
CIRCLE1
#define CIRCLE1
Definition: define.h:509
TELEPORTER
@ TELEPORTER
Definition: object.h:141
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
private_data
static PyObject * private_data
Definition: cfpython.c:110
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:146
NDI_GREY
#define NDI_GREY
Definition: newclient.h:252
SPELLBOOK
@ SPELLBOOK
Definition: object.h:203
Crossfire_ObjectType
PyTypeObject Crossfire_ObjectType
getPeriodofdayName
static PyObject * getPeriodofdayName(PyObject *self, PyObject *args)
Definition: cfpython.c:666
init_object_assoc_table
void init_object_assoc_table(void)
Definition: cfpython_object.c:60
EVENT_KICK
#define EVENT_KICK
Definition: events.h:42
getTime
static PyObject * getTime(PyObject *self, PyObject *args)
Definition: cfpython.c:544
FORCE
@ FORCE
Definition: object.h:224
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:161
TRAPDOOR
@ TRAPDOOR
Definition: object.h:210
AT_DRAIN
#define AT_DRAIN
Definition: attack.h:83
DETECTOR
@ DETECTOR
Definition: object.h:149
getUniqueDirectory
static PyObject * getUniqueDirectory(PyObject *self, PyObject *args)
Definition: cfpython.c:257
NDI_LT_GREEN
#define NDI_LT_GREEN
Definition: newclient.h:250
CFAPI_PLAYER_PROP_NEXT
#define CFAPI_PLAYER_PROP_NEXT
Definition: plugin.h:240
_cfpcontext::options
char options[1024]
Definition: cfpython.h:100
cf_get_time
void cf_get_time(timeofday_t *tod)
Definition: plugin_common.c:1539
GOD
@ GOD
Definition: object.h:148
_timeofday::hour
int hour
Definition: tod.h:43
llevDebug
@ llevDebug
Definition: logger.h:13
MISC_OBJECT
@ MISC_OBJECT
Definition: object.h:193
MONEY
@ MONEY
Definition: object.h:137
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:206
give.name
name
Definition: give.py:27
EVENT_APPLY
#define EVENT_APPLY
Definition: events.h:19
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