It says in documentation that the DictionaryAdd function was updated for 5.8 so that an error didn't happen when adding a duplicate. It would just remove it quietly and replace with the new one.
But I'm getting this error:
Error running script: Error adding key 'xp' to dictionary: An item with the same key has already been added.
I checked the DictionaryAdd function, and it looked alright, but just in case I modified it to make it a little clearer, and still got the same error. my updated version is this...
<function name="DictionaryAdd" parameters="dict, key, val">
if (dict = null or TypeOf(dict)="object") {
error ("DictionaryAdd: Dictionary does not exist!")
}
if (DictionaryContains(dict, key)) {
dictionary remove (dict, key)
dictionary add (dict, key, val)
}
else {
dictionary add (dict, key, val)
}
</function>
Please and thank you for any help!
Ok, so I couldn't figure out how to fix the problem by modifying DictionaryAdd
It might be a lost cause, as I read this:
https://docs.textadventures.co.uk/quest/using_dictionaries.html
But... the checks that it gives to try helped me find a workaround. I ended up changing the function that was adding to the dictionary by using a check from the documentation instead.
if ("xp" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "xp", "XP: !")
}
I had to run the check for each attribute being possibly added in the script.
This seems to have made the engine happy and everything working...
Edit: Good to see it works. But I can't figure out why that should make a difference.
Hmmm... It might be something like what you're describing.
The context is that I'm updating to integrate Pixie's CombatLib into my core as a "feature."
(if everything goes smoothly, I'll figure out how to work github and share "core3" with everyone plus the documentation of any updates and additions.)
So in the case of using Pixie's CombatLib, ChangePOV doesn't do all that it needs to.
Pixie has a function called "CombatInitialise," which sets a whole bunch of attributes needed for the library to check. It sets some to the game object, and others to game.pov.
I've created a CombatInitialiseChgPOV to be called in the updated "InitPOV" function if the game object has the CombatLib Feature enabled.
All this to say that in context, the DictionaryAdds are being done every time the POV changes to the "new" POV object. But if you're changing to something that already had that in the dictionary, then it was erroring before my workaround.
My current CombatInitialiseChgPOV function looks like this:
if (game.povstatusattributes = null) {
game.povstatusattributes = NewStringDictionary()
}
if (game.pov.statusattributes = null) {
game.pov.statusattributes = NewStringDictionary()
}
if (not HasScript (game.pov, "changedhitpoints")) {
game.pov.changedhitpoints = scriptholder.changedhitpoints
}
if (not HasScript (game.pov, "changedstamina")) {
game.pov.changedstamina = scriptholder.changedstamina
}
if (not HasScript (game.pov, "changedmoney")) {
game.pov.changedmoney = scriptholder.changedmoney
}
if (not HasScript (game.pov, "changedequipped")) {
game.pov.changedequipped = scriptholder.changedequipped
}
if (not HasScript (game.pov, "changedshield")) {
game.pov.changedshield = scriptholder.changedshield
}
atts = "money;turncount;armour;armour10;stamina;xp;ob_bonus;next_round_ob_bonus;db_bonus;defence;magiccurse;sneaklevel;magiccountdown"
atts = atts + ";attackbonus;defencebonus;armourbonus;magicbonus;damagebonus"
atts = atts + ";strength;agility;stamina;intelligence;pointsleft;level"
foreach (s, Split(atts, ";")) {
if (not HasInt (game.pov, s)) {
set (game.pov, s, 0)
}
}
if ("xp" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "xp", "XP: !")
}
if ("hitpoints" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "hitpoints", "Hitpoints: !")
}
if ("money" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "money", "Money: !")
}
game.pov.status = ""
game.pov.immunities = NewStringList()
if (game.pov.equipped = null) {
game.pov.equipped = game.pov.defaultunequipped
}
if (HasAttribute(game.pov, "dead")) {
}
else {
game.pov.dead = false
}
if (not HasAttribute(game.pov, "hitpoints")) {
game.pov.hitpoints = CalcFullHits()
}
if (game.pov.hitpoints < 1) {
if (GetBoolean(game.pov, "dead")) {
msg ("It's dead, you can't change into it!")
}
else {
game.pov.hitpoints = CalcFullHits()
}
}
else {
}
game.pov.hitpointmax = CalcFullHits()
UpdateStatus
if (not HasAttribute(game, "statnames")) {
game.statnames = NewStringDictionary()
}
if (not DictionaryContains(game.statnames, "strength")) {
dictionary add (game.statnames, "strength", "Strength")
}
if (not DictionaryContains(game.statnames, "stamina")) {
dictionary add (game.statnames, "stamina", "Stamina")
}
if (not DictionaryContains(game.statnames, "agility")) {
dictionary add (game.statnames, "agility", "Agility")
}
if (not DictionaryContains(game.statnames, "intelligence")) {
dictionary add (game.statnames, "intelligence", "Intelligence")
}
foreach (att, game.statnames) {
if (not HasInt(game.pov, att)) {
set (game.pov, att, 0)
}
}
if (not HasAttribute(game.pov, "statnames")) {
game.pov.statnames = NewStringDictionary()
}
foreach (att, game.pov.statnames) {
if (not HasInt(game.pov, att)) {
set (game.pov, att, 0)
}
}
if (GetBoolean(game, "feature_mana")) {
if (not HasScript (game.pov, "changedmana")) {
game.pov.changedmana = scriptholder.changedmana
}
if (not HasScript (game.pov, "changedmana_bonus")) {
game.pov.changedmana_bonus = scriptholder.changedmana_bonus
}
if (not HasScript (game.pov, "changedintelligence")) {
game.pov.changedintelligence = scriptholder.changedintelligence
}
if (not HasScript (game.pov, "changedmagicuser")) {
game.pov.changedmagicuser = scriptholder.changedmagicuser
}
if (GetBoolean(game.pov, "magicuser")) {
if (HasAttribute(game.pov, "mana")) {
if (HasAttribute(game.pov, "mana_max")) {
}
else {
game.pov.mana_max = 0
}
}
else if (HasAttribute(game.pov, "mana_max")) {
if (HasAttribute(game.pov, "mana")) {
}
else {
game.pov.mana = 0
}
}
else {
SetMana
}
if ("mana" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "mana", "MP: !")
}
}
else {
}
}
else {
}
if (game.showhealth) {
if ("health" in game.pov.statusattributes) {
}
else {
dictionary add (game.pov.statusattributes, "health", "Health: !%")
}
}
Some of the dictionary adds are because I updated InitStatusAttributes also, so that if CombatLib is enabled, then attributes are added to game.pov.statusattributes instead of game.povstatusattributes. This was for stats where I thought maybe someone might want to make a creature that didn't have a particular attribute which was auto-set by the core.
Hello.
It looks like you are actually using the dictionary add
Quest Script in your scripts?
I'm not sure, though, because I see you modifying the DictionaryAdd
function in your posts...
It is slightly muddled. Before Quest 5.8, all that existed was the dictionary add
Quest script, which throws an error if the dictionary already has the same key. Quest 5.8 introduced a function called DictionaryAdd
to handle things if the key already exists.
I just made a test game, and DictionaryAdd
works for me.
<!--Saved by Quest 5.8.7753.35184-->
<asl version="580">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="DictionaryAdd Tester">
<gameid>804fad71-5fa1-4b9f-ac11-9fd5d8b4ddf8</gameid>
<version>1.0</version>
<firstpublished>2024</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<isroom />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
<statusattributes type="stringdictionary">
<item>
<key>xp</key>
<value>XP: !</value>
</item>
</statusattributes>
<xp type="int">0</xp>
</object>
</object>
<command name="test">
<pattern>test</pattern>
<script><![CDATA[
msg ("Attempting to add <code>xp</code> to game.pov.statusattributes when it already exists as set up in the editor...")
msg("")
msg("Before the change, game.pov.statusattributes[\"xp\"]:")
msg(game.pov.statusattributes["xp"])
msg("")
DictionaryAdd (game.pov.statusattributes, "xp", "XXPP !!")
msg("After the change, game.pov.statusattributes[\"xp\"]:")
msg(game.pov.statusattributes["xp"])
]]></script>
</command>
</asl>
DictionaryAdd Tester
You are in a room.
> test
Attempting to add xp to game.pov.statusattributes when it already exists as set up in the editor...Before the change, game.pov.statusattributes["xp"]:
XP: !After the change, game.pov.statusattributes["xp"]:
XXPP !!