Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - lixiss

Pages: [1]
Modifications / [Technique] Minor Monster Mutators
« on: 18 December 2020, 22:57:59 »

"Monster Mutators" is some effect applied to monster in game. Generally this term used in GD in challenge areas, and mutator is just some effect (you can think about like prefix or affix) applied to monster or player. Generally same things exist in TQ/Tartarus, called by enemy / player buffs (and done as passive skills).

"Minor" or "Personal" Monster Mutator - is similar concept, but it is not related to challenge areas at all. There is about to give any monster some minor bonuses randomly. For self, I'm mostly interested to play with health modifiers to mimic HD rolls.

So, what is possible to use to implement this? If you familiar with BG internals, your answer should be immediate - RING! (Because in BG non-droppable rings are often used to give monsters right capabilities / resist / etc.)


1. I'm generated 30 amulets each with steppy health modifier progression: from -50% health modifier up-to +85% health modifier.

2. Generated loot table with this items.

3. Assign this loot table to monster's equipment slot (Neck) for every monster. (Surely this is done programmatically.)  (100% chance to equip)

Result: every monster in game has different HP even if you face multiple same monsters (same level / same record).

On top of basic item parameters surely there is possible to add prefix/affix and roll it from own tables with additional mutators you like.

Technical notes:

1. Items has no mesh, so they invisible. (May be have sense define "empty" mesh instead, because I believe engine complain about missed mesh in internal logs.)

2. Items can't be normally picked up, so this is doesn't changes normal play behavior. [cannotPickUp=true]

3. I'm use "Neck" slot in monsters because it is absolutely not used in game (it even doesn't defined in templates). In fact, monsters has Neck slot. Use it if you need. :)

4. In TQAE there is only single monster (Toxeus) who has chance to equip 2 rings simultaneously. So, actually, there is possible add another mutator item for monsters without drawbacks. [I believe game don't allow equip items where chance to equip is 0 under any case. Many monsters has item table for Finger2 but 0 chance to equip, however, I'm doesn't know if this chance can be adjusted, and think what there is "copy paste"]

5. Base item properties get "jitted" (randomized), looks like by 20% (e.g. +80% health modifier actually rolls between: +64..96%, while +10% HP rolls only in 8..12 range). And this may work... not like expected (because we already "roll" a +80% modifier base item, but may get much smaller value. This becomes especially important if you want create non-equally weighted loot table -> there is just will no have any sense in the end).

To counter this: instead of base item properties, there is possible to use affixes (so need 1 item and 30 affixes). [For LootRandomizers there is possible to adjust jitter's power]. Surely you still can create more base items with properties which you want roll, and on top of this always apply affix (health in my case).

6. Never use / equip > -100% health for monsters or player. Especially for player, otherwise it will immediate die. Ressurect and immediately die.


I'm prepared sample modification (custom map), so if some one want, it can try how it work in action.

* there is -50%..+85% health modifiers: this numbers most likely good for me, but i'm doesn't sure what they are good in general for standard game. Surely, they can be adjusted.

You can download from

Normal Version: Archive Glacie Atlas 0.1-1.7z is version which will not allow pickup "monster mutator" items, so you never will see what stats game rolled.

Development: Glacie Atlas 0.1-1-development.7z - same as above, but makes this items pickable by player, so you can see which actual stats item have and useful for testing (this items are of Broken quality, doesn't need to say what there is not intended to equip them).

Modifications / Glacie 0.1.0: library for manipulation game files
« on: 18 August 2020, 14:36:23 »

I'm just published sources of library at github: glacie and glacie-tools. Library available as packages at However it currently miss any readmes, but it was long night... so i'm currently shortly describe here.

So, what is about? It is about helping library for "procedural" mod development. I'm get messed with this .dbrs in past, because I'm want modify few fields in some record, but should import full record instead. This forces to write changes aside. Or another case: applying same expression over different equation files is kind of stupid work (and need templating or apply manually). Or another case: you can't simple write something for try, and then enable/disable feature and rebuild mod (what if feature affect all monsters?). Someone probably can remember mine very dirty tool glacie-checkdb (which i'm think doesn't do job right actually), which work very slow, because working over flat .dbr files is not fine, and it rises lot of issues. So, I'm hold general idea for library lot of time, but hit only recently.

Library should be considered as preview, and has some things not completed. However it already can handle some work (unfortunately lot less than i'm want...).

It splitted by some components (and packages):

- Glacie.Data.Arz - expose ArzDatabase, ArzRecord and ArzField, as well ArzReader and ArzWriter.
   ArzDatabase represents content of any given single ARZ file. Database generally can be treated as collection of named records, while record can be treated as collection of fields. This focuses on exact ARZ representation, it doesn't support templates (and never will do), it doesn't care about case-insensitive record lookups or so, it doesn't validate your edits. It just provides access to data in file as-is, and surely allow modify data (add/remove records, add/remove/set field values). API is not final, and can be changed in future.

  So, code which open database, turn all items into rare (so they can be enchanted) can looks something like:
Code: [Select]
            using var database = ArzDatabase.Open("path/to/database.arz");
            foreach (var record in database.GetAll())
                if (record.TryGet("itemClassification", out var field))
                    var value = field.Get<string>();

                    if (value == "Epic" || value == "Legendary")
                        record["itemClassification"] = "Rare";
                        record["--gx-itemClassification"] = value; // keep original value for later use
            ArzWriter.Write("out.arz", database);

   I'm should add more examples later, but i hope anyone got idea.

   ArzDatabase has direct support for TQ/IT, TQ/AE and GD files (yes, there is 3 incompatible file formats with minor variations). File format inferred from file, so you not need specify it (but can).

   There is exist limited multithreading support: if reader read data in "full" mode (immediately decompress data), - then it might be done concurrently, making this step bit faster. Reader also implements "raw" mode, where data completely reads but not decompressed, and "lazy" mode when data doesn't read at all, except "headers", but in this mode, records will be readed as you access to them. There is exist different job loads, where different modes more profitable than others (if you plan modify 90% of records, full will be best, but if you touch only few records directly AND want save only changes (e.g. custom map mod) - lazy mode will be better.

   For writer, there is also exist multithreading support: compression done in concurrently, so full recompression even at highest levels is not fearsome. (multithreading is optional, - when it is enabled - writer result is not reproductible, because final order of records in file are effectively race, also this has effect on internal encoder state so you might get different output file size when write same file). Writer able to write only changes or write everything (so you can grab game's database.arz, and write only changes for custom map or write back full content for "database replacement mod").

- Glacie.Data.Compression compression... huh. TQ/IT and TQ/AE uses ZLIB compression, while GD uses LZ4. This package offers two ZLIB implementations: based on .NET DeflateStream (which are sucky for ARZ), and when available, uses libdeflate which offers better performance, and higher compression ratio with more compression levels. However libdeflate in home repository offers binaries only for windows, so it available only on windows. (I'm not build it for self, and while whole library should work on other OSes too, i'm doesn't care about, and currently doesn't see reason to do.)

- Glacie.All - just metapackage which references everything.

- Glacie - soul of project, but currently not usable (as you can't do many things and can't save results).

This gives another look on same what ArzDatabase do, but eventually will provide more services. At least this provide

Code: [Select]
            using var context = Context.Create(c =>
                c.Source(s => s.Path("./test-data/gd-"));
                c.Source(s => s.Path("./test-data/gd-"));
                c.Source(s => s.Path("./test-data/gd-"));
                c.Target(t => t.Path("./out"));

            // do something with context.Database
            var record = context.Database[@"records\xpack\game\gameengine.dbr"]; // Will throw exception, because GD has no this record.

GDX1 and GDX2 act like custom maps in TQ, effectively shadow records, but unlike IT/AE they release expansions as internal mods, rather than having big single database. This already work (record shadowing and record importing).

Generally that's all what done.

Features to future:
- Support ARC files.
- Support Templates.
- Support Text resources.
- Support reading/writing from/to DBR sets.
- Typed access to records.

I'm will delay with simple samples, because... well, they will not look as they should without having completed features.

Just now you already can do something like:

Code: [Select]
            var rGameEngine = database[@"records\xpack\game\gameengine.dbr"];
            rGameEngine["potionStackLimit"] = 100;
            rGameEngine["scrollStackLimit"] = 100;

And, there is not what i'm want! This is weak code. You can assign strings, float (real) numbers, boolean for fields, nothing stop you. And there is problem: no one know how game engine will answer, so it is not desired. This is why i'm greedy for future features, and want typed access.

However, in glacie-tools releases i'm put one tool (you need install latest .NET Core 3.1 to run, i'm doesn't use self-contained deployment to avoid too big sizes, it is easier install and try). So, this repository now hold simple tool which at this moment act as show case. :)


Modders probably already noticed, what record names stored are in lower case, but references to .dbr files (in fields) preserve original casing. And ARZ file store them separately for sure, because this strings naturally different. This turns makes what excess number of strings are stored, making file bigger. This tool remap every such string to respective (lower) casing, and write new arz file with rebuilding new string table / reencode every record, so every unused string disappear.

Let's look on results over some files:

Code: [Select]

> gx-arz-optimizer.exe --target=gx-opt-tqae-2.9.arz .\glacie-test-suite\arz\tqae-2.9\database\database.arz

[ INFO ] Reading: .\glacie-test-suite\arz\tqae-2.9\database\database.arz
[ INFO ] Done In: 424ms
[ INFO ] Optimizing...
[ INFO ] Optimization Result:
  Completed In: 1,560ms
  # of Remapped Strings: 29192
  Estimated Size Reduction: 1875697 bytes
  Estimated File Size: 52650726 (96.6%)
[ INFO ] Writing To: gx-opt-tqae-2.9.arz
[ INFO ] Compression Level: 12
[ INFO ] Written In: 5,740ms
[ INFO ] Source File Length: 54526423
[ INFO ] Target File Length: 51245482 (94.0%)

> gx-arz-optimizer.exe --target=gx-opt-sv-aera-1.7.arz .\glacie-test-suite\arz\sv-aera-1.7\database\database.arz

[ INFO ] Reading: .\glacie-test-suite\arz\sv-aera-1.7\database\database.arz
[ INFO ] Done In: 539ms
[ INFO ] Optimizing...
[ INFO ] Optimization Result:
  Completed In: 2,198ms
  # of Remapped Strings: 40451
  Estimated Size Reduction: 2721844 bytes
  Estimated File Size: 74895993 (96.5%)
[ INFO ] Writing To: gx-opt-sv-aera-1.7.arz
[ INFO ] Compression Level: 12
[ INFO ] Written In: 8,064ms
[ INFO ] Source File Length: 77617837
[ INFO ] Target File Length: 73906007 (95.2%)

> gx-arz-optimizer.exe --compression-level=9 --target=gx-opt-gd.arz .\glacie-test-suite\arz\gd-\database\database.arz

[ INFO ] Reading: .\glacie-test-suite\arz\gd-\database\database.arz
[ INFO ] Done In: 282ms
[ INFO ] Optimizing...
[ INFO ] Optimization Result:
  Completed In: 876ms
  # of Remapped Strings: 0
  Estimated Size Reduction: 0 bytes
  Estimated File Size: 56402016 (100.0%)
[ INFO ] Writing To: gx-opt-gd.arz
[ INFO ] Compression Level: 9
[ INFO ] Written In: 2,193ms
[ INFO ] Source File Length: 56402016
[ INFO ] Target File Length: 47038301 (83.4%)

You can see, what GD already has this kind of optimization, while TQ win few MiBs. :) Funny, what GD compressed so loosy, because even at relatively small compression levels it is easy to win 10-15%. :) You can see also what just reencoding file (recompressing) it, gives smaller file.

I'm even quick-test optimized version in SV-AERA, seems like run fine (however doesn't played too much). (It's funny what over five minutes test, i meet hero and he drop soul... rng never drop when you look for, and gives for free when you don't care :) ).

That's all. I'm will be glad to any feedback.

PS: I'm put this post into wrong section. Sorry.


I'm trying to adjust maxPlayerLevel (in playerlevels.dbr) file. Other file values are really used, so this is right file, but regardless to maxPlayerLevel value it caps at level 85. I'm use custom-non bouncing mod without world (so default is used) if it matters.

PS: And second unrelated question, may be some one know... i'm use TQ AE 2.9 nowadays, and noticed what it no more write into log anything (log.xml/.html files), it only creates them, but they keep only header, without actual content (instead of showing errors, which are present even in unmodded database). It was very handy read for errors, when something wrong, and TQ 2.7 and 2.8 do it without any additional work (but lost older versions with mine HDD, so doesn't have them just now...).

Pages: [1]

SimplePortal 2.3.7 © 2008-2022, SimplePortal