1# -*-python-*-
2# GemRB - Infinity Engine Emulator
3# Copyright (C) 2010 The GemRB Project
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; either version 2
8# of the License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18#
19
20import GemRB
21import GameCheck
22import GUIClasses
23import GUICommon
24import GUIWORLD
25import InventoryCommon
26from ie_stats import *
27from GUIDefines import *
28
29def SetGameGUIHidden(hide):
30	op = OP_OR if hide else OP_NAND
31	GemRB.GameSetScreenFlags(GS_HIDEGUI, op)
32
33def IsGameGUIHidden():
34	return GemRB.GetGUIFlags() & GS_HIDEGUI
35
36# for keymap.2da
37def ToggleGUIHidden():
38	SetGameGUIHidden(not IsGameGUIHidden())
39
40
41##################################################################
42# functions dealing with containers
43##################################################################
44
45HideOnClose = False
46ContainerWindow = None
47Container = None
48if GameCheck.IsIWD2():
49	leftdiv = 5
50	ground_size = 10
51else:
52	leftdiv = 3
53	ground_size = 6
54
55if GameCheck.IsPST():
56	import GUICommonWindows
57
58def UpdateContainerWindow ():
59	global Container
60
61	Window = ContainerWindow
62
63	pc = GemRB.GameGetFirstSelectedPC ()
64	if GameCheck.IsPST():
65		GUICommon.SetEncumbranceLabels (Window, 54, None, pc)
66	else:
67		GUICommon.SetEncumbranceLabels (Window, 0x10000045, 0x10000046, pc)
68
69	party_gold = GemRB.GameGetPartyGold ()
70	Text = Window.GetControl (0x10000036)
71	Text.SetText (str (party_gold))
72
73	Container = GemRB.GetContainer (0) #will use first selected pc anyway
74	LeftCount = Container['ItemCount']
75	ScrollBar = Window.GetControl (52)
76	Count = max (0, (LeftCount - ground_size + leftdiv - 1) // leftdiv)
77	ScrollBar.SetVarAssoc ("LeftTopIndex", GemRB.GetVar ("LeftTopIndex"), 0, Count)
78
79	inventory_slots = GemRB.GetSlots (pc, 0x8000)
80	RightCount = len(inventory_slots)
81	ScrollBar = Window.GetControl (53)
82	Count = max (0, (RightCount - 4 + 1) // 2)
83	ScrollBar.SetVarAssoc ("RightTopIndex", GemRB.GetVar ("RightTopIndex"), 0, Count)
84
85	RedrawContainerWindow ()
86
87def RedrawContainerWindow ():
88	Window = ContainerWindow
89
90	# scroll in multiples of the number of columns
91	LeftTopIndex = GemRB.GetVar ("LeftTopIndex") * leftdiv
92	RightTopIndex = GemRB.GetVar ("RightTopIndex") * 2
93	pc = GemRB.GameGetFirstSelectedPC ()
94	inventory_slots = GemRB.GetSlots (pc, 0x8000)
95	RightCount = len(inventory_slots)
96
97	for i in range (ground_size):
98		#this is an autoselected container, but we could use PC too
99		Slot = GemRB.GetContainerItem (0, i+LeftTopIndex)
100		Button = Window.GetControl (i)
101		if Slot:
102			Button.SetVarAssoc ("LeftIndex", LeftTopIndex+i)
103			function = TakeItemContainer
104		else:
105			Button.SetVarAssoc ("LeftIndex", -1)
106			function = None
107		if GameCheck.IsPST():
108			GUICommonWindows.SetItemButton (Window, Button, Slot, function, None)
109		else:
110			InventoryCommon.UpdateInventorySlot (pc, Button, Slot, "container")
111
112	for i in range (4):
113		if i+RightTopIndex < RightCount:
114			Slot = GemRB.GetSlotItem (pc, inventory_slots[i+RightTopIndex])
115		else:
116			Slot = None
117		Button = Window.GetControl (i+10)
118
119		#pst had a redundant call here, reenable if it turns out it isn't redundant:
120		#GUICommonWindows.SetItemButton (Window, Button, Slot, None, None)
121
122		if Slot:
123			Button.SetVarAssoc ("RightIndex", RightTopIndex+i)
124			function = DropItemContainer
125		else:
126			Button.SetVarAssoc ("RightIndex", -1)
127			function = None
128		if GameCheck.IsPST():
129			GUICommonWindows.SetItemButton (Window, Button, Slot, function, None)
130		else:
131			InventoryCommon.UpdateInventorySlot (pc, Button, Slot, "inventory")
132
133	# shade the inventory icon if it is full
134	Button = Window.GetControl (54)
135	if Button:
136		free_slots = GemRB.GetSlots (pc, 0x8000, -1)
137		if free_slots == ():
138			Button.SetState (IE_GUI_BUTTON_PRESSED)
139		else:
140			Button.SetState (IE_GUI_BUTTON_LOCKED)
141
142def OpenContainerWindow ():
143	global ContainerWindow, Container
144
145	if ContainerWindow:
146		return
147
148	global HideOnClose
149	HideOnClose = IsGameGUIHidden()
150
151	if HideOnClose:
152		SetGameGUIHidden(False)
153		# must use a timed event because SetGameGUIHidden(False) sets a flag to unhide the gui next frame
154		# AFIK not needed, commented out in case it turns out there are conditions we will need it
155		# GemRB.SetTimedEvent (lambda: GemRB.GetView ("MSGWIN").SetVisible(False), 1)
156	else:
157		GemRB.GetView ("MSGWIN").SetVisible (False)
158		ActWin = GemRB.GetView ("ACTWIN")
159		if ActWin:
160			ActWin.SetVisible (False)
161
162	ContainerWindow = Window = GemRB.LoadWindow (8, GUICommon.GetWindowPack(), WINDOW_BOTTOM|WINDOW_HCENTER)
163	# fix wrong height in the guiw10.chu and reposition
164	# that chu is also used as a base for some arbitrary resolutions
165	if GameCheck.IsBG2 () and GemRB.GetSystemVariable (SV_HEIGHT) >= 768:
166		Size = Window.GetSize ()
167		Pos = Window.GetPos ()
168		Window.SetSize (Size[0], 90)
169		Window.SetPos (Pos[0], GemRB.GetSystemVariable (SV_HEIGHT) - 90)
170
171	if not GameCheck.IsIWD2 () and not GameCheck.IsGemRBDemo () and not GameCheck.IsPST ():
172		# container window shouldnt be in front
173		GemRB.GetView("OPTWIN").Focus()
174		GemRB.GetView("PORTWIN").Focus()
175
176	Container = GemRB.GetContainer(0)
177
178	# Gears (time) when options pane is down
179	if GameCheck.IsBG2():
180		Button = Window.GetControl (62)
181		if Button: # the demo lacks this button
182			Label = Button.CreateLabel (0x10000047, "NORMAL", "", IE_FONT_SINGLE_LINE)
183
184			Label.SetAnimation ("CPEN")
185			Button.SetAnimation ("CGEAR")
186			Button.SetBAM ("CDIAL", 0, 0)
187			Button.SetState (IE_GUI_BUTTON_ENABLED)
188			Button.SetFlags (IE_GUI_BUTTON_PICTURE|IE_GUI_BUTTON_ANIMATED|IE_GUI_BUTTON_NORMAL, OP_SET)
189			Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, GUICommon.GearsClicked)
190			GUICommon.SetGamedaysAndHourToken()
191			Button.SetTooltip(16041)
192
193	# 0-5 - Ground Item
194	for i in range (ground_size):
195		Button = Window.GetControl (i)
196		Button.SetVarAssoc ("LeftIndex", i)
197		Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, TakeItemContainer)
198		if GameCheck.IsPST():
199			Button.SetFont ("NUMBER")
200			Button.SetFlags (IE_GUI_BUTTON_ALIGN_RIGHT | IE_GUI_BUTTON_ALIGN_BOTTOM, OP_OR)
201
202	# 10-13 - Personal Item
203	for i in range (4):
204		Button = Window.GetControl (i+10)
205		Button.SetVarAssoc ("RightIndex", i)
206		Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, DropItemContainer)
207		if GameCheck.IsPST():
208			Button.SetFont ("NUMBER")
209			Button.SetFlags (IE_GUI_BUTTON_ALIGN_RIGHT | IE_GUI_BUTTON_ALIGN_BOTTOM, OP_OR)
210
211	# left scrollbar (container)
212	ScrollBar = Window.GetControl (52)
213	ScrollBar.SetVisible(True) # unhide because in PST it is linked to a TextArea
214	ScrollBar.SetEvent (IE_GUI_SCROLLBAR_ON_CHANGE, RedrawContainerWindow)
215
216	# right scrollbar (inventory)
217	ScrollBar = Window.GetControl (53)
218	ScrollBar.SetVisible(True) # unhide because in PST it is linked to a TextArea
219	ScrollBar.SetEvent (IE_GUI_SCROLLBAR_ON_CHANGE, RedrawContainerWindow)
220
221	# encumbrance and inventory icon
222	# iwd has a handy button
223	Button = Window.GetControl (54)
224	if Button:
225		if GameCheck.IsPST():
226			Button.SetFont ("NUMBER")
227			Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_SET)
228		Button.CreateLabel (0x10000045, "NUMBER", "", IE_FONT_ALIGN_LEFT|IE_FONT_ALIGN_TOP|IE_FONT_SINGLE_LINE)
229		Button.CreateLabel (0x10000046, "NUMBER", "", IE_FONT_ALIGN_RIGHT|IE_FONT_ALIGN_BOTTOM|IE_FONT_SINGLE_LINE)
230	else:
231		Window.CreateLabel (0x10000045, 323, 14, 60, 15, "NUMBER", "0:", IE_FONT_ALIGN_LEFT|IE_FONT_ALIGN_TOP|IE_FONT_SINGLE_LINE)
232		Window.CreateLabel (0x10000046, 323, 20, 80, 15, "NUMBER", "0:", IE_FONT_ALIGN_RIGHT|IE_FONT_ALIGN_TOP|IE_FONT_SINGLE_LINE)
233
234	# container icon
235	Button = Window.GetControl (50)
236	if GameCheck.IsPST():
237		Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_SET)
238	Button.SetState (IE_GUI_BUTTON_LOCKED)
239
240	if not GameCheck.IsPST():
241		Table = GemRB.LoadTable ("containr")
242		row = Container['Type']
243		tmp = Table.GetValue (row, 0)
244		if tmp!='*':
245			GemRB.PlaySound (tmp)
246		tmp = Table.GetValue (row, 1)
247		if tmp!='*':
248			Button.SetSprites (tmp, 0, 0, 0, 0, 0 )
249
250	# Done
251	Button = Window.GetControl (51)
252	if GameCheck.IsPST():
253		Button.SetText (1403)
254	else:
255		Button.SetText ("")
256
257	Button.MakeEscape()
258	Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, LeaveContainer)
259
260	GemRB.SetVar ("LeftTopIndex", 0)
261	GemRB.SetVar ("RightTopIndex", 0)
262	UpdateContainerWindow ()
263
264def CloseContainerWindow ():
265	global ContainerWindow
266
267	if not ContainerWindow:
268		return
269
270	ContainerWindow.Close ()
271	ContainerWindow = None
272	GemRB.GetView ("MSGWIN").SetVisible (True)
273	if GemRB.GetView ("ACTWIN"):
274		GemRB.GetView ("ACTWIN").SetVisible (True)
275	SetGameGUIHidden(HideOnClose)
276
277	Table = GemRB.LoadTable ("containr")
278	row = Container['Type']
279	tmp = Table.GetValue (row, 2)
280	#play closing sound if applicable
281	if tmp!='*':
282		GemRB.PlaySound (tmp)
283
284#doing this way it will inform the core system too, which in turn will call
285#CloseContainerWindow ()
286def LeaveContainer ():
287	GemRB.LeaveContainer()
288
289def DropItemContainer ():
290	RightIndex = GemRB.GetVar ("RightIndex")
291	if RightIndex < 0:
292		return
293
294	#we need to get the right slot number
295	pc = GemRB.GameGetFirstSelectedPC ()
296	inventory_slots = GemRB.GetSlots (pc, 0x8000)
297	if RightIndex >= len(inventory_slots):
298		return
299
300	GemRB.ChangeContainerItem (0, inventory_slots[RightIndex], 0)
301	UpdateContainerWindow ()
302
303def TakeItemContainer ():
304	LeftIndex = GemRB.GetVar ("LeftIndex")
305	if LeftIndex < 0:
306		return
307
308	if LeftIndex >= Container['ItemCount']:
309		return
310
311	GemRB.ChangeContainerItem (0, LeftIndex, 1)
312	UpdateContainerWindow ()
313