Skip to content

[MOD} Several BGEE/SOD BG2EE/TOB Leveling Progress Bar tweaks

AncientCowboyAncientCowboy Member Posts: 199
edited December 2016 in UI Modding

I love playing multi-class characters, but I'm old and lazy. While I appreciate the progress bar label telling me how much class XP is needed to level up, I hate having to do the mental multiplication to determine the total XP I need to earn. So I created an alternative to the getNextLevelString function named getAdjustedNextLevelString that does the arithmetic for me.

Also, while I like the idea of the quick 'How far I've progressed to the next level' visual that the progress bar provides; I'm not fond of the fact that it is displaying an absolute (ratio of total current XP to total required XP) rather than a level relative (ratio of XP earned since last level up to additional XP needed to reach next level) value. So, I created a Lua function, getNextLevelXPDeltas, that returns the deltas needed to feed the existing getPercent function.

I've hidden all of the previous stuff behind a spoiler tag. It's concerned with doing manual editing - interesting perhaps from a historical point of view but no longer relevant :smile:

I'm going to start with how to do the tweaks - then I'll finish with a few comments on the implementation and limitations of the getNextLevelXPDeltas function.

First, copy and paste the following code into your preferred text editor and save it as a file named LvlPgBar.lua in the {installation-directory}/00806/override directory.

function getAdjustedNextLevelString()
	local multiplier = 1
	if (characters[currentID].race ~= 1096) then -- Not human
		if (characters[currentID].classlevel.third) then
			multiplier = 3
		elseif (characters[currentID].classlevel.second) then
			multiplier = 2
		end
	end
	local nextLevelXp = (characters[currentID].level.nextLvlXp - characters[currentID].level.xp) * multiplier
	local str = ""
	if(nextLevelXp > 0) then
		str = t("NEXT_LEVEL_LABEL")
		str = str .. " "
		str = str .. nextLevelXp
		str = str .. " "
		str = str .. t("XP_LABEL")
	else
		str = t("READY_TO_LEVEL_LABEL")
	end
	return str
	
end

-- Extracted from clastext.2DA
local MixIdtoClassIdMap = {
-- MixedId  ClassId  Class/kit name
	[502]   =	1,		--ABJURER             
	[504]   =	1,		--CONJURER            
	[1076]  =	2,		--FIGHTER             
	[1077]  =	12,		--RANGER              
	[1078]  =	6,		--PALADIN             
	[1079]  =	3,		--CLERIC              
	[1080]  =	11,		--DRUID               
	[1081]  =	1,		--MAGE                
	[1082]  =	4,		--THIEF               
	[1083]  =	5,		--BARD                
	[2012]  =	1,		--DIVINER             
	[2022]  =	1,		--ENCHANTER           
	[10369] =	12,		--FALLEN_RANGER       
	[10371] =	6,		--FALLEN_PALADIN      
	[12785] =	1,		--ILLUSIONIST         
	[12786] =	1,		--INVOKER             
	[12787] =	1,		--NECROMANCER         
	[12788] =	1,		--TRANSMUTER          
	[24205] =	3,		--FALLEN_CLERIC       
	[24206] =	3,		--FALLEN_GODLATHANDER 
	[24208] =	6,		--FALLEN_CAVALIER     
	[24210] =	6,		--FALLEN_INQUISITOR   
	[24212] =	6,		--FALLEN_UNDEAD_HUNTER
	[24214] =	12,		--FALLEN_FERALAN    
	[24216] =	12,		--FALLEN_STALKER      
	[24218] =	12,		--FALLEN_BEAST_MASTER 
	[24227] =	19,		--SORCERER            
	[24228] =	20,		--MONK                
	[24229] =	2,		--BARBARIAN           
	[24261] =	2,		--BERSERKER           
	[24262] =	2,		--WIZARD_SLAYER       
	[24263] =	2,		--KENSAI              
	[24264] =	6,		--CAVALIER            
	[24265] =	6,		--INQUISITOR          
	[24266] =	6,		--UNDEAD_HUNTER       
	[24267] =	12,		--FERALAN           
	[24268] =	12,		--STALKER             
	[24269] =	12,		--BEAST_MASTER        
	[24270] =	4,		--ASSASSIN            
	[24271] =	4,		--BOUNTY_HUNTER       
	[24272] =	4,		--SWASHBUCKLER        
	[24273] =	5,		--BLADE               
	[24274] =	5,		--JESTER              
	[24275] =	5,		--SKALD               
	[24276] =	3,		--GODTALOS            
	[24277] =	3,		--GODHELM             
	[24278] =	3,		--GODLATHANDER        
	[24279] =	11,		--TOTEMIC_DRUID       
	[24280] =	11,		--SHAPESHIFTER        
	[24281] =	11,		--AVENGER             
	[24282] =	1,		--WILD_MAGE           
	[28605] =	6,		--BLACKGUARD          
	[31971] =	4,		--SHADOWDANCER        
	[31974] =	2,		--DWARVEN_DEFENDER    
	[31977] =	19,		--DRAGON_DISCIPLE     
	[31980] =	20,		--DARK_MOON           
	[31983] =	20,		--SUN_SOUL            
	[32307] =	6,		--FALLEN_BLACKGUARD   
	[32342] =	21,		--SHAMAN              
	[32345] =	3		--OHTYR
}	

-- Extracted from xplist.2DA
local ClassIdToXPLevelMap = {
-- Class      ID    Level ?1       ?2       ?3       ?4       ?5       ?6       ?7       ?8       ?9       ?0
--[[MAGE]]    [1] ={       0,    2500,    5000,   10000,   20000,   40000,   60000,   90000,  135000,  250000,
                      375000,  750000, 1125000, 1500000, 1875000, 2250000, 2625000, 3000000, 3375000, 3750000,
                     4125000, 4500000, 4875000, 5250000, 5625000, 6000000, 6375000, 6750000, 7125000, 7500000,
                     7875000, 8250000, 8625000, 9000000, 9375000, 9750000,10125000,10500000,10875000,11250000,
                    13000000},
--[[FIGHTER]] [2] ={       0,    2000,    4000,    8000,   16000,   32000,   64000,  125000,  250000,  500000,
                      750000, 1000000, 1250000, 1500000, 1750000, 2000000, 2250000, 2500000, 2750000, 3000000,
                     3250000, 3500000, 3750000, 4000000, 4250000, 4500000, 4750000, 5000000, 5250000, 5500000,
                     5750000, 6000000, 6250000, 6500000, 6750000, 7000000, 7250000, 7500000, 7750000, 8000000, 
                     8250000},
--[[CLERIC]]  [3] ={       0,    1500,    3000,    6000,   13000,   27500,   55000,  110000,  225000,  450000,
                      675000,  900000,  125000, 1350000, 1575000, 1800000, 2025000, 2250000, 2475000, 2700000,
                     2925000, 3150000, 3375000, 3600000, 3825000, 4050000, 4275000, 4500000, 4725000, 4950000,
                     5175000, 5400000, 5625000, 5850000, 6075000, 6300000, 6525000, 6750000, 6975000, 8000000, 
                     9000000},
--[[THIEF]]   [4] ={       0,    1250,    2500,    5000,   10000,   20000,   40000,   70000,  110000,  160000,
                      220000,  440000,  660000,  880000, 1100000, 1320000, 1540000, 1760000, 1980000, 2200000,
                     2420000, 2640000, 2860000, 3080000, 3300000, 3520000, 3740000, 3960000, 4180000, 4400000,
                     4620000, 4840000, 5060000, 5280000, 5500000, 5720000, 5940000, 6160000, 6380000, 8000000, 
                     9000000},
--[[BARD]]    [5] ={       0,    1250,    2500,    5000,   10000,   20000,   40000,   70000,  110000,  160000,
                      220000,  440000,  660000,  880000, 1100000, 1320000, 1540000, 1760000, 1980000, 2200000,
                     2420000, 2640000, 2860000, 3080000, 3300000, 3520000, 3740000, 3960000, 4180000, 4400000,
                     4620000, 4840000, 5060000, 5280000, 5500000, 5720000, 5940000, 6160000, 6380000, 8000000, 
                     9000000},
--[[PALADIN]] [6] ={       0,    2250,    4500,    9000,   18000,   36000,   75000,  150000,  300000,  600000,
                      900000, 1200000, 1500000, 1800000, 2100000, 2400000, 2700000, 3000000, 3300000, 3600000,
                     3900000, 4200000, 4500000, 4800000, 5100000, 5400000, 5700000, 6000000, 6300000, 6600000,
                     6900000, 7200000, 7500000, 7800000, 8100000, 8400000, 8700000, 9000000, 9300000, 9600000, 
                     9900000},
--[[DRUID]]   [11]={       0,    2000,    4000,    7500,   12500,   20000,   35000,   60000,   90000,  125000,
                      200000,  300000,  750000, 1500000, 3000000, 3150000, 3300000, 3450000, 3600000, 3750000,
                     3900000, 4150000, 4400000, 4700000, 5000000, 5500000, 6000000, 6500000, 7000000, 7500000,
                     8000000, 8500000, 9000000, 9500000,10000000,10500000,11000000,11500000,12000000,12500000,
                    13000000},
--[[RANGER]]  [12]={       0,    2250,    4500,    9000,   18000,   36000,   75000,  150000,  300000,  600000,
                      900000, 1200000, 1500000, 1800000, 2100000, 2400000, 2700000, 3000000, 3300000, 3600000,
                     3900000, 4200000, 4500000, 4800000, 5100000, 5400000, 5700000, 6000000, 6300000, 6600000,
                     6900000, 7200000, 7500000, 7800000, 8100000, 8400000, 8700000, 9000000, 9300000, 9600000, 
                     9900000},
--[[SORCERER]][19]={       0,    2500,    5000,   10000,   20000,   40000,   60000,   90000,  135000,  250000,
                      375000,  750000, 1125000, 1500000, 1875000, 2250000, 2625000, 3000000, 3375000, 3750000,
                     4125000, 4500000, 4875000, 5250000, 5625000, 6000000, 6375000, 6750000, 7125000, 7500000,
                     7875000, 8250000, 8625000, 9000000, 9375000, 9750000,10125000,10500000,10875000,11250000,
                    13000000},
--[[MONK]]    [20]={       0,    1500,    3000,    6000,   13000,   27500,   55000,  110000,  225000,  450000,
                      675000,  900000, 1125000, 1350000, 1575000, 1800000, 2025000, 2250000, 2475000, 2700000,
                     2925000, 3150000, 3375000, 3600000, 3825000, 4050000, 4275000, 4500000, 4725000, 4950000,
                     5175000, 5400000, 5625000, 5850000, 6075000, 6300000, 6525000, 6750000, 6975000, 8000000,
                     9000000},
--[[SHAMAN]]  [21]={       0,    2500,    5000,   10000,   20000,   40000,   60000,   90000,  135000,  250000,
                      375000,  750000, 1125000, 1500000, 1875000, 2250000, 2625000, 3000000, 3375000, 3750000,
                     4125000, 4500000, 4875000, 5250000, 5625000, 6000000, 6375000, 6750000, 7125000, 7500000,
                     7875000, 8250000, 8625000, 9000000, 9375000, 9750000,10125000,10500000,10875000,11250000,
                    13000000}
}

local u8asciiMatchString = "^([^:]-)%s*:%D+(%d+)"
local u3colonMatchString = "^(..-)[\239][\188][\154]%D-(%d+)"
local nbspaceMatchString = "^([^:]-)[\194][\160]:%D+(%d+)"

local LanguageMatch = {
	['zh_CN'] = u3colonMatchString,
	['cs_CZ'] = u8asciiMatchString,
	['en_US'] = u8asciiMatchString,
	['fr_FR'] = nbspaceMatchString,
	['de_DE'] = u8asciiMatchString,
	['it_IT'] = u8asciiMatchString,
	['ja_JP'] = u3colonMatchString,
	['ko_KR'] = u8asciiMatchString,
	['nb_NO'] = u8asciiMatchString, 
	['pl_PL'] = u8asciiMatchString,
	['pt_BR'] = u8asciiMatchString,
	['ru_RU'] = u8asciiMatchString,
	['es_ES'] = u8asciiMatchString,
	['tr_TR'] = u8asciiMatchString,
	['uk_UA'] = u8asciiMatchString,
	['hu_HU'] = u8asciiMatchString
}

local KitStringToXPMap = {}

local function KitStringToXPMapInit()
	for k,v in pairs(MixIdtoClassIdMap) do
		KitStringToXPMap[Infinity_FetchString(k)] = ClassIdToXPLevelMap[v]
	end
	KitStringToXPMap['Matchstring'] = LanguageMatch[Infinity_GetINIString('Language','Text')]
	KitStringToXPMap['Initialized'] = true
end

local function getCurrentLevelXP(targetDetails)
	local targetKit
	local targetLevel
	local currentlevelxp = 0

	targetKit,targetLevel = string.match(targetDetails, KitStringToXPMap['Matchstring'])
	
	if	( -- Fail safe for kit strings that haven't yet been put into language files
		targetKit and 
		targetLevel and
		#targetKit > 0 and
		not string.match(targetKit, "placeholder")
		) 
	then
		currentlevelxp = KitStringToXPMap[targetKit][tonumber(targetLevel)]
	end
	return currentlevelxp
end

function getNextLevelXPDeltas()
	if (not KitStringToXPMap['Initialized']) then KitStringToXPMapInit() end

-- Fail safe. Can't determine language so fail by returning non-delta values
	if (not KitStringToXPMap['Matchstring']) then
		return characters[currentID].level.xp, characters[currentID].level.nextLvlXp
	end

	local candidates = {} -- Array of current level base XP for each class that will next level up
	
	if	(
		characters[currentID].classlevel.third and
		characters[currentID].classlevel.third.active and
		characters[currentID].classlevel.third.nextLvlXp == characters[currentID].level.nextLvlXp
		)
	then
		candidates[#candidates+1] = getCurrentLevelXP(characters[currentID].classlevel.third.details)
	end
	
	if	(
		characters[currentID].classlevel.second and
		characters[currentID].classlevel.second.active and
		characters[currentID].classlevel.second.nextLvlXp == characters[currentID].level.nextLvlXp
		)
	then
		candidates[#candidates+1] = getCurrentLevelXP(characters[currentID].classlevel.second.details)
	end
	
	if	(
		characters[currentID].classlevel.first and
		characters[currentID].classlevel.first.nextLvlXp == characters[currentID].level.nextLvlXp
		)
	then
		candidates[#candidates+1] = getCurrentLevelXP(characters[currentID].classlevel.first.details)
	end
		
	local currentlevelxp
	if(#candidates > 0) then
		currentlevelxp = candidates[1]
		for i = 2, #candidates do
			currentlevelxp = math.max(currentlevelxp, candidates[i])
		end
	else
		currentlevelxp = 0 -- Something is bogus, fail safe
	end

	return characters[currentID].level.xp - currentlevelxp, characters[currentID].level.nextLvlXp - currentlevelxp
end

Next, open ui.menu. Near the beginning, you'll find a Lua if() then ... else ... end statement that makes a couple of calls to Infinity_DoFile. Add the following after that code:

Infinity_DoFile("LvlPgBar")

This will add the code from our LvlPgBar.lua file to the current environment. If you want to use a different file name be aware that, at least under Windows (all I can test), the file name must conform to the old 8.3 convention for Infinity_DoFile to work. Wasted an hour or so learning that. Good thing my grandsons weren't visiting at the time - they'd have learned a couple of new cuss words :smile: .

If you want to enable the getAdjustedNextLevelString tweak, search for the label (or button if you've incorporated one of my prior tweaks) that has the line that looks like this:

    text		lua "getNextLevelString()"

Change it to this:

    text		lua "getAdjustedNextLevelString()"

To enable the getNextLevelXPDeltas tweak, search for the label containing the line:

    progressbar lua "getPercent(characters[currentID].level.xp, characters[currentID].level.nextLvlXp)"

Change it to this:

    progressbar lua "getPercent(getNextLevelXPDeltas())"

That's it! Now for the why's and limits.

The obvious why is 'Why a separate override file?'. The equally obvious answer is that the ui.menu file is inconveniently large due to the interactive ui editing feature needing all of the ui code to be in one file. Since most of the code I've created here is Lua rather than ui code - I've opt'ed to not clutter ui.menu with an extra 250 lines of code.

Why create getAdjustedNextLevelString instead of just tweaking getNextLevelString? Because one of the next things I'm going to look at is the possibility of defining my own Options and this would be a simple one to investigate. I suspect that other folks already have or will soon implement this, so it may a fairly trivial exercise (for me - not them :smile:)

The next thing has to do with the behavior of getNextLevelXPDeltas. I decided early that if, for one reason or another, the function was unable to determine the current level's base XP value, that the function should 'fail safe' - which in this case means returning the same values as the existing 'non-tweaked' code. To look up the current level's base XP value for each of the (3) potential classes/kits that could be candidates for leveling, it's necessary to know the class and the current level for that class. The only way I could discover to do this from the Lua code was by extracting them from the 'details' string of the (potentially) 3 classlevel tables. Without going into the gory details, this/these string(s) is/are what you see at the top of the 'wall of text' Information panel of the character screen (disregarding the initial 'Multi-Class'/'Dual-Class' bit). To decode them, the code needs to know the language so it can properly decode the string(s) and identify the kit/class. Thus, getting back to the original point (at last!), there are 3 possibilities for the 'fail-safe' behavior. First, if the code can't recognize the language. If you're busy creating a Klingon .tlk file, this tweak won't do you any good (at least until you tell me what language string you're stuffing into Baldur.lua). Second, and most frequent, is where a new class/kit hasn't yet been added to the .tlk file or where 'placeholder' has been used until the translation team gets around to it. There are, for example, several of the languages that have 'placeholder' for the Shaman class (and yes, I know that a lot of the translation work is done by volunteers - what I'm saying should not be considered a complaint or criticism). In those cases, for characters of the 'placeholder' class(es) - you'll get the 'fail-safe' behavior. The final case is where there's a bug. Currently (2.1), the Turkish language 'details' string(s) are missing the class/kit portion. The strings (with the appropriate strrefs) are in the .tlk file. They're just not being used to build the 'details' strings. I'm assuming this is such an obvious problem that it's already been noted. So, for Turkish, this tweak doesn't accomplish anything. I'll obviously be checking this when 2.2 drops.

The last item to mention is where multiple classes will level up at the same point - with different current level base XP values. Which base value is used? The highest one. It makes the code a bit simpler (and thus faster) and also makes the progress bar a bit more sensitive to smaller XP gains. If you would prefer, you can change the line that invokes 'math.max' to 'max.min' - just be sure you're dealing with (or don't have to deal with) the case where the private getCurrentLevelXP function returns 0 (typically the 'placeholder' case above).

The current release is part of EEUITweaks
The file below contains information for configuring the mod by editing Baldur.lua (versus using Mods Options)

Enjoy - and if anyone wishes to use any or all of this (or anything else I've posted on this forum) in their own tweaks/mods, please feel free to do so. Posted publicly to be used by anyone.

Post edited by AncientCowboy on
Mr2150Peccamf2112lefreutlolienGrammarsaladJuliusBorisovbrus
«1

Comments

  • Mr2150Mr2150 Member Posts: 1,170
    Do you have any pictures of the changes in action?
    jackjack
  • Mr2150Mr2150 Member Posts: 1,170
    Also - just a thought, I was playing around with the code and was trying to get a bar for each class to show but I was struggling with the XP calculation (that you've fixed above...

    The following code works a treat for displaying 3 bars... you just need to amend it with your altered XP calculations:

    label { area 575 642 210 28 progressbar lua "getPercent(characters[currentID].classlevel.first.xp, characters[currentID].classlevel.first.nextLvlXp)" greyscale 0 --display greyscale or not, number 0-1 progressbar color 92 34 10 255 --color when percentage != 100 progressbar full 0 46 99 255 --color when percentage == 100 } label { area 575 678 210 28 enabled "characters[currentID].classlevel.second.xp > 0" progressbar lua "getPercent(characters[currentID].classlevel.second.xp, characters[currentID].classlevel.second.nextLvlXp)" greyscale 0 --display greyscale or not, number 0-1 progressbar color 92 34 10 255 --color when percentage != 100 progressbar full 0 46 99 255 --color when percentage == 100 } label { area 575 714 210 28 enabled "characters[currentID].classlevel.third > 0" progressbar lua "getPercent(characters[currentID].classlevel.third.xp, characters[currentID].classlevel.third.nextLvlXp)" greyscale 0 --display greyscale or not, number 0-1 progressbar color 92 34 10 255 --color when percentage != 100 progressbar full 0 46 99 255 --color when percentage == 100 }

    Note the enabled bars to 'switch on/off' the progressbar. Here's the bars for jaheira with a bad XP calculation...




  • mf2112mf2112 Member, Moderator Posts: 1,919
    edited May 2016
    This reminded me of something I was thinking about the other day. Is it possible to dump all the various characteristics into a text array up front and then displaying text in various ways would be a lot easier? I mean the combat stats, proficiencies, skills, saves, everything. Well, obviously anything is possible, is that a potentially worthwhile approach I guess is what I mean.
    Post edited by mf2112 on
  • Mr2150Mr2150 Member Posts: 1,170
    Most of the stats are available exactly like that - however there are some which are unfortunately not. From scouring the code it's quite easy to work out which ones are and which ones aren't...

    Take for example this code:

    text lua "t('AC_LABEL') .. ': ' .. characters[currentID].AC.current .. '\n' .. '\n' .. t('HP_LABEL') .. ': ' .. characters[currentID].HP.current .. '/' .. characters[currentID].HP.max .. '\n' .. '\n' .. t('THAC0_LABEL') .. ': ' .. displayLabelTHAC() .. '\n' .. '\n' .. t('DAMAGE_LABEL') .. ': ' .. displayLabelDamage() .. '\n' .. '\n' .. Infinity_FetchString(characters[currentID].proficiencies.numAttacks.strRef) .. ': ' .. characters[currentID].proficiencies.numAttacks.current .. '\n' .. '\n' .. t('SAVING_THROWS_LABEL') .. ': ' .. '' .. '\n' .. characters[currentID].proficiencies.savingThrows .. '\n' .. '\n' .. t('RESISTANCES_LABEL') .. ': ' .. '' .. '\n' .. characters[currentID].proficiencies.resistances"

    It produces the following 'text block' in game:



    Code like t('AC_LABEL') is a direct reference to a label name in the language file. characters[currentID].AC.current is the selected character's (referenced as currentID) current AC and so on... You can reference this pretty much anywhere quite easily and don't need any extra work to retrieve it. Unfortunately, the XP values are a little more complicated (and even more complicated if multi/dual class) hence @AncientCowboy and his excellent work above.
  • lroumenlroumen Member Posts: 2,508
    General question. Is it possible to import the 2da file with the tables rather than hard code the tables? Because then we can mod a lot better.
  • AncientCowboyAncientCowboy Member Posts: 199

    @Mr2150 - I've created 3 new functions that behave like getNextLevelXPDeltas but are specific to the three potential classes. Just add them to the end of LvlPgBar.lua (or whatever you named it :smile: ) and change your GetPercentage calls as appropriate.

    function getFirstLevelXPDeltas()
    	if (not KitStringToXPMap['Initialized']) then KitStringToXPMapInit() end
    
    	local currentlevelxp = getCurrentLevelXP(characters[currentID].classlevel.first.details)
    	return characters[currentID].classlevel.first.xp - currentlevelxp, 
    	       characters[currentID].classlevel.first.nextLvlXp - currentlevelxp
    end
    
    function getSecondLevelXPDeltas(showfull) -- For DualClass nil or false => Empty, Any other => Full  
    	if (not KitStringToXPMap['Initialized']) then KitStringToXPMapInit() end
    
    	if(not characters[currentID].classlevel.second) then  -- Fail safe
    		return characters[currentID].level.xp, characters[currentID].level.nextLvlXp
    	end
    	
    	local currentlevelxp = 0
    	local need
    	local have
    	if (characters[currentID].classlevel.second.active) then -- Multi-class
    		need = characters[currentID].classlevel.second.nextLvlXp
    		have = characters[currentID].classlevel.second.xp
    		if(KitStringToXPMap['Matchstring']) then
    			currentlevelxp = getCurrentLevelXP(characters[currentID].classlevel.second.details)
    		end
    	elseif(showfull) then -- Dual class full
    		need = characters[currentID].classlevel.second.xp
    		have = need
    	else                  -- Dual class empty
    		need = characters[currentID].level.nextLvlXp
    		have = 0
    	end
    	return have - currentlevelxp, need - currentlevelxp
    end
    
    function getThirdLevelXPDeltas()
    	if (not KitStringToXPMap['Initialized']) then KitStringToXPMapInit() end
    
    	if(not characters[currentID].classlevel.third) then
    		return characters[currentID].level.xp, characters[currentID].level.nextLvlXp
    	end
    	
    	local currentlevelxp = 0
    	if(KitStringToXPMap['Matchstring']) then
    		currentlevelxp = getCurrentLevelXP(characters[currentID].classlevel.third.details)
    	end
    	return characters[currentID].classlevel.third.xp - currentlevelxp, 
    	       characters[currentID].classlevel.third.nextLvlXp - currentlevelxp
    end
    

    I'll update the original post once I've checked out a couple of additional things. However, it will probably be after 2.2 drops so I can incorporate any 2.2 changes.

    The functions themselves - getFirstLevelXPDeltas,getSecondLevelXPDeltas, and getThirdLevelXPDeltas - have the same language specific fail-safe behavior as getNextLevelXPDeltas. In additon, getSecondLevelXPDeltas and getThirdLevelXPDeltas will return the non-delta next-level values if there is no second/third class. Thus, calls to them should be protected as you do in your 'enabled' code.

    To deal with dual-classed characters, getSecondLevelXPDeltas has an optional argument showfull. It's ignored for single/multi-class, but for dual-class characters it controls whether getSecondLevelXPDeltas should return values that will result in an empty or a full progress bar for the non-leveling class (which is always classlevel.second). If you want an empty progress bar, call it with no argument (nil in Lua terms) or false (not 'false'). If you want a full (but blinking - unless you know how to turn off the infernal blinking :smile:) bar, call it with true, 1, 0, 'Hello World', or anything other than false.

    Anyway, have fun!

    Mr2150mf2112
  • AncientCowboyAncientCowboy Member Posts: 199
    @mf2112 - @Mr2150 answered as well as I could. Most of the information is collected and formatted by the updateAttrTable function (near the beginning of ui.menu). It just takes a bit of chasing through it to find what you need. The difficulty, of course, is that the information is organized in a fashion that is best suited to the general layout of the current Character panel. If you want a very different layout, you'll pretty much have to get some information from here, some from there, some from elsewhere...

    @Iroumen - I feel your pain :smile: . Putting those tables together, even with the help of OpenOffice spreadsheet, was no fun. Having to change both xplist.2da and the tables in this code in order to change the leveling curve for a class (e.g. Druid) won't be fun either. For this particular mod/tweak however, I think the approach I'm going to take is to request an enhancement in the information provided in the characters[currentID].classlevel tables and eliminate the parsing and table stuff altogether. Then if you edit xplist.2da for example, the changed values should be automatically incorporated.
    Mr2150mf2112
  • Mr2150Mr2150 Member Posts: 1,170
    Excellent work... well done !! I shall be adding this for sure.
  • Mr2150Mr2150 Member Posts: 1,170
    WOW - you have been busy - the screens look amazing :) Great job!
    mf2112
  • AncientCowboyAncientCowboy Member Posts: 199
    Mr2150 said:

    WOW - you have been busy - the screens look amazing :) Great job!

    Thanks! It was fun :smile:
    Mr2150mf2112
  • BillyYankBillyYank Member Posts: 2,768
    edited May 2016
    Very nice. That dual-classing progress bar is incredibly innovative. I'm dual-classing in my current run, so I'll have to give that a try.
    mf2112
  • AncientCowboyAncientCowboy Member Posts: 199
    @BillyYank Thanks for the kind words. One of my goals when I decided I wanted separate bars for Multi/Dual classes was to figure out how to make Dual actually useful :smile:
    mf2112
  • Mr2150Mr2150 Member Posts: 1,170
    I fully implemented this now and I have to say it's great... I was a little shocked at first as I thought I had done something wrong as the numbers seemed huge, but no... that's the XP I really need to get to achieve the next level (because I am a FMT).

    It really is a great job :)


    AncientCowboyJuliusBorisov
  • AncientCowboyAncientCowboy Member Posts: 199
    @Mr2150 Thanks! Glad you like it. And yeah, the leveling gets real slow for an FMT. On the other hand, the flexibility it gives you in BGII makes it worth the wait...
    Mr2150mf2112
  • AncientCowboyAncientCowboy Member Posts: 199

    I've released a new version of the tweaks that have 2 major enhancements over the prior version. First, there is now a BG2EE/TOB version of the tweaks. Second, I've created a 'Mods Options' options setting menu for each version. You'll need to install the base version of the 'Mods Options' mod to make use of it (see the Mod Options mod thread for details). The 'Progress Bar Tweaks' option menus look like this:


    The updated zips are in the detailed description message above. The new zips contain a 'xxx_Installation.txt' file that contains complete installation instructions.

    Enjoy!

    JuliusBorisovmf2112
  • AncientCowboyAncientCowboy Member Posts: 199
    I've created a new version of Progress Bar Tweaks that incorporates several enhancements:
    • It installs via WeiDU, patching UI.MENU and copying files for you. No more editing!
    • As part of the installation, it extracts class and leveling information from XPLEVEL.2DA and SODCLTXT(SOD)/CLASTEXT(BGII).2DA and builds Lua code files that are used to generate the internal leveling table. Thus, if you've changed XPLEVEL.2DA either manually or via a mod, those changes will be automatically incorporated. If you change XPLEVEL.2DA after installing PB Tweaks, it's a simple matter of re-installing this mod via setup-ProgressBar.exe to incorporate the changes. Although I haven't tested it, this setup should also work with mods that add new class kits. This feature was added in response to a request by @Iroumen back in May.
    • It installs and runs with @Pecca s SoD GUI Overhaul (v2.06) and @Kerozevok s BG2EE GUI to BGEE mods (inspired by a comment by @subtledoctor in the BG2EE GUI discussion) - with some caveats that I'll discuss later.
    • Fixed a couple of minor bugs and added a minor enhancement to the ACuimenulib.tph WeiDU ui.menu parsing library - which is probably not interesting to anyone but me :smile:

    To install, first extract a copy of UI.MENU to your override directory (WeiDU isn't quite there yet), Then grab the appropriate zip file(s) from the original post above (yeah, I've re-arranged things). If you are running a generic BeamDog UI.MENU and you want to configure PB Tweaks via the Options menu, you'll want to install the Mods Options mod (if you haven't already) prior to installing this mod. The installation itself is the usual WeiDU process - put the zip contents in your installation directory, run setup-ProgressBar.exe (probably as Administrator), and answer the questions. If you've previously manually installed this mod - don't worry. Just install over it. The WeiDU script is smart enough to work around prior manual installations.

    There's a file named 'Installation.txt' in the ProgressBar directory within the zip that has full instructions and additonal information for those who aren't familar with WeiDU, for those who would rather configure PB Tweaks via Baldur.lua, and for those running one of the full UI.MENU GUIs I mentioned earlier.

    As for SoD GUI Overhaul and BG2EE GUI to BGEE users: First, the Mods Options mod is incompatible with both - at least for now. So you're stuck with manual configuration via Baldur.lua. The 'Installation.txt' file has all the info you'll need.

    In terms of functionality, SOD Overhaul has no general Report screen Progress Bar, so that part of the mod obviously doesn't apply - the installation fails it gracefully. The Large Portrait portion works fine. However, when you click in the small portrait/battle stats area the Proficiencies/Skills info is displayed in the inforation pane. If you would like to change this, instructions on how to do so is in 'Installation.txt'.

    For BG2EE GUI to BGEE, there is a progress bar and it is modded appropriately. The Large Portrait component also works. However, when you click in the small portrait/battle stats area, nothing useful is displayed in the info pane. This is because there is no definition for currentTab being set to 9. If this is a problem, once again 'Installation.txt' has the solution.

    If you have any difficulties, please let me know. Enjoy!

    Mr2150mf2112
  • Mr2150Mr2150 Member Posts: 1,170
    This really is fantastic. Great job @AncientCowboy !
    brusmf2112
  • ScrybeScrybe Member Posts: 13
    Just wanted to say; this looks really well done. Going to install it and give it a whorl later on this afternoon.

  • AncientCowboyAncientCowboy Member Posts: 199
    @Scrybe - Hope you enjoy it. Give me a shout if you have any difficulties.
  • AncientCowboyAncientCowboy Member Posts: 199

    I've posted above new versions of Progress Bar Tweaks. The main features are:

    1. The Progress Bar Options panel will now decrease/increase the color sliders by 1 slider (2 color) values when you click immediately to the left or right of the slider, respectively. The areas are 10 pixels wide and slightly overlap the sliders. Yes I did consider arrows/+- symbols - it made the GUI too 'busy' :smile: .
    2. If you install the newest version of Mods Options, it is now meaningful to install the Progress Bar Options on either the 'Dragonspear UI++' or the 'BG2EE GUI To BGEE' environments.
    3. I added code to the 'BGEE GUI to BGEE' installation that implements the Combat Stats functionality so that something meaningful is displayed when you click the lower portion of the alternate portrait display. I did NOT define a button for it or in any other way change the Character/Record screen to accommodate this code.

    If you're familiar with installing WeiDU mods, you'll find nothing surprising in the installation. If not, within the ProgressBar directory/folder you'll find a file named 'Installation.txt' that will walk you through the process. As before, you'll need to have a copy of UI.MENU in your override directory.

    Installation.txt also contains the Baldur.lua settings if you choose to manually configure the mod (rather than using Mod Options/Progress Bar Options); and it contains a section entitled 'Modding the Mod' that describes how to change what is displayed when you click on the top or bottom areas of the alternate portrait area.

    Enjoy - and give me a shout if you have any difficulties.

    mf2112
  • AncientCowboyAncientCowboy Member Posts: 199

    I've created a new version of this mod that provides the option for the 'alternate portrait display' to not show a small portrait and combat stats below the leveling bars; but rather a centered, medium-sized portrait - as below:


    The reason is two-fold: As @Mr2150 pointed out to me, on DragonSpear UI++ the information is redundant. It's all in the left-most pane of the display. I have also gathered from comments on this forum that some believe that the Record panel is not the correct place for combat information.

    The new code is part of EEUITweaks. And, as I don't want to have two different versions of the mod floating around, the zip in the OP has been removed. For those who prefer to configure the mod by editing Baldur.lua rather than using Mods Options; I will attach a zip of a text file documenting the settings to the original post.

    Enjoy!

    Mr2150
  • BillyYankBillyYank Member Posts: 2,768
    I had a weird thing happen with this mod.

    I installed EEUITweaks-1.3 on a heavily modded version of BG/SOD 2.3. Everything Installed successfully, but when I ran it, I got this message.


    The game ran fine, but the level bar doesn't show the progress color.


    I then installed the tweak pack on a clean install and everything worked OK. There was no error, and the progress bar showed correct colors.

    I looked at the properties of WX_PgBar.lua files in both installations and noticed they were different sizes. I copied the one from the clean install to the modded install and now it works fine.

    I'm attaching the two files as working.zip and broken.zip and also my WeiDU log in case you need it.
  • AncientCowboyAncientCowboy Member Posts: 199
    @BillyYank - Would you mind zipping SODCLTXT.2DA and XPLEVEL.2DA for me from the failing system? Looks like the code that generates WX_PgBar.lua is encountering something it is not expecting. Thanks.
  • BillyYankBillyYank Member Posts: 2,768
    Neither of those appear in the override of either install. I can extract them later if you want.
  • AncientCowboyAncientCowboy Member Posts: 199
    Hmm - that's interesting. How about clastext.2DA?
  • BillyYankBillyYank Member Posts: 2,768
    I'm at work now, I'll check when I get home.
  • AncientCowboyAncientCowboy Member Posts: 199
    I was able to reproduce the WX_PgBar.lua corruption and come up with a fix - at least for how I was corrupting it :smile: . Unzip the attached 'ProgressBars.tpa', and use it to replace the version in the EEUITweaks/include directory under your game install on the failing system. Re-install Progress Bars Tweaks - this hopefully will fix it.
    BillyYank
  • BillyYankBillyYank Member Posts: 2,768
    Yes, that works.

    Thank you.
  • AncientCowboyAncientCowboy Member Posts: 199
    You're welcome - and thanks for bringing the issue to my attention. One of your mods has likely buried a form of xplevel.tp2 in a biff (since it's not in the override folder as an individual file) - and it probably is based on the BG2 (all classes up to level 41) version. I made the WX_PgBar.lua writer code a little more 'open-minded' about the input file format :smile:.
    The fix will be included in the next EEUITweaks update.
Sign In or Register to comment.