GUIScript: Fix typo in attribute error.
[gemrb.git] / gemrb / plugins / GUIScript / GUIScript.cpp
blob3b438820848fc0720a60d0a7395e2ed75ac13b31
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "GUIScript.h"
23 #include "PythonHelpers.h"
25 #include "Audio.h"
26 #include "Button.h"
27 #include "ControlAnimation.h"
28 #include "DataFileMgr.h"
29 #include "EffectQueue.h"
30 #include "GSUtils.h" //checkvariable
31 #include "Game.h"
32 #include "GameControl.h"
33 #include "GameData.h"
34 #include "ImageFactory.h"
35 #include "ImageMgr.h"
36 #include "Interface.h"
37 #include "Item.h"
38 #include "Label.h"
39 #include "Map.h"
40 #include "MapControl.h"
41 #include "MusicMgr.h"
42 #include "Palette.h"
43 #include "PalettedImageMgr.h"
44 #include "ResourceDesc.h"
45 #include "SaveGameIterator.h"
46 #include "Spell.h"
47 #include "TextEdit.h"
48 #include "TileMap.h"
49 #include "Video.h"
50 #include "WorldMap.h"
51 #include "WorldMapControl.h"
53 #include <cstdio>
55 GUIScript *gs = NULL;
57 //this stuff is missing from Python 2.2
58 #ifndef PyDoc_VAR
59 #define PyDoc_VAR(name) static char name[]
60 #endif
62 #ifndef PyDoc_STR
63 # ifdef WITH_DOC_STRINGS
64 # define PyDoc_STR(str) str
65 # else
66 # define PyDoc_STR(str) ""
67 # endif
68 #endif
70 #ifndef PyDoc_STRVAR
71 #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
72 #endif
74 // a shorthand for declaring methods in method table
75 #define METHOD(name, args) {#name, GemRB_ ## name, args, GemRB_ ## name ## __doc}
77 static int SpecialItemsCount = -1;
78 static int SpecialSpellsCount = -1;
79 static int StoreSpellsCount = -1;
80 static int UsedItemsCount = -1;
81 static int ItemSoundsCount = -1;
83 //#define UIT_ALLOW_REPLACE 1 //item is replaceable with another item on this list
85 struct UsedItemType {
86 ieResRef itemname;
87 ieVariable username; //death variable
88 ieStrRef value;
89 // int flags; //UIT flags
92 struct SpellDescType {
93 ieResRef resref;
94 ieStrRef value;
97 typedef char EventNameType[17];
98 #define IS_DROP 0
99 #define IS_GET 1
101 typedef ieResRef ResRefPairs[2];
103 #define UNINIT_IEDWORD 0xcccccccc
105 static SpellDescType *SpecialItems = NULL;
106 static SpellDescType *SpecialSpells = NULL;
108 #define SP_IDENTIFY 1 //any spell that cannot be cast from the menu
109 #define SP_SILENCE 2 //any spell that can be cast in silence
111 static SpellDescType *StoreSpells = NULL;
112 static ItemExtHeader *ItemArray = NULL;
113 static SpellExtHeader *SpellArray = NULL;
114 static UsedItemType *UsedItems = NULL;
115 static ResRefPairs *ItemSounds = NULL;
117 static int ReputationIncrease[20]={(int) UNINIT_IEDWORD};
118 static int ReputationDonation[20]={(int) UNINIT_IEDWORD};
119 //4 action button indices are packed on a single ieDword, there are 32 actions max.
120 //there are additional fake action buttons
121 static ieDword GUIAction[MAX_ACT_COUNT]={UNINIT_IEDWORD};
122 static ieDword GUITooltip[MAX_ACT_COUNT]={UNINIT_IEDWORD};
123 static ieResRef GUIResRef[MAX_ACT_COUNT];
124 static EventNameType GUIEvent[MAX_ACT_COUNT];
125 static bool QuitOnError = false;
127 // Natural screen size of currently loaded winpack
128 static int CHUWidth = 0;
129 static int CHUHeight = 0;
131 static EffectRef fx_learn_spell_ref={"Spell:Learn",NULL,-1};
133 // Like PyString_FromString(), but for ResRef
134 inline PyObject* PyString_FromResRef(char* ResRef)
136 unsigned int i = strnlen(ResRef,sizeof(ieResRef));
137 return PyString_FromStringAndSize( ResRef, i );
140 // Like PyString_FromString(), but for ResRef
141 inline PyObject* PyString_FromAnimID(const char* AnimID)
143 unsigned int i = strnlen(AnimID,2);
144 return PyString_FromStringAndSize( AnimID, i );
147 /* Sets RuntimeError exception and returns NULL, so this function
148 * can be called in `return'.
150 inline PyObject* RuntimeError(const char* msg)
152 printMessage( "GUIScript", "Runtime Error:\n", LIGHT_RED );
153 PyErr_SetString( PyExc_RuntimeError, msg );
154 if (QuitOnError) {
155 core->Quit();
157 return NULL;
160 /* Prints error msg for invalid function parameters and also the function's
161 * doc string (given as an argument). Then returns NULL, so this function
162 * can be called in `return'. The exception should be set by previous
163 * call to e.g. PyArg_ParseTuple()
165 inline PyObject* AttributeError(const char* doc_string)
167 printMessage( "GUIScript", "Syntax Error:\n", LIGHT_RED );
168 PyErr_SetString(PyExc_AttributeError, doc_string);
169 if (QuitOnError) {
170 core->Quit();
172 return NULL;
175 inline Control *GetControl( int wi, int ci, int ct)
177 char errorbuffer[256];
179 Window* win = core->GetWindow( wi );
180 if (win == NULL) {
181 snprintf(errorbuffer, sizeof(errorbuffer), "Cannot find window index #%d (unloaded?)", wi);
182 RuntimeError(errorbuffer);
183 return NULL;
185 Control* ctrl = win->GetControl( ci );
186 if (!ctrl) {
187 snprintf(errorbuffer, sizeof(errorbuffer), "Cannot find control #%d", ci);
188 RuntimeError(errorbuffer);
189 return NULL;
191 if ((ct>=0) && (ctrl->ControlType != ct)) {
192 snprintf(errorbuffer, sizeof(errorbuffer), "Invalid control type: %d!=%d", ctrl->ControlType, ct);
193 RuntimeError(errorbuffer);
194 return NULL;
196 return ctrl;
199 //sets tooltip with Fx key prepended
200 static inline void SetFunctionTooltip(int WindowIndex, int ControlIndex, char *txt, int Function)
202 if (txt) {
203 if (txt[0]) {
204 char *txt2 = (char *) malloc(strlen(txt)+10);
205 if (Function) {
206 sprintf(txt2,"F%d - %s",Function,txt);
207 } else {
208 sprintf(txt2,"F%d - %s",ControlIndex+1,txt);
210 core->FreeString(txt);
211 core->SetTooltip((ieWord) WindowIndex, (ieWord) ControlIndex, txt2);
212 free (txt2);
213 return;
215 core->FreeString(txt);
217 core->SetTooltip((ieWord) WindowIndex, (ieWord) ControlIndex, "");
220 static void ReadItemSounds()
222 int table = gamedata->LoadTable( "itemsnd" );
223 if (table<0) {
224 ItemSoundsCount = 0;
225 ItemSounds = NULL;
226 return;
228 Holder<TableMgr> tab = gamedata->GetTable( table );
229 ItemSoundsCount = tab->GetRowCount();
230 ItemSounds = (ResRefPairs *) malloc( sizeof(ResRefPairs)*ItemSoundsCount);
231 for (int i = 0; i < ItemSoundsCount; i++) {
232 strnlwrcpy(ItemSounds[i][0], tab->QueryField(i,0), 8);
233 strnlwrcpy(ItemSounds[i][1], tab->QueryField(i,1), 8);
235 gamedata->DelTable( table );
238 static void GetItemSound(ieResRef &Sound, ieDword ItemType, const char *ID, ieDword Col)
240 Sound[0]=0;
241 if (Col>1) {
242 return;
245 if (ItemSoundsCount<0) {
246 ReadItemSounds();
249 if (ID[1]=='A') {
250 //the last 4 item sounds are used for '1A', '2A', '3A' and '4A'
251 //item animation types
252 ItemType = ItemSoundsCount-4+ID[0]-'1';
255 if (ItemType>=(ieDword) ItemSoundsCount) {
256 return;
258 strnlwrcpy(Sound, ItemSounds[ItemType][Col], 8);
261 static int GetCreatureStrRef(Actor *actor, unsigned int Str)
263 return actor->StrRefs[Str];
266 static inline bool CheckStat(Actor * actor, ieDword stat, ieDword value, int op)
268 int dc = DiffCore(actor->GetBase(stat), value, op);
269 return dc;
272 static int GetCreatureStat(Actor *actor, unsigned int StatID, int Mod)
274 if (Mod) {
275 return actor->GetStat( StatID );
277 return actor->GetBase( StatID );
280 static int SetCreatureStat(Actor *actor, unsigned int StatID, int StatValue)
282 actor->SetBase( StatID, StatValue );
283 actor->CreateDerivedStats();
284 return 1;
287 /* create an item entry
288 TODO: this code snippet exists in many copies, maybe consolidate */
289 static CREItem *CreateCreItem(const char *ItemResRef, int Charge0, int Charge1, int Charge2)
291 CREItem *TmpItem = new CREItem();
292 strnlwrcpy(TmpItem->ItemResRef, ItemResRef, 8);
293 TmpItem->Expired=0;
294 TmpItem->Usages[0]=(ieWord) Charge0;
295 TmpItem->Usages[1]=(ieWord) Charge1;
296 TmpItem->Usages[2]=(ieWord) Charge2;
297 TmpItem->Flags=0;
298 if (core->ResolveRandomItem(TmpItem) && gamedata->Exists(TmpItem->ItemResRef, IE_ITM_CLASS_ID)) {
299 return TmpItem;
301 /* item couldn't be resolved */
302 delete TmpItem;
303 return NULL;
306 PyDoc_STRVAR( GemRB_SetInfoTextColor__doc,
307 "SetInfoTextColor(red, green, blue, [alpha])\n\n"
308 "Sets the color of Floating Messages in GameControl." );
310 static PyObject* GemRB_SetInfoTextColor(PyObject*, PyObject* args)
312 int r,g,b,a;
314 if (!PyArg_ParseTuple( args, "iii|i", &r, &g, &b, &a)) {
315 return AttributeError( GemRB_SetInfoTextColor__doc );
317 Color c = {r,g,b,a};
318 core->SetInfoTextColor( c );
319 Py_INCREF( Py_None );
320 return Py_None;
323 PyDoc_STRVAR( GemRB_UnhideGUI__doc,
324 "UnhideGUI()\n\n"
325 "Shows the Game GUI and redraws windows." );
327 static PyObject* GemRB_UnhideGUI(PyObject*, PyObject* /*args*/)
329 GameControl* gc = (GameControl *) GetControl( 0, 0, IE_GUI_GAMECONTROL);
330 if (!gc) {
331 return RuntimeError("No gamecontrol!");
333 gc->UnhideGUI();
334 //this enables mouse in dialogs, which is wrong
335 //gc->SetCutSceneMode( false );
336 Py_INCREF( Py_None );
337 return Py_None;
340 PyDoc_STRVAR( GemRB_HideGUI__doc,
341 "HideGUI()=>returns 1 if it did something\n\n"
342 "Hides the Game GUI." );
344 static PyObject* GemRB_HideGUI(PyObject*, PyObject* /*args*/)
346 GameControl* gc = (GameControl *) GetControl( 0, 0, IE_GUI_GAMECONTROL);
347 if (!gc) {
348 return RuntimeError("No gamecontrol!");
350 int ret = gc->HideGUI();
352 return PyInt_FromLong( ret );
355 PyDoc_STRVAR( GemRB_GetGameString__doc,
356 "GetGameString(Index) => string\n\n"
357 "Returns various string attributes of the Game object, see the docs.");
359 static PyObject* GemRB_GetGameString(PyObject*, PyObject* args)
361 int Index;
363 if (!PyArg_ParseTuple( args, "i", &Index )) {
364 return AttributeError( GemRB_GetGameString__doc );
366 switch(Index&0xf0) {
367 case 0: //game strings
368 Game *game = core->GetGame();
369 if (!game) {
370 return PyString_FromString("");
372 switch(Index&15) {
373 case 0:
374 return PyString_FromString( game->LoadMos );
375 case 1:
376 return PyString_FromString( game->CurrentArea );
380 return AttributeError( GemRB_GetGameString__doc );
383 PyDoc_STRVAR( GemRB_LoadGame__doc,
384 "LoadGame(Index)\n\n"
385 "Loads and enters the Game." );
387 static PyObject* GemRB_LoadGame(PyObject*, PyObject* args)
389 PyObject *obj;
390 int VersionOverride = 0;
392 if (!PyArg_ParseTuple( args, "O|i", &obj, &VersionOverride )) {
393 return AttributeError( GemRB_LoadGame__doc );
395 CObject<SaveGame> save(obj);
396 core->SetupLoadGame(save.get(), VersionOverride);
397 Py_INCREF( Py_None );
398 return Py_None;
401 PyDoc_STRVAR( GemRB_EnterGame__doc,
402 "EnterGame()\n\n"
403 "Starts new game and enters it." );
405 static PyObject* GemRB_EnterGame(PyObject*, PyObject* /*args*/)
407 core->QuitFlag|=QF_ENTERGAME;
409 Py_INCREF( Py_None );
410 return Py_None;
413 PyDoc_STRVAR( GemRB_QuitGame__doc,
414 "QuitGame()\n\n"
415 "Stops the current game.");
416 static PyObject* GemRB_QuitGame(PyObject*, PyObject* /*args*/)
418 core->QuitFlag=QF_QUITGAME;
419 Py_INCREF( Py_None );
420 return Py_None;
423 PyDoc_STRVAR( GemRB_TextArea_MoveText__doc,
424 "MoveTAText(srcWin, srcCtrl, dstWin, dstCtrl)\n\n"
425 "Copies a TextArea content to another.");
427 static PyObject* GemRB_TextArea_MoveText(PyObject * /*self*/, PyObject* args)
429 int srcWin, srcCtrl, dstWin, dstCtrl;
431 if (!PyArg_ParseTuple( args, "iiii", &srcWin, &srcCtrl, &dstWin, &dstCtrl )) {
432 return AttributeError( GemRB_TextArea_MoveText__doc );
435 TextArea* SrcTA = ( TextArea* ) GetControl( srcWin, srcCtrl, IE_GUI_TEXTAREA);
436 if (!SrcTA) {
437 return NULL;
440 TextArea* DstTA = ( TextArea* ) GetControl( dstWin, dstCtrl, IE_GUI_TEXTAREA);
441 if (!DstTA) {
442 return NULL;
445 SrcTA->CopyTo( DstTA );
447 Py_INCREF( Py_None );
448 return Py_None;
451 PyDoc_STRVAR( GemRB_TextArea_Rewind__doc,
452 "RewindTA(Win, Ctrl, Ticks)\n\n"
453 "Sets up a TextArea for scrolling. Ticks is the delay between the steps in scrolling.");
455 static PyObject* GemRB_TextArea_Rewind(PyObject * /*self*/, PyObject* args)
457 int Win, Ctrl, Ticks;
459 if (!PyArg_ParseTuple( args, "iii", &Win, &Ctrl, &Ticks)) {
460 return AttributeError( GemRB_TextArea_Rewind__doc );
463 TextArea* ctrl = ( TextArea* ) GetControl( Win, Ctrl, IE_GUI_TEXTAREA);
464 if (!ctrl) {
465 return NULL;
468 ctrl->SetupScroll(Ticks);
469 Py_INCREF( Py_None );
470 return Py_None;
473 PyDoc_STRVAR( GemRB_TextArea_SetHistory__doc,
474 "SetTAHistory(Win, Ctrl, KeepLines)\n\n"
475 "Sets up a TextArea to expire scrolled out lines.");
477 static PyObject* GemRB_TextArea_SetHistory(PyObject * /*self*/, PyObject* args)
479 int Win, Ctrl, Keep;
481 if (!PyArg_ParseTuple( args, "iii", &Win, &Ctrl, &Keep)) {
482 return AttributeError( GemRB_TextArea_SetHistory__doc );
485 TextArea* ctrl = ( TextArea* ) GetControl( Win, Ctrl, IE_GUI_TEXTAREA);
486 if (!ctrl) {
487 return NULL;
490 ctrl->SetPreservedRow(Keep);
491 Py_INCREF( Py_None );
492 return Py_None;
495 PyDoc_STRVAR( GemRB_StatComment__doc,
496 "StatComment(Strref, X, Y) => string\n\n"
497 "Replaces values X and Y into an strref in place of %%d." );
499 static PyObject* GemRB_StatComment(PyObject * /*self*/, PyObject* args)
501 ieStrRef Strref;
502 int X, Y;
503 PyObject* ret;
505 if (!PyArg_ParseTuple( args, "iii", &Strref, &X, &Y )) {
506 return AttributeError( GemRB_StatComment__doc );
508 char* text = core->GetString( Strref );
509 size_t bufflen = strlen( text ) + 12;
510 if (bufflen<12) {
511 return AttributeError( GemRB_StatComment__doc );
513 char* newtext = ( char* ) malloc( bufflen );
514 //this could be DANGEROUS, not anymore (snprintf is your friend)
515 snprintf( newtext, bufflen, text, X, Y );
516 core->FreeString( text );
517 ret = PyString_FromString( newtext );
518 free( newtext );
519 return ret;
522 PyDoc_STRVAR( GemRB_GetString__doc,
523 "GetString(strref[,flags]) => string\n\n"
524 "Returns string for given strref. " );
526 static PyObject* GemRB_GetString(PyObject * /*self*/, PyObject* args)
528 ieStrRef strref;
529 int flags = 0;
530 PyObject* ret;
532 if (!PyArg_ParseTuple( args, "i|i", &strref, &flags )) {
533 return AttributeError( GemRB_GetString__doc );
536 char *text = core->GetString( strref, flags );
537 ret=PyString_FromString( text );
538 core->FreeString( text );
539 return ret;
542 PyDoc_STRVAR( GemRB_EndCutSceneMode__doc,
543 "EndCutSceneMode()\n\n"
544 "Exits the CutScene Mode." );
546 static PyObject* GemRB_EndCutSceneMode(PyObject * /*self*/, PyObject* /*args*/)
548 core->SetCutSceneMode( false );
549 Py_INCREF( Py_None );
550 return Py_None;
553 PyDoc_STRVAR( GemRB_LoadWindowPack__doc,
554 "LoadWindowPack(CHUIResRef, [Width=0, Height=0])\n\n"
555 "Loads a WindowPack into the Window Manager Module. "
556 "Width and Height set winpack's natural screen size if nonzero." );
558 static PyObject* GemRB_LoadWindowPack(PyObject * /*self*/, PyObject* args)
560 char* string;
561 int width = 0, height = 0;
563 if (!PyArg_ParseTuple( args, "s|ii", &string, &width, &height )) {
564 return AttributeError( GemRB_LoadWindowPack__doc );
567 if (!core->LoadWindowPack( string )) {
568 return RuntimeError("Can't find resource");
571 CHUWidth = width;
572 CHUHeight = height;
574 if ( (width && (width>core->Width)) ||
575 (height && (height>core->Height)) ) {
576 printMessage("GUIScript","Screen is too small!\n",LIGHT_RED);
577 printf("This window requires %d x %d resolution.\n",width,height);
578 return RuntimeError("Please change your settings.");
580 Py_INCREF( Py_None );
581 return Py_None;
584 PyDoc_STRVAR( GemRB_LoadWindow__doc,
585 "LoadWindow(WindowID) => WindowIndex\n\n"
586 "Returns a Window." );
588 static PyObject* GemRB_LoadWindow(PyObject * /*self*/, PyObject* args)
590 int WindowID;
592 if (!PyArg_ParseTuple( args, "i", &WindowID )) {
593 return AttributeError( GemRB_LoadWindow__doc );
596 int ret = core->LoadWindow( WindowID );
597 if (ret == -1) {
598 char buf[256];
599 snprintf( buf, sizeof( buf ), "Can't find window #%d!", WindowID );
600 return RuntimeError(buf);
603 // If the current winpack windows are placed for screen resolution
604 // other than the current one, reposition them
605 Window* win = core->GetWindow( ret );
606 if (CHUWidth && CHUWidth != core->Width)
607 win->XPos += (core->Width - CHUWidth) / 2;
608 if (CHUHeight && CHUHeight != core->Height)
609 win->YPos += (core->Height - CHUHeight) / 2;
611 return gs->ConstructObject("Window", ret);
614 PyDoc_STRVAR( GemRB_Window_SetSize__doc,
615 "SetWindowSize(WindowIndex, Width, Height)\n\n"
616 "Resizes a Window.");
618 static PyObject* GemRB_Window_SetSize(PyObject * /*self*/, PyObject* args)
620 int WindowIndex, Width, Height;
622 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &Width, &Height )) {
623 return AttributeError( GemRB_Window_SetSize__doc );
626 Window* win = core->GetWindow( WindowIndex );
627 if (win == NULL) {
628 return RuntimeError("Cannot find window!\n");
631 win->Width = Width;
632 win->Height = Height;
633 win->Invalidate();
635 Py_INCREF( Py_None );
636 return Py_None;
639 PyDoc_STRVAR( GemRB_Window_SetFrame__doc,
640 "SetWindowFrame(WindowIndex)\n\n"
641 "Sets Window frame used to fill screen on higher resolutions.");
643 static PyObject* GemRB_Window_SetFrame(PyObject * /*self*/, PyObject* args)
645 int WindowIndex;
647 if (!PyArg_ParseTuple( args, "i", &WindowIndex )) {
648 return AttributeError( GemRB_Window_SetFrame__doc );
651 Window* win = core->GetWindow( WindowIndex );
652 if (win == NULL) {
653 return RuntimeError("Cannot find window!\n");
656 win->SetFrame();
658 Py_INCREF( Py_None );
659 return Py_None;
662 PyDoc_STRVAR( GemRB_LoadWindowFrame__doc,
663 "LoadWindowFrame(MOSResRef_Left, MOSResRef_Right, MOSResRef_Top, MOSResRef_Bottom))\n\n"
664 "Load the parts of window frame used to decorate windows on higher resolutions." );
666 static PyObject* GemRB_LoadWindowFrame(PyObject * /*self*/, PyObject* args)
668 char* ResRef[4];
670 if (!PyArg_ParseTuple( args, "ssss", &ResRef[0], &ResRef[1], &ResRef[2], &ResRef[3] )) {
671 return AttributeError( GemRB_LoadWindowFrame__doc );
675 for (int i = 0; i < 4; i++) {
676 if (ResRef[i] == 0) {
677 return AttributeError( GemRB_LoadWindowFrame__doc );
680 ResourceHolder<ImageMgr> im(ResRef[i]);
681 if (im == NULL) {
682 return NULL;
685 Sprite2D* Picture = im->GetSprite2D();
686 if (Picture == NULL) {
687 return NULL;
690 // FIXME: delete previous WindowFrames
691 //core->WindowFrames[i] = Picture;
692 core->SetWindowFrame(i, Picture);
695 Py_INCREF( Py_None );
696 return Py_None;
700 PyDoc_STRVAR( GemRB_EnableCheatKeys__doc,
701 "EnableCheatKeys(flag)\n\n"
702 "Sets CheatFlags." );
704 static PyObject* GemRB_EnableCheatKeys(PyObject * /*self*/, PyObject* args)
706 int Flag;
708 if (!PyArg_ParseTuple( args, "i", &Flag )) {
709 return AttributeError( GemRB_EnableCheatKeys__doc );
712 core->EnableCheatKeys( Flag );
714 Py_INCREF( Py_None );
715 return Py_None;
718 PyDoc_STRVAR( GemRB_Window_SetPicture__doc,
719 "SetWindowPicture(WindowIndex, MosResRef)\n\n"
720 "Changes the background of a Window." );
722 static PyObject* GemRB_Window_SetPicture(PyObject * /*self*/, PyObject* args)
724 int WindowIndex;
725 char* MosResRef;
727 if (!PyArg_ParseTuple( args, "is", &WindowIndex, &MosResRef )) {
728 return AttributeError( GemRB_Window_SetPicture__doc );
731 Window* win = core->GetWindow( WindowIndex );
732 if (win == NULL) {
733 return RuntimeError("Cannot find window!\n");
736 ResourceHolder<ImageMgr> mos(MosResRef);
737 if (mos != NULL) {
738 win->SetBackGround( mos->GetSprite2D(), true );
740 win->Invalidate();
742 Py_INCREF( Py_None );
743 return Py_None;
746 PyDoc_STRVAR( GemRB_Window_SetPos__doc,
747 "SetWindowPos(WindowIndex, X, Y, [Flags=WINDOW_TOPLEFT])\n\n"
748 "Moves a Window to pos. (X, Y).\n"
749 "Flags is a bitmask of WINDOW_(TOPLEFT|CENTER|ABSCENTER|RELATIVE|SCALE|BOUNDED) and "
750 "they are used to modify the meaning of X and Y.\n"
751 "TOPLEFT: X, Y are coordinates of upper-left corner.\n"
752 "CENTER: X, Y are coordinates of window's center.\n"
753 "ABSCENTER: window is placed at screen center, moved by X, Y.\n"
754 "RELATIVE: window is moved by X, Y.\n"
755 "SCALE: window is moved by diff of screen size and X, Y, divided by 2.\n"
756 "BOUNDED: the window is kept within screen boundaries." );
758 static PyObject* GemRB_Window_SetPos(PyObject * /*self*/, PyObject* args)
760 int WindowIndex, X, Y, Flags = WINDOW_TOPLEFT;
762 if (!PyArg_ParseTuple( args, "iii|i", &WindowIndex, &X, &Y, &Flags )) {
763 return AttributeError( GemRB_Window_SetPos__doc );
766 Window* win = core->GetWindow( WindowIndex );
767 if (win == NULL) {
768 return RuntimeError("Cannot find window!\n");
771 if (Flags & WINDOW_CENTER) {
772 X -= win->Width / 2;
773 Y -= win->Height / 2;
775 else if (Flags & WINDOW_ABSCENTER) {
776 X += (core->Width - win->Width) / 2;
777 Y += (core->Height - win->Height) / 2;
779 else if (Flags & WINDOW_RELATIVE) {
780 X += win->XPos;
781 Y += win->YPos;
783 else if (Flags & WINDOW_SCALE) {
784 X = win->XPos + (core->Width - X) / 2;
785 Y = win->YPos + (core->Height - Y) / 2;
788 // Keep window within screen
789 // FIXME: keep it within gamecontrol
790 if (Flags & WINDOW_BOUNDED) {
791 // FIXME: grrrr, should be < 0!!!
792 if (X > 32767 || X < 0)
793 X = 0;
794 if (Y > 32767 || Y < 0)
795 Y = 0;
797 if (X + win->Width >= core->Width)
798 X = core->Width - win->Width;
799 if (Y + win->Height >= core->Height)
800 Y = core->Height - win->Height;
803 win->XPos = X;
804 win->YPos = Y;
805 win->Invalidate();
807 Py_INCREF( Py_None );
808 return Py_None;
811 PyDoc_STRVAR( GemRB_LoadTable__doc,
812 "LoadTable(2DAResRef, [ignore_error=0]) => GTable\n\n"
813 "Loads a 2DA Table." );
815 static PyObject* GemRB_LoadTable(PyObject * /*self*/, PyObject* args)
817 char* tablename;
818 int noerror = 0;
820 if (!PyArg_ParseTuple( args, "s|i", &tablename, &noerror )) {
821 return AttributeError( GemRB_LoadTable__doc );
824 int ind = gamedata->LoadTable( tablename );
825 if (!noerror && ind == -1) {
826 return RuntimeError("Can't find resource");
828 return gs->ConstructObject("Table", ind);
831 PyDoc_STRVAR( GemRB_Table_Unload__doc,
832 "UnloadTable(TableIndex)\n\n"
833 "Unloads a 2DA Table." );
835 static PyObject* GemRB_Table_Unload(PyObject * /*self*/, PyObject* args)
837 int ti;
839 if (!PyArg_ParseTuple( args, "i", &ti )) {
840 return AttributeError( GemRB_Table_Unload__doc );
843 int ind = gamedata->DelTable( ti );
844 if (ind == -1) {
845 return RuntimeError("Can't find resource");
848 Py_INCREF( Py_None );
849 return Py_None;
852 PyDoc_STRVAR( GemRB_Table_GetValue__doc,
853 "GetTableValue(TableIndex, RowIndex/RowString, ColIndex/ColString, type) => value\n\n"
854 "Returns a field of a 2DA Table. If Type is omitted the return type is the autodetected, "
855 "otherwise 0 means string, 1 means integer, 2 means stat symbol translation." );
857 static PyObject* GemRB_Table_GetValue(PyObject * /*self*/, PyObject* args)
859 PyObject* ti, * row, * col;
860 PyObject* type = NULL;
861 int which = -1;
863 if (!PyArg_UnpackTuple( args, "ref", 3, 4, &ti, &row, &col, &type )) {
864 return AttributeError( GemRB_Table_GetValue__doc );
866 if (type!=NULL) {
867 if (!PyObject_TypeCheck( type, &PyInt_Type )) {
868 return AttributeError( GemRB_Table_GetValue__doc );
870 which = PyInt_AsLong( type );
873 if (!PyObject_TypeCheck( ti, &PyInt_Type )) {
874 return AttributeError( GemRB_Table_GetValue__doc );
876 long TableIndex = PyInt_AsLong( ti );
877 if (( !PyObject_TypeCheck( row, &PyInt_Type ) ) &&
878 ( !PyObject_TypeCheck( row, &PyString_Type ) )) {
879 return AttributeError( GemRB_Table_GetValue__doc );
881 if (( !PyObject_TypeCheck( col, &PyInt_Type ) ) &&
882 ( !PyObject_TypeCheck( col, &PyString_Type ) )) {
883 return AttributeError( GemRB_Table_GetValue__doc );
885 if (PyObject_TypeCheck( row, &PyInt_Type ) &&
886 ( !PyObject_TypeCheck( col, &PyInt_Type ) )) {
887 printMessage( "GUIScript",
888 "Type Error: RowIndex/RowString and ColIndex/ColString must be the same type\n",
889 LIGHT_RED );
890 return NULL;
892 if (PyObject_TypeCheck( row, &PyString_Type ) &&
893 ( !PyObject_TypeCheck( col, &PyString_Type ) )) {
894 printMessage( "GUIScript",
895 "Type Error: RowIndex/RowString and ColIndex/ColString must be the same type\n",
896 LIGHT_RED );
897 return NULL;
899 Holder<TableMgr> tm = gamedata->GetTable( TableIndex );
900 if (!tm) {
901 return RuntimeError("Can't find resource");
903 const char* ret;
904 if (PyObject_TypeCheck( row, &PyString_Type )) {
905 char* rows = PyString_AsString( row );
906 char* cols = PyString_AsString( col );
907 ret = tm->QueryField( rows, cols );
908 } else {
909 long rowi = PyInt_AsLong( row );
910 long coli = PyInt_AsLong( col );
911 ret = tm->QueryField( rowi, coli );
913 if (ret == NULL)
914 return NULL;
916 long val;
917 //if which = 0, then return string
918 if (!which) {
919 return PyString_FromString( ret );
921 //if which = 1 then return number
922 //if which = -1 (omitted) then return the best format
923 if (valid_number( ret, val ) || (which==1) ) {
924 return PyInt_FromLong( val );
926 if (which==2) {
927 val = core->TranslateStat(ret);
928 return PyInt_FromLong( val );
930 return PyString_FromString( ret );
933 PyDoc_STRVAR( GemRB_Table_FindValue__doc,
934 "FindTableValue(TableIndex, ColumnIndex, Value[, StartRow]) => Row\n\n"
935 "Returns the first rowcount of a field of a 2DA Table." );
937 static PyObject* GemRB_Table_FindValue(PyObject * /*self*/, PyObject* args)
939 int ti, col;
940 int start = 0;
941 long Value;
943 if (!PyArg_ParseTuple( args, "iil|i", &ti, &col, &Value, &start )) {
944 return AttributeError( GemRB_Table_FindValue__doc );
947 Holder<TableMgr> tm = gamedata->GetTable( ti );
948 if (tm == NULL) {
949 return RuntimeError("Can't find resource");
951 return PyInt_FromLong(tm->FindTableValue(col, Value, start));
954 PyDoc_STRVAR( GemRB_Table_GetRowIndex__doc,
955 "GetTableRowIndex(TableIndex, RowName) => Row\n\n"
956 "Returns the Index of a Row in a 2DA Table." );
958 static PyObject* GemRB_Table_GetRowIndex(PyObject * /*self*/, PyObject* args)
960 int ti;
961 char* rowname;
963 if (!PyArg_ParseTuple( args, "is", &ti, &rowname )) {
964 return AttributeError( GemRB_Table_GetRowIndex__doc );
967 Holder<TableMgr> tm = gamedata->GetTable( ti );
968 if (tm == NULL) {
969 return RuntimeError("Can't find resource");
971 int row = tm->GetRowIndex( rowname );
972 //no error if the row doesn't exist
973 return PyInt_FromLong( row );
976 PyDoc_STRVAR( GemRB_Table_GetRowName__doc,
977 "GetTableRowName(TableIndex, RowIndex) => string\n\n"
978 "Returns the Name of a Row in a 2DA Table." );
980 static PyObject* GemRB_Table_GetRowName(PyObject * /*self*/, PyObject* args)
982 int ti, row;
984 if (!PyArg_ParseTuple( args, "ii", &ti, &row )) {
985 return AttributeError( GemRB_Table_GetRowName__doc );
988 Holder<TableMgr> tm = gamedata->GetTable( ti );
989 if (tm == NULL) {
990 return RuntimeError("Can't find resource");
992 const char* str = tm->GetRowName( row );
993 if (str == NULL) {
994 return NULL;
997 return PyString_FromString( str );
1000 PyDoc_STRVAR( GemRB_Table_GetColumnIndex__doc,
1001 "GetTableColumnIndex(TableIndex, ColumnName) => Column\n\n"
1002 "Returns the Index of a Column in a 2DA Table." );
1004 static PyObject* GemRB_Table_GetColumnIndex(PyObject * /*self*/, PyObject* args)
1006 int ti;
1007 char* colname;
1009 if (!PyArg_ParseTuple( args, "is", &ti, &colname )) {
1010 return AttributeError( GemRB_Table_GetColumnIndex__doc );
1013 Holder<TableMgr> tm = gamedata->GetTable( ti );
1014 if (tm == NULL) {
1015 return RuntimeError("Can't find resource");
1017 int col = tm->GetColumnIndex( colname );
1018 //no error if the column doesn't exist
1019 return PyInt_FromLong( col );
1022 PyDoc_STRVAR( GemRB_Table_GetColumnName__doc,
1023 "GetTableColumnName(TableIndex, ColumnIndex) => string\n\n"
1024 "Returns the Name of a Column in a 2DA Table." );
1026 static PyObject* GemRB_Table_GetColumnName(PyObject * /*self*/, PyObject* args)
1028 int ti, col;
1030 if (!PyArg_ParseTuple( args, "ii", &ti, &col )) {
1031 return AttributeError( GemRB_Table_GetColumnName__doc );
1034 Holder<TableMgr> tm = gamedata->GetTable( ti );
1035 if (tm == NULL) {
1036 return RuntimeError("Can't find resource");
1038 const char* str = tm->GetColumnName( col );
1039 if (str == NULL) {
1040 return NULL;
1043 return PyString_FromString( str );
1046 PyDoc_STRVAR( GemRB_Table_GetRowCount__doc,
1047 "GetTableRowCount(TableIndex) => RowCount\n\n"
1048 "Returns the number of rows in a 2DA Table." );
1050 static PyObject* GemRB_Table_GetRowCount(PyObject * /*self*/, PyObject* args)
1052 int ti;
1054 if (!PyArg_ParseTuple( args, "i", &ti )) {
1055 return AttributeError( GemRB_Table_GetRowCount__doc );
1058 Holder<TableMgr> tm = gamedata->GetTable( ti );
1059 if (tm == NULL) {
1060 return RuntimeError("Can't find resource");
1063 return PyInt_FromLong( tm->GetRowCount() );
1066 PyDoc_STRVAR( GemRB_Table_GetColumnCount__doc,
1067 "GetTableColumnCount(TableIndex[, Row]) => ColumnCount\n\n"
1068 "Returns the number of columns in the given row of a 2DA Table. Row may be omitted." );
1070 static PyObject* GemRB_Table_GetColumnCount(PyObject * /*self*/, PyObject* args)
1072 int ti;
1073 int row = 0;
1075 if (!PyArg_ParseTuple( args, "i|i", &ti, &row )) {
1076 return AttributeError( GemRB_Table_GetColumnCount__doc );
1079 Holder<TableMgr> tm = gamedata->GetTable( ti );
1080 if (tm == NULL) {
1081 return RuntimeError("Can't find resource");
1084 return PyInt_FromLong( tm->GetColumnCount(row) );
1087 PyDoc_STRVAR( GemRB_LoadSymbol__doc,
1088 "LoadSymbol(IDSResRef) => SymbolIndex\n\n"
1089 "Loads an IDS Symbol Table." );
1091 static PyObject* GemRB_LoadSymbol(PyObject * /*self*/, PyObject* args)
1093 const char* string;
1095 if (!PyArg_ParseTuple( args, "s", &string )) {
1096 return AttributeError( GemRB_LoadSymbol__doc );
1099 int ind = core->LoadSymbol( string );
1100 if (ind == -1) {
1101 return NULL;
1104 return gs->ConstructObject("Symbol", ind);
1107 PyDoc_STRVAR( GemRB_Symbol_Unload__doc,
1108 "UnloadSymbol(SymbolIndex)\n\n"
1109 "Unloads an IDS Symbol Table." );
1111 static PyObject* GemRB_Symbol_Unload(PyObject * /*self*/, PyObject* args)
1113 int si;
1115 if (!PyArg_ParseTuple( args, "i", &si )) {
1116 return AttributeError( GemRB_Symbol_Unload__doc );
1119 int ind = core->DelSymbol( si );
1120 if (ind == -1) {
1121 return NULL;
1124 Py_INCREF( Py_None );
1125 return Py_None;
1128 PyDoc_STRVAR( GemRB_Symbol_GetValue__doc,
1129 "GetSymbolValue(SymbolIndex, StringVal) => int\n"
1130 "GetSymbolValue(SymbolIndex, IntVal) => string\n\n"
1131 "Returns a field of an IDS Symbol Table." );
1133 static PyObject* GemRB_Symbol_GetValue(PyObject * /*self*/, PyObject* args)
1135 PyObject* si, * sym;
1137 if (PyArg_UnpackTuple( args, "ref", 2, 2, &si, &sym )) {
1138 if (!PyObject_TypeCheck( si, &PyInt_Type )) {
1139 return AttributeError( GemRB_Symbol_GetValue__doc );
1141 long SymbolIndex = PyInt_AsLong( si );
1142 if (PyObject_TypeCheck( sym, &PyString_Type )) {
1143 char* syms = PyString_AsString( sym );
1144 Holder<SymbolMgr> sm = core->GetSymbol( SymbolIndex );
1145 if (!sm)
1146 return NULL;
1147 long val = sm->GetValue( syms );
1148 return PyInt_FromLong( val );
1150 if (PyObject_TypeCheck( sym, &PyInt_Type )) {
1151 long symi = PyInt_AsLong( sym );
1152 Holder<SymbolMgr> sm = core->GetSymbol( SymbolIndex );
1153 if (!sm)
1154 return NULL;
1155 const char* str = sm->GetValue( symi );
1156 return PyString_FromString( str );
1159 return AttributeError( GemRB_Symbol_GetValue__doc );
1162 PyDoc_STRVAR( GemRB_GetControl__doc,
1163 "GetControl(WindowIndex, ControlID) => ControlIndex\n\n"
1164 "Returns a control in a Window." );
1166 static PyObject* GemRB_GetControl(PyObject * /*self*/, PyObject* args)
1168 int WindowIndex, ControlID;
1170 if (!PyArg_ParseTuple( args, "ii", &WindowIndex, &ControlID )) {
1171 return AttributeError( GemRB_GetControl__doc );
1175 int ret = core->GetControl( WindowIndex, ControlID );
1176 if (ret == -1) {
1177 return RuntimeError( "Control is not found" );
1180 return PyInt_FromLong( ret );
1183 PyDoc_STRVAR( GemRB_Window_GetControl__doc,
1184 "GetControlObject(WindowID, ControlID) => GControl, or\n"
1185 "Window.GetControl(ControlID) => GControl\n\n"
1186 "Returns a control as an object." );
1188 static PyObject* GemRB_Window_GetControl(PyObject * self, PyObject* args)
1190 int WindowIndex, ControlID;
1192 if (!PyArg_ParseTuple( args, "ii", &WindowIndex, &ControlID )) {
1193 return AttributeError( GemRB_Window_GetControl__doc );
1196 PyObject* control = GemRB_GetControl( self, args );
1197 if (!control || !PyObject_TypeCheck( control, &PyInt_Type ))
1198 return control; // exception
1200 PyObject* ctrltuple = PyTuple_New(2);
1201 PyTuple_SET_ITEM(ctrltuple, 0, PyInt_FromLong(WindowIndex));
1202 PyTuple_SET_ITEM(ctrltuple, 1, control);
1204 PyObject* ret = 0;
1205 // TODO: get this from 'control' python variable
1206 int ctrlindex = core->GetControl(WindowIndex, ControlID);
1207 Control *ctrl = GetControl(WindowIndex, ctrlindex, -1);
1208 if (!ctrl) {
1209 // GetControl will already have raised an exception
1210 return 0;
1212 const char* type = "Control";
1213 switch(ctrl->ControlType) {
1214 case IE_GUI_LABEL:
1215 type = "Label";
1216 break;
1217 case IE_GUI_EDIT:
1218 type = "TextEdit";
1219 break;
1220 case IE_GUI_SCROLLBAR:
1221 type = "ScrollBar";
1222 break;
1223 case IE_GUI_TEXTAREA:
1224 type = "TextArea";
1225 break;
1226 case IE_GUI_BUTTON:
1227 type = "Button";
1228 break;
1229 case IE_GUI_WORLDMAP:
1230 type = "WorldMap";
1231 break;
1232 default:
1233 break;
1235 ret = gs->ConstructObject(type, ctrltuple);
1236 Py_DECREF(ctrltuple);
1238 if (!ret) {
1239 char buf[256];
1240 snprintf( buf, sizeof( buf ), "Couldn't construct Control object for control %d in window %d!", ControlID, WindowIndex );
1241 return RuntimeError(buf);
1243 return ret;
1246 PyDoc_STRVAR( GemRB_Window_HasControl__doc,
1247 "HasControl(WindowIndex, ControlID[, ControlType]) => bool\n\n"
1248 "Returns true if the control exists." );
1250 static PyObject* GemRB_Window_HasControl(PyObject * /*self*/, PyObject* args)
1252 int WindowIndex, ControlID;
1253 int Type = -1;
1255 if (!PyArg_ParseTuple( args, "ii|i", &WindowIndex, &ControlID, &Type )) {
1256 return AttributeError( GemRB_Window_HasControl__doc );
1258 int ret = core->GetControl( WindowIndex, ControlID );
1259 if (ret == -1) {
1260 return PyInt_FromLong( 0 );
1263 if (Type!=-1) {
1264 Control *ctrl = GetControl(WindowIndex, ControlID, -1);
1265 if (ctrl->ControlType!=Type) {
1266 return PyInt_FromLong( 0 );
1269 return PyInt_FromLong( 1 );
1272 PyDoc_STRVAR( GemRB_Control_QueryText__doc,
1273 "QueryText(WindowIndex, ControlIndex) => string\n\n"
1274 "Returns the Text of a TextEdit control." );
1276 static PyObject* GemRB_Control_QueryText(PyObject * /*self*/, PyObject* args)
1278 int wi, ci;
1280 if (!PyArg_ParseTuple( args, "ii", &wi, &ci )) {
1281 return AttributeError( GemRB_Control_QueryText__doc );
1284 Control *ctrl = GetControl(wi, ci, -1);
1285 if (!ctrl) {
1286 return NULL;
1288 switch(ctrl->ControlType) {
1289 case IE_GUI_LABEL:
1290 return PyString_FromString(((Label *) ctrl)->QueryText() );
1291 case IE_GUI_EDIT:
1292 return PyString_FromString(((TextEdit *) ctrl)->QueryText() );
1293 case IE_GUI_TEXTAREA:
1294 return PyString_FromString(((TextArea *) ctrl)->QueryText() );
1295 default:
1296 return RuntimeError("Invalid control type");
1300 PyDoc_STRVAR( GemRB_TextEdit_SetBufferLength__doc,
1301 "SetBufferLength(WindowIndex, ControlIndex, Length)\n\n"
1302 "Sets the maximum text length of a TextEdit Control. It cannot be more than 65535." );
1304 static PyObject* GemRB_TextEdit_SetBufferLength(PyObject * /*self*/, PyObject* args)
1306 int WindowIndex, ControlIndex, Length;
1308 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &Length)) {
1309 return AttributeError( GemRB_TextEdit_SetBufferLength__doc );
1312 TextEdit* te = (TextEdit *) GetControl( WindowIndex, ControlIndex, IE_GUI_EDIT );
1313 if (!te)
1314 return NULL;
1316 if ((ieDword) Length>0xffff) {
1317 return AttributeError( GemRB_Control_QueryText__doc );
1320 te->SetBufferLength((ieWord) Length );
1322 Py_INCREF( Py_None );
1323 return Py_None;
1326 PyDoc_STRVAR( GemRB_Control_SetText__doc,
1327 "SetText(WindowIndex, ControlIndex, String|Strref) => int\n\n"
1328 "Sets the Text of a control in a Window." );
1330 static PyObject* GemRB_Control_SetText(PyObject * /*self*/, PyObject* args)
1332 PyObject* wi, * ci, * str;
1333 long WindowIndex, ControlIndex, StrRef;
1334 char* string;
1335 int ret;
1337 if (!PyArg_UnpackTuple( args, "ref", 3, 3, &wi, &ci, &str )) {
1338 return AttributeError( GemRB_Control_SetText__doc );
1341 if (!PyObject_TypeCheck( wi, &PyInt_Type ) ||
1342 !PyObject_TypeCheck( ci, &PyInt_Type ) ||
1343 ( !PyObject_TypeCheck( str, &PyString_Type ) &&
1344 !PyObject_TypeCheck( str, &PyInt_Type ) )) {
1345 return AttributeError( GemRB_Control_SetText__doc );
1348 WindowIndex = PyInt_AsLong( wi );
1349 ControlIndex = PyInt_AsLong( ci );
1350 if (PyObject_TypeCheck( str, &PyString_Type )) {
1351 string = PyString_AsString( str );
1352 if (string == NULL) {
1353 return RuntimeError("Null string received");
1355 ret = core->SetText( (ieWord) WindowIndex, (ieWord) ControlIndex, string );
1356 if (ret == -1) {
1357 return RuntimeError("Cannot set text");
1359 } else {
1360 StrRef = PyInt_AsLong( str );
1361 if (StrRef == -1) {
1362 ret = core->SetText( (ieWord) WindowIndex, (ieWord) ControlIndex, GEMRB_STRING );
1363 } else {
1364 char *tmpstr = core->GetString( StrRef );
1365 ret = core->SetText( (ieWord) WindowIndex, (ieWord) ControlIndex, tmpstr );
1366 core->FreeString( tmpstr );
1368 if (ret == -1) {
1369 return RuntimeError("Cannot set text");
1372 return PyInt_FromLong( ret );
1375 PyDoc_STRVAR( GemRB_TextArea_Append__doc,
1376 "TextAreaAppend(WindowIndex, ControlIndex, String|Strref [, Row[, Flag]]) => int\n\n"
1377 "Appends the Text to the TextArea Control in the Window. "
1378 "If Row is given then it will insert the text after that row. "
1379 "If Flag is given, then it will use that value as a GetString flag.");
1381 static PyObject* GemRB_TextArea_Append(PyObject * /*self*/, PyObject* args)
1383 PyObject* wi, * ci, * str;
1384 PyObject* row = NULL;
1385 PyObject* flag = NULL;
1386 long WindowIndex, ControlIndex;
1387 long StrRef, Row, Flag = 0;
1388 char* string;
1389 int ret;
1391 if (!PyArg_UnpackTuple( args, "ref", 3, 5, &wi, &ci, &str, &row, &flag )) {
1392 return AttributeError( GemRB_TextArea_Append__doc );
1394 if (!PyObject_TypeCheck( wi, &PyInt_Type ) ||
1395 !PyObject_TypeCheck( ci, &PyInt_Type ) ||
1396 ( !PyObject_TypeCheck( str, &PyString_Type ) &&
1397 !PyObject_TypeCheck( str, &PyInt_Type ) )) {
1398 return AttributeError( GemRB_TextArea_Append__doc );
1400 WindowIndex = PyInt_AsLong( wi );
1401 ControlIndex = PyInt_AsLong( ci );
1403 TextArea* ta = ( TextArea* ) GetControl( WindowIndex, ControlIndex, IE_GUI_TEXTAREA);
1404 if (!ta) {
1405 return NULL;
1407 if (row) {
1408 if (!PyObject_TypeCheck( row, &PyInt_Type )) {
1409 printMessage( "GUIScript",
1410 "Syntax Error: AppendText row must be integer\n", LIGHT_RED );
1411 return NULL;
1413 Row = PyInt_AsLong( row );
1414 if (Row > ta->GetRowCount() - 1)
1415 Row = -1;
1416 } else
1417 Row = ta->GetRowCount() - 1;
1419 if (flag) {
1420 if (!PyObject_TypeCheck( flag, &PyInt_Type )) {
1421 printMessage( "GUIScript",
1422 "Syntax Error: GetString flag must be integer\n", LIGHT_RED );
1423 return NULL;
1425 Flag = PyInt_AsLong( flag );
1428 if (PyObject_TypeCheck( str, &PyString_Type )) {
1429 string = PyString_AsString( str );
1430 if (string == NULL)
1431 return RuntimeError("Null string received");
1432 ret = ta->AppendText( string, Row );
1433 } else {
1434 StrRef = PyInt_AsLong( str );
1435 char* str = core->GetString( StrRef, Flag );
1436 ret = ta->AppendText( str, Row );
1437 core->FreeString( str );
1440 return PyInt_FromLong( ret );
1443 PyDoc_STRVAR( GemRB_TextArea_Clear__doc,
1444 "TextAreaClear(WindowIndex, ControlIndex)\n\n"
1445 "Clears the Text from the TextArea Control in the Window." );
1447 static PyObject* GemRB_TextArea_Clear(PyObject * /*self*/, PyObject* args)
1449 PyObject* wi, * ci;
1450 long WindowIndex, ControlIndex;
1452 if (!PyArg_UnpackTuple( args, "ref", 2, 2, &wi, &ci )) {
1453 return AttributeError( GemRB_TextArea_Clear__doc );
1455 if (!PyObject_TypeCheck( wi, &PyInt_Type ) ||
1456 !PyObject_TypeCheck( ci, &PyInt_Type )) {
1457 return AttributeError( GemRB_TextArea_Clear__doc );
1459 WindowIndex = PyInt_AsLong( wi );
1460 ControlIndex = PyInt_AsLong( ci );
1461 TextArea* ta = ( TextArea* ) GetControl( WindowIndex, ControlIndex, IE_GUI_TEXTAREA);
1462 if (!ta) {
1463 return NULL;
1465 ta->Clear();
1467 Py_INCREF( Py_None );
1468 return Py_None;
1471 PyDoc_STRVAR( GemRB_TextArea_Scroll__doc,
1472 "TextAreaScroll(WindowIndex, ControlIndex, offset)\n\n"
1473 "Scrolls the textarea up or down by offset." );
1475 static PyObject* GemRB_TextArea_Scroll(PyObject * /*self*/, PyObject* args)
1477 int WindowIndex, ControlIndex, offset;
1479 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &offset)) {
1480 return AttributeError( GemRB_TextArea_Scroll__doc );
1482 TextArea* ta = ( TextArea* ) GetControl( WindowIndex, ControlIndex, IE_GUI_TEXTAREA);
1483 if (!ta) {
1484 return NULL;
1486 int row = ta->GetTopIndex()+offset;
1487 if (row<0) {
1488 row = 0;
1490 ta->SetRow( row );
1491 core->RedrawAll();
1492 Py_INCREF( Py_None );
1493 return Py_None;
1496 PyDoc_STRVAR( GemRB_Control_SetTooltip__doc,
1497 "SetTooltip(WindowIndex, ControlIndex, String|Strref) => int\n\n"
1498 "Sets control's tooltip." );
1500 static PyObject* GemRB_Control_SetTooltip(PyObject * /*self*/, PyObject* args)
1502 PyObject* wi, * ci, * str;
1503 long WindowIndex, ControlIndex, StrRef;
1504 char* string;
1505 int ret;
1507 if (!PyArg_UnpackTuple( args, "ref", 3, 3, &wi, &ci, &str )) {
1508 return AttributeError( GemRB_Control_SetTooltip__doc );
1510 if (!PyObject_TypeCheck( wi, &PyInt_Type ) ||
1511 !PyObject_TypeCheck( ci, &PyInt_Type ) ||
1512 ( !PyObject_TypeCheck( str, &PyString_Type ) &&
1513 !PyObject_TypeCheck( str, &PyInt_Type ) )) {
1514 return AttributeError( GemRB_Control_SetTooltip__doc );
1517 WindowIndex = PyInt_AsLong( wi );
1518 ControlIndex = PyInt_AsLong( ci );
1519 if (PyObject_TypeCheck( str, &PyString_Type )) {
1520 string = PyString_AsString( str );
1521 if (string == NULL) {
1522 return RuntimeError("Null string received");
1524 ret = core->SetTooltip( (ieWord) WindowIndex, (ieWord) ControlIndex, string );
1525 if (ret == -1) {
1526 return RuntimeError("Cannot set tooltip");
1528 } else {
1529 StrRef = PyInt_AsLong( str );
1530 if (StrRef == -1) {
1531 ret = core->SetTooltip( (ieWord) WindowIndex, (ieWord) ControlIndex, GEMRB_STRING );
1532 } else {
1533 char* str = core->GetString( StrRef );
1534 ret = core->SetTooltip( (ieWord) WindowIndex, (ieWord) ControlIndex, str );
1535 core->FreeString( str );
1537 if (ret == -1) {
1538 return RuntimeError("Cannot set tooltip");
1542 return PyInt_FromLong( ret );
1545 PyDoc_STRVAR( GemRB_Window_SetVisible__doc,
1546 "SetVisible(WindowIndex, Visible)\n\n"
1547 "Sets the Visibility Flag of a Window." );
1549 static PyObject* GemRB_Window_SetVisible(PyObject * /*self*/, PyObject* args)
1551 int WindowIndex;
1552 int visible;
1554 if (!PyArg_ParseTuple( args, "ii", &WindowIndex, &visible )) {
1555 return AttributeError( GemRB_Window_SetVisible__doc );
1558 int ret = core->SetVisible( WindowIndex, visible );
1559 if (ret == -1) {
1560 return RuntimeError("Invalid window in SetVisible");
1562 if (!WindowIndex) {
1563 core->SetEventFlag(EF_CONTROL);
1566 Py_INCREF( Py_None );
1567 return Py_None;
1570 //useful only for ToB and HoW, sets masterscript/worldmap name
1571 PyDoc_STRVAR( GemRB_SetMasterScript__doc,
1572 "SetMasterScript(ScriptResRef, WMPResRef)\n\n"
1573 "Sets the worldmap and masterscript names." );
1575 PyObject* GemRB_SetMasterScript(PyObject * /*self*/, PyObject* args)
1577 char* script;
1578 char* worldmap;
1580 if (!PyArg_ParseTuple( args, "ss", &script, &worldmap )) {
1581 return AttributeError( GemRB_SetMasterScript__doc );
1583 strnlwrcpy( core->GlobalScript, script, 8 );
1584 strnlwrcpy( core->WorldMapName, worldmap, 8 );
1585 core->UpdateMasterScript();
1586 Py_INCREF( Py_None );
1587 return Py_None;
1590 PyDoc_STRVAR( GemRB_Window_ShowModal__doc,
1591 "ShowModal(WindowIndex, [Shadow=MODAL_SHADOW_NONE])\n\n"
1592 "Show a Window on Screen setting the Modal Status. "
1593 "If Shadow is MODAL_SHADOW_GRAY, other windows are grayed. "
1594 "If Shadow is MODAL_SHADOW_BLACK, they are blacked out." );
1596 static PyObject* GemRB_Window_ShowModal(PyObject * /*self*/, PyObject* args)
1598 int WindowIndex, Shadow = MODAL_SHADOW_NONE;
1600 if (!PyArg_ParseTuple( args, "i|i", &WindowIndex, &Shadow )) {
1601 return AttributeError( GemRB_Window_ShowModal__doc );
1604 int ret = core->ShowModal( WindowIndex, Shadow );
1605 if (ret == -1) {
1606 return NULL;
1609 core->PlaySound(DS_WINDOW_OPEN);
1610 Py_INCREF( Py_None );
1611 return Py_None;
1614 PyDoc_STRVAR( GemRB_SetTimedEvent__doc,
1615 "SetTimedEvent(Function, Rounds)\n\n"
1616 "Sets a timed event, the timing is handled by the game object\n"
1617 "if the game object doesn't exist, this command is ignored." );
1619 static PyObject* GemRB_SetTimedEvent(PyObject * /*self*/, PyObject* args)
1621 PyObject* function;
1622 int rounds;
1624 if (!PyArg_ParseTuple( args, "Oi", &function, &rounds )) {
1625 return AttributeError( GemRB_SetTimedEvent__doc );
1628 EventHandler handler;
1629 if (function == Py_None) {
1630 handler = new Callback();
1631 } else if (PyCallable_Check(function)) {
1632 handler = new PythonCallback(function);
1633 } else {
1634 char buf[256];
1635 // TODO: Print function name. (func.__name__)
1636 snprintf(buf, sizeof(buf), "Can't set timed event handler!");
1637 return RuntimeError(buf);
1639 Game *game = core->GetGame();
1640 if (game) {
1641 game->SetTimedEvent(handler, rounds);
1643 Py_INCREF( Py_None );
1644 return Py_None;
1647 PyDoc_STRVAR( GemRB_SetTimedEventByName__doc,
1648 "SetTimedEventByName(FunctionName, Rounds)\n\n"
1649 "Sets a timed event, the timing is handled by the game object\n"
1650 "if the game object doesn't exist, this command is ignored." );
1652 static PyObject* GemRB_SetTimedEventByName(PyObject * /*self*/, PyObject* args)
1654 PyObject* funcName;
1655 int rounds;
1657 if (!PyArg_ParseTuple( args, "Oi", &funcName, &rounds )) {
1658 return AttributeError( GemRB_SetTimedEventByName__doc );
1660 if (!PyString_Check(funcName)) {
1661 return AttributeError( GemRB_SetTimedEventByName__doc );
1664 Game *game = core->GetGame();
1665 if (game) {
1666 game->SetTimedEvent(new StringCallback(funcName), rounds);
1668 Py_INCREF( Py_None );
1669 return Py_None;
1672 PyDoc_STRVAR( GemRB_Control_SetEvent__doc,
1673 "Control.SetEvent(EventMask, Function)\n\n"
1674 "Sets an event of a control on a window to a script defined function." );
1676 static PyObject* GemRB_Control_SetEvent(PyObject * /*self*/, PyObject* args)
1678 int WindowIndex, ControlIndex;
1679 int event;
1680 PyObject* func;
1682 if (!PyArg_ParseTuple(args, "iiiO", &WindowIndex, &ControlIndex,
1683 &event, &func)) {
1684 return AttributeError(GemRB_Control_SetEvent__doc);
1687 Control* ctrl = GetControl(WindowIndex, ControlIndex, -1);
1688 if (!ctrl)
1689 return NULL;
1691 EventHandler handler;
1692 if (func == Py_None) {
1693 handler = new Callback();
1694 } else if (PyCallable_Check(func)) {
1695 handler = new PythonCallback(func);
1697 if (!handler || !ctrl->SetEvent(event, handler)) {
1698 char buf[256];
1699 // TODO: Print function name. (func.__name__)
1700 snprintf(buf, sizeof(buf), "Can't set event handler!");
1701 return RuntimeError(buf);
1704 Py_INCREF(Py_None);
1705 return Py_None;
1708 PyDoc_STRVAR( GemRB_Control_SetEventByName__doc,
1709 "Control.SetEventByName(EventMask, FunctionName)\n\n"
1710 "Sets an event of a control on a window to a script defined function." );
1712 static PyObject* GemRB_Control_SetEventByName(PyObject * /*self*/, PyObject* args)
1714 int WindowIndex, ControlIndex;
1715 int event;
1716 PyObject* funcName;
1718 if (!PyArg_ParseTuple( args, "iiiO", &WindowIndex, &ControlIndex, &event,
1719 &funcName )) {
1720 return AttributeError( GemRB_Control_SetEventByName__doc );
1722 if (!PyString_Check(funcName)) {
1723 return AttributeError( GemRB_Control_SetEventByName__doc );
1726 Control* ctrl = GetControl( WindowIndex, ControlIndex, -1 );
1727 if (!ctrl)
1728 return NULL;
1730 if (! ctrl->SetEvent( event, new StringCallback(funcName) )) {
1731 char buf[256];
1732 snprintf( buf, sizeof( buf ), "Can't set event handler: %s!", PyString_AsString(funcName) );
1733 return RuntimeError( buf );
1736 Py_INCREF( Py_None );
1737 return Py_None;
1740 PyDoc_STRVAR( GemRB_SetNextScript__doc,
1741 "SetNextScript(GUIScriptName)\n\n"
1742 "Sets the Next Script File to be loaded." );
1744 static PyObject* GemRB_SetNextScript(PyObject * /*self*/, PyObject* args)
1746 const char* funcName;
1748 if (!PyArg_ParseTuple( args, "s", &funcName )) {
1749 return AttributeError( GemRB_SetNextScript__doc );
1752 core->SetNextScript(funcName);
1754 Py_INCREF( Py_None );
1755 return Py_None;
1758 PyDoc_STRVAR( GemRB_Control_SetStatus__doc,
1759 "SetControlStatus(WindowIndex, ControlIndex, Status)\n\n"
1760 "Sets the status of a Control." );
1762 static PyObject* GemRB_Control_SetStatus(PyObject * /*self*/, PyObject* args)
1764 int WindowIndex, ControlIndex;
1765 int status;
1767 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &status )) {
1768 return AttributeError( GemRB_Control_SetStatus__doc );
1771 int ret = core->SetControlStatus( WindowIndex, ControlIndex, status );
1772 if (ret == -1) {
1773 return NULL;
1776 Py_INCREF( Py_None );
1777 return Py_None;
1780 PyDoc_STRVAR( GemRB_Control_AttachScrollBar__doc,
1781 "AttachScrollBar(WindowIndex, ControlIndex, ScrollBarControlIndex)\n\n"
1782 "Attaches a ScrollBar to another control." );
1784 static PyObject* GemRB_Control_AttachScrollBar(PyObject * /*self*/, PyObject* args)
1786 int WindowIndex, ControlIndex, ScbControlIndex;
1788 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &ScbControlIndex )) {
1789 return AttributeError( GemRB_Control_AttachScrollBar__doc );
1792 Control *ctrl = GetControl(WindowIndex, ControlIndex, -1);
1793 if (!ctrl) {
1794 return NULL;
1797 Control *scb = NULL;
1799 if (ScbControlIndex != -1) {
1800 scb = GetControl(WindowIndex, ScbControlIndex, IE_GUI_SCROLLBAR);
1801 if (!scb) {
1802 return NULL;
1806 int ret = ctrl->SetScrollBar( scb );
1807 if (ret == -1) {
1808 return NULL;
1811 Py_INCREF( Py_None );
1812 return Py_None;
1815 PyDoc_STRVAR( GemRB_Control_SetVarAssoc__doc,
1816 "SetVarAssoc(WindowIndex, ControlIndex, VariableName, LongValue)\n\n"
1817 "Sets the name of the Variable associated with a control." );
1819 static PyObject* GemRB_Control_SetVarAssoc(PyObject * /*self*/, PyObject* args)
1821 int WindowIndex, ControlIndex;
1822 ieDword Value;
1823 char* VarName;
1825 if (!PyArg_ParseTuple( args, "iisi", &WindowIndex, &ControlIndex,
1826 &VarName, &Value )) {
1827 return AttributeError( GemRB_Control_SetVarAssoc__doc );
1830 Control* ctrl = GetControl( WindowIndex, ControlIndex, -1 );
1831 if (!ctrl) {
1832 return NULL;
1835 //max variable length is not 32, but 40 (in guiscripts), but that includes zero terminator!
1836 strnlwrcpy( ctrl->VarName, VarName, MAX_VARIABLE_LENGTH-1 );
1837 ctrl->Value = Value;
1838 /** setting the correct state for this control */
1839 /** it is possible to set up a default value, if Lookup returns false, use it */
1840 Value = 0;
1841 core->GetDictionary()->Lookup( VarName, Value );
1842 Window* win = core->GetWindow( WindowIndex );
1843 win->RedrawControls(VarName, Value);
1845 Py_INCREF( Py_None );
1846 return Py_None;
1849 PyDoc_STRVAR( GemRB_Window_Unload__doc,
1850 "UnloadWindow(WindowIndex)\n\n"
1851 "Unloads a previously Loaded Window." );
1853 static PyObject* GemRB_Window_Unload(PyObject * /*self*/, PyObject* args)
1855 int WindowIndex;
1857 if (!PyArg_ParseTuple( args, "i", &WindowIndex )) {
1858 return AttributeError( GemRB_Window_Unload__doc );
1861 unsigned short arg = (unsigned short) WindowIndex;
1862 if (arg == 0xffff) {
1863 return AttributeError( "Feature unsupported! ");
1865 int ret = core->DelWindow( arg );
1866 if (ret == -1) {
1867 return RuntimeError( "Can't unload window!" );
1870 core->PlaySound(DS_WINDOW_CLOSE);
1871 Py_INCREF( Py_None );
1872 return Py_None;
1875 PyDoc_STRVAR( GemRB_Window_Invalidate__doc,
1876 "InvalidateWindow(WindowIndex)\n\n"
1877 "Invalidates the given Window." );
1879 static PyObject* GemRB_Window_Invalidate(PyObject * /*self*/, PyObject* args)
1881 int WindowIndex;
1883 if (!PyArg_ParseTuple( args, "i", &WindowIndex )) {
1884 return AttributeError( GemRB_Window_Invalidate__doc );
1887 Window* win = core->GetWindow( WindowIndex );
1888 if (win == NULL) {
1889 return RuntimeError("Cannot find window!");
1891 win->Invalidate();
1893 Py_INCREF( Py_None );
1894 return Py_None;
1897 PyDoc_STRVAR( GemRB_CreateWindow__doc,
1898 "CreateWindow(WindowID, X, Y, Width, Height, MosResRef) => WindowIndex\n\n"
1899 "Creates a new empty window and returns its index.");
1901 static PyObject* GemRB_CreateWindow(PyObject * /*self*/, PyObject* args)
1903 int WindowID, x, y, w, h;
1904 char* Background;
1906 if (!PyArg_ParseTuple( args, "iiiiis", &WindowID, &x, &y,
1907 &w, &h, &Background )) {
1908 return AttributeError( GemRB_CreateWindow__doc );
1910 int WindowIndex = core->CreateWindow( WindowID, x, y, w, h, Background );
1911 if (WindowIndex == -1) {
1912 return RuntimeError( "Can't create window" );
1915 return PyInt_FromLong( WindowIndex );
1918 PyDoc_STRVAR( GemRB_Button_CreateLabelOnButton__doc,
1919 "CreateLabelOnButton(WindowIndex, ControlIndex, NewControlID, font, align)"
1920 "Creates a label on top of a button, copying the button's size and position." );
1922 static PyObject* GemRB_Button_CreateLabelOnButton(PyObject * /*self*/, PyObject* args)
1924 int WindowIndex, ControlIndex, ControlID, align;
1925 char *font;
1927 if (!PyArg_ParseTuple( args, "iiisi", &WindowIndex, &ControlIndex,
1928 &ControlID, &font, &align )) {
1929 return AttributeError( GemRB_Button_CreateLabelOnButton__doc );
1932 Window* win = core->GetWindow( WindowIndex );
1933 if (win == NULL) {
1934 return RuntimeError("Cannot find window!");
1936 Control *btn = GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
1937 if (!btn) {
1938 return NULL;
1940 Label* lbl = new Label( core->GetFont( font ) );
1941 lbl->XPos = btn->XPos;
1942 lbl->YPos = btn->YPos;
1943 lbl->Width = btn->Width;
1944 lbl->Height = btn->Height;
1945 lbl->ControlID = ControlID;
1946 lbl->ControlType = IE_GUI_LABEL;
1947 lbl->Owner = win;
1948 lbl->SetAlignment( align );
1949 win->AddControl( lbl );
1951 int ret = core->GetControl( WindowIndex, ControlID );
1953 if (ret<0) {
1954 return NULL;
1956 return PyInt_FromLong( ret );
1957 //Py_INCREF( Py_None );
1958 //return Py_None;
1961 PyDoc_STRVAR( GemRB_Window_CreateLabel__doc,
1962 "CreateLabel(WindowIndex, ControlID, x, y, w, h, font, text, align)\n\n"
1963 "Creates and adds a new Label to a Window." );
1965 static PyObject* GemRB_Window_CreateLabel(PyObject * /*self*/, PyObject* args)
1967 int WindowIndex, ControlID, x, y, w, h, align;
1968 char *font, *text;
1970 if (!PyArg_ParseTuple( args, "iiiiiissi", &WindowIndex, &ControlID, &x,
1971 &y, &w, &h, &font, &text, &align )) {
1972 return AttributeError( GemRB_Window_CreateLabel__doc );
1975 Window* win = core->GetWindow( WindowIndex );
1976 if (win == NULL) {
1977 return RuntimeError("Cannot find window!");
1979 Label* lbl = new Label( core->GetFont( font ) );
1980 lbl->XPos = x;
1981 lbl->YPos = y;
1982 lbl->Width = w;
1983 lbl->Height = h;
1984 lbl->ControlID = ControlID;
1985 lbl->ControlType = IE_GUI_LABEL;
1986 lbl->Owner = win;
1987 lbl->SetText( text );
1988 lbl->SetAlignment( align );
1989 win->AddControl( lbl );
1991 int ret = core->GetControl( WindowIndex, ControlID );
1993 if (ret<0) {
1994 return NULL;
1996 return PyInt_FromLong( ret );
1997 //Py_INCREF( Py_None );
1998 //return Py_None;
2001 PyDoc_STRVAR( GemRB_Label_SetTextColor__doc,
2002 "SetLabelTextColor(WindowIndex, ControlIndex, red, green, blue)\n\n"
2003 "Sets the Text Color of a Label Control." );
2005 static PyObject* GemRB_Label_SetTextColor(PyObject * /*self*/, PyObject* args)
2007 int WindowIndex, ControlIndex, r, g, b;
2009 if (!PyArg_ParseTuple( args, "iiiii", &WindowIndex, &ControlIndex, &r, &g,
2010 &b )) {
2011 return AttributeError( GemRB_Label_SetTextColor__doc );
2014 Label* lab = ( Label* ) GetControl(WindowIndex, ControlIndex, IE_GUI_LABEL);
2015 if (!lab) {
2016 return NULL;
2019 Color fore = {r,g, b, 0}, back = {0, 0, 0, 0};
2020 lab->SetColor( fore, back );
2022 Py_INCREF( Py_None );
2023 return Py_None;
2026 PyDoc_STRVAR( GemRB_Window_CreateTextEdit__doc,
2027 "CreateTextEdit(WindowIndex, ControlID, x, y, w, h, font, text)\n\n"
2028 "Creates and adds a new TextEdit to a Window." );
2030 static PyObject* GemRB_Window_CreateTextEdit(PyObject * /*self*/, PyObject* args)
2032 int WindowIndex, ControlID, x, y, w, h;
2033 char *font, *text;
2035 if (!PyArg_ParseTuple( args, "iiiiiiss", &WindowIndex, &ControlID, &x,
2036 &y, &w, &h, &font, &text )) {
2037 return AttributeError( GemRB_Window_CreateTextEdit__doc );
2040 Window* win = core->GetWindow( WindowIndex );
2041 if (win == NULL) {
2042 return RuntimeError("Cannot find window!");
2044 //there is no need to set these differently, currently
2045 TextEdit* edit = new TextEdit( 500, 0, 0);
2046 edit->SetFont( core->GetFont( font ) );
2047 edit->XPos = x;
2048 edit->YPos = y;
2049 edit->Width = w;
2050 edit->Height = h;
2051 edit->ControlID = ControlID;
2052 edit->ControlType = IE_GUI_EDIT;
2053 edit->Owner = win;
2054 edit->SetText( text );
2056 Sprite2D* spr = core->GetCursorSprite();
2057 if (spr)
2058 edit->SetCursor( spr );
2059 else
2060 return RuntimeError( "BAM not found" );
2062 win->AddControl( edit );
2064 int ret = core->GetControl( WindowIndex, ControlID );
2066 if (ret<0) {
2067 return NULL;
2069 return PyInt_FromLong( ret );
2070 //Py_INCREF( Py_None );
2071 //return Py_None;
2074 PyDoc_STRVAR( GemRB_Window_CreateScrollBar__doc,
2075 "CreateScrollBar(WindowIndex, ControlID, x, y, w, h) => ControlIndex\n\n"
2076 "Creates and adds a new ScrollBar to a Window.");
2078 static PyObject* GemRB_Window_CreateScrollBar(PyObject * /*self*/, PyObject* args)
2080 int WindowIndex, ControlID, x, y, w, h;
2082 if (!PyArg_ParseTuple( args, "iiiiii", &WindowIndex, &ControlID, &x, &y,
2083 &w, &h )) {
2084 return AttributeError( GemRB_Window_CreateScrollBar__doc );
2087 Window* win = core->GetWindow( WindowIndex );
2088 if (win == NULL) {
2089 return RuntimeError("Cannot find window!");
2092 ScrollBar* sb = new ScrollBar( );
2093 sb->XPos = x;
2094 sb->YPos = y;
2095 sb->Width = w;
2096 sb->Height = h;
2097 sb->ControlID = ControlID;
2098 sb->ControlType = IE_GUI_SCROLLBAR;
2099 sb->Owner = win;
2100 win->AddControl( sb );
2102 int ret = core->GetControl( WindowIndex, ControlID );
2104 if (ret<0) {
2105 return NULL;
2107 return PyInt_FromLong( ret );
2108 //Py_INCREF( Py_None );
2109 //return Py_None;
2113 PyDoc_STRVAR( GemRB_Window_CreateButton__doc,
2114 "CreateButton(WindowIndex, ControlID, x, y, w, h) => ControlIndex\n\n"
2115 "Creates and adds a new Button to a Window." );
2117 static PyObject* GemRB_Window_CreateButton(PyObject * /*self*/, PyObject* args)
2119 int WindowIndex, ControlID, x, y, w, h;
2121 if (!PyArg_ParseTuple( args, "iiiiii", &WindowIndex, &ControlID, &x, &y,
2122 &w, &h )) {
2123 return AttributeError( GemRB_Window_CreateButton__doc );
2126 Window* win = core->GetWindow( WindowIndex );
2127 if (win == NULL) {
2128 return RuntimeError("Cannot find window!");
2131 Button* btn = new Button( );
2132 btn->XPos = x;
2133 btn->YPos = y;
2134 btn->Width = w;
2135 btn->Height = h;
2136 btn->ControlID = ControlID;
2137 btn->ControlType = IE_GUI_BUTTON;
2138 btn->Owner = win;
2139 win->AddControl( btn );
2141 int ret = core->GetControl( WindowIndex, ControlID );
2143 if (ret<0) {
2144 return NULL;
2146 return PyInt_FromLong( ret );
2147 //Py_INCREF( Py_None );
2148 //return Py_None;
2152 PyDoc_STRVAR( GemRB_TextEdit_ConvertEdit__doc,
2153 "ConvertEdit(WindowIndex, ControlIndex, ScrollBarID) => ControlIndex\n\n"
2154 "Converts a simple Edit Control to a TextArea, keeping its ControlID." );
2156 static PyObject* GemRB_TextEdit_ConvertEdit(PyObject * /*self*/, PyObject* args)
2158 int WindowIndex, ControlIndex;
2159 Color fore={255,255,255,0};
2160 Color init={255,255,255,0};
2161 Color back={0,0,0,0};
2162 int ScrollBarID=0;
2164 if (!PyArg_ParseTuple( args, "ii|i", &WindowIndex, &ControlIndex, &ScrollBarID)) {
2165 return AttributeError( GemRB_TextEdit_ConvertEdit__doc );
2168 Window* win = core->GetWindow( WindowIndex );
2169 if (win == NULL) {
2170 return RuntimeError("Cannot find window!");
2173 TextEdit *ctrl = (TextEdit *) GetControl(WindowIndex, ControlIndex, IE_GUI_EDIT);
2174 if (!ctrl) {
2175 return NULL;
2177 TextArea* ta = new TextArea( fore, init, back );
2178 ta->XPos = ctrl->XPos;
2179 ta->YPos = ctrl->YPos;
2180 ta->Width = ctrl->Width;
2181 ta->Height = ctrl->Height;
2182 ta->ControlID = ctrl->ControlID;
2183 ta->ControlType = IE_GUI_TEXTAREA;
2184 ta->Owner = win;
2185 ta->SetFonts (ctrl->GetFont(), ctrl->GetFont() );
2186 ta->Flags |= IE_GUI_TEXTAREA_EDITABLE;
2187 win->AddControl( ta );
2188 win->Link( ScrollBarID, ( unsigned short ) ta->ControlID );
2190 int ret = core->GetControl( WindowIndex, ta->ControlID );
2192 if (ret<0) {
2193 return NULL;
2195 return PyInt_FromLong( ret );
2198 PyDoc_STRVAR( GemRB_ScrollBar_SetSprites__doc,
2199 "SetScrollBarSprites(WindowIndex, ControlIndex, ResRef, Cycle, UpUnpressedFrame, UpPressedFrame, DownUnpressedFrame, DownPressedFrame, TroughFrame, SliderFrame)\n\n"
2200 "Sets a ScrollBar Sprites Images." );
2202 static PyObject* GemRB_ScrollBar_SetSprites(PyObject * /*self*/, PyObject* args)
2204 int WindowIndex, ControlIndex, cycle, upunpressed, uppressed;
2205 int downunpressed, downpressed, trough, knob;
2206 char *ResRef;
2208 if (!PyArg_ParseTuple( args, "iisiiiiiii", &WindowIndex, &ControlIndex,
2209 &ResRef, &cycle, &upunpressed, &uppressed, &downunpressed, &downpressed, &trough, &knob )) {
2210 return AttributeError( GemRB_ScrollBar_SetSprites__doc );
2213 ScrollBar* sb = ( ScrollBar* ) GetControl(WindowIndex, ControlIndex, IE_GUI_SCROLLBAR);
2214 if (!sb) {
2215 return NULL;
2218 if (ResRef[0] == 0) {
2219 sb->SetImage( IE_GUI_SCROLLBAR_UP_UNPRESSED, 0 );
2220 sb->SetImage( IE_GUI_SCROLLBAR_UP_PRESSED, 0 );
2221 sb->SetImage( IE_GUI_SCROLLBAR_DOWN_UNPRESSED, 0 );
2222 sb->SetImage( IE_GUI_SCROLLBAR_DOWN_PRESSED, 0 );
2223 sb->SetImage( IE_GUI_SCROLLBAR_TROUGH, 0 );
2224 sb->SetImage( IE_GUI_SCROLLBAR_SLIDER, 0 );
2225 Py_INCREF( Py_None );
2226 return Py_None;
2229 AnimationFactory* af = ( AnimationFactory* )
2230 gamedata->GetFactoryResource( ResRef,
2231 IE_BAM_CLASS_ID, IE_NORMAL );
2232 if (!af) {
2233 return RuntimeError( "BAM not found" );
2235 Sprite2D *tspr = af->GetFrame(upunpressed, (unsigned char)cycle);
2236 sb->SetImage( IE_GUI_SCROLLBAR_UP_UNPRESSED, tspr );
2237 tspr = af->GetFrame( uppressed, (unsigned char) cycle);
2238 sb->SetImage( IE_GUI_SCROLLBAR_UP_PRESSED, tspr );
2239 tspr = af->GetFrame( downunpressed, (unsigned char)cycle);
2240 sb->SetImage( IE_GUI_SCROLLBAR_DOWN_UNPRESSED, tspr );
2241 tspr = af->GetFrame( downpressed, (unsigned char) cycle);
2242 sb->SetImage( IE_GUI_SCROLLBAR_DOWN_PRESSED, tspr );
2243 tspr = af->GetFrame( trough, (unsigned char) cycle);
2244 sb->SetImage( IE_GUI_SCROLLBAR_TROUGH, tspr );
2245 tspr = af->GetFrame( knob, (unsigned char) cycle);
2246 sb->SetImage( IE_GUI_SCROLLBAR_SLIDER, tspr );
2248 Py_INCREF( Py_None );
2249 return Py_None;
2253 PyDoc_STRVAR( GemRB_Button_SetSprites__doc,
2254 "SetButtonSprites(WindowIndex, ControlIndex, ResRef, Cycle, UnpressedFrame, PressedFrame, SelectedFrame, DisabledFrame)\n\n"
2255 "Sets a Button Sprites Images." );
2257 static PyObject* GemRB_Button_SetSprites(PyObject * /*self*/, PyObject* args)
2259 int WindowIndex, ControlIndex, cycle, unpressed, pressed, selected,
2260 disabled;
2261 char *ResRef;
2263 if (!PyArg_ParseTuple( args, "iisiiiii", &WindowIndex, &ControlIndex,
2264 &ResRef, &cycle, &unpressed, &pressed, &selected, &disabled )) {
2265 return AttributeError( GemRB_Button_SetSprites__doc );
2268 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2269 if (!btn) {
2270 return NULL;
2273 if (ResRef[0] == 0) {
2274 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, 0 );
2275 btn->SetImage( IE_GUI_BUTTON_PRESSED, 0 );
2276 btn->SetImage( IE_GUI_BUTTON_SELECTED, 0 );
2277 btn->SetImage( IE_GUI_BUTTON_DISABLED, 0 );
2278 Py_INCREF( Py_None );
2279 return Py_None;
2282 AnimationFactory* af = ( AnimationFactory* )
2283 gamedata->GetFactoryResource( ResRef,
2284 IE_BAM_CLASS_ID, IE_NORMAL );
2285 if (!af) {
2286 return RuntimeError( "BAM not found" );
2288 Sprite2D *tspr = af->GetFrame(unpressed, (unsigned char)cycle);
2289 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, tspr );
2290 tspr = af->GetFrame( pressed, (unsigned char) cycle);
2291 btn->SetImage( IE_GUI_BUTTON_PRESSED, tspr );
2292 tspr = af->GetFrame( selected, (unsigned char) cycle);
2293 btn->SetImage( IE_GUI_BUTTON_SELECTED, tspr );
2294 tspr = af->GetFrame( disabled, (unsigned char) cycle);
2295 btn->SetImage( IE_GUI_BUTTON_DISABLED, tspr );
2297 Py_INCREF( Py_None );
2298 return Py_None;
2301 PyDoc_STRVAR( GemRB_Button_SetOverlay__doc,
2302 "SetButtonOverlay(WindowIndex, ControlIndex, Current, Max, r,g,b,a, r,g,b,a)\n\n"
2303 "Sets up a portrait button for hitpoint overlay" );
2305 static PyObject* GemRB_Button_SetOverlay(PyObject * /*self*/, PyObject* args)
2307 int WindowIndex, ControlIndex;
2308 double Clipping;
2309 int r1,g1,b1,a1;
2310 int r2,g2,b2,a2;
2312 if (!PyArg_ParseTuple( args, "iidiiiiiiii", &WindowIndex, &ControlIndex,
2313 &Clipping, &r1, &g1, &b1, &a1, &r2, &g2, &b2, &a2)) {
2314 return AttributeError( GemRB_Button_SetOverlay__doc );
2317 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2318 if (!btn) {
2319 return NULL;
2322 const Color src = { r1, g1, b1, a1 };
2323 const Color dest = { r2, g2, b2, a2 };
2325 if (Clipping<0.0) Clipping = 0.0;
2326 else if (Clipping>1.0) Clipping = 1.0;
2327 //can't call clipping, because the change of ratio triggers color change
2328 btn->SetHorizontalOverlay(Clipping, src, dest);
2329 Py_INCREF( Py_None );
2330 return Py_None;
2333 PyDoc_STRVAR( GemRB_Button_SetBorder__doc,
2334 "SetButtonBorder(WindowIndex, ControlIndex, BorderIndex, dx1, dy1, dx2, dy2, R, G, B, A, [enabled, filled])\n\n"
2335 "Sets border/frame parameters for a button." );
2337 static PyObject* GemRB_Button_SetBorder(PyObject * /*self*/, PyObject* args)
2339 int WindowIndex, ControlIndex, BorderIndex, dx1, dy1, dx2, dy2, r, g, b, a, enabled = 0, filled = 0;
2341 if (!PyArg_ParseTuple( args, "iiiiiiiiiii|ii", &WindowIndex, &ControlIndex,
2342 &BorderIndex, &dx1, &dy1, &dx2, &dy2, &r, &g, &b, &a, &enabled, &filled)) {
2343 return AttributeError( GemRB_Button_SetBorder__doc );
2346 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2347 if (!btn) {
2348 return NULL;
2351 const Color color = { r, g, b, a };
2352 btn->SetBorder( BorderIndex, dx1, dy1, dx2, dy2, color, (bool)enabled, (bool)filled );
2354 Py_INCREF( Py_None );
2355 return Py_None;
2358 PyDoc_STRVAR( GemRB_Button_EnableBorder__doc,
2359 "EnableButtonBorder(WindowIndex, ControlIndex, BorderIndex, enabled)\n\n"
2360 "Enable or disable specified border/frame." );
2362 static PyObject* GemRB_Button_EnableBorder(PyObject * /*self*/, PyObject* args)
2364 int WindowIndex, ControlIndex, BorderIndex, enabled;
2366 if (!PyArg_ParseTuple( args, "iiii", &WindowIndex, &ControlIndex,
2367 &BorderIndex, &enabled)) {
2368 return AttributeError( GemRB_Button_EnableBorder__doc );
2371 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2372 if (!btn) {
2373 return NULL;
2376 btn->EnableBorder( BorderIndex, (bool)enabled );
2378 Py_INCREF( Py_None );
2379 return Py_None;
2382 PyDoc_STRVAR( GemRB_Button_SetFont__doc,
2383 "SetButtonFont(WindowIndex, ControlIndex, FontResRef)\n\n"
2384 "Sets font used for drawing button label." );
2386 static PyObject* GemRB_Button_SetFont(PyObject * /*self*/, PyObject* args)
2388 int WindowIndex, ControlIndex;
2389 char *FontResRef;
2391 if (!PyArg_ParseTuple( args, "iis", &WindowIndex, &ControlIndex,
2392 &FontResRef)) {
2393 return AttributeError( GemRB_Button_SetFont__doc );
2396 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2397 if (!btn) {
2398 return NULL;
2401 btn->SetFont( core->GetFont( FontResRef ));
2403 Py_INCREF( Py_None );
2404 return Py_None;
2407 PyDoc_STRVAR( GemRB_Button_SetTextColor__doc,
2408 "SetButtonTextColor(WindowIndex, ControlIndex, red, green, blue[, invert=false])\n\n"
2409 "Sets the Text Color of a Button Control. Invert is used for fonts with swapped background and text colors." );
2411 static PyObject* GemRB_Button_SetTextColor(PyObject * /*self*/, PyObject* args)
2413 int WindowIndex, ControlIndex, r, g, b, swap = 0;
2415 if (!PyArg_ParseTuple( args, "iiiii|i", &WindowIndex, &ControlIndex, &r, &g, &b, &swap )) {
2416 return AttributeError( GemRB_Button_SetTextColor__doc );
2419 Button* but = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2420 if (!but) {
2421 return NULL;
2424 Color fore = {r,g, b, 0}, back = {0, 0, 0, 0};
2426 // FIXME: swap is a hack for fonts which apparently have swapped f & B
2427 // colors. Maybe it depends on need_palette?
2428 if (! swap)
2429 but->SetTextColor( fore, back );
2430 else
2431 but->SetTextColor( back, fore );
2434 Py_INCREF( Py_None );
2435 return Py_None;
2438 PyDoc_STRVAR( GemRB_Window_DeleteControl__doc,
2439 "DeleteControl(WindowIndex, ControlID)\n\n"
2440 "Deletes a control from a Window." );
2442 static PyObject* GemRB_Window_DeleteControl(PyObject * /*self*/, PyObject* args)
2444 int WindowIndex, ControlID;
2446 if (!PyArg_ParseTuple( args, "ii", &WindowIndex, &ControlID)) {
2447 return AttributeError( GemRB_Window_DeleteControl__doc );
2450 Window* win = core->GetWindow( WindowIndex );
2451 if (win == NULL) {
2452 return RuntimeError("Cannot find window!");
2454 int CtrlIndex = core->GetControl( WindowIndex, ControlID );
2455 if (CtrlIndex == -1) {
2456 return RuntimeError( "Control is not found" );
2458 win -> DelControl( CtrlIndex );
2460 Py_INCREF( Py_None );
2461 return Py_None;
2464 PyDoc_STRVAR( GemRB_WorldMap_AdjustScrolling__doc,
2465 "AdjustScrolling(WindowIndex, ControlIndex, x, y)\n\n"
2466 "Sets the scrolling offset of a WorldMapControl.");
2468 static PyObject* GemRB_WorldMap_AdjustScrolling(PyObject * /*self*/, PyObject* args)
2470 int WindowIndex, ControlIndex, x, y;
2472 if (!PyArg_ParseTuple( args, "iiii", &WindowIndex, &ControlIndex, &x, &y )) {
2473 return AttributeError( GemRB_WorldMap_AdjustScrolling__doc );
2476 core->AdjustScrolling( WindowIndex, ControlIndex, x, y );
2477 Py_INCREF( Py_None );
2478 return Py_None;
2481 PyDoc_STRVAR( GemRB_CreateMovement__doc,
2482 "CreateMovement(Area, Entrance, Direction)\n\n"
2483 "Moves actors to a new area." );
2485 static PyObject* GemRB_CreateMovement(PyObject * /*self*/, PyObject* args)
2487 int everyone;
2488 char *area;
2489 char *entrance;
2490 int direction = 0;
2492 if (!PyArg_ParseTuple( args, "ss|i", &area, &entrance, &direction)) {
2493 return AttributeError( GemRB_CreateMovement__doc );
2495 if (core->HasFeature(GF_TEAM_MOVEMENT) ) {
2496 everyone = CT_WHOLE;
2497 } else {
2498 everyone = CT_GO_CLOSER;
2500 Game *game = core->GetGame();
2501 if (!game) {
2502 return RuntimeError( "No game loaded!" );
2504 game->GetCurrentArea()->MoveToNewArea(area, entrance, (unsigned int)direction, everyone, NULL);
2505 Py_INCREF( Py_None );
2506 return Py_None;
2509 PyDoc_STRVAR( GemRB_WorldMap_GetDestinationArea__doc,
2510 "GetDestinationArea(WindowIndex, ControlID[, RndEncounter]) => WorldMap entry\n\n"
2511 "Returns the last area pointed on the worldmap.\n"
2512 "If the random encounter flag is set, the random encounters will be evaluated too." );
2514 static PyObject* GemRB_WorldMap_GetDestinationArea(PyObject * /*self*/, PyObject* args)
2516 int WindowIndex, ControlIndex;
2517 int eval = 0;
2519 if (!PyArg_ParseTuple( args, "ii|i", &WindowIndex, &ControlIndex, &eval)) {
2520 return AttributeError( GemRB_WorldMap_GetDestinationArea__doc );
2523 WorldMapControl* wmc = (WorldMapControl *) GetControl(WindowIndex, ControlIndex, IE_GUI_WORLDMAP);
2524 if (!wmc) {
2525 return NULL;
2527 //no area was pointed on
2528 if (!wmc->Area) {
2529 Py_INCREF( Py_None );
2530 return Py_None;
2532 WorldMap *wm = core->GetWorldMap();
2533 PyObject* dict = PyDict_New();
2534 //the area the user clicked on
2535 PyDict_SetItemString(dict, "Target", PyString_FromString (wmc->Area->AreaName) );
2536 bool encounter;
2537 WMPAreaLink *wal = wm->GetEncounterLink(wmc->Area->AreaName, encounter);
2538 if (!wal) {
2539 PyDict_SetItemString(dict, "Distance", PyInt_FromLong (-1) );
2540 return dict;
2542 PyDict_SetItemString(dict, "Destination", PyString_FromString (wmc->Area->AreaName) );
2543 PyDict_SetItemString(dict, "Entrance", PyString_FromString (wal->DestEntryPoint) );
2544 PyDict_SetItemString(dict, "Direction", PyInt_FromLong (wal->DirectionFlags) );
2545 //the area the user will fall on
2546 if (encounter && eval) {
2547 int i=rand()%5;
2549 if(wal->EncounterChance>=100) {
2550 wal->EncounterChance-=100;
2552 for(int j=0;j<5;j++) {
2553 if (wal->EncounterAreaResRef[(i+j)%5][0]) {
2554 PyDict_SetItemString(dict, "Destination", PyString_FromString (wal->EncounterAreaResRef[(i+j)%5]) );
2555 PyDict_SetItemString(dict, "Entrance", PyString_FromString ("") );
2556 // do we need to change Direction here?
2557 break;
2562 //the entrance the user will fall on
2563 PyDict_SetItemString(dict, "Distance", PyInt_FromLong (wm->GetDistance(wmc->Area->AreaName)) );
2564 return dict;
2567 PyDoc_STRVAR( GemRB_Window_CreateWorldMapControl__doc,
2568 "CreateWorldMapControl(WindowIndex, ControlID, x, y, w, h, direction[, font])\n\n"
2569 "Creates and adds a new WorldMap control to a Window." );
2571 static PyObject* GemRB_Window_CreateWorldMapControl(PyObject * /*self*/, PyObject* args)
2573 int WindowIndex, ControlID, x, y, w, h, direction;
2574 char *font=NULL;
2576 if (!PyArg_ParseTuple( args, "iiiiiii|s", &WindowIndex, &ControlID, &x,
2577 &y, &w, &h, &direction, &font )) {
2578 return AttributeError( GemRB_Window_CreateWorldMapControl__doc );
2581 Window* win = core->GetWindow( WindowIndex );
2582 if (win == NULL) {
2583 return RuntimeError("Cannot find window!");
2585 int CtrlIndex = core->GetControl( WindowIndex, ControlID );
2586 if (CtrlIndex != -1) {
2587 Control *ctrl = win->GetControl( CtrlIndex );
2588 x = ctrl->XPos;
2589 y = ctrl->YPos;
2590 w = ctrl->Width;
2591 h = ctrl->Height;
2592 //flags = ctrl->Value;
2593 win->DelControl( CtrlIndex );
2595 WorldMapControl* wmap = new WorldMapControl( font?font:"", direction );
2596 wmap->XPos = x;
2597 wmap->YPos = y;
2598 wmap->Width = w;
2599 wmap->Height = h;
2600 wmap->ControlID = ControlID;
2601 wmap->ControlType = IE_GUI_WORLDMAP;
2602 wmap->Owner = win;
2603 win->AddControl( wmap );
2605 int ret = core->GetControl( WindowIndex, ControlID );
2607 if (ret<0) {
2608 return NULL;
2610 return PyInt_FromLong( ret );
2611 //Py_INCREF( Py_None );
2612 //return Py_None;
2615 PyDoc_STRVAR( GemRB_WorldMap_SetTextColor__doc,
2616 "SetWorldMapTextColor(WindowIndex, ControlIndex, which, red, green, blue)\n\n"
2617 "Sets the label colors of a WorldMap Control. WHICH selects color affected"
2618 "and is one of IE_GUI_WMAP_COLOR_(NORMAL|SELECTED|NOTVISITED)." );
2620 static PyObject* GemRB_WorldMap_SetTextColor(PyObject * /*self*/, PyObject* args)
2622 int WindowIndex, ControlIndex, which, r, g, b, a;
2624 if (!PyArg_ParseTuple( args, "iiiiiii", &WindowIndex, &ControlIndex, &which, &r, &g, &b, &a )) {
2625 return AttributeError( GemRB_WorldMap_SetTextColor__doc );
2628 WorldMapControl* wmap = ( WorldMapControl* ) GetControl( WindowIndex, ControlIndex, IE_GUI_WORLDMAP);
2629 if (!wmap) {
2630 return NULL;
2633 Color color = {r, g, b, a};
2634 wmap->SetColor( which, color );
2636 Py_INCREF( Py_None );
2637 return Py_None;
2641 PyDoc_STRVAR( GemRB_Window_CreateMapControl__doc,
2642 "CreateMapControl(WindowIndex, ControlID, x, y, w, h, "
2643 "[LabelID, FlagResRef[, Flag2ResRef]])\n\n"
2644 "Creates and adds a new Area Map Control to a Window.\n"
2645 "Note: LabelID is an ID, not an index. "
2646 "If there are two flags given, they will be considered a BMP.");
2648 static PyObject* GemRB_Window_CreateMapControl(PyObject * /*self*/, PyObject* args)
2650 int WindowIndex, ControlID, x, y, w, h;
2651 int LabelID;
2652 char *Flag=NULL;
2653 char *Flag2=NULL;
2655 if (!PyArg_ParseTuple( args, "iiiiiiis|s", &WindowIndex, &ControlID,
2656 &x, &y, &w, &h, &LabelID, &Flag, &Flag2)) {
2657 Flag=NULL;
2658 PyErr_Clear(); //clearing the exception
2659 if (!PyArg_ParseTuple( args, "iiiiii", &WindowIndex, &ControlID,
2660 &x, &y, &w, &h)) {
2661 return AttributeError( GemRB_Window_CreateMapControl__doc );
2664 Window* win = core->GetWindow( WindowIndex );
2665 if (win == NULL) {
2666 return RuntimeError("Cannot find window!");
2668 int CtrlIndex = core->GetControl( WindowIndex, ControlID );
2669 if (CtrlIndex != -1) {
2670 Control *ctrl = win->GetControl( CtrlIndex );
2671 x = ctrl->XPos;
2672 y = ctrl->YPos;
2673 w = ctrl->Width;
2674 h = ctrl->Height;
2675 // do *not* delete the existing control, we want to replace
2676 // it in the sort order!
2677 //win->DelControl( CtrlIndex );
2680 MapControl* map = new MapControl( );
2681 map->XPos = x;
2682 map->YPos = y;
2683 map->Width = w;
2684 map->Height = h;
2685 map->ControlID = ControlID;
2686 map->ControlType = IE_GUI_MAP;
2687 map->Owner = win;
2688 if (Flag2) { //pst flavour
2689 map->convertToGame = false;
2690 CtrlIndex = core->GetControl( WindowIndex, LabelID );
2691 Control *lc = win->GetControl( CtrlIndex );
2692 map->LinkedLabel = lc;
2693 ResourceHolder<ImageMgr> anim(Flag);
2694 if (anim) {
2695 map->Flag[0] = anim->GetSprite2D();
2697 ResourceHolder<ImageMgr> anim2(Flag2);
2698 if (anim2) {
2699 map->Flag[1] = anim2->GetSprite2D();
2701 goto setup_done;
2703 if (Flag) {
2704 CtrlIndex = core->GetControl( WindowIndex, LabelID );
2705 Control *lc = win->GetControl( CtrlIndex );
2706 map->LinkedLabel = lc;
2707 AnimationFactory* af = ( AnimationFactory* )
2708 gamedata->GetFactoryResource( Flag,
2709 IE_BAM_CLASS_ID, IE_NORMAL );
2710 if (af) {
2711 for (int i=0;i<8;i++) {
2712 map->Flag[i] = af->GetFrame(0,i);
2717 setup_done:
2718 win->AddControl( map );
2720 int ret = core->GetControl( WindowIndex, ControlID );
2722 if (ret<0) {
2723 return NULL;
2725 return PyInt_FromLong( ret );
2726 //Py_INCREF( Py_None );
2727 //return Py_None;
2730 PyDoc_STRVAR( GemRB_Control_SetPos__doc,
2731 "SetControlPos(WindowIndex, ControlIndex, X, Y)\n\n"
2732 "Moves a Control." );
2734 static PyObject* GemRB_Control_SetPos(PyObject * /*self*/, PyObject* args)
2736 int WindowIndex, ControlIndex, X, Y;
2738 if (!PyArg_ParseTuple( args, "iiii", &WindowIndex, &ControlIndex, &X, &Y )) {
2739 return AttributeError( GemRB_Control_SetPos__doc );
2742 Control* ctrl = GetControl(WindowIndex, ControlIndex, -1);
2743 if (!ctrl) {
2744 return NULL;
2747 ctrl->XPos = X;
2748 ctrl->YPos = Y;
2750 Py_INCREF( Py_None );
2751 return Py_None;
2754 PyDoc_STRVAR( GemRB_Control_SetSize__doc,
2755 "SetControlSize(WindowIndex, ControlIndex, Width, Height)\n\n"
2756 "Resizes a Control." );
2758 static PyObject* GemRB_Control_SetSize(PyObject * /*self*/, PyObject* args)
2760 int WindowIndex, ControlIndex, Width, Height;
2762 if (!PyArg_ParseTuple( args, "iiii", &WindowIndex, &ControlIndex, &Width,
2763 &Height )) {
2764 return AttributeError( GemRB_Control_SetSize__doc );
2767 Control* ctrl = GetControl(WindowIndex, ControlIndex, -1);
2768 if (!ctrl) {
2769 return NULL;
2772 ctrl->Width = Width;
2773 ctrl->Height = Height;
2775 Py_INCREF( Py_None );
2776 return Py_None;
2779 PyDoc_STRVAR( GemRB_Label_SetUseRGB__doc,
2780 "SetLabelUseRGB(WindowIndex, ControlIndex, status)\n\n"
2781 "Tells a Label to use the RGB colors with the text." );
2783 static PyObject* GemRB_Label_SetUseRGB(PyObject * /*self*/, PyObject* args)
2785 int WindowIndex, ControlIndex, status;
2787 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &status )) {
2788 return AttributeError( GemRB_Label_SetUseRGB__doc );
2791 Label* lab = (Label *) GetControl(WindowIndex, ControlIndex, IE_GUI_LABEL);
2792 if (!lab) {
2793 return NULL;
2796 lab->useRGB = ( status != 0 );
2798 Py_INCREF( Py_None );
2799 return Py_None;
2802 PyDoc_STRVAR( GemRB_GameSetPartySize__doc,
2803 "GameSetPartySize(size)\n\n"
2804 "Sets the maximum party size." );
2806 static PyObject* GemRB_GameSetPartySize(PyObject * /*self*/, PyObject* args)
2808 int Flags;
2810 if (!PyArg_ParseTuple( args, "i", &Flags )) {
2811 return AttributeError( GemRB_GameSetPartySize__doc );
2814 Game *game = core->GetGame();
2815 if (!game) {
2816 return RuntimeError( "No game loaded!" );
2819 game->SetPartySize( Flags );
2821 Py_INCREF( Py_None );
2822 return Py_None;
2825 PyDoc_STRVAR( GemRB_GameSetProtagonistMode__doc,
2826 "GameSetProtagonistMode(PM)\n\n"
2827 "Sets the protagonist mode, 0-no check, 1-protagonist, 2-team." );
2829 static PyObject* GemRB_GameSetProtagonistMode(PyObject * /*self*/, PyObject* args)
2831 int Flags;
2833 if (!PyArg_ParseTuple( args, "i", &Flags )) {
2834 return AttributeError( GemRB_GameSetProtagonistMode__doc );
2837 Game *game = core->GetGame();
2838 if (!game) {
2839 return RuntimeError( "No game loaded!" );
2842 game->SetProtagonistMode( Flags );
2844 Py_INCREF( Py_None );
2845 return Py_None;
2848 PyDoc_STRVAR( GemRB_GameSetExpansion__doc,
2849 "GameSetExpansion(expmode)\n\n"
2850 "Sets the expansion mode, 0-no expansion, 1-expansion." );
2852 static PyObject* GemRB_GameSetExpansion(PyObject * /*self*/, PyObject* args)
2854 int Flags;
2856 if (!PyArg_ParseTuple( args, "i", &Flags )) {
2857 return AttributeError( GemRB_GameSetExpansion__doc );
2860 Game *game = core->GetGame();
2861 if (game) {
2862 game->SetExpansion( Flags );
2865 Py_INCREF( Py_None );
2866 return Py_None;
2869 PyDoc_STRVAR( GemRB_GameSetScreenFlags__doc,
2870 "GameSetScreenFlags(Flags, Operation)\n\n"
2871 "Sets the Display Flags of the main game screen (pane status, dialog textarea size)." );
2873 static PyObject* GemRB_GameSetScreenFlags(PyObject * /*self*/, PyObject* args)
2875 int Flags, Operation;
2877 if (!PyArg_ParseTuple( args, "ii", &Flags, &Operation )) {
2878 return AttributeError( GemRB_GameSetScreenFlags__doc );
2880 if (Operation < BM_SET || Operation > BM_NAND) {
2881 printMessage( "GUIScript",
2882 "Syntax Error: operation must be 0-4\n", LIGHT_RED );
2883 return NULL;
2886 Game *game = core->GetGame();
2887 if (!game) {
2888 return RuntimeError( "No game loaded!" );
2891 game->SetControlStatus( Flags, Operation );
2893 Py_INCREF( Py_None );
2894 return Py_None;
2897 PyDoc_STRVAR( GemRB_GameControlSetScreenFlags__doc,
2898 "GameControlSetScreenFlags(Flags, Operation)\n\n"
2899 "Sets the Display Flags of the main game screen control (centeronactor,...)." );
2901 static PyObject* GemRB_GameControlSetScreenFlags(PyObject * /*self*/, PyObject* args)
2903 int Flags, Operation;
2905 if (!PyArg_ParseTuple( args, "ii", &Flags, &Operation )) {
2906 return AttributeError( GemRB_GameControlSetScreenFlags__doc );
2908 if (Operation < BM_SET || Operation > BM_NAND) {
2909 printMessage( "GUIScript",
2910 "Syntax Error: operation must be 0-4\n", LIGHT_RED );
2911 return NULL;
2914 GameControl *gc = core->GetGameControl();
2915 if (!gc) {
2916 printMessage ("GUIScript", "Flag cannot be set!\n",LIGHT_RED);
2917 return NULL;
2920 gc->SetScreenFlags( Flags, Operation );
2922 Py_INCREF( Py_None );
2923 return Py_None;
2927 PyDoc_STRVAR( GemRB_GameControlSetTargetMode__doc,
2928 "GameControlSetTargetMode(Mode, Types)\n\n"
2929 "Sets the targetting mode of the main game screen control (attack, cast spell,...) and type of target (ally, enemy and/or neutral; all by default)" );
2931 static PyObject* GemRB_GameControlSetTargetMode(PyObject * /*self*/, PyObject* args)
2933 int Mode;
2934 int Types = GA_SELECT | GA_NO_DEAD | GA_NO_HIDDEN;
2936 if (!PyArg_ParseTuple( args, "i|i", &Mode, &Types )) {
2937 return AttributeError( GemRB_GameControlSetTargetMode__doc );
2940 GameControl *gc = core->GetGameControl();
2941 if (!gc) {
2942 return RuntimeError("Can't find GameControl!");
2945 //target mode is only the low bits (which is a number)
2946 gc->target_mode = Mode&GA_ACTION;
2947 //target type is all the bits
2948 gc->target_types = (Mode&GA_ACTION)|Types;
2950 Py_INCREF( Py_None );
2951 return Py_None;
2954 PyDoc_STRVAR( GemRB_GameControlGetTargetMode__doc,
2955 "GameControlGetTargetMode() => Mode\n\n"
2956 "Returns the targetting mode of the main game screen control (attack, cast spell,...)." );
2958 static PyObject* GemRB_GameControlGetTargetMode(PyObject * /*self*/, PyObject* /*args*/)
2960 GameControl *gc = core->GetGameControl();
2961 if (!gc) {
2962 return RuntimeError("Can't find GameControl!");
2965 return PyInt_FromLong(gc->target_mode);
2968 PyDoc_STRVAR( GemRB_Button_SetFlags__doc,
2969 "SetButtonFlags(WindowIndex, ControlIndex, Flags, Operation)\n\n"
2970 "Sets the Display Flags of a Button." );
2972 static PyObject* GemRB_Button_SetFlags(PyObject * /*self*/, PyObject* args)
2974 int WindowIndex, ControlIndex, Flags, Operation;
2976 if (!PyArg_ParseTuple( args, "iiii", &WindowIndex, &ControlIndex, &Flags, &Operation )) {
2977 return AttributeError( GemRB_Button_SetFlags__doc );
2979 if (Operation < BM_SET || Operation > BM_NAND) {
2980 printMessage( "GUIScript",
2981 "Syntax Error: operation must be 0-4\n", LIGHT_RED );
2982 return NULL;
2985 Control* btn = ( Control* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
2986 if (!btn) {
2987 return NULL;
2990 if (btn->SetFlags( Flags, Operation ) ) {
2991 printMessage ("GUIScript", "Flag cannot be set!\n",LIGHT_RED);
2992 return NULL;
2995 Py_INCREF( Py_None );
2996 return Py_None;
2999 PyDoc_STRVAR( GemRB_Control_TextArea_SetFlags__doc,
3000 "SetTextAreaFlags(WindowIndex, ControlIndex, Flags, Operation)\n\n"
3001 "Sets the Display Flags of a TextArea. Flags are: IE_GUI_TA_SELECTABLE, IE_GUI_TA_AUTOSCROLL, IE_GUI_TA_SMOOTHSCROLL. Operation defaults to OP_SET." );
3003 static PyObject* GemRB_Control_TextArea_SetFlags(PyObject * /*self*/, PyObject* args)
3005 int WindowIndex, ControlIndex, Flags;
3006 int Operation=0;
3008 if (!PyArg_ParseTuple( args, "iii|i", &WindowIndex, &ControlIndex, &Flags, &Operation )) {
3009 return AttributeError( GemRB_Control_TextArea_SetFlags__doc );
3011 if (Operation < BM_SET || Operation > BM_NAND) {
3012 printMessage( "GUIScript",
3013 "Syntax Error: operation must be 0-4\n", LIGHT_RED );
3014 return NULL;
3017 Control* ta = ( Control* ) GetControl(WindowIndex, ControlIndex, IE_GUI_TEXTAREA);
3018 if (!ta) {
3019 return NULL;
3022 if (ta->SetFlags( Flags, Operation )) {
3023 printMessage ("GUIScript", "Flag cannot be set!\n",LIGHT_RED);
3024 return NULL;
3027 Py_INCREF( Py_None );
3028 return Py_None;
3031 PyDoc_STRVAR( GemRB_ScrollBar_SetDefaultScrollBar__doc,
3032 "SetDefaultScrollBar(WindowIndex, ControlIndex)\n\n"
3033 "Sets the ScrollBar control as default." );
3035 static PyObject* GemRB_ScrollBar_SetDefaultScrollBar(PyObject * /*self*/, PyObject* args)
3037 int WindowIndex, ControlIndex;
3039 if (!PyArg_ParseTuple( args, "ii", &WindowIndex, &ControlIndex)) {
3040 return AttributeError( GemRB_ScrollBar_SetDefaultScrollBar__doc );
3043 Control* sb = ( Control* ) GetControl(WindowIndex, ControlIndex, IE_GUI_SCROLLBAR);
3044 if (!sb) {
3045 return NULL;
3048 sb->SetFlags( (IE_GUI_SCROLLBAR<<24) | IE_GUI_SCROLLBAR_DEFAULT, BM_OR );
3050 Py_INCREF( Py_None );
3051 return Py_None;
3054 PyDoc_STRVAR( GemRB_Button_SetState__doc,
3055 "SetButtonState(WindowIndex, ControlIndex, State)\n\n"
3056 "Sets the state of a Button Control." );
3058 static PyObject* GemRB_Button_SetState(PyObject * /*self*/, PyObject* args)
3060 int WindowIndex, ControlIndex, state;
3062 if (!PyArg_ParseTuple( args, "iii", &WindowIndex, &ControlIndex, &state )) {
3063 return AttributeError( GemRB_Button_SetState__doc );
3066 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
3067 if (!btn) {
3068 return NULL;
3071 btn->SetState( state );
3073 Py_INCREF( Py_None );
3074 return Py_None;
3077 PyDoc_STRVAR( GemRB_Button_SetPictureClipping__doc,
3078 "SetButtonPictureClipping(Window, Button, ClippingPercent)\n\n"
3079 "Sets percent (0-1.0) of width to which button picture will be clipped." );
3081 static PyObject* GemRB_Button_SetPictureClipping(PyObject * /*self*/, PyObject* args)
3083 int WindowIndex, ControlIndex;
3084 double Clipping;
3086 if (!PyArg_ParseTuple( args, "iid", &WindowIndex, &ControlIndex, &Clipping )) {
3087 return AttributeError( GemRB_Button_SetPictureClipping__doc );
3090 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
3091 if (!btn) {
3092 return NULL;
3095 if (Clipping<0.0) Clipping = 0.0;
3096 else if (Clipping>1.0) Clipping = 1.0;
3097 btn->SetPictureClipping( Clipping );
3099 Py_INCREF( Py_None );
3100 return Py_None;
3103 PyDoc_STRVAR( GemRB_Button_SetPicture__doc,
3104 "SetButtonPicture(WindowIndex, ControlIndex, PictureResRef, DefaultResRef)\n\n"
3105 "Sets the Picture of a Button Control from a BMP file. You can also supply a default picture." );
3107 static PyObject* GemRB_Button_SetPicture(PyObject * /*self*/, PyObject* args)
3109 int WindowIndex, ControlIndex;
3110 char *ResRef;
3111 char *DefResRef = NULL;
3113 if (!PyArg_ParseTuple( args, "iis|s", &WindowIndex, &ControlIndex, &ResRef, &DefResRef )) {
3114 return AttributeError( GemRB_Button_SetPicture__doc );
3117 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
3118 if (!btn) {
3119 return NULL;
3122 if (ResRef[0] == 0) {
3123 btn->SetPicture( NULL );
3124 Py_INCREF( Py_None );
3125 return Py_None;
3128 ImageFactory* fact = ( ImageFactory* )
3129 gamedata->GetFactoryResource( ResRef, IE_BMP_CLASS_ID, IE_NORMAL );
3131 //if the resource doesn't exist, but we have a default resource
3132 //use this resource
3133 if (!fact && DefResRef) {
3134 fact = ( ImageFactory* )
3135 gamedata->GetFactoryResource( DefResRef, IE_BMP_CLASS_ID, IE_NORMAL );
3138 if (!fact) {
3139 return NULL;
3142 Sprite2D* Picture = fact->GetSprite2D();
3143 if (Picture == NULL) {
3144 return NULL;
3147 btn->SetPicture( Picture );
3149 Py_INCREF( Py_None );
3150 return Py_None;
3153 PyDoc_STRVAR( GemRB_Button_SetSprite2D__doc,
3154 "Button.SetSprite2D(WindowIndex, ControlIndex, Sprite2D)\n\n"
3155 "Sets a Sprite2D onto a button as picture." );
3157 static PyObject* GemRB_Button_SetSprite2D(PyObject * /*self*/, PyObject* args)
3159 int wi, ci;
3160 PyObject *obj;
3162 if (!PyArg_ParseTuple( args, "iiO", &wi, &ci, &obj )) {
3163 return AttributeError( GemRB_Button_SetSprite2D__doc );
3165 Button* btn = ( Button* ) GetControl( wi, ci, IE_GUI_BUTTON);
3166 if (!btn) {
3167 return NULL;
3170 CObject<Sprite2D> spr(obj);
3172 if (spr)
3173 spr->acquire();
3174 btn->SetPicture( spr.get() );
3176 Py_INCREF( Py_None );
3177 return Py_None;
3180 PyDoc_STRVAR( GemRB_Button_SetMOS__doc,
3181 "SetButtonMOS(WindowIndex, ControlIndex, MOSResRef)\n\n"
3182 "Sets the Picture of a Button Control from a MOS file." );
3184 static PyObject* GemRB_Button_SetMOS(PyObject * /*self*/, PyObject* args)
3186 int WindowIndex, ControlIndex;
3187 char *ResRef;
3189 if (!PyArg_ParseTuple( args, "iis", &WindowIndex, &ControlIndex, &ResRef )) {
3190 return AttributeError( GemRB_Button_SetMOS__doc );
3193 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
3194 if (!btn) {
3195 return NULL;
3198 if (ResRef[0] == 0) {
3199 btn->SetPicture( NULL );
3200 Py_INCREF( Py_None );
3201 return Py_None;
3204 ResourceHolder<ImageMgr> im(ResRef);
3205 if (im == NULL) {
3206 return NULL;
3209 Sprite2D* Picture = im->GetSprite2D();
3210 if (Picture == NULL) {
3211 return NULL;
3214 btn->SetPicture( Picture );
3216 Py_INCREF( Py_None );
3217 return Py_None;
3220 PyDoc_STRVAR( GemRB_Button_SetPLT__doc,
3221 "SetButtonPLT(WindowIndex, ControlIndex, PLTResRef, col1, col2, col3, col4, col5, col6, col7, col8, type)\n\n"
3222 "Sets the Picture of a Button Control from a PLT file." );
3224 static PyObject* GemRB_Button_SetPLT(PyObject * /*self*/, PyObject* args)
3226 int WindowIndex, ControlIndex;
3227 ieDword col[8];
3228 int type = 0;
3229 char *ResRef;
3231 memset(col,-1,sizeof(col));
3232 if (!PyArg_ParseTuple( args, "iisiiiiiiii|i", &WindowIndex, &ControlIndex,
3233 &ResRef, &(col[0]), &(col[1]), &(col[2]), &(col[3]),
3234 &(col[4]), &(col[5]), &(col[6]), &(col[7]), &type) ) {
3235 return AttributeError( GemRB_Button_SetPLT__doc );
3238 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
3239 if (!btn) {
3240 return NULL;
3243 //empty image
3244 if (ResRef[0] == 0 || ResRef[0]=='*') {
3245 btn->SetPicture( NULL );
3246 Py_INCREF( Py_None );
3247 return Py_None;
3250 Sprite2D *Picture;
3251 Sprite2D *Picture2=NULL;
3253 ResourceHolder<PalettedImageMgr> im(ResRef);
3255 if (im == NULL ) {
3256 AnimationFactory* af = ( AnimationFactory* )
3257 gamedata->GetFactoryResource( ResRef,
3258 IE_BAM_CLASS_ID, IE_NORMAL );
3259 if (!af) {
3260 printMessage("GUISCript","PLT/BAM not found for ref: ",YELLOW);
3261 printf("%s\n", ResRef);
3262 textcolor(WHITE);
3263 if (type == 0)
3264 return NULL;
3265 else {
3266 Py_INCREF( Py_None );
3267 return Py_None;
3271 Picture = af->GetPaperdollImage(col[0]==0xFFFFFFFF?0:col, Picture2,(unsigned int)type);
3272 if (Picture == NULL) {
3273 printf ("Picture == NULL\n");
3274 return NULL;
3276 } else {
3277 Picture = im->GetSprite2D(type, col);
3278 if (Picture == NULL) {
3279 printf ("Picture == NULL\n");
3280 return NULL;
3284 if (type == 0)
3285 btn->ClearPictureList();
3286 btn->StackPicture(Picture);
3287 if (Picture2) {
3288 btn->SetFlags ( IE_GUI_BUTTON_BG1_PAPERDOLL, BM_OR );
3289 btn->StackPicture( Picture2 );
3290 } else if (type == 0) {
3291 btn->SetFlags ( ~IE_GUI_BUTTON_BG1_PAPERDOLL, BM_AND );
3294 Py_INCREF( Py_None );
3295 return Py_None;
3298 PyDoc_STRVAR( GemRB_Button_SetBAM__doc,
3299 "SetButtonBAM(WindowIndex, ControlIndex, BAMResRef, CycleIndex, FrameIndex, col1)\n\n"
3300 "Sets the Picture of a Button Control from a BAM file. If col1 is >= 0, changes palette picture's palette to one specified by col1. Since it uses 12 colors palette, it has issues in PST." );
3302 static PyObject* SetButtonBAM(int wi, int ci, const char *ResRef, int CycleIndex, int FrameIndex, int col1)
3304 Button* btn = ( Button* ) GetControl(wi, ci, IE_GUI_BUTTON);
3305 if (!btn) {
3306 return NULL;
3309 if (ResRef[0] == 0) {
3310 btn->SetPicture( NULL );
3311 //no incref! (happens in caller if necessary)
3312 return Py_None;
3315 AnimationFactory* af = ( AnimationFactory* )
3316 gamedata->GetFactoryResource( ResRef,
3317 IE_BAM_CLASS_ID, IE_NORMAL );
3318 if (!af)
3319 return NULL;
3320 Sprite2D* Picture = af->GetFrame ( FrameIndex, CycleIndex );
3322 if (Picture == NULL) {
3323 return NULL;
3326 if (col1 >= 0) {
3327 Sprite2D* old = Picture;
3328 Picture = core->GetVideoDriver()->DuplicateSprite(old);
3329 core->GetVideoDriver()->FreeSprite(old);
3331 Palette* newpal = Picture->GetPalette()->Copy();
3332 core->GetPalette( col1, 12, &newpal->col[4]);
3333 Picture->SetPalette( newpal );
3334 newpal->Release();
3337 btn->SetPicture( Picture );
3339 //no incref! (happens in caller if necessary)
3340 return Py_None;
3343 static PyObject* GemRB_Button_SetBAM(PyObject * /*self*/, PyObject* args)
3345 int wi, ci, CycleIndex, FrameIndex, col1 = -1;
3346 char *ResRef;
3348 if (!PyArg_ParseTuple( args, "iisii|i", &wi, &ci,
3349 &ResRef, &CycleIndex, &FrameIndex, &col1 )) {
3350 return AttributeError( GemRB_Button_SetBAM__doc );
3353 PyObject *ret = SetButtonBAM(wi,ci, ResRef, CycleIndex, FrameIndex,col1);
3354 if (ret) {
3355 Py_INCREF(ret);
3357 return ret;
3360 PyDoc_STRVAR( GemRB_Control_SetAnimationPalette__doc,
3361 "SetAnimationPalette(WindowIndex, ControlIndex, col1, col2, col3, col4, col5, col6, col7, col8)\n\n"
3362 "Sets the palette of an animation already assigned to the button.");
3364 static PyObject* GemRB_Control_SetAnimationPalette(PyObject * /*self*/, PyObject* args)
3366 int wi, ci;
3367 ieDword col[8];
3369 memset(col,-1,sizeof(col));
3370 if (!PyArg_ParseTuple( args, "iiiiiiiiii", &wi, &ci,
3371 &(col[0]), &(col[1]), &(col[2]), &(col[3]),
3372 &(col[4]), &(col[5]), &(col[6]), &(col[7])) ) {
3373 return AttributeError( GemRB_Control_SetAnimationPalette__doc );
3376 Control* ctl = GetControl(wi, ci, -1);
3377 if (!ctl) {
3378 return NULL;
3381 ControlAnimation* anim = ctl->animation;
3382 if (!anim) {
3383 return RuntimeError("No animation!");
3386 anim->SetPaletteGradients(col);
3387 Py_INCREF( Py_None );
3388 return Py_None;
3391 PyDoc_STRVAR( GemRB_Control_SetAnimation__doc,
3392 "SetAnimation(WindowIndex, ControlIndex, BAMResRef[, Cycle])\n\n"
3393 "Sets the animation of a Control (usually a Button) from a BAM file. Optionally an animation cycle could be set too.");
3395 static PyObject* GemRB_Control_SetAnimation(PyObject * /*self*/, PyObject* args)
3397 int wi, ci;
3398 char *ResRef;
3399 int Cycle = 0;
3401 if (!PyArg_ParseTuple( args, "iis|i", &wi, &ci, &ResRef, &Cycle )) {
3402 return AttributeError( GemRB_Control_SetAnimation__doc );
3405 Control* ctl = GetControl(wi, ci, -1);
3406 if (!ctl) {
3407 return NULL;
3410 //who knows, there might have been an active animation lurking
3411 if (ctl->animation) {
3412 //if this control says the resource is the same
3413 //we wanted to set, we don't reset it
3414 if(ctl->animation->SameResource(ResRef, Cycle)) {
3415 Py_INCREF( Py_None );
3416 return Py_None;
3418 delete ctl->animation;
3419 ctl->animation = NULL;
3422 if (ResRef[0] == 0) {
3423 ctl->SetAnimPicture( NULL );
3424 Py_INCREF( Py_None );
3425 return Py_None;
3428 ControlAnimation* anim = new ControlAnimation( ctl, ResRef, Cycle );
3430 anim->UpdateAnimation();
3432 Py_INCREF( Py_None );
3433 return Py_None;
3437 PyDoc_STRVAR( GemRB_PlaySound__doc,
3438 "PlaySound(SoundResource, xpos, ypos, type)\n\n"
3439 "Plays a Sound." );
3441 static PyObject* GemRB_PlaySound(PyObject * /*self*/, PyObject* args)
3443 char *ResRef;
3444 int xpos = 0;
3445 int ypos = 0;
3446 unsigned int flags = 1; //GEM_SND_RELATIVE
3448 if (!PyArg_ParseTuple( args, "z|iii", &ResRef, &xpos, &ypos, &flags )) {
3449 return AttributeError( GemRB_PlaySound__doc );
3452 core->GetAudioDrv()->Play( ResRef, xpos, ypos, flags );
3454 Py_INCREF( Py_None );
3455 return Py_None;
3458 PyDoc_STRVAR( GemRB_DrawWindows__doc,
3459 "DrawWindows()\n\n"
3460 "Refreshes the User Interface." );
3462 static PyObject* GemRB_DrawWindows(PyObject * /*self*/, PyObject * /*args*/)
3464 core->DrawWindows();
3466 Py_INCREF( Py_None );
3467 return Py_None;
3470 PyDoc_STRVAR( GemRB_Quit__doc,
3471 "Quit()\n\n"
3472 "Quits GemRB." );
3474 static PyObject* GemRB_Quit(PyObject * /*self*/, PyObject * /*args*/)
3476 bool ret = core->Quit();
3477 if (!ret) {
3478 return NULL;
3481 Py_INCREF( Py_None );
3482 return Py_None;
3485 PyDoc_STRVAR( GemRB_LoadMusicPL__doc,
3486 "LoadMusicPL(MusicPlayListResource, HardEnd)\n\n"
3487 "Loads and starts a Music PlayList." );
3489 static PyObject* GemRB_LoadMusicPL(PyObject * /*self*/, PyObject* args)
3491 char *ResRef;
3492 int HardEnd = 0;
3494 if (!PyArg_ParseTuple( args, "s|i", &ResRef, &HardEnd )) {
3495 return AttributeError( GemRB_LoadMusicPL__doc );
3498 core->GetMusicMgr()->SwitchPlayList( ResRef, (bool) HardEnd );
3500 Py_INCREF( Py_None );
3501 return Py_None;
3504 PyDoc_STRVAR( GemRB_SoftEndPL__doc,
3505 "SoftEndPL()\n\n"
3506 "Ends a Music Playlist softly." );
3508 static PyObject* GemRB_SoftEndPL(PyObject * /*self*/, PyObject * /*args*/)
3510 core->GetMusicMgr()->End();
3512 Py_INCREF( Py_None );
3513 return Py_None;
3516 PyDoc_STRVAR( GemRB_HardEndPL__doc,
3517 "HardEndPL()\n\n"
3518 "Ends a Music Playlist immediately." );
3520 static PyObject* GemRB_HardEndPL(PyObject * /*self*/, PyObject * /*args*/)
3522 core->GetMusicMgr()->HardEnd();
3524 Py_INCREF( Py_None );
3525 return Py_None;
3528 PyDoc_STRVAR( GemRB_SetToken__doc,
3529 "SetToken(VariableName, Value)\n\n"
3530 "Set/Create a token to be replaced in StrRefs." );
3532 static PyObject* GemRB_SetToken(PyObject * /*self*/, PyObject* args)
3534 char *Variable;
3535 char *value;
3537 if (!PyArg_ParseTuple( args, "ss", &Variable, &value )) {
3538 return AttributeError( GemRB_SetToken__doc );
3540 core->GetTokenDictionary()->SetAtCopy( Variable, value );
3542 Py_INCREF( Py_None );
3543 return Py_None;
3546 PyDoc_STRVAR( GemRB_SetVar__doc,
3547 "SetVar(VariableName, Value)\n\n"
3548 "Set/Create a Variable in the Global Dictionary." );
3550 static PyObject* GemRB_SetVar(PyObject * /*self*/, PyObject* args)
3552 char *Variable;
3553 //this should be 32 bits, always, but i cannot tell that to Python
3554 unsigned long value;
3556 if (!PyArg_ParseTuple( args, "sl", &Variable, &value )) {
3557 return AttributeError( GemRB_SetVar__doc );
3560 core->GetDictionary()->SetAt( Variable, (ieDword) value );
3562 Py_INCREF( Py_None );
3563 return Py_None;
3566 PyDoc_STRVAR( GemRB_GetMessageWindowSize__doc,
3567 "GetMessageWindowSize() => int\n\n"
3568 "Returns current MessageWindowSize, it works only when a game is loaded." );
3570 static PyObject* GemRB_GetMessageWindowSize(PyObject * /*self*/, PyObject* /*args*/)
3572 Game *game = core->GetGame();
3573 if (!game) {
3574 return RuntimeError( "No game loaded!" );
3576 return PyInt_FromLong( game->ControlStatus );
3579 PyDoc_STRVAR( GemRB_GetToken__doc,
3580 "GetToken(VariableName) => string\n\n"
3581 "Get a Variable value from the Token Dictionary." );
3583 static PyObject* GemRB_GetToken(PyObject * /*self*/, PyObject* args)
3585 const char *Variable;
3586 char *value;
3588 if (!PyArg_ParseTuple( args, "s", &Variable )) {
3589 return AttributeError( GemRB_GetToken__doc );
3592 //returns only the pointer
3593 if (!core->GetTokenDictionary()->Lookup( Variable, value )) {
3594 return PyString_FromString( "" );
3597 return PyString_FromString( value );
3600 PyDoc_STRVAR( GemRB_GetVar__doc,
3601 "GetVar(VariableName) => int\n\n"
3602 "Get a Variable value from the Global Dictionary." );
3604 static PyObject* GemRB_GetVar(PyObject * /*self*/, PyObject* args)
3606 const char *Variable;
3607 ieDword value;
3609 if (!PyArg_ParseTuple( args, "s", &Variable )) {
3610 return AttributeError( GemRB_GetVar__doc );
3613 if (!core->GetDictionary()->Lookup( Variable, value )) {
3614 return PyInt_FromLong( 0 );
3617 // A PyInt is internally (probably) a long. Since we sometimes set
3618 // variables to -1, cast value to a signed integer first, so it is
3619 // sign-extended into a long if long is larger than int.
3620 return PyInt_FromLong( (int)value );
3623 PyDoc_STRVAR( GemRB_CheckVar__doc,
3624 "CheckVar(VariableName, Context) => long\n\n"
3625 "Return (and output on terminal) the value of a Game Variable." );
3627 static PyObject* GemRB_CheckVar(PyObject * /*self*/, PyObject* args)
3629 char *Variable;
3630 char *Context;
3632 if (!PyArg_ParseTuple( args, "ss", &Variable, &Context )) {
3633 return AttributeError( GemRB_CheckVar__doc );
3635 GameControl *gc = core->GetGameControl();
3636 if (!gc) {
3637 return RuntimeError("Can't find GameControl!");
3639 Scriptable *Sender = (Scriptable *) gc->GetLastActor();
3640 if (!Sender) {
3641 Sender = (Scriptable *) core->GetGame()->GetCurrentArea();
3643 if (!Sender) {
3644 printMessage("GUIScript","No Game!\n", LIGHT_RED);
3645 return NULL;
3647 long value =(long) CheckVariable(Sender, Variable, Context);
3648 printMessage("GUISCript"," ",YELLOW);
3649 printf("%s %s=%ld\n",Context, Variable, value);
3650 textcolor(WHITE);
3651 return PyInt_FromLong( value );
3654 PyDoc_STRVAR( GemRB_SetGlobal__doc,
3655 "SetGlobal(VariableName, Context, Value)\n\n"
3656 "Sets a gamescript variable to the specificed numeric value." );
3658 static PyObject* GemRB_SetGlobal(PyObject * /*self*/, PyObject* args)
3660 char *Variable;
3661 char *Context;
3662 int Value;
3664 if (!PyArg_ParseTuple( args, "ssi", &Variable, &Context, &Value )) {
3665 return AttributeError( GemRB_SetGlobal__doc );
3668 Scriptable *Sender = NULL;
3669 Game *game = core->GetGame();
3670 if (!game) {
3671 printMessage("GUIScript","No Game!\n", LIGHT_RED);
3672 return NULL;
3674 if (!strnicmp(Context, "MYAREA", 6) || !strnicmp(Context, "LOCALS", 6)) {
3675 GameControl *gc = core->GetGameControl();
3676 if (!gc) {
3677 return RuntimeError("Can't find GameControl!");
3679 Sender = (Scriptable *) gc->GetLastActor();
3680 if (!Sender) {
3681 Sender = (Scriptable *) game->GetCurrentArea();
3683 if (!Sender) {
3684 printMessage("GUIScript","No Sender!\n", LIGHT_RED);
3685 return NULL;
3687 } // else GLOBAL, area name or KAPUTZ
3689 SetVariable(Sender, Variable, Context, (ieDword) Value);
3690 Py_INCREF( Py_None );
3691 return Py_None;
3694 PyDoc_STRVAR( GemRB_GetGameVar__doc,
3695 "GetGameVar(VariableName) => long\n\n"
3696 "Get a Variable value from the Game Global Dictionary." );
3698 static PyObject* GemRB_GetGameVar(PyObject * /*self*/, PyObject* args)
3700 const char *Variable;
3701 ieDword value;
3703 if (!PyArg_ParseTuple( args, "s", &Variable )) {
3704 return AttributeError( GemRB_GetGameVar__doc );
3707 if (!core->GetGame()->locals->Lookup( Variable, value )) {
3708 return PyInt_FromLong( ( unsigned long ) 0 );
3711 return PyInt_FromLong( (unsigned long) value );
3714 PyDoc_STRVAR( GemRB_PlayMovie__doc,
3715 "PlayMovie(MOVResRef[, flag]) => int\n\n"
3716 "Plays the movie named. If flag is set to 1, it won't play it if it was already played once (set in .ini). It returns 0 if it played the movie." );
3718 static PyObject* GemRB_PlayMovie(PyObject * /*self*/, PyObject* args)
3720 const char *string;
3721 int flag = 0;
3723 if (!PyArg_ParseTuple( args, "s|i", &string, &flag )) {
3724 return AttributeError( GemRB_PlayMovie__doc );
3727 ieDword ind = 0;
3729 //Lookup will leave the flag untouched if it doesn't exist yet
3730 core->GetDictionary()->Lookup(string, ind);
3731 if (flag)
3732 ind = 0;
3733 if (!ind) {
3734 ind = core->PlayMovie( string );
3736 //don't return NULL
3737 return PyInt_FromLong( ind );
3740 PyDoc_STRVAR( GemRB_SaveCharacter__doc,
3741 "SaveCharacter(PartyID, CharName)\n\n"
3742 "Exports the character from party.");
3744 static PyObject* GemRB_SaveCharacter(PyObject * /*self*/, PyObject * args)
3746 int PartyID;
3747 const char *name;
3749 if (!PyArg_ParseTuple( args, "is", &PartyID, &name )) {
3750 return AttributeError( GemRB_SaveCharacter__doc );
3752 if (!name[0]) {
3753 return AttributeError( GemRB_SaveCharacter__doc );
3756 Game *game = core->GetGame();
3757 if (!game) {
3758 return RuntimeError( "No game loaded!" );
3760 Actor *actor = game->FindPC(PartyID);
3761 if (!actor) {
3762 return RuntimeError( "Actor not found" );
3764 return PyInt_FromLong(core->WriteCharacter(name, actor) );
3767 PyDoc_STRVAR( GemRB_SaveGame__doc,
3768 "SaveGame(SlotCount, GameName[,version])\n\n"
3769 "Dumps the save game, if version is given, it will save a specific version.");
3771 static PyObject* GemRB_SaveGame(PyObject * /*self*/, PyObject * args)
3773 PyObject *obj;
3774 int Version = -1;
3775 const char *folder;
3777 if (!PyArg_ParseTuple( args, "Os|i", &obj, &folder, &Version )) {
3778 return AttributeError( GemRB_SaveGame__doc );
3781 CObject<SaveGame> save(obj);
3783 Game *game = core->GetGame();
3784 if (!game) {
3785 return RuntimeError( "No game loaded!" );
3788 SaveGameIterator *sgi = core->GetSaveGameIterator();
3789 if (!sgi) {
3790 return RuntimeError("No savegame iterator");
3793 if (Version>0) {
3794 game->version = Version;
3796 return PyInt_FromLong(sgi->CreateSaveGame(save.get(), folder) );
3799 PyDoc_STRVAR( GemRB_GetSaveGames__doc,
3800 "GetSaveGameCount() => int\n\n"
3801 "Returns the list of saved games." );
3803 static PyObject* GemRB_GetSaveGames(PyObject * /*self*/, PyObject * /*args*/)
3805 return MakePyList<SaveGame>(core->GetSaveGameIterator()->GetSaveGames());
3808 PyDoc_STRVAR( GemRB_DeleteSaveGame__doc,
3809 "DeleteSaveGame(Slot)\n\n"
3810 "Deletes a saved game folder completely." );
3812 static PyObject* GemRB_DeleteSaveGame(PyObject * /*self*/, PyObject* args)
3814 PyObject *Slot;
3816 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3817 return AttributeError( GemRB_DeleteSaveGame__doc );
3820 CObject<SaveGame> game(Slot);
3821 core->GetSaveGameIterator()->DeleteSaveGame( game.get() );
3822 Py_INCREF( Py_None );
3823 return Py_None;
3826 PyDoc_STRVAR( GemRB_SaveGame_GetName__doc,
3827 "SaveGame.GetName() => string/int\n\n"
3828 "Returns name of the saved game." );
3830 static PyObject* GemRB_SaveGame_GetName(PyObject * /*self*/, PyObject* args)
3832 PyObject* Slot;
3834 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3835 return AttributeError( GemRB_SaveGame_GetName__doc );
3838 CObject<SaveGame> save(Slot);
3839 return PyString_FromString(save->GetName());
3842 PyDoc_STRVAR( GemRB_SaveGame_GetDate__doc,
3843 "SaveGame.GetDate() => string/int\n\n"
3844 "Returns date of the saved game." );
3846 static PyObject* GemRB_SaveGame_GetDate(PyObject * /*self*/, PyObject* args)
3848 PyObject* Slot;
3850 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3851 return AttributeError( GemRB_SaveGame_GetDate__doc );
3854 CObject<SaveGame> save(Slot);
3855 return PyString_FromString(save->GetDate());
3858 PyDoc_STRVAR( GemRB_SaveGame_GetGameDate__doc,
3859 "SaveGame.GetGameDate() => string/int\n\n"
3860 "Returns game date of the saved game." );
3862 static PyObject* GemRB_SaveGame_GetGameDate(PyObject * /*self*/, PyObject* args)
3864 PyObject* Slot;
3866 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3867 return AttributeError( GemRB_SaveGame_GetGameDate__doc );
3870 CObject<SaveGame> save(Slot);
3871 return PyString_FromString(save->GetGameDate());
3874 PyDoc_STRVAR( GemRB_SaveGame_GetSaveID__doc,
3875 "SaveGame.GetSaveID() => string/int\n\n"
3876 "Returns ID of the saved game." );
3878 static PyObject* GemRB_SaveGame_GetSaveID(PyObject * /*self*/, PyObject* args)
3880 PyObject* Slot;
3882 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3883 return AttributeError( GemRB_SaveGame_GetSaveID__doc );
3886 CObject<SaveGame> save(Slot);
3887 return PyInt_FromLong(save->GetSaveID());
3890 PyDoc_STRVAR( GemRB_SaveGame_GetPreview__doc,
3891 "SaveGame.GetPreview() => string/int\n\n"
3892 "Returns preview of the saved game." );
3894 static PyObject* GemRB_SaveGame_GetPreview(PyObject * /*self*/, PyObject* args)
3896 PyObject* Slot;
3898 if (!PyArg_ParseTuple( args, "O", &Slot )) {
3899 return AttributeError( GemRB_SaveGame_GetPreview__doc );
3902 CObject<SaveGame> save(Slot);
3903 return CObject<Sprite2D>(save->GetPreview());
3906 PyDoc_STRVAR( GemRB_SaveGame_GetPortrait__doc,
3907 "SaveGame.GetPortrait(int index) => string/int\n\n"
3908 "Returns portrait of the saved game." );
3910 static PyObject* GemRB_SaveGame_GetPortrait(PyObject * /*self*/, PyObject* args)
3912 PyObject* Slot;
3913 int index;
3915 if (!PyArg_ParseTuple( args, "Oi", &Slot, &index )) {
3916 return AttributeError( GemRB_SaveGame_GetPortrait__doc );
3919 CObject<SaveGame> save(Slot);
3920 return CObject<Sprite2D>(save->GetPortrait(index));
3923 PyDoc_STRVAR( GemRB_GetGamePreview__doc,
3924 "GetGamePreview()\n\n"
3925 "Gets current game area preview." );
3927 static PyObject* GemRB_GetGamePreview(PyObject * /*self*/, PyObject* args)
3929 if (!PyArg_ParseTuple( args, "" )) {
3930 return AttributeError( GemRB_GetGamePreview__doc );
3933 return CObject<Sprite2D>(core->GetGameControl()->GetPreview());
3936 PyDoc_STRVAR( GemRB_GetGamePortraitPreview__doc,
3937 "GetGamePortraitPreview(PCSlotCount)\n\n"
3938 "Gets a current game PC portrait." );
3940 static PyObject* GemRB_GetGamePortraitPreview(PyObject * /*self*/, PyObject* args)
3942 int PCSlotCount;
3944 if (!PyArg_ParseTuple( args, "i", &PCSlotCount )) {
3945 return AttributeError( GemRB_GetGamePreview__doc );
3948 return CObject<Sprite2D>(core->GetGameControl()->GetPortraitPreview(PCSlotCount));
3951 PyDoc_STRVAR( GemRB_Roll__doc,
3952 "Roll(Dice, Size, Add) => int\n\n"
3953 "Calls traditional dice roll." );
3955 static PyObject* GemRB_Roll(PyObject * /*self*/, PyObject* args)
3957 int Dice, Size, Add;
3959 if (!PyArg_ParseTuple( args, "iii", &Dice, &Size, &Add )) {
3960 return AttributeError( GemRB_Roll__doc );
3962 return PyInt_FromLong( core->Roll( Dice, Size, Add ) );
3965 PyDoc_STRVAR( GemRB_TextArea_GetPortraits__doc,
3966 "GetPortraits(WindowIndex, ControlIndex, SmallOrLarge) => int\n\n"
3967 "Reads in the contents of the portraits subfolder." );
3969 static PyObject* GemRB_TextArea_GetPortraits(PyObject * /*self*/, PyObject* args)
3971 int wi, ci;
3972 int suffix;
3974 if (!PyArg_ParseTuple( args, "iii", &wi, &ci, &suffix )) {
3975 return AttributeError( GemRB_TextArea_GetPortraits__doc );
3977 TextArea* ta = ( TextArea* ) GetControl( wi, ci, IE_GUI_TEXTAREA );
3978 if (!ta) {
3979 return NULL;
3981 return PyInt_FromLong( core->GetPortraits( ta, suffix ) );
3984 PyDoc_STRVAR( GemRB_TextArea_GetCharSounds__doc,
3985 "GetCharSounds(WindowIndex, ControlIndex) => int\n\n"
3986 "Reads in the contents of the sounds subfolder." );
3988 static PyObject* GemRB_TextArea_GetCharSounds(PyObject * /*self*/, PyObject* args)
3990 int wi, ci;
3992 if (!PyArg_ParseTuple( args, "ii", &wi, &ci )) {
3993 return AttributeError( GemRB_TextArea_GetCharSounds__doc );
3995 TextArea* ta = ( TextArea* ) GetControl( wi, ci, IE_GUI_TEXTAREA );
3996 if (!ta) {
3997 return NULL;
3999 return PyInt_FromLong( core->GetCharSounds( ta ) );
4002 PyDoc_STRVAR( GemRB_TextArea_GetCharacters__doc,
4003 "GetCharacters(WindowIndex, ControlIndex) => int\n\n"
4004 "Reads in the contents of the characters subfolder." );
4006 static PyObject* GemRB_TextArea_GetCharacters(PyObject * /*self*/, PyObject* args)
4008 int wi, ci;
4010 if (!PyArg_ParseTuple( args, "ii", &wi, &ci )) {
4011 return AttributeError( GemRB_TextArea_GetCharacters__doc );
4013 TextArea* ta = ( TextArea* ) GetControl( wi, ci, IE_GUI_TEXTAREA );
4014 if (!ta) {
4015 return NULL;
4017 return PyInt_FromLong( core->GetCharacters( ta ) );
4020 PyDoc_STRVAR( GemRB_GetPartySize__doc,
4021 "GetPartySize() => int\n\n"
4022 "Returns the number of PCs." );
4024 static PyObject* GemRB_GetPartySize(PyObject * /*self*/, PyObject * /*args*/)
4026 Game *game = core->GetGame();
4027 if (!game) {
4028 return RuntimeError( "No game loaded!" );
4030 return PyInt_FromLong( game->GetPartySize(0) );
4033 PyDoc_STRVAR( GemRB_GetGameTime__doc,
4034 "GetGameTime() => int\n\n"
4035 "Returns current game time." );
4037 static PyObject* GemRB_GetGameTime(PyObject * /*self*/, PyObject* /*args*/)
4039 unsigned long GameTime = core->GetGame()->GameTime/AI_UPDATE_TIME;
4040 return PyInt_FromLong( GameTime );
4043 PyDoc_STRVAR( GemRB_GameGetReputation__doc,
4044 "GameGetReputation() => int\n\n"
4045 "Returns party reputation." );
4047 static PyObject* GemRB_GameGetReputation(PyObject * /*self*/, PyObject* /*args*/)
4049 int Reputation = (int) core->GetGame()->Reputation;
4050 return PyInt_FromLong( Reputation );
4053 PyDoc_STRVAR( GemRB_GameSetReputation__doc,
4054 "GameSetReputation(Reputation)\n\n"
4055 "Sets current party reputation." );
4057 static PyObject* GemRB_GameSetReputation(PyObject * /*self*/, PyObject* args)
4059 int Reputation;
4061 if (!PyArg_ParseTuple( args, "i", &Reputation )) {
4062 return AttributeError( GemRB_GameSetReputation__doc );
4064 core->GetGame()->SetReputation( (unsigned int) Reputation );
4066 Py_INCREF( Py_None );
4067 return Py_None;
4070 void ReadReputation()
4072 int table = gamedata->LoadTable( "reputati" );
4073 if (table<0) {
4074 memset(ReputationIncrease,0,sizeof(ReputationIncrease) );
4075 memset(ReputationDonation,0,sizeof(ReputationDonation) );
4076 return;
4078 Holder<TableMgr> tab = gamedata->GetTable( table );
4079 for (int i = 0; i < 20; i++) {
4080 ReputationIncrease[i] = atoi( tab->QueryField(i,4) );
4081 ReputationDonation[i] = atoi( tab->QueryField(i,8) );
4083 gamedata->DelTable( table );
4086 PyDoc_STRVAR( GemRB_IncreaseReputation__doc,
4087 "IncreaseReputation( donation ) => int\n\n"
4088 "Increases party reputation according to the donation. (See reputati.2da)" );
4090 static PyObject* GemRB_IncreaseReputation(PyObject * /*self*/, PyObject* args)
4092 int Donation;
4093 int Increase = 0;
4095 if (!PyArg_ParseTuple( args, "i", &Donation )) {
4096 return AttributeError( GemRB_IncreaseReputation__doc );
4099 Game *game = core->GetGame();
4100 if (!game) {
4101 return RuntimeError( "No game loaded!" );
4103 int Row = (game->Reputation-9)/10;
4104 if (Row>19) {
4105 Row = 19;
4107 if (ReputationDonation[0]==(int) UNINIT_IEDWORD) {
4108 ReadReputation();
4110 int Limit = ReputationDonation[Row];
4111 if (Limit<=Donation) {
4112 Increase = ReputationIncrease[Row];
4113 if (Increase) {
4114 game->SetReputation( game->Reputation + Increase );
4117 return PyInt_FromLong ( Increase );
4120 PyDoc_STRVAR( GemRB_GameGetPartyGold__doc,
4121 "GameGetPartyGold() => int\n\n"
4122 "Returns current party gold." );
4124 static PyObject* GemRB_GameGetPartyGold(PyObject * /*self*/, PyObject* /*args*/)
4126 Game *game = core->GetGame();
4127 if (!game) {
4128 return RuntimeError( "No game loaded!" );
4130 int Gold = game->PartyGold;
4131 return PyInt_FromLong( Gold );
4134 PyDoc_STRVAR( GemRB_GameSetPartyGold__doc,
4135 "GameSetPartyGold(Gold)\n\n"
4136 "Sets current party gold." );
4138 static PyObject* GemRB_GameSetPartyGold(PyObject * /*self*/, PyObject* args)
4140 int Gold, flag = 0;
4142 if (!PyArg_ParseTuple( args, "i|i", &Gold, &flag )) {
4143 return AttributeError( GemRB_GameSetPartyGold__doc );
4145 Game *game = core->GetGame();
4146 if (!game) {
4147 return RuntimeError( "No game loaded!" );
4149 if (flag) {
4150 game->AddGold((ieDword) Gold);
4151 } else {
4152 game->PartyGold=Gold;
4155 Py_INCREF( Py_None );
4156 return Py_None;
4159 PyDoc_STRVAR( GemRB_GameGetFormation__doc,
4160 "GameGetFormation([Which]) => int\n\n"
4161 "Returns current party formation. If Which was supplied, it returns one of the preset formations." );
4163 static PyObject* GemRB_GameGetFormation(PyObject * /*self*/, PyObject* args)
4165 int Which = -1;
4166 int Formation;
4168 if (!PyArg_ParseTuple( args, "|i", &Which )) {
4169 return AttributeError( GemRB_GameGetFormation__doc );
4171 if (Which<0) {
4172 Formation = core->GetGame()->WhichFormation;
4173 } else {
4174 if (Which>4) {
4175 return AttributeError( GemRB_GameGetFormation__doc );
4177 Formation = core->GetGame()->Formations[Which];
4179 return PyInt_FromLong( Formation );
4182 PyDoc_STRVAR( GemRB_GameSetFormation__doc,
4183 "GameSetFormation(Formation[, Which])\n\n"
4184 "Sets party formation. If Which was supplied, it sets one of the preset formations." );
4186 static PyObject* GemRB_GameSetFormation(PyObject * /*self*/, PyObject* args)
4188 int Formation, Which=-1;
4190 if (!PyArg_ParseTuple( args, "i|i", &Formation, &Which )) {
4191 return AttributeError( GemRB_GameSetFormation__doc );
4193 if (Which<0) {
4194 core->GetGame()->WhichFormation = Formation;
4195 } else {
4196 if (Which>4) {
4197 return AttributeError( GemRB_GameSetFormation__doc );
4199 core->GetGame()->Formations[Which] = Formation;
4202 Py_INCREF( Py_None );
4203 return Py_None;
4206 PyDoc_STRVAR( GemRB_GetJournalSize__doc,
4207 "GetJournalSize(chapter[, section]) => int\n\n"
4208 "Returns the number of entries in the given section of journal." );
4210 static PyObject* GemRB_GetJournalSize(PyObject * /*self*/, PyObject * args)
4212 int chapter;
4213 int section = -1;
4215 if (!PyArg_ParseTuple( args, "i|i", &chapter, &section )) {
4216 return AttributeError( GemRB_GetJournalSize__doc );
4219 int count = 0;
4220 for (unsigned int i = 0; i < core->GetGame()->GetJournalCount(); i++) {
4221 GAMJournalEntry* je = core->GetGame()->GetJournalEntry( i );
4222 //printf ("JE: sec: %d; text: %d, time: %d, chapter: %d, un09: %d, un0b: %d\n", je->Section, je->Text, je->GameTime, je->Chapter, je->unknown09, je->unknown0B);
4223 if ((section == -1 || section == je->Section) && (chapter==je->Chapter) )
4224 count++;
4227 return PyInt_FromLong( count );
4230 PyDoc_STRVAR( GemRB_GetJournalEntry__doc,
4231 "GetJournalEntry(chapter, index[, section]) => JournalEntry\n\n"
4232 "Returns dictionary representing journal entry w/ given chapter, section and index." );
4234 static PyObject* GemRB_GetJournalEntry(PyObject * /*self*/, PyObject * args)
4236 int section=-1, index, chapter;
4238 if (!PyArg_ParseTuple( args, "ii|i", &chapter, &index, &section )) {
4239 return AttributeError( GemRB_GetJournalEntry__doc );
4242 int count = 0;
4243 for (unsigned int i = 0; i < core->GetGame()->GetJournalCount(); i++) {
4244 GAMJournalEntry* je = core->GetGame()->GetJournalEntry( i );
4245 if ((section == -1 || section == je->Section) && (chapter == je->Chapter)) {
4246 if (index == count) {
4247 PyObject* dict = PyDict_New();
4248 PyDict_SetItemString(dict, "Text", PyInt_FromLong ((signed) je->Text));
4249 PyDict_SetItemString(dict, "GameTime", PyInt_FromLong (je->GameTime));
4250 PyDict_SetItemString(dict, "Section", PyInt_FromLong (je->Section));
4251 PyDict_SetItemString(dict, "Chapter", PyInt_FromLong (je->Chapter));
4253 return dict;
4255 count++;
4259 Py_INCREF( Py_None );
4260 return Py_None;
4263 PyDoc_STRVAR( GemRB_GameIsBeastKnown__doc,
4264 "GameIsBeastKnown(index) => int\n\n"
4265 "Returns whether beast with given index is known to PCs (works only on PST)." );
4267 static PyObject* GemRB_GameIsBeastKnown(PyObject * /*self*/, PyObject * args)
4269 int index;
4270 if (!PyArg_ParseTuple( args, "i", &index )) {
4271 return AttributeError( GemRB_GameIsBeastKnown__doc );
4274 return PyInt_FromLong( core->GetGame()->IsBeastKnown( index ));
4277 PyDoc_STRVAR( GemRB_GetINIPartyCount__doc,
4278 "GetINIPartyCount() =>int\n\n"
4279 "Returns the Number of Party defined in Party.ini (works only on IWD2)." );
4281 static PyObject* GemRB_GetINIPartyCount(PyObject * /*self*/,
4282 PyObject * /*args*/)
4284 if (!core->GetPartyINI()) {
4285 return RuntimeError( "INI resource not found!" );
4287 return PyInt_FromLong( core->GetPartyINI()->GetTagsCount() );
4290 PyDoc_STRVAR( GemRB_GetINIQuestsKey__doc,
4291 "GetINIQuestsKey(Tag, Key, Default) => string\n\n"
4292 "Returns a Value from the quests.ini File (works only on PST)." );
4294 static PyObject* GemRB_GetINIQuestsKey(PyObject * /*self*/, PyObject* args)
4296 char *Tag, *Key, *Default;
4298 if (!PyArg_ParseTuple( args, "sss", &Tag, &Key, &Default )) {
4299 return AttributeError( GemRB_GetINIQuestsKey__doc );
4301 if (!core->GetQuestsINI()) {
4302 return RuntimeError( "INI resource not found!" );
4304 return PyString_FromString(
4305 core->GetQuestsINI()->GetKeyAsString( Tag, Key, Default ) );
4308 PyDoc_STRVAR( GemRB_GetINIBeastsKey__doc,
4309 "GetINIBeastsKey(Tag, Key, Default) => string\n\n"
4310 "Returns a Value from the beasts.ini File (works only on PST)." );
4312 static PyObject* GemRB_GetINIBeastsKey(PyObject * /*self*/, PyObject* args)
4314 char *Tag, *Key, *Default;
4316 if (!PyArg_ParseTuple( args, "sss", &Tag, &Key, &Default )) {
4317 return AttributeError( GemRB_GetINIBeastsKey__doc );
4319 if (!core->GetBeastsINI()) {
4320 return NULL;
4322 return PyString_FromString(
4323 core->GetBeastsINI()->GetKeyAsString( Tag, Key, Default ) );
4326 PyDoc_STRVAR( GemRB_GetINIPartyKey__doc,
4327 "GetINIPartyKey(Tag, Key, Default) => string\n\n"
4328 "Returns a Value from the Party.ini File (works only on IWD2)." );
4330 static PyObject* GemRB_GetINIPartyKey(PyObject * /*self*/, PyObject* args)
4332 const char *Tag, *Key, *Default;
4334 if (!PyArg_ParseTuple( args, "sss", &Tag, &Key, &Default )) {
4335 return AttributeError( GemRB_GetINIPartyKey__doc );
4337 if (!core->GetPartyINI()) {
4338 return RuntimeError( "INI resource not found!" );
4340 return PyString_FromString(
4341 core->GetPartyINI()->GetKeyAsString( Tag, Key, Default ) );
4344 PyDoc_STRVAR( GemRB_CreatePlayer__doc,
4345 "CreatePlayer(CREResRef, Slot [,Import] ) => PlayerSlot\n\n"
4346 "Creates or removes a player character in a given party slot. If import is nonzero, then reads a CHR instead of a CRE." );
4348 static PyObject* GemRB_CreatePlayer(PyObject * /*self*/, PyObject* args)
4350 const char *CreResRef;
4351 int PlayerSlot, Slot;
4352 int Import=0;
4354 if (!PyArg_ParseTuple( args, "si|i", &CreResRef, &PlayerSlot, &Import)) {
4355 return AttributeError( GemRB_CreatePlayer__doc );
4357 //PlayerSlot is zero based
4358 Slot = ( PlayerSlot & 0x7fff );
4359 Game *game = core->GetGame();
4360 if (!game) {
4361 return RuntimeError( "No game loaded!" );
4363 //FIXME:overwriting original slot
4364 //is dangerous if the game is already loaded
4365 //maybe the actor should be removed from the area first
4366 if (PlayerSlot & 0x8000) {
4367 PlayerSlot = game->FindPlayer( Slot );
4368 if (PlayerSlot >= 0) {
4369 game->DelPC(PlayerSlot, true);
4371 } else {
4372 PlayerSlot = game->FindPlayer( PlayerSlot );
4373 if (PlayerSlot >= 0) {
4374 return RuntimeError("Slot is already filled!");
4377 if (CreResRef[0]) {
4378 PlayerSlot = gamedata->LoadCreature( CreResRef, Slot, (bool) Import );
4379 } else {
4380 //just destroyed the previous actor, not going to create one
4381 PlayerSlot = 0;
4383 if (PlayerSlot < 0) {
4384 return RuntimeError("File not found!");
4386 return PyInt_FromLong( PlayerSlot );
4389 PyDoc_STRVAR( GemRB_GetPlayerStates__doc,
4390 "GetPlayerStates(PartyID) => string\n\n"
4391 "Returns the state string for the player.");
4393 static PyObject* GemRB_GetPlayerStates(PyObject * /*self*/, PyObject* args)
4395 int PartyID;
4397 if (!PyArg_ParseTuple( args, "i", &PartyID )) {
4398 return AttributeError( GemRB_GetPlayerStates__doc );
4400 Game *game = core->GetGame();
4401 if (!game) {
4402 return RuntimeError( "No game loaded!" );
4404 Actor* MyActor = game->FindPC( PartyID );
4405 if (!MyActor) {
4406 return RuntimeError( "Actor not found" );
4408 return PyString_FromString((const char *) MyActor->GetStateString() );
4411 PyDoc_STRVAR( GemRB_GetPlayerName__doc,
4412 "GetPlayerName(PartyID[, LongOrShort]) => string\n\n"
4413 "Queries the player name." );
4415 static PyObject* GemRB_GetPlayerName(PyObject * /*self*/, PyObject* args)
4417 int PartyID, Which;
4419 Which = 0;
4420 if (!PyArg_ParseTuple( args, "i|i", &PartyID, &Which )) {
4421 return AttributeError( GemRB_GetPlayerName__doc );
4423 Game *game = core->GetGame();
4424 if (!game) {
4425 return RuntimeError( "No game loaded!" );
4427 Actor* MyActor = game->FindPC( PartyID );
4428 if (!MyActor) {
4429 return RuntimeError( "Actor not found" );
4431 return PyString_FromString( MyActor->GetName(Which) );
4434 PyDoc_STRVAR( GemRB_SetPlayerName__doc,
4435 "SetPlayerName(Slot, Name[, LongOrShort])\n\n"
4436 "Sets the player name." );
4438 static PyObject* GemRB_SetPlayerName(PyObject * /*self*/, PyObject* args)
4440 const char *Name=NULL;
4441 int PlayerSlot, Which;
4443 Which = 0;
4444 if (!PyArg_ParseTuple( args, "is|i", &PlayerSlot, &Name, &Which )) {
4445 return AttributeError( GemRB_SetPlayerName__doc );
4447 Game *game = core->GetGame();
4448 if (!game) {
4449 return RuntimeError( "No game loaded!" );
4451 Actor* MyActor = game->FindPC( PlayerSlot );
4452 if (!MyActor) {
4453 return RuntimeError( "Actor not found!" );
4455 MyActor->SetName(Name, Which);
4456 MyActor->SetMCFlag(MC_EXPORTABLE,BM_OR);
4457 Py_INCREF( Py_None );
4458 return Py_None;
4461 PyDoc_STRVAR( GemRB_CreateString__doc,
4462 "CreateString( Text )->StrRef\n\n"
4463 "Creates a custom string." );
4465 static PyObject* GemRB_CreateString(PyObject * /*self*/, PyObject* args)
4467 const char *Text;
4468 ieStrRef strref;
4470 if (!PyArg_ParseTuple( args, "is", &strref, &Text )) {
4471 return AttributeError( GemRB_CreateString__doc );
4473 Game *game = core->GetGame();
4474 if (!game) {
4475 return RuntimeError( "No game loaded!" );
4478 strref = core->UpdateString(strref, Text);
4479 return PyInt_FromLong( strref );
4482 PyDoc_STRVAR( GemRB_SetPlayerString__doc,
4483 "SetPlayerString(PlayerSlot, StringSlot, StrRef)\n\n"
4484 "Sets one of the player character's verbal constants. Mostly useful for setting biography." );
4486 static PyObject* GemRB_SetPlayerString(PyObject * /*self*/, PyObject* args)
4488 int PlayerSlot, StringSlot, StrRef;
4490 if (!PyArg_ParseTuple( args, "iii", &PlayerSlot, &StringSlot, &StrRef )) {
4491 return AttributeError( GemRB_SetPlayerString__doc );
4493 Game *game = core->GetGame();
4494 if (!game) {
4495 return RuntimeError( "No game loaded!" );
4497 Actor* MyActor = game->FindPC( PlayerSlot );
4498 if (!MyActor) {
4499 return RuntimeError( "Actor not found!" );
4502 if (StringSlot>=VCONST_COUNT) {
4503 return AttributeError( "StringSlot is out of range!" );
4506 MyActor->StrRefs[StringSlot]=StrRef;
4508 Py_INCREF( Py_None );
4509 return Py_None;
4512 PyDoc_STRVAR( GemRB_SetPlayerSound__doc,
4513 "SetPlayerSound(Slot, SoundFolder)\n\n"
4514 "Sets the player character's sound set." );
4516 static PyObject* GemRB_SetPlayerSound(PyObject * /*self*/, PyObject* args)
4518 const char *Sound=NULL;
4519 int PlayerSlot;
4521 if (!PyArg_ParseTuple( args, "is", &PlayerSlot, &Sound )) {
4522 return AttributeError( GemRB_SetPlayerSound__doc );
4524 Game *game = core->GetGame();
4525 if (!game) {
4526 return RuntimeError( "No game loaded!" );
4528 Actor* MyActor = game->FindPC( PlayerSlot );
4529 if (!MyActor) {
4530 return RuntimeError( "Actor not found!" );
4532 MyActor->SetSoundFolder(Sound);
4533 Py_INCREF( Py_None );
4534 return Py_None;
4537 PyDoc_STRVAR( GemRB_GetSlotType__doc,
4538 "GetSlotType(idx[, PartyID]) => dict\n\n"
4539 "Returns dictionary of an itemslot type (slottype.2da).");
4541 static PyObject* GemRB_GetSlotType(PyObject * /*self*/, PyObject* args)
4543 int idx;
4544 int PartyID = 0;
4545 Actor *actor = NULL;
4547 if (!PyArg_ParseTuple( args, "i|i", &idx, &PartyID )) {
4548 return AttributeError( GemRB_GetSlotType__doc );
4551 if (PartyID) {
4552 Game *game = core->GetGame();
4553 if (!game) {
4554 return RuntimeError( "No game loaded!" );
4556 actor = game->FindPC( PartyID );
4559 PyObject* dict = PyDict_New();
4560 if (idx==-1) {
4561 PyDict_SetItemString(dict, "Count", PyInt_FromLong(core->GetInventorySize()));
4562 return dict;
4564 int tmp = core->QuerySlot(idx);
4565 if (core->QuerySlotEffects(idx)==0xffffffffu) {
4566 tmp=idx;
4569 PyDict_SetItemString(dict, "Slot", PyInt_FromLong(tmp));
4570 PyDict_SetItemString(dict, "Type", PyInt_FromLong((int)core->QuerySlotType(tmp)));
4571 PyDict_SetItemString(dict, "ID", PyInt_FromLong((int)core->QuerySlotID(tmp)));
4572 PyDict_SetItemString(dict, "Tip", PyInt_FromLong((int)core->QuerySlottip(tmp)));
4573 //see if the actor shouldn't have some slots displayed
4574 if (!actor || !actor->PCStats) {
4575 goto has_slot;
4577 //WARNING:idx isn't used any more, recycling it
4578 idx = actor->inventory.GetWeaponSlot();
4579 if (tmp<idx || tmp>idx+3) {
4580 goto has_slot;
4582 if (actor->GetQuickSlot(tmp-idx)==0xffff) {
4583 PyDict_SetItemString(dict, "ResRef", PyString_FromString (""));
4584 goto continue_quest;
4586 has_slot:
4587 PyDict_SetItemString(dict, "ResRef", PyString_FromString (core->QuerySlotResRef(tmp)));
4588 continue_quest:
4589 PyDict_SetItemString(dict, "Effects", PyInt_FromLong (core->QuerySlotEffects(tmp)));
4590 return dict;
4593 PyDoc_STRVAR( GemRB_GetPCStats__doc,
4594 "GetPCStats(PartyID) => dict\n\n"
4595 "Returns dictionary of PC's performance stats." );
4597 static PyObject* GemRB_GetPCStats(PyObject * /*self*/, PyObject* args)
4599 int PartyID;
4601 if (!PyArg_ParseTuple( args, "i", &PartyID )) {
4602 return AttributeError( GemRB_GetPCStats__doc );
4604 Game *game = core->GetGame();
4605 if (!game) {
4606 return RuntimeError( "No game loaded!" );
4608 Actor* MyActor = game->FindPC( PartyID );
4609 if (!MyActor || !MyActor->PCStats) {
4610 Py_INCREF( Py_None );
4611 return Py_None;
4614 PyObject* dict = PyDict_New();
4615 PCStatsStruct* ps = MyActor->PCStats;
4617 PyDict_SetItemString(dict, "BestKilledName", PyInt_FromLong ((signed) ps->BestKilledName));
4618 PyDict_SetItemString(dict, "BestKilledXP", PyInt_FromLong (ps->BestKilledXP));
4619 PyDict_SetItemString(dict, "AwayTime", PyInt_FromLong (ps->AwayTime));
4620 PyDict_SetItemString(dict, "JoinDate", PyInt_FromLong (ps->JoinDate));
4621 PyDict_SetItemString(dict, "KillsChapterXP", PyInt_FromLong (ps->KillsChapterXP));
4622 PyDict_SetItemString(dict, "KillsChapterCount", PyInt_FromLong (ps->KillsChapterCount));
4623 PyDict_SetItemString(dict, "KillsTotalXP", PyInt_FromLong (ps->KillsTotalXP));
4624 PyDict_SetItemString(dict, "KillsTotalCount", PyInt_FromLong (ps->KillsTotalCount));
4626 // FIXME!!!
4627 if (ps->FavouriteSpells[0][0]) {
4628 int largest = 0;
4630 for (int i = 1; i < 4; ++i) {
4631 if (ps->FavouriteSpellsCount[i] > ps->FavouriteSpellsCount[largest]) {
4632 largest = i;
4636 Spell* spell = gamedata->GetSpell(ps->FavouriteSpells[largest]);
4637 if (spell == NULL) {
4638 return NULL;
4641 PyDict_SetItemString(dict, "FavouriteSpell", PyInt_FromLong ((signed) spell->SpellName));
4643 gamedata->FreeSpell( spell, ps->FavouriteSpells[largest], false );
4644 } else {
4645 PyDict_SetItemString(dict, "FavouriteSpell", PyString_FromString (""));
4650 // FIXME!!!
4651 if (ps->FavouriteWeapons[0][0]) {
4652 int largest = 0;
4654 for (int i = 1; i < 4; ++i) {
4655 if (ps->FavouriteWeaponsCount[i] > ps->FavouriteWeaponsCount[largest]) {
4656 largest = i;
4660 Item* item = gamedata->GetItem(ps->FavouriteWeapons[largest]);
4661 if (item == NULL) {
4662 return RuntimeError( "Item not found!" );
4665 PyDict_SetItemString(dict, "FavouriteWeapon", PyInt_FromLong ((signed) item->GetItemName(false)));
4667 gamedata->FreeItem( item, ps->FavouriteWeapons[largest], false );
4668 } else {
4669 PyDict_SetItemString(dict, "FavouriteWeapon", PyString_FromString (""));
4672 return dict;
4676 PyDoc_STRVAR( GemRB_GameSelectPC__doc,
4677 "GameSelectPC(PartyID, Selected, [Flags = SELECT_NORMAL])\n\n"
4678 "Selects or deselects PC."
4679 "if PartyID=0, (De)selects all PC."
4680 "Flags is combination of SELECT_REPLACE and SELECT_QUIET."
4681 "SELECT_REPLACE: when selecting other party members, unselect the others." );
4683 static PyObject* GemRB_GameSelectPC(PyObject * /*self*/, PyObject* args)
4685 int PartyID, Select;
4686 int Flags = SELECT_NORMAL;
4688 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &Select, &Flags )) {
4689 return AttributeError( GemRB_GameSelectPC__doc );
4691 Game *game = core->GetGame();
4692 if (!game) {
4693 return RuntimeError( "No game loaded!" );
4696 Actor* actor;
4697 if (PartyID > 0) {
4698 actor = game->FindPC( PartyID );
4699 if (!actor) {
4700 Py_INCREF( Py_None );
4701 return Py_None;
4703 } else {
4704 actor = NULL;
4707 game->SelectActor( actor, (bool) Select, Flags );
4709 Py_INCREF( Py_None );
4710 return Py_None;
4713 PyDoc_STRVAR( GemRB_GameIsPCSelected__doc,
4714 "GameIsPCSelected(Slot) => bool\n\n"
4715 "Returns true if the PC is selected." );
4717 static PyObject* GemRB_GameIsPCSelected(PyObject * /*self*/, PyObject* args)
4719 int PlayerSlot;
4721 if (!PyArg_ParseTuple( args, "i", &PlayerSlot )) {
4722 return AttributeError( GemRB_GameIsPCSelected__doc );
4724 Game *game = core->GetGame();
4725 if (!game) {
4726 return RuntimeError( "No game loaded!" );
4728 Actor* MyActor = game->FindPC( PlayerSlot );
4729 if (!MyActor) {
4730 return PyInt_FromLong( 0 );
4732 return PyInt_FromLong( MyActor->IsSelected() );
4736 PyDoc_STRVAR( GemRB_GameSelectPCSingle__doc,
4737 "GameSelectPCSingle(index)\n\n"
4738 "Selects one PC in non-walk environment (i.e. in shops, inventory,...)"
4739 "Index must be greater than zero." );
4741 static PyObject* GemRB_GameSelectPCSingle(PyObject * /*self*/, PyObject* args)
4743 int index;
4745 if (!PyArg_ParseTuple( args, "i", &index )) {
4746 return AttributeError( GemRB_GameSelectPCSingle__doc );
4749 core->GetGame()->SelectPCSingle( index );
4751 Py_INCREF( Py_None );
4752 return Py_None;
4755 PyDoc_STRVAR( GemRB_GameGetSelectedPCSingle__doc,
4756 "GameGetSelectedPCSingle(flag) => int\n\n"
4757 "Returns index of the selected PC in non-walk environment (i.e. in shops, inventory,...). Index should be greater than zero. If flag is set, then this function will return the PC currently talking." );
4759 static PyObject* GemRB_GameGetSelectedPCSingle(PyObject * /*self*/, PyObject* args)
4761 int flag = 0;
4763 if (!PyArg_ParseTuple( args, "|i", &flag )) {
4764 return AttributeError( GemRB_GameGetSelectedPCSingle__doc );
4766 Game *game = core->GetGame();
4767 if (!game) {
4768 return RuntimeError( "No game loaded!" );
4770 if (flag) {
4771 GameControl *gc = core->GetGameControl();
4772 if (!gc) {
4773 return RuntimeError("Can't find GameControl!");
4775 Actor *ac = gc->GetSpeaker();
4776 int ret = 0;
4777 if (ac) {
4778 ret = ac->InParty;
4780 return PyInt_FromLong( ret );
4782 return PyInt_FromLong( game->GetSelectedPCSingle() );
4785 PyDoc_STRVAR( GemRB_GameGetFirstSelectedPC__doc,
4786 "GameGetFirstSelectedPC() => int\n\n"
4787 "Returns index of the first selected PC or 0 if none." );
4789 static PyObject* GemRB_GameGetFirstSelectedPC(PyObject * /*self*/, PyObject* /*args*/)
4791 Actor *actor = core->GetFirstSelectedPC(false);
4792 if (actor) {
4793 return PyInt_FromLong( actor->InParty);
4796 return PyInt_FromLong( 0 );
4799 PyDoc_STRVAR( GemRB_ActOnPC__doc,
4800 "ActOnPC(player)\n\n"
4801 "Targets the selected PC for an action (cast spell, attack, ...)" );
4803 static PyObject* GemRB_ActOnPC(PyObject * /*self*/, PyObject* args)
4805 int PartyID;
4807 if (!PyArg_ParseTuple( args, "i", &PartyID )) {
4808 return AttributeError( GemRB_ActOnPC__doc );
4810 Game *game = core->GetGame();
4811 if (!game) {
4812 return RuntimeError( "No game loaded!" );
4814 Actor* MyActor = game->FindPC( PartyID );
4815 if (MyActor) {
4816 GameControl* gc = core->GetGameControl();
4817 if(gc) {
4818 gc->PerformActionOn(MyActor);
4821 Py_INCREF(Py_None) ;
4822 return Py_None ;
4825 PyDoc_STRVAR( GemRB_GetPlayerPortrait__doc,
4826 "GetPlayerPortrait(Slot[, SmallOrLarge]) => string\n\n"
4827 "Queries the player portrait." );
4829 static PyObject* GemRB_GetPlayerPortrait(PyObject * /*self*/, PyObject* args)
4831 int PlayerSlot, Which;
4833 Which = 0;
4834 if (!PyArg_ParseTuple( args, "i|i", &PlayerSlot, &Which )) {
4835 return AttributeError( GemRB_GetPlayerPortrait__doc );
4837 Game *game = core->GetGame();
4838 if (!game) {
4839 return RuntimeError( "No game loaded!" );
4841 Actor* MyActor = game->FindPC( PlayerSlot );
4842 if (!MyActor) {
4843 return PyString_FromString( "");
4845 return PyString_FromString( MyActor->GetPortrait(Which) );
4848 PyDoc_STRVAR( GemRB_GetPlayerString__doc,
4849 "GetPlayerString(Slot, ID) => int\n\n"
4850 "Queries a string reference (verbal constant) from the actor." );
4852 static PyObject* GemRB_GetPlayerString(PyObject * /*self*/, PyObject* args)
4854 int PlayerSlot, Index, StatValue;
4856 if (!PyArg_ParseTuple( args, "ii", &PlayerSlot, &Index)) {
4857 return AttributeError( GemRB_GetPlayerString__doc );
4859 Actor* MyActor = core->GetGame()->FindPC( PlayerSlot );
4860 if (!MyActor) {
4861 return RuntimeError("Cannot find actor!\n");
4863 if (Index>=VCONST_COUNT) {
4864 return RuntimeError("String reference too high!\n");
4866 StatValue = GetCreatureStrRef( MyActor, Index );
4867 return PyInt_FromLong( StatValue );
4870 PyDoc_STRVAR( GemRB_GetPlayerStat__doc,
4871 "GetPlayerStat(Slot, ID[, BaseStat]) => int\n\n"
4872 "Queries a stat." );
4874 static PyObject* GemRB_GetPlayerStat(PyObject * /*self*/, PyObject* args)
4876 int PlayerSlot, StatID, StatValue, BaseStat;
4878 BaseStat = 0;
4879 if (!PyArg_ParseTuple( args, "ii|i", &PlayerSlot, &StatID, &BaseStat )) {
4880 return AttributeError( GemRB_GetPlayerStat__doc );
4882 Actor* MyActor = core->GetGame()->FindPC( PlayerSlot );
4883 if (!MyActor) {
4884 return RuntimeError("Cannot find actor!\n");
4886 //returning the modified stat if BaseStat was 0 (default)
4887 StatValue = GetCreatureStat( MyActor, StatID, !BaseStat );
4888 return PyInt_FromLong( StatValue );
4891 PyDoc_STRVAR( GemRB_SetPlayerStat__doc,
4892 "SetPlayerStat(Slot, ID, Value)\n\n"
4893 "Changes a stat." );
4895 static PyObject* GemRB_SetPlayerStat(PyObject * /*self*/, PyObject* args)
4897 int PlayerSlot, StatID, StatValue;
4899 if (!PyArg_ParseTuple( args, "iii", &PlayerSlot, &StatID, &StatValue )) {
4900 return AttributeError( GemRB_SetPlayerStat__doc );
4902 Actor* MyActor = core->GetGame()->FindPC( PlayerSlot );
4903 if (!MyActor) {
4904 return RuntimeError("Cannot find actor!\n");
4906 //Setting the creature's base stat
4907 SetCreatureStat( MyActor, StatID, StatValue);
4908 Py_INCREF( Py_None );
4909 return Py_None;
4912 PyDoc_STRVAR( GemRB_GetPlayerScript__doc,
4913 "GetPlayerScript(Slot[, Index])\n\n"
4914 "Retrieves the script resource for a player. If index is omitted, it will default to "
4915 "the class script slot (customisable by players)." );
4917 static PyObject* GemRB_GetPlayerScript(PyObject * /*self*/, PyObject* args)
4919 //class script is the custom slot for player scripts
4920 int PlayerSlot, Index = SCR_CLASS;
4922 if (!PyArg_ParseTuple( args, "i|i", &PlayerSlot, &Index )) {
4923 return AttributeError( GemRB_GetPlayerScript__doc );
4925 Actor *actor = core->GetGame()->FindPC(PlayerSlot);
4926 if (!actor) {
4927 return RuntimeError("Cannot find actor!\n");
4929 const char *scr = actor->GetScript(Index);
4930 if (scr[0]==0) {
4931 scr="None";
4933 return PyString_FromString( scr );
4936 PyDoc_STRVAR( GemRB_SetPlayerScript__doc,
4937 "SetPlayerScript(Slot, Resource[, Index])\n\n"
4938 "Sets the script resource for a player. If index is omitted, it will default to "
4939 "the class script slot (customisable by players)." );
4941 static PyObject* GemRB_SetPlayerScript(PyObject * /*self*/, PyObject* args)
4943 const char *ScriptName;
4944 int PlayerSlot, Index = SCR_CLASS;
4946 if (!PyArg_ParseTuple( args, "is|i", &PlayerSlot, &ScriptName, &Index )) {
4947 return AttributeError( GemRB_SetPlayerScript__doc );
4949 Actor *actor = core->GetGame()->FindPC(PlayerSlot);
4950 if (!actor) {
4951 return RuntimeError("Cannot find actor!\n");
4953 actor->SetScript(ScriptName, Index, true);
4954 Py_INCREF( Py_None );
4955 return Py_None;
4958 PyDoc_STRVAR( GemRB_FillPlayerInfo__doc,
4959 "FillPlayerInfo(Slot[, Portrait1, Portrait2])\n\n"
4960 "Fills basic character info, that is not stored in stats." );
4962 static PyObject* GemRB_FillPlayerInfo(PyObject * /*self*/, PyObject* args)
4964 int PlayerSlot;
4965 const char *Portrait1=NULL, *Portrait2=NULL;
4967 if (!PyArg_ParseTuple( args, "i|ss", &PlayerSlot, &Portrait1, &Portrait2)) {
4968 return AttributeError( GemRB_FillPlayerInfo__doc );
4970 // here comes some code to transfer icon/name to the PC sheet
4973 Game *game = core->GetGame();
4974 if (!game) {
4975 return RuntimeError( "No game loaded!" );
4978 Actor* MyActor = game->FindPC( PlayerSlot );
4979 if (!MyActor) {
4980 return RuntimeError( "Actor not found!" );
4982 if (Portrait1) {
4983 MyActor->SetPortrait( Portrait1, 1);
4985 if (Portrait2) {
4986 MyActor->SetPortrait( Portrait2, 2);
4988 int mastertable = gamedata->LoadTable( "avprefix" );
4989 Holder<TableMgr> mtm = gamedata->GetTable( mastertable );
4990 int count = mtm->GetRowCount();
4991 if (count< 1 || count>8) {
4992 return RuntimeError("Table is invalid." );
4994 const char *poi = mtm->QueryField( 0 );
4995 int AnimID = strtoul( poi, NULL, 0 );
4996 for (int i = 1; i < count; i++) {
4997 poi = mtm->QueryField( i );
4998 int table = gamedata->LoadTable( poi );
4999 Holder<TableMgr> tm = gamedata->GetTable( table );
5000 int StatID = atoi( tm->QueryField() );
5001 StatID = MyActor->GetBase( StatID );
5002 poi = tm->QueryField( StatID );
5003 AnimID += strtoul( poi, NULL, 0 );
5004 gamedata->DelTable( table );
5006 MyActor->SetBase(IE_ANIMATION_ID, AnimID);
5007 //setting PST's starting stance to 18
5008 poi = mtm->QueryField( 0, 1 );
5009 if (*poi != '*') {
5010 MyActor->SetStance( atoi( poi ) );
5012 gamedata->DelTable( mastertable );
5013 MyActor->SetOver( false );
5014 MyActor->InitButtons(MyActor->GetStat(IE_CLASS), true); //force re-init of actor's buttons
5015 Py_INCREF( Py_None );
5016 return Py_None;
5019 PyDoc_STRVAR( GemRB_Button_SetSpellIcon__doc,
5020 "SetSpellIcon(WindowIndex, ControlIndex, SPLResRef[, type, tooltip, function])\n\n"
5021 "Sets Spell icon image on a button. Type is the icon's type." );
5023 PyObject *SetSpellIcon(int wi, int ci, const ieResRef SpellResRef, int type, int tooltip, int Function)
5025 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
5026 if (!btn) {
5027 return NULL;
5030 if (!SpellResRef[0]) {
5031 btn->SetPicture( NULL );
5032 //no incref here!
5033 return Py_None;
5036 Spell* spell = gamedata->GetSpell( SpellResRef, 1 );
5037 if (spell == NULL) {
5038 btn->SetPicture( NULL );
5039 printMessage( "GUIScript", " ", LIGHT_RED);
5040 printf("Spell not found :%.8s", SpellResRef );
5041 //no incref here!
5042 return Py_None;
5045 const char* IconResRef;
5046 if (type) {
5047 IconResRef = spell->ext_headers[0].MemorisedIcon;
5049 else {
5050 IconResRef = spell->SpellbookIcon;
5052 AnimationFactory* af = ( AnimationFactory* )
5053 gamedata->GetFactoryResource( IconResRef,
5054 IE_BAM_CLASS_ID, IE_NORMAL, 1 );
5055 if (!af) {
5056 printf("Searched for: %s\n", IconResRef);
5057 return RuntimeError( "BAM not found" );
5059 //small difference between pst and others
5060 if (af->GetCycleSize(0)!=4) { //non-pst
5061 btn->SetPicture( af->GetFrame(0, 0));
5063 else { //pst
5064 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, af->GetFrame(0, 0));
5065 btn->SetImage( IE_GUI_BUTTON_PRESSED, af->GetFrame(1, 0));
5066 btn->SetImage( IE_GUI_BUTTON_SELECTED, af->GetFrame(2, 0));
5067 btn->SetImage( IE_GUI_BUTTON_DISABLED, af->GetFrame(3, 0));
5069 if (tooltip) {
5070 char *str = core->GetString(spell->SpellName,0);
5071 SetFunctionTooltip(wi, ci, str, Function); //will free str
5073 gamedata->FreeSpell( spell, SpellResRef, false );
5074 //no incref here!
5075 return Py_None;
5078 static PyObject* GemRB_Button_SetSpellIcon(PyObject * /*self*/, PyObject* args)
5080 int wi, ci;
5081 const char *SpellResRef;
5082 int type=0;
5083 int tooltip=0;
5084 int Function=0;
5086 if (!PyArg_ParseTuple( args, "iis|iii", &wi, &ci, &SpellResRef, &type, &tooltip, &Function )) {
5087 return AttributeError( GemRB_Button_SetSpellIcon__doc );
5089 PyObject *ret = SetSpellIcon(wi, ci, SpellResRef, type, tooltip, Function);
5090 if (ret) {
5091 Py_INCREF(ret);
5093 return ret;
5097 static Sprite2D* GetUsedWeaponIcon(Item *item, int which)
5099 ITMExtHeader *ieh = item->GetWeaponHeader(false);
5100 if (!ieh) {
5101 ieh = item->GetWeaponHeader(true);
5103 if (ieh) {
5104 return gamedata->GetBAMSprite(ieh->UseIcon, -1, which);
5106 return gamedata->GetBAMSprite(item->ItemIcon, -1, which);
5109 static void SetItemText(int wi, int ci, int charges, bool oneisnone)
5111 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
5112 if (!btn) {
5113 return;
5115 char tmp[10];
5117 if (charges && (charges>1 || !oneisnone) ) {
5118 sprintf(tmp,"%d",charges);
5119 } else {
5120 tmp[0]=0;
5122 btn->SetText(tmp);
5125 PyDoc_STRVAR( GemRB_Button_SetItemIcon__doc,
5126 "SetItemIcon(WindowIndex, ControlIndex, ITMResRef[, type, tooltip, Function, ITM2ResRef])\n\n"
5127 "Sets Item icon image on a button. 0/1 - Inventory Icons, 2 - Description Icon, 3 - No icon,\n"
5128 " 4/5 - Weapon icons, 6 and above - Extended header icons." );
5130 PyObject *SetItemIcon(int wi, int ci, const char *ItemResRef, int Which, int tooltip, int Function, const char *Item2ResRef)
5132 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
5133 if (!btn) {
5134 return NULL;
5137 if (!ItemResRef[0]) {
5138 btn->SetPicture( NULL );
5139 //no incref here!
5140 return Py_None;
5142 Item* item = gamedata->GetItem(ItemResRef);
5143 if (item == NULL) {
5144 btn->SetPicture(NULL);
5145 //no incref here!
5146 return Py_None;
5149 btn->SetFlags( IE_GUI_BUTTON_PICTURE, BM_OR );
5150 Sprite2D* Picture;
5151 bool setpicture = true;
5152 int i;
5153 switch (Which) {
5154 case 0: case 1:
5155 Picture = gamedata->GetBAMSprite(item->ItemIcon, -1, Which);
5156 break;
5157 case 2:
5158 btn->SetPicture( NULL ); // also calls ClearPictureList
5159 for (i=0;i<4;i++) {
5160 Picture = gamedata->GetBAMSprite(item->DescriptionIcon, -1, i);
5161 if (Picture)
5162 btn->StackPicture(Picture);
5164 //fallthrough
5165 case 3:
5166 setpicture = false;
5167 Picture = NULL;
5168 break;
5169 case 4: case 5:
5170 Picture = GetUsedWeaponIcon(item, Which-4);
5171 if (Item2ResRef) {
5172 btn->SetPicture( NULL ); // also calls ClearPictureList
5173 Item* item2 = gamedata->GetItem(Item2ResRef);
5174 if (item2) {
5175 Sprite2D* Picture2;
5176 Picture2 = gamedata->GetBAMSprite(item2->ItemIcon, -1, Which-4);
5177 if (Picture2) btn->StackPicture(Picture2);
5178 gamedata->FreeItem( item2, Item2ResRef, false );
5180 if (Picture) btn->StackPicture(Picture);
5181 setpicture = false;
5183 break;
5184 default:
5185 ITMExtHeader *eh = item->GetExtHeader(Which-6);
5186 if (eh) {
5187 Picture = gamedata->GetBAMSprite(eh->UseIcon, -1, 0);
5189 else {
5190 Picture = NULL;
5194 if (setpicture)
5195 btn->SetPicture( Picture );
5196 if (tooltip) {
5197 //later getitemname could also return tooltip stuff
5198 char *str = core->GetString(item->GetItemName(tooltip==2),0);
5199 //this will free str, no need of freeing it
5200 SetFunctionTooltip(wi, ci, str, Function);
5203 gamedata->FreeItem( item, ItemResRef, false );
5204 //no incref here!
5205 return Py_None;
5208 static PyObject* GemRB_Button_SetItemIcon(PyObject * /*self*/, PyObject* args)
5210 int wi, ci;
5211 const char *ItemResRef;
5212 int Which = 0;
5213 int tooltip = 0;
5214 int Function = 0;
5215 const char *Item2ResRef = NULL;
5217 if (!PyArg_ParseTuple( args, "iis|iiis", &wi, &ci, &ItemResRef, &Which, &tooltip, &Function, &Item2ResRef )) {
5218 return AttributeError( GemRB_Button_SetItemIcon__doc );
5221 PyObject *ret = SetItemIcon(wi, ci, ItemResRef, Which, tooltip, Function, Item2ResRef);
5222 if (ret) {
5223 Py_INCREF(ret);
5225 return ret;
5228 PyDoc_STRVAR( GemRB_EnterStore__doc,
5229 "EnterStore(STOResRef)\n\n"
5230 "Loads the store referenced and opens the store window." );
5232 static PyObject* GemRB_EnterStore(PyObject * /*self*/, PyObject* args)
5234 const char* StoreResRef;
5236 if (!PyArg_ParseTuple( args, "s", &StoreResRef )) {
5237 return AttributeError( GemRB_EnterStore__doc );
5240 //stores are cached, bags could be opened while in shops
5241 //so better just switch to the requested store silently
5242 //the core will be intelligent enough to not do excess work
5243 core->SetCurrentStore( StoreResRef, NULL );
5245 //the error flag is not optional, we should open a store now
5246 //core->GetGUIScriptEngine()->RunFunction( "OpenStoreWindow", true);
5247 core->SetEventFlag(EF_OPENSTORE);
5248 Py_INCREF( Py_None );
5249 return Py_None;
5252 PyDoc_STRVAR( GemRB_LeaveStore__doc,
5253 "LeaveStore(STOResRef)\n\n"
5254 "Saves the current store to the Cache folder and frees it from memory." );
5256 static PyObject* GemRB_LeaveStore(PyObject * /*self*/, PyObject* /*args*/)
5258 if (core->CloseCurrentStore() ) {
5259 return RuntimeError("Cannot save store!");
5261 Py_INCREF( Py_None );
5262 return Py_None;
5265 PyDoc_STRVAR( GemRB_LeaveContainer__doc,
5266 "LeaveContainer()\n\n"
5267 "Clears the current container variable and initiates the 'CloseContainerWindow' guiscript call in the next window update cycle.");
5269 static PyObject* GemRB_LeaveContainer(PyObject * /*self*/, PyObject* /*args*/)
5271 core->CloseCurrentContainer();
5272 Py_INCREF( Py_None );
5273 return Py_None;
5276 PyDoc_STRVAR( GemRB_GetContainer__doc,
5277 "GetContainer( PartyID, autoselect ) => dictionary\n\n"
5278 "Returns relevant data of the container used by the selected actor. Use autoselect if the container is an item pile at the feet of the actor. It will create the container if required." );
5280 static PyObject* GemRB_GetContainer(PyObject * /*self*/, PyObject* args)
5282 int PartyID;
5283 int autoselect=0;
5285 if (!PyArg_ParseTuple( args, "i|i", &PartyID, &autoselect )) {
5286 return AttributeError( GemRB_GetContainer__doc );
5289 Actor *actor;
5291 Game *game = core->GetGame();
5292 if (!game) {
5293 return RuntimeError( "No game loaded!" );
5295 if (PartyID) {
5296 actor = game->FindPC( PartyID );
5297 } else {
5298 actor = core->GetFirstSelectedPC(false);
5300 if (!actor) {
5301 return RuntimeError( "Actor not found" );
5303 Container *container = NULL;
5304 if (autoselect) { //autoselect works only with piles
5305 Map *map = actor->GetCurrentArea();
5306 //GetContainer should create an empty container
5307 container = map->GetPile(actor->Pos);
5308 } else {
5309 container = core->GetCurrentContainer();
5311 if (!container) {
5312 return RuntimeError("No current container!");
5315 PyObject* dict = PyDict_New();
5316 PyDict_SetItemString(dict, "Type", PyInt_FromLong( container->Type ));
5317 PyDict_SetItemString(dict, "ItemCount", PyInt_FromLong( container->inventory.GetSlotCount() ));
5319 return dict;
5322 PyDoc_STRVAR( GemRB_GetContainerItem__doc,
5323 "GetContainerItem(PartyID, idx) => dictionary\n\n"
5324 "Returns the container item referenced by the index. If PartyID is 0 then the container was opened manually and should be the current container. If PartyID is not 0 then the container is autoselected and should be at the feet of the player." );
5326 static PyObject* GemRB_GetContainerItem(PyObject * /*self*/, PyObject* args)
5328 int PartyID;
5329 int index;
5331 if (!PyArg_ParseTuple( args, "ii", &PartyID, &index )) {
5332 return AttributeError( GemRB_GetContainerItem__doc );
5334 Container *container;
5336 if (PartyID) {
5337 Game *game = core->GetGame();
5338 if (!game) {
5339 return RuntimeError( "No game loaded!" );
5341 Actor *actor = game->FindPC( PartyID );
5342 if (!actor) {
5343 return RuntimeError( "Actor not found" );
5345 Map *map = actor->GetCurrentArea();
5346 container = map->TMap->GetContainer(actor->Pos, IE_CONTAINER_PILE);
5347 } else {
5348 container = core->GetCurrentContainer();
5350 if (!container) {
5351 return RuntimeError("No current container!");
5353 if (index>=(int) container->inventory.GetSlotCount()) {
5354 Py_INCREF( Py_None );
5355 return Py_None;
5357 PyObject* dict = PyDict_New();
5359 CREItem *ci=container->inventory.GetSlotItem( index );
5361 PyDict_SetItemString(dict, "ItemResRef", PyString_FromResRef( ci->ItemResRef ));
5362 PyDict_SetItemString(dict, "Usages0", PyInt_FromLong (ci->Usages[0]));
5363 PyDict_SetItemString(dict, "Usages1", PyInt_FromLong (ci->Usages[1]));
5364 PyDict_SetItemString(dict, "Usages2", PyInt_FromLong (ci->Usages[2]));
5365 PyDict_SetItemString(dict, "Flags", PyInt_FromLong (ci->Flags));
5367 Item *item = gamedata->GetItem( ci->ItemResRef );
5369 bool identified = ci->Flags & IE_INV_ITEM_IDENTIFIED;
5370 PyDict_SetItemString(dict, "ItemName", PyInt_FromLong( (signed) item->GetItemName( identified )) );
5371 PyDict_SetItemString(dict, "ItemDesc", PyInt_FromLong( (signed) item->GetItemDesc( identified )) );
5372 gamedata->FreeItem( item, ci->ItemResRef, false );
5373 return dict;
5376 PyDoc_STRVAR( GemRB_ChangeContainerItem__doc,
5377 "ChangeContainerItem(PartyID, slot, action)\n\n"
5378 "Takes an item from a container, or puts it there. "
5379 "If PC is 0 then it uses the first selected PC and the current container, "
5380 "if it is not 0 then it autoselects the container. "
5381 "action=0: move item from PC to container."
5382 "action=1: move item from container to PC.");
5384 static PyObject* GemRB_ChangeContainerItem(PyObject * /*self*/, PyObject* args)
5386 int PartyID, Slot;
5387 int action;
5389 if (!PyArg_ParseTuple( args, "iii", &PartyID, &Slot, &action)) {
5390 return AttributeError( GemRB_ChangeContainerItem__doc );
5392 Game *game = core->GetGame();
5393 if (!game) {
5394 return RuntimeError( "No game loaded!" );
5396 Actor* actor;
5397 Container *container;
5398 if (PartyID) {
5399 actor = game->FindPC( PartyID );
5400 if (!actor) {
5401 return RuntimeError( "Actor not found" );
5403 Map *map = actor->GetCurrentArea();
5404 container = map->TMap->GetContainer(actor->Pos, IE_CONTAINER_PILE);
5405 } else {
5406 actor = core->GetFirstSelectedPC(false);
5407 if (!actor) {
5408 return RuntimeError( "Actor not found" );
5410 container = core->GetCurrentContainer();
5412 if (!container) {
5413 return RuntimeError("No current container!");
5416 ieResRef Sound;
5417 CREItem *si;
5418 int res;
5420 Sound[0]=0;
5421 if (action) { //get stuff from container
5422 if (Slot<0 || Slot>=(int) container->inventory.GetSlotCount()) {
5423 return RuntimeError("Invalid Container slot!");
5426 res = core->CanMoveItem(container->inventory.GetSlotItem(Slot) );
5427 if (!res) { //cannot move
5428 printMessage("GUIScript","Cannot move item, it is undroppable!\n", GREEN);
5429 Py_INCREF( Py_None );
5430 return Py_None;
5433 //this will update the container
5434 si = container->RemoveItem(Slot,0);
5435 if (!si) {
5436 printMessage("GUIScript","Cannot move item, there is something weird!\n", YELLOW);
5437 Py_INCREF( Py_None );
5438 return Py_None;
5440 Item *item = gamedata->GetItem(si->ItemResRef);
5441 if (item) {
5442 if (core->HasFeature(GF_HAS_PICK_SOUND) && item->ReplacementItem[0]) {
5443 memcpy(Sound,item->ReplacementItem,sizeof(ieResRef));
5444 } else {
5445 GetItemSound(Sound, item->ItemType, item->AnimationType, IS_DROP);
5447 gamedata->FreeItem(item, si->ItemResRef,0);
5449 if (res!=-1) { //it is gold!
5450 game->PartyGold += res;
5451 delete si;
5452 } else {
5453 res = actor->inventory.AddSlotItem(si, SLOT_ONLYINVENTORY);
5454 if (res !=ASI_SUCCESS) { //putting it back
5455 container->AddItem(si);
5458 } else { //put stuff in container, simple!
5459 res = core->CanMoveItem(actor->inventory.GetSlotItem(core->QuerySlot(Slot) ) );
5460 if (!res) { //cannot move
5461 printMessage("GUIScript","Cannot move item, it is undroppable!\n", GREEN);
5462 Py_INCREF( Py_None );
5463 return Py_None;
5466 si = actor->inventory.RemoveItem(core->QuerySlot(Slot));
5467 if (!si) {
5468 printMessage("GUIScript","Cannot move item, there is something weird!\n", YELLOW);
5469 Py_INCREF( Py_None );
5470 return Py_None;
5472 Item *item = gamedata->GetItem(si->ItemResRef);
5473 if (item) {
5474 if (core->HasFeature(GF_HAS_PICK_SOUND) && item->DescriptionIcon[0]) {
5475 memcpy(Sound,item->DescriptionIcon,sizeof(ieResRef));
5476 } else {
5477 GetItemSound(Sound, item->ItemType, item->AnimationType, IS_GET);
5479 gamedata->FreeItem(item, si->ItemResRef,0);
5481 actor->ReinitQuickSlots();
5483 if (res!=-1) { //it is gold!
5484 game->PartyGold += res;
5485 delete si;
5486 } else {
5487 container->AddItem(si);
5491 if (Sound[0]) {
5492 core->GetAudioDrv()->Play(Sound);
5495 Py_INCREF( Py_None );
5496 return Py_None;
5499 PyDoc_STRVAR( GemRB_GetStore__doc,
5500 "GetStore() => dictionary\n\n"
5501 "Returns relevant data of the current store." );
5503 #define STORETYPE_COUNT 7
5504 static int storebuttons[STORETYPE_COUNT][4]={
5505 //store
5506 {STA_BUYSELL,STA_IDENTIFY|STA_OPTIONAL,STA_STEAL|STA_OPTIONAL,STA_CURE|STA_OPTIONAL},
5507 //tavern
5508 {STA_DRINK,STA_BUYSELL|STA_OPTIONAL,STA_IDENTIFY|STA_OPTIONAL,STA_STEAL|STA_OPTIONAL},
5509 //inn
5510 {STA_ROOMRENT,STA_BUYSELL|STA_OPTIONAL,STA_DRINK|STA_OPTIONAL,STA_STEAL|STA_OPTIONAL},
5511 //temple
5512 {STA_CURE, STA_DONATE|STA_OPTIONAL,STA_BUYSELL|STA_OPTIONAL,STA_IDENTIFY|STA_OPTIONAL},
5513 //iwd container
5514 {STA_BUYSELL,-1,-1,-1,},
5515 //no need to steal from your own container (original engine had STEAL instead of DRINK)
5516 {STA_BUYSELL,STA_IDENTIFY|STA_OPTIONAL,STA_DRINK|STA_OPTIONAL,STA_CURE|STA_OPTIONAL},
5517 //gemrb specific store type: (temple 2), added steal, removed identify
5518 {STA_BUYSELL,STA_STEAL|STA_OPTIONAL,STA_DONATE|STA_OPTIONAL,STA_CURE|STA_OPTIONAL} };
5520 //buy/sell, identify, steal, cure, donate, drink, rent
5521 static int storebits[7]={IE_STORE_BUY|IE_STORE_SELL,IE_STORE_ID,IE_STORE_STEAL,
5522 IE_STORE_CURE,IE_STORE_DONATE,IE_STORE_DRINK,IE_STORE_RENT};
5524 static PyObject* GemRB_GetStore(PyObject * /*self*/, PyObject* args)
5526 if (!PyArg_ParseTuple( args, "" )) {
5527 return AttributeError( GemRB_GetStore__doc );
5530 Store *store = core->GetCurrentStore();
5531 if (!store) {
5532 Py_INCREF( Py_None );
5533 return Py_None;
5535 if (store->Type>STORETYPE_COUNT-1) {
5536 store->Type=STORETYPE_COUNT-1;
5538 PyObject* dict = PyDict_New();
5539 PyDict_SetItemString(dict, "StoreType", PyInt_FromLong( store->Type ));
5540 PyDict_SetItemString(dict, "StoreName", PyInt_FromLong( (signed) store->StoreName ));
5541 PyDict_SetItemString(dict, "StoreDrinkCount", PyInt_FromLong( store->DrinksCount ));
5542 PyDict_SetItemString(dict, "StoreCureCount", PyInt_FromLong( store->CuresCount ));
5543 PyDict_SetItemString(dict, "StoreItemCount", PyInt_FromLong( store->GetRealStockSize() ));
5544 PyDict_SetItemString(dict, "StoreCapacity", PyInt_FromLong( store->Capacity ));
5545 PyObject* p = PyTuple_New( 4 );
5547 int i;
5548 int j=1;
5549 int k;
5550 for (i = 0; i < 4; i++) {
5551 if (store->AvailableRooms&j) {
5552 k = store->RoomPrices[i];
5554 else k=-1;
5555 PyTuple_SetItem( p, i, PyInt_FromLong( k ) );
5556 j<<=1;
5558 PyDict_SetItemString(dict, "StoreRoomPrices", p);
5560 p = PyTuple_New( 4 );
5561 j=0;
5562 for (i = 0; i < 4; i++) {
5563 k = storebuttons[store->Type][i];
5564 if (k&STA_OPTIONAL) {
5565 k&=~STA_OPTIONAL;
5566 //check if the type was disabled
5567 if (!(store->Flags & storebits[k]) ) {
5568 continue;
5571 PyTuple_SetItem( p, j++, PyInt_FromLong( k ) );
5573 for (;j<4;j++) {
5574 PyTuple_SetItem( p, j, PyInt_FromLong( -1 ) );
5576 PyDict_SetItemString(dict, "StoreButtons", p);
5577 PyDict_SetItemString(dict, "StoreFlags", PyInt_FromLong( store->Flags ) );
5578 PyDict_SetItemString(dict, "TavernRumour", PyString_FromResRef( store->RumoursTavern ));
5579 PyDict_SetItemString(dict, "TempleRumour", PyString_FromResRef( store->RumoursTemple ));
5580 PyDict_SetItemString(dict, "IDPrice", PyInt_FromLong( store->IDPrice ) );
5581 PyDict_SetItemString(dict, "Lore", PyInt_FromLong( store->Lore ) );
5582 PyDict_SetItemString(dict, "Depreciation", PyInt_FromLong( store->DepreciationRate ) );
5583 PyDict_SetItemString(dict, "SellMarkup", PyInt_FromLong( store->SellMarkup ) );
5584 PyDict_SetItemString(dict, "BuyMarkup", PyInt_FromLong( store->BuyMarkup ) );
5585 PyDict_SetItemString(dict, "StealFailure", PyInt_FromLong( store->StealFailureChance ) );
5587 return dict;
5591 PyDoc_STRVAR( GemRB_IsValidStoreItem__doc,
5592 "IsValidStoreItem(pc, idx[, type]) => int\n\n"
5593 "Returns if a pc's inventory item or a store item is valid for buying, selling, identifying or stealing. It also has a flag for selected items. "
5594 "Type is 1 for store items and 0 for PC items." );
5596 static PyObject* GemRB_IsValidStoreItem(PyObject * /*self*/, PyObject* args)
5598 int PartyID, Slot, ret;
5599 int type = 0;
5601 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &Slot, &type)) {
5602 return AttributeError( GemRB_IsValidStoreItem__doc );
5604 Game *game = core->GetGame();
5605 if (!game) {
5606 return RuntimeError( "No game loaded!" );
5608 Actor* actor = game->FindPC( PartyID );
5609 if (!actor) {
5610 return RuntimeError( "Actor not found" );
5613 Store *store = core->GetCurrentStore();
5614 if (!store) {
5615 return RuntimeError("No current store!");
5618 const char *ItemResRef;
5619 ieDword Flags;
5621 if (type) {
5622 STOItem* si = store->GetItem( Slot );
5623 if (!si) {
5624 return PyInt_FromLong(0);
5626 ItemResRef = si->ItemResRef;
5627 Flags = si->Flags;
5628 } else {
5629 CREItem* si = actor->inventory.GetSlotItem( core->QuerySlot(Slot) );
5630 if (!si) {
5631 return PyInt_FromLong(0);
5633 ItemResRef = si->ItemResRef;
5634 Flags = si->Flags;
5636 Item *item = gamedata->GetItem( ItemResRef );
5637 if (!item) {
5638 printMessage("GUIScript", " ", LIGHT_RED);
5639 printf("Invalid resource reference: %s\n", ItemResRef);
5640 return PyInt_FromLong(0);
5643 ret = store->AcceptableItemType( item->ItemType, Flags, !type );
5645 //don't allow putting a bag into itself
5646 if (!strnicmp(ItemResRef, store->Name, sizeof(ieResRef)) ) {
5647 ret &= ~IE_STORE_SELL;
5649 //this is a hack to report on selected items
5650 if (Flags & IE_INV_ITEM_SELECTED) {
5651 ret |= IE_STORE_SELECT;
5653 gamedata->FreeItem( item, ItemResRef, false );
5654 return PyInt_FromLong(ret);
5657 PyDoc_STRVAR( GemRB_SetPurchasedAmount__doc,
5658 "SetPurchasedAmount(idx, amount)\n\n"
5659 "Sets the amount of purchased items of a type.");
5661 static PyObject* GemRB_SetPurchasedAmount(PyObject * /*self*/, PyObject* args)
5663 int Slot, tmp;
5664 ieDword amount;
5666 if (!PyArg_ParseTuple( args, "ii", &Slot, &tmp)) {
5667 return AttributeError( GemRB_SetPurchasedAmount__doc );
5669 amount = (ieDword) tmp;
5670 Store *store = core->GetCurrentStore();
5671 if (!store) {
5672 return RuntimeError("No current store!");
5674 STOItem* si = store->GetItem( Slot );
5675 if (!si) {
5676 return RuntimeError("Store item not found!");
5679 if (si->InfiniteSupply != -1) {
5680 if (si->AmountInStock<amount) {
5681 amount=si->AmountInStock;
5684 si->PurchasedAmount=amount;
5685 if (amount) {
5686 si->Flags |= IE_INV_ITEM_SELECTED;
5687 } else {
5688 si->Flags &= ~IE_INV_ITEM_SELECTED;
5691 Py_INCREF( Py_None );
5692 return Py_None;
5695 PyDoc_STRVAR( GemRB_ChangeStoreItem__doc,
5696 "ChangeStoreItem(PartyID, Slot, action)=>int\n\n"
5697 "Performs an action of buying, selling, identifying or stealing in a store. "
5698 "It can also toggle the selection of an item." );
5700 static PyObject* GemRB_ChangeStoreItem(PyObject * /*self*/, PyObject* args)
5702 int PartyID, Slot;
5703 int action;
5704 int res = ASI_FAILED;
5706 if (!PyArg_ParseTuple( args, "iii", &PartyID, &Slot, &action)) {
5707 return AttributeError( GemRB_ChangeStoreItem__doc );
5709 Game *game = core->GetGame();
5710 if (!game) {
5711 return RuntimeError( "No game loaded!" );
5713 Actor* actor = game->FindPC( PartyID );
5714 if (!actor) {
5715 return RuntimeError( "Actor not found" );
5718 Store *store = core->GetCurrentStore();
5719 if (!store) {
5720 return RuntimeError("No current store!");
5722 switch (action) {
5723 case IE_STORE_BUY: case IE_STORE_STEAL:
5725 STOItem* si = store->GetItem( Slot );
5726 if (!si) {
5727 return RuntimeError("Store item not found!");
5729 //the amount of items is stored in si->PurchasedAmount
5730 //it will adjust AmountInStock/PurchasedAmount
5731 actor->inventory.AddStoreItem(si, action);
5732 if (si->PurchasedAmount) {
5733 //was not able to buy it due to lack of space
5734 res = ASI_FAILED;
5735 break;
5737 //if no item remained, remove it
5738 if (si->AmountInStock) {
5739 si->Flags &= ~IE_INV_ITEM_SELECTED;
5740 } else {
5741 store->RemoveItem( Slot );
5743 res = ASI_SUCCESS;
5744 break;
5746 case IE_STORE_ID:
5748 CREItem* si = actor->inventory.GetSlotItem( core->QuerySlot(Slot) );
5749 if (!si) {
5750 return RuntimeError( "Item not found!" );
5752 si->Flags |= IE_INV_ITEM_IDENTIFIED;
5753 res = ASI_SUCCESS;
5754 break;
5756 case IE_STORE_SELECT|IE_STORE_BUY:
5758 STOItem* si = store->GetItem( Slot );
5759 if (!si) {
5760 return RuntimeError("Store item not found!");
5762 si->Flags ^= IE_INV_ITEM_SELECTED;
5763 if (si->Flags & IE_INV_ITEM_SELECTED) {
5764 si->PurchasedAmount=1;
5765 } else {
5766 si->PurchasedAmount=0;
5768 res = ASI_SUCCESS;
5769 break;
5772 case IE_STORE_SELECT|IE_STORE_SELL:
5774 //this is not removeitem, because the item is just marked
5775 CREItem* si = actor->inventory.GetSlotItem( core->QuerySlot(Slot) );
5776 if (!si) {
5777 return RuntimeError( "Item not found!" );
5779 si->Flags ^= IE_INV_ITEM_SELECTED;
5780 res = ASI_SUCCESS;
5781 break;
5783 case IE_STORE_SELL:
5785 //store/bag is at full capacity
5786 if (store->Capacity && (store->Capacity <= store->GetRealStockSize()) ) {
5787 printMessage("GUIScript", "Store is full.\n", GREEN);
5788 res = ASI_FAILED;
5789 break;
5791 //this is removeitem, because the item leaves our inventory
5792 CREItem* si = actor->inventory.RemoveItem( core->QuerySlot(Slot) );
5793 if (!si) {
5794 return RuntimeError( "Item not found!" );
5796 //well, it shouldn't be sold at all, but if it is here
5797 //it will vanish!!!
5798 if (!si->Expired && (si->Flags& IE_INV_ITEM_RESELLABLE)) {
5799 si->Flags &= ~IE_INV_ITEM_SELECTED;
5800 store->AddItem( si );
5802 delete si;
5803 res = ASI_SUCCESS;
5804 break;
5807 return PyInt_FromLong(res);
5810 PyDoc_STRVAR( GemRB_GetStoreItem__doc,
5811 "GetStoreItem(idx) => dictionary\n\n"
5812 "Returns the store item referenced by the index." );
5814 static PyObject* GemRB_GetStoreItem(PyObject * /*self*/, PyObject* args)
5816 int index;
5818 if (!PyArg_ParseTuple( args, "i", &index )) {
5819 return AttributeError( GemRB_GetStoreItem__doc );
5821 Store *store = core->GetCurrentStore();
5822 if (!store) {
5823 return RuntimeError("No current store!");
5825 if (index>=(int) store->GetRealStockSize()) {
5826 printMessage("GUIScript","Item is not available???",YELLOW);
5827 Py_INCREF( Py_None );
5828 return Py_None;
5830 PyObject* dict = PyDict_New();
5831 STOItem *si=store->GetItem( index );
5832 if (!si) {
5833 printMessage("GUIScript","Item is not available???",YELLOW);
5834 Py_INCREF( Py_None );
5835 return Py_None;
5837 PyDict_SetItemString(dict, "ItemResRef", PyString_FromResRef( si->ItemResRef ));
5838 PyDict_SetItemString(dict, "Usages0", PyInt_FromLong (si->Usages[0]));
5839 PyDict_SetItemString(dict, "Usages1", PyInt_FromLong (si->Usages[1]));
5840 PyDict_SetItemString(dict, "Usages2", PyInt_FromLong (si->Usages[2]));
5841 PyDict_SetItemString(dict, "Flags", PyInt_FromLong (si->Flags));
5842 PyDict_SetItemString(dict, "Purchased", PyInt_FromLong (si->PurchasedAmount) );
5844 int amount;
5845 if (si->InfiniteSupply==-1) {
5846 PyDict_SetItemString(dict, "Amount", PyInt_FromLong( -1 ) );
5847 amount = 100;
5848 } else {
5849 amount = si->AmountInStock;
5850 PyDict_SetItemString(dict, "Amount", PyInt_FromLong( amount ) );
5853 Item *item = gamedata->GetItem( si->ItemResRef );
5855 if (!item) {
5856 printMessage("GUIScript","Item is not available???",YELLOW);
5857 Py_INCREF( Py_None );
5858 return Py_None;
5861 int identified = !!(si->Flags & IE_INV_ITEM_IDENTIFIED);
5862 PyDict_SetItemString(dict, "ItemName", PyInt_FromLong( (signed) item->GetItemName( (bool) identified )) );
5863 PyDict_SetItemString(dict, "ItemDesc", PyInt_FromLong( (signed) item->GetItemDesc( (bool) identified )) );
5865 int price = item->Price * store->SellMarkup / 100;
5866 //calculate depreciation too
5867 //store->DepreciationRate, mount
5869 if (item->StackAmount>1) {
5870 price *= si->Usages[0];
5872 //is this correct?
5873 if (price<1) {
5874 price = 1;
5876 PyDict_SetItemString(dict, "Price", PyInt_FromLong( price ) );
5878 gamedata->FreeItem( item, si->ItemResRef, false );
5879 return dict;
5882 PyDoc_STRVAR( GemRB_GetStoreDrink__doc,
5883 "GetStoreDrink(idx) => dictionary\n\n"
5884 "Returns the drink structure indexed. Returns None if the index is wrong." );
5886 static PyObject* GemRB_GetStoreDrink(PyObject * /*self*/, PyObject* args)
5888 int index;
5890 if (!PyArg_ParseTuple( args, "i", &index )) {
5891 return AttributeError( GemRB_GetStoreDrink__doc );
5893 Store *store = core->GetCurrentStore();
5894 if (!store) {
5895 return RuntimeError("No current store!");
5897 if (index>=(int) store->DrinksCount) {
5898 Py_INCREF( Py_None );
5899 return Py_None;
5901 PyObject* dict = PyDict_New();
5902 STODrink *drink=store->GetDrink(index);
5903 PyDict_SetItemString(dict, "DrinkName", PyInt_FromLong( (signed) drink->DrinkName ));
5904 PyDict_SetItemString(dict, "Price", PyInt_FromLong( drink->Price ));
5905 PyDict_SetItemString(dict, "Strength", PyInt_FromLong( drink->Strength ));
5906 return dict;
5909 static void ReadSpecialSpells()
5911 int i;
5913 SpecialSpellsCount = 0;
5914 int table = gamedata->LoadTable("splspec");
5915 if (table>=0) {
5916 Holder<TableMgr> tab = gamedata->GetTable(table);
5917 if (!tab) goto table_loaded;
5918 SpecialSpellsCount = tab->GetRowCount();
5919 SpecialSpells = (SpellDescType *) malloc( sizeof(SpellDescType) * SpecialSpellsCount);
5920 for (i=0;i<SpecialSpellsCount;i++) {
5921 strnlwrcpy(SpecialSpells[i].resref, tab->GetRowName(i),8 );
5922 //if there are more flags, compose this value into a bitfield
5923 SpecialSpells[i].value = atoi(tab->QueryField(i,0) );
5925 table_loaded:
5926 gamedata->DelTable(table);
5930 int GetSpecialSpell(ieResRef resref)
5932 if (SpecialSpellsCount==-1) {
5933 ReadSpecialSpells();
5935 for (int i=0;i<SpecialSpellsCount;i++) {
5936 if (!strnicmp(resref, SpecialSpells[i].resref, sizeof(ieResRef))) {
5937 return SpecialSpells[i].value;
5940 return 0;
5943 //disable spells based on some circumstances
5944 int CheckSpecialSpell(ieResRef resref, Actor *actor)
5946 int sp = GetSpecialSpell(resref);
5948 //the identify spell is always disabled on the menu
5949 if (sp&SP_IDENTIFY) {
5950 return 1;
5953 //if actor is silenced, and spell cannot be cast in silence, disable it
5954 if (actor->GetStat(IE_STATE_ID) & STATE_SILENCED ) {
5955 if (!(sp&SP_SILENCE)) {
5956 return 1;
5960 return 0;
5963 static void ReadUsedItems()
5965 int i;
5967 UsedItemsCount = 0;
5968 int table = gamedata->LoadTable("item_use");
5969 if (table>=0) {
5970 Holder<TableMgr> tab = gamedata->GetTable(table);
5971 if (!tab) goto table_loaded;
5972 UsedItemsCount = tab->GetRowCount();
5973 UsedItems = (UsedItemType *) malloc( sizeof(UsedItemType) * UsedItemsCount);
5974 for (i=0;i<UsedItemsCount;i++) {
5975 strnlwrcpy(UsedItems[i].itemname, tab->GetRowName(i),8 );
5976 strnlwrcpy(UsedItems[i].username, tab->QueryField(i,0),32 );
5977 //this is an strref
5978 UsedItems[i].value = atoi(tab->QueryField(i,1) );
5980 table_loaded:
5981 gamedata->DelTable(table);
5985 static void ReadSpecialItems()
5987 int i;
5989 SpecialItemsCount = 0;
5990 int table = gamedata->LoadTable("itemspec");
5991 if (table>=0) {
5992 Holder<TableMgr> tab = gamedata->GetTable(table);
5993 if (!tab) goto table_loaded;
5994 SpecialItemsCount = tab->GetRowCount();
5995 SpecialItems = (SpellDescType *) malloc( sizeof(SpellDescType) * SpecialItemsCount);
5996 for (i=0;i<SpecialItemsCount;i++) {
5997 strnlwrcpy(SpecialItems[i].resref, tab->GetRowName(i),8 );
5998 //if there are more flags, compose this value into a bitfield
5999 SpecialItems[i].value = atoi(tab->QueryField(i,0) );
6001 table_loaded:
6002 gamedata->DelTable(table);
6006 static ieStrRef GetSpellDesc(ieResRef CureResRef)
6008 int i;
6010 if (StoreSpellsCount==-1) {
6011 StoreSpellsCount = 0;
6012 int table = gamedata->LoadTable("speldesc");
6013 if (table>=0) {
6014 Holder<TableMgr> tab = gamedata->GetTable(table);
6015 if (!tab) goto table_loaded;
6016 StoreSpellsCount = tab->GetRowCount();
6017 StoreSpells = (SpellDescType *) malloc( sizeof(SpellDescType) * StoreSpellsCount);
6018 for (i=0;i<StoreSpellsCount;i++) {
6019 strnlwrcpy(StoreSpells[i].resref, tab->GetRowName(i),8 );
6020 StoreSpells[i].value = atoi(tab->QueryField(i,0) );
6022 table_loaded:
6023 gamedata->DelTable(table);
6026 if (StoreSpellsCount==0) {
6027 Spell *spell = gamedata->GetSpell(CureResRef);
6028 if (!spell) {
6029 return 0;
6031 int ret = spell->SpellDescIdentified;
6032 gamedata->FreeSpell(spell, CureResRef, false);
6033 return ret;
6035 for (i=0;i<StoreSpellsCount;i++) {
6036 if (!strnicmp(StoreSpells[i].resref, CureResRef, 8) ) {
6037 return StoreSpells[i].value;
6040 return 0;
6043 PyDoc_STRVAR( GemRB_GetStoreCure__doc,
6044 "GetStoreCure(idx) => dictionary\n\n"
6045 "Returns the cure structure indexed. Returns None if the index is wrong." );
6047 static PyObject* GemRB_GetStoreCure(PyObject * /*self*/, PyObject* args)
6049 int index;
6051 if (!PyArg_ParseTuple( args, "i", &index )) {
6052 return AttributeError( GemRB_GetStoreCure__doc );
6054 Store *store = core->GetCurrentStore();
6055 if (!store) {
6056 return RuntimeError("No current store!");
6058 if (index>=(int) store->CuresCount) {
6059 Py_INCREF( Py_None );
6060 return Py_None;
6062 PyObject* dict = PyDict_New();
6063 STOCure *cure=store->GetCure(index);
6064 PyDict_SetItemString(dict, "CureResRef", PyString_FromResRef( cure->CureResRef ));
6065 PyDict_SetItemString(dict, "Price", PyInt_FromLong( cure->Price ));
6066 PyDict_SetItemString(dict, "Description", PyInt_FromLong( (signed) GetSpellDesc(cure->CureResRef) ) );
6067 return dict;
6070 PyDoc_STRVAR( GemRB_ExecuteString__doc,
6071 "ExecuteString(String[,PC])\n\n"
6072 "Executes an In-Game Script Action in the current Area Script Context. "
6073 "If a number was given, it will execute the action in the numbered PC's context." );
6075 static PyObject* GemRB_ExecuteString(PyObject * /*self*/, PyObject* args)
6077 char* String;
6078 int actornum=0;
6080 if (!PyArg_ParseTuple( args, "s|i", &String, &actornum )) {
6081 return AttributeError( GemRB_ExecuteString__doc );
6083 Game *game = core->GetGame();
6084 if (!game) {
6085 return RuntimeError( "No game loaded!" );
6087 if (actornum) {
6088 Actor *pc = game->FindPC(actornum);
6089 if (pc) {
6090 GameScript::ExecuteString( pc, String );
6091 } else {
6092 printMessage("GUIScript","Player not found!\n", YELLOW);
6094 } else {
6095 GameScript::ExecuteString( game->GetCurrentArea( ), String );
6097 Py_INCREF( Py_None );
6098 return Py_None;
6101 PyDoc_STRVAR( GemRB_RunEventHandler__doc,
6102 "RunEventHandler(String[, error])\n\n"
6103 "Executes a GUIScript event handler function named String. "
6104 "If error is set to nonzero, then a missing handler will cause an error." );
6106 static PyObject* GemRB_RunEventHandler(PyObject * /*self*/, PyObject* args)
6108 char* String;
6109 int error = 0;
6111 if (!PyArg_ParseTuple( args, "s|i", &String, error )) {
6112 return AttributeError( GemRB_RunEventHandler__doc );
6114 core->GetGUIScriptEngine()->RunFunction( String, error );
6115 Py_INCREF( Py_None );
6116 return Py_None;
6119 PyDoc_STRVAR( GemRB_EvaluateString__doc,
6120 "EvaluateString(String)\n\n"
6121 "Evaluate an In-Game Script Trigger in the current Area Script Context." );
6123 static PyObject* GemRB_EvaluateString(PyObject * /*self*/, PyObject* args)
6125 char* String;
6127 if (!PyArg_ParseTuple( args, "s", &String )) {
6128 return AttributeError( GemRB_EvaluateString__doc );
6130 if (GameScript::EvaluateString( core->GetGame()->GetCurrentArea( ), String )) {
6131 printf( "%s returned True\n", String );
6132 } else {
6133 printf( "%s returned False\n", String );
6135 Py_INCREF( Py_None );
6136 return Py_None;
6139 PyDoc_STRVAR( GemRB_UpdateMusicVolume__doc,
6140 "UpdateMusicVolume()\n\n"
6141 "Update music volume on-the-fly." );
6143 static PyObject* GemRB_UpdateMusicVolume(PyObject * /*self*/, PyObject* /*args*/)
6145 core->GetAudioDrv()->UpdateVolume( GEM_SND_VOL_MUSIC );
6147 Py_INCREF( Py_None );
6148 return Py_None;
6151 PyDoc_STRVAR( GemRB_UpdateAmbientsVolume__doc,
6152 "UpdateAmbientsVolume()\n\n"
6153 "Update ambients volume on-the-fly." );
6155 static PyObject* GemRB_UpdateAmbientsVolume(PyObject * /*self*/, PyObject* /*args*/)
6157 core->GetAudioDrv()->UpdateVolume( GEM_SND_VOL_AMBIENTS );
6159 Py_INCREF( Py_None );
6160 return Py_None;
6163 PyDoc_STRVAR( GemRB_GetCurrentArea__doc,
6164 "GetCurrentArea()=>resref\n\n"
6165 "Returns current area's ResRef." );
6167 static PyObject* GemRB_GetCurrentArea(PyObject * /*self*/, PyObject* /*args*/)
6169 return PyString_FromString( core->GetGame()->CurrentArea );
6172 PyDoc_STRVAR( GemRB_MoveToArea__doc,
6173 "MoveToArea(resref)\n\n"
6174 "Moves the selected characters to the area." );
6176 static PyObject* GemRB_MoveToArea(PyObject * /*self*/, PyObject* args)
6178 const char *String;
6180 if (!PyArg_ParseTuple( args, "s", &String )) {
6181 return AttributeError( GemRB_MoveToArea__doc );
6183 Game *game = core->GetGame();
6184 if (!game) {
6185 return RuntimeError( "No game loaded!" );
6187 Map* map2 = game->GetMap(String, true);
6188 if (!map2) {
6189 return RuntimeError( "Map not found!" );
6191 int i = game->GetPartySize(true);
6192 while (i--) {
6193 Actor* actor = game->GetPC(i, false);
6194 if (!actor->Selected) {
6195 continue;
6197 Map* map1 = actor->GetCurrentArea();
6198 if (map1) {
6199 map1->RemoveActor( actor );
6201 map2->AddActor( actor );
6204 Py_INCREF( Py_None );
6205 return Py_None;
6208 PyDoc_STRVAR( GemRB_GetMemorizableSpellsCount__doc,
6209 "GetMemorizableSpellsCount(PartyID, SpellType, Level [,Bonus])=>int\n\n"
6210 "Returns number of memorizable spells of given type and level in PC's spellbook." );
6212 static PyObject* GemRB_GetMemorizableSpellsCount(PyObject* /*self*/, PyObject* args)
6214 int PartyID, SpellType, Level, Bonus=1;
6216 if (!PyArg_ParseTuple( args, "iii|i", &PartyID, &SpellType, &Level, &Bonus )) {
6217 return AttributeError( GemRB_GetMemorizableSpellsCount__doc );
6219 Game *game = core->GetGame();
6220 if (!game) {
6221 return RuntimeError( "No game loaded!" );
6223 Actor* actor = game->FindPC( PartyID );
6224 if (!actor) {
6225 return RuntimeError( "Actor not found" );
6228 //this isn't in the actor's spellbook, handles Wisdom
6229 return PyInt_FromLong(actor->spellbook.GetMemorizableSpellsCount( (ieSpellType) SpellType, Level, (bool) Bonus ) );
6232 PyDoc_STRVAR( GemRB_SetMemorizableSpellsCount__doc,
6233 "SetMemorizableSpellsCount(PartyID, Value, SpellType, Level, [Bonus])=>int\n\n"
6234 "Sets number of memorizable spells of given type and level in PC's spellbook." );
6236 static PyObject* GemRB_SetMemorizableSpellsCount(PyObject* /*self*/, PyObject* args)
6238 int PartyID, Value, SpellType, Level;
6240 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &Value, &SpellType, &Level)) {
6241 return AttributeError( GemRB_SetMemorizableSpellsCount__doc );
6243 Game *game = core->GetGame();
6244 if (!game) {
6245 return RuntimeError( "No game loaded!" );
6247 Actor* actor = game->FindPC( PartyID );
6248 if (!actor) {
6249 return RuntimeError( "Actor not found" );
6252 //the bonus increased value (with wisdom too) is handled by the core
6253 actor->spellbook.SetMemorizableSpellsCount( Value, (ieSpellType) SpellType, Level, 0 );
6255 Py_INCREF( Py_None );
6256 return Py_None;
6259 PyDoc_STRVAR( GemRB_GetKnownSpellsCount__doc,
6260 "GetKnownSpellsCount(PartyID, SpellType, Level)=>int\n\n"
6261 "Returns number of known spells of given type and level in PC's spellbook." );
6263 static PyObject* GemRB_GetKnownSpellsCount(PyObject * /*self*/, PyObject* args)
6265 int PartyID, SpellType, Level;
6267 if (!PyArg_ParseTuple( args, "iii", &PartyID, &SpellType, &Level )) {
6268 return AttributeError( GemRB_GetKnownSpellsCount__doc );
6270 Game *game = core->GetGame();
6271 if (!game) {
6272 return RuntimeError( "No game loaded!" );
6274 Actor* actor = game->FindPC( PartyID );
6275 if (!actor) {
6276 return RuntimeError( "Actor not found" );
6279 return PyInt_FromLong(actor->spellbook.GetKnownSpellsCount( SpellType, Level ) );
6282 PyDoc_STRVAR( GemRB_GetKnownSpell__doc,
6283 "GetKnownSpell(PartyID, SpellType, Level, Index)=>dict\n\n"
6284 "Returns dict with specified known spell from PC's spellbook." );
6286 static PyObject* GemRB_GetKnownSpell(PyObject * /*self*/, PyObject* args)
6288 int PartyID, SpellType, Level, Index;
6290 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &SpellType, &Level, &Index )) {
6291 return AttributeError( GemRB_GetKnownSpell__doc );
6293 Game *game = core->GetGame();
6294 if (!game) {
6295 return RuntimeError( "No game loaded!" );
6297 Actor* actor = game->FindPC( PartyID );
6298 if (!actor) {
6299 return RuntimeError( "Actor not found!" );
6302 CREKnownSpell* ks = actor->spellbook.GetKnownSpell( SpellType, Level, Index );
6303 if (! ks) {
6304 return RuntimeError( "Spell not found!" );
6307 PyObject* dict = PyDict_New();
6308 PyDict_SetItemString(dict, "SpellResRef", PyString_FromResRef (ks->SpellResRef));
6309 //PyDict_SetItemString(dict, "Flags", PyInt_FromLong (ms->Flags));
6311 return dict;
6315 PyDoc_STRVAR( GemRB_GetMemorizedSpellsCount__doc,
6316 "GetMemorizedSpellsCount(PartyID, SpellType[, Level])=>int\n\n"
6317 "Returns number of spells of given type and level in PartyID's memory. "
6318 "If level is omitted then it returns the number of distinct spells memorised." );
6320 static PyObject* GemRB_GetMemorizedSpellsCount(PyObject * /*self*/, PyObject* args)
6322 int PartyID, SpellType, Level = -1;
6324 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &SpellType, &Level )) {
6325 return AttributeError( GemRB_GetMemorizedSpellsCount__doc );
6327 Game *game = core->GetGame();
6328 if (!game) {
6329 return RuntimeError( "No game loaded!" );
6331 Actor* actor = game->FindPC( PartyID );
6332 if (!actor) {
6333 return RuntimeError( "Actor not found!" );
6336 if (Level<0) {
6337 return PyInt_FromLong( actor->spellbook.GetSpellInfoSize( SpellType ) );
6338 } else {
6339 return PyInt_FromLong( actor->spellbook.GetMemorizedSpellsCount( SpellType, Level ) );
6343 PyDoc_STRVAR( GemRB_GetMemorizedSpell__doc,
6344 "GetMemorizedSpell(PartyID, SpellType, Level, Index)=>dict\n\n"
6345 "Returns dict with specified memorized spell from PC's spellbook." );
6347 static PyObject* GemRB_GetMemorizedSpell(PyObject * /*self*/, PyObject* args)
6349 int PartyID, SpellType, Level, Index;
6351 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &SpellType, &Level, &Index )) {
6352 return AttributeError( GemRB_GetMemorizedSpell__doc );
6354 Game *game = core->GetGame();
6355 if (!game) {
6356 return RuntimeError( "No game loaded!" );
6358 Actor* actor = game->FindPC( PartyID );
6359 if (!actor) {
6360 return RuntimeError( "Actor not found!" );
6363 CREMemorizedSpell* ms = actor->spellbook.GetMemorizedSpell( SpellType, Level, Index );
6364 if (! ms) {
6365 return RuntimeError( "Spell not found!" );
6368 PyObject* dict = PyDict_New();
6369 PyDict_SetItemString(dict, "SpellResRef", PyString_FromResRef (ms->SpellResRef));
6370 PyDict_SetItemString(dict, "Flags", PyInt_FromLong (ms->Flags));
6372 return dict;
6376 PyDoc_STRVAR( GemRB_GetSpell__doc,
6377 "GetSpell(ResRef[, silent])=>dict\n\n"
6378 "Returns dict with specified spell. Verbose by default." );
6380 static PyObject* GemRB_GetSpell(PyObject * /*self*/, PyObject* args)
6382 const char* ResRef;
6383 int silent = 0;
6385 if (!PyArg_ParseTuple( args, "s|i", &ResRef, &silent)) {
6386 return AttributeError( GemRB_GetSpell__doc );
6389 if (silent && !gamedata->Exists(ResRef,IE_SPL_CLASS_ID, true)) {
6390 Py_INCREF( Py_None );
6391 return Py_None;
6394 Spell* spell = gamedata->GetSpell(ResRef, silent);
6395 if (spell == NULL) {
6396 Py_INCREF( Py_None );
6397 return Py_None;
6400 PyObject* dict = PyDict_New();
6401 PyDict_SetItemString(dict, "SpellName", PyInt_FromLong ((signed) spell->SpellName));
6402 PyDict_SetItemString(dict, "SpellDesc", PyInt_FromLong ((signed) spell->SpellDesc));
6403 PyDict_SetItemString(dict, "SpellbookIcon", PyString_FromResRef (spell->SpellbookIcon));
6404 PyDict_SetItemString(dict, "SpellExclusion", PyInt_FromLong (spell->ExclusionSchool)); //this will list school exclusions and alignment
6405 PyDict_SetItemString(dict, "SpellDivine", PyInt_FromLong (spell->PriestType)); //this will tell apart a priest spell from a druid spell
6406 PyDict_SetItemString(dict, "SpellSchool", PyInt_FromLong (spell->PrimaryType));
6407 PyDict_SetItemString(dict, "SpellType", PyInt_FromLong (spell->SecondaryType));
6408 PyDict_SetItemString(dict, "SpellLevel", PyInt_FromLong (spell->SpellLevel));
6409 gamedata->FreeSpell( spell, ResRef, false );
6410 return dict;
6414 PyDoc_STRVAR( GemRB_LearnSpell__doc,
6415 "LearnSpell(PartyID, SpellResRef[, Flags])=>int\n\n"
6416 "Learns specified spell. Returns 0 on success." );
6418 static PyObject* GemRB_LearnSpell(PyObject * /*self*/, PyObject* args)
6420 int PartyID;
6421 const char *Spell;
6422 int Flags=0;
6424 if (!PyArg_ParseTuple( args, "is|i", &PartyID, &Spell, &Flags )) {
6425 return AttributeError( GemRB_LearnSpell__doc );
6427 Game *game = core->GetGame();
6428 if (!game) {
6429 return RuntimeError( "No game loaded!" );
6431 Actor* actor = game->FindPC( PartyID );
6432 if (!actor) {
6433 return RuntimeError( "Actor not found" );
6436 int ret = actor->LearnSpell( Spell, Flags ); // returns 0 on success
6437 if (!ret) core->SetEventFlag( EF_ACTION );
6438 return PyInt_FromLong( ret );
6441 PyDoc_STRVAR( GemRB_DispelEffect__doc,
6442 "DispelEffect(PartyID, EffectName, Parameter2)\n\n"
6443 "Removes all effects from target whose opcode and second parameter matches the arguments." );
6445 static EffectRef work_ref;
6447 static PyObject* GemRB_DispelEffect(PyObject * /*self*/, PyObject* args)
6449 int PartyID, Parameter2;
6450 const char *EffectName;
6452 if (!PyArg_ParseTuple( args, "isi", &PartyID, &EffectName, &Parameter2 )) {
6453 return AttributeError( GemRB_DispelEffect__doc );
6455 Game *game = core->GetGame();
6456 if (!game) {
6457 return RuntimeError( "No game loaded!" );
6459 Actor* actor = game->FindPC( PartyID );
6460 if (!actor) {
6461 return RuntimeError( "Actor not found!" );
6464 work_ref.Name=EffectName;
6465 work_ref.opcode=-1;
6466 actor->fxqueue.RemoveAllEffectsWithParam(work_ref, Parameter2);
6468 Py_INCREF( Py_None );
6469 return Py_None;
6473 PyDoc_STRVAR( GemRB_RemoveEffects__doc,
6474 "RemoveEffects(PartyID, SpellResRef)\n\n"
6475 "Removes all effects from target whose source is SpellResRef." );
6477 static PyObject* GemRB_RemoveEffects(PyObject * /*self*/, PyObject* args)
6479 int PartyID;
6480 const char * SpellResRef;
6482 if (!PyArg_ParseTuple( args, "is", &PartyID, &SpellResRef )) {
6483 return AttributeError( GemRB_RemoveEffects__doc );
6485 Game *game = core->GetGame();
6486 if (!game) {
6487 return RuntimeError( "No game loaded!" );
6489 Actor* actor = game->FindPC( PartyID );
6490 if (!actor) {
6491 return RuntimeError( "Actor not found!" );
6494 actor->fxqueue.RemoveAllEffects(SpellResRef);
6496 Py_INCREF( Py_None );
6497 return Py_None;
6500 PyDoc_STRVAR( GemRB_RemoveSpell__doc,
6501 "RemoveSpell(PartyID, SpellType, Level, Index)=>bool\n\n"
6502 "Removes specified known spell. Returns 1 on success." );
6504 static PyObject* GemRB_RemoveSpell(PyObject * /*self*/, PyObject* args)
6506 int PartyID, SpellType, Level, Index;
6508 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &SpellType, &Level, &Index )) {
6509 return AttributeError( GemRB_RemoveSpell__doc );
6511 Game *game = core->GetGame();
6512 if (!game) {
6513 return RuntimeError( "No game loaded!" );
6515 Actor* actor = game->FindPC( PartyID );
6516 if (!actor) {
6517 return RuntimeError( "Actor not found!" );
6520 CREKnownSpell* ks = actor->spellbook.GetKnownSpell( SpellType, Level, Index );
6521 if (! ks) {
6522 return RuntimeError( "Spell not known!" );
6525 return PyInt_FromLong( actor->spellbook.RemoveSpell( ks ) );
6528 PyDoc_STRVAR( GemRB_RemoveItem__doc,
6529 "RemoveItem(PartyID, Slot[, Count])=>bool\n\n"
6530 "Removes (or decreases the charges) of a specified item. Returns 1 on success." );
6532 static PyObject* GemRB_RemoveItem(PyObject * /*self*/, PyObject* args)
6534 int PartyID, Slot;
6535 int Count = 0;
6537 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &Slot, &Count )) {
6538 return AttributeError( GemRB_RemoveItem__doc );
6540 Game *game = core->GetGame();
6541 if (!game) {
6542 return RuntimeError( "No game loaded!" );
6544 Actor* actor = game->FindPC( PartyID );
6545 if (!actor) {
6546 return RuntimeError( "Actor not found!" );
6549 int ok;
6551 Slot = core->QuerySlot(Slot);
6552 actor->inventory.UnEquipItem( Slot, false );
6553 CREItem *si = actor->inventory.RemoveItem( Slot, Count );
6554 if (si) {
6555 ok = true;
6556 delete si;
6557 } else {
6558 ok = false;
6560 return PyInt_FromLong( ok );
6563 PyDoc_STRVAR( GemRB_MemorizeSpell__doc,
6564 "MemorizeSpell(PartyID, SpellType, Level, Index)=>bool\n\n"
6565 "Memorizes specified known spell. Returns 1 on success." );
6567 static PyObject* GemRB_MemorizeSpell(PyObject * /*self*/, PyObject* args)
6569 int PartyID, SpellType, Level, Index;
6571 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &SpellType, &Level, &Index )) {
6572 return AttributeError( GemRB_MemorizeSpell__doc );
6574 Game *game = core->GetGame();
6575 if (!game) {
6576 return RuntimeError( "No game loaded!" );
6578 Actor* actor = game->FindPC( PartyID );
6579 if (!actor) {
6580 return RuntimeError( "Actor not found!" );
6583 CREKnownSpell* ks = actor->spellbook.GetKnownSpell( SpellType, Level, Index );
6584 if (! ks) {
6585 return RuntimeError( "Spell not found!" );
6588 bool enabled = false;
6589 if (SpellType == IE_SPELL_TYPE_INNATE) enabled = true;
6591 return PyInt_FromLong( actor->spellbook.MemorizeSpell( ks, enabled ) );
6595 PyDoc_STRVAR( GemRB_UnmemorizeSpell__doc,
6596 "UnmemorizeSpell(PartyID, SpellType, Level, Index)=>bool\n\n"
6597 "Unmemorizes specified known spell. Returns 1 on success." );
6599 static PyObject* GemRB_UnmemorizeSpell(PyObject * /*self*/, PyObject* args)
6601 int PartyID, SpellType, Level, Index;
6603 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &SpellType, &Level, &Index )) {
6604 return AttributeError( GemRB_UnmemorizeSpell__doc );
6606 Game *game = core->GetGame();
6607 if (!game) {
6608 return RuntimeError( "No game loaded!" );
6610 Actor* actor = game->FindPC( PartyID );
6611 if (!actor) {
6612 return RuntimeError( "Actor not found!" );
6615 CREMemorizedSpell* ms = actor->spellbook.GetMemorizedSpell( SpellType, Level, Index );
6616 if (! ms) {
6617 return RuntimeError( "Spell not found!" );
6620 return PyInt_FromLong( actor->spellbook.UnmemorizeSpell( ms ) );
6623 PyDoc_STRVAR( GemRB_GetSlotItem__doc,
6624 "GetSlotItem(PartyID, slot)=>dict\n\n"
6625 "Returns dict with specified slot item from PC's inventory or the dragged item if PartyID is 0." );
6627 static PyObject* GemRB_GetSlotItem(PyObject * /*self*/, PyObject* args)
6629 int PartyID, Slot;
6631 if (!PyArg_ParseTuple( args, "ii", &PartyID, &Slot)) {
6632 return AttributeError( GemRB_GetSlotItem__doc );
6634 CREItem *si;
6635 int header = -1;
6637 if (PartyID==0) {
6638 si = core->GetDraggedItem();
6639 } else {
6640 Game *game = core->GetGame();
6641 if (!game) {
6642 return RuntimeError( "No game loaded!" );
6644 Actor *actor = game->FindPC( PartyID );
6645 if (!actor) {
6646 return RuntimeError( "Actor not found" );
6649 Slot = core->QuerySlot(Slot);
6650 header = actor->PCStats->GetHeaderForSlot(Slot);
6652 si = actor->inventory.GetSlotItem( Slot );
6654 if (! si) {
6655 Py_INCREF( Py_None );
6656 return Py_None;
6658 PyObject* dict = PyDict_New();
6659 PyDict_SetItemString(dict, "ItemResRef", PyString_FromResRef (si->ItemResRef));
6660 PyDict_SetItemString(dict, "Usages0", PyInt_FromLong (si->Usages[0]));
6661 PyDict_SetItemString(dict, "Usages1", PyInt_FromLong (si->Usages[1]));
6662 PyDict_SetItemString(dict, "Usages2", PyInt_FromLong (si->Usages[2]));
6663 PyDict_SetItemString(dict, "Flags", PyInt_FromLong (si->Flags));
6664 PyDict_SetItemString(dict, "Header", PyInt_FromLong (header));
6666 return dict;
6669 PyDoc_STRVAR( GemRB_ChangeItemFlag__doc,
6670 "ChangeItemFlag(PartyID, slot, flags, op) => bool\n\n"
6671 "Changes an item flag of a player character in inventory slot. Returns false if failed." );
6673 static PyObject* GemRB_ChangeItemFlag(PyObject * /*self*/, PyObject* args)
6675 int PartyID, Slot, Flags, Mode;
6677 if (!PyArg_ParseTuple( args, "iiii", &PartyID, &Slot, &Flags, &Mode)) {
6678 return AttributeError( GemRB_ChangeItemFlag__doc );
6680 Game *game = core->GetGame();
6681 if (!game) {
6682 return RuntimeError( "No game loaded!" );
6684 Actor *actor = game->FindPC( PartyID );
6685 if (!actor) {
6686 return RuntimeError( "Actor not found" );
6688 if (actor->inventory.ChangeItemFlag(core->QuerySlot(Slot), Flags, Mode)) {
6689 return PyInt_FromLong(1);
6691 return PyInt_FromLong(0);
6695 PyDoc_STRVAR( GemRB_CanUseItemType__doc,
6696 "CanUseItemType( slottype, itemname[, actor])=>bool\n\n"
6697 "Checks the itemtype vs. slottype, and also checks the usability flags vs. Actor's stats (alignment, class, race, kit etc.)" );
6699 static PyObject* GemRB_CanUseItemType(PyObject * /*self*/, PyObject* args)
6701 int SlotType, PartyID;
6702 const char *ItemName;
6704 PartyID = 0;
6705 if (!PyArg_ParseTuple( args, "is|i", &SlotType, &ItemName, &PartyID)) {
6706 return AttributeError( GemRB_CanUseItemType__doc );
6708 if (!ItemName[0]) {
6709 return PyInt_FromLong(0);
6711 Item *item = gamedata->GetItem(ItemName);
6712 if (!item) {
6713 return PyInt_FromLong(0);
6715 Actor* actor = 0;
6716 if (PartyID) {
6717 Game *game = core->GetGame();
6718 if (!game) {
6719 return RuntimeError( "No game loaded!" );
6721 actor = game->FindPC( PartyID );
6722 if (!actor) {
6723 return RuntimeError( "Actor not found" );
6727 int ret=core->CanUseItemType(SlotType, item, actor, false);
6728 gamedata->FreeItem(item, ItemName, false);
6729 return PyInt_FromLong(ret);
6733 PyDoc_STRVAR( GemRB_GetSlots__doc,
6734 "GetSlots(PartyID, SlotType[,flag])=>dict\n\n"
6735 "Returns a tuple of slots of the inventory of a PC matching the slot type criteria.\n"
6736 "If the flag is >0, it will ignore empty slots.\n"
6737 "If the flag is <0, it will ignore filled slots.\n"
6738 "If the flag is 0, it will return all slots.\n"
6739 "The default is 1." );
6741 static PyObject* GemRB_GetSlots(PyObject * /*self*/, PyObject* args)
6743 int SlotType, Count, MaxCount, PartyID;
6744 int flag = 1;
6746 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &SlotType, &flag)) {
6747 return AttributeError( GemRB_GetSlots__doc );
6750 Game *game = core->GetGame();
6751 if (!game) {
6752 return RuntimeError( "No game loaded!" );
6754 Actor* actor = game->FindPC( PartyID );
6755 if (!actor) {
6756 return RuntimeError( "Actor not found" );
6759 MaxCount = core->SlotTypes;
6760 int i;
6761 Count = 0;
6762 for (i=0;i<MaxCount;i++) {
6763 int id = core->QuerySlot(i);
6764 if ((core->QuerySlotType( id ) & (ieDword) SlotType) != (ieDword) SlotType) {
6765 continue;
6767 CREItem *slot = actor->inventory.GetSlotItem( id );
6768 if (flag) {
6769 if(flag<0 && slot) continue;
6770 if(flag>0 && !slot) continue;
6772 Count++;
6775 PyObject* tuple = PyTuple_New( Count );
6776 Count = 0;
6777 for (i=0;i<MaxCount;i++) {
6778 int id = core->QuerySlot(i);
6779 if ((core->QuerySlotType( id ) & (ieDword) SlotType) != (ieDword) SlotType) {
6780 continue;
6782 CREItem *slot = actor->inventory.GetSlotItem( id );
6783 if (flag) {
6784 if(flag<0 && slot) continue;
6785 if(flag>0 && !slot) continue;
6787 PyTuple_SetItem( tuple, Count++, PyInt_FromLong( i ) );
6790 return tuple;
6793 PyDoc_STRVAR( GemRB_GetItem__doc,
6794 "GetItem(ResRef)=>dict\n\n"
6795 "Returns dict with specified item." );
6797 #define CAN_DRINK 1 //potions
6798 #define CAN_READ 2 //scrolls
6799 #define CAN_STUFF 4 //containers
6800 #define CAN_SELECT 8 //items with more abilities
6802 static PyObject* GemRB_GetItem(PyObject * /*self*/, PyObject* args)
6804 char* ResRef;
6805 int PartyID = 0;
6806 Actor *actor = NULL;
6808 if (!PyArg_ParseTuple( args, "s|i", &ResRef, &PartyID)) {
6809 return AttributeError( GemRB_GetItem__doc );
6811 //it isn't a problem if actor not found
6812 Game *game = core->GetGame();
6813 if (game) {
6814 if (!PartyID) {
6815 PartyID = game->GetSelectedPCSingle();
6817 actor = game->FindPC( PartyID );
6820 Item* item = gamedata->GetItem(ResRef);
6821 if (item == NULL) {
6822 Py_INCREF( Py_None );
6823 return Py_None;
6826 PyObject* dict = PyDict_New();
6827 PyDict_SetItemString(dict, "ItemName", PyInt_FromLong ((signed) item->GetItemName(false)));
6828 PyDict_SetItemString(dict, "ItemNameIdentified", PyInt_FromLong ((signed) item->GetItemName(true)));
6829 PyDict_SetItemString(dict, "ItemDesc", PyInt_FromLong ((signed) item->GetItemDesc(false)));
6830 PyDict_SetItemString(dict, "ItemDescIdentified", PyInt_FromLong ((signed)item->GetItemDesc(true)));
6831 PyDict_SetItemString(dict, "ItemIcon", PyString_FromResRef (item->ItemIcon));
6832 PyDict_SetItemString(dict, "DescIcon", PyString_FromResRef (item->DescriptionIcon));
6833 PyDict_SetItemString(dict, "BrokenItem", PyString_FromResRef (item->ReplacementItem));
6834 PyDict_SetItemString(dict, "StackAmount", PyInt_FromLong (item->StackAmount));
6835 PyDict_SetItemString(dict, "Dialog", PyString_FromResRef (item->Dialog));
6836 PyDict_SetItemString(dict, "DialogName", PyInt_FromLong ((signed)item->DialogName));
6837 PyDict_SetItemString(dict, "Price", PyInt_FromLong (item->Price));
6838 PyDict_SetItemString(dict, "Type", PyInt_FromLong (item->ItemType));
6839 PyDict_SetItemString(dict, "AnimationType", PyString_FromAnimID(item->AnimationType));
6840 PyDict_SetItemString(dict, "Exclusion", PyInt_FromLong(item->ItemExcl));
6841 PyDict_SetItemString(dict, "LoreToID", PyInt_FromLong(item->LoreToID));
6843 int ehc = item->ExtHeaderCount;
6845 PyObject* tooltiptuple = PyTuple_New(ehc);
6846 for(int i=0;i<ehc;i++) {
6847 int tip = core->GetItemTooltip(ResRef, i, 1);
6848 PyTuple_SetItem(tooltiptuple, i, PyInt_FromLong(tip));
6851 PyDict_SetItemString(dict, "Tooltips", tooltiptuple);
6853 int function=0;
6855 if (core->CanUseItemType(SLOT_POTION, item, actor, false) ) {
6856 function|=CAN_DRINK;
6858 if (core->CanUseItemType(SLOT_SCROLL, item, actor, false) ) {
6859 ITMExtHeader *eh;
6860 Effect *f;
6861 //determining if this is a copyable scroll
6862 if (ehc<2) {
6863 goto not_a_scroll;
6865 eh = item->ext_headers+1;
6866 if (eh->FeatureCount<1) {
6867 goto not_a_scroll;
6869 f = eh->features; //+0
6871 //normally the learn spell opcode is 147
6872 EffectQueue::ResolveEffect(fx_learn_spell_ref);
6873 if (f->Opcode!=(ieDword) fx_learn_spell_ref.opcode) {
6874 goto not_a_scroll;
6876 //maybe further checks for school exclusion?
6877 //no, those were done by CanUseItemType
6878 function|=CAN_READ;
6879 PyDict_SetItemString(dict, "Spell", PyString_FromResRef (f->Resource));
6880 } else if (ehc>1) {
6881 function|=CAN_SELECT;
6883 not_a_scroll:
6884 if (core->CanUseItemType(SLOT_BAG, item, NULL, false) ) {
6885 //allow the open container flag only if there is
6886 //a store file (this fixes pst eye items, which
6887 //got the same item type as bags)
6888 //while this isn't required anymore, as bag itemtypes are customisable
6889 //we still better check for the existence of the store, or we
6890 //get a crash somewhere.
6891 if (gamedata->Exists( ResRef, IE_STO_CLASS_ID) ) {
6892 function|=CAN_STUFF;
6895 PyDict_SetItemString(dict, "Function", PyInt_FromLong(function));
6896 gamedata->FreeItem( item, ResRef, false );
6897 return dict;
6900 void DragItem(CREItem *si)
6902 if (!si) {
6903 return;
6905 Item *item = gamedata->GetItem (si->ItemResRef );
6906 if (!item) {
6907 return;
6909 core->DragItem(si, item->ItemIcon);
6910 gamedata->FreeItem( item, si->ItemResRef, false );
6913 int CheckRemoveItem(Actor *actor, CREItem *si)
6915 ///check if item is undroppable because the actor likes it
6916 if (UsedItemsCount==-1) {
6917 ReadUsedItems();
6919 unsigned int i=UsedItemsCount;
6921 while(i--) {
6922 if (UsedItems[i].itemname[0] && strnicmp(UsedItems[i].itemname, si->ItemResRef,8) ) {
6923 continue;
6925 if (UsedItems[i].username[0] && strnicmp(UsedItems[i].username, actor->GetScriptName(), 32) ) {
6926 continue;
6928 core->DisplayString(UsedItems[i].value,0xffffff, IE_STR_SOUND);
6929 return 1;
6931 return 0;
6934 CREItem *TryToUnequip(Actor *actor, unsigned int Slot, unsigned int Count)
6936 //we should use getslotitem, because
6937 //getitem would remove the item from the inventory!
6938 CREItem *si = actor->inventory.GetSlotItem(Slot);
6939 if (!si) {
6940 return NULL;
6943 //it is always possible to put these items into the inventory
6944 if (!(core->QuerySlotType(Slot)&SLOT_INVENTORY)) {
6945 if (CheckRemoveItem(actor, si)) {
6946 return NULL;
6949 ///fixme: make difference between cursed/unmovable
6950 if (! actor->inventory.UnEquipItem( Slot, false )) {
6951 // Item is currently undroppable/cursed
6952 core->DisplayConstantString(STR_CANT_DROP_ITEM,0xffffff);
6953 return NULL;
6955 si = actor->inventory.RemoveItem( Slot, Count );
6956 return si;
6959 PyDoc_STRVAR( GemRB_DragItem__doc,
6960 "DragItem(PartyID, Slot, ResRef, [Count=0, Type])\n\n"
6961 "Start dragging specified item, if Slot is negative, drag the PartyID portrait instead." );
6963 static PyObject* GemRB_DragItem(PyObject * /*self*/, PyObject* args)
6965 ieResRef Sound;
6966 int PartyID, Slot, Count = 0, Type = 0;
6967 const char *ResRef;
6969 if (!PyArg_ParseTuple( args, "iis|ii", &PartyID, &Slot, &ResRef, &Count, &Type)) {
6970 return AttributeError( GemRB_DragItem__doc );
6973 // FIXME
6974 // we should Drop the Dragged item in place of the current item
6975 // but only if the current item is draggable, tough!
6976 if (core->GetDraggedItem()) {
6977 Py_INCREF( Py_None );
6978 return Py_None;
6981 Game *game = core->GetGame();
6982 if (!game) {
6983 return RuntimeError( "No game loaded!" );
6985 Actor* actor = game->FindPC( PartyID );
6986 //allow -1,-1
6987 if (!actor && ( PartyID || ResRef[0]) ) {
6988 return RuntimeError( "Actor not found" );
6991 //dragging a portrait
6992 if (!ResRef[0]) {
6993 core->SetDraggedPortrait(PartyID, Slot);
6994 Py_INCREF( Py_None );
6995 return Py_None;
6998 if ((unsigned int) Slot>core->GetInventorySize()) {
6999 return AttributeError( "Invalid slot" );
7001 CREItem* si;
7002 if (Type) {
7003 Map *map = actor->GetCurrentArea();
7004 Container *cc = map->GetPile(actor->Pos);
7005 if (!cc) {
7006 return RuntimeError( "No current container" );
7008 si = cc->RemoveItem(Slot, Count);
7009 } else {
7010 si = TryToUnequip( actor, core->QuerySlot(Slot), Count );
7011 actor->RefreshEffects(NULL);
7012 printf("Actor ac:%d\n", actor->Modified[IE_ARMORCLASS]);
7013 actor->ReinitQuickSlots();
7014 core->SetEventFlag(EF_SELECTION);
7016 if (! si) {
7017 Py_INCREF( Py_None );
7018 return Py_None;
7021 Item *item = gamedata->GetItem(si->ItemResRef);
7022 if (item) {
7023 if (core->HasFeature(GF_HAS_PICK_SOUND) && item->DescriptionIcon[0]) {
7024 memcpy(Sound,item->DescriptionIcon,sizeof(ieResRef));
7025 } else {
7026 GetItemSound(Sound, item->ItemType, item->AnimationType, IS_GET);
7028 gamedata->FreeItem(item, si->ItemResRef,0);
7030 if (Sound[0]) {
7031 core->GetAudioDrv()->Play(Sound);
7034 //if res is positive, it is gold!
7035 int res = core->CanMoveItem(si);
7036 if (res>0) {
7037 game->AddGold(res);
7038 delete si;
7039 Py_INCREF( Py_None );
7040 return Py_None;
7043 core->DragItem (si, ResRef);
7044 Py_INCREF( Py_None );
7045 return Py_None;
7048 PyDoc_STRVAR( GemRB_DropDraggedItem__doc,
7049 "DropDraggedItem(PartyID, Slot)=>int\n\n"
7050 "Put currently dragged item to specified PC and slot. "
7051 "If Slot==-1, puts it to a first usable slot. "
7052 "If Slot==-2, puts it to a ground pile. "
7053 "If Slot==-3, puts it to the first empty inventory slot. "
7054 "Returns 0 (unsuccessful), 1 (partial success) or 2 (complete success)."
7055 "Can also return 3 (swapped item)\n" );
7057 static PyObject* GemRB_DropDraggedItem(PyObject * /*self*/, PyObject* args)
7059 ieResRef Sound;
7060 int PartyID, Slot;
7062 if (!PyArg_ParseTuple( args, "ii", &PartyID, &Slot)) {
7063 return AttributeError( GemRB_DropDraggedItem__doc );
7066 // FIXME
7067 if (core->GetDraggedItem() == NULL) {
7068 Py_INCREF( Py_None );
7069 return Py_None;
7072 Game *game = core->GetGame();
7073 if (!game) {
7074 return RuntimeError( "No game loaded!" );
7076 Actor* actor = game->FindPC( PartyID );
7077 if (!actor) {
7078 return RuntimeError( "Actor not found" );
7081 int res;
7083 if (Slot==-2) {
7084 Map *map = actor->GetCurrentArea();
7085 Container *cc = map->GetPile(actor->Pos);
7086 if (!cc) {
7087 return RuntimeError( "No current container" );
7089 CREItem *si = core->GetDraggedItem();
7090 res = cc->AddItem(si);
7091 Item *item = gamedata->GetItem(si->ItemResRef);
7092 if (item) {
7093 if (core->HasFeature(GF_HAS_PICK_SOUND) && item->ReplacementItem[0]) {
7094 memcpy(Sound,item->ReplacementItem,sizeof(ieResRef));
7095 } else {
7096 GetItemSound(Sound, item->ItemType, item->AnimationType, IS_DROP);
7098 gamedata->FreeItem(item, si->ItemResRef,0);
7099 if (Sound[0]) {
7100 core->GetAudioDrv()->Play(Sound);
7103 if (res == 2) {
7104 // Whole amount was placed
7105 core->ReleaseDraggedItem ();
7107 return PyInt_FromLong( res );
7110 int Slottype, Effect;
7111 switch(Slot) {
7112 case -1:
7113 //anything but inventory
7114 Slottype = ~SLOT_INVENTORY;
7115 Effect = 1;
7116 break;
7117 case -3:
7118 //only inventory
7119 Slottype = -1;
7120 Effect = 0;
7121 break;
7122 default:
7123 Slot = core->QuerySlot(Slot);
7124 Slottype = core->QuerySlotType( Slot );
7125 Effect = core->QuerySlotEffects( Slot );
7127 CREItem * slotitem = core->GetDraggedItem();
7128 Item *item = gamedata->GetItem( slotitem->ItemResRef );
7129 if (!item) {
7130 return PyInt_FromLong( -1 );
7133 // can't equip item because of similar already equipped
7134 if (Effect) {
7135 if (item->ItemExcl & actor->inventory.GetEquipExclusion(Slot)) {
7136 core->DisplayConstantString(STR_ITEMEXCL, 0xf0f0f0);
7137 //freeing the item before returning
7138 gamedata->FreeItem( item, slotitem->ItemResRef, false );
7139 return PyInt_FromLong( 0 );
7143 // can't equip item because it is not identified
7144 if ( (Slottype == SLOT_ITEM) && !(slotitem->Flags&IE_INV_ITEM_IDENTIFIED)) {
7145 ITMExtHeader *eh = item->GetExtHeader(0);
7146 if (eh && eh->IDReq) {
7147 core->DisplayConstantString(STR_ITEMID, 0xf0f0f0);
7148 gamedata->FreeItem( item, slotitem->ItemResRef, false );
7149 return PyInt_FromLong( 0 );
7153 //CanUseItemType will check actor's class bits too
7154 Slottype = core->CanUseItemType (Slottype, item, actor, true);
7155 //resolve the equipping sound, it needs to be resolved before
7156 //the item is freed
7157 if (core->HasFeature(GF_HAS_PICK_SOUND) && item->ReplacementItem[0]) {
7158 memcpy(Sound, item->ReplacementItem, 9);
7159 } else {
7160 GetItemSound(Sound, item->ItemType, item->AnimationType, IS_DROP);
7163 //freeing the item before returning
7164 gamedata->FreeItem( item, slotitem->ItemResRef, false );
7165 if ( !Slottype) {
7166 return PyInt_FromLong( 0 );
7168 res = actor->inventory.AddSlotItem( slotitem, Slot, Slottype );
7169 if (res) {
7170 //release it only when fully placed
7171 if (res==ASI_SUCCESS) {
7172 core->ReleaseDraggedItem ();
7174 //EquipItem (in AddSlotItem) already called RefreshEffects
7175 actor->ReinitQuickSlots();
7176 //couldn't place item there, try swapping (only if slot is explicit)
7177 } else if ( Slot >= 0 ) {
7178 //swapping won't cure this
7179 res = actor->inventory.WhyCantEquip(Slot, slotitem->Flags&IE_INV_ITEM_TWOHANDED);
7180 if (res) {
7181 core->DisplayConstantString(res,0xffffff);
7182 return PyInt_FromLong( 0 );
7184 CREItem *tmp = TryToUnequip(actor, Slot, 0 );
7185 if (tmp) {
7186 //this addslotitem MUST succeed because the slot was
7187 //just emptied (canuseitemtype already confirmed too)
7188 actor->inventory.AddSlotItem( slotitem, Slot, Slottype );
7189 core->ReleaseDraggedItem ();
7190 DragItem(tmp);
7191 // switched items, not returned by normal AddSlotItem
7192 res = ASI_SWAPPED;
7193 //EquipItem (in AddSlotItem) already called RefreshEffects
7194 actor->RefreshEffects(NULL);
7195 actor->ReinitQuickSlots();
7196 core->SetEventFlag(EF_SELECTION);
7197 } else {
7198 res = ASI_FAILED;
7201 if (Sound[0]) {
7202 core->GetAudioDrv()->Play(Sound);
7204 return PyInt_FromLong( res );
7207 PyDoc_STRVAR( GemRB_IsDraggingItem__doc,
7208 "IsDraggingItem()=>int\n\n"
7209 "Returns 1 if we are dragging some item.\n"
7210 "Returns 2 if we are dragging a portrait." );
7212 static PyObject* GemRB_IsDraggingItem(PyObject * /*self*/, PyObject* /*args*/)
7214 if (core->GetDraggedPortrait()) {
7215 return PyInt_FromLong(2);
7217 return PyInt_FromLong( core->GetDraggedItem() != NULL );
7220 PyDoc_STRVAR( GemRB_GetSystemVariable__doc,
7221 "GetSystemVariable(Variable)=>int\n\n"
7222 "Returns the named Interface attribute." );
7224 static PyObject* GemRB_GetSystemVariable(PyObject * /*self*/, PyObject* args)
7226 int Variable, value;
7228 if (!PyArg_ParseTuple( args, "i", &Variable)) {
7229 return AttributeError( GemRB_GetSystemVariable__doc );
7231 switch(Variable) {
7232 case SV_BPP: value = core->Bpp; break;
7233 case SV_WIDTH: value = core->Width; break;
7234 case SV_HEIGHT: value = core->Height; break;
7235 default: value = -1; break;
7237 return PyInt_FromLong( value );
7240 PyDoc_STRVAR( GemRB_CreateItem__doc,
7241 "CreateItem(PartyID, ItemResRef, [SlotID, Charge0, Charge1, Charge2])\n\n"
7242 "Creates Item in the inventory of the player character.");
7244 static PyObject* GemRB_CreateItem(PyObject * /*self*/, PyObject* args)
7246 int PartyID;
7247 int SlotID=-1;
7248 int Charge0=1,Charge1=0,Charge2=0;
7249 const char *ItemResRef;
7251 if (!PyArg_ParseTuple( args, "is|iiii", &PartyID, &ItemResRef, &SlotID, &Charge0, &Charge1, &Charge2)) {
7252 return AttributeError( GemRB_CreateItem__doc );
7254 Game *game = core->GetGame();
7255 if (!game) {
7256 return RuntimeError( "No game loaded!" );
7258 Actor* actor = game->FindPC( PartyID );
7259 if (!actor) {
7260 return RuntimeError( "Actor not found" );
7263 if (SlotID==-1) {
7264 //This is already a slot ID we need later
7265 SlotID=actor->inventory.FindCandidateSlot(SLOT_INVENTORY,0);
7266 } else {
7267 //I believe we need this only here
7268 SlotID = core->QuerySlot(SlotID);
7271 if (SlotID==-1) {
7272 // Create item on ground
7273 Map *map = actor->GetCurrentArea();
7274 if (map) {
7275 CREItem *item = CreateCreItem(ItemResRef, Charge0, Charge1, Charge2 );
7276 if (item) {
7277 map->AddItemToLocation(actor->Pos, item);
7280 } else {
7281 // Note: this forcefully gets rid of any item currently
7282 // in the slot without properly unequipping it
7283 actor->inventory.SetSlotItemRes( ItemResRef, SlotID, Charge0, Charge1, Charge2 );
7284 actor->inventory.EquipItem(SlotID);
7285 //EquipItem already called RefreshEffects
7286 actor->ReinitQuickSlots();
7288 Py_INCREF( Py_None );
7289 return Py_None;
7292 PyDoc_STRVAR( GemRB_SetMapnote__doc,
7293 "SetMapnote(X, Y, color, Text)\n\n"
7294 "Adds or removes a mapnote.");
7296 static PyObject* GemRB_SetMapnote(PyObject * /*self*/, PyObject* args)
7298 int x,y;
7299 int color=0;
7300 const char *txt=NULL;
7302 if (!PyArg_ParseTuple( args, "ii|is", &x, &y, &color, &txt)) {
7303 return AttributeError( GemRB_SetMapnote__doc );
7305 Game *game = core->GetGame();
7306 if (!game) {
7307 return RuntimeError( "No game loaded!" );
7309 Map *map = game->GetCurrentArea();
7310 if (!map) {
7311 return RuntimeError( "No current area" );
7313 ieStrRef strref;
7314 Point point;
7315 point.x=x;
7316 point.y=y;
7317 if (txt && txt[0]) {
7318 char* newvalue = ( char* ) malloc( strlen( txt ) + 1 ); //duplicating the string
7319 strcpy( newvalue, txt );
7320 MapNote *old = map->GetMapNote(point);
7321 if (old) strref = old->strref;
7322 else strref = 0xffffffff;
7323 map->AddMapNote(point, color, newvalue, strref);
7324 } else {
7325 map->RemoveMapNote(point);
7327 Py_INCREF( Py_None );
7328 return Py_None;
7331 PyDoc_STRVAR( GemRB_CreateCreature__doc,
7332 "CreateCreature(PartyID, CreResRef)\n\n"
7333 "Creates Creature in vicinity of a player character.");
7335 static PyObject* GemRB_CreateCreature(PyObject * /*self*/, PyObject* args)
7337 int PartyID;
7338 const char *CreResRef;
7340 if (!PyArg_ParseTuple( args, "is", &PartyID, &CreResRef)) {
7341 return AttributeError( GemRB_CreateCreature__doc );
7344 Game *game = core->GetGame();
7345 if (!game) {
7346 return RuntimeError( "No game loaded!" );
7348 Actor* actor = game->FindPC( PartyID );
7349 if (!actor) {
7350 return RuntimeError( "Actor not found" );
7352 Map *map=game->GetCurrentArea();
7353 if (!map) {
7354 return RuntimeError( "No current area" );
7357 map->SpawnCreature(actor->Pos, CreResRef, 10);
7358 Py_INCREF( Py_None );
7359 return Py_None;
7362 PyDoc_STRVAR( GemRB_RevealArea__doc,
7363 "RevealArea(x, y, radius, type)\n\n"
7364 "Reveals part of the area.");
7366 static PyObject* GemRB_RevealArea(PyObject * /*self*/, PyObject* args)
7368 int x,y;
7369 int radius;
7370 int Value;
7372 if (!PyArg_ParseTuple( args, "iiii", &x, &y, &radius, &Value)) {
7373 return AttributeError( GemRB_RevealArea__doc );
7376 Point p(x,y);
7377 Game *game = core->GetGame();
7378 if (!game) {
7379 return RuntimeError( "No game loaded!" );
7381 Map *map=game->GetCurrentArea();
7382 if (!map) {
7383 return RuntimeError( "No current area" );
7385 map->ExploreMapChunk( p, radius, Value );
7387 Py_INCREF( Py_None );
7388 return Py_None;
7391 PyDoc_STRVAR( GemRB_ExploreArea__doc,
7392 "ExploreArea([bitvalue=-1])\n\n"
7393 "Explores or unexplores whole area.");
7395 static PyObject* GemRB_ExploreArea(PyObject * /*self*/, PyObject* args)
7397 int Value=-1;
7399 if (!PyArg_ParseTuple( args, "|i", &Value)) {
7400 return AttributeError( GemRB_ExploreArea__doc );
7402 Game *game = core->GetGame();
7403 if (!game) {
7404 return RuntimeError( "No game loaded!" );
7406 Map *map=game->GetCurrentArea();
7407 if (!map) {
7408 return RuntimeError( "No current area" );
7410 map->Explore( Value );
7412 Py_INCREF( Py_None );
7413 return Py_None;
7417 PyDoc_STRVAR( GemRB_GetRumour__doc,
7418 "GetRumour(percent, ResRef) => ieStrRef\n\n"
7419 "Returns a string to a rumour message. ResRef is a dialog resource.");
7421 static PyObject* GemRB_GetRumour(PyObject * /*self*/, PyObject* args)
7423 int percent;
7424 const char *ResRef;
7426 if (!PyArg_ParseTuple( args, "is", &percent, &ResRef)) {
7427 return AttributeError( GemRB_GetRumour__doc );
7429 if (rand()%100 >= percent) {
7430 return PyInt_FromLong( -1 );
7433 ieStrRef strref = core->GetRumour( ResRef );
7434 return PyInt_FromLong( strref );
7437 PyDoc_STRVAR( GemRB_GamePause__doc,
7438 "GamePause(Pause, Quiet)\n\n"
7439 "Pause or unpause the game or just toggle the pause.");
7441 static PyObject* GemRB_GamePause(PyObject * /*self*/, PyObject* args)
7443 int pause, quiet;
7445 if (!PyArg_ParseTuple( args, "ii", &pause, &quiet)) {
7446 return AttributeError( GemRB_GamePause__doc );
7449 GameControl *gc = core->GetGameControl();
7450 if (gc) {
7451 //this will trigger when pause is not 0 or 1
7452 if ((unsigned int) pause > 1) {
7453 pause = ~gc->GetDialogueFlags()&DF_FREEZE_SCRIPTS;
7456 if (pause) {
7457 gc->SetDialogueFlags(DF_FREEZE_SCRIPTS, BM_OR);
7458 } else {
7459 gc->SetDialogueFlags(DF_FREEZE_SCRIPTS, BM_NAND);
7461 if (!quiet) {
7462 if (gc->GetDialogueFlags()&DF_FREEZE_SCRIPTS) {
7463 core->DisplayConstantString(STR_PAUSED,0xff0000);
7464 } else {
7465 core->DisplayConstantString(STR_UNPAUSED,0xff0000);
7470 Py_INCREF( Py_None );
7471 return Py_None;
7474 PyDoc_STRVAR( GemRB_CheckFeatCondition__doc,
7475 "CheckFeatCondition(partyslot, a_stat, a_value, b_stat, b_value, c_stat, c_value, d_stat, d_value[,a_op, b_op, c_op, d_op]) => bool\n\n"
7476 "Checks if actor in partyslot is eligible for a feat, the formula is: (stat[a]~a or stat[b]~b) and (stat[c]~c or stat[d]~d). Where ~ is a relational operator. If the operators are omitted, the default operator is <=.");
7478 static PyObject* GemRB_CheckFeatCondition(PyObject * /*self*/, PyObject* args)
7480 int i;
7481 const char *callback = NULL;
7482 PyObject* p[13];
7483 int v[13];
7484 for(i=9;i<13;i++) {
7485 p[i]=NULL;
7486 v[i]=GREATER_OR_EQUALS;
7489 if (!PyArg_UnpackTuple( args, "ref", 9, 13, &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12] )) {
7490 return AttributeError( GemRB_CheckFeatCondition__doc );
7493 if (!PyObject_TypeCheck( p[0], &PyInt_Type )) {
7494 return AttributeError( GemRB_CheckFeatCondition__doc );
7496 v[0]=PyInt_AsLong( p[0] ); //slot
7498 if (PyObject_TypeCheck( p[1], &PyInt_Type )) {
7499 v[1]=PyInt_AsLong( p[1] ); //a_stat
7500 } else {
7501 if (!PyObject_TypeCheck( p[1], &PyString_Type )) {
7502 return AttributeError( GemRB_CheckFeatCondition__doc );
7504 callback = PyString_AsString( p[1] ); // callback
7505 if (callback == NULL) {
7506 return RuntimeError("Null string received");
7509 v[0]=PyInt_AsLong( p[0] );
7511 for(i=2;i<9;i++) {
7512 if (!PyObject_TypeCheck( p[i], &PyInt_Type )) {
7513 return AttributeError( GemRB_CheckFeatCondition__doc );
7515 v[i]=PyInt_AsLong( p[i] );
7518 if (p[9]) {
7519 for(i=9;i<13;i++) {
7520 if (!PyObject_TypeCheck( p[i], &PyInt_Type )) {
7521 return AttributeError( GemRB_CheckFeatCondition__doc );
7523 v[i]=PyInt_AsLong( p[i] );
7527 Game *game = core->GetGame();
7528 if (!game) {
7529 return RuntimeError( "No game loaded!" );
7532 Actor *actor = core->GetGame()->FindPC(v[0]);
7533 if (!actor) {
7534 return RuntimeError( "Actor not found" );
7537 /* see if the special function exists */
7538 if (callback) {
7539 char fname[32];
7541 snprintf(fname, 32, "Check_%s", callback);
7542 PyObject* param = PyTuple_New( 11 );
7543 PyTuple_SetItem( param, 0, PyInt_FromLong(v[0]) );
7544 for (i = 3;i<13;i++) {
7545 PyTuple_SetItem( param, i-2, PyInt_FromLong( v[i] ) );
7548 PyObject *pValue = gs->CallbackFunction(fname, param);
7550 /* we created this parameter, now we don't need it*/
7551 Py_DECREF( param );
7552 if (pValue) {
7553 /* don't think we need any incref */
7554 return pValue;
7556 return RuntimeError( "Callback failed" );
7559 bool ret = true;
7561 if (v[1] || v[2])
7562 ret = CheckStat(actor, v[1], v[2], v[9]);
7564 if (v[3] || v[4])
7565 ret |= CheckStat(actor, v[3], v[4], v[10]);
7567 if (!ret)
7568 goto endofquest;
7570 if (v[5] || v[6])
7571 // no | because the formula is (a|b) & (c|d)
7572 ret = CheckStat(actor, v[5], v[6], v[11]);
7574 if (v[7] || v[8])
7575 ret |= CheckStat(actor, v[7], v[8], v[12]);
7577 endofquest:
7578 if (ret) {
7579 Py_INCREF( Py_True );
7580 return Py_True;
7581 } else {
7582 Py_INCREF( Py_False );
7583 return Py_False;
7587 PyDoc_STRVAR( GemRB_GetAbilityBonus__doc,
7588 "GetAbilityBonus(stat, column, value[, ex])\n\n"
7589 "Returns an ability bonus value based on various .2da files.");
7591 static PyObject* GemRB_GetAbilityBonus(PyObject * /*self*/, PyObject* args)
7593 int stat, column, value, ex = 0;
7594 int ret;
7596 if (!PyArg_ParseTuple( args, "iii|i", &stat, &column, &value, &ex)) {
7597 return AttributeError( GemRB_GetAbilityBonus__doc );
7600 Game *game = core->GetGame();
7601 if (!game) {
7602 return RuntimeError( "No game loaded!" );
7604 Actor *actor = game->FindPC(game->GetSelectedPCSingle());
7605 if (!actor) {
7606 return RuntimeError( "Actor not found" );
7609 switch (stat) {
7610 case IE_STR:
7611 ret=core->GetStrengthBonus(column, value, ex);
7612 break;
7613 case IE_INT:
7614 ret=core->GetIntelligenceBonus(column, value);
7615 break;
7616 case IE_DEX:
7617 ret=core->GetDexterityBonus(column, value);
7618 break;
7619 case IE_CON:
7620 ret=core->GetConstitutionBonus(column, value);
7621 break;
7622 case IE_CHR:
7623 ret=core->GetCharismaBonus(column, value);
7624 break;
7625 case IE_LORE:
7626 ret=core->GetLoreBonus(column, value);
7627 break;
7628 case IE_REPUTATION: //both chr and reputation affect the reaction, but chr is already taken
7629 ret=GetReaction(actor, NULL); // this is used only for display, so the null is fine
7630 break;
7631 case IE_WIS:
7632 ret=core->GetWisdomBonus(column, value);
7633 break;
7634 default:
7635 return RuntimeError( "Invalid ability!");
7637 return PyInt_FromLong( ret );
7640 PyDoc_STRVAR( GemRB_LeaveParty__doc,
7641 "LeaveParty(Slot [,dialog])\n\n"
7642 "Makes player in Slot leave party, and initiate dialog if demanded." );
7644 static PyObject* GemRB_LeaveParty(PyObject * /*self*/, PyObject* args)
7646 int PlayerSlot, initDialog;
7648 if (!PyArg_ParseTuple( args, "i|i", &PlayerSlot, &initDialog )) {
7649 return AttributeError( GemRB_LeaveParty__doc );
7651 Game *game = core->GetGame();
7652 if (!game) {
7653 return RuntimeError( "No game loaded!" );
7655 Actor *actor = game->FindPC(PlayerSlot);
7656 if (!actor) {
7657 return RuntimeError( "Actor not found" );
7660 if (initDialog) {
7661 if (initDialog == 2)
7662 GameScript::SetLeavePartyDialogFile(actor, NULL);
7663 if(actor->GetBase(IE_HITPOINTS) > 0) {
7664 char Tmp[40];
7665 actor->ClearPath();
7666 actor->ClearActions();
7667 strncpy(Tmp,"Dialogue([PC])",sizeof(Tmp) );
7668 actor->AddAction( GenerateAction(Tmp) );
7671 game->LeaveParty (actor);
7673 Py_INCREF( Py_None );
7674 return Py_None;
7677 typedef union pack {
7678 ieDword data;
7679 ieByte bytes[4];
7680 } packtype;
7682 static void ReadActionButtons()
7684 unsigned int i;
7686 memset(GUIAction, -1, sizeof(GUIAction));
7687 memset(GUITooltip, -1, sizeof(GUITooltip));
7688 memset(GUIResRef, 0, sizeof(GUIResRef));
7689 memset(GUIEvent, 0, sizeof(GUIEvent));
7690 int table = gamedata->LoadTable( "guibtact" );
7691 if (table<0) {
7692 return;
7694 Holder<TableMgr> tab = gamedata->GetTable( table );
7695 for (i = 0; i < MAX_ACT_COUNT; i++) {
7696 packtype row;
7698 row.bytes[0] = (ieByte) atoi( tab->QueryField(i,0) );
7699 row.bytes[1] = (ieByte) atoi( tab->QueryField(i,1) );
7700 row.bytes[2] = (ieByte) atoi( tab->QueryField(i,2) );
7701 row.bytes[3] = (ieByte) atoi( tab->QueryField(i,3) );
7702 GUIAction[i] = row.data;
7703 GUITooltip[i] = atoi( tab->QueryField(i,4) );
7704 strnlwrcpy(GUIResRef[i], tab->QueryField(i,5), 8);
7705 strncpy(GUIEvent[i], tab->GetRowName(i), 16);
7707 gamedata->DelTable( table );
7710 static void SetButtonCycle(AnimationFactory *bam, Button *btn, int cycle, unsigned char which)
7712 Sprite2D *tspr = bam->GetFrame( cycle, 0 );
7713 btn->SetImage( which, tspr );
7716 PyDoc_STRVAR( GemRB_Button_SetActionIcon__doc,
7717 "SetActionIcon(Window, Button, ActionIndex[, Function])\n\n"
7718 "Sets up an action button. The ActionIndex should be less than 34." );
7720 static PyObject* SetActionIcon(int WindowIndex, int ControlIndex, int Index, int Function)
7722 if (ControlIndex>99) {
7723 return AttributeError( GemRB_Button_SetActionIcon__doc );
7725 if (Index>=MAX_ACT_COUNT) {
7726 return AttributeError( GemRB_Button_SetActionIcon__doc );
7728 Button* btn = ( Button* ) GetControl(WindowIndex, ControlIndex, IE_GUI_BUTTON);
7729 if (!btn) {
7730 return NULL;
7733 if (Index<0) {
7734 btn->SetImage( IE_GUI_BUTTON_UNPRESSED, 0 );
7735 btn->SetImage( IE_GUI_BUTTON_PRESSED, 0 );
7736 btn->SetImage( IE_GUI_BUTTON_SELECTED, 0 );
7737 btn->SetImage( IE_GUI_BUTTON_DISABLED, 0 );
7738 btn->SetFlags( IE_GUI_BUTTON_NO_IMAGE, BM_SET );
7739 btn->SetEvent( IE_GUI_BUTTON_ON_PRESS, NULL );
7740 core->SetTooltip( (ieWord) WindowIndex, (ieWord) ControlIndex, "" );
7741 //no incref
7742 return Py_None;
7745 if (GUIAction[0]==0xcccccccc) {
7746 ReadActionButtons();
7750 //FIXME: this is a hardcoded resource (pst has no such one)
7751 AnimationFactory* bam = ( AnimationFactory* )
7752 gamedata->GetFactoryResource( GUIResRef[Index],
7753 IE_BAM_CLASS_ID, IE_NORMAL );
7754 if (!bam) {
7755 return RuntimeError( "BAM not found" );
7757 packtype row;
7759 row.data = GUIAction[Index];
7760 SetButtonCycle(bam, btn, (char) row.bytes[0], IE_GUI_BUTTON_UNPRESSED);
7761 SetButtonCycle(bam, btn, (char) row.bytes[1], IE_GUI_BUTTON_PRESSED);
7762 SetButtonCycle(bam, btn, (char) row.bytes[2], IE_GUI_BUTTON_SELECTED);
7763 SetButtonCycle(bam, btn, (char) row.bytes[3], IE_GUI_BUTTON_DISABLED);
7764 btn->SetFlags( IE_GUI_BUTTON_NO_IMAGE|IE_GUI_BUTTON_PICTURE, BM_NAND );
7765 ieVariable Event;
7766 snprintf(Event,sizeof(Event)-1, "Action%sPressed", GUIEvent[Index]);
7767 btn->SetEvent( IE_GUI_BUTTON_ON_PRESS, new StringCallback(Event) );
7768 //cannot make this const, because it will be freed
7769 char *txt = core->GetString( GUITooltip[Index] );
7770 //will free txt
7771 SetFunctionTooltip(WindowIndex, ControlIndex, txt, Function);
7772 //no incref
7773 return Py_None;
7776 static PyObject* GemRB_Button_SetActionIcon(PyObject * /*self*/, PyObject* args)
7778 int WindowIndex, ControlIndex, Index;
7779 int Function = 0;
7781 if (!PyArg_ParseTuple( args, "iii|i", &WindowIndex, &ControlIndex, &Index, &Function )) {
7782 return AttributeError( GemRB_Button_SetActionIcon__doc );
7785 PyObject* ret = SetActionIcon(WindowIndex, ControlIndex, Index, Function);
7786 if (ret) {
7787 Py_INCREF(ret);
7789 return ret;
7792 PyDoc_STRVAR( GemRB_HasResource__doc,
7793 "HasResource(ResRef, ResType)\n\n"
7794 "Returns true if resource is accessible." );
7796 static PyObject* GemRB_HasResource(PyObject * /*self*/, PyObject* args)
7798 const char *ResRef;
7799 int ResType;
7800 int silent = 0;
7802 if (!PyArg_ParseTuple( args, "si|i", &ResRef, &ResType, &silent )) {
7803 return AttributeError( GemRB_HasResource__doc );
7805 if (gamedata->Exists(ResRef, ResType, silent)) {
7806 Py_INCREF( Py_True );
7807 return Py_True;
7808 } else {
7809 Py_INCREF( Py_False );
7810 return Py_False;
7814 PyDoc_STRVAR( GemRB_Window_SetupEquipmentIcons__doc,
7815 "SetupEquipmentIcons(WindowIndex, slot[, Start, Offset])\n\n"
7816 "Automagically sets up the controls of the equipment list window for a PC indexed by slot.\n"
7817 "Start is the beginning of the visible part of the item list.\n"
7818 "Offset is the ID of the first usable button.");
7820 static PyObject* GemRB_Window_SetupEquipmentIcons(PyObject * /*self*/, PyObject* args)
7822 int wi, slot;
7823 int Start = 0;
7824 int Offset = 0; //control offset (iwd2 has the action buttons starting at 6)
7826 if (!PyArg_ParseTuple( args, "ii|ii", &wi, &slot, &Start, &Offset )) {
7827 return AttributeError( GemRB_Window_SetupEquipmentIcons__doc );
7830 Game *game = core->GetGame();
7831 if (!game) {
7832 return RuntimeError( "No game loaded!" );
7834 Actor* actor = game->FindPC( slot );
7835 if (!actor) {
7836 return RuntimeError( "Actor not found" );
7839 //-2 because of the left/right scroll icons
7840 if (!ItemArray) {
7841 ItemArray = (ItemExtHeader *) malloc((GUIBT_COUNT) * sizeof (ItemExtHeader) );
7843 bool more = actor->inventory.GetEquipmentInfo(ItemArray, Start, GUIBT_COUNT-(Start?1:0));
7844 int i;
7845 if (Start) {
7846 PyObject *ret = SetActionIcon(wi,core->GetControl(wi, Offset),ACT_LEFT,0);
7847 if (!ret) {
7848 return RuntimeError("Cannot set action button!\n");
7851 //FIXME: this is a hardcoded resource (pst has no such one)
7852 AnimationFactory* bam = ( AnimationFactory* )
7853 gamedata->GetFactoryResource( "guibtbut",
7854 IE_BAM_CLASS_ID, IE_NORMAL );
7855 if (!bam) {
7856 return RuntimeError( "BAM not found" );
7859 for (i=0;i<GUIBT_COUNT-(more?1:0);i++) {
7860 int ci = core->GetControl(wi, i+Offset+(Start?1:0) );
7861 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
7862 btn->SetEvent(IE_GUI_BUTTON_ON_PRESS, new StringCallback("EquipmentPressed"));
7863 strcpy(btn->VarName,"Equipment");
7864 btn->Value = Start+i;
7866 ItemExtHeader *item = ItemArray+i;
7867 Sprite2D *Picture = NULL;
7869 if (item->UseIcon[0]) {
7870 Picture = gamedata->GetBAMSprite(item->UseIcon, 1, 0);
7873 if (!Picture) {
7874 btn->SetState(IE_GUI_BUTTON_DISABLED);
7875 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE, BM_SET);
7876 btn->SetTooltip(NULL);
7877 } else {
7878 SetButtonCycle(bam, btn, 0, IE_GUI_BUTTON_UNPRESSED);
7879 SetButtonCycle(bam, btn, 1, IE_GUI_BUTTON_PRESSED);
7880 SetButtonCycle(bam, btn, 2, IE_GUI_BUTTON_SELECTED);
7881 SetButtonCycle(bam, btn, 3, IE_GUI_BUTTON_DISABLED);
7882 btn->SetPicture( Picture );
7883 btn->SetState(IE_GUI_BUTTON_UNPRESSED);
7884 btn->SetFlags(IE_GUI_BUTTON_PICTURE|IE_GUI_BUTTON_ALIGN_BOTTOM|IE_GUI_BUTTON_ALIGN_RIGHT, BM_SET);
7886 const CREItem *item_slot = actor->inventory.GetSlotItem(item->slot);
7887 int tip = core->GetItemTooltip(item->itemname, item->headerindex, item_slot->Flags&IE_INV_ITEM_IDENTIFIED);
7888 if (tip>0) {
7889 //cannot make this const, because it will be freed
7890 char *tmp = core->GetString((ieStrRef) tip,0);
7891 btn->SetTooltip(tmp);
7892 core->FreeString(tmp);
7893 } else {
7894 btn->SetTooltip(NULL);
7896 char usagestr[10];
7898 if (item->Charges && (item->Charges!=0xffff) ) {
7899 sprintf(usagestr,"%d", item->Charges);
7900 btn->SetText( usagestr );
7902 if (!item->Charges && (item->ChargeDepletion==CHG_NONE) ) {
7903 btn->SetState(IE_GUI_BUTTON_DISABLED);
7908 if (more) {
7909 PyObject *ret = SetActionIcon(wi,core->GetControl(wi, i+Offset+1),ACT_RIGHT,i+1);
7910 if (!ret) {
7911 return RuntimeError("Cannot set action button!\n");
7915 Py_INCREF( Py_None );
7916 return Py_None;
7919 PyDoc_STRVAR( GemRB_Window_SetupSpellIcons__doc,
7920 "SetupSpellIcons(WindowIndex, slot, type[, Start, Offset])\n\n"
7921 "Automagically sets up the controls of the spell or innate list window for a PC indexed by slot.\n"
7922 "Start is the beginning of the visible part of the spell list.\n"
7923 "Offset is the ID of the first usable button.");
7925 static PyObject* GemRB_Window_SetupSpellIcons(PyObject * /*self*/, PyObject* args)
7927 int wi, slot, Type;
7928 int Start = 0;
7929 int Offset = 0;
7931 if (!PyArg_ParseTuple( args, "iii|ii", &wi, &slot, &Type, &Start, &Offset )) {
7932 return AttributeError( GemRB_Window_SetupSpellIcons__doc );
7935 Game *game = core->GetGame();
7936 if (!game) {
7937 return RuntimeError( "No game loaded!" );
7939 Actor* actor = game->FindPC( slot );
7940 if (!actor) {
7941 return RuntimeError( "Actor not found" );
7944 //-2 because of the left/right scroll icons
7945 if (!SpellArray) {
7946 SpellArray = (SpellExtHeader *) malloc((GUIBT_COUNT) * sizeof (SpellExtHeader) );
7948 int more = actor->spellbook.GetSpellInfo(SpellArray, Type, Start, GUIBT_COUNT-(Start?1:0));
7949 int i;
7950 if (Start) {
7951 more |= 2;
7953 if (more) {
7954 int ci = core->GetControl(wi, Offset);
7955 PyObject *ret = SetActionIcon(wi, ci, ACT_LEFT, 0);
7956 if (!ret) {
7957 return RuntimeError("Cannot set action button!\n");
7959 Button * btn = (Button *) GetControl(wi, ci, IE_GUI_BUTTON);
7960 if (Start) {
7961 btn->SetState(IE_GUI_BUTTON_UNPRESSED);
7962 } else {
7963 btn->SetState(IE_GUI_BUTTON_DISABLED);
7967 //FIXME: this is a hardcoded resource (pst has no such one)
7968 AnimationFactory* bam = ( AnimationFactory* )
7969 gamedata->GetFactoryResource( "guibtbut",
7970 IE_BAM_CLASS_ID, IE_NORMAL );
7971 if (!bam) {
7972 return RuntimeError( "BAM not found" );
7975 // disable all spells if fx_disable_spellcasting was run with the same type
7976 // but only if there are any spells of that type to disable
7977 int disabled_spellcasting = actor->fxqueue.DisabledSpellcasting(7);
7979 for (i=0;i<GUIBT_COUNT-(more?2:0);i++) {
7980 SpellExtHeader *spell = SpellArray+i;
7982 int ci = core->GetControl(wi, i+Offset+(more?1:0) );
7983 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
7984 strcpy(btn->VarName,"Spell");
7985 btn->Value = i+Start;
7987 // disable spells that should be cast from the inventory
7988 // Identify is misclassified and has Target 3 (Dead char)
7990 if (CheckSpecialSpell(spell->spellname, actor) || (disabled_spellcasting&(1<<spell->type)) ) {
7991 btn->SetState(IE_GUI_BUTTON_DISABLED);
7992 btn->EnableBorder(1, IE_GUI_BUTTON_DISABLED);
7993 btn->SetEvent(IE_GUI_BUTTON_ON_PRESS, new StringCallback("UpdateActionsWindow")); //noop
7994 } else {
7995 btn->SetState(IE_GUI_BUTTON_UNPRESSED);
7996 btn->SetEvent(IE_GUI_BUTTON_ON_PRESS, new StringCallback("SpellPressed"));
7998 Sprite2D *Picture = NULL;
8000 if (spell->MemorisedIcon[0]) {
8001 Picture = gamedata->GetBAMSprite(spell->MemorisedIcon, 0, 0);
8004 if (!Picture) {
8005 btn->SetState(IE_GUI_BUTTON_DISABLED);
8006 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE, BM_SET);
8007 btn->SetTooltip(NULL);
8008 } else {
8009 SetButtonCycle(bam, btn, 0, IE_GUI_BUTTON_UNPRESSED);
8010 SetButtonCycle(bam, btn, 1, IE_GUI_BUTTON_PRESSED);
8011 SetButtonCycle(bam, btn, 2, IE_GUI_BUTTON_SELECTED);
8012 SetButtonCycle(bam, btn, 3, IE_GUI_BUTTON_DISABLED);
8013 btn->SetPicture( Picture );
8014 btn->SetFlags(IE_GUI_BUTTON_PICTURE|IE_GUI_BUTTON_ALIGN_BOTTOM|IE_GUI_BUTTON_ALIGN_RIGHT, BM_SET);
8015 //cannot make this const, because it will be freed
8016 char *tmp = core->GetString(spell->strref,0);
8017 btn->SetTooltip(tmp);
8018 core->FreeString(tmp);
8019 char usagestr[10];
8021 if (spell->count>0) {
8022 sprintf(usagestr,"%d", spell->count);
8023 btn->SetText( usagestr );
8024 btn->SetState(IE_GUI_BUTTON_UNPRESSED);
8025 } else {
8026 btn->SetState(IE_GUI_BUTTON_DISABLED);
8031 if (more) {
8032 int ci = core->GetControl(wi, i+Offset+1);
8033 PyObject *ret = SetActionIcon(wi, ci, ACT_RIGHT, i+1);
8034 if (!ret) {
8035 return RuntimeError("Cannot set action button!\n");
8037 Button* btn = (Button *) GetControl( wi, ci, IE_GUI_BUTTON );
8038 if (more&1) {
8039 btn->SetState(IE_GUI_BUTTON_UNPRESSED);
8040 } else {
8041 btn->SetState(IE_GUI_BUTTON_DISABLED);
8042 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE, BM_SET);
8043 btn->SetTooltip(NULL);
8047 Py_INCREF( Py_None );
8048 return Py_None;
8051 PyDoc_STRVAR( GemRB_Window_SetupControls__doc,
8052 "SetupControls(WindowIndex, slot[, Start])\n\n"
8053 "Automagically sets up the controls of the action window for a PC indexed by slot." );
8055 static PyObject* GemRB_Window_SetupControls(PyObject * /*self*/, PyObject* args)
8057 int wi, slot;
8058 int Start = 0;
8060 if (!PyArg_ParseTuple( args, "ii|i", &wi, &slot, &Start )) {
8061 return AttributeError( GemRB_Window_SetupControls__doc );
8064 Game *game = core->GetGame();
8065 if (!game) {
8066 return RuntimeError( "No game loaded!" );
8068 Actor* actor = game->FindPC( slot );
8069 if (!actor) {
8070 return RuntimeError( "Actor not found" );
8073 ActionButtonRow myrow;
8074 actor->GetActionButtonRow(myrow);
8075 bool fistdrawn = true;
8076 ieDword magicweapon = actor->inventory.GetMagicSlot();
8077 if (!actor->inventory.HasItemInSlot("",magicweapon) ) {
8078 magicweapon = 0xffff;
8080 ieDword fistweapon = actor->inventory.GetFistSlot();
8081 ieDword usedslot = actor->inventory.GetEquippedSlot();
8082 ieDword disabledbutton = actor->GetStat(IE_DISABLEDBUTTON);
8083 int tmp;
8084 for (int i=0;i<GUIBT_COUNT;i++) {
8085 int ci = core->GetControl(wi, i+Start);
8086 if (ci<0) {
8087 printf("Couldn't find button #%d on Window #%d\n", i+Start, wi);
8088 return RuntimeError ("No such control!\n");
8090 int action = myrow[i];
8091 if (action==100) {
8092 action = -1;
8093 } else {
8094 action&=31;
8096 Button * btn = (Button *) GetControl(wi,ci,IE_GUI_BUTTON);
8097 if (!btn) {
8098 return NULL;
8100 btn->SetFlags(IE_GUI_BUTTON_NO_IMAGE|IE_GUI_BUTTON_ALIGN_BOTTOM|IE_GUI_BUTTON_ALIGN_RIGHT, BM_SET);
8101 SetItemText(wi, ci, 0, false);
8102 PyObject *ret = SetActionIcon(wi,ci,action,i+1);
8104 int state = IE_GUI_BUTTON_UNPRESSED;
8105 ieDword modalstate = actor->ModalState;
8106 int type;
8107 switch (action) {
8108 case ACT_INNATE:
8109 if (actor->spellbook.IsIWDSpellBook()) {
8110 type = IE_IWD2_SPELL_INNATE;
8111 } else {
8112 type = IE_SPELL_TYPE_INNATE;
8114 if (!actor->spellbook.GetMemorizedSpellsCount(type)) {
8115 state = IE_GUI_BUTTON_DISABLED;
8117 break;
8118 case ACT_CAST:
8119 //luckily the castable spells in IWD2 are all bits below INNATE, so we can do this trick
8120 if (actor->spellbook.IsIWDSpellBook()) {
8121 type = (1<<IE_IWD2_SPELL_INNATE)-1;
8122 } else {
8123 type = (1<<IE_SPELL_TYPE_INNATE)-1;
8125 //returns true if there are ANY spells to cast
8126 if (!actor->spellbook.GetSpellInfoSize(type)) {
8127 state = IE_GUI_BUTTON_DISABLED;
8129 break;
8130 case ACT_SHAPE:
8131 if (actor->spellbook.IsIWDSpellBook()) {
8132 type = 1<<IE_IWD2_SPELL_SHAPE;
8133 } else {
8134 type = 0; //no separate shapes in old spellbook
8136 //returns true if there is ANY shape
8137 if (!actor->spellbook.GetSpellInfoSize(type)) {
8138 state = IE_GUI_BUTTON_DISABLED;
8140 break;
8141 case ACT_USE:
8142 //returns true if there is ANY equipment
8143 if (!actor->inventory.GetEquipmentInfo(NULL, 0, 0)) {
8144 state = IE_GUI_BUTTON_DISABLED;
8146 break;
8147 case ACT_BARDSONG:
8148 if (actor->spellbook.IsIWDSpellBook()) {
8149 type = 1<<IE_IWD2_SPELL_SONG;
8150 if (!actor->spellbook.GetSpellInfoSize(type)) {
8151 state = IE_GUI_BUTTON_DISABLED;
8153 } else {
8154 if (modalstate==MS_BATTLESONG) {
8155 state = IE_GUI_BUTTON_SELECTED;
8158 break;
8159 case ACT_TURN:
8160 if (actor->GetStat(IE_TURNUNDEADLEVEL)<1) {
8161 state = IE_GUI_BUTTON_DISABLED;
8162 } else {
8163 if (modalstate==MS_TURNUNDEAD) {
8164 state = IE_GUI_BUTTON_SELECTED;
8167 break;
8168 case ACT_STEALTH:
8169 if (modalstate==MS_STEALTH) {
8170 state = IE_GUI_BUTTON_SELECTED;
8172 break;
8173 case ACT_SEARCH:
8174 if (modalstate==MS_DETECTTRAPS) {
8175 state = IE_GUI_BUTTON_SELECTED;
8177 break;
8178 case ACT_WEAPON1:
8179 case ACT_WEAPON2:
8180 case ACT_WEAPON3:
8181 case ACT_WEAPON4:
8183 SetButtonBAM(wi, ci, "stonweap",0,0,-1);
8184 ieDword slot;
8185 if (magicweapon!=0xffff) {
8186 slot = magicweapon;
8187 } else {
8188 slot = actor->GetQuickSlot(action-ACT_WEAPON1);
8190 if (slot!=0xffff) {
8191 CREItem *item = actor->inventory.GetSlotItem(slot);
8192 //no slot translation required
8193 int launcherslot = actor->inventory.FindSlotRangedWeapon(slot);
8194 const char* Item2ResRef = 0;
8195 if (launcherslot != actor->inventory.GetFistSlot()) {
8196 // launcher/projectile in this slot
8197 CREItem* item2;
8198 item2 = actor->inventory.GetSlotItem(launcherslot);
8199 Item2ResRef = item2->ItemResRef;
8202 if (item) {
8203 int mode = 4;
8204 if (slot == fistweapon) {
8205 if (fistdrawn) {
8206 fistdrawn = false;
8207 } else {
8208 //empty weapon slot, already drawn
8209 break;
8212 SetItemIcon(wi, ci, item->ItemResRef,mode,(item->Flags&IE_INV_ITEM_IDENTIFIED)?2:1, i+1, Item2ResRef);
8213 SetItemText(wi, ci, item->Usages[actor->PCStats->QuickWeaponHeaders[action-ACT_WEAPON1]], true);
8214 if (usedslot == slot) {
8215 btn->EnableBorder(0, true);
8216 if (core->GetGameControl()->target_mode == TARGET_MODE_ATTACK) {
8217 state = IE_GUI_BUTTON_SELECTED;
8218 } else {
8219 state = IE_GUI_BUTTON_THIRD;
8221 } else {
8222 btn->EnableBorder(0, false);
8227 break;
8228 case ACT_QSPELL1:
8229 case ACT_QSPELL2:
8230 case ACT_QSPELL3:
8231 //fixme iwd2 has 9
8233 SetButtonBAM(wi, ci, "stonspel",0,0,-1);
8234 ieResRef *poi = &actor->PCStats->QuickSpells[action-ACT_QSPELL1];
8235 if ((*poi)[0]) {
8236 SetSpellIcon(wi, ci, *poi, 1, 1, i+1);
8239 break;
8240 case ACT_QSLOT1:
8241 tmp=0;
8242 goto jump_label;
8243 case ACT_QSLOT2:
8244 tmp=1;
8245 goto jump_label;
8246 case ACT_QSLOT3:
8247 tmp=2;
8248 goto jump_label;
8249 case ACT_QSLOT4:
8250 tmp=3;
8251 goto jump_label;
8252 case ACT_QSLOT5:
8253 tmp=4;
8254 jump_label:
8256 SetButtonBAM(wi, ci, "stonitem",0,0,-1);
8257 ieDword slot = actor->PCStats->QuickItemSlots[tmp];
8258 if (slot!=0xffff) {
8259 //no slot translation required
8260 CREItem *item = actor->inventory.GetSlotItem(slot);
8261 if (item) {
8262 //MISC3H (horn of blasting) is not displayed when it is out of usages
8263 int header = actor->PCStats->QuickItemHeaders[tmp];
8264 int usages = item->Usages[header];
8265 //I don't like this feature, if the goal is full IE compatibility
8266 //uncomment the next line.
8267 //if (usages)
8269 //SetItemIcon parameter needs header+6 to display extended header icons
8270 SetItemIcon(wi, ci, item->ItemResRef,header+6,(item->Flags&IE_INV_ITEM_IDENTIFIED)?2:1, i+1, NULL);
8271 SetItemText(wi, ci, usages, false);
8276 break;
8277 default:
8278 break;
8280 if (!ret) {
8281 return RuntimeError("Cannot set action button!\n");
8283 if (action<0 || (disabledbutton & (1<<action) )) {
8284 state = IE_GUI_BUTTON_DISABLED;
8286 btn->SetState(state);
8287 //you have to set this overlay up
8288 btn->EnableBorder(1, state==IE_GUI_BUTTON_DISABLED);
8290 Py_INCREF( Py_None );
8291 return Py_None;
8294 PyDoc_STRVAR( GemRB_ClearActions__doc,
8295 "ClearActions(slot)\n\n"
8296 "Stops an action for a PC indexed by slot." );
8298 static PyObject* GemRB_ClearActions(PyObject * /*self*/, PyObject* args)
8300 int slot;
8302 if (!PyArg_ParseTuple( args, "i", &slot )) {
8303 return AttributeError( GemRB_ClearActions__doc );
8305 Game *game = core->GetGame();
8306 if (!game) {
8307 return RuntimeError( "No game loaded!" );
8309 Actor* actor = game->FindPC( slot );
8310 if (!actor) {
8311 return RuntimeError( "Actor not found" );
8313 if (actor->GetInternalFlag()&IF_NOINT) {
8314 printMessage( "GuiScript","Cannot break action", GREEN);
8315 Py_INCREF( Py_None );
8316 return Py_None;
8318 if (!(actor->GetNextStep()) && !actor->ModalState) {
8319 printMessage( "GuiScript","No breakable action", GREEN);
8320 Py_INCREF( Py_None );
8321 return Py_None;
8323 actor->ClearPath(); //stop walking
8324 actor->ClearActions(); //stop pending action involved walking
8325 actor->SetModal(MS_NONE);//stop modal actions
8326 Py_INCREF( Py_None );
8327 return Py_None;
8331 PyDoc_STRVAR( GemRB_SetDefaultActions__doc,
8332 "SetDefaultActions(qslot, slot1, slot2, slot3)\n\n"
8333 "Sets whether qslots need an additional translation like in iwd2. "
8334 "Also sets up the first three default action types." );
8336 static PyObject* GemRB_SetDefaultActions(PyObject * /*self*/, PyObject* args)
8338 int qslot;
8339 int slot1, slot2, slot3;
8341 if (!PyArg_ParseTuple( args, "iiii", &qslot, &slot1, &slot2, &slot3 )) {
8342 return AttributeError( GemRB_SetDefaultActions__doc );
8344 Actor::SetDefaultActions((bool) qslot, (ieByte) slot1, (ieByte) slot2, (ieByte) slot3);
8345 Py_INCREF( Py_None );
8346 return Py_None;
8349 PyDoc_STRVAR( GemRB_SetupQuickSlot__doc,
8350 "SetupQuickSlot(PartyID, quickslot, inventoryslot, headerindex)\n\n"
8351 "Set up a quick slot or weapon slot of a PC to use a weapon ability.\n\n"
8352 "If the inventoryslot number is -1, only the header index will be changed. "
8353 "If the quick slot is 0, then the inventory slot will be used to find which "
8354 "headerindex should be set. The default value for headerindex is 0.");
8356 static PyObject* GemRB_SetupQuickSlot(PyObject * /*self*/, PyObject* args)
8358 int PartyID, which, slot, headerindex = 0;
8360 if (!PyArg_ParseTuple( args, "iii|i", &PartyID, &which, &slot, &headerindex )) {
8361 return AttributeError( GemRB_SetupQuickSlot__doc );
8364 Game *game = core->GetGame();
8365 if (!game) {
8366 return RuntimeError( "No game loaded!" );
8368 Actor* actor = game->FindPC( PartyID );
8369 if (!actor) {
8370 return RuntimeError( "Actor not found" );
8372 actor->SetupQuickSlot(which, slot, headerindex);
8373 Py_INCREF( Py_None );
8374 return Py_None;
8377 PyDoc_STRVAR( GemRB_SetEquippedQuickSlot__doc,
8378 "SetEquippedQuickSlot(PartyID, QWeaponSlot[, ability])->int\n\n"
8379 "Sets the named weapon/item slot as equipped weapon slot, optionally sets the used ability."
8380 "Returns strref number of failure (0 success, -1 silent failure)." );
8382 static PyObject* GemRB_SetEquippedQuickSlot(PyObject * /*self*/, PyObject* args)
8384 int slot;
8385 int PartyID;
8386 int ability = -1;
8388 if (!PyArg_ParseTuple( args, "ii|i", &PartyID, &slot, &ability)) {
8389 return AttributeError( GemRB_SetEquippedQuickSlot__doc );
8392 Game *game = core->GetGame();
8393 if (!game) {
8394 return RuntimeError( "No game loaded!" );
8396 Actor* actor = game->FindPC( PartyID );
8397 if (!actor) {
8398 return RuntimeError( "Actor not found" );
8401 int ret = actor->SetEquippedQuickSlot(slot, ability);
8402 return PyInt_FromLong( ret );
8405 PyDoc_STRVAR( GemRB_GetEquippedQuickSlot__doc,
8406 "GetEquippedQuickSlot(PartyID[, NoTrans]) => Slot\n\n"
8407 "Returns the inventory slot (translation) or quick weapon index (no translation) of the equipped weapon." );
8409 static PyObject* GemRB_GetEquippedQuickSlot(PyObject * /*self*/, PyObject* args)
8411 int PartyID;
8412 int NoTrans = 0;
8414 if (!PyArg_ParseTuple( args, "i|i", &PartyID, &NoTrans)) {
8415 return AttributeError( GemRB_GetEquippedQuickSlot__doc );
8418 Game *game = core->GetGame();
8419 if (!game) {
8420 return RuntimeError( "No game loaded!" );
8422 Actor* actor = game->FindPC( PartyID );
8423 if (!actor) {
8424 return RuntimeError( "Actor not found" );
8427 int ret = actor->inventory.GetEquippedSlot();
8428 /*int effect = core->QuerySlotEffects(ret);
8429 if (effect == SLOT_EFFECT_MISSILE) {
8430 ret = actor->inventory.FindRangedWeapon();
8432 if (actor->PCStats) {
8433 for(int i=0;i<4;i++) {
8434 if (ret == actor->PCStats->QuickWeaponSlots[i]) {
8435 if (NoTrans) {
8436 return PyInt_FromLong(i);
8438 ret = i+actor->inventory.GetWeaponSlot();
8439 break;
8442 } /*else {
8443 ret-=actor->inventory.GetWeaponSlot();
8445 return PyInt_FromLong( core->FindSlot(ret) );
8448 PyDoc_STRVAR( GemRB_GetEquippedAmmunition__doc,
8449 "GetEquippedAmmunition(PartyID) => QSlot\n\n"
8450 "Returns the equipped ammunition slot, if any; -1 if none." );
8452 static PyObject* GemRB_GetEquippedAmmunition(PyObject * /*self*/, PyObject* args)
8454 int PartyID;
8456 if (!PyArg_ParseTuple( args, "i", &PartyID)) {
8457 return AttributeError( GemRB_GetEquippedQuickSlot__doc );
8460 Game *game = core->GetGame();
8461 if (!game) {
8462 return RuntimeError( "No game loaded!" );
8464 Actor* actor = game->FindPC( PartyID );
8465 if (!actor) {
8466 return RuntimeError( "Actor not found" );
8469 int ret = actor->inventory.GetEquippedSlot();
8470 int effect = core->QuerySlotEffects(ret);
8471 if (effect == SLOT_EFFECT_MISSILE) {
8472 return PyInt_FromLong( core->FindSlot(ret) );
8473 } else {
8474 return PyInt_FromLong( -1 );
8478 PyDoc_STRVAR( GemRB_SetModalState__doc,
8479 "SetModalState(slot, state[,spell])\n\n"
8480 "Sets the modal state of the actor.\n"
8481 "If 'spell' is not given, it will set a default spell resource associated with the state.");
8483 static PyObject* GemRB_SetModalState(PyObject * /*self*/, PyObject* args)
8485 int slot;
8486 int state;
8487 const char *spell=NULL;
8489 if (!PyArg_ParseTuple( args, "ii|s", &slot, &state, &spell )) {
8490 return AttributeError( GemRB_SetModalState__doc );
8492 Game *game = core->GetGame();
8493 if (!game) {
8494 return RuntimeError( "No game loaded!" );
8496 Actor* actor = game->FindPC( slot );
8497 if (!actor) {
8498 return RuntimeError( "Actor not found" );
8500 actor->SetModal( (ieDword) state, 0);
8501 actor->SetModalSpell(state, spell);
8503 Py_INCREF( Py_None );
8504 return Py_None;
8507 PyDoc_STRVAR( GemRB_SpellCast__doc,
8508 "SpellCast(actor, type, spell)\n\n"
8509 "Makes the actor try to cast a spell. Type is the spell type like 3 for normal spells and 4 for innates.\n"
8510 "Spell is the index of the spell in the memorised spell list.");
8512 static PyObject* GemRB_SpellCast(PyObject * /*self*/, PyObject* args)
8514 unsigned int slot;
8515 unsigned int type;
8516 unsigned int spell;
8518 if (!PyArg_ParseTuple( args, "iii", &slot, &type, &spell )) {
8519 return AttributeError( GemRB_SpellCast__doc );
8521 Game *game = core->GetGame();
8522 if (!game) {
8523 return RuntimeError( "No game loaded!" );
8525 Actor* actor = game->FindPC( slot );
8526 if (!actor) {
8527 return RuntimeError( "Actor not found" );
8530 SpellExtHeader spelldata; // = SpellArray[spell];
8531 actor->spellbook.GetSpellInfo(&spelldata, type, spell, 1);
8533 printf("Cast spell: %s\n", spelldata.spellname);
8534 printf("Slot: %d\n", spelldata.slot);
8535 printf("Type: %d\n", spelldata.type);
8536 //cannot make this const, because it will be freed
8537 char *tmp = core->GetString(spelldata.strref);
8538 printf("Spellname: %s\n", tmp);
8539 core->FreeString(tmp);
8540 printf("Target: %d\n", spelldata.Target);
8541 printf("Range: %d\n", spelldata.Range);
8542 if(! (1<<spelldata.type) & type) {
8543 return RuntimeError( "Wrong type of spell!");
8546 GameControl *gc = core->GetGameControl();
8547 switch (spelldata.Target) {
8548 case TARGET_SELF:
8549 // FIXME: GA_NO_DEAD and such are not actually used by SetupCasting
8550 gc->SetupCasting(spelldata.type, spelldata.level, spelldata.slot, actor, GA_NO_DEAD, spelldata.TargetNumber);
8551 gc->TryToCast(actor, actor);
8552 break;
8553 case TARGET_NONE:
8554 //reset the cursor
8555 gc->target_mode = TARGET_MODE_NONE;
8556 //this is always instant casting
8557 core->ApplySpell(spelldata.spellname, actor, actor, 0);
8558 break;
8559 case TARGET_AREA:
8560 gc->SetupCasting(spelldata.type, spelldata.level, spelldata.slot, actor, GA_POINT, spelldata.TargetNumber);
8561 break;
8562 case TARGET_CREA:
8563 gc->SetupCasting(spelldata.type, spelldata.level, spelldata.slot, actor, GA_NO_DEAD, spelldata.TargetNumber);
8564 break;
8565 case TARGET_DEAD:
8566 gc->SetupCasting(spelldata.type, spelldata.level, spelldata.slot, actor, 0, spelldata.TargetNumber);
8567 break;
8568 case TARGET_INV:
8569 //bring up inventory in the end???
8570 //break;
8571 default:
8572 printf("Unhandled target type: %d\n", spelldata.Target);
8573 break;
8575 Py_INCREF( Py_None );
8576 return Py_None;
8579 PyDoc_STRVAR( GemRB_ApplySpell__doc,
8580 "ApplySpell(actor, spellname)\n\n"
8581 "Applies a spell on actor.");
8583 static PyObject* GemRB_ApplySpell(PyObject * /*self*/, PyObject* args)
8585 int PartyID;
8586 const char *spell;
8588 if (!PyArg_ParseTuple( args, "is", &PartyID, &spell )) {
8589 return AttributeError( GemRB_ApplySpell__doc );
8592 Game *game = core->GetGame();
8593 if (!game) {
8594 return RuntimeError( "No game loaded!" );
8596 Actor* actor = game->FindPC( PartyID );
8597 if (!actor) {
8598 return RuntimeError( "Actor not found" );
8600 core->ApplySpell(spell, actor, actor, 0);
8602 Py_INCREF( Py_None );
8603 return Py_None;
8606 PyDoc_STRVAR( GemRB_UseItem__doc,
8607 "UseItem(actor, slot, header[,forcetarget])\n\n"
8608 "Makes the actor try to use an item. "
8609 "If slot is -1, then header is the index of the item functionality in the use item list. "
8610 "If slot is -2, then header is the quickslot index. "
8611 "If slot is non-negative, then header is the header of the item in the 'slot'.");
8613 static PyObject* GemRB_UseItem(PyObject * /*self*/, PyObject* args)
8615 int PartyID;
8616 int slot;
8617 int header;
8618 int forcetarget=-1; //some crappy scrolls don't target self correctly!
8620 if (!PyArg_ParseTuple( args, "iii|i", &PartyID, &slot, &header, &forcetarget )) {
8621 return AttributeError( GemRB_UseItem__doc );
8624 Game *game = core->GetGame();
8625 if (!game) {
8626 return RuntimeError( "No game loaded!" );
8628 Actor* actor = game->FindPC( PartyID );
8629 if (!actor) {
8630 return RuntimeError( "Actor not found" );
8632 ItemExtHeader itemdata;
8633 int flags = 0;
8635 switch (slot) {
8636 case -1:
8637 //some equipment
8638 actor->inventory.GetEquipmentInfo(&itemdata, header, 1);
8639 break;
8640 case -2:
8641 //quickslot
8642 actor->GetItemSlotInfo(&itemdata, header, -1);
8643 if (!itemdata.Charges) {
8644 printMessage("GUIScript","QuickItem has no charges.\n", WHITE);
8645 Py_INCREF( Py_None );
8646 return Py_None;
8648 break;
8649 default:
8650 //any normal slot
8651 actor->GetItemSlotInfo(&itemdata, core->QuerySlot(slot), header);
8652 flags = UI_SILENT;
8653 break;
8656 if(forcetarget==-1) {
8657 forcetarget = itemdata.Target;
8660 //is there any better check for a non existent item?
8661 if (!itemdata.itemname[0]) {
8662 printMessage("GUIScript","Empty slot used?\n", YELLOW);
8663 Py_INCREF( Py_None );
8664 return Py_None;
8667 /// remove this after projectile is done
8668 printf("Use item: %s\n", itemdata.itemname);
8669 printf("Extended header: %d\n", itemdata.headerindex);
8670 printf("Attacktype: %d\n",itemdata.AttackType);
8671 printf("Range: %d\n",itemdata.Range);
8672 printf("Target: %d\n",forcetarget);
8673 printf("Projectile: %d\n", itemdata.ProjectileAnimation);
8675 switch (forcetarget) {
8676 case TARGET_SELF:
8677 actor->UseItem(itemdata.slot, itemdata.headerindex, actor, flags);
8678 break;
8679 case TARGET_NONE:
8680 actor->UseItem(itemdata.slot, itemdata.headerindex, NULL, flags);
8681 break;
8682 case TARGET_AREA:
8683 core->GetGameControl()->SetupItemUse(itemdata.slot, itemdata.headerindex, actor, GA_POINT, itemdata.TargetNumber);
8684 break;
8685 case TARGET_CREA:
8686 core->GetGameControl()->SetupItemUse(itemdata.slot, itemdata.headerindex, actor, GA_NO_DEAD, itemdata.TargetNumber);
8687 break;
8688 case TARGET_DEAD:
8689 core->GetGameControl()->SetupItemUse(itemdata.slot, itemdata.headerindex, actor, 0, itemdata.TargetNumber);
8690 break;
8691 default:
8692 printMessage("GUIScript", "Unhandled target type!", LIGHT_RED );
8693 break;
8695 Py_INCREF( Py_None );
8696 return Py_None;
8699 PyDoc_STRVAR( GemRB_SetGamma__doc,
8700 "SetGamma(brightness, contrast)\n\n"
8701 "Adjusts brightness and contrast.");
8703 static PyObject* GemRB_SetGamma(PyObject * /*self*/, PyObject* args)
8705 int brightness, contrast;
8707 if (!PyArg_ParseTuple( args, "ii", &brightness, &contrast )) {
8708 return AttributeError( GemRB_SetGamma__doc );
8710 if (brightness<0 || brightness>40) {
8711 return RuntimeError( "Brightness must be 0-40" );
8713 if (contrast<0 || contrast>5) {
8714 return RuntimeError( "Contrast must be 0-5" );
8716 core->GetVideoDriver()->SetGamma(brightness, contrast);
8717 Py_INCREF( Py_None );
8718 return Py_None;
8721 PyDoc_STRVAR( GemRB_SetMouseScrollSpeed__doc,
8722 "SetMouseScrollSpeed(mouseSpeed)\n\n"
8723 "Adjusts mouse scroll speed.");
8725 static PyObject* GemRB_SetMouseScrollSpeed(PyObject * /*self*/, PyObject* args)
8727 int mouseSpeed;
8729 if (!PyArg_ParseTuple( args, "i", &mouseSpeed)) {
8730 return AttributeError( GemRB_SetMouseScrollSpeed__doc );
8733 core->SetMouseScrollSpeed(mouseSpeed);
8735 Py_INCREF( Py_None );
8736 return Py_None;
8739 PyDoc_STRVAR( GemRB_SetTooltipDelay__doc,
8740 "SetTooltipDelay(tooltipDelay)\n\n"
8741 "Adjusts tooltip appearing speed.");
8743 static PyObject* GemRB_SetTooltipDelay(PyObject * /*self*/, PyObject* args)
8745 int tooltipDelay;
8747 if (!PyArg_ParseTuple( args, "i", &tooltipDelay)) {
8748 return AttributeError( GemRB_SetTooltipDelay__doc );
8751 core->TooltipDelay = tooltipDelay;
8753 Py_INCREF( Py_None );
8754 return Py_None;
8757 PyDoc_STRVAR( GemRB_SetFullScreen__doc,
8758 "SetFullScreen(int)\n\n"
8759 "0 - windowed, 1 - fullscreen, -1 - toggle");
8761 static PyObject* GemRB_SetFullScreen(PyObject * /*self*/, PyObject* args)
8763 int fullscreen;
8765 if (!PyArg_ParseTuple( args, "i", &fullscreen )) {
8766 return AttributeError( GemRB_SetFullScreen__doc );
8768 core->GetVideoDriver()->ToggleFullscreenMode(fullscreen);
8769 Py_INCREF( Py_None );
8770 return Py_None;
8773 PyDoc_STRVAR( GemRB_RestParty__doc,
8774 "RestParty(noareacheck, dream, hp)\n\n"
8775 "Executes the party rest function, used from both stores and via the main screen.");
8777 static PyObject* GemRB_RestParty(PyObject * /*self*/, PyObject* args)
8779 int noareacheck;
8780 int dream, hp;
8782 if (!PyArg_ParseTuple( args, "iii", &noareacheck, &dream, &hp)) {
8783 return AttributeError( GemRB_RestParty__doc );
8785 Game *game = core->GetGame();
8786 if (!game) {
8787 return RuntimeError( "No game loaded!" );
8789 game->RestParty(noareacheck, dream, hp);
8790 Py_INCREF( Py_None );
8791 return Py_None;
8794 PyDoc_STRVAR( GemRB_HasSpecialItem__doc,
8795 "HasSpecialItem(pc, itemtype, useup) => bool\n\n"
8796 "Checks if a team member has an item, optionally uses it.");
8798 //itemtype 1 - identify
8799 static PyObject* GemRB_HasSpecialItem(PyObject * /*self*/, PyObject* args)
8801 int PartyID, itemtype, useup;
8803 if (!PyArg_ParseTuple( args, "iii", &PartyID, &itemtype, &useup)) {
8804 return AttributeError( GemRB_HasSpecialItem__doc );
8806 if (SpecialItemsCount==-1) {
8807 ReadSpecialItems();
8810 Game *game = core->GetGame();
8811 if (!game) {
8812 return RuntimeError( "No game loaded!" );
8814 Actor* actor = game->FindPC( PartyID );
8815 if (!actor) {
8816 return RuntimeError( "Actor not found" );
8818 int i = SpecialItemsCount;
8819 int slot = -1;
8820 while(i--) {
8821 if (itemtype&SpecialItems[i].value) {
8822 slot = actor->inventory.FindItem(SpecialItems[i].resref,0);
8823 if (slot>=0) {
8824 break;
8829 if (slot<0) {
8830 return PyInt_FromLong( 0 );
8833 if (useup) {
8834 //use the found item's first usage
8835 useup = actor->UseItem((ieDword) slot, 0, actor, UI_SILENT);
8836 } else {
8837 CREItem *si = actor->inventory.GetSlotItem( slot );
8838 if (si->Usages[0]) useup = 1;
8840 return PyInt_FromLong( useup );
8843 PyDoc_STRVAR( GemRB_HasSpecialSpell__doc,
8844 "HasSpecialSpell(pc, itemtype, useup) => bool\n\n"
8845 "Checks if a team member has a spell, optionally uses it.");
8847 //itemtype 1 - identify
8848 static PyObject* GemRB_HasSpecialSpell(PyObject * /*self*/, PyObject* args)
8850 int PartyID, itemtype, useup;
8852 if (!PyArg_ParseTuple( args, "iii", &PartyID, &itemtype, &useup)) {
8853 return AttributeError( GemRB_HasSpecialSpell__doc );
8855 if (SpecialSpellsCount==-1) {
8856 ReadSpecialSpells();
8859 Game *game = core->GetGame();
8860 if (!game) {
8861 return RuntimeError( "No game loaded!" );
8863 Actor* actor = game->FindPC( PartyID );
8864 if (!actor) {
8865 return RuntimeError( "Actor not found" );
8867 int i = SpecialSpellsCount;
8868 while(i--) {
8869 if (itemtype&SpecialSpells[i].value) {
8870 if (actor->spellbook.HaveSpell(SpecialSpells[i].resref,useup)) {
8871 if (useup) {
8872 //actor->SpellCast(SpecialSpells[i].resref, actor);
8874 break;
8879 if (i<0) {
8880 return PyInt_FromLong( 0 );
8882 return PyInt_FromLong( 1 );
8885 PyDoc_STRVAR( GemRB_ApplyEffect__doc,
8886 "ApplyEffect(pc, effect, param1, param2[,resref,resref2, resref3]])\n\n"
8887 "Creates a basic effect and applies it on the player character. "
8888 "This function could be used to add stats that are stored in effect blocks. "
8889 "The resource fields are optional.");
8891 static PyObject* GemRB_ApplyEffect(PyObject * /*self*/, PyObject* args)
8893 int PartyID;
8894 const char *opcodename;
8895 int param1, param2;
8896 const char *resref1 = NULL;
8897 const char *resref2 = NULL;
8898 const char *resref3 = NULL;
8899 const char *source = NULL;
8901 if (!PyArg_ParseTuple( args, "isii|ssss", &PartyID, &opcodename, &param1, &param2, &resref1, &resref2, &resref3, &source)) {
8902 return AttributeError( GemRB_ApplyEffect__doc );
8904 Game *game = core->GetGame();
8905 if (!game) {
8906 return RuntimeError( "No game loaded!" );
8908 Actor* actor = game->FindPC( PartyID );
8909 if (!actor) {
8910 return RuntimeError( "Actor not found" );
8912 work_ref.Name=opcodename;
8913 work_ref.opcode=-1;
8914 Effect *fx = EffectQueue::CreateEffect(work_ref, param1, param2, FX_DURATION_INSTANT_PERMANENT_AFTER_BONUSES);
8915 if (!fx) {
8916 //invalid effect name didn't resolve to opcode
8917 return RuntimeError( "Invalid effect name!" );
8919 if (resref1) {
8920 strnlwrcpy(fx->Resource, resref1, 8);
8922 if (resref2) {
8923 strnlwrcpy(fx->Resource2, resref2, 8);
8925 if (resref3) {
8926 strnlwrcpy(fx->Resource3, resref3, 8);
8928 if (source) {
8929 strnlwrcpy(fx->Source, source, 8);
8931 //This is a hack...
8932 fx->Parameter3=1;
8934 //fx is not freed by this function
8935 core->ApplyEffect(fx, actor, actor);
8937 //lets kill it
8938 delete fx;
8940 Py_INCREF( Py_None );
8941 return Py_None;
8944 PyDoc_STRVAR( GemRB_CountEffects__doc,
8945 "CountEffects(pc, effect, param1, param2[,resref])\n\n"
8946 "Counts how many matching effects are applied on the player character. "
8947 "This function could be used to get HLA information in ToB. "
8948 "The resource field is optional.");
8950 static PyObject* GemRB_CountEffects(PyObject * /*self*/, PyObject* args)
8952 int PartyID;
8953 const char *opcodename;
8954 int param1, param2;
8955 const char *resref = NULL;
8957 if (!PyArg_ParseTuple( args, "isii|s", &PartyID, &opcodename, &param1, &param2, &resref)) {
8958 return AttributeError( GemRB_CountEffects__doc );
8960 Game *game = core->GetGame();
8961 if (!game) {
8962 return RuntimeError( "No game loaded!" );
8964 Actor* actor = game->FindPC( PartyID );
8965 if (!actor) {
8966 return RuntimeError( "Actor not found" );
8968 work_ref.Name=opcodename;
8969 work_ref.opcode=-1;
8970 ieDword ret = actor->fxqueue.CountEffects(work_ref, param1, param2, resref);
8971 return PyInt_FromLong( ret );
8974 PyDoc_STRVAR( GemRB_ModifyEffect__doc,
8975 "ModifyEffect(pc, effect, p1, p2)\n\n"
8976 "Changes/sets the target coordinates of the specified effect. "
8977 "This command is used for the farsight spell.");
8979 static PyObject* GemRB_ModifyEffect(PyObject * /*self*/, PyObject* args)
8981 int PartyID;
8982 const char *opcodename;
8983 int px, py;
8985 if (!PyArg_ParseTuple( args, "isii", &PartyID, &opcodename, &px, &py)) {
8986 return AttributeError( GemRB_ModifyEffect__doc );
8988 Game *game = core->GetGame();
8989 if (!game) {
8990 return RuntimeError( "No game loaded!" );
8992 Actor* actor = game->FindPC( PartyID );
8993 if (!actor) {
8994 return RuntimeError( "Actor not found" );
8996 work_ref.Name=opcodename;
8997 work_ref.opcode=-1;
8998 actor->fxqueue.ModifyEffectPoint(work_ref, px, py);
8999 Py_INCREF( Py_None );
9000 return Py_None;
9003 PyDoc_STRVAR( GemRB_StealFailed__doc,
9004 "StealFailed()\n\n"
9005 "Sends the steal failed trigger (attacked) to the owner of the current store. "
9006 "The owner of the current store was set to the Sender of StartStore action.");
9008 static PyObject* GemRB_StealFailed(PyObject * /*self*/, PyObject* /*args*/)
9010 Game *game = core->GetGame();
9011 if (!game) {
9012 return RuntimeError( "No game loaded!" );
9014 Store *store = core->GetCurrentStore();
9015 if (!store) {
9016 return RuntimeError( "No store loaded!" );
9018 Map *map = game->GetCurrentArea();
9019 if (!map) {
9020 return RuntimeError( "No area loaded!" );
9022 Actor* owner = map->GetActor( store->GetOwner(), 0 );
9023 if (!owner) {
9024 printMessage("GUIScript", "No owner found!", YELLOW );
9025 Py_INCREF( Py_None );
9026 return Py_None;
9028 Actor* attacker = game->FindPC((int) game->GetSelectedPCSingle() );
9029 if (!attacker) {
9030 printMessage("GUIScript", "No thief found!", YELLOW );
9031 Py_INCREF( Py_None );
9032 return Py_None;
9034 //not sure if this is ok
9035 //owner->LastAttacker = attacker->GetID();
9036 owner->LastDisarmFailed = attacker->GetID();
9037 Py_INCREF( Py_None );
9038 return Py_None;
9041 PyDoc_STRVAR( GemRB_SwapPCs__doc,
9042 "SwapPCs(idx1, idx2)\n\n"
9043 "Swaps the party order for two player characters.");
9045 static PyObject* GemRB_SwapPCs(PyObject * /*self*/, PyObject* args)
9047 int idx1, idx2;
9049 if (!PyArg_ParseTuple( args, "ii", &idx1, &idx2)) {
9050 return AttributeError( GemRB_SwapPCs__doc );
9053 Game *game = core->GetGame();
9054 if (!game) {
9055 return RuntimeError( "No game loaded!" );
9058 game->SwapPCs(game->FindPlayer(idx1), game->FindPlayer(idx2));
9059 //leader changed
9060 if (idx1==1 || idx2==1) {
9061 DisplayStringCore( game->FindPC(1), VB_LEADER, DS_CONST);
9064 Py_INCREF( Py_None );
9065 return Py_None;
9068 PyDoc_STRVAR( GemRB_SetRepeatClickFlags__doc,
9069 "SetRepeatClickFlags(value, op)\n\n"
9070 "Sets the mode repeat clicks are handled.");
9072 static PyObject* GemRB_SetRepeatClickFlags(PyObject * /*self*/, PyObject* args)
9074 int value, op;
9075 unsigned long ret;
9077 if (!PyArg_ParseTuple( args, "ii", &value, &op)) {
9078 return AttributeError( GemRB_SetRepeatClickFlags__doc );
9080 ret = core->GetEventMgr()->SetRKFlags( (unsigned long) value, (unsigned long) op);
9081 return PyInt_FromLong( ret );
9084 PyDoc_STRVAR( GemRB_DisplayString__doc,
9085 "DisplayString(strref, color[,actor])\n\n"
9086 "Displays string on the MessageWindow using methods supplied by the engine core. "
9087 "The optional actor is the party ID of the character whose name will be displayed.");
9089 static PyObject* GemRB_DisplayString(PyObject * /*self*/, PyObject* args)
9091 int strref, color;
9092 int PartyID = 0;
9094 if (!PyArg_ParseTuple( args, "ii|i", &strref, &color, &PartyID)) {
9095 return AttributeError( GemRB_DisplayString__doc );
9097 if (PartyID) {
9098 Game *game = core->GetGame();
9099 if (!game) {
9100 return RuntimeError( "No game loaded!" );
9102 Actor *actor = game->FindPC(PartyID);
9103 if (!actor) {
9104 return RuntimeError( "Actor not found" );
9106 core->DisplayStringName(strref, (unsigned int) color, actor, IE_STR_SOUND);
9107 } else {
9108 core->DisplayString(strref, (unsigned int) color, IE_STR_SOUND);
9110 Py_INCREF( Py_None );
9111 return Py_None;
9114 PyDoc_STRVAR( GemRB_GetCombatDetails__doc,
9115 "GetCombatDetails(pc, leftorright) => dict\n\n"
9116 "Returns the current THAC0 and other data in relation to the equipped weapon.");
9118 static PyObject* GemRB_GetCombatDetails(PyObject * /*self*/, PyObject* args)
9120 int PartyID;
9121 int leftorright;
9123 if (!PyArg_ParseTuple( args, "ii", &PartyID, &leftorright)) {
9124 return AttributeError( GemRB_GetCombatDetails__doc );
9126 Game *game = core->GetGame();
9127 if (!game) {
9128 return RuntimeError( "No game loaded!" );
9130 Actor* actor = game->FindPC( PartyID );
9131 if (!actor) {
9132 return RuntimeError( "Actor not found" );
9135 leftorright = leftorright&1;
9136 WeaponInfo wi;
9137 ITMExtHeader *header = NULL;
9138 ITMExtHeader *hittingheader = NULL;
9139 int tohit=20;
9140 ieDword Flags=0;
9141 int DamageBonus=0, CriticalBonus=0;
9142 int speed, style=0;
9144 PyObject* dict = PyDict_New();
9145 if (!actor->GetCombatDetails(tohit, leftorright, wi, header, hittingheader, Flags, DamageBonus, speed, CriticalBonus, style)) {
9146 //TODO: handle error, so tohit will still be set correctly?
9148 PyDict_SetItemString(dict, "ToHit", PyInt_FromLong (tohit));
9149 PyDict_SetItemString(dict, "Flags", PyInt_FromLong (Flags));
9150 PyDict_SetItemString(dict, "DamageBonus", PyInt_FromLong (DamageBonus));
9151 PyDict_SetItemString(dict, "Speed", PyInt_FromLong (speed));
9152 PyDict_SetItemString(dict, "CriticalBonus", PyInt_FromLong (CriticalBonus));
9153 PyDict_SetItemString(dict, "Style", PyInt_FromLong (style));
9154 return dict;
9157 PyDoc_STRVAR( GemRB_IsDualWielding__doc,
9158 "IsDualWielding(pc)\n\n"
9159 "1 if the pc is dual wielding; 0 otherwise.");
9161 static PyObject* GemRB_IsDualWielding(PyObject * /*self*/, PyObject* args)
9163 int PartyID;
9165 if (!PyArg_ParseTuple( args, "i", &PartyID)) {
9166 return AttributeError( GemRB_IsDualWielding__doc );
9168 Game *game = core->GetGame();
9169 if (!game) {
9170 return RuntimeError( "No game loaded!" );
9172 Actor* actor = game->FindPC( PartyID );
9173 if (!actor) {
9174 return RuntimeError( "Actor not found" );
9177 int dualwield = actor->IsDualWielding();
9178 return PyInt_FromLong( dualwield );
9181 PyDoc_STRVAR( GemRB_GetSelectedSize__doc,
9182 "GetSelectedSize() => int\n\n"
9183 "Returns the number of actors selected in the party.");
9185 static PyObject* GemRB_GetSelectedSize(PyObject* /*self*/, PyObject* /*args*/)
9187 return PyInt_FromLong(core->GetGame()->selected.size());
9190 PyDoc_STRVAR( GemRB_GetSpellCastOn__doc,
9191 "GetSpellCastOn(pc) => resref\n\n"
9192 "Returns the last spell cast on a partymember.");
9194 static PyObject* GemRB_GetSpellCastOn(PyObject* /*self*/, PyObject* args)
9196 int PartyID;
9197 ieResRef splname;
9199 if (!PyArg_ParseTuple( args, "i", &PartyID )) {
9200 return AttributeError( GemRB_GetSpellCastOn__doc );
9202 Game *game = core->GetGame();
9203 if (!game) {
9204 return RuntimeError( "No game loaded!" );
9206 Actor* actor = game->FindPC( PartyID );
9207 if (!actor) {
9208 return RuntimeError( "Actor not found" );
9211 ResolveSpellName(splname, actor->LastSpellOnMe);
9212 return PyString_FromString(splname);
9215 static PyMethodDef GemRBMethods[] = {
9216 METHOD(ActOnPC, METH_VARARGS),
9217 METHOD(ApplyEffect, METH_VARARGS),
9218 METHOD(ApplySpell, METH_VARARGS),
9219 METHOD(CanUseItemType, METH_VARARGS),
9220 METHOD(ChangeContainerItem, METH_VARARGS),
9221 METHOD(ChangeItemFlag, METH_VARARGS),
9222 METHOD(ChangeStoreItem, METH_VARARGS),
9223 METHOD(CheckFeatCondition, METH_VARARGS),
9224 METHOD(CheckVar, METH_VARARGS),
9225 METHOD(ClearActions, METH_VARARGS),
9226 METHOD(CountEffects, METH_VARARGS),
9227 METHOD(CreateCreature, METH_VARARGS),
9228 METHOD(CreateItem, METH_VARARGS),
9229 METHOD(CreateMovement, METH_VARARGS),
9230 METHOD(CreatePlayer, METH_VARARGS),
9231 METHOD(CreateString, METH_VARARGS),
9232 METHOD(CreateWindow, METH_VARARGS),
9233 METHOD(DeleteSaveGame, METH_VARARGS),
9234 METHOD(DispelEffect, METH_VARARGS),
9235 METHOD(DisplayString, METH_VARARGS),
9236 METHOD(DragItem, METH_VARARGS),
9237 METHOD(DrawWindows, METH_NOARGS),
9238 METHOD(DropDraggedItem, METH_VARARGS),
9239 METHOD(EnableCheatKeys, METH_VARARGS),
9240 METHOD(EndCutSceneMode, METH_NOARGS),
9241 METHOD(EnterGame, METH_NOARGS),
9242 METHOD(EnterStore, METH_VARARGS),
9243 METHOD(EvaluateString, METH_VARARGS),
9244 METHOD(ExecuteString, METH_VARARGS),
9245 METHOD(ExploreArea, METH_VARARGS),
9246 METHOD(FillPlayerInfo, METH_VARARGS),
9247 METHOD(GameControlGetTargetMode, METH_NOARGS),
9248 METHOD(GameControlSetScreenFlags, METH_VARARGS),
9249 METHOD(GameControlSetTargetMode, METH_VARARGS),
9250 METHOD(GameGetReputation, METH_NOARGS),
9251 METHOD(GameSetReputation, METH_VARARGS),
9252 METHOD(GameGetFirstSelectedPC, METH_NOARGS),
9253 METHOD(GameGetFormation, METH_VARARGS),
9254 METHOD(GameGetPartyGold, METH_NOARGS),
9255 METHOD(GameGetSelectedPCSingle, METH_VARARGS),
9256 METHOD(GameIsBeastKnown, METH_VARARGS),
9257 METHOD(GameIsPCSelected, METH_VARARGS),
9258 METHOD(GamePause, METH_VARARGS),
9259 METHOD(GameSelectPC, METH_VARARGS),
9260 METHOD(GameSelectPCSingle, METH_VARARGS),
9261 METHOD(GameSetExpansion, METH_VARARGS),
9262 METHOD(GameSetFormation, METH_VARARGS),
9263 METHOD(GameSetPartyGold, METH_VARARGS),
9264 METHOD(GameSetPartySize, METH_VARARGS),
9265 METHOD(GameSetProtagonistMode, METH_VARARGS),
9266 METHOD(GameSetScreenFlags, METH_VARARGS),
9267 METHOD(GetAbilityBonus, METH_VARARGS),
9268 METHOD(GetCombatDetails, METH_VARARGS),
9269 METHOD(GetContainer, METH_VARARGS),
9270 METHOD(GetContainerItem, METH_VARARGS),
9271 METHOD(GetControl, METH_VARARGS),
9272 METHOD(GetCurrentArea, METH_NOARGS),
9273 METHOD(GetEquippedAmmunition, METH_VARARGS),
9274 METHOD(GetEquippedQuickSlot, METH_VARARGS),
9275 METHOD(GetGamePortraitPreview, METH_VARARGS),
9276 METHOD(GetGamePreview, METH_VARARGS),
9277 METHOD(GetGameString, METH_VARARGS),
9278 METHOD(GetGameTime, METH_NOARGS),
9279 METHOD(GetGameVar, METH_VARARGS),
9280 METHOD(GetINIBeastsKey, METH_VARARGS),
9281 METHOD(GetINIPartyCount, METH_NOARGS),
9282 METHOD(GetINIPartyKey, METH_VARARGS),
9283 METHOD(GetINIQuestsKey, METH_VARARGS),
9284 METHOD(GetItem, METH_VARARGS),
9285 METHOD(GetJournalEntry, METH_VARARGS),
9286 METHOD(GetJournalSize, METH_VARARGS),
9287 METHOD(GetKnownSpell, METH_VARARGS),
9288 METHOD(GetKnownSpellsCount, METH_VARARGS),
9289 METHOD(GetMemorizableSpellsCount, METH_VARARGS),
9290 METHOD(GetMemorizedSpell, METH_VARARGS),
9291 METHOD(GetMemorizedSpellsCount, METH_VARARGS),
9292 METHOD(GetMessageWindowSize, METH_NOARGS),
9293 METHOD(GetPartySize, METH_NOARGS),
9294 METHOD(GetPCStats, METH_VARARGS),
9295 METHOD(GetPlayerName, METH_VARARGS),
9296 METHOD(GetPlayerPortrait, METH_VARARGS),
9297 METHOD(GetPlayerStat, METH_VARARGS),
9298 METHOD(GetPlayerStates, METH_VARARGS),
9299 METHOD(GetPlayerScript, METH_VARARGS),
9300 METHOD(GetPlayerString, METH_VARARGS),
9301 METHOD(GetSaveGames, METH_VARARGS),
9302 METHOD(GetSelectedSize, METH_NOARGS),
9303 METHOD(GetString, METH_VARARGS),
9304 METHOD(GetSpellCastOn, METH_VARARGS),
9305 METHOD(GetToken, METH_VARARGS),
9306 METHOD(GetVar, METH_VARARGS),
9307 METHOD(GetSlotType, METH_VARARGS),
9308 METHOD(GetStore, METH_VARARGS),
9309 METHOD(GetStoreDrink, METH_VARARGS),
9310 METHOD(GetStoreCure, METH_VARARGS),
9311 METHOD(GetStoreItem, METH_VARARGS),
9312 METHOD(GetSpell, METH_VARARGS),
9313 METHOD(GetSlotItem, METH_VARARGS),
9314 METHOD(GetSlots, METH_VARARGS),
9315 METHOD(GetSystemVariable, METH_VARARGS),
9316 METHOD(GetRumour, METH_VARARGS),
9317 METHOD(HardEndPL, METH_NOARGS),
9318 METHOD(HasResource, METH_VARARGS),
9319 METHOD(HasSpecialItem, METH_VARARGS),
9320 METHOD(HasSpecialSpell, METH_VARARGS),
9321 METHOD(HideGUI, METH_NOARGS),
9322 METHOD(IncreaseReputation, METH_VARARGS),
9323 METHOD(IsDraggingItem, METH_NOARGS),
9324 METHOD(IsDualWielding, METH_VARARGS),
9325 METHOD(IsValidStoreItem, METH_VARARGS),
9326 METHOD(LearnSpell, METH_VARARGS),
9327 METHOD(LeaveContainer, METH_VARARGS),
9328 METHOD(LeaveParty, METH_VARARGS),
9329 METHOD(LeaveStore, METH_VARARGS),
9330 METHOD(LoadGame, METH_VARARGS),
9331 METHOD(LoadMusicPL, METH_VARARGS),
9332 METHOD(LoadSymbol, METH_VARARGS),
9333 METHOD(LoadTable, METH_VARARGS),
9334 METHOD(LoadWindowPack, METH_VARARGS),
9335 METHOD(LoadWindow, METH_VARARGS),
9336 METHOD(LoadWindowFrame, METH_VARARGS),
9337 METHOD(MemorizeSpell, METH_VARARGS),
9338 METHOD(ModifyEffect, METH_VARARGS),
9339 METHOD(MoveToArea, METH_VARARGS),
9340 METHOD(Quit, METH_NOARGS),
9341 METHOD(QuitGame, METH_NOARGS),
9342 METHOD(PlaySound, METH_VARARGS),
9343 METHOD(PlayMovie, METH_VARARGS),
9344 METHOD(RemoveItem, METH_VARARGS),
9345 METHOD(RemoveSpell, METH_VARARGS),
9346 METHOD(RemoveEffects, METH_VARARGS),
9347 METHOD(RestParty, METH_VARARGS),
9348 METHOD(RevealArea, METH_VARARGS),
9349 METHOD(Roll, METH_VARARGS),
9350 METHOD(RunEventHandler, METH_VARARGS),
9351 METHOD(SaveCharacter, METH_VARARGS),
9352 METHOD(SaveGame, METH_VARARGS),
9353 METHOD(SetDefaultActions, METH_VARARGS),
9354 METHOD(SetEquippedQuickSlot, METH_VARARGS),
9355 METHOD(SetFullScreen, METH_VARARGS),
9356 METHOD(SetGamma, METH_VARARGS),
9357 METHOD(SetGlobal, METH_VARARGS),
9358 METHOD(SetInfoTextColor, METH_VARARGS),
9359 METHOD(SetMapnote, METH_VARARGS),
9360 METHOD(SetMasterScript, METH_VARARGS),
9361 METHOD(SetMemorizableSpellsCount, METH_VARARGS),
9362 METHOD(SetModalState, METH_VARARGS),
9363 METHOD(SetMouseScrollSpeed, METH_VARARGS),
9364 METHOD(SetNextScript, METH_VARARGS),
9365 METHOD(SetPlayerName, METH_VARARGS),
9366 METHOD(SetPlayerScript, METH_VARARGS),
9367 METHOD(SetPlayerStat, METH_VARARGS),
9368 METHOD(SetPlayerString, METH_VARARGS),
9369 METHOD(SetPlayerSound, METH_VARARGS),
9370 METHOD(SetPurchasedAmount, METH_VARARGS),
9371 METHOD(SetRepeatClickFlags, METH_VARARGS),
9372 METHOD(SetTimedEvent, METH_VARARGS),
9373 METHOD(SetTimedEventByName, METH_VARARGS),
9374 METHOD(SetToken, METH_VARARGS),
9375 METHOD(SetTooltipDelay, METH_VARARGS),
9376 METHOD(SetupQuickSlot, METH_VARARGS),
9377 METHOD(SetVar, METH_VARARGS),
9378 METHOD(SoftEndPL, METH_NOARGS),
9379 METHOD(SpellCast, METH_VARARGS),
9380 METHOD(StatComment, METH_VARARGS),
9381 METHOD(StealFailed, METH_NOARGS),
9382 METHOD(SwapPCs, METH_VARARGS),
9383 METHOD(UnhideGUI, METH_NOARGS),
9384 METHOD(UnmemorizeSpell, METH_VARARGS),
9385 METHOD(UpdateAmbientsVolume, METH_NOARGS),
9386 METHOD(UpdateMusicVolume, METH_NOARGS),
9387 METHOD(UseItem, METH_VARARGS),
9388 // terminating entry
9389 {NULL, NULL, 0, NULL}
9392 static PyMethodDef GemRBInternalMethods[] = {
9393 METHOD(Button_CreateLabelOnButton, METH_VARARGS),
9394 METHOD(Button_EnableBorder, METH_VARARGS),
9395 METHOD(Button_SetActionIcon, METH_VARARGS),
9396 METHOD(Button_SetBAM, METH_VARARGS),
9397 METHOD(Button_SetBorder, METH_VARARGS),
9398 METHOD(Button_SetFlags, METH_VARARGS),
9399 METHOD(Button_SetFont, METH_VARARGS),
9400 METHOD(Button_SetItemIcon, METH_VARARGS),
9401 METHOD(Button_SetMOS, METH_VARARGS),
9402 METHOD(Button_SetOverlay, METH_VARARGS),
9403 METHOD(Button_SetPLT, METH_VARARGS),
9404 METHOD(Button_SetPicture, METH_VARARGS),
9405 METHOD(Button_SetPictureClipping, METH_VARARGS),
9406 METHOD(Button_SetSpellIcon, METH_VARARGS),
9407 METHOD(Button_SetSprite2D, METH_VARARGS),
9408 METHOD(Button_SetSprites, METH_VARARGS),
9409 METHOD(Button_SetState, METH_VARARGS),
9410 METHOD(Button_SetTextColor, METH_VARARGS),
9411 METHOD(Control_AttachScrollBar, METH_VARARGS),
9412 METHOD(Control_QueryText, METH_VARARGS),
9413 METHOD(Control_SetAnimation, METH_VARARGS),
9414 METHOD(Control_SetAnimationPalette, METH_VARARGS),
9415 METHOD(Control_SetEvent, METH_VARARGS),
9416 METHOD(Control_SetEventByName, METH_VARARGS),
9417 METHOD(Control_SetPos, METH_VARARGS),
9418 METHOD(Control_SetSize, METH_VARARGS),
9419 METHOD(Control_SetStatus, METH_VARARGS),
9420 METHOD(Control_SetText, METH_VARARGS),
9421 METHOD(Control_SetTooltip, METH_VARARGS),
9422 METHOD(Control_SetVarAssoc, METH_VARARGS),
9423 METHOD(Control_TextArea_SetFlags, METH_VARARGS),
9424 METHOD(Label_SetTextColor, METH_VARARGS),
9425 METHOD(Label_SetUseRGB, METH_VARARGS),
9426 METHOD(SaveGame_GetDate, METH_VARARGS),
9427 METHOD(SaveGame_GetGameDate, METH_VARARGS),
9428 METHOD(SaveGame_GetName, METH_VARARGS),
9429 METHOD(SaveGame_GetPortrait, METH_VARARGS),
9430 METHOD(SaveGame_GetPreview, METH_VARARGS),
9431 METHOD(SaveGame_GetSaveID, METH_VARARGS),
9432 METHOD(ScrollBar_SetDefaultScrollBar, METH_VARARGS),
9433 METHOD(ScrollBar_SetSprites, METH_VARARGS),
9434 METHOD(Symbol_GetValue, METH_VARARGS),
9435 METHOD(Symbol_Unload, METH_VARARGS),
9436 METHOD(Table_FindValue, METH_VARARGS),
9437 METHOD(Table_GetColumnCount, METH_VARARGS),
9438 METHOD(Table_GetColumnIndex, METH_VARARGS),
9439 METHOD(Table_GetColumnName, METH_VARARGS),
9440 METHOD(Table_GetRowCount, METH_VARARGS),
9441 METHOD(Table_GetRowIndex, METH_VARARGS),
9442 METHOD(Table_GetRowName, METH_VARARGS),
9443 METHOD(Table_GetValue, METH_VARARGS),
9444 METHOD(Table_Unload, METH_VARARGS),
9445 METHOD(TextArea_Append, METH_VARARGS),
9446 METHOD(TextArea_Clear, METH_VARARGS),
9447 METHOD(TextArea_GetCharSounds, METH_VARARGS),
9448 METHOD(TextArea_GetCharacters, METH_VARARGS),
9449 METHOD(TextArea_GetPortraits, METH_VARARGS),
9450 METHOD(TextArea_MoveText, METH_VARARGS),
9451 METHOD(TextArea_Rewind, METH_VARARGS),
9452 METHOD(TextArea_Scroll, METH_VARARGS),
9453 METHOD(TextArea_SetHistory, METH_VARARGS),
9454 METHOD(TextEdit_ConvertEdit, METH_VARARGS),
9455 METHOD(TextEdit_SetBufferLength, METH_VARARGS),
9456 METHOD(Window_CreateButton, METH_VARARGS),
9457 METHOD(Window_CreateLabel, METH_VARARGS),
9458 METHOD(Window_CreateMapControl, METH_VARARGS),
9459 METHOD(Window_CreateScrollBar, METH_VARARGS),
9460 METHOD(Window_CreateTextEdit, METH_VARARGS),
9461 METHOD(Window_CreateWorldMapControl, METH_VARARGS),
9462 METHOD(Window_DeleteControl, METH_VARARGS),
9463 METHOD(Window_GetControl, METH_VARARGS),
9464 METHOD(Window_HasControl, METH_VARARGS),
9465 METHOD(Window_Invalidate, METH_VARARGS),
9466 METHOD(Window_SetFrame, METH_VARARGS),
9467 METHOD(Window_SetPicture, METH_VARARGS),
9468 METHOD(Window_SetPos, METH_VARARGS),
9469 METHOD(Window_SetSize, METH_VARARGS),
9470 METHOD(Window_SetVisible, METH_VARARGS),
9471 METHOD(Window_SetupControls, METH_VARARGS),
9472 METHOD(Window_SetupEquipmentIcons, METH_VARARGS),
9473 METHOD(Window_SetupSpellIcons, METH_VARARGS),
9474 METHOD(Window_ShowModal, METH_VARARGS),
9475 METHOD(Window_Unload, METH_VARARGS),
9476 METHOD(WorldMap_AdjustScrolling, METH_VARARGS),
9477 METHOD(WorldMap_GetDestinationArea, METH_VARARGS),
9478 METHOD(WorldMap_SetTextColor, METH_VARARGS),
9479 // terminating entry
9480 {NULL, NULL, 0, NULL}
9483 GUIScript::GUIScript(void)
9485 gs = this;
9486 pDict = NULL; //borrowed, but used outside a function
9487 pModule = NULL; //should decref it
9488 pMainDic = NULL; //borrowed, but used outside a function
9491 GUIScript::~GUIScript(void)
9493 if (Py_IsInitialized()) {
9494 if (pModule) {
9495 Py_DECREF( pModule );
9497 Py_Finalize();
9499 if (ItemArray) {
9500 free(ItemArray);
9501 ItemArray=NULL;
9503 if (SpellArray) {
9504 free(SpellArray);
9505 SpellArray=NULL;
9507 if (StoreSpells) {
9508 free(StoreSpells);
9509 StoreSpells=NULL;
9511 if (SpecialSpells) {
9512 free(SpecialSpells);
9513 SpecialSpells=NULL;
9515 if (SpecialItems) {
9516 free(SpecialItems);
9517 SpecialItems=NULL;
9519 if (UsedItems) {
9520 free(UsedItems);
9521 UsedItems=NULL;
9523 if (ItemSounds) {
9524 free(ItemSounds);
9525 ItemSounds=NULL;
9528 StoreSpellsCount = -1;
9529 SpecialSpellsCount = -1;
9530 SpecialItemsCount = -1;
9531 UsedItemsCount = -1;
9532 ItemSoundsCount = -1;
9533 ReputationIncrease[0]=(int) UNINIT_IEDWORD;
9534 ReputationDonation[0]=(int) UNINIT_IEDWORD;
9535 GUIAction[0]=UNINIT_IEDWORD;
9538 PyDoc_STRVAR( GemRB__doc,
9539 "Module exposing GemRB data and engine internals\n\n"
9540 "This module exposes to python GUIScripts GemRB engine data and internals."
9541 "It's implemented in gemrb/plugins/GUIScript/GUIScript.cpp" );
9543 PyDoc_STRVAR( GemRB_internal__doc,
9544 "Internal module for GemRB metaclasses.\n\n"
9545 "This module is only for implementing GUIClass.py."
9546 "It's implemented in gemrb/plugins/GUIScript/GUIScript.cpp" );
9548 /** Initialization Routine */
9550 bool GUIScript::Init(void)
9552 Py_Initialize();
9553 if (!Py_IsInitialized()) {
9554 return false;
9556 PyObject* pGemRB = Py_InitModule3( "GemRB", GemRBMethods, GemRB__doc );
9557 if (!pGemRB) {
9558 return false;
9561 PyObject* p_GemRB = Py_InitModule3( "_GemRB", GemRBInternalMethods, GemRB_internal__doc );
9562 if (!p_GemRB) {
9563 return false;
9566 char string[256];
9568 sprintf( string, "import sys" );
9569 if (PyRun_SimpleString( string ) == -1) {
9570 printMessage( "GUIScript", string, RED );
9571 return false;
9573 char path[_MAX_PATH];
9574 char path2[_MAX_PATH];
9576 PathJoin(path, core->GUIScriptsPath, "GUIScripts", NULL);
9578 // use the iwd guiscripts for how, but leave its override
9579 if (stricmp( core->GameType, "how" ) == 0) {
9580 PathJoin(path2, path, "iwd", NULL);
9581 } else {
9582 PathJoin(path2, path, core->GameType, NULL);
9585 #ifdef WIN32
9586 char *p;
9588 for (p = path; *p != 0; p++)
9590 if (*p == '\\')
9591 *p = '/';
9594 for (p = path2; *p != 0; p++)
9596 if (*p == '\\')
9597 *p = '/';
9599 #endif
9601 sprintf( string, "sys.path.append(\"%s\")", path2 );
9602 if (PyRun_SimpleString( string ) == -1) {
9603 printMessage( "GUIScript", string, RED );
9604 return false;
9606 sprintf( string, "sys.path.append(\"%s\")", path );
9607 if (PyRun_SimpleString( string ) == -1) {
9608 printMessage( "GUIScript", string, RED );
9609 return false;
9611 sprintf( string, "import GemRB\n");
9612 if (PyRun_SimpleString( "import GemRB" ) == -1) {
9613 printMessage( "GUIScript", string, RED );
9614 return false;
9617 sprintf( string, "GemRB.GameType = \"%s\"", core->GameType);
9618 if (PyRun_SimpleString( string ) == -1) {
9619 printMessage( "GUIScript", string, RED );
9620 return false;
9623 #if PY_MAJOR_VERSION == 2
9624 #if PY_MINOR_VERSION > 5
9625 // warn about python stuff that will go away in 3.0
9626 Py_Py3kWarningFlag = true;
9627 #endif
9628 #endif
9630 if (PyRun_SimpleString( "from GUIDefines import *" ) == -1) {
9631 printMessage( "GUIScript", " ", RED );
9632 printf("Check if %s/GUIDefines.py exists! ", path);
9633 return false;
9636 if (PyRun_SimpleString( "from GUIClasses import *" ) == -1) {
9637 printMessage( "GUIScript", " ", RED );
9638 printf("Check if %s/GUIClasses.py exists! ", path);
9639 return false;
9642 if (PyRun_SimpleString( "from GemRB import *" ) == -1) {
9643 printMessage( "GUIScript", " ", RED );
9644 printf("builtin GemRB module failed to load!!! ");
9645 return false;
9648 PyObject *pMainMod = PyImport_AddModule( "__main__" );
9649 /* pMainMod is a borrowed reference */
9650 pMainDic = PyModule_GetDict( pMainMod );
9651 /* pMainDic is a borrowed reference */
9653 PyObject *pClassesMod = PyImport_AddModule( "GUIClasses" );
9654 /* pClassesMod is a borrowed reference */
9655 pGUIClasses = PyModule_GetDict( pClassesMod );
9656 /* pGUIClasses is a borrowed reference */
9658 return true;
9661 bool GUIScript::LoadScript(const char* filename)
9663 if (!Py_IsInitialized()) {
9664 return false;
9666 printMessage( "GUIScript", "Loading Script ", WHITE );
9667 printf( "%s...", filename );
9669 char path[_MAX_PATH];
9670 strcpy( path, filename );
9672 PyObject *pName = PyString_FromString( filename );
9673 /* Error checking of pName left out */
9674 if (pName == NULL) {
9675 printStatus( "ERROR", LIGHT_RED );
9676 return false;
9679 if (pModule) {
9680 Py_DECREF( pModule );
9683 pModule = PyImport_Import( pName );
9684 Py_DECREF( pName );
9686 if (pModule != NULL) {
9687 pDict = PyModule_GetDict( pModule );
9688 if (PyDict_Merge( pDict, pMainDic, false ) == -1)
9689 return false;
9690 /* pDict is a borrowed reference */
9691 } else {
9692 PyErr_Print();
9693 printStatus( "ERROR", LIGHT_RED );
9694 return false;
9696 printStatus( "OK", LIGHT_GREEN );
9697 return true;
9700 /* Similar to RunFunction, but with parameters, and doesn't necessarily fails */
9701 PyObject *GUIScript::CallbackFunction(const char* fname, PyObject* pArgs)
9703 if (!Py_IsInitialized()) {
9704 return NULL;
9706 if (pDict == NULL) {
9707 return NULL;
9709 PyObject *pFunc = PyDict_GetItemString( pDict, (char *) fname );
9710 /* pFunc: Borrowed reference */
9711 if (( !pFunc ) || ( !PyCallable_Check( pFunc ) )) {
9712 printMessage("GUIScript", " ", LIGHT_RED);
9713 printf("%s is not callable!\n", fname);
9714 return NULL;
9716 PyObject *pValue = PyObject_CallObject( pFunc, pArgs );
9717 if (pValue == NULL) {
9718 if (PyErr_Occurred()) {
9719 PyErr_Print();
9722 return pValue;
9725 bool GUIScript::RunFunction(const char *ModuleName, const char* FunctionName, bool error, int intparam)
9727 if (!Py_IsInitialized()) {
9728 return false;
9731 PyObject *module;
9732 if (ModuleName) {
9733 module = PyImport_Import(PyString_FromString(ModuleName));
9734 } else {
9735 module = pModule;
9736 Py_XINCREF(module);
9738 if (module == NULL) {
9739 return false;
9741 PyObject *dict = PyModule_GetDict(module);
9743 PyObject *pFunc = PyDict_GetItemString( dict, const_cast<char*>(FunctionName) );
9744 /* pFunc: Borrowed reference */
9745 if (( !pFunc ) || ( !PyCallable_Check( pFunc ) )) {
9746 if (error) {
9747 printMessage( "GUIScript", "Missing function:", LIGHT_RED );
9748 printf("%s\n", FunctionName);
9750 Py_DECREF(module);
9751 return false;
9753 PyObject *pArgs;
9754 if (intparam == -1) {
9755 pArgs = NULL;
9756 } else {
9757 pArgs = Py_BuildValue("(i)", intparam);
9759 PyObject *pValue = PyObject_CallObject( pFunc, pArgs );
9760 Py_XDECREF( pArgs );
9761 if (pValue == NULL) {
9762 if (PyErr_Occurred()) {
9763 PyErr_Print();
9765 Py_DECREF(module);
9766 return false;
9768 Py_DECREF( pValue );
9769 Py_DECREF(module);
9770 return true;
9773 /** Exec a single String */
9774 void GUIScript::ExecString(const char* string)
9776 if (PyRun_SimpleString( (char *) string ) == -1) {
9777 if (PyErr_Occurred()) {
9778 PyErr_Print();
9783 PyObject* GUIScript::ConstructObject(const char* type, int arg)
9785 PyObject* tuple = PyTuple_New(1);
9786 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(arg));
9787 PyObject* ret = gs->ConstructObject(type, tuple);
9788 Py_DECREF(tuple);
9789 return ret;
9792 PyObject* GUIScript::ConstructObject(const char* type, PyObject* pArgs)
9794 char classname[_MAX_PATH] = "G";
9795 strncat(classname, type, _MAX_PATH - 2);
9796 if (!pGUIClasses) {
9797 char buf[256];
9798 snprintf(buf, sizeof(buf), "Tried to use an object (%s) before script compiled!", classname);
9799 return RuntimeError(buf);
9802 PyObject* cobj = PyDict_GetItemString( pGUIClasses, classname );
9803 if (!cobj) {
9804 char buf[256];
9805 snprintf(buf, sizeof(buf), "Failed to lookup name '%s'", classname);
9806 return RuntimeError(buf);
9808 PyObject* ret = PyObject_Call(cobj, pArgs, NULL);
9809 if (!ret) {
9810 return RuntimeError("Failed to call constructor");
9812 return ret;
9815 #include "plugindef.h"
9817 GEMRB_PLUGIN(0x1B01BE6B, "GUI Script Engine (Python)")
9818 PLUGIN_CLASS(IE_GUI_SCRIPT_CLASS_ID, GUIScript)
9819 END_PLUGIN()