def LocationPressed (): AreaInfo = GemRB.GetAreaInfo() print( "%s [%d.%d]\n"%(AreaInfo["CurrentArea"], AreaInfo["PositionX"], AreaInfo["PositionY"]) ) return
def GetAbilityBonus (Actor, Stat): Ability = GemRB.GetPlayerStat (Actor, Stat) return Ability//2-5
def CheckStat20 (Actor, Stat, Diff): mystat = GemRB.GetPlayerStat (Actor, Stat) goal = GemRB.Roll (1,20, Diff) if mystat>=goal: return True return False
def UpdateSlot(pc, slot): """Updates a specific slot.""" Window = GemRB.GetView("WIN_INV") using_fists = slot_item = SlotType = None if GameCheck.IsPST(): if slot >= len(SlotMap): #this prevents accidental out of range errors from the avslots list return GemRB.GetSlotType(slot + 1) elif SlotMap[slot] == -1: # This decides which icon to display in the empty slot # NOTE: there are invisible items (e.g. MORTEP) in inaccessible slots # used to assign powers and protections SlotType = GemRB.GetSlotType(slot + 1, pc) slot_item = None else: SlotType = GemRB.GetSlotType(SlotMap[slot] + 1) slot_item = GemRB.GetSlotItem(pc, SlotMap[slot] + 1) #PST displays the default weapon in the first slot if nothing else was equipped if slot_item is None and SlotType[ "ID"] == 10 and GemRB.GetEquippedQuickSlot(pc) == 10: slot_item = GemRB.GetSlotItem(pc, 0) using_fists = 1 else: SlotType = GemRB.GetSlotType(slot + 1, pc) slot_item = GemRB.GetSlotItem(pc, slot + 1) ControlID = SlotType["ID"] if ControlID == -1: return None if GemRB.IsDraggingItem() == 1: #get dragged item drag_item = GemRB.GetSlotItem(0, 0) itemname = drag_item["ItemResRef"] else: itemname = "" Button = Window.GetControl(ControlID) # It is important to check for a control - some games use CID 0 for slots with no control, others -1 if not Button: return Button.SetAction(OnDragItem, IE_ACT_DRAG_DROP_DST) Button.SetFlags(IE_GUI_BUTTON_NO_IMAGE, OP_NAND) # characters should auto-identify any item they recieve if slot_item: item = GemRB.GetItem(slot_item["ItemResRef"]) TryAutoIdentification( pc, item, slot + 1, slot_item, GemRB.GetVar("GUIEnhancements") & GE_TRY_IDENTIFY_ON_TRANSFER) UpdateInventorySlot(pc, Button, slot_item, "inventory", SlotType["Type"] & SLOT_INVENTORY == 0) if slot_item: Button.SetAction(OnDragItem, IE_ACT_DRAG_DROP_CRT) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, OnDragItem) Button.SetEvent(IE_GUI_BUTTON_ON_RIGHT_PRESS, OpenItemInfoWindow) Button.SetEvent(IE_GUI_BUTTON_ON_SHIFT_PRESS, OpenItemAmountWindow) #If the slot is being used to display the 'default' weapon, disable dragging. if SlotType["ID"] == 10 and using_fists: Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, None) #dropping is ok, because it will drop in the quick weapon slot and not the default weapon slot. else: if SlotType["ResRef"] == "*": Button.SetBAM("", 0, 0) Button.SetTooltip(SlotType["Tip"]) itemname = "" elif SlotType["ResRef"] == "": Button.SetBAM("", 0, 0) Button.SetFlags(IE_GUI_BUTTON_NO_IMAGE, OP_OR) Button.SetTooltip("") itemname = "" else: if SlotType["Flags"] & 2: Button.SetPicture(SlotType["ResRef"]) else: Button.SetBAM(SlotType["ResRef"], 0, 0) Button.SetTooltip(SlotType["Tip"]) if SlotMap and SlotMap[slot] < 0: Button.SetBAM("", 0, 0) Button.SetFlags(IE_GUI_BUTTON_NO_IMAGE, OP_OR) Button.SetTooltip("") itemname = "" Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, None) Button.SetEvent(IE_GUI_BUTTON_ON_RIGHT_PRESS, None) Button.SetEvent(IE_GUI_BUTTON_ON_SHIFT_PRESS, None) Button.SetEvent(IE_GUI_BUTTON_ON_DOUBLE_PRESS, OpenItemAmountWindow) if (SlotType["Type"] & SLOT_INVENTORY) or not GemRB.CanUseItemType( SlotType["Type"], itemname): Button.SetState(IE_GUI_BUTTON_ENABLED) else: Button.SetState(IE_GUI_BUTTON_FAKEPRESSED) if slot_item and (GemRB.GetEquippedQuickSlot(pc) == slot + 1 or GemRB.GetEquippedAmmunition(pc) == slot + 1): Button.SetState(IE_GUI_BUTTON_FAKEDISABLED) return SlotType
def SelectAllOnPress (): GemRB.GameSelectPC (0, 1)
def MouseLeaveGround(Button): if GemRB.IsDraggingItem() == 1: Button.SetState(IE_GUI_BUTTON_FAKEPRESSED) return
def TryAutoIdentification(pc, item, slot, slot_item, enabled=0): if enabled and item["LoreToID"] <= GemRB.GetPlayerStat(pc, IE_LORE): GemRB.ChangeItemFlag(pc, slot, IE_INV_ITEM_IDENTIFIED, OP_OR) slot_item["Flags"] |= IE_INV_ITEM_IDENTIFIED return True return False
def ApplyFeats(MyChar): #don't mess with feats outside of IWD2 if not GameCheck.IsIWD2(): return #feats giving a single innate ability SetSpell(MyChar, "SPIN111", FEAT_WILDSHAPE_BOAR) SetSpell(MyChar, "SPIN197", FEAT_MAXIMIZED_ATTACKS) SetSpell(MyChar, "SPIN231", FEAT_ENVENOM_WEAPON) SetSpell(MyChar, "SPIN245", FEAT_WILDSHAPE_PANTHER) SetSpell(MyChar, "SPIN246", FEAT_WILDSHAPE_SHAMBLER) SetSpell(MyChar, "SPIN275", FEAT_POWER_ATTACK) SetSpell(MyChar, "SPIN276", FEAT_EXPERTISE) SetSpell(MyChar, "SPIN277", FEAT_ARTERIAL_STRIKE) SetSpell(MyChar, "SPIN278", FEAT_HAMSTRING) SetSpell(MyChar, "SPIN279", FEAT_RAPID_SHOT) #extra rage level = GemRB.GetPlayerStat(MyChar, IE_LEVELBARBARIAN) if level > 0: if level >= 15: GemRB.RemoveSpell(MyChar, "SPIN236") Spell = "SPIN260" else: GemRB.RemoveSpell(MyChar, "SPIN260") Spell = "SPIN236" cnt = GemRB.GetPlayerStat(MyChar, IE_FEAT_EXTRA_RAGE) + (level + 3) // 4 GUICommon.MakeSpellCount(MyChar, Spell, cnt) else: GemRB.RemoveSpell(MyChar, "SPIN236") GemRB.RemoveSpell(MyChar, "SPIN260") #extra smiting level = GemRB.GetPlayerStat(MyChar, IE_LEVELPALADIN) if level > 1: cnt = GemRB.GetPlayerStat(MyChar, IE_FEAT_EXTRA_SMITING) + 1 GUICommon.MakeSpellCount(MyChar, "SPIN152", cnt) else: GemRB.RemoveSpell(MyChar, "SPIN152") #extra turning level = GemRB.GetPlayerStat(MyChar, IE_TURNUNDEADLEVEL) if level > 0: cnt = GUICommon.GetAbilityBonus(MyChar, IE_CHR) + 3 if cnt < 1: cnt = 1 cnt += GemRB.GetPlayerStat(MyChar, IE_FEAT_EXTRA_TURNING) GUICommon.MakeSpellCount(MyChar, "SPIN970", cnt) else: GemRB.RemoveSpell(MyChar, "SPIN970") #stunning fist if GemRB.HasFeat(MyChar, FEAT_STUNNING_FIST): cnt = GemRB.GetPlayerStat(MyChar, IE_CLASSLEVELSUM) // 4 GUICommon.MakeSpellCount(MyChar, "SPIN232", cnt) else: GemRB.RemoveSpell(MyChar, "SPIN232") #remove any previous SPLFOCUS #GemRB.ApplyEffect(MyChar, "RemoveEffects",0,0,"SPLFOCUS") #spell focus stats SPLFocusTable = GemRB.LoadTable("splfocus") for i in range(SPLFocusTable.GetRowCount()): Row = SPLFocusTable.GetRowName(i) Stat = SPLFocusTable.GetValue(Row, "STAT", GTV_STAT) if Stat: Column = GemRB.GetPlayerStat(MyChar, Stat) if Column: Value = SPLFocusTable.GetValue(i, Column) if Value: #add the effect, value could be 2 or 4, timing mode is 8 - so it is not saved GemRB.ApplyEffect(MyChar, "SpellFocus", Value, i, "", "", "", "SPLFOCUS", 8) return
def SetSpell(pc, SpellName, Feat): if GemRB.HasFeat(pc, Feat): GUICommon.MakeSpellCount(pc, SpellName, 1) else: GemRB.RemoveSpell(pc, SpellName) return
def SetupSavingThrows(pc, Level=None): """Updates an actors saving throws based upon level. Level should contain the actors current level. If Level is None, it is filled with the actors current level.""" Levels, NumClasses, Class = _SetupLevels(pc, Level, -1) if NumClasses > len(Levels): return #get some basic values Race = GemRB.GetPlayerStat(pc, IE_RACE) #see if we can add racial bonuses to saves Race = CommonTables.Races.GetRowName(CommonTables.Races.FindValue(3, Race)) RaceSaveTableName = CommonTables.Races.GetValue(Race, "SAVE", GTV_STR) RaceSaveTable = None if RaceSaveTableName != "-1" and RaceSaveTableName != "*": Con = GemRB.GetPlayerStat(pc, IE_CON, 1) - 1 RaceSaveTable = GemRB.LoadTable(RaceSaveTableName) if Con >= RaceSaveTable.GetColumnCount(): Con = RaceSaveTable.GetColumnCount() - 1 #preload our tables to limit multi-classed lookups SaveTables = [] ClassBonus = 0 for i in range(NumClasses): RowName = GUICommon.GetClassRowName(Class[i], "class") SaveName = CommonTables.Classes.GetValue(RowName, "SAVE", GTV_STR) SaveTables.append(GemRB.LoadTable(SaveName)) #use numeric value ClassBonus += CommonTables.ClassSkills.GetValue( RowName, "SAVEBONUS", GTV_INT) if not len(SaveTables): return #make sure to limit the levels to the table allowable MaxLevel = SaveTables[0].GetColumnCount() - 1 for i in range(len(Levels)): if Levels[i] > MaxLevel: Levels[i] = MaxLevel #save the saves for row in range(5): CurrentSave = GemRB.GetPlayerStat(pc, IE_SAVEVSDEATH + i, 1) for i in range(NumClasses): #loop through each class and update the save value if we have #a better save TmpSave = SaveTables[i].GetValue(row, Levels[i]) if TmpSave and (TmpSave < CurrentSave or i == 0): CurrentSave = TmpSave #add racial bonuses if applicable (small pc's) if RaceSaveTable: CurrentSave -= RaceSaveTable.GetValue(row, Con) #add class bonuses if applicable (paladin) CurrentSave -= ClassBonus GemRB.SetPlayerStat(pc, IE_SAVEVSDEATH + row, CurrentSave) return
def SetupHP(pc, Level=None, LevelDiff=None): """Updates an actors hp based upon level. Level should contain the actors current level. LevelDiff should contain the change in levels. Level and LevelDiff must be of the same length. If either are None, they are filled with the actors current level.""" Levels, NumClasses, Class = _SetupLevels(pc, Level, noclass=1) LevelDiffs, NumClasses, Class = _SetupLevels(pc, LevelDiff, noclass=1) if len(Levels) != len(LevelDiffs): return #adjust the class for multi/dual chars Class = [GemRB.GetPlayerStat(pc, IE_CLASS)] Multi = GUICommon.IsMultiClassed(pc, 1) Dual = GUICommon.IsDualClassed(pc, 1) NumClasses = 1 if Multi[0] > 1: #get each of the multi-classes NumClasses = Multi[0] Class = [Multi[1], Multi[2], Multi[3]] elif Dual[0]: #only worry about the newer class #we only get the hp bonus if the old class is reactivated if (Levels[0] <= Levels[1]): return if Dual[0] == 3: Class = [CommonTables.KitList.GetValue(Dual[2], 7)] else: ClassRow = GUICommon.GetClassRowName(Dual[2], "index") Class = [CommonTables.Classes.GetValue(ClassRow, "ID")] #if Level and LevelDiff are passed, we assume it is correct if GUICommon.IsDualSwap(pc) and not Level and not LevelDiff: LevelDiffs = [LevelDiffs[1], LevelDiffs[0], LevelDiffs[2]] elif GameCheck.IsIWD2(): Class = GetAllClasses(Levels) if NumClasses > len(Levels): return #get the correct hp for barbarians Kit = GUICommon.GetKitIndex(pc) ClassName = None if Kit and not Dual[0] and Multi[0] < 2: KitName = CommonTables.KitList.GetValue(Kit, 0, GTV_STR) if CommonTables.Classes.GetRowIndex(KitName) >= 0: ClassName = KitName # determine the minimum hp roll ConBonTable = GemRB.LoadTable("hpconbon") MinRoll = ConBonTable.GetValue(GemRB.GetPlayerStat(pc, IE_CON) - 1, 2) # MIN_ROLL column #loop through each class and update the hp OldHP = GemRB.GetPlayerStat(pc, IE_MAXHITPOINTS, 1) CurrentHP = 0 Divisor = float(NumClasses) if GameCheck.IsIWD2(): # hack around so we can reuse more of the main loop NumClasses = len(Levels) Divisor = 1.0 for i in range(NumClasses): if GameCheck.IsIWD2() and not Class[i]: continue #check this classes hp table for any gain if not ClassName or NumClasses > 1: ClassName = GUICommon.GetClassRowName(Class[i], "class") HPTable = CommonTables.Classes.GetValue(ClassName, "HP") HPTable = GemRB.LoadTable(HPTable) #make sure we are within table ranges MaxLevel = HPTable.GetRowCount() - 1 LowLevel = Levels[i] - LevelDiffs[i] HiLevel = Levels[i] if LowLevel >= HiLevel: continue if LowLevel < 0: LowLevel = 0 elif LowLevel > MaxLevel: LowLevel = MaxLevel if HiLevel < 0: HiLevel = 0 elif HiLevel > MaxLevel: HiLevel = MaxLevel #add all the hp for the given level #we use ceil to ensure each class gets hp for level in range(LowLevel, HiLevel): sides = HPTable.GetValue(level, 0) rolls = HPTable.GetValue(level, 1) bonus = HPTable.GetValue(level, 2) # we only do a roll on core difficulty or higher # and if maximum HP rolls (bg2 and later) are disabled # and/or if it is bg1 chargen (I guess too many testers got annoyed) # BUT when we do roll, constitution gives a kind of a luck bonus to the roll if rolls: if GemRB.GetVar ("Difficulty Level") >= 3 and not GemRB.GetVar ("Maximum HP") \ and not (GameCheck.IsBG1() and LowLevel == 0) and MinRoll < sides: if MinRoll > 1: roll = GemRB.Roll(rolls, sides, bonus) if roll - bonus < MinRoll: roll = MinRoll + bonus AddedHP = int(roll / Divisor + 0.5) else: AddedHP = int( GemRB.Roll(rolls, sides, bonus) / Divisor + 0.5) else: AddedHP = int((rolls * sides + bonus) / Divisor + 0.5) else: AddedHP = int(bonus / Divisor + 0.5) # ensure atleast 1hp is given # this is safe for inactive dualclass levels too (handled above) if AddedHP == 0: AddedHP = 1 CurrentHP += AddedHP #update our hp values GemRB.SetPlayerStat(pc, IE_MAXHITPOINTS, CurrentHP + OldHP) # HACK: account also for the new constitution bonus for the current hitpoints GemRB.SetPlayerStat( pc, IE_HITPOINTS, GemRB.GetPlayerStat(pc, IE_HITPOINTS, 1) + CurrentHP + 5) return
def CreditsPress(): if MovieWindow: MovieWindow.Unload() GemRB.SetNextScript("GUISONGS") return
def OpenFloatMenuWindow (x, y): if GameCheck.IsPST(): import FloatMenuWindow FloatMenuWindow.OpenFloatMenuWindow(x, y) else: GemRB.GameControlSetTargetMode (TARGET_MODE_NONE)
def SelectFormation (): GemRB.GameSetFormation (GemRB.GetVar ("Formation")) return
def MouseLeaveSlot(btn, slot): pc = GemRB.GameGetSelectedPCSingle() UpdateSlot(pc, slot - 1) return
def CanLevelUp(actor): """Returns true if the actor can level up.""" # get our class and placements for Multi'd and Dual'd characters Class = GUICommon.GetClassRowName(actor) Multi = GUICommon.IsMultiClassed(actor, 1) Dual = GUICommon.IsDualClassed(actor, 1) # get all the levels and overall xp here xp = GemRB.GetPlayerStat(actor, IE_XP) Levels = [GemRB.GetPlayerStat (actor, IE_LEVEL), GemRB.GetPlayerStat (actor, IE_LEVEL2),\ GemRB.GetPlayerStat (actor, IE_LEVEL3)] if GemRB.GetPlayerStat(actor, IE_LEVELDRAIN) > 0: return 0 if GameCheck.IsIWD2(): import GUIREC levelsum = GemRB.GetPlayerStat(actor, IE_CLASSLEVELSUM) next = GUIREC.GetNextLevelExp(levelsum, GUIREC.GetECL(actor)) return next <= xp # hardcoded special case to handle TNO, who is usually a single class # but with three separate Levels/XP values and the ability to switch between them # it returns the active class if true SwitcherClass = GUICommon.NamelessOneClass(actor) if SwitcherClass: xp = { "FIGHTER": GemRB.GetPlayerStat(actor, IE_XP), "MAGE": GemRB.GetPlayerStat(actor, IE_XP_MAGE), "THIEF": GemRB.GetPlayerStat(actor, IE_XP_THIEF) } lvls = {"FIGHTER": Levels[0], "MAGE": Levels[1], "THIEF": Levels[2]} tmpNext = GetNextLevelExp(lvls[SwitcherClass], SwitcherClass) if (tmpNext != 0 or lvls[SwitcherClass] == 0) and tmpNext <= xp[SwitcherClass]: return 1 #ignore the rest of this function, to avoid false positives #other classes can only be achieved by hacking the game somehow return 0 if Multi[0] > 1: # multiclassed xp = xp // Multi[0] # divide the xp evenly between the classes for i in range(Multi[0]): # if any class can level, return 1 TmpClassName = GUICommon.GetClassRowName(Multi[i + 1], "class") tmpNext = GetNextLevelExp(Levels[i], TmpClassName) if (tmpNext != 0 or Levels[i] == 0) and tmpNext <= xp: return 1 # didn't find a class that could level return 0 elif Dual[0] > 0: # dual classed # get the class we can level if Dual[0] == 3: ClassID = CommonTables.KitList.GetValue(Dual[2], 7) Class = GUICommon.GetClassRowName(ClassID, "class") else: Class = GUICommon.GetClassRowName(Dual[2], "index") if GUICommon.IsDualSwap(actor): Levels = [Levels[1], Levels[0], Levels[2]] # check the class that can be level (single or dual) tmpNext = GetNextLevelExp(Levels[0], Class) return ((tmpNext != 0 or Levels[0] == 0) and tmpNext <= xp)
def MouseEnterGround(Button): if GemRB.IsDraggingItem() == 1: Button.SetState(IE_GUI_BUTTON_SELECTED) return
# This is a script that allows you to talk to the embedded python interpreter # using ssh. To use it, put it in the GUIScript directory and then add the # following to include.py, or issue using the python console # # import manhole # manhole.createManhole(port = 2222, users = { 'gemrb': 'password' }) # # Then you can connect using ssh to the given port and issue python commands. import GemRB from twisted.internet import reactor reactor.startRunning() GemRB.SetTimer(lambda: reactor.iterate()) from twisted.conch import manhole, manhole_ssh from twisted.conch.insults import insults from twisted.cred import checkers, portal def createManhole(port=2222, users={'gemrb': 'password'}): """Create a twisted manhole for accessing the embedded python interpreter""" namespace = {'GemRB': GemRB} def makeProtocol(): return insults.ServerProtocol(manhole.ColoredManhole, namespace) r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = makeProtocol c = checkers.InMemoryUsernamePasswordDatabaseDontUse() for (username, password) in users.iteritems():
def DisplayItem(slotItem, itemtype): global ItemInfoWindow item = GemRB.GetItem(slotItem["ItemResRef"]) #window can be refreshed by cycling to next/prev item, so it may still exist if not ItemInfoWindow: ItemInfoWindow = GemRB.LoadWindow(5) Window = ItemInfoWindow def OnClose(): global ItemInfoWindow ItemInfoWindow = None Window.SetAction(OnClose, ACTION_WINDOW_CLOSED) if GameCheck.IsPST(): strrefs = [1403, 4256, 4255, 4251, 4252, 4254, 4279] elif GameCheck.IsGemRBDemo(): strrefs = [84, 105, 106, 104, 107, item["DialogName"], 108] else: strrefs = [ 11973, 14133, 11960, 19392, 17104, item["DialogName"], 17108 ] # item name Label = Window.GetControl(0x10000000) if (itemtype & 2): text = item["ItemName"] else: text = item["ItemNameIdentified"] Label.SetText(text) #item icon Button = Window.GetControl(2) if GameCheck.IsPST(): Button.SetFlags(IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_NO_IMAGE, OP_SET) Button.SetItemIcon(slotItem["ItemResRef"]) else: Button.SetFlags(IE_GUI_BUTTON_PICTURE, OP_OR) Button.SetItemIcon(slotItem["ItemResRef"], 0) Button.SetState(IE_GUI_BUTTON_LOCKED) #middle button Button = Window.GetControl(4) Button.SetText(strrefs[0]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, CloseItemInfoWindow) Button.MakeDefault() #textarea Text = Window.GetControl(5) if GameCheck.IsBG2(): # I believe only BG2 has special initials Text.SetColor(ColorWhitish, TA_COLOR_INITIALS) if (itemtype & 2): text = item["ItemDesc"] else: text = item["ItemDescIdentified"] Text.Clear() Text.Append(text) Window.SetEventProxy(Text) #left button Button = Window.GetControl(8) select = (itemtype & 1) and (item["Function"] & ITM_F_ABILITIES) if itemtype & 2: Button.SetText(strrefs[1]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, IdentifyItemWindow) Button.SetFlags(IE_GUI_BUTTON_PICTURE, OP_SET) elif select and not GameCheck.IsPST(): Button.SetText(strrefs[2]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, AbilitiesItemWindow) Button.SetFlags(IE_GUI_BUTTON_PICTURE, OP_SET) else: Button.SetText("") Button.SetState(IE_GUI_BUTTON_LOCKED) Button.SetFlags(IE_GUI_BUTTON_NO_IMAGE, OP_SET) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, None) # description icon (not present in iwds) if not GameCheck.IsIWD1() and not GameCheck.IsIWD2(): Button = Window.GetControl(7) Button.SetFlags( IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_CENTER_PICTURES | IE_GUI_BUTTON_NO_IMAGE, OP_OR) if GameCheck.IsPST(): Button.SetItemIcon(slotItem["ItemResRef"], 1) # no DescIcon else: Button.SetItemIcon(slotItem["ItemResRef"], 2) Button.SetState(IE_GUI_BUTTON_LOCKED) #right button Button = Window.GetControl(9) Button.SetFlags(IE_GUI_BUTTON_PICTURE, OP_SET) drink = (itemtype & 1) and (item["Function"] & ITM_F_DRINK) read = (itemtype & 1) and (item["Function"] & ITM_F_READ) # sorcerers cannot learn spells pc = GemRB.GameGetSelectedPCSingle() if Spellbook.HasSorcererBook(pc): read = 0 container = (itemtype & 1) and (item["Function"] & ITM_F_CONTAINER) dialog = (itemtype & 1) and (item["Dialog"] != "" and item["Dialog"] != "*") familiar = (itemtype & 1) and (item["Type"] == 38) # The "conversable" bit in PST actually means "usable", eg clot charm # unlike BG2 (which only has the bit set on SW2H14 Lilarcor) # Meanwhile IWD series has the bit set on important quest items # So the widely accepted name of this bit is misleading # There are also items in PST, cube.itm and doll.itm # that are not flagged usable but still have dialog attached. # this is how the original game draws the distinction between 'use item' and 'talk to item' # if the item has dialog and is flagged usable = use item string, open dialog # if the item has dialog and is not flagged usable = talk to item, open dialog # if the item has no dialog and is flagged usable = use item string, consume item if GameCheck.IsPST() and slotItem["Flags"] & IE_INV_ITEM_CONVERSABLE: drink = True # "Use" if drink and not dialog: # Standard consumable item Button.SetText(strrefs[3]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, ConsumeItem) elif read: Button.SetText(strrefs[4]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, ReadItemWindow) elif container: # Just skip the redundant info page and go directly to the container if GemRB.GetVar("GUIEnhancements") & GE_ALWAYS_OPEN_CONTAINER_ITEMS: OpenItemWindow() return if GameCheck.IsIWD2() or GameCheck.IsHOW(): Button.SetText(24891) # Open Container elif GameCheck.IsBG2(): Button.SetText(44002) # open container else: # a fallback, since the originals have nothing appropriate from not having any bags Button.SetText("Open container") Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, OpenItemWindow) elif dialog: if drink: # Dialog item that is 'used' Button.SetText(strrefs[3]) else: # Dialog item that is 'talked to' Button.SetText(strrefs[5]) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, DialogItemWindow) elif familiar and not GameCheck.IsPST(): # PST earings share a type with familiars, so no # mods that allow familiars would be possible in PST Button.SetText(4373) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, ReleaseFamiliar) else: Button.SetState(IE_GUI_BUTTON_LOCKED) Button.SetFlags(IE_GUI_BUTTON_NO_IMAGE, OP_SET) Button.SetText("") Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, None) Label = Window.GetControl(0x1000000b) if Label: if (itemtype & 2): # NOT IDENTIFIED Label.SetText(strrefs[6]) else: Label.SetText("") # in pst one can cycle through all the items from the description window if GameCheck.IsPST(): #left scroll Button = Window.GetControl(13) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, lambda: CycleDisplayItem(-1)) #right scroll Button = Window.GetControl(14) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, lambda: CycleDisplayItem(1)) ItemInfoWindow.ShowModal(MODAL_SHADOW_GRAY) return
def OnJournalQuestSelect(): row = GemRB.GetVar('SelectedQuest') q = quests[selected_quest_class][row] QuestDesc.SetText(int(q[1]))
def OpenItemAmountWindow(btn, slot): """Open the split window.""" global UsedSlot, OverSlot global ItemAmountWindow, StackAmount pc = GemRB.GameGetSelectedPCSingle() UsedSlot = slot if GemRB.IsDraggingItem() == 1: GemRB.DropDraggedItem(pc, UsedSlot) #redraw slot UpdateSlot(pc, UsedSlot - 1) # disallow splitting while holding split items (double splitting) if GemRB.IsDraggingItem() == 1: return slot_item = GemRB.GetSlotItem(pc, UsedSlot) if slot_item: StackAmount = slot_item["Usages0"] else: StackAmount = 0 if StackAmount <= 1: UpdateSlot(pc, UsedSlot - 1) return ItemAmountWindow = Window = GemRB.LoadWindow(4) Window.SetFlags(WF_ALPHA_CHANNEL, OP_OR) Window.SetAction(ItemAmountWindowClosed, ACTION_WINDOW_CLOSED) strings = {'Done': 11973, "Cancel": 13727} if GameCheck.IsPST(): strings = {'Done': 1403, "Cancel": 4196} elif GameCheck.IsGemRBDemo(): strings = {'Done': 84, 'Cancel': 103} # item icon Icon = Window.GetControl(0) Icon.SetFlags(IE_GUI_BUTTON_PICTURE | IE_GUI_BUTTON_NO_IMAGE, OP_SET) Icon.SetItemIcon(slot_item['ItemResRef']) # item amount Text = Window.GetControl(6) # FIXME: use a proper size # FIXME: fix it for all the games if GameCheck.IsIWD2(): Text.SetSize(40, 40) Text.SetText(str(StackAmount // 2)) Text.SetFlags(IE_GUI_TEXTEDIT_ALPHACHARS, OP_NAND) Text.Focus() # Decrease Button = Window.GetControl(4) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, DecreaseStackAmount) Button.SetActionInterval(200) # Increase Button = Window.GetControl(3) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, IncreaseStackAmount) Button.SetActionInterval(200) # Done Button = Window.GetControl(2) Button.SetText(strings['Done']) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, DragItemAmount) Button.MakeDefault() # Cancel Button = Window.GetControl(1) Button.SetText(strings['Cancel']) Button.SetEvent(IE_GUI_BUTTON_ON_PRESS, lambda: Window.Close()) Button.MakeEscape() Window.ShowModal(MODAL_SHADOW_GRAY) return
def EvaluateQuest(index): tag = str(index) endings = int(GemRB.GetINIQuestsKey(tag, 'possibleEndings', '1')) for e in range(endings): if e == 0: suff = '' else: suff = chr(ord('A') + e) completed = 1 cc = int(GemRB.GetINIQuestsKey(tag, 'completeChecks' + suff, '0')) for i in range(1, cc + 1): var = GemRB.GetINIQuestsKey(tag, 'cVar' + suff + str(i), '') value = GemRB.GetINIQuestsKey(tag, 'cValue' + suff + str(i), '0') condition = GemRB.GetINIQuestsKey(tag, 'cCondition' + suff + str(i), 'EQ') completed = completed and EvaluateCondition(var, value, condition) #print 'CC:', var, int (GemRB.GetGameVar (var)), condition, value, ': ', completed if not completed: break if completed: #print "COMPLETED", suff desc = GemRB.GetINIQuestsKey(tag, 'descCompleted' + suff, '0') return (1, desc) break assigned = 1 ac = int(GemRB.GetINIQuestsKey(tag, 'assignedChecks', '0')) for i in range(1, ac + 1): var = GemRB.GetINIQuestsKey(tag, 'aVar' + str(i), '') value = GemRB.GetINIQuestsKey(tag, 'aValue' + str(i), '0') condition = GemRB.GetINIQuestsKey(tag, 'aCondition' + str(i), 'EQ') assigned = assigned and EvaluateCondition(var, value, condition) #print 'AC:', var, condition, value, ': ', assigned if not assigned: break if assigned: #print "ASSIGNED" desc = GemRB.GetINIQuestsKey(tag, 'descAssigned', '0') return (0, desc) return None
def OnDragItem(btn, slot): """Updates dragging.""" #don't call when splitting items if ItemAmountWindow != None: return pc = GemRB.GameGetSelectedPCSingle() slot_item = GemRB.GetSlotItem(pc, slot) if not GemRB.IsDraggingItem(): item = GemRB.GetItem(slot_item["ItemResRef"]) GemRB.DragItem(pc, slot, item["ItemIcon"], 0, 0) else: SlotType = GemRB.GetSlotType(slot, pc) #special monk check if GemRB.GetPlayerStat( pc, IE_CLASS) == 20 and SlotType["Effects"] == TYPE_OFFHAND: SlotType["ResRef"] = "" GemRB.DisplayString(61355, ColorWhite) if SlotType["ResRef"] != "": if slot_item: item = GemRB.GetItem(slot_item["ItemResRef"]) #drag items into a bag if item["Function"] & ITM_F_CONTAINER: #first swap them GemRB.DropDraggedItem(pc, slot) #enter the store GemRB.EnterStore(slot_item["ItemResRef"]) #if it is possible to add, then do it ret = GemRB.IsValidStoreItem(pc, slot, 0) if ret & SHOP_SELL: GemRB.ChangeStoreItem(pc, slot, SHOP_SELL) else: msg = 9375 if ret & SHOP_FULL: if GameCheck.IsIWD1() or GameCheck.IsIWD2(): msg = 24893 elif GameCheck.HasTOB(): msg = 54692 GemRB.DisplayString(msg, ColorWhite) #leave (save) store GemRB.LeaveStore() GemRB.DropDraggedItem(pc, slot) # drop item if it caused us to disable the inventory view (example: cursed berserking sword) if GemRB.GetPlayerStat(pc, IE_STATE_ID) & ( STATE_BERSERK) and GemRB.IsDraggingItem(): GemRB.DropDraggedItem(pc, -3) UpdateInventoryWindow() return
def BackPress(): if AppearanceWindow: AppearanceWindow.Close() GemRB.SetNextScript("CharGen") GemRB.SetVar("Gender", 0) #scrapping the gender value return
def GearsClicked (): #GemRB.SetPlayerStat(GemRB.GameGetFirstSelectedPC (),44,249990) GemRB.GamePause (2, 0)
def DoneAbilitiesItemWindow(): pc = GemRB.GameGetSelectedPCSingle() slot = GemRB.GetVar("ItemButton") GemRB.SetupQuickSlot(pc, 0, slot, GemRB.GetVar("Ability")) CloseAbilitiesItemWindow() return
def SetColorStat (Actor, Stat, Value): t = Value & 0xFF t |= t << 8 t |= t << 16 GemRB.SetPlayerStat (Actor, Stat, t) return
def UpdateInventorySlot(pc, Button, Slot, Type, Equipped=False): Button.SetFont("NUMBER") color = {'r': 128, 'g': 128, 'b': 255, 'a': 64} Button.SetBorder(0, color, 0, 1) color = {'r': 32, 'g': 32, 'b': 255, 'a': 255} Button.SetBorder(1, color, 0, 0, Button.GetInsetFrame(2)) colorUnusable = {'r': 255, 'g': 128, 'b': 128, 'a': 64} Button.SetBorder(2, colorUnusable, 0, 1) colorUMD = {'r': 255, 'g': 255, 'b': 0, 'a': 64} Button.SetText("") Button.SetFlags( IE_GUI_BUTTON_ALIGN_RIGHT | IE_GUI_BUTTON_ALIGN_BOTTOM | IE_GUI_BUTTON_PICTURE, OP_OR) if Slot == None: Button.SetFlags(IE_GUI_BUTTON_PICTURE, OP_NAND) tooltips = {"inventory": 12013, "ground": 12011, "container": ""} if GameCheck.IsGemRBDemo(): tooltips = {"inventory": 82, "ground": 83, "container": ""} Button.SetTooltip(tooltips[Type]) Button.EnableBorder(0, 0) Button.EnableBorder(1, 0) Button.EnableBorder(2, 0) return item = GemRB.GetItem(Slot['ItemResRef']) identified = Slot["Flags"] & IE_INV_ITEM_IDENTIFIED magical = item["Enchantment"] > 0 # MaxStackAmount holds the *maximum* item count in the stack while Usages0 holds the actual if item["MaxStackAmount"] > 1: Button.SetText(str(Slot["Usages0"])) # auto-identify mundane items; the actual indentification will happen on transfer if not identified and item["LoreToID"] == 0: identified = True if not identified or item["ItemNameIdentified"] == -1: Button.SetTooltip(item["ItemName"]) Button.EnableBorder(0, 1) Button.EnableBorder(1, 0) else: Button.SetTooltip(item["ItemNameIdentified"]) Button.EnableBorder(0, 0) if magical and not GameCheck.IsPST(): Button.EnableBorder(1, 1) else: Button.EnableBorder(1, 0) usable = GemRB.CanUseItemType(SLOT_ALL, Slot['ItemResRef'], pc, Equipped) if usable: # enable yellow overlay for "use magical device" if usable & 0x100000: Button.SetBorder(2, colorUMD, 1, 1) else: Button.EnableBorder(2, 0) else: Button.SetBorder(2, colorUnusable, 1, 1) Button.SetItemIcon(Slot['ItemResRef'], 0) return
def Gain(infostr, ability): GemRB.SetToken ('SPECIALABILITYNAME', GemRB.GetString(int(ability) ) ) GemRB.DisplayString (infostr)
def DisplayAC (pc, window, labelID): AC = GemRB.GetPlayerStat (pc, IE_ARMORCLASS) + GetACStyleBonus (pc) Label = window.GetControl (labelID) Label.SetText (str (AC)) Label.SetTooltip (17183)