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 GUICommon 23import Spellbook 24from GUIDefines import * 25from ie_stats import * 26from ie_slots import * 27from ie_spells import * 28from ie_sounds import DEF_IDENTIFY 29 30UsedSlot = None 31ItemInfoWindow = None 32ItemAmountWindow = None 33ItemIdentifyWindow = None 34ItemAbilitiesWindow = None 35ErrorWindow = None 36ColorPicker = None 37StackAmount = 0 38 39 # A map that defines which inventory slots are used per character (PST) 40SlotMap = None 41 42UpdateInventoryWindow = None 43 44def OnDragItemGround (btn, slot): 45 """Drops and item to the ground.""" 46 47 pc = GemRB.GameGetSelectedPCSingle () 48 slot = slot + GemRB.GetVar ("TopIndex") - (47 if GameCheck.IsPST () else 68) 49 50 if GemRB.IsDraggingItem ()==0: 51 slot_item = GemRB.GetContainerItem (pc, slot) 52 item = GemRB.GetItem (slot_item["ItemResRef"]) 53 GemRB.DragItem (pc, slot, item["ItemIcon"], 0, 1) #container 54 if GameCheck.IsPST(): 55 GemRB.PlaySound (item["DescIcon"]) 56 else: 57 GemRB.DropDraggedItem (pc, -2) #dropping on ground 58 59 UpdateInventoryWindow () 60 return 61 62def OnAutoEquip (): 63 """Auto-equips equipment if possible.""" 64 65 if GemRB.IsDraggingItem ()!=1: 66 return 67 68 pc = GemRB.GameGetSelectedPCSingle () 69 70 #-1 : drop stuff in equipable slots (but not inventory) 71 GemRB.DropDraggedItem (pc, -1) 72 73 if GemRB.IsDraggingItem ()==1: 74 GemRB.PlaySound("GAM_47") #failed equip 75 76 UpdateInventoryWindow () 77 return 78 79def OnDragItem (btn, slot): 80 """Updates dragging.""" 81 82 #don't call when splitting items 83 if ItemAmountWindow != None: 84 return 85 86 pc = GemRB.GameGetSelectedPCSingle () 87 slot_item = GemRB.GetSlotItem (pc, slot) 88 89 if not GemRB.IsDraggingItem (): 90 item = GemRB.GetItem (slot_item["ItemResRef"]) 91 GemRB.DragItem (pc, slot, item["ItemIcon"], 0, 0) 92 else: 93 SlotType = GemRB.GetSlotType (slot, pc) 94 #special monk check 95 if GemRB.GetPlayerStat (pc, IE_CLASS) == 20 and SlotType["Effects"] == TYPE_OFFHAND: 96 SlotType["ResRef"] = "" 97 GemRB.DisplayString (61355, ColorWhite) 98 99 if SlotType["ResRef"]!="": 100 if slot_item: 101 item = GemRB.GetItem (slot_item["ItemResRef"]) 102 #drag items into a bag 103 if item["Function"] & ITM_F_CONTAINER: 104 #first swap them 105 GemRB.DropDraggedItem (pc, slot) 106 #enter the store 107 GemRB.EnterStore (slot_item["ItemResRef"]) 108 #if it is possible to add, then do it 109 ret = GemRB.IsValidStoreItem (pc, slot, 0) 110 if ret&SHOP_SELL: 111 GemRB.ChangeStoreItem (pc, slot, SHOP_SELL) 112 else: 113 msg = 9375 114 if ret&SHOP_FULL: 115 if GameCheck.IsIWD1() or GameCheck.IsIWD2(): 116 msg = 24893 117 elif GameCheck.HasTOB(): 118 msg = 54692 119 GemRB.DisplayString(msg, ColorWhite) 120 #leave (save) store 121 GemRB.LeaveStore() 122 123 GemRB.DropDraggedItem (pc, slot) 124 # drop item if it caused us to disable the inventory view (example: cursed berserking sword) 125 if GemRB.GetPlayerStat (pc, IE_STATE_ID) & (STATE_BERSERK) and GemRB.IsDraggingItem (): 126 GemRB.DropDraggedItem (pc, -3) 127 128 UpdateInventoryWindow () 129 return 130 131def OnDropItemToPC (pc): 132 """Gives an item to another character.""" 133 134 if pc > GemRB.GetPartySize (): 135 return 136 #-3 : drop stuff in inventory (but not equippable slots) 137 GemRB.DropDraggedItem (pc, -3) 138 UpdateInventoryWindow () 139 return 140 141def DecreaseStackAmount (): 142 """Decreases the split size.""" 143 144 Text = ItemAmountWindow.GetControl (6) 145 Amount = Text.QueryText () 146 number = int ("0"+Amount)-1 147 if number<1: 148 number=1 149 Text.SetText (str (number)) 150 return 151 152def IncreaseStackAmount (): 153 """Increases the split size.""" 154 155 Text = ItemAmountWindow.GetControl (6) 156 Amount = Text.QueryText () 157 number = int ("0"+Amount)+1 158 if number>StackAmount: 159 number=StackAmount 160 Text.SetText (str (number)) 161 return 162 163def DragItemAmount (): 164 """Drag a split item.""" 165 166 pc = GemRB.GameGetSelectedPCSingle () 167 168 #emergency dropping 169 if GemRB.IsDraggingItem()==1: 170 GemRB.DropDraggedItem (pc, UsedSlot) 171 UpdateSlot (pc, UsedSlot-1) 172 173 slot_item = GemRB.GetSlotItem (pc, UsedSlot) 174 175 #if dropping didn't help, don't die if slot_item isn't here 176 if slot_item: 177 Text = ItemAmountWindow.GetControl (6) 178 Amount = Text.QueryText () 179 item = GemRB.GetItem (slot_item["ItemResRef"]) 180 GemRB.DragItem (pc, UsedSlot, item["ItemIcon"], int ("0"+Amount), 0) 181 ItemAmountWindow.Close() 182 return 183 184def MouseEnterSlot (btn, slot): 185 pc = GemRB.GameGetSelectedPCSingle () 186 187 if GemRB.IsDraggingItem ()==1: 188 drag_item = GemRB.GetSlotItem (0,0) 189 SlotType = UpdateSlot (pc, slot-1) 190 191 if GemRB.CanUseItemType (SlotType["Type"], drag_item["ItemResRef"]): 192 btn.SetState (IE_GUI_BUTTON_SELECTED) 193 else: 194 btn.SetState (IE_GUI_BUTTON_ENABLED) 195 196 return 197 198def MouseLeaveSlot (btn, slot): 199 pc = GemRB.GameGetSelectedPCSingle () 200 201 UpdateSlot (pc, slot-1) 202 return 203 204def MouseEnterGround (Button): 205 if GemRB.IsDraggingItem ()==1: 206 Button.SetState (IE_GUI_BUTTON_SELECTED) 207 return 208 209def MouseLeaveGround (Button): 210 if GemRB.IsDraggingItem ()==1: 211 Button.SetState (IE_GUI_BUTTON_FAKEPRESSED) 212 return 213 214def CloseItemInfoWindow (): 215 if ItemInfoWindow: 216 ItemInfoWindow.Unload () 217 UpdateInventoryWindow () 218 return 219 220def DisplayItem (slotItem, itemtype): 221 global ItemInfoWindow 222 223 item = GemRB.GetItem (slotItem["ItemResRef"]) 224 225 #window can be refreshed by cycling to next/prev item, so it may still exist 226 if not ItemInfoWindow: 227 ItemInfoWindow = GemRB.LoadWindow (5) 228 229 Window = ItemInfoWindow 230 def OnClose(): 231 global ItemInfoWindow 232 ItemInfoWindow = None 233 Window.SetAction (OnClose, ACTION_WINDOW_CLOSED) 234 235 if GameCheck.IsPST(): 236 strrefs = [ 1403, 4256, 4255, 4251, 4252, 4254, 4279 ] 237 elif GameCheck.IsGemRBDemo (): 238 strrefs = [ 84, 105, 106, 104, 107, item["DialogName"], 108 ] 239 else: 240 strrefs = [ 11973, 14133, 11960, 19392, 17104, item["DialogName"], 17108 ] 241 242 # item name 243 Label = Window.GetControl (0x10000000) 244 if (itemtype & 2): 245 text = item["ItemName"] 246 else: 247 text = item["ItemNameIdentified"] 248 Label.SetText (text) 249 250 #item icon 251 Button = Window.GetControl (2) 252 if GameCheck.IsPST(): 253 Button.SetFlags (IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_NO_IMAGE, OP_SET) 254 Button.SetItemIcon (slotItem["ItemResRef"]) 255 else: 256 Button.SetFlags (IE_GUI_BUTTON_PICTURE, OP_OR) 257 Button.SetItemIcon (slotItem["ItemResRef"], 0) 258 Button.SetState (IE_GUI_BUTTON_LOCKED) 259 260 #middle button 261 Button = Window.GetControl (4) 262 Button.SetText (strrefs[0]) 263 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, CloseItemInfoWindow) 264 Button.MakeDefault() 265 266 #textarea 267 Text = Window.GetControl (5) 268 if GameCheck.IsBG2(): # I believe only BG2 has special initials 269 Text.SetColor (ColorWhitish, TA_COLOR_INITIALS) 270 if (itemtype & 2): 271 text = item["ItemDesc"] 272 else: 273 text = item["ItemDescIdentified"] 274 275 Text.Clear () 276 Text.Append (text) 277 278 Window.SetEventProxy(Text) 279 280 #left button 281 Button = Window.GetControl(8) 282 select = (itemtype & 1) and (item["Function"]&ITM_F_ABILITIES) 283 284 if itemtype & 2: 285 Button.SetText (strrefs[1]) 286 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, IdentifyItemWindow) 287 Button.SetFlags (IE_GUI_BUTTON_PICTURE, OP_SET) 288 elif select and not GameCheck.IsPST(): 289 Button.SetText (strrefs[2]) 290 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, AbilitiesItemWindow) 291 Button.SetFlags (IE_GUI_BUTTON_PICTURE, OP_SET) 292 else: 293 Button.SetText ("") 294 Button.SetState (IE_GUI_BUTTON_LOCKED) 295 Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_SET) 296 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, None) 297 298 # description icon (not present in iwds) 299 if not GameCheck.IsIWD1() and not GameCheck.IsIWD2(): 300 Button = Window.GetControl (7) 301 Button.SetFlags (IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_CENTER_PICTURES | IE_GUI_BUTTON_NO_IMAGE, OP_OR) 302 if GameCheck.IsPST(): 303 Button.SetItemIcon (slotItem["ItemResRef"], 1) # no DescIcon 304 else: 305 Button.SetItemIcon (slotItem["ItemResRef"], 2) 306 Button.SetState (IE_GUI_BUTTON_LOCKED) 307 308 #right button 309 Button = Window.GetControl(9) 310 Button.SetFlags (IE_GUI_BUTTON_PICTURE, OP_SET) 311 drink = (itemtype & 1) and (item["Function"]&ITM_F_DRINK) 312 read = (itemtype & 1) and (item["Function"]&ITM_F_READ) 313 # sorcerers cannot learn spells 314 pc = GemRB.GameGetSelectedPCSingle () 315 if Spellbook.HasSorcererBook (pc): 316 read = 0 317 container = (itemtype & 1) and (item["Function"]&ITM_F_CONTAINER) 318 dialog = (itemtype & 1) and (item["Dialog"]!="" and item["Dialog"]!="*") 319 familiar = (itemtype & 1) and (item["Type"] == 38) 320 321 # The "conversable" bit in PST actually means "usable", eg clot charm 322 # unlike BG2 (which only has the bit set on SW2H14 Lilarcor) 323 # Meanwhile IWD series has the bit set on important quest items 324 # So the widely accepted name of this bit is misleading 325 326 # There are also items in PST, cube.itm and doll.itm 327 # that are not flagged usable but still have dialog attached. 328 # this is how the original game draws the distinction between 'use item' and 'talk to item' 329 330 # if the item has dialog and is flagged usable = use item string, open dialog 331 # if the item has dialog and is not flagged usable = talk to item, open dialog 332 # if the item has no dialog and is flagged usable = use item string, consume item 333 334 if GameCheck.IsPST() and slotItem["Flags"] & IE_INV_ITEM_CONVERSABLE: 335 336 drink = True # "Use" 337 338 if drink and not dialog: 339 # Standard consumable item 340 Button.SetText (strrefs[3]) 341 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, ConsumeItem) 342 elif read: 343 Button.SetText (strrefs[4]) 344 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, ReadItemWindow) 345 elif container: 346 # Just skip the redundant info page and go directly to the container 347 if GemRB.GetVar("GUIEnhancements")&GE_ALWAYS_OPEN_CONTAINER_ITEMS: 348 OpenItemWindow() 349 return 350 if GameCheck.IsIWD2() or GameCheck.IsHOW(): 351 Button.SetText (24891) # Open Container 352 elif GameCheck.IsBG2(): 353 Button.SetText (44002) # open container 354 else: 355 # a fallback, since the originals have nothing appropriate from not having any bags 356 Button.SetText ("Open container") 357 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, OpenItemWindow) 358 elif dialog: 359 if drink: 360 # Dialog item that is 'used' 361 Button.SetText (strrefs[3]) 362 else: 363 # Dialog item that is 'talked to' 364 Button.SetText (strrefs[5]) 365 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, DialogItemWindow) 366 elif familiar and not GameCheck.IsPST(): 367 # PST earings share a type with familiars, so no 368 # mods that allow familiars would be possible in PST 369 Button.SetText (4373) 370 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, ReleaseFamiliar) 371 else: 372 Button.SetState (IE_GUI_BUTTON_LOCKED) 373 Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_SET) 374 Button.SetText ("") 375 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, None) 376 377 Label = Window.GetControl(0x1000000b) 378 if Label: 379 if (itemtype & 2): 380 # NOT IDENTIFIED 381 Label.SetText (strrefs[6]) 382 else: 383 Label.SetText ("") 384 385 # in pst one can cycle through all the items from the description window 386 if GameCheck.IsPST(): 387 388 #left scroll 389 Button = Window.GetControl (13) 390 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, lambda: CycleDisplayItem(-1)) 391 392 #right scroll 393 Button = Window.GetControl (14) 394 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, lambda: CycleDisplayItem(1)) 395 396 ItemInfoWindow.ShowModal(MODAL_SHADOW_GRAY) 397 return 398 399def CycleDisplayItem(direction): 400 401 slot = int(GemRB.GetVar('ItemButton')) 402 403 pc = GemRB.GameGetSelectedPCSingle () 404 405 slot_item = None 406 407 #try the next slot for an item. if the slot is empty, loop until one is found. 408 while not slot_item: 409 slot += direction 410 411 #wrap around if last slot is reached 412 if slot > 53: 413 slot = 0 414 elif slot < 0: 415 slot = 53 416 417 slot_item = GemRB.GetSlotItem (pc, slot) 418 GemRB.SetVar('ItemButton', slot) 419 420 if slot_item: 421 OpenItemInfoWindow (None, slot) 422 423def OpenItemInfoWindow (btn, slot): 424 pc = GemRB.GameGetSelectedPCSingle () 425 426 slotItem = GemRB.GetSlotItem (pc, slot) 427 slotType = GemRB.GetSlotType (slot, pc) 428 429 # PST: if the slot is empty but is also the first quick weapon slot, display the info for the "default" weapon 430 if GameCheck.IsPST() and slotItem is None and slotType["ID"] == 10 and GemRB.GetEquippedQuickSlot(pc) == 10: 431 DisplayItem (GemRB.GetSlotItem (pc, 0), 1) 432 return 433 434 item = GemRB.GetItem (slotItem["ItemResRef"]) 435 436 if TryAutoIdentification(pc, item, slot, slotItem, True): 437 UpdateInventoryWindow () 438 439 if slotItem["Flags"] & IE_INV_ITEM_IDENTIFIED: 440 value = 1 441 else: 442 value = 3 443 DisplayItem (slotItem, value) 444 return 445 446#auto identify when lore is high enough 447def TryAutoIdentification(pc, item, slot, slot_item, enabled=0): 448 if enabled and item["LoreToID"]<=GemRB.GetPlayerStat (pc, IE_LORE): 449 GemRB.ChangeItemFlag (pc, slot, IE_INV_ITEM_IDENTIFIED, OP_OR) 450 slot_item["Flags"] |= IE_INV_ITEM_IDENTIFIED 451 return True 452 return False 453 454def OpenGroundItemInfoWindow (btn, slot): 455 global ItemInfoWindow 456 457 pc = GemRB.GameGetSelectedPCSingle () 458 slot = slot + GemRB.GetVar ("TopIndex") - (47 if GameCheck.IsPST () else 68) 459 slot_item = GemRB.GetContainerItem (pc, slot) 460 461 #the ground items are only displayable 462 if slot_item["Flags"] & IE_INV_ITEM_IDENTIFIED: 463 value = 0 464 else: 465 value = 2 466 DisplayItem(slot_item, value) 467 return 468 469# TODO: implement, reuse OpenItemAmountWindow, but be careful about any other uses of ItemButton 470def OpenGroundItemAmountWindow (): 471 pass 472 473def ItemAmountWindowClosed(win): 474 global ItemAmountWindow, UsedSlot 475 476 ItemAmountWindow = None 477 UsedSlot = None 478 UpdateInventoryWindow() 479 480# TODO: can the GUISTORE be consolidate with this one? 481def OpenItemAmountWindow (btn, slot): 482 """Open the split window.""" 483 484 global UsedSlot, OverSlot 485 global ItemAmountWindow, StackAmount 486 487 pc = GemRB.GameGetSelectedPCSingle () 488 489 UsedSlot = slot 490 if GemRB.IsDraggingItem ()==1: 491 GemRB.DropDraggedItem (pc, UsedSlot) 492 #redraw slot 493 UpdateSlot (pc, UsedSlot-1) 494 # disallow splitting while holding split items (double splitting) 495 if GemRB.IsDraggingItem () == 1: 496 return 497 498 slot_item = GemRB.GetSlotItem (pc, UsedSlot) 499 500 if slot_item: 501 StackAmount = slot_item["Usages0"] 502 else: 503 StackAmount = 0 504 if StackAmount<=1: 505 UpdateSlot (pc, UsedSlot-1) 506 return 507 508 ItemAmountWindow = Window = GemRB.LoadWindow (4) 509 Window.SetFlags(WF_ALPHA_CHANNEL, OP_OR) 510 Window.SetAction(ItemAmountWindowClosed, ACTION_WINDOW_CLOSED) 511 512 strings = { 'Done': 11973, "Cancel": 13727} 513 if GameCheck.IsPST(): 514 strings = { 'Done': 1403, "Cancel": 4196} 515 elif GameCheck.IsGemRBDemo (): 516 strings = { 'Done': 84, 'Cancel': 103} 517 518 # item icon 519 Icon = Window.GetControl (0) 520 Icon.SetFlags (IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_NO_IMAGE, OP_SET) 521 Icon.SetItemIcon (slot_item['ItemResRef']) 522 523 # item amount 524 Text = Window.GetControl (6) 525 # FIXME: use a proper size 526 # FIXME: fix it for all the games 527 if GameCheck.IsIWD2(): 528 Text.SetSize (40, 40) 529 Text.SetText (str (StackAmount//2)) 530 Text.SetFlags (IE_GUI_TEXTEDIT_ALPHACHARS, OP_NAND) 531 Text.Focus() 532 533 # Decrease 534 Button = Window.GetControl (4) 535 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, DecreaseStackAmount) 536 Button.SetActionInterval (200) 537 538 # Increase 539 Button = Window.GetControl (3) 540 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, IncreaseStackAmount) 541 Button.SetActionInterval (200) 542 543 # Done 544 Button = Window.GetControl (2) 545 Button.SetText (strings['Done']) 546 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, DragItemAmount) 547 Button.MakeDefault() 548 549 # Cancel 550 Button = Window.GetControl (1) 551 Button.SetText (strings['Cancel']) 552 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, lambda: Window.Close()) 553 Button.MakeEscape() 554 555 Window.ShowModal (MODAL_SHADOW_GRAY) 556 return 557 558def UpdateSlot (pc, slot): 559 """Updates a specific slot.""" 560 561 Window = GemRB.GetView("WIN_INV") 562 563 using_fists = slot_item = SlotType = None 564 565 if GameCheck.IsPST(): 566 if slot >= len(SlotMap): 567 #this prevents accidental out of range errors from the avslots list 568 return GemRB.GetSlotType (slot+1) 569 elif SlotMap[slot] == -1: 570 # This decides which icon to display in the empty slot 571 # NOTE: there are invisible items (e.g. MORTEP) in inaccessible slots 572 # used to assign powers and protections 573 574 SlotType = GemRB.GetSlotType (slot+1, pc) 575 slot_item = None 576 else: 577 SlotType = GemRB.GetSlotType (SlotMap[slot]+1) 578 slot_item = GemRB.GetSlotItem (pc, SlotMap[slot]+1) 579 #PST displays the default weapon in the first slot if nothing else was equipped 580 if slot_item is None and SlotType["ID"] == 10 and GemRB.GetEquippedQuickSlot(pc) == 10: 581 slot_item = GemRB.GetSlotItem (pc, 0) 582 using_fists = 1 583 else: 584 SlotType = GemRB.GetSlotType (slot+1, pc) 585 slot_item = GemRB.GetSlotItem (pc, slot+1) 586 587 ControlID = SlotType["ID"] 588 589 if ControlID == -1: 590 return None 591 592 if GemRB.IsDraggingItem ()==1: 593 #get dragged item 594 drag_item = GemRB.GetSlotItem (0,0) 595 itemname = drag_item["ItemResRef"] 596 else: 597 itemname = "" 598 599 Button = Window.GetControl (ControlID) 600 601 # It is important to check for a control - some games use CID 0 for slots with no control, others -1 602 if not Button: 603 return 604 605 Button.SetAction (OnDragItem, IE_ACT_DRAG_DROP_DST) 606 Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_NAND) 607 608 # characters should auto-identify any item they recieve 609 if slot_item: 610 item = GemRB.GetItem (slot_item["ItemResRef"]) 611 TryAutoIdentification(pc, item, slot+1, slot_item, GemRB.GetVar("GUIEnhancements")&GE_TRY_IDENTIFY_ON_TRANSFER) 612 613 UpdateInventorySlot (pc, Button, slot_item, "inventory", SlotType["Type"]&SLOT_INVENTORY == 0) 614 615 if slot_item: 616 Button.SetAction(OnDragItem, IE_ACT_DRAG_DROP_CRT) 617 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, OnDragItem) 618 Button.SetEvent (IE_GUI_BUTTON_ON_RIGHT_PRESS, OpenItemInfoWindow) 619 Button.SetEvent (IE_GUI_BUTTON_ON_SHIFT_PRESS, OpenItemAmountWindow) 620 #If the slot is being used to display the 'default' weapon, disable dragging. 621 if SlotType["ID"] == 10 and using_fists: 622 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, None) 623 #dropping is ok, because it will drop in the quick weapon slot and not the default weapon slot. 624 else: 625 if SlotType["ResRef"]=="*": 626 Button.SetBAM ("",0,0) 627 Button.SetTooltip (SlotType["Tip"]) 628 itemname = "" 629 elif SlotType["ResRef"]=="": 630 Button.SetBAM ("",0,0) 631 Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_OR) 632 Button.SetTooltip ("") 633 itemname = "" 634 else: 635 if SlotType["Flags"] & 2: 636 Button.SetPicture (SlotType["ResRef"]) 637 else: 638 Button.SetBAM (SlotType["ResRef"], 0, 0) 639 Button.SetTooltip (SlotType["Tip"]) 640 641 if SlotMap and SlotMap[slot]<0: 642 Button.SetBAM ("",0,0) 643 Button.SetFlags (IE_GUI_BUTTON_NO_IMAGE, OP_OR) 644 Button.SetTooltip ("") 645 itemname = "" 646 647 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, None) 648 Button.SetEvent (IE_GUI_BUTTON_ON_RIGHT_PRESS, None) 649 Button.SetEvent (IE_GUI_BUTTON_ON_SHIFT_PRESS, None) 650 Button.SetEvent (IE_GUI_BUTTON_ON_DOUBLE_PRESS, OpenItemAmountWindow) 651 652 if (SlotType["Type"]&SLOT_INVENTORY) or not GemRB.CanUseItemType (SlotType["Type"], itemname): 653 Button.SetState (IE_GUI_BUTTON_ENABLED) 654 else: 655 Button.SetState (IE_GUI_BUTTON_FAKEPRESSED) 656 657 if slot_item and (GemRB.GetEquippedQuickSlot (pc)==slot+1 or GemRB.GetEquippedAmmunition (pc)==slot+1): 658 Button.SetState (IE_GUI_BUTTON_FAKEDISABLED) 659 660 return SlotType 661 662def CancelColor(): 663 global ColorPicker 664 if ColorPicker: 665 ColorPicker.Unload () 666 InventoryWindow = GemRB.GetView ("WIN_INV") 667 InventoryWindow.Focus () 668 return 669 670def ColorDonePress(): 671 """Saves the selected colors.""" 672 673 pc = GemRB.GameGetSelectedPCSingle () 674 675 if ColorPicker: 676 ColorPicker.Unload () 677 678 ColorTable = GemRB.LoadTable ("clowncol") 679 PickedColor=ColorTable.GetValue (ColorIndex, GemRB.GetVar ("Selected")) 680 if ColorIndex==0: 681 GUICommon.SetColorStat (pc, IE_HAIR_COLOR, PickedColor) 682 elif ColorIndex==1: 683 GUICommon.SetColorStat (pc, IE_SKIN_COLOR, PickedColor) 684 elif ColorIndex==2: 685 GUICommon.SetColorStat (pc, IE_MAJOR_COLOR, PickedColor) 686 else: 687 GUICommon.SetColorStat (pc, IE_MINOR_COLOR, PickedColor) 688 UpdateInventoryWindow () 689 return 690 691def HairPress(): 692 global ColorIndex, PickedColor 693 694 pc = GemRB.GameGetSelectedPCSingle () 695 ColorIndex = 0 696 PickedColor = GemRB.GetPlayerStat (pc, IE_HAIR_COLOR, 1) & 0xFF 697 GetColor() 698 return 699 700def SkinPress(): 701 global ColorIndex, PickedColor 702 703 pc = GemRB.GameGetSelectedPCSingle () 704 ColorIndex = 1 705 PickedColor = GemRB.GetPlayerStat (pc, IE_SKIN_COLOR, 1) & 0xFF 706 GetColor() 707 return 708 709def MajorPress(): 710 """Selects the major color.""" 711 global ColorIndex, PickedColor 712 713 pc = GemRB.GameGetSelectedPCSingle () 714 ColorIndex = 2 715 PickedColor = GemRB.GetPlayerStat (pc, IE_MAJOR_COLOR, 1) & 0xFF 716 GetColor() 717 return 718 719def MinorPress(): 720 """Selects the minor color.""" 721 global ColorIndex, PickedColor 722 723 pc = GemRB.GameGetSelectedPCSingle () 724 ColorIndex = 3 725 PickedColor = GemRB.GetPlayerStat (pc, IE_MINOR_COLOR, 1) & 0xFF 726 GetColor() 727 return 728 729def GetColor(): 730 """Opens the color selection window.""" 731 732 global ColorPicker 733 734 ColorTable = GemRB.LoadTable ("clowncol") 735 InventoryWindow = GemRB.GetView ("WIN_INV") 736 InventoryWindow.SetDisabled (True) #darken it 737 ColorPicker = GemRB.LoadWindow (3) 738 GemRB.SetVar ("Selected",-1) 739 if GameCheck.IsIWD2 () or GameCheck.IsGemRBDemo (): 740 Button = ColorPicker.GetControl (35) 741 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, CancelColor) 742 Button.SetText (103) 743 if GameCheck.IsIWD2 (): 744 Button.SetText (13727) 745 746 for i in range (34): 747 Button = ColorPicker.GetControl (i) 748 MyColor = ColorTable.GetValue (ColorIndex, i) 749 if MyColor == "*": 750 Button.SetState (IE_GUI_BUTTON_LOCKED) 751 continue 752 if PickedColor == MyColor: 753 GemRB.SetVar ("Selected",i) 754 Button.SetState (IE_GUI_BUTTON_LOCKED) 755 Button.MakeEscape() 756 else: 757 Button.SetBAM ("COLGRAD", 2, 0, MyColor) 758 Button.SetFlags (IE_GUI_BUTTON_PICTURE|IE_GUI_BUTTON_RADIOBUTTON, OP_OR) 759 Button.SetState (IE_GUI_BUTTON_ENABLED) 760 Button.SetVarAssoc ("Selected",i) 761 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, ColorDonePress) 762 ColorPicker.Focus() 763 return 764 765def ReleaseFamiliar (): 766 """Simple Use Item""" 767 768 pc = GemRB.GameGetSelectedPCSingle () 769 slot = GemRB.GetVar ("ItemButton") 770 # the header is always the first, target is always self 771 GemRB.UseItem (pc, slot, 0, 5) 772 CloseItemInfoWindow () 773 return 774 775def ConsumeItem (): 776 """Drink the potion""" 777 778 pc = GemRB.GameGetSelectedPCSingle () 779 slot = GemRB.GetVar ("ItemButton") 780 # the drink item header is always the first 781 # pst also requires forcing the target (eg. clot charms), which doesn't hurt elsewhere 782 GemRB.UseItem (pc, slot, 0, 5) 783 CloseItemInfoWindow () 784 return 785 786def OpenErrorWindow (strref): 787 """Opens the error window and displays the string.""" 788 789 global ErrorWindow 790 791 ErrorWindow = Window = GemRB.LoadWindow (7) 792 Button = Window.GetControl (0) 793 if GameCheck.IsPST(): 794 Button.SetText (1403) 795 else: 796 Button.SetText (11973) 797 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, CloseErrorWindow) 798 Button.MakeDefault() 799 800 TextArea = Window.GetControl (3) 801 TextArea.SetText (strref) 802 Window.ShowModal (MODAL_SHADOW_GRAY) 803 return 804 805def CloseErrorWindow (): 806 if ErrorWindow: 807 ErrorWindow.Unload () 808 UpdateInventoryWindow () 809 return 810 811def ReadItemWindow (): 812 """Tries to learn the mage scroll.""" 813 814 pc = GemRB.GameGetSelectedPCSingle () 815 slot = GemRB.GetVar ("ItemButton") 816 ret = Spellbook.CannotLearnSlotSpell() 817 818 if ret: 819 # these failures are soft - the scroll is not destroyed 820 if ret == LSR_KNOWN and GameCheck.HasTOB(): 821 strref = 72873 822 elif ret == LSR_KNOWN and GameCheck.IsPST(): 823 strref = 50394 824 elif ret == LSR_STAT and GameCheck.HasTOB(): 825 # reached for sorcerers, schools/usability is handled before 826 strref = 72874 # your spell school does not permit you to learn 827 elif ret == LSR_LEVEL and GameCheck.HasTOB(): 828 strref = 48806 # inadequate intelligence (good enough approximation) 829 elif ret == LSR_FULL and GameCheck.IsBG2(): 830 strref = 32097 831 elif ret == LSR_FULL and GameCheck.IsPST(): 832 strref = 50395 833 elif GameCheck.IsPST(): 834 strref = 4250 835 else: 836 strref = 10831 837 838 CloseItemInfoWindow () 839 GemRB.PlaySound ("EFF_M10") # failure! 840 OpenErrorWindow (strref) 841 return 842 843 # we already checked for most failures, but we can still fail with bad % rolls vs intelligence 844 ret = Spellbook.LearnFromScroll (pc, slot) 845 if ret == LSR_OK: 846 GemRB.PlaySound ("GAM_44") # success! 847 if GameCheck.IsPST(): 848 strref = 4249 849 else: 850 strref = 10830 851 else: 852 GemRB.PlaySound ("EFF_M10") # failure! 853 if GameCheck.IsPST(): 854 strref = 4250 855 else: 856 strref = 10831 857 858 CloseItemInfoWindow () 859 OpenErrorWindow (strref) 860 861def OpenItemWindow (): 862 """Displays information about the item.""" 863 864 #close inventory 865 GemRB.SetVar ("Inventory", 1) 866 slot = GemRB.GetVar ("ItemButton") #get this before closing win 867 if ItemInfoWindow: 868 ItemInfoWindow.Unload () 869 870 pc = GemRB.GameGetSelectedPCSingle () 871 slot_item = GemRB.GetSlotItem (pc, slot) 872 ResRef = slot_item['ItemResRef'] 873 #the store will have to reopen the inventory 874 GemRB.EnterStore (ResRef) 875 return 876 877def DialogItemWindow (): 878 """Converse with an item.""" 879 880 pc = GemRB.GameGetSelectedPCSingle () 881 882 slot = GemRB.GetVar ("ItemButton") 883 slot_item = GemRB.GetSlotItem (pc, slot) 884 885 ResRef = slot_item['ItemResRef'] 886 item = GemRB.GetItem (ResRef) 887 dialog=item["Dialog"] 888 if ItemInfoWindow: 889 ItemInfoWindow.Unload () 890 891 GemRB.ExecuteString ("StartDialogOverride(\""+dialog+"\",Myself,0,0,1)", pc) 892 return 893 894def IdentifyUseSpell (): 895 """Identifies the item with a memorized spell.""" 896 897 global ItemIdentifyWindow 898 899 pc = GemRB.GameGetSelectedPCSingle () 900 slot = GemRB.GetVar ("ItemButton") 901 if ItemIdentifyWindow: 902 ItemIdentifyWindow.Unload () 903 GemRB.HasSpecialSpell (pc, SP_IDENTIFY, 1) 904 if ItemInfoWindow: 905 ItemInfoWindow.Unload () 906 GemRB.ChangeItemFlag (pc, slot, IE_INV_ITEM_IDENTIFIED, OP_OR) 907 GemRB.PlaySound(DEF_IDENTIFY) 908 OpenItemInfoWindow(None, slot) 909 return 910 911def IdentifyUseScroll (): 912 """Identifies the item with a scroll or other item.""" 913 914 global ItemIdentifyWindow 915 916 pc = GemRB.GameGetSelectedPCSingle () 917 slot = GemRB.GetVar ("ItemButton") 918 if ItemIdentifyWindow: 919 ItemIdentifyWindow.Unload () 920 if ItemInfoWindow: 921 ItemInfoWindow.Unload () 922 if GemRB.HasSpecialItem (pc, 1, 1): 923 GemRB.ChangeItemFlag (pc, slot, IE_INV_ITEM_IDENTIFIED, OP_OR) 924 GemRB.PlaySound(DEF_IDENTIFY) 925 OpenItemInfoWindow(None, slot) 926 return 927 928def CloseIdentifyItemWindow (): 929 global ItemIdentifyWindow, ItemInfoWindow 930 931 if ItemIdentifyWindow: 932 ItemIdentifyWindow.Unload () 933 ItemIdentifyWindow = None 934 if ItemInfoWindow: 935 ItemInfoWindow.ShowModal (MODAL_SHADOW_GRAY) 936 return 937 938def IdentifyItemWindow (): 939 global ItemIdentifyWindow 940 941 pc = GemRB.GameGetSelectedPCSingle () 942 943 ItemIdentifyWindow = Window = GemRB.LoadWindow (9) 944 Button = Window.GetControl (0) 945 if GameCheck.IsPST(): 946 Button.SetText (4259) 947 else: 948 Button.SetText (17105) 949 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, IdentifyUseSpell) 950 if not GemRB.HasSpecialSpell (pc, SP_IDENTIFY, 0): 951 Button.SetState (IE_GUI_BUTTON_DISABLED) 952 953 Button = Window.GetControl (1) 954 if GameCheck.IsPST(): 955 Button.SetText (4260) 956 else: 957 Button.SetText (17106) 958 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, IdentifyUseScroll) 959 if not GemRB.HasSpecialItem (pc, 1, 0): 960 Button.SetState (IE_GUI_BUTTON_DISABLED) 961 962 Button = Window.GetControl (2) 963 if GameCheck.IsPST(): 964 Button.SetText (4196) 965 else: 966 Button.SetText (13727) 967 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, CloseIdentifyItemWindow) 968 Button.MakeEscape() 969 970 TextArea = Window.GetControl (3) 971 if GameCheck.IsPST(): 972 TextArea.SetText (4258) 973 else: 974 TextArea.SetText (19394) 975 Window.ShowModal (MODAL_SHADOW_GRAY) 976 return 977 978def DoneAbilitiesItemWindow (): 979 pc = GemRB.GameGetSelectedPCSingle () 980 slot = GemRB.GetVar ("ItemButton") 981 GemRB.SetupQuickSlot (pc, 0, slot, GemRB.GetVar ("Ability") ) 982 CloseAbilitiesItemWindow () 983 return 984 985def CloseAbilitiesItemWindow (): 986 global ItemAbilitiesWindow, ItemInfoWindow 987 988 if ItemAbilitiesWindow: 989 ItemAbilitiesWindow.Unload () 990 ItemAbilitiesWindow = None 991 if ItemInfoWindow: 992 ItemInfoWindow.ShowModal (MODAL_SHADOW_GRAY) 993 return 994 995def AbilitiesItemWindow (): 996 global ItemAbilitiesWindow 997 998 ItemAbilitiesWindow = Window = GemRB.LoadWindow (6) 999 1000 pc = GemRB.GameGetSelectedPCSingle () 1001 slot = GemRB.GetVar ("ItemButton") 1002 slot_item = GemRB.GetSlotItem (pc, slot) 1003 item = GemRB.GetItem (slot_item["ItemResRef"]) 1004 Tips = item["Tooltips"] 1005 1006 GemRB.SetVar ("Ability", slot_item["Header"]) 1007 for i in range(3): 1008 Button = Window.GetControl (i+1) 1009 if GameCheck.IsBG2(): # TODO: check pst 1010 Button.SetSprites ("GUIBTBUT",i,0,1,2,0) 1011 Button.SetFlags (IE_GUI_BUTTON_RADIOBUTTON, OP_OR) 1012 Button.SetVarAssoc ("Ability",i) 1013 Text = Window.GetControl (i+0x10000003) 1014 if i<len(Tips): 1015 Button.SetItemIcon (slot_item['ItemResRef'],i+6) 1016 Text.SetText (Tips[i]) 1017 else: 1018 #disable button 1019 Button.SetItemIcon ("",3) 1020 Text.SetText ("") 1021 Button.SetState (IE_GUI_BUTTON_DISABLED) 1022 1023 TextArea = Window.GetControl (8) 1024 TextArea.SetText (11322) 1025 1026 Button = Window.GetControl (7) 1027 Button.SetText (11973) 1028 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, DoneAbilitiesItemWindow) 1029 Button.MakeDefault() 1030 1031 Button = Window.GetControl (10) 1032 Button.SetText (13727) 1033 Button.SetEvent (IE_GUI_BUTTON_ON_PRESS, CloseAbilitiesItemWindow) 1034 Button.MakeEscape() 1035 Window.ShowModal (MODAL_SHADOW_GRAY) 1036 return 1037 1038def UpdateInventorySlot (pc, Button, Slot, Type, Equipped=False): 1039 Button.SetFont ("NUMBER") 1040 1041 color = {'r' : 128, 'g' : 128, 'b' : 255, 'a' : 64} 1042 Button.SetBorder (0, color, 0,1) 1043 color = {'r' : 32, 'g' : 32, 'b' : 255, 'a' : 255} 1044 Button.SetBorder (1, color, 0,0, Button.GetInsetFrame(2)) 1045 color = {'r' : 255, 'g' : 128, 'b' : 128, 'a' : 64} 1046 Button.SetBorder (2, color, 0,1) 1047 1048 Button.SetText ("") 1049 Button.SetFlags (IE_GUI_BUTTON_ALIGN_RIGHT | IE_GUI_BUTTON_ALIGN_BOTTOM | IE_GUI_BUTTON_PICTURE, OP_OR) 1050 1051 if Slot == None: 1052 Button.SetFlags (IE_GUI_BUTTON_PICTURE, OP_NAND) 1053 tooltips = { "inventory": 12013, "ground": 12011, "container": "" } 1054 if GameCheck.IsGemRBDemo (): 1055 tooltips = { "inventory": 82, "ground": 83, "container": "" } 1056 Button.SetTooltip (tooltips[Type]) 1057 Button.EnableBorder (0, 0) 1058 Button.EnableBorder (1, 0) 1059 Button.EnableBorder (2, 0) 1060 else: 1061 item = GemRB.GetItem (Slot['ItemResRef']) 1062 identified = Slot["Flags"] & IE_INV_ITEM_IDENTIFIED 1063 magical = item["Enchantment"] > 0 1064 1065 # MaxStackAmount holds the *maximum* item count in the stack while Usages0 holds the actual 1066 if item["MaxStackAmount"] > 1: 1067 Button.SetText (str (Slot["Usages0"])) 1068 else: 1069 Button.SetText ("") 1070 1071 # auto-identify mundane items; the actual indentification will happen on transfer 1072 if not identified and item["LoreToID"] == 0: 1073 identified = True 1074 1075 if not identified or item["ItemNameIdentified"] == -1: 1076 Button.SetTooltip (item["ItemName"]) 1077 Button.EnableBorder (0, 1) 1078 Button.EnableBorder (1, 0) 1079 else: 1080 Button.SetTooltip (item["ItemNameIdentified"]) 1081 Button.EnableBorder (0, 0) 1082 if magical and not GameCheck.IsPST(): 1083 Button.EnableBorder (1, 1) 1084 else: 1085 Button.EnableBorder (1, 0) 1086 1087 if GemRB.CanUseItemType (SLOT_ALL, Slot['ItemResRef'], pc, Equipped): 1088 Button.EnableBorder (2, 0) 1089 else: 1090 Button.EnableBorder (2, 1) 1091 1092 Button.SetItemIcon (Slot['ItemResRef'], 0) 1093 1094 return 1095