#include "sd_arrays" //Options on the Tag with posision in the Tag-string //max TAG length = 32 //Static value : FI (pos 01 - 02) , Short for ForgeItem //Dynamic value : Whatever (pos 03 - 20) , Description, also ensure uniqueness //PC Level : _01 (pos 21 - 23) , Leading zeroes //Once pr boot : _0 (pos 24 - 25) , Only once pr. server boot? .Values 1 = TRUE, 0 = FALSE //GP-cost % of item : _20 (pos 26 - 28) , Initial GP value for PC, percentage of original price. //XP * : _5 (pos 29 - 30) , Some items might have a greater XP penalty //GP * : _5 (pos 31 - 32) , Some items might be more expensive //Non-settable, standard algoritms. //Initial GP cost : Original GP value of item //initial XP cost : Based on 2000K xp * level of the item. Tag pos 21 - 23 //global variables available when this script is included int iTalkVolume = TALKVOLUME_TALK; int iXPPrLevel = 500; int iXP_To_GP_Multiplyer = 10; //Only to be used for the chest containing the actual item PC want to have int ItemLevel_Get(string ChestTag) { int iLevel = StringToInt(GetSubString(ChestTag, 21, 2)); return iLevel; } //Entrepret the TAB of a chest to see if its gonna be destroyed after someone has 'bought' the item int ItemOncePrServerBoot_Get(string ChestTag) { int iBoot = StringToInt(GetSubString(ChestTag, 24, 1)); return iBoot; } //Only to be used for the chest containing the actual item PC want to have int XPLoss_Get(string ChestTag) { object oChest = GetObjectByTag(ChestTag); object oItem = GetFirstItemInInventory(oChest); int iLevel = ItemLevel_Get(ChestTag); int iXPMultiplyer = StringToInt(GetSubString(ChestTag, 29, 1)); int iXP = iXPPrLevel * iLevel * iXPMultiplyer; //SpeakString("XP Multiplier" + IntToString(iXPMultiplyer), TALKVOLUME_SHOUT); return iXP; } //Only to be used for the chest containing the actual item PC want to have int GPLoss_Get(string ChestTag) { /* object oChest = GetObjectByTag(ChestTag); object oItem = GetFirstItemInInventory(oChest); */ int iGPMultiplyer = StringToInt(GetSubString(ChestTag, 31, 1)); int iGPCost = StringToInt(GetSubString(ChestTag, 26, 2)); int iGPValue = 0; iGPValue = iGPCost * 100000 + iGPMultiplyer * 1000000 ; /* iGPValue = GetGoldPieceValue(oItem); iGPValue = ((iGPValue / 100) * iGPCost) * iGPMultiplyer; */ return iGPValue; } int GetMinimumXPForLevel(int Level) { int iXP; if (Level == 20) iXP = 190000; else if (Level == 19) iXP = 171000; else if (Level == 18) iXP = 153000; else if (Level == 17) iXP = 136000; else if (Level == 16) iXP = 120000; else if (Level == 15) iXP = 105000; else if (Level == 14) iXP = 91000; else if (Level == 13) iXP = 78000; else if (Level == 12) iXP = 66000; else if (Level == 11) iXP = 55000; else if (Level == 10) iXP = 45000; else if (Level == 9) iXP = 36000; else if (Level == 8) iXP = 28000; else if (Level == 7) iXP = 21000; else if (Level == 6) iXP = 15000; else if (Level == 5) iXP = 10000; else if (Level == 4) iXP = 6000; else if (Level == 3) iXP = 3000; else if (Level == 2) iXP = 1000; else if (Level == 1) iXP = 0; else iXP = 190000; return iXP; } //Only to be used for the chest containing the actual item PC want to have int CalculateTotalXPLoss(object oPC, string ChestTag) { //int iPCLevel = GetLevelByClass(1, oPC) + GetLevelByClass(2, oPC) + GetLevelByClass(3, oPC); int iPCLevel = GetHitDice(oPC); int iPCXp = GetXP(oPC); int iXPMinimum = GetMinimumXPForLevel(iPCLevel); int iXPLoss_Pre = XPLoss_Get(ChestTag); int iXPLoss_Fin = iPCXp - iXPLoss_Pre; //Make sure PC dont level down if (iXPLoss_Fin0) iGPLoss_Fin = iGPLoss_Fin + (iXPLoss_Fin * iXP_To_GP_Multiplyer); //SpeakString("Calculated Total GP loss is: " + IntToString(iGPLoss_Fin), TALKVOLUME_SHOUT); return iGPLoss_Fin; } int CheckExchangeItems(object oPC, int Exchange) { int iResult; int iChoice = GetLocalInt(oPC, "ForgeItemChoice"); string sTAG_Chest1 = GetLocalArrayString(oPC, "ForgeItem", iChoice + 1000); string sTAG_Chest2 = "FI" + GetStringRight(sTAG_Chest1, GetStringLength(sTAG_Chest1)-2); object oChest = GetObjectByTag(sTAG_Chest1); object oItem = GetFirstItemInInventory(oChest); int iItemCounter = 0; int iTotalItems = 0; string sResRef = ""; int iItemFound = 0; int iStackItems = 0; //build a local array of resrefs on the PC to run comparison against while (oItem != OBJECT_INVALID) { iItemCounter++; sResRef = GetResRef(oItem); SetLocalArrayString(oPC, "ChestItem", iItemCounter, sResRef); SetLocalArrayInt(oPC, "ChestItemStack", iItemCounter, GetNumStackedItems(oItem)); oItem = GetNextItemInInventory(oChest); } //set a local memory variable to the pc, with the information of how many items there were in the chest. SetLocalInt(oPC, "ChestItemCount", iItemCounter); //reset the counters for looping the memory variables and the PC's inventory iTotalItems = iItemCounter; iItemCounter = 0; while (iItemCounter=iItemXP) iReturn = 1; else { if (GetIsDM(oPC)) iReturn = 1; else iReturn = 0; } return iReturn; } int Get_HasEnoughGP(object oPC, string sTAG_Chest1) { int iPCLevel = GetLevelByPosition(1, oPC) + GetLevelByPosition(2, oPC) + GetLevelByPosition(3, oPC); int iPCGP = GetGold(oPC); int iItemGP = GPLoss_Get(sTAG_Chest1); int iReturn = 0; if (iPCGP > iItemGP) iReturn = 1; else { if (GetIsDM(oPC)) iReturn = 1; else iReturn = 0; } return iReturn; } void DoForgeMenyChoice(int Choice) { object oPC = GetLastSpeaker(); object oChest = OBJECT_INVALID; object oItem = OBJECT_INVALID; string sTAG_Chest1 = ""; string sTAG_Chest2 = ""; string sReport = ""; int iGPLoss = 0; SetLocalInt(oPC, "ForgeItemChoice", Choice); sTAG_Chest1 = GetLocalArrayString(oPC, "ForgeItem", Choice + 1000); sTAG_Chest2 = "FI" + GetStringRight(sTAG_Chest1, GetStringLength(sTAG_Chest1)-2); oChest = GetObjectByTag(sTAG_Chest1); oItem = GetFirstItemInInventory(oChest); sReport = "You need to get the following items:"; sReport = sReport + "\n----------------------------------"; while (GetIsObjectValid(oItem)) { sReport = sReport + "\n" + GetName(oItem) + "(" + IntToString(GetNumStackedItems(oItem)) + ")"; oItem = GetNextItemInInventory(oChest); } sReport = sReport + "\n----------------------------------"; //check to see if the pc has enough XP, and adjust the report accordingly if (Get_HasEnoughXP(oPC, sTAG_Chest1)) sReport = sReport + "\nXP needed is: " + IntToString(XPLoss_Get(sTAG_Chest1)) + ". You seem to have enough to spare"; else sReport = sReport + "\nXP needed is: " + IntToString(XPLoss_Get(sTAG_Chest1)) + ". You dont have enough to spare"; sReport = sReport + "\n----------------------------------"; //check to see if the pc has enough GP, and adjust the report accordingly if (Get_HasEnoughGP(oPC, sTAG_Chest2)) sReport = sReport + "\nGP needed is: " + IntToString(GPLoss_Get(sTAG_Chest2)) + ". You seem to have enough to spare"; else sReport = sReport + "\nGP needed is: " + IntToString(GPLoss_Get(sTAG_Chest2)) + ". You dont have enough to spare"; sReport = sReport + "\n----------------------------------"; sReport = sReport + "\n\n" + "Do you want me to look through your inventory for the items required? The items required will automatically be removed from your inventory and replaced with the item you choose."; SetCustomToken(2000, sReport); //SpeakString("Calculated XP loss for item: " + IntToString(CalculateTotalXPLoss(oPC, sTAG_Chest2)), iTalkVolume); //SpeakString("Calculated GP loss for item: " + IntToString(CalculateTotalGPLoss(oPC, sTAG_Chest2)), iTalkVolume); //iGPLoss = GPLoss_Get(sTAG_Chest2); } int Forge_GetCurrentPage(object oPC) { int iCurrentPage = GetLocalInt(oPC, "ForgeCurrentPage"); //if (iCurrentPage == 0) iCurrentPage = 1; return iCurrentPage; } void Forge_SetCurrentPage(object oPC, int iValidItems) { SetLocalInt(oPC, "ForgeCurrentPage", iValidItems); } void Forge_List() { object oPC = GetLastSpeaker(); object oArea = GetArea(oPC); object oForgeChest1 = GetFirstObjectInArea(oArea); object oForgeChest2 = OBJECT_INVALID; object oItem = OBJECT_INVALID; int iPCLevel = GetLevelByPosition(1,oPC) + GetLevelByPosition(2,oPC) + GetLevelByPosition(3,oPC); int iCurrentPage = Forge_GetCurrentPage(oPC); int iLoop = 0; int iCount = 0; int iValidItems = 0; int iMenuChoice = 0; int iLevelReq = 0; string sTAG_Chest1 = ""; string sTAG_Chest2 = ""; string sNAME_Item = ""; string sRESREF_Item = ""; if (iCurrentPage == 0) iCurrentPage == 1; while (oForgeChest1 != OBJECT_INVALID) { //GET the tag of the current object. It may not be a chest that we're looking for sTAG_Chest1 = ""; sTAG_Chest1 = GetTag(oForgeChest1); if (GetStringLeft(sTAG_Chest1, 2) == "FR") { iCount++; //found a 'chest1' to work with, lets keep info in memory and continue loop SetLocalArrayString(oPC, "ForgeItemList", iCount, sTAG_Chest1); } oForgeChest1 = GetNextObjectInArea(oArea); } while (iLoop<=iCount) { iLoop++; sTAG_Chest1 = GetLocalArrayString(oPC, "ForgeItemList", iLoop); sTAG_Chest2 = "FI" + GetStringRight(sTAG_Chest1, GetStringLength(sTAG_Chest1)-2); oForgeChest2 = GetObjectByTag(sTAG_Chest2); if (GetIsObjectValid(oForgeChest2)) { //check the level requirements for this item. If PC dont meet them, then dont display it iLevelReq = ItemLevel_Get(sTAG_Chest1); if (GetIsDM(oPC)) { iPCLevel = 40; } if (iPCLevel>=iLevelReq) { iValidItems++; if (iValidItems>iCurrentPage * 10) { iMenuChoice++; //Oki, this item is valid for showing on the list. Lets get the name and resref of the item in the chest2 //only one item is gonna be in the chest .. so we get only the first item in the chest oItem = GetFirstItemInInventory(oForgeChest2); sNAME_Item = GetName(oItem); sRESREF_Item = GetResRef(oItem); // set the row value in the conversation SetCustomToken(1000 + iMenuChoice, sNAME_Item); // set a local variable on the PC. Itemnumbers tag of chest1 SetLocalArrayString(oPC, "ForgeItem", 1000 + iMenuChoice, sTAG_Chest1); } } } } SetCustomToken(1000, "<- Previous"); SetCustomToken(1011, "Next ->"); Forge_SetCurrentPage(oPC, iCurrentPage); SetLocalInt(oPC, "ForgeItemCount", iValidItems); } string ForgeItemInfo(object oItem, int nLongForm = 0) { string sReturnString = ""; string sBaseType = ""; string sStacked = ""; string sIdentified = ""; string sGPValue = ""; string sACValue = ""; string sProperties = ""; switch(GetBaseItemType(oItem)) { case BASE_ITEM_AMULET: sBaseType ="Amulet";break; case BASE_ITEM_ARMOR: sBaseType ="Armor";break; case BASE_ITEM_ARROW: sBaseType ="Arrow";break; case BASE_ITEM_BASTARDSWORD: sBaseType ="Bastard Sword";break; case BASE_ITEM_BATTLEAXE: sBaseType ="Battle Axe";break; case BASE_ITEM_BELT: sBaseType ="Belt";break; case BASE_ITEM_BOLT : sBaseType ="Bolt";break; case BASE_ITEM_BOOK: sBaseType ="Book";break; case BASE_ITEM_BOOTS: sBaseType ="Boots";break; case BASE_ITEM_BRACER: sBaseType ="Bracer";break; case BASE_ITEM_BULLET: sBaseType ="Bullet";break; case BASE_ITEM_CBLUDGWEAPON: sBaseType ="Bludgeoning Weap.";break; case BASE_ITEM_CLOAK: sBaseType ="Cloak";break; case BASE_ITEM_CLUB: sBaseType ="Club";break; case BASE_ITEM_CPIERCWEAPON: sBaseType ="Pierceing Weap.";break; case BASE_ITEM_CREATUREITEM: sBaseType ="Creature Item";break; case BASE_ITEM_CSLASHWEAPON: sBaseType ="Slash Weap.";break; case BASE_ITEM_CSLSHPRCWEAP: sBaseType ="Slash/Pierce Weap.";break; case BASE_ITEM_DAGGER: sBaseType ="Dagger";break; case BASE_ITEM_DART: sBaseType ="Dart";break; case BASE_ITEM_DIREMACE: sBaseType ="Mace";break; case BASE_ITEM_DOUBLEAXE: sBaseType ="Double Axe";break; case BASE_ITEM_GEM: sBaseType ="Gem";break; case BASE_ITEM_GLOVES: sBaseType ="Gloves";break; case BASE_ITEM_GOLD: sBaseType ="Gold";break; case BASE_ITEM_GREATAXE: sBaseType ="Great Axe";break; case BASE_ITEM_GREATSWORD: sBaseType ="Great Sword";break; case BASE_ITEM_HALBERD: sBaseType ="Halberd";break; case BASE_ITEM_HANDAXE: sBaseType ="Hand Axe";break; case BASE_ITEM_HEALERSKIT: sBaseType ="Healers Kit";break; case BASE_ITEM_HEAVYCROSSBOW: sBaseType ="Heavy Xbow";break; case BASE_ITEM_HEAVYFLAIL: sBaseType ="Heavy Flail";break; case BASE_ITEM_HELMET: sBaseType ="Helmet";break; case BASE_ITEM_INVALID: sBaseType ="";break; case BASE_ITEM_KAMA: sBaseType ="Kama";break; case BASE_ITEM_KATANA: sBaseType ="Katana";break; case BASE_ITEM_KEY: sBaseType ="Key";break; case BASE_ITEM_KUKRI: sBaseType ="Kukri";break; case BASE_ITEM_LARGEBOX: sBaseType ="Large Box";break; case BASE_ITEM_LARGESHIELD: sBaseType ="Large Shield";break; case BASE_ITEM_LIGHTCROSSBOW: sBaseType ="Light Xbow";break; case BASE_ITEM_LIGHTFLAIL: sBaseType ="Light Flail";break; case BASE_ITEM_LIGHTHAMMER: sBaseType ="Light Hammer";break; case BASE_ITEM_LIGHTMACE: sBaseType ="Light Mace";break; case BASE_ITEM_LONGBOW: sBaseType ="Long Bow";break; case BASE_ITEM_LONGSWORD: sBaseType ="Long Sword";break; case BASE_ITEM_MAGICROD: sBaseType ="Magic Rod";break; case BASE_ITEM_MAGICSTAFF: sBaseType ="Magic Staff";break; case BASE_ITEM_MAGICWAND: sBaseType ="Magic Wand";break; case BASE_ITEM_MISCLARGE: sBaseType ="Misc. Large";break; case BASE_ITEM_MISCMEDIUM: sBaseType ="Misc. Medium";break; case BASE_ITEM_MISCSMALL: sBaseType ="Misc. Small";break; case BASE_ITEM_MISCTALL: sBaseType ="Misc. Small";break; case BASE_ITEM_MISCTHIN: sBaseType ="Misc. Thin";break; case BASE_ITEM_MISCWIDE: sBaseType ="Misc. Wide";break; case BASE_ITEM_MORNINGSTAR: sBaseType ="Morningstar";break; case BASE_ITEM_POTIONS: sBaseType ="Potion";break; case BASE_ITEM_QUARTERSTAFF: sBaseType ="Quarterstaff";break; case BASE_ITEM_RAPIER: sBaseType ="Rapier";break; case BASE_ITEM_RING: sBaseType ="Ring";break; case BASE_ITEM_SCIMITAR: sBaseType ="Scimitar";break; case BASE_ITEM_SCROLL: sBaseType ="Scroll";break; case BASE_ITEM_SCYTHE: sBaseType ="Scythe";break; case BASE_ITEM_SHORTBOW: sBaseType ="Shortbow";break; case BASE_ITEM_SHORTSPEAR: sBaseType ="Short Spear";break; case BASE_ITEM_SHORTSWORD: sBaseType ="Short Sword";break; case BASE_ITEM_SHURIKEN: sBaseType ="Shuriken";break; case BASE_ITEM_SICKLE: sBaseType ="Sickle";break; case BASE_ITEM_SLING: sBaseType ="Sling";break; case BASE_ITEM_SMALLSHIELD: sBaseType ="Small Shield";break; case BASE_ITEM_SPELLSCROLL: sBaseType ="Spell Scroll";break; case BASE_ITEM_THIEVESTOOLS: sBaseType ="Thieves Tools";break; case BASE_ITEM_THROWINGAXE: sBaseType ="Throwing Axe";break; case BASE_ITEM_TORCH: sBaseType ="Torch";break; case BASE_ITEM_TOWERSHIELD: sBaseType ="Tower Shield";break; case BASE_ITEM_TRAPKIT: sBaseType ="Trap Kit";break; case BASE_ITEM_TWOBLADEDSWORD: sBaseType ="2 Bladed Sword";break; case BASE_ITEM_WARHAMMER: sBaseType ="Warhammer";break; } if (sBaseType != "Gold") { // If more than one item (stacked) if (GetNumStackedItems(oItem) > 1 ) { sStacked = "(" + IntToString(GetNumStackedItems(oItem)) + ") "; } else { // Build remainder of output string sStacked = ""; } } if(nLongForm) { sIdentified = "Identified: " + ((GetIdentified(oItem))?"Yes":"No"); sGPValue = "Gold Piece Value: " + IntToString(GetGoldPieceValue(oItem)); int nACValue = GetItemACValue(oItem); if(nACValue) { sACValue = "Total AC: " + IntToString(nACValue); } sProperties = GetCampaignString("SD_FORGE","sd_"+GetTag(oItem),GetModule()); if(sProperties != "") { sProperties = "Properties:\n" + sProperties; } //sIdentified + "\n" + sReturnString = sStacked + GetName(oItem) + "\n" + "-------------------------------------------\n" + sBaseType + "\n" + ((nACValue)?sACValue + "\n":"") + "-------------------------------------------\n" + sProperties; } else { sReturnString = sStacked + GetName(oItem) + " (" + sBaseType + ")"; } return sReturnString; } void CleanUpVariables() { object oPC = GetLastSpeaker(); int iCounter = 0; //destroy conversation variables while (++iCounter<=10) { DeleteLocalInt(oPC, "ForgeItemChoice" + IntToString(iCounter)); DeleteLocalString(oPC, "ForgeItemList" + IntToString(iCounter)); DeleteLocalString(oPC, "ForgeItem" + IntToString(iCounter+1000)); DeleteLocalString(oPC, "ChestItem" + IntToString(iCounter)); } DeleteLocalInt(oPC, "ForgeCurrentPage"); } void RemoveXP(object oPC, string TAG_Chest1) { int iXPLoss = XPLoss_Get(TAG_Chest1); //SpeakString("RemoveXP has been called, and xploss is calculated to(" + TAG_Chest1 + "): " + IntToString(iXPLoss),TALKVOLUME_SHOUT); //GiveXPToCreature(oPC, iXPLoss); SetXP(oPC, GetXP(oPC) - iXPLoss); } void RemoveGP(object oPC, string TAG_Chest1) { int iGPLoss = GPLoss_Get(TAG_Chest1); TakeGoldFromCreature(iGPLoss,oPC,TRUE); }