====== Sets ======
Sets are a versatile "bag like" storage mechanism in GPHUD. These are only really useful for scripting purposes, though the Inventory module and uses Sets as a backing store.
A "set" contains "elements" and a "quantity" associated with them ; the most typical example is a bag of items, which may contain e.g. 5 x apples and 2 x bread. The elements are Apples and Bread with the quantities associated being 5 and 2 respectively.
====Example====
As a practical example we will use this Set mechanism along with Effects to provide a "memorised spell" capability, we won't get too creative but we will offer two spells, "Heal Self" and "Magic Missile", the character will be allowed to store a total of 3 spells in their "Learned List", and once a day they will be able to refresh their available spells to match the Learned List.
For this example we will need two Sets, "KnownSpells" and "AvailableSpells".
There will be an NPC, the "Manifestation of Magic" which can be interacted with ; if the user has less than 3 known spells they may choose one to add to their known set. If the user knows 3 spells then this NPC will offer to refresh their AvailableSpells, assuming the character hasn't done it in the last 24 hours, and the user will be inflicted with a hidden Effect called "SpellsRefreshed" for 24 hours after doing this.
====Implementation====
* Under the Configuration, Characters page create two new attributes, one called AvailableSpells of type SET (nothing else needs setting on the attribute creation page), and then do this for another attribute called "KnownSpells" of type SET.
* Under Configuration, Effects, add a new effect called SpellsRefreshed, select it, and change the SpellsRefreshed Effect value for Effects.ShowEffect to false. Set Effects.ApplyMessage for SpellsRefreshed to "You feel that your magic powers have been recharged, though the toll taken on you will prevent you from doing this again within the next day!". Set Effects.RemoveMessage for SpellsRefreshed to "You feel as if you have recovered from your last magical recharge and could sustain another recharge if desired"
* Create a new Script named spellWizard and enter the following script:
// Spell wizard - will let you learn spells until you have 3 total, after that it will allow a daily refresh of your known spells.
Integer knownSpells=gsSetQuantity(CALLER,"KnownSpells");
if (knownSpells<3) {
// then offer to teach them a spell
String learn=gsGetChoice(CALLER,"Pick a spell to memorise",["Heal Self","Magic Missile"]);
Integer discard=gsSetAdd(CALLER,"KnownSpells",learn,1);
discard=gsSayToChar(CALLER,"You feel the essence of magic infuse you and the knowledge of "+learn+" is seared into the back of your brain.");
} else {
// they already know the maximum number of spells, lets see if they can 'refresh' what they know
if (gsGetEffectDuration(CALLER,"SpellsRefreshed")>0) {
Integer discard=gsSayToChar(CALLER,"It has been too soon since your last magical recharge, the essence safeguards you by remaining inert");
} else {
// they can do the refresh!
// wipe the available spells
Integer previousquantity=gsSetWipe(CALLER,"AvailableSpells");
Integer copied=gsSetCopy(CALLER,"KnownSpells","AvailableSpells");
Integer applied=gsApplyEffect(CALLER,"SpellsRefreshed",60*60*23); // block spell refresh for 23 hours
}
}
* Create an object in world, name it "Essence of Magic", drop the object driver script into it.
* In the Configuration, Objects page, create a new object type called "Essence of Magic", set its behaviour to "Causes the character to run a script on a click", select "spellWizard" as the script and leave the interaction range at 10 meters.
* Back under Configuration, Objects, bind the Essence of Magic object to the Essence of Magic behaviour.
* Create a new script called spellCast containing the following:
// cast a spell from AvailableSpells
Integer totalquantity=gsSetQuantity(CALLER,"AvailableSpells");
if (totalquantity<1) {
Integer a=gsSayToChar(CALLER,"You have no magic available. You may return to the Essence of Magic to refresh your spells, if you have not done so within the last day");
} else {
String cast=gsGetChoice(CALLER,"Select spell to cast",gsSetList(CALLER,"AvailableSpells"));
if (cast=="Heal Self") {
Response discard=gsAPIX(CALLER,"Health.healRoll",[CALLER,1,1,3,"Self heal cast for 4 points max of healing"]);
Integer selfheal=gsSayToChar(CALLER,"You healed yourself, your health is now "+gsGetCharacterKV(CALLER,"health.health"));
Integer update=gsSetAdd(CALLER,"AvailableSpells",cast,-1);
}
if (cast=="Magic Missile") {
Character target=gsSelectCharacter(CALLER,"Pick a target for magic missile!");
Response r=gsAPIX(CALLER,"Roller.RollDamageAgainst",[target,1,1,1,1,1,0,4,"Magic missile strikes you"]);
Integer discard=gsSayToChar(CALLER,"You strike at "+target+" with magic missile!");
Integer discard=gsSayToChar(target,"You are struck by a magic missile from "+CALLER+" and now have "+gsGetCharacterKV(target,"health.health")+" health remaining.");
Integer update=gsSetAdd(CALLER,"AvailableSpells",cast,-1);
}
}
* Bind Scripting.spellCast onto a menu or quickbutton somewhere