Passing Values through String Dictionaries?(Solved)

onimike
13 Oct 2017, 23:25

Hello all again, got a problem. So I am making my own spell casting system which is contained in a staff, in staff I have 2 attributes one called spells (which is a stringlist) which holds each of the spells and I can add and take away either or and spelldamage (which is stringdictonary) which I want to hold the values of each spell. So how do I access and use the values of each spell?

Here is my spell casting function.

if (staff.worn = True) {
  ShowMenu ("Choose a spell to cast.", staff.spells, true) {
    s = result
    if (result = "Fireball") {
    }
    else if (result = "Ice Orb") {
    }
    else if (result = "Fire Orb") {
    }
    else if (result = "Bubble Shield") {
    }
    else if (result = "Summon") {
      Mage.followers = NewObjectList()
      list add (Mage.followers, Ghoul)
      MoveObject (Ghoul, game.pov.parent)
    }
    msg ("You cast " +s+ ".")
  }
}

After I get result I want to be able to call the spells damage using "s" variable I set to result. I know its possible but am I on right track? Any help always appreciated.

Mike

Edited: By the way I have been over this page http://docs.textadventures.co.uk/quest/using_dictionaries.html 100x or better, can't wrap my head around it.


Doctor Agon
14 Oct 2017, 00:21

Not really used the ShowMenu as such yet, but if you're setting the variable 's' equals 'result', I think then that you need to set your If statement as follows:

if (s = "Fireball") {
}
else if (s = "Ice Orb")
etc

K.V.
14 Oct 2017, 01:21

Hello!


So:

You have staff.spells and staff.spelldamage.

You have ShowMenu iterating through staff.spells, and that result will be one item on the staff.spells string list.

From there, you want to retrieve information from staff.spelldamage.


This is a crappy example game, but I believe it will show you what you need to know.

CLICK HERE FOR THE CODE ``` ```

onimike
14 Oct 2017, 01:53

Oh KV your so awesome thats what I needed wasn't sure on how to call it thank you so much.
and Agon yeah I could change that to be safe

Thanks Again
Mike

Edited: KV how would I subtract the value of Fireball from health? I just tried a few combination to no success.


K.V.
14 Oct 2017, 02:08
ShowMenu ("Choose a spell to cast.", staff.spells, true) {
  if (result = "Fireball") {
    x = DictionaryItem(staff.spelldamage, result)
    msg ("Staff Damage: " + x)
  }
  msg ("You cast " + result + ".")
  DecreaseHealth(ToInt(x))
}


You could use game.pov.health = game.pov.health - ToInt(x) in place of DecreaseHealth(ToInt(x)), if you prefer.


hegemonkhan
14 Oct 2017, 02:10

KV beat me to it, (I was busy writing in our/the/KV's 'favorite story' thread, lol):

an example (using random selection)

color_list_variable = split ("red;blue;yellow", ";")
string_variable = StringListItem (color_list_variable, GetRandomInt (0, ListCount (color_list_variable) - 1))
msg (string_variable)

you could use an 'Objectlist' Attribute instead, having your spells as Objects (which allows you to have Attributes on them and to access/use those Attributes)

and there's also Dictionary Attributes as well


here's a guide on using Lists and Dictionaries:

http://textadventures.co.uk/forum/samples/topic/5137/list-and-dictionary-extensive-guide-by-hk

and you can take a look at this too (its old though and has some mistakes and inefficiencies, as this was back when I myself was first learning how lists and dictionaries worked, hehe):

http://textadventures.co.uk/forum/samples/topic/5138/explore-and-travel-code-sample-by-hk


ask if you need help with anything.


onimike
14 Oct 2017, 02:34

Tried and can't seem to get to work. I was trying to use against npc

npc.health = npc.health - ToInt(x)

Am I doing it wrong? lol sorry


hegemonkhan
14 Oct 2017, 02:36

you may need to toggle on the 'health' feature in the GUI/Editor

and/or... the 'health' feature only applies for the Player Objects... and thus doesn't work with a npc (non-Player) Object...


onimike
14 Oct 2017, 02:39

HK yes but i was using an attribute i made in the npc should i call it hp?


onimike
14 Oct 2017, 02:43

Heres the error I get

Error running script: Error evaluating expression 'Ghoul.health - ToInt(x)': Input string was not in a correct format.

hegemonkhan
14 Oct 2017, 03:25

hmm... can you post your code, make sure you got VARIABLES that do hold values...

is your 'npc' an actual Object (its actual name) or are you using 'npc' as a dynamic Variable (if you are, they you need a way to give it a value, which is usually done via 'foreach' through a list, checking/if what you want to find in it, and then using the foreach's special custom variable, which you could name as 'npc', for what you want to do, for example:

<game name="example_game">
</game>

<object name="joe">
</object>

<object name="jim">
</object>

<object name="jan">
</object>

<object name="staff">
  <attr name="spells" type="simplestringlist">Fireball;Tornado;Blizzard;Quake</attr>
  <attr name="spelldamage" type="simplestringdictionary">Fireball = 50; Tornado = 25; Blizzard = 75; Quake = 100</attr>
</object>

// ----------------------------------

x = "unknown" // this might be required for scope reasons... (without creating the 'x' Variable here, it'd otherwise only exist within the 'if (result = "Fireball") { /* scripting */ }' Script block, you'd have to make the rest of the scripting that uses the 'x' be within this same scripting block, not outside of it, but it's easier to just create the 'x' in a larger script block, as I've done here with this, lol)

ShowMenu ("Choose a spell to cast.", staff.spells, true) {
  // if (result = "Fireball") { // actually this isn't really even needed...
    x = DictionaryItem(staff.spelldamage, result)
    msg ("Staff Damage: " + x)
  // } // actually this isn't really even needed...
  msg ("You cast " + result + ".")

  game.npc_objectlist_attribute = NewObjectlist ()
  list add (game.npc_objectlist_attribute, joe)
  list add (game.npc_objectlist_attribute, jim)
  list add (game.npc_objectlist_attribute, jan)
  foreach (npc_object_variable, game.npc_objectlist_attribute) {
    if (npc_object_variable = jan) {
      npc_object_variable.health = npc_object_variable.health - ToInt (x)
    }
  }
}

jmnevil54
14 Oct 2017, 03:27

Health is a built in attribute. Yes, you should call it HP!


hegemonkhan
14 Oct 2017, 03:32

(filler for getting my edited post, updated/posted)
(again, filler for getting my edited post, updated/posted)


here's some (edited/fixed/added) examples from my guide/link on using list and dictionaries (scroll down to its 'dictionary' section to find these examples, and see the rest of dictionary section as I try to help/explain dictionary usage):

<attr name="day_stringdictionary" type="simplestringdictionary">1=sunday;2=monday;3=tuesday;4=wednesday;5=thursday;6=friday;7=saturday;sunday=1;monday=2;tuesday=3;wednesday=4;thursday=5;friday=6;saturday=7</attr>

<attr name="month_to_season_stringdictionary" type="simplestringdictionary">january=winter;february=winter;march=spring;april=spring;may=spring;june=summer;july=summer;august=summer;september=autumn;october=autumn;november=autumn;december=winter</attr>

<attr name="opposing_magic_elementals_stringdictionary" type="simplestringdictionary">fire=water;water=fire;air=earth;earth=air</attr>

// -------------------------------------

game.day_integer_stringlist = split ("1;2;3;4;5;6;7", ";")
show menu ("What day is it?", game.day_integer_stringlist, false) {
  game.day_string = StringdictionaryItem (game.day_stringdictionary, result)
  msg (game.day_string) // (outputs the name of the day)
}

// ----------------------------------------------

game.day_stringlist = split ("sunday;monday;tuesday;wednesday;thursday;friday;saturday", ";")
show menu ("What day is it?", game.day_stringlist, false) {
  game.day_string = StringdictionaryItem (game.day_stringdictionary, result)
  msg (game.day_string) // (outputs the number of the day)
}

// -----------------------------------

(I forgot to do this example in my link)

show menu ("Month?" game.month_to_season_stringdictionary, false) {

  msg (result) // displays the name of the selected month

  season_string_variable = StringDictionaryItem (game.month_to_season_stringdictionary, result)

  msg (season_string_variable) // displays the name of the season

}

// --------------------------------

// let's see if I can remember how to do this, lol ~ its been a while ... Credit goes to Pixie's Spell Library for this ingenius usage of Dictionaries:

ice_dragon.elemental = "water"
fireball_spell.elemental = "fire"

'Cast' Verb on your 'spell' Objects (specific, non-global, non-dynamic, example):

spell = GetObject (fireball_spell)
enemy = GetObject (ice_dragon)

if (spell.elemental = StringDictionaryItem (opposing_magic_elementals_stringdictionary, enemy.elemental) ) {
  enemy.life = enemy.life - (spell.damage * 2)
  msg ("You do double the damage to the enemy, using the correct~opposing spell for its elemental vulnerability~weakness!")
} else if (spell.elemental = enemy.elemental) {
  enemy.life = enemy.life + spell.damage
  msg ("Doh!, You used the same elemental spell as the enemy's elemental, healing it instead of damaging it! You idiot!")
} else {
  enemy.life = enemy.life - spell.damage
  msg ("Your elemental spell, being neither the same nor opposite of the enemy's elemental, thus does its normal damage to the enemy.")
}

K.V.
14 Oct 2017, 04:01

It works for me, onimike.

Is npc.health set up as an integer?

CLICK HERE TO VIEW THE REVISED EXAMPLE CODE ``` ```

jmnevil54
14 Oct 2017, 04:07

Since when was I onimike... what?


K.V.
14 Oct 2017, 04:41

Ha-ha!

I was answering this: http://textadventures.co.uk/forum/quest/topic/r8_aowp_bkiusojvbxluuw/passing-values-through-string-dictionariessolved#ff372cb3-0a48-4c03-82be-c3350b86091c

...but...

It works for me, jmne.

http://textadventures.co.uk/games/view/t5-wt1xs2uclibt6xw52_a/dictionary-tricks


onimike
14 Oct 2017, 12:31

thats weird KV I tried many times last night and this morning here is the code.

Edited: Never mind like i said I forgot to set s var as the dictionary lmao guess i needed sleep, code works now below.

if (staff.worn = True) {
  ShowMenu ("Choose a spell to cast.", staff.spells, true) {
    x = result
    msg ("You cast " +x+ ".")
    s = DictionaryItem(staff.spelldamage, result)
    if (x = "Fireball") {
      msg ("Staff Damage: " + DictionaryItem(staff.spelldamage, result))
      npc.health = npc.health - ToInt(s)
      msg ("npc has " +npc.health+ " left.")
    }
    else if (result = "Ice Orb") {
      msg ("Staff Damage: " + DictionaryItem(staff.spelldamage, result))
    }
    else if (result = "Fire Orb") {
      msg ("Staff Damage: " + DictionaryItem(staff.spelldamage, result))
    }
    else if (result = "Bubble Shield") {
    }
    else if (result = "Summon") {
      Mage.followers = NewObjectList()
      list add (Mage.followers, Ghoul)
      MoveObject (Ghoul, game.pov.parent)
    }
  }
}

I have an npc set as an object yes health is an int, I don't know why its acting like this.

Mike

Edited: I just seen my problem, Im not setting my x var to equal the dictonary hahaha lol man im blind sometimes. Ill post if it works

Thanks again everyone and HK I might steal so of that code :)


mrangel
14 Oct 2017, 13:12

I would point out that this kind of if/elseif/elseif block is exactly what a switch statement is made for.

For example, replicating the effect of the code sample above ("Fireball" does damage; "Ice Orb" and "Fire Orb" display damage but don't inflict anything).

if (staff.worn = True) {
  ShowMenu ("Choose a spell to cast.", staff.spells, true) {
    x = result
    s = DictionaryItem(staff.spelldamage, x)
    msg ("You cast " +x+ ".")
    switch (x) {
      case ("Fireball") {
        msg ("Staff Damage: " + s)
        npc.health = npc.health - ToInt(s)
        msg ("npc has " +npc.health+ " left.")
      }
      case ("Ice Orb", "Fire Orb") {
        msg ("Staff Damage: " + s)
      }
      case ("Bubble Shield") {
      }
      case ("Summon") {
        Mage.followers = NewObjectList()
        list add (Mage.followers, Ghoul)
        MoveObject (Ghoul, game.pov.parent)
      }
    }
  }
}

Or if all the spells that don't have some other effect are intended to be damaging ones, you could simplify it to:

if (staff.worn = True) {
  ShowMenu ("Choose a spell to cast.", staff.spells, true) {
    x = result
    msg ("You cast " +x+ ".")
    switch (x) {
      case ("Bubble Shield") {
        // presumably you have some effect here
      }
      case ("Summon") {
        Mage.followers = NewObjectList()
        list add (Mage.followers, Ghoul)
        MoveObject (Ghoul, game.pov.parent)
      }
      default {
        s = DictionaryItem(staff.spelldamage, x)
        msg ("Staff Damage: " + s)
        npc.health = npc.health - ToInt(s)
        msg (GetDisplayName(npc)+" has " +npc.health+ " left.")
      }
    }
  }
}

hegemonkhan
14 Oct 2017, 19:04

the 'if' (if, if/else, if/else-if, if/else-if/else) and 'switch' are exactly the same, everything you can do with an 'if', you can do with the 'switch' too (requires some fanciness/creativity though: credit to pertex, lol)

sometimes I prefer the 'if', but generally, the 'switch' does have a more human-friendly style/look to it than using 'if'


you really don't need to check each type (via 'if' or 'switch'), as if you got a dictionary of it (which holds each type, acting as your 'if/switch' usage), you only need one line:

VARIABLE = StringDictionaryItem (DICT, INPUT)
// or:
VARIABLE = ObjectDictionaryItem (DICT, INPUT)
// or:
VARIABLE = ScriptDictionaryItem (DICT, INPUT) // or: invoke (ScriptDictionaryItem (DICT, INPUT))


onimike
14 Oct 2017, 23:05

Oh wow Mrangel thats a great idea never thought of a switch and HK thats even more awesome lol how would one set that up?


mrangel
15 Oct 2017, 00:27

Rather than having a 'switch' statement, you could have a dictionary which contains a number for damage-dealing spells or a script for spells that do something else.

But if you're doing that, I think that having spells as objects is likely to give the same benefits while being easier to organise.


K.V.
15 Oct 2017, 00:30

having spells as objects is likely to give the same benefits while being easier to organise.

I second that!


onimike
15 Oct 2017, 00:37

You know mrangel and kv ithat was my initial thought because I could have done that without all the dictionaries but thought that the dic way is easier where i really second guessed myself then you both conformed it lol

Thanks all for taking time to help and just add input
Mike


jmnevil54
15 Oct 2017, 00:41

Just put the spells in a different room, or something. Or not.


hegemonkhan
15 Oct 2017, 02:18

(filler for getting my edited post, updated/posted)
(again, filler for getting my edited post, updated/posted)
(again, filler for getting my edited post, updated/posted)


here's an example... man this took me a long time, lol (was trying to track down Jay's post, but I wasn't sure if I had the right one or not, so was trying to do more searching/research, which was a waste of time, as I think I had the right one this entire time, lol):

(you can modify the scripting in my example to actually do what you want, as it's only an example of mine -- I had to do something)

(my example isn't complete: for example we'd need rooms, the player, spells, and monsters, all set it with the right 'types', but its framework is there for you as an example, and you can always ask for help, if you're confused at what to do and/or what is missing that you'd need to add to it for it to work)

(hopefully this design and its code lines/methods/syntax do work... lol)

<object name="staff">

  <inherit name="editor_object" />

  <attr name="take" type="boolean">true</attr>
  <attr name="drop" type="boolean">true</attr>

  <attr name="worn" type="boolean">false</attr>

  <attr name="wear" type="script">
  </attr>

  <attr name="remove" type="script">
  </attr>

  <attr name="spells" type="objectlist"></attr>

  <attr name="learn" type="script">
  </attr>

  <attr name="cast" type="script">
    if (this.worn) {
      if (ListCount (this.spells) = 0) {
        msg ("You've not learned any spells yet, silly")
      } else {
        ShowMenu ("Choose a spell to cast", this.spells, true) {
          spell_object_variable = result
          msg ("You cast " + spell_object_variable.name + ".")
          objectdictionary_variable = NewObjectDictionary ()
          dictionary add (objectdictionary_variable, "spell", spell_object_variable)
          if (DoesInherit (spell_object_variable, "damage_spell_type")) {
            enemy_objectlist_variable = NewObjectList ()
            foreach (object_variable, ScopeReachableNotHeldForRoom (game.pov.parent)) {
              if (DoesInherit (object_variable, "enemy_type")) {
                list add (enemy_objectlist_variable, object_variable)
              }
            }
            enemy_list_count_integer_variable = ListCount (enemy_objectlist_variable)
            enemy_last_index_number_integer_variable = enemy_list_count_integer_variable - 1
            enemy_random_index_number_integer_variable = GetRandomInt (0, enemy_last_index_number_integer_variable)
            enemy_object_variable = ObjectListItem (enemy_objectlist_variable, enemy_random_index_number_integer_variable)
            dictionary add (objectdictionary_variable, "enemy", enemy_object_variable)
          } else if (DoesInherit (spell_object_variable, "shield_spell_type")) {
            msg ("Shield Spell Type")
          } else if (DoesInherit (spell_object_variable, "summon_spell_type")) {
            msg ("Summon Spell Type")
          } else if (DoesInherit (spell_object_variable, "healing_spell_type")) {
            msg ("Healing Spell Type")
          } else {
            msg ("Whatever else or error handling-catch")
          }
          invoke (ScriptDictionaryItem (spell_data_object.spell_scriptdictionary_attribute, spell_object_variable.name), objectdictionary_variable)
        }
      }
    } else {
      msg ("You need to wear this first, before you can use it, silly")
    }
  </attr>
</object>

<object name="spell_data_object">

  <inherit name="editor_object" />

  <attr name="spell_scriptdictionary_attribute" type="scriptdictionary">

    <item key="Fireball">
      msg ("Staff Damage: " + spell.damage)
      enemy.health = enemy.health - spell.damage
      msg (enemy.name + " has " + enemy.health+ " health left.")
    </item>

    <item key="Blizzard">
      msg ("Staff Damage: " + spell.damage)
      enemy.health = enemy.health - spell.damage
      msg (enemy.name + " has " + enemy.health+ " health left.")
    </item>

    <item key="Earthquake">
      msg ("Staff Damage: " + spell.damage)
      enemy.health = enemy.health - spell.damage
      msg (enemy.name + " has " + enemy.health+ " health left.")
    </item>

    <item key="Tornado">
      msg ("Staff Damage: " + spell.damage)
      enemy.health = enemy.health - spell.damage
      msg (enemy.name + " has " + enemy.health+ " health left.")
    </item>

    <item key="BubbleShield">
      msg ("Staff Spell: " + spell.name)
    </item>

    <item key="Summon">
      msg ("Staff Spell: " + spell.name)
      Mage.followers = NewObjectList()
      list add (Mage.followers, Ghoul)
      MoveObject (Ghoul, game.pov.parent)
    </item>

  </attr>

  <object name="Fireball">
    <inherit name="editor_object" />
    <inherit name="damage_spell_type" />
    <attr name="damage" type="int">50</attr>
  </object>

  <object name="Blizzard">
    <inherit name="editor_object" />
    <inherit name="damage_spell_type" />
    <attr name="damage" type="int">25</attr>
  </object>

  <object name="Earthquake">
    <inherit name="editor_object" />
    <inherit name="damage_spell_type" />
    <attr name="damage" type="int">75</attr>
  </object>

  <object name="Tornado">
    <inherit name="editor_object" />
    <inherit name="damage_spell_type" />
    <attr name="damage" type="int">100</attr>
  </object>

  <object name="BubbleShield">
    <inherit name="editor_object" />
    <inherit name="shield_spell_type" />
  </object>

  <object name="Summon">
    <inherit name="editor_object" />
    <inherit name="summon_spell_type" />
  </object>

</object>

<type name="damage_spell_type">
  <inherit name="spell_type" />
  <attr name="damage" type="int">0</attr>
</type>

<type name="healing_spell_type">
  <inherit name="spell_type" />
</type>

<type name="shield_spell_type">
  <inherit name="spell_type" />
</type>

<type name="summon_spell_type">
  <inherit name="spell_type" />
</type>

<type name="spell_type">
  <!-- You can have 'learn' and 'cast' here, so they'll be on your individual spell Objects/Clones instead of your 'staff' Object, but that'd be a bit of a different design and a bit of moving and adjusting/altering code around -->
</type>

<type name="enemy_type">
  <inherit name="character_type" >
  <attr name="dead" type="boolean">false</attr>
</type>

<type name="character_type">
  <attr name="health" type="int">0</attr>
</type>

if you need help with it, let me know, and I'll help explain it to you.


hegemonkhan
15 Oct 2017, 02:20

or...

you can do: Objects + (Object Types / Types / Inherited Attributes) + Lists + Dictionaries... lol (see my immediate previous post: has large code example)