Bug - Fixed string_modifier($item[class-specific skill book],"Class") should return a class

zarqon

Well-known member
string_modifier($item[class-specific skill book],"Class") should return a class

While writing a little scriptlet to deal with skill books after breaking the prism, I ran afoul of the Traveling Trader books being class-specific. Trying to use them causes mafia to print a "(usable quantity of Uncle Romulus is limited to 0 by your class)" message. However, I couldn't seem to find any way of detecting this information in ASH so as to avoid using impossible books. I could hardcode a list, but I was fairly sure mafia has some kind of framework for knowing these sorts of things.

A quick look at modref revealed a string modifier called "Class". Aha! However, for each class-specific Traveling Trader book, Both string_modifier(i, "Class") and class_modifier(i,"Class") returned "" and $class[none], respectively. (Those methods seem to be identical other than return type, by the way (both return positive results for the same number of items). And while we're here, why is there a second parameter for class_modifier()? Is it ever anything other than "Class"? Perhaps I am -- once again -- missing something?)

I wasn't sure whether to call this a feature request or a bug, so I looked more closely at the 143 items with positive results. The overwhelming majority of them are equipment, so at first I thought I might be requesting new functionality. However! While 142 of the 143 items are equipment, 1 of them is a usable item! Yes, the experimental carbon fiber pasta additive returns "Pastamancer", and thus the precedent is established and this must therefore be a bug. :D

Anyway, I would find it handy if the Traveling Trader books (and their used variants) had the appropriate class modifier. Thanks!
 
The skills that are obtained from the books do have the Class string modifier (for the couple I checked anyway).

There doesn't seem any way to obtain a skill from a skill-granting item in ASH though. (The list of skill granting items seems to be hardcoded in UseItemRequest).

So an alternative way of achieving this would be for skill granting $items to have a modifier/field showing which skill they grant, which seems like it could be useful for other applications.
 

Veracity

Developer
Staff member
Looking at the item desc for Uncle Romulus, I see:

Only Turtle Tamers may use this item.

Looking at modifiers.txt, I see:

# Uncle Romulus: <b>Only Turtle Tamers may use this item.</b>

Looking at Modifiers.java, I see:

Code:
		{ "Class",
		  null,
		  Pattern.compile( "Class: \"(.*?)\"" )
		},
So, it looks like we don't automatically parse the message in the description to get the class.

Looking at the ancient Saucehelm, the description says:

Bonus for Saucerors only

but we manually added the class to the modifier string, since we don't parse that, either.

Looking at UseItemRequest.java, I see:

Code:
	private static final String itemToClass( final int itemId )
	{
		switch ( itemId )
		{
		case ItemPool.SLAPFIGHTING_BOOK:
		case ItemPool.SLAPFIGHTING_BOOK_USED:
			return KoLCharacter.SEAL_CLUBBER;
		case ItemPool.UNCLE_ROMULUS:
		case ItemPool.UNCLE_ROMULUS_USED:
			return KoLCharacter.TURTLE_TAMER;
		case ItemPool.SNAKE_CHARMING_BOOK:
		case ItemPool.SNAKE_CHARMING_BOOK_USED:
			return KoLCharacter.PASTAMANCER;
		case ItemPool.ZU_MANNKASE_DIENEN:
		case ItemPool.ZU_MANNKASE_DIENEN_USED:
			return KoLCharacter.SAUCEROR;
		case ItemPool.DYNAMITE_SUPERMAN_JONES:
		case ItemPool.DYNAMITE_SUPERMAN_JONES_USED:
			return KoLCharacter.DISCO_BANDIT;
		case ItemPool.INIGO_BOOK:
		case ItemPool.INIGO_BOOK_USED:
			return KoLCharacter.ACCORDION_THIEF;
		}

		return null;
	}
Seems like we could do this:

- Fix Modifiers to recognize the (multiple) forms that a class-specific item is described in the item description (we can have multiple regexps)
- Add Class modifiers to the skill books
- Fix UseItemRequest to look for the Class modifier.

Yes, it would be nice to have a way to map skill items to the skill they grant without hardcoding - but that is not deducable from the description, so we'd have to hardcode it in modifiers.txt. If you mean to expose it to ASH, that could be a proxy field that uses the existing function
 

Veracity

Developer
Staff member
Regarding why there is a second parameter to class_modifier when there is, currently, only a single modifier named "Class"? I dunno. Are we guaranteed to never add a second modifier that is a class?
 

heeheehee

Developer
Staff member
Isn't that also the case with effect_modifier (I have no idea if rollover effect is a thing we track)? I figured that was done for the sake of consistency.
 

Veracity

Developer
Staff member
Darzil recently added "Rollover Effect". Sure is nice that you can use effect_modifier as it has always existed to get it as an effect object, rather than having to use to_effect on the result of string_modifier...
 

zarqon

Well-known member
Seems like we could do this:

- Fix Modifiers to recognize the (multiple) forms that a class-specific item is described in the item description (we can have multiple regexps)
- Add Class modifiers to the skill books
- Fix UseItemRequest to look for the Class modifier.

That all sounds excellent.

Yes, it would be nice to have a way to map skill items to the skill they grant without hardcoding - but that is not deducable from the description, so we'd have to hardcode it in modifiers.txt.

Most if not all of the skill-granting items have "Grants Skill: <bolded skill link>" in their description. Perhaps that could be parsed?

Also, for clarification, are all the modifiers accessible by effect_modifier() and class_modifier() duplicated in string_modifier()? If not, then I may have to request that effect and class modifiers be added to "modref".
 

Veracity

Developer
Staff member
Most if not all of the skill-granting items have "Grants Skill: <bolded skill link>" in their description. Perhaps that could be parsed?
Huh. So they do. OK, yes - that could be just another modifier. Ant that don't have that in the description would have to be added manually. And we should probably add skill_modifier() methods to parallel effect_modifier() and class_modifier().

Also, for clarification, are all the modifiers accessible by effect_modifier() and class_modifier() duplicated in string_modifier()? If not, then I may have to request that effect and class modifiers be added to "modref".
Yes.

Code:
[color=green]> ash string_modifier( $item[ ancient saucehelm ], "Modifiers" )[/color]

Returned: Mysticality: +11, Spell Damage: +11, Class: "Sauceror", Familiar Effect: "3xGhuol, cap 25"
 

Veracity

Developer
Staff member
Revision 16391 does this:

When an item description says that the item is only usable by a certain class, set the "Class" modifier appropriately for that item.
When an item description says that the item grants a skill, set the "Skill" modifier appropriately for that item.
For all items which grant skills but whose descriptions do not mention that, give them the appropriate "Skill" modifier.
UseItemRequest now determines the Class and Granted skill for an item by looking in the item's modifiers, rather than having a hardcoded list.
Add ASH skill_modifier(object, modifiername) (currently only useful for "Skill") to interpret the specified modifier of an item as a skill object.

Which I think is everything we discussed. I did most of it by making item description parsing recognizing things as appropriate, but there were a bunch of old skill items that did not have a Grants Skill annotation, so I added those by hand.

I also note that the new "list the enchantments granted by the effect that using this item gives" confuses the parsing if the enchantment has more than one enchantment: the 2nd and subsequent ones get parsed as if they came from the item, not the effect. If I recall, those are displayed messily. I'll have to see if I can figure out how to decide "these enchantments are from the Effect" and ignore them. Sigh.
 

Theraze

Active member
alias listitemskills => ashq foreach it in $items[] { skill sk = skill_modifier(it, "Skill"); if (sk != $skill[none] && !have_skill(sk) && mall_price(it) > 0) print_html("You don't know "+sk+", but it would cost about "+mall_price(it)+" for "+it+" to fix that."); }
Nifty. Definitely better than the woefully outdated get_skill script.

Edit: Or, in my preferred form:
String successfully aliased.
listitemskills => ashq foreach it in $items[] { skill sk = skill_modifier(it, "Skill"); if (sk != $skill[none] && (sk.class == my_class() || sk.class == $class[none]) && !have_skill(sk) && mall_price(it) > 0 && mall_price(it) <= %%) print_html("You don't know "+sk+", but it would cost about "+mall_price(it)+" for "+it+" to fix that."); }

> listitemskills 10000

You don't know Maximum Chill, but it would cost about 4321 for Maxing, Relaxing to fix that.
You don't know Mudbath, but it would cost about 2900 for Travels with Jerry to fix that.
You don't know Inappropriate Backrub, but it would cost about 3500 for Sensual Massage for Creeps to fix that.
You don't know Summon Holiday Fun!, but it would cost about 1500 for Holiday Fun! to fix that.
You don't know Wassail, but it would cost about 6999 for The Joy of Wassailing to fix that.
 
Last edited:
Top