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 struct pycode_cache_entry {
79  PyCodeObject *code;
80  time_t cached_time,
82 };
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  std::vector<archetype *> archs;
387  (void)self;
388  (void)args;
389 
391  list = PyList_New(0);
392  for (auto arch : archs) {
393  PyList_Append(list, Crossfire_Archetype_wrap(arch));
394  }
395  return list;
396 }
397 
398 static PyObject *getPlayers(PyObject *self, PyObject *args) {
399  PyObject *list;
400  std::vector<object *> players;
401  (void)self;
402  (void)args;
403 
405 
406  list = PyList_New(0);
407  for (auto pl : players) {
408  PyList_Append(list, Crossfire_Object_wrap(pl));
409  }
410  return list;
411 }
412 
413 static PyObject *getMaps(PyObject *self, PyObject *args) {
414  PyObject *list;
415  std::vector<mapstruct *> maps;
416  (void)self;
417  (void)args;
418 
420 
421  list = PyList_New(0);
422  for (auto map : maps) {
423  PyList_Append(list, Crossfire_Map_wrap(map));
424  }
425  return list;
426 }
427 
428 static PyObject *getParties(PyObject *self, PyObject *args) {
429  PyObject *list;
430  std::vector<partylist *> parties;
431  (void)self;
432  (void)args;
433 
435  list = PyList_New(0);
436  for (auto party : parties) {
437  PyList_Append(list, Crossfire_Party_wrap(party));
438  }
439  return list;
440 }
441 
442 static PyObject *getRegions(PyObject *self, PyObject *args) {
443  PyObject *list;
444  std::vector<region *> regions;
445  (void)self;
446  (void)args;
447 
449  list = PyList_New(0);
450  for (auto reg : regions) {
451  PyList_Append(list, Crossfire_Region_wrap(reg));
452  }
453  return list;
454 }
455 
456 static PyObject *getFriendlyList(PyObject *self, PyObject *args) {
457  PyObject *list;
458  std::vector<object *> friends;
459  (void)self;
460  (void)args;
461 
463  list = PyList_New(0);
464  for (auto ob : friends) {
465  PyList_Append(list, Crossfire_Object_wrap(ob));
466  }
467  return list;
468 }
469 
470 static void python_command_function(object *op, const char *params, const char *script) {
471  char buf[1024], path[1024];
472  CFPContext *context;
473 
474  snprintf(buf, sizeof(buf), "%s.py", cf_get_maps_directory(script, path, sizeof(path)));
475 
476  context = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
477  context->message[0] = 0;
478 
479  context->who = Crossfire_Object_wrap(op);
480  context->activator = NULL;
481  context->third = NULL;
482  /* We are not running from an event, so set it to NULL to avoid segfaults. */
483  context->event = NULL;
484  snprintf(context->script, sizeof(context->script), "%s", buf);
485  if (params)
486  snprintf(context->options, sizeof(context->options), "%s", params);
487  else
488  context->options[0] = 0;
489  context->returnvalue = 1; /* Default is "command successful" */
490 
491  if (!do_script(context)) {
492  freeContext(context);
493  return;
494  }
495 
496  context = popContext();
497  freeContext(context);
498 }
499 
500 static PyObject *registerCommand(PyObject *self, PyObject *args) {
501  char *cmdname;
502  char *scriptname;
503  double cmdspeed;
505  (void)self;
506 
507  if (!PyArg_ParseTuple(args, "ssd|i", &cmdname, &scriptname, &cmdspeed, &type))
508  return NULL;
509 
510  if (cmdspeed < 0) {
511  set_exception("speed must not be negative");
512  return NULL;
513  }
514 
515  if (type < 0 || type > COMMAND_TYPE_WIZARD) {
516  set_exception("type must be between 0 and 2");
517  return NULL;
518  }
519 
520  for (index = 0; index < MAX_COMMANDS; index++) {
521  if (registered_commands[index] == 0) {
522  break;
523  }
524  }
525  if (index == MAX_COMMANDS) {
526  set_exception("too many registered commands");
527  return NULL;
528  }
529 
531  if (registered_commands[index] == 0) {
532  set_exception("failed to register command (overriding an existing one with a different type?)");
533  return NULL;
534  }
535 
536  Py_INCREF(Py_None);
537  return Py_None;
538 }
539 
540 static PyObject *getTime(PyObject *self, PyObject *args) {
541  PyObject *list;
542  timeofday_t tod;
543  (void)self;
544  (void)args;
545 
546  cf_get_time(&tod);
547 
548  list = PyList_New(0);
549  PyList_Append(list, Py_BuildValue("i", tod.year));
550  PyList_Append(list, Py_BuildValue("i", tod.month));
551  PyList_Append(list, Py_BuildValue("i", tod.day));
552  PyList_Append(list, Py_BuildValue("i", tod.hour));
553  PyList_Append(list, Py_BuildValue("i", tod.minute));
554  PyList_Append(list, Py_BuildValue("i", tod.dayofweek));
555  PyList_Append(list, Py_BuildValue("i", tod.weekofmonth));
556  PyList_Append(list, Py_BuildValue("i", tod.season));
557  PyList_Append(list, Py_BuildValue("i", tod.periodofday));
558 
559  return list;
560 }
561 
562 static PyObject *destroyTimer(PyObject *self, PyObject *args) {
563  int id;
564  (void)self;
565 
566  if (!PyArg_ParseTuple(args, "i", &id))
567  return NULL;
568  return Py_BuildValue("i", cf_timer_destroy(id));
569 }
570 
571 static PyObject *getMapHasBeenLoaded(PyObject *self, PyObject *args) {
572  char *name;
573  (void)self;
574 
575  if (!PyArg_ParseTuple(args, "s", &name))
576  return NULL;
578 }
579 
580 static PyObject *findFace(PyObject *self, PyObject *args) {
581  char *name;
582  (void)self;
583 
584  if (!PyArg_ParseTuple(args, "s", &name))
585  return NULL;
586  return Py_BuildValue("i", cf_find_face(name, 0));
587 }
588 
589 static PyObject *log_message(PyObject *self, PyObject *args) {
590  LogLevel level;
591  int intLevel;
592  char *message;
593  (void)self;
594 
595  if (!PyArg_ParseTuple(args, "is", &intLevel, &message))
596  return NULL;
597 
598  switch (intLevel) {
599  case llevError:
600  level = llevError;
601  break;
602 
603  case llevInfo:
604  level = llevInfo;
605  break;
606 
607  case llevDebug:
608  level = llevDebug;
609  break;
610 
611  case llevMonster:
612  level = llevMonster;
613  break;
614 
615  default:
616  return NULL;
617  }
618  if ((message != NULL) && (message[strlen(message)] == '\n'))
619  cf_log(level, "CFPython: %s", message);
620  else
621  cf_log(level, "CFPython: %s\n", message);
622  Py_INCREF(Py_None);
623  return Py_None;
624 }
625 
626 static PyObject *findAnimation(PyObject *self, PyObject *args) {
627  char *name;
628  (void)self;
629 
630  if (!PyArg_ParseTuple(args, "s", &name))
631  return NULL;
632  return Py_BuildValue("i", cf_find_animation(name));
633 }
634 
635 static PyObject *getSeasonName(PyObject *self, PyObject *args) {
636  int i;
637  (void)self;
638 
639  if (!PyArg_ParseTuple(args, "i", &i))
640  return NULL;
641  return Py_BuildValue("s", cf_get_season_name(i));
642 }
643 
644 static PyObject *getMonthName(PyObject *self, PyObject *args) {
645  int i;
646  (void)self;
647 
648  if (!PyArg_ParseTuple(args, "i", &i))
649  return NULL;
650  return Py_BuildValue("s", cf_get_month_name(i));
651 }
652 
653 static PyObject *getWeekdayName(PyObject *self, PyObject *args) {
654  int i;
655  (void)self;
656 
657  if (!PyArg_ParseTuple(args, "i", &i))
658  return NULL;
659  return Py_BuildValue("s", cf_get_weekday_name(i));
660 }
661 
662 static PyObject *getPeriodofdayName(PyObject *self, PyObject *args) {
663  int i;
664  (void)self;
665 
666  if (!PyArg_ParseTuple(args, "i", &i))
667  return NULL;
668  return Py_BuildValue("s", cf_get_periodofday_name(i));
669 }
670 
671 static PyObject *addReply(PyObject *self, PyObject *args) {
672  char *word, *reply;
673  talk_info *talk;
674  (void)self;
675 
676  if (current_context->talk == NULL) {
677  set_exception("not in a dialog context");
678  return NULL;
679  }
680  talk = current_context->talk;
681 
682  if (!PyArg_ParseTuple(args, "ss", &word, &reply)) {
683  return NULL;
684  }
685 
686  if (talk->replies_count == MAX_REPLIES) {
687  set_exception("too many replies");
688  return NULL;
689  }
690 
691  talk->replies_words[talk->replies_count] = cf_add_string(word);
692  talk->replies[talk->replies_count] = cf_add_string(reply);
693  talk->replies_count++;
694  Py_INCREF(Py_None);
695  return Py_None;
696 
697 }
698 
699 static PyObject *setPlayerMessage(PyObject *self, PyObject *args) {
700  char *message;
701  int type = rt_reply;
702  (void)self;
703 
704  if (current_context->talk == NULL) {
705  set_exception("not in a dialog context");
706  return NULL;
707  }
708 
709  if (!PyArg_ParseTuple(args, "s|i", &message, &type)) {
710  return NULL;
711  }
712 
713  if (current_context->talk->message != NULL)
716  current_context->talk->message_type = static_cast<reply_type>(type);
717 
718  Py_INCREF(Py_None);
719  return Py_None;
720 }
721 
722 static PyObject *npcSay(PyObject *self, PyObject *args) {
723  Crossfire_Object *npc = NULL;
724  char *message, buf[2048];
725  (void)self;
726 
727  if (!PyArg_ParseTuple(args, "O!s", &Crossfire_ObjectType, &npc, &message))
728  return NULL;
729 
730  if (current_context->talk == NULL) {
731  set_exception("not in a dialog context");
732  return NULL;
733  }
734 
736  set_exception("too many NPCs");
737  return NULL;
738  }
739 
740  if (strlen(message) >= sizeof(buf) - 1)
741  cf_log(llevError, "CFPython: warning, too long message in npcSay, will be truncated");
743  snprintf(buf, sizeof(buf), "%s says: %s", npc->obj->name, message);
744 
747 
748  Py_INCREF(Py_None);
749  return Py_None;
750 }
751 
752 static PyObject *costStringFromValue(PyObject *self, PyObject *args) {
753  uint64_t value;
754  char buf[2048];
755  int largest_coin = 0;
756  (void)self;
757 
758  if (!PyArg_ParseTuple(args, "L|i", &value, &largest_coin))
759  return NULL;
760 
761  cf_cost_string_from_value(value, largest_coin, buf, sizeof(buf));
762  return Py_BuildValue("s", buf);
763 }
764 
765 PyMethodDef CFPythonMethods[] = {
766  { "WhoAmI", getWhoAmI, METH_NOARGS, NULL },
767  { "WhoIsActivator", getWhoIsActivator, METH_NOARGS, NULL },
768  { "WhoIsOther", getWhoIsThird, METH_NOARGS, NULL },
769  { "WhatIsMessage", getWhatIsMessage, METH_NOARGS, NULL },
770  { "ScriptName", getScriptName, METH_NOARGS, NULL },
771  { "ScriptParameters", getScriptParameters, METH_NOARGS, NULL },
772  { "WhatIsEvent", getEvent, METH_NOARGS, NULL },
773  { "MapDirectory", getMapDirectory, METH_NOARGS, NULL },
774  { "UniqueDirectory", getUniqueDirectory, METH_NOARGS, NULL },
775  { "TempDirectory", getTempDirectory, METH_NOARGS, NULL },
776  { "ConfigDirectory", getConfigDirectory, METH_NOARGS, NULL },
777  { "LocalDirectory", getLocalDirectory, METH_NOARGS, NULL },
778  { "PlayerDirectory", getPlayerDirectory, METH_NOARGS, NULL },
779  { "DataDirectory", getDataDirectory, METH_NOARGS, NULL },
780  { "ReadyMap", readyMap, METH_VARARGS, NULL },
781  { "CreateMap", createMap, METH_VARARGS, NULL },
782  { "FindPlayer", findPlayer, METH_VARARGS, NULL },
783  { "MatchString", matchString, METH_VARARGS, NULL },
784  { "GetReturnValue", getReturnValue, METH_NOARGS, NULL },
785  { "SetReturnValue", setReturnValue, METH_VARARGS, NULL },
786  { "PluginVersion", getCFPythonVersion, METH_NOARGS, NULL },
787  { "CreateObject", createCFObject, METH_NOARGS, NULL },
788  { "CreateObjectByName", createCFObjectByName, METH_VARARGS, NULL },
789  { "GetPrivateDictionary", getPrivateDictionary, METH_NOARGS, NULL },
790  { "GetSharedDictionary", getSharedDictionary, METH_NOARGS, NULL },
791  { "GetPlayers", getPlayers, METH_NOARGS, NULL },
792  { "GetArchetypes", getArchetypes, METH_NOARGS, NULL },
793  { "GetMaps", getMaps, METH_NOARGS, NULL },
794  { "GetParties", getParties, METH_NOARGS, NULL },
795  { "GetRegions", getRegions, METH_NOARGS, NULL },
796  { "GetFriendlyList", getFriendlyList, METH_NOARGS, NULL },
797  { "RegisterCommand", registerCommand, METH_VARARGS, NULL },
798  { "RegisterGlobalEvent", registerGEvent, METH_VARARGS, NULL },
799  { "UnregisterGlobalEvent", unregisterGEvent, METH_VARARGS, NULL },
800  { "GetTime", getTime, METH_NOARGS, NULL },
801  { "DestroyTimer", destroyTimer, METH_VARARGS, NULL },
802  { "MapHasBeenLoaded", getMapHasBeenLoaded, METH_VARARGS, NULL },
803  { "Log", log_message, METH_VARARGS, NULL },
804  { "FindFace", findFace, METH_VARARGS, NULL },
805  { "FindAnimation", findAnimation, METH_VARARGS, NULL },
806  { "GetSeasonName", getSeasonName, METH_VARARGS, NULL },
807  { "GetMonthName", getMonthName, METH_VARARGS, NULL },
808  { "GetWeekdayName", getWeekdayName, METH_VARARGS, NULL },
809  { "GetPeriodofdayName", getPeriodofdayName, METH_VARARGS, NULL },
810  { "AddReply", addReply, METH_VARARGS, NULL },
811  { "SetPlayerMessage", setPlayerMessage, METH_VARARGS, NULL },
812  { "NPCSay", npcSay, METH_VARARGS, NULL },
813  { "CostStringFromValue", costStringFromValue, METH_VARARGS, NULL },
814  { NULL, NULL, 0, NULL }
815 };
816 
817 static void initContextStack(void) {
818  current_context = NULL;
819  context_stack = NULL;
820 }
821 
822 static void pushContext(CFPContext *context) {
823  if (current_context == NULL) {
824  context_stack = context;
825  context->down = NULL;
826  } else {
827  context->down = current_context;
828  }
829  current_context = context;
830 }
831 
832 static CFPContext *popContext(void) {
833  CFPContext *oldcontext;
834 
835  if (current_context != NULL) {
836  oldcontext = current_context;
838  return oldcontext;
839  }
840  else
841  return NULL;
842 }
843 
844 static void freeContext(CFPContext *context) {
845  Py_XDECREF(context->event);
846  Py_XDECREF(context->third);
847  Py_XDECREF(context->who);
848  Py_XDECREF(context->activator);
849  free(context);
850 }
851 
855 static PyObject* cfpython_openpyfile(char *filename) {
856  PyObject *scriptfile;
857  int fd;
858  fd = open(filename, O_RDONLY);
859  if (fd == -1)
860  return NULL;
861  scriptfile = PyFile_FromFd(fd, filename, "r", -1, NULL, NULL, NULL, 1);
862  return scriptfile;
863 }
864 
869 static FILE* cfpython_pyfile_asfile(PyObject* obj) {
870  return fdopen(PyObject_AsFileDescriptor(obj), "r");
871 }
872 
877 static PyObject *catcher = NULL;
878 
879 #ifdef IS_PY3K10
880 
884 static PyObject *io_module = NULL;
885 #endif
886 
893 static void log_python_error(void) {
894 
895  PyErr_Print();
896 
897  if (catcher != NULL) {
898  PyObject *output = PyObject_GetAttrString(catcher, "value"); //get the stdout and stderr from our catchOutErr object
899  PyObject* empty = PyUnicode_FromString("");
900 
901  cf_log_plain(llevError, PyUnicode_AsUTF8(output));
902  Py_DECREF(output);
903 
904  PyObject_SetAttrString(catcher, "value", empty);
905  Py_DECREF(empty);
906  }
907 
908  return;
909 }
910 
911 
913 static PyCodeObject *compilePython(char *filename) {
914  PyObject *scriptfile = NULL;
915  sstring sh_path;
916  struct stat stat_buf;
917  struct _node *n;
918  int i;
919  pycode_cache_entry *replace = NULL, *run = NULL;
920 
921  if (stat(filename, &stat_buf)) {
922  cf_log(llevError, "CFPython: script file %s can't be stat'ed\n", filename);
923  return NULL;
924  }
925 
926  sh_path = cf_add_string(filename);
927 
928  /* Search through cache. Four cases:
929  * 1) script in cache, but older than file -> replace cached
930  * 2) script in cache and up to date -> use cached
931  * 3) script not in cache, cache not full -> add to end of cache
932  * 4) script not in cache, cache full -> replace least recently used
933  */
934  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
935  if (pycode_cache[i].file == NULL) { /* script not in cache, cache not full */
936  replace = &pycode_cache[i]; /* add to end of cache */
937  break;
938  } else if (pycode_cache[i].file == sh_path) {
939  /* script in cache */
940  if (pycode_cache[i].code == NULL || (pycode_cache[i].cached_time < stat_buf.st_mtime)) {
941  /* cache older than file, replace cached */
942  replace = &pycode_cache[i];
943  } else {
944  /* cache uptodate, use cached*/
945  replace = NULL;
946  run = &pycode_cache[i];
947  }
948  break;
949  } else if (replace == NULL || pycode_cache[i].used_time < replace->used_time)
950  /* if we haven't found it yet, set replace to the oldest cache */
951  replace = &pycode_cache[i];
952  }
953 
954  /* replace a specific cache index with the file */
955  if (replace) {
956  Py_XDECREF(replace->code); /* safe to call on NULL */
957  replace->code = NULL;
958 
959  /* Need to replace path string? */
960  if (replace->file != sh_path) {
961  if (replace->file) {
962  cf_free_string(replace->file);
963  }
964  replace->file = cf_add_string(sh_path);
965  }
966 #ifdef IS_PY3K10
967  /* 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.
968  * The new parser removes the PyNode functions as well as PyParser_SimpleParseFile,
969  * so the code needed to be completely rewritten to work.
970  *
971  * Python's solution to these changes is to import the io module and use Python's read method to read in the file,
972  * and then convert the bytes object into a c-string for Py_CompileString
973  *
974  * Though, if it is more performant than the previous code, Py_CompileString is
975  * available for all Python 3, so it is possible to simplify all of them to this if we need to.
976  */
977  if (!io_module)
978  io_module = PyImport_ImportModule("io");
979  scriptfile = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
980  if (!scriptfile) {
981  cf_log(llevDebug, "CFPython: script file %s can't be opened\n", filename);
982  cf_free_string(sh_path);
983  return NULL;
984  }
985  PyObject *source_bytes = PyObject_CallMethod(scriptfile, "read", "");
986  (void)PyObject_CallMethod(scriptfile, "close", "");
987  PyObject *code = Py_CompileString(PyBytes_AsString(source_bytes), filename, Py_file_input);
988  if (code) {
989  replace->code = (PyCodeObject *)code;
990  }
991  if (PyErr_Occurred())
993  else
994  replace->cached_time = stat_buf.st_mtime;
995  run = replace;
996 #else
997  /* Load, parse and compile. Note: because Pyhon may have been built with a
998  * different library than Crossfire, the FILE* it uses may be incompatible.
999  * Therefore we use PyFile to open the file, then convert to FILE* and get
1000  * Python's own structure. Messy, but can't be helped... */
1001  if (!(scriptfile = cfpython_openpyfile(filename))) {
1002  cf_log(llevDebug, "CFPython: script file %s can't be opened\n", filename);
1003  cf_free_string(sh_path);
1004  return NULL;
1005  } else {
1006  /* Note: FILE* being opaque, it works, but the actual structure may be different! */
1007  FILE* pyfile = cfpython_pyfile_asfile(scriptfile);
1008  if ((n = PyParser_SimpleParseFile(pyfile, filename, Py_file_input))) {
1009  replace->code = PyNode_Compile(n, filename);
1010  PyNode_Free(n);
1011  }
1012  if (PyErr_Occurred())
1013  log_python_error();
1014  else
1015  replace->cached_time = stat_buf.st_mtime;
1016  run = replace;
1017  }
1018 #endif
1019  }
1020 
1021  cf_free_string(sh_path);
1022 
1023  if (scriptfile) {
1024  Py_DECREF(scriptfile);
1025  }
1026 
1027  assert(run != NULL);
1028  run->used_time = time(NULL);
1029  return run->code;
1030 }
1031 
1032 static int do_script(CFPContext *context) {
1033  PyCodeObject *pycode;
1034  PyObject *dict;
1035  PyObject *ret;
1036 
1037  cf_log(llevDebug, "CFPython: running script %s\n", context->script);
1038 
1039  pycode = compilePython(context->script);
1040  if (pycode) {
1041  pushContext(context);
1042  dict = PyDict_New();
1043  PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
1044  ret = PyEval_EvalCode((PyObject *)pycode, dict, NULL);
1045  if (PyErr_Occurred()) {
1046  log_python_error();
1047  }
1048  Py_XDECREF(ret);
1049  Py_DECREF(dict);
1050  return 1;
1051  } else
1052  return 0;
1053 }
1054 
1062 static void addConstants(PyObject *module, const char *name, const CFConstant *constants) {
1063  int i = 0;
1064  char tmp[1024];
1065  PyObject *cst;
1066  PyObject *dict;
1067 
1068  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1069 
1070  cst = PyModule_New(tmp);
1071  dict = PyDict_New();
1072 
1073  while (constants[i].name != NULL) {
1074  PyModule_AddIntConstant(cst, (char *)constants[i].name, constants[i].value);
1075  PyDict_SetItem(dict, PyLong_FromLong(constants[i].value), PyUnicode_FromString(constants[i].name));
1076  i++;
1077  }
1078  PyDict_SetItemString(PyModule_GetDict(module), name, cst);
1079 
1080  snprintf(tmp, sizeof(tmp), "%sName", name);
1081  PyDict_SetItemString(PyModule_GetDict(module), tmp, dict);
1082  Py_DECREF(dict);
1083 }
1084 
1094 static void addSimpleConstants(PyObject *module, const char *name, const CFConstant *constants) {
1095  int i = 0;
1096  char tmp[1024];
1097  PyObject *cst;
1098 
1099  snprintf(tmp, sizeof(tmp), "Crossfire_%s", name);
1100 
1101  cst = PyModule_New(tmp);
1102 
1103  while (constants[i].name != NULL) {
1104  PyModule_AddIntConstant(cst, (char *)constants[i].name, constants[i].value);
1105  i++;
1106  }
1107  PyDict_SetItemString(PyModule_GetDict(module), name, cst);
1108 }
1109 
1111  { "NORTH", 1 },
1112  { "NORTHEAST", 2 },
1113  { "EAST", 3 },
1114  { "SOUTHEAST", 4 },
1115  { "SOUTH", 5 },
1116  { "SOUTHWEST", 6 },
1117  { "WEST", 7 },
1118  { "NORTHWEST", 8 },
1119  { NULL, 0 }
1120 };
1121 
1122 const CFConstant cstType[] = {
1123  { "PLAYER", PLAYER },
1124  { "TRANSPORT", TRANSPORT },
1125  { "ROD", ROD },
1126  { "TREASURE", TREASURE },
1127  { "POTION", POTION },
1128  { "FOOD", FOOD },
1129  { "POISON", POISON },
1130  { "BOOK", BOOK },
1131  { "CLOCK", CLOCK },
1132  { "DRAGON_FOCUS", DRAGON_FOCUS },
1133  { "ARROW", ARROW },
1134  { "BOW", BOW },
1135  { "WEAPON", WEAPON },
1136  { "ARMOUR", ARMOUR },
1137  { "PEDESTAL", PEDESTAL },
1138  { "ALTAR", ALTAR },
1139  { "LOCKED_DOOR", LOCKED_DOOR },
1140  { "SPECIAL_KEY", SPECIAL_KEY },
1141  { "MAP", MAP },
1142  { "DOOR", DOOR },
1143  { "KEY", KEY },
1144  { "TIMED_GATE", TIMED_GATE },
1145  { "TRIGGER", TRIGGER },
1146  { "GRIMREAPER", GRIMREAPER },
1147  { "MAGIC_EAR", MAGIC_EAR },
1148  { "TRIGGER_BUTTON", TRIGGER_BUTTON },
1149  { "TRIGGER_ALTAR", TRIGGER_ALTAR },
1150  { "TRIGGER_PEDESTAL", TRIGGER_PEDESTAL },
1151  { "SHIELD", SHIELD },
1152  { "HELMET", HELMET },
1153  { "MONEY", MONEY },
1154  { "CLASS", CLASS },
1155  { "AMULET", AMULET },
1156  { "PLAYERMOVER", PLAYERMOVER },
1157  { "TELEPORTER", TELEPORTER },
1158  { "CREATOR", CREATOR },
1159  { "SKILL", SKILL },
1160  { "EARTHWALL", EARTHWALL },
1161  { "GOLEM", GOLEM },
1162  { "THROWN_OBJ", THROWN_OBJ },
1163  { "BLINDNESS", BLINDNESS },
1164  { "GOD", GOD },
1165  { "DETECTOR", DETECTOR },
1166  { "TRIGGER_MARKER", TRIGGER_MARKER },
1167  { "DEAD_OBJECT", DEAD_OBJECT },
1168  { "DRINK", DRINK },
1169  { "MARKER", MARKER },
1170  { "HOLY_ALTAR", HOLY_ALTAR },
1171  { "PLAYER_CHANGER", PLAYER_CHANGER },
1172  { "BATTLEGROUND", BATTLEGROUND },
1173  { "PEACEMAKER", PEACEMAKER },
1174  { "GEM", GEM },
1175  { "FIREWALL", FIREWALL },
1176  { "CHECK_INV", CHECK_INV },
1177  { "MOOD_FLOOR", MOOD_FLOOR },
1178  { "EXIT", EXIT },
1179  { "ENCOUNTER", ENCOUNTER },
1180  { "SHOP_FLOOR", SHOP_FLOOR },
1181  { "SHOP_MAT", SHOP_MAT },
1182  { "RING", RING },
1183  { "FLOOR", FLOOR },
1184  { "FLESH", FLESH },
1185  { "INORGANIC", INORGANIC },
1186  { "SKILL_TOOL", SKILL_TOOL },
1187  { "LIGHTER", LIGHTER },
1188  { "WALL", WALL },
1189  { "MISC_OBJECT", MISC_OBJECT },
1190  { "MONSTER", MONSTER },
1191  { "LAMP", LAMP },
1192  { "DUPLICATOR", DUPLICATOR },
1193  { "SPELLBOOK", SPELLBOOK },
1194  { "CLOAK", CLOAK },
1195  { "SPINNER", SPINNER },
1196  { "GATE", GATE },
1197  { "BUTTON", BUTTON },
1198  { "CF_HANDLE", CF_HANDLE },
1199  { "HOLE", HOLE },
1200  { "TRAPDOOR", TRAPDOOR },
1201  { "SIGN", SIGN },
1202  { "BOOTS", BOOTS },
1203  { "GLOVES", GLOVES },
1204  { "SPELL", SPELL },
1205  { "SPELL_EFFECT", SPELL_EFFECT },
1206  { "CONVERTER", CONVERTER },
1207  { "BRACERS", BRACERS },
1208  { "POISONING", POISONING },
1209  { "SAVEBED", SAVEBED },
1210  { "WAND", WAND },
1211  { "SCROLL", SCROLL },
1212  { "DIRECTOR", DIRECTOR },
1213  { "GIRDLE", GIRDLE },
1214  { "FORCE", FORCE },
1215  { "POTION_RESIST_EFFECT", POTION_RESIST_EFFECT },
1216  { "EVENT_CONNECTOR", EVENT_CONNECTOR },
1217  { "CLOSE_CON", CLOSE_CON },
1218  { "CONTAINER", CONTAINER },
1219  { "ARMOUR_IMPROVER", ARMOUR_IMPROVER },
1220  { "WEAPON_IMPROVER", WEAPON_IMPROVER },
1221  { "SKILLSCROLL", SKILLSCROLL },
1222  { "DEEP_SWAMP", DEEP_SWAMP },
1223  { "IDENTIFY_ALTAR", IDENTIFY_ALTAR },
1224  { "SHOP_INVENTORY", SHOP_INVENTORY },
1225  { "RUNE", RUNE },
1226  { "TRAP", TRAP },
1227  { "POWER_CRYSTAL", POWER_CRYSTAL },
1228  { "CORPSE", CORPSE },
1229  { "DISEASE", DISEASE },
1230  { "SYMPTOM", SYMPTOM },
1231  { "BUILDER", BUILDER },
1232  { "MATERIAL", MATERIAL },
1233  { "MIMIC", MIMIC },
1234  { "LIGHTABLE", LIGHTABLE },
1235  { NULL, 0 }
1236 };
1237 
1238 const CFConstant cstMove[] = {
1239  { "WALK", MOVE_WALK },
1240  { "FLY_LOW", MOVE_FLY_LOW },
1241  { "FLY_HIGH", MOVE_FLY_HIGH },
1242  { "FLYING", MOVE_FLYING },
1243  { "SWIM", MOVE_SWIM },
1244  { "BOAT", MOVE_BOAT },
1245  { "ALL", MOVE_ALL },
1246  { NULL, 0 }
1247 };
1248 
1250  { "NDI_BLACK", NDI_BLACK },
1251  { "NDI_WHITE", NDI_WHITE },
1252  { "NDI_NAVY", NDI_NAVY },
1253  { "NDI_RED", NDI_RED },
1254  { "NDI_ORANGE", NDI_ORANGE },
1255  { "NDI_BLUE", NDI_BLUE },
1256  { "NDI_DK_ORANGE", NDI_DK_ORANGE },
1257  { "NDI_GREEN", NDI_GREEN },
1258  { "NDI_LT_GREEN", NDI_LT_GREEN },
1259  { "NDI_GREY", NDI_GREY },
1260  { "NDI_BROWN", NDI_BROWN },
1261  { "NDI_GOLD", NDI_GOLD },
1262  { "NDI_TAN", NDI_TAN },
1263  { "NDI_UNIQUE", NDI_UNIQUE },
1264  { "NDI_ALL", NDI_ALL },
1265  { "NDI_ALL_DMS", NDI_ALL_DMS },
1266  { NULL, 0 }
1267 };
1268 
1270  { "PHYSICAL", AT_PHYSICAL },
1271  { "MAGIC", AT_MAGIC },
1272  { "FIRE", AT_FIRE },
1273  { "ELECTRICITY", AT_ELECTRICITY },
1274  { "COLD", AT_COLD },
1275  { "CONFUSION", AT_CONFUSION },
1276  { "ACID", AT_ACID },
1277  { "DRAIN", AT_DRAIN },
1278  { "WEAPONMAGIC", AT_WEAPONMAGIC },
1279  { "GHOSTHIT", AT_GHOSTHIT },
1280  { "POISON", AT_POISON },
1281  { "SLOW", AT_SLOW },
1282  { "PARALYZE", AT_PARALYZE },
1283  { "TURN_UNDEAD", AT_TURN_UNDEAD },
1284  { "FEAR", AT_FEAR },
1285  { "CANCELLATION", AT_CANCELLATION },
1286  { "DEPLETE", AT_DEPLETE },
1287  { "DEATH", AT_DEATH },
1288  { "CHAOS", AT_CHAOS },
1289  { "COUNTERSPELL", AT_COUNTERSPELL },
1290  { "GODPOWER", AT_GODPOWER },
1291  { "HOLYWORD", AT_HOLYWORD },
1292  { "BLIND", AT_BLIND },
1293  { "INTERNAL", AT_INTERNAL },
1294  { "LIFE_STEALING", AT_LIFE_STEALING },
1295  { "DISEASE", AT_DISEASE },
1296  { NULL, 0 }
1297 };
1298 
1300  { "PHYSICAL", ATNR_PHYSICAL },
1301  { "MAGIC", ATNR_MAGIC },
1302  { "FIRE", ATNR_FIRE },
1303  { "ELECTRICITY", ATNR_ELECTRICITY },
1304  { "COLD", ATNR_COLD },
1305  { "CONFUSION", ATNR_CONFUSION },
1306  { "ACID", ATNR_ACID },
1307  { "DRAIN", ATNR_DRAIN },
1308  { "WEAPONMAGIC", ATNR_WEAPONMAGIC },
1309  { "GHOSTHIT", ATNR_GHOSTHIT },
1310  { "POISON", ATNR_POISON },
1311  { "SLOW", ATNR_SLOW },
1312  { "PARALYZE", ATNR_PARALYZE },
1313  { "TURN_UNDEAD", ATNR_TURN_UNDEAD },
1314  { "FEAR", ATNR_FEAR },
1315  { "CANCELLATION", ATNR_CANCELLATION },
1316  { "DEPLETE", ATNR_DEPLETE },
1317  { "DEATH", ATNR_DEATH },
1318  { "CHAOS", ATNR_CHAOS },
1319  { "COUNTERSPELL", ATNR_COUNTERSPELL },
1320  { "GODPOWER", ATNR_GODPOWER },
1321  { "HOLYWORD", ATNR_HOLYWORD },
1322  { "BLIND", ATNR_BLIND },
1323  { "INTERNAL", ATNR_INTERNAL },
1324  { "LIFE_STEALING", ATNR_LIFE_STEALING },
1325  { "DISEASE", ATNR_DISEASE },
1326  { NULL, 0 }
1327 };
1328 
1331  { "APPLY", EVENT_APPLY },
1332  { "ATTACK", EVENT_ATTACKED },
1333  { "ATTACKS", EVENT_ATTACKS },
1334  { "BOUGHT", EVENT_BOUGHT },
1335  { "CLOSE", EVENT_CLOSE },
1336  { "DEATH", EVENT_DEATH },
1337  { "DESTROY", EVENT_DESTROY },
1338  { "DROP", EVENT_DROP },
1339  { "PICKUP", EVENT_PICKUP },
1340  { "SAY", EVENT_SAY },
1341  { "SELLING", EVENT_SELLING },
1342  { "STOP", EVENT_STOP },
1343  { "TIME", EVENT_TIME },
1344  { "THROW", EVENT_THROW },
1345  { "TRIGGER", EVENT_TRIGGER },
1346  { "TIMER", EVENT_TIMER },
1347  { "USER", EVENT_USER },
1348 
1350  { "BORN", EVENT_BORN },
1351  { "CLOCK", EVENT_CLOCK },
1352  { "CRASH", EVENT_CRASH },
1353  { "GKILL", EVENT_GKILL },
1354  { "KICK", EVENT_KICK },
1355  { "LOGIN", EVENT_LOGIN },
1356  { "LOGOUT", EVENT_LOGOUT },
1357  { "MAPENTER", EVENT_MAPENTER },
1358  { "MAPLEAVE", EVENT_MAPLEAVE },
1359  { "MAPLOAD", EVENT_MAPLOAD },
1360  { "MAPREADY", EVENT_MAPREADY },
1361  { "MAPRESET", EVENT_MAPRESET },
1362  { "MAPUNLOAD", EVENT_MAPUNLOAD },
1363  { "MUZZLE", EVENT_MUZZLE },
1364  { "PLAYER_DEATH", EVENT_PLAYER_DEATH },
1365  { "REMOVE", EVENT_REMOVE },
1366  { "SHOUT", EVENT_SHOUT },
1367  { "TELL", EVENT_TELL },
1368  { NULL, 0 }
1369 };
1370 
1371 const CFConstant cstTime[] = {
1372  { "HOURS_PER_DAY", HOURS_PER_DAY },
1373  { "DAYS_PER_WEEK", DAYS_PER_WEEK },
1374  { "WEEKS_PER_MONTH", WEEKS_PER_MONTH },
1375  { "MONTHS_PER_YEAR", MONTHS_PER_YEAR },
1376  { "SEASONS_PER_YEAR", SEASONS_PER_YEAR },
1377  { "PERIODS_PER_DAY", PERIODS_PER_DAY },
1378  { NULL, 0 }
1379 };
1380 
1382  { "SAY", rt_say },
1383  { "REPLY", rt_reply },
1384  { "QUESTION", rt_question },
1385  { NULL, 0 }
1386 };
1387 
1389  { "DISTATT", DISTATT },
1390  { "RUNATT", RUNATT },
1391  { "HITRUN", HITRUN },
1392  { "WAITATT", WAITATT },
1393  { "RUSH", RUSH },
1394  { "ALLRUN", ALLRUN },
1395  { "DISTHIT", DISTHIT },
1396  { "WAIT2", WAIT2 },
1397  { "PETMOVE", PETMOVE },
1398  { "CIRCLE1", CIRCLE1 },
1399  { "CIRCLE2", CIRCLE2 },
1400  { "PACEH", PACEH },
1401  { "PACEH2", PACEH2 },
1402  { "RANDO", RANDO },
1403  { "RANDO2", RANDO2 },
1404  { "PACEV", PACEV },
1405  { "PACEV2", PACEV2 },
1406  { NULL, 0 }
1407 };
1408 
1409 static void initConstants(PyObject *module) {
1410  addConstants(module, "Direction", cstDirection);
1411  addConstants(module, "Type", cstType);
1412  addConstants(module, "Move", cstMove);
1413  addConstants(module, "MessageFlag", cstMessageFlag);
1414  addConstants(module, "AttackType", cstAttackType);
1415  addConstants(module, "AttackTypeNumber", cstAttackTypeNumber);
1416  addConstants(module, "EventType", cstEventType);
1417  addSimpleConstants(module, "Time", cstTime);
1418  addSimpleConstants(module, "ReplyType", cstReplyTypes);
1419  addSimpleConstants(module, "AttackMovement", cstAttackMovement);
1420 }
1421 
1422 /*
1423  * Set up the main module and handle misc plugin loading stuff and such.
1424  */
1425 
1430 static void cfpython_init_types(PyObject* m) {
1431  PyObject *d = PyModule_GetDict(m);
1432 
1433  Crossfire_ObjectType.tp_new = PyType_GenericNew;
1434  Crossfire_MapType.tp_new = PyType_GenericNew;
1435  Crossfire_PlayerType.tp_new = PyType_GenericNew;
1436  Crossfire_ArchetypeType.tp_new = PyType_GenericNew;
1437  Crossfire_PartyType.tp_new = PyType_GenericNew;
1438  Crossfire_RegionType.tp_new = PyType_GenericNew;
1439  PyType_Ready(&Crossfire_ObjectType);
1440  PyType_Ready(&Crossfire_MapType);
1441  PyType_Ready(&Crossfire_PlayerType);
1442  PyType_Ready(&Crossfire_ArchetypeType);
1443  PyType_Ready(&Crossfire_PartyType);
1444  PyType_Ready(&Crossfire_RegionType);
1445 
1446  Py_INCREF(&Crossfire_ObjectType);
1447  Py_INCREF(&Crossfire_MapType);
1448  Py_INCREF(&Crossfire_PlayerType);
1449  Py_INCREF(&Crossfire_ArchetypeType);
1450  Py_INCREF(&Crossfire_PartyType);
1451  Py_INCREF(&Crossfire_RegionType);
1452 
1453  PyModule_AddObject(m, "Object", (PyObject *)&Crossfire_ObjectType);
1454  PyModule_AddObject(m, "Map", (PyObject *)&Crossfire_MapType);
1455  PyModule_AddObject(m, "Player", (PyObject *)&Crossfire_PlayerType);
1456  PyModule_AddObject(m, "Archetype", (PyObject *)&Crossfire_ArchetypeType);
1457  PyModule_AddObject(m, "Party", (PyObject *)&Crossfire_PartyType);
1458  PyModule_AddObject(m, "Region", (PyObject *)&Crossfire_RegionType);
1459 
1460  PyModule_AddObject(m, "LogError", Py_BuildValue("i", llevError));
1461  PyModule_AddObject(m, "LogInfo", Py_BuildValue("i", llevInfo));
1462  PyModule_AddObject(m, "LogDebug", Py_BuildValue("i", llevDebug));
1463  PyModule_AddObject(m, "LogMonster", Py_BuildValue("i", llevMonster));
1464 
1465  CFPythonError = PyErr_NewException("Crossfire.error", NULL, NULL);
1466  PyDict_SetItemString(d, "error", CFPythonError);
1467 }
1468 
1469 extern PyObject* PyInit_cjson(void);
1470 
1471 static PyModuleDef CrossfireModule = {
1472  PyModuleDef_HEAD_INIT,
1473  "Crossfire", /* m_name */
1474  NULL, /* m_doc */
1475  -1, /* m_size */
1476  CFPythonMethods, /* m_methods */
1477  NULL, /* m_reload */
1478  NULL, /* m_traverse */
1479  NULL, /* m_clear */
1480  NULL /* m_free */
1481 };
1482 
1483 static PyObject* PyInit_Crossfire(void)
1484 {
1485  PyObject *m = PyModule_Create(&CrossfireModule);
1486  Py_INCREF(m);
1487  return m;
1488 }
1489 
1490 extern "C"
1491 int initPlugin(const char *iversion, f_plug_api gethooksptr) {
1492  PyObject *m;
1493  /* Python code to redirect stdouts/stderr. */
1494  const char *stdOutErr =
1495 "import sys\n\
1496 class CatchOutErr:\n\
1497  def __init__(self):\n\
1498  self.value = ''\n\
1499  def write(self, txt):\n\
1500  self.value += txt\n\
1501 catchOutErr = CatchOutErr()\n\
1502 sys.stdout = catchOutErr\n\
1503 sys.stderr = catchOutErr\n\
1504 ";
1505  (void)iversion;
1506 
1507  for (int c = 0; c < MAX_COMMANDS; c++) {
1508  registered_commands[c] = 0;
1509  }
1510 
1511  cf_init_plugin(gethooksptr);
1512  cf_log(llevDebug, "CFPython 2.0a init\n");
1513 
1514  PyImport_AppendInittab("Crossfire", &PyInit_Crossfire);
1515  PyImport_AppendInittab("cjson", &PyInit_cjson);
1516 
1517  Py_Initialize();
1518 
1519  m = PyImport_ImportModule("Crossfire");
1520 
1522 
1523  initConstants(m);
1524  private_data = PyDict_New();
1525  shared_data = PyDict_New();
1526 
1527  /* Redirect Python's stderr to a special object so it can be put to
1528  * the Crossfire log. */
1529  m = PyImport_AddModule("__main__");
1530  PyRun_SimpleString(stdOutErr);
1531  catcher = PyObject_GetAttrString(m, "catchOutErr");
1532  return 0;
1533 }
1534 
1536  va_list args;
1537  const char *propname;
1538  int size;
1539  char *buf;
1540 
1541  va_start(args, type);
1542  propname = va_arg(args, const char *);
1543  if (!strcmp(propname, "Identification")) {
1544  buf = va_arg(args, char *);
1545  size = va_arg(args, int);
1546  va_end(args);
1547  snprintf(buf, size, PLUGIN_NAME);
1548  return NULL;
1549  } else if (!strcmp(propname, "FullName")) {
1550  buf = va_arg(args, char *);
1551  size = va_arg(args, int);
1552  va_end(args);
1553  snprintf(buf, size, PLUGIN_VERSION);
1554  return NULL;
1555  }
1556  va_end(args);
1557  return NULL;
1558 }
1559 
1560 static int GECodes[] = {
1561  EVENT_BORN,
1562  EVENT_CLOCK,
1564  EVENT_GKILL,
1565  EVENT_LOGIN,
1566  EVENT_LOGOUT,
1570  EVENT_REMOVE,
1571  EVENT_SHOUT,
1572  EVENT_TELL,
1573  EVENT_MUZZLE,
1574  EVENT_KICK,
1576  EVENT_MAPLOAD,
1578  0
1579 };
1580 
1581 static const char* GEPaths[] = {
1582  "born",
1583  "clock",
1584  "death",
1585  "gkill",
1586  "login",
1587  "logout",
1588  "mapenter",
1589  "mapleave",
1590  "mapreset",
1591  "remove",
1592  "shout",
1593  "tell",
1594  "muzzle",
1595  "kick",
1596  "mapunload",
1597  "mapload",
1598  "mapready",
1599  NULL
1600 };
1601 
1607 static void freeEventFiles(char **eventFiles) {
1608  assert(eventFiles);
1609  for (int e = 0; eventFiles[e] != NULL; e++) {
1610  free(eventFiles[e]);
1611  }
1612  free(eventFiles);
1613 }
1614 
1620 static char **getEventFiles(CFPContext *context) {
1621  char **eventFiles = NULL;
1622  char name[NAME_MAX+1], path[NAME_MAX + 1];
1623 
1624  int allocated = 0, current = 0;
1625  DIR *dp;
1626  struct dirent *d;
1627  struct stat sb;
1628 
1629  snprintf(name, sizeof(name), "python/events/%s/", context->options);
1630  cf_get_maps_directory(name, path, sizeof(path));
1631 
1632  dp = opendir(path);
1633  if (dp == NULL) {
1634  eventFiles = static_cast<char **>(calloc(1, sizeof(eventFiles[0])));
1635  eventFiles[0] = NULL;
1636  return eventFiles;
1637  }
1638 
1639  while ((d = readdir(dp)) != NULL) {
1640  snprintf(name, sizeof(name), "%s%s", path, d->d_name);
1641  stat(name, &sb);
1642  if (S_ISDIR(sb.st_mode)) {
1643  continue;
1644  }
1645  if (strcmp(d->d_name + strlen(d->d_name) - 3, ".py")) {
1646  continue;
1647  }
1648 
1649  if (allocated == current) {
1650  allocated += 10;
1651  eventFiles = static_cast<char **>(realloc(eventFiles, sizeof(char *) * (allocated + 1)));
1652  for (int i = current; i < allocated + 1; i++) {
1653  eventFiles[i] = NULL;
1654  }
1655  }
1656  eventFiles[current] = strdup(name);
1657  current++;
1658  }
1659  (void)closedir(dp);
1660  return eventFiles;
1661 }
1662 
1664  PyObject *scriptfile;
1665  char path[1024];
1666  int i;
1667 
1668  cf_log(llevDebug, "CFPython 2.0a post init\n");
1669  initContextStack();
1670  for (i = 0; GECodes[i] != 0; i++)
1672 
1673  scriptfile = cfpython_openpyfile(cf_get_maps_directory("python/events/python_init.py", path, sizeof(path)));
1674  if (scriptfile != NULL) {
1675  FILE* pyfile = cfpython_pyfile_asfile(scriptfile);
1676  PyRun_SimpleFile(pyfile, cf_get_maps_directory("python/events/python_init.py", path, sizeof(path)));
1677  Py_DECREF(scriptfile);
1678  }
1679 
1680  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
1681  pycode_cache[i].code = NULL;
1682  pycode_cache[i].file = NULL;
1683  pycode_cache[i].cached_time = 0;
1684  pycode_cache[i].used_time = 0;
1685  }
1686 
1687  return 0;
1688 }
1689 
1690 static const char *getGlobalEventPath(int code) {
1691  for (int i = 0; GECodes[i] != 0; i++) {
1692  if (GECodes[i] == code)
1693  return GEPaths[i];
1694  }
1695  return "";
1696 }
1697 
1699  va_list args;
1700  int rv = 0;
1701  CFPContext *context;
1702  char *buf;
1703  player *pl;
1704  object *op;
1705  context = static_cast<CFPContext *>(calloc(1, sizeof(CFPContext)));
1706  char **files;
1707 
1708  va_start(args, type);
1709  context->event_code = va_arg(args, int);
1710 
1711  context->message[0] = 0;
1712 
1713  rv = context->returnvalue = 0;
1714  switch (context->event_code) {
1715  case EVENT_CRASH:
1716  cf_log(llevDebug, "CFPython: event_crash unimplemented for now\n");
1717  break;
1718 
1719  case EVENT_BORN:
1720  op = va_arg(args, object *);
1721  context->activator = Crossfire_Object_wrap(op);
1722  break;
1723 
1724  case EVENT_PLAYER_DEATH:
1725  op = va_arg(args, object *);
1726  context->who = Crossfire_Object_wrap(op);
1727  op = va_arg(args, object *);
1728  context->activator = Crossfire_Object_wrap(op);
1729  break;
1730 
1731  case EVENT_GKILL:
1732  {
1733  op = va_arg(args, object *);
1734  object* hitter = va_arg(args, object *);
1735  context->who = Crossfire_Object_wrap(op);
1737  break;
1738  }
1739 
1740  case EVENT_LOGIN:
1741  pl = va_arg(args, player *);
1742  context->activator = Crossfire_Object_wrap(pl->ob);
1743  buf = va_arg(args, char *);
1744  if (buf != NULL)
1745  snprintf(context->message, sizeof(context->message), "%s", buf);
1746  break;
1747 
1748  case EVENT_LOGOUT:
1749  pl = va_arg(args, player *);
1750  context->activator = Crossfire_Object_wrap(pl->ob);
1751  buf = va_arg(args, char *);
1752  if (buf != NULL)
1753  snprintf(context->message, sizeof(context->message), "%s", buf);
1754  break;
1755 
1756  case EVENT_REMOVE:
1757  op = va_arg(args, object *);
1758  context->activator = Crossfire_Object_wrap(op);
1759  break;
1760 
1761  case EVENT_SHOUT:
1762  op = va_arg(args, object *);
1763  context->activator = Crossfire_Object_wrap(op);
1764  buf = va_arg(args, char *);
1765  if (buf != NULL)
1766  snprintf(context->message, sizeof(context->message), "%s", buf);
1767  break;
1768 
1769  case EVENT_MUZZLE:
1770  op = va_arg(args, object *);
1771  context->activator = Crossfire_Object_wrap(op);
1772  buf = va_arg(args, char *);
1773  if (buf != NULL)
1774  snprintf(context->message, sizeof(context->message), "%s", buf);
1775  break;
1776 
1777  case EVENT_KICK:
1778  op = va_arg(args, object *);
1779  context->activator = Crossfire_Object_wrap(op);
1780  buf = va_arg(args, char *);
1781  if (buf != NULL)
1782  snprintf(context->message, sizeof(context->message), "%s", buf);
1783  break;
1784 
1785  case EVENT_MAPENTER:
1786  op = va_arg(args, object *);
1787  context->activator = Crossfire_Object_wrap(op);
1788  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1789  break;
1790 
1791  case EVENT_MAPLEAVE:
1792  op = va_arg(args, object *);
1793  context->activator = Crossfire_Object_wrap(op);
1794  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1795  break;
1796 
1797  case EVENT_CLOCK:
1798  break;
1799 
1800  case EVENT_MAPRESET:
1801  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1802  break;
1803 
1804  case EVENT_TELL:
1805  op = va_arg(args, object *);
1806  buf = va_arg(args, char *);
1807  context->activator = Crossfire_Object_wrap(op);
1808  if (buf != NULL)
1809  snprintf(context->message, sizeof(context->message), "%s", buf);
1810  op = va_arg(args, object *);
1811  context->third = Crossfire_Object_wrap(op);
1812  break;
1813 
1814  case EVENT_MAPUNLOAD:
1815  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1816  break;
1817 
1818  case EVENT_MAPLOAD:
1819  context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *));
1820  break;
1821  }
1822  va_end(args);
1823  context->returnvalue = 0;
1824 
1825  if (context->event_code == EVENT_CLOCK) {
1826  // Ignore EVENT_CLOCK. It is not being used in maps, but nevertheless
1827  // runs python_init.py several times per second even while idling.
1828  freeContext(context);
1829  return rv;
1830  }
1831 
1832  snprintf(context->options, sizeof(context->options), "%s", getGlobalEventPath(context->event_code));
1833  files = getEventFiles(context);
1834  for (int file = 0; files[file] != NULL; file++)
1835  {
1836  CFPContext *copy = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
1837  (*copy) = (*context);
1838  Py_XINCREF(copy->activator);
1839  Py_XINCREF(copy->event);
1840  Py_XINCREF(copy->third);
1841  Py_XINCREF(copy->who);
1842  strncpy(copy->script, files[file], sizeof(copy->script));
1843 
1844  if (!do_script(copy)) {
1845  freeContext(copy);
1846  freeEventFiles(files);
1847  return rv;
1848  }
1849 
1850  copy = popContext();
1851  rv = copy->returnvalue;
1852 
1853  freeContext(copy);
1854  }
1855  freeEventFiles(files);
1856 
1857  /* Invalidate freed map wrapper. */
1858  if (context->event_code == EVENT_MAPUNLOAD)
1860 
1861  free(context);
1862 
1863  return rv;
1864 }
1865 
1866 CF_PLUGIN int eventListener(int *type, ...) {
1867  int rv = 0;
1868  va_list args;
1869  char *buf;
1870  CFPContext *context;
1871  object *event;
1872 
1873  context = static_cast<CFPContext *>(malloc(sizeof(CFPContext)));
1874 
1875  context->message[0] = 0;
1876 
1877  va_start(args, type);
1878 
1879  context->who = Crossfire_Object_wrap(va_arg(args, object *));
1880  context->activator = Crossfire_Object_wrap(va_arg(args, object *));
1881  context->third = Crossfire_Object_wrap(va_arg(args, object *));
1882  buf = va_arg(args, char *);
1883  if (buf != NULL)
1884  snprintf(context->message, sizeof(context->message), "%s", buf);
1885  /* fix = */va_arg(args, int);
1886  event = va_arg(args, object *);
1887  context->talk = va_arg(args, talk_info *);
1888  context->event_code = event->subtype;
1889  context->event = Crossfire_Object_wrap(event);
1890  cf_get_maps_directory(event->slaying, context->script, sizeof(context->script));
1891  snprintf(context->options, sizeof(context->options), "%s", event->name);
1892  context->returnvalue = 0;
1893 
1894  va_end(args);
1895 
1896  if (!do_script(context)) {
1897  freeContext(context);
1898  return rv;
1899  }
1900 
1901  context = popContext();
1902  rv = context->returnvalue;
1903  freeContext(context);
1904  return rv;
1905 }
1906 
1908  int i;
1909 
1910  cf_log(llevDebug, "CFPython 2.0a closing\n");
1911 
1912  for (int c = 0; c < MAX_COMMANDS; c++) {
1913  if (registered_commands[c]) {
1915  }
1916  }
1917 
1918  for (i = 0; i < PYTHON_CACHE_SIZE; i++) {
1919  Py_XDECREF(pycode_cache[i].code);
1920  if (pycode_cache[i].file != NULL)
1922  }
1923 
1924  Py_Finalize();
1925 
1926  return 0;
1927 }
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:994
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:644
CFPContext::event_code
int event_code
Definition: cfpython.h:98
TRIGGER
@ TRIGGER
Definition: object.h:132
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:1522
ATNR_PARALYZE
#define ATNR_PARALYZE
Definition: attack.h:61
cstMove
const CFConstant cstMove[]
Definition: cfpython.cpp:1238
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:1574
cf_add_string
sstring cf_add_string(const char *str)
Definition: plugin_common.cpp:1167
talk_info::replies
sstring replies[MAX_REPLIES]
Definition: dialog.h:59
MAP
@ MAP
Definition: object.h:128
getSeasonName
static PyObject * getSeasonName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:635
cf_get_directory
const char * cf_get_directory(int id)
Definition: plugin_common.cpp:1130
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
maps
static std::unordered_map< std::string, mapzone * > maps
Definition: citylife.cpp:92
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:1556
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
player
Definition: player.h:105
GLOVES
@ GLOVES
Definition: object.h:216
altar_valkyrie.obj
obj
Definition: altar_valkyrie.py:33
GIRDLE
@ GIRDLE
Definition: object.h:226
compilePython
static PyCodeObject * compilePython(char *filename)
Definition: cfpython.cpp:913
ATNR_ACID
#define ATNR_ACID
Definition: attack.h:55
BUTTON
@ BUTTON
Definition: object.h:210
timeofday_t::year
int year
Definition: tod.h:39
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
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:137
NDI_GREEN
#define NDI_GREEN
Definition: newclient.h:249
KEY
@ KEY
Definition: object.h:130
CFBank.open
def open()
Definition: CFBank.py:70
CFPContext::third
PyObject * third
Definition: cfpython.h:95
Crossfire_Object
Definition: cfpython_object.h:32
timeofday_t::weekofmonth
int weekofmonth
Definition: tod.h:45
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:1663
eventListener
CF_PLUGIN int eventListener(int *type,...)
Definition: cfpython.cpp:1866
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:186
GEM
@ GEM
Definition: object.h:170
cf_create_object_by_name
object * cf_create_object_by_name(const char *name)
Definition: plugin_common.cpp:1093
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:699
CFPythonError
static PyObject * CFPythonError
Definition: cfpython.cpp:90
player::ob
object * ob
Definition: player.h:176
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:832
WEAPON
@ WEAPON
Definition: object.h:122
TIMED_GATE
@ TIMED_GATE
Definition: object.h:131
guildjoin.ob
ob
Definition: guildjoin.py:42
timeofday_t
Definition: tod.h:38
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
CFPContext::activator
PyObject * activator
Definition: cfpython.h:94
cf_timer_destroy
int cf_timer_destroy(int id)
Definition: plugin_common.cpp:1620
ATNR_SLOW
#define ATNR_SLOW
Definition: attack.h:60
CFAPI_SYSTEM_ARCHETYPES
#define CFAPI_SYSTEM_ARCHETYPES
Definition: plugin.h:286
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:1491
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:113
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
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.cpp:101
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:500
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:822
COMMAND_TYPE_NORMAL
#define COMMAND_TYPE_NORMAL
Definition: commands.h:35
llevMonster
@ llevMonster
Definition: logger.h:14
EVENT_SAY
#define EVENT_SAY
Definition: events.h:29
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
SIGN
@ SIGN
Definition: object.h:214
CFAPI_SYSTEM_PLAYERS
#define CFAPI_SYSTEM_PLAYERS
Definition: plugin.h:285
NAME_MAX
#define NAME_MAX
Definition: define.h:30
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:1620
npc_dialog.filename
filename
Definition: npc_dialog.py:99
friends
static std::vector< std::pair< object *, tag_t > > friends
Definition: friend.cpp:23
CFPContext::down
CFPContext * down
Definition: cfpython.h:92
Handle_Map_Unload_Hook
void Handle_Map_Unload_Hook(Crossfire_Map *map)
Definition: cfpython_map.cpp:430
NDI_BLUE
#define NDI_BLUE
Definition: newclient.h:247
current_context
CFPContext * current_context
Definition: cfpython.cpp:106
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:1551
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:1606
cstMessageFlag
const CFConstant cstMessageFlag[]
Definition: cfpython.cpp:1249
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
cf_system_get_region_vector
void cf_system_get_region_vector(int property, std::vector< region * > *list)
Definition: plugin_common.cpp:2140
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
CFPContext::who
PyObject * who
Definition: cfpython.h:93
m
static event_registration m
Definition: citylife.cpp:425
getPluginProperty
CF_PLUGIN void * getPluginProperty(int *type,...)
Definition: cfpython.cpp:1535
AT_CHAOS
#define AT_CHAOS
Definition: attack.h:94
CLOAK
@ CLOAK
Definition: object.h:207
timeofday_t::day
int day
Definition: tod.h:41
pycode_cache_entry::cached_time
time_t cached_time
Definition: cfpython.cpp:80
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:1542
EVENT_STOP
#define EVENT_STOP
Definition: events.h:31
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:571
GEPaths
static const char * GEPaths[]
Definition: cfpython.cpp:1581
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
timeofday_t::periodofday
int periodofday
Definition: tod.h:47
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:1510
BUILDER
@ BUILDER
Definition: object.h:249
EVENT_DROP
#define EVENT_DROP
Definition: events.h:27
findFace
static PyObject * findFace(PyObject *self, PyObject *args)
Definition: cfpython.cpp:580
EVENT_TRIGGER
#define EVENT_TRIGGER
Definition: events.h:34
f_plug_api
void(* f_plug_api)(int *type,...)
Definition: plugin.h:79
EVENT_MAPENTER
#define EVENT_MAPENTER
Definition: events.h:46
cstDirection
const CFConstant cstDirection[]
Definition: cfpython.cpp:1110
CFPContext
Definition: cfpython.h:91
npcSay
static PyObject * npcSay(PyObject *self, PyObject *args)
Definition: cfpython.cpp:722
cf_system_unregister_global_event
void cf_system_unregister_global_event(int event, const char *name)
Definition: plugin_common.cpp:1109
cf_get_month_name
const char * cf_get_month_name(int index)
Definition: plugin_common.cpp:1565
cf_init_plugin
int cf_init_plugin(f_plug_api getHooks)
Definition: plugin_common.cpp:146
ROD
@ ROD
Definition: object.h:112
CONTAINER
@ CONTAINER
Definition: object.h:234
INORGANIC
@ INORGANIC
Definition: object.h:191
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:948
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:126
PLAYERMOVER
@ PLAYERMOVER
Definition: object.h:143
PLUGIN_NAME
#define PLUGIN_NAME
Definition: cfanim.h:32
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:1094
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:752
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:1032
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:1560
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:877
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:456
timeofday_t::dayofweek
int dayofweek
Definition: tod.h:42
GOLEM
@ GOLEM
Definition: object.h:148
registered_commands
static command_registration registered_commands[MAX_COMMANDS]
Definition: cfpython.cpp:85
sstring
const typedef char * sstring
Definition: global.h:47
ATNR_COUNTERSPELL
#define ATNR_COUNTERSPELL
Definition: attack.h:68
closePlugin
CF_PLUGIN int closePlugin(void)
Definition: cfpython.cpp:1907
getPlayers
static PyObject * getPlayers(PyObject *self, PyObject *args)
Definition: cfpython.cpp:398
EVENT_USER
#define EVENT_USER
Definition: events.h:36
MOOD_FLOOR
@ MOOD_FLOOR
Definition: object.h:173
CFAPI_SYSTEM_MAPS
#define CFAPI_SYSTEM_MAPS
Definition: plugin.h:284
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
BOOK
@ BOOK
Definition: object.h:117
empty
const char * empty[]
Definition: check_treasure.cpp:107
CFPContext::message
char message[1024]
Definition: cfpython.h:97
Crossfire_Region_wrap
PyObject * Crossfire_Region_wrap(region *what)
Definition: cfpython_region.cpp:72
timeofday_t::month
int month
Definition: tod.h:40
RING
@ RING
Definition: object.h:188
CFAPI_SYSTEM_REGIONS
#define CFAPI_SYSTEM_REGIONS
Definition: plugin.h:287
EVENT_SHOUT
#define EVENT_SHOUT
Definition: events.h:55
BLINDNESS
@ BLINDNESS
Definition: object.h:150
replace
Definition: replace.py:1
timeofday_t::season
int season
Definition: tod.h:46
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
getUniqueDirectory
static PyObject * getUniqueDirectory(PyObject *self, PyObject *args)
Definition: cfpython.cpp:257
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:1182
cstTime
const CFConstant cstTime[]
Definition: cfpython.cpp:1371
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
destroyTimer
static PyObject * destroyTimer(PyObject *self, PyObject *args)
Definition: cfpython.cpp:562
CFPContext::talk
struct talk_info * talk
Definition: cfpython.h:102
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:869
cstType
const CFConstant cstType[]
Definition: cfpython.cpp:1122
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:2103
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:653
PLUGIN_VERSION
#define PLUGIN_VERSION
Definition: cfanim.h:33
getMaps
static PyObject * getMaps(PyObject *self, PyObject *args)
Definition: cfpython.cpp:413
cstReplyTypes
const CFConstant cstReplyTypes[]
Definition: cfpython.cpp:1381
diamondslots.message
string message
Definition: diamondslots.py:57
cf_system_get_object_vector
void cf_system_get_object_vector(int property, std::vector< object * > *list)
Definition: plugin_common.cpp:2116
replace
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Definition: utils.cpp:327
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:1102
llevInfo
@ llevInfo
Definition: logger.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:855
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:1498
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:765
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
AT_SLOW
#define AT_SLOW
Definition: attack.h:87
CFAPI_SYSTEM_FRIENDLY_LIST
#define CFAPI_SYSTEM_FRIENDLY_LIST
Definition: plugin.h:289
CFConstant
Definition: cfpython.h:105
MAX_REPLIES
#define MAX_REPLIES
Definition: dialog.h:45
players
std::vector< archetype * > players
Definition: player.cpp:493
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:1583
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
timeofday_t::minute
int minute
Definition: tod.h:44
CrossfireModule
static PyModuleDef CrossfireModule
Definition: cfpython.cpp:1471
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:470
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:1690
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:165
mapstruct
Definition: map.h:316
cf_system_get_map_vector
void cf_system_get_map_vector(int property, std::vector< mapstruct * > *list)
Definition: plugin_common.cpp:2122
createCFObjectByName
static PyObject * createCFObjectByName(PyObject *self, PyObject *args)
Definition: cfpython.cpp:152
cstAttackType
const CFConstant cstAttackType[]
Definition: cfpython.cpp:1269
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
cstAttackTypeNumber
const CFConstant cstAttackTypeNumber[]
Definition: cfpython.cpp:1299
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:961
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:1143
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:442
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:428
timeofday_t::hour
int hour
Definition: tod.h:43
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:1081
cf_get_maps_directory
char * cf_get_maps_directory(const char *name, char *buf, int size)
Definition: plugin_common.cpp:1069
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
freeEventFiles
static void freeEventFiles(char **eventFiles)
Definition: cfpython.cpp:1607
cfpython_init_types
static void cfpython_init_types(PyObject *m)
Definition: cfpython.cpp:1430
regions
static std::unordered_map< std::string, Region * > regions
Definition: cfcitybell.cpp:43
CFPContext::event
PyObject * event
Definition: cfpython.h:96
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:248
addReply
static PyObject * addReply(PyObject *self, PyObject *args)
Definition: cfpython.cpp:671
level
int level
Definition: readable.cpp:1549
pycode_cache_entry
Definition: cfpython.cpp:77
initConstants
static void initConstants(PyObject *module)
Definition: cfpython.cpp:1409
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_system_get_archetype_vector
void cf_system_get_archetype_vector(int property, std::vector< archetype * > *list)
Definition: plugin_common.cpp:2128
cf_player_find
player * cf_player_find(const char *plname)
Definition: plugin_common.cpp:825
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:2111
AT_FEAR
#define AT_FEAR
Definition: attack.h:90
FOOD
@ FOOD
Definition: object.h:115
AT_GODPOWER
#define AT_GODPOWER
Definition: attack.h:96
CFPContext::options
char options[1024]
Definition: cfpython.h:100
PYTHON_CACHE_SIZE
#define PYTHON_CACHE_SIZE
Definition: cfpython.cpp:72
CFAPI_SYSTEM_PARTIES
#define CFAPI_SYSTEM_PARTIES
Definition: plugin.h:288
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:935
WAIT2
#define WAIT2
Definition: define.h:499
DRINK
@ DRINK
Definition: object.h:160
ATNR_GHOSTHIT
#define ATNR_GHOSTHIT
Definition: attack.h:58
cf_system_get_party_vector
void cf_system_get_party_vector(int property, std::vector< partylist * > *list)
Definition: plugin_common.cpp:2134
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:1388
LogLevel
LogLevel
Definition: logger.h:10
MOVE_SWIM
#define MOVE_SWIM
Definition: define.h:396
DISTATT
#define DISTATT
Definition: define.h:491
log_message
static PyObject * log_message(PyObject *self, PyObject *args)
Definition: cfpython.cpp:589
CFPContext::script
char script[1024]
Definition: cfpython.h:99
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:893
getTime
static PyObject * getTime(PyObject *self, PyObject *args)
Definition: cfpython.cpp:540
EVENT_GKILL
#define EVENT_GKILL
Definition: events.h:42
addConstants
static void addConstants(PyObject *module, const char *name, const CFConstant *constants)
Definition: cfpython.cpp:1062
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:435
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:662
CFPContext::returnvalue
int returnvalue
Definition: cfpython.h:101
EVENT_KICK
#define EVENT_KICK
Definition: events.h:43
cstEventType
const CFConstant cstEventType[]
Definition: cfpython.cpp:1329
PyInit_cjson
PyObject * PyInit_cjson(void)
Definition: cjson.cpp:1186
cfpython_globalEventListener
CF_PLUGIN int cfpython_globalEventListener(int *type,...)
Definition: cfpython.cpp:1698
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
PyInit_Crossfire
static PyObject * PyInit_Crossfire(void)
Definition: cfpython.cpp:1483
initContextStack
static void initContextStack(void)
Definition: cfpython.cpp:817
cf_get_time
void cf_get_time(timeofday_t *tod)
Definition: plugin_common.cpp:1549
GOD
@ GOD
Definition: object.h:151
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:626
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:844
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