Discrepancies with messages reflecting a shop's quality

Post here if you need help getting started with Daggerfall Unity or just want to clarify a potential bug. Questions about playing or modding classic Daggerfall should be posted to Community.
Post Reply
PLRDLF
Posts: 7
Joined: Thu May 11, 2023 8:17 pm

Discrepancies with messages reflecting a shop's quality

Post by PLRDLF »

I've been using Donald Tipton's ATLAS tool for ages in classic Daggerfall for mapping towns in advance (which town has a specific guild/temple, which town has low-level shops for selling goods, etc.), and since Daggerfall Unity uses the same game data as classic Daggerfall, I've been using the ATLAS tool for the same purpose now.
However, over the years, I've been noticing some discrepancies between the tool's output and the messages that are displayed when entering shops. These discrepancies can also be found in Daggerfall Unity, here is an example:

The city of Chesterbeth in Ykalon has two alchemists located at the local market. According to the ATLAS tool the southern alchemist (Chesterbeth's Best Potherbs) is a class 1 shop whereas the north-eastern alchemist (Chesterbeth's Herbs) is a class 2 shop. When entering either of both shops, I get an identical message typical for a class 2 shop ("The shop is laid out in a practical and straightforward manner. All the items seem to be of adequate construction."). However when selling exactly the same goods, the southern alchemist gives me indeed a better price compared to the other alchemist. So in the end, the ATLAS tool's data is more accurate and the southern alchemist is a class 1 shop and not a class 2 shop as the game message may imply.

This is just one example, and as already written, I've encountered these discrepancies numerous times in classic Daggerfall and currently using Dagerfall Unity. I just wanted to mention this, so maybe someone can look into this and maybe fix this issue which was carried over from classic Daggerfall.

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: Discrepancies with messages reflecting a shop's quality

Post by Interkarma »

There are 5 unique messages for shop quality found in TEXT.RSC IDs 266-270. Shops have a quality level from 01-20, so it's to be expected that shops differing by only a point might share a quality message. This isn't really an issue in DFU or classic, it's just how the system operates.

If you're interested in how Daggerfall determines thresholds for which text ID to use, here's the relevant bit of code.

Code: Select all

const int qualityLevel1TextId = 266;    // "Incense and soft music soothe your nerves"
const int qualityLevel2TextId = 267;    // "The shop is better appointed than many"
const int qualityLevel3TextId = 268;    // "The shop is laid out in a practical"
const int qualityLevel4TextId = 269;    // "Sturdy shelves, cobbled together"
const int qualityLevel5TextId = 270;    // "Rusty relics lie wherever they were last tossed"

// Set quality level text ID from quality value 01-20
// UESP states this is building quality / 4 but Daggerfall uses manual thresholds
int qualityTextId;
if (buildingSummary.Quality <= 3)
    qualityTextId = qualityLevel5TextId;        // 01 - 03
else if (buildingSummary.Quality <= 7)
    qualityTextId = qualityLevel4TextId;        // 04 - 07
else if (buildingSummary.Quality <= 13)
    qualityTextId = qualityLevel3TextId;        // 08 - 13
else if (buildingSummary.Quality <= 17)
    qualityTextId = qualityLevel2TextId;        // 14 - 17
else
    qualityTextId = qualityLevel1TextId;        // 18 - 20

PLRDLF
Posts: 7
Joined: Thu May 11, 2023 8:17 pm

Re: Discrepancies with messages reflecting a shop's quality

Post by PLRDLF »

Hello, and thanks.

I've always assumed there were only 5 levels of quality in game, ranging from 0 to 4, because the ATLAS tool uses exactly this system when displaying a building's quality, and you can also get only five different massages when entering a shop.

And since I've currently the opportunity to write to the main developer of Daggerfall Unity, I just wanted to ask whether it is possible that we can get something like ATLAS for Daggerfall Unity.
Maybe a console command which dumps all data of a given location. The usage could be similar to ATLAS: <console command> region number/region name/part of region name location name/part of location name

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: Discrepancies with messages reflecting a shop's quality

Post by Interkarma »

Yeah, Daggerfall can be very obscure looking in from the outside. A building's internal 01-20 quality range is used in price calculations, that's why you'll see one shop can have a different price outcome despite having the same flavour text for shop quality in-game. The two systems have different "resolutions", so to speak.

When first implementing shop quality strings, I followed the quality/4 rule. This turned out to not always produce correct flavour text. Allofich later found the correct thresholds as part of their reverse engineering efforts. The way it works now (code above) is matched to classic behaviour. Most likely ATLAS makes the same error here and uses quality/4. The proper thresholds weren't understood until many years later during DFU's development.

In regards to creating a new ATLAS-like tool - I'm wrapping up development on DFU very soon. I won't be creating any new tools or adding anything substantial to the game. What you see now is effectively 1.0. I'll remain somewhat active in the community and occasionally fix some of the lower-priority outstanding bugs, but otherwise that's it for me. :) All the code is open source and heavily battle-tested by this stage, and it's always possible someone else might explore this.

It's probably not quite what you're after, but you can use the various "dump" commands from console to export detailed information about places in-game. "dumpblock", "dumplocation", "dumpregion", etc. might get you part of the way there. These are designed for modders, but still contain tons of data. Output is in JSON format and generally human readable. Use "help" to see all commands and "help <commandname>" to get syntax of a specific console command.

User avatar
MrFlibble
Posts: 411
Joined: Sat Jan 27, 2018 10:43 am

Re: Discrepancies with messages reflecting a shop's quality

Post by MrFlibble »

Interkarma wrote: Tue Jun 27, 2023 5:42 am Shops have a quality level from 01-20, so it's to be expected that shops differing by only a point might share a quality message.
I did not know that, very interesting! I've always assumed that there are indeed only as many fixed quality levels as there are messages. That explains why I'd get somewhat different prices from shops that have the same quality description.

Hopefully not to derail the topic, but are the buy/sell prices in any way affected by the player's reputation with the Merchants group, or only by shop quality, Personality attribute and Mercantile skill?

Also it looks like temples also have different quality levels like other shops, which affects prices, but no message is displayed (since it would not be appropriate to temples). Some mods do display temple quality as well.

User avatar
Interkarma
Posts: 7247
Joined: Sun Mar 22, 2015 1:51 am

Re: Discrepancies with messages reflecting a shop's quality

Post by Interkarma »

Yeah, all buildings have a 01-20 quality rating in gamedata - temples, shops, guilds, even residences. The text you see when entering a shop is just a bit of flavour and gives you a rough sense of their quality number.

Here's the complete method for CalculateTradePrice() formula. The building quality, player personality and mercantile all influence trade price. Some of the factors such as merchant's opposing mercantile and personality are simply derived from shop quality. Player's reputation with Merchants isn't a factor.

Code: Select all

public static int CalculateTradePrice(int cost, int shopQuality, bool selling)
{
    Func<int, int, bool, int> del;
    if (TryGetOverride("CalculateTradePrice", out del))
        return del(cost, shopQuality, selling);

    PlayerEntity player = GameManager.Instance.PlayerEntity;
    int merchant_mercantile_level = 5 * (shopQuality - 10) + 50;
    int merchant_personality_level = 5 * (shopQuality - 10) + 50;

    int delta_mercantile;
    int delta_personality;
    int amount = 0;

    if (selling)
    {
        delta_mercantile = (((100 - merchant_mercantile_level) << 8) / 200 + 128) * (((player.Skills.GetLiveSkillValue(DFCareer.Skills.Mercantile)) << 8) / 200 + 128) >> 8;
        delta_personality = (((100 - merchant_personality_level) << 8) / 200 + 128) * ((player.Stats.LivePersonality << 8) / 200 + 128) >> 8;
        amount = ((((179 * delta_mercantile) >> 8) + ((51 * delta_personality) >> 8)) * cost) >> 8;
    }
    else // buying
    {
        delta_mercantile = ((merchant_mercantile_level << 8) / 200 + 128) * (((100 - (player.Skills.GetLiveSkillValue(DFCareer.Skills.Mercantile))) << 8) / 200 + 128) >> 8;
        delta_personality = ((merchant_personality_level << 8) / 200 + 128) * (((100 - player.Stats.LivePersonality) << 8) / 200 + 128) >> 8 << 6;
        amount = ((((192 * delta_mercantile) >> 8) + (delta_personality >> 8)) * cost) >> 8;
    }

    return amount;
}
The Daggerfall Unity Bible has a cleaner breakdown of this in their Mercantile entry. Link:

https://en.uesp.net/wiki/Daggerfall_Mod ... Mercantile

Post Reply