In the spirit of open communication between shard admins and to foster an environment of mutual idea sharing, Derrick has graciously welcomed me to these boards to share my findings with regard to era accuracy.
I too am working on a shard of roughly the same era - Publish 5, April 27, 2000, so many of my findings will be of value to the UO Second Age Designers, admins, and ultimately the community.
With that introduction out of the way, here is the issue:
The consistent and accurate applications of the Articles 'a' and 'an'.
First for the test:
Click on the shirt of the Avatar in the online tutorial. You will see: "fancy shirt"
Click on the (new style) tinkers tools on the production shard and you will see "a tool kit"
I believe both of these are wrong, and here's why:
First, if you launch the original Demo that comes on the second age CD and click on the Avatar's shirt, you will see (and as I remember it) "a fancy shirt"
If you then spawn tinker's tools and click on it, you will see "tool kit" not "a tool kit".
As you can infer form the above example, era accurate in this case means being consistent with the era and not necessarily being consistent with proper article usage!
Solution:
You will find that the ItemData associated with all items has flag members ArticleA & ArticleAN.
If we apply these rules consistently, I believe we will be era accurate.
Implementation:
The proper application of ArticleA & ArticleAN can be accomplished in many ways. The approach I took was to leverage the case logic that is already in place for handling items with the Name property already set. (For the casual reader: very few in-game items have the Name property set, the server calculates the offset to the name in the form of an integer and passes that back to the client who then looks it up.) I.e., 1020000 + (m_ItemID & 0x3FFF)
A freshly spawned katana for instance has no Name property. if a GM then names it: [set Name "Sting" the internal server code will process single-click actions and vendor naming actions differently than if the item had no name and the name offset was the usual calculation: 1020000 + (m_ItemID & 0x3FFF);
The Approach I used for applying ArticleA & ArticleAN leverages this special case handling already present in the server code; we simply add a new special case 'OldName'. If it has an OldName (which everything without a Name property will) we then check also 'OldArticle'.
server/item.cs now looks like this:
Code: Select all
public virtual string OldName
{
get
{
string name = this.ItemData.Name;
if (name != null)
name = name.Trim();
return name;
}
}
public virtual string OldArticle
{
get
{
if ((this.ItemData.Flags & TileFlag.ArticleA) != 0)
return "a";
else if ((this.ItemData.Flags & TileFlag.ArticleAn) != 0)
return "an";
else
return null;
}
}
That's pretty much it.
By using this logic in OnSingleClick:Item.cs you will cover most cases.
You will likely also need to apply this to BaseClothing.cs, BaseWeapon.cs, and BaseArmor.cs as well since those modules have special attribute processing.
PS. There is a funniness with some of the ItemData.Name's as they may contain a trailing space (at least on some client versions.) 'buckler ' for instance.
It is for this reason I Trim() the resulting string.
PPS. It is understood that the ItemData can change from client version to client version; but as long as the server has an era accurate client graphic database, then all is well.
Should the server be using an out-of-era graphic database, then an Article Compiler could be written to build a lookup table of itemID-to-Article mappings. This table would then be plugged into the OldArticle() function above.