1# GemRB - Infinity Engine Emulator
2# Copyright (C) 2003 The GemRB Project
3#
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.
8#
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.
13#
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.
17#
18#
19# Some small attempt to re-use code in character generation.
20# Attempting to emulate lynx's loop method from BG2 GUI
21
22# Should be called CharGenCommon for continuity but I started
23# this with something else in mind and then changed it
24# - Fyorl
25
26# CharOverview.py (GUICG)
27
28import GemRB
29from GUIDefines import *
30from ie_stats import *
31
32CharGenWindow = 0
33TextAreaControl = 0
34PortraitButton = 0
35StepButtons = {}
36PersistButtons = {}
37Steps = ['Gender', 'Race', 'Class', 'Alignment', 'Abilities', 'Enemy', 'Appearance', 'Name']
38GlobalStep = 0
39
40### Utility functions
41def AddText(strref, newlines=0):
42	TextAreaControl.Append (strref)
43	TextAreaControl.Append ("\n" * newlines)
44### End utility functions
45
46def PositionCharGenWin(window, offset = 0):
47	global CharGenWindow
48
49	CGFrame = CharGenWindow.GetFrame()
50	WFrame = window.GetFrame()
51	window.SetPos(CGFrame['x'] + CGFrame['w'] - WFrame['w'] - 18,
52				  offset + CGFrame['y'] + (CGFrame['h'] - WFrame['h'] - 24))
53
54def UpdateOverview(CurrentStep):
55	global CharGenWindow, TextAreaControl, PortraitButton
56	global StepButtons, Steps, PersistButtons, GlobalStep
57
58	GlobalStep = CurrentStep
59
60	CharGenWindow = GemRB.LoadWindow(0, "GUICG")
61	CharGenWindow.SetFlags (IE_GUI_VIEW_IGNORE_EVENTS, OP_OR)
62
63	PortraitButton = CharGenWindow.GetControl(12)
64	PortraitButton.SetFlags(IE_GUI_BUTTON_PICTURE|IE_GUI_BUTTON_NO_IMAGE,OP_SET)
65
66	# Handle portrait
67	PortraitName = GemRB.GetToken('LargePortrait')
68	if PortraitName != '' and CurrentStep > 1:
69		PortraitButton.SetPicture(PortraitName, 'NOPORTLG')
70
71	# Handle step buttons
72	TextLookup = [11956, 11957, 11959, 11958, 11960, 11983, 11961, 11963]
73	for i, Step in enumerate(Steps):
74		StepButtons[Step] = CharGenWindow.GetControl(i)
75		StepButtons[Step].SetText(TextLookup[i])
76		State = IE_GUI_BUTTON_DISABLED
77		if CurrentStep - 1 == i:
78			State = IE_GUI_BUTTON_ENABLED
79			StepButtons[Step].MakeDefault()
80			StepButtons[Step].SetEvent(IE_GUI_BUTTON_ON_PRESS, NextPress)
81		StepButtons[Step].SetState(State)
82
83	# Handle (not so) persistent buttons
84	# This array handles all the default values for the buttons
85	# Exceptions are handled within the loop
86	ControlLookup = {
87		'Bio': [16, 18003, 0, None],
88		'Import': [13, 13955, 0, None],
89		'Back': [11, 15416, 1, BackPress],
90		'Next': [8, 28210, 0, None],
91		'Start': [15, 36788, 1, StartOver]
92	}
93	States = [IE_GUI_BUTTON_DISABLED, IE_GUI_BUTTON_ENABLED]
94	for Key in ControlLookup:
95		PersistButtons[Key] = CharGenWindow.GetControl(ControlLookup[Key][0])
96		Text = ControlLookup[Key][1]
97		State = States[ControlLookup[Key][2]]
98		Event = ControlLookup[Key][3]
99
100		if Key == 'Bio' and CurrentStep == 9:
101			State = States[1]
102			import CharGen9
103			Event = CharGen9.BioPress
104
105		if Key == 'Import' and CurrentStep == 1:
106			State = States[1]
107			Event = ImportPress
108
109		if Key == 'Back':
110			if CurrentStep == 1:
111				State = States[0]
112				Event = None
113			else:
114				PersistButtons[Key].MakeEscape()
115
116		if Key == 'Next' and CurrentStep == 9:
117			State = 1
118			Event = NextPress
119			PersistButtons[Key].MakeDefault()
120
121		if Key == 'Start' and CurrentStep == 1:
122			Text = 13727
123			Event = CancelPress
124			PersistButtons[Key].MakeEscape()
125
126		PersistButtons[Key].SetText(Text)
127		PersistButtons[Key].SetState(State)
128
129		if Event:
130			PersistButtons[Key].SetEvent(IE_GUI_BUTTON_ON_PRESS, Event)
131
132	# Handle character overview information
133	TextAreaControl = CharGenWindow.GetControl(9)
134	Tables = []
135	for tbl in ['races', 'classes', 'aligns', 'ability', 'skillsta', 'skills', 'featreq', 'feats']:
136		Tables.append(GemRB.LoadTable(tbl))
137
138	if GemRB.GetVar('Gender') > 0:
139		name = GemRB.GetToken('CHARNAME')
140		if not name:
141			TextAreaControl.SetText(12135)
142		else:
143			TextAreaControl.SetText(1047)
144			AddText(': ' + GemRB.GetToken('CHARNAME'), 1)
145			AddText(12135)
146		AddText(': ')
147		strref = 1049 + GemRB.GetVar('Gender')
148		AddText(strref, 1)
149
150	if GemRB.GetVar('Race') > 0:
151		AddText(1048)
152		AddText(': ')
153		AddText(Tables[0].GetValue(Tables[0].FindValue(3, GemRB.GetVar('Race')), 2), 1)
154
155	if GemRB.GetVar('Class') > 0:
156		AddText(11959)
157		AddText(': ')
158		AddText(Tables[1].GetValue(GemRB.GetVar('Class') - 1, 0), 1)
159
160	if GemRB.GetVar('Alignment') > 0:
161		AddText(11958)
162		AddText(': ')
163		AddText(Tables[2].GetValue(GemRB.GetVar('Alignment') - 1, 0), 1)
164
165	if GemRB.GetVar('Ability 0') > 0:
166		AddText('\n[color=FFFF00]' + GemRB.GetString(17088) + '[/color]', 1)
167		for i in range(0, 6):
168			strref = Tables[3].GetValue(i, 2)
169			AddText(strref)
170			abl = GemRB.GetVar('Ability ' + str(i))
171			AddText(': %d (%+d)' % (abl, abl / 2 - 5), 1)
172
173	if CurrentStep > 6:
174		AddText('\n[color=FFFF00]' + GemRB.GetString(11983) + '[/color]', 1)
175
176		ClassColumn = Tables[1].GetValue(GemRB.GetVar('Class') - 1, 3, GTV_INT) # Finds base class row id
177		if ClassColumn < 1: ClassColumn = GemRB.GetVar('Class') - 1 # If 0 then already a base class so need actual row
178		else: ClassColumn -= 1 # 'CLASS' column in classes.2da is out by 1 for some reason
179		ClassColumn += 4 # There are 4 columns before the classes in skills.2da
180		# At the moment only cleric kits get skill bonuses but their column names in skills.2da don't match up
181		# to their kit names. All classes aren't covered in skills.2da either which is why I have to resort
182		# to calculating the base class. This isn't ideal. Recommend a new 2DA be created with *all* classes
183		# as rows and skills as columns. Something like SKILCLAS.2DA
184
185		### Cleric kit hack:
186		if GemRB.GetVar('Class') in range(27, 36):
187			ClassColumn = GemRB.GetVar('Class') - 12
188
189		RaceName = Tables[0].GetRowName(Tables[0].FindValue(3, GemRB.GetVar('Race')))
190		SkillColumn = Tables[0].GetValue(RaceName, 'SKILL_COLUMN', GTV_INT) + 1
191		Lookup = {'STR': 0, 'DEX': 1, 'CON': 2, 'INT': 3, 'WIS': 4, 'CHR': 5} # Probably a better way to do this
192		for i in range(Tables[4].GetRowCount()):
193			SkillName = Tables[5].GetRowName(i)
194			Abl = Tables[4].GetValue(i, 1, GTV_STR)
195			Ranks = GemRB.GetVar('Skill ' + str(i))
196			value = Ranks
197			value += (GemRB.GetVar('Ability ' + str(Lookup[Abl])) / 2 - 5)
198			value += Tables[5].GetValue(i, SkillColumn, GTV_INT)
199			value += Tables[5].GetValue(i, ClassColumn, GTV_INT)
200
201			untrained = Tables[5].GetValue(i, 3, GTV_INT)
202			if not untrained and Ranks < 1:
203				value = 0
204
205			if value:
206				strref = Tables[5].GetValue(i, 1)
207				AddText(strref)
208				strn = ': ' + str(value)
209				if value != Ranks: strn += ' (' + str(Ranks) + ')'
210				AddText(strn, 1)
211
212		AddText('\n[color=FFFF00]' + GemRB.GetString(36310) + '[/color]', 1)
213
214		for i in range(Tables[6].GetRowCount()):
215			value = GemRB.GetVar('Feat ' + str(i))
216			if value:
217				strref = Tables[7].GetValue(i, 1)
218				AddText(strref)
219				multiple = Tables[6].GetValue(i, 0)
220				if multiple != 0:
221					AddText(': ' + str(value))
222				AddText('\n')
223
224		AddText('\n')
225		import CommonTables
226		import Spellbook
227		MyChar = GemRB.GetVar ("Slot")
228		BookTypes = { IE_IWD2_SPELL_BARD:39341, IE_IWD2_SPELL_CLERIC:11028, \
229			IE_IWD2_SPELL_DRUID:39342, IE_IWD2_SPELL_PALADIN:39343, IE_IWD2_SPELL_RANGER:39344, \
230			IE_IWD2_SPELL_SORCERER:39345, IE_IWD2_SPELL_WIZARD:11027, IE_IWD2_SPELL_DOMAIN:0 }
231		for bt in BookTypes:
232			KnownSpells = Spellbook.GetKnownSpells(MyChar, bt)
233			if len(KnownSpells):
234				BTName = BookTypes[bt]
235				# individual domains, luckily in kit order
236				if BTName == 0:
237					KitIndex = GemRB.GetVar ("Class") - 1
238					KitIndex -= CommonTables.Classes.FindValue ("CLASS", GemRB.GetVar ("BaseClass"))
239					BTName = 39346 + KitIndex
240				AddText ('\n[color=FFFF00]')
241				AddText (BTName)
242				AddText ('[/color]\n')
243				for ks in KnownSpells:
244					AddText (GemRB.GetString(ks['SpellName'])+"\n")
245
246	# And we're done, w00t!
247	CharGenWindow.Focus()
248	return
249
250def NextPress():
251	if len(Steps) > GlobalStep - 1:
252		GemRB.SetNextScript(Steps[GlobalStep - 1])
253	else: #start the game
254		import CharGen9
255		CharGen9.NextPress()
256	return
257
258def CancelPress():
259	#destroy the half generated character
260	slot = GemRB.GetVar("Slot")
261	GemRB.CreatePlayer("", slot|0x8000)
262	if CharGenWindow:
263		CharGenWindow.Unload()
264	GemRB.SetNextScript('SPPartyFormation')
265	return
266
267def StartOver():
268	StartOverWindow = GemRB.LoadWindow(53)
269
270	def RestartGen():
271		StartOverWindow.Close()
272		CharGenWindow.Close()
273		GemRB.SetNextScript('CharGen')
274		return
275
276	YesButton = StartOverWindow.GetControl(0)
277	YesButton.SetText(13912)
278	YesButton.SetEvent(IE_GUI_BUTTON_ON_PRESS, RestartGen)
279
280	NoButton = StartOverWindow.GetControl(1)
281	NoButton.SetText(13913)
282	NoButton.SetEvent(IE_GUI_BUTTON_ON_PRESS, lambda: StartOverWindow.Close())
283
284	TextAreaControl = StartOverWindow.GetControl(2)
285	TextAreaControl.SetText(40275)
286	return
287
288def ImportPress():
289	GemRB.SetToken('NextScript', 'CharGen')
290	GemRB.SetNextScript('ImportFile')
291	return
292
293def BackPress():
294	# Need to clear relevant variables
295	if GlobalStep == 2: GemRB.SetVar('Gender', 0)
296	elif GlobalStep == 3: GemRB.SetVar('Race', 0)
297	elif GlobalStep == 4: GemRB.SetVar('Class', 0)
298	elif GlobalStep == 5: GemRB.SetVar('Alignment', 0)
299	elif GlobalStep == 6:
300		for i in range(0, 7):
301			GemRB.SetVar('Ability ' + str(i), 0)
302
303	elif GlobalStep == 9: GemRB.SetToken('CHARNAME', '')
304
305	ScrName = 'CharGen' + str(GlobalStep - 1)
306	if GlobalStep == 2: ScrName = 'CharGen'
307	GemRB.SetNextScript(ScrName)
308	return
309