Jump to content
Sign in to follow this  
khelban12

GemRB BG2 Weapon Slots and other questions

Recommended Posts

Greetings.

 

I gave gemrb (v0.8.1 and the git version as it is now) another try and i would like to ask some questions.

 

1) ToBEx has a feature "universal four weapon slots" that shows all four weapon slots in the inventory display and permits equipping all of them regardless of the class. Does gemrb support this feature ? Forgive me if this is already answered but i searched the wiki and forum and although i found the "concordance of features" and other threads, i couldn't find what ToBEx features are supported.

 

 

 

I tried to find the place where this is implemented and i saw that in Actor.cpp there is an "else" branch that disables the two slots for classes that shouldn't have them. I changed the code as the following patch shows and now it sort of works. The first time i open the inventory screen, only two slots are shown but when i pick any item and the reinit function runs then all four slots appear and can be equipped.

 

However, i am not familiar with the gemrb code so i do not know if this is the proper way to do it or even if it is already implemented and i missed it. :)

 

diff --git a/gemrb/core/Interface.cpp b/gemrb/core/Interface.cpp

index d708c78..d83a3ee 100644

--- a/gemrb/core/Interface.cpp

+++ b/gemrb/core/Interface.cpp

@@ -2382,6 +2382,7 @@ static const char *game_flags[GF_COUNT+1]={

         "SkipUpdateHack",     //74GF_SKIPUPDATE_HACK

         "MeleeHeaderUsesProjectile", //75GF_MELEEHEADER_USESPROJECTILE

         "ForceDialogPause",   //76GF_FORCE_DIALOGPAUSE

+        "UniversalWeaponSlots", //77 GF_UNIVERSAL_WEAPON_SLOTS

         NULL                  //for our own safety, this marks the end of the pole

 };

 

diff --git a/gemrb/core/Scriptable/Actor.cpp b/gemrb/core/Scriptable/Actor.cpp

index 3453003..e6564f3 100644

--- a/gemrb/core/Scriptable/Actor.cpp

+++ b/gemrb/core/Scriptable/Actor.cpp

@@ -5118,7 +5118,7 @@ void Actor::ReinitQuickSlots()

     //these are always present

     CheckWeaponQuickSlot(0);

     CheckWeaponQuickSlot(1);

-    if (version==22) {

+    if ((version==22) || (core->HasFeature(GF_UNIVERSAL_WEAPON_SLOTS))) {

         CheckWeaponQuickSlot(2);

         CheckWeaponQuickSlot(3);

     } else {

diff --git a/gemrb/docs/en/gemrb_ini.txt b/gemrb/docs/en/gemrb_ini.txt

index 2613833..0f426ee 100644

--- a/gemrb/docs/en/gemrb_ini.txt

+++ b/gemrb/docs/en/gemrb_ini.txt

@@ -570,6 +570,13 @@ If set to 1, the team always moves to the protagonist (first player).

 This option is 1 for original PST.

 

 

+UniversalWeaponSlots = <bool>

+- - - - - - - - - - - - -

+If set to 1, the inventory display will always support four weapon slots

+regardless of the class. This will only affect the inventory display

+and not the quick bar at the bottom of the screen.

+

+

 UpperButtonText = <bool>

 - - - - - - - - - - - - -

 Set to 1 if button labels should be converted to upper-case (e.g. BG2)

diff --git a/gemrb/includes/globals.h b/gemrb/includes/globals.h

index 2de02a2..e910e8f 100644

--- a/gemrb/includes/globals.h

+++ b/gemrb/includes/globals.h

@@ -164,9 +164,10 @@ namespace GemRB {

 #define  GF_SKIPUPDATE_HACK             74 // how, not bg2

 #define  GF_MELEEHEADER_USESPROJECTILE  75 // minimally bg2

 #define  GF_FORCE_DIALOGPAUSE           76 // iwd/how, not bg1, bg2 is special

+#define  GF_UNIVERSAL_WEAPON_SLOTS      77

 

 //update this or bad things can happen

-#define GF_COUNT 77

+#define GF_COUNT 78

 

 //the number of item usage fields (used in CREItem and STOItem)

 #define CHARGE_COUNTERS  3

diff --git a/gemrb/unhardcoded/bg2/gemrb.ini b/gemrb/unhardcoded/bg2/gemrb.ini

index a8e5965..855b69b 100644

--- a/gemrb/unhardcoded/bg2/gemrb.ini

+++ b/gemrb/unhardcoded/bg2/gemrb.ini

@@ -130,5 +130,6 @@ StartActive = 1

 StealIsAttack = 1

 StrrefSaveGame = 0

 TeamMovement = 0

+UniversalWeaponSlots = 1

 UpperButtonText = 1

 ZeroTimerIsValid = 0



 

 

 

2) When i save a game in gemrb, i cannot open it either from bgmain.exe (with wine + linux if it matters) or from shadowkeeper (invalid cre signature). I haven't changed the SaveAsOriginal variable so shouldn't the saves be compatible with the original game ?

 

3) Using the stealth button on a thief results in immediate hiding in shadows in the original game while in gemrb it takes a round before the thief hides. Is this normal ?

 

Thank you for your time.

Share this post


Link to post

1. You could achive it just by modding unhardcoded/qslots.2da (making sure the 3rd and 4th weapon slot ids are in the first two positions), but that would also affect the quickbar in the main game view. So your approach is good, but to make it always work, you also likely need to override QSlots[3] and QSlots[4] elsewhere.

 

2. They should be, but bugs creep up. The fact that SK doesn't like them makes troubleshooting much easier. CRE files are embedded in the GAM (embedded in the SAV). We don't do anything special with the signatures, so that's interesting. Maybe it got corrupted. SK does not display the invalid signature? Should be easier to debug from its source.

 

3. Modal actions are checked and applied each round (Actor::UpdateActorState) and the missing arbitrary start time is an oversight.

 

Patches like that are very welcome!

Share this post


Link to post

Thank you very much for the quick reply.

 

1. You could achive it just by modding unhardcoded/qslots.2da (making sure the 3rd and 4th weapon slot ids are in the first two positions), but that would also affect the quickbar in the main game view. So your approach is good, but to make it always work, you also likely need to override QSlots[3] and QSlots[4] elsewhere.

Do you think this is a "desired by many people" change so that it should warrant a new feature flag and ini variable (i do not known about gemrb but most projects are against adding feature flags without sufficient reason) ?

 

2. They should be, but bugs creep up. The fact that SK doesn't like them makes troubleshooting much easier. CRE files are embedded in the GAM (embedded in the SAV). We don't do anything special with the signatures, so that's interesting. Maybe it got corrupted. SK does not display the invalid signature? Should be easier to debug from its source.

I have two saves in Irenicus Dungeon. Both load fine in gemrb but do not in original engine. Shadowkeeper mentions "Error 1025: Missing CRE signature" and "Error 1056: The out of party character information does not follow the in-party data." respectively.

 

Interestingly enough, when i initially tested gemrb yesterday i had a fully modded game with 20-30 mods and the save game could be loaded in the original engine (but again didn't work in shadowkeeper).

 

Another thing i noticed is about scripting. The "Dungeon BeGone" mod creates a character in the Irenicus Dungeon that allows you to skip the whole dungeon. The following script is inserted in baldur.bcs.

 

IF
  AreaCheck("AR0602")
  Global("MoveScreen","AR0602",1)
  Global("FWWheresJassy","GLOBAL",0)
THEN
  RESPONSE #100
    SetGlobal("FWWheresJassy","GLOBAL",1)
    CreateCreature("FWJASSY",[3741.2936],3)
END
So when you are in irenicus dungeon & the character isn't spawned & Imoen has said her dialog -> Spawn the character. Out of 15 times i load the save, only 2 times the character is spawned and the weird is that the two germb.log files do not have any differences that suggest what went wrong.

Share this post


Link to post

1. Ideally this would be handled on the guiscript side, where we're also have a infantile system for toggling enhancements. The feature is mostly about the gui anyway, but the core is in the way, as you're also changing the inventory. So no, it can't really be nicely decoupled and a GF is needed. As far as I'm concerned, this bit here would not constitute feature creep (and the version hack could be removed). It just needs the final polishing (which may make it too ugly, but I can't tell yet).

 

2. Chateau Irenicus is too crowded to be a good starting test, but a fresh run in the first tob area is ideal. Start in original, save, quit, load in gemrb, save into another slot, quit, try to load in sk/original (just to confirm the problem). Then you could unpack both saves and inspect the differences, which there will be for sure (gametime, garbage fields). There's plenty of objects in the save files, so it's easiest to compare them with ielister (ie_shell repo on our sourceforge page), which makes a plaintext dump. If you combine that with git and our admin/enable-ie-git-diff, by creating a repo with the first save's contents and then dumping the other one's on top, you can actually use git diff to see the changes. Long process either way. I'll try with iwd2 tomorrow, it's one of the things that still runs in wine for me.

 

4. DBG would be a trigger problem, though the inconsistency makes me suspicious. You're loading the initial autosave or what?

 

I've added a tobex-map wiki page:

http://www.gemrb.org/wiki/doku.php?id=engine:tobex (still working on it, will require some digging)

Share this post


Link to post

Tried the gam diff in iwd1 starting area. Could still load it in the original after a resave, but it is a good baseline. If you'll be trying with bg2, expect case differences, null padding of fields and some reordering (with offset fields updated to match). Some fields will have different values and that's where the problems should lie. Note that some are inconsequential, since they are rewritten at runtime (ie the local/global id). In this case, only the two unknowns could be problematic. Looking for the signature field would be trivial though.

 

http://sprunge.us/SYQB?diff

 

EDIT: one unknown is truly unknown (likely unused), while the other has just been made consistent.

 

Also forgot I made a special iediff wrapper (also in the ie_shell repo), so there's no need for involving git for you.

Edited by lynx
squashing

Share this post


Link to post

2. Chateau Irenicus is too crowded to be a good starting test, but a fresh run in the first tob area is ideal. Start in original, save, quit, load in gemrb, save into another slot, quit, try to load in sk/original (just to confirm the problem). Then you could unpack both saves and inspect the differences, which there will be for sure (gametime, garbage fields). There's plenty of objects in the save files, so it's easiest to compare them with ielister (ie_shell repo on our sourceforge page), which makes a plaintext dump. If you combine that with git and our admin/enable-ie-git-diff, by creating a repo with the first save's contents and then dumping the other one's on top, you can actually use git diff to see the changes. Long process either way. I'll try with iwd2 tomorrow, it's one of the things that still runs in wine for me.

Tried the gam diff in iwd1 starting area. Could still load it in the original after a resave, but it is a good baseline. If you'll be trying with bg2, expect case differences, null padding of fields and some reordering (with offset fields updated to match). Some fields will have different values and that's where the problems should lie. Note that some are inconsequential, since they are rewritten at runtime (ie the local/global id). In this case, only the two unknowns could be problematic. Looking for the signature field would be trivial though.

 

http://sprunge.us/SYQB?diff

 

EDIT: one unknown is truly unknown (likely unused), while the other has just been made consistent.

 

Also forgot I made a special iediff wrapper (also in the ie_shell repo), so there's no need for involving git for you.

Again thanks for you help.

 

I used ToB and the gemrb save can be loaded in the original engine. I ran ielister for both saves and indeed there are many case differences, unknown field differences, creature field differences (original save has "*obthief" for player character while gemrb save is empty). I hexedit-ed the gemrb save trying to transplant the different fields but all of the "header" fields do not make any difference. After the game header there are many differences due to different ordering of effects and stuff so maybe there lies the fault. I will try to transplant small chunks of changes to see if i can get it to work.

 

Trying to create the saves i found some other issues too.

 

1) GemRB could not find the ToB saves at all and showed me an empty load screen (SoA saves are found correctly). I ran strace and saw that it tried to access the mpsave folder instead of the save one.

 

Is this supposed to happen ?

 

I use the old CD/DVD version of BG2 (the one that installs by default in program files\black isle\bgii - soa) and it always saves files in save directory for both SoA and ToB but i don't know if GOG version behaves differently. I had the impression that mpsave folder is for "multiplayer mode" save but i do not know for sure.

 

I saw the this behavior was introduced in the following commit

commit b198d67b87795910ece74f33a8d63979724af722
Author:     Tom Prince <tom.prince@ualberta.net>
AuthorDate: Fri Dec 11 17:44:47 2009 -0500
Commit:     Willem Jan Palenstijn <wjpalenstijn@users.sourceforge.net>
CommitDate: Sat Mar 27 14:53:12 2010 +0100

    Make SaveGameIterator key save directory off SaveDir instead of PlayMode.
Anyway i did the the following change

diff --git a/gemrb/GUIScripts/bg2/Start2.py b/gemrb/GUIScripts/bg2/Start2.py
index 4310191..1abc5bd 100644
--- a/gemrb/GUIScripts/bg2/Start2.py
+++ b/gemrb/GUIScripts/bg2/Start2.py
@@ -197,7 +197,7 @@ def LoadSingle():
                TutorialWindow.Unload()
        if GemRB.GetVar ("oldgame") == 0:
                GemRB.SetVar ("PlayMode", 2)
-               GemRB.SetVar ("SaveDir", 1)
+               GemRB.SetVar ("SaveDir", 0)
        else:
                GemRB.SetVar ("PlayMode", 0)
                GemRB.SetVar ("SaveDir", 0)
@@ -214,7 +214,7 @@ def NewSingle():
                TutorialWindow.Unload()
        if GemRB.GetVar ("oldgame") == 0:
                GemRB.SetVar ("PlayMode", 2)
-               GemRB.SetVar ("SaveDir", 1)
+               GemRB.SetVar ("SaveDir", 0)
        else:
                GemRB.SetVar ("PlayMode", 0)
                GemRB.SetVar ("SaveDir", 0)
and now the saves were correctly loaded.

 

At this point GemRB correctly shows SoA saves only in SoA loading screen and ToB saves only in ToB loading screen. However, when i tried to load the gemrb save from the original game i couldn't find it in the ToB screen. The save file was shown in the SoA loading screen and if clicked it loaded fine and everything worked perfectly as if loading from ToB.

 

Running strace again showed that the original engine searched for the file "tobtemp.bmp" to exist in the save directory. Creating an empty file named tobtemp.bmp resulted in the save correctly appearing in the ToB screen.

 

2) Due to ease / laziness, i didn't generate a new character every time i tested a save but used the pre-made character files instead. I noticed that while i used "TOBTHIEF" character in the original save, i couldn't find it in GemRB character generation.

 

Initially i thought the GetCharacters function was faulty but after testing i noticed that the AppendText function that is in turn called behaved correctly and "pushed_back" every character file. After messing with functions for some time to see which one did not behave correctly, i found the DrawInternal function.

 

size_t linesize = lines.size() - 1; // -1 because 0 counts
At some point in the function there is the above line. It subtracts 1 because C indexing starts at 0 so all is ok.

 

Forward some lines and there are the following two for statements that use "i < linesize". Since the C indexing is taken care of in the linesize variable, shouldn't these run up to _including_ linesize ?

 

After making the following change and testing with different number of character files, i could always see every character.

 

diff --git a/gemrb/core/GUI/TextArea.cpp b/gemrb/core/GUI/TextArea.cpp
index 116e377..767742a 100644
--- a/gemrb/core/GUI/TextArea.cpp
+++ b/gemrb/core/GUI/TextArea.cpp
@@ -204,7 +204,7 @@ void TextArea::DrawInternal(Region& clip)
        int sr = startrow;
        unsigned int i;
        int yl;
-       for (i = 0; i < linesize; i++) {
+       for (i = 0; i <= linesize; i++) {
                if (rc + lrows[i] <= sr) {
                        rc += lrows[i];
                        continue;
@@ -225,7 +225,7 @@ void TextArea::DrawInternal(Region& clip)
                clip.h-=yl;
                break;
        }
-       for (i++; i < linesize; i++) {
+       for (i++; i <= linesize; i++) {
                Palette* pal = NULL;
                if (seltext == (int) i)
                        pal = selected;
Edited by khelban12

Share this post


Link to post

If reloading/SKing works, wasn't the exercise a bit pointless?

 

mpsave == mission pack save. I don't know how it was elsewhere, but it's pretty nifty that the dirs are separate (and iwd uses only mpsave). Your change is fine, but just lacks a migration path — I have everything tob in mpsave, so now the list is empty. Start.py already has the os module loaded (on sanely packaged pythons), so that's where the saves could be checked and moved (plus tobtemp.bmp placeholders added) on startup. Interestingly enough, I don't see that file name in the strings output over the original binary. No original tob saves to check either, but it does sound like DoSave will need another hack.

 

Textarea: nice! This whole part has been rewritten, but not yet merged, as the work is not complete yet (but >200 commits already). Do you have an email and preffered alias under which to be credited?

Share this post


Link to post

If reloading/SKing works, wasn't the exercise a bit pointless?

If you mean about ielister, only loading the tob save in original engine works. SK continues to not work that is why i am doing the exercise.

 

mpsave == mission pack save. I don't know how it was elsewhere, but it's pretty nifty that the dirs are separate (and iwd uses only mpsave). Your change is fine, but just lacks a migration path I have everything tob in mpsave, so now the list is empty. Start.py already has the os module loaded (on sanely packaged pythons), so that's where the saves could be checked and moved (plus tobtemp.bmp placeholders added) on startup.

I mentioned what i did to have the saves appear not that it is the correct thing to do. Maybe the current gemrb behavior is the correct one and mpsave should be used. Maybe someone else here runs bg2 both on gemrb and original (preferably the GOG version) and can tell us his experience.

 

Interestingly enough, I don't see that file name in the strings output over the original binary. No original tob saves to check either, but it does sound like DoSave will need another hack.

% ls -al bgmain.exe
-rwxr-xr-x 1 user users 7839790 Αύγ   1 16:59 bgmain.exe*

% md5sum bgmain.exe
a70bb3802dff34fe2ab9338c7de0cfd9  bgmain.exe    (ToB v26498 bgmain.exe with 5-6 bytes modified for nocd)

% strings bgmain.exe |grep -i tobt
TOBTEMP
\TOBTEMP.bmp

Textarea: nice! This whole part has been rewritten, but not yet merged, as the work is not complete yet (but >200 commits already).

Ah nice. I didn't know that. I browsed the master branch but forgot to check for feature branches.

 

Do you have an email and preffered alias under which to be credited?

As long as i helped and didn't bother you with my long posts i am happy. I don't need to be credited (i made 5 one-line changes after all).

Share this post


Link to post
bg2 0 $ strings bgmain.exe |grep -i tobt

bg2 1 $

And yeah, 1 is the return value for not found. This is an ancient cd install though and I see the strings two other binaries (one should be gog too). Must be an ancient error of mine. Cool.

 

Every effort counts and should be credited, but if you don't want to share an email address, I'll use an example.com.

Share this post


Link to post

I found at last the problem with ShadowKeeper. It is the ordering as i thought.

 

The original engine saves CRE files as Spells -> Item Slots -> Inventory -> Effects. GemRB on the other hand uses a different order: Spells -> Effects -> Inventory -> Item Slots.

 

I changed CREImporter.cpp to produce the original format and voila the save can be opened in Shadow Keeper.

 

IMHO since the files contain all these "offset" fields there is no order set in stone and so the saves produced by GemRB are correct (which is strengthened by the fact that gemrb saves can be loaded in the original engine). However this different ordering makes shadow keeper barf.

Share this post


Link to post

Do you perchance still have a diff of your changes?

Share this post


Link to post

Do you perchance still have a diff of your changes?

Do you mean the reordering of the save files ? If yes, i have the changes.

 

 

diff --git a/gemrb/plugins/CREImporter/CREImporter.cpp b/gemrb/plugins/CREImporter/CREImporter.cpp
index 105d746..dff9575 100644
--- a/gemrb/plugins/CREImporter/CREImporter.cpp
+++ b/gemrb/plugins/CREImporter/CREImporter.cpp
@@ -2268,20 +2268,10 @@ int CREImporter::GetStoredFileSize(Actor *actor)
 		MemorizedSpellsCount = actor->spellbook.GetTotalMemorizedSpellsCount();
 		headersize += MemorizedSpellsCount * 12;
 	}
-	EffectsOffset = headersize;
+	ItemSlotsOffset = headersize;
 
-	//adding effects
-	EffectsCount = actor->fxqueue.GetSavedEffectsCount();
-	VariablesCount = actor->locals->GetCount();
-	if (VariablesCount) {
-		TotSCEFF=1;
-	}
-	if (TotSCEFF) {
-		headersize += (VariablesCount + EffectsCount) * 264;
-	} else {
-		//if there are variables, then TotSCEFF is set
-		headersize += EffectsCount * 48;
-	}
+	//adding itemslot table size and equipped slot fields
+	headersize += (Inventory_Size) * sizeof(ieWord) + sizeof(ieWord) * 2;
 	ItemsOffset = headersize;
 
 	//counting items (calculating item storage)
@@ -2294,10 +2284,22 @@ int CREImporter::GetStoredFileSize(Actor *actor)
 		}
 	}
 	headersize += ItemsCount * 20;
-	ItemSlotsOffset = headersize;
 
-	//adding itemslot table size and equipped slot fields
-	return headersize + (Inventory_Size)*sizeof(ieWord)+sizeof(ieWord)*2;
+	EffectsOffset = headersize;
+	//adding effects
+	EffectsCount = actor->fxqueue.GetSavedEffectsCount();
+	VariablesCount = actor->locals->GetCount();
+	if (VariablesCount) {
+		TotSCEFF=1;
+	}
+	if (TotSCEFF) {
+		headersize += (VariablesCount + EffectsCount) * 264;
+	} else {
+		//if there are variables, then TotSCEFF is set
+		headersize += EffectsCount * 48;
+	}
+
+	return headersize;
 }
 
 int CREImporter::PutInventory(DataStream *stream, Actor *actor, unsigned int size)
@@ -2316,6 +2318,21 @@ int CREImporter::PutInventory(DataStream *stream, Actor *actor, unsigned int siz
 		//ignore first element, getinventorysize makes space for fist
 		unsigned int j = core->QuerySlot(i+1);
 		CREItem *it = actor->inventory.GetSlotItem( j );
+		if (it) {
+			indices[i] = ItemCount++;
+		}
+		stream->WriteWord( indices+i);
+	}
+	free(indices);
+	tmpWord = (ieWord) actor->inventory.GetEquipped();
+	stream->WriteWord( &tmpWord);
+	tmpWord = (ieWord) actor->inventory.GetEquippedHeader();
+	stream->WriteWord( &tmpWord);
+
+	for (i=0;i<size;i++) {
+		//ignore first element, getinventorysize makes space for fist
+		unsigned int j = core->QuerySlot(i+1);
+		CREItem *it = actor->inventory.GetSlotItem( j );
 		if (!it) {
 			continue;
 		}
@@ -2334,16 +2351,7 @@ int CREImporter::PutInventory(DataStream *stream, Actor *actor, unsigned int siz
 			}
 		}
 		stream->WriteDword( &tmpDword);
-		indices[i] = ItemCount++;
-	}
-	for (i=0;i<size;i++) {
-		stream->WriteWord( indices+i);
 	}
-	tmpWord = (ieWord) actor->inventory.GetEquipped();
-	stream->WriteWord( &tmpWord);
-	tmpWord = (ieWord) actor->inventory.GetEquippedHeader();
-	stream->WriteWord( &tmpWord);
-	free(indices);
 	return 0;
 }
 
@@ -3213,6 +3221,13 @@ int CREImporter::PutActor(DataStream *stream, Actor *actor, bool chr)
 		}
 	}
 
+	//items and inventory slots
+	assert(stream->GetPos() == CREOffset+ItemSlotsOffset);
+	ret = PutInventory( stream, actor, Inventory_Size);
+	if (ret) {
+		return ret;
+	}
+
 	assert(stream->GetPos() == CREOffset+EffectsOffset);
 	ret = PutEffects(stream, actor);
 	if (ret) {
@@ -3224,12 +3239,6 @@ int CREImporter::PutActor(DataStream *stream, Actor *actor, bool chr)
 		return ret;
 	}
 
-	//items and inventory slots
-	assert(stream->GetPos() == CREOffset+ItemsOffset);
-	ret = PutInventory( stream, actor, Inventory_Size);
-	if (ret) {
-		return ret;
-	}
 	return 0;
 }
 

 

 

I rebased against the current master (v0.8.1-92-ge9a6022) and compiled it to test it again. I created one save with just the current master and one with the patch applied. Both can be opened in original BG2 and gemrb. Shadowkeeper can open the reordered save but not the first save. The patch seems to work fine but i have only tested it on BG2.

 

If you want, i can break it in small commits and explain in the commit msg why i did the change.

Edited by khelban12

Share this post


Link to post

Hello again.

 

I have some more questions.

 

1) unhardcoded/bg2/skills.2da gives 40 / 25 skill points in First Level / Other levels respectively for every thief kit except Assassin and Bounty Hunter. Assassin gets 15 / 15 and Bounty Hunter gets 20 / 20. Is this supposed to happen ?

 

Creating an Elf Assassin / BH in gemrb gives me 120 / 160 skills points to allocate during creation. Using the same stats in original game gives me 145 / 180 skill points which gives me the impression that original game gives 40 skill points to all thief kits at first level.

 

2) During character creation, all skill points start as 0 where in original engine they contain the race and dexterity bonus. I did a mini search and noticed that LUSkillsSelection.py uses the modified skill and not the base one so it is correct, but at that point during character creation i don't think that stats contain any values yet. I tried to find the function that sets the stat values and insert it in LUSkillSelection.py. If i read the code correctly, it is the RefreshPCStats function but is this exposed to python ? Anyway, this is a cosmetic issue.

 

3)

3) Using the stealth button on a thief results in immediate hiding in shadows in the original game while in gemrb it takes a round before the thief hides. Is this normal ?

3. Modal actions are checked and applied each round (Actor::UpdateActorState) and the missing arbitrary start time is an oversight.

 

Patches like that are very welcome!

I solved it locally by adding a IsHidden variable to the Actor structure. If it has value of 0 then the character hides immediately. After that and until we unhide, the original behavior takes over and the code is only run at the start of the round. It worked fine but it is pretty lame way to do it.

 

Is there a proper way to differentiate between first time entering shadows and subsequent ones ?

 

I am not familiar with the code so i am messing here and there in the dark, that is why i ask so many questions. If i am bothering you, feel free to tell me and i will stop.

 

Thank you for your time.

Share this post


Link to post
Is there a proper way to differentiate between first time entering shadows and subsequent ones?

From what you describe, it sounds like the button callback for the stealth button needs to do something to immediately run the hide in shadows action, instead of simply setting the flag (this is a guess, I havent looked at implementation). that callback would only happen on the "first time".

 

Edited by SyntaxError

Share this post


Link to post
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...