From 476fad96c90177ea9daace48313b06e138cbbc08 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 18 Nov 2025 00:20:14 -0600 Subject: [PATCH 01/43] Masonry Skill --- .../items/skills/tools/blacksmithy.dfn | 3 +- data/dfndata/items/skills/tools/carpenty.dfn | 29 +++++ data/dictionaries/dictionary.ENG | 23 ++++ data/js/item/masonrybook.js | 35 ++++++ data/js/item/stoneminingbook.js | 4 +- data/js/jse_fileassociations.scp | 3 +- data/js/skill/craft/craftgump.js | 118 ++++++++++++++++-- data/js/skill/craft/crafttool.js | 29 +++++ 8 files changed, 229 insertions(+), 15 deletions(-) create mode 100644 data/js/item/masonrybook.js diff --git a/data/dfndata/items/skills/tools/blacksmithy.dfn b/data/dfndata/items/skills/tools/blacksmithy.dfn index debd46232..ddfd9c2f8 100644 --- a/data/dfndata/items/skills/tools/blacksmithy.dfn +++ b/data/dfndata/items/skills/tools/blacksmithy.dfn @@ -49,5 +49,4 @@ id=0x0fb0 [anvil] { get=0x0faf 0x0fb0 -} - +} \ No newline at end of file diff --git a/data/dfndata/items/skills/tools/carpenty.dfn b/data/dfndata/items/skills/tools/carpenty.dfn index 64a7319b6..7cb9dfa08 100644 --- a/data/dfndata/items/skills/tools/carpenty.dfn +++ b/data/dfndata/items/skills/tools/carpenty.dfn @@ -300,4 +300,33 @@ usesleft=25 script=2200// uses left tooltip } +[malletandchisel] +{ +get=base_item +name=mallet and chisel +id=0x12B3 +colour=0x3B9 +weight=100 +value=9 4 +restock=20 +decay=1 +good=51 +maxuses=75 +usesleft=25 +script=2200// uses left tooltip +script=4037// craft tool +} +[masonrybook] +{ +get=base_item +name=Making Valuables With Stonecrafting +id=0xFBE +weight=500 +movable=1 +pileable=1 +decay=1 +value=10637 5318 +origin=lbr +script=5055 +} diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index c7830a3e7..db4104439 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -3518,6 +3518,9 @@ 6278=You have to use your taste identification skill to know more about this potion. 6279=Tip: Skill check success guaranteed due to elevated command level! 6280=Spellcast delay ignored due to elevated command level! +6297=You havent learned masonry. +6298=Only a Grandmaster Carpenter can learn from this book. +6299= You have learned to make items from stone. You will need miners to gather stones for you to make these items. 6300=You havent learned glassblowing. 6301=Only a Grandmaster Alchemist can learn from this book. 6302=You have already learned this information. @@ -5022,6 +5025,26 @@ 13609=empty vials 13610=full vials 13611=spinning hourglass +// 14001 - 14500 Masonary Crafting Skill +14001=Masonry Menu +14002=Decorations +14003=Furniture +14004=Statues +14005=Misc Addons +14006=Stone Armor +14007=Stone Weapons +14008=Stone Walls +14009=Stone Stairs +14010=Stone Floors +14011=Granite +14012=DullCopperGranite +14013=ShadowIronGranite +14014=CopperGranite +14015=BronzeGranite +14016=GoldGranite +14017=AgapiteGranite +14018=VeriteGranite +14019=ValoriteGranite // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/js/item/masonrybook.js b/data/js/item/masonrybook.js new file mode 100644 index 000000000..f4b664f3f --- /dev/null +++ b/data/js/item/masonrybook.js @@ -0,0 +1,35 @@ +/// +// @ts-check +/** @type { ( user: Character, iUsing: Item ) => boolean } */ +function onUseChecked( pUser, iUsed ) +{ + var socket = pUser.socket; + var itemOwner = GetPackOwner( iUsed, 0 ); + + if( socket && iUsed && iUsed.isItem ) + { + if( itemOwner == null || itemOwner.serial != pUser.serial ) + { + socket.SysMessage( GetDictionaryEntry( 1763, socket.language )); // That item must be in your backpack before it can be used. + } + else if( pUser.skills[0] < 1000 ) + { + socket.SysMessage( GetDictionaryEntry( 6298, socket.language )); // Only a Grandmaster Carpenter can learn from this book. + } + else if( pUser.GetTag( "StoneCrafting" ) == 1 ) + { + socket.SysMessage( GetDictionaryEntry( 6302, socket.language )); // You have already learned this information. + } + else if( iUsed.movable == 2 || iUsed.movable == 3 ) + { + socket.SysMessage( GetDictionaryEntry( 774, socket.language )); //That is locked down and you cannot use it + } + else + { + pUser.SetTag( "StoneCrafting", 1 ); + socket.SysMessage( GetDictionaryEntry( 6299, socket.language )); // You have learned to make items from stone. You will need miners to gather stones for you to make these items. + iUsed.Delete(); + } + } + return false; +} diff --git a/data/js/item/stoneminingbook.js b/data/js/item/stoneminingbook.js index 60cbec328..1b9408b6d 100644 --- a/data/js/item/stoneminingbook.js +++ b/data/js/item/stoneminingbook.js @@ -22,12 +22,12 @@ function onUseChecked( pUser, iUsed ) } else if( iUsed.movable == 2 || iUsed.movable == 3 ) { - pSocket.SysMessage( GetDictionaryEntry( 774, pSocket.Language )); //That is locked down and you cannot use it + pSocket.SysMessage( GetDictionaryEntry( 774, pSocket.language )); //That is locked down and you cannot use it } else { pUser.SetTag( "GatheringStone", 1 ); - pSocket.SysMessage( GetDictionaryEntry( 9411, pSocket.Language )); // You have learned to mine for stones. Target mountains when mining to find stones. + pSocket.SysMessage( GetDictionaryEntry( 9411, pSocket.language )); // You have learned to mine for stones. Target mountains when mining to find stones. iUsed.Delete(); } } diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 770f1e77b..938a3d875 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -236,6 +236,7 @@ 4034=skill/craft/cooking.js 4035=skill/craft/cartography.js 4036=skill/craft/glassblowing.js +4037=skill/craft/masonry.js 4050=skill/mining.js 4055=skill/snooping.js @@ -309,7 +310,7 @@ 5052=item/sandminingbook.js 5053=item/stoneminingbook.js 5054=item/glassblowingbook.js -//reserved for granitebook +5055=item/masonrybook.js 5056=item/crystalball.js 5057=item/ballofpetsummoning.js 5058=item/bagofsending.js diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 2e894f588..99795dd49 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -14,6 +14,7 @@ const Tinkering = 4032; const Cooking = 4034; const Cartography = 4035; const Glassblowing = 4036; +const Masonry = 4037; // If enabled, players can craft coloured variants of weapons using Blacksmithing skill, though // unless the craftItems array in blacksmithing.js is updated with specific create entries for the @@ -43,6 +44,16 @@ function CraftingGumpMenu( myGump, socket ) var hides = pUser.ResourceCount( 0x1078 ); var hides1 = pUser.ResourceCount( 0x1079 ); + var granite = pUser.ResourceCount( 0x1779 ); + var dullcoppergranite = pUser.ResourceCount( 0x1779, 0x0973 ); + var shadowirongranite = pUser.ResourceCount( 0x1779, 0x0966 ); + var coppergranite = pUser.ResourceCount( 0x1779, 0x07dd ); + var bronzegranite = pUser.ResourceCount( 0x1779, 0x06d6 ); + var goldgranite = pUser.ResourceCount( 0x1779, 0x08a5 ); + var agapitegranite = pUser.ResourceCount( 0x1779, 0x0979 ); + var veritegranite = pUser.ResourceCount( 0x1779, 0x089f ); + var valoritegranite = pUser.ResourceCount( 0x1779, 0x08ab ); + var resourcename = 10291; var resource = iron; var groupList; @@ -140,7 +151,55 @@ function CraftingGumpMenu( myGump, socket ) case 9: // Glassblowing grouplist = [13502]; //CATEGORIES gumpMenuName = 13501;//Cartography Menu - break; + break; + case 10: // Masonry + grouplist = [14002, 14003, 14004, 14005, 14006, 14007, 14008, 14009, 14010] //CATEGORIES + gumpMenuName = 14001;//Masonry Menu + switch( pUser.GetTempTag( "Granite" )) + { + case 0: // Granite + resourcename = 14011; + resource = granite; + break; + case 1: // Dull Copper + resourcename = 14012; + resource = dullcoppergranite; + break; + case 2: // Shadow Iron + resourcename = 14013; + resource = shadowirongranite; + break; + case 3: // Copper + resourcename = 14014; + resource = coppergranite; + break; + case 4: // Bronze + resourcename = 14015; + resource = bronzegranite; + break; + case 5: // Gold + resourcename = 14016; + resource = goldgranite; + break; + case 6: // Agapite + resourcename = 14017; + resource = agapitegranite; + break; + case 7: // Verite + resourcename = 14018; + resource = veritegranite; + break; + case 8: // Valorite + resourcename = 14019; + resource = valoritegranite; + break; + default: // Iron + resourcename = 14011; + resource = irongranite; + break; + } + repair = 49; + break; } myGump.AddPage( 0 ); @@ -346,8 +405,12 @@ function onGumpPress( pSock, pButton, gumpData ) break; case 9: TriggerEvent( Glassblowing, "PageX", pSock, pUser, 1 ); - break; - default: + break; + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 1 ); + } break; } case 2: @@ -377,8 +440,11 @@ function onGumpPress( pSock, pButton, gumpData ) break; case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 2 ); - break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 2 ); + } break; } case 3: @@ -409,7 +475,11 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 3 ); break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 3 ); + } break; } case 4: @@ -437,7 +507,11 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 4 ); break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 4 ); + } break; } case 5: @@ -459,7 +533,11 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 5 ); break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 5 ); + } break; } case 6: @@ -481,7 +559,11 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 6 ); break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 6 ); + } break; } case 7: @@ -503,7 +585,11 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 7 ); break; - default: + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 7 ); + } break; } case 8: @@ -519,6 +605,12 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 8 ); break; + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 8 ); + } + break; } break; case 9: @@ -534,6 +626,12 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 9 ); break; + case 10: + if( pUser.GetTempTag( "Granite" ) >= 0 && pUser.GetTempTag( "Granite" ) <= 8 ) + { + TriggerEvent( Masonry, "PageX", pSock, pUser, 9 ); + } + break; } break; case 10: diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 99410252a..32bd8eb9c 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -10,6 +10,7 @@ const Tinkering = 4032; const Cooking = 4034; const Cartography = 4035; const Glassblowing = 4036; +const Masonry = 4037; /** @type { ( user: Character, iUsing: Item ) => boolean } */ function onUseChecked( pUser, iUsed ) @@ -23,6 +24,7 @@ function onUseChecked( pUser, iUsed ) var gumpID6 = Cooking + 0xffff; var gumpID7 = Tinkering + 0xffff; var gumpID8 = Cartography + 0xffff; + var gumpID10 = Masonry + 0xffff; if( socket && ValidateObject( iUsed ) && iUsed.isItem ) { @@ -269,6 +271,33 @@ function onUseChecked( pUser, iUsed ) break; } } + else if( iUsed.sectionID == "malletandchisel" ) + { + if( pUser.GetTag( "StoneCrafting" ) == 0 ) + { + socket.SysMessage( GetDictionaryEntry( 6297, socket.language ));// You havent learned masonry. + return false; + } + // Masonry + socket.CloseGump( gumpID10, 0 ); + pUser.SetTempTag( "CRAFT", 10 ); + switch( tempPage ) + { + case 1: // Page 1 + case 2: // Page 2 + case 3: // Page 3 + case 4: // Page 4 + case 5: // Page 5 + case 6: // Page 6 + case 7: // Page 7 + case 8: // Page 8 + case 9: // Page 9 + TriggerEvent( Masonry, "PageX", socket, pUser, tempPage); + break; + default: TriggerEvent( Masonry, "PageX", socket, pUser, 1); + break; + } + } } return false; } From 28eea029179f18625bc1724fac323d7966b8c639 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 18 Nov 2025 20:54:47 -0600 Subject: [PATCH 02/43] additions --- data/dfndata/create/masonry.dfn | 107 ++ data/dfndata/create/resources.dfn | 5 + data/dfndata/items/building/decs/misc_sa.dfn | 44 + data/dfndata/items/building/decs/misc_se.dfn | 17 + data/dfndata/items/building/decs/misc_tol.dfn | 17 + data/dfndata/items/misc/crafting_recipes.dfn | 14 + .../dfndata/items/skills/resources/mining.dfn | 2 +- data/dfndata/items/skills/tools/carpenty.dfn | 2 +- data/dictionaries/dictionary.ENG | 25 +- data/dictionaries/dictionary.ZRO | 29 + data/js/skill/craft/crafttool.js | 7 +- data/js/skill/craft/itemdetailgump.js | 72 +- data/js/skill/craft/masonry.js | 1378 +++++++++++++++++ 13 files changed, 1704 insertions(+), 15 deletions(-) create mode 100644 data/dfndata/create/masonry.dfn create mode 100644 data/dfndata/items/building/decs/misc_sa.dfn create mode 100644 data/dfndata/items/building/decs/misc_se.dfn create mode 100644 data/dfndata/items/building/decs/misc_tol.dfn create mode 100644 data/js/skill/craft/masonry.js diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn new file mode 100644 index 000000000..ee67d61c8 --- /dev/null +++ b/data/dfndata/create/masonry.dfn @@ -0,0 +1,107 @@ +[ITEM 3500] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3501] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3502] +{ +NAME=Small Urn +ID=0x241c +RESOURCE=STONE 3 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3503] +{ +NAME=Tower Sculpture +ID=0x241a +RESOURCE=STONE 3 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3504] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3505] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3505] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3506] +{ +NAME=Tall 18th Anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3507] +{ +NAME=Short 18th Anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/resources.dfn b/data/dfndata/create/resources.dfn index fff348454..188fa2388 100644 --- a/data/dfndata/create/resources.dfn +++ b/data/dfndata/create/resources.dfn @@ -163,4 +163,9 @@ ID=0x423A { ID=0x14eb ID=0x0E34 +} + +[RESOURCE STONE] +{ +ID=0x1779 } \ No newline at end of file diff --git a/data/dfndata/items/building/decs/misc_sa.dfn b/data/dfndata/items/building/decs/misc_sa.dfn new file mode 100644 index 000000000..b81df5c7b --- /dev/null +++ b/data/dfndata/items/building/decs/misc_sa.dfn @@ -0,0 +1,44 @@ +[0x403d] +{ +get=base_item +name=gargoyle painting +id=0x403d +weight=1000 +movable=1 +} + +[0x403e] +{ +get=0x403d +id=0x403e +} + +[0x403f] +{ +get=base_item +name=gargoyle sculpture +id=0x403f +weight=100 +movable=1 +} + +[0x4040] +{ +get=0x403f +id=0x4040 +} + +[0x4042] +{ +get=base_item +name=gargoyle vase +id=0x4042 +weight=1000 +movable=1 +} + +[0x403e] +{ +get=0x4042 +id=0x403e +} \ No newline at end of file diff --git a/data/dfndata/items/building/decs/misc_se.dfn b/data/dfndata/items/building/decs/misc_se.dfn new file mode 100644 index 000000000..ea016e08d --- /dev/null +++ b/data/dfndata/items/building/decs/misc_se.dfn @@ -0,0 +1,17 @@ +[0x241C] +{ +get=base_item +name=Small Urn +id=0x241C +weight=100 +movable=1 +} + +[0x241A] +{ +get=base_item +name=Tower Sculpture +id=0x241A +weight=100 +movable=1 +} \ No newline at end of file diff --git a/data/dfndata/items/building/decs/misc_tol.dfn b/data/dfndata/items/building/decs/misc_tol.dfn new file mode 100644 index 000000000..c286e275e --- /dev/null +++ b/data/dfndata/items/building/decs/misc_tol.dfn @@ -0,0 +1,17 @@ +[0x9bc7] +{ +get=base_item +name=Tall 18th Anniversary Vase +id=0x9bc7 +weight=1000 +movable=1 +} + +[0x9bca] +{ +get=base_item +name=Short 18th Anniversary Vase +id=0x9bca +weight=100 +movable=1 +} \ No newline at end of file diff --git a/data/dfndata/items/misc/crafting_recipes.dfn b/data/dfndata/items/misc/crafting_recipes.dfn index 157851d7b..99f6ab82f 100644 --- a/data/dfndata/items/misc/crafting_recipes.dfn +++ b/data/dfndata/items/misc/crafting_recipes.dfn @@ -16,4 +16,18 @@ origin=ml get=base_recipe_scroll custominttag=recipeID 18 customstringtag=recipeName skullcap +} + +[tall_18th_anniversary_vase_recipe] +{ +get=base_recipe_scroll +custominttag=recipeID 3500 +customstringtag=recipeName Tall 18th Anniversary Vase +} + +[short_18th_anniversary_vase_recipe] +{ +get=base_recipe_scroll +custominttag=recipeID 3501 +customstringtag=recipeName Short 18th Anniversary Vase } \ No newline at end of file diff --git a/data/dfndata/items/skills/resources/mining.dfn b/data/dfndata/items/skills/resources/mining.dfn index ecb8b78f9..f5ee7084a 100644 --- a/data/dfndata/items/skills/resources/mining.dfn +++ b/data/dfndata/items/skills/resources/mining.dfn @@ -85,7 +85,7 @@ decay=1 good=46 } -[irongranite] +[granite] { get=base_granite } diff --git a/data/dfndata/items/skills/tools/carpenty.dfn b/data/dfndata/items/skills/tools/carpenty.dfn index 7cb9dfa08..fadaef46a 100644 --- a/data/dfndata/items/skills/tools/carpenty.dfn +++ b/data/dfndata/items/skills/tools/carpenty.dfn @@ -314,7 +314,7 @@ good=51 maxuses=75 usesleft=25 script=2200// uses left tooltip -script=4037// craft tool +script=4031// craft tool } [masonrybook] diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index db4104439..ce9f0de86 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -5037,14 +5037,23 @@ 14009=Stone Stairs 14010=Stone Floors 14011=Granite -14012=DullCopperGranite -14013=ShadowIronGranite -14014=CopperGranite -14015=BronzeGranite -14016=GoldGranite -14017=AgapiteGranite -14018=VeriteGranite -14019=ValoriteGranite +14012=Dull Copper Granite +14013=Shadow Iron Granite +14014=Copper Granite +14015=Bronze Granite +14016=Gold Granite +14017=Agapite Granite +14018=Verite Granite +14019=Valorite Granite +14050=vase +14051=large vase +14052=small urn +14053=Tower Sculpture +14054=gargoyle painting +14055=gargoyle sculpture +14056=gargoyle vase +14057=Tall 18th Anniversary Vase +14058=Short 18th Anniversary Vase // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index dbdce3ff4..00ae9e915 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -5022,6 +5022,35 @@ 13609=empty vials 13610=full vials 13611=spinning hourglass +// 14001 - 14500 Masonary Crafting Skill +14001=Masonry Menu +14002=Decorations +14003=Furniture +14004=Statues +14005=Misc Addons +14006=Stone Armor +14007=Stone Weapons +14008=Stone Walls +14009=Stone Stairs +14010=Stone Floors +14011=Granite +14012=DullCopperGranite +14013=ShadowIronGranite +14014=CopperGranite +14015=BronzeGranite +14016=GoldGranite +14017=AgapiteGranite +14018=VeriteGranite +14019=ValoriteGranite +14050=vase +14051=large vase +14052=small urn +14053=Tower Sculpture +14054=gargoyle painting +14055=gargoyle sculpture +14056=gargoyle vase +14057=Tall 18th Anniversary Vase +14058=Short 18th Anniversary Vase // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 32bd8eb9c..0d2fda5f0 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -292,9 +292,12 @@ function onUseChecked( pUser, iUsed ) case 7: // Page 7 case 8: // Page 8 case 9: // Page 9 - TriggerEvent( Masonry, "PageX", socket, pUser, tempPage); + TriggerEvent( Masonry, "PageX", socket, pUser, tempPage ); break; - default: TriggerEvent( Masonry, "PageX", socket, pUser, 1); + case 20: + TriggerEvent( Masonry, "Page20", socket, pUser ); + break; + default: TriggerEvent( Masonry, "PageX", socket, pUser, 1 ); break; } } diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 78a460347..30d2a1526 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -11,6 +11,7 @@ const scriptID = 4026; // This script const Cooking = 4034; const Cartography = 4035; const Glassblowing = 4036; +const Masonry = 4037; const exceptionalWearablesOnly = true; @@ -1765,6 +1766,52 @@ function ItemDetailGump( pUser ) HARVEST = [13504]; mainSkill = parseInt(pUser.skills.alchemy); break; + //Start masonry + case 3500:// vase + createEntry = CreateEntries[3500]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3501:// large vase + createEntry = CreateEntries[3501]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3502:// small urn + createEntry = CreateEntries[3502]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3503:// Tower Sculpture + createEntry = CreateEntries[3503]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3504:// gargoyle painting + createEntry = CreateEntries[3504]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3505:// gargoyle sculpture + createEntry = CreateEntries[3505]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3506:// gargoyle vase + createEntry = CreateEntries[3506]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3507:// Tall 18th Anniversary Vase + createEntry = CreateEntries[3507]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3508:// Short 18th Anniversary Vase + createEntry = CreateEntries[3508]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; default: break; } @@ -2111,9 +2158,28 @@ function onGumpPress( pSock, pButton, gumpData ) TriggerEvent( Glassblowing, "PageX", pSock, pUser, pUser.GetTempTag( "page" )); break; default: TriggerEvent( Glassblowing, "PageX", pSock, pUser, 1 ); - break; - } - break; + } + break; + case 10: // masonry + pUser.SetTempTag( "ITEMDETAILS", null ) + pSock.CloseGump( gumpID, 0 ); + switch( pUser.GetTempTag("page" )) + { + case 1: // Page 1 + case 2: // Page 2 + case 3: // Page 3 + case 4: // Page 4 + case 5: // Page 5 + case 6: // Page 6 + case 7: // Page 7 + case 8: // Page 8 + case 9: // Page 9 + TriggerEvent( Masonry, "PageX", pSock, pUser, pUser.GetTempTag( "page" )); + break; + default: TriggerEvent( Masonry, "PageX", pSock, pUser, 1 ); + break; + } + break; } } } diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js new file mode 100644 index 000000000..fb4eff0f0 --- /dev/null +++ b/data/js/skill/craft/masonry.js @@ -0,0 +1,1378 @@ +/// +// @ts-check +const textHue = 0x480; // Color of the text. +const scriptID = 4023; // Script ID used to identify and close this gump +const masonryID = scriptID; // Backwards-compat alias +const gumpDelay = 2000; // Timer for the gump to reappear after crafting. +const ingotDelay = 200; // Timer for the gump to reappear after selecting an ingot. +const repairDelay = 200; // Timer for the gump to reappear after repairing an item +const craftGumpID = 4027; +const itemDetailsScriptID = 4026; + +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // Show recipes player has not learned (if we add any later) +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); + +// If enabled, players can craft coloured variants of weapons, though unless the craftItems array +// is updated with specific create entries for the coloured weapon variants, they will just be +// regular weapons with granite colour applied +const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); + +// Optional: if you later decide to make some blacksmith items recipe-locked, we will use this map: +// MasonryMap[buttonID] = { dictID, page, timerID, graniteMake: [makeIDByOre], recipeID?, minEra?, maxEra? } +// o--------------------------------------------------------------------------o +// | Script - blacksmith.js | +// | System - Blacksmith Crafting Gump (Tailoring-style version) | +// o--------------------------------------------------------------------------o +// | Purpose - | +// | Provides the blacksmith crafting menu using the same data-driven | +// | system used by the tailoring script. | +// | | +// | All craftable items are defined in tables (myPage, craftItems) and | +// | then mapped into a BlacksmithMap structure that controls: | +// | - Which dictionary entry is shown per row | +// | - Which "makeID" entry is used for each ore type | +// | - Which page and timer ID to use when reopening the gump | +// | - Optional per-item recipe and era requirements | +// | - Optional per-item custom names for display | +// | | +// | The script also handles: | +// | - Ingot selection (iron / colored ores) with skill requirements | +// | - Smelting metal items back into ingots | +// | - Repairing metal armor and weapons at an anvil | +// | - Tool wear and runic hammer handling | +// | - A "Make Last" feature | +// | - A "Last Ten Blacksmith" list (optional) | +// o--------------------------------------------------------------------------o +// | Data Tables | +// o--------------------------------------------------------------------------o +// | myPage | +// | myPage[pageIndex] = [ dictID1, dictID2, ... ] | +// | pageIndex 0 => Page 1: Metal Armor | +// | pageIndex 1 => Page 2: Helmets | +// | pageIndex 2 => Page 3: Shields | +// | pageIndex 3 => Page 4: Bladed weapons | +// | pageIndex 4 => Page 5: Axes | +// | pageIndex 5 => Page 6: Polearms | +// | pageIndex 6 => Page 7: Bashing weapons | +// | | +// | Each entry is a dictionary ID that will be used to look up the text | +// | for that row, unless a customName is defined for that button in | +// | BlacksmithMap. | +// | | +// | craftItems | +// | craftItems[oreIndex][pageIndex][itemIndex] = makeID | +// | oreIndex 0 = Iron | +// | oreIndex 1 = Dull Copper | +// | oreIndex 2 = Shadow Iron | +// | oreIndex 3 = Copper | +// | oreIndex 4 = Bronze | +// | oreIndex 5 = Gold | +// | oreIndex 6 = Agapite | +// | oreIndex 7 = Verite | +// | oreIndex 8 = Valorite | +// | | +// | For each ore type and page, this holds the createEntry ID used by | +// | MakeItem when the player crafts that item. The same index positions | +// | on each page line up with the matching entries in myPage. | +// o--------------------------------------------------------------------------o +// | BlacksmithMap | +// o--------------------------------------------------------------------------o +// | BlacksmithMap is built automatically from myPage and craftItems. | +// | | +// | BlacksmithMap[buttonID] = { | +// | dictID : number, // Base dictionary entry for the row | +// | page : number, // Main page (1..7, or 999 for Last Ten) | +// | timerID : number, // Timer ID to reopen same page | +// | oreMake : number[], // oreMake[oreIndex] = makeID | +// | customName: string?, // Optional override for display text | +// | recipeID : number?, // Optional recipe requirement | +// | minEra : string?, // Optional minimum shard era | +// | maxEra : string? // Optional maximum shard era | +// | }; | +// | | +// | Button ID mapping (same as original script): | +// | Page 1 (Metal Armor) : 100..112 | +// | Page 2 (Helmets) : 200..204 | +// | Page 3 (Shields) : 300..305 | +// | Page 4 (Bladed) : 400..407 | +// | Page 5 (Axes) : 500..506 | +// | Page 6 (Polearms) : 600..604 | +// | Page 7 (Bashing) : 700..704 | +// | | +// | Custom Names | +// | To override the display name for a specific row, set customName after | +// | the BlacksmithMap has been initialized, for example: | +// | | +// | BlacksmithMap[400].customName = "Elven Broadsword"; | +// | | +// | PageX() will use this order of preference for text: | +// | 1. entry.customName (if set) | +// | 2. GetDictionaryEntry(entry.dictID) | +// | 3. A fallback "[Unnamed Item: buttonID]" | +// | | +// | Recipes | +// | If recipeID is set on a BlacksmithMap entry, onGumpPress will call: | +// | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | +// | to check if the player has learned that recipe. If not, the craft | +// | attempt is blocked and a message is shown. | +// | | +// | Era Gating | +// | The script reads the shard era using: | +// | const coreShardEra = EraStringToNum(GetServerSetting("CoreShardEra")); | +// | | +// | If an entry defines minEra or maxEra (strings like "lbr","aos","ml", | +// | "sa","hs","tol"), eraOK(entry) will ensure the current server era is | +// | within that range before allowing craft or display. | +// o--------------------------------------------------------------------------o +// | Notes | +// o--------------------------------------------------------------------------o +// | - This blacksmith script is intentionally structured to match the | +// | tailoring crafting script, so future changes (recipes, era gating, | +// | new categories, last ten behavior) can be implemented in the same | +// | way for both systems. | +// | - To add new blacksmith items, update myPage and craftItems, then | +// | optionally decorate their BlacksmithMap entries with customName, | +// | recipeID, minEra, and maxEra. | +// o--------------------------------------------------------------------------o + +const myPage = [ + // Page 1 - Decorations + [14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058] + // Page 2 - Helmets + //[10230, 10231, 10232, 10233, 10234], + // Page 3 - Shields + //[10235, 10236, 10237, 10238, 10239, 10293], + // Page 4 - Bladed + //[10240, 10241, 10242, 10243, 10244, 10245, 10246, 10247], + // Page 5 - Axes + //[10248, 10249, 10250, 10251, 10252, 10253, 10254], + // Page 6 - PoleArms + //[10255, 10256, 10257, 10258, 10259], + // Page 7 - Bashing + //[10260, 10261, 10262, 10263, 10264] +]; + +const craftItems = [ + // Iron + [ + // Decorations + [3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508] + // Helmets + //[ 46, 48, 45, 47, 49 ], + // Shields + //[ 1, 2, 6, 3, 5, 4 ], + // Bladed + //[ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + //[ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + //[ 38, 39, 35, 36, 37 ], + // Bashing + //[ 44, 40, 41, 42, 43 ] + ], + + // Dull Copper + [ + // Metal Armors + [ 506, 508, 507, 509, 510, 511, 512, 515, 514, 513, 516, 517, 518 ], + // Helmets + [ 520, 522, 519, 521, 523 ], + // Shields + [ 500, 501, 505, 502, 504, 503 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Shadow Iron + [ + // Metal Armors + [ 606, 608, 607, 609, 610, 611, 612, 615, 614, 613, 616, 617, 618 ], + // Helmets + [ 620, 622, 619, 621, 623 ], + // Shields + [ 600, 601, 605, 602, 604, 603 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Copper + [ + // Metal Armors + [ 706, 708, 707, 709, 710, 711, 7012, 715, 714, 713, 716, 717, 718 ], + // Helmets + [ 720, 722, 719, 721, 723 ], + // Shields + [ 700, 701, 705, 702, 704, 703 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Bronze + [ + // Metal Armors + [ 806, 808, 807, 809, 810, 811, 812, 815, 814, 813, 816, 817, 818 ], + // Helmets + [ 820, 822, 819, 821, 823 ], + // Shields + [ 800, 801, 805, 802, 804, 803 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Gold + [ + // Metal Armors + [ 906, 908, 907, 909, 910, 911, 912, 915, 914, 913, 916, 917, 918 ], + // Helmets + [ 920, 922, 919, 921, 923 ], + // Shields + [ 900, 901, 905, 902, 904, 903 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Agapite + [ + // Metal Armors + [ 1206, 1208, 1207, 1209, 1210, 1211, 1212, 1215, 1214, 1213, 1216, 1217, 1218 ], + // Helmets + [ 1220, 1222, 1219, 1221, 1223 ], + // Shields + [ 1200, 1201, 1205, 1202, 1204, 1203 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Verite + [ + // Metal Armors + [ 1006, 1008, 1007, 1009, 1010, 1011, 1012, 1015, 1014, 1013, 1016, 1017, 1018 ], + // Helmets + [ 1020, 1022, 1019, 1021, 1023 ], + // Shields + [ 1000, 1001, 1005, 1002, 1004, 1003 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ], + + // Valorite + [ + // Metal Armors + [ 1106, 1108, 1107, 1109, 1110, 1111, 1112, 1115, 1114, 1113, 1116, 1117, 1118 ], + // Helmets + [ 1120, 1122, 1119, 1121, 1123 ], + // Shields + [ 1100, 1101, 1105, 1102, 1104, 1103 ], + // Bladed + [ 25, 21, 20, 22, 23, 26, 24, 27 ], + // Axes + [ 29, 28, 32, 30, 33, 31, 34 ], + // Polearms + [ 38, 39, 35, 36, 37 ], + // Bashing + [ 44, 40, 41, 42, 43 ] + ] +]; + +// MasonryMap[buttonID] = { +// dictID: , +// page: , +// timerID: , +// graniteMake: [ makeIDForIron, makeIDForDullCopper, ... ], // index is graniteID (0..8) +// // Optional later: +// // recipeID: , +// // minEra: "lbr" / "aos" / "ml" / "sa" / "hs" / "tol", +// // maxEra: ... +// }; + +const MasonryMap = {}; + +(function initMasonryMap() +{ + // graniteIndex: 0 = iron, 1 = dull copper, ... 8 = valorite + for( var graniteIndex = 0; graniteIndex < craftItems.length; graniteIndex++ ) + { + var graniteRows = craftItems[graniteIndex]; + + // pageIdx: 0..6 => pages 1..7 + for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) + { + var dictList = myPage[pageIdx]; + var makeList = graniteRows[pageIdx]; + + for( var i = 0; i < dictList.length && i < makeList.length; i++ ) + { + // Old script uses: + // page 1 => 100..112 + // page 2 => 200..204 + // page 3 => 300..305 + // etc. + var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; + var dictID = dictList[i]; + var makeID = makeList[i]; + + if( !MasonryMap[buttonID] ) + { + MasonryMap[buttonID] = { + dictID: dictID, + page: pageIdx + 1, + timerID: pageIdx + 1, + graniteMake: [] + // recipeID: undefined, + // minEra: undefined, + // maxEra: undefined + }; + } + + MasonryMap[buttonID].graniteMake[graniteIndex] = makeID; + } + } + } +})(); + +// 3) AFTER initMasonryMap, you can override entries: +// Page 1 Starts buttonID 100 - 108 for map example +//MasonryMap[100].customName = "Elven Broadsword"; +//MasonryMap[100].recipeID = 5101; // if you want it recipe-locked +//MasonryMap[100].minEra = "ml"; // if you want it ML and later only + +MasonryMap[102].minEra = "se"; +MasonryMap[103].minEra = "se"; +MasonryMap[104].minEra = "sa"; +MasonryMap[105].minEra = "sa"; +MasonryMap[106].minEra = "sa"; +MasonryMap[107].minEra = "tol"; +MasonryMap[107].recipeID = 3500; +MasonryMap[108].minEra = "tol"; +MasonryMap[108].recipeID = 3501; + +function PageX( socket, pUser, pageNum ) +{ + if( !ValidateObject( pUser )) + return; + + // Pages 1 - 7: normal crafting pages + // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) + + var subPage = pUser.GetTempTag( "subPage" ); + var pageItems = []; + + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenMasonry" ) || ""; + var split = lastTenRaw.split( "," ); + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val ) && MasonryMap[val] ) + pageItems.push( val ); // here val is the buttonID itself + } + } + else + { + // Build list of buttonIDs for this page from MasonryMap + for( var buttonID in MasonryMap ) + { + var data = MasonryMap[buttonID]; + if( data.page == pageNum && eraOK( data )) + { + // If we later add recipes and want to hide unknown ones: + var needsRecipe = data.recipeID; + var showAll = displayUnlearnedRecipes; + if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) + { + pageItems.push( parseInt( buttonID ) ); + } + } + } + + // Sort by buttonID to keep consistent ordering + pageItems.sort( function( a, b ){ return a - b; } ); + } + + if( pageItems.length == 0 ) + { + var emptyGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", emptyGump, socket ); + emptyGump.AddPage( 1 ); + emptyGump.AddText( 220, 60, textHue, "No items available on this page." ); + emptyGump.Send( socket ); + emptyGump.Free(); + return; + } + + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var resourceHue = pUser.GetTempTag( "resourceHue" ); + var blacksmithMenu = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", blacksmithMenu, socket ); + blacksmithMenu.AddPage( 1 ); + + var drawIndex = 0; + + for( var i = startIndex; i < endIndex; i++ ) + { + var buttonID = pageItems[i]; + var data = MasonryMap[buttonID]; + + // Do not show weapons when colgranited ingots selected and colgranited weapons are disabled + if( !allowColouredWeapons && resourceHue > 0 && data.page > 3 ) + continue; + + var entryText = ""; + if( data.customName ) + { + entryText = data.customName; + } + else if( data.dictID ) + { + entryText = GetDictionaryEntry( data.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + buttonID + "]"; + } + + // Same layout as tailoring: button, text, details button + blacksmithMenu.AddButton( 220, 60 + ( drawIndex * 20 ), 4005, 4007, 1, 0, buttonID ); + blacksmithMenu.AddText( 255, 60 + ( drawIndex * 20 ), textHue, entryText ); + blacksmithMenu.AddButton( 480, 60 + ( drawIndex * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); + + drawIndex++; + } + + // Prev subpage + if( subPage > 1 ) + { + blacksmithMenu.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + blacksmithMenu.AddHTMLGump( 255, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + + // Next subpage + if( subPage < totalSubPages ) + { + blacksmithMenu.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + blacksmithMenu.AddHTMLGump( 405, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + blacksmithMenu.Send( socket ); + blacksmithMenu.Free(); +} + +function Page20( socket, pUser ) +{ + //granite Choices + var myGump = new Gump; + pUser.SetTempTag( "page", 20 ); + TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); + var iron = pUser.ResourceCount( 0x1779 ); + var bronze = pUser.ResourceCount( 0x1779, 0x06d6 ); + var copper = pUser.ResourceCount( 0x1779, 0x07dd ); + var agapite = pUser.ResourceCount( 0x1779, 0x0979 ); + var dullcopper = pUser.ResourceCount( 0x1779, 0x0973 ); + var gold = pUser.ResourceCount( 0x1779, 0x08a5 ); + var shadowiron = pUser.ResourceCount( 0x1779, 0x0966 ); + var valorite = pUser.ResourceCount( 0x1779, 0x08ab ); + var verite = pUser.ResourceCount( 0x1779, 0x089f ); + var myPage20 = [ + GetDictionaryEntry( 14011, socket.language ) + " (" + iron.toString() + ")", + GetDictionaryEntry( 14012, socket.language ) + " (" + dullcopper.toString() + ")", + GetDictionaryEntry( 14013, socket.language ) + " (" + shadowiron.toString() + ")", + GetDictionaryEntry( 14014, socket.language ) + " (" + copper.toString() + ")", + GetDictionaryEntry( 14015, socket.language ) + " (" + bronze.toString() + ")", + GetDictionaryEntry( 14016, socket.language ) + " (" + gold.toString() + ")", + GetDictionaryEntry( 14017, socket.language ) + " (" + agapite.toString() + ")", + GetDictionaryEntry( 14018, socket.language ) + " (" + verite.toString() + ")", + GetDictionaryEntry( 14019, socket.language ) + " (" + valorite.toString() + ")" + ]; + + for( var i = 0; i < myPage20.length; i++ ) + { + var index = i % 10; + if( index == 0 ) + { + if( i > 0 ) + { + myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); + myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + } + + myGump.AddPage(( i / 10 ) + 1 ); + + if( i > 0 ) + { + myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); + myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + } + } + + myGump.AddButton( 220, 60 + ( index * 20), 4005, 4007, 1, 0, 1000 + i ); + myGump.AddText( 255, 60 + ( index * 20), textHue, myPage20[i] ); + } + myGump.Send( socket ); + myGump.Free(); +} + +function FindNearbyAnvils( pUser, trgItem, pSock ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + return ( trgItem.id == 0x0faf || trgItem.id == 0x0fb0 || trgItem.id == 0x2dd5 || trgItem.id == 0x2dd6 ); +} + +function FindNearbyForges( pUser, trgItem, pSock ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + return (( trgItem.id >= 0x197a && trgItem.id <= 0x19a9 ) || trgItem.id == 0x0Fb1 || trgItem.id == 0x2db0 || trgItem.id == 0x2dd8 ); +} + +function SmeltTarget( pSock ) +{ + pSock.CustomTarget( 1, GetDictionaryEntry( 440, pSock.language )); // What item would you like to smelt? +} + +// Armor and weapons can be smelted back into ingots. +/** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ +function onCallback1( pSock, ourObj ) +{ + // Smelt item, get ingots in return + var mChar = pSock.currentChar; + + if( !ValidateObject( ourObj ) || !ourObj.isItem ) + { + // Targeted object is not an item that can be smelted + mChar.SetTempTag( "prevActionResult", "CANTSMELT" ); + mChar.StartTimer( ingotDelay, 1, true ); + return; + } + + var nearbyAnvil = AreaItemFunction( "FindNearbyAnvils", mChar, 3, pSock ); + var nearbyForge = AreaItemFunction( "FindNearbyForges", mChar, 3, pSock ); + if( nearbyForge == 0 || nearbyAnvil == 0) + { + // No forge nearby + mChar.SetTempTag( "prevActionResult", "NOFORGEORANVIL" ); + mChar.StartTimer( ingotDelay, 1, true ); + return; + } + + var creatorSerial = ourObj.creator; + var entryMadeFrom = ourObj.entryMadeFrom; + var createEntry; + if( entryMadeFrom != null && entryMadeFrom != 0 ) + { + createEntry = CreateEntries[entryMadeFrom]; + } + if( createEntry != null && createEntry.id != ourObj.id ) + { + createEntry = null; + } + + var resourceName = "granite"; + var resourceAmount = 0; + var maxResourceAmount = 1; + var resourceHue = ourObj.colour; + + if( creatorSerial == -1 || entryMadeFrom == 0 || createEntry == null ) + { + // Not a player-crafted item, return 1 ingot if item is made of metal + var materialType = TriggerEvent( 2506, "GetItemMaterialType", ourObj ); + if( materialType == "metal" ) + { + resourceAmount = 1; + } + } + else + { + if( createEntry.avgMinSkill > mChar.skills.mining ) + { + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "NOSMELTSKILL" ); + mChar.StartTimer( gumpDelay, 1, true ); + return; + } + + // Loop through resources used to craft item, see how many ingots were used + var resourcesUsed = createEntry.resources; + for( var i = 0; i < resourcesUsed.length; i++ ) + { + var resource = resourcesUsed[i]; + var amountNeeded = resource[0]; + var colorNeeded = resource[1]; + var resourceIDs = resource[2]; + + // Loop through list of resourceIDs that were valid for crafting this item, see if ANY + // were a match for the resource we're trying to return + for( var j = 0; j <= resourceIDs.length; j++ ) + { + // If both resource needed matches up, and resource color matches up, go for it + if( resourceIDs[j] == 0x1bf2 && colorNeeded == resourceHue ) + { + maxResourceAmount = amountNeeded; + break; + } + } + } + + if( maxResourceAmount > 1 ) + { + // Calculate amount of resources returned based on player's mining skill, item's wear and tear, + // and amount of resources that went into making the item in the first place + if ( ourObj.health >= 1 || ourObj.usesLeft >= 1 ) + { + var healthPercentage = 0; + if( ourObj.health >= 1 ) + { + healthPercentage = Math.floor( ( ourObj.health * 100) / ourObj.maxhp ); + } + + var usesPercentage = 0; + if( ourObj.usesLeft >= 1 ) + { + usesPercentage = Math.floor( ( ourObj.usesLeft * 100 ) / ourObj.maxUses ); + } + + var itemPercentage = usesPercentage > 0 ? Math.min( healthPercentage, usesPercentage ) : healthPercentage; + + resourceAmount = Math.floor( ( maxResourceAmount * itemPercentage ) / 100 ); + } + + // Halve the amount of resources returned + resourceAmount = Math.max( Math.floor( resourceAmount / 2 ), 1 ); + + // Fetch player's Mining skill + var playerSkill = mChar.skills.mining; + + // Based on player's Mining skill, return between 1 to maxResourceAmount + resourceAmount = Math.min( Math.max( Math.floor( resourceAmount * ( playerSkill / 1000 )), 1 ), resourceAmount ); + } + else + { + resourceAmount = 1; + } + } + + if( resourceAmount == 0 ) + { + // Targeted object is not an item that can be smelted + mChar.SetTempTag( "prevActionResult", "CANTSMELT" ); + mChar.StartTimer( ingotDelay, 1, true ); + return; + } + + if( ourObj.isDyeable ) + { + // Dyeable items should return regular iron ingots + resourceHue = 0; + } + + switch( resourceHue ) + { + case 0: // Iron granite + default: + break; + case 0x0973: // Dull Copper + resourceName = "dull copper granite"; + break; + case 0x0966: // Shadow Iron + resourceName = "shadow iron granite"; + break; + case 0x07dd: // Copper + resourceName = "copper granite"; + break; + case 0x06d6: // Bronze + resourceName = "bronze granite"; + break; + case 0x08a5: // Gold + resourceName = "gold granite"; + break; + case 0x0979: // Agapite + resourceName = "agapite granite"; + break; + case 0x089f: // Verite + resourceName = "verite granite"; + break; + case 0x08ab: // Valorite + resourceName = "valorite granite"; + break; + } + + // Delete the melted item + ourObj.Delete(); + + // Run a generic skill check to give player a chance to increase their mining skill + mChar.CheckSkill( 45, 0, mChar.skillCaps.mining ); + + var newResource = CreateDFNItem( pSock, mChar, "0x1779", resourceAmount, "ITEM", true, resourceHue ); + newResource.name = resourceName; + + mChar.SetTempTag( "ingotsFromSmelting", resourceAmount ); + mChar.SetTempTag( "prevActionResult", "SMELTITEMSUCCESS" ); + mChar.StartTimer( gumpDelay, 1, true ); +} + +function RepairTarget( pSock ) +{ + pSock.CustomTarget( 2, GetDictionaryEntry( 485, pSock.language )); // What item would you like to repair? +} + +/** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ +function onCallback2( pSock, ourObj ) +{ + // Repair Item + var mChar = pSock.currentChar; + + // Don't continue if character is invalid, or worse... dead! + if( !ValidateObject( mChar ) || mChar.dead ) + return; + + var bItem = pSock.tempObj; + var anvil = AreaItemFunction( "FindNearbyAnvils", mChar, 3, pSock ); + var gumpID = masonryID + 0xffff; + pSock.tempObj = null; + + if( ValidateObject( mChar ) && mChar.isChar && ValidateObject( bItem ) && bItem.isItem ) + { + if( !ValidateObject( ourObj ) || !ourObj.isItem + || TriggerEvent( 2506, "GetItemMaterialType", ourObj ) != "metal" + || !CheckTileFlag( ourObj.id, 22 )) // TF_WEARABLE + { + // Targeted object is not an item that can be repaired + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "CANTREPAIR" ); + mChar.StartTimer( repairDelay, 1, true ); + return; + } + + if( anvil == 0 ) + { + // No anvil nearby + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "NOANVIL" ); + mChar.StartTimer( repairDelay, 1, true ); + return; + } + + var itemDurabilityLossEnabled = GetServerSetting( "ItemRepairDurabilityLoss" ); + var repairID = ourObj.id; + var ownerObj = GetPackOwner( ourObj, 0 ); + if( ownerObj && mChar.serial == ownerObj.serial ) + { + var maxHitpoints = ourObj.maxhp; + var currentHitpoints = ourObj.health; + if( currentHitpoints < maxHitpoints ) + { + // Get base repair difficulty based on amount of HP missing and max hitpoints + var deltaHP = maxHitpoints - currentHitpoints; + var repairDifficulty = (( deltaHP / maxHitpoints ) * 1000 ); + var minDifficulty = repairDifficulty - 250; + var skillBonus = 0; + var repairSkill = mChar.skills.blacksmithing; + if( minDifficulty < 0 ) + { + // If minDifficulty is negative, add the negative value as a bonus to player's skill + skillBonus = minDifficulty * -1; + minDifficulty = 0; + } + else if( minDifficulty > repairSkill ) + { + // Player skill below minimum repair difficulty, Too difficult to make the attempt! + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "CANTREPAIR" ); + mChar.StartTimer( repairDelay, 1, true ); + return; + } + var maxDifficulty = Math.min( repairDifficulty + 250, mChar.skillCaps.blacksmithing ); + + // Allow repair if random number between min and base difficulty is under player's skill + if( RandomNumber( minDifficulty, 1000 ) < ( Math.max( repairSkill + skillBonus, 999 ))) + { + // Give player a chance every now and then to gain skill from repairing + if( RandomNumber( 1, 5 ) == 1 ) + { + // Run a skill-check, which might trigger a skill-gain if player passes + mChar.CheckSkill( 8, minDifficulty, maxDifficulty ); // Skill 8 = blacksmithing + } + + // Reduce object's max durability by 1 + if( itemDurabilityLossEnabled ) + { + ourObj.maxhp -= 1; + } + + // Repair item here + ourObj.health = ourObj.maxhp; + pSock.SoundEffect( 0x002A, true ); + + // Reopen gump after a short delay + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "REPAIRSUCCESS" ); + mChar.StartTimer( repairDelay, 1, true ); + + // GM skill (100.0 skillpoints) + // Item with 51 HP max + // item with 2 hp left - 99.65% chance to repair + // item with 25 hp left - 99.86% chance to repair + // item with 40 hp left - 99.9% chance to repair + + // Expert Smith (71.5 skill points) + // Item with 51 HP max + // item with 2 hp left - 1.45% chance to repair + // item with 25 hp left - 61.49% chance to repair + // item with 40 hp left - 74.9% chance to repair + // item with 48 hp left - 90.6% chance to repair + + // Apprentice Smith (51.5 skill points) + // Item with 51 HP max + // item with 2 hp left - 0% chance to repair + // item with 25 hp left - 34.5% chance to repair + // item with 40 hp left - 54.9% chance to repair + // item with 48 hp left - 70.6% chance to repair + } + else + { + // Failed to repair item - decrease item health! + if( repairSkill >= 1000 ) // GM Smith + { + ourObj.health -= 1; + } + else if( repairSkill >= 715 ) // Expert Smith + { + ourObj.health -= 2; + } + else // Below Expert Smith + { + ourObj.health -= 3; + } + + if( ourObj.health <= 0 ) + { + // Item has been destroyed! + pSock.SysMessage( GetDictionaryEntry( 311, pSock.language ).replace(/%s/gi, ourObj.name )); // Your %s has been destroyed. + ourObj.Delete(); + } + + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "FAILREPAIR" ); + mChar.StartTimer( repairDelay, 1, true ); + } + } + else + { + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "FULLREPAIR" ); + mChar.StartTimer( repairDelay, 1, true ); + } + } + else + { + pSock.tempObj = bItem; + pSock.CloseGump( gumpID, 0 ); + mChar.SetTempTag( "prevActionResult", "CHECKPACK" ); + mChar.StartTimer( repairDelay, 1, true ); + } + } +} + +/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +function onTimer( pUser, timerID ) +{ + if( !ValidateObject( pUser )) + return; + + var socket = pUser.socket; + + if( timerID >= 1 && timerID <= 7 ) + { + PageX( socket, pUser, timerID ); // Pages 1 - 7 + } + else if( timerID == 20 ) + { + Page20( socket, pUser ); // Ingot selection + } + else if( timerID == 999 ) + { + PageX( socket, pUser, 999 ); // Last Ten Blacksmith (if used) + } +} + + +/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ +function onGumpPress( pSock, pButton, gumpData ) +{ + var pUser = pSock.currentChar; + var usedMakeLast = false; + + if( !ValidateObject( pUser ) || pUser.dead ) + return; + + var bItem = pSock.tempObj; + if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + { + pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + return; + } + + if( bItem.movable == 3 ) + { + pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + return; + } + + var iPackOwner = GetPackOwner( bItem, 0 ); + if( ValidateObject( iPackOwner )) + { + if( iPackOwner.serial != pUser.serial ) + { + pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + return; + } + } + else + { + pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack befgranite you can use it. + return; + } + + var gumpID = scriptID + 0xffff; + + // Close / Exit + if( pButton == 0 ) + { + pUser.SetTempTag( "prevActionResult", null ); + pUser.SetTempTag( "MAKELAST", null ); + pSock.CloseGump( gumpID, 0 ); + return; + } + + // Repair Item + if( pButton == 49 ) + { + RepairTarget( pSock ); + return; + } + + // Select Materials (ingots) + if( pButton == 50 ) + { + pSock.CloseGump( gumpID, 0 ); + Page20( pSock, pUser ); + return; + } + + // Smelt Item + if( pButton == 52 ) + { + SmeltTarget( pSock ); + return; + } + + // Page buttons (1..7) + if( pButton >= 1 && pButton <= 7 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + pSock.CloseGump( gumpID, 0 ); + PageX( pSock, pUser, pButton ); + return; + } + + // Last Ten page (if you wire it into the gump) + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, 999 ); + return; + } + + // Subpage navigation (8000 = prev, 9000 = next) + if( pButton >= 8000 && pButton < 9000 ) + { + var prevSub = pButton - 8000; + var curPage = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", prevSub ); + PageX( pSock, pUser, curPage ); + return; + } + + if( pButton >= 9000 && pButton < 10000 ) + { + var nextSub = pButton - 9000; + var curPage2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", nextSub ); + PageX( pSock, pUser, curPage2 ); + return; + } + + // Handle "Make Last" + if(( pButton >= 100 && pButton <= 799 ) || pButton == 5000 ) + { + if( pButton == 5000 ) + { + pButton = pUser.GetTempTag( "MAKELAST" ); + usedMakeLast = true; + } + else + { + pUser.SetTempTag( "MAKELAST", pButton ); + } + } + + // Item detail buttons (2000 + buttonID) + if( pButton >= 2000 && pButton < 3000 ) + { + var detailButtonID = pButton - 2000; + var entry = MasonryMap[detailButtonID]; + if( entry ) + { + // For details we just pass the granite version (granite index 0) to 4026 + var graniteMakeID = entry.graniteMake[0]; + if( graniteMakeID > 0 ) + { + pUser.SetTempTag( "ITEMDETAILS", graniteMakeID ); + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + } + return; + } + + // If this is a craft button in our map: + if( MasonryMap[pButton] != undefined ) + { + var entry2 = MasonryMap[pButton]; + var graniteID = pUser.GetTempTag( "Granite" ); + var resourceHue = pUser.GetTempTag( "resourceHue" ); + + // Ensure graniteID within range + if( graniteID < 0 || graniteID >= craftItems.length ) + graniteID = 0; + + // Era / recipe gating + if( !eraOK( entry2 )) + { + pSock.SysMessage( "That item is not available in this era." ); + return; + } + + if( entry2.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, entry2.recipeID )) + { + pSock.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + // No colored granited weapons if disabled and using non-iron ingots + if( !allowColouredWeapons && resourceHue > 0 && entry2.page > 3 ) + { + pSock.SysMessage( "You cannot use colored granited ingots for weapons on this shard." ); + return; + } + + var makeID = entry2.graniteMake[graniteID]; + if( !makeID || makeID == 0 ) + { + // Fallback to iron version if for some reason we did not get a specific granite entry + makeID = entry2.graniteMake[0]; + } + + if( !makeID || makeID == 0 ) + { + pSock.SysMessage( "That item is not properly configured." ); + return; + } + + // Runic hammer bonus logic (unchanged from your original) + pUser.AddScriptTrigger( 4033 ); + + MakeItem( pSock, pUser, makeID, resourceHue ); + + // Tool wear + var toolUseLimit = GetServerSetting( "ToolUseLimit" ); + var toolUseBreak = GetServerSetting( "ToolUseBreak" ); + + var runicHammer = pUser.FindItemLayer( 0x01 ); // Right Hand + if( ValidateObject( runicHammer ) && runicHammer.GetTag( "runicHammer" ) && runicHammer.usesLeft > 0 ) + { + pUser.SetTempTag( "usedRunicHammer", true ); + pUser.SetTempTag( "runicHammerType", runicHammer.color ); + + if( toolUseLimit && runicHammer != bItem ) + { + runicHammer.usesLeft -= 1; + if( runicHammer.usesLeft == 0 && toolUseBreak ) + { + runicHammer.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); + } + } + } + + if( toolUseLimit ) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && toolUseBreak ) + { + bItem.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); + } + } + + // Track in last ten list for blacksmith + AddToLastTenmMasonry( pUser, pButton ); + + // Reopen page after delay + pUser.StartTimer( gumpDelay, entry2.timerID, true ); + return; + } + + // Granite selection buttons (Page20) + if( pButton >= 1000 && pButton <= 1008 ) + { + var index = pButton - 1000; // 0..8 + var newGraniteID = index; + var newResourceHue = 0; + + // Optional: use Mining skill gating like ingots + var miningSkill = pUser.skills.mining | 0; + + switch( index ) + { + case 0: // Iron + newResourceHue = 0; + break; + + case 1: // Dull Copper + if( miningSkill < 650 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0973; + break; + + case 2: // Shadow Iron + if( miningSkill < 700 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0966; + break; + + case 3: // Copper + if( miningSkill < 750 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x07dd; + break; + + case 4: // Bronze + if( miningSkill < 800 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x06d6; + break; + + case 5: // Gold + if( miningSkill < 850 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x08a5; + break; + + case 6: // Agapite + if( miningSkill < 900 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0979; + break; + + case 7: // Verite + if( miningSkill < 950 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x089f; + break; + + case 8: // Valorite + if( miningSkill < 990 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x08ab; + break; + } + + // Store selection + pUser.SetTempTag( "Granite", newGraniteID ); + pUser.SetTempTag( "resourceHue", newResourceHue ); + pUser.SetTempTag( "prevActionResult", null ); + pUser.SetTempTag( "MAKELAST", null ); + + // Close the material select gump + pSock.CloseGump( gumpID, 0 ); + + // Go back to the last craft page, or default to page 1 + var curPage = pUser.GetTempTag( "page" ); + if( !curPage || curPage == 20 ) + curPage = 1; + + pUser.SetTempTag( "page", curPage ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, curPage ); + return; + } +} + +function AddToLastTenmMasonry( pUser, buttonID ) +{ + var raw = pUser.GetTempTag( "LastTenMasonry" ) || ""; + var list = raw.split( "," ); + + // Remove if already in list + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == buttonID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [buttonID]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenMasonry", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + // Optional per-entry gates. Strings like "lbr","aos","ml","sa","hs","tol". + // If not present, the entry is valid for all eras. + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file From 235e091a09e40b7cc08bddf6b4d82374ff09e28f Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 19 Nov 2025 21:29:22 -0600 Subject: [PATCH 03/43] Update itemlists.dfn --- data/dfndata/items/itemlists/itemlists.dfn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/dfndata/items/itemlists/itemlists.dfn b/data/dfndata/items/itemlists/itemlists.dfn index b9eba6b67..f3c57ea2b 100644 --- a/data/dfndata/items/itemlists/itemlists.dfn +++ b/data/dfndata/items/itemlists/itemlists.dfn @@ -1226,7 +1226,7 @@ itemlist=randomgranite [ITEMLIST randomgranite] { -irongranite +granite dullcoppergranite shadowirongranite coppergranite From b133bf946975b5be2c44f12b999ef90221921b59 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 19 Nov 2025 23:10:19 -0600 Subject: [PATCH 04/43] update --- data/dfndata/create/masonry.dfn | 158 ++++++++++++++- data/dfndata/house/house.dfn | 186 ++++++++++++++++++ data/dfndata/items/building/decs/misc_sa.dfn | 57 ++++++ data/dfndata/items/building/decs/stoneart.dfn | 4 +- .../items/building/furniture/chairs.dfn | 8 +- data/dfndata/items/deeds/houseaddon_deeds.dfn | 45 +++++ data/dictionaries/dictionary.ENG | 12 ++ data/dictionaries/dictionary.ZRO | 12 ++ data/js/skill/craft/itemdetailgump.js | 55 ++++++ data/js/skill/craft/masonry.js | 152 +++++++------- 10 files changed, 613 insertions(+), 76 deletions(-) diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index ee67d61c8..239aaa743 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -104,4 +104,160 @@ ADDITEM=0x9bca MINRANK=1 MAXRANK=10 SOUND=0x23D -} \ No newline at end of file +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 3508] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 +SKILL=11 550 105 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3509] +{ +NAME=stone table (east) +ID=0x14F0 +RESOURCE=STONE 6 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3510] +{ +NAME=stone table (south) +ID=0x14F0 +RESOURCE=STONE 6 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3511] +{ +NAME=large stone table (east) +ID=0x14F0 +RESOURCE=STONE 9 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3512] +{ +NAME=large stone table (south) +ID=0x14F0 +RESOURCE=STONE 9 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3513] +{ +NAME=ritual table +ID=0x14F0 +RESOURCE=STONE 8 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Statues ///// +////////////////////////////////////// + +[ITEM 3514] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3515] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3516] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3517] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3518] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3519] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc Addons ///// +////////////////////////////////////// \ No newline at end of file diff --git a/data/dfndata/house/house.dfn b/data/dfndata/house/house.dfn index 8ef288aae..96f05211d 100644 --- a/data/dfndata/house/house.dfn +++ b/data/dfndata/house/house.dfn @@ -1639,6 +1639,80 @@ HOUSE_ITEM=629 HOUSE_ITEM=630 } +// House Addon - stone table (east) +[HOUSE 210] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=mediumstonetableeastdeed +HOUSE_ITEM=631 +HOUSE_ITEM=632 +} + +// House Addon - stone table (south) +[HOUSE 211] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=mediumstonetablesouthdeed +HOUSE_ITEM=633 +HOUSE_ITEM=634 +} + +// House Addon - large stone table (east) +[HOUSE 212] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=largestonetableeastdeed +HOUSE_ITEM=635 +HOUSE_ITEM=636 +HOUSE_ITEM=637 +} + +// House Addon - large stone table (south) +[HOUSE 213] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=largestonetablesouthdeed +HOUSE_ITEM=638 +HOUSE_ITEM=639 +HOUSE_ITEM=640 +} + +// House Addon - ritual table +[HOUSE 214] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=ritualtabledeed +HOUSE_ITEM=641 +HOUSE_ITEM=642 +HOUSE_ITEM=643 +HOUSE_ITEM=644 +} + [HOUSE ITEM 1] { Wooden Door (Small house) ITEM=0x06A5 @@ -3891,6 +3965,118 @@ Y=2 Z=0 } +[HOUSE ITEM 631] +{ +ITEM=0x1202 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 632] +{ +ITEM=0x1201 +X=0 +Y=1 +Z=0 +} + +[HOUSE ITEM 633] +{ +ITEM=0x1205 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 634] +{ +ITEM=0x1204 +X=1 +Y=0 +Z=0 +} + +[HOUSE ITEM 635] +{ +ITEM=0x1202 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 636] +{ +ITEM=0x1203 +X=0 +Y=1 +Z=0 +} + +[HOUSE ITEM 637] +{ +ITEM=0x1201 +X=0 +Y=2 +Z=0 +} + +[HOUSE ITEM 638] +{ +ITEM=0x1205 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 639] +{ +ITEM=0x1206 +X=1 +Y=0 +Z=0 +} + +[HOUSE ITEM 640] +{ +ITEM=0x1204 +X=2 +Y=0 +Z=0 +} + +[HOUSE ITEM 641] +{ +ITEM=0x4985 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 642] +{ +ITEM=0x4984 +X=0 +Y=1 +Z=0 +} + +[HOUSE ITEM 643] +{ +ITEM=0x4983 +X=1 +Y=0 +Z=0 +} + +[HOUSE ITEM 644] +{ +ITEM=0x4982 +X=1 +Y=1 +Z=0 +} + // Dull Copper Colored Anvil 1/1 [HOUSE ITEM 700] { diff --git a/data/dfndata/items/building/decs/misc_sa.dfn b/data/dfndata/items/building/decs/misc_sa.dfn index b81df5c7b..474a7d88a 100644 --- a/data/dfndata/items/building/decs/misc_sa.dfn +++ b/data/dfndata/items/building/decs/misc_sa.dfn @@ -41,4 +41,61 @@ movable=1 { get=0x4042 id=0x403e +} + +[0x4985] +{ +get=base_item +name=ritual table +id=0x4985 +weight=1000 +movable=2 +} + +[0x4984] +{ +get=0x4985 +id=0x4984 +} + +[0x4983] +{ +get=0x4985 +id=0x4983 +} + +[0x4982] +{ +get=0x4985 +id=0x4982 +} + +[0x494e] +{ +get=base_item +name=gargoyle statue +id=0x494e +weight=100 +movable=2 +} + +[0x494d] +{ +get=0x494e +id=0x494d +} + +[0x493e] +{ +get=base_item +name=gryphon statue +id=0x493e +weight=100 +movable=2 +} + +[0x493b] +{ +get=0x493e +id=0x493b } \ No newline at end of file diff --git a/data/dfndata/items/building/decs/stoneart.dfn b/data/dfndata/items/building/decs/stoneart.dfn index 290036814..efbb39478 100644 --- a/data/dfndata/items/building/decs/stoneart.dfn +++ b/data/dfndata/items/building/decs/stoneart.dfn @@ -228,9 +228,9 @@ decay=1 [0x139d] { S pegasus get=base_item -name=statue +name=pegasus statuette id=0x139d -weight=1000 +weight=100 movable=1 decay=1 } diff --git a/data/dfndata/items/building/furniture/chairs.dfn b/data/dfndata/items/building/furniture/chairs.dfn index 21b636a28..9348c29ad 100644 --- a/data/dfndata/items/building/furniture/chairs.dfn +++ b/data/dfndata/items/building/furniture/chairs.dfn @@ -607,7 +607,7 @@ movable=2 get=base_item name=stone chair id=0x1218 -weight=4000 +weight=1000 value=30 15 restock=10 movable=1 @@ -620,7 +620,7 @@ good=1 get=base_item name=stone chair id=0x1219 -weight=4000 +weight=1000 value=30 15 restock=10 movable=1 @@ -633,7 +633,7 @@ good=1 get=base_item name=stone chair id=0x121a -weight=4000 +weight=1000 value=30 15 restock=10 movable=1 @@ -646,7 +646,7 @@ good=1 get=base_item name=stone chair id=0x121b -weight=4000 +weight=1000 value=30 15 restock=10 movable=1 diff --git a/data/dfndata/items/deeds/houseaddon_deeds.dfn b/data/dfndata/items/deeds/houseaddon_deeds.dfn index 9bd5fecbd..92da87dfb 100644 --- a/data/dfndata/items/deeds/houseaddon_deeds.dfn +++ b/data/dfndata/items/deeds/houseaddon_deeds.dfn @@ -486,3 +486,48 @@ origin=uor { get=dc_anvil_deed si_anvil_deed c_anvil_deed b_anvil_deed g_anvil_deed a_anvil_deed ve_anvil_deed va_anvil_deed } + +[mediumstonetableeastdeed] +{ +name=stone table (east) +id=0x14f0 +morex=210 +value=1000 500 +restock=15 +} + +[mediumstonetablesouthdeed] +{ +name=stone table (south) +id=0x14f0 +morex=211 +value=1000 500 +restock=15 +} + +[largestonetableeastdeed] +{ +name=large stone table (east) +id=0x14f0 +morex=212 +value=1000 500 +restock=15 +} + +[largestonetablesouthdeed] +{ +name=large stone table (south) +id=0x14f0 +morex=213 +value=1000 500 +restock=15 +} + +[ritualtabledeed] +{ +name=ritual table +id=0x14f0 +morex=214 +value=1000 500 +restock=15 +} \ No newline at end of file diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index ce9f0de86..0ceac9385 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -5054,6 +5054,18 @@ 14056=gargoyle vase 14057=Tall 18th Anniversary Vase 14058=Short 18th Anniversary Vase +14059=stone chair +14060=stone table (east) +14061=stone table (south) +14062=large stone table (east) +14063=large stone table (south) +14064=ritual table +14065=small statue (south) +14066=small statue (north) +14067=small statue (east) +14068=pegasus statuette +14069=gargoyle statue +14070=gryphon statue // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index 00ae9e915..6ae82cd07 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -5051,6 +5051,18 @@ 14056=gargoyle vase 14057=Tall 18th Anniversary Vase 14058=Short 18th Anniversary Vase +14059=stone chair +14060=stone table (east) +14061=stone table (south) +14062=large stone table (east) +14063=large stone table (south) +14064=ritual table +14065=small statue (south) +14066=small statue (north) +14067=small statue (east) +14068=pegasus statuette +14069=gargoyle statue +14070=gryphon statue // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 30d2a1526..186be0522 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -1812,6 +1812,61 @@ function ItemDetailGump( pUser ) HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; + case 3509:// + createEntry = CreateEntries[3509]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3510:// + createEntry = CreateEntries[3510]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3511:// + createEntry = CreateEntries[3511]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3512:// + createEntry = CreateEntries[3512]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3513:// + createEntry = CreateEntries[3513]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3514:// + createEntry = CreateEntries[3514]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3515:// + createEntry = CreateEntries[3515]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3516:// + createEntry = CreateEntries[3516]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3517:// + createEntry = CreateEntries[3517]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3518:// + createEntry = CreateEntries[3518]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3519:// + createEntry = CreateEntries[3519]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; default: break; } diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index fb4eff0f0..57785f9f5 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -18,18 +18,18 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); // regular weapons with granite colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); -// Optional: if you later decide to make some blacksmith items recipe-locked, we will use this map: +// Optional: if you later decide to make some masonry items recipe-locked, we will use this map: // MasonryMap[buttonID] = { dictID, page, timerID, graniteMake: [makeIDByOre], recipeID?, minEra?, maxEra? } // o--------------------------------------------------------------------------o -// | Script - blacksmith.js | -// | System - Blacksmith Crafting Gump (Tailoring-style version) | +// | Script - masonry.js | +// | System - Masonry Crafting Gump | // o--------------------------------------------------------------------------o // | Purpose - | // | Provides the blacksmith crafting menu using the same data-driven | // | system used by the tailoring script. | // | | // | All craftable items are defined in tables (myPage, craftItems) and | -// | then mapped into a BlacksmithMap structure that controls: | +// | then mapped into a MasonryMap structure that controls: | // | - Which dictionary entry is shown per row | // | - Which "makeID" entry is used for each ore type | // | - Which page and timer ID to use when reopening the gump | @@ -37,12 +37,12 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); // | - Optional per-item custom names for display | // | | // | The script also handles: | -// | - Ingot selection (iron / colored ores) with skill requirements | -// | - Smelting metal items back into ingots | -// | - Repairing metal armor and weapons at an anvil | +// | - Granite selection (iron / colored ores) with skill requirements | +// | - Smelting stone items back into Granite | +// | - Repairing stone armor and weapons at an anvil | // | - Tool wear and runic hammer handling | // | - A "Make Last" feature | -// | - A "Last Ten Blacksmith" list (optional) | +// | - A "Last Ten Masonry" list (optional) | // o--------------------------------------------------------------------------o // | Data Tables | // o--------------------------------------------------------------------------o @@ -58,33 +58,33 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); // | | // | Each entry is a dictionary ID that will be used to look up the text | // | for that row, unless a customName is defined for that button in | -// | BlacksmithMap. | +// | MasonryMap. | // | | // | craftItems | -// | craftItems[oreIndex][pageIndex][itemIndex] = makeID | -// | oreIndex 0 = Iron | -// | oreIndex 1 = Dull Copper | -// | oreIndex 2 = Shadow Iron | -// | oreIndex 3 = Copper | -// | oreIndex 4 = Bronze | -// | oreIndex 5 = Gold | -// | oreIndex 6 = Agapite | -// | oreIndex 7 = Verite | -// | oreIndex 8 = Valorite | +// | craftItems[graniteIndex][pageIndex][itemIndex] = makeID | +// | graniteIndex 0 = Iron | +// | graniteIndex 1 = Dull Copper | +// | graniteIndex 2 = Shadow Iron | +// | graniteIndex 3 = Copper | +// | graniteIndex 4 = Bronze | +// | graniteIndex 5 = Gold | +// | graniteIndex 6 = Agapite | +// | graniteIndex 7 = Verite | +// | graniteIndex 8 = Valorite | // | | -// | For each ore type and page, this holds the createEntry ID used by | +// | For each granite type and page, this holds the createEntry ID used by | // | MakeItem when the player crafts that item. The same index positions | // | on each page line up with the matching entries in myPage. | // o--------------------------------------------------------------------------o -// | BlacksmithMap | +// | MasonryMap | // o--------------------------------------------------------------------------o -// | BlacksmithMap is built automatically from myPage and craftItems. | +// | MasonryMap is built automatically from myPage and craftItems. | // | | -// | BlacksmithMap[buttonID] = { | +// | MasonryMap[buttonID] = { | // | dictID : number, // Base dictionary entry for the row | // | page : number, // Main page (1..7, or 999 for Last Ten) | // | timerID : number, // Timer ID to reopen same page | -// | oreMake : number[], // oreMake[oreIndex] = makeID | +// | graniteMake : number[], // graniteMake[graniteIndex] = makeID | // | customName: string?, // Optional override for display text | // | recipeID : number?, // Optional recipe requirement | // | minEra : string?, // Optional minimum shard era | @@ -92,19 +92,21 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); // | }; | // | | // | Button ID mapping (same as original script): | -// | Page 1 (Metal Armor) : 100..112 | -// | Page 2 (Helmets) : 200..204 | -// | Page 3 (Shields) : 300..305 | -// | Page 4 (Bladed) : 400..407 | -// | Page 5 (Axes) : 500..506 | -// | Page 6 (Polearms) : 600..604 | -// | Page 7 (Bashing) : 700..704 | +// | Page 1 (Decorations) : 100..108 | +// | Page 2 (Furniture) : 200..205 | +// | Page 3 (Statues) : 300..305 | +// | Page 4 (Misc Addons) : 400..407 | +// | Page 5 (Stone Armor) : 500..506 | +// | Page 6 (Stone Weapons) : 600..604 | +// | Page 7 (Stone Walls): 700..704 | +// | Page 8 (Stone Stairs): 800..804 | +// | Page 9 (Stone Floors): 900..904 | // | | // | Custom Names | // | To override the display name for a specific row, set customName after | -// | the BlacksmithMap has been initialized, for example: | +// | the MasonryMap has been initialized, for example: | // | | -// | BlacksmithMap[400].customName = "Elven Broadsword"; | +// | MasonryMap[100].customName = "Hump vase"; | // | | // | PageX() will use this order of preference for text: | // | 1. entry.customName (if set) | @@ -112,7 +114,7 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); // | 3. A fallback "[Unnamed Item: buttonID]" | // | | // | Recipes | -// | If recipeID is set on a BlacksmithMap entry, onGumpPress will call: | +// | If recipeID is set on a MasonryMap entry, onGumpPress will call: | // | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | // | to check if the player has learned that recipe. If not, the craft | // | attempt is blocked and a message is shown. | @@ -127,29 +129,29 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); // o--------------------------------------------------------------------------o // | Notes | // o--------------------------------------------------------------------------o -// | - This blacksmith script is intentionally structured to match the | -// | tailoring crafting script, so future changes (recipes, era gating, | -// | new categories, last ten behavior) can be implemented in the same | -// | way for both systems. | -// | - To add new blacksmith items, update myPage and craftItems, then | -// | optionally decorate their BlacksmithMap entries with customName, | +// | - To add new Masonry items, update myPage and craftItems, then | +// | optionally decorate their MasonryMap entries with customName, | // | recipeID, minEra, and maxEra. | // o--------------------------------------------------------------------------o const myPage = [ // Page 1 - Decorations - [14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058] - // Page 2 - Helmets - //[10230, 10231, 10232, 10233, 10234], - // Page 3 - Shields - //[10235, 10236, 10237, 10238, 10239, 10293], - // Page 4 - Bladed + [14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058], + // Page 2 - Furniture + [14059, 14060, 14061, 14062, 14063, 14064], + // Page 3 - Statues + [14065, 14066, 14067, 14068, 14069, 14070] + // Page 4 - Misc Addons //[10240, 10241, 10242, 10243, 10244, 10245, 10246, 10247], - // Page 5 - Axes + // Page 5 - Stone Armor //[10248, 10249, 10250, 10251, 10252, 10253, 10254], - // Page 6 - PoleArms + // Page 6 - Stone Weapons //[10255, 10256, 10257, 10258, 10259], - // Page 7 - Bashing + // Page 7 - Stone Walls + //[10260, 10261, 10262, 10263, 10264] + // Page 8 - Stone Stairs + //[10260, 10261, 10262, 10263, 10264] + // Page 9 - Stone Floors //[10260, 10261, 10262, 10263, 10264] ]; @@ -157,18 +159,22 @@ const craftItems = [ // Iron [ // Decorations - [3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508] - // Helmets - //[ 46, 48, 45, 47, 49 ], - // Shields - //[ 1, 2, 6, 3, 5, 4 ], - // Bladed + [3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507], + // Furniture + [ 3508, 3509, 3510, 3511, 3512, 3513 ], + // Statues + [ 3514, 3515, 3516, 3517, 3518, 3519 ] + // Misc Addons //[ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes + // Stone Armor //[ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms + // Stone Weapons //[ 38, 39, 35, 36, 37 ], - // Bashing + // Stone Walls + //[ 44, 40, 41, 42, 43 ] + // Stone Stairs + //[ 44, 40, 41, 42, 43 ] + // Stone Floors //[ 44, 40, 41, 42, 43 ] ], @@ -374,21 +380,29 @@ const MasonryMap = {}; })(); // 3) AFTER initMasonryMap, you can override entries: -// Page 1 Starts buttonID 100 - 108 for map example +// Page 1 Starts buttonID 100 - 107 for map example //MasonryMap[100].customName = "Elven Broadsword"; //MasonryMap[100].recipeID = 5101; // if you want it recipe-locked //MasonryMap[100].minEra = "ml"; // if you want it ML and later only -MasonryMap[102].minEra = "se"; -MasonryMap[103].minEra = "se"; -MasonryMap[104].minEra = "sa"; -MasonryMap[105].minEra = "sa"; -MasonryMap[106].minEra = "sa"; -MasonryMap[107].minEra = "tol"; +//Page 1 starts at 100 +MasonryMap[102].minEra = "se"; // small urn +MasonryMap[103].minEra = "se"; // Tower Sculpture +MasonryMap[104].minEra = "sa"; // gargoyle painting +MasonryMap[105].minEra = "sa"; // gargoyle sculpture +MasonryMap[106].minEra = "sa"; // gargoyle vase +MasonryMap[107].minEra = "tol"; // Tall 18th Anniversary Vase MasonryMap[107].recipeID = 3500; -MasonryMap[108].minEra = "tol"; +MasonryMap[108].minEra = "tol"; // Short 18th Anniversary Vase MasonryMap[108].recipeID = 3501; +//Page 2 starts at 200 +MasonryMap[205].minEra = "sa"; // ritual table + +//Page 3 starts at 300 +MasonryMap[304].minEra = "sa"; // gargoyle statue +MasonryMap[305].minEra = "sa"; // gryphon statue + function PageX( socket, pUser, pageNum ) { if( !ValidateObject( pUser )) @@ -1041,8 +1055,8 @@ function onGumpPress( pSock, pButton, gumpData ) return; } - // Page buttons (1..7) - if( pButton >= 1 && pButton <= 7 ) + // Page buttons (1..9) + if( pButton >= 1 && pButton <= 9 ) { pUser.SetTempTag( "page", pButton ); pUser.SetTempTag( "subPage", 1 ); @@ -1080,7 +1094,7 @@ function onGumpPress( pSock, pButton, gumpData ) } // Handle "Make Last" - if(( pButton >= 100 && pButton <= 799 ) || pButton == 5000 ) + if(( pButton >= 100 && pButton <= 998 ) || pButton == 5000 ) { if( pButton == 5000 ) { From 3e81d1a7aa050db124b0731c86ea8a2c6d6ed4ed Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:08:01 -0600 Subject: [PATCH 05/43] updates --- data/dfndata/create/masonry.dfn | 332 +++++++++++++++++- data/dfndata/house/house.dfn | 48 --- data/dfndata/house/house_addons_ml.dfn | 42 +++ data/dfndata/house/house_addons_sa.dfn | 293 ++++++++++++++++ .../items/building/furniture/beds_sa.dfn | 116 ++++++ .../items/building/furniture/chairs_sa.dfn | 31 ++ .../items/building/walls/craftablewalls.dfn | 182 ++++++++++ data/dfndata/items/deeds/houseaddon_deeds.dfn | 9 - .../items/deeds/houseaddon_deeds_ml.dfn | 20 ++ .../items/deeds/houseaddon_deeds_sa.dfn | 49 +++ data/dfndata/items/misc/crafting_recipes.dfn | 18 + data/dfndata/items/misc/jewelry_sa.dfn | 32 ++ .../items/skills/tools/blacksmithy.dfn | 17 +- data/js/item/buildingcraftables.js | 136 +++++++ data/js/item/interiordecorator.js | 33 +- data/js/jse_fileassociations.scp | 1 + data/js/server/house/houseCommands.js | 2 +- data/js/server/misc/furniture_smartturn.js | 166 +++++++-- 18 files changed, 1431 insertions(+), 96 deletions(-) create mode 100644 data/dfndata/house/house_addons_sa.dfn create mode 100644 data/dfndata/items/building/furniture/beds_sa.dfn create mode 100644 data/dfndata/items/building/furniture/chairs_sa.dfn create mode 100644 data/dfndata/items/building/walls/craftablewalls.dfn create mode 100644 data/dfndata/items/deeds/houseaddon_deeds_sa.dfn create mode 100644 data/dfndata/items/misc/jewelry_sa.dfn create mode 100644 data/js/item/buildingcraftables.js diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index 239aaa743..960e71c7f 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -125,7 +125,7 @@ SOUND=0x23D [ITEM 3509] { NAME=stone table (east) -ID=0x14F0 +ID=0x14f0 RESOURCE=STONE 6 SKILL=11 650 1150 ADDITEM=mediumstonetableeastdeed @@ -137,7 +137,7 @@ SOUND=0x23D [ITEM 3510] { NAME=stone table (south) -ID=0x14F0 +ID=0x14f0 RESOURCE=STONE 6 SKILL=11 650 1150 ADDITEM=mediumstonetablesouthdeed @@ -149,7 +149,7 @@ SOUND=0x23D [ITEM 3511] { NAME=large stone table (east) -ID=0x14F0 +ID=0x14f0 RESOURCE=STONE 9 SKILL=11 750 1250 ADDITEM=largestonetableeastdeed @@ -161,7 +161,7 @@ SOUND=0x23D [ITEM 3512] { NAME=large stone table (south) -ID=0x14F0 +ID=0x14f0 RESOURCE=STONE 9 SKILL=11 750 1250 ADDITEM=largestonetablesouthdeed @@ -173,7 +173,7 @@ SOUND=0x23D [ITEM 3513] { NAME=ritual table -ID=0x14F0 +ID=0x14f0 RESOURCE=STONE 8 SKILL=11 940 1030 ADDITEM=ritualtabledeed @@ -260,4 +260,324 @@ SOUND=0x23D ////////////////////////////////////// //// Misc Addons ///// -////////////////////////////////////// \ No newline at end of file +////////////////////////////////////// + +[ITEM 3520] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3521] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3522] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3523] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3524] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3525] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Stone Armor ///// +////////////////////////////////////// + +[ITEM 3526] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3527] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3528] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3529] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3530] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3531] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3532] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3533] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3534] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3535] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Stone Weapons ///// +////////////////////////////////////// + +[ITEM 3536] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Stone Walls ///// +////////////////////////////////////// + +[ITEM 3537] +{ +NAME=Rough Windowless +ID=0x01D0 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughWindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3538] +{ +NAME=Rough Window +ID=0x01D3 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughWindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3539] +{ +NAME=Rough Arch +ID=0x01D5 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughArch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3540] +{ +NAME=Rough Pillar +ID=0x01DA +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughPillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3541] +{ +NAME=Rough Rounded Arch +ID=0x01DB +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughRoundedArch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3542] +{ +NAME=Rough Small Arch +ID=0x01E0 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughSmallArch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3543] +{ +NAME=Rough Angled Pillar +ID=0x01E6 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=RoughAngledPillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3544] +{ +NAME=Short Rough +ID=0x01E8 +RESOURCE=STONE 10 +SKILL=11 600 110 +ADDITEM=ShortRough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/house/house.dfn b/data/dfndata/house/house.dfn index 96f05211d..2fcbf6ccf 100644 --- a/data/dfndata/house/house.dfn +++ b/data/dfndata/house/house.dfn @@ -1697,22 +1697,6 @@ HOUSE_ITEM=639 HOUSE_ITEM=640 } -// House Addon - ritual table -[HOUSE 214] -{ -ID=0x14F0 -SPACEX=1 -SPACEY=1 -CHARX=0 -CHARY=0 -CHARZ=0 -HOUSE_DEED=ritualtabledeed -HOUSE_ITEM=641 -HOUSE_ITEM=642 -HOUSE_ITEM=643 -HOUSE_ITEM=644 -} - [HOUSE ITEM 1] { Wooden Door (Small house) ITEM=0x06A5 @@ -4045,38 +4029,6 @@ Y=0 Z=0 } -[HOUSE ITEM 641] -{ -ITEM=0x4985 -X=0 -Y=0 -Z=0 -} - -[HOUSE ITEM 642] -{ -ITEM=0x4984 -X=0 -Y=1 -Z=0 -} - -[HOUSE ITEM 643] -{ -ITEM=0x4983 -X=1 -Y=0 -Z=0 -} - -[HOUSE ITEM 644] -{ -ITEM=0x4982 -X=1 -Y=1 -Z=0 -} - // Dull Copper Colored Anvil 1/1 [HOUSE ITEM 700] { diff --git a/data/dfndata/house/house_addons_ml.dfn b/data/dfndata/house/house_addons_ml.dfn index 57d6fe89d..3fc3f45e4 100644 --- a/data/dfndata/house/house_addons_ml.dfn +++ b/data/dfndata/house/house_addons_ml.dfn @@ -346,6 +346,32 @@ HOUSE_ITEM=1058 HOUSE_ITEM=1059 } +// House Addon - stone anvil (east) +[HOUSE 324] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=stoneanvileastdeed +HOUSE_ITEM=1060 +} + +// House Addon - stone anvil (south) +[HOUSE 325] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=stoneanvilsouthdeed +HOUSE_ITEM=1061 +} + [HOUSE ITEM 1000] { alchemist table part 1 (east) ITEM=0x3077 @@ -825,4 +851,20 @@ ITEM=0x3056 X=0 Y=1 Z=0 +} + +[HOUSE ITEM 1060] +{ stone anvil east +ITEM=0x2dd6 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 1061] +{ stone anvil south +ITEM=0x2dd5 +X=0 +Y=0 +Z=0 } \ No newline at end of file diff --git a/data/dfndata/house/house_addons_sa.dfn b/data/dfndata/house/house_addons_sa.dfn new file mode 100644 index 000000000..1c31010bf --- /dev/null +++ b/data/dfndata/house/house_addons_sa.dfn @@ -0,0 +1,293 @@ +// House Addon - ritual table +[HOUSE 2000] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=ritualtabledeed +HOUSE_ITEM=2000 +HOUSE_ITEM=2001 +HOUSE_ITEM=2002 +HOUSE_ITEM=2003 +} + +// House Addon - large gargish bed (east) +[HOUSE 2001] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=largegargoylebedeastdeed +HOUSE_ITEM=2006 +HOUSE_ITEM=2007 +HOUSE_ITEM=2008 +HOUSE_ITEM=2009 +HOUSE_ITEM=2010 +HOUSE_ITEM=2011 +HOUSE_ITEM=2012 +HOUSE_ITEM=2013 +HOUSE_ITEM=2014 +} + +// House Addon - large gargish bed (south) +[HOUSE 2002] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=largegargoylebedsouthdeed +HOUSE_ITEM=2015 +HOUSE_ITEM=2016 +HOUSE_ITEM=2017 +HOUSE_ITEM=2018 +HOUSE_ITEM=2019 +HOUSE_ITEM=2020 +HOUSE_ITEM=2021 +HOUSE_ITEM=2022 +HOUSE_ITEM=2023 +} + +// House Addon - gargish cot (east) +[HOUSE 2003] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=gargishcoteasteastdeed +HOUSE_ITEM=2024 +HOUSE_ITEM=2025 +} + +// House Addon - gargish cot (south) +[HOUSE 2004] +{ +ID=0x14F0 +SPACEX=1 +SPACEY=1 +CHARX=0 +CHARY=0 +CHARZ=0 +HOUSE_DEED=gargishcoteastsouthdeed +HOUSE_ITEM=2026 +HOUSE_ITEM=2027 +} + +[HOUSE ITEM 2000] +{ // ritual table +ITEM=0x4985 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 2001] +{ // ritual table +ITEM=0x4984 +X=0 +Y=1 +Z=0 +} + +[HOUSE ITEM 2002] +{ // ritual table +ITEM=0x4983 +X=1 +Y=0 +Z=0 +} + +[HOUSE ITEM 2003] +{ // ritual table +ITEM=0x4982 +X=1 +Y=1 +Z=0 +} + +[HOUSE ITEM 2006] +{ E Left Side Gargoyle Bed +ITEM=0x4019 +X=0 +Y=0 +Z=0 +} + +[HOUSE ITEM 2007] +{ E Left Side Gargoyle Bed +ITEM=0x401c +X=0 +Y=1 +Z=0 +} + +[HOUSE ITEM 2008] +{ E Left Side Gargoyle Bed +ITEM=0x401f +X=0 +Y=2 +Z=0 +} + +HOUSE ITEM 2009] +{ E Middle Gargoyle Bed +ITEM=0x401a +X=1 +Y=0 +Z=0 +} + +HOUSE ITEM 2010] +{ E Middle Gargoyle Bed +ITEM=0x401d +X=1 +Y=1 +Z=0 +} + +HOUSE ITEM 2011] +{ E Middle Gargoyle Bed +ITEM=0x4020 +X=1 +Y=2 +Z=0 +} + +HOUSE ITEM 2012] +{ E Right Side Gargoyle Bed +ITEM=0x401b +X=2 +Y=0 +Z=0 +} + +HOUSE ITEM 2013] +{ E Right Side Gargoyle Bed +ITEM=0x401e +X=2 +Y=1 +Z=0 +} + +HOUSE ITEM 2014] +{ E Right Side Gargoyle Bed +ITEM=0x4021 +X=2 +Y=2 +Z=0 +} + +HOUSE ITEM 2015] +{ S Left Side Gargoyle Bed +ITEM=0x4010 +X=0 +Y=0 +Z=0 +} + +HOUSE ITEM 2016] +{ S Left Side Gargoyle Bed +ITEM=0x4013 +X=0 +Y=1 +Z=0 +} + +HOUSE ITEM 2017] +{ S Left Side Gargoyle Bed +ITEM=0x4016 +X=0 +Y=2 +Z=0 +} + +HOUSE ITEM 2018] +{ S Middle Gargoyle Bed +ITEM=0x4011 +X=1 +Y=0 +Z=0 +} + +HOUSE ITEM 2019] +{ S Middle Gargoyle Bed +ITEM=0x4014 +X=1 +Y=1 +Z=0 +} + +HOUSE ITEM 2020] +{ S Middle Gargoyle Bed +ITEM=0x4017 +X=1 +Y=2 +Z=0 +} + +HOUSE ITEM 2021] +{ S left Side Gargoyle Bed +ITEM=0x4012 +X=2 +Y=0 +Z=0 +} + +HOUSE ITEM 2022] +{ S left Side Gargoyle Bed +ITEM=0x4015 +X=2 +Y=1 +Z=0 +} + +HOUSE ITEM 2023] +{ S left Side Gargoyle Bed +ITEM=0x4018 +X=2 +Y=2 +Z=0 +} + +HOUSE ITEM 2024] +{ E Gargoyle Cot +ITEM=0x400e +X=0 +Y=0 +Z=0 +} + +HOUSE ITEM 2025] +{ E Gargoyle Cot +ITEM=0x400f +X=1 +Y=0 +Z=0 +} + +HOUSE ITEM 2026] +{ S Gargoyle Cot +ITEM=0x400d +X=0 +Y=0 +Z=0 +} + +HOUSE ITEM 2027] +{ S Gargoyle Cot +ITEM=0x400c +X=0 +Y=-1 +Z=0 +} \ No newline at end of file diff --git a/data/dfndata/items/building/furniture/beds_sa.dfn b/data/dfndata/items/building/furniture/beds_sa.dfn new file mode 100644 index 000000000..4ea646876 --- /dev/null +++ b/data/dfndata/items/building/furniture/beds_sa.dfn @@ -0,0 +1,116 @@ +[base_bed_sa] +{ +get=base_item +name=bed +weight=10000 +movable=2 +origin=sa +} + +[0x4019] +{ E gargoyle bed +get=base_bed_sa +id=0x4019 +} + +[0x401c] +{ E gargoyle bed +get=base_bed_sa +id=0x401c +} + +[0x401f] +{ E gargoyle bed +get=base_bed_sa +id=0x401f +} + +[0x401a] +{ E gargoyle bed +get=base_bed_sa +id=0x401a +} + +[0x401d] +{ E gargoyle bed +get=base_bed_sa +id=0x401d +} + +[0x4020] +{ E gargoyle bed +get=base_bed_sa +id=0x4020 +} + +[0x401b] +{ E gargoyle bed +get=base_bed_sa +id=0x401b +} + +[0x401e] +{ E gargoyle bed +get=base_bed_sa +id=0x401e +} + +[0x4021] +{ E gargoyle bed +get=base_bed_sa +id=0x4021 +} + +[0x4010] +{ S gargoyle bed +get=base_bed_sa +id=0x4010 +} + +[0x4013] +{ S gargoyle bed +get=base_bed_sa +id=0x4013 +} + +[0x4016] +{ S gargoyle bed +get=base_bed_sa +id=0x4016 +} + +[0x4011] +{ S gargoyle bed +get=base_bed_sa +id=0x4011 +} + +[0x4014] +{ S gargoyle bed +get=base_bed_sa +id=0x4014 +} + +[0x4017] +{ S gargoyle bed +get=base_bed_sa +id=0x4017 +} + +[0x4012] +{ S gargoyle bed +get=base_bed_sa +id=0x4012 +} + +[0x4015] +{ S gargoyle bed +get=base_bed_sa +id=0x4015 +} + +[0x4018] +{ S gargoyle bed +get=base_bed_sa +id=0x4018 +} \ No newline at end of file diff --git a/data/dfndata/items/building/furniture/chairs_sa.dfn b/data/dfndata/items/building/furniture/chairs_sa.dfn new file mode 100644 index 000000000..ce740bb14 --- /dev/null +++ b/data/dfndata/items/building/furniture/chairs_sa.dfn @@ -0,0 +1,31 @@ +[base_chair_sa] +{ +get=base_item +weight=10000 +movable=2 +origin=sa +} + +[0x400e] +{ E Gargoyle Cot +get=base_chair_sa +id=0x400e +} + +[0x400f] +{ E Gargoyle Cot +get=base_chair_sa +id=0x400f +} + +[0x400d] +{ S Gargoyle Cot +get=base_chair_sa +id=0x400d +} + +[0x400c] +{ S Gargoyle Cot +get=base_chair_sa +id=0x400c +} \ No newline at end of file diff --git a/data/dfndata/items/building/walls/craftablewalls.dfn b/data/dfndata/items/building/walls/craftablewalls.dfn new file mode 100644 index 000000000..ebc49c901 --- /dev/null +++ b/data/dfndata/items/building/walls/craftablewalls.dfn @@ -0,0 +1,182 @@ +[base_craftable_wall] +{ +get=base_item +script=5080 +weight=1000 +movable=1 +decay=1 +} + +[RoughWindowless1] +{ +get=base_craftable_wall +id=0x01CF +} + +[RoughWindowless2] +{ +get=base_craftable_wall +id=0x01D0 +} + +[RoughWindowless3] +{ +get=base_craftable_wall +id=0x01D1 +} + +[RoughWindowless4] +{ +get=base_craftable_wall +id=0x01D2 +} + +[RoughWindow1] +{ +get=base_craftable_wall +id=0x01D3 +} + +[RoughWindow2] +{ +get=base_craftable_wall +id=0x01D4 +} + +[RoughArch1] +{ +get=base_craftable_wall +id=0x01D5 +} + +[RoughArch2] +{ +get=base_craftable_wall +id=0x01D6 +} + +[RoughArch3] +{ +get=base_craftable_wall +id=0x01D7 +} + +[RoughArch4] +{ +get=base_craftable_wall +id=0x01D8 +} + +[RoughArch5] +{ +get=base_craftable_wall +id=0x01D9 +} + +[RoughPillar] +{ +get=base_craftable_wall +id=0x01DA +} + +[RoughRoundedArch1] +{ +get=base_craftable_wall +id=0x01DB +} + +[RoughRoundedArch2] +{ +get=base_craftable_wall +id=0x01DC +} + +[RoughRoundedArch3] +{ +get=base_craftable_wall +id=0x01DD +} + +[RoughRoundedArch4] +{ +get=base_craftable_wall +id=0x01DE +} + +[RoughRoundedArch5] +{ +get=base_craftable_wall +id=0x01DF +} + +[RoughSmallArch1] +{ +get=base_craftable_wall +id=0x01E0 +} + +[RoughSmallArch2] +{ +get=base_craftable_wall +id=0x01E1 +} + +[RoughSmallArch3] +{ +get=base_craftable_wall +id=0x01E2 +} + +[RoughSmallArch4] +{ +get=base_craftable_wall +id=0x01E3 +} + +[RoughSmallArch5] +{ +get=base_craftable_wall +id=0x01E4 +} + +[RoughSmallArch6] +{ +get=base_craftable_wall +id=0x01E5 +} + +[RoughAngledPillar1] +{ +get=base_craftable_wall +id=0x01E6 +} + +[RoughAngledPillar2] +{ +get=base_craftable_wall +id=0x01E7 +} + +[ShortRough1] +{ +get=base_craftable_wall +id=0x01E8 +} + +[ShortRough2] +{ +get=base_craftable_wall +id=0x01E9 +} + +[ShortRough3] +{ +get=base_craftable_wall +id=0x01EA +} + +[ShortRough4] +{ +get=base_craftable_wall +id=0x01EB +} diff --git a/data/dfndata/items/deeds/houseaddon_deeds.dfn b/data/dfndata/items/deeds/houseaddon_deeds.dfn index 92da87dfb..524e91099 100644 --- a/data/dfndata/items/deeds/houseaddon_deeds.dfn +++ b/data/dfndata/items/deeds/houseaddon_deeds.dfn @@ -521,13 +521,4 @@ id=0x14f0 morex=213 value=1000 500 restock=15 -} - -[ritualtabledeed] -{ -name=ritual table -id=0x14f0 -morex=214 -value=1000 500 -restock=15 } \ No newline at end of file diff --git a/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn b/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn index 59ffb2c8e..e6d102192 100644 --- a/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn +++ b/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn @@ -212,4 +212,24 @@ name=Tall Elven Bed (South) id=0x14F0 morex=323 origin=ml +} + +[stoneanvileastdeed] +{ +name=stone anvil (east) +id=0x14f0 +morex=324 +value=1000 500 +restock=15 +origin=ml +} + +[stoneanvilsouthdeed] +{ +name=stone anvil (south) +id=0x14f0 +morex=325 +value=1000 500 +restock=15 +origin=ml } \ No newline at end of file diff --git a/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn b/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn new file mode 100644 index 000000000..50ec3e40e --- /dev/null +++ b/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn @@ -0,0 +1,49 @@ +[ritualtabledeed] +{ +name=ritual table +id=0x14f0 +morex=2000 +value=1000 500 +restock=15 +origin=sa +} + +[largegargoylebedeastdeed] +{ +name=large gargish bed (east) +id=0x14f0 +morex=2001 +value=1000 500 +restock=15 +origin=sa +} + +[largegargoylebedsouthdeed] +{ +name=large gargish bed (south) +id=0x14f0 +morex=2002 +value=1000 500 +restock=15 +origin=sa +} + +[gargishcoteasteastdeed] +{ +name=gargish cot (east) +id=0x14f0 +morex=2003 +value=1000 500 +restock=15 +origin=sa +} + +[gargishcoteastsouthdeed] +{ +name=gargish cot (south) +id=0x14f0 +morex=2004 +value=1000 500 +restock=15 +origin=sa +} \ No newline at end of file diff --git a/data/dfndata/items/misc/crafting_recipes.dfn b/data/dfndata/items/misc/crafting_recipes.dfn index 99f6ab82f..26a64fa7e 100644 --- a/data/dfndata/items/misc/crafting_recipes.dfn +++ b/data/dfndata/items/misc/crafting_recipes.dfn @@ -23,6 +23,7 @@ customstringtag=recipeName skullcap get=base_recipe_scroll custominttag=recipeID 3500 customstringtag=recipeName Tall 18th Anniversary Vase +origin=sa } [short_18th_anniversary_vase_recipe] @@ -30,4 +31,21 @@ customstringtag=recipeName Tall 18th Anniversary Vase get=base_recipe_scroll custominttag=recipeID 3501 customstringtag=recipeName Short 18th Anniversary Vase +origin=sa +} + +[stone_anvil_east_recipe] +{ +get=base_recipe_scroll +custominttag=recipeID 3520 +customstringtag=recipeName Stone Anvil (East) +origin=sa +} + +[stone_anvil_south_recipe] +{ +get=base_recipe_scroll +custominttag=recipeID 3521 +customstringtag=recipeName Stone Anvil (South) +origin=sa } \ No newline at end of file diff --git a/data/dfndata/items/misc/jewelry_sa.dfn b/data/dfndata/items/misc/jewelry_sa.dfn new file mode 100644 index 000000000..f8f338a49 --- /dev/null +++ b/data/dfndata/items/misc/jewelry_sa.dfn @@ -0,0 +1,32 @@ +[base_jewelry_sa] +{ +get=base_item +weight=100 +value=26 13 +restock=10 +decay=1 +good=37 +} + +[0x4D0a] +{ +get=base_jewelry_sa +name=gargish stone amulet +id=0x4D0a +colour=2500 +layer=0x0a +str=40 +} + +[0x4210] +{ +get=base_jewelry_sa +name=gargish amulet +id=0x4210 +layer=0x0a +str=40 +hp=30 +maxhp=40 +def=1 +elementresist=2 2 3 2 +} \ No newline at end of file diff --git a/data/dfndata/items/skills/tools/blacksmithy.dfn b/data/dfndata/items/skills/tools/blacksmithy.dfn index ddfd9c2f8..f99512e04 100644 --- a/data/dfndata/items/skills/tools/blacksmithy.dfn +++ b/data/dfndata/items/skills/tools/blacksmithy.dfn @@ -1,5 +1,4 @@ //Blacksmithy Tools - [0x0fbb] { get=base_item @@ -49,4 +48,20 @@ id=0x0fb0 [anvil] { get=0x0faf 0x0fb0 +} + +[0x2dd6] +{// stone anvil east +get=0x0faf +name=elven anvil +id=0x2dd6 +origin=ml +} + +[0x2dd5] +{// stone anvil south +get=0x0faf +name=elven anvil +id=0x2dd5 +origin=ml } \ No newline at end of file diff --git a/data/js/item/buildingcraftables.js b/data/js/item/buildingcraftables.js new file mode 100644 index 000000000..cb1ff6468 --- /dev/null +++ b/data/js/item/buildingcraftables.js @@ -0,0 +1,136 @@ +/// +// @ts-check +/** @type { ( thingCreated: BaseObject, thingType: 0 | 1 ) => void } */ +function onCreateDFN( iCreated, dfnSection ) +{ + setLockedState( iCreated, false ); + iCreated.SetTag( "BuildingCraftable", 1 ); +} + +/** @type { ( user: Character, iUsing: Item ) => boolean } */ +function onUseChecked( pUser, iUsed ) +{ + var pSocket = pUser.socket; + + if( iUsed.container !== null ) + { + if( iUsed.container === pUser.pack ) + { + if (pSocket) + pSocket.SysMessage( "Place the wall in your house, then double-click it to lock it down." ); + } + else + { + if( pSocket ) + pSocket.SysMessage( "You must first place this wall in the world." ); + } + return false; + } + + if( !isInOwnHouse( pUser )) + { + if( pSocket ) + { + pSocket.SysMessage( GetDictionaryEntry( 2067, pSocket.language )); // You must be in your house to do this. + } + return false; + } + + var iMulti = iUsed.multi; + if( !ValidateObject( iMulti ) || iMulti !== pUser.multi ) + { + if( pSocket ) + pSocket.SysMessage( "This crafted wall must be inside your house to lock it down." ); + return false; + } + + var locked = iUsed.GetTag( "CraftWallLocked" ); + + if( locked == 1) + { + setLockedState( iUsed, false ); + if( pSocket ) + pSocket.SysMessage( "You unlock the crafted wall. It can now be moved and will decay normally." ); + } + else + { + setLockedState( iUsed, true ); + if( pSocket ) + pSocket.SysMessage( "You lock the crafted wall in place. It will no longer decay." ); + } + + return false; +} + +/** @type { ( myObj: BaseObject, pSocket: Socket ) => string } */ +function onTooltip( myObj, pSocket ) +{ + var locked = myObj.GetTag( "CraftWallLocked" ); + + if( locked == 1 ) + { + // Line 1: House Only + // Line 2: unlock hint + return "House Only
You must double click this to unlock it."; + } + else + { + // Line 1: House Only + // Line 2: lock hint + return "House Only
You must double click this to lock it down."; + } +} + +function onDropItemOnNpc( pDropper, pDroppedOn, iDropped ) +{ + var targPack = pDroppedOn.pack; + if( ValidateObject( targPack ) && pDroppedOn.sectionID == "packhorse" ) + { + return 0; + } + + return 1; +} + +function isInOwnHouse( pUser ) +{ + if( !ValidateObject( pUser )) + return false; + + var iMulti = pUser.multi; + if( !ValidateObject( iMulti )) + return false; + + // Owner / co-owner / whatever IsOnOwnerList covers + if( iMulti.IsOnOwnerList( pUser )) + return true; + + // Optional: co-owned houses on same account + if( GetServerSetting( "COOWNHOUSESONSAMEACCOUNT" )) + { + if( ValidateObject( iMulti.owner ) && iMulti.owner.accountNum === pUser.accountNum ) + return true; + } + + return false; +} + +function setLockedState( item, locked ) +{ + if( !ValidateObject( item )) + return; + + if( locked ) + { + item.SetTag( "CraftWallLocked", 1 ); + item.movable = 2; // locked down / secure + item.decayable = false; // no decay + } + else + { + item.SetTag( "CraftWallLocked", 0 ); + item.movable = 1; // movable + item.decayable = true; // normal decay + } + item.Refresh(); +} \ No newline at end of file diff --git a/data/js/item/interiordecorator.js b/data/js/item/interiordecorator.js index a3161e947..a2dae4819 100644 --- a/data/js/item/interiordecorator.js +++ b/data/js/item/interiordecorator.js @@ -30,6 +30,7 @@ function onUseChecked( pUser, iUsed ) function interiorDecoratorGump( pUser ) { + var socket = pUser.socket; var interiorGump = new Gump; interiorGump.AddPage( 0 ); interiorGump.AddBackground( 0, 0, 200, 200, 2600 ); @@ -39,7 +40,7 @@ function interiorDecoratorGump( pUser ) interiorGump.AddXMFHTMLGump( 90, 100, 70, 40, 1018324, false, false );//up interiorGump.AddButton( 50, 145, 0x868, 1, 0, 3 ); interiorGump.AddXMFHTMLGump( 90, 150, 70, 40, 1018325, false, false );//down - interiorGump.Send( pUser ); + interiorGump.Send( socket ); interiorGump.Free(); return false; } @@ -84,10 +85,18 @@ function onGumpPress( socket, pButton, gumpData ) /** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ function onCallback1( socket, ourObj ) { + if( !ValidateObject( ourObj )) + { + return; + } + + var isBuilding = ourObj.GetTag( "BuildingCraftable" ) === 1; + var isWallLocked = ourObj.GetTag( "CraftWallLocked" ) === 1; var pUser = socket.currentChar; - if( !ValidateObject( ourObj ) || !ourObj.isItem || ourObj.movable != 3 ) + if( !ourObj.isItem || ( isBuilding && !isWallLocked ) || ( !isBuilding && ourObj.movable != 3 )) { socket.SysMessage( GetDictionaryEntry( 2072, socket.language )); // You can only use the interior decorator on locked down items. + socket.CustomTarget( 1 ); return; } @@ -126,10 +135,18 @@ function onCallback1( socket, ourObj ) /** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ function onCallback2( socket, ourObj ) { + if( !ValidateObject( ourObj )) + { + return; + } + + var isBuilding = ourObj.GetTag( "BuildingCraftable" ) === 1; + var isWallLocked = ourObj.GetTag( "CraftWallLocked" ) === 1; var pUser = socket.currentChar; - if( !ValidateObject( ourObj ) || !ourObj.isItem || ourObj.movable != 3 ) + if( !ourObj.isItem || ( isBuilding && !isWallLocked ) || ( !isBuilding && ourObj.movable != 3 )) { socket.SysMessage( GetDictionaryEntry( 2072, socket.language )); // You can only use the interior decorator on locked down items. + socket.CustomTarget( 2 ); return; } @@ -168,10 +185,18 @@ function onCallback2( socket, ourObj ) /** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ function onCallback3( socket, ourObj ) { + if( !ValidateObject( ourObj )) + { + return; + } + + var isBuilding = ourObj.GetTag( "BuildingCraftable" ) === 1; + var isWallLocked = ourObj.GetTag( "CraftWallLocked" ) === 1; var pUser = socket.currentChar; - if( !ValidateObject( ourObj ) || !ourObj.isItem || ourObj.movable != 3 ) + if( !ourObj.isItem || ( isBuilding && !isWallLocked ) || ( !isBuilding && ourObj.movable != 3 )) { socket.SysMessage( GetDictionaryEntry( 2072, socket.language )); // You can only use the interior decorator on locked down items. + socket.CustomTarget( 3 ); return; } diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 938a3d875..46405c3a4 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -319,6 +319,7 @@ 5061=item/puzzlechest.js 5062=item/shrines.js 5063=item/recipescroll.js +5080=item/buildingcraftables.js 19100=item/plant_growing/plantsystem.js 19101=item/plant_growing/plantbowl.js diff --git a/data/js/server/house/houseCommands.js b/data/js/server/house/houseCommands.js index cdd078fe2..4d51c1052 100644 --- a/data/js/server/house/houseCommands.js +++ b/data/js/server/house/houseCommands.js @@ -1129,7 +1129,7 @@ function onCallback8( pSocket, myTarget ) { pSocket.SysMessage( GetDictionaryEntry( 1888, pSocket.language )); // You cannot lock down trash barrels. } - else if( myTarget.movable == 3 ) + else if( myTarget.movable == 3 || myTarget.GetTag( "BuildingCraftable" ) == 1 ) { pSocket.SysMessage( GetDictionaryEntry( 1889, pSocket.language )); // That is already locked down! } diff --git a/data/js/server/misc/furniture_smartturn.js b/data/js/server/misc/furniture_smartturn.js index 7bcf3e35e..ab1c1caf4 100644 --- a/data/js/server/misc/furniture_smartturn.js +++ b/data/js/server/misc/furniture_smartturn.js @@ -59,7 +59,7 @@ function LookForSittingPlayers( srcItem, trgChar, pSock ) function onDrop( iDropped, pDropper ) { SmartTurn( iDropped ); - return true; + return 1; } // Turn supported furniture clockwise, based on previous direction @@ -81,110 +81,222 @@ function SmartTurn( iTurn ) // our partner is listed! this is an implicit subtraction operation iTurn.id--; }// Special Turn for glass made items - else if (iTurn.id == 0x1810 )//spinning hourglass + else if( iTurn.id == 0x1810 )//spinning hourglass { iTurn.id = 0x1811; } - else if (iTurn.id == 0x1811 || iTurn.id == 0x1812 || iTurn.id == 0x1813 || iTurn.id == 0x1814 || iTurn.id == 0x1815 || iTurn.id == 0x1816 || iTurn.id == 0x1817 || iTurn.id == 0x1818 || iTurn.id == 0x1819 || iTurn.id == 0x181A || iTurn.id == 0x181B || iTurn.id == 0x181C)//spinning hourglass animations + else if( iTurn.id == 0x1811 || iTurn.id == 0x1812 || iTurn.id == 0x1813 || iTurn.id == 0x1814 || iTurn.id == 0x1815 || iTurn.id == 0x1816 || iTurn.id == 0x1817 || iTurn.id == 0x1818 || iTurn.id == 0x1819 || iTurn.id == 0x181A || iTurn.id == 0x181B || iTurn.id == 0x181C )//spinning hourglass animations { iTurn.id = 0x1810; } - else if (iTurn.id == 0x185d)// Full Vials + else if( iTurn.id == 0x185d )// Full Vials { iTurn.id = 0x185e; } - else if (iTurn.id == 0x185e)// Full Vials + else if( iTurn.id == 0x185e )// Full Vials { iTurn.id = 0x185d; } - else if (iTurn.id == 0x185b)// Empty Vials + else if( iTurn.id == 0x185b )// Empty Vials { iTurn.id = 0x185c; } - else if (iTurn.id == 0x185c)// Full Vials + else if( iTurn.id == 0x185c )// Full Vials { iTurn.id = 0x185b; } - else if (iTurn.id == 0x182a)// Medium Flask + else if( iTurn.id == 0x182a )// Medium Flask { iTurn.id = 0x182b; } - else if (iTurn.id == 0x182b)// Medium Flask + else if( iTurn.id == 0x182b )// Medium Flask { iTurn.id = 0x182c; } - else if (iTurn.id == 0x182c)// Medium Flask + else if( iTurn.id == 0x182c )// Medium Flask { iTurn.id = 0x182d; } - else if (iTurn.id == 0x182d)// Medium Flask + else if( iTurn.id == 0x182d )// Medium Flask { iTurn.id = 0x182a; } - else if (iTurn.id == 0x182e)// Small Flask + else if( iTurn.id == 0x182e )// Small Flask { iTurn.id = 0x182f; } - else if (iTurn.id == 0x182f)// Small Flask + else if( iTurn.id == 0x182f )// Small Flask { iTurn.id = 0x1830; } - else if (iTurn.id == 0x1830)// Small Flask + else if( iTurn.id == 0x1830 )// Small Flask { iTurn.id = 0x1831; } - else if (iTurn.id == 0x1831)// Small Flask + else if( iTurn.id == 0x1831 )// Small Flask { iTurn.id = 0x182e; } - else if (iTurn.id == 0x1832)// Curved Flask + else if( iTurn.id == 0x1832 )// Curved Flask { iTurn.id = 0x1833; } - else if (iTurn.id == 0x1833)// Curved Flask + else if( iTurn.id == 0x1833 )// Curved Flask { iTurn.id = 0x1834; } - else if (iTurn.id == 0x1834)// Curved Flask + else if( iTurn.id == 0x1834 )// Curved Flask { iTurn.id = 0x1835; } - else if (iTurn.id == 0x1835)// Curved Flask + else if( iTurn.id == 0x1835 )// Curved Flask { iTurn.id = 0x1836; } - else if (iTurn.id == 0x1836)// Curved Flask + else if( iTurn.id == 0x1836 )// Curved Flask { iTurn.id = 0x1837; } - else if (iTurn.id == 0x1837)// Curved Flask + else if( iTurn.id == 0x1837 )// Curved Flask { iTurn.id = 0x1832; } - else if (iTurn.id == 0x1838)// Large Flask + else if( iTurn.id == 0x1838 )// Large Flask { iTurn.id = 0x1839; } - else if (iTurn.id == 0x1839)// Large Flask + else if( iTurn.id == 0x1839 )// Large Flask { iTurn.id = 0x183a; } - else if (iTurn.id == 0x1838)// Large Flask + else if( iTurn.id == 0x1838 )// Large Flask { iTurn.id = 0x183b; } - else if (iTurn.id == 0x183b)// Large Flask 2 + else if( iTurn.id == 0x183b )// Large Flask 2 { iTurn.id = 0x183c; } - else if (iTurn.id == 0x183c)// Large Flask 2 + else if( iTurn.id == 0x183c )// Large Flask 2 { iTurn.id = 0x183d; } - else if (iTurn.id == 0x183d)// Large Flask 2 + else if( iTurn.id == 0x183d )// Large Flask 2 { iTurn.id = 0x183b; } + else if( iTurn.id == 0x01CF ) // RoughWindowless + { + iTurn.id = 0x01D0; + } + else if( iTurn.id == 0x01D0 ) + { + iTurn.id = 0x01D1; + } + else if( iTurn.id == 0x01D1 ) + { + iTurn.id = 0x01D0; + } + else if( iTurn.id == 0x01D2 ) + { + iTurn.id = 0x01CF; + } + else if( iTurn.id == 0x01D3 ) // RoughWindow + { + iTurn.id = 0x01D4; + } + else if( iTurn.id == 0x01D4 ) + { + iTurn.id = 0x01D3; + } + else if( iTurn.id == 0x01D5 ) // RoughArch + { + iTurn.id = 0x01D6; + } + else if( iTurn.id == 0x01D6 ) + { + iTurn.id = 0x01D7; + } + else if( iTurn.id == 0x01D7 ) + { + iTurn.id = 0x01D8; + } + else if( iTurn.id == 0x01D8 ) + { + iTurn.id = 0x01D9; + } + else if( iTurn.id == 0x01D9 ) + { + iTurn.id = 0x01D5; + } + else if( iTurn.id == 0x01DB ) // RoughRoundedArch + { + iTurn.id = 0x01DC; + } + else if( iTurn.id == 0x01DC ) + { + iTurn.id = 0x01DD; + } + else if( iTurn.id == 0x01DD ) + { + iTurn.id = 0x01DE; + } + else if( iTurn.id == 0x01DE ) + { + iTurn.id = 0x01DF; + } + else if( iTurn.id == 0x01DF ) + { + iTurn.id = 0x01DB; + } + else if( iTurn.id == 0x01E0 ) // RoughSmallArch + { + iTurn.id = 0x01E1; + } + else if( iTurn.id == 0x01E1 ) + { + iTurn.id = 0x01E2; + } + else if( iTurn.id == 0x01E2 ) + { + iTurn.id = 0x01E3; + } + else if( iTurn.id == 0x01E3 ) + { + iTurn.id = 0x01E4; + } + else if( iTurn.id == 0x01E4 ) + { + iTurn.id = 0x01E5; + } + else if( iTurn.id == 0x01E5 ) + { + iTurn.id = 0x01E0; + } + else if( iTurn.id == 0x01E6 ) // RoughAngledPillar + { + iTurn.id = 0x01E7; + } + else if( iTurn.id == 0x01E7 ) + { + iTurn.id = 0x01E6; + } + else if( iTurn.id == 0x01E8 ) // ShortRough + { + iTurn.id = 0x01E9; + } + else if( iTurn.id == 0x01E9 ) + { + iTurn.id = 0x01EA; + } + else if( iTurn.id == 0x01EA ) + { + iTurn.id = 0x01E9; + } + else if( iTurn.id == 0x01EB ) + { + iTurn.id = 0x01E8; + } } var divorcedPairs = [ // they are paired up, but more than one index apart and out of order, [hex ID, add or subtract distance] From 802d9b57da2093815cd9c6863f16df9de95ecf80 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:35:54 -0600 Subject: [PATCH 06/43] Update buildingcraftables.js --- data/js/item/buildingcraftables.js | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/data/js/item/buildingcraftables.js b/data/js/item/buildingcraftables.js index cb1ff6468..0a5cf1d98 100644 --- a/data/js/item/buildingcraftables.js +++ b/data/js/item/buildingcraftables.js @@ -92,6 +92,51 @@ function onDropItemOnNpc( pDropper, pDroppedOn, iDropped ) return 1; } +function onDropItemOnItem( iDropped, cDropper, iDroppedOn ) +{ + if( !ValidateObject( iDropped ) || !ValidateObject( cDropper ) || !ValidateObject( iDroppedOn )) + return 0; + + var isBuilding = iDropped.GetTag( "BuildingCraftable" ) === 1; + if( !isBuilding ) + return 0 + + var owner = iDroppedOn.container; + if( ValidateObject( owner ) && owner.isChar && owner.sectionID == "packhorse" ) + { + var sock = cDropper.socket; + if( sock ) + sock.SysMessage( "You cannot place building pieces on a pack animal." ); + + return 0; + } + + return 1; +} + +function onDrop( iDropped, pDropper ) +{ + if( !ValidateObject( iDropped ) || !ValidateObject( pDropper )) + return 0; + + var isBuilding = iDropped.GetTag( "BuildingCraftable" ) === 1; + if( !isBuilding ) + return 0; + + var socket = pDropper.socket; + if( !isInOwnHouse( pDropper )) + { + if( socket != null) + socket.SysMessage( "The building piece crumbles when dropped on the ground." ); + + iDropped.Delete(); + return 2; + } + + return 1; +} + + function isInOwnHouse( pUser ) { if( !ValidateObject( pUser )) From 12f44a17ba179b683ebc00367cf9f59f8630130f Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:53:27 -0600 Subject: [PATCH 07/43] small update --- data/dfndata/items/deeds/houseaddon_deeds_ml.dfn | 2 ++ data/dfndata/items/deeds/houseaddon_deeds_sa.dfn | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn b/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn index e6d102192..e5a86e7b5 100644 --- a/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn +++ b/data/dfndata/items/deeds/houseaddon_deeds_ml.dfn @@ -216,6 +216,7 @@ origin=ml [stoneanvileastdeed] { +get=base_item name=stone anvil (east) id=0x14f0 morex=324 @@ -226,6 +227,7 @@ origin=ml [stoneanvilsouthdeed] { +get=base_item name=stone anvil (south) id=0x14f0 morex=325 diff --git a/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn b/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn index 50ec3e40e..9a5c93d3e 100644 --- a/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn +++ b/data/dfndata/items/deeds/houseaddon_deeds_sa.dfn @@ -1,5 +1,6 @@ [ritualtabledeed] { +get=base_item name=ritual table id=0x14f0 morex=2000 @@ -10,6 +11,7 @@ origin=sa [largegargoylebedeastdeed] { +get=base_item name=large gargish bed (east) id=0x14f0 morex=2001 @@ -20,6 +22,7 @@ origin=sa [largegargoylebedsouthdeed] { +get=base_item name=large gargish bed (south) id=0x14f0 morex=2002 @@ -30,6 +33,7 @@ origin=sa [gargishcoteasteastdeed] { +get=base_item name=gargish cot (east) id=0x14f0 morex=2003 @@ -40,6 +44,7 @@ origin=sa [gargishcoteastsouthdeed] { +get=base_item name=gargish cot (south) id=0x14f0 morex=2004 From d50ad1aff76633e8db61d61e0b1b33aa093f8941 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 19:49:41 -0600 Subject: [PATCH 08/43] update --- data/dfndata/create/masonry.dfn | 277 +++++-- data/dfndata/create/masonry_agapite.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_bronze.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_copper.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_dullcopper.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_gold.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_shadowiron.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_valorite.dfn | 704 ++++++++++++++++++ data/dfndata/create/masonry_verite.dfn | 704 ++++++++++++++++++ .../items/building/floors/craftable_tiles.dfn | 26 + .../items/building/walls/craftablewalls.dfn | 222 ++++-- data/dictionaries/dictionary.ENG | 38 + data/dictionaries/dictionary.ZRO | 54 +- data/js/server/misc/furniture_smartturn.js | 80 ++ data/js/skill/craft/masonry.js | 361 +++++---- 15 files changed, 6417 insertions(+), 273 deletions(-) create mode 100644 data/dfndata/create/masonry_agapite.dfn create mode 100644 data/dfndata/create/masonry_bronze.dfn create mode 100644 data/dfndata/create/masonry_copper.dfn create mode 100644 data/dfndata/create/masonry_dullcopper.dfn create mode 100644 data/dfndata/create/masonry_gold.dfn create mode 100644 data/dfndata/create/masonry_shadowiron.dfn create mode 100644 data/dfndata/create/masonry_valorite.dfn create mode 100644 data/dfndata/create/masonry_verite.dfn create mode 100644 data/dfndata/items/building/floors/craftable_tiles.dfn diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index 960e71c7f..5b229b77b 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -24,7 +24,7 @@ SOUND=0x23D [ITEM 3502] { -NAME=Small Urn +NAME=small Urn ID=0x241c RESOURCE=STONE 3 SKILL=11 820 1030 @@ -36,7 +36,7 @@ SOUND=0x23D [ITEM 3503] { -NAME=Tower Sculpture +NAME=Tower sculpture ID=0x241a RESOURCE=STONE 3 SKILL=11 820 1030 @@ -70,7 +70,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3505] +[ITEM 3506] { NAME=gargoyle vase ID=0x4042 @@ -82,9 +82,9 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3506] +[ITEM 3507] { -NAME=Tall 18th Anniversary Vase +NAME=Tall 18th anniversary Vase ID=0x9bc7 RESOURCE=STONE 6 SKILL=11 600 1100 @@ -94,9 +94,9 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3507] +[ITEM 3508] { -NAME=Short 18th Anniversary Vase +NAME=short 18th anniversary Vase ID=0x9bca RESOURCE=STONE 6 SKILL=11 600 1100 @@ -110,7 +110,7 @@ SOUND=0x23D //// furniture ///// ////////////////////////////////////// -[ITEM 3508] +[ITEM 3509] { NAME=stone chair ID=0x1218 @@ -122,7 +122,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3509] +[ITEM 3510] { NAME=stone table (east) ID=0x14f0 @@ -134,7 +134,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3510] +[ITEM 3511] { NAME=stone table (south) ID=0x14f0 @@ -146,7 +146,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3511] +[ITEM 3512] { NAME=large stone table (east) ID=0x14f0 @@ -158,7 +158,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3512] +[ITEM 3513] { NAME=large stone table (south) ID=0x14f0 @@ -170,7 +170,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3513] +[ITEM 3514] { NAME=ritual table ID=0x14f0 @@ -183,10 +183,10 @@ SOUND=0x23D } ////////////////////////////////////// -//// Statues ///// +//// statues ///// ////////////////////////////////////// -[ITEM 3514] +[ITEM 3515] { NAME=small statue (south) ID=0x139a @@ -198,7 +198,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3515] +[ITEM 3516] { NAME=small statue (north) ID=0x139b @@ -210,7 +210,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3516] +[ITEM 3517] { NAME=small statue (east) ID=0x139c @@ -222,7 +222,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3517] +[ITEM 3518] { NAME=pegasus statuette ID=0x139d @@ -234,7 +234,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3518] +[ITEM 3519] { NAME=gargoyle statue ID=0x494e @@ -246,7 +246,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3519] +[ITEM 3520] { NAME=gryphon statue ID=0x494e @@ -259,10 +259,10 @@ SOUND=0x23D } ////////////////////////////////////// -//// Misc Addons ///// +//// Misc addons ///// ////////////////////////////////////// -[ITEM 3520] +[ITEM 3521] { NAME=stone anvil (east) ID=0x14f0 @@ -274,7 +274,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3521] +[ITEM 3522] { NAME=stone anvil (south) ID=0x14f0 @@ -286,12 +286,12 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3522] +[ITEM 3523] { NAME=large gargish bed (east) ID=0x14f0 RESOURCE=STONE 3 -RESOURCE=CLOTH 100 +rEsOUrCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=largegargoylebedeastdeed @@ -300,12 +300,12 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3523] +[ITEM 3524] { NAME=large gargish bed (south) ID=0x14f0 RESOURCE=STONE 3 -RESOURCE=CLOTH 100 +rEsOUrCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=largegargoylebedsouthdeed @@ -314,12 +314,12 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3524] +[ITEM 3525] { NAME=gargish cot (east) ID=0x14f0 RESOURCE=STONE 3 -RESOURCE=CLOTH 100 +rEsOUrCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=gargishcoteasteastdeed @@ -328,12 +328,12 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3525] +[ITEM 3526] { NAME=gargish cot (south) ID=0x14f0 RESOURCE=STONE 3 -RESOURCE=CLOTH 100 +rEsOUrCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=gargishcoteastsouthdeed @@ -343,10 +343,10 @@ SOUND=0x23D } ////////////////////////////////////// -//// Stone Armor ///// +//// stone armor ///// ////////////////////////////////////// -[ITEM 3526] +[ITEM 3527] { NAME=gargish stone arms ID=0x0283 @@ -358,7 +358,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3527] +[ITEM 3528] { NAME=gargish stone chest ID=0x0285 @@ -370,7 +370,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3528] +[ITEM 3529] { NAME=gargish stone leggings ID=0x0289 @@ -382,7 +382,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3529] +[ITEM 3530] { NAME=gargish stone kilt ID=0x0287 @@ -394,7 +394,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3530] +[ITEM 3531] { NAME=gargish stone arms ID=0x0284 @@ -406,7 +406,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3531] +[ITEM 3532] { NAME=gargish stone chest ID=0x0286 @@ -418,7 +418,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3532] +[ITEM 3533] { NAME=gargish stone leggings ID=0x028a @@ -430,7 +430,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3533] +[ITEM 3534] { NAME=gargish stone kilt ID=0x0288 @@ -442,7 +442,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3534] +[ITEM 3535] { NAME=large stone shield ID=0x4205 @@ -454,7 +454,7 @@ MAXRANK=10 SOUND=0x23D } -[ITEM 3535] +[ITEM 3536] { NAME=gargish stone amulet ID=0x4D0a @@ -467,10 +467,10 @@ SOUND=0x23D } ////////////////////////////////////// -//// Stone Weapons ///// +//// stone weapons ///// ////////////////////////////////////// -[ITEM 3536] +[ITEM 3537] { NAME=stone war sword ID=0x4D0a @@ -483,100 +483,221 @@ SOUND=0x23D } ////////////////////////////////////// -//// Stone Walls ///// +//// stone walls ///// ////////////////////////////////////// -[ITEM 3537] +[ITEM 3538] { -NAME=Rough Windowless +NAME=rough windowless ID=0x01D0 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughWindowless1 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3538] +[ITEM 3539] { -NAME=Rough Window +NAME=rough window ID=0x01D3 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughWindow1 +SKILL=11 600 1100 +ADDITEM=roughwindow1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3539] +[ITEM 3540] { -NAME=Rough Arch +NAME=rough arch ID=0x01D5 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughArch1 +SKILL=11 600 1100 +ADDITEM=rougharch1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3540] +[ITEM 3541] { -NAME=Rough Pillar -ID=0x01DA +NAME=rough pillar +ID=0x01Da RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughPillar +SKILL=11 600 1100 +ADDITEM=roughpillar MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3541] +[ITEM 3542] { -NAME=Rough Rounded Arch +NAME=rough rounded arch ID=0x01DB RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughRoundedArch1 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3542] +[ITEM 3543] { -NAME=Rough Small Arch +NAME=rough small arch ID=0x01E0 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughSmallArch1 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3543] +[ITEM 3544] { -NAME=Rough Angled Pillar +NAME=rough angled pillar ID=0x01E6 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=RoughAngledPillar1 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 MINRANK=1 MAXRANK=10 SOUND=0x23D } -[ITEM 3544] +[ITEM 3545] { -NAME=Short Rough +NAME=short rough ID=0x01E8 RESOURCE=STONE 10 -SKILL=11 600 110 -ADDITEM=ShortRough1 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 3546] +//[ITEM 3547] +//[ITEM 3548] +//[ITEM 3549] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 3550] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3551] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3552] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3553] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3554] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3555] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 3556] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3557] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3558] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 +SKILL=11 600 1100 +ADDITEM=darkpaver MINRANK=1 MAXRANK=10 SOUND=0x23D diff --git a/data/dfndata/create/masonry_agapite.dfn b/data/dfndata/create/masonry_agapite.dfn new file mode 100644 index 000000000..fd07b68b6 --- /dev/null +++ b/data/dfndata/create/masonry_agapite.dfn @@ -0,0 +1,704 @@ +[ITEM 4100] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x979 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4101] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x979 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4102] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x979 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4103] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x979 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4104] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x979 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4105] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x979 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4106] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x979 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4107] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x979 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4108] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x979 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 4109] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x979 +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4110] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x979 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4111] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x979 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4112] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x979 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4113] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x979 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4114] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x979 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 4115] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x979 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4116] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x979 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4117] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x979 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4118] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x979 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4119] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x979 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4120] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x979 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 4121] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x979 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4122] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x979 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4123] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x979 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4124] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x979 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4125] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x979 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4126] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x979 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 4127] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x979 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4128] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x979 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4129] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x979 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4130] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x979 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4131] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x979 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4132] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x979 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4133] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x979 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4134] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x979 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4135] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x979 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4136] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x979 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 4137] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x979 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 4138] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4139] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4140] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4141] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4142] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4143] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4144] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4145] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x979 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 4146] +//[ITEM 4147] +//[ITEM 4148] +//[ITEM 4149] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 4150] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4151] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4152] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4153] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4154] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4155] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 4156] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4157] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4158] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x979 +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_bronze.dfn b/data/dfndata/create/masonry_bronze.dfn new file mode 100644 index 000000000..5fb705bd3 --- /dev/null +++ b/data/dfndata/create/masonry_bronze.dfn @@ -0,0 +1,704 @@ +[ITEM 3900] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x6d6 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3901] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x6d6 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3902] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x6d6 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3903] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x6d6 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3904] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x6d6 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3905] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x6d6 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3906] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x6d6 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3907] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3908] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 3909] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x6d6 +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3910] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x6d6 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3911] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x6d6 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3912] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x6d6 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3913] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x6d6 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3914] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x6d6 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 3915] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3916] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3917] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3918] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x6d6 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3919] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x6d6 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3920] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x6d6 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 3921] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x6d6 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3922] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x6d6 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3923] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x6d6 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3924] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x6d6 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3925] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x6d6 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3926] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x6d6 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 3927] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x6d6 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3928] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x6d6 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3929] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x6d6 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3930] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x6d6 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3931] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x6d6 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3932] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x6d6 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3933] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x6d6 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3934] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x6d6 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3935] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x6d6 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3936] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x6d6 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 3937] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x6d6 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 3938] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3939] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3940] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3941] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3942] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3943] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3944] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3945] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x6d6 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 3946] +//[ITEM 3947] +//[ITEM 3948] +//[ITEM 3949] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 3950] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3951] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3952] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3953] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3954] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3955] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 3956] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3957] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3958] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x6d6 +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_copper.dfn b/data/dfndata/create/masonry_copper.dfn new file mode 100644 index 000000000..017e58ce9 --- /dev/null +++ b/data/dfndata/create/masonry_copper.dfn @@ -0,0 +1,704 @@ +[ITEM 3800] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x7dd +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3801] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x7dd +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3802] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x7dd +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3803] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x7dd +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3804] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x7dd +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3805] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x7dd +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3806] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x7dd +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3807] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x7dd +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3808] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x7dd +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 3809] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x7dd +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3810] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x7dd +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3811] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x7dd +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3812] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x7dd +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3813] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x7dd +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3814] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x7dd +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 3815] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x7dd +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3816] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x7dd +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3817] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x7dd +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3818] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x7dd +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3819] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x7dd +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3820] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x7dd +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 3821] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x7dd +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3822] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x7dd +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3823] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x7dd +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3824] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x7dd +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3825] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x7dd +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3826] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x7dd +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 3827] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x7dd +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3828] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x7dd +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3829] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x7dd +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3830] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x7dd +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3831] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x7dd +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3832] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x7dd +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3833] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x7dd +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3834] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x7dd +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3835] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x7dd +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3836] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x7dd +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 3837] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x7dd +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 3838] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3839] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3840] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3841] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3842] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3843] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3844] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3845] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x7dd +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 3846] +//[ITEM 3847] +//[ITEM 3848] +//[ITEM 3849] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 3850] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3851] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3852] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3853] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3854] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3855] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 3856] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3857] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3858] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x7dd +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_dullcopper.dfn b/data/dfndata/create/masonry_dullcopper.dfn new file mode 100644 index 000000000..223b6d47b --- /dev/null +++ b/data/dfndata/create/masonry_dullcopper.dfn @@ -0,0 +1,704 @@ +[ITEM 3600] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x973 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3601] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x973 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3602] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x973 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3603] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x973 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3604] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x973 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3605] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x973 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3606] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x973 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3607] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x973 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3608] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x973 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 3609] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x973 +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3610] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x973 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3611] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x973 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3612] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x973 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3613] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x973 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3614] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x973 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 3615] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x973 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3616] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x973 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3617] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x973 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3618] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x973 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3619] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x973 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3620] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x973 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 3621] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x973 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3622] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x973 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3623] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x973 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3624] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x973 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3625] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x973 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3626] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x973 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 3627] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x973 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3628] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x973 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3629] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x973 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3630] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x973 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3631] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x973 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3632] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x973 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3633] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x973 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3634] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x973 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3635] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x973 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3636] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x973 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 3637] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x973 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 3638] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3639] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3640] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3641] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3642] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3643] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3644] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3645] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x973 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 3646] +//[ITEM 3647] +//[ITEM 3648] +//[ITEM 3649] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 3650] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3651] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3652] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3653] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3654] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3655] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 3656] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3657] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3658] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x973 +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_gold.dfn b/data/dfndata/create/masonry_gold.dfn new file mode 100644 index 000000000..22daec47a --- /dev/null +++ b/data/dfndata/create/masonry_gold.dfn @@ -0,0 +1,704 @@ +[ITEM 4000] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x8a5 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4001] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x8a5 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4002] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x8a5 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4003] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x8a5 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4004] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x8a5 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4005] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x8a5 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4006] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x8a5 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4007] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4008] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 4009] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x8a5 +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4010] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x8a5 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4011] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x8a5 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4012] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x8a5 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4013] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x8a5 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4014] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x8a5 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 4015] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4016] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4017] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4018] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x8a5 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4019] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x8a5 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4020] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x8a5 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 4021] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x8a5 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4022] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x8a5 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4023] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x8a5 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4024] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x8a5 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4025] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x8a5 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4026] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x8a5 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 4027] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x8a5 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4028] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x8a5 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4029] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x8a5 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4030] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x8a5 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4031] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x8a5 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4032] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x8a5 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4033] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x8a5 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4034] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x8a5 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4035] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x8a5 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4036] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x8a5 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 4037] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x8a5 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 4038] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4039] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4040] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4041] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4042] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4043] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4044] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4045] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x8a5 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 4046] +//[ITEM 4047] +//[ITEM 4048] +//[ITEM 4049] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 4050] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4051] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4052] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4053] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4054] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4055] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 4056] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4057] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4058] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x8a5 +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_shadowiron.dfn b/data/dfndata/create/masonry_shadowiron.dfn new file mode 100644 index 000000000..40ce6105c --- /dev/null +++ b/data/dfndata/create/masonry_shadowiron.dfn @@ -0,0 +1,704 @@ +[ITEM 3700] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x966 +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3701] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x966 +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3702] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x966 +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3703] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x966 +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3704] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x966 +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3705] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x966 +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3706] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x966 +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3707] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x966 +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3708] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x966 +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 3709] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x966 +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3710] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x966 +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3711] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x966 +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3712] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x966 +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3713] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x966 +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3714] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x966 +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 3715] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x966 +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3716] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x966 +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3717] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x966 +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3718] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x966 +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3719] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x966 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3720] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x966 +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 3721] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x966 +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3722] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x966 +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3723] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x966 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3724] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x966 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3725] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x966 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3726] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x966 +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 3727] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x966 +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3728] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x966 +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3729] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x966 +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3730] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x966 +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3731] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x966 +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3732] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x966 +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3733] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x966 +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3734] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x966 +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3735] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x966 +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3736] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x966 +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 3737] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x966 +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 3738] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3739] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3740] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3741] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3742] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3743] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3744] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3745] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x966 +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 3746] +//[ITEM 3747] +//[ITEM 3748] +//[ITEM 3749] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 3750] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3751] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3752] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3753] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3754] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3755] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 3756] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3757] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3758] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x966 +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_valorite.dfn b/data/dfndata/create/masonry_valorite.dfn new file mode 100644 index 000000000..911b991b8 --- /dev/null +++ b/data/dfndata/create/masonry_valorite.dfn @@ -0,0 +1,704 @@ +[ITEM 4300] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x8ab +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4301] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x8ab +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4302] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x8ab +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4303] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x8ab +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4304] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x8ab +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4305] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x8ab +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4306] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x8ab +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4307] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x8ab +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4308] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x8ab +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 4309] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x8ab +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4310] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x8ab +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4311] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x8ab +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4312] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x8ab +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4313] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x8ab +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4314] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x8ab +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 4315] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x8ab +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4316] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x8ab +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4317] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x8ab +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4318] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x8ab +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4319] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x8ab +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4320] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x8ab +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 4321] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x8ab +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4322] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x8ab +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4323] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x8ab +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4324] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x8ab +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4325] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x8ab +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4326] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x8ab +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 4327] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x8ab +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4328] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x8ab +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4329] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x8ab +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4330] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x8ab +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4331] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x8ab +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4332] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x8ab +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4333] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x8ab +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4334] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x8ab +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4335] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x8ab +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4336] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x8ab +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 4337] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x8ab +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 4338] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4339] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4340] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4341] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4342] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4343] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4344] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4345] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x8ab +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 4346] +//[ITEM 4347] +//[ITEM 4348] +//[ITEM 4349] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 4350] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4351] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4352] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4353] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4354] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4355] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 4356] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4357] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4358] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x8ab +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/create/masonry_verite.dfn b/data/dfndata/create/masonry_verite.dfn new file mode 100644 index 000000000..e3b5b51f9 --- /dev/null +++ b/data/dfndata/create/masonry_verite.dfn @@ -0,0 +1,704 @@ +[ITEM 4200] +{ +NAME=Vase +ID=0x0b46 +RESOURCE=STONE 1 0x89f +SKILL=11 520 1020 +ADDITEM=0x0b46 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4201] +{ +NAME=Large Vase +ID=0x0b45 +RESOURCE=STONE 3 0x89f +SKILL=11 520 1020 +ADDITEM=0x0b45 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4202] +{ +NAME=small Urn +ID=0x241c +RESOURCE=STONE 3 0x89f +SKILL=11 820 1030 +ADDITEM=0x241c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4203] +{ +NAME=Tower sculpture +ID=0x241a +RESOURCE=STONE 3 0x89f +SKILL=11 820 1030 +ADDITEM=0x241a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4204] +{ +NAME=gargoyle painting +ID=0x403d +RESOURCE=STONE 3 0x89f +SKILL=11 820 1330 +ADDITEM=0x403d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4205] +{ +NAME=gargoyle sculpture +ID=0x403f +RESOURCE=STONE 3 0x89f +SKILL=11 820 1320 +ADDITEM=0x403f +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4206] +{ +NAME=gargoyle vase +ID=0x4042 +RESOURCE=STONE 3 0x89f +SKILL=11 800 1260 +ADDITEM=0x4042 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4207] +{ +NAME=Tall 18th anniversary Vase +ID=0x9bc7 +RESOURCE=STONE 6 0x89f +SKILL=11 600 1100 +ADDITEM=0x9bc7 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4208] +{ +NAME=short 18th anniversary Vase +ID=0x9bca +RESOURCE=STONE 6 0x89f +SKILL=11 600 1100 +ADDITEM=0x9bca +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// furniture ///// +////////////////////////////////////// + +[ITEM 4209] +{ +NAME=stone chair +ID=0x1218 +RESOURCE=STONE 4 0x89f +SKILL=11 550 1050 +ADDITEM=0x1218 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4210] +{ +NAME=stone table (east) +ID=0x14f0 +RESOURCE=STONE 6 0x89f +SKILL=11 650 1150 +ADDITEM=mediumstonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4211] +{ +NAME=stone table (south) +ID=0x14f0 +RESOURCE=STONE 6 0x89f +SKILL=11 650 1150 +ADDITEM=mediumstonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4212] +{ +NAME=large stone table (east) +ID=0x14f0 +RESOURCE=STONE 9 0x89f +SKILL=11 750 1250 +ADDITEM=largestonetableeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4213] +{ +NAME=large stone table (south) +ID=0x14f0 +RESOURCE=STONE 9 0x89f +SKILL=11 750 1250 +ADDITEM=largestonetablesouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4214] +{ +NAME=ritual table +ID=0x14f0 +RESOURCE=STONE 8 0x89f +SKILL=11 940 1030 +ADDITEM=ritualtabledeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// statues ///// +////////////////////////////////////// + +[ITEM 4215] +{ +NAME=small statue (south) +ID=0x139a +RESOURCE=STONE 3 0x89f +SKILL=11 600 1100 +ADDITEM=0x139a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4216] +{ +NAME=small statue (north) +ID=0x139b +RESOURCE=STONE 3 0x89f +SKILL=11 600 1100 +ADDITEM=0x139b +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4217] +{ +NAME=small statue (east) +ID=0x139c +RESOURCE=STONE 3 0x89f +SKILL=11 600 1100 +ADDITEM=0x139c +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4218] +{ +NAME=pegasus statuette +ID=0x139d +RESOURCE=STONE 4 0x89f +SKILL=11 700 1200 +ADDITEM=0x139d +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4219] +{ +NAME=gargoyle statue +ID=0x494e +RESOURCE=STONE 20 0x89f +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4220] +{ +NAME=gryphon statue +ID=0x494e +RESOURCE=STONE 15 0x89f +SKILL=11 540 1040 +ADDITEM=0x494e +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// Misc addons ///// +////////////////////////////////////// + +[ITEM 4221] +{ +NAME=stone anvil (east) +ID=0x14f0 +RESOURCE=STONE 20 0x89f +SKILL=11 780 1280 +ADDITEM=stoneanvileastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4222] +{ +NAME=stone anvil (south) +ID=0x14f0 +RESOURCE=STONE 20 0x89f +SKILL=11 780 1280 +ADDITEM=stoneanvilsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4223] +{ +NAME=large gargish bed (east) +ID=0x14f0 +RESOURCE=STONE 3 0x89f +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedeastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4224] +{ +NAME=large gargish bed (south) +ID=0x14f0 +RESOURCE=STONE 3 0x89f +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=largegargoylebedsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4225] +{ +NAME=gargish cot (east) +ID=0x14f0 +RESOURCE=STONE 3 0x89f +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteasteastdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4226] +{ +NAME=gargish cot (south) +ID=0x14f0 +RESOURCE=STONE 3 0x89f +RESOURCE=CLOTH 100 +SKILL=11 760 1260 +SKILL=34 700 750 +ADDITEM=gargishcoteastsouthdeed +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone armor ///// +////////////////////////////////////// + +[ITEM 4227] +{ +NAME=gargish stone arms +ID=0x0283 +RESOURCE=STONE 8 0x89f +SKILL=11 560 1060 +ADDITEM=femalegargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4228] +{ +NAME=gargish stone chest +ID=0x0285 +RESOURCE=STONE 12 0x89f +SKILL=11 560 1060 +ADDITEM=femalegargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4229] +{ +NAME=gargish stone leggings +ID=0x0289 +RESOURCE=STONE 10 0x89f +SKILL=11 560 1060 +ADDITEM=femalegargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4230] +{ +NAME=gargish stone kilt +ID=0x0287 +RESOURCE=STONE 6 0x89f +SKILL=11 480 980 +ADDITEM=femalegargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4231] +{ +NAME=gargish stone arms +ID=0x0284 +RESOURCE=STONE 8 0x89f +SKILL=11 560 1060 +ADDITEM=gargishstonearms +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4232] +{ +NAME=gargish stone chest +ID=0x0286 +RESOURCE=STONE 12 0x89f +SKILL=11 560 1060 +ADDITEM=gargishstonechest +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4233] +{ +NAME=gargish stone leggings +ID=0x028a +RESOURCE=STONE 10 0x89f +SKILL=11 560 1060 +ADDITEM=gargishstoneleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4234] +{ +NAME=gargish stone kilt +ID=0x0288 +RESOURCE=STONE 6 0x89f +SKILL=11 480 980 +ADDITEM=gargishstonekilt +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4235] +{ +NAME=large stone shield +ID=0x4205 +RESOURCE=STONE 16 0x89f +SKILL=11 550 1060 +ADDITEM=largestoneshield +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4236] +{ +NAME=gargish stone amulet +ID=0x4D0a +RESOURCE=STONE 3 0x89f +SKILL=11 600 1100 +ADDITEM=0x4D0a +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone weapons ///// +////////////////////////////////////// + +[ITEM 4237] +{ +NAME=stone war sword +ID=0x4D0a +RESOURCE=STONE 18 0x89f +SKILL=11 550 1050 +ADDITEM=stonewarsword +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone walls ///// +////////////////////////////////////// + +[ITEM 4238] +{ +NAME=rough windowless +ID=0x01D0 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughwindowless1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4239] +{ +NAME=rough window +ID=0x01D3 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughwindow1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4240] +{ +NAME=rough arch +ID=0x01D5 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=rougharch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4241] +{ +NAME=rough pillar +ID=0x01Da +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughpillar +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4242] +{ +NAME=rough rounded arch +ID=0x01DB +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughroundedarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4243] +{ +NAME=rough small arch +ID=0x01E0 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughsmallarch1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4244] +{ +NAME=rough angled pillar +ID=0x01E6 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=roughangledpillar1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4245] +{ +NAME=short rough +ID=0x01E8 +RESOURCE=STONE 10 0x89f +SKILL=11 600 1100 +ADDITEM=shortrough1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +//[ITEM 4246] +//[ITEM 4247] +//[ITEM 4248] +//[ITEM 4249] + +////////////////////////////////////// +//// stone stairs ///// +////////////////////////////////////// + +[ITEM 4250] +{ +NAME=short rough +ID=0x0788 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughblock +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4251] +{ +NAME=rough steps +ID=0x0789 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4252] +{ +NAME=rough corner steps +ID=0x078d +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughcornersteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4253] +{ +NAME=rough rounded corner step +ID=0x0791 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughroundedcornerseps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4254] +{ +NAME=rough inset steps +ID=0x0795 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughinsetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4255] +{ +NAME=rough rounded inset steps +ID=0x0799 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=roughroundedisetsteps1 +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +////////////////////////////////////// +//// stone floors ///// +////////////////////////////////////// + +[ITEM 4256] +{ +NAME=light paver +ID=0x0519 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=lightpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4257] +{ +NAME=medium paver +ID=0x0519 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=mediumpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 4258] +{ +NAME=dark paver +ID=0x0519 +RESOURCE=STONE 5 0x89f +SKILL=11 600 1100 +ADDITEM=darkpaver +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} \ No newline at end of file diff --git a/data/dfndata/items/building/floors/craftable_tiles.dfn b/data/dfndata/items/building/floors/craftable_tiles.dfn new file mode 100644 index 000000000..cf9b816f4 --- /dev/null +++ b/data/dfndata/items/building/floors/craftable_tiles.dfn @@ -0,0 +1,26 @@ +[base_craftable_tile] +{ +get=base_item +script=5080 +weight=500 +movable=1 +decay=1 +} + +[lightpaver] +{ +get=base_craftable_tile +id=0x0519 +} + +[mediumpaver] +{ +get=base_craftable_tile +id=0x051d +} + +[darkpaver] +{ +get=base_craftable_tile +id=0x0521 +} \ No newline at end of file diff --git a/data/dfndata/items/building/walls/craftablewalls.dfn b/data/dfndata/items/building/walls/craftablewalls.dfn index ebc49c901..2d40adb5a 100644 --- a/data/dfndata/items/building/walls/craftablewalls.dfn +++ b/data/dfndata/items/building/walls/craftablewalls.dfn @@ -7,176 +7,302 @@ movable=1 decay=1 } -[RoughWindowless1] +[roughwindowless1] { get=base_craftable_wall -id=0x01CF +id=0x01cf } -[RoughWindowless2] +[roughwindowless2] { get=base_craftable_wall -id=0x01D0 +id=0x01d0 } -[RoughWindowless3] +[roughwindowless3] { get=base_craftable_wall -id=0x01D1 +id=0x01d1 } -[RoughWindowless4] +[roughwindowless4] { get=base_craftable_wall -id=0x01D2 +id=0x01d2 } -[RoughWindow1] +[roughwindow1] { get=base_craftable_wall -id=0x01D3 +id=0x01d3 } -[RoughWindow2] +[roughwindow2] { get=base_craftable_wall -id=0x01D4 +id=0x01d4 } -[RoughArch1] +[rougharch1] { get=base_craftable_wall -id=0x01D5 +id=0x01d5 } -[RoughArch2] +[rougharch2] { get=base_craftable_wall -id=0x01D6 +id=0x01d6 } -[RoughArch3] +[rougharch3] { get=base_craftable_wall -id=0x01D7 +id=0x01d7 } -[RoughArch4] +[rougharch4] { get=base_craftable_wall -id=0x01D8 +id=0x01d8 } -[RoughArch5] +[rougharch5] { get=base_craftable_wall -id=0x01D9 +id=0x01d9 } -[RoughPillar] +[roughPillar] { get=base_craftable_wall -id=0x01DA +id=0x01da } -[RoughRoundedArch1] +[roughroundedarch1] { get=base_craftable_wall -id=0x01DB +id=0x01db } -[RoughRoundedArch2] +[roughroundedarch2] { get=base_craftable_wall -id=0x01DC +id=0x01dc } -[RoughRoundedArch3] +[roughroundedarch3] { get=base_craftable_wall -id=0x01DD +id=0x01dd } -[RoughRoundedArch4] +[roughroundedarch4] { get=base_craftable_wall -id=0x01DE +id=0x01dE } -[RoughRoundedArch5] +[roughroundedarch5] { get=base_craftable_wall -id=0x01DF +id=0x01df } -[RoughSmallArch1] +[roughsmallarch1] { get=base_craftable_wall id=0x01E0 } -[RoughSmallArch2] +[roughsmallarch2] { get=base_craftable_wall id=0x01E1 } -[RoughSmallArch3] +[roughsmallarch3] { get=base_craftable_wall id=0x01E2 } -[RoughSmallArch4] +[roughsmallarch4] { get=base_craftable_wall id=0x01E3 } -[RoughSmallArch5] +[roughsmallarch5] { get=base_craftable_wall id=0x01E4 } -[RoughSmallArch6] +[roughsmallarch6] { get=base_craftable_wall id=0x01E5 } -[RoughAngledPillar1] +[roughangledPillar1] { get=base_craftable_wall id=0x01E6 } -[RoughAngledPillar2] +[roughangledPillar2] { get=base_craftable_wall id=0x01E7 } -[ShortRough1] +[shortrough1] { get=base_craftable_wall id=0x01E8 } -[ShortRough2] +[shortrough2] { get=base_craftable_wall id=0x01E9 } -[ShortRough3] +[shortrough3] { get=base_craftable_wall -id=0x01EA +id=0x01Ea } -[ShortRough4] +[shortrough4] { get=base_craftable_wall -id=0x01EB +id=0x01Eb } + +[roughblock] +{ +get=base_craftable_wall +id=0x0788 +} + +[roughsteps1] +{ +get=base_craftable_wall +id=0x0789 +} + +[roughsteps2] +{ +get=base_craftable_wall +id=0x078a +} + +[roughsteps3] +{ +get=base_craftable_wall +id=0x078b +} + +[roughsteps4] +{ +get=base_craftable_wall +id=0x078c +} + +[roughcornersteps1] +{ +get=base_craftable_wall +id=0x078d +} + +[roughcornersteps2] +{ +get=base_craftable_wall +id=0x078E +} + +[roughcornersteps3] +{ +get=base_craftable_wall +id=0x078f +} + +[roughcornersteps4] +{ +get=base_craftable_wall +id=0x0790 +} + +[roughroundedcornerseps1] +{ +get=base_craftable_wall +id=0x0791 +} + +[roughroundedcornerseps2] +{ +get=base_craftable_wall +id=0x0792 +} + +[roughroundedcornerseps3] +{ +get=base_craftable_wall +id=0x0793 +} + +[roughroundedcornerseps4] +{ +get=base_craftable_wall +id=0x0794 +} + +[roughinsetsteps1] +{ +get=base_craftable_wall +id=0x0795 +} + +[roughinsetsteps2] +{ +get=base_craftable_wall +id=0x0796 +} + +[roughinsetsteps3] +{ +get=base_craftable_wall +id=0x0797 +} + +[roughinsetsteps4] +{ +get=base_craftable_wall +id=0x0798 +} + +[roughroundedisetsteps1] +{ +get=base_craftable_wall +id=0x0799 +} + +[roughroundedisetsteps2] +{ +get=base_craftable_wall +id=0x079a +} + +[roughroundedisetsteps3] +{ +get=base_craftable_wall +id=0x079b +} + +[roughroundedisetsteps4] +{ +get=base_craftable_wall +id=0x079c +} \ No newline at end of file diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index 0ceac9385..614739c13 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -5066,6 +5066,44 @@ 14068=pegasus statuette 14069=gargoyle statue 14070=gryphon statue +14071=stone anvil (east) +14072=stone anvil (south) +14073=large gargish bed (east) +14074=large gargish bed (south) +14075=gargish cot (east) +14076=gargish cot (south) +14077=gargish stone arms +14078=gargish stone chest +14079=gargish stone leggings +14080=gargish stone kilt +14081=gargish stone arms +14082=gargish stone chest +14083=gargish stone leggings +14084=gargish stone kilt +14085=large stone shield +14086=gargish stone amulet +14087=stone war sword +14088=Rough Windowless +14089=Rough Window +14090=Rough Arch +14091=Rough Pillar +14092=Rough Rounded Arch +14093=Rough Small Arch +14094=Rough Angled Pillar +14095=Short Rough +14096=Stone Door (S In) +14097=Stone Door (E Out) +14098=Left Metal Door (S In) +14099=Right Metal Door (S In) +14100=short rough +14101=rough steps +14102=rough corner steps +14103=rough rounded corner step +14104=rough inset steps +14105=rough rounded inset steps +14106=light paver +14107=medium paver +14108=dark paver // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index 6ae82cd07..31cf82523 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -5034,14 +5034,14 @@ 14009=Stone Stairs 14010=Stone Floors 14011=Granite -14012=DullCopperGranite -14013=ShadowIronGranite -14014=CopperGranite -14015=BronzeGranite -14016=GoldGranite -14017=AgapiteGranite -14018=VeriteGranite -14019=ValoriteGranite +14012=Dull Copper Granite +14013=Shadow Iron Granite +14014=Copper Granite +14015=Bronze Granite +14016=Gold Granite +14017=Agapite Granite +14018=Verite Granite +14019=Valorite Granite 14050=vase 14051=large vase 14052=small urn @@ -5063,6 +5063,44 @@ 14068=pegasus statuette 14069=gargoyle statue 14070=gryphon statue +14071=stone anvil (east) +14072=stone anvil (south) +14073=large gargish bed (east) +14074=large gargish bed (south) +14075=gargish cot (east) +14076=gargish cot (south) +14077=gargish stone arms +14078=gargish stone chest +14079=gargish stone leggings +14080=gargish stone kilt +14081=gargish stone arms +14082=gargish stone chest +14083=gargish stone leggings +14084=gargish stone kilt +14085=large stone shield +14086=gargish stone amulet +14087=stone war sword +14088=Rough Windowless +14089=Rough Window +14090=Rough Arch +14091=Rough Pillar +14092=Rough Rounded Arch +14093=Rough Small Arch +14094=Rough Angled Pillar +14095=Short Rough +14096=Stone Door (S In) +14097=Stone Door (E Out) +14098=Left Metal Door (S In) +14099=Right Metal Door (S In) +14100=short rough +14101=rough steps +14102=rough corner steps +14103=rough rounded corner step +14104=rough inset steps +14105=rough rounded inset steps +14106=light paver +14107=medium paver +14108=dark paver // 15000 Skills 15000=Alchemy 15001=Anatomy diff --git a/data/js/server/misc/furniture_smartturn.js b/data/js/server/misc/furniture_smartturn.js index ab1c1caf4..1fd25f1f5 100644 --- a/data/js/server/misc/furniture_smartturn.js +++ b/data/js/server/misc/furniture_smartturn.js @@ -297,6 +297,86 @@ function SmartTurn( iTurn ) { iTurn.id = 0x01E8; } + else if( iTurn.id == 0x0789 ) // Rough steps + { + iTurn.id = 0x078A; + } + else if( iTurn.id == 0x078A ) + { + iTurn.id = 0x078B; + } + else if( iTurn.id == 0x078B ) + { + iTurn.id = 0x078C; + } + else if( iTurn.id == 0x078C ) + { + iTurn.id = 0x0789; + } + else if( iTurn.id == 0x078D ) // Rough corner steps + { + iTurn.id = 0x078E; + } + else if( iTurn.id == 0x078E ) + { + iTurn.id = 0x078F; + } + else if( iTurn.id == 0x078F ) + { + iTurn.id = 0x0790; + } + else if( iTurn.id == 0x0790 ) + { + iTurn.id = 0x078D; + } + else if( iTurn.id == 0x0791 ) // Rough rounded corner steps + { + iTurn.id = 0x0792; + } + else if( iTurn.id == 0x0792 ) + { + iTurn.id = 0x0793; + } + else if( iTurn.id == 0x0793 ) + { + iTurn.id = 0x0794; + } + else if( iTurn.id == 0x0794 ) + { + iTurn.id = 0x0791; + } + else if( iTurn.id == 0x0795 ) // Rough inset steps + { + iTurn.id = 0x0796; + } + else if( iTurn.id == 0x0796 ) + { + iTurn.id = 0x0797; + } + else if( iTurn.id == 0x0797 ) + { + iTurn.id = 0x0798; + } + else if( iTurn.id == 0x0798 ) + { + iTurn.id = 0x0795; + } + else if( iTurn.id == 0x0799 ) // Rough rounded inset steps + { + iTurn.id = 0x079A; + } + else if( iTurn.id == 0x079A ) + { + iTurn.id = 0x079B; + } + else if( iTurn.id == 0x079B ) + { + iTurn.id = 0x079C; + } + else if( iTurn.id == 0x079C ) + { + iTurn.id = 0x0799; + } } var divorcedPairs = [ // they are paired up, but more than one index apart and out of order, [hex ID, add or subtract distance] diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 57785f9f5..46edacb8c 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -17,6 +17,7 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); // is updated with specific create entries for the coloured weapon variants, they will just be // regular weapons with granite colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); +const allowColouredBuildings = false; // Set to true if you want coloured stone walls, stairs, floors // Optional: if you later decide to make some masonry items recipe-locked, we will use this map: // MasonryMap[buttonID] = { dictID, page, timerID, graniteMake: [makeIDByOre], recipeID?, minEra?, maxEra? } @@ -136,190 +137,222 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); const myPage = [ // Page 1 - Decorations - [14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058], + [ 14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058 ], // Page 2 - Furniture - [14059, 14060, 14061, 14062, 14063, 14064], + [ 14059, 14060, 14061, 14062, 14063, 14064 ], // Page 3 - Statues - [14065, 14066, 14067, 14068, 14069, 14070] - // Page 4 - Misc Addons - //[10240, 10241, 10242, 10243, 10244, 10245, 10246, 10247], + [ 14065, 14066, 14067, 14068, 14069, 14070 ], + // Page 4 - Misc Addons + [ 14071, 14072, 14073, 14074, 14075, 14076 ], // Page 5 - Stone Armor - //[10248, 10249, 10250, 10251, 10252, 10253, 10254], + [ 14077, 14078, 14079, 14080, 14081, 14082, 14083, 14084, 14085, 14086 ], // Page 6 - Stone Weapons - //[10255, 10256, 10257, 10258, 10259], + [ 14087 ], // Page 7 - Stone Walls - //[10260, 10261, 10262, 10263, 10264] + [ 14088, 14089, 14090, 14091, 14092, 14093, 14094, 14095, 14096,14097, 14098, 14099 ], // Page 8 - Stone Stairs - //[10260, 10261, 10262, 10263, 10264] + [ 14100, 14101, 14102, 14103, 14104, 14105 ], // Page 9 - Stone Floors - //[10260, 10261, 10262, 10263, 10264] + [ 14106, 14107, 14108 ] ]; const craftItems = [ // Iron [ // Decorations - [3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507], + [ 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508 ], // Furniture - [ 3508, 3509, 3510, 3511, 3512, 3513 ], + [ 3509, 3510, 3511, 3512, 3513, 3514 ], // Statues - [ 3514, 3515, 3516, 3517, 3518, 3519 ] + [ 3515, 3516, 3517, 3518, 3519, 3520 ], // Misc Addons - //[ 25, 21, 20, 22, 23, 26, 24, 27 ], + [ 3521, 3522, 3523, 3524, 3525, 3526 ], // Stone Armor - //[ 29, 28, 32, 30, 33, 31, 34 ], + [ 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536 ], // Stone Weapons - //[ 38, 39, 35, 36, 37 ], + [ 3537 ], // Stone Walls - //[ 44, 40, 41, 42, 43 ] + [ 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549 ], // Stone Stairs - //[ 44, 40, 41, 42, 43 ] + [ 3550, 3551, 3552, 3553, 3554, 3555 ], // Stone Floors - //[ 44, 40, 41, 42, 43 ] + [ 3556, 3557, 3558] ], // Dull Copper [ - // Metal Armors - [ 506, 508, 507, 509, 510, 511, 512, 515, 514, 513, 516, 517, 518 ], - // Helmets - [ 520, 522, 519, 521, 523 ], - // Shields - [ 500, 501, 505, 502, 504, 503 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608 ], + // Furniture + [ 3609, 3610, 3611, 3612, 3613, 3614 ], + // Statues + [ 3615, 3616, 3617, 3618, 3619, 3620 ], + // Misc Addons + [ 3621, 3622, 3623, 3624, 3625, 3626 ], + // Stone Armor + [ 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636 ], + // Stone Weapons + [ 3637 ], + // Stone Walls + [ 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649 ], + // Stone Stairs + [ 3650, 3651, 3652, 3653, 3654, 3655 ], + // Stone Floors + [ 3656, 3657, 3658] ], // Shadow Iron [ - // Metal Armors - [ 606, 608, 607, 609, 610, 611, 612, 615, 614, 613, 616, 617, 618 ], - // Helmets - [ 620, 622, 619, 621, 623 ], - // Shields - [ 600, 601, 605, 602, 604, 603 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708 ], + // Furniture + [ 3709, 3710, 3711, 3712, 3713, 3714 ], + // Statues + [ 3715, 3716, 3717, 3718, 3719, 3720 ], + // Misc Addons + [ 3721, 3722, 3723, 3724, 3725, 3726 ], + // Stone Armor + [ 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736 ], + // Stone Weapons + [ 3737 ], + // Stone Walls + [ 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749 ], + // Stone Stairs + [ 3750, 3751, 3752, 3753, 3754, 3755 ], + // Stone Floors + [ 3756, 3757, 3758] ], // Copper [ - // Metal Armors - [ 706, 708, 707, 709, 710, 711, 7012, 715, 714, 713, 716, 717, 718 ], - // Helmets - [ 720, 722, 719, 721, 723 ], - // Shields - [ 700, 701, 705, 702, 704, 703 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808 ], + // Furniture + [ 3809, 3810, 3811, 3812, 3813, 3814 ], + // Statues + [ 3815, 3816, 3817, 3818, 3819, 3820 ], + // Misc Addons + [ 3821, 3822, 3823, 3824, 3825, 3826 ], + // Stone Armor + [ 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836 ], + // Stone Weapons + [ 3837 ], + // Stone Walls + [ 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849 ], + // Stone Stairs + [ 3850, 3851, 3852, 3853, 3854, 3855 ], + // Stone Floors + [ 3856, 3857, 3858] ], // Bronze [ - // Metal Armors - [ 806, 808, 807, 809, 810, 811, 812, 815, 814, 813, 816, 817, 818 ], - // Helmets - [ 820, 822, 819, 821, 823 ], - // Shields - [ 800, 801, 805, 802, 804, 803 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908 ], + // Furniture + [ 3909, 3910, 3911, 3912, 3913, 3914 ], + // Statues + [ 3915, 3916, 3917, 3918, 3919, 3920 ], + // Misc Addons + [ 3921, 3922, 3923, 3924, 3925, 3926 ], + // Stone Armor + [ 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936 ], + // Stone Weapons + [ 3937 ], + // Stone Walls + [ 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949 ], + // Stone Stairs + [ 3950, 3951, 3952, 3953, 3954, 3955 ], + // Stone Floors + [ 3956, 3957, 3958] ], // Gold [ - // Metal Armors - [ 906, 908, 907, 909, 910, 911, 912, 915, 914, 913, 916, 917, 918 ], - // Helmets - [ 920, 922, 919, 921, 923 ], - // Shields - [ 900, 901, 905, 902, 904, 903 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008 ], + // Furniture + [ 4009, 4010, 4011, 4012, 4013, 4014 ], + // Statues + [ 4015, 4016, 4017, 4018, 4019, 4020 ], + // Misc Addons + [ 4021, 4022, 4023, 4024, 4025, 4026 ], + // Stone Armor + [ 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036 ], + // Stone Weapons + [ 4037 ], + // Stone Walls + [ 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049 ], + // Stone Stairs + [ 4050, 4051, 4052, 4053, 4054, 4055 ], + // Stone Floors + [ 4056, 4057, 4058] ], // Agapite [ - // Metal Armors - [ 1206, 1208, 1207, 1209, 1210, 1211, 1212, 1215, 1214, 1213, 1216, 1217, 1218 ], - // Helmets - [ 1220, 1222, 1219, 1221, 1223 ], - // Shields - [ 1200, 1201, 1205, 1202, 1204, 1203 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108 ], + // Furniture + [ 4109, 4110, 4111, 4112, 4113, 4114 ], + // Statues + [ 4115, 4116, 4117, 4118, 4119, 4120 ], + // Misc Addons + [ 4121, 4122, 4123, 4124, 4125, 4126 ], + // Stone Armor + [ 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136 ], + // Stone Weapons + [ 4137 ], + // Stone Walls + [ 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149 ], + // Stone Stairs + [ 4150, 4151, 4152, 4153, 4154, 4155 ], + // Stone Floors + [ 4156, 4157, 4158] ], // Verite [ - // Metal Armors - [ 1006, 1008, 1007, 1009, 1010, 1011, 1012, 1015, 1014, 1013, 1016, 1017, 1018 ], - // Helmets - [ 1020, 1022, 1019, 1021, 1023 ], - // Shields - [ 1000, 1001, 1005, 1002, 1004, 1003 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208 ], + // Furniture + [ 4209, 4210, 4211, 4212, 4213, 4214 ], + // Statues + [ 4215, 4216, 4217, 4218, 4219, 4220 ], + // Misc Addons + [ 4221, 4222, 4223, 4224, 4225, 4226 ], + // Stone Armor + [ 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236 ], + // Stone Weapons + [ 4237 ], + // Stone Walls + [ 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249 ], + // Stone Stairs + [ 4250, 4251, 4252, 4253, 4254, 4255 ], + // Stone Floors + [ 4256, 4257, 4258] ], // Valorite [ - // Metal Armors - [ 1106, 1108, 1107, 1109, 1110, 1111, 1112, 1115, 1114, 1113, 1116, 1117, 1118 ], - // Helmets - [ 1120, 1122, 1119, 1121, 1123 ], - // Shields - [ 1100, 1101, 1105, 1102, 1104, 1103 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] + // Decorations + [ 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308 ], + // Furniture + [ 4309, 4310, 4311, 4312, 4313, 4314 ], + // Statues + [ 4315, 4316, 4317, 4318, 4319, 4320 ], + // Misc Addons + [ 4321, 4322, 4323, 4324, 4325, 4326 ], + // Stone Armor + [ 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336 ], + // Stone Weapons + [ 4337 ], + // Stone Walls + [ 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349 ], + // Stone Stairs + [ 4350, 4351, 4352, 4353, 4354, 4355 ], + // Stone Floors + [ 4356, 4357, 4358] ] ]; @@ -343,7 +376,7 @@ const MasonryMap = {}; { var graniteRows = craftItems[graniteIndex]; - // pageIdx: 0..6 => pages 1..7 + // pageIdx: 0..6 => pages 1..9 for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) { var dictList = myPage[pageIdx]; @@ -395,20 +428,64 @@ MasonryMap[107].minEra = "tol"; // Tall 18th Anniversary Vase MasonryMap[107].recipeID = 3500; MasonryMap[108].minEra = "tol"; // Short 18th Anniversary Vase MasonryMap[108].recipeID = 3501; - //Page 2 starts at 200 MasonryMap[205].minEra = "sa"; // ritual table - //Page 3 starts at 300 MasonryMap[304].minEra = "sa"; // gargoyle statue MasonryMap[305].minEra = "sa"; // gryphon statue +//Page 4 starts at 400 +MasonryMap[400].minEra = "ml"; // stone anvil (east) +MasonryMap[400].recipeID = 3520; +MasonryMap[401].minEra = "ml"; // stone anvil (south) +MasonryMap[401].recipeID = 3521; +MasonryMap[402].minEra = "sa"; // large gargish bed (east) +MasonryMap[403].minEra = "sa"; // large gargish bed (south) +MasonryMap[404].minEra = "sa"; // gargish cot (east) +MasonryMap[405].minEra = "sa"; // gargish cot (south) +//Page 5 starts at 500 +MasonryMap[500].minEra = "sa"; // gargish stone arms +MasonryMap[501].minEra = "sa"; // gargish stone chest +MasonryMap[502].minEra = "sa"; // gargish stone leggings +MasonryMap[503].minEra = "sa"; // gargish stone kilt +MasonryMap[504].minEra = "sa"; // gargish stone arms +MasonryMap[505].minEra = "sa"; // gargish stone chest +MasonryMap[506].minEra = "sa"; // gargish stone leggings +MasonryMap[507].minEra = "sa"; // gargish stone kilt +MasonryMap[508].minEra = "sa"; // large stone shield +MasonryMap[509].minEra = "sa"; // gargish stone amulet +//Page 6 starts at 600 +MasonryMap[600].minEra = "sa"; // stone war sword +//Page 7 starts at 700 +MasonryMap[700].minEra = "tol"; // Rough Windowless +MasonryMap[701].minEra = "tol"; // Rough Window +MasonryMap[702].minEra = "tol"; // Rough Arch +MasonryMap[703].minEra = "tol"; // Rough Pillar +MasonryMap[704].minEra = "tol"; // Rough Rounded Arch +MasonryMap[705].minEra = "tol"; // Rough Small Arch +MasonryMap[706].minEra = "tol"; // Rough Angled Pillar +MasonryMap[707].minEra = "tol"; // Short Rough +MasonryMap[708].minEra = "tol"; // Stone Door (S In) +MasonryMap[709].minEra = "tol"; // Stone Door (E Out) +MasonryMap[710].minEra = "tol"; // Left Metal Door (S In) +MasonryMap[711].minEra = "tol"; // Right Metal Door (S In) +//Page 8 starts at 800 +MasonryMap[800].minEra = "tol"; // short rough +MasonryMap[801].minEra = "tol"; // rough steps +MasonryMap[802].minEra = "tol"; // rough corner steps +MasonryMap[803].minEra = "tol"; // rough rounded corner step +MasonryMap[804].minEra = "tol"; // rough inset steps +MasonryMap[805].minEra = "tol"; // rough rounded inset steps +//Page 9 starts at 900 +MasonryMap[900].minEra = "tol"; // light paver +MasonryMap[901].minEra = "tol"; // medium paver +MasonryMap[902].minEra = "tol"; // dark paver function PageX( socket, pUser, pageNum ) { if( !ValidateObject( pUser )) return; - // Pages 1 - 7: normal crafting pages + // Pages 1 - 9: normal crafting pages // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) var subPage = pUser.GetTempTag( "subPage" ); @@ -491,8 +568,12 @@ function PageX( socket, pUser, pageNum ) var buttonID = pageItems[i]; var data = MasonryMap[buttonID]; - // Do not show weapons when colgranited ingots selected and colgranited weapons are disabled - if( !allowColouredWeapons && resourceHue > 0 && data.page > 3 ) + // Do not show weapons when colored granited ingots selected and colored granited weapons are disabled + if( !allowColouredWeapons && resourceHue > 0 && data.page == 6 ) + continue; + + // Do not show walls when colored granited ingots selected and colored granited walls are disabled + if( !allowColouredBuildings && resourceHue > 0 && data.page > 6 ) continue; var entryText = ""; @@ -970,9 +1051,9 @@ function onTimer( pUser, timerID ) var socket = pUser.socket; - if( timerID >= 1 && timerID <= 7 ) + if( timerID >= 1 && timerID <= 9 ) { - PageX( socket, pUser, timerID ); // Pages 1 - 7 + PageX( socket, pUser, timerID ); // Pages 1 - 9 } else if( timerID == 20 ) { @@ -991,6 +1072,8 @@ function onGumpPress( pSock, pButton, gumpData ) var pUser = pSock.currentChar; var usedMakeLast = false; + pSock.SysMessage( "DEBUG: button " + pButton ); + if( !ValidateObject( pUser ) || pUser.dead ) return; From 124e852550ed4e0a55a9bb5e587103a914b048f3 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 19:56:49 -0600 Subject: [PATCH 09/43] dictionary updates --- data/dictionaries/dictionary.CSY | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.FRE | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.GER | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.ITA | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.POL | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.PTG | 79 ++++++++++++++++++++++++++++++++ data/dictionaries/dictionary.SPA | 79 ++++++++++++++++++++++++++++++++ 7 files changed, 553 insertions(+) diff --git a/data/dictionaries/dictionary.CSY b/data/dictionaries/dictionary.CSY index 93cd549fa..bee4c28d6 100644 --- a/data/dictionaries/dictionary.CSY +++ b/data/dictionaries/dictionary.CSY @@ -5020,6 +5020,85 @@ 13609=prázdné lahviÄky 13610=plné lahviÄky 13611=toÄící se pÅ™esýpací hodiny +// 14001 - 14500 Zednické Å™emeslné dovednosti +14001=Zednické menu +14002=Dekorace +14003=Nábytek +14004=Sochy +14005=Různé doplňky +14006=Kamenné brnÄ›ní +14007=Kamenné zbranÄ› +14008=Kamenné zdi +14009=Kamenné schody +14010=Kamenné podlahy +14011=Žula +14012=Malá mÄ›dÄ›ná žula +14013=Žula Shadow Iron +14014=MÄ›dÄ›ná žula +14015=Bronzová žula +14016=Zlatá žula +14017=Agapitová žula +14018=Verite žula +14019=Valoritová žula +14050=váza +14051=velká váza +14052=malá urna +14053=věžová socha +14054=obraz chrliÄe +14055=socha chrliÄe +14056=váza chrliÄ +14057=vysoká váza k 18. výroÄí +14058=nízká váza k 18. výroÄí +14059=kamenná židle +14060=kamenný stůl (východ) +14061=kamenný stůl (jih) +14062=velký kamenný stůl (východ) +14063=velký kamenný stůl (jih) +14064=rituální stůl +14065=malá socha (jih) +14066=malá socha (sever) +14067=malá socha (východ) +14068=soÅ¡ka pegase +14069=socha chrliÄe +14070=socha gryfona +14071=kamenná kovadlina (východ) +14072=kamenná kovadlina (jih) +14073=velká Äernobílá postel (východ) +14074=velká Äernobílá postel (jih) +14075=Äernobílá postýlka (východ) +14076=Äernobílá postýlka (jih) +14077=Äernobílé kamenné paže +14078=Äernobílá kamenná truhla +14079=Äernobílé kamenné legíny +14080=Äernobílý kamenný kilt +14081=Äernobílé kamenné paže +14082=Äernobílá kamenná truhla +14083=Äernobílé kamenné legíny +14084=Äernobílý kamenný kilt +14085=velký kamenný Å¡tít +14086=Äernobílý kamenný amulet +14087=kamenný váleÄný meÄ +14088=Drůstkový Bez oken +14089=Drůstkový Okno +14090=Drůstkový Oblouk +14091=Hrubý sloupek +14092=Hrubý zaoblený oblouk +14093=Hrubý malý oblouk +14094=Hrubý Å¡ikmý sloupek +14095=Krátký hrubý +14096=Kamenné dveÅ™e (J dovnitÅ™) +14097=Kamenné dveÅ™e (V ven) +14098=Levé kovové dveÅ™e (J dovnitÅ™) +14099=Pravé kovové dveÅ™e (J dovnitÅ™) +14100=krátký hrubý +14101=hrubé schody +14102=hrubé rohové schody +14103=hrubÄ› zaoblený rohový schod +14104=hrubé vložené schody +14105=hrubÄ› zaoblené vložené schody +14106=svÄ›tlá dlažba +14107=stÅ™ední dlažba +14108=tmavá dlažba // 15000 Dovednosti 15000=Alchymie 15001=Anatomie diff --git a/data/dictionaries/dictionary.FRE b/data/dictionaries/dictionary.FRE index ceffa3267..c6e82877c 100644 --- a/data/dictionaries/dictionary.FRE +++ b/data/dictionaries/dictionary.FRE @@ -5178,6 +5178,85 @@ 13609=flacons vides 13610=flacons pleins 13611=sablier tournant +// 14001 - 14500 Compétence en maçonnerie +14001=Menu Maçonnerie +14002=Décorations +14003=Mobilier +14004=Statues +14005=Accessoires divers +14006=Armure de pierre +14007=Armes de pierre +14008=Murs de pierre +14009=Escaliers de pierre +14010=Sols en pierre +14011=Granite +14012=Granite de cuivre mat +14013=Granite de fer de l'ombre +14014=Granite de cuivre +14015=Granite de bronze +14016=Granite d'or +14017=Granite d'agapite +14018=Granite de vératie +14019=Granite de valorite +14050=Vase +14051=Grand Vase +14052=Petite urne +14053=Sculpture de tour +14054=Peinture de gargouille +14055=Sculpture de gargouille +14056=Vase à gargouille +14057=Grand vase du 18e anniversaire +14058=Petit vase du 18e anniversaire +14059=Chaise en pierre +14060=Table en pierre (est) +14061=Table en pierre (sud) +14062=Grande table en pierre (est) +14063=Grande table en pierre (sud) +14064=Table rituelle +14065=Petite statue (sud) +14066=Petite statue (nord) +14067=Petite statue (est) +14068=Statuette de Pégase +14069=Statue de gargouille +14070=Statue de griffon +14071=Enclume en pierre (est) +14072=Pierre Enclume (sud) +14073=Grand lit gargish (est) +14074=Grand lit gargish (sud) +14075=Bébé gargish (est) +14076=Bébé gargish (sud) +14077=Armes en pierre gargish +14078=Coffre en pierre gargish +14079=Jambières en pierre gargish +14080=Kilt en pierre gargish +14081=Armes en pierre gargish +14082=Coffre en pierre gargish +14083=Jambières en pierre gargish +14084=Kilt en pierre gargish +14085=Grand bouclier en pierre +14086=Amulette en pierre gargish +14087=Épée de guerre en pierre +14088=Rugueux sans fenêtre +14089=Rugueux avec fenêtre +14090=Arche rugueuse +14091=Rugueux Pilier +14092 = Arche arrondie brute +14093 = Petite arche brute +14094 = Pilier angulaire brut +14095 = Courte marche brute +14096 = Porte en pierre (S vers l'intérieur) +14097 = Porte en pierre (E vers l'extérieur) +14098 = Porte métallique gauche (S vers l'intérieur) +14099 = Porte métallique droite (S vers l'intérieur) +14100 = Courte marche brute +14101 = Marches brutes +14102 = Marches d'angle brutes +14103 = Marche d'angle grossièrement arrondie +14104 = Marches encastrées brutes +14105 = Marches encastrées grossièrement arrondies +14106 = Pavé clair +14107 = Pavé moyen +14108 = Pavé foncé // 15000 compétences 15000=Alchimie 15001=Anatomie diff --git a/data/dictionaries/dictionary.GER b/data/dictionaries/dictionary.GER index 87c66291b..6ca2243f0 100644 --- a/data/dictionaries/dictionary.GER +++ b/data/dictionaries/dictionary.GER @@ -5022,6 +5022,85 @@ 13609=leere Fläschchen 13610=volle Fläschchen 13611=drehende Sanduhr +// 14001 - 14500 Maurerhandwerksfertigkeit +14001=Mauerwerksmenü +14002=Dekorationen +14003=Möbel +14004=Statuen +14005=Sonstige Erweiterungen +14006=Steinrüstung +14007=Steinwaffen +14008=Steinmauern +14009=Steintreppen +14010=Steinböden +14011=Granit +14012=Mattkupfergranit +14013=Schatteneisengranit +14014=Kupfergranit +14015=Bronzegranit +14016=Goldgranit +14017=Agapitgranit +14018=Veritgranit +14019=Valorit Granit +14050=Vase +14051=Große Vase +14052=Kleine Urne +14053=Turmskulptur +14054=Gemälde mit Wasserspeier +14055=Wasserspeier-Skulptur +14056=Wasserspeier-Vase +14057=Hohe Vase zum 18. Jahrestag +14058=Kleine Vase zum 18. Jahrestag +14059=Steinstuhl +14060=Steintisch (Osten) +14061=Steintisch (Süden) +14062=Großer Steintisch (Osten) +14063=Großer Steintisch (Süden) +14064=Ritualtisch +14065=Kleine Statue (Süden) +14066=Kleine Statue (Norden) +14067=Kleine Statue (Osten) +14068=Pegasus-Statuette +14069=Wasserspeier Statue +14070=Greifenstatue +14071=Steinamboss (Osten) +14072=Steinamboss (Süden) +14073=Großes, grelles Bett (Osten) +14074=Großes, grelles Bett (Süden) +14075=Grelles Feldbett (Osten) +14076=Grelles Feldbett (Süden) +14077=Grelle Steinarme +14078=Grelle Steintruhe +14079=Grelle Steinbeinlinge +14080=Grelle Steinkilt +14081=Grelle Steinarme +14082=Grelle Steintruhe +14083=Grelle Steinbeinlinge +14084=Grelle Steinkilt +14085=Großer Steinschild +14086=Grelles Steinamulett +14087=Steinkrieger Schwert +14088=Rohbau ohne Fenster +14089=Rohbau mit Fenster +14090=Rohbau mit Bogen +14091=Rohbau mit Pfeiler +14092=Rohbau mit Rundbogen +14093=Rohbau mit kleinem Bogen +14094=Rohbau mit abgewinkeltem Pfeiler +14095=Kurzbau +14096=Steintür (Südseite) +14097=Steintür (Ostseite) +14098=Linke Metalltür (Südseite) +14099=Rechte Metalltür (Südseite) +14100=Kurzbau +14101=Rohbau mit Stufen +14102=Rohbau mit Eckstufen +14103=Rohbau mit abgerundeten Eckstufen +14104=Rohbau mit Einsatzstufen +14105=Rohbau mit abgerundeten Einsatzstufen +14106=Heller Pflasterstein +14107=Mittelgroßer Pflasterstein +14108=Dunkler Pflasterstein // 15000 Fertigkeiten 15000=Alchemie 15001=Anatomie diff --git a/data/dictionaries/dictionary.ITA b/data/dictionaries/dictionary.ITA index ed7d775ca..fbbe1ac88 100644 --- a/data/dictionaries/dictionary.ITA +++ b/data/dictionaries/dictionary.ITA @@ -5022,6 +5022,85 @@ 13609=fialette vuote 13610=flaconi pieni 13611=clessidra rotante +// 14001 - 14500 Abilità di lavorazione della muratura +14001=Menu muratura +14002=Decorazioni +14003=Mobili +14004=Statue +14005=Accessori vari +14006=Armature di pietra +14007=Armi di pietra +14008=Muri di pietra +14009=Scale di pietra +14010=Pavimenti di pietra +14011=Granito +14012=Granito rame opaco +14013=Granito ferro ombra +14014=Granito rame +14015=Granito bronzo +14016=Granito oro +14017=Granito agapite +14018=Granito Verite +14019=Valorite Granito +14050=vaso +14051=vaso grande +14052=urna piccola +14053=scultura a torre +14054=dipinto a gargoyle +14055=scultura a gargoyle +14056=vaso a gargoyle +14057=vaso alto per il 18° anniversario +14058=vaso basso per il 18° anniversario +14059=sedia in pietra +14060=tavolo in pietra (est) +14061=tavolo in pietra (sud) +14062=tavolo in pietra grande (est) +14063=tavolo in pietra grande (sud) +14064=tavolo rituale +14065=statua piccola (sud) +14066=statua piccola (nord) +14067=statua piccola (est) +14068=statuetta di Pegaso +14069=gargoyle statua +14070=statua di grifone +14071=incudine di pietra (est) +14072=incudine di pietra (sud) +14073=grande letto di pietra (est) +14074=grande letto di pietra (sud) +14075=branda di pietra (est) +14076=branda di pietra (sud) +14077=braccia di pietra +14078=baule di pietra +14079=gambali di pietra +14080=kilt di pietra +14081=braccia di pietra +14082=baule di pietra +14083=gambali di pietra +14084=kilt di pietra +14085=grande scudo di pietra +14086=amuleto di pietra +14087=spada da guerra di pietra +14088=Grezzo Senza finestre +14089=Finestra grezza +14090=Arco grezzo +14091=Pilastro grezzo +14092=Arco arrotondato grezzo +14093=Arco piccolo grezzo +14094=Pilastro angolare grezzo +14095=Corto grezzo +14096=Porta in pietra (Ingresso S) +14097=Porta in pietra (Uscita E) +14098=Porta metallica sinistra (Ingresso S) +14099=Porta metallica destra (Ingresso S) +14100=Corto grezzo +14101=Gradini grezzi +14102=Gradini angolari grezzi +14103=Gradino angolare arrotondato grezzo +14104=Gradini con inserto grezzo +14105=Gradini con inserto arrotondato grezzo +14106=Pavimentazione chiara +14107=Pavimentazione media +14108=Pavimentazione scura // 15000 Abilità 15000=Alchimia 15001=Anatomia diff --git a/data/dictionaries/dictionary.POL b/data/dictionaries/dictionary.POL index 1c275eefc..2d20c829b 100644 --- a/data/dictionaries/dictionary.POL +++ b/data/dictionaries/dictionary.POL @@ -5021,6 +5021,85 @@ 13609=puste fiolki 13610=peÅ‚ne fiolki 13611=wirujÄ…ca klepsydra +// 14001 - 14500 UmiejÄ™tność rzemiosÅ‚a murarskiego +14001=Menu murarskie +14002=Dekoracje +14003=Meble +14004=PosÄ…gi +14005=Różne dodatki +14006=Kamienna zbroja +14007=Kamienna broÅ„ +14008=Kamienne Å›ciany +14009=Kamienne schody +14010=Kamienne podÅ‚ogi +14011=Granit +14012=Matowy granit miedziany +14013=Granit z cienistego żelaza +14014=Granit miedziany +14015=BrÄ…zowy granit +14016=ZÅ‚oty granit +14017=Granit agapitowy +14018=Granit verite +14019=Wartość Granity +14050=wazon +14051=duży wazon +14052=maÅ‚a urna +14053=rzeźba wieży +14054=obraz gargulca +14055=rzeźba gargulca +14056=wazon gargulca +14057=wysoki wazon na 18. rocznicÄ™ +14058=niski wazon na 18. rocznicÄ™ +14059=kamienne krzesÅ‚o +14060=kamienny stół (wschód) +14061=kamienny stół (poÅ‚udnie) +14062=duży kamienny stół (wschód) +14063=duży kamienny stół (poÅ‚udnie) +14064=stół rytualny +14065=maÅ‚a statua (poÅ‚udnie) +14066=maÅ‚a statua (północ) +14067=maÅ‚a statua (wschód) +14068=pegaz Statuetki +14069=posÄ…gi gargulców +14070=posÄ…g gryfa +14071=kamienne kowadÅ‚o (wschód) +14072=kamienne kowadÅ‚o (poÅ‚udnie) +14073=duże Å‚oże gargish (wschód) +14074=duże Å‚oże gargish (poÅ‚udnie) +14075=Å‚oże gargish (wschód) +14076=Å‚oże gargish (poÅ‚udnie) +14077=kamienne ramiona gargish +14078=skrzynia gargish +14079=kamienne nagolenniki gargish +14080=kamienny kilt gargish +14081=kamienne ramiona gargish +14082=kamienna skrzynia gargish +14083=kamienne nagolenniki gargish +14084=kamienny kilt gargish +14085=duża kamienna tarcza +14086=kamieÅ„ gargish Amulet +14087=Kamienny miecz wojenny +14088=Surowy bez okien +14089=Surowy okno +14090=Surowy Å‚uk +14091=Surowy filar +14092=Surowy Å‚uk zaokrÄ…glony +14093=Surowy maÅ‚y Å‚uk +14094=Surowy filar kÄ…towy +14095=Krótki surowy +14096=Kamienne drzwi (poÅ‚udniowe wejÅ›cie) +14097=Kamienne drzwi (wschodnie wyjÅ›cie) +14098=Lewe metalowe drzwi (poÅ‚udniowe wejÅ›cie) +14099=Prawe metalowe drzwi (poÅ‚udniowe wejÅ›cie) +14100=Krótki surowy +14101=Surowe stopnie +14102=Surowe stopnie narożne +14103=Surowy stopieÅ„ z zaokrÄ…glonym narożnikiem +14104=Surowe stopnie z wstawkami +14105=Surowe stopnie z zaokrÄ…glonymi wstawkami +14106=Jasny strach +14107=Å›rednia kostka brukowa +14108=ciemny strach // 15000 UmiejÄ™tnoÅ›ci 15000=Alchemia 15001=Anatomia diff --git a/data/dictionaries/dictionary.PTG b/data/dictionaries/dictionary.PTG index 913bd723d..a7da11198 100644 --- a/data/dictionaries/dictionary.PTG +++ b/data/dictionaries/dictionary.PTG @@ -5022,6 +5022,85 @@ 13609=frascos vazios 13610=frascos cheios 13611=ampulheta girando +// 14001 - 14500 Habilidade em Alvenaria +14001=Menu de Alvenaria +14002=Decorações +14003=Móveis +14004=Estátuas +14005=Acessórios Diversos +14006=Armadura de Pedra +14007=Armas de Pedra +14008=Paredes de Pedra +14009=Escadas de Pedra +14010=Pisos de Pedra +14011=Granito +14012=Granito Cobre Mate +14013=Granito Ferro Sombrio +14014=Granito Cobre +14015=Granito Bronze +14016=Granito Ouro +14017=Granito Agapita +14018=Granito Verita +14019=Valor Granitos +14050=vaso +14051=vaso grande +14052=urna pequena +14053=Escultura de Torre +14054=pintura de gárgula +14055=escultura de gárgula +14056=vaso de gárgula +14057=Vaso Alto do 18º Aniversário +14058=Vaso Baixo do 18º Aniversário +14059=cadeira de pedra +14060=mesa de pedra (nascente) +14061=mesa em pedra (sul) +14062=mesa de pedra grande (nascente) +14063=mesa de pedra grande (sul) +14064=mesa ritual +14065=estátua pequena (sul) +14066=estátua pequena (norte) +14067=estátua pequena (leste) +14068=pégaso estatuetas +14069=estátuas de gárgula +14070=estátua de grifo +14071=bigorna de pedra (leste) +14072=bigorna de pedra (sul) +14073=cama grande de gárgula (nascente) +14074=cama grande de gárgulas (sul) +14075=berço de gárgula (nascente) +14076=berço de gárgula (sul) +14077=braços de pedra de gárgula +14078=baú em pedra de gárgula +14079=calças de pedra de gárgula +14080=saia de pedra de gárgula +14081=braços de pedra de gárgula +14082=baú em pedra de gárgula +14083=calças de pedra de gárgula +14084=saia de pedra de gárgula +14085=escudo de pedra grande +14086=gárgula Amuleto de pedra +14087=Espada de guerra de pedra +14088=Sem janela rústica +14089=Janela rústica +14090=Arco rústico +14091=Pilar rústico +14092=Arco arredondado rústico +14093=Arco pequeno rústico +14094=Pilar angular rústico +14095=Rouco curto +14096=Porta em pedra (entrada sul) +14097=Porta de pedra (saída nascente) +14098=Porta metálica esquerda (entrada sul) +14099=Porta metálica direita (entrada sul) +14100=Rouco curto +14101=Degraus rústicos +14102=Degraus de canto rústicos +14103=Degrau de canto arredondado rústico +14104=Degraus embutidos rústicos +14105=Degraus embutidos arredondados rústicos +14106=Luz medo +14107=pavimento médio +14108=medo escuro // 15000 Competências 15000=Alchemia 15001=Anatomia diff --git a/data/dictionaries/dictionary.SPA b/data/dictionaries/dictionary.SPA index 3ab2d97f3..890a701e1 100644 --- a/data/dictionaries/dictionary.SPA +++ b/data/dictionaries/dictionary.SPA @@ -5022,6 +5022,85 @@ 13609=frascos vacíos 13610=frascos llenos 13611=reloj de arena giratorio +// 14001 - 14500 Habilidad de Artesanía en Albañilería +14001=Menú de Albañilería +14002=Decoraciones +14003=Mobiliario +14004=Estatuas +14005=Complementos Varios +14006=Armadura de Piedra +14007=Armas de Piedra +14008=Muros de Piedra +14009=Escaleras de Piedra +14010=Suelos de Piedra +14011=Granito +14012=Granito de Cobre Mate +14013=Granito de Hierro Sombrío +14014=Granito de Cobre +14015=Granito de Bronce +14016=Granito de Oro +14017=Granito de Agapita +14018=Granito de Verita +14019=Valor Granitos +14050=jarrón +14051=jarrón grande +14052=urna pequeña +14053=escultura de torre +14054=pintura de gárgola +14055=escultura de gárgola +14056=jarrón de gárgola +14057=jarrón alto del 18.º aniversario +14058=jarrón bajo del 18.º aniversario +14059=silla de piedra +14060=mesa de piedra (este) +14061=mesa de piedra (sur) +14062=mesa de piedra grande (este) +14063=mesa de piedra grande (sur) +14064=mesa ritual +14065=estatua pequeña (sur) +14066=estatua pequeña (norte) +14067=estatua pequeña (este) +14068=estatuillas de pegaso +14069=gárgola Estatuas +14070=Estatua de grifo +14071=Yunque de piedra (este) +14072=Yunque de piedra (sur) +14073=Cama grande de gárgola (este) +14074=Cama grande de gárgola (sur) +14075=Cuna de gárgola (este) +14076=Cuna de gárgola (sur) +14077=Brazos de piedra de gárgola +14078=Cofre de piedra de gárgola +14079=Polainas de piedra de gárgola +14080=Falda de piedra de gárgola +14081=Brazos de piedra de gárgola +14082=Cofre de piedra de gárgola +14083=Polainas de piedra de gárgola +14084=Falda de piedra de gárgola +14085=Escudo grande de piedra +14086=Amuleto de piedra de gárgola +14087=Espada de guerra de piedra +14088=Búsqueda Sin ventanas +14089=Ventana rústica +14090=Arco rústico +14091=Pilar rústico +14092=Arco redondeado rústico +14093=Arco pequeño rústico +14094=Pilar angular rústico +14095=Rústico corto +14096=Puerta de piedra (Sin entrada) +14097=Puerta de piedra (E sin salida) +14098=Puerta metálica izquierda (Sin entrada) +14099=Puerta metálica derecha (Sin entrada) +14100=Rústico corto +14101=Escalones rústicos +14102=Escalones de esquina rústicos +14103=Escalón de esquina redondeado rústico +14104=Escalones empotrados rústicos +14105=Escalones empotrados redondeados rústicos +14106=Piso claro +14107=Adoquín mediano +14108=Piso oscuro // 15000 Habilidades 15000=Alquimia 15001=Anatomía From 6fada609bd945062095281f06d54fd3ed9c04554 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 20:20:39 -0600 Subject: [PATCH 10/43] update --- data/dfndata/create/masonry.dfn | 51 ++++++++++++-- .../items/building/walls/craftablewalls.dfn | 28 ++++++++ data/js/item/buildingcraftables.js | 68 +++++++++++-------- data/js/server/house/houseCommands.js | 2 +- 4 files changed, 115 insertions(+), 34 deletions(-) diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index 5b229b77b..299084556 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -582,10 +582,53 @@ MAXRANK=10 SOUND=0x23D } -//[ITEM 3546] -//[ITEM 3547] -//[ITEM 3548] -//[ITEM 3549] +[ITEM 3546] +{ +NAME=StoneDoor_S_In +ID=0x0326 +RESOURCE=STONE 10 +SKILL=11 600 1100 +ADDITEM=StoneDoor_S_In +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3547] +{ +NAME=StoneDoor_E_Out +ID=0x032C +RESOURCE=STONE 10 +SKILL=11 600 1100 +ADDITEM=StoneDoor_E_Out +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3548] +{ +NAME=StoneDoor_S_Out +ID=0x032a +RESOURCE=STONE 10 +SKILL=11 600 1100 +ADDITEM=StoneDoor_S_Out +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} + +[ITEM 3549] +{ +NAME=StoneDoor_E_In +ID=0x0330 +RESOURCE=STONE 10 +SKILL=11 600 1100 +ADDITEM=StoneDoor_E_In +MINRANK=1 +MAXRANK=10 +SOUND=0x23D +} ////////////////////////////////////// //// stone stairs ///// diff --git a/data/dfndata/items/building/walls/craftablewalls.dfn b/data/dfndata/items/building/walls/craftablewalls.dfn index 2d40adb5a..2b705d919 100644 --- a/data/dfndata/items/building/walls/craftablewalls.dfn +++ b/data/dfndata/items/building/walls/craftablewalls.dfn @@ -305,4 +305,32 @@ id=0x079b { get=base_craftable_wall id=0x079c +} + +[StoneDoor_S_In] +{ +get=base_craftable_wall +id=0x0326 +custominttag=CraftableDoor 1 +} + +[StoneDoor_E_Out] +{ +get=base_craftable_wall +id=0x032C +custominttag=CraftableDoor 1 +} + +[StoneDoor_S_Out] +{ +get=base_craftable_wall +id=0x032a +custominttag=CraftableDoor 1 +} + +[StoneDoor_E_In] +{ +get=base_craftable_wall +id=0x0330 +custominttag=CraftableDoor 1 } \ No newline at end of file diff --git a/data/js/item/buildingcraftables.js b/data/js/item/buildingcraftables.js index 0a5cf1d98..b053e19df 100644 --- a/data/js/item/buildingcraftables.js +++ b/data/js/item/buildingcraftables.js @@ -3,7 +3,10 @@ /** @type { ( thingCreated: BaseObject, thingType: 0 | 1 ) => void } */ function onCreateDFN( iCreated, dfnSection ) { - setLockedState( iCreated, false ); + if( iCreated.GetTag( "CraftableDoor") == null ) + { + setLockedState( iCreated, false ); + } iCreated.SetTag( "BuildingCraftable", 1 ); } @@ -44,20 +47,23 @@ function onUseChecked( pUser, iUsed ) return false; } - var locked = iUsed.GetTag( "CraftWallLocked" ); - - if( locked == 1) - { - setLockedState( iUsed, false ); - if( pSocket ) - pSocket.SysMessage( "You unlock the crafted wall. It can now be moved and will decay normally." ); - } - else - { - setLockedState( iUsed, true ); - if( pSocket ) - pSocket.SysMessage( "You lock the crafted wall in place. It will no longer decay." ); - } + if( iUsed.GetTag( "CraftableDoor") == null ) + { + var locked = iUsed.GetTag( "CraftWallLocked" ); + + if( locked == 1 ) + { + setLockedState( iUsed, false ); + if( pSocket ) + pSocket.SysMessage( "You unlock the crafted wall. It can now be moved and will decay normally." ); + } + else + { + setLockedState( iUsed, true ); + if( pSocket ) + pSocket.SysMessage( "You lock the crafted wall in place. It will no longer decay." ); + } + } return false; } @@ -65,20 +71,24 @@ function onUseChecked( pUser, iUsed ) /** @type { ( myObj: BaseObject, pSocket: Socket ) => string } */ function onTooltip( myObj, pSocket ) { - var locked = myObj.GetTag( "CraftWallLocked" ); - - if( locked == 1 ) - { - // Line 1: House Only - // Line 2: unlock hint - return "House Only
You must double click this to unlock it."; - } - else - { - // Line 1: House Only - // Line 2: lock hint - return "House Only
You must double click this to lock it down."; - } + if( myObj.GetTag( "CraftableDoor") == null ) + { + var locked = myObj.GetTag( "CraftWallLocked" ); + + if( locked == 1 ) + { + // Line 1: House Only + // Line 2: unlock hint + return "House Only
You must double click this to unlock it."; + } + else + { + // Line 1: House Only + // Line 2: lock hint + return "House Only
You must double click this to lock it down."; + } + } + return "House Only"; } function onDropItemOnNpc( pDropper, pDroppedOn, iDropped ) diff --git a/data/js/server/house/houseCommands.js b/data/js/server/house/houseCommands.js index 4d51c1052..bfb905cef 100644 --- a/data/js/server/house/houseCommands.js +++ b/data/js/server/house/houseCommands.js @@ -1129,7 +1129,7 @@ function onCallback8( pSocket, myTarget ) { pSocket.SysMessage( GetDictionaryEntry( 1888, pSocket.language )); // You cannot lock down trash barrels. } - else if( myTarget.movable == 3 || myTarget.GetTag( "BuildingCraftable" ) == 1 ) + else if( myTarget.movable == 3 || (myTarget.GetTag( "BuildingCraftable" ) == 1 && myTarget.GetTag( "CraftableDoor" ) == null )) { pSocket.SysMessage( GetDictionaryEntry( 1889, pSocket.language )); // That is already locked down! } From 852c213d39748399e8c2b5d0e6f860fe146c93eb Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 20:37:37 -0600 Subject: [PATCH 11/43] update --- data/js/item/buildingcraftables.js | 182 +++++++++++------------ data/js/item/buildingcraftables_doors.js | 91 ++++++++++++ data/js/jse_fileassociations.scp | 1 + data/js/server/house/houseCommands.js | 8 +- 4 files changed, 183 insertions(+), 99 deletions(-) create mode 100644 data/js/item/buildingcraftables_doors.js diff --git a/data/js/item/buildingcraftables.js b/data/js/item/buildingcraftables.js index b053e19df..53e2cd690 100644 --- a/data/js/item/buildingcraftables.js +++ b/data/js/item/buildingcraftables.js @@ -3,92 +3,82 @@ /** @type { ( thingCreated: BaseObject, thingType: 0 | 1 ) => void } */ function onCreateDFN( iCreated, dfnSection ) { - if( iCreated.GetTag( "CraftableDoor") == null ) - { - setLockedState( iCreated, false ); - } + setLockedState( iCreated, false ); iCreated.SetTag( "BuildingCraftable", 1 ); } /** @type { ( user: Character, iUsing: Item ) => boolean } */ function onUseChecked( pUser, iUsed ) { - var pSocket = pUser.socket; - - if( iUsed.container !== null ) - { - if( iUsed.container === pUser.pack ) - { - if (pSocket) - pSocket.SysMessage( "Place the wall in your house, then double-click it to lock it down." ); - } - else - { - if( pSocket ) - pSocket.SysMessage( "You must first place this wall in the world." ); - } - return false; - } - - if( !isInOwnHouse( pUser )) - { - if( pSocket ) - { - pSocket.SysMessage( GetDictionaryEntry( 2067, pSocket.language )); // You must be in your house to do this. - } - return false; - } - - var iMulti = iUsed.multi; - if( !ValidateObject( iMulti ) || iMulti !== pUser.multi ) - { - if( pSocket ) - pSocket.SysMessage( "This crafted wall must be inside your house to lock it down." ); - return false; - } - - if( iUsed.GetTag( "CraftableDoor") == null ) - { - var locked = iUsed.GetTag( "CraftWallLocked" ); + var pSocket = pUser.socket; - if( locked == 1 ) + if( iUsed.container !== null ) + { + if( iUsed.container === pUser.pack ) { - setLockedState( iUsed, false ); - if( pSocket ) - pSocket.SysMessage( "You unlock the crafted wall. It can now be moved and will decay normally." ); + if (pSocket) + pSocket.SysMessage( "Place the wall in your house, then double-click it to lock it down." ); } else { - setLockedState( iUsed, true ); - if( pSocket ) - pSocket.SysMessage( "You lock the crafted wall in place. It will no longer decay." ); + if( pSocket ) + pSocket.SysMessage( "You must first place this wall in the world." ); + } + return false; + } + + if( !isInOwnHouse( pUser )) + { + if( pSocket ) + { + pSocket.SysMessage( GetDictionaryEntry( 2067, pSocket.language )); // You must be in your house to do this. } + return false; + } + + var iMulti = iUsed.multi; + if( !ValidateObject( iMulti ) || iMulti !== pUser.multi ) + { + if( pSocket ) + pSocket.SysMessage( "This crafted wall must be inside your house to lock it down." ); + return false; + } + + var locked = iUsed.GetTag("CraftWallLocked"); + + if( locked == 1 ) + { + setLockedState( iUsed, false ); + if( pSocket ) + pSocket.SysMessage("You unlock the crafted wall. It can now be moved and will decay normally."); + } + else + { + setLockedState( iUsed, true ); + if( pSocket ) + pSocket.SysMessage("You lock the crafted wall in place. It will no longer decay."); } - return false; + return false; } /** @type { ( myObj: BaseObject, pSocket: Socket ) => string } */ function onTooltip( myObj, pSocket ) { - if( myObj.GetTag( "CraftableDoor") == null ) - { - var locked = myObj.GetTag( "CraftWallLocked" ); + var locked = myObj.GetTag( "CraftWallLocked" ); - if( locked == 1 ) - { - // Line 1: House Only - // Line 2: unlock hint - return "House Only
You must double click this to unlock it."; - } - else - { - // Line 1: House Only - // Line 2: lock hint - return "House Only
You must double click this to lock it down."; - } + if( locked == 1 ) + { + // Line 1: House Only + // Line 2: unlock hint + return "House Only
You must double click this to unlock it."; + } + else + { + // Line 1: House Only + // Line 2: lock hint + return "House Only
You must double click this to lock it down."; } - return "House Only"; } function onDropItemOnNpc( pDropper, pDroppedOn, iDropped ) @@ -149,43 +139,43 @@ function onDrop( iDropped, pDropper ) function isInOwnHouse( pUser ) { - if( !ValidateObject( pUser )) - return false; + if( !ValidateObject( pUser )) + return false; - var iMulti = pUser.multi; - if( !ValidateObject( iMulti )) - return false; + var iMulti = pUser.multi; + if( !ValidateObject( iMulti )) + return false; - // Owner / co-owner / whatever IsOnOwnerList covers - if( iMulti.IsOnOwnerList( pUser )) - return true; + // Owner / co-owner / whatever IsOnOwnerList covers + if( iMulti.IsOnOwnerList( pUser )) + return true; - // Optional: co-owned houses on same account - if( GetServerSetting( "COOWNHOUSESONSAMEACCOUNT" )) - { - if( ValidateObject( iMulti.owner ) && iMulti.owner.accountNum === pUser.accountNum ) - return true; - } + // Optional: co-owned houses on same account + if( GetServerSetting( "COOWNHOUSESONSAMEACCOUNT" )) + { + if( ValidateObject( iMulti.owner ) && iMulti.owner.accountNum === pUser.accountNum ) + return true; + } - return false; + return false; } function setLockedState( item, locked ) { - if( !ValidateObject( item )) - return; - - if( locked ) - { - item.SetTag( "CraftWallLocked", 1 ); - item.movable = 2; // locked down / secure - item.decayable = false; // no decay - } - else - { - item.SetTag( "CraftWallLocked", 0 ); - item.movable = 1; // movable - item.decayable = true; // normal decay - } - item.Refresh(); + if( !ValidateObject( item )) + return; + + if( locked ) + { + item.SetTag( "CraftWallLocked", 1 ); + item.movable = 2; // locked down / secure + item.decayable = false; // no decay + } + else + { + item.SetTag( "CraftWallLocked", 0 ); + item.movable = 1; // movable + item.decayable = true; // normal decay + } + item.Refresh(); } \ No newline at end of file diff --git a/data/js/item/buildingcraftables_doors.js b/data/js/item/buildingcraftables_doors.js new file mode 100644 index 000000000..c55a77da4 --- /dev/null +++ b/data/js/item/buildingcraftables_doors.js @@ -0,0 +1,91 @@ +/// +// @ts-check +/** @type { ( thingCreated: BaseObject, thingType: 0 | 1 ) => void } */ +function onCreateDFN( iCreated, dfnSection ) +{ + iCreated.SetTag( "BuildingCraftableDoor", 1 ); +} + +/** @type { ( myObj: BaseObject, pSocket: Socket ) => string } */ +function onTooltip( myObj, pSocket ) +{ + return "House Only"; +} + +function onDropItemOnNpc( pDropper, pDroppedOn, iDropped ) +{ + var targPack = pDroppedOn.pack; + if( ValidateObject( targPack ) && pDroppedOn.sectionID == "packhorse" ) + { + return 0; + } + + return 1; +} + +function onDropItemOnItem( iDropped, cDropper, iDroppedOn ) +{ + if( !ValidateObject( iDropped ) || !ValidateObject( cDropper ) || !ValidateObject( iDroppedOn )) + return 0; + + var isBuilding = iDropped.GetTag( "BuildingCraftableDoor" ) === 1; + if( !isBuilding ) + return 0 + + var owner = iDroppedOn.container; + if( ValidateObject( owner ) && owner.isChar && owner.sectionID == "packhorse" ) + { + var sock = cDropper.socket; + if( sock ) + sock.SysMessage( "You cannot place building pieces on a pack animal." ); + + return 0; + } + + return 1; +} + +function onDrop( iDropped, pDropper ) +{ + if( !ValidateObject( iDropped ) || !ValidateObject( pDropper )) + return 0; + + var isBuilding = iDropped.GetTag( "BuildingCraftableDoor" ) === 1; + if( !isBuilding ) + return 0; + + var socket = pDropper.socket; + if( !isInOwnHouse( pDropper )) + { + if( socket != null) + socket.SysMessage( "The building piece crumbles when dropped on the ground." ); + + iDropped.Delete(); + return 2; + } + + return 1; +} + +function isInOwnHouse( pUser ) +{ + if( !ValidateObject( pUser )) + return false; + + var iMulti = pUser.multi; + if( !ValidateObject( iMulti )) + return false; + + // Owner / co-owner / whatever IsOnOwnerList covers + if( iMulti.IsOnOwnerList( pUser )) + return true; + + // Optional: co-owned houses on same account + if( GetServerSetting( "COOWNHOUSESONSAMEACCOUNT" )) + { + if( ValidateObject( iMulti.owner ) && iMulti.owner.accountNum === pUser.accountNum ) + return true; + } + + return false; +} \ No newline at end of file diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 46405c3a4..2221a52bd 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -320,6 +320,7 @@ 5062=item/shrines.js 5063=item/recipescroll.js 5080=item/buildingcraftables.js +5081=item/buildingcraftables_doors.js 19100=item/plant_growing/plantsystem.js 19101=item/plant_growing/plantbowl.js diff --git a/data/js/server/house/houseCommands.js b/data/js/server/house/houseCommands.js index bfb905cef..02a01a107 100644 --- a/data/js/server/house/houseCommands.js +++ b/data/js/server/house/houseCommands.js @@ -1125,15 +1125,17 @@ function onCallback8( pSocket, myTarget ) var StrangeByte = pSocket.GetWord( 1 ); if( StrangeByte === 0 && ValidateObject( myTarget ) && myTarget.isItem ) { + var isDoor = ( myTarget.GetTag( "BuildingCraftableDoor" ) === 1 ); + if( myTarget.type == 87 ) { pSocket.SysMessage( GetDictionaryEntry( 1888, pSocket.language )); // You cannot lock down trash barrels. } - else if( myTarget.movable == 3 || (myTarget.GetTag( "BuildingCraftable" ) == 1 && myTarget.GetTag( "CraftableDoor" ) == null )) + else if( !isDoor && ( myTarget.movable == 3 || myTarget.GetTag( "BuildingCraftable" ) == 1 )) { pSocket.SysMessage( GetDictionaryEntry( 1889, pSocket.language )); // That is already locked down! } - else if( myTarget.type == 12 || myTarget.type == 13 || myTarget.type == 203 || myTarget.id == 0x0BD2 || + else if( !isDoor && myTarget.type == 12 || myTarget.type == 13 || myTarget.type == 203 || myTarget.id == 0x0BD2 || myTarget.movable == 2 || myTarget.movable == 3 || myTarget.id == 0x3996 || myTarget.id == 0x398C || myTarget.id == 0x3915 || myTarget.id == 0x3920 || myTarget.id == 0x3979 || myTarget.id == 0x3967 || myTarget.id == 0x3956 || myTarget.id == 0x3946 ) @@ -1173,7 +1175,7 @@ function onCallback8( pSocket, myTarget ) // Check if item blocks movement and is too close to a door // 6 = TF_BLOCKING - if( CheckTileFlag( myTarget.id, 6 )) + if( !isDoor && CheckTileFlag( myTarget.id, 6 )) { // Check for nearby doors var foundDoor = AreaItemFunction( "CheckForNearbyDoors", myTarget, 3, pSocket ); From 0e1e31e09ef98d11ac0cec65e6aef405781e4d84 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 21 Nov 2025 20:37:59 -0600 Subject: [PATCH 12/43] Update craftablewalls.dfn --- .../items/building/walls/craftablewalls.dfn | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/data/dfndata/items/building/walls/craftablewalls.dfn b/data/dfndata/items/building/walls/craftablewalls.dfn index 2b705d919..948988ad2 100644 --- a/data/dfndata/items/building/walls/craftablewalls.dfn +++ b/data/dfndata/items/building/walls/craftablewalls.dfn @@ -307,30 +307,36 @@ get=base_craftable_wall id=0x079c } +[base_craftable_door] +{ +get=base_door +script=5081 +weight=1000 +movable=1 +decay=1 +type=12 +} + [StoneDoor_S_In] { -get=base_craftable_wall +get=base_craftable_door id=0x0326 -custominttag=CraftableDoor 1 } [StoneDoor_E_Out] { -get=base_craftable_wall +get=base_craftable_door id=0x032C -custominttag=CraftableDoor 1 } [StoneDoor_S_Out] { -get=base_craftable_wall +get=base_craftable_door id=0x032a -custominttag=CraftableDoor 1 } [StoneDoor_E_In] { -get=base_craftable_wall +get=base_craftable_door id=0x0330 -custominttag=CraftableDoor 1 } \ No newline at end of file From a0544a2eed075cd3d4b86f40a95fe12d2b2de1f0 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:20:31 -0600 Subject: [PATCH 13/43] small update --- data/dfndata/create/masonry.dfn | 8 +- data/js/skill/craft/itemdetailgump.js | 217 ++++++++++++++++++++++++-- 2 files changed, 210 insertions(+), 15 deletions(-) diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index 299084556..e7ba74343 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -584,7 +584,7 @@ SOUND=0x23D [ITEM 3546] { -NAME=StoneDoor_S_In +NAME=Stone Door S In ID=0x0326 RESOURCE=STONE 10 SKILL=11 600 1100 @@ -596,7 +596,7 @@ SOUND=0x23D [ITEM 3547] { -NAME=StoneDoor_E_Out +NAME=Stone Door E Out ID=0x032C RESOURCE=STONE 10 SKILL=11 600 1100 @@ -608,7 +608,7 @@ SOUND=0x23D [ITEM 3548] { -NAME=StoneDoor_S_Out +NAME=Stone Door S Out ID=0x032a RESOURCE=STONE 10 SKILL=11 600 1100 @@ -620,7 +620,7 @@ SOUND=0x23D [ITEM 3549] { -NAME=StoneDoor_E_In +NAME=Stone Door E In ID=0x0330 RESOURCE=STONE 10 SKILL=11 600 1100 diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 186be0522..c911871cc 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -1812,61 +1812,256 @@ function ItemDetailGump( pUser ) HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3509:// + case 3509:// stone chair createEntry = CreateEntries[3509]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3510:// + case 3510:// stone table (east) createEntry = CreateEntries[3510]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3511:// + case 3511:// stone table (south) createEntry = CreateEntries[3511]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3512:// + case 3512:// large stone table (east) createEntry = CreateEntries[3512]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3513:// + case 3513:// large stone table (south) createEntry = CreateEntries[3513]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3514:// + case 3514:// ritual table createEntry = CreateEntries[3514]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3515:// + case 3515:// small statue (south) createEntry = CreateEntries[3515]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3516:// + case 3516:// small statue (north) createEntry = CreateEntries[3516]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3517:// + case 3517:// small statue (east) createEntry = CreateEntries[3517]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3518:// + case 3518:// pegasus statuette createEntry = CreateEntries[3518]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; - case 3519:// + case 3519:// gargoyle statue createEntry = CreateEntries[3519]; HARVEST = [14011]; mainSkill = parseInt( pUser.skills.carpentry ); break; + case 3520:// gryphon statue + createEntry = CreateEntries[3520]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3521:// stone anvil (east) + createEntry = CreateEntries[3521]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3522:// stone anvil (south) + createEntry = CreateEntries[3522]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3523:// large gargish bed (east) + createEntry = CreateEntries[3523]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3524:// large gargish bed (south) + createEntry = CreateEntries[3524]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3525:// gargish cot (east) + createEntry = CreateEntries[3525]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3526:// gargish cot (south) + createEntry = CreateEntries[3526]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3527:// gargish stone arms + createEntry = CreateEntries[3527]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3528:// gargish stone chest + createEntry = CreateEntries[3528]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3529:// gargish stone leggings + createEntry = CreateEntries[3529]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3530:// gargish stone kilt + createEntry = CreateEntries[3530]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3531:// gargish stone arms + createEntry = CreateEntries[3531]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3532:// gargish stone chest + createEntry = CreateEntries[3532]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3533:// gargish stone leggings + createEntry = CreateEntries[3533]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3534:// gargish stone kilt + createEntry = CreateEntries[3534]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3535:// large stone shield + createEntry = CreateEntries[3535]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3536:// gargish stone amulet + createEntry = CreateEntries[3536]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3537:// stone war sword + createEntry = CreateEntries[3537]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3538:// rough windowless + createEntry = CreateEntries[3538]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3539:// rough window + createEntry = CreateEntries[3539]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3540:// rough arch + createEntry = CreateEntries[3540]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3541:// rough pillar + createEntry = CreateEntries[3541]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3542:// rough rounded arch + createEntry = CreateEntries[3542]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3543:// rough small arch + createEntry = CreateEntries[3543]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3544:// rough angled pillar + createEntry = CreateEntries[3544]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3545:// short rough + createEntry = CreateEntries[3545]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3546:// Stone Door S In + createEntry = CreateEntries[3546]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3547:// Stone Door E Out + createEntry = CreateEntries[3547]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3548:// Stone Door S Out + createEntry = CreateEntries[3548]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3549:// Stone Door E In + createEntry = CreateEntries[3549]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3550:// short rough + createEntry = CreateEntries[3550]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3551:// rough steps + createEntry = CreateEntries[3551]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3552:// rough corner steps + createEntry = CreateEntries[3552]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3553:// rough rounded corner step + createEntry = CreateEntries[3553]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3554:// rough inset steps + createEntry = CreateEntries[3554]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3555:// rough rounded inset steps + createEntry = CreateEntries[3555]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3556:// light paver + createEntry = CreateEntries[3556]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3557:// medium paver + createEntry = CreateEntries[3557]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; + case 3558:// dark paver + createEntry = CreateEntries[3558]; + HARVEST = [14011]; + mainSkill = parseInt( pUser.skills.carpentry ); + break; default: break; } From 43cf446a320ee6205ed215c287ed48db511a87f5 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:37:21 -0600 Subject: [PATCH 14/43] update --- data/js/skill/craft/itemdetailgump.js | 106 +++++++++++++++++++++++++- data/js/skill/craft/masonry.js | 28 ++++++- 2 files changed, 129 insertions(+), 5 deletions(-) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index c911871cc..c77c70bfd 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -17,12 +17,114 @@ const exceptionalWearablesOnly = true; function ItemDetailGump( pUser ) { + var skillNames = [ + "alchemy", + "anatomy", + "animallore", + "itemid", + "armslore", + "parrying", + "begging", + "blacksmithing", + "bowcraft", + "peacemaking", + "camping", + "carpentry", + "cartography", + "cooking", + "detectinghidden", + "enticement", + "evaluatingintel", + "healing", + "fishing", + "forensics", + "herding", + "hiding", + "provocation", + "inscription", + "lockpicking", + "magery", + "magicresistance", + "tactics", + "snooping", + "musicianship", + "poisoning", + "archery", + "spiritspeak", + "stealing", + "tailoring", + "taming", + "tasteid", + "tinkering", + "tracking", + "veterinary", + "swordsmanship", + "macefighting", + "fencing", + "wrestling", + "lumberjacking", + "mining", + "meditation", + "stealth", + "removetrap", + "necromancy", + "focus", + "chivalry", + "bushido", + "ninjitsu", + "spellweaving ", + "mysticism ", + "imbuing", + "throwing " + ]; var socket = pUser.socket; var itemGump = new Gump; var createEntry = null; var HARVEST; var mainSkill; - switch( pUser.GetTempTag( "ITEMDETAILS" )) + + // --- Override from temp tags if present (minimal change) --- + var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); + var skillTag = pUser.GetTempTag( "Skill" ); + var harvest1Tag = pUser.GetTempTag( "Harvest" ); + var harvest2Tag = pUser.GetTempTag( "Harvest2" ); + var harvest3Tag = pUser.GetTempTag( "Harvest3" ); + var harvest4Tag = pUser.GetTempTag( "Harvest4" ); + + // If detail is provided, re-point createEntry + if( detailTag !== null ) + { + createEntry = CreateEntries[ detailTag ]; + } + + if( skillTag >= 0 && skillTag < skillNames.length ) + { + mainSkill = parseInt( pUser.skills[ skillNames[skillTag] ] ); + } + else + {// if all fails fallback to alchemy + mainSkill = mainSkill = parseInt( pUser.skills.alchemy ); + } + + // If harvest info is provided, rebuild HARVEST array + if( harvest1Tag !== null || harvest2Tag !== null || harvest3Tag !== null || harvest4Tag !== null ) + { + HARVEST = []; + + if( harvest1Tag !== null ) + HARVEST.push( parseInt( harvest1Tag, 10 )); + + if( harvest2Tag !== null ) + HARVEST.push( parseInt( harvest2Tag, 10 )); + + if( harvest3Tag !== null ) + HARVEST.push( parseInt( harvest3Tag, 10 )); + + if( harvest4Tag !== null ) + HARVEST.push( parseInt( harvest4Tag, 10 )); + } + + /*switch( pUser.GetTempTag( "ITEMDETAILS" )) { //Start Blacksmith case 1: @@ -2064,7 +2166,7 @@ function ItemDetailGump( pUser ) break; default: break; - } + }*/ if( createEntry == null ) { diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 46edacb8c..6c866ac77 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -399,10 +399,15 @@ const MasonryMap = {}; dictID: dictID, page: pageIdx + 1, timerID: pageIdx + 1, - graniteMake: [] + graniteMake: [], // recipeID: undefined, // minEra: undefined, // maxEra: undefined + skill: 11, // carpentry / masonry skill ID + harvest: [14011], // granite dict + harvest2: [], // optional second resource + harvest3: [], // optional second resource + harvest4: [] // optional second resource }; } @@ -439,9 +444,13 @@ MasonryMap[400].recipeID = 3520; MasonryMap[401].minEra = "ml"; // stone anvil (south) MasonryMap[401].recipeID = 3521; MasonryMap[402].minEra = "sa"; // large gargish bed (east) +MasonryMap[402].harvest2 = [10016]; // Cloth MasonryMap[403].minEra = "sa"; // large gargish bed (south) +MasonryMap[403].harvest2 = [10016]; // Cloth MasonryMap[404].minEra = "sa"; // gargish cot (east) +MasonryMap[404].harvest2 = [10016]; // Cloth MasonryMap[405].minEra = "sa"; // gargish cot (south) +MasonryMap[405].harvest2 = [10016]; // Cloth //Page 5 starts at 500 MasonryMap[500].minEra = "sa"; // gargish stone arms MasonryMap[501].minEra = "sa"; // gargish stone chest @@ -1072,8 +1081,6 @@ function onGumpPress( pSock, pButton, gumpData ) var pUser = pSock.currentChar; var usedMakeLast = false; - pSock.SysMessage( "DEBUG: button " + pButton ); - if( !ValidateObject( pUser ) || pUser.dead ) return; @@ -1201,6 +1208,21 @@ function onGumpPress( pSock, pButton, gumpData ) var graniteMakeID = entry.graniteMake[0]; if( graniteMakeID > 0 ) { + // Masonry uses Carpentry skill + pUser.SetTempTag("Skill", entry.skill | 0); + + if( entry.harvest && entry.harvest.length > 0 ) + pUser.SetTempTag("Harvest", entry.harvest[0]); + + if( entry.harvest2 && entry.harvest2.length > 0 ) + pUser.SetTempTag("Harvest2", entry.harvest2[0]); + + if( entry.harvest3 && entry.harvest3.length > 0 ) + pUser.SetTempTag("Harvest3", entry.harvest3[0]); + + if( entry.harvest4 && entry.harvest4.length > 0 ) + pUser.SetTempTag("Harvest4", entry.harvest4[0]); + pUser.SetTempTag( "ITEMDETAILS", graniteMakeID ); TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); } From 3097ca482e05b35626471cfedf815059c35bb1d5 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:39:24 -0600 Subject: [PATCH 15/43] Update masonry.js --- data/js/skill/craft/masonry.js | 1156 ++++++++++++++++---------------- 1 file changed, 578 insertions(+), 578 deletions(-) diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 6c866ac77..7833de9f4 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -371,50 +371,50 @@ const MasonryMap = {}; (function initMasonryMap() { - // graniteIndex: 0 = iron, 1 = dull copper, ... 8 = valorite - for( var graniteIndex = 0; graniteIndex < craftItems.length; graniteIndex++ ) - { - var graniteRows = craftItems[graniteIndex]; - - // pageIdx: 0..6 => pages 1..9 - for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) - { - var dictList = myPage[pageIdx]; - var makeList = graniteRows[pageIdx]; - - for( var i = 0; i < dictList.length && i < makeList.length; i++ ) - { - // Old script uses: - // page 1 => 100..112 - // page 2 => 200..204 - // page 3 => 300..305 - // etc. - var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; - var dictID = dictList[i]; - var makeID = makeList[i]; - - if( !MasonryMap[buttonID] ) - { - MasonryMap[buttonID] = { - dictID: dictID, - page: pageIdx + 1, - timerID: pageIdx + 1, - graniteMake: [], - // recipeID: undefined, - // minEra: undefined, - // maxEra: undefined + // graniteIndex: 0 = iron, 1 = dull copper, ... 8 = valorite + for( var graniteIndex = 0; graniteIndex < craftItems.length; graniteIndex++ ) + { + var graniteRows = craftItems[graniteIndex]; + + // pageIdx: 0..6 => pages 1..9 + for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) + { + var dictList = myPage[pageIdx]; + var makeList = graniteRows[pageIdx]; + + for( var i = 0; i < dictList.length && i < makeList.length; i++ ) + { + // Old script uses: + // page 1 => 100..112 + // page 2 => 200..204 + // page 3 => 300..305 + // etc. + var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; + var dictID = dictList[i]; + var makeID = makeList[i]; + + if( !MasonryMap[buttonID] ) + { + MasonryMap[buttonID] = { + dictID: dictID, + page: pageIdx + 1, + timerID: pageIdx + 1, + graniteMake: [], + // recipeID: undefined, + // minEra: undefined, + // maxEra: undefined skill: 11, // carpentry / masonry skill ID harvest: [14011], // granite dict harvest2: [], // optional second resource harvest3: [], // optional second resource harvest4: [] // optional second resource - }; - } + }; + } - MasonryMap[buttonID].graniteMake[graniteIndex] = makeID; - } - } - } + MasonryMap[buttonID].graniteMake[graniteIndex] = makeID; + } + } + } })(); // 3) AFTER initMasonryMap, you can override entries: @@ -491,142 +491,142 @@ MasonryMap[902].minEra = "tol"; // dark paver function PageX( socket, pUser, pageNum ) { - if( !ValidateObject( pUser )) - return; - - // Pages 1 - 9: normal crafting pages - // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) - - var subPage = pUser.GetTempTag( "subPage" ); - var pageItems = []; - - if( pageNum == 999 ) - { - var lastTenRaw = pUser.GetTempTag( "LastTenMasonry" ) || ""; - var split = lastTenRaw.split( "," ); - for( var i = 0; i < split.length; i++ ) - { - var val = parseInt( split[i] ); - if( !isNaN( val ) && MasonryMap[val] ) - pageItems.push( val ); // here val is the buttonID itself - } - } - else - { - // Build list of buttonIDs for this page from MasonryMap - for( var buttonID in MasonryMap ) - { - var data = MasonryMap[buttonID]; - if( data.page == pageNum && eraOK( data )) - { - // If we later add recipes and want to hide unknown ones: - var needsRecipe = data.recipeID; - var showAll = displayUnlearnedRecipes; - if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) - { - pageItems.push( parseInt( buttonID ) ); - } - } - } - - // Sort by buttonID to keep consistent ordering - pageItems.sort( function( a, b ){ return a - b; } ); - } - - if( pageItems.length == 0 ) - { - var emptyGump = new Gump; - TriggerEvent( craftGumpID, "CraftingGumpMenu", emptyGump, socket ); - emptyGump.AddPage( 1 ); - emptyGump.AddText( 220, 60, textHue, "No items available on this page." ); - emptyGump.Send( socket ); - emptyGump.Free(); - return; - } - - var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); - - if( subPage < 1 ) - subPage = 1; - if( subPage > totalSubPages ) - subPage = totalSubPages; - - pUser.SetTempTag( "page", pageNum ); - pUser.SetTempTag( "subPage", subPage ); - - var startIndex = ( subPage - 1 ) * itemsPerPage; - var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); - - if( startIndex >= pageItems.length ) - { - subPage = 1; - startIndex = 0; - endIndex = Math.min( itemsPerPage, pageItems.length ); - pUser.SetTempTag( "subPage", subPage ); - } - - var resourceHue = pUser.GetTempTag( "resourceHue" ); - var blacksmithMenu = new Gump; - TriggerEvent( craftGumpID, "CraftingGumpMenu", blacksmithMenu, socket ); - blacksmithMenu.AddPage( 1 ); - - var drawIndex = 0; - - for( var i = startIndex; i < endIndex; i++ ) - { - var buttonID = pageItems[i]; - var data = MasonryMap[buttonID]; - - // Do not show weapons when colored granited ingots selected and colored granited weapons are disabled - if( !allowColouredWeapons && resourceHue > 0 && data.page == 6 ) - continue; + if( !ValidateObject( pUser )) + return; + + // Pages 1 - 9: normal crafting pages + // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) + + var subPage = pUser.GetTempTag( "subPage" ); + var pageItems = []; + + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenMasonry" ) || ""; + var split = lastTenRaw.split( "," ); + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val ) && MasonryMap[val] ) + pageItems.push( val ); // here val is the buttonID itself + } + } + else + { + // Build list of buttonIDs for this page from MasonryMap + for( var buttonID in MasonryMap ) + { + var data = MasonryMap[buttonID]; + if( data.page == pageNum && eraOK( data )) + { + // If we later add recipes and want to hide unknown ones: + var needsRecipe = data.recipeID; + var showAll = displayUnlearnedRecipes; + if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) + { + pageItems.push( parseInt( buttonID ) ); + } + } + } + + // Sort by buttonID to keep consistent ordering + pageItems.sort( function( a, b ){ return a - b; } ); + } + + if( pageItems.length == 0 ) + { + var emptyGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", emptyGump, socket ); + emptyGump.AddPage( 1 ); + emptyGump.AddText( 220, 60, textHue, "No items available on this page." ); + emptyGump.Send( socket ); + emptyGump.Free(); + return; + } + + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var resourceHue = pUser.GetTempTag( "resourceHue" ); + var blacksmithMenu = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", blacksmithMenu, socket ); + blacksmithMenu.AddPage( 1 ); + + var drawIndex = 0; + + for( var i = startIndex; i < endIndex; i++ ) + { + var buttonID = pageItems[i]; + var data = MasonryMap[buttonID]; + + // Do not show weapons when colored granited ingots selected and colored granited weapons are disabled + if( !allowColouredWeapons && resourceHue > 0 && data.page == 6 ) + continue; // Do not show walls when colored granited ingots selected and colored granited walls are disabled - if( !allowColouredBuildings && resourceHue > 0 && data.page > 6 ) - continue; - - var entryText = ""; - if( data.customName ) - { - entryText = data.customName; - } - else if( data.dictID ) - { - entryText = GetDictionaryEntry( data.dictID, socket.language ); - if( !entryText || entryText === "" ) - entryText = "[Missing EntryID: " + data.dictID + "]"; - } - else - { - entryText = "[Unnamed Item: " + buttonID + "]"; - } - - // Same layout as tailoring: button, text, details button - blacksmithMenu.AddButton( 220, 60 + ( drawIndex * 20 ), 4005, 4007, 1, 0, buttonID ); - blacksmithMenu.AddText( 255, 60 + ( drawIndex * 20 ), textHue, entryText ); - blacksmithMenu.AddButton( 480, 60 + ( drawIndex * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); - - drawIndex++; - } - - // Prev subpage - if( subPage > 1 ) - { - blacksmithMenu.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); - blacksmithMenu.AddHTMLGump( 255, 263, 100, 18, 0, 0, - "" + GetDictionaryEntry( 10101, socket.language ) + "" ); - } - - // Next subpage - if( subPage < totalSubPages ) - { - blacksmithMenu.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); - blacksmithMenu.AddHTMLGump( 405, 263, 100, 18, 0, 0, - "" + GetDictionaryEntry( 10100, socket.language ) + "" ); - } - - blacksmithMenu.Send( socket ); - blacksmithMenu.Free(); + if( !allowColouredBuildings && resourceHue > 0 && data.page > 6 ) + continue; + + var entryText = ""; + if( data.customName ) + { + entryText = data.customName; + } + else if( data.dictID ) + { + entryText = GetDictionaryEntry( data.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + buttonID + "]"; + } + + // Same layout as tailoring: button, text, details button + blacksmithMenu.AddButton( 220, 60 + ( drawIndex * 20 ), 4005, 4007, 1, 0, buttonID ); + blacksmithMenu.AddText( 255, 60 + ( drawIndex * 20 ), textHue, entryText ); + blacksmithMenu.AddButton( 480, 60 + ( drawIndex * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); + + drawIndex++; + } + + // Prev subpage + if( subPage > 1 ) + { + blacksmithMenu.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + blacksmithMenu.AddHTMLGump( 255, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + + // Next subpage + if( subPage < totalSubPages ) + { + blacksmithMenu.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + blacksmithMenu.AddHTMLGump( 405, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + blacksmithMenu.Send( socket ); + blacksmithMenu.Free(); } function Page20( socket, pUser ) @@ -1055,159 +1055,159 @@ function onCallback2( pSock, ourObj ) /** @type { ( tObject: BaseObject, timerId: number ) => void } */ function onTimer( pUser, timerID ) { - if( !ValidateObject( pUser )) - return; - - var socket = pUser.socket; - - if( timerID >= 1 && timerID <= 9 ) - { - PageX( socket, pUser, timerID ); // Pages 1 - 9 - } - else if( timerID == 20 ) - { - Page20( socket, pUser ); // Ingot selection - } - else if( timerID == 999 ) - { - PageX( socket, pUser, 999 ); // Last Ten Blacksmith (if used) - } + if( !ValidateObject( pUser )) + return; + + var socket = pUser.socket; + + if( timerID >= 1 && timerID <= 9 ) + { + PageX( socket, pUser, timerID ); // Pages 1 - 9 + } + else if( timerID == 20 ) + { + Page20( socket, pUser ); // Ingot selection + } + else if( timerID == 999 ) + { + PageX( socket, pUser, 999 ); // Last Ten Blacksmith (if used) + } } /** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ function onGumpPress( pSock, pButton, gumpData ) { - var pUser = pSock.currentChar; - var usedMakeLast = false; - - if( !ValidateObject( pUser ) || pUser.dead ) - return; - - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) - { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. - return; - } - - if( bItem.movable == 3 ) - { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! - return; - } - - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) - { - if( iPackOwner.serial != pUser.serial ) - { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! - return; - } - } - else - { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack befgranite you can use it. - return; - } - - var gumpID = scriptID + 0xffff; - - // Close / Exit - if( pButton == 0 ) - { - pUser.SetTempTag( "prevActionResult", null ); - pUser.SetTempTag( "MAKELAST", null ); - pSock.CloseGump( gumpID, 0 ); - return; - } - - // Repair Item - if( pButton == 49 ) - { - RepairTarget( pSock ); - return; - } - - // Select Materials (ingots) - if( pButton == 50 ) - { - pSock.CloseGump( gumpID, 0 ); - Page20( pSock, pUser ); - return; - } - - // Smelt Item - if( pButton == 52 ) - { - SmeltTarget( pSock ); - return; - } - - // Page buttons (1..9) - if( pButton >= 1 && pButton <= 9 ) - { - pUser.SetTempTag( "page", pButton ); - pUser.SetTempTag( "subPage", 1 ); - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - return; - } - - // Last Ten page (if you wire it into the gump) - if( pButton == 11000 ) - { - pUser.SetTempTag( "page", 999 ); - pUser.SetTempTag( "subPage", 1 ); - PageX( pSock, pUser, 999 ); - return; - } - - // Subpage navigation (8000 = prev, 9000 = next) - if( pButton >= 8000 && pButton < 9000 ) - { - var prevSub = pButton - 8000; - var curPage = pUser.GetTempTag( "page" ); - pUser.SetTempTag( "subPage", prevSub ); - PageX( pSock, pUser, curPage ); - return; - } - - if( pButton >= 9000 && pButton < 10000 ) - { - var nextSub = pButton - 9000; - var curPage2 = pUser.GetTempTag( "page" ); - pUser.SetTempTag( "subPage", nextSub ); - PageX( pSock, pUser, curPage2 ); - return; - } - - // Handle "Make Last" - if(( pButton >= 100 && pButton <= 998 ) || pButton == 5000 ) - { - if( pButton == 5000 ) - { - pButton = pUser.GetTempTag( "MAKELAST" ); - usedMakeLast = true; - } - else - { - pUser.SetTempTag( "MAKELAST", pButton ); - } - } - - // Item detail buttons (2000 + buttonID) - if( pButton >= 2000 && pButton < 3000 ) - { - var detailButtonID = pButton - 2000; - var entry = MasonryMap[detailButtonID]; - if( entry ) - { - // For details we just pass the granite version (granite index 0) to 4026 - var graniteMakeID = entry.graniteMake[0]; - if( graniteMakeID > 0 ) - { + var pUser = pSock.currentChar; + var usedMakeLast = false; + + if( !ValidateObject( pUser ) || pUser.dead ) + return; + + var bItem = pSock.tempObj; + if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + { + pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + return; + } + + if( bItem.movable == 3 ) + { + pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + return; + } + + var iPackOwner = GetPackOwner( bItem, 0 ); + if( ValidateObject( iPackOwner )) + { + if( iPackOwner.serial != pUser.serial ) + { + pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + return; + } + } + else + { + pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack befgranite you can use it. + return; + } + + var gumpID = scriptID + 0xffff; + + // Close / Exit + if( pButton == 0 ) + { + pUser.SetTempTag( "prevActionResult", null ); + pUser.SetTempTag( "MAKELAST", null ); + pSock.CloseGump( gumpID, 0 ); + return; + } + + // Repair Item + if( pButton == 49 ) + { + RepairTarget( pSock ); + return; + } + + // Select Materials (ingots) + if( pButton == 50 ) + { + pSock.CloseGump( gumpID, 0 ); + Page20( pSock, pUser ); + return; + } + + // Smelt Item + if( pButton == 52 ) + { + SmeltTarget( pSock ); + return; + } + + // Page buttons (1..9) + if( pButton >= 1 && pButton <= 9 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + pSock.CloseGump( gumpID, 0 ); + PageX( pSock, pUser, pButton ); + return; + } + + // Last Ten page (if you wire it into the gump) + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, 999 ); + return; + } + + // Subpage navigation (8000 = prev, 9000 = next) + if( pButton >= 8000 && pButton < 9000 ) + { + var prevSub = pButton - 8000; + var curPage = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", prevSub ); + PageX( pSock, pUser, curPage ); + return; + } + + if( pButton >= 9000 && pButton < 10000 ) + { + var nextSub = pButton - 9000; + var curPage2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", nextSub ); + PageX( pSock, pUser, curPage2 ); + return; + } + + // Handle "Make Last" + if(( pButton >= 100 && pButton <= 998 ) || pButton == 5000 ) + { + if( pButton == 5000 ) + { + pButton = pUser.GetTempTag( "MAKELAST" ); + usedMakeLast = true; + } + else + { + pUser.SetTempTag( "MAKELAST", pButton ); + } + } + + // Item detail buttons (2000 + buttonID) + if( pButton >= 2000 && pButton < 3000 ) + { + var detailButtonID = pButton - 2000; + var entry = MasonryMap[detailButtonID]; + if( entry ) + { + // For details we just pass the granite version (granite index 0) to 4026 + var graniteMakeID = entry.graniteMake[0]; + if( graniteMakeID > 0 ) + { // Masonry uses Carpentry skill pUser.SetTempTag("Skill", entry.skill | 0); @@ -1223,275 +1223,275 @@ function onGumpPress( pSock, pButton, gumpData ) if( entry.harvest4 && entry.harvest4.length > 0 ) pUser.SetTempTag("Harvest4", entry.harvest4[0]); - pUser.SetTempTag( "ITEMDETAILS", graniteMakeID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); - } - } - return; - } - - // If this is a craft button in our map: - if( MasonryMap[pButton] != undefined ) - { - var entry2 = MasonryMap[pButton]; - var graniteID = pUser.GetTempTag( "Granite" ); - var resourceHue = pUser.GetTempTag( "resourceHue" ); - - // Ensure graniteID within range - if( graniteID < 0 || graniteID >= craftItems.length ) - graniteID = 0; - - // Era / recipe gating - if( !eraOK( entry2 )) - { - pSock.SysMessage( "That item is not available in this era." ); - return; - } - - if( entry2.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, entry2.recipeID )) - { - pSock.SysMessage( "You must learn that recipe from a scroll." ); - return; - } - - // No colored granited weapons if disabled and using non-iron ingots - if( !allowColouredWeapons && resourceHue > 0 && entry2.page > 3 ) - { - pSock.SysMessage( "You cannot use colored granited ingots for weapons on this shard." ); - return; - } - - var makeID = entry2.graniteMake[graniteID]; - if( !makeID || makeID == 0 ) - { - // Fallback to iron version if for some reason we did not get a specific granite entry - makeID = entry2.graniteMake[0]; - } - - if( !makeID || makeID == 0 ) - { - pSock.SysMessage( "That item is not properly configured." ); - return; - } - - // Runic hammer bonus logic (unchanged from your original) - pUser.AddScriptTrigger( 4033 ); - - MakeItem( pSock, pUser, makeID, resourceHue ); - - // Tool wear - var toolUseLimit = GetServerSetting( "ToolUseLimit" ); - var toolUseBreak = GetServerSetting( "ToolUseBreak" ); - - var runicHammer = pUser.FindItemLayer( 0x01 ); // Right Hand - if( ValidateObject( runicHammer ) && runicHammer.GetTag( "runicHammer" ) && runicHammer.usesLeft > 0 ) - { - pUser.SetTempTag( "usedRunicHammer", true ); - pUser.SetTempTag( "runicHammerType", runicHammer.color ); - - if( toolUseLimit && runicHammer != bItem ) - { - runicHammer.usesLeft -= 1; - if( runicHammer.usesLeft == 0 && toolUseBreak ) - { - runicHammer.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); - } - } - } - - if( toolUseLimit ) - { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && toolUseBreak ) - { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); - } - } - - // Track in last ten list for blacksmith - AddToLastTenmMasonry( pUser, pButton ); - - // Reopen page after delay - pUser.StartTimer( gumpDelay, entry2.timerID, true ); - return; - } - - // Granite selection buttons (Page20) - if( pButton >= 1000 && pButton <= 1008 ) - { - var index = pButton - 1000; // 0..8 - var newGraniteID = index; - var newResourceHue = 0; - - // Optional: use Mining skill gating like ingots - var miningSkill = pUser.skills.mining | 0; - - switch( index ) - { - case 0: // Iron - newResourceHue = 0; - break; - - case 1: // Dull Copper - if( miningSkill < 650 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x0973; - break; - - case 2: // Shadow Iron - if( miningSkill < 700 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x0966; - break; - - case 3: // Copper - if( miningSkill < 750 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x07dd; - break; - - case 4: // Bronze - if( miningSkill < 800 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x06d6; - break; - - case 5: // Gold - if( miningSkill < 850 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x08a5; - break; - - case 6: // Agapite - if( miningSkill < 900 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x0979; - break; - - case 7: // Verite - if( miningSkill < 950 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x089f; - break; - - case 8: // Valorite - if( miningSkill < 990 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - return; - } - newResourceHue = 0x08ab; - break; - } - - // Store selection - pUser.SetTempTag( "Granite", newGraniteID ); - pUser.SetTempTag( "resourceHue", newResourceHue ); - pUser.SetTempTag( "prevActionResult", null ); - pUser.SetTempTag( "MAKELAST", null ); - - // Close the material select gump - pSock.CloseGump( gumpID, 0 ); - - // Go back to the last craft page, or default to page 1 - var curPage = pUser.GetTempTag( "page" ); - if( !curPage || curPage == 20 ) - curPage = 1; - - pUser.SetTempTag( "page", curPage ); - pUser.SetTempTag( "subPage", 1 ); - PageX( pSock, pUser, curPage ); - return; - } + pUser.SetTempTag( "ITEMDETAILS", graniteMakeID ); + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + } + return; + } + + // If this is a craft button in our map: + if( MasonryMap[pButton] != undefined ) + { + var entry2 = MasonryMap[pButton]; + var graniteID = pUser.GetTempTag( "Granite" ); + var resourceHue = pUser.GetTempTag( "resourceHue" ); + + // Ensure graniteID within range + if( graniteID < 0 || graniteID >= craftItems.length ) + graniteID = 0; + + // Era / recipe gating + if( !eraOK( entry2 )) + { + pSock.SysMessage( "That item is not available in this era." ); + return; + } + + if( entry2.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, entry2.recipeID )) + { + pSock.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + // No colored granited weapons if disabled and using non-iron ingots + if( !allowColouredWeapons && resourceHue > 0 && entry2.page > 3 ) + { + pSock.SysMessage( "You cannot use colored granited ingots for weapons on this shard." ); + return; + } + + var makeID = entry2.graniteMake[graniteID]; + if( !makeID || makeID == 0 ) + { + // Fallback to iron version if for some reason we did not get a specific granite entry + makeID = entry2.graniteMake[0]; + } + + if( !makeID || makeID == 0 ) + { + pSock.SysMessage( "That item is not properly configured." ); + return; + } + + // Runic hammer bonus logic (unchanged from your original) + pUser.AddScriptTrigger( 4033 ); + + MakeItem( pSock, pUser, makeID, resourceHue ); + + // Tool wear + var toolUseLimit = GetServerSetting( "ToolUseLimit" ); + var toolUseBreak = GetServerSetting( "ToolUseBreak" ); + + var runicHammer = pUser.FindItemLayer( 0x01 ); // Right Hand + if( ValidateObject( runicHammer ) && runicHammer.GetTag( "runicHammer" ) && runicHammer.usesLeft > 0 ) + { + pUser.SetTempTag( "usedRunicHammer", true ); + pUser.SetTempTag( "runicHammerType", runicHammer.color ); + + if( toolUseLimit && runicHammer != bItem ) + { + runicHammer.usesLeft -= 1; + if( runicHammer.usesLeft == 0 && toolUseBreak ) + { + runicHammer.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); + } + } + } + + if( toolUseLimit ) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && toolUseBreak ) + { + bItem.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); + } + } + + // Track in last ten list for blacksmith + AddToLastTenmMasonry( pUser, pButton ); + + // Reopen page after delay + pUser.StartTimer( gumpDelay, entry2.timerID, true ); + return; + } + + // Granite selection buttons (Page20) + if( pButton >= 1000 && pButton <= 1008 ) + { + var index = pButton - 1000; // 0..8 + var newGraniteID = index; + var newResourceHue = 0; + + // Optional: use Mining skill gating like ingots + var miningSkill = pUser.skills.mining | 0; + + switch( index ) + { + case 0: // Iron + newResourceHue = 0; + break; + + case 1: // Dull Copper + if( miningSkill < 650 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0973; + break; + + case 2: // Shadow Iron + if( miningSkill < 700 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0966; + break; + + case 3: // Copper + if( miningSkill < 750 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x07dd; + break; + + case 4: // Bronze + if( miningSkill < 800 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x06d6; + break; + + case 5: // Gold + if( miningSkill < 850 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x08a5; + break; + + case 6: // Agapite + if( miningSkill < 900 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x0979; + break; + + case 7: // Verite + if( miningSkill < 950 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x089f; + break; + + case 8: // Valorite + if( miningSkill < 990 ) + { + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + return; + } + newResourceHue = 0x08ab; + break; + } + + // Store selection + pUser.SetTempTag( "Granite", newGraniteID ); + pUser.SetTempTag( "resourceHue", newResourceHue ); + pUser.SetTempTag( "prevActionResult", null ); + pUser.SetTempTag( "MAKELAST", null ); + + // Close the material select gump + pSock.CloseGump( gumpID, 0 ); + + // Go back to the last craft page, or default to page 1 + var curPage = pUser.GetTempTag( "page" ); + if( !curPage || curPage == 20 ) + curPage = 1; + + pUser.SetTempTag( "page", curPage ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, curPage ); + return; + } } function AddToLastTenmMasonry( pUser, buttonID ) { - var raw = pUser.GetTempTag( "LastTenMasonry" ) || ""; - var list = raw.split( "," ); - - // Remove if already in list - for( var i = 0; i < list.length; i++ ) - { - if( parseInt( list[i] ) == buttonID ) - { - list.splice( i, 1 ); - break; - } - } - - var newList = [buttonID]; - for( var j = 0; j < list.length && newList.length < 10; j++ ) - { - var entry = parseInt( list[j] ); - if( !isNaN( entry ) && entry > 0 ) - newList.push( entry ); - } - - pUser.SetTempTag( "LastTenMasonry", newList.join( "," ) ); + var raw = pUser.GetTempTag( "LastTenMasonry" ) || ""; + var list = raw.split( "," ); + + // Remove if already in list + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == buttonID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [buttonID]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenMasonry", newList.join( "," ) ); } function HasLearnedRecipe( pUser, recipeID ) { - var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); - if( !myData || myData.length == 0 ) - return false; - - for( var i = 0; i < myData.length; i++ ) - { - var data = myData[i].split( "," ); - if( data[0] == recipeID ) - return true; - } - return false; + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; } function eraOK( entry ) { - // Optional per-entry gates. Strings like "lbr","aos","ml","sa","hs","tol". - // If not present, the entry is valid for all eras. - if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) - return false; - if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) - return false; - return true; + // Optional per-entry gates. Strings like "lbr","aos","ml","sa","hs","tol". + // If not present, the entry is valid for all eras. + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; } \ No newline at end of file From f7efd23bceb0a176beeafbf1f1a1c43ccd58bb38 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:04:23 -0600 Subject: [PATCH 16/43] added books to addmenu --- data/dfndata/items/ItemMenu.bulk.dfn | 4 ++++ data/dfndata/items/skills/tools/carpenty.dfn | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/data/dfndata/items/ItemMenu.bulk.dfn b/data/dfndata/items/ItemMenu.bulk.dfn index 253202779..c792e3201 100644 --- a/data/dfndata/items/ItemMenu.bulk.dfn +++ b/data/dfndata/items/ItemMenu.bulk.dfn @@ -13540,6 +13540,10 @@ ADDITEM=0x10E5 ADDITEM=0x10E6 0x10E7=scorp ADDITEM=0x10E7 +0x12B3=mallet and chisel +ADDITEM=malletandchisel +0x0FBE=Making Valuables With Stonecrafting +ADDITEM=masonrybook <=Previous Menu ITEMMENU=127 } diff --git a/data/dfndata/items/skills/tools/carpenty.dfn b/data/dfndata/items/skills/tools/carpenty.dfn index fadaef46a..a12e9e45f 100644 --- a/data/dfndata/items/skills/tools/carpenty.dfn +++ b/data/dfndata/items/skills/tools/carpenty.dfn @@ -310,7 +310,7 @@ weight=100 value=9 4 restock=20 decay=1 -good=51 +good=53 maxuses=75 usesleft=25 script=2200// uses left tooltip @@ -327,6 +327,7 @@ movable=1 pileable=1 decay=1 value=10637 5318 +good=53 origin=lbr script=5055 } From 007f5f942548c18ce205b438ad09d468dd150ca9 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:29:17 -0600 Subject: [PATCH 17/43] update --- data/js/skill/craft/itemdetailgump.js | 30 +++++++++++++++------------ data/js/skill/craft/masonry.js | 17 +++++++-------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index c77c70bfd..e540fcb43 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -7,7 +7,7 @@ const Alchemy = 4028; const Fletching = 4029; const Tailoring = 4030; const Tinkering = 4032; -const scriptID = 4026; // This script +const itemDetailID = 4026; // This script const Cooking = 4034; const Cartography = 4035; const Glassblowing = 4036; @@ -80,13 +80,13 @@ function ItemDetailGump( pUser ) var socket = pUser.socket; var itemGump = new Gump; var createEntry = null; - var HARVEST; + var harvestResource; var mainSkill; // --- Override from temp tags if present (minimal change) --- var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); var skillTag = pUser.GetTempTag( "Skill" ); - var harvest1Tag = pUser.GetTempTag( "Harvest" ); + var harvestTag = pUser.GetTempTag( "Harvest" ); var harvest2Tag = pUser.GetTempTag( "Harvest2" ); var harvest3Tag = pUser.GetTempTag( "Harvest3" ); var harvest4Tag = pUser.GetTempTag( "Harvest4" ); @@ -107,21 +107,21 @@ function ItemDetailGump( pUser ) } // If harvest info is provided, rebuild HARVEST array - if( harvest1Tag !== null || harvest2Tag !== null || harvest3Tag !== null || harvest4Tag !== null ) + if( harvestTag !== null || harvest2Tag !== null || harvest3Tag !== null || harvest4Tag !== null ) { - HARVEST = []; + harvestResource = []; - if( harvest1Tag !== null ) - HARVEST.push( parseInt( harvest1Tag, 10 )); + if( harvestTag !== null ) + harvestResource.push( parseInt( harvestTag, 10 )); if( harvest2Tag !== null ) - HARVEST.push( parseInt( harvest2Tag, 10 )); + harvestResource.push( parseInt( harvest2Tag, 10 )); if( harvest3Tag !== null ) - HARVEST.push( parseInt( harvest3Tag, 10 )); + harvestResource.push( parseInt( harvest3Tag, 10 )); if( harvest4Tag !== null ) - HARVEST.push( parseInt( harvest4Tag, 10 )); + harvestResource.push( parseInt( harvest4Tag, 10 )); } /*switch( pUser.GetTempTag( "ITEMDETAILS" )) @@ -2281,9 +2281,13 @@ function ItemDetailGump( pUser ) chance += (( pUser.intelligence * ( primaryCraftSkill.intelligence / 10 )) / 10000 ); } - for( var i = 0; i < HARVEST.length; i++ ) + var maxHarvest = harvestResource.length; + if( resources.length < maxHarvest ) + maxHarvest = resources.length; + + for( var i = 0; i < maxHarvest; i++ ) { - itemGump.AddText( 170, 219 + ( i * 20 ), textHue, GetDictionaryEntry( HARVEST[i], socket.language )); + itemGump.AddText( 170, 219 + ( i * 20 ), textHue, GetDictionaryEntry( harvestResource[i], socket.language )); itemGump.AddText( 430, 219 + ( i * 20 ), textHue, resources[i][0] ); } @@ -2356,7 +2360,7 @@ function onGumpPress( pSock, pButton, gumpData ) return; var bItem = pSock.tempObj; - var gumpID = scriptID + 0xffff; + var gumpID = itemDetailID + 0xffff; switch( pButton ) { case 0: diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 7833de9f4..a44439f43 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -1,16 +1,15 @@ /// // @ts-check -const textHue = 0x480; // Color of the text. -const scriptID = 4023; // Script ID used to identify and close this gump -const masonryID = scriptID; // Backwards-compat alias -const gumpDelay = 2000; // Timer for the gump to reappear after crafting. -const ingotDelay = 200; // Timer for the gump to reappear after selecting an ingot. -const repairDelay = 200; // Timer for the gump to reappear after repairing an item +const textHue = 0x480; // Color of the text. +const masonryID = 4023; // Script ID used to identify and close this gump +const gumpDelay = 2000; // Timer for the gump to reappear after crafting. +const ingotDelay = 200; // Timer for the gump to reappear after selecting an ingot. +const repairDelay = 200; // Timer for the gump to reappear after repairing an item const craftGumpID = 4027; const itemDetailsScriptID = 4026; -const itemsPerPage = 10; // Number of craftable items shown per gump subpage -const displayUnlearnedRecipes = true; // Show recipes player has not learned (if we add any later) +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // Show recipes player has not learned (if we add any later) const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); // If enabled, players can craft coloured variants of weapons, though unless the craftItems array @@ -1112,7 +1111,7 @@ function onGumpPress( pSock, pButton, gumpData ) return; } - var gumpID = scriptID + 0xffff; + var gumpID = masonryID + 0xffff; // Close / Exit if( pButton == 0 ) From d7dd77287e0575b27f27f3bd5294d891cad369ff Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:29:34 -0600 Subject: [PATCH 18/43] Update masonry.dfn --- data/dfndata/create/masonry.dfn | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/dfndata/create/masonry.dfn b/data/dfndata/create/masonry.dfn index e7ba74343..99973ac63 100644 --- a/data/dfndata/create/masonry.dfn +++ b/data/dfndata/create/masonry.dfn @@ -291,7 +291,7 @@ SOUND=0x23D NAME=large gargish bed (east) ID=0x14f0 RESOURCE=STONE 3 -rEsOUrCE=CLOTH 100 +RESOURCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=largegargoylebedeastdeed @@ -305,7 +305,7 @@ SOUND=0x23D NAME=large gargish bed (south) ID=0x14f0 RESOURCE=STONE 3 -rEsOUrCE=CLOTH 100 +RESOURCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=largegargoylebedsouthdeed @@ -319,7 +319,7 @@ SOUND=0x23D NAME=gargish cot (east) ID=0x14f0 RESOURCE=STONE 3 -rEsOUrCE=CLOTH 100 +RESOURCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=gargishcoteasteastdeed @@ -333,7 +333,7 @@ SOUND=0x23D NAME=gargish cot (south) ID=0x14f0 RESOURCE=STONE 3 -rEsOUrCE=CLOTH 100 +RESOURCE=CLOTH 100 SKILL=11 760 1260 SKILL=34 700 750 ADDITEM=gargishcoteastsouthdeed From e54da36dcdb32d6acc3379a36d530dde0df668e7 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:09:53 -0600 Subject: [PATCH 19/43] Update itemdetailgump.js --- data/js/skill/craft/itemdetailgump.js | 2067 +------------------------ 1 file changed, 12 insertions(+), 2055 deletions(-) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index e540fcb43..08fee3c74 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -77,13 +77,13 @@ function ItemDetailGump( pUser ) "imbuing", "throwing " ]; + var socket = pUser.socket; var itemGump = new Gump; var createEntry = null; var harvestResource; var mainSkill; - // --- Override from temp tags if present (minimal change) --- var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); var skillTag = pUser.GetTempTag( "Skill" ); var harvestTag = pUser.GetTempTag( "Harvest" ); @@ -91,7 +91,6 @@ function ItemDetailGump( pUser ) var harvest3Tag = pUser.GetTempTag( "Harvest3" ); var harvest4Tag = pUser.GetTempTag( "Harvest4" ); - // If detail is provided, re-point createEntry if( detailTag !== null ) { createEntry = CreateEntries[ detailTag ]; @@ -124,2050 +123,6 @@ function ItemDetailGump( pUser ) harvestResource.push( parseInt( harvest4Tag, 10 )); } - /*switch( pUser.GetTempTag( "ITEMDETAILS" )) - { - //Start Blacksmith - case 1: - createEntry = CreateEntries[1]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 2: - createEntry = CreateEntries[2]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 3: - createEntry = CreateEntries[3]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 4: - createEntry = CreateEntries[4]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 5: - createEntry = CreateEntries[5]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 6: - createEntry = CreateEntries[6]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 7: - createEntry = CreateEntries[7]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 8: - createEntry = CreateEntries[8]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 9: - createEntry = CreateEntries[9]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 10: - createEntry = CreateEntries[10]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 11: - createEntry = CreateEntries[11]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 12: - createEntry = CreateEntries[12]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 13: - createEntry = CreateEntries[13]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 14: - createEntry = CreateEntries[14]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 15: - createEntry = CreateEntries[15]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 16: - createEntry = CreateEntries[16]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 17: - createEntry = CreateEntries[17]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 18: - createEntry = CreateEntries[18]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 19: - createEntry = CreateEntries[19]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 20: - createEntry = CreateEntries[20]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 21: - createEntry = CreateEntries[21]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 22: - createEntry = CreateEntries[22]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 23: - createEntry = CreateEntries[23]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 24: - createEntry = CreateEntries[24]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 25: - createEntry = CreateEntries[25]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 26: - createEntry = CreateEntries[26]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 27: - createEntry = CreateEntries[27]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 28: - createEntry = CreateEntries[28]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 29: - createEntry = CreateEntries[29]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 30: - createEntry = CreateEntries[30]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 31: - createEntry = CreateEntries[31]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 32: - createEntry = CreateEntries[32]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 33: - createEntry = CreateEntries[33]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 34: - createEntry = CreateEntries[34]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 35: - createEntry = CreateEntries[35]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 36: - createEntry = CreateEntries[36]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 37: - createEntry = CreateEntries[37]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 38: - createEntry = CreateEntries[38]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 39: - createEntry = CreateEntries[39]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 40: - createEntry = CreateEntries[40]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 41: - createEntry = CreateEntries[41]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 42: - createEntry = CreateEntries[42]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 43: - createEntry = CreateEntries[43]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 44: - createEntry = CreateEntries[44]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 45: - createEntry = CreateEntries[45]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 46: - createEntry = CreateEntries[46]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 47: - createEntry = CreateEntries[47]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 48: - createEntry = CreateEntries[48]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - case 49: - createEntry = CreateEntries[49]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.blacksmithing ); - break; - //Start Carpentry - case 50: - createEntry = CreateEntries[50]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 51: - createEntry = CreateEntries[51]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 52: - createEntry = CreateEntries[52]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 53: - createEntry = CreateEntries[53]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 54: - createEntry = CreateEntries[54]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 55: - createEntry = CreateEntries[55]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 56: - createEntry = CreateEntries[56]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 57: - createEntry = CreateEntries[57]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 58: - createEntry = CreateEntries[58]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 59: - createEntry = CreateEntries[59]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 60: - createEntry = CreateEntries[60]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 61: - createEntry = CreateEntries[61]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 62: - createEntry = CreateEntries[62]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 63: - createEntry = CreateEntries[63]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 64: - createEntry = CreateEntries[64]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 65: - createEntry = CreateEntries[65]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 66: - createEntry = CreateEntries[66]; - HARVEST = [10611, 10612];//missing loops - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 67: - createEntry = CreateEntries[67]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 68: - createEntry = CreateEntries[68]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 69: - createEntry = CreateEntries[69]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 70: - createEntry = CreateEntries[70]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 71: - createEntry = CreateEntries[71]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 72: - createEntry = CreateEntries[72]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 73: - createEntry = CreateEntries[73]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 74: - createEntry = CreateEntries[74]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 75: - createEntry = CreateEntries[75]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 76: - createEntry = CreateEntries[76]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 77: - createEntry = CreateEntries[77]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 78: - createEntry = CreateEntries[78]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 79: - createEntry = CreateEntries[79]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 80: - createEntry = CreateEntries[80]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 81: - createEntry = CreateEntries[81]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 82: - createEntry = CreateEntries[82]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 83: - createEntry = CreateEntries[83]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 84: - createEntry = CreateEntries[84]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 85: - createEntry = CreateEntries[85]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 86: - createEntry = CreateEntries[86]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 87: - createEntry = CreateEntries[87]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 88: - createEntry = CreateEntries[8]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 89: - createEntry = CreateEntries[89]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 90: - createEntry = CreateEntries[90]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 91: - createEntry = CreateEntries[91]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 92: - createEntry = CreateEntries[92]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 93: - createEntry = CreateEntries[93]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 94: - createEntry = CreateEntries[94]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 95: - createEntry = CreateEntries[95]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 96: - createEntry = CreateEntries[96]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 97: - createEntry = CreateEntries[97]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 98: - createEntry = CreateEntries[98]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 99: - createEntry = CreateEntries[99]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 100: - createEntry = CreateEntries[100]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 101: - createEntry = CreateEntries[101]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 102: - createEntry = CreateEntries[102]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 103: - createEntry = CreateEntries[103]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 104: - createEntry = CreateEntries[104]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 105: - createEntry = CreateEntries[105]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 106: - createEntry = CreateEntries[106]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 107: - createEntry = CreateEntries[107]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 108: - createEntry = CreateEntries[108]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 109: - createEntry = CreateEntries[109]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 110: - pUser.TextMessage( "Case 110!" ); - createEntry = CreateEntries[110]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 111: - createEntry = CreateEntries[111]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 112: - createEntry = CreateEntries[112]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 113: - createEntry = CreateEntries[113]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 114: - createEntry = CreateEntries[114]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 115: - createEntry = CreateEntries[115]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 116: - createEntry = CreateEntries[116]; - HARVEST = [10014, 10016]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 117: - createEntry = CreateEntries[117]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 118: - createEntry = CreateEntries[118]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 119: - createEntry = CreateEntries[119]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 120: - createEntry = CreateEntries[120]; - HARVEST = [10014, 10015]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 121: - createEntry = CreateEntries[121]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 122: - createEntry = CreateEntries[122]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 123: - createEntry = CreateEntries[123]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 124: - createEntry = CreateEntries[124]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - // Start Tailoring - case 130: - createEntry = CreateEntries[130]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 131: - createEntry = CreateEntries[131]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 132: - createEntry = CreateEntries[132]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 133: - createEntry = CreateEntries[133]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 134: - createEntry = CreateEntries[134]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 135: - createEntry = CreateEntries[135]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 136: - createEntry = CreateEntries[136]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 137: - createEntry = CreateEntries[137]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 138: - createEntry = CreateEntries[138]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 139: - createEntry = CreateEntries[139]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 140: - createEntry = CreateEntries[140]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 141: - createEntry = CreateEntries[141]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 142: - createEntry = CreateEntries[142]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 143: - createEntry = CreateEntries[143]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 144: - createEntry = CreateEntries[144]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 145: - createEntry = CreateEntries[145]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 146: - createEntry = CreateEntries[146]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 147: - createEntry = CreateEntries[147]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 148: - createEntry = CreateEntries[148]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 149: - createEntry = CreateEntries[149]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 150: - createEntry = CreateEntries[150]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 151: - createEntry = CreateEntries[151]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 152: - createEntry = CreateEntries[152]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 153: - createEntry = CreateEntries[153]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 154: - createEntry = CreateEntries[154]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 155: - createEntry = CreateEntries[155]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 156: - createEntry = CreateEntries[156]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 157: - createEntry = CreateEntries[157]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 158: - createEntry = CreateEntries[158]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break - case 159: - createEntry = CreateEntries[159]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 160: - createEntry = CreateEntries[160]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 161: - createEntry = CreateEntries[161]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 162: - createEntry = CreateEntries[162]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 163: - createEntry = CreateEntries[163]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 164: - createEntry = CreateEntries[164]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 165: - createEntry = CreateEntries[165]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 166: - createEntry = CreateEntries[166]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 167: - createEntry = CreateEntries[167]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 168: - createEntry = CreateEntries[168]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 169: - createEntry = CreateEntries[169]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 170: - createEntry = CreateEntries[170]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 171: - createEntry = CreateEntries[171]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 172: - createEntry = CreateEntries[172]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 173: - createEntry = CreateEntries[173]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 174: - createEntry = CreateEntries[174]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 175: - createEntry = CreateEntries[175]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 176: - createEntry = CreateEntries[176]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 177: - createEntry = CreateEntries[177]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 178: - createEntry = CreateEntries[178]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 179: - createEntry = CreateEntries[179]; - HARVEST = [10007]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 180: - createEntry = CreateEntries[180]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 181: - createEntry = CreateEntries[181]; - HARVEST = [10007, 10008]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 182: - createEntry = CreateEntries[182]; - HARVEST = [10007, 10008]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 183: - createEntry = CreateEntries[184]; - HARVEST = [10007, 10008]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 184: - createEntry = CreateEntries[184]; - HARVEST = [10007, 10008]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 185: - createEntry = CreateEntries[185]; - HARVEST = [10007, 10008]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - case 186: - createEntry = CreateEntries[135]; - HARVEST = [10016]; - mainSkill = parseInt( pUser.skills.tailoring ); - break; - // Start Fletching - case 190: - createEntry = CreateEntries[190]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 190: // Kindling - createEntry = CreateEntries[190]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 191: // Bow - createEntry = CreateEntries[191]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 192: // Crossbow - createEntry = CreateEntries[192]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 193: // Heavy Crossbow - createEntry = CreateEntries[193]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 194: // Shaft - createEntry = CreateEntries[194]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 195: // Five Shafts - createEntry = CreateEntries[195]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 196: // Twenty Shafts - createEntry = CreateEntries[196]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 197: // Fifty Shafts - createEntry = CreateEntries[197]; - HARVEST = [10014]; // Boards or Logs - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 198: // Arrow - createEntry = CreateEntries[198]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 199: // Five Arrows - createEntry = CreateEntries[199]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 200: // Twenty Arrows - createEntry = CreateEntries[200]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 201: // Fifty Arrows - createEntry = CreateEntries[201]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 202: // Bolt - createEntry = CreateEntries[202]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 203: // Five Bolts - createEntry = CreateEntries[203]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 204: // Twenty Bolts - createEntry = CreateEntries[204]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 205: // Fifty Bolts - createEntry = CreateEntries[205]; - HARVEST = [10029, 10028]; // Shaft, Feather - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 206: - createEntry = CreateEntries[206]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 207: - createEntry = CreateEntries[207]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - case 208: - createEntry = CreateEntries[208]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.bowcraft ); - break; - // Start Tinkering - case 274: // Axle - createEntry = CreateEntries[274]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 273: // Clock Frame - createEntry = CreateEntries[273]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 270: // Jointing Plane - createEntry = CreateEntries[270]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 271: // Moulding Plane - createEntry = CreateEntries[271]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 272: // Smoothing Plane - createEntry = CreateEntries[272]; - HARVEST = [10014]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 2 - Tools - case 218: // Dovetail Saw - createEntry = CreateEntries[218]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 215: // Draw Knife - createEntry = CreateEntries[215]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 252: // Froe - createEntry = CreateEntries[252]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 255: // Hammer - createEntry = CreateEntries[255]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 214: // Hatchet - createEntry = CreateEntries[214]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 258: // Inshave - createEntry = CreateEntries[258]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 260: // Lockpick - createEntry = CreateEntries[260]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 211: // Mortar and Pestle - createEntry = CreateEntries[211]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 259: // Pick Axe - createEntry = CreateEntries[259]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 217: // Saw - createEntry = CreateEntries[217]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 210: // Scissors - createEntry = CreateEntries[210]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 212: // Scorp - createEntry = CreateEntries[212]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 216: // Sewing Kit - createEntry = CreateEntries[216]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 254: // Shovel - createEntry = CreateEntries[254]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 257: // Sledge Hammer - createEntry = CreateEntries[257]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 256: // Smith's Hammer - createEntry = CreateEntries[256]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 253: // Tongs - createEntry = CreateEntries[253]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 213: // Tool Kit (Tinker's tools) - createEntry = CreateEntries[213]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 214: // Fletcher's Tools - createEntry = CreateEntries[284]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 3 - Parts - case 224: // Barrel Hoops - createEntry = CreateEntries[224]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 221: // Barrel Tap - createEntry = CreateEntries[221]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 220: // Clock parts - createEntry = CreateEntries[220]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 219: // Gears - createEntry = CreateEntries[219]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 225: // Hinge - createEntry = CreateEntries[225]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 223: // Sextant parts - createEntry = CreateEntries[223]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 222: // Springs - createEntry = CreateEntries[222]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 4 - Utensils - case 226: // Butcher Knife - createEntry = CreateEntries[226]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 232: // Cleaver - createEntry = CreateEntries[232]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 230: // Fork - createEntry = CreateEntries[230]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 231: // Fork - createEntry = CreateEntries[231]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 235: // Goblet - createEntry = CreateEntries[235]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 233: // Knife - createEntry = CreateEntries[233]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 234: // Knife - createEntry = CreateEntries[234]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 236: // Pewter Mug - createEntry = CreateEntries[236]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 229: // Plate - createEntry = CreateEntries[229]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 237: // Skinning Knife - createEntry = CreateEntries[237]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 227: // Spoon - createEntry = CreateEntries[227]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 228: // Spoon - createEntry = CreateEntries[228]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 5 - Jewelry - case 243: // Bracelet - createEntry = CreateEntries[243]; - HARVEST = [10015, 12005]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 241: // Earrings - createEntry = CreateEntries[241]; - HARVEST = [10015, 12005]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 239: // Necklage (Golden beads) - createEntry = CreateEntries[239]; - HARVEST = [10015, 12005]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 240: // Necklace (Silver beads) - createEntry = CreateEntries[240]; - HARVEST = [10015, 12005]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 242: // Necklace (Round) - createEntry = CreateEntries[242]; - HARVEST = [10015, 12005]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 238: // Weddingband (newbiefied) - createEntry = CreateEntries[238]; - HARVEST = [10015, 12006]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 6 - Miscellaneous - case 248: // Globe - createEntry = CreateEntries[248]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 251: // Heating stand - createEntry = CreateEntries[251]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 247: // Iron Key - createEntry = CreateEntries[247]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 244: // Keyring - createEntry = CreateEntries[244]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 250: // Lantern - createEntry = CreateEntries[250]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 246: // Scales - createEntry = CreateEntries[246]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 249: // Spy glass - createEntry = CreateEntries[249]; - HARVEST = [10015]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 7 - Multi-Component Items - case 275: // Axle and Gears - createEntry = CreateEntries[275]; - HARVEST = [11801, 11863]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 276: // Clock - createEntry = CreateEntries[276]; - HARVEST = [11802, 11862]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 277: // Clock - createEntry = CreateEntries[277]; - HARVEST = [11802, 11862]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 278: // Clock Parts - createEntry = CreateEntries[278]; - HARVEST = [11801, 11863]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 279: // Locked Box - createEntry = CreateEntries[279]; - HARVEST = [10634]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 280: // Locked Chest - createEntry = CreateEntries[280]; - HARVEST = [10638]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 281: // Potion Keg - createEntry = CreateEntries[281]; - HARVEST = [10642, 11861, 10612, 10928]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 282: // Sextant - createEntry = CreateEntries[282]; - HARVEST = [11948]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 283: // Sextant Parts - createEntry = CreateEntries[283]; - HARVEST = [11801, 11863]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 8 - Candles - case 245: // Candelabra - createEntry = CreateEntries[245]; - HARVEST = [10015, 12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 310: // Standing Candelabra - createEntry = CreateEntries[310]; - HARVEST = [10015, 12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 315: // Regular Candle - createEntry = CreateEntries[315]; - HARVEST = [10015, 12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 312: // Round Candle - createEntry = CreateEntries[312]; - HARVEST = [12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 316: // Skull with Candle - createEntry = CreateEntries[316]; - HARVEST = [12000, 12004]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 314: // Small Candle - createEntry = CreateEntries[314]; - HARVEST = [12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 311: // Tall Candle - createEntry = CreateEntries[311]; - HARVEST = [10015, 12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 313: // Thick Candle - createEntry = CreateEntries[313]; - HARVEST = [12000]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - // Page 9 - Traps - case 261: // Dart Trap - createEntry = CreateEntries[261]; - HARVEST = [10015, 12001]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 263: // Explosion Trap - createEntry = CreateEntries[263]; - HARVEST = [10015, 12003]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - case 262: // Poison Trap - createEntry = CreateEntries[262]; - HARVEST = [10015, 12002]; - mainSkill = parseInt( pUser.skills.tinkering ); - break; - //Start Alchemy - case 290: - createEntry = CreateEntries[290]; - HARVEST = [10019]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 291: - createEntry = CreateEntries[291]; - HARVEST = [10019]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 292: - createEntry = CreateEntries[292]; - HARVEST = [10020]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 293: - createEntry = CreateEntries[293]; - HARVEST = [10020]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 294: - createEntry = CreateEntries[294]; - HARVEST = [10020]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 295: - createEntry = CreateEntries[295]; - HARVEST = [10021]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 296: - createEntry = CreateEntries[296]; - HARVEST = [10021]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 297: - createEntry = CreateEntries[297]; - HARVEST = [10021]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 298: - createEntry = CreateEntries[298]; - HARVEST = [10022]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 299: - createEntry = CreateEntries[299]; - HARVEST = [10022]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 300: - createEntry = CreateEntries[300]; - HARVEST = [10022]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 301: - createEntry = CreateEntries[301]; - HARVEST = [10024]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 302: - createEntry = CreateEntries[302]; - HARVEST = [10024]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 303: - createEntry = CreateEntries[303]; - HARVEST = [10024]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 304: - createEntry = CreateEntries[304]; - HARVEST = [10024]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 305: - createEntry = CreateEntries[305]; - HARVEST = [10025]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 306: - createEntry = CreateEntries[306]; - HARVEST = [10025]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 307: - createEntry = CreateEntries[307]; - HARVEST = [10026]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 308: - createEntry = CreateEntries[308]; - HARVEST = [10026]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - case 309: - createEntry = CreateEntries[309]; - HARVEST = [10023]; - mainSkill = parseInt( pUser.skills.alchemy ); - break; - // Start Cooking - // Page 1 - Ingredients - case 1500: // Sack of Flour - createEntry = CreateEntries[1500]; - HARVEST = [11636]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1501: // Dough - createEntry = CreateEntries[1501]; - HARVEST = [11637, 11638]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1502: // Sweet Dough - createEntry = CreateEntries[1502]; - HARVEST = [11607, 11639]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1503: // Cake Mix - createEntry = CreateEntries[1503]; - HARVEST = [11637, 11608]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1504: // Cookie Mix - createEntry = CreateEntries[1504]; - HARVEST = [11639, 11608]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - // Page 2 - Preparation - case 1550: // Unbaked Quiche - createEntry = CreateEntries[1550]; - HARVEST = [11607, 11640]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1551: // Unbaked Meat Pie - createEntry = CreateEntries[1551]; - HARVEST = [11607, 11641]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1552: // Uncooked Sausage Pizza - createEntry = CreateEntries[1552]; - HARVEST = [11607, 11642]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1553: // Uncooked Cheese Pizza - createEntry = CreateEntries[1553]; - HARVEST = [11607, 11643]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1554: // Unbaked Fruit Pie - createEntry = CreateEntries[1554]; - HARVEST = [11607, 11644]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1555: // Unbaked Peach Cobbler - createEntry = CreateEntries[1555]; - HARVEST = [11607, 11645]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1556: // Unbaked Apple Pie - createEntry = CreateEntries[1556]; - HARVEST = [11607, 11646]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1557: // Unbaked Pumpkin Pie - createEntry = CreateEntries[1557]; - HARVEST = [11607, 11647]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - // Page 3 - Baking - case 1600: // Bread Loaf - createEntry = CreateEntries[1600]; - HARVEST = [11607]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1601: // Pan of Cookies - createEntry = CreateEntries[1601]; - HARVEST = [11610]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1602: // Cake - createEntry = CreateEntries[1602]; - HARVEST = [11609]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1603: // Muffins - createEntry = CreateEntries[1603]; - HARVEST = [11608]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1604: // Baked Quiche - createEntry = CreateEntries[1604]; - HARVEST = [11611]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1605: // Baked Meat Pie - createEntry = CreateEntries[1605]; - HARVEST = [11612]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1606: // Sausage Pizza - createEntry = CreateEntries[1606]; - HARVEST = [11613]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1607: // Cheese Pizza - createEntry = CreateEntries[1607]; - HARVEST = [11614]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1608: // Baked Fruit Pie - createEntry = CreateEntries[1608]; - HARVEST = [11615]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1609: // Baked Peach Cobbler - createEntry = CreateEntries[1609]; - HARVEST = [11616]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1610: // Baked Apple Pie - createEntry = CreateEntries[1610]; - HARVEST = [11617]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1611: // Baked Pumpkin Pie - createEntry = CreateEntries[1611]; - HARVEST = [11618]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - // Page 4 - Barbecue - case 1650: // Cooked Bird - createEntry = CreateEntries[1650]; - HARVEST = [11648]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1651: // Chicken Leg - createEntry = CreateEntries[1651]; - HARVEST = [11649]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1652: // Fish Steak - createEntry = CreateEntries[1652]; - HARVEST = [11650]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1653: // Fried Eggs - createEntry = CreateEntries[1653]; - HARVEST = [11651]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1654: // Leg of Lamb - createEntry = CreateEntries[1654]; - HARVEST = [11652]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - case 1655: // Cut of Ribs - createEntry = CreateEntries[1655]; - HARVEST = [11653]; - mainSkill = parseInt( pUser.skills.cooking ); - break; - // Cartography - case 2000: // Local Map - createEntry = CreateEntries[2000]; - HARVEST = [13004]; - mainSkill = parseInt( pUser.skills.cartography ); - break; - case 2001: // City Map - createEntry = CreateEntries[2001]; - HARVEST = [13004]; - mainSkill = parseInt( pUser.skills.cartography ); - break; - case 2002: // Sea Chart - createEntry = CreateEntries[2002]; - HARVEST = [13004]; - mainSkill = parseInt( pUser.skills.cartography ); - break; - case 2003: // World Map - createEntry = CreateEntries[2003]; - HARVEST = [13004]; - mainSkill = parseInt( pUser.skills.cartography ); - break; - // Glassblowing - case 3000: // empty bottle - createEntry = CreateEntries[3000]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3001: // flask (small) - createEntry = CreateEntries[3001]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3002: // flask (medium) - createEntry = CreateEntries[3002]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3003: // flask (curved) - createEntry = CreateEntries[3003]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3004: // flask (large #1) - createEntry = CreateEntries[3004]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3005: // flask (large #2) - createEntry = CreateEntries[3005]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3006: // flask (bubbling blue) - createEntry = CreateEntries[3006]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3007: // flask (bubbling purple) - createEntry = CreateEntries[3007]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3008: // flask (bubbling red) - createEntry = CreateEntries[3008]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3009: // empty vials - createEntry = CreateEntries[3009]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3010: // full vials - createEntry = CreateEntries[3010]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - case 3011: // spinning hourglass - createEntry = CreateEntries[3011]; - HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; - //Start masonry - case 3500:// vase - createEntry = CreateEntries[3500]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3501:// large vase - createEntry = CreateEntries[3501]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3502:// small urn - createEntry = CreateEntries[3502]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3503:// Tower Sculpture - createEntry = CreateEntries[3503]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3504:// gargoyle painting - createEntry = CreateEntries[3504]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3505:// gargoyle sculpture - createEntry = CreateEntries[3505]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3506:// gargoyle vase - createEntry = CreateEntries[3506]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3507:// Tall 18th Anniversary Vase - createEntry = CreateEntries[3507]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3508:// Short 18th Anniversary Vase - createEntry = CreateEntries[3508]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3509:// stone chair - createEntry = CreateEntries[3509]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3510:// stone table (east) - createEntry = CreateEntries[3510]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3511:// stone table (south) - createEntry = CreateEntries[3511]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3512:// large stone table (east) - createEntry = CreateEntries[3512]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3513:// large stone table (south) - createEntry = CreateEntries[3513]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3514:// ritual table - createEntry = CreateEntries[3514]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3515:// small statue (south) - createEntry = CreateEntries[3515]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3516:// small statue (north) - createEntry = CreateEntries[3516]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3517:// small statue (east) - createEntry = CreateEntries[3517]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3518:// pegasus statuette - createEntry = CreateEntries[3518]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3519:// gargoyle statue - createEntry = CreateEntries[3519]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3520:// gryphon statue - createEntry = CreateEntries[3520]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3521:// stone anvil (east) - createEntry = CreateEntries[3521]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3522:// stone anvil (south) - createEntry = CreateEntries[3522]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3523:// large gargish bed (east) - createEntry = CreateEntries[3523]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3524:// large gargish bed (south) - createEntry = CreateEntries[3524]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3525:// gargish cot (east) - createEntry = CreateEntries[3525]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3526:// gargish cot (south) - createEntry = CreateEntries[3526]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3527:// gargish stone arms - createEntry = CreateEntries[3527]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3528:// gargish stone chest - createEntry = CreateEntries[3528]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3529:// gargish stone leggings - createEntry = CreateEntries[3529]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3530:// gargish stone kilt - createEntry = CreateEntries[3530]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3531:// gargish stone arms - createEntry = CreateEntries[3531]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3532:// gargish stone chest - createEntry = CreateEntries[3532]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3533:// gargish stone leggings - createEntry = CreateEntries[3533]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3534:// gargish stone kilt - createEntry = CreateEntries[3534]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3535:// large stone shield - createEntry = CreateEntries[3535]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3536:// gargish stone amulet - createEntry = CreateEntries[3536]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3537:// stone war sword - createEntry = CreateEntries[3537]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3538:// rough windowless - createEntry = CreateEntries[3538]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3539:// rough window - createEntry = CreateEntries[3539]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3540:// rough arch - createEntry = CreateEntries[3540]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3541:// rough pillar - createEntry = CreateEntries[3541]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3542:// rough rounded arch - createEntry = CreateEntries[3542]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3543:// rough small arch - createEntry = CreateEntries[3543]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3544:// rough angled pillar - createEntry = CreateEntries[3544]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3545:// short rough - createEntry = CreateEntries[3545]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3546:// Stone Door S In - createEntry = CreateEntries[3546]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3547:// Stone Door E Out - createEntry = CreateEntries[3547]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3548:// Stone Door S Out - createEntry = CreateEntries[3548]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3549:// Stone Door E In - createEntry = CreateEntries[3549]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3550:// short rough - createEntry = CreateEntries[3550]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3551:// rough steps - createEntry = CreateEntries[3551]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3552:// rough corner steps - createEntry = CreateEntries[3552]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3553:// rough rounded corner step - createEntry = CreateEntries[3553]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3554:// rough inset steps - createEntry = CreateEntries[3554]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3555:// rough rounded inset steps - createEntry = CreateEntries[3555]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3556:// light paver - createEntry = CreateEntries[3556]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3557:// medium paver - createEntry = CreateEntries[3557]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - case 3558:// dark paver - createEntry = CreateEntries[3558]; - HARVEST = [14011]; - mainSkill = parseInt( pUser.skills.carpentry ); - break; - default: - break; - }*/ - if( createEntry == null ) { return; @@ -2216,7 +171,7 @@ function ItemDetailGump( pUser ) var minSkill = skillReq[1]; var maxSkill = skillReq[2]; - itemGump.AddHTMLGump( 170, 132 + ( i * 20 ), 200, 18, 0, 0, "
" + GetDictionaryEntry( 15000 + skills[i][0], socket.language ) + "
" ); + itemGump.AddHTMLGump( 170, 132 + ( i * 20 ), 200, 18, false, false, "
" + GetDictionaryEntry( 15000 + skills[i][0], socket.language ) + "
" ); itemGump.AddText( 430, 132 + ( i * 20 ), textHue, skills[i][1]/10 ); if( i == 0 ) @@ -2297,7 +252,9 @@ function ItemDetailGump( pUser ) exceptionalChance = 0; } else if( chance > 1.0 ) + { chance = 1.0; // Cap chance at 100% + } itemGump.AddText( 430, 80, textHue, ( chance * 100 ).toFixed( 1 ) + "%" ); // Success Chance: if( !exceptionalWearablesOnly || CheckTileFlag( createID, 22 )) // TF_WEARABLE @@ -2315,7 +272,7 @@ function ItemDetailGump( pUser ) { itemGump.AddText( 430, 100, textHue, "-" ); // No chance of exceptional, not a wearable item! } - itemGump.Send( pUser ); + itemGump.Send( socket ); itemGump.Free(); } @@ -2335,18 +292,18 @@ function ItemDetailsGump( itemGump, pUser ) itemGump.AddTiledGump( 165, 302, 355, 80, 2624 ); itemGump.AddTiledGump( 10, 387, 510, 22, 2624 ); itemGump.AddCheckerTrans( 10, 10, 510, 399 ); - itemGump.AddHTMLGump( 170, 40, 150, 20, 0, 0, "
" + GetDictionaryEntry( 10000, socket.language ) + "
" ); // ITEM + itemGump.AddHTMLGump( 170, 40, 150, 20, false, false, "
" + GetDictionaryEntry( 10000, socket.language ) + "
" ); // ITEM - itemGump.AddHTMLGump( 10, 217, 150, 22, 0, 0, "
" + GetDictionaryEntry( 10001, socket.language ) + "
" ); //
MATERIALS
- itemGump.AddHTMLGump( 10, 302, 150, 22, 0, 0, "
" + GetDictionaryEntry( 10002, socket.language ) + "
" ); //
OTHER
- itemGump.AddHTMLGump( 170, 80, 250, 18, 0, 0, "" + GetDictionaryEntry( 10003, socket.language ) + "" ); // Success Chance: + itemGump.AddHTMLGump( 10, 217, 150, 22, false, false, "
" + GetDictionaryEntry( 10001, socket.language ) + "
" ); //
MATERIALS
+ itemGump.AddHTMLGump( 10, 302, 150, 22, false, false, "
" + GetDictionaryEntry( 10002, socket.language ) + "
" ); //
OTHER
+ itemGump.AddHTMLGump( 170, 80, 250, 18, false, false, "" + GetDictionaryEntry( 10003, socket.language ) + "" ); // Success Chance: if( GetServerSetting( "RankSystem" )) { - itemGump.AddHTMLGump( 170, 100, 250, 18, 0, 0, "" + GetDictionaryEntry( 10004, socket.language ) + "" ); // Exceptional Chance: + itemGump.AddHTMLGump( 170, 100, 250, 18, false, false, "" + GetDictionaryEntry( 10004, socket.language ) + "" ); // Exceptional Chance: } itemGump.AddButton( 15, 387, 0xfa5, 1, 0, 1 ); - itemGump.AddHTMLGump( 50, 390, 150, 18, 0, 0, "" + GetDictionaryEntry( 10005, socket.language ) + "" ); // BACK - itemGump.AddHTMLGump( 170, ( 302 + 20 ), 310, 18, 0, 0, "" + GetDictionaryEntry( 10006, socket.language ) + "" ); // * The item retains the color of this material + itemGump.AddHTMLGump( 50, 390, 150, 18, false, false, "" + GetDictionaryEntry( 10005, socket.language ) + "" ); // BACK + itemGump.AddHTMLGump( 170, ( 302 + 20 ), 310, 18, false, false, "" + GetDictionaryEntry( 10006, socket.language ) + "" ); // * The item retains the color of this material itemGump.AddText( 500, 219, textHue, "*" ); } From e3543a24040add302f0f5e4e3c46959f81e2f4d3 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:28:56 -0600 Subject: [PATCH 20/43] update --- data/js/skill/craft/itemdetailgump.js | 42 +++++++++++++++++++++++++++ data/js/skill/craft/masonry.js | 5 ++++ 2 files changed, 47 insertions(+) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 08fee3c74..4362ca458 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -83,6 +83,7 @@ function ItemDetailGump( pUser ) var createEntry = null; var harvestResource; var mainSkill; + //var recipeID = 0; // default: no recipe required var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); var skillTag = pUser.GetTempTag( "Skill" ); @@ -90,6 +91,7 @@ function ItemDetailGump( pUser ) var harvest2Tag = pUser.GetTempTag( "Harvest2" ); var harvest3Tag = pUser.GetTempTag( "Harvest3" ); var harvest4Tag = pUser.GetTempTag( "Harvest4" ); + var recipeID = pUser.GetTempTag( "needRecipeID" ); if( detailTag !== null ) { @@ -128,6 +130,14 @@ function ItemDetailGump( pUser ) return; } + // Recipe flags + var needsRecipe = ( recipeID > 0 ); + var hasRecipe = false; + if( needsRecipe ) + { + hasRecipe = HasLearnedRecipe( pUser, recipeID ); + } + // Fetch properties of create entry var createName = createEntry.name; // name of the create entry var createID = createEntry.id; // section id of item to craft @@ -272,6 +282,23 @@ function ItemDetailGump( pUser ) { itemGump.AddText( 430, 100, textHue, "-" ); // No chance of exceptional, not a wearable item! } + + if( needsRecipe ) + { + var recipeMsg; + if( hasRecipe ) + { + recipeMsg = "You have learned this recipe."; + } + else + { + recipeMsg = "You have not learned this recipe."; + } + + // OTHER box starts at y=302, you already use 302+20 for the color note (dict 10006), + // so 302+40 (342) is a safe line under that. + itemGump.AddHTMLGump( 170, 342, 310, 18, false, false, recipeMsg ); + } itemGump.Send( socket ); itemGump.Free(); } @@ -496,3 +523,18 @@ function onGumpPress( pSock, pButton, gumpData ) } } } + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} \ No newline at end of file diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index a44439f43..3678b6ea4 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -1222,6 +1222,11 @@ function onGumpPress( pSock, pButton, gumpData ) if( entry.harvest4 && entry.harvest4.length > 0 ) pUser.SetTempTag("Harvest4", entry.harvest4[0]); + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + pUser.SetTempTag( "ITEMDETAILS", graniteMakeID ); TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); } From 5591eb46b9398ef53dbe0793089c60c085c3b692 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 20:09:59 -0600 Subject: [PATCH 21/43] Update itemdetailgump.js --- data/js/skill/craft/itemdetailgump.js | 1 - 1 file changed, 1 deletion(-) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 4362ca458..4c0642c0c 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -83,7 +83,6 @@ function ItemDetailGump( pUser ) var createEntry = null; var harvestResource; var mainSkill; - //var recipeID = 0; // default: no recipe required var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); var skillTag = pUser.GetTempTag( "Skill" ); From 36174ff56ebb1be956f14c833ac34dea4b87848e Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:33:38 -0600 Subject: [PATCH 22/43] update Blacksmithing --- data/js/skill/craft/blacksmithing.js | 1029 ++++++++++++++------------ data/js/skill/craft/masonry.js | 12 +- 2 files changed, 577 insertions(+), 464 deletions(-) diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index 8ffa0eba4..fbb0b4444 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -1,32 +1,135 @@ /// // @ts-check -const textHue = 0x480; // Color of the text. -const blacksmithID = 4023; // Use this to tell the gump what script to close. -const bronzeID = 4015; -const copperID = 4016; -const agapiteID = 4017; -const dullcopperID = 4018; -const goldID = 4019; -const shadowironID = 4020; -const valoriteID = 4021; -const veriteID = 4022; -const gumpDelay = 2000; // Timer for the gump to reappear after crafting. -const ingotDelay = 200; // Timer for the gump to reappear after selecting a ingot. -const repairDelay = 200; // Timer for the gump to reappear after repairing an item +const textHue = 0x480; // Color of the text. +const blacksmithID = 4023; // Script ID used to identify and close this gump +const gumpDelay = 2000; // Timer for the gump to reappear after crafting. +const ingotDelay = 200; // Timer for the gump to reappear after selecting an ingot. +const repairDelay = 200; // Timer for the gump to reappear after repairing an item const craftGumpID = 4027; const itemDetailsScriptID = 4026; - // If enabled, players can craft coloured variants of weapons, though unless the craftItems array - // is updated with specific create entries for the coloured weapon variants, they'll just be - // regular weapons with ore colour applied +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // Show recipes player has not learned (if we add any later) +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); + +// If enabled, players can craft coloured variants of weapons, though unless the craftItems array +// is updated with specific create entries for the coloured weapon variants, they will just be +// regular weapons with ore colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); -////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the armor or weapon to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// +// Optional: if you later decide to make some blacksmith items recipe-locked, we will use this map: +// BlacksmithMap[buttonID] = { dictID, page, timerID, oreMake: [makeIDByOre], recipeID?, minEra?, maxEra? } +// o--------------------------------------------------------------------------o +// | Script - blacksmithing.js | +// | System - Blacksmith Crafting Gump | +// o--------------------------------------------------------------------------o +// | Purpose - | +// | Provides the blacksmith crafting menu using the same data-driven | +// | system used by the tailoring script. | +// | | +// | All craftable items are defined in tables (myPage, craftItems) and | +// | then mapped into a MasonryMap structure that controls: | +// | - Which dictionary entry is shown per row | +// | - Which "makeID" entry is used for each ore type | +// | - Which page and timer ID to use when reopening the gump | +// | - Optional per-item recipe and era requirements | +// | - Optional per-item custom names for display | +// | | +// | The script also handles: | +// | - iron selection (iron / colored ores) with skill requirements | +// | - Smelting iron items back into Granite | +// | - Repairing stone armor and weapons at an anvil | +// | - Tool wear and runic hammer handling | +// | - A "Make Last" feature | +// | - A "Last Ten Masonry" list (optional) | +// o--------------------------------------------------------------------------o +// | Data Tables | +// o--------------------------------------------------------------------------o +// | myPage | +// | myPage[pageIndex] = [ dictID1, dictID2, ... ] | +// | pageIndex 0 => Page 1: Metal Armor | +// | pageIndex 1 => Page 2: Helmets | +// | pageIndex 2 => Page 3: Shields | +// | pageIndex 3 => Page 4: Bladed weapons | +// | pageIndex 4 => Page 5: Axes | +// | pageIndex 5 => Page 6: Polearms | +// | pageIndex 6 => Page 7: Bashing weapons | +// | | +// | Each entry is a dictionary ID that will be used to look up the text | +// | for that row, unless a customName is defined for that button in | +// | MasonryMap. | +// | | +// | craftItems | +// | craftItems[ironIndex][pageIndex][itemIndex] = makeID | +// | oreIndex 0 = Iron | +// | oreIndex 1 = Dull Copper | +// | oreIndex 2 = Shadow Iron | +// | oreIndex 3 = Copper | +// | oreIndex 4 = Bronze | +// | oreIndex 5 = Gold | +// | oreIndex 6 = Agapite | +// | oreIndex 7 = Verite | +// | oreIndex 8 = Valorite | +// | | +// | For each granite type and page, this holds the createEntry ID used by | +// | MakeItem when the player crafts that item. The same index positions | +// | on each page line up with the matching entries in myPage. | +// o--------------------------------------------------------------------------o +// | BlacksmithMap | +// o--------------------------------------------------------------------------o +// | BlacksmithMap is built automatically from myPage and craftItems. | +// | | +// | BlacksmithMap[buttonID] = { | +// | dictID : number, // Base dictionary entry for the row | +// | page : number, // Main page (1..7, or 999 for Last Ten) | +// | timerID : number, // Timer ID to reopen same page | +// | oreMake : number[], // oreMake[oreIndex] = makeID | +// | customName: string?, // Optional override for display text | +// | recipeID : number?, // Optional recipe requirement | +// | minEra : string?, // Optional minimum shard era | +// | maxEra : string? // Optional maximum shard era | +// | }; | +// | | +// | Button ID mapping (same as original script): | +// | Page 1 (Metal Armors) : 100..108 | +// | Page 2 (Helmets) : 200..205 | +// | Page 3 (Shields) : 300..305 | +// | Page 4 (Bladed) : 400..407 | +// | Page 5 (Axes) : 500..506 | +// | Page 6 (PoleArms) : 600..604 | +// | Page 7 (Bashing): 700..704 | +// | | +// | Custom Names | +// | To override the display name for a specific row, set customName after | +// | the BlacksmithMap has been initialized, for example: | +// | | +// | BlacksmithMap[100].customName = "Hump vase"; | +// | | +// | PageX() will use this order of preference for text: | +// | 1. entry.customName (if set) | +// | 2. GetDictionaryEntry(entry.dictID) | +// | 3. A fallback "[Unnamed Item: buttonID]" | +// | | +// | Recipes | +// | If recipeID is set on a MasonryMap entry, onGumpPress will call: | +// | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | +// | to check if the player has learned that recipe. If not, the craft | +// | attempt is blocked and a message is shown. | +// | | +// | Era Gating | +// | The script reads the shard era using: | +// | const coreShardEra = EraStringToNum(GetServerSetting("CoreShardEra")); | +// | | +// | If an entry defines minEra or maxEra (strings like "lbr","aos","ml", | +// | "sa","hs","tol"), eraOK(entry) will ensure the current server era is | +// | within that range before allowing craft or display. | +// o--------------------------------------------------------------------------o +// | Notes | +// o--------------------------------------------------------------------------o +// | - To add new blacksmith items, update myPage and craftItems, then | +// | optionally decorate their BlacksmithMap entries with customName, | +// | recipeID, minEra, and maxEra. | +// o--------------------------------------------------------------------------o const myPage = [ // Page 1 - Metal Armors @@ -209,47 +312,209 @@ const craftItems = [ ] ]; -function PageX( socket, pUser, pageNum ) -{ - // Pages 1 - 7 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - var resourceHue = pUser.GetTempTag( "resourceHue" ); +// BlacksmithMap[buttonID] = { +// dictID: , +// page: , +// timerID: , +// oreMake: [ makeIDForIron, makeIDForDullCopper, ... ], // index is oreID (0..8) +// // Optional later: +// // recipeID: , +// // minEra: "lbr" / "aos" / "ml" / "sa" / "hs" / "tol", +// // maxEra: ... +// }; - for( var i = 0; i < myPage[pageNum - 1].length; i++ ) +const BlacksmithMap = {}; + +(function initBlacksmithMap() +{ + // oreIndex: 0 = iron, 1 = dull copper, ... 8 = valorite + for( var oreIndex = 0; oreIndex < craftItems.length; oreIndex++ ) { - // Don't show weapon entries if player has coloured ingots selected - if( !allowColouredWeapons && resourceHue > 0 && pageNum > 3 ) - continue; + var oreRows = craftItems[oreIndex]; - var index = i % 10; - if( index == 0 ) + // pageIdx: 0..6 => pages 1..7 + for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) { - if( i > 0 ) + var dictList = myPage[pageIdx]; + var makeList = oreRows[pageIdx]; + + for( var i = 0; i < dictList.length && i < makeList.length; i++ ) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + // Old script uses: + // page 1 => 100..112 + // page 2 => 200..204 + // page 3 => 300..305 + // etc. + var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; + var dictID = dictList[i]; + var makeID = makeList[i]; + + if( !BlacksmithMap[buttonID] ) + { + BlacksmithMap[buttonID] = { + dictID: dictID, + page: pageIdx + 1, + timerID: pageIdx + 1, + oreMake: [], + // recipeID: undefined, + // minEra: undefined, + // maxEra: undefined + skill: 7, // blacksmithing skill ID + harvest: [10291], // iron dict + harvest2: [], // optional second resource + harvest3: [], // optional second resource + harvest4: [] // optional second resource + }; + } + + BlacksmithMap[buttonID].oreMake[oreIndex] = makeID; } + } + } +})(); - myGump.AddPage(( i / 10) + 1 ); +// 3) AFTER initBlacksmithMap, you can override entries: +// BlacksmithMap[400].customName = "Elven Broadsword"; +// BlacksmithMap[400].recipeID = 5101; // if you want it recipe-locked +// BlacksmithMap[400].minEra = "ml"; // if you want it ML and later only - if( i > 0 ) +function PageX( socket, pUser, pageNum ) +{ + if( !ValidateObject( pUser )) + return; + + // Pages 1 - 7: normal crafting pages + // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) + + var subPage = pUser.GetTempTag( "subPage" ) || 1; + var pageItems = []; + + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenBlacksmith" ) || ""; + var split = lastTenRaw.split( "," ); + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val ) && BlacksmithMap[val] ) + pageItems.push( val ); // here val is the buttonID itself + } + } + else + { + // Build list of buttonIDs for this page from BlacksmithMap + for( var buttonID in BlacksmithMap ) + { + var data = BlacksmithMap[buttonID]; + if( data.page == pageNum && eraOK( data )) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + // If we later add recipes and want to hide unknown ones: + var needsRecipe = data.recipeID; + var showAll = displayUnlearnedRecipes; + if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) + { + pageItems.push( parseInt( buttonID ) ); + } } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); - myGump.AddText( 255, 60 + ( index * 20 ), textHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language )); + // Sort by buttonID to keep consistent ordering + pageItems.sort( function( a, b ){ return a - b; } ); + } - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, ( 2000 + ( 100 * pageNum )) + i ); + if( pageItems.length == 0 ) + { + var emptyGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", emptyGump, socket ); + emptyGump.AddPage( 1 ); + emptyGump.AddText( 220, 60, textHue, "No items available on this page." ); + emptyGump.Send( socket ); + emptyGump.Free(); + return; } - myGump.Send( socket ); - myGump.Free(); + + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var resourceHue = pUser.GetTempTag( "resourceHue" ) | 0; + var blacksmithMenu = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", blacksmithMenu, socket ); + blacksmithMenu.AddPage( 1 ); + + var drawIndex = 0; + + for( var i = startIndex; i < endIndex; i++ ) + { + var buttonID = pageItems[i]; + var data = BlacksmithMap[buttonID]; + + // Do not show weapons when colored ingots selected and colored weapons are disabled + if( !allowColouredWeapons && resourceHue > 0 && data.page > 3 ) + continue; + + var entryText = ""; + if( data.customName ) + { + entryText = data.customName; + } + else if( data.dictID ) + { + entryText = GetDictionaryEntry( data.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + buttonID + "]"; + } + + // Same layout as tailoring: button, text, details button + blacksmithMenu.AddButton( 220, 60 + ( drawIndex * 20 ), 4005, 4007, 1, 0, buttonID ); + blacksmithMenu.AddText( 255, 60 + ( drawIndex * 20 ), textHue, entryText ); + blacksmithMenu.AddButton( 480, 60 + ( drawIndex * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); + + drawIndex++; + } + + // Prev subpage + if( subPage > 1 ) + { + blacksmithMenu.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + blacksmithMenu.AddHTMLGump( 255, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + + // Next subpage + if( subPage < totalSubPages ) + { + blacksmithMenu.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + blacksmithMenu.AddHTMLGump( 405, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + blacksmithMenu.Send( socket ); + blacksmithMenu.Free(); } + function Page8( socket, pUser ) { //Ingot Choices @@ -681,22 +946,17 @@ function onTimer( pUser, timerID ) var socket = pUser.socket; - switch( timerID ) + if( timerID >= 1 && timerID <= 7 ) { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - PageX( socket, pUser, timerID ); - break; - case 8: // Page 8 - Page8( socket, pUser ); - break; - default: - break; + PageX( socket, pUser, timerID ); // Pages 1 - 7 + } + else if( timerID == 8 ) + { + Page8( socket, pUser ); // Ingot selection + } + else if( timerID == 999 ) + { + PageX( socket, pUser, 999 ); // Last Ten Blacksmith (if used) } } @@ -704,12 +964,11 @@ function onTimer( pUser, timerID ) function onGumpPress( pSock, pButton, gumpData ) { var pUser = pSock.currentChar; + var usedMakeLast = false; - // Don't continue if character is invalid, or worse... dead! if( !ValidateObject( pUser ) || pUser.dead ) return; - // Don't continue if player no longer has access to the crafting tool var bItem = pSock.tempObj; if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) { @@ -724,9 +983,9 @@ function onGumpPress( pSock, pButton, gumpData ) } var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + if( ValidateObject( iPackOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( iPackOwner.serial != pUser.serial ) { pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! return; @@ -739,422 +998,276 @@ function onGumpPress( pSock, pButton, gumpData ) } var gumpID = blacksmithID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var oreID = pUser.GetTempTag( "ORE" ); - var resourceHue = pUser.GetTempTag( "resourceHue" ); - var newOreID = -1; - var newResourceHue = -1; - var timerID = 0; - - // Check for nearby anvil - var anvil = 0; - - // If button pressed is one of the crafting buttons (or "make last"), check that anvil was found - if(( pButton >= 100 && pButton <= 704 ) || pButton == 5000 ) + + // Close / Exit + if( pButton == 0 ) + { + pUser.SetTempTag( "prevActionResult", null ); + pUser.SetTempTag( "MAKELAST", null ); + pSock.CloseGump( gumpID, 0 ); + return; + } + + // Repair Item + if( pButton == 49 ) + { + RepairTarget( pSock ); + return; + } + + // Select Materials (ingots) + if( pButton == 50 ) + { + pSock.CloseGump( gumpID, 0 ); + Page8( pSock, pUser ); + return; + } + + // Smelt Item + if( pButton == 52 ) + { + SmeltTarget( pSock ); + return; + } + + // Page buttons (1..7) + if( pButton >= 1 && pButton <= 7 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + pSock.CloseGump( gumpID, 0 ); + PageX( pSock, pUser, pButton ); + return; + } + + // Last Ten page (if you wire it into the gump) + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, 999 ); + return; + } + + // Subpage navigation (8000 = prev, 9000 = next) + if( pButton >= 8000 && pButton < 9000 ) + { + var prevSub = pButton - 8000; + var curPage = pUser.GetTempTag( "page" ) || 1; + pUser.SetTempTag( "subPage", prevSub ); + PageX( pSock, pUser, curPage ); + return; + } + + if( pButton >= 9000 && pButton < 10000 ) + { + var nextSub = pButton - 9000; + var curPage2 = pUser.GetTempTag( "page" ) || 1; + pUser.SetTempTag( "subPage", nextSub ); + PageX( pSock, pUser, curPage2 ); + return; + } + + // Handle "Make Last" + if(( pButton >= 100 && pButton <= 799 ) || pButton == 5000 ) { - anvil = AreaItemFunction( "FindNearbyAnvils", pUser, 2, pSock ); - if( anvil > 0 ) + if( pButton == 5000 ) { - if( pButton == 5000 ) - { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); - } - else - { - // Update Make Last entry - pUser.SetTempTag( "MAKELAST", pButton ); - } + pButton = pUser.GetTempTag( "MAKELAST" ); + usedMakeLast = true; } else { - // No anvil found nearby! - pUser.SetTempTag( "prevActionResult", "NOANVIL" ); + pUser.SetTempTag( "MAKELAST", pButton ); } } - switch( pButton ) + // Item detail buttons (2000 + buttonID) + if( pButton >= 2000 && pButton < 3000 ) { - case 0: - pUser.SetTempTag( "prevActionResult", null ); - pUser.SetTempTag( "MAKELAST", null ); - pSock.CloseGump( gumpID, 0 ); - break;// abort and do nothing - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - case 49: // Repair Item - RepairTarget( pSock ); - break; - case 50: // Select Materials - pSock.CloseGump( gumpID, 0 ); - Page8( pSock, pUser ); - break; - case 52: // Smelt Item - SmeltTarget( pSock ); - break; - // [100-199] - case 100: // Ringmail Gloves - makeID = craftItems[oreID][0][0]; timerID = 1; break; - case 101: // Ringmail Legs - makeID = craftItems[oreID][0][1]; timerID = 1; break; - case 102: // Ringmail Arms - makeID = craftItems[oreID][0][2]; timerID = 1; break; - case 103: // Ringmail Chest - makeID = craftItems[oreID][0][3]; timerID = 1; break; - case 104: // Chain Coif - makeID = craftItems[oreID][0][4]; timerID = 1; break; - case 105: // Chain Legs - makeID = craftItems[oreID][0][5]; timerID = 1; break; - case 106: // Chain Chest - makeID = craftItems[oreID][0][6]; timerID = 1; break; - case 107: // Plate Arms - makeID = craftItems[oreID][0][7]; timerID = 1; break; - case 108: // Plate Gloves - makeID = craftItems[oreID][0][8]; timerID = 1; break; - case 109: // Plate Gorget - makeID = craftItems[oreID][0][9]; timerID = 1; break; - case 110: // Plate Legs - makeID = craftItems[oreID][0][10]; timerID = 1; break; - case 111: // Plate Chest - makeID = craftItems[oreID][0][11]; timerID = 1; break; - case 112: // Female Plate Chest - makeID = craftItems[oreID][0][12]; timerID = 1; break; - // [200-299] - case 200: // Bascinet - makeID = craftItems[oreID][1][0]; timerID = 2; break; - case 201: // Close Helm - makeID = craftItems[oreID][1][1]; timerID = 2; break; - case 202: // Helmet - makeID = craftItems[oreID][1][2]; timerID = 2; break; - case 203: // Norse Helm - makeID = craftItems[oreID][1][3]; timerID = 2; break; - case 204: // Plate Helm - makeID = craftItems[oreID][1][4]; timerID = 2; break; - // [300-399] - case 300: // Buckler - makeID = craftItems[oreID][2][0]; timerID = 3; break; - case 301: // Bronze Shield - makeID = craftItems[oreID][2][1]; timerID = 3; break; - case 302: // Heater Shield - makeID = craftItems[oreID][2][2]; timerID = 3; break; - case 303: // Metal Shield - makeID = craftItems[oreID][2][3]; timerID = 3; break; - case 304: // Metal Kite Shield - makeID = craftItems[oreID][2][4]; timerID = 3; break; - case 305: // Tear Kite Shield - makeID = craftItems[oreID][2][5]; timerID = 3; break; - // [400-499] - case 400: // Broadsword - makeID = craftItems[oreID][3][0]; timerID = 4; break; - case 401: // Cutlass - makeID = craftItems[oreID][3][1]; timerID = 4; break; - case 402: // Dagger - makeID = craftItems[oreID][3][2]; timerID = 4; break; - case 403: // Katana - makeID = craftItems[oreID][3][3]; timerID = 4; break; - case 404: // Kryss - makeID = craftItems[oreID][3][4]; timerID = 4; break; - case 405: // Longsword - makeID = craftItems[oreID][3][5]; timerID = 4; break; - case 406: // Scimitar - makeID = craftItems[oreID][3][6]; timerID = 4; break; - case 407: // Viking Sword - makeID = craftItems[oreID][3][7]; timerID = 4; break; - // [500-599] - case 500: // Axe - makeID = craftItems[oreID][4][0]; timerID = 5; break; - case 501: // Battle Axe - makeID = craftItems[oreID][4][1]; timerID = 5; break; - case 502: // Double Axe - makeID = craftItems[oreID][4][2]; timerID = 5; break; - case 503: // Executioners Axe - makeID = craftItems[oreID][4][3]; timerID = 5; break; - case 504: // Large Battle Axe - makeID = craftItems[oreID][4][4]; timerID = 5; break; - case 505: // Two Handed Axe - makeID = craftItems[oreID][4][5]; timerID = 5; break; - case 506: // War Axe - makeID = craftItems[oreID][4][6]; timerID = 5; break; - // [600-699] - case 600: // Bardiche - makeID = craftItems[oreID][5][0]; timerID = 6; break; - case 601: // Halberd - makeID = craftItems[oreID][5][1]; timerID = 6; break; - case 602: // Short Spear - makeID = craftItems[oreID][5][2]; timerID = 6; break; - case 603: // Spear - makeID = craftItems[oreID][5][3]; timerID = 6; break; - case 604: // War Fork - makeID = craftItems[oreID][5][4]; timerID = 6; break; - // [700-799] - case 700: // Hammer Pick - makeID = craftItems[oreID][6][0]; timerID = 7; break; - case 701: // Mace - makeID = craftItems[oreID][6][1]; timerID = 7; break; - case 702: // Maul - makeID = craftItems[oreID][6][2]; timerID = 7; break; - case 703: // War Mace - makeID = craftItems[oreID][6][3]; timerID = 7; break; - case 704: // War Hammer - makeID = craftItems[oreID][6][4]; timerID = 7; break; - // Select Ore Type - case 1000: // Iron - newOreID = (( newOreID == -1 ) ? 0 : newOreID ); - newResourceHue = 0; // Update manually if color changes in skills.dfn! - case 1001: // Dull Copper - if( pButton == 1001 && pUser.skills[7] < 650 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x0973 : newResourceHue ); // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 1 : newOreID ); - case 1002: // Shadow Iron - if( pButton == 1002 && pUser.skills[7] < 700 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x0966 : newResourceHue ); // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 2 : newOreID ); - case 1003: // Copper - if( pButton == 1003 && pUser.skills[7] < 750 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x07dd : newResourceHue ); // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 3 : newOreID ); - case 1004: // Bronze - if( pButton == 1004 && pUser.skills[7] < 800 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x06d6 : newResourceHue ); // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 4 : newOreID ); - case 1005: // Gold - if( pButton == 1005 && pUser.skills[7] < 850 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x08a5 : newResourceHue ); // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 5 : newOreID ); - case 1006: // Agapite - if( pButton == 1006 && pUser.skills[7] < 900 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x0979 : newResourceHue );; // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 6 : newOreID ); - case 1007: // Verite - if( pButton == 1007 && pUser.skills[7] < 950 ) - { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x089f : newResourceHue );; // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 7 : newOreID ); - case 1008: // Valorite - if( pButton == 1008 && pUser.skills[7] < 990 ) + var detailButtonID = pButton - 2000; + var entry = BlacksmithMap[detailButtonID]; + if( entry ) + { + // For details we just pass the iron version (ore index 0) to 4026 + var ironMakeID = entry.oreMake[0] || 0; + if( ironMakeID > 0 ) { - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true); - pUser.SetTempTag( "prevActionResult", "FAILED" ); - break; - } - newResourceHue = (( newResourceHue == - 1 ) ? 0x08ab : newResourceHue );; // Update manually if color changes in skills.dfn! - newOreID = (( newOreID == -1 ) ? 8 : newOreID ); + // Masonry uses Carpentry skill + pUser.SetTempTag( "Skill", entry.skill | 0 ); - // Run common code for this group of buttons - pSock.CloseGump( gumpID, 0 ); - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "prevActionResult", null ); - pUser.SetTempTag( "ORE", newOreID ); - pUser.SetTempTag( "resourceHue", newResourceHue ); - Page8( pSock, pUser ); - break; - // Show Item Details - case 2100: // Ringmail Gloves - itemDetailsID = 7; break; - case 2101: // Ringmail Legs - itemDetailsID = 9; break; - case 2102: // Ringmail Arms - itemDetailsID = 8; break; - case 2103: // Ringmail Chest - itemDetailsID = 10; break; - case 2104: // Chain Coif - itemDetailsID = 11; break; - case 2105: // Chain Legs - itemDetailsID = 12; break; - case 2106: // Chain Chest - itemDetailsID = 13; break; - case 2107: // Plate Arms - itemDetailsID = 16; break; - case 2108: // Plate Gloves - itemDetailsID = 15; break; - case 2109: // Plate Gorget - itemDetailsID = 14; break; - case 2110: // Plate Legs - itemDetailsID = 17; break; - case 2111: // Plate Chest - itemDetailsID = 18; break; - case 2112: // Female Plate Chest - itemDetailsID = 19; break; - // [200-299] - case 2200: // Bascinet - itemDetailsID = 46; break; - case 2201: // Close Helm - itemDetailsID = 48; break; - case 2202: //Helmet - itemDetailsID = 45; break; - case 2203: // Norse Helm - itemDetailsID = 47; break; - case 2204: // Plate Helm - itemDetailsID = 49; break; - // [300-399] - case 2300: // Buckler - itemDetailsID = 1; break; - case 2301: // Bronze Shield - itemDetailsID = 2; break; - case 2302: // Heater Shield - itemDetailsID = 6; break; - case 2303: // Metal Shield - itemDetailsID = 3; break; - case 2304: // MetalKiteShield - itemDetailsID = 5; break; - case 2305: // tear kite shield - itemDetailsID = 4; break; - // [400-499] - case 2400: // Broadsword - itemDetailsID = 25; break; - case 2401: // Cutlass - itemDetailsID = 21; break; - case 2402: // Dagger - itemDetailsID = 20; break; - case 2403: // Katana - itemDetailsID = 22; break; - case 2404: // Kryss - itemDetailsID = 23; break; - case 2405: // Longsword - itemDetailsID = 26; break; - case 2406: // Scimitar - itemDetailsID = 24; break; - case 2407: // Viking Sword - itemDetailsID = 27; break; - // [500-599] - case 2500: // Axe - itemDetailsID = 29; break; - case 2501: // Battle Axe - itemDetailsID = 28; break; - case 2502: // Double Axe - itemDetailsID = 32; break; - case 2503: // Executioners Axe - itemDetailsID = 30; break; - case 2504: // Large Battle Axe - itemDetailsID = 33; break; - case 2505: // Two Handed Axe - itemDetailsID = 31; break; - case 2506: // War Axe - itemDetailsID = 34; break; - // [600-699] - case 2600: // Bardiche - itemDetailsID = 38; break; - case 2601: // Halberd - itemDetailsID = 39; break; - case 2602: // Short Spear - itemDetailsID = 35; break; - case 2603: // Spear - itemDetailsID = 36; break; - case 2604: // WarFork - itemDetailsID = 37; break; - // [700-799] - case 2700: // Hammer Pick - itemDetailsID = 44; break; - case 2701: // Mace - itemDetailsID = 40; break; - case 2702: // Maul - itemDetailsID = 41; break; - case 2703: // War Mace - itemDetailsID = 42; break; - case 2704: // War Hammer - itemDetailsID = 43; break; - default: - break; + if( entry.harvest && entry.harvest.length > 0 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + + if( entry.harvest2 && entry.harvest2.length > 0 ) + pUser.SetTempTag( "Harvest2", entry.harvest2[0] ); + + if( entry.harvest3 && entry.harvest3.length > 0 ) + pUser.SetTempTag( "Harvest3", entry.harvest3[0] ); + + if( entry.harvest4 && entry.harvest4.length > 0 ) + pUser.SetTempTag( "Harvest4", entry.harvest4[0] ); + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + pUser.SetTempTag( "ITEMDETAILS", ironMakeID ); + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + } + return; } - if( makeID != 0 ) + // If this is a craft button in our map: + if( BlacksmithMap[pButton] != undefined ) { - if( anvil > 0 ) + var entry2 = BlacksmithMap[pButton]; + var oreID = pUser.GetTempTag( "ORE" ); + var resourceHue = pUser.GetTempTag( "resourceHue" ); + + // Ensure oreID within range + if( oreID < 0 || oreID >= craftItems.length ) + oreID = 0; + + // Era / recipe gating + if( !eraOK( entry2 )) { - // crafting_complete.js for applying special bonuses for exceptional equipment/from runic hammers - pUser.AddScriptTrigger( 4033 ); - MakeItem( pSock, pUser, makeID, resourceHue ); - var toolUseLimit = GetServerSetting( "ToolUseLimit" ); - var toolUseBreak = GetServerSetting( "ToolUseBreak" ); - - // Check if player had runic hammer equipped while crafting - var runicHammer = pUser.FindItemLayer( 0x01 ); // Right Hand - if( ValidateObject( runicHammer ) && runicHammer.GetTag( "runicHammer" ) && runicHammer.usesLeft > 0 ) - { - // Store some temp tags on player to get info on runic hammer used in crafting_complete.js - pUser.SetTempTag( "usedRunicHammer", true ); - pUser.SetTempTag( "runicHammerType", runicHammer.color ); + pSock.SysMessage( "That item is not available in this era." ); + return; + } - // Wear and tear for equipped runic hammer, even if another tool was used to craft - if( toolUseLimit && runicHammer != bItem ) + if( entry2.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, entry2.recipeID )) + { + pSock.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + // Check for nearby anvil + var anvil = AreaItemFunction( "FindNearbyAnvils", pUser, 2, pSock ); + if( anvil == 0 ) + { + pUser.SetTempTag( "prevActionResult", "NOANVIL" ); + pUser.StartTimer( gumpDelay, entry2.timerID, true ); + return; + } + + // No colored weapons if disabled and using non-iron ingots + if( !allowColouredWeapons && resourceHue > 0 && entry2.page > 3 ) + { + pSock.SysMessage( "You cannot use colored ingots for weapons on this shard." ); + return; + } + + var makeID = entry2.oreMake[oreID]; + if( !makeID || makeID == 0 ) + { + // Fallback to iron version if for some reason we did not get a specific ore entry + makeID = entry2.oreMake[0]; + } + + if( !makeID || makeID == 0 ) + { + pSock.SysMessage( "That item is not properly configured." ); + return; + } + + // Runic hammer bonus logic (unchanged from your original) + pUser.AddScriptTrigger( 4033 ); + + MakeItem( pSock, pUser, makeID, resourceHue ); + + // Tool wear + var toolUseLimit = GetServerSetting( "ToolUseLimit" ); + var toolUseBreak = GetServerSetting( "ToolUseBreak" ); + + var runicHammer = pUser.FindItemLayer( 0x01 ); // Right Hand + if( ValidateObject( runicHammer ) && runicHammer.GetTag( "runicHammer" ) && runicHammer.usesLeft > 0 ) + { + pUser.SetTempTag( "usedRunicHammer", true ); + pUser.SetTempTag( "runicHammerType", runicHammer.color ); + + if( toolUseLimit && runicHammer != bItem ) + { + runicHammer.usesLeft -= 1; + if( runicHammer.usesLeft == 0 && toolUseBreak ) { - runicHammer.usesLeft -= 1; - if( runicHammer.usesLeft == 0 && toolUseBreak ) - { - runicHammer.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking - } + runicHammer.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); } } + } - if( toolUseLimit ) + if( toolUseLimit ) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && toolUseBreak ) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && toolUseBreak ) - { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking - } + bItem.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); } } - pUser.StartTimer( gumpDelay, timerID, true ); + + // Track in last ten list for blacksmith + AddToLastTenBlacksmith( pUser, pButton ); + + // Reopen page after delay + pUser.StartTimer( gumpDelay, entry2.timerID, true ); + return; } - else if( itemDetailsID != 0 ) + + // Any other buttons fall through and do nothing +} + +function AddToLastTenBlacksmith( pUser, buttonID ) +{ + var raw = pUser.GetTempTag( "LastTenBlacksmith" ) || ""; + var list = raw.split( "," ); + + // Remove if already in list + for( var i = 0; i < list.length; i++ ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + if( parseInt( list[i] ) == buttonID ) + { + list.splice( i, 1 ); + break; + } } + + var newList = [buttonID]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenBlacksmith", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; } + +function eraOK( entry ) +{ + // Optional per-entry gates. Strings like "lbr","aos","ml","sa","hs","tol". + // If not present, the entry is valid for all eras. + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 3678b6ea4..8b6994cb5 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -76,7 +76,7 @@ const allowColouredBuildings = false; // Set to true if you want coloured stone // | MakeItem when the player crafts that item. The same index positions | // | on each page line up with the matching entries in myPage. | // o--------------------------------------------------------------------------o -// | MasonryMap | +// | MasonryMap | // o--------------------------------------------------------------------------o // | MasonryMap is built automatically from myPage and craftItems. | // | | @@ -1208,19 +1208,19 @@ function onGumpPress( pSock, pButton, gumpData ) if( graniteMakeID > 0 ) { // Masonry uses Carpentry skill - pUser.SetTempTag("Skill", entry.skill | 0); + pUser.SetTempTag( "Skill", entry.skill | 0 ); if( entry.harvest && entry.harvest.length > 0 ) - pUser.SetTempTag("Harvest", entry.harvest[0]); + pUser.SetTempTag( "Harvest", entry.harvest[0] ); if( entry.harvest2 && entry.harvest2.length > 0 ) - pUser.SetTempTag("Harvest2", entry.harvest2[0]); + pUser.SetTempTag( "Harvest2", entry.harvest2[0] ); if( entry.harvest3 && entry.harvest3.length > 0 ) - pUser.SetTempTag("Harvest3", entry.harvest3[0]); + pUser.SetTempTag( "Harvest3", entry.harvest3[0] ); if( entry.harvest4 && entry.harvest4.length > 0 ) - pUser.SetTempTag("Harvest4", entry.harvest4[0]); + pUser.SetTempTag( "Harvest4", entry.harvest4[0] ); if( entry.recipeID && entry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", entry.recipeID ); From 4d9a35f5198591d16e5bd5a1e03b9cf7f8dfecbc Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:37:17 -0600 Subject: [PATCH 23/43] Update blacksmithing.js --- data/js/skill/craft/blacksmithing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index fbb0b4444..f6c09f0d7 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -360,7 +360,7 @@ const BlacksmithMap = {}; // minEra: undefined, // maxEra: undefined skill: 7, // blacksmithing skill ID - harvest: [10291], // iron dict + harvest: [10015], // ingots dict harvest2: [], // optional second resource harvest3: [], // optional second resource harvest4: [] // optional second resource From 2b7dcefe2edfdac024f05964b93541034b4e9627 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:02:45 -0600 Subject: [PATCH 24/43] Update alchemy.js --- data/js/skill/craft/alchemy.js | 240 --------------------------------- 1 file changed, 240 deletions(-) diff --git a/data/js/skill/craft/alchemy.js b/data/js/skill/craft/alchemy.js index 5a954c492..8b1378917 100644 --- a/data/js/skill/craft/alchemy.js +++ b/data/js/skill/craft/alchemy.js @@ -1,241 +1 @@ -/// -// @ts-check -const textHue = 0x480; // Color of the text. -const scriptID = 4028; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; -////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// - -const myPage = [ - // Page 1 - Healing and Curative - [10908, 10909, 10910, 10911, 10912, 10913, 10914, 10915], - - // Page 2 - Enhancement - [10916, 10917, 10918, 10919, 10920], - - // Page 3 - Toxic - [10921, 10922, 10923, 10924], - - // Page 4 - Explosives - [10925, 10926, 10927] -]; - -function PageX( socket, pUser, pageNum ) -{ - // Pages 1 - 4 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for( var i = 0; i < myPage[pageNum - 1].length; i++ ) - { - var index = i % 10; - if( index == 0 ) - { - if( i > 0 ) - { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE - } - - myGump.AddPage(( i / 10 ) + 1 ); - - if( i > 0 ) - { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE - } - } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); - - myGump.AddText( 255, 60 + ( index * 20 ), textHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language )); - - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, ( 2000 + ( 100 * pageNum )) + i ); - } - myGump.Send( socket ); - myGump.Free(); -} - -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ -function onTimer( pUser, timerID ) -{ - if( !ValidateObject( pUser )) - return; - - var socket = pUser.socket; - - switch( timerID ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - TriggerEvent( scriptID, "PageX", socket, pUser, timerID ); - break; - default: - break; - } -} - -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) -{ - var pUser = pSock.currentChar; - - // Don't continue if character is invalid, or worse... dead! - if( !ValidateObject( pUser ) || pUser.dead ) - return; - - // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) - { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. - return; - } - - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var timerID = 0; - - if(( pButton >= 100 && pButton <= 402 ) || pButton == 5000 ) - { - if( pButton == 5000 ) - { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); - } - else - { - pUser.SetTempTag( "MAKELAST", pButton ); - } - } - - switch( pButton ) - { - case 0: - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break;// abort and do nothing - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - pSock.CloseGump( gumpID, 0 ); - TriggerEvent( scriptID, "PageX", pSock, pUser, pButton ); - break; - // Make Items - case 100: // Refresh - makeID = 305; timerID = 1; break; - case 101: // Greater Refresh - makeID = 306; timerID = 1; break; - case 102: // Lesser Heal - makeID = 298; timerID = 1; break; - case 103: // Heal - makeID = 299; timerID = 1; break; - case 104: // Greater Heal - makeID = 300; timerID = 1; break; - case 105: // Lesser Cure - makeID = 292; timerID = 1; break; - case 106: // Cure - makeID = 293; timerID = 1; break; - case 107: // Greater Cure - makeID = 294; timerID = 1; break; - case 200: // Agility - makeID = 290; timerID = 2; break; - case 201: // Greater Agility - makeID = 291; timerID = 2; break; - case 202: // Night Sight - makeID = 309; timerID = 2; break; - case 203: // Strength - makeID = 307; timerID = 2; break; - case 204: // Greater Strength - makeID = 308; timerID = 2; break; - case 300: // Lesser Poison - makeID = 301; timerID = 3; break; - case 301: // Poison - makeID = 302; timerID = 3; break; - case 302: // Greater Poison - makeID = 303; timerID = 3; break; - case 303: // Deadly Poison - makeID = 304; timerID = 3; break; - case 400: // Lesser Explosion - makeID = 295; timerID = 4; break; - case 401: // Explosion - makeID = 296; timerID = 4; break; - case 402: // Greater Explosion - makeID = 297; timerID = 4; break; - // Show Item Details - case 2100: // Item Details - Refresh - itemDetailsID = 305; break; - case 2101: // Item Details - Greater Refreshment - itemDetailsID = 306; break; - case 2102: // Item Details - Lesser Heal - itemDetailsID = 298; break; - case 2103: // Item Details - Heal - itemDetailsID = 299; break; - case 2104: // Item Details - Greater Heal - itemDetailsID = 300; break; - case 2105: // Item Details - Lesser Cure - itemDetailsID = 292; break; - case 2106: // Item Details - Cure - itemDetailsID = 293; break; - case 2107: // Item Details - Greater Cure - itemDetailsID = 294; break; - case 2200: // Item Details - Agility - itemDetailsID = 290; break; - case 2201: // Item Details - Greater Agility - itemDetailsID = 291; break; - case 2202: // Item Details - Night Sight - itemDetailsID = 309; break; - case 2203: // Item Details - Strength - itemDetailsID = 307; break; - case 2204: // Item Details - Greater Strength - itemDetailsID = 308; break; - case 2300: // Item Details - Lesser Poison - itemDetailsID = 301; break; - case 2301: // Item Details - Poison - itemDetailsID = 302; break; - case 2302: // Item Details - Greater Poison - itemDetailsID = 303; break; - case 2303: // Item Details - Deadly Poison - itemDetailsID = 304; break; - case 2400: // Item Details - Lesser Explosion - itemDetailsID = 295; break; - case 2401: // Item Details - Explosion - itemDetailsID = 296; break; - case 2402: // Item Details - Greater Explosion - itemDetailsID = 297; break; - default: - break; - } - - if( makeID != 0 ) - { - MakeItem( pSock, pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) - { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) - { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking - } - } - pUser.StartTimer( gumpDelay, timerID, true ); - } - else if( itemDetailsID != 0 ) - { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); - } -} From bb2ea6d0db2db9de0cab294c8325ae8439414202 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:26:41 -0600 Subject: [PATCH 25/43] update --- data/js/skill/craft/alchemy.js | 534 +++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) diff --git a/data/js/skill/craft/alchemy.js b/data/js/skill/craft/alchemy.js index 8b1378917..b8b256902 100644 --- a/data/js/skill/craft/alchemy.js +++ b/data/js/skill/craft/alchemy.js @@ -1 +1,535 @@ +/// +// @ts-check +const textHue = 0x480; // Color of the text. +const alchemyID = 4028; // Script ID for this alchemy gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Generic item details gump +const craftGumpID = 4027; // Shared crafting menu frame +const itemsPerPage = 10; // Items per subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const alchemySkillID = 0; // Skill ID: Alchemy +// o--------------------------------------------------------------------------o +// | AlchemyMap | +// o--------------------------------------------------------------------------o +// | Keyed by makeID (create entry ID). | +// | Each entry: | +// | dictID - dictionary entry for row text | +// | page - main category page (1..4) | +// | timerID - which page timer should reopen | +// | skill - skill used (default: alchemySkillID) | +// | recipeID?, minEra?, maxEra?, harvest?[] can be added later | +// o--------------------------------------------------------------------------o +// If you want to add multi-reagent potions later +// (e.g. harvest: [ REAG_GARLIC, REAG_GINSENG ]), +// the same pattern will just work with no script changes. + +const AlchemyMap = { + // Page 1 - Curative / Refresh + 298: { dictID: 10910, page: 1, timerID: 1, harvest: [ 10022 ] }, // Lesser Heal + 299: { dictID: 10911, page: 1, timerID: 1, harvest: [ 10022 ] }, // Heal + 300: { dictID: 10912, page: 1, timerID: 1, harvest: [ 10022 ] }, // Greater Heal + 305: { dictID: 10908, page: 1, timerID: 1, harvest: [ 10025 ] }, // Refresh + 306: { dictID: 10909, page: 1, timerID: 1, harvest: [ 10025 ] }, // Total Refresh + 292: { dictID: 10913, page: 1, timerID: 1, harvest: [ 10020 ] }, // Lesser Cure + 293: { dictID: 10914, page: 1, timerID: 1, harvest: [ 10020 ] }, // Cure + 294: { dictID: 10915, page: 1, timerID: 1, harvest: [ 10020 ] }, // Greater Cure + + // Page 2 - Enhancement + 290: { dictID: 10916, page: 2, timerID: 2, harvest: [ 10019 ] }, // Agility + 291: { dictID: 10917, page: 2, timerID: 2, harvest: [ 10019 ] }, // Greater Agility + 295: { dictID: 10918, page: 2, timerID: 2, harvest: [ 10021 ] }, // Strength + 296: { dictID: 10919, page: 2, timerID: 2, harvest: [ 10021 ] }, // Greater Strength + 297: { dictID: 10920, page: 2, timerID: 2, harvest: [ 10021 ] }, // Night Sight + + // Page 3 - Poison + 301: { dictID: 10921, page: 3, timerID: 3, harvest: [ 10024 ] }, // Lesser Poison + 302: { dictID: 10922, page: 3, timerID: 3, harvest: [ 10024 ] }, // Poison + 303: { dictID: 10923, page: 3, timerID: 3, harvest: [ 10024 ] }, // Greater Poison + 304: { dictID: 10924, page: 3, timerID: 3, harvest: [ 10024 ] }, // Deadly Poison + + // Page 4 - Explosive + 307: { dictID: 10925, page: 4, timerID: 4, harvest: [ 10026 ] }, // Explosion + 308: { dictID: 10926, page: 4, timerID: 4, harvest: [ 10026 ] }, // Greater Explosion + 309: { dictID: 10927, page: 4, timerID: 4, harvest: [ 10023 ] } // Conflagration (or w/e 10927 is) +}; + +// Fill in defaults (skill, etc) +(function initAlchemyMap() +{ + for( var key in AlchemyMap ) + { + if( !AlchemyMap.hasOwnProperty( key )) + continue; + + var entry = AlchemyMap[key]; + + if( entry.skill === undefined ) + entry.skill = alchemySkillID; + + // If you ever want to drive item detail resources here: + // entry.harvest = [ , , ... ]; + // For now, the detail gump will infer resources directly from DFN create entries. + } +})(); + +// o--------------------------------------------------------------------------o +// | PageX() - build a page of alchemy items | +// o--------------------------------------------------------------------------o +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ +function PageX( socket, pUser, pageNum ) +{ + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // Special Last Ten page + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenAlchemy" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); // makeID itself + } + } + else + { + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in AlchemyMap ) + { + if( !AlchemyMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = AlchemyMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) + { + var ea = AlchemyMap[a]; + var eb = AlchemyMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering (no recipes yet, but keep hook) + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = AlchemyMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe ))) + pageItems.push( id ); + } + + // Fallback: if no items on this page and it's not page 1, go to page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; + + makeIDs = []; + for( var key2 in AlchemyMap ) + { + if( !AlchemyMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = AlchemyMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; + + makeIDs.push( mid2 ); + } + + makeIDs.sort( function( a, b ) + { + var ea2 = AlchemyMap[a]; + var eb2 = AlchemyMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) + { + var id2 = makeIDs[m]; + var data4 = AlchemyMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 ))) + pageItems.push( id2 ); + } + } + } + + // Subpage handling + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( totalSubPages < 1 ) + totalSubPages = 1; + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var alchGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", alchGump, socket ); + alchGump.AddPage( 1 ); + + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // use makeID directly as buttonID + + var data5 = AlchemyMap[makeID]; + + if( !data5 ) + { + entryText = "[Missing MakeID: " + makeID + "]"; + } + else + { + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; + } + } + + // Craft button uses makeID + alchGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + alchGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); + + // Detail button: 20000 + makeID (same pattern as glassblowing) + alchGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); + } + + // Prev subpage + if( subPage > 1 ) + { + alchGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + alchGump.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + + // Next subpage + if( subPage < totalSubPages ) + { + alchGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + alchGump.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + alchGump.Send( socket ); + alchGump.Free(); +} + +// o--------------------------------------------------------------------------o +// | onTimer - reopen last page after crafting | +// o--------------------------------------------------------------------------o +/** @type { ( pUser: Character, timerID: number ) => void } */ +function onTimer( pUser, timerID ) +{ + if( !ValidateObject( pUser )) + return; + + var pSocket = pUser.socket; + if( pSocket == null ) + return; + + if( timerID >= 1 && timerID <= 8 ) + { + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); + } +} + +// o--------------------------------------------------------------------------o +// | onGumpPress - navigation, Make Last, craft & details | +// o--------------------------------------------------------------------------o +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) +{ + if( socket == null ) + return; + + var pUser = socket.currentChar; + if( !ValidateObject( pUser ) || pUser.dead ) + return; + + var tool = socket.tempObj; + if( !ValidateObject( tool ) || !pUser.InRange( tool, 3 )) + { + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. + return; + } + + if( tool.movable == 3 ) + { + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // That is locked down and cannot be used. + return; + } + + var packOwner = GetPackOwner( tool, 0 ); + if( ValidateObject( packOwner )) + { + if( packOwner.serial != pUser.serial ) + { + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That is not in your pack. + return; + } + } + else + { + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // You must have that item in your pack to use it. + return; + } + + var gumpID = alchemyID + 0xffff; + + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) + { + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; + } + + if( pButton >= 9001 && pButton < 10000 ) + { + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; + } + + // Page tabs (Alchemy has 4 categories, but using <=8 is harmless) + if( pButton >= 1 && pButton <= 8 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; + } + + // Last Ten + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Alchemy", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); + return; + } + + var makeID = 0; + var timerID = 0; + + // Make Last + if( pButton == 5000 ) + { + var last = pUser.GetTempTag( "MakeLast_Alchemy" ); + if( last ) + pButton = last; + else + return; + } + + // Craft buttons use makeID directly + if( AlchemyMap[pButton] != undefined ) + { + makeID = pButton; + var data = AlchemyMap[makeID]; + timerID = data.timerID || 1; + + if( !eraOK( data )) + { + socket.SysMessage( "That item is not available in this era." ); + return; + } + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + pUser.SetTempTag( "MakeLast_Alchemy", makeID ); + + MakeItem( socket, pUser, makeID ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + tool.usesLeft -= 1; + if( tool.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + { + tool.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // Your tool wears out. + } + } + + pUser.StartTimer( gumpDelay, timerID, alchemyID ); + return; + } + + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) + { + var detailMakeID = pButton - 20000; + var entry = AlchemyMap[detailMakeID]; + + if( entry ) + { + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || alchemySkillID ); + + // Clear old harvest tags to avoid cross-contamination + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // If you later add entry.harvest = [dictID1, dictID2,...], you can push them here + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; + } +} + +// o--------------------------------------------------------------------------o +// | Last Ten handling | +// o--------------------------------------------------------------------------o +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenAlchemy" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenAlchemy", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file From b52ae204848dfc5c8d6c59e81a4c68be66ff05f9 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:15:55 -0600 Subject: [PATCH 26/43] update --- data/js/skill/craft/alchemy.js | 2 +- data/js/skill/craft/carpentry.js | 934 +++++++++++++++---------------- 2 files changed, 465 insertions(+), 471 deletions(-) diff --git a/data/js/skill/craft/alchemy.js b/data/js/skill/craft/alchemy.js index b8b256902..ff905dfe4 100644 --- a/data/js/skill/craft/alchemy.js +++ b/data/js/skill/craft/alchemy.js @@ -22,7 +22,7 @@ const alchemySkillID = 0; // Skill ID: Alchemy // | recipeID?, minEra?, maxEra?, harvest?[] can be added later | // o--------------------------------------------------------------------------o // If you want to add multi-reagent potions later -// (e.g. harvest: [ REAG_GARLIC, REAG_GINSENG ]), +// (e.g. harvest: [ garlic_dictNumber, ginseng_dictNumber ]), // the same pattern will just work with no script changes. const AlchemyMap = { diff --git a/data/js/skill/craft/carpentry.js b/data/js/skill/craft/carpentry.js index abf9fb725..5dcb89318 100644 --- a/data/js/skill/craft/carpentry.js +++ b/data/js/skill/craft/carpentry.js @@ -1,18 +1,20 @@ /// // @ts-check -const textHue = 0x480; // Color of the text. -const scriptID = 4025; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reappear after crafting. -const repairDelay = 200; // Timer for the gump to reappear after repairing an item -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; - -////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// +const textHue = 0x480; // Color of the text. +const carpentryID = 4025; // Use this to tell the gump what script to close. +const gumpDelay = 2000; // Timer for the gump to reappear after crafting. +const repairDelay = 200; // Timer for the gump to reappear after repairing an item. +const itemDetailsScriptID = 4026; // Generic item detail gump +const craftGumpID = 4027; // Crafting frame gump +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); +const carpentrySkillID = 11; // Carpentry skill ID +const harvestDict = 10014; // Dictionary entry for "wood" (boards/logs) + +//====================================================================================== +// Data tables +//====================================================================================== const myPage = [ @@ -47,39 +49,264 @@ const myPage = [ [10683, 10684, 10685, 10686] ]; +const craftItems = [ + // Page 1 (button 100..110) + [ 73, 74, 89, 90, 91, 92, 76, 77, 78, 79, 72 ], + + // Page 2 (200..212) + [ 50, 51, 52, 53, 57, 58, 54, 55, 56, 59, 60, 61, 62 ], + + // Page 3 (300..308) + [ 63, 64, 65, 67, 68, 69, 70, 71, 66 ], + + // Page 4 (400..404) + [ 80, 81, 82, 123, 124 ], + + // Page 5 (500) + [ 75 ], + + // Page 6 (600..605) + [ 83, 84, 85, 86, 87, 88 ], + + // Page 7 (700..710) + [ 93, 93, 94, 93, 96, 95, 97, 98, 99, 100, 101 ], + + // Page 8 (800..812) + [ 115, 116, 107, 108, 109, 110, 117, 118, 119, 120, 121, 122 ], + + // Page 9 (900..904) + [ 102, 103, 104, 105, 106 ], + + // Page 10 (1000..1003) + [ 111, 112, 113, 114 ] +]; + +// Map: buttonID carpentry entry +// buttonID: 100..110, 200..212, ... 1000..1003 +// CarpentryMap[buttonID] = { +// dictID: number, +// page: number, +// timerID: number, +// makeID: number, +// customName?: string, +// recipeID?: number, +// minEra?: string, +// maxEra?: string, +// skill: number, +// harvest: number[] +// }; +const CarpentryMap = {}; + +(function initCarpentryMap() +{ + for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) + { + var dictList = myPage[pageIdx]; + var makeList = craftItems[pageIdx]; + + for( var i = 0; i < dictList.length && i < makeList.length; i++ ) + { + // Button layout: + // page 1 => 100..110 + // page 2 => 200..212 + // page 3 => 300..308 + // ... + var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; + var dictID = dictList[i]; + var makeID = makeList[i]; + + CarpentryMap[buttonID] = { + dictID: dictID, + page: pageIdx + 1, + timerID: pageIdx + 1, + makeID: makeID, + // recipeID: undefined, + // minEra: undefined, + // maxEra: undefined + skill: carpentrySkillID, + harvest: [ harvestDict ] // default: wood + }; + } + } + + // If you need per-entry overrides in future (recipes, extra resources, era gating), + // you can do: + // CarpentryMap[704].harvest = [ harvestDict, 11402 ]; // wood + cloth + // CarpentryMap[709].minEra = "ml"; +})(); + +CarpentryMap[109].harvest = [ harvestDict, 10016 ]; // Fishing Pole wood + cloth +CarpentryMap[308].harvest = [ 10611, 10612, 11860 ]; // open keg Barrel Staves Barrel Hoops Barrel Lid +CarpentryMap[600].harvest = [ harvestDict, 10016 ]; // lap harp wood + cloth +CarpentryMap[601].harvest = [ harvestDict, 10016 ]; // Standing Harp wood + cloth +CarpentryMap[602].harvest = [ harvestDict, 10016 ]; // Drum wood + cloth +CarpentryMap[603].harvest = [ harvestDict, 10016 ]; // Lute wood + cloth +CarpentryMap[604].harvest = [ harvestDict, 10016 ]; // Tambourine wood + cloth +CarpentryMap[605].harvest = [ harvestDict, 10016 ]; // Tambourine wood + cloth +CarpentryMap[700].harvest = [ harvestDict, 10016 ]; // Small Bed (S) wood + cloth +CarpentryMap[701].harvest = [ harvestDict, 10016 ]; // Small Bed (E) wood + cloth +CarpentryMap[702].harvest = [ harvestDict, 10016 ]; // Large Bed (S) wood + cloth +CarpentryMap[703].harvest = [ harvestDict, 10016 ]; // Large Bed (E) wood + cloth +CarpentryMap[709].harvest = [ harvestDict, 10015 ]; // Pentagram wood + ingots +CarpentryMap[710].harvest = [ harvestDict, 10015 ]; // Abbatoir wood + ingots + + +CarpentryMap[800].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth +CarpentryMap[801].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth +CarpentryMap[802].harvest = [ harvestDict, 10016 ]; // Spin Wheel (E) wood + cloth +CarpentryMap[803].harvest = [ harvestDict, 10016 ]; // Spin Wheel (S) wood + cloth +CarpentryMap[804].harvest = [ harvestDict, 10016 ]; // Loom (E) wood + cloth +CarpentryMap[805].harvest = [ harvestDict, 10016 ]; // Loom (S) wood + cloth +CarpentryMap[806].harvest = [ harvestDict, 10015 ]; // Stone Oven (E) wood + ingots +CarpentryMap[807].harvest = [ harvestDict, 10015 ]; // Stone Oven (S) wood + ingots +CarpentryMap[808].harvest = [ harvestDict, 10015 ]; // Flour Mill (E) wood + ingots +CarpentryMap[809].harvest = [ harvestDict, 10015 ]; // Flour Mill (S) wood + ingots + +CarpentryMap[900].harvest = [ harvestDict, 10015 ]; // Small Forge wood + ingots +CarpentryMap[901].harvest = [ harvestDict, 10015 ]; // Large Forge (E) wood + ingots +CarpentryMap[902].harvest = [ harvestDict, 10015 ]; // Large Forge (S) wood + ingots +CarpentryMap[903].harvest = [ harvestDict, 10015 ]; // Anvil (E) wood + ingots +CarpentryMap[904].harvest = [ harvestDict, 10015 ]; // Anvil (S) wood + ingots + +CarpentryMap[1000].harvest = [ harvestDict, 10016 ]; // Dummy (E) wood + cloth +CarpentryMap[1001].harvest = [ harvestDict, 10016 ]; // Dummy (S) wood + cloth +CarpentryMap[1002].harvest = [ harvestDict, 10016 ]; // Pickpocket (E) wood + cloth +CarpentryMap[1003].harvest = [ harvestDict, 10016 ]; // Pickpocket (S) wood + cloth + + function PageX( socket, pUser, pageNum ) { - // Pages 1 - 10 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems = []; + + if( pageNum == 999 ) { - var index = i % 10; - if( index == 0 ) + var lastRaw = pUser.GetTempTag( "LastTenCarpentry" ) || ""; + var split = lastRaw.split( "," ); + for( var i = 0; i < split.length; i++ ) { - if( i > 0 ) - { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE - } + var val = parseInt( split[i] ); + if( !isNaN( val ) && CarpentryMap[val] ) + pageItems.push( val ); + } + } + else + { + for( var buttonIDStr in CarpentryMap ) + { + if( !CarpentryMap.hasOwnProperty( buttonIDStr )) + continue; - myGump.AddPage(( i / 10) + 1 ); + var buttonID = parseInt( buttonIDStr ); + var data = CarpentryMap[buttonID]; - if( i > 0 ) + if( data.page == pageNum && eraOK( data )) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + var needsRecipe = data.recipeID; + var showAll = displayUnlearnedRecipes; + + if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) + { + pageItems.push( buttonID ); + } } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); - myGump.AddText( 255, 60 + ( index * 20 ), textHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language )); + pageItems.sort(function(a, b){ return a - b; }); + } - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, ( 2000 + ( 100 * pageNum )) + i ); + if( pageItems.length == 0 ) + { + var emptyGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", emptyGump, socket ); + emptyGump.AddPage( 1 ); + emptyGump.AddText( 220, 60, textHue, "No items available on this page." ); + emptyGump.Send( socket ); + emptyGump.Free(); + return; } - myGump.Send( socket ); - myGump.Free(); + + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( totalSubPages < 1 ) + totalSubPages = 1; + + if( subPage < 1 ) + subPage = 1; + + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var carpGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", carpGump, socket ); + carpGump.AddPage( 1 ); + + var drawIndex = 0; + + for( var i = startIndex; i < endIndex; i++ ) + { + var buttonID = pageItems[i]; + var data = CarpentryMap[buttonID]; + + var entryText = ""; + if( data.customName ) + { + entryText = data.customName; + } + else if( data.dictID ) + { + entryText = GetDictionaryEntry( data.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + buttonID + "]"; + } + + carpGump.AddButton( 220, 60 + ( drawIndex * 20 ), 4005, 4007, 1, 0, buttonID ); + carpGump.AddText( 255, 60 + ( drawIndex * 20 ), textHue, entryText ); + + carpGump.AddButton( 480, 60 + ( drawIndex * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); + + drawIndex++; + } + + // Prev subpage + if( subPage > 1 ) + { + carpGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + carpGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + + // Next subpage + if( subPage < totalSubPages ) + { + carpGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + carpGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + carpGump.Send( socket ); + carpGump.Free(); } function RepairTarget( pSock ) @@ -97,8 +324,8 @@ function onCallback2( pSock, ourObj ) if( !ValidateObject( mChar ) || mChar.dead ) return; - var bItem = pSock.tempObj; - var gumpID = scriptID + 0xffff; + var bItem = pSock.tempObj; + var gumpID = carpentryID + 0xffff; pSock.tempObj = null; if( ValidateObject( mChar ) && mChar.isChar && ValidateObject( bItem ) && bItem.isItem ) @@ -116,102 +343,64 @@ function onCallback2( pSock, ourObj ) } var itemDurabilityLossEnabled = GetServerSetting( "ItemRepairDurabilityLoss" ); - var repairID = ourObj.id; var ownerObj = GetPackOwner( ourObj, 0 ); + if( ownerObj && mChar.serial == ownerObj.serial ) { - var maxHitpoints = ourObj.maxhp; + var maxHitpoints = ourObj.maxhp; var currentHitpoints = ourObj.health; + if( currentHitpoints < maxHitpoints ) { - // Get base repair difficulty based on amount of HP missing and max hitpoints - var deltaHP = maxHitpoints - currentHitpoints; + var deltaHP = maxHitpoints - currentHitpoints; var repairDifficulty = (( deltaHP / maxHitpoints ) * 1000 ); - var minDifficulty = repairDifficulty - 250; - var skillBonus = 0; - var repairSkill = mChar.skills.carpentry; + var minDifficulty = repairDifficulty - 250; + var skillBonus = 0; + var repairSkill = mChar.skills.carpentry; + if( minDifficulty < 0 ) { - // If minDifficulty is negative, add the negative value as a bonus to player's skill - skillBonus = minDifficulty * -1; + skillBonus = minDifficulty * -1; minDifficulty = 0; } else if( minDifficulty > repairSkill ) { - // Player skill below minimum repair difficulty, Too difficult to make the attempt! pSock.tempObj = bItem; pSock.CloseGump( gumpID, 0 ); mChar.SetTempTag( "prevActionResult", "CANTREPAIR" ); mChar.StartTimer( repairDelay, 1, true ); return; } + var maxDifficulty = Math.min( repairDifficulty + 250, mChar.skillCaps.carpentry ); - // Allow repair if random number between min and base difficulty is under player's skill if( RandomNumber( minDifficulty, 1000 ) < ( Math.max( repairSkill + skillBonus, 999 ))) { - // Give player a chance every now and then to gain skill from repairing if( RandomNumber( 1, 5 ) == 1 ) - { - // Run a skill-check, which might trigger a skill-gain if player passes - mChar.CheckSkill( 11, minDifficulty, maxDifficulty ); // Skill 11 = carpentry - } + mChar.CheckSkill( 11, minDifficulty, maxDifficulty ); // carpentry - // Reduce object's max durability by 1 if( itemDurabilityLossEnabled ) - { ourObj.maxhp -= 1; - } - // Repair item here ourObj.health = ourObj.maxhp; pSock.SoundEffect( 0x023D, true ); - // Reopen gump after a short delay pSock.CloseGump( gumpID, 0 ); mChar.SetTempTag( "prevActionResult", "REPAIRSUCCESS" ); mChar.StartTimer( repairDelay, 1, true ); - - // GM skill (100.0 skillpoints) - // Item with 51 HP max - // item with 2 hp left - 99.65% chance to repair - // item with 25 hp left - 99.86% chance to repair - // item with 40 hp left - 99.9% chance to repair - - // Expert Smith (71.5 skill points) - // Item with 51 HP max - // item with 2 hp left - 1.45% chance to repair - // item with 25 hp left - 61.49% chance to repair - // item with 40 hp left - 74.9% chance to repair - // item with 48 hp left - 90.6% chance to repair - - // Apprentice Smith (51.5 skill points) - // Item with 51 HP max - // item with 2 hp left - 0% chance to repair - // item with 25 hp left - 34.5% chance to repair - // item with 40 hp left - 54.9% chance to repair - // item with 48 hp left - 70.6% chance to repair } else { - // Failed to repair item - decrease item health! - if( repairSkill >= 1000 ) // GM Smith - { + if( repairSkill >= 1000 ) ourObj.health -= 1; - } - else if( repairSkill >= 715 ) // Expert Smith - { + else if( repairSkill >= 715 ) ourObj.health -= 2; - } - else // Below Expert Smith - { + else ourObj.health -= 3; - } if( ourObj.health <= 0 ) { - // Item has been destroyed! - pSock.SysMessage( GetDictionaryEntry( 311, pSock.language ).replace(/%s/gi, ourObj.name )); // Your %s has been destroyed. + pSock.SysMessage( GetDictionaryEntry( 311, pSock.language ).replace(/%s/gi, ourObj.name )); // destroyed ourObj.Delete(); } @@ -246,436 +435,241 @@ function onTimer( pUser, timerID ) return; var socket = pUser.socket; + if( socket == null ) + return; - switch ( timerID ) + if( timerID >= 1 && timerID <= 10 ) { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - case 9: // Page 9 - case 10: // Page 10 - PageX( socket, pUser, timerID ); - break; + PageX( socket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( socket, pUser, 999 ); } } /** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ function onGumpPress( pSock, pButton, gumpData ) { - var pUser = pSock.currentChar; + if( pSock == null ) + return; - // Don't continue if character is invalid, or worse... dead! + var pUser = pSock.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; - // Don't continue if player no longer has access to the crafting tool var bItem = pSock.tempObj; if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // too far return; } if( bItem.movable == 3 ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // locked down return; } var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + if( ValidateObject( iPackOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( iPackOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // someone else's pack return; } } else { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // must be in pack return; } - - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var timerID = 0; - - // If button pressed is one of the crafting buttons (or "make last") - if(( pButton >= 100 && pButton <= 1003 ) || pButton == 5000 ) + + var gumpID = carpentryID + 0xffff; + + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) { - if( pButton == 5000 ) - { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); - } - else - { - // Update Make Last entry - pUser.SetTempTag( "MAKELAST", pButton ); - } + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( pSock, pUser, pageNum ); + return; } - switch( pButton ) + if( pButton >= 9001 && pButton < 10000 ) { - case 0: - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break;// abort and do nothing - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - case 9: // Page 9 - case 10: // Page 10 - pSock.CloseGump( gumpID, 0 ); - TriggerEvent( scriptID, "PageX", pSock, pUser, pButton ); - break; - case 51: - RepairTarget( pSock ); - break; - case 100: // Barrel Staves - makeID = 73; timerID = 1; break; - case 101: // Barrel Lid - makeID = 74; timerID = 1; break; - case 102: // short music stand ( left ) - makeID = 89; timerID = 1; break; - case 103: // short music stand ( right ) - makeID = 90; timerID = 1; break; - case 104: // tall music stand ( left ) - makeID = 91; timerID = 1; break; - case 105: // tall music stand ( left ) - makeID = 92; timerID = 1; break; - case 106: // Easel ( S ) - makeID = 76; timerID = 1; break; - case 107: // Easel ( E ) - makeID = 77; timerID = 1; break; - case 108: // Easel ( N ) - makeID = 78; timerID = 1; break; - case 109: // Fishing Pole - makeID = 79; timerID = 1; break; - case 110: // Boards - makeID = 72; timerID = 1; break; - case 200: // Barstool - makeID = 50; timerID = 2; break; - case 201: // Stool - makeID = 51; timerID = 2; break; - case 202: // Straw Chair - makeID = 52; timerID = 2; break; - case 203: // Wooden Chair - makeID = 53; timerID = 2; break; - case 204: // Vesper Style - makeID = 57; timerID = 2; break; - case 205: // Trinsic Style - makeID = 58; timerID = 2; break; - case 206: // Bench - makeID = 54; timerID = 2; break; - case 207: // Wooden Throne - makeID = 55; timerID = 2; break; - case 208: // Magincian Throne - makeID = 56; timerID = 2; break; - case 209: // Small Table - makeID = 59; timerID = 2; break; - case 210: // Writing Table - makeID = 60; timerID = 2; break; - case 211: // Large Table - makeID = 61; timerID = 2; break; - case 212: // Yew-wood Table - makeID = 62; timerID = 2; break; - case 300: // Small Chest - makeID = 63; timerID = 3; break; - case 301: // Small Crate - makeID = 64; timerID = 3; break; - case 302: // Medium Crate - makeID = 65; timerID = 3; break; - case 303: // Large Crate - makeID = 67; timerID = 3; break; - case 304: // Chest - makeID = 68; timerID = 3; break; - case 305: // Bookshelf - makeID = 69; timerID = 3; break; - case 306: // Armoire - makeID = 70; timerID = 3; break; - case 307: // Armoire - makeID = 71; timerID = 3; break; - case 308: // Open Keg - makeID = 66; timerID = 3; break; - case 400: // Shepard's Crook - makeID = 80; timerID = 4; break; - case 401: // Quarter Staff - makeID = 81; timerID = 4; break; - case 402: // Gnarled Staff - makeID = 82; timerID = 4; break; - case 403: // Club - makeID = 123; timerID = 4; break; - case 404: // Black Staff - makeID = 124; timerID = 4; break; - case 500: // Wooden Shield - makeID = 75; timerID = 5; break; - case 600: // Lap Harp - makeID = 83; timerID = 6; break; - case 601: // Standing Harp - makeID = 84; timerID = 6; break; - case 602: // Drum - makeID = 85; timerID = 6; break; - case 603: // Lute - makeID = 86; timerID = 6; break; - case 604: // Tambourine - makeID = 87; timerID = 6; break; - case 605: // Tambourine ( tassel ) - makeID = 88; timerID = 6; break; - case 700: // bulletin board ( east ) - makeID = 93; timerID = 7; break; - case 701: // bulletin board ( south ) - makeID = 93; timerID = 7; break; - case 702: // Sm Bed ( E ) - makeID = 94; timerID = 7; break; - case 703: // Sm Bed ( S ) - makeID = 93; timerID = 7; break; - case 704: // Lg Bed ( E ) - makeID = 96; timerID = 7; break; - case 705: // Lg Bed ( S ) - makeID = 95; timerID = 7; break; - case 706: // Dart Board ( S ) - makeID = 97; timerID = 7; break; - case 707: // Dart Board ( E ) - makeID = 98; timerID = 7; break; - case 708: // Ballot Box - makeID = 99; timerID = 7; break; - case 709: // Pentagram - makeID = 100; timerID = 7; break; - case 710: // Abbatoir - makeID = 101; timerID = 7; break; - case 800: // Dressform - makeID = 115; timerID = 8; break; - case 801: // Dressform - makeID = 116; timerID = 8; break; - case 802: // Spin Wheel ( E ) - makeID = 107; timerID = 8; break; - case 803: // Spin Wheel ( S ) - makeID = 108; timerID = 8; break; - case 804: // Loom ( E ) - makeID = 109; timerID = 8; break; - case 805: // Loom ( S ) - makeID = 110; timerID = 8; break; - case 806: // Stone Oven ( E ) - makeID = 117; timerID = 8; break; - case 807: // Stone Oven ( S ) - makeID = 118; timerID = 8; break; - case 808: // Flour Mill ( E ) - makeID = 119; timerID = 8; break; - case 809: // Flour Mill ( S ) - makeID = 120; timerID = 8; break; - case 810: // Water Trough( E ) - makeID = 121; timerID = 8; break; - case 811: // Water Trough( S ) - makeID = 122; timerID = 8; break; - case 900: // Small Forge - makeID = 102; timerID = 9; break; - case 901: // Lg Forge ( E ) - makeID = 103; timerID = 9; break; - case 902: // Lg Forge ( S ) - makeID = 104; timerID = 9; break; - case 903: // Anvil ( E ) - makeID = 105; timerID = 9; break; - case 904: // Anvil ( S ) - makeID = 106; timerID = 9; break; - case 1000: // Dummy ( E ) - makeID = 111; timerID = 10; break; - case 1001: // Dummy ( S ) - makeID = 112; timerID = 10; break; - case 1002: // Pickpocket ( E ) - makeID = 113; timerID = 10; break; - case 1003: // Pickpocket ( S ) - makeID = 114; timerID = 10; break; - case 2100: // Barrel Staves - itemDetailsID = 73; break; - case 2101: // Barrel Lid - itemDetailsID = 74; break; - case 2102: // short music stand ( left ) - itemDetailsID = 89; break; - case 2103: // short music stand ( right ) - itemDetailsID = 90; break; - case 2104: // tall music stand ( left ) - itemDetailsID = 91; break; - case 2105: // tall music stand ( left ) - itemDetailsID = 92; break; - case 2106: // Easel ( S ) - itemDetailsID = 76; break; - case 2107: // Easel ( E ) - itemDetailsID = 77; break; - case 2108: // Easel ( N ) - itemDetailsID = 78; break; - case 2109: // Fishing Pole - itemDetailsID = 79; break; - case 2110: // Boards - itemDetailsID = 72; break; - case 2200: // Barstool - itemDetailsID = 50; break; - case 2201: // Stool - itemDetailsID = 51; break; - case 2202: // Straw Chair - itemDetailsID = 52; break; - case 2203: // Wooden Chair - itemDetailsID = 53; break; - case 2204: // Vesper Style - itemDetailsID = 57; break; - case 2205: // Trinsic Style - itemDetailsID = 58; break; - case 2206: // Bench - itemDetailsID = 54; break; - case 2207: // Wooden Throne - itemDetailsID = 55; break; - case 2208: // Magincian Throne - itemDetailsID = 56; break; - case 2209: - itemDetailsID = 59; break; - case 2210: // Writing Table - itemDetailsID = 60; break; - case 2211: // Large Table - itemDetailsID = 61; break; - case 2212: // Yew-wood Table - itemDetailsID = 62; break; - case 2300: // Small Chest - itemDetailsID = 63; break; - case 2301: // Small Crate - itemDetailsID = 64; break; - case 2302: // Medium Crate - itemDetailsID = 65; break; - case 2303: // Large Crate - itemDetailsID = 67; break; - case 2304: // Chest - itemDetailsID = 68; break; - case 2305: // Bookshelf - itemDetailsID = 69; break; - case 2306: // Armoire - itemDetailsID = 70; break; - case 2307: // Armoire - itemDetailsID = 71; break; - case 2308: // Open Keg - itemDetailsID = 66; break; - case 2400: // Shepard's Crook - itemDetailsID = 80; break; - case 2401: // Quarter Staff - itemDetailsID = 81; break; - case 2402: // Gnarled Staff - itemDetailsID = 82; break; - case 2403: // Club - itemDetailsID = 123; break; - case 2404: // Black Staff - itemDetailsID = 124; break; - case 2500: // Wooden Shield - itemDetailsID = 75; break; - case 2600: // Lap Harp - itemDetailsID = 83; break; - case 2601: // Standing Harp - itemDetailsID = 84; break; - case 2602: // Drum - itemDetailsID = 85; break; - case 2603: // Lute - itemDetailsID = 86; break; - case 2604: // Tambourine - itemDetailsID = 87; break; - case 2605: // Tambourine ( tassel ) - itemDetailsID = 88; break; - case 2700: // bulletin board ( east ) - itemDetailsID = 93; break; - case 2701: // bulletin board ( south ) - itemDetailsID = 93; break; - case 2702: // Sm Bed ( E ) - itemDetailsID = 94; break; - case 2703: // Sm Bed ( S ) - itemDetailsID = 93; break; - case 2704: // Lg Bed ( E ) - itemDetailsID = 96; break; - case 2705: // Lg Bed ( S ) - itemDetailsID = 95; break; - case 2706: // Dart Board ( S ) - itemDetailsID = 97; break; - case 2707: // Dart Board ( E ) - itemDetailsID = 98; break; - case 2708: // Ballot Box - itemDetailsID = 99; break; - case 2709: // Pentagram - itemDetailsID = 100; break; - case 2710: // Abbatoir - itemDetailsID = 101; break; - case 2800: // Dressform - itemDetailsID = 115; break; - case 2801: // Dressform - itemDetailsID = 116; break; - case 2802: // Spin Wheel ( E ) - itemDetailsID = 107; break; - case 2803: // Spin Wheel ( S ) - itemDetailsID = 108; break; - case 2804: // Loom ( E ) - itemDetailsID = 109; break; - case 2805: // Loom ( S ) - itemDetailsID = 110; break; - case 2806: // Stone Oven ( E ) - itemDetailsID = 117; break; - case 2807: // Stone Oven ( S ) - itemDetailsID = 118; break; - case 2808: // Flour Mill ( E ) - itemDetailsID = 119; break; - case 2809: // Flour Mill ( S ) - itemDetailsID = 120; break; - case 2810: // Water Trough( E ) - itemDetailsID = 121; break; - case 2811: // Water Trough( S ) - itemDetailsID = 122; break; - case 2900: // Small Forge - itemDetailsID = 102; break; - case 2901: // Lg Forge ( E ) - itemDetailsID = 103; break; - case 2902: // Lg Forge ( S ) - itemDetailsID = 104; break; - case 2903: // Anvil ( E ) - itemDetailsID = 105; break; - case 2904: // Anvil ( S ) - itemDetailsID = 106; break; - case 3000: // Dummy ( E ) - itemDetailsID = 111; break; - case 3001: // Dummy ( S ) - itemDetailsID = 112; break; - case 3002: // Pickpocket ( E ) - itemDetailsID = 113; break; - case 3003: // Pickpocket ( S ) - itemDetailsID = 114; break; - default: - break; + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( pSock, pUser, pageNum2 ); + return; + } + + // Page tabs 1..10 + if( pButton >= 1 && pButton <= 10 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, pButton ); + return; + } + + // Last Ten + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( pSock, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Carpentry", null ); + pUser.SetTempTag( "CRAFT", null ); + pSock.CloseGump( gumpID, 0 ); + return; } - if( makeID != 0 ) + // Make Last + if( pButton == 5000 ) { - pUser.AddScriptTrigger( 4033 ); // crafting_complete.js for applying locks to crafted containers + var last = pUser.GetTempTag( "MakeLast_Carpentry" ); + if( last ) + pButton = last; + else + return; + } + + if( CarpentryMap[pButton] !== undefined ) + { + var entry = CarpentryMap[pButton]; + var makeID = entry.makeID; + var timerID = entry.timerID || entry.page || 1; + + if( !eraOK( entry )) + { + pSock.SysMessage( "That item is not available in this era." ); + return; + } + + if( entry.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, entry.recipeID )) + { + pSock.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + pUser.SetTempTag( "MakeLast_Carpentry", pButton ); + + // Let crafting_complete.js hook things like locks on containers + pUser.AddScriptTrigger( 4033 ); + MakeItem( pSock, pUser, makeID ); + AddToLastTen( pUser, pButton ); + if( GetServerSetting( "ToolUseLimit" )) { bItem.usesLeft -= 1; if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) { bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // tool worn out } - } - pUser.StartTimer( gumpDelay, timerID, true ); + } + + pUser.StartTimer( gumpDelay, timerID, carpentryID ); + return; } - else if( itemDetailsID != 0 ) + + // Item detail buttons: 2000 + buttonID + if( pButton >= 2000 && pButton < 4000 ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + var detailButtonID = pButton - 2000; + var dEntry = CarpentryMap[detailButtonID]; + + if( dEntry ) + { + pUser.SetTempTag( "ITEMDETAILS", dEntry.makeID ); + + pUser.SetTempTag( "Skill", dEntry.skill || carpentrySkillID ); + + // Clear old harvests + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + if( dEntry.harvest && dEntry.harvest.length > 0 ) + { + if( dEntry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", dEntry.harvest[0] ); + if( dEntry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", dEntry.harvest[1] ); + if( dEntry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", dEntry.harvest[2] ); + if( dEntry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", dEntry.harvest[3] ); + } + + if( dEntry.recipeID && dEntry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", dEntry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; } } + +function AddToLastTen( pUser, buttonID ) +{ + var raw = pUser.GetTempTag( "LastTenCarpentry" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == buttonID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [ buttonID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenCarpentry", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file From 03da71d53c42e11455c7ee327f92ab95b4e79323 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 12:21:30 -0600 Subject: [PATCH 27/43] update --- data/js/skill/craft/carpentry.js | 29 ++++++-- data/js/skill/craft/itemdetailgump.js | 96 ++++++++++++++++++++++----- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/data/js/skill/craft/carpentry.js b/data/js/skill/craft/carpentry.js index 5dcb89318..084ec5247 100644 --- a/data/js/skill/craft/carpentry.js +++ b/data/js/skill/craft/carpentry.js @@ -93,7 +93,7 @@ const craftItems = [ // minEra?: string, // maxEra?: string, // skill: number, -// harvest: number[] +// harvest: number[] // dictionary IDs for resources; labels can be overridden in ItemDetailGump // }; const CarpentryMap = {}; @@ -132,6 +132,10 @@ const CarpentryMap = {}; // If you need per-entry overrides in future (recipes, extra resources, era gating), // you can do: // CarpentryMap[704].harvest = [ harvestDict, 11402 ]; // wood + cloth + // CarpentryMap[109].harvest = [ harvestDict ]; // Fishing Pole wood + cloth + // CarpentryMap[109].harvestNames = [ "", "Cloth" ]; // Fishing Pole wood + cloth + // CarpentryMap[308].harvest = [ 0 ]; // open keg Barrel Staves Barrel Hoops Barrel Lid + // CarpentryMap[308].harvestNames = [ "Barrel Staves", "Barrel Hoops", "Barrel Lid" ]; // open keg Barrel Staves Barrel Hoops Barrel Lid // CarpentryMap[709].minEra = "ml"; })(); @@ -149,8 +153,6 @@ CarpentryMap[702].harvest = [ harvestDict, 10016 ]; // Large Bed (S) wood + clo CarpentryMap[703].harvest = [ harvestDict, 10016 ]; // Large Bed (E) wood + cloth CarpentryMap[709].harvest = [ harvestDict, 10015 ]; // Pentagram wood + ingots CarpentryMap[710].harvest = [ harvestDict, 10015 ]; // Abbatoir wood + ingots - - CarpentryMap[800].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth CarpentryMap[801].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth CarpentryMap[802].harvest = [ harvestDict, 10016 ]; // Spin Wheel (E) wood + cloth @@ -161,13 +163,11 @@ CarpentryMap[806].harvest = [ harvestDict, 10015 ]; // Stone Oven (E) wood + in CarpentryMap[807].harvest = [ harvestDict, 10015 ]; // Stone Oven (S) wood + ingots CarpentryMap[808].harvest = [ harvestDict, 10015 ]; // Flour Mill (E) wood + ingots CarpentryMap[809].harvest = [ harvestDict, 10015 ]; // Flour Mill (S) wood + ingots - CarpentryMap[900].harvest = [ harvestDict, 10015 ]; // Small Forge wood + ingots CarpentryMap[901].harvest = [ harvestDict, 10015 ]; // Large Forge (E) wood + ingots CarpentryMap[902].harvest = [ harvestDict, 10015 ]; // Large Forge (S) wood + ingots CarpentryMap[903].harvest = [ harvestDict, 10015 ]; // Anvil (E) wood + ingots CarpentryMap[904].harvest = [ harvestDict, 10015 ]; // Anvil (S) wood + ingots - CarpentryMap[1000].harvest = [ harvestDict, 10016 ]; // Dummy (E) wood + cloth CarpentryMap[1001].harvest = [ harvestDict, 10016 ]; // Dummy (S) wood + cloth CarpentryMap[1002].harvest = [ harvestDict, 10016 ]; // Pickpocket (E) wood + cloth @@ -602,6 +602,12 @@ function onGumpPress( pSock, pButton, gumpData ) pUser.SetTempTag( "Harvest3", null ); pUser.SetTempTag( "Harvest4", null ); + // Clear old harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + if( dEntry.harvest && dEntry.harvest.length > 0 ) { if( dEntry.harvest.length >= 1 ) @@ -614,6 +620,19 @@ function onGumpPress( pSock, pButton, gumpData ) pUser.SetTempTag( "Harvest4", dEntry.harvest[3] ); } + // OPTIONAL custom names – these override the dictionary string + if( dEntry.harvestNames && dEntry.harvestNames.length > 0 ) + { + if( dEntry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", dEntry.harvestNames[0] ); + if( dEntry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", dEntry.harvestNames[1] ); + if( dEntry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", dEntry.harvestNames[2] ); + if( dEntry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", dEntry.harvestNames[3] ); + } + if( dEntry.recipeID && dEntry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", dEntry.recipeID ); else diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 4c0642c0c..28fda39e6 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -81,7 +81,9 @@ function ItemDetailGump( pUser ) var socket = pUser.socket; var itemGump = new Gump; var createEntry = null; - var harvestResource; + // Now supports both dict-based and custom harvest names + // harvestResource[i] = { id: number, name: string } + var harvestResource = []; var mainSkill; var detailTag = pUser.GetTempTag( "ITEMDETAILS" ); @@ -90,6 +92,13 @@ function ItemDetailGump( pUser ) var harvest2Tag = pUser.GetTempTag( "Harvest2" ); var harvest3Tag = pUser.GetTempTag( "Harvest3" ); var harvest4Tag = pUser.GetTempTag( "Harvest4" ); + + // NEW: optional custom harvest names + var harvestNameTag = pUser.GetTempTag( "HarvestName" ); + var harvest2NameTag = pUser.GetTempTag( "Harvest2Name" ); + var harvest3NameTag = pUser.GetTempTag( "Harvest3Name" ); + var harvest4NameTag = pUser.GetTempTag( "Harvest4Name" ); + var recipeID = pUser.GetTempTag( "needRecipeID" ); if( detailTag !== null ) @@ -106,22 +115,45 @@ function ItemDetailGump( pUser ) mainSkill = mainSkill = parseInt( pUser.skills.alchemy ); } - // If harvest info is provided, rebuild HARVEST array - if( harvestTag !== null || harvest2Tag !== null || harvest3Tag !== null || harvest4Tag !== null ) + // Helper to build harvest entries with both id + optional custom name + function makeHarvestObj(idTag, nameTag) { - harvestResource = []; + // nothing set at all + var hasName = !!(nameTag && nameTag.length); + if (idTag === null && !hasName) + return null; + + var idNum = 0; + if (idTag !== null) + { + var n = parseInt(idTag, 10); + if (!isNaN(n) && n > 0) + idNum = n; + } - if( harvestTag !== null ) - harvestResource.push( parseInt( harvestTag, 10 )); + // if no valid dict id and no name, skip + if (idNum === 0 && !hasName) + return null; - if( harvest2Tag !== null ) - harvestResource.push( parseInt( harvest2Tag, 10 )); + return { + id: idNum, // 0 = "no dict" + name: hasName ? nameTag : "" + }; + } - if( harvest3Tag !== null ) - harvestResource.push( parseInt( harvest3Tag, 10 )); - - if( harvest4Tag !== null ) - harvestResource.push( parseInt( harvest4Tag, 10 )); + // If harvest info is provided, rebuild harvestResource array + if( harvestTag !== null || harvest2Tag !== null || harvest3Tag !== null || harvest4Tag !== null + || harvestNameTag !== null || harvest2NameTag !== null || harvest3NameTag !== null || harvest4NameTag !== null ) + { + var h1 = makeHarvestObj( harvestTag, harvestNameTag ); + var h2 = makeHarvestObj( harvest2Tag, harvest2NameTag ); + var h3 = makeHarvestObj( harvest3Tag, harvest3NameTag ); + var h4 = makeHarvestObj( harvest4Tag, harvest4NameTag ); + + if( h1 ) harvestResource.push( h1 ); + if( h2 ) harvestResource.push( h2 ); + if( h3 ) harvestResource.push( h3 ); + if( h4 ) harvestResource.push( h4 ); } if( createEntry == null ) @@ -249,9 +281,43 @@ function ItemDetailGump( pUser ) if( resources.length < maxHarvest ) maxHarvest = resources.length; + // MATERIALS list, now supporting custom names for( var i = 0; i < maxHarvest; i++ ) { - itemGump.AddText( 170, 219 + ( i * 20 ), textHue, GetDictionaryEntry( harvestResource[i], socket.language )); + var hObj = harvestResource[i]; // { id, name } + var label = ""; + + if( hObj ) + { + var dictText = ""; + if( hObj.id && hObj.id > 0 ) + dictText = GetDictionaryEntry( hObj.id, socket.language ) || ""; + + if( hObj.name && hObj.name.length > 0 ) + { + // Both set: "Custom (Dict)" + if( dictText && dictText.length > 0 ) + label = hObj.name + " (" + dictText + ")"; + else + label = hObj.name; + } + else + { + // Only dict + label = dictText; + } + + // Optional safety fallback if both are empty + if( !label || label.length === 0 ) + { + if( hObj.id && hObj.id > 0 ) + label = "Resource " + hObj.id; + else + label = "Resource"; + } + } + + itemGump.AddText( 170, 219 + ( i * 20 ), textHue, label ); itemGump.AddText( 430, 219 + ( i * 20 ), textHue, resources[i][0] ); } @@ -476,7 +542,7 @@ function onGumpPress( pSock, pButton, gumpData ) break; } break; - case 8: // Cartography + case 8: // Cartography pUser.SetTempTag( "ITEMDETAILS", null ); pSock.CloseGump( gumpID, 0 ); switch( pUser.GetTempTag( "page" )) From 6e7c68f2228acf2026d71acbdf7137b2bdf9a0e6 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:18:55 -0600 Subject: [PATCH 28/43] update --- data/js/skill/craft/alchemy.js | 24 +- data/js/skill/craft/blacksmithing.js | 43 +- data/js/skill/craft/carpentry.js | 48 +-- data/js/skill/craft/cartography.js | 588 +++++++++++++++++++++------ data/js/skill/craft/masonry.js | 43 +- 5 files changed, 586 insertions(+), 160 deletions(-) diff --git a/data/js/skill/craft/alchemy.js b/data/js/skill/craft/alchemy.js index ff905dfe4..4069092f9 100644 --- a/data/js/skill/craft/alchemy.js +++ b/data/js/skill/craft/alchemy.js @@ -19,10 +19,11 @@ const alchemySkillID = 0; // Skill ID: Alchemy // | page - main category page (1..4) | // | timerID - which page timer should reopen | // | skill - skill used (default: alchemySkillID) | -// | recipeID?, minEra?, maxEra?, harvest?[] can be added later | +// | recipeID?, minEra?, maxEra?, harvest?[] harvestNames? ["cloth" ] | +// | can be added later | // o--------------------------------------------------------------------------o // If you want to add multi-reagent potions later -// (e.g. harvest: [ garlic_dictNumber, ginseng_dictNumber ]), +// (e.g. harvest: [ garlic_dictNumber, ginseng_dictNumber ] or harvestNames: [ "garlic, "ginseng" ]), // the same pattern will just work with no script changes. const AlchemyMap = { @@ -458,6 +459,12 @@ function onGumpPress( socket, pButton, gumpData ) pUser.SetTempTag( "Harvest3", null ); pUser.SetTempTag( "Harvest4", null ); + // Clear old harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + // If you later add entry.harvest = [dictID1, dictID2,...], you can push them here if( entry.harvest && entry.harvest.length > 0 ) { @@ -471,6 +478,19 @@ function onGumpPress( socket, pButton, gumpData ) pUser.SetTempTag( "Harvest4", entry.harvest[3] ); } + // OPTIONAL custom names – these override the dictionary string + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + if( entry.recipeID && entry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", entry.recipeID ); else diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index f6c09f0d7..8b331658c 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -1096,17 +1096,42 @@ function onGumpPress( pSock, pButton, gumpData ) // Masonry uses Carpentry skill pUser.SetTempTag( "Skill", entry.skill | 0 ); - if( entry.harvest && entry.harvest.length > 0 ) - pUser.SetTempTag( "Harvest", entry.harvest[0] ); - - if( entry.harvest2 && entry.harvest2.length > 0 ) - pUser.SetTempTag( "Harvest2", entry.harvest2[0] ); + // Clear old harvests + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); - if( entry.harvest3 && entry.harvest3.length > 0 ) - pUser.SetTempTag( "Harvest3", entry.harvest3[0] ); + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } - if( entry.harvest4 && entry.harvest4.length > 0 ) - pUser.SetTempTag( "Harvest4", entry.harvest4[0] ); + // OPTIONAL custom names – these override the dictionary string + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } if( entry.recipeID && entry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", entry.recipeID ); diff --git a/data/js/skill/craft/carpentry.js b/data/js/skill/craft/carpentry.js index 084ec5247..49eaeef76 100644 --- a/data/js/skill/craft/carpentry.js +++ b/data/js/skill/craft/carpentry.js @@ -588,13 +588,13 @@ function onGumpPress( pSock, pButton, gumpData ) if( pButton >= 2000 && pButton < 4000 ) { var detailButtonID = pButton - 2000; - var dEntry = CarpentryMap[detailButtonID]; + var entry = CarpentryMap[detailButtonID]; - if( dEntry ) + if( entry ) { - pUser.SetTempTag( "ITEMDETAILS", dEntry.makeID ); + pUser.SetTempTag( "ITEMDETAILS", entry.makeID ); - pUser.SetTempTag( "Skill", dEntry.skill || carpentrySkillID ); + pUser.SetTempTag( "Skill", entry.skill || carpentrySkillID ); // Clear old harvests pUser.SetTempTag( "Harvest", null ); @@ -608,33 +608,33 @@ function onGumpPress( pSock, pButton, gumpData ) pUser.SetTempTag( "Harvest3Name", null ); pUser.SetTempTag( "Harvest4Name", null ); - if( dEntry.harvest && dEntry.harvest.length > 0 ) + if( entry.harvest && entry.harvest.length > 0 ) { - if( dEntry.harvest.length >= 1 ) - pUser.SetTempTag( "Harvest", dEntry.harvest[0] ); - if( dEntry.harvest.length >= 2 ) - pUser.SetTempTag( "Harvest2", dEntry.harvest[1] ); - if( dEntry.harvest.length >= 3 ) - pUser.SetTempTag( "Harvest3", dEntry.harvest[2] ); - if( dEntry.harvest.length >= 4 ) - pUser.SetTempTag( "Harvest4", dEntry.harvest[3] ); + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); } // OPTIONAL custom names – these override the dictionary string - if( dEntry.harvestNames && dEntry.harvestNames.length > 0 ) + if( entry.harvestNames && entry.harvestNames.length > 0 ) { - if( dEntry.harvestNames.length >= 1 ) - pUser.SetTempTag( "HarvestName", dEntry.harvestNames[0] ); - if( dEntry.harvestNames.length >= 2 ) - pUser.SetTempTag( "Harvest2Name", dEntry.harvestNames[1] ); - if( dEntry.harvestNames.length >= 3 ) - pUser.SetTempTag( "Harvest3Name", dEntry.harvestNames[2] ); - if( dEntry.harvestNames.length >= 4 ) - pUser.SetTempTag( "Harvest4Name", dEntry.harvestNames[3] ); + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); } - if( dEntry.recipeID && dEntry.recipeID > 0 ) - pUser.SetTempTag( "needRecipeID", dEntry.recipeID ); + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); else pUser.SetTempTag( "needRecipeID", 0 ); diff --git a/data/js/skill/craft/cartography.js b/data/js/skill/craft/cartography.js index 38f8bc563..57f0b88d6 100644 --- a/data/js/skill/craft/cartography.js +++ b/data/js/skill/craft/cartography.js @@ -1,193 +1,549 @@ /// // @ts-check -const LabelHue = 0x480; // Color of the text. -const LabelColor = 0x7FFF; // Second Color of text. -const scriptID = 4035; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; +const textHue = 0x480; // Color of the text. +const cartographyID = 4035; // Script ID for this cartography gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Generic item details gump +const craftGumpID = 4027; // Shared crafting menu frame +const itemsPerPage = 10; // Items per subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const cartographySkillID = 12; // Skill index for "cartography" in ItemDetailGump ////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// +// CartographyMap +// Keyed by makeID (create entry ID). +// Each entry: +// dictID - dictionary entry for row text (13100..13103) +// page - main category page (1..N) +// timerID - which page timer should reopen +// skill - skill used (default: cartographySkillID) +// recipeID? - optional recipe ID +// minEra/maxEra? - optional era gating +// harvest?[] - optional material dictionary IDs +// harvestNames?[] - optional custom material names +// +// NOTE: For the World Map row, we use base makeID 2003. +// At craft time, we still adjust to 2003..2007 depending on worldnumber, +// just like the original script did. +// +////////////////////////////////////////////////////////////////////////////////////////// -const myPage = [ +const CartographyMap = { // Page 1 - Maps - [ 13100, 13101, 13102, 13103 ] -]; + 2000: { dictID: 13100, page: 1, timerID: 1 }, // Local Map + 2001: { dictID: 13101, page: 1, timerID: 1 }, // City Map + 2002: { dictID: 13102, page: 1, timerID: 1 }, // Sea Chart + 2003: { dictID: 13103, page: 1, timerID: 1 } // World Map (base; world-specific in onGumpPress) +}; + +// Fill in defaults (skill, etc) +(function initCartographyMap() +{ + for( var key in CartographyMap ) + { + if( !CartographyMap.hasOwnProperty( key )) + continue; + + var entry = CartographyMap[key]; + if( entry.skill === undefined ) + entry.skill = cartographySkillID; + + // If you later want harvest info for detail gump, you can do: + // CartographyMap[2000].harvest = [ ]; + // CartographyMap[2000].harvestNames = [ "Blank scroll" ]; + } +})(); + +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) { - // Pages 1 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for ( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // Special Last Ten page (if you ever want it for Cartography) + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenCartography" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); // makeID itself + } + } + else { - var index = i % 10; - if ( index == 0 ) + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in CartographyMap ) { - if ( i > 0 ) + if( !CartographyMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = CartographyMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) + { + var ea = CartographyMap[a]; + var eb = CartographyMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering (hooks for future use) + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = CartographyMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) ) + pageItems.push( id ); + } + + // Fallback: if no items on this page and it's not page 1, go to page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; + + makeIDs = []; + for( var key2 in CartographyMap ) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + if( !CartographyMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = CartographyMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; + + makeIDs.push( mid2 ); } - myGump.AddPage( ( i / 10 ) + 1 ); + makeIDs.sort( function( a, b ) + { + var ea2 = CartographyMap[a]; + var eb2 = CartographyMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); - if ( i > 0 ) + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + var id2 = makeIDs[m]; + var data4 = CartographyMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 )) ) + pageItems.push( id2 ); } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); + } - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language ) ); + // Subpage handling (future-proof; only 1 subpage needed right now) + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + if( totalSubPages < 1 ) + totalSubPages = 1; + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var cartGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", cartGump, socket ); + cartGump.AddPage( 1 ); + + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // use makeID directly as buttonID + + var data5 = CartographyMap[makeID]; + + if( !data5 ) + { + entryText = "[Missing MakeID: " + makeID + "]"; + } + else + { + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; + } + } + + // Craft button uses makeID + cartGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + cartGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); + + // Detail button: 20000 + makeID + cartGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); + } + + // Prev subpage + if( subPage > 1 ) + { + cartGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + cartGump.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE } - myGump.Send( socket ); - myGump.Free(); + + // Next subpage + if( subPage < totalSubPages ) + { + cartGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + cartGump.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + cartGump.Send( socket ); + cartGump.Free(); } -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +/** @type { ( pUser: Character, timerID: number ) => void } */ function onTimer( pUser, timerID ) { if( !ValidateObject( pUser )) return; - var socket = pUser.socket; + var pSocket = pUser.socket; + if( pSocket == null ) + return; - switch ( timerID ) + if( timerID >= 1 && timerID <= 8 ) { - case 1: // Page 1 - Maps - PageX( socket, pUser, timerID ); - break; + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); } } -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) { - var pUser = pSock.currentChar; + if( socket == null ) + return; - // Don't continue if character is invalid, or worse... dead! + var pUser = socket.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; - // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + var tool = socket.tempObj; + if( !ValidateObject( tool ) || !pUser.InRange( tool, 3 )) { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. return; } - if( bItem.movable == 3 ) + if( tool.movable == 3 ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! return; } - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + var packOwner = GetPackOwner( tool, 0 ); + if( ValidateObject( packOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( packOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That is in someone else's pack. return; } } else { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // Must be in your pack to use it. + return; + } + + var gumpID = cartographyID + 0xffff; + + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) + { + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; + } + + if( pButton >= 9001 && pButton < 10000 ) + { + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; + } + + // Page tabs (Cartography only uses page 1 for now, but up to 8 is harmless) + if( pButton >= 1 && pButton <= 8 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; + } + + // Last Ten + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Cartography", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); return; } - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; + var makeID = 0; var timerID = 0; - if(( pButton >= 100 && pButton <= 305 ) || pButton == 5000 ) + // Make Last + if( pButton == 5000 ) { - if( pButton == 5000 ) + var last = pUser.GetTempTag( "MakeLast_Cartography" ); + if( last ) + pButton = last; + else + return; + } + + // Craft buttons use makeID directly + if( CartographyMap[pButton] != undefined ) + { + makeID = pButton; + var data = CartographyMap[makeID]; + timerID = data.timerID || 1; + + if( !eraOK( data )) { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); + socket.SysMessage( "That item is not available in this era." ); + return; } - else + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) { - pUser.SetTempTag( "MAKELAST", pButton ); + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; } - } - switch ( pButton ) - { - case 0: // Abort and do nothing - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break; - case 1: // Page 1 - Maps - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - // Make Items - case 100: // Local Map - makeID = 2000; timerID = 1; break; - case 101: // City Map - makeID = 2001; timerID = 1; break; - case 102: // Sea Chart - makeID = 2002; timerID = 1; break; - case 103: // World map - mapID = 0; + // Save Make Last + pUser.SetTempTag( "MakeLast_Cartography", makeID ); + + // Special case: World Map uses different create entries per world + var makeToCraft = makeID; + if( makeID == 2003 ) // world map row + { switch( pUser.worldnumber ) { - case 0: mapID = 2003; break;//fel - case 1: mapID = 2003; break;//tram - case 2: mapID = 2004; break;//ilsh - case 3: mapID = 2005; break;//malas - case 4: mapID = 2006; break;//Tokuno - case 5: mapID = 2007; break;//TerMur + case 0: // Felucca + case 1: // Trammel + makeToCraft = 2003; break; + case 2: // Ilshenar + makeToCraft = 2004; break; + case 3: // Malas + makeToCraft = 2005; break; + case 4: // Tokuno + makeToCraft = 2006; break; + case 5: // TerMur + makeToCraft = 2007; break; } - makeID = mapID; timerID = 1; break; - // Show Item Details - case 2100: // Local Map - itemDetailsID = 2000; break; - case 2101: // City Map - itemDetailsID = 2001; break; - case 2102: // Sea Chart - itemDetailsID = 2002; break; - case 2103: // World map - itemDetailsID = 2003; break; - default: - break; + } + + // Let crafting_complete.js handle map-specific setup + pUser.AddScriptTrigger( 4033 ); + + MakeItem( socket, pUser, makeToCraft ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + tool.usesLeft -= 1; + if( tool.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + { + tool.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! + } + } + + pUser.StartTimer( gumpDelay, timerID, cartographyID ); + return; } - if( makeID != 0 ) + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) { - pUser.AddScriptTrigger(4033); // crafting_complete.js for applying map settings - MakeItem( pSock, pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) + var detailMakeID = pButton - 20000; + var entry = CartographyMap[detailMakeID]; + + if( entry ) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || cartographySkillID ); + + // Clear old harvest tags + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old custom harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // If you later add entry.harvest = [ ... ], push them into tags + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } + + // OPTIONAL custom names – override / supplement dictionary labels + if( entry.harvestNames && entry.harvestNames.length > 0 ) { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); } - } - pUser.StartTimer( gumpDelay, timerID, true ); + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; } - else if( itemDetailsID != 0 ) +} + +// Last Ten handling +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenCartography" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); } + + pUser.SetTempTag( "LastTenCartography", newList.join( "," ) ); } + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 8b6994cb5..228033e0e 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -1210,17 +1210,42 @@ function onGumpPress( pSock, pButton, gumpData ) // Masonry uses Carpentry skill pUser.SetTempTag( "Skill", entry.skill | 0 ); - if( entry.harvest && entry.harvest.length > 0 ) - pUser.SetTempTag( "Harvest", entry.harvest[0] ); - - if( entry.harvest2 && entry.harvest2.length > 0 ) - pUser.SetTempTag( "Harvest2", entry.harvest2[0] ); + // Clear old harvests + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); - if( entry.harvest3 && entry.harvest3.length > 0 ) - pUser.SetTempTag( "Harvest3", entry.harvest3[0] ); + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } - if( entry.harvest4 && entry.harvest4.length > 0 ) - pUser.SetTempTag( "Harvest4", entry.harvest4[0] ); + // OPTIONAL custom names – these override the dictionary string + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } if( entry.recipeID && entry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", entry.recipeID ); From 6aa1901ff26ed492788fc5e7f9a01897cf6c2e67 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:33:34 -0600 Subject: [PATCH 29/43] Update cooking.js --- data/js/skill/craft/cooking.js | 890 +++++++++++++++++++++------------ 1 file changed, 565 insertions(+), 325 deletions(-) diff --git a/data/js/skill/craft/cooking.js b/data/js/skill/craft/cooking.js index 393b4306a..552c79353 100644 --- a/data/js/skill/craft/cooking.js +++ b/data/js/skill/craft/cooking.js @@ -1,389 +1,475 @@ /// // @ts-check -const LabelHue = 0x480; // Color of the text. -const LabelColor = 0x7FFF; // Second Color of text. -const scriptID = 4034; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; -const manualMillTarget = true; // If true, player must manually target mills when grinding wheat +const textHue = 0x480; // Color of the text. +const cookingID = 4034; // Script ID for this cooking gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Generic item details gump +const craftGumpID = 4027; // Shared crafting menu frame +const itemsPerPage = 10; // Items per subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const cookingSkillID = 13; // Index for "cooking" in ItemDetailGump skillNames[] +const manualMillTarget = true; // If true, player must target mills when grinding wheat + +// Mills / ovens / heat sources for AreaItemFunction + StaticInRange checks +const mills = [ + 0x188b, 0x1893, 0x1920, 0x1922, 0x192c, 0x192e +]; + +const ovens = [ + 0x0461, 0x046f, 0x092b, 0x093f +]; + +const heatSources = [ + 0x0461, 0x0480, 0x092B, 0x0933, 0x0937, 0x0942, 0x0945, 0x0950, 0x0953, + 0x095e, 0x0961, 0x096c, 0x0de3, 0x0de8, 0x0fac +]; + +function FindNearbyMills( pUser, trgItem, pSock ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + return ( mills.indexOf( trgItem.id ) != -1 ); +} +function FindNearbyOvens( pUser, trgItem, pSock ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + return ( ovens.indexOf( trgItem.id ) != -1 ); +} + +function FindNearbyHeatSources( pUser, trgItem, pSock ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + return ( heatSources.indexOf( trgItem.id ) != -1 ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// CookingMap +// Keyed by makeID (create entry ID). +// Each entry: +// dictID - dictionary entry for the row text (11606..11635) +// page - main category page (1..4) +// timerID - which page timer should reopen +// skill - skill used (default: cookingSkillID) +// recipeID? - optional recipe ID (for recipe system) +// minEra/maxEra? - optional era gating +// harvest?[] - optional dictIDs for MATERIALS list in ItemDetailGump +// harvestNames?[] - optional custom material names (works with your new custom-name system) +// ////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// -const myPage = [ +const CookingMap = { // Page 1 - Ingredients - [ 11606, 11607, 11608, 11609, 11610 ], + 1500: { dictID: 11606, page: 1, timerID: 1 }, // Sack of Flour + 1501: { dictID: 11607, page: 1, timerID: 1 }, // Dough + 1502: { dictID: 11608, page: 1, timerID: 1 }, // Sweet Dough + 1503: { dictID: 11609, page: 1, timerID: 1 }, // Cake Mix + 1504: { dictID: 11610, page: 1, timerID: 1 }, // Cookie Mix // Page 2 - Preparations - [ 11611, 11612, 11613, 11614, 11615, 11616, 11617, 11618 ], + 1550: { dictID: 11611, page: 2, timerID: 2 }, // Unbaked Quiche + 1551: { dictID: 11612, page: 2, timerID: 2 }, // Unbaked Meat Pie + 1552: { dictID: 11613, page: 2, timerID: 2 }, // Uncooked Sausage Pizza + 1553: { dictID: 11614, page: 2, timerID: 2 }, // Uncooked Cheese Pizza + 1554: { dictID: 11615, page: 2, timerID: 2 }, // Unbaked Fruit Pie + 1555: { dictID: 11616, page: 2, timerID: 2 }, // Unbaked Peach Cobbler + 1556: { dictID: 11617, page: 2, timerID: 2 }, // Unbaked Apple Pie + 1557: { dictID: 11618, page: 2, timerID: 2 }, // Unbaked Pumpkin Pie // Page 3 - Baking - [11619, 11620, 11621, 11657, 11622, 11623, 11624, 11625, 11626, 11627, 11628, 11629 ], + 1600: { dictID: 11619, page: 3, timerID: 3 }, // Bread Loaf + 1601: { dictID: 11620, page: 3, timerID: 3 }, // Pan of Cookies + 1602: { dictID: 11621, page: 3, timerID: 3 }, // Cake + 1603: { dictID: 11657, page: 3, timerID: 3 }, // Muffins + 1604: { dictID: 11622, page: 3, timerID: 3 }, // Baked Quiche + 1605: { dictID: 11623, page: 3, timerID: 3 }, // Baked Meat Pie + 1606: { dictID: 11624, page: 3, timerID: 3 }, // Sausage Pizza + 1607: { dictID: 11625, page: 3, timerID: 3 }, // Cheese Pizza + 1608: { dictID: 11626, page: 3, timerID: 3 }, // Baked Fruit Pie + 1609: { dictID: 11627, page: 3, timerID: 3 }, // Baked Peach Cobbler + 1610: { dictID: 11628, page: 3, timerID: 3 }, // Baked Apple Pie + 1611: { dictID: 11629, page: 3, timerID: 3 }, // Baked Pumpkin Pie // Page 4 - Barbecue - [ 11630, 11631, 11632, 11633, 11634, 11635 ] + 1650: { dictID: 11630, page: 4, timerID: 4 }, // Cooked Bird + 1651: { dictID: 11631, page: 4, timerID: 4 }, // Chicken Leg + 1652: { dictID: 11632, page: 4, timerID: 4 }, // Fish Steak + 1653: { dictID: 11633, page: 4, timerID: 4 }, // Fried Eggs + 1654: { dictID: 11634, page: 4, timerID: 4 }, // Leg of Lamb + 1655: { dictID: 11635, page: 4, timerID: 4 } // Cut of Ribs +}; + +// Fill in defaults (skill, etc) +(function initCookingMap() +{ + for( var key in CookingMap ) + { + if( !CookingMap.hasOwnProperty( key )) + continue; -]; + var entry = CookingMap[key]; + + if( entry.skill === undefined ) + entry.skill = cookingSkillID; + + // In future you can add: + // entry.harvest = [ dictID_for_flour, dictID_for_water ]; + // entry.harvestNames = [ "Flour", "Water" ]; + } +})(); +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) { - // Pages 1 - 4 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for ( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // No "Last Ten" page here (but we keep the infrastructure if you want it later) + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenCooking" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); + } + } + else { - var index = i % 10; - if ( index == 0 ) + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in CookingMap ) + { + if( !CookingMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = CookingMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) { - if ( i > 0 ) + var ea = CookingMap[a]; + var eb = CookingMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering (hooks for future use) + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = CookingMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) ) + pageItems.push( id ); + } + + // Fallback: if no items on this page and it's not page 1, go to page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; + + makeIDs = []; + for( var key2 in CookingMap ) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE - } + if( !CookingMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = CookingMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; - myGump.AddPage( ( i / 10 ) + 1 ); + makeIDs.push( mid2 ); + } - if ( i > 0 ) + makeIDs.sort( function( a, b ) + { + var ea2 = CookingMap[a]; + var eb2 = CookingMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + var id2 = makeIDs[m]; + var data4 = CookingMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 )) ) + pageItems.push( id2 ); } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); + } + + // Subpage handling (future-proof; currently only 1 subpage per page) + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language )); + if( totalSubPages < 1 ) + totalSubPages = 1; + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); } - myGump.Send( socket ); - myGump.Free(); -} -const mills = [ - 0x188b, 0x1893, 0x1920, 0x1922, 0x192c, 0x192e -]; -function FindNearbyMills( pUser, trgItem, pSock ) -{ - if( !ValidateObject( trgItem ) || !trgItem.isItem ) - return false; + var cookGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", cookGump, socket ); + cookGump.AddPage( 1 ); - return ( mills.indexOf( trgItem.id ) != -1 ); -} + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // use makeID directly as buttonID -const ovens = [ - 0x461, 0x46F, 0x92B, 0x93F -]; -function FindNearbyOvens( pUser, trgItem, pSock ) -{ - if( !ValidateObject( trgItem ) || !trgItem.isItem ) - return false; + var data5 = CookingMap[makeID]; - return ( ovens.indexOf( trgItem.id ) != -1 ); -} + if( !data5 ) + { + entryText = "[Missing MakeID: " + makeID + "]"; + } + else + { + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; + } + } -const heatSources = [ - 0x0461, 0x0480, 0x092B, 0x0933, 0x0937, 0x0942, 0x0945, 0x0950, 0x0953, - 0x095e, 0x0961, 0x096c, 0x0de3, 0x0de8, 0x0fac -]; -function FindNearbyHeatSources( pUser, trgItem, pSock ) -{ - if( !ValidateObject( trgItem ) || !trgItem.isItem ) - return false; + // Craft button uses makeID + cookGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + cookGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); - return ( heatSources.indexOf( trgItem.id ) != -1 ); + // Detail button: 20000 + makeID + cookGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); + } + + // Prev subpage + if( subPage > 1 ) + { + cookGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + cookGump.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + + // Next subpage + if( subPage < totalSubPages ) + { + cookGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + cookGump.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + cookGump.Send( socket ); + cookGump.Free(); } -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +/** @type { ( pUser: Character, timerID: number ) => void } */ function onTimer( pUser, timerID ) { if( !ValidateObject( pUser )) return; - var socket = pUser.socket; + var pSocket = pUser.socket; + if( pSocket == null ) + return; - switch ( timerID ) + if( timerID >= 1 && timerID <= 4 ) { - case 1: // Page 1 - Ingredients - case 2: // Page 2 - Preparation - case 3: // Page 3 - Baking - case 4: // Page 4 - Barbecue - PageX( socket, pUser, timerID ); - break; + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); } } -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) { - var pUser = pSock.currentChar; + if( socket == null ) + return; - // Don't continue if character is invalid, or worse... dead! + var pUser = socket.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; - // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + // Don't continue if player no longer has access to the cooking tool + var tool = socket.tempObj; + if( !ValidateObject( tool ) || !pUser.InRange( tool, 3 )) { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. return; } - if( bItem.movable == 3 ) + if( tool.movable == 3 ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! return; } - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + var packOwner = GetPackOwner( tool, 0 ); + if( ValidateObject( packOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( packOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That is in someone else's backpack! return; } } else { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This must be in your pack to use. return; } - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var timerID = 0; + var gumpID = cookingID + 0xffff; - // Check for nearby heatsource - var nearbyHeatSource = 0; - var nearbyMill = 0; - var nearbyOven = 0; + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) + { + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; + } - // Make Last Button - if( pButton == 5000 ) + if( pButton >= 9001 && pButton < 10000 ) { - pButton = pUser.GetTempTag( "MAKELAST" ); + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; } - if( pButton >= 300 && pButton <= 311 ) + // Page tabs (1–4: Ingredients, Preparation, Baking, Barbecue) + if( pButton >= 1 && pButton <= 4 ) { - // Baking - Requires Oven - nearbyOven = AreaItemFunction( "FindNearbyOvens", pUser, 2, pSock ); - if( nearbyOven > 0 ) - { - pUser.SetTempTag( "MAKELAST", pButton ); - } - else - { - // No dynamic oven found nearby! Look for a static one? - var staticFound = false; - for( var i = 0; i < ovens.length; i++ ) - { - if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, ovens[i] )) - { - staticFound = true; - break; - } - } - if( !staticFound ) - { - pUser.SetTempTag( "prevActionResult", "NOOVEN" ); - } - } + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; } - else if( pButton >= 400 && pButton <= 405 ) + + // Last Ten (if you ever wire it into the main craft gump) + if( pButton == 11000 ) { - // Barbecue - Requires Fire/Generic Heat Source - nearbyHeatSource = AreaItemFunction( "FindNearbyHeatSources", pUser, 2, pSock ); - if( nearbyHeatSource > 0 ) - { - pUser.SetTempTag( "MAKELAST", pButton ); - } - else - { - // No dynamic heat source found nearby! Look for a static one? - var staticFound = false; - for( var i = 0; i < heatSources.length; i++ ) - { - if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, heatSources[i] )) - { - staticFound = true; - break; - } - } - if( !staticFound ) - { - pUser.SetTempTag( "prevActionResult", "NOHEATSOURCE" ); - } - } + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; } - else if( pButton >= 101 && pButton <= 207 ) + + // Close gump + if( pButton == 0 ) { - // Ingredients and Preparation - no heatsource required - pUser.SetTempTag( "MAKELAST", pButton ); + pUser.SetTempTag( "MakeLast_Cooking", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); + return; } - switch ( pButton ) + // Make Last + if( pButton == 5000 ) { - case 0: // Abort and do nothing - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break; - case 1: // Page 1 - Ingredients - case 2: // Page 2 - Preparation - case 3: // Page 3 - Baking - case 4: // Page 4 - Barbecue - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - // Make Items - // Page 1 - Ingredients - case 100: // Sack of Flour - makeID = 1500; timerID = 1; break; - case 101: // Dough - makeID = 1501; timerID = 1; break; - case 102: // Sweet Dough - makeID = 1502; timerID = 1; break; - case 103: // Cake Mix - makeID = 1503; timerID = 1; break; - case 104: // Cookie Mix - makeID = 1504; timerID = 1; break; - // Page 2 - Preparation - case 200: // Unbaked Quiche - makeID = 1550; timerID = 2; break; - case 201: // Unbaked Meat Pie - makeID = 1551; timerID = 2; break; - case 202: // Uncooked Sausage Pizza - makeID = 1552; timerID = 2; break; - case 203: // Uncooked Cheese Pizza - makeID = 1553; timerID = 2; break; - case 204: // Unbaked Fruit Pie - makeID = 1554; timerID = 2; break; - case 205: // Unbaked Peach Cobbler - makeID = 1555; timerID = 2; break; - case 206: // Unbaked Applie Pie - makeID = 1556; timerID = 2; break; - case 207: // Unbaked Pumpkin Pie - makeID = 1557; timerID = 2; break; - // Page 3 - Baking - case 300: // Bread Loaf - makeID = 1600; timerID = 3; break; - case 301: // Pan of Cookies - makeID = 1601; timerID = 3; break; - case 302: // Cake - makeID = 1602; timerID = 3; break; - case 303: // Muffins - makeID = 1603; timerID = 3; break; - case 304: // Baked Quiche - makeID = 1604; timerID = 3; break; - case 305: // Baked Meat Pie - makeID = 1605; timerID = 3; break; - case 306: // Sausage Pizza - makeID = 1606; timerID = 3; break; - case 307: // Cheese Pizza - makeID = 1607; timerID = 3; break; - case 308: // Baked Fruit Pie - makeID = 1608; timerID = 3; break; - case 309: // Baked Peach Cobbler - makeID = 1609; timerID = 3; break; - case 310: // Baked Applie Pie - makeID = 1610; timerID = 3; break; - case 311: // Baked Pumpkin Pie - makeID = 1611; timerID = 3; break; - // Page 4 - Barbecue - case 400: // Cooked Bird - makeID = 1650; timerID = 4; break; - case 401: // Chicken Leg - makeID = 1651; timerID = 4; break; - case 402: // Fish Steak - makeID = 1652; timerID = 4; break; - case 403: // Fried Eggs - makeID = 1653; timerID = 4; break; - case 404: // Leg of Lamb - makeID = 1654; timerID = 4; break; - case 405: // Cut of Ribs - makeID = 1655; timerID = 4; break; - // Show Item Details - case 2100: // Sack of Flour - itemDetailsID = 1500; break; - case 2101: // Dough - itemDetailsID = 1501; break; - case 2102: // Sweet Dough - itemDetailsID = 1502; break; - case 2103: // Cake Mix - itemDetailsID = 1503; break; - case 2104: // Cookie Mix - itemDetailsID = 1504; break; - case 2200: // Unbaked Quiche - itemDetailsID = 1550; break; - case 2201: // Unbaked Meat Pie - itemDetailsID = 1551; break; - case 2202: // Uncooked Sausage Pizza - itemDetailsID = 1552; break; - case 2203: // Uncooked Cheese Pizza - itemDetailsID = 1553; break; - case 2204: // Unbaked Fruit Pie - itemDetailsID = 1554; break; - case 2205: // Unbaked Peach Cobbler - itemDetailsID = 1555; break; - case 2206: // Unbaked Apple Pie - itemDetailsID = 1556; break; - case 2207: // Unbaked Pumpkin Pie - itemDetailsID = 1557; break; - case 2300: // Bread Loaf - itemDetailsID = 1600; break; - case 2301: // Pan of Cookies - itemDetailsID = 1601; break; - case 2302: // Cake - itemDetailsID = 1602; break; - case 2303: // Muffins - itemDetailsID = 1603; break; - case 2304: // Baked Quiche - itemDetailsID = 1604; break; - case 2305: // Baked Meat Pie - itemDetailsID = 1605; break; - case 2306: // Sausage Pizza - itemDetailsID = 1606; break; - case 2307: // Cheese Pizza - itemDetailsID = 1607; break; - case 2308: // Baked Fruit Pie - itemDetailsID = 1608; break; - case 2309: // Baked Peach Cobbler - itemDetailsID = 1609; break; - case 2310: // Baked Apple Pie - itemDetailsID = 1610; break; - case 2311: // Baked Pumpkin Pie - itemDetailsID = 1611; break; - case 2400: // Cooked Bird - itemDetailsID = 1650; break; - case 2401: // Chicken Leg - itemDetailsID = 1651; break; - case 2402: // Fish Steak - itemDetailsID = 1652; break; - case 2403: // Fried Eggs - itemDetailsID = 1653; break; - case 2404: // Leg of Lamb - itemDetailsID = 1654; break; - case 2405: // Cut of Ribs - itemDetailsID = 1655; break; - default: - break; + var last = pUser.GetTempTag( "MakeLast_Cooking" ); + if( last ) + pButton = last; + else + return; } - if( makeID != 0 ) + var makeID = 0; + var timerID = 0; + + // Craft buttons use makeID directly + if( CookingMap[pButton] != undefined ) { + makeID = pButton; + var data = CookingMap[makeID]; + timerID = data.timerID || 1; + + // Era / recipe checks + if( !eraOK( data )) + { + socket.SysMessage( "That item is not available in this era." ); + return; + } + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + pUser.SetTempTag( "MakeLast_Cooking", makeID ); + + // Environment checks var makeItem = false; + if( makeID == 1500 ) { - // Grind wheat to flour + // Sack of Flour – wheat grinding if( manualMillTarget ) { // Require player to manually target mill @@ -393,34 +479,38 @@ function onGumpPress( pSock, pButton, gumpData ) { if( ValidateObject( packItem ) && packItem.id == 0x1ebd ) { - // Found wheat item in inventory, ask user where to grind it + // Found wheat; call its onUseChecked TriggerEvent( 101, "onUseChecked", pUser, packItem ); // 101 = wheat.js return; } } + + // No wheat found – just fail silently and let DFN/msg handle it + return; } else { - // Look for nearby dynamic mill - var nearbyMill = AreaItemFunction( "FindNearbyMills", pUser, 2, pSock ); + // Auto mill lookup (dynamic first, then static) + var nearbyMill = AreaItemFunction( "FindNearbyMills", pUser, 2, socket ); if( nearbyMill == 0 ) { - // No dynamic oven found nearby! Look for a static one? var staticFound = false; - for( var i = 0; i < ovens.length; i++ ) + for( var i = 0; i < mills.length; i++ ) { - if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, ovens[i] )) + if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, mills[i] )) { - nearbyMill = 1; + staticFound = true; break; } } + + if( staticFound ) + nearbyMill = 1; } if( nearbyMill > 0 ) { makeItem = true; - pUser.SetTempTag( "MAKELAST", pButton ); } else { @@ -428,41 +518,191 @@ function onGumpPress( pSock, pButton, gumpData ) } } } - else if( makeID >= 1650 && makeID <= 1655 && nearbyHeatSource > 0 ) + else if( makeID >= 1600 && makeID <= 1611 ) { - // Barbecue - makeItem = true; + // Baking – requires oven + var nearbyOven = AreaItemFunction( "FindNearbyOvens", pUser, 2, socket ); + if( nearbyOven > 0 ) + { + makeItem = true; + } + else + { + var staticFoundOven = false; + for( var o = 0; o < ovens.length; o++ ) + { + if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, ovens[o] )) + { + staticFoundOven = true; + break; + } + } + if( !staticFoundOven ) + pUser.SetTempTag( "prevActionResult", "NOOVEN" ); + else + makeItem = true; + } } - else if( makeID >= 1600 && makeID <= 1611 && nearbyOven > 0 ) + else if( makeID >= 1650 && makeID <= 1655 ) { - // Baking - makeItem = true; + // Barbecue – requires generic heat source + var nearbyHeat = AreaItemFunction( "FindNearbyHeatSources", pUser, 2, socket ); + if( nearbyHeat > 0 ) + { + makeItem = true; + } + else + { + var staticFoundHeat = false; + for( var h = 0; h < heatSources.length; h++ ) + { + if( StaticInRange( pUser.x, pUser.y, pUser.worldnumber, 2, heatSources[h] )) + { + staticFoundHeat = true; + break; + } + } + if( !staticFoundHeat ) + pUser.SetTempTag( "prevActionResult", "NOHEATSOURCE" ); + else + makeItem = true; + } } - else if( makeID >= 1501 && makeID <= 1557 ) + else if( ( makeID >= 1501 && makeID <= 1557 ) ) { - // Ingredients/Baking - no heatsource or mill required + // Ingredients & preparations – no heat source or mill required makeItem = true; } if( makeItem ) { - MakeItem( pSock, pUser, makeID ); + MakeItem( socket, pUser, makeID ); + AddToLastTen( pUser, makeID ); + if( GetServerSetting( "ToolUseLimit" )) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + tool.usesLeft -= 1; + if( tool.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + tool.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! } } } - pUser.StartTimer( gumpDelay, timerID, true ); + + pUser.StartTimer( gumpDelay, timerID, cookingID ); + return; + } + + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) + { + var detailMakeID = pButton - 20000; + var entry = CookingMap[detailMakeID]; + + if( entry ) + { + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || cookingSkillID ); + + // Clear old harvest tags + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old custom harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // Optional harvest dictIDs + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } + + // Optional custom names – plug into your new ItemDetail custom text logic + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; + } +} + +// Last Ten handling +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenCooking" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } } - else if( itemDetailsID != 0 ) + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); } + + pUser.SetTempTag( "LastTenCooking", newList.join( "," ) ); } + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file From 20391cad18e0fef143f6515746b72eb493d53cdc Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:40:19 -0600 Subject: [PATCH 30/43] Update cooking.js --- data/js/skill/craft/cooking.js | 62 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/data/js/skill/craft/cooking.js b/data/js/skill/craft/cooking.js index 552c79353..236b78826 100644 --- a/data/js/skill/craft/cooking.js +++ b/data/js/skill/craft/cooking.js @@ -66,43 +66,43 @@ function FindNearbyHeatSources( pUser, trgItem, pSock ) const CookingMap = { // Page 1 - Ingredients - 1500: { dictID: 11606, page: 1, timerID: 1 }, // Sack of Flour - 1501: { dictID: 11607, page: 1, timerID: 1 }, // Dough - 1502: { dictID: 11608, page: 1, timerID: 1 }, // Sweet Dough - 1503: { dictID: 11609, page: 1, timerID: 1 }, // Cake Mix - 1504: { dictID: 11610, page: 1, timerID: 1 }, // Cookie Mix + 1500: { dictID: 11606, page: 1, timerID: 1, harvest: [ 11636 ] }, // Sack of Flour + 1501: { dictID: 11607, page: 1, timerID: 1, harvest: [ 11637, 11638 ] }, // Dough + 1502: { dictID: 11608, page: 1, timerID: 1, harvest: [ 11607, 11639 ] }, // Sweet Dough + 1503: { dictID: 11609, page: 1, timerID: 1, harvest: [ 11637, 11608 ] }, // Cake Mix + 1504: { dictID: 11610, page: 1, timerID: 1, harvest: [ 11639, 11608 ] }, // Cookie Mix // Page 2 - Preparations - 1550: { dictID: 11611, page: 2, timerID: 2 }, // Unbaked Quiche - 1551: { dictID: 11612, page: 2, timerID: 2 }, // Unbaked Meat Pie - 1552: { dictID: 11613, page: 2, timerID: 2 }, // Uncooked Sausage Pizza - 1553: { dictID: 11614, page: 2, timerID: 2 }, // Uncooked Cheese Pizza - 1554: { dictID: 11615, page: 2, timerID: 2 }, // Unbaked Fruit Pie - 1555: { dictID: 11616, page: 2, timerID: 2 }, // Unbaked Peach Cobbler - 1556: { dictID: 11617, page: 2, timerID: 2 }, // Unbaked Apple Pie - 1557: { dictID: 11618, page: 2, timerID: 2 }, // Unbaked Pumpkin Pie + 1550: { dictID: 11611, page: 2, timerID: 2, harvest: [ 11607, 11640 ] }, // Unbaked Quiche + 1551: { dictID: 11612, page: 2, timerID: 2, harvest: [ 11607, 11641 ] }, // Unbaked Meat Pie + 1552: { dictID: 11613, page: 2, timerID: 2, harvest: [ 11607, 11642 ] }, // Uncooked Sausage Pizza + 1553: { dictID: 11614, page: 2, timerID: 2, harvest: [ 11607, 11643 ] }, // Uncooked Cheese Pizza + 1554: { dictID: 11615, page: 2, timerID: 2, harvest: [ 11607, 11644 ] }, // Unbaked Fruit Pie + 1555: { dictID: 11616, page: 2, timerID: 2, harvest: [ 11607, 11645 ] }, // Unbaked Peach Cobbler + 1556: { dictID: 11617, page: 2, timerID: 2, harvest: [ 11607, 11646 ] }, // Unbaked Apple Pie + 1557: { dictID: 11618, page: 2, timerID: 2, harvest: [ 11607, 11647 ] }, // Unbaked Pumpkin Pie // Page 3 - Baking - 1600: { dictID: 11619, page: 3, timerID: 3 }, // Bread Loaf - 1601: { dictID: 11620, page: 3, timerID: 3 }, // Pan of Cookies - 1602: { dictID: 11621, page: 3, timerID: 3 }, // Cake - 1603: { dictID: 11657, page: 3, timerID: 3 }, // Muffins - 1604: { dictID: 11622, page: 3, timerID: 3 }, // Baked Quiche - 1605: { dictID: 11623, page: 3, timerID: 3 }, // Baked Meat Pie - 1606: { dictID: 11624, page: 3, timerID: 3 }, // Sausage Pizza - 1607: { dictID: 11625, page: 3, timerID: 3 }, // Cheese Pizza - 1608: { dictID: 11626, page: 3, timerID: 3 }, // Baked Fruit Pie - 1609: { dictID: 11627, page: 3, timerID: 3 }, // Baked Peach Cobbler - 1610: { dictID: 11628, page: 3, timerID: 3 }, // Baked Apple Pie - 1611: { dictID: 11629, page: 3, timerID: 3 }, // Baked Pumpkin Pie + 1600: { dictID: 11619, page: 3, timerID: 3, harvest: [ 11607 ] }, // Bread Loaf + 1601: { dictID: 11620, page: 3, timerID: 3, harvest: [ 11610 ] }, // Pan of Cookies + 1602: { dictID: 11621, page: 3, timerID: 3, harvest: [ 11609 ] }, // Cake + 1603: { dictID: 11657, page: 3, timerID: 3, harvest: [ 11608 ] }, // Muffins + 1604: { dictID: 11622, page: 3, timerID: 3, harvest: [ 11611 ] }, // Baked Quiche + 1605: { dictID: 11623, page: 3, timerID: 3, harvest: [ 11612 ] }, // Baked Meat Pie + 1606: { dictID: 11624, page: 3, timerID: 3, harvest: [ 11613 ] }, // Sausage Pizza + 1607: { dictID: 11625, page: 3, timerID: 3, harvest: [ 11614 ] }, // Cheese Pizza + 1608: { dictID: 11626, page: 3, timerID: 3, harvest: [ 11615 ] }, // Baked Fruit Pie + 1609: { dictID: 11627, page: 3, timerID: 3, harvest: [ 11616 ] }, // Baked Peach Cobbler + 1610: { dictID: 11628, page: 3, timerID: 3, harvest: [ 11617 ] }, // Baked Apple Pie + 1611: { dictID: 11629, page: 3, timerID: 3, harvest: [ 11618 ] }, // Baked Pumpkin Pie // Page 4 - Barbecue - 1650: { dictID: 11630, page: 4, timerID: 4 }, // Cooked Bird - 1651: { dictID: 11631, page: 4, timerID: 4 }, // Chicken Leg - 1652: { dictID: 11632, page: 4, timerID: 4 }, // Fish Steak - 1653: { dictID: 11633, page: 4, timerID: 4 }, // Fried Eggs - 1654: { dictID: 11634, page: 4, timerID: 4 }, // Leg of Lamb - 1655: { dictID: 11635, page: 4, timerID: 4 } // Cut of Ribs + 1650: { dictID: 11630, page: 4, timerID: 4, harvest: [ 11648 ] }, // Cooked Bird + 1651: { dictID: 11631, page: 4, timerID: 4, harvest: [ 11649 ] }, // Chicken Leg + 1652: { dictID: 11632, page: 4, timerID: 4, harvest: [ 11650 ] }, // Fish Steak + 1653: { dictID: 11633, page: 4, timerID: 4, harvest: [ 11651 ] }, // Fried Eggs + 1654: { dictID: 11634, page: 4, timerID: 4, harvest: [ 11652 ] }, // Leg of Lamb + 1655: { dictID: 11635, page: 4, timerID: 4, harvest: [ 11653 ] } // Cut of Ribs }; // Fill in defaults (skill, etc) From 9720e6e2772deaca54f29f588761c204c4da9621 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:41:28 -0600 Subject: [PATCH 31/43] Update cartography.js --- data/js/skill/craft/cartography.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/js/skill/craft/cartography.js b/data/js/skill/craft/cartography.js index 57f0b88d6..0a92dbd90 100644 --- a/data/js/skill/craft/cartography.js +++ b/data/js/skill/craft/cartography.js @@ -31,10 +31,10 @@ const cartographySkillID = 12; // Skill index for "cartogr const CartographyMap = { // Page 1 - Maps - 2000: { dictID: 13100, page: 1, timerID: 1 }, // Local Map - 2001: { dictID: 13101, page: 1, timerID: 1 }, // City Map - 2002: { dictID: 13102, page: 1, timerID: 1 }, // Sea Chart - 2003: { dictID: 13103, page: 1, timerID: 1 } // World Map (base; world-specific in onGumpPress) + 2000: { dictID: 13100, page: 1, timerID: 1, harvest: [ 13004 ] }, // Local Map + 2001: { dictID: 13101, page: 1, timerID: 1, harvest: [ 13004 ] }, // City Map + 2002: { dictID: 13102, page: 1, timerID: 1, harvest: [ 13004 ] }, // Sea Chart + 2003: { dictID: 13103, page: 1, timerID: 1, harvest: [ 13004 ] } // World Map (base; world-specific in onGumpPress) }; // Fill in defaults (skill, etc) From 65b07c8e04a09f764ea5e338c89db702fce5a9fe Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:58:46 -0600 Subject: [PATCH 32/43] Update fletching.js --- data/js/skill/craft/fletching.js | 629 +++++++++++++++++++++++-------- 1 file changed, 465 insertions(+), 164 deletions(-) diff --git a/data/js/skill/craft/fletching.js b/data/js/skill/craft/fletching.js index d93541437..51b73486c 100644 --- a/data/js/skill/craft/fletching.js +++ b/data/js/skill/craft/fletching.js @@ -1,240 +1,541 @@ /// // @ts-check -const LabelHue = 0x480; // Color of the text. -const LabelColor = 0x7FFF; // Second Color of text. -const scriptID = 4029; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; - -////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// - -const myPage = [ +const textHue = 0x480; // Color of the text. +const fletchingID = 4029; // Script ID for this fletching gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Generic item details gump +const craftGumpID = 4027; // Shared crafting menu frame +const itemsPerPage = 10; // Items per subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const fletchingSkillID = 8; // Index of "bowcraft" in ItemDetailGump skillNames[] + +// o--------------------------------------------------------------------------o +// | FletchingMap | +// o--------------------------------------------------------------------------o +// | Keyed by makeID (create entry ID). | +// | Each entry: | +// | dictID - dictionary entry for row text (11205..11220) | +// | page - main category page (1..3) | +// | timerID - which page timer should reopen | +// | skill - skill used (default: fletchingSkillID) | +// | recipeID? - optional recipe ID | +// | minEra?, maxEra? - optional era gating | +// | harvest?[] - optional dictIDs for MATERIALS list | +// | harvestNames?[] - optional custom material names | +// o--------------------------------------------------------------------------o + +const FletchingMap = { // Page 1 - Materials - [ 11205, 11206, 11207, 11208, 11209 ], + 190: { dictID: 11205, page: 1, timerID: 1, harvest: [ 10014 ] }, // Kindling + 194: { dictID: 11206, page: 1, timerID: 1, harvest: [ 10014 ] }, // Shaft + 195: { dictID: 11207, page: 1, timerID: 1, harvest: [ 10014 ] }, // Five Shafts + 196: { dictID: 11208, page: 1, timerID: 1, harvest: [ 10014 ] }, // Twenty Shafts + 197: { dictID: 11209, page: 1, timerID: 1, harvest: [ 10014 ] }, // Fifty Shafts // Page 2 - Ammunition - [ 11210, 11211, 11212, 11213, 11214, 11215, 11216, 11217 ], + 198: { dictID: 11210, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Arrow + 199: { dictID: 11211, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Five Arrows + 200: { dictID: 11212, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Twenty Arrows + 201: { dictID: 11213, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Fifty Arrows + 202: { dictID: 11214, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Bolt + 203: { dictID: 11215, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Five Bolts + 204: { dictID: 11216, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Twenty Bolts + 205: { dictID: 11217, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Fifty Bolts // Page 3 - Weapons - [ 11218, 11219, 11220 ] -]; + 191: { dictID: 11218, page: 3, timerID: 3, harvest: [ 10014 ] }, // Bow + 192: { dictID: 11219, page: 3, timerID: 3, harvest: [ 10014 ] }, // Crossbow + 193: { dictID: 11220, page: 3, timerID: 3, harvest: [ 10014 ] } // Heavy Crossbow +}; + +// Fill in defaults (skill, etc) +(function initFletchingMap() +{ + for( var key in FletchingMap ) + { + if( !FletchingMap.hasOwnProperty( key )) + continue; + var entry = FletchingMap[key]; + + if( entry.skill === undefined ) + entry.skill = fletchingSkillID; + + // In future you can do: + // entry.harvest = [ woodDictID, featherDictID ]; + // entry.harvestNames = [ "Wood", "Feathers" ]; + } +})(); + +// o--------------------------------------------------------------------------o +// | PageX() - build a page of fletching items | +// o--------------------------------------------------------------------------o +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) { - // Pages 1 - 3 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for ( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // Last Ten page (only if you wire a tab to 999 later) + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenFletching" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); + } + } + else { - var index = i % 10; - if ( index == 0 ) + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in FletchingMap ) { - if ( i > 0 ) + if( !FletchingMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = FletchingMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) + { + var ea = FletchingMap[a]; + var eb = FletchingMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = FletchingMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) ) + pageItems.push( id ); + } + + // Fallback: if no items on this page and it's not page 1, go to page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; + + makeIDs = []; + for( var key2 in FletchingMap ) + { + if( !FletchingMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = FletchingMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; + + makeIDs.push( mid2 ); + } + + makeIDs.sort( function( a, b ) + { + var ea2 = FletchingMap[a]; + var eb2 = FletchingMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + var id2 = makeIDs[m]; + var data4 = FletchingMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 )) ) + pageItems.push( id2 ); } + } + } - myGump.AddPage( ( i / 10 ) + 1 ); + // Subpage handling (future-proof; currently only 1 subpage per page) + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); - if ( i > 0 ) + if( totalSubPages < 1 ) + totalSubPages = 1; + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var fletchGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", fletchGump, socket ); + fletchGump.AddPage( 1 ); + + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // use makeID directly as buttonID + + var data5 = FletchingMap[makeID]; + + if( !data5 ) + { + entryText = "[Missing MakeID: " + makeID + "]"; + } + else + { + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + entryText = "[Unnamed Item: " + makeID + "]"; } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language ) ); + // Craft button uses makeID + fletchGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + fletchGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + // Detail button: 20000 + makeID + fletchGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); } - myGump.Send( socket ); - myGump.Free(); + + // Prev subpage + if( subPage > 1 ) + { + fletchGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + fletchGump.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + + // Next subpage + if( subPage < totalSubPages ) + { + fletchGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + fletchGump.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + fletchGump.Send( socket ); + fletchGump.Free(); } -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +/** @type { ( pUser: Character, timerID: number ) => void } */ function onTimer( pUser, timerID ) { if( !ValidateObject( pUser )) return; - var socket = pUser.socket; + var pSocket = pUser.socket; + if( pSocket == null ) + return; - switch ( timerID ) + if( timerID >= 1 && timerID <= 3 ) { - case 1: // Page 1 - Materials - case 2: // Page 2 - Ammunition - case 3: // Page 3 - Weapons - PageX( socket, pUser, timerID ); - break; + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); } } -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) { - var pUser = pSock.currentChar; + if( socket == null ) + return; - // Don't continue if character is invalid, or worse... dead! + var pUser = socket.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + var tool = socket.tempObj; + if( !ValidateObject( tool ) || !pUser.InRange( tool, 3 )) { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. return; } - if( bItem.movable == 3 ) + if( tool.movable == 3 ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! return; } - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + var packOwner = GetPackOwner( tool, 0 ); + if( ValidateObject( packOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( packOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That resource is in someone else's backpack! return; } } else { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This has to be in your backpack before you can use it. + return; + } + + var gumpID = fletchingID + 0xffff; + + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) + { + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; + } + + if( pButton >= 9001 && pButton < 10000 ) + { + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; + } + + // Page tabs (1–3: Materials, Ammunition, Weapons) + if( pButton >= 1 && pButton <= 3 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; + } + + // Last Ten (if you wire a tab to this) + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Fletching", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); return; } - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; + // Make Last + if( pButton == 5000 ) + { + var last = pUser.GetTempTag( "MakeLast_Fletching" ); + if( last ) + pButton = last; + else + return; + } + + var makeID = 0; var timerID = 0; - if(( pButton >= 100 && pButton <= 302 ) || pButton == 5000 ) + // Craft buttons use makeID directly + if( FletchingMap[pButton] != undefined ) { - if( pButton == 5000 ) + makeID = pButton; + var data = FletchingMap[makeID]; + timerID = data.timerID || 1; + + // Era / recipe checks + if( !eraOK( data )) { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); + socket.SysMessage( "That item is not available in this era." ); + return; } - else + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) { - pUser.SetTempTag( "MAKELAST", pButton ); + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; } - } - switch ( pButton ) - { - case 0: // Abort and do nothing - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break; - case 1: // Page 1 - Materials - case 2: // Page 2 - Ammunition - case 3: // Page 3 - Weapons - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - // Make Items - case 100: // Kindling - makeID = 190; timerID = 1; break; - case 101: // Shaft - makeID = 194; timerID = 1; break; - case 102: // Five Shafts - makeID = 195; timerID = 1; break; - case 103: // Twenty Shafts - makeID = 196; timerID = 1; break; - case 104: // Fifty Shafts - makeID = 197; timerID = 1; break; - case 200: // Arrow - makeID = 198; timerID = 2; break; - case 201: // Five Arrows - makeID = 199; timerID = 2; break; - case 202: // Twenty Arrows - makeID = 200; timerID = 2; break; - case 203: // Fifty Arrows - makeID = 201; timerID = 2; break; - case 204: // Bolt - makeID = 202; timerID = 2; break; - case 205: // Five Bolts - makeID = 203; timerID = 2; break; - case 206: // Twenty Bolts - makeID = 204; timerID = 2; break; - case 207: // Fifty Bolts - makeID = 205; timerID = 2; break; - case 300: // Bow - makeID = 191; timerID = 3; break; - case 301: // Crossbow - makeID = 192; timerID = 3; break; - case 302: // Heavy Crossbow - makeID = 193; timerID = 3; break; - // Show Item Details - case 2100: // Kindling - itemDetailsID = 190; break; - case 2101: // Shaft - itemDetailsID = 194; break; - case 2102: // Five Shafts - itemDetailsID = 195; break; - case 2103: // Twenty Shafts - itemDetailsID = 196; break; - case 2104: // Fifty Shafts - itemDetailsID = 197; break; - case 2200: // Arrow - itemDetailsID = 198; break; - case 2201: // Five Arrows - itemDetailsID = 199; break; - case 2202: // Twenty Arrows - itemDetailsID = 200; break; - case 2203: // Fifty Arrows - itemDetailsID = 201; break; - case 2204: // Bolt - itemDetailsID = 202; break; - case 2205: // Five Bolts - itemDetailsID = 203; break; - case 2206: // Twenty Bolts - itemDetailsID = 204; break; - case 2207: // Fifty Bolts - itemDetailsID = 205; break; - case 2300: // Bow - itemDetailsID = 191; break; - case 2301: // Crossbow - itemDetailsID = 192; break; - case 2302: // Heavy Crossbow - itemDetailsID = 193; break; - default: - break; + pUser.SetTempTag( "MakeLast_Fletching", makeID ); + + MakeItem( socket, pUser, makeID ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + tool.usesLeft -= 1; + if( tool.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + { + tool.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! + } + } + + pUser.StartTimer( gumpDelay, timerID, fletchingID ); + return; } - if( makeID != 0 ) + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) { - MakeItem( pSock, pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) + var detailMakeID = pButton - 20000; + var entry = FletchingMap[detailMakeID]; + + if( entry ) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || fletchingSkillID ); + + // Clear old harvest tags + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old custom harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // Optional harvest dictIDs + if( entry.harvest && entry.harvest.length > 0 ) { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); } - } - pUser.StartTimer( gumpDelay, timerID, true ); + + // Optional custom names – plugs into your ItemDetail custom harvest name logic + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; + } +} + +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenFletching" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } } - else if( itemDetailsID != 0 ) + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); } + + pUser.SetTempTag( "LastTenFletching", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; } From b744614427046c0be407f368d526333b34ce1487 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:42:31 -0600 Subject: [PATCH 33/43] Update tinkering.js --- data/js/skill/craft/tinkering.js | 1064 ++++++++++++++++-------------- 1 file changed, 579 insertions(+), 485 deletions(-) diff --git a/data/js/skill/craft/tinkering.js b/data/js/skill/craft/tinkering.js index dfb4b3623..c1ab673e5 100644 --- a/data/js/skill/craft/tinkering.js +++ b/data/js/skill/craft/tinkering.js @@ -1,538 +1,584 @@ /// // @ts-check -const LabelHue = 0x480; // Color of the text. -const LabelColor = 0x7FFF; // Second Color of text. -const scriptID = 4032; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; - -////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// - -const myPage = [ +const textHue = 0x480; // Color of the text. +const tinkeringID = 4032; // Script ID for this tinkering gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Generic item details gump +const craftGumpID = 4027; // Shared crafting menu frame +const itemsPerPage = 10; // Items per subpage +const displayUnlearnedRecipes = true; // For future recipe use +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const tinkeringSkillID = 37; // Index of "tinkering" in ItemDetailGump.skillNames[] + +// o--------------------------------------------------------------------------o +// | TinkeringMap | +// o--------------------------------------------------------------------------o +// | Keyed by makeID (create entry ID). | +// | Each entry: | +// | dictID - dictionary entry for row text (11801..11982) | +// | page - main category page (1..9) | +// | timerID - which page timer should reopen | +// | skill - skill used (default: tinkeringSkillID) | +// | recipeID? - optional recipe ID | +// | minEra?, maxEra? - optional era gating | +// | harvest?[] - optional dictIDs for MATERIALS list | +// | harvestNames?[] - optional custom material names | +// | requiresGemTarget? - jewelry requiring manual gem selection | +// o--------------------------------------------------------------------------o + +const TinkeringMap = { // Page 1 - Wooden Items - [ 11801, 11802, 11803, 11804, 11805 ], + 274: { dictID: 11801, page: 1, timerID: 1, harvest: [ 10014 ] }, // Axle + 273: { dictID: 11802, page: 1, timerID: 1, harvest: [ 10014 ] }, // Clock Frame + 270: { dictID: 11803, page: 1, timerID: 1, harvest: [ 10014 ] }, // Jointing Plane + 271: { dictID: 11804, page: 1, timerID: 1, harvest: [ 10014 ] }, // Moulding Plane + 272: { dictID: 11805, page: 1, timerID: 1, harvest: [ 10014 ] }, // Smoothing Plane // Page 2 - Tools - [ 11820, 11821, 11822, 11823, 11824, 11825, 11826, 11827, 11828, 11829, 11830, 11831, 11832, 11833, 11834, 11835, 11836, 11837, 11838 ], + 218: { dictID: 11820, page: 2, timerID: 2, harvest: [ 10015 ] }, // Dovetail Saw + 215: { dictID: 11821, page: 2, timerID: 2, harvest: [ 10015 ] }, // Draw Knife + 252: { dictID: 11822, page: 2, timerID: 2, harvest: [ 10015 ] }, // Froe + 255: { dictID: 11823, page: 2, timerID: 2, harvest: [ 10015 ] }, // Hammer + 214: { dictID: 11824, page: 2, timerID: 2, harvest: [ 10015 ] }, // Hatchet + 258: { dictID: 11825, page: 2, timerID: 2, harvest: [ 10015 ] }, // Inshave + 260: { dictID: 11826, page: 2, timerID: 2, harvest: [ 10015 ] }, // Lockpick + 211: { dictID: 11827, page: 2, timerID: 2, harvest: [ 10015 ] }, // Mortar and Pestle + 259: { dictID: 11828, page: 2, timerID: 2, harvest: [ 10015 ] }, // Pick Axe + 217: { dictID: 11829, page: 2, timerID: 2, harvest: [ 10015 ] }, // Saw + 210: { dictID: 11830, page: 2, timerID: 2, harvest: [ 10015 ] }, // Scissors + 212: { dictID: 11831, page: 2, timerID: 2, harvest: [ 10015 ] }, // Scorp + 216: { dictID: 11832, page: 2, timerID: 2, harvest: [ 10015 ] }, // Sewing Kit + 254: { dictID: 11833, page: 2, timerID: 2, harvest: [ 10015 ] }, // Shovel + 257: { dictID: 11834, page: 2, timerID: 2, harvest: [ 10015 ] }, // Sledge Hammer + 256: { dictID: 11835, page: 2, timerID: 2, harvest: [ 10015 ] }, // Smith's Hammer + 253: { dictID: 11836, page: 2, timerID: 2, harvest: [ 10015 ] }, // Tongs + 213: { dictID: 11837, page: 2, timerID: 2, harvest: [ 10015 ] }, // Tool Kit (Tinker's tools) + 284: { dictID: 11838, page: 2, timerID: 2, harvest: [ 10015 ] }, // Fletcher's Tools // Page 3 - Parts - [ 11860, 11861, 11862, 11863, 11864, 11865, 11866 ], + 224: { dictID: 11860, page: 3, timerID: 3, harvest: [ 10015 ] }, // Barrel Hoops + 221: { dictID: 11861, page: 3, timerID: 3, harvest: [ 10015 ] }, // Barrel Tap + 220: { dictID: 11862, page: 3, timerID: 3, harvest: [ 10015 ] }, // Clock parts + 219: { dictID: 11863, page: 3, timerID: 3, harvest: [ 10015 ] }, // Gears + 225: { dictID: 11864, page: 3, timerID: 3, harvest: [ 10015 ] }, // Hinge + 223: { dictID: 11865, page: 3, timerID: 3, harvest: [ 10015 ] }, // Sextant parts + 222: { dictID: 11866, page: 3, timerID: 3, harvest: [ 10015 ] }, // Springs // Page 4 - Utensils - [ 11880, 11881, 11882, 11883, 11884, 11885, 11886, 11887, 11888, 11889, 11890, 11891 ], - - // Page 5 - Jewelry - [ 11900, 11901, 11902, 11903, 11904, 11905 ], - - // Page 6 - Miscellaneuos - [ 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927 ], + 226: { dictID: 11880, page: 4, timerID: 4, harvest: [ 10015 ] }, // Butcher Knife + 232: { dictID: 11881, page: 4, timerID: 4, harvest: [ 10015 ] }, // Cleaver + 230: { dictID: 11882, page: 4, timerID: 4, harvest: [ 10015 ] }, // Fork + 231: { dictID: 11883, page: 4, timerID: 4, harvest: [ 10015 ] }, // Fork + 235: { dictID: 11884, page: 4, timerID: 4, harvest: [ 10015 ] }, // Goblet + 233: { dictID: 11885, page: 4, timerID: 4, harvest: [ 10015 ] }, // Knife + 234: { dictID: 11886, page: 4, timerID: 4, harvest: [ 10015 ] }, // Knife + 236: { dictID: 11887, page: 4, timerID: 4, harvest: [ 10015 ] }, // Pewter Mug + 229: { dictID: 11888, page: 4, timerID: 4, harvest: [ 10015 ] }, // Plate + 237: { dictID: 11889, page: 4, timerID: 4, harvest: [ 10015 ] }, // Skinning Knife + 227: { dictID: 11890, page: 4, timerID: 4, harvest: [ 10015 ] }, // Spoon + 228: { dictID: 11891, page: 4, timerID: 4, harvest: [ 10015 ] }, // Spoon + + // Page 5 - Jewelry (gem-targeted) + 243: { dictID: 11900, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Bracelet + 241: { dictID: 11901, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Earrings + 239: { dictID: 11902, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Golden beads) + 240: { dictID: 11903, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Silver beads) + 242: { dictID: 11904, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Round) + 238: { dictID: 11905, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12006 ] }, // Weddingband (newbiefied) + + // Page 6 - Miscellaneous + 245: { dictID: 11920, page: 6, timerID: 6, harvest: [ 10015, 12000 ] }, // Candelabra (also appears in Candles page in old script) + 248: { dictID: 11921, page: 6, timerID: 6, harvest: [ 10015 ] }, // Globe + 251: { dictID: 11922, page: 6, timerID: 6, harvest: [ 10015 ] }, // Heating stand + 247: { dictID: 11923, page: 6, timerID: 6, harvest: [ 10015 ] }, // Iron Key + 244: { dictID: 11924, page: 6, timerID: 6, harvest: [ 10015 ] }, // Keyring + 250: { dictID: 11925, page: 6, timerID: 6, harvest: [ 10015 ] }, // Lantern + 246: { dictID: 11926, page: 6, timerID: 6, harvest: [ 10015 ] }, // Scales + 249: { dictID: 11927, page: 6, timerID: 6, harvest: [ 10015 ] }, // Spy glass // Page 7 - Multi-Component Items - [ 11940, 11941, 11942, 11943, 11946, 11947, 11948 ], + 275: { dictID: 11940, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Axle and Gears + 276: { dictID: 11941, page: 7, timerID: 7, harvest: [ 11802, 11862 ] }, // Clock + 277: { dictID: 11942, page: 7, timerID: 7, harvest: [ 11802, 11862 ] }, // Clock + 278: { dictID: 11943, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Clock Parts + 279: { dictID: 11944, page: 7, timerID: 7, harvest: [ 10634 ] }, // Locked Box + 280: { dictID: 11945, page: 7, timerID: 7, harvest: [ 10638 ] }, // Locked Chest + 281: { dictID: 11946, page: 7, timerID: 7, harvest: [ 10642, 11861, 10612, 10928 ] }, // Potion Keg + 282: { dictID: 11947, page: 7, timerID: 7, harvest: [ 11948 ] }, // Sextant + 283: { dictID: 11948, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Sextant Parts // Page 8 - Candles - [ 11960, 11961, 11962, 11963, 11964, 11965, 11966, 11967 ], + // NOTE: in the original script, Candelabra (245) appears here too. + // To avoid conflicts (map is keyed by makeID), this page uses the + // actual candle-specific items only. + 310: { dictID: 11961, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Standing Candelabra + 315: { dictID: 11962, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Regular Candle + 312: { dictID: 11963, page: 8, timerID: 8, harvest: [ 12000 ] }, // Round Candle + 316: { dictID: 11964, page: 8, timerID: 8, harvest: [ 12000, 12004 ] }, // Skull with Candle + 314: { dictID: 11965, page: 8, timerID: 8, harvest: [ 12000 ] }, // Small Candle + 311: { dictID: 11966, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Tall Candle + 313: { dictID: 11967, page: 8, timerID: 8, harvest: [ 12000 ] }, // Thick Candle // Page 9 - Traps - [ 11980, 11981, 11982 ] -]; + 261: { dictID: 11980, page: 9, timerID: 9, harvest: [ 10015, 12001 ] }, // Dart Trap + 263: { dictID: 11981, page: 9, timerID: 9, harvest: [ 10015, 12003 ] }, // Explosion Trap + 262: { dictID: 11982, page: 9, timerID: 9, harvest: [ 10015, 12002 ] } // Poison Trap +}; + +// Fill in defaults (skill, etc) +(function initTinkeringMap() +{ + for( var key in TinkeringMap ) + { + if( !TinkeringMap.hasOwnProperty( key )) + continue; + + var entry = TinkeringMap[key]; + if( entry.skill === undefined ) + entry.skill = tinkeringSkillID; + + // In future you can do e.g.: + // entry.harvest = [ woodDictID, ingotDictID ]; + // entry.harvestNames = [ "Wood", "Ingots" ]; + } +})(); + +// o--------------------------------------------------------------------------o +// | PageX() - build a page of tinkering items | +// o--------------------------------------------------------------------------o +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) { - // Pages 1 - 9 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for ( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // Last Ten page (if you wire a tab to 999 later) + if( pageNum == 999 ) { - var index = i % 10; - if ( index == 0 ) + var lastTenRaw = pUser.GetTempTag( "LastTenTinkering" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) { - if ( i > 0 ) + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); + } + } + else + { + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in TinkeringMap ) + { + if( !TinkeringMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = TinkeringMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) + { + var ea = TinkeringMap[a]; + var eb = TinkeringMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = TinkeringMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) ) + pageItems.push( id ); + } + + // Fallback: if no items on this page and it's not page 1, go to page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; + + makeIDs = []; + for( var key2 in TinkeringMap ) + { + if( !TinkeringMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = TinkeringMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; + + makeIDs.push( mid2 ); + } + + makeIDs.sort( function( a, b ) + { + var ea2 = TinkeringMap[a]; + var eb2 = TinkeringMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + var id2 = makeIDs[m]; + var data4 = TinkeringMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 )) ) + pageItems.push( id2 ); } + } + } + + // Subpage handling (future-proof; currently you effectively have 1 or 2 subpages per category) + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( totalSubPages < 1 ) + totalSubPages = 1; + if( subPage < 1 ) + subPage = 1; + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); - myGump.AddPage( ( i / 10 ) + 1 ); + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); - if ( i > 0 ) + if( startIndex >= pageItems.length ) + { + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); + } + + var tinkGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", tinkGump, socket ); + tinkGump.AddPage( 1 ); + + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // use makeID directly as buttonID + + var data5 = TinkeringMap[makeID]; + + if( !data5 ) + { + entryText = "[Missing MakeID: " + makeID + "]"; + } + else + { + if( data5.customName ) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; } } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language ) ); + // Craft button + tinkGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + tinkGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + // Detail button: 20000 + makeID + tinkGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); } - myGump.Send( socket ); - myGump.Free(); + + // Prev subpage + if( subPage > 1 ) + { + tinkGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + tinkGump.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + + // Next subpage + if( subPage < totalSubPages ) + { + tinkGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + tinkGump.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + tinkGump.Send( socket ); + tinkGump.Free(); } -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +/** @type { ( pUser: Character, timerID: number ) => void } */ function onTimer( pUser, timerID ) { if( !ValidateObject( pUser )) return; - var socket = pUser.socket; + var pSocket = pUser.socket; + if( pSocket == null ) + return; - switch ( timerID ) + if( timerID >= 1 && timerID <= 9 ) { - case 1: // Page 1 - Wooden Items - case 2: // Page 2 - Tools - case 3: // Page 3 - Parts - case 4: // Page 4 - Utensils - case 5: // Page 5 - Jewelry - case 6: // Page 6 - Miscellaneous - case 7: // Page 7 - Multi-Component Items - case 8: // Page 8 - Candles - case 9: // Page 9 - Traps - PageX( socket, pUser, timerID ); - break; + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); } } -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) { - var pUser = pSock.currentChar; + if( socket == null ) + return; - // Don't continue if character is invalid, or worse... dead! + var pUser = socket.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + var tool = socket.tempObj; + if( !ValidateObject( tool ) || !pUser.InRange( tool, 3 )) { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. return; } - if( bItem.movable == 3 ) + if( tool.movable == 3 ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! return; } - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + var packOwner = GetPackOwner( tool, 0 ); + if( ValidateObject( packOwner )) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? + if( packOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That resource is in someone else's backpack! return; } } else { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This has to be in your backpack before you can use it. return; } - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var timerID = 0; + var gumpID = tinkeringID + 0xffff; - if(( pButton >= 100 && pButton <= 950 ) || pButton == 5000 ) + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) { - if( pButton == 5000 ) - { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); - } - else - { - pUser.SetTempTag( "MAKELAST", pButton ); - } + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; } - switch ( pButton ) + if( pButton >= 9001 && pButton < 10000 ) { - case 0: // Abort and do nothing - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break; - case 1: // Page 1 - Wooden Items - case 2: // Page 2 - Tools - case 3: // Page 3 - Parts - case 4: // Page 4 - Utensils - case 5: // Page 5 - Jewelry - case 6: // Page 6 - Miscellaneous - case 7: // Page 7 - Multi-Component Items - case 8: // Page 8 - Candles - case 9: // Page 9 - Traps - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - // Make Items - // Page 1 - Wooden Items - case 100: // Axle - makeID = 274; timerID = 1; break; - case 101: // Clock Frame - makeID = 273; timerID = 1; break; - case 102: // Jointing Plane - makeID = 270; timerID = 1; break; - case 103: // Moulding Plane - makeID = 271; timerID = 1; break; - case 104: // Smoothing Plane - makeID = 272; timerID = 1; break; - // Page 2 - Tools - case 200: // Dovetail Saw - makeID = 218; timerID = 2; break; - case 201: // Draw Knife - makeID = 215; timerID = 2; break; - case 202: // Froe - makeID = 252; timerID = 2; break; - case 203: // Hammer - makeID = 255; timerID = 2; break; - case 204: // Hatchet - makeID = 214; timerID = 2; break; - case 205: // Inshave - makeID = 258; timerID = 2; break; - case 206: // Lockpick - makeID = 260; timerID = 2; break; - case 207: // Mortar and Pestle - makeID = 211; timerID = 2; break; - case 208: // Pick Axe - makeID = 259; timerID = 2; break; - case 209: // Saw - makeID = 217; timerID = 2; break; - case 210: // Scissors - makeID = 210; timerID = 2; break; - case 211: // Scorp - makeID = 212; timerID = 2; break; - case 212: // Sewing Kit - makeID = 216; timerID = 2; break; - case 213: // Shovel - makeID = 254; timerID = 2; break; - case 214: // Sledge Hammer - makeID = 257; timerID = 2; break; - case 215: // Smith's Hammer - makeID = 256; timerID = 2; break; - case 216: // Tongs - makeID = 253; timerID = 2; break; - case 217: // Tool Kit (Tinker's tools) - makeID = 213; timerID = 2; break; - case 218: // Fletcher's Tools - makeID = 284; timerID = 2; break; - // Page 3 - Parts - case 300: // Barrel Hoops - makeID = 224; timerID = 3; break; - case 301: // Barrel Tap - makeID = 221; timerID = 3; break; - case 302: // Clock parts - makeID = 220; timerID = 3; break; - case 303: // Gears - makeID = 219; timerID = 3; break; - case 304: // Hinge - makeID = 225; timerID = 3; break; - case 305: // Sextant parts - makeID = 223; timerID = 3; break; - case 306: // Springs - makeID = 222; timerID = 3; break; - // Page 4 - Utensils - case 400: // Butcher Knife - makeID = 226; timerID = 4; break; - case 401: // Cleaver - makeID = 232; timerID = 4; break; - case 402: // Fork - makeID = 230; timerID = 4; break; - case 403: // Fork - makeID = 231; timerID = 4; break; - case 404: // Goblet - makeID = 235; timerID = 4; break; - case 405: // Knife - makeID = 233; timerID = 4; break; - case 406: // Knife - makeID = 234; timerID = 4; break; - case 407: // Pewter Mug - makeID = 236; timerID = 4; break; - case 408: // Plate - makeID = 229; timerID = 4; break; - case 409: // Skinning Knife - makeID = 237; timerID = 4; break; - case 410: // Spoon - makeID = 227; timerID = 4; break; - case 411: // Spoon - makeID = 228; timerID = 4; break; - // Page 5 - Jewelry - case 500: // Bracelet - makeID = 243; timerID = 5; break; - case 501: // Earrings - makeID = 241; timerID = 5; break; - case 502: // Necklage (Golden beads) - makeID = 239; timerID = 5; break; - case 503: // Necklace (Silver beads) - makeID = 240; timerID = 5; break; - case 504: // Necklace (Round) - makeID = 242; timerID = 5; break; - case 505: // Weddingband (newbiefied) - makeID = 238; timerID = 5; break; - // Page 6 - Miscellaneous - case 600: // Candelabra - makeID = 245; timerID = 6; break; - case 601: // Globe - makeID = 248; timerID = 6; break; - case 602: // Heating stand - makeID = 251; timerID = 6; break; - case 603: // Iron Key - makeID = 247; timerID = 6; break; - case 604: // Keyring - makeID = 244; timerID = 6; break; - case 605: // Lantern - makeID = 250; timerID = 6; break; - case 606: // Scales - makeID = 246; timerID = 6; break; - case 607: // Spy glass - makeID = 249; timerID = 6; break; - // Page 7 - Multi-Component Items - case 700: // Axle and Gears - makeID = 275; timerID = 7; break; - case 701: // Clock - makeID = 276; timerID = 7; break; - case 702: // Clock - makeID = 277; timerID = 7; break; - case 703: // Clock Parts - makeID = 278; timerID = 7; break; - case 704: // Potion Keg - makeID = 281; timerID = 7; break; - case 705: // Sextant - makeID = 282; timerID = 7; break; - case 706: // Sextant Parts - makeID = 283; timerID = 7; break; - // Page 8 - Candles - case 800: // Candelabra - makeID = 245; timerID = 8; break; - case 801: // Standing Candelabra - makeID = 310; timerID = 8; break; - case 802: // Regular Candle - makeID = 315; timerID = 8; break; - case 803: // Round Candle - makeID = 312; timerID = 8; break; - case 804: // Skull with Candle - makeID = 316; timerID = 8; break; - case 805: // Small Candle - makeID = 314; timerID = 8; break; - case 806: // Tall Candle - makeID = 311; timerID = 8; break; - case 807: // Thick Candle - makeID = 313; timerID = 8; break; - // Page 9 - Traps - case 900: // Dart Trap - makeID = 261; timerID = 9; break; - case 901: // Explosion Trap - makeID = 263; timerID = 9; break; - case 902: // Poison Trap - makeID = 262; timerID = 9; break; - // Show Item Details - case 2100: // Axle - itemDetailsID = 274; break; - case 2101: // Clock Frame - itemDetailsID = 273; break; - case 2102: // Jointing Plane - itemDetailsID = 270; break; - case 2103: // Moulding Plane - itemDetailsID = 271; break; - case 2104: // Smoothing Plane - itemDetailsID = 272; break; - // Page 2 - Tools - case 2200: // Dovetail Saw - itemDetailsID = 218; break; - case 2201: // Draw Knife - itemDetailsID = 215; break; - case 2202: // Froe - itemDetailsID = 252; break; - case 2203: // Hammer - itemDetailsID = 255; break; - case 2204: // Hatchet - itemDetailsID = 214; break; - case 2205: // Inshave - itemDetailsID = 258; break; - case 2206: // Lockpick - itemDetailsID = 260; break; - case 2207: // Mortar and Pestle - itemDetailsID = 211; break; - case 2208: // Pick Axe - itemDetailsID = 259; break; - case 2209: // Saw - itemDetailsID = 217; break; - case 2210: // Scissors - itemDetailsID = 210; break; - case 2211: // Scorp - itemDetailsID = 212; break; - case 2212: // Sewing Kit - itemDetailsID = 216; break; - case 2213: // Shovel - itemDetailsID = 254; break; - case 2214: // Sledge Hammer - itemDetailsID = 257; break; - case 2215: // Smith's Hammer - itemDetailsID = 256; break; - case 2216: // Tongs - itemDetailsID = 253; break; - case 2217: // Tool Kit (Tinker's tools) - itemDetailsID = 213; break; - case 2218: // Fletcher's Tools - itemDetailsID = 284; break; - // Page 3 - Parts - case 2300: // Barrel Hoops - itemDetailsID = 224; break; - case 2301: // Barrel Tap - itemDetailsID = 221; break; - case 2302: // Clock parts - itemDetailsID = 220; break; - case 2303: // Gears - itemDetailsID = 219; break; - case 2304: // Hinge - itemDetailsID = 225; break; - case 2305: // Sextant parts - itemDetailsID = 223; break; - case 2306: // Springs - itemDetailsID = 222; break; - // Page 4 - Utensils - case 2400: // Butcher Knife - itemDetailsID = 226; break; - case 2401: // Cleaver - itemDetailsID = 232; break; - case 2402: // Fork - itemDetailsID = 230; break; - case 2403: // Fork - itemDetailsID = 231; break; - case 2404: // Goblet - itemDetailsID = 235; break; - case 2405: // Knife - itemDetailsID = 233; break; - case 2406: // Knife - itemDetailsID = 234; break; - case 2407: // Pewter Mug - itemDetailsID = 236; break; - case 2408: // Plate - itemDetailsID = 229; break; - case 2409: // Skinning Knife - itemDetailsID = 237; break; - case 2410: // Spoon - itemDetailsID = 227; break; - case 2411: // Spoon - itemDetailsID = 228; break; - // Page 5 - Jewelry - case 2500: // Bracelet - itemDetailsID = 243; break; - case 2501: // Earrings - itemDetailsID = 241; break; - case 2502: // Necklage (Golden beads) - itemDetailsID = 239; break; - case 2503: // Necklace (Silver beads) - itemDetailsID = 240; break; - case 2504: // Necklace (Round) - itemDetailsID = 242; break; - case 2505: // Weddingband (newbiefied) - itemDetailsID = 238; break; - // Page 6 - Miscellaneous - case 2600: // Candelabra - itemDetailsID = 245; break; - case 2601: // Globe - itemDetailsID = 248; break; - case 2602: // Heating stand - itemDetailsID = 251; break; - case 2603: // Iron Key - itemDetailsID = 247; break; - case 2604: // Keyring - itemDetailsID = 244; break; - case 2605: // Lantern - itemDetailsID = 250; break; - case 2606: // Scales - itemDetailsID = 246; break; - case 2607: // Spy glass - itemDetailsID = 249; break; - // Page 7 - Multi-Component Items - case 2700: // Axle and Gears - itemDetailsID = 275; break; - case 2701: // Clock - itemDetailsID = 276; break; - case 2702: // Clock - itemDetailsID = 277; break; - case 2703: // Clock Parts - itemDetailsID = 278; break; - case 2704: // Potion Keg - itemDetailsID = 281; break; - case 2705: // Sextant - itemDetailsID = 282; break; - case 2706: // Sextant Parts - itemDetailsID = 283; break; - // Page 8 - Candles - case 2800: // Candelabra - itemDetailsID = 245; break; - case 2801: // Standing Candelabra - itemDetailsID = 310; break; - case 2802: // Regular Candle - itemDetailsID = 315; break; - case 2803: // Round Candle - itemDetailsID = 312; break; - case 2804: // Skull with Candle - itemDetailsID = 316; break; - case 2805: // Small Candle - itemDetailsID = 314; break; - case 2806: // Tall Candle - itemDetailsID = 311; break; - case 2807: // Thick Candle - itemDetailsID = 313; break; - // Page 9 - Traps - case 2900: // Dart Trap - itemDetailsID = 261; break; - case 2901: // Explosion Trap - itemDetailsID = 263; break; - case 2902: // Poison Trap - itemDetailsID = 262; break; - default: - break; + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; + } + + // Page tabs (1–9) + if( pButton >= 1 && pButton <= 9 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; + } + + // Last Ten (if you add a tab that sends 11000) + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Tinkering", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); + return; } - if( makeID != 0 ) + // Make Last + if( pButton == 5000 ) { - if(( pButton >= 500 && pButton <= 505 )) + var last = pUser.GetTempTag( "MakeLast_Tinkering" ); + if( last ) + pButton = last; + else + return; + } + + var makeID = 0; + var timerID = 0; + + // Craft buttons use makeID directly + if( TinkeringMap[pButton] != undefined ) + { + makeID = pButton; + var data = TinkeringMap[makeID]; + timerID = data.timerID || 1; + + // Era / recipe checks + if( !eraOK( data )) + { + socket.SysMessage( "That item is not available in this era." ); + return; + } + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + // Jewelry that needs gem targeting + if( data.requiresGemTarget ) { - // Ask crafter which material to use pUser.SetTempTag( "makeID", makeID ); pUser.SetTempTag( "timerID", timerID ); - pUser.AddScriptTrigger( 4033 ); - pSock.CustomTarget( 2, GetDictionaryEntry( 12008, pSock.language )); // Select material to use: + pUser.AddScriptTrigger( 4033 ); // crafting_complete.js + socket.CustomTarget( 2, GetDictionaryEntry( 12008, socket.language )); // Select material to use: return; } - MakeItem( pSock, pUser, makeID ); + // Normal craft + pUser.SetTempTag( "MakeLast_Tinkering", makeID ); + + MakeItem( socket, pUser, makeID ); + AddToLastTen( pUser, makeID ); + if( GetServerSetting( "ToolUseLimit" )) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + tool.usesLeft -= 1; + if( tool.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + tool.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! } - } - pUser.StartTimer( gumpDelay, timerID, true ); + } + + pUser.StartTimer( gumpDelay, timerID, tinkeringID ); + return; } - else if( itemDetailsID != 0 ) + + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + var detailMakeID = pButton - 20000; + var entry = TinkeringMap[detailMakeID]; + + if( entry ) + { + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || tinkeringSkillID ); + + // Clear old harvest tags + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old custom harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // Optional harvest dictIDs + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } + + // Optional custom names – plugs into your ItemDetail custom harvest name logic + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; } } -/** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ +/** @type { ( pSock: Socket, targObj: Character | Item | null ) => void } */ function onCallback2( pSock, targObj ) { var pUser = pSock.currentChar; @@ -540,61 +586,109 @@ function onCallback2( pSock, targObj ) return; // Fetch makeID and timerID from temp tag - var makeID = pUser.GetTempTag( "makeID" ); + var makeID = pUser.GetTempTag( "makeID" ); var timerID = pUser.GetTempTag( "timerID" ); pUser.SetTempTag( "makeID", null ); pUser.SetTempTag( "timerID", null ); var bItem = pSock.tempObj; // tool - if( ValidateObject( bItem )) + if( !ValidateObject( bItem )) + return; + + if( ValidateObject( targObj ) && targObj.isItem ) { - if( ValidateObject( targObj ) && targObj.isItem ) + // Make sure targeted item is in player's backpack + var iPackOwner = GetPackOwner( targObj, 0 ); + if( ValidateObject( iPackOwner )) { - // Make sure targeted item is in player's backpack - var iPackOwner = GetPackOwner( targObj, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? - { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? - { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! - return; - } - } - else + if( iPackOwner.serial != pUser.serial ) { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! return; } + } + else + { + pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. + return; + } - if( makeID >= 238 && makeID <= 243 ) + // Jewelry: verify gem + if( makeID >= 238 && makeID <= 243 ) + { + var resourceType = TriggerEvent( 2506, "GetResourceType", targObj.id ); + if( resourceType != "gems" ) { - // Jewlery - var resourceType = TriggerEvent( 2506, "GetResourceType", targObj.id ); - if( resourceType != "gems" ) - { - pSock.SysMessage( GetDictionaryEntry( 12007, pSock.language )); // That's not a gem resource! - return; - } - - // Set a temporary tag on character with ID of selected gem - // We'll check for this ID in the crafting process, and remove it - // in the onMakeItem event script (crafting_complete.js) - pUser.SetTempTag( "targetedSubResourceId", targObj.id ); - pUser.SetTempTag( "targetedSubResourceName", targObj.name ); + pSock.SysMessage( GetDictionaryEntry( 12007, pSock.language )); // That's not a gem resource! + return; } - MakeItem( pSock, pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) + // Tags used by crafting_complete.js + pUser.SetTempTag( "targetedSubResourceId", targObj.id ); + pUser.SetTempTag( "targetedSubResourceName", targObj.name ); + } + + MakeItem( pSock, pUser, makeID ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) - { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking - } + bItem.Delete(); + pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! } - pUser.StartTimer( gumpDelay, timerID, true ); } + pUser.StartTimer( gumpDelay, timerID, tinkeringID ); } } + +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenTinkering" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenTinkering", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} From d5ee3786f1485448e1150c7c63851d80956c0d2d Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:04:07 -0600 Subject: [PATCH 34/43] Update tailoring.js --- data/js/skill/craft/tailoring.js | 803 ++++++++++++++++--------------- 1 file changed, 423 insertions(+), 380 deletions(-) diff --git a/data/js/skill/craft/tailoring.js b/data/js/skill/craft/tailoring.js index 66cf7874f..f07b50e95 100644 --- a/data/js/skill/craft/tailoring.js +++ b/data/js/skill/craft/tailoring.js @@ -1,194 +1,227 @@ /// // @ts-check -const textHue = 0x480; // Color hue for all text in the crafting gump -const scriptID = 4030; // Script ID used to identify and close this gump -const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting -const repairDelay = 200; // Delay (ms) before gump reappears after selecting a resource -const itemDetailsScriptID = 4026; // Script ID used to show item detail tooltips -const craftGumpID = 4027; // TriggerEvent ID used to build the crafting gump UI -const itemsPerPage = 10; // Number of craftable items shown per gump subpage -const displayUnlearnedRecipes = true; // Show recipes player hasn't learned -const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const textHue = 0x480; // Color hue for all text in the crafting gump +const tailoringID = 4030; // Script ID used to identify and close this gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const repairDelay = 200; // Delay (ms) before gump reappears after selecting a resource +const itemDetailsScriptID = 4026; // Script ID used to show item detail tooltips +const craftGumpID = 4027; // TriggerEvent ID used to build the crafting gump UI +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // Show recipes player hasn't learned +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); +const tailoringSkillID = 34; // Tailoring skill index + ////////////////////////////////////////////////////////////////////////////////////////// -// UOX3 Tailoring CraftingMap Configuration -// -// Description: -// This file defines the `CraftingMap` used to populate the tailoring crafting gump in UOX3. -// Each entry links a craftable item (defined in `create/tailoring.dfn`) to its display name, -// gump page, and crafting behavior. This setup powers the dynamic UI for tailoring. -// -// Data Sources: -// - `makeID` refers to the unique item ID defined in `create/tailoring.dfn`. -// - `dictID` refers to a localized string entry defined in `dictionaries/dictionary.eng`. -// - `customName` is an optional hardcoded string that overrides dictionary text if present. -// - `recipeID` is an optional ID that locks the item behind a learned recipe. -// -// Entry Format: -// makeID: { -// dictID: , // (Optional) Used for localized names via dictionary.eng -// customName: "", // (Optional) Overrides dictionary name if present -// page: , // Gump page to display item on -// timerID: , // Timer used to re-show gump after crafting -// recipeID: // (Optional) Requires the player to learn the recipe before crafting -// } -// -// Display Logic: -// - If `customName` is present, it is used directly in the crafting gump. -// - If `dictID` is present (and `customName` is not), `GetDictionaryEntry()` is used. -// - If both are missing, the gump will show a fallback like `[Unnamed Item: ####]`. -// - The `page` field determines which category tab the item appears under. -// - If `recipeID` is present and the player has not learned it, the item will either be: -// - Hidden entirely (default behavior), or -// - Displayed but uncraftable, depending on `displayUnlearnedRecipes` setting. -// -// Example Entries: -// -// // Standard item using dictionary ID for localization -// 130: { dictID: 11415, page: 1, timerID: 1 }, -// -// // Custom item with hardcoded display name, no dictionary entry required -// 999: { customName: "harrys sword", page: 1, timerID: 1 }, -// -// // Recipe-locked item (only craftable if recipe is learned) -// 185: { dictID: 11469, page: 8, timerID: 8, recipeID: 185 }, -// -// // Era Gating -// 130: { dictID: 11415, page: 1, timerID: 1, minEra: "uo" }, // from UO and up -// 185: { dictID: 11469, page: 8, timerID: 8, recipeID: 185, minEra: "aos" }, // AoS+ -// 169: { dictID: 11454, page: 6, timerID: 6, maxEra: "lbr" }, // up to LBR -// -// Organization: -// - Items are grouped by `page` value (e.g., Hats, Armor, etc.). -// - The crafting gump dynamically builds its layout from this CraftingMap. -// - This system supports localized, custom, hybrid, and recipe-locked crafting menus. -// +// Tailoring CraftingMap ////////////////////////////////////////////////////////////////////////////////////////// +// You can later add: +// skill, minEra, maxEra, recipeID, harvest, harvestNames, customName +// per entry, like in Alchemy / Tinkering. + const CraftingMap = { // Hats (Page 1) - 130: { dictID: 11415, page: 1, timerID: 1 }, - 131: { dictID: 11416, page: 1, timerID: 1 }, - 132: { dictID: 11417, page: 1, timerID: 1 }, - 134: { dictID: 11418, page: 1, timerID: 1 }, - 133: { dictID: 11419, page: 1, timerID: 1 }, - 136: { dictID: 11420, page: 1, timerID: 1 }, - 137: { dictID: 11421, page: 1, timerID: 1 }, - 138: { dictID: 11422, page: 1, timerID: 1 }, - 139: { dictID: 11423, page: 1, timerID: 1 }, - 140: { dictID: 11424, page: 1, timerID: 1 }, - 141: { dictID: 11425, page: 1, timerID: 1 }, - 135: { dictID: 11470, page: 1, timerID: 1 }, + 130: { dictID: 11415, page: 1, timerID: 1, harvest: [ 10016 ] }, + 131: { dictID: 11416, page: 1, timerID: 1, harvest: [ 10016 ] }, + 132: { dictID: 11417, page: 1, timerID: 1, harvest: [ 10016 ] }, + 134: { dictID: 11418, page: 1, timerID: 1, harvest: [ 10016 ] }, + 133: { dictID: 11419, page: 1, timerID: 1, harvest: [ 10016 ] }, + 136: { dictID: 11420, page: 1, timerID: 1, harvest: [ 10016 ] }, + 137: { dictID: 11421, page: 1, timerID: 1, harvest: [ 10016 ] }, + 138: { dictID: 11422, page: 1, timerID: 1, harvest: [ 10016 ] }, + 139: { dictID: 11423, page: 1, timerID: 1, harvest: [ 10016 ] }, + 140: { dictID: 11424, page: 1, timerID: 1, harvest: [ 10016 ] }, + 141: { dictID: 11425, page: 1, timerID: 1, harvest: [ 10016 ] }, + 135: { dictID: 11470, page: 1, timerID: 1, harvest: [ 10016 ] }, // Shirts & Pants (Page 2) - 142: { dictID: 11426, page: 2, timerID: 2 }, - 143: { dictID: 11427, page: 2, timerID: 2 }, - 144: { dictID: 11428, page: 2, timerID: 2 }, - 145: { dictID: 11429, page: 2, timerID: 2 }, - 146: { dictID: 11430, page: 2, timerID: 2 }, - 147: { dictID: 11431, page: 2, timerID: 2 }, - 148: { dictID: 11432, page: 2, timerID: 2 }, - 149: { dictID: 11433, page: 2, timerID: 2 }, - 150: { dictID: 11434, page: 2, timerID: 2 }, - 151: { dictID: 11435, page: 2, timerID: 2 }, - 180: { dictID: 11436, page: 2, timerID: 2 }, - 152: { dictID: 11437, page: 2, timerID: 2 }, - 153: { dictID: 11438, page: 2, timerID: 2 }, - 154: { dictID: 11439, page: 2, timerID: 2 }, + 142: { dictID: 11426, page: 2, timerID: 2, harvest: [ 10016 ] }, + 143: { dictID: 11427, page: 2, timerID: 2, harvest: [ 10016 ] }, + 144: { dictID: 11428, page: 2, timerID: 2, harvest: [ 10016 ] }, + 145: { dictID: 11429, page: 2, timerID: 2, harvest: [ 10016 ] }, + 146: { dictID: 11430, page: 2, timerID: 2, harvest: [ 10016 ] }, + 147: { dictID: 11431, page: 2, timerID: 2, harvest: [ 10016 ] }, + 148: { dictID: 11432, page: 2, timerID: 2, harvest: [ 10016 ] }, + 149: { dictID: 11433, page: 2, timerID: 2, harvest: [ 10016 ] }, + 150: { dictID: 11434, page: 2, timerID: 2, harvest: [ 10016 ] }, + 151: { dictID: 11435, page: 2, timerID: 2, harvest: [ 10016 ] }, + 180: { dictID: 11436, page: 2, timerID: 2, harvest: [ 10016 ] }, + 152: { dictID: 11437, page: 2, timerID: 2, harvest: [ 10016 ] }, + 153: { dictID: 11438, page: 2, timerID: 2, harvest: [ 10016 ] }, + 154: { dictID: 11439, page: 2, timerID: 2, harvest: [ 10016 ] }, // Misc (Page 3) - 155: { dictID: 11440, page: 3, timerID: 3 }, - 156: { dictID: 11441, page: 3, timerID: 3 }, - 157: { dictID: 11442, page: 3, timerID: 3 }, - 158: { dictID: 11443, page: 3, timerID: 3 }, + 155: { dictID: 11440, page: 3, timerID: 3, harvest: [ 10016 ] }, + 156: { dictID: 11441, page: 3, timerID: 3, harvest: [ 10016 ] }, + 157: { dictID: 11442, page: 3, timerID: 3, harvest: [ 10016 ] }, + 158: { dictID: 11443, page: 3, timerID: 3, harvest: [ 10016 ] }, // Footwear (Page 4) - 159: { dictID: 11444, page: 4, timerID: 4 }, - 160: { dictID: 11445, page: 4, timerID: 4 }, - 161: { dictID: 11446, page: 4, timerID: 4 }, - 162: { dictID: 11447, page: 4, timerID: 4 }, + 159: { dictID: 11444, page: 4, timerID: 4, harvest: [ 10007 ] }, + 160: { dictID: 11445, page: 4, timerID: 4, harvest: [ 10007 ] }, + 161: { dictID: 11446, page: 4, timerID: 4, harvest: [ 10007 ] }, + 162: { dictID: 11447, page: 4, timerID: 4, harvest: [ 10007 ] }, // Leather Armor (Page 5) - 163: { dictID: 11448, page: 5, timerID: 5 }, - 164: { dictID: 11449, page: 5, timerID: 5 }, - 165: { dictID: 11450, page: 5, timerID: 5 }, - 166: { dictID: 11451, page: 5, timerID: 5 }, - 167: { dictID: 11452, page: 5, timerID: 5 }, - 168: { dictID: 11453, page: 5, timerID: 5 }, + 163: { dictID: 11448, page: 5, timerID: 5, harvest: [ 10007 ] }, + 164: { dictID: 11449, page: 5, timerID: 5, harvest: [ 10007 ] }, + 165: { dictID: 11450, page: 5, timerID: 5, harvest: [ 10007 ] }, + 166: { dictID: 11451, page: 5, timerID: 5, harvest: [ 10007 ] }, + 167: { dictID: 11452, page: 5, timerID: 5, harvest: [ 10007 ] }, + 168: { dictID: 11453, page: 5, timerID: 5, harvest: [ 10007 ] }, // Studded Armor (Page 6) - 169: { dictID: 11454, page: 6, timerID: 6 }, - 170: { dictID: 11455, page: 6, timerID: 6 }, - 171: { dictID: 11456, page: 6, timerID: 6 }, - 172: { dictID: 11457, page: 6, timerID: 6 }, - 173: { dictID: 11458, page: 6, timerID: 6 }, + 169: { dictID: 11454, page: 6, timerID: 6, harvest: [ 10007 ] }, + 170: { dictID: 11455, page: 6, timerID: 6, harvest: [ 10007 ] }, + 171: { dictID: 11456, page: 6, timerID: 6, harvest: [ 10007 ] }, + 172: { dictID: 11457, page: 6, timerID: 6, harvest: [ 10007 ] }, + 173: { dictID: 11458, page: 6, timerID: 6, harvest: [ 10007 ] }, // Female Armor (Page 7) - 174: { dictID: 11459, page: 7, timerID: 7 }, - 175: { dictID: 11460, page: 7, timerID: 7 }, - 176: { dictID: 11461, page: 7, timerID: 7 }, - 177: { dictID: 11462, page: 7 , timerID: 7}, - 178: { dictID: 11463, page: 7, timerID: 7 }, - 179: { dictID: 11464, page: 7, timerID: 7 }, + 174: { dictID: 11459, page: 7, timerID: 7, harvest: [ 10007 ] }, + 175: { dictID: 11460, page: 7, timerID: 7, harvest: [ 10007 ] }, + 176: { dictID: 11461, page: 7, timerID: 7, harvest: [ 10007 ] }, + 177: { dictID: 11462, page: 7, timerID: 7, harvest: [ 10007 ] }, + 178: { dictID: 11463, page: 7, timerID: 7, harvest: [ 10007 ] }, + 179: { dictID: 11464, page: 7, timerID: 7, harvest: [ 10007 ] }, // Bone Armor (Page 8) - 181: { dictID: 11465, page: 8, timerID: 8 }, - 182: { dictID: 11466, page: 8, timerID: 8 }, - 183: { dictID: 11467, page: 8, timerID: 8 }, - 184: { dictID: 11468, page: 8, timerID: 8 }, - 185: { dictID: 11469, page: 8, timerID: 8 } + 181: { dictID: 11465, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, + 182: { dictID: 11466, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, + 183: { dictID: 11467, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, + 184: { dictID: 11468, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, + 185: { dictID: 11469, page: 8, timerID: 8, harvest: [ 10007, 10008 ] } // can add recipeID/minEra here later }; -function PageX( socket, pUser, pageNum ) +// Fill defaults (skill, etc.) +(function initTailoringMap() { - let subPage = pUser.GetTempTag( "subPage" ) || 1; - - // Build pages dynamically from CraftingMap - let myPage = []; - let dictToMakeID = {}; // local reverse map - - for( let makeID in CraftingMap ) + for( var key in CraftingMap ) { - let data = CraftingMap[makeID]; - let page = data.page; - if( !myPage[page - 1] ) - myPage[page - 1] = []; - - let needsRecipe = data.recipeID; - let showAll = displayUnlearnedRecipes; + if( !CraftingMap.hasOwnProperty( key )) + continue; - if( eraOK( data ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe ))) - { - myPage[page - 1].push( data.dictID ); - } - - dictToMakeID[data.dictID] = parseInt( makeID ); + var entry = CraftingMap[key]; + if( entry.skill === undefined ) + entry.skill = tailoringSkillID; } +})(); - let pageItems; +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ +function PageX( socket, pUser, pageNum ) +{ + if( !socket || !ValidateObject( pUser )) + return; + + var subPage = pUser.GetTempTag( "subPage" ) || 1; + var pageItems; + // Last Ten page if( pageNum == 999 ) { - let lastTenRaw = pUser.GetTag( "LastTenTailoring" ) || ""; - let split = lastTenRaw.split( "," ); + var lastTenRaw = pUser.GetTempTag( "LastTenTailoring" ) || ""; + var split = lastTenRaw.split( "," ); pageItems = []; for( var i = 0; i < split.length; i++ ) { - let val = parseInt(split[i]); + var val = parseInt( split[i] ); if( !isNaN( val )) - pageItems.push( val ); + pageItems.push( val ); // makeID } } else { - if( pageNum < 1 || pageNum > myPage.length ) + // Collect all makeIDs for this page + var makeIDs = []; + for( var key in CraftingMap ) + { + if( !CraftingMap.hasOwnProperty( key )) + continue; + + var makeID = parseInt( key ); + var data = CraftingMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort by dictID so order matches dictionary sequence + makeIDs.sort( function( a, b ) + { + var ea = CraftingMap[a]; + var eb = CraftingMap[b]; + if( ea && eb ) + return ( ea.dictID || 0 ) - ( eb.dictID || 0 ); + return a - b; + }); + + // Era / recipe filtering + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) + { + var id = makeIDs[k]; + var data2 = CraftingMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) ) + pageItems.push( id ); + } + + // Fallback if page empty (and not page 1) + if( pageItems.length == 0 && pageNum != 1 ) + { pageNum = 1; - pageItems = myPage[pageNum - 1]; - } + makeIDs = []; + for( var key2 in CraftingMap ) + { + if( !CraftingMap.hasOwnProperty( key2 )) + continue; + + var mid2 = parseInt( key2 ); + var d3 = CraftingMap[mid2]; + if( !d3 || d3.page != 1 ) + continue; - let totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + makeIDs.push( mid2 ); + } + makeIDs.sort( function( a, b ) + { + var ea2 = CraftingMap[a]; + var eb2 = CraftingMap[b]; + if( ea2 && eb2 ) + return ( ea2.dictID || 0 ) - ( eb2.dictID || 0 ); + return a - b; + }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) + { + var id2 = makeIDs[m]; + var data4 = CraftingMap[id2]; + if( !data4 ) + continue; + + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 )) ) + pageItems.push( id2 ); + } + } + } + + // Subpage handling + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + if( totalSubPages < 1 ) + totalSubPages = 1; if( subPage < 1 ) subPage = 1; if( subPage > totalSubPages ) @@ -197,108 +230,104 @@ function PageX( socket, pUser, pageNum ) pUser.SetTempTag( "page", pageNum ); pUser.SetTempTag( "subPage", subPage ); - let startIndex = ( subPage - 1 ) * itemsPerPage; - let endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); - if( startIndex >= pageItems.length ) + if( startIndex >= pageItems.length ) { - subPage = 1; + subPage = 1; startIndex = 0; - endIndex = Math.min( itemsPerPage, pageItems.length ); + endIndex = Math.min( itemsPerPage, pageItems.length ); pUser.SetTempTag( "subPage", subPage ); } - let tailoringMenu = new Gump; + var tailoringMenu = new Gump; TriggerEvent( craftGumpID, "CraftingGumpMenu", tailoringMenu, socket ); tailoringMenu.AddPage( 1 ); - for( let i = startIndex; i < endIndex; i++) + for( var j = startIndex; j < endIndex; j++ ) { - let index = i - startIndex; - let makeID, entryID, entryText, buttonID; + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; // craft button uses makeID directly + var data5 = CraftingMap[makeID]; - if( pageNum == 999 ) + if( !data5 ) { - makeID = pageItems[i]; + entryText = "[Missing MakeID: " + makeID + "]"; } else { - entryID = pageItems[i]; - makeID = dictToMakeID[entryID]; + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; + } } - let data = CraftingMap[makeID]; - - if( !data ) - { - entryText = "[Missing MakeID: " + makeID + "]"; - buttonID = makeID; + tailoringMenu.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + tailoringMenu.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); + // Detail button: 20000 + makeID (new system pattern) + tailoringMenu.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); } - else - { - buttonID = makeID; - - if( data.customName ) - { - entryText = data.customName; - } - else if( data.dictID ) - { - entryText = GetDictionaryEntry( data.dictID, socket.language ); - if( !entryText || entryText === "" ) - entryText = "[Missing EntryID: " + data.dictID + "]"; - } - else - { - entryText = "[Unnamed Item: " + makeID + "]"; - } - } - - tailoringMenu.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); - tailoringMenu.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); - tailoringMenu.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + buttonID ); -} + // Prev subpage if( subPage > 1 ) { tailoringMenu.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); - tailoringMenu.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry(10101, socket.language ) + "" ); + tailoringMenu.AddHTMLGump( 255, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10101, socket.language ) + "" ); } + // Next subpage if( subPage < totalSubPages ) { tailoringMenu.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); - tailoringMenu.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry(10100, socket.language ) + "" ); + tailoringMenu.AddHTMLGump( 405, 263, 100, 18, false, false, + "" + GetDictionaryEntry( 10100, socket.language ) + "" ); } tailoringMenu.Send( socket ); tailoringMenu.Free(); } -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +/** @type { ( pUser: Character, timerID: number ) => void } */ function onTimer( pUser, timerID ) { if( !ValidateObject( pUser )) return; - let socket = pUser.socket; + var socket = pUser.socket; + if( socket == null ) + return; if( timerID >= 1 && timerID <= 8 ) { - PageX( socket, pUser, timerID ); // Pages 1 - 8 + PageX( socket, pUser, timerID ); // Pages 1–8 } - else if ( timerID == 999 ) + else if( timerID == 999 ) { - PageX(socket, pUser, 999); // Last Ten + PageX( socket, pUser, 999 ); // Last Ten } } -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ +/** @type { ( socket: Socket, pButton: number, gumpData: GumpData ) => void } */ function onGumpPress( socket, pButton, gumpData ) { - var pUser = socket.currentChar; - var usedMakeLast = false; + if( socket == null ) + return; + var pUser = socket.currentChar; if( !ValidateObject( pUser ) || pUser.dead ) return; @@ -315,39 +344,43 @@ function onGumpPress( socket, pButton, gumpData ) return; } - var iPackOwner = GetPackOwner(bItem, 0); + var iPackOwner = GetPackOwner( bItem, 0 ); if( ValidateObject( iPackOwner )) { if( iPackOwner.serial != pUser.serial ) { - socket.SysMessage(GetDictionaryEntry( 6032, socket.language )); + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); return; } } else { - socket.SysMessage(GetDictionaryEntry( 6022, socket.language )); + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); return; } + var gumpID = tailoringID + 0xffff; + + // Subpage back/forward if( pButton >= 8001 && pButton < 9000 ) { - let subPage = pButton - 8000; - let pageNum = pUser.GetTempTag( "page" ) || 1; + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ) || 1; pUser.SetTempTag( "subPage", subPage ); - PageX(socket, pUser, pageNum); + PageX( socket, pUser, pageNum ); return; } if( pButton >= 9001 && pButton < 10000 ) { - let subPage = pButton - 9000; - let pageNum = pUser.GetTempTag( "page" ) || 1; - pUser.SetTempTag("subPage", subPage); - PageX( socket, pUser, pageNum ); + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ) || 1; + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); return; } + // Page tabs (1–8) if( pButton >= 1 && pButton <= 8 ) { pUser.SetTempTag( "page", pButton ); @@ -356,83 +389,95 @@ function onGumpPress( socket, pButton, gumpData ) return; } + // Last Ten if( pButton == 11000 ) { pUser.SetTempTag( "page", 999 ); pUser.SetTempTag( "subPage", 1 ); - PageX(socket, pUser, 999); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Tailoring", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); + return; + } + + // Unravel button + if( pButton == 52 ) + { + UnravelTarget( socket ); return; } + var usedMakeLast = false; var makeID = 0; var timerID = 0; - // Handle "Make Last" - if(( pButton >= 100 && pButton <= 804 ) || pButton == 5000 ) + // Make Last + if( pButton == 5000 ) { - if( pButton == 5000 ) + var last = pUser.GetTempTag( "MakeLast_Tailoring" ); + if( last ) { - pButton = pUser.GetTempTag( "MAKELAST" ); + pButton = last; usedMakeLast = true; } else { - pUser.SetTempTag( "MAKELAST", pButton ); + return; } } - // If it's a craft button (found in map) + // Craft buttons use makeID directly (if in map) if( CraftingMap[pButton] != undefined ) { makeID = pButton; - timerID = CraftingMap[makeID].timerID || 1; + var data = CraftingMap[makeID]; + timerID = data.timerID || 1; + + // Era / recipe checks + if( !eraOK( data )) + { + socket.SysMessage( "That item is not available in this era." ); + return; + } + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } - let materialHue = pUser.GetTempTag( "LastResourceColor" ); + pUser.SetTempTag( "MakeLast_Tailoring", makeID ); + + var materialHue = pUser.GetTempTag( "LastResourceColor" ); + + // Cloth items: select cloth (colour) unless Make Last + cached hue if(( makeID >= 100 && makeID <= 158 ) || makeID == 180 ) { if( usedMakeLast && materialHue != null ) { - // Check if recipe required and not known - let data = CraftingMap[makeID]; - if( data && !eraOK( data )) - { - socket.SysMessage( "That item is not available in this era." ); - return; - } - - if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) - { - socket.SysMessage("You must learn that recipe from a scroll."); - return; - } MakeItem( socket, pUser, makeID, materialHue ); AddToLastTen( pUser, makeID ); - pUser.StartTimer( gumpDelay, timerID, 4030 ); + pUser.StartTimer( gumpDelay, timerID, tailoringID ); } else { pUser.SetTempTag( "makeID", makeID ); pUser.SetTempTag( "timerID", timerID ); - socket.CustomTarget(1, GetDictionaryEntry( 444, socket.language )); + socket.CustomTarget( 1, GetDictionaryEntry( 444, socket.language )); // Select material: } } else { - // Check if recipe required and not known - let data = CraftingMap[makeID]; - if( data && !eraOK( data )) - { - socket.SysMessage( "That item is not available in this era." ); - return; - } - - if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) - { - socket.SysMessage("You must learn that recipe from a scroll."); - return; - } + // Non-colour-selected tailoring (leather/bone etc.) MakeItem( socket, pUser, makeID ); AddToLastTen( pUser, makeID ); + if( GetServerSetting( "ToolUseLimit" )) { bItem.usesLeft -= 1; @@ -442,40 +487,74 @@ function onGumpPress( socket, pButton, gumpData ) socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); } } - pUser.StartTimer( gumpDelay, timerID, 4030 ); + pUser.StartTimer( gumpDelay, timerID, tailoringID ); } return; } - // If it's a detail button (2000+ button ID pattern) - if( pButton >= 2000 && pButton <= 3000 ) + // Detail buttons: 20000 + makeID (new system) + if( pButton >= 20000 && pButton < 30000 ) { - let makeID = pButton - 2000; - if( CraftingMap[makeID] ) + var detailMakeID = pButton - 20000; + var entry = CraftingMap[detailMakeID]; + if( entry ) { - pUser.SetTempTag( "ITEMDETAILS", makeID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); - } - return; - } + // Which item to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || tailoringSkillID ); + + // Clear old harvest tags + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old custom harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // Optional harvest dictIDs (cloth, leather, bone etc.) – add later per item + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } - if( pButton == 0 ) // Exit/Close - { - let gumpID = scriptID + 0xffff; - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ); - socket.CloseGump( gumpID, 0 ); - return; - } + // Optional custom resource names (e.g. "Cloth", "Leather") + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } - if( pButton == 52 ) // Unravel Item - { - UnravelTarget( socket ); + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } return; } } -/** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ +/** @type { ( socket: Socket, ourObj: Character | Item | null ) => void } */ function onCallback1( socket, ourObj ) { var pUser = socket.currentChar; @@ -483,58 +562,57 @@ function onCallback1( socket, ourObj ) return; // Fetch makeID and timerID from temp tag - var makeID = pUser.GetTempTag( "makeID" ); + var makeID = pUser.GetTempTag( "makeID" ); var timerID = pUser.GetTempTag( "timerID" ); pUser.SetTempTag( "makeID", null ); pUser.SetTempTag( "timerID", null ); var bItem = socket.tempObj; - if( ValidateObject( bItem )) + if( !ValidateObject( bItem )) + return; + + if( ValidateObject( ourObj ) && ourObj.isItem ) { - if( ValidateObject( ourObj ) && ourObj.isItem ) + // Make sure targeted item is in player's backpack + var iPackOwner = GetPackOwner( ourObj, 0 ); + if( ValidateObject( iPackOwner )) { - // Make sure targeted item is in player's backpack - var iPackOwner = GetPackOwner( ourObj, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? + if( iPackOwner.serial != pUser.serial ) { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? - { - socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That resource is in someone else's backpack! - return; - } - } - else - { - socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This has to be in your backpack before you can use it. + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); return; } + } + else + { + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); + return; + } - //Cache cloth color for future "Make Last" - pUser.SetTempTag( "LastResourceColor", ourObj.colour ); + // Cache cloth color for Make Last + pUser.SetTempTag( "LastResourceColor", ourObj.colour ); - // Check if recipe required and not known - let data = CraftingMap[makeID]; - if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) - { - socket.SysMessage("You must learn that recipe from a scroll."); - return; - } + // Recipe re-check (just in case) + var data = CraftingMap[makeID]; + if( data && data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } - // Pass in the colour of the desired material to use for crafting - MakeItem( socket, pUser, makeID, ourObj.colour ); - AddToLastTen( pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) + MakeItem( socket, pUser, makeID, ourObj.colour ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) - { - bItem.Delete(); - socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! - // Play sound effect of tool breaking - } + bItem.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); // You have worn out your tool! } - pUser.StartTimer( gumpDelay, timerID, 4030 ); } + pUser.StartTimer( gumpDelay, timerID, tailoringID ); } } @@ -544,15 +622,13 @@ function UnravelTarget( socket ) } // Clothes and leather armor can be unravelled back into cloth and leather -/** @type { ( tSock: Socket, target: Character | Item | null ) => void } */ +/** @type { ( socket: Socket, ourObj: Character | Item | null ) => void } */ function onCallback2( socket, ourObj ) { - // Unravel item, get cloth/leather in return var mChar = socket.currentChar; if( !ValidateObject( ourObj ) || !ourObj.isItem ) { - // Targeted object is not an item that can be smelted mChar.SetTempTag( "prevActionResult", "CANTUNRAVEL" ); mChar.StartTimer( repairDelay, 1, true ); return; @@ -571,46 +647,40 @@ function onCallback2( socket, ourObj ) var resourceColor = ourObj.colour; var materialType = TriggerEvent( 2506, "GetItemMaterialType", ourObj, 0 ); + var resourceID = 0; + if( creatorSerial == -1 || entryMadeFrom == 0 || createEntry == null ) { - // Not a player-crafted item, return 1 resource if item is made of cloth/leather + // Not player-crafted; 1 resource if cloth/leather if( materialType == "cloth" || materialType == "leather" ) - { resourceAmount = 1; - } } else { if( createEntry.avgMinSkill > mChar.skills.tailoring ) { + var gumpID = tailoringID + 0xffff; socket.CloseGump( gumpID, 0 ); mChar.SetTempTag( "prevActionResult", "NOUNRAVELSKILL" ); - mChar.StartTimer( gumpDelay, 1, 4030 ); + mChar.StartTimer( gumpDelay, 1, tailoringID ); return; } - // Loop through resources used to craft item, see how many resources were used - var resourceID = 0; + // Loop resources used to craft item var resourcesUsed = createEntry.resources; for( var i = 0; i < resourcesUsed.length; i++ ) { var resource = resourcesUsed[i]; var amountNeeded = resource[0]; - var colorNeeded = resource[1]; - var resourceIDs = resource[2]; + var colorNeeded = resource[1]; // unused here but kept for completeness + var resourceIDs = resource[2]; - // Loop through list of resourceIDs that were valid for crafting this item, see if ANY - // were a match for the resource we're trying to return for( var j = 0; j <= resourceIDs.length; j++ ) { if( !isNaN( parseInt( resourceIDs[j] ))) { - // If we found some resource that match up to cloth, or leather, go for it - var resourceType = TriggerEvent( 2506, "GetResourceType", parseInt( resourceIDs[j] )); - /*mChar.TextMessage( "MaterialType: " + materialType ); - mChar.TextMessage( "ResourceType: " + resourceType ); - mChar.TextMessage( "resourceID: " + resourceIDs[j] );*/ - if( materialType == resourceType ) + var resType = TriggerEvent( 2506, "GetResourceType", parseInt( resourceIDs[j] )); + if( materialType == resType ) { maxResourceAmount = amountNeeded; resourceID = resourceIDs[j]; @@ -619,42 +689,26 @@ function onCallback2( socket, ourObj ) } } - // We only really care about the first and primary resource.... if( maxResourceAmount > 0 ) break; } if( maxResourceAmount > 1 ) { - // Calculate amount of resources returned based on player's mining skill, item's wear and tear, - // and amount of resources that went into making the item in the first place - if( ourObj.health >= 1 || ourObj.usesLeft >= 1 ) - { - var healthPercentage = 0; - if( ourObj.health >= 1 ) - { - healthPercentage = Math.floor( ( ourObj.health * 100 ) / ourObj.maxhp ); - } + var healthPercentage = 0; + if( ourObj.health >= 1 ) + healthPercentage = Math.floor( ( ourObj.health * 100 ) / ourObj.maxhp ); - var usesPercentage = 0; - if( ourObj.usesLeft >= 1 ) - { - usesPercentage = Math.floor( ( ourObj.usesLeft * 100 ) / ourObj.maxUses ); - } + var usesPercentage = 0; + if( ourObj.usesLeft >= 1 ) + usesPercentage = Math.floor( ( ourObj.usesLeft * 100 ) / ourObj.maxUses ); - var itemPercentage = usesPercentage > 0 ? Math.min( healthPercentage, usesPercentage ) : healthPercentage; + var itemPercentage = usesPercentage > 0 ? Math.min( healthPercentage, usesPercentage ) : healthPercentage; - // Reduce amount of resources returned based on state of object's wear and tear - resourceAmount = Math.floor( ( maxResourceAmount * itemPercentage ) / 100 ); - } - - // Halve the amount of resources returned + resourceAmount = Math.floor( ( maxResourceAmount * itemPercentage ) / 100 ); resourceAmount = Math.max( Math.floor( resourceAmount / 2 ), 1 ); - // Fetch player's Tailoring skill var playerSkill = mChar.skills.tailoring; - - // Based on player's Tailoring skill, return between 1 to maxResourceAmount resourceAmount = Math.min( Math.max( Math.floor( resourceAmount * ( playerSkill / 1000 )), 1 ), resourceAmount ); } else @@ -665,76 +719,67 @@ function onCallback2( socket, ourObj ) if( resourceAmount == 0 || resourceID == 0 ) { - // Targeted object is not an item that can be unravelled mChar.SetTempTag( "prevActionResult", "CANTUNRAVEL" ); - mChar.StartTimer( repairDelay, 1, 4030 ); + mChar.StartTimer( repairDelay, 1, tailoringID ); return; } - // Delete the unravelled item + // Delete unravelled item ourObj.Delete(); - // Run a generic skill check to give player a chance to increase their tailoring skill - mChar.CheckSkill( 34, 0, mChar.skillCaps.tailoring ); + // Generic skill check + mChar.CheckSkill( tailoringSkillID, 0, mChar.skillCaps.tailoring ); - // Determine the actual resource item to add to player's backpack - // We'll default to one specific resource per material type + // Determine returned resource var itemToAdd = ""; switch( materialType ) { - case "cloth": - itemToAdd = "0x1766"; // cut cloth - break; - case "leather": - itemToAdd = "0x1068"; // cut leather - break; - default: - break; + case "cloth": itemToAdd = "0x1766"; break; // cut cloth + case "leather": itemToAdd = "0x1068"; break; // cut leather + default: break; } + var newResource = CreateDFNItem( socket, mChar, itemToAdd, resourceAmount, "ITEM", true, resourceColor ); mChar.SetTempTag( "resourceFromUnravelling", resourceAmount ); mChar.SetTempTag( "prevActionResult", "UNRAVELSUCCESS" ); - mChar.StartTimer( gumpDelay, 1, 4030 ); + mChar.StartTimer( gumpDelay, 1, tailoringID ); } function AddToLastTen( pUser, makeID ) { - // Append makeID to last ten list - var raw = pUser.GetTag( "LastTenTailoring" ) || ""; + var raw = pUser.GetTempTag( "LastTenTailoring" ) || ""; var list = raw.split( "," ); - // Remove if already in list for( var i = 0; i < list.length; i++ ) { - if( parseInt( list[i]) == makeID ) + if( parseInt( list[i] ) == makeID ) { - list.splice(i, 1); + list.splice( i, 1 ); break; } } - // Add to front (no unshift in SpiderMonkey 1.8) - var newList = [makeID]; - for( var i = 0; i < list.length && newList.length < 10; i++ ) + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) { - var entry = parseInt( list[i] ); + var entry = parseInt( list[j] ); if( !isNaN( entry ) && entry > 0 ) newList.push( entry ); } - pUser.SetTag( "LastTenTailoring", newList.join( "," )); + pUser.SetTempTag( "LastTenTailoring", newList.join( "," )); } function HasLearnedRecipe( pUser, recipeID ) { var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); - if( !myData || myData.length == 0) + if( !myData || myData.length == 0 ) return false; - for( let i = 0; i < myData.length; i++ ) + for( var i = 0; i < myData.length; i++ ) { - let data = myData[i].split( "," ); + var data = myData[i].split( "," ); if( data[0] == recipeID ) return true; } @@ -743,11 +788,9 @@ function HasLearnedRecipe( pUser, recipeID ) function eraOK( entry ) { - // Optional per-entry gates. Accept either/both. Strings like "lbr","aos","ml","tol". - // If not present, the entry is valid for all eras. if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) return false; if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) return false; return true; -} +} \ No newline at end of file From 33e48985f7c59c3482a63ba020cfc843e162cd99 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:19:03 -0600 Subject: [PATCH 35/43] Update crafttool.js --- data/js/skill/craft/crafttool.js | 544 ++++++++++++++++--------------- 1 file changed, 273 insertions(+), 271 deletions(-) diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 0d2fda5f0..34dc95c0f 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -1,306 +1,308 @@ /// // @ts-check -const enableUOX3Craft = 0; // Disable or enable to use old uox3 menus. -const blacksmithID = 4023; // Use this to tell the gump what script to close. -const Carpentry = 4025; -const Alchemy = 4028; -const Fletching = 4029; -const Tailoring = 4030; -const Tinkering = 4032; -const Cooking = 4034; -const Cartography = 4035; -const Glassblowing = 4036; -const Masonry = 4037; - -/** @type { ( user: Character, iUsing: Item ) => boolean } */ -function onUseChecked( pUser, iUsed ) +const enableUOX3Craft = 0; // 0 = new system, 1 = old UOX3 menus +const BlacksmithingID = 4023; +const CarpentryID = 4025; +const AlchemyID = 4028; +const FletchingID = 4029; +const TailoringID = 4030; +const TinkeringID = 4032; +const CookingID = 4034; +const CartographyID = 4035; +const GlassblowingID = 4036; +const MasonryID = 4037; + +/** + * Ensure the tool is usable: charges > 0, in range, not locked down, + * and in the user's own backpack. + * @param {Character} pUser + * @param {Item} iUsed + * @returns {boolean} + */ +function checkToolUsable(pUser, iUsed) { var socket = pUser.socket; - var gumpID = Carpentry + 0xffff; - var gumpID2 = Alchemy + 0xffff; - var gumpID3 = Fletching + 0xffff; - var gumpID4 = Tailoring + 0xffff; - var gumpID5 = blacksmithID + 0xffff; - var gumpID6 = Cooking + 0xffff; - var gumpID7 = Tinkering + 0xffff; - var gumpID8 = Cartography + 0xffff; - var gumpID10 = Masonry + 0xffff; - - if( socket && ValidateObject( iUsed ) && iUsed.isItem ) + if( !socket || !ValidateObject( iUsed ) || !iUsed.isItem ) + return false; + + if( GetServerSetting( "ToolUseLimit" ) && iUsed.usesLeft == 0 ) { - if( GetServerSetting( "ToolUseLimit" ) && iUsed.usesLeft == 0 ) + socket.SysMessage( GetDictionaryEntry( 9262, socket.language )); // This has no more charges. + return false; + } + + if( !pUser.InRange( iUsed, 3 )) + { + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. + return false; + } + + if( iUsed.movable == 3 ) + { + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! + return false; + } + + var iPackOwner = GetPackOwner( iUsed, 0 ); + if( ValidateObject( iPackOwner )) + { + if( iPackOwner.serial != pUser.serial ) { - // Tool has no uses left - socket.SysMessage( GetDictionaryEntry( 9262, socket.language )); // This has no more charges. + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That resource is in someone else's backpack! return false; } + } + else + { + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This has to be in your backpack before you can use it. + return false; + } + + return true; +} + +/** + * Open a paged crafting gump using a standard "PageX" entry point, with optional + * special page handlers (e.g. Page8, Page20). + * + * @param {Character} pUser + * @param {Socket} socket + * @param {number} scriptID Script ID of the crafting handler + * @param {number} craftIndex Value to store in "CRAFT" temp tag + * @param {number} maxPage Highest normal page number (handled by "PageX") + * @param {{[page: number]: string}=} specialPages Map: page -> function name + */ +function openCraftMenu(pUser, socket, scriptID, craftIndex, maxPage, specialPages) +{ + if( !socket ) + return; + + var gumpID = scriptID + 0xffff; + var tempPage = pUser.GetTempTag( "page" ); - if( !pUser.InRange( iUsed, 3 )) + socket.CloseGump( gumpID, 0 ); + pUser.SetTempTag( "CRAFT", craftIndex ); + + if( typeof tempPage !== "number" || tempPage < 1 ) + tempPage = 1; + + // Custom page handlers (e.g. Page8, Page20) + if( specialPages && specialPages[tempPage] ) + { + TriggerEvent( scriptID, specialPages[tempPage], socket, pUser ); + return; + } + + // Normal pages handled by PageX, up to maxPage + if( tempPage >= 1 && tempPage <= maxPage ) + { + TriggerEvent( scriptID, "PageX", socket, pUser, tempPage ); + } + else + { + TriggerEvent( scriptID, "PageX", socket, pUser, 1 ); + } +} + +// Tool ID helpers for readability +function isCarpentryTool( id ) +{ + return (( id >= 0x1026 && id <= 0x1029 ) || + ( id >= 0x102C && id <= 0x102F ) || + ( id >= 0x1030 && id <= 0x1035 ) || + ( id >= 0x10E4 && id <= 0x10E6 )); +} + +function isFletchingTool( id ) +{ + return ( id == 0x1022 || id == 0x1BD1 || id == 0x1BD4 ); +} + +function isBlacksmithTool( id ) +{ + return ( id == 0x0FBB || id == 0x0FBC || id == 0x13E3 || id == 0x13E4 ); +} + +function isCookingTool( id ) +{ + return ( id == 0x1043 || id == 0x097F || id == 0x09E2 || id == 0x103E ); +} + +// --------------------------------------------------------------------------- +// Main entry +// --------------------------------------------------------------------------- + +/** @type { ( pUser: Character, iUsed: Item ) => boolean } */ +function onUseChecked( pUser, iUsed ) +{ + var socket = pUser.socket; + if( !socket ) + return false; + + if( !checkToolUsable( pUser, iUsed )) + return false; + + // Save tool on socket so skill gumps can reference it + socket.tempObj = iUsed; + var id = iUsed.id; + + // ------------------------------------------------------------------- + // Carpentry + // ------------------------------------------------------------------- + if( isCarpentryTool( id )) + { + if( enableUOX3Craft == 1 ) { - socket.SysMessage( GetDictionaryEntry( 461, socket.language )); // You are too far away. + // Old UOX3 carpentry gump + TriggerEvent( 4006, "onUseChecked", pUser, iUsed ); return false; } - if( iUsed.movable == 3 ) + // New carpentry menu – Pages 1–10 + openCraftMenu( pUser, socket, CarpentryID, 1, 10 ); + return false; + } + + // ------------------------------------------------------------------- + // Alchemy (mortar and pestle) + // ------------------------------------------------------------------- + if( id == 0x0E9B ) + { + if( enableUOX3Craft == 1 ) { - socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); // Locked down resources cannot be used! + TriggerEvent( 4007, "onUseChecked", pUser, iUsed ); return false; } - var iPackOwner = GetPackOwner( iUsed, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? - { - if( iPackOwner.serial != pUser.serial ) //And if so does the pack belong to the user? - { - socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); // That resource is in someone else's backpack! - return false; - } - } - else + // New alchemy menu – Pages 1–4 + openCraftMenu( pUser, socket, AlchemyID, 2, 4 ); + return false; + } + + // ------------------------------------------------------------------- + // Bowcraft / Fletching + // ------------------------------------------------------------------- + if( isFletchingTool( id )) + { + if( enableUOX3Craft == 1 ) { - socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); // This has to be in your backpack before you can use it. + TriggerEvent( 4005, "onUseChecked", pUser, iUsed ); return false; } - socket.tempObj = iUsed; - var tempPage = pUser.GetTempTag( "page" ); - if( iUsed.id >= 0x1026 && iUsed.id <= 0x1029 || iUsed.id >= 0x102C && iUsed.id <= 0x102F || iUsed.id >= 0x1030 && iUsed.id <= 0x1035 || iUsed.id >= 0x10E4 && iUsed.id <= 0x10E6 ) - { - // Carpentry - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4006, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID, 0 ); - pUser.SetTempTag( "CRAFT", 1 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - case 9: // Page 9 - case 10: // Page 10 - TriggerEvent( Carpentry, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Carpentry, "PageX", socket, pUser, 1 ); - break; - } - } - else if( iUsed.id == 0x0E9B ) // mortar and pestle - { - // Alchemy - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4007, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID2, 0 ); - pUser.SetTempTag( "CRAFT", 2 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - TriggerEvent( Alchemy, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Alchemy, "PageX", socket, pUser, 1 ); - break; - } - } - else if( iUsed.id == 0x1022 || iUsed.id == 0x1BD1 || iUsed.id == 0x1BD4 ) - { - // Bowcraft/Fletching - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4005, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID3, 0 ); - pUser.SetTempTag( "CRAFT", 3 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - TriggerEvent( Fletching, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Fletching, "PageX", socket, pUser, 1 ); - break; - } - } - else if( iUsed.id == 0x0F9D ) // Sewing Kit - { - // Tailoring - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4004, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID4, 0 ); - pUser.SetTempTag( "CRAFT", 4 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - TriggerEvent( Tailoring, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Tailoring, "PageX", socket, pUser, 1 ); - break; - } - } - else if( iUsed.id == 0x0FBB || iUsed.id == 0x0FBC || iUsed.id == 0x13E3 || iUsed.id == 0x13E4 ) + // New fletching menu – Pages 1–3 + openCraftMenu( pUser, socket, FletchingID, 3, 3 ); + return false; + } + + // ------------------------------------------------------------------- + // Tailoring (sewing kit) + // ------------------------------------------------------------------- + if( id == 0x0F9D ) + { + if( enableUOX3Craft == 1 ) { - // Blacksmithing - if( enableUOX3Craft == 1 ) - { - return true; - } - socket.CloseGump( gumpID5, 0 ); - pUser.SetTempTag( "CRAFT", 5 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - TriggerEvent( blacksmithID, "PageX", socket, pUser, tempPage ); - break; - case 8: - TriggerEvent( blacksmithID, "Page8", socket, pUser ); - break; - default: TriggerEvent( blacksmithID, "PageX", socket, pUser, 1 ); - break; - } + TriggerEvent( 4004, "onUseChecked", pUser, iUsed ); + return false; } - else if( iUsed.id == 0x1043 || iUsed.id == 0x097f || iUsed.id == 0x09e2 || iUsed.id == 0x103e ) + + // New tailoring menu – Pages 1–8 + openCraftMenu( pUser, socket, TailoringID, 4, 8 ); + return false; + } + + // ------------------------------------------------------------------- + // Blacksmithing (tongs, smith hammers) + // ------------------------------------------------------------------- + if( isBlacksmithTool( id )) + { + if( enableUOX3Craft == 1 ) { - // Cooking - if( enableUOX3Craft == 1 ) - { - //socket.SysMessage( "Old-school crafting gumps have not been implemented for Cooking. Use raw food with heat sources to cook!" ); - TriggerEvent( 104, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID6, 0 ); - pUser.SetTempTag( "CRAFT", 6 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - TriggerEvent( Cooking, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Cooking, "PageX", socket, pUser, 1 ); - break; - } + // Fall back to original blacksmith behavior when enabled + return true; } - else if( iUsed.id == 0x1eb8 || iUsed.id == 0x1eb9 || iUsed.id == 0x1eba || iUsed.id == 0x1ebb || iUsed.id == 0x1ebc ) // Tinker's tools + + // New blacksmithing menu – Pages 1–7 = PageX, page 8 = Page8 + openCraftMenu( pUser, socket, BlacksmithingID, 5, 7, { 8: "Page8" } ); + return false; + } + + // ------------------------------------------------------------------- + // Cooking (skillet, flour sifter, rolling pin, etc.) + // ------------------------------------------------------------------- + if( isCookingTool( id )) + { + if( enableUOX3Craft == 1 ) { - // Tinkering - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4003, "onUseChecked", pUser, iUsed ); - return; - } - socket.CloseGump( gumpID7, 0 ); - pUser.SetTempTag( "CRAFT", 7 ) - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - case 9: // Page 9 - TriggerEvent( Tinkering, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Tinkering, "PageX", socket, pUser, 1 ); - break; - } + // Old-school cooking: use raw food with heat sources, or legacy script + TriggerEvent( 104, "onUseChecked", pUser, iUsed ); + return false; } - else if( iUsed.sectionID == "mapmakerspen" ) + + // New cooking menu – Pages 1–4 + openCraftMenu( pUser, socket, CookingID, 6, 4 ); + return false; + } + + // ------------------------------------------------------------------- + // Tinkering (tinker's tools) + // ------------------------------------------------------------------- + if( iUsed.sectionID == "tinkerstools" || // optional if you use sectionID + id == 0x1EB8 || id == 0x1EB9 || id == 0x1EBA || id == 0x1EBB || id == 0x1EBC ) + { + if( enableUOX3Craft == 1 ) { - // Cartography - socket.CloseGump( gumpID8, 0 ); - pUser.SetTempTag( "CRAFT", 8 ); - switch( tempPage ) - { - case 1: // Page 1 - TriggerEvent( Cartography, "PageX", socket, pUser, tempPage ); - break; - default: TriggerEvent( Cartography, "PageX", socket, pUser, 1 ); - break; - } + TriggerEvent( 4003, "onUseChecked", pUser, iUsed ); + return false; } - else if( iUsed.sectionID == "blowpipe" ) + + // New tinkering menu – Pages 1–9 + openCraftMenu( pUser, socket, TinkeringID, 7, 9 ); + return false; + } + + // ------------------------------------------------------------------- + // Cartography (mapmaker's pen) + // ------------------------------------------------------------------- + if( iUsed.sectionID == "mapmakerspen" ) + { + // Only one page currently – PageX with page 1 + openCraftMenu( pUser, socket, CartographyID, 8, 1 ); + return false; + } + + // ------------------------------------------------------------------- + // Glassblowing (blow pipe) + // ------------------------------------------------------------------- + if( iUsed.sectionID == "blowpipe" ) + { + if( pUser.GetTag( "GlassBlowing" ) == 0 ) { - if( pUser.GetTag( "GlassBlowing" ) == 0 ) - { - socket.SysMessage( GetDictionaryEntry( 6300, socket.Language ));// You havent learned glassblowing. - return; - } - // Cartography - socket.CloseGump( gumpID8, 0 ); - pUser.SetTempTag( "CRAFT", 9 ); - switch( tempPage ) - { - case 1: // Page 1 - TriggerEvent( Glassblowing, "PageX", socket, pUser, tempPage); - break; - default: TriggerEvent( Glassblowing, "PageX", socket, pUser, 1); - break; - } + // NOTE: fixed .Language -> .language here + socket.SysMessage( GetDictionaryEntry( 6300, socket.language )); // You haven't learned glassblowing. + return false; } - else if( iUsed.sectionID == "malletandchisel" ) + + // New glassblowing menu – Page 1 only for now + openCraftMenu( pUser, socket, GlassblowingID, 9, 1 ); + return false; + } + + // ------------------------------------------------------------------- + // Masonry (mallet and chisel) + // ------------------------------------------------------------------- + if( iUsed.sectionID == "malletandchisel" ) + { + if( pUser.GetTag( "StoneCrafting" ) == 0 ) { - if( pUser.GetTag( "StoneCrafting" ) == 0 ) - { - socket.SysMessage( GetDictionaryEntry( 6297, socket.language ));// You havent learned masonry. - return false; - } - // Masonry - socket.CloseGump( gumpID10, 0 ); - pUser.SetTempTag( "CRAFT", 10 ); - switch( tempPage ) - { - case 1: // Page 1 - case 2: // Page 2 - case 3: // Page 3 - case 4: // Page 4 - case 5: // Page 5 - case 6: // Page 6 - case 7: // Page 7 - case 8: // Page 8 - case 9: // Page 9 - TriggerEvent( Masonry, "PageX", socket, pUser, tempPage ); - break; - case 20: - TriggerEvent( Masonry, "Page20", socket, pUser ); - break; - default: TriggerEvent( Masonry, "PageX", socket, pUser, 1 ); - break; - } + socket.SysMessage( GetDictionaryEntry( 6297, socket.language )); // You haven't learned masonry. + return false; } + + // Masonry: Pages 1–9 = PageX, Page 20 = Page20 + openCraftMenu( pUser, socket, MasonryID, 10, 9, { 20: "Page20" } ); + return false; } + return false; -} +} \ No newline at end of file From 4ca6e3e9923c6ea999829d038be7f10a8dd56345 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:48:34 -0600 Subject: [PATCH 36/43] update combined --- data/dfndata/create/glassblowing.dfn | 120 +++- data/dfndata/items/skills/tools/alchemy.dfn | 101 +++ data/js/item/glassblowingbook.js | 8 +- data/js/item/sandminingbook.js | 2 +- data/js/skill/craft/craftgump.js | 8 +- data/js/skill/craft/glassblowing.js | 643 +++++++++++++++----- 6 files changed, 698 insertions(+), 184 deletions(-) diff --git a/data/dfndata/create/glassblowing.dfn b/data/dfndata/create/glassblowing.dfn index 18c05abd7..b91971368 100644 --- a/data/dfndata/create/glassblowing.dfn +++ b/data/dfndata/create/glassblowing.dfn @@ -2,7 +2,7 @@ { NAME=Empty Bottle ID=0x0f0e -RESOURCE=SAND 1 +RESOURCE=SAND 1 0x96d SKILL=0 1000 1150 ADDITEM=emptybottle MINRANK=1 @@ -14,7 +14,7 @@ SOUND=0x0242 { NAME=flask (small) ID=0x182e -RESOURCE=SAND 2 +RESOURCE=SAND 2 0x96d SKILL=0 1000 1150 ADDITEM=0x182e MINRANK=1 @@ -26,7 +26,7 @@ SOUND=0x0242 { NAME=flask (medium) ID=0x182a -RESOURCE=SAND 3 +RESOURCE=SAND 3 0x96d SKILL=0 1000 1150 ADDITEM=0x182a MINRANK=1 @@ -38,7 +38,7 @@ SOUND=0x0242 { NAME=flask (curved) ID=0x1832 -RESOURCE=SAND 3 +RESOURCE=SAND 3 0x96d SKILL=0 1000 1150 ADDITEM=0x1832 MINRANK=1 @@ -50,7 +50,7 @@ SOUND=0x0242 { NAME=flask (large #1) ID=0x1838 -RESOURCE=SAND 4 +RESOURCE=SAND 4 0x96d SKILL=0 1000 1150 ADDITEM=0x1838 MINRANK=1 @@ -62,7 +62,7 @@ SOUND=0x0242 { NAME=flask (large #2) ID=0x183b -RESOURCE=SAND 5 +RESOURCE=SAND 5 0x96d SKILL=0 1000 1150 ADDITEM=0x183b MINRANK=1 @@ -74,7 +74,7 @@ SOUND=0x0242 { NAME=flask (bubbling blue) ID=0x1844 -RESOURCE=SAND 5 +RESOURCE=SAND 5 0x96d SKILL=0 1000 1150 ADDITEM=bubblingblueflask MINRANK=1 @@ -86,7 +86,7 @@ SOUND=0x0242 { NAME=flask (bubbling purple) ID=0x1841 -RESOURCE=SAND 5 +RESOURCE=SAND 5 0x96d SKILL=0 1000 1150 ADDITEM=bubblingpurpleflask MINRANK=1 @@ -98,7 +98,7 @@ SOUND=0x0242 { NAME=flask (bubbling red) ID=0x183e -RESOURCE=SAND 7 +RESOURCE=SAND 7 0x96d SKILL=0 1000 1150 ADDITEM=bubblingredflask MINRANK=1 @@ -110,7 +110,7 @@ SOUND=0x0242 { NAME=empty vials ID=0x185b -RESOURCE=SAND 8 +RESOURCE=SAND 8 0x96d SKILL=0 1000 1150 ADDITEM=emptyvials MINRANK=1 @@ -122,7 +122,7 @@ SOUND=0x0242 { NAME=full vials ID=0x185d -RESOURCE=SAND 8 +RESOURCE=SAND 8 0x96d SKILL=0 1000 1150 ADDITEM=fullvials MINRANK=1 @@ -134,10 +134,106 @@ SOUND=0x0242 { NAME=spinning hourglass ID=0x1810 -RESOURCE=SAND 10 +RESOURCE=SAND 10 0x96d SKILL=0 1000 1150 ADDITEM=0x1810 MINRANK=1 MAXRANK=10 SOUND=0x0242 +} + +[ITEM 3012] +{ +NAME=hollow prism +ID=0x2f5d +RESOURCE=SAND 8 0x96d +SKILL=0 1000 1500 +ADDITEM=hollowprism +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3013] +{ +NAME=gargoyle floor mirror +ID=0x403A +RESOURCE=SAND 20 0x96d +SKILL=0 750 1250 +ADDITEM=gargoylefloormirror +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3014] +{ +NAME=gargoyle wall mirror +ID=0x4044 +RESOURCE=SAND 10 0x96d +SKILL=0 700 1200 +ADDITEM=gargoylewallmirror +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3015] +{ +NAME=empty venom vial +ID=0x0E24 +RESOURCE=SAND 1 0x96d +SKILL=0 520 1000 +ADDITEM=emptyvenomvial +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3016] +{ +NAME=empty oil flask +ID=0x1C18 +RESOURCE=SAND 5 0x96d +SKILL=0 600 1100 +ADDITEM=emptyoilflask +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3017] +{ +NAME=workable glass +ID=0x4B80 +RESOURCE=SAND 10 0x96d +SKILL=0 550 1050 +ADDITEM=workableglass +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3018] +{ +NAME=glass sword +ID=0x090c +RESOURCE=SAND 14 0x96d +SKILL=0 550 1050 +ADDITEM=glasssword +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 +} + +[ITEM 3019] +{ +NAME=glass staff +ID=0x0905 +RESOURCE=SAND 10 0x96d +SKILL=0 530 1030 +ADDITEM=glassstaff +MINRANK=1 +MAXRANK=10 +SOUND=0x0242 } \ No newline at end of file diff --git a/data/dfndata/items/skills/tools/alchemy.dfn b/data/dfndata/items/skills/tools/alchemy.dfn index d46e1a729..3828fbd4c 100644 --- a/data/dfndata/items/skills/tools/alchemy.dfn +++ b/data/dfndata/items/skills/tools/alchemy.dfn @@ -789,4 +789,105 @@ decay=1 value=10637 5318 origin=lbr script=5054 +} + +[0x2f5d] +{ +get=base_item +name=hollow prism +id=0x2f5d +weight=100 +restock=20 +movable=1 +decay=1 +good=51 +} + +[hollowprism] +{ +get=0x2f5d +} + +[0x403a] +{ +get=base_item +name=Gargoyle Floor Mirror +id=0x403a +weight=1000 +restock=20 +movable=1 +decay=1 +good=51 +} + +[0x4046] +{ +get=0x403a +id=0x4046 +} + +[gargoylefloormirror] +{ +get=0x403a 0x4046 +} + +[0x4044] +{ +get=base_item +name=Gargoyle Wall Mirror +id=0x4044 +weight=1000 +restock=20 +movable=1 +decay=1 +good=51 +} + +[0x4045] +{ +get=0x4044 +id=0x4045 +} + +[gargoylewallmirror] +{ +get=0x4044 0x4045 +} + +[emptyvenomvial] +{ +get=base_item +name=Empty Venom Vial +id=0x0E24 +weight=100 +restock=20 +movable=1 +decay=1 +good=51 +} + +[emptyoilflask] +{ +get=base_item +name=empty oil flask +id=0x1C18 +weight=100 +restock=20 +pilable=1 +movable=1 +decay=1 +good=51 +} + +[workableglass] +{ +get=base_item +name=workable glass +id=0x4B80 +weight=100 +restock=20 +pilable=1 +movable=1 +decay=1 +good=51 } \ No newline at end of file diff --git a/data/js/item/glassblowingbook.js b/data/js/item/glassblowingbook.js index acf70e220..57afa8322 100644 --- a/data/js/item/glassblowingbook.js +++ b/data/js/item/glassblowingbook.js @@ -14,20 +14,20 @@ function onUseChecked( pUser, iUsed ) } else if( pUser.skills[0] < 1000 ) { - socket.SysMessage( GetDictionaryEntry( 6301, socket.Language ) ); // Only a Grandmaster Alchemist can learn from this book. + socket.SysMessage( GetDictionaryEntry( 6301, socket.language )); // Only a Grandmaster Alchemist can learn from this book. } else if( pUser.GetTag( "GlassBlowing" ) == 1 ) { - socket.SysMessage( GetDictionaryEntry( 6302, socket.Language ) ); // You have already learned this information. + socket.SysMessage( GetDictionaryEntry( 6302, socket.language )); // You have already learned this information. } else if( iUsed.movable == 2 || iUsed.movable == 3 ) { - socket.SysMessage( GetDictionaryEntry( 774, socket.Language )); //That is locked down and you cannot use it + socket.SysMessage( GetDictionaryEntry( 774, socket.language )); //That is locked down and you cannot use it } else { pUser.SetTag( "GlassBlowing", 1 ); - socket.SysMessage( GetDictionaryEntry( 6303, socket.Language )); // You have learned to mine for stones. Target mountains when mining to find stones. + socket.SysMessage( GetDictionaryEntry( 6303, socket.language )); // You have learned to make items from glass. You will need to find miners to mine fine iUsed.Delete(); } } diff --git a/data/js/item/sandminingbook.js b/data/js/item/sandminingbook.js index 89f05f69a..7fa887671 100644 --- a/data/js/item/sandminingbook.js +++ b/data/js/item/sandminingbook.js @@ -22,7 +22,7 @@ function onUseChecked( pUser, iUsed ) } else if( iUsed.movable == 2 || iUsed.movable == 3 ) { - pSocket.SysMessage( GetDictionaryEntry( 774, pSocket.Language )); //That is locked down and you cannot use it + pSocket.SysMessage( GetDictionaryEntry( 774, pSocket.language )); //That is locked down and you cannot use it } else { diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 99795dd49..45330cae4 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -20,6 +20,7 @@ const Masonry = 4037; // unless the craftItems array in blacksmithing.js is updated with specific create entries for the // coloured weapon variants, they'll just be regular weapons with ore colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); function CraftingGumpMenu( myGump, socket ) { @@ -150,6 +151,11 @@ function CraftingGumpMenu( myGump, socket ) break; case 9: // Glassblowing grouplist = [13502]; //CATEGORIES + // Only show Glass Weapons (page 2) in SA+ era + if( coreShardEra >= EraStringToNum( "sa" )) + { + grouplist.push( 13503 ); // Glass Weapons + } gumpMenuName = 13501;//Cartography Menu break; case 10: // Masonry @@ -308,7 +314,7 @@ function CraftingGumpMenu( myGump, socket ) break; } - if( craftingSkillUsed != 2 && craftingSkillUsed != 6 && craftingSkillUsed != 8 ) + if( craftingSkillUsed != 2 && craftingSkillUsed != 6 && craftingSkillUsed != 8 && craftingSkillUsed != 9 ) { myGump.AddText( 50, 362, textHue, GetDictionaryEntry( resourcename, socket.language ) + " (" + resource.toString() + ")" ); diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 304b41a31..02ac1a063 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -1,215 +1,526 @@ /// // @ts-check -const LabelHue = 0x480; // Color of the text. -const LabelColor = 0x7FFF; // Second Color of text. -const scriptID = 4036; // Use this to tell the gump what script to close. -const gumpDelay = 2000; // Timer for the gump to reapear after crafting. -const itemDetailsScriptID = 4026; -const craftGumpID = 4027; +const textHue = 0x480; // Color hue for all text in the crafting gump +const glassblowingID = 4036; // Script ID used to identify and close this gump +const gumpDelay = 2000; // Delay (ms) before gump reappears after crafting +const itemDetailsScriptID = 4026; // Script ID used to show item detail tooltips +const craftGumpID = 4027; // TriggerEvent ID used to build the crafting gump UI +const itemsPerPage = 10; // Number of craftable items shown per gump subpage +const displayUnlearnedRecipes = true; // Show recipes player has not learned +const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); +const glassSkillID = 0; // alchmey skill +const glassHarvestDict = 13504; // sand ////////////////////////////////////////////////////////////////////////////////////////// -// The section below is the tables for each page. -// All you have to do is add the item to your dictionary -// and then list the dictionary number in the right page and it will -// add it to the crafting gump. -/////////////////////////////////////////////////////////////////////////////////////////// +// Glassblowing GlassBlowingMap +////////////////////////////////////////////////////////////////////////////////////////// + +const GlassBlowingMap = { + // Page 1 - Misc Glassware + 3000: { dictID: 13600, page: 1, timerID: 1 }, // empty bottle + 3001: { dictID: 13601, page: 1, timerID: 1 }, // flask (small) + 3002: { dictID: 13602, page: 1, timerID: 1 }, // flask (medium) + 3003: { dictID: 13603, page: 1, timerID: 1 }, // flask (curved) + 3004: { dictID: 13604, page: 1, timerID: 1 }, // flask (large #1) + 3005: { dictID: 13605, page: 1, timerID: 1 }, // flask (large #2) + 3006: { dictID: 13606, page: 1, timerID: 1 }, // flask (bubbling blue) + 3007: { dictID: 13607, page: 1, timerID: 1 }, // flask (bubbling purple) + 3008: { dictID: 13608, page: 1, timerID: 1 }, // flask (bubbling red) + 3009: { dictID: 13609, page: 1, timerID: 1 }, // empty vials + 3010: { dictID: 13610, page: 1, timerID: 1 }, // full vials + 3011: { dictID: 13611, page: 1, timerID: 1 }, // spinning hourglass + 3012: { customName: "hollow prism", page: 1, timerID: 1, minEra: "ml" }, // hollow prism + 3013: { customName: "gargoyle floor mirror", page: 1, timerID: 1, minEra: "sa" }, // Gargoyle Floor Mirror + 3014: { customName: "gargoyle wall mirror", page: 1, timerID: 1, minEra: "sa" }, // Gargoyle Wall Mirror + 3015: { customName: "empty venom vial", page: 1, timerID: 1, minEra: "sa" }, // Empty Venom Vial + 3016: { customName: "empty oil flask", page: 1, timerID: 1, minEra: "sa" }, // Empty Oil Flask + 3017: { customName: "workable glass", page: 1, timerID: 1, minEra: "sa" }, // Workable Glass + // Page 2 Glass Weapons + 3018: { customName: "glass sword", page: 2, timerID: 2, minEra: "sa" }, // Glass sword + 3019: { customName: "glass staff", page: 2, timerID: 2, minEra: "sa" } // Glass staff +}; + +// After the GlassBlowingMap literal +(function initGlassBlowingMap() +{ + for( var key in GlassBlowingMap ) + { + if( !GlassBlowingMap.hasOwnProperty( key )) + continue; + + var entry = GlassBlowingMap[key]; + + // Default skill (if not already set) + if( entry.skill === undefined ) + entry.skill = glassSkillID; + + // Default harvest list (if not already set) + if( !entry.harvest ) + entry.harvest = [ glassHarvestDict ]; + + // If you have special cases, you can override here, e.g.: + // if( key == "3017" ) { // workable glass + // entry.harvest = [ glassHarvestDict, 10016 ]; // sand + cloth + // } + } +})(); -const myPage = [ - // Page 1 - Misc - [13600, 13601, 13602, 13603, 13604, 13605, 13606, 13607, 13608, 13609, 13610, 13611 ] -]; +// If you ever need a specific item to use 2 or more resources, just override its harvest array: +// GlassBlowingMap[3017].harvest = [ glassHarvestDict, 10016 ]; // two harvest resources function PageX( socket, pUser, pageNum ) { - // Pages 1 - var myGump = new Gump; - pUser.SetTempTag( "page", pageNum ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - for ( var i = 0; i < myPage[pageNum - 1].length; i++ ) + if( !socket || !ValidateObject( pUser )) + return; + + var pageItems; + + // Special "Last Ten" page uses stored makeIDs directly + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenGlassblowing" ) || ""; + var split = lastTenRaw.split( "," ); + pageItems = []; + + for( var i = 0; i < split.length; i++ ) + { + var val = parseInt( split[i] ); + if( !isNaN( val )) + pageItems.push( val ); + } + } + else { - var index = i % 10; - if ( index == 0 ) + // Build list of makeIDs for this page from GlassBlowingMap + var makeIDs = []; + for( var makeIDStr in GlassBlowingMap ) + { + if( !GlassBlowingMap.hasOwnProperty( makeIDStr )) + continue; + + var makeID = parseInt( makeIDStr ); + var data = GlassBlowingMap[makeID]; + if( !data || data.page != pageNum ) + continue; + + makeIDs.push( makeID ); + } + + // Sort numeric so order is stable: 3000,3001,...,3012 + makeIDs.sort(function(a, b){ return a - b; }); + + // Filter by era / recipe in that order + pageItems = []; + for( var k = 0; k < makeIDs.length; k++ ) { - if ( i > 0 ) + var id = makeIDs[k]; + var data2 = GlassBlowingMap[id]; + if( !data2 ) + continue; + + var needsRecipe = data2.recipeID; + var showAll = displayUnlearnedRecipes; + + if( eraOK( data2 ) && ( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe ))) { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE + pageItems.push( id ); } + } - myGump.AddPage( ( i / 10 ) + 1 ); + // Fallback if page empty and not page 1 + if( pageItems.length == 0 && pageNum != 1 ) + { + pageNum = 1; - if ( i > 0 ) + makeIDs = []; + for( var makeIDStr2 in GlassBlowingMap ) { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE + if( !GlassBlowingMap.hasOwnProperty( makeIDStr2 )) + continue; + + var makeID2 = parseInt( makeIDStr2 ); + var data3 = GlassBlowingMap[makeID2]; + if( !data3 || data3.page != 1 ) + continue; + + makeIDs.push( makeID2 ); } - } - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, ( 100 * pageNum ) + i ); + makeIDs.sort(function(a, b){ return a - b; }); + + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) + { + var id2 = makeIDs[m]; + var data4 = GlassBlowingMap[id2]; + if( !data4 ) + continue; - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language ) ); + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + if( eraOK( data4 ) && ( !needsRecipe2 || showAll2 || HasLearnedRecipe( pUser, needsRecipe2 ))) + { + pageItems.push( id2 ); + } + } + } } - myGump.Send( socket ); - myGump.Free(); -} -/** @type { ( tObject: BaseObject, timerId: number ) => void } */ -function onTimer( pUser, timerID ) -{ - if( !ValidateObject( pUser )) - return; + // Subpage handling + var subPage = pUser.GetTempTag( "subPage" ); + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); - var socket = pUser.socket; + if( totalSubPages < 1 ) + totalSubPages = 1; - switch( timerID ) - { - case 1: // Page 1 - Maps - PageX( socket, pUser, timerID ); - break; - } -} + if( subPage < 1 ) + subPage = 1; -/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ -function onGumpPress( pSock, pButton, gumpData ) -{ - var pUser = pSock.currentChar; + if( subPage > totalSubPages ) + subPage = totalSubPages; - // Don't continue if character is invalid, or worse... dead! - if( !ValidateObject( pUser ) || pUser.dead ) - return; + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); - // Don't continue if player no longer has access to the crafting tool - var bItem = pSock.tempObj; - if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) - { - pSock.SysMessage( GetDictionaryEntry( 461, pSock.language )); // You are too far away. - return; - } + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); - if( bItem.movable == 3 ) + if( startIndex >= pageItems.length ) { - pSock.SysMessage( GetDictionaryEntry( 6031, pSock.language )); // Locked down resources cannot be used! - return; + subPage = 1; + startIndex = 0; + endIndex = Math.min( itemsPerPage, pageItems.length ); + pUser.SetTempTag( "subPage", subPage ); } - var iPackOwner = GetPackOwner( bItem, 0 ); - if( ValidateObject( iPackOwner )) // Is the item in a backpack? - { - if( iPackOwner.serial != pUser.serial ) // And if so does the pack belong to the user? - { - pSock.SysMessage( GetDictionaryEntry( 6032, pSock.language )); // That resource is in someone else's backpack! - return; - } - } - else + var glassGump = new Gump; + TriggerEvent( craftGumpID, "CraftingGumpMenu", glassGump, socket ); + glassGump.AddPage( 1 ); + + for( var j = startIndex; j < endIndex; j++ ) { - pSock.SysMessage( GetDictionaryEntry( 6022, pSock.language )); // This has to be in your backpack before you can use it. - return; - } + var index = j - startIndex; + var makeID = pageItems[j]; + var entryText; + var buttonID = makeID; - var gumpID = scriptID + 0xffff; - var makeID = 0; - var itemDetailsID = 0; - var timerID = 0; + var data5 = GlassBlowingMap[makeID]; - if(( pButton >= 100 && pButton <= 305 ) || pButton == 5000 ) - { - if( pButton == 5000 ) + if( !data5 ) { - // Make Last button - pButton = pUser.GetTempTag( "MAKELAST" ); + entryText = "[Missing MakeID: " + makeID + "]"; } else { - pUser.SetTempTag( "MAKELAST", pButton ); + if( data5.customName ) + { + entryText = data5.customName; + } + else if( data5.dictID ) + { + entryText = GetDictionaryEntry( data5.dictID, socket.language ); + if( !entryText || entryText === "" ) + entryText = "[Missing EntryID: " + data5.dictID + "]"; + } + else + { + entryText = "[Unnamed Item: " + makeID + "]"; + } } + + // Craft button uses makeID + glassGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, buttonID ); + glassGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); + + // Detail button: 20000 + makeID (matches your current onGumpPress) + glassGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + buttonID ); } - switch ( pButton ) + // Prev subpage + if( subPage > 1 ) { - case 0: // Abort and do nothing - pUser.SetTempTag( "MAKELAST", null ); - pUser.SetTempTag( "CRAFT", null ) - pSock.CloseGump( gumpID, 0 ); - break; - case 1: // Page 1 - Maps - pSock.CloseGump( gumpID, 0 ); - PageX( pSock, pUser, pButton ); - break; - // Make Items - case 100: // empty bottle - makeID = 3000; timerID = 1; break; - case 101: // flask (small) - makeID = 3001; timerID = 1; break; - case 102: // flask (medium) - makeID = 3002; timerID = 1; break; - case 103: // flask (curved) - makeID = 3003; timerID = 1; break; - case 103: // flask (large #1) - makeID = 3004; timerID = 1; break; - case 103: // flask (large #2) - makeID = 3005; timerID = 1; break; - case 103: // flask (bubbling blue) - makeID = 3006; timerID = 1; break; - case 103: // flask (bubbling purple) - makeID = 3007; timerID = 1; break; - case 103: // flask (bubbling red) - makeID = 3008; timerID = 1; break; - case 103: // empty vials - makeID = 3009; timerID = 1; break; - case 103: // full vials - makeID = 3010; timerID = 1; break; - case 103: // spinning hourglass - makeID = 3011; timerID = 1; break; - // Show Item Details - case 2100: // empty bottle - itemDetailsID = 3000; break; - case 2101: // flask (small) - itemDetailsID = 3001; break; - case 2102: // flask (medium) - itemDetailsID = 3002; break; - case 2103: // flask (curved) - itemDetailsID = 3003; break; - case 2104: // flask (large #1) - itemDetailsID = 3004; break; - case 2105: // flask (large #2) - itemDetailsID = 3005; break; - case 2106: // flask (bubbling blue) - itemDetailsID = 3006; break; - case 2107: // flask (bubbling purple) - itemDetailsID = 3007; break; - case 2108: // flask (bubbling red) - itemDetailsID = 3008; break; - case 2109: // empty vials - itemDetailsID = 3009; break; - case 2110: // full vials - itemDetailsID = 3010; break; - case 2111: // spinning hourglass - itemDetailsID = 3011; break; - default: - break; + glassGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + glassGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); } - if( makeID != 0 ) + // Next subpage + if( subPage < totalSubPages ) + { + glassGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + glassGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + glassGump.Send( socket ); + glassGump.Free(); +} + +/** @type { ( tObject: BaseObject, timerId: number ) => void } */ +function onTimer( pUser, timerID ) +{ + if( !ValidateObject( pUser )) + return; + + var pSocket = pUser.socket; + if( pSocket == null ) + return; + + if( timerID >= 1 && timerID <= 8 ) + { + PageX( pSocket, pUser, timerID ); + } + else if( timerID == 999 ) + { + PageX( pSocket, pUser, 999 ); + } +} + +/** @type { ( myObj: Socket, pressed: number, gump: GumpData ) => void } */ +function onGumpPress( socket, pButton, gumpData ) +{ + if( socket == null ) + return; + + var pUser = socket.currentChar; + + if( !ValidateObject( pUser ) || pUser.dead ) + return; + + var bItem = socket.tempObj; + if( !ValidateObject( bItem ) || !pUser.InRange( bItem, 3 )) + { + socket.SysMessage( GetDictionaryEntry( 461, socket.language )); + return; + } + + if( bItem.movable == 3 ) + { + socket.SysMessage( GetDictionaryEntry( 6031, socket.language )); + return; + } + + var iPackOwner = GetPackOwner( bItem, 0 ); + if( ValidateObject( iPackOwner )) + { + if( iPackOwner.serial != pUser.serial ) + { + socket.SysMessage( GetDictionaryEntry( 6032, socket.language )); + return; + } + } + else + { + socket.SysMessage( GetDictionaryEntry( 6022, socket.language )); + return; + } + + var gumpID = glassblowingID + 0xffff; + + // Subpage back / forward + if( pButton >= 8001 && pButton < 9000 ) + { + var subPage = pButton - 8000; + var pageNum = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage ); + PageX( socket, pUser, pageNum ); + return; + } + + if( pButton >= 9001 && pButton < 10000 ) + { + var subPage2 = pButton - 9000; + var pageNum2 = pUser.GetTempTag( "page" ); + pUser.SetTempTag( "subPage", subPage2 ); + PageX( socket, pUser, pageNum2 ); + return; + } + + // Page tabs + if( pButton >= 1 && pButton <= 8 ) + { + pUser.SetTempTag( "page", pButton ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, pButton ); + return; + } + + // Last Ten + if( pButton == 11000 ) + { + pUser.SetTempTag( "page", 999 ); + pUser.SetTempTag( "subPage", 1 ); + PageX( socket, pUser, 999 ); + return; + } + + // Close gump + if( pButton == 0 ) + { + pUser.SetTempTag( "MakeLast_Glass", null ); + pUser.SetTempTag( "CRAFT", null ); + socket.CloseGump( gumpID, 0 ); + return; + } + + var makeID = 0; + var timerID = 0; + + // Make Last + if( pButton == 5000 ) + { + var last = pUser.GetTempTag( "MakeLast_Glass" ); + if( last ) + pButton = last; + else + return; + } + + // Craft buttons use makeID directly + if( GlassBlowingMap[pButton] != undefined ) + { + makeID = pButton; + var data = GlassBlowingMap[makeID]; + timerID = data.timerID || 1; + + if( !eraOK( data )) + { + socket.SysMessage( "That item is not available in this era." ); + return; + } + + if( data.recipeID && !TriggerEvent( 4022, "NeedRecipe", pUser, data.recipeID )) + { + socket.SysMessage( "You must learn that recipe from a scroll." ); + return; + } + + pUser.SetTempTag( "MakeLast_Glass", makeID ); + + MakeItem( socket, pUser, makeID ); + AddToLastTen( pUser, makeID ); + + if( GetServerSetting( "ToolUseLimit" )) + { + bItem.usesLeft -= 1; + if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + { + bItem.Delete(); + socket.SysMessage( GetDictionaryEntry( 10202, socket.language )); + } + } + + pUser.StartTimer( gumpDelay, timerID, glassblowingID ); + return; + } + + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) { - pUser.AddScriptTrigger(4033); // crafting_complete.js for applying map settings - MakeItem( pSock, pUser, makeID ); - if( GetServerSetting( "ToolUseLimit" )) + var detailMakeID = pButton - 20000; + var entry = AlchemyMap[detailMakeID]; + + if( entry ) { - bItem.usesLeft -= 1; - if( bItem.usesLeft == 0 && GetServerSetting( "ToolUseBreak" )) + // Which item details to show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // Skill used + pUser.SetTempTag( "Skill", entry.skill || glassSkillID ); + + // Clear old harvest tags to avoid cross-contamination + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Clear old harvest names + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); + + // If you later add entry.harvest = [dictID1, dictID2,...], you can push them here + if( entry.harvest && entry.harvest.length > 0 ) { - bItem.Delete(); - pSock.SysMessage( GetDictionaryEntry( 10202, pSock.language )); // You have worn out your tool! - // Play sound effect of tool breaking + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); } + + // OPTIONAL custom names – these override the dictionary string + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + + if( entry.recipeID && entry.recipeID > 0 ) + pUser.SetTempTag( "needRecipeID", entry.recipeID ); + else + pUser.SetTempTag( "needRecipeID", 0 ); + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); } - pUser.StartTimer( gumpDelay, timerID, true ); - } - else if( itemDetailsID != 0 ) - { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + return; } } + +// Last Ten +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTempTag( "LastTenGlassblowing" ) || ""; + var list = raw.split( "," ); + + for( var i = 0; i < list.length; i++ ) + { + if( parseInt( list[i] ) == makeID ) + { + list.splice( i, 1 ); + break; + } + } + + var newList = [ makeID ]; + for( var j = 0; j < list.length && newList.length < 10; j++ ) + { + var entry = parseInt( list[j] ); + if( !isNaN( entry ) && entry > 0 ) + newList.push( entry ); + } + + pUser.SetTempTag( "LastTenGlassblowing", newList.join( "," ) ); +} + +function HasLearnedRecipe( pUser, recipeID ) +{ + var myData = TriggerEvent( 4022, "ReadRecipeID", pUser ); + if( !myData || myData.length == 0 ) + return false; + + for( var i = 0; i < myData.length; i++ ) + { + var data = myData[i].split( "," ); + if( data[0] == recipeID ) + return true; + } + return false; +} + +function eraOK( entry ) +{ + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + return true; +} \ No newline at end of file From 53574e9e074ce4c043256e33df6aa0e025891f26 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sun, 7 Dec 2025 22:42:32 -0600 Subject: [PATCH 37/43] Added Scales Added Dragon Scales to Blacksmithing --- data/dfndata/create/resources.dfn | 5 + data/dfndata/create/smithing.dfn | 59 +++++ data/dictionaries/dictionary.ENG | 6 + data/dictionaries/dictionary.ZRO | 6 + data/js/skill/craft/blacksmithing.js | 348 +++++++++++++++++++++------ data/js/skill/craft/craftgump.js | 42 ++++ data/js/skill/craft/masonry.js | 16 +- 7 files changed, 397 insertions(+), 85 deletions(-) diff --git a/data/dfndata/create/resources.dfn b/data/dfndata/create/resources.dfn index 188fa2388..0befb09ae 100644 --- a/data/dfndata/create/resources.dfn +++ b/data/dfndata/create/resources.dfn @@ -50,6 +50,11 @@ ID=0x1081 ID=0x1082 } +[RESOURCE SCALE] +{ +ID=0x26b4 +} + [RESOURCE BONE] { ID=0x0f7e diff --git a/data/dfndata/create/smithing.dfn b/data/dfndata/create/smithing.dfn index 21ddee92a..d7f0f3635 100644 --- a/data/dfndata/create/smithing.dfn +++ b/data/dfndata/create/smithing.dfn @@ -979,6 +979,65 @@ MAXRANK=10 SOUND=0x002A } +[ITEM 367] +{ +NAME=dragon sleeves +ID=0x2657 +RESOURCE=SCALE 24 +SKILL=7 763 1120 +ADDITEM=dragonsleeves +MINRANK=1 +MAXRANK=10 +SOUND=0x002A +} + +[ITEM 368] +{ +NAME=dragon breast plate +ID=0x2657 +RESOURCE=SCALE 36 +SKILL=7 850 1120 +ADDITEM=dragonbreastplate +MINRANK=1 +MAXRANK=10 +SOUND=0x002A +} + +[ITEM 369] +{ +NAME=dragon gloves +ID=0x2657 +RESOURCE=SCALE 16 +SKILL=7 689 1120 +ADDITEM=dragongloves +MINRANK=1 +MAXRANK=10 +SOUND=0x002A +} + +[ITEM 370] +{ +NAME=dragon helmet +ID=0x2657 +RESOURCE=SCALE 20 +SKILL=7 722 1120 +ADDITEM=dragonhelm +MINRANK=1 +MAXRANK=10 +SOUND=0x002A +} + +[ITEM 371] +{ +NAME=dragon leggings +ID=0x2657 +RESOURCE=SCALE 28 +SKILL=7 788 1120 +ADDITEM=dragonleggings +MINRANK=1 +MAXRANK=10 +SOUND=0x002A +} // end of blacksmithing section //***************************************** \ No newline at end of file diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index 614739c13..283f7ab65 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -4619,6 +4619,12 @@ 10296=You have no knowledge on how to unravel that. 10297=You unravel the item and place 5 resources in your pack. 20298=You aren't skilled enough to unravel this. +20299=RED SCALES +20300=YELLOW SCALES +20301=BLACK SCALES +20302=GREEN SCALES +20303=WHITE SCALES +20304=BLUE SCALES // [10600-10900] Carpentry Crafting Skill 10600=CARPENTRY MENU 10601=Other diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index 31cf82523..93c152a98 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -4616,6 +4616,12 @@ 10296=You have no knowledge on how to unravel that. 10297=You unravel the item and place 5 resources in your pack. 20298=You aren't skilled enough to unravel this. +20299=RED SCALES +20300=YELLOW SCALES +20301=BLACK SCALES +20302=GREEN SCALES +20303=WHITE SCALES +20304=BLUE SCALES // [10600-10900] Carpentry Crafting Skill 10600=CARPENTRY MENU 10601=Other diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index 8b331658c..8cd887418 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -17,6 +17,29 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); // regular weapons with ore colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); +const OreTypes = [ + { nameDict: 10291, hue: 0x0000, minMining: 0 }, // Iron + { nameDict: 10203, hue: 0x0973, minMining: 650 }, // Dull Copper + { nameDict: 10204, hue: 0x0966, minMining: 700 }, // Shadow Iron + { nameDict: 10205, hue: 0x07dd, minMining: 750 }, // Copper + { nameDict: 10206, hue: 0x06d6, minMining: 800 }, // Bronze + { nameDict: 10207, hue: 0x08a5, minMining: 850 }, // Gold + { nameDict: 10208, hue: 0x0979, minMining: 900 }, // Agapite + { nameDict: 10209, hue: 0x089f, minMining: 950 }, // Verite + { nameDict: 10210, hue: 0x08ab, minMining: 990 } // Valorite +]; + +const ScaleTypes = [ + // Example placeholders — replace with real values: + { nameDict: 20299, hue: 0x0663, minSkill: 0 }, // Red + { nameDict: 20300, hue: 0x084d, minSkill: 0 }, // Yellow + { nameDict: 20301, hue: 0x0455, minSkill: 0 }, // Black + { nameDict: 20302, hue: 0x0851, minSkill: 0 }, // Green + { nameDict: 20303, hue: 0x02c2, minSkill: 0 }, // White + { nameDict: 20304, hue: 0x0006, minSkill: 0 } // Blue + // add more as required +]; + // Optional: if you later decide to make some blacksmith items recipe-locked, we will use this map: // BlacksmithMap[buttonID] = { dictID, page, timerID, oreMake: [makeIDByOre], recipeID?, minEra?, maxEra? } // o--------------------------------------------------------------------------o @@ -133,7 +156,7 @@ const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); const myPage = [ // Page 1 - Metal Armors - [10217, 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10225, 10226, 10227, 10228, 10229], + [10217, 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10225, 10226, 10227, 10228, 10229, 0, 0, 0, 0 ,0], // Page 2 - Helmets [10230, 10231, 10232, 10233, 10234], // Page 3 - Shields @@ -152,7 +175,7 @@ const craftItems = [ // Iron [ // Metal Armors - [ 7, 9, 8, 10, 11, 12, 13, 16, 15, 14, 17, 18, 19 ], + [ 7, 9, 8, 10, 11, 12, 13, 16, 15, 14, 17, 18, 19, 367, 368, 369, 370, 371 ], // Helmets [ 46, 48, 45, 47, 49 ], // Shields @@ -377,6 +400,16 @@ const BlacksmithMap = {}; // BlacksmithMap[400].customName = "Elven Broadsword"; // BlacksmithMap[400].recipeID = 5101; // if you want it recipe-locked // BlacksmithMap[400].minEra = "ml"; // if you want it ML and later only +BlacksmithMap[113].customName = "Dragon Sleeves"; +BlacksmithMap[113].useScales = true; +BlacksmithMap[114].customName = "Dragon Breast Plate"; +BlacksmithMap[114].useScales = true; +BlacksmithMap[115].customName = "Dragon Gloves"; +BlacksmithMap[115].useScales = true; +BlacksmithMap[116].customName = "Dragon Helmet"; +BlacksmithMap[116].useScales = true; +BlacksmithMap[117].customName = "Dragon leggings"; +BlacksmithMap[117].useScales = true; function PageX( socket, pUser, pageNum ) { @@ -514,59 +547,124 @@ function PageX( socket, pUser, pageNum ) blacksmithMenu.Free(); } - function Page8( socket, pUser ) { - //Ingot Choices - var myGump = new Gump; - pUser.SetTempTag( "page", 8 ); - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - var iron = pUser.ResourceCount( 0x1BF2 ); - var bronze = pUser.ResourceCount( 0x1BF2, 0x06d6 ); - var copper = pUser.ResourceCount( 0x1BF2, 0x07dd ); - var agapite = pUser.ResourceCount( 0x1BF2, 0x0979 ); - var dullcopper = pUser.ResourceCount( 0x1BF2, 0x0973 ); - var gold = pUser.ResourceCount( 0x1BF2, 0x08a5 ); - var shadowiron = pUser.ResourceCount( 0x1BF2, 0x0966 ); - var valorite = pUser.ResourceCount( 0x1BF2, 0x08ab ); - var verite = pUser.ResourceCount( 0x1BF2, 0x089f ); - var myPage8 = [ - GetDictionaryEntry( 10291, socket.language ) + " (" + iron.toString() + ")", - GetDictionaryEntry( 10203, socket.language ) + " (" + dullcopper.toString() + ")", - GetDictionaryEntry( 10204, socket.language ) + " (" + shadowiron.toString() + ")", - GetDictionaryEntry( 10205, socket.language ) + " (" + copper.toString() + ")", - GetDictionaryEntry( 10206, socket.language ) + " (" + bronze.toString() + ")", - GetDictionaryEntry( 10207, socket.language ) + " (" + gold.toString() + ")", - GetDictionaryEntry( 10208, socket.language ) + " (" + agapite.toString() + ")", - GetDictionaryEntry( 10209, socket.language ) + " (" + verite.toString() + ")", - GetDictionaryEntry( 10210, socket.language ) + " (" + valorite.toString() + ")" - ]; - - for( var i = 0; i < myPage8.length; i++ ) - { - var index = i % 10; - if( index == 0 ) - { - if( i > 0 ) - { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10100, socket.language ) + "" );// NEXT PAGE - } - - myGump.AddPage(( i / 10 ) + 1 ); - - if( i > 0 ) - { - myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, 0, 0, "" + GetDictionaryEntry( 10101, socket.language ) + "" );// PREV PAGE - } - } + // Ingot choices page + var myGump = new Gump(); + pUser.SetTempTag( "page", 8 ); + + // Draw standard crafting frame (title, buttons, notices etc.) + TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); + + // Count ingots by hue + var iron = pUser.ResourceCount( 0x1BF2 ); + var dullcopper = pUser.ResourceCount( 0x1BF2, 0x0973 ); + var shadowiron = pUser.ResourceCount( 0x1BF2, 0x0966 ); + var copper = pUser.ResourceCount( 0x1BF2, 0x07dd ); + var bronze = pUser.ResourceCount( 0x1BF2, 0x06d6 ); + var gold = pUser.ResourceCount( 0x1BF2, 0x08a5 ); + var agapite = pUser.ResourceCount( 0x1BF2, 0x0979 ); + var verite = pUser.ResourceCount( 0x1BF2, 0x089f ); + var valorite = pUser.ResourceCount( 0x1BF2, 0x08ab ); + + var counts = [ iron, dullcopper, shadowiron, copper, bronze, gold, agapite, verite, valorite ]; + + var lines = []; + for( var i = 0; i < OreTypes.length; i++ ) + { + var oreInfo = OreTypes[i]; + var label = GetDictionaryEntry( oreInfo.nameDict, socket.language ); + lines.push( label + " (" + counts[i].toString() + ")" ); + } + + for( var j = 0; j < lines.length; j++ ) + { + var index = j % 10; + + if( index == 0 ) + { + if( j > 0 ) + { + myGump.AddButton( 370, 260, 4005, 4007, 0, ( j / 10 ) + 1, 0 ); + myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + myGump.AddPage(( j / 10 ) + 1 ); + + if( j > 0 ) + { + myGump.AddButton( 220, 260, 4014, 4015, 0, j / 10, 0 ); + myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + } + + myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1000 + j ); + myGump.AddText( 255, 60 + ( index * 20 ), textHue, lines[j] ); + } + + myGump.Send( socket ); + myGump.Free(); +} - myGump.AddButton( 220, 60 + ( index * 20), 4005, 4007, 1, 0, 1000 + i ); - myGump.AddText( 255, 60 + ( index * 20), textHue, myPage8[i] ); - } - myGump.Send( socket ); - myGump.Free(); +function Page30( socket, pUser ) +{ + var myGump = new Gump(); + pUser.SetTempTag( "page", 30 ); // page index for scales (use any unused index) + + // Base crafting frame (same as other pages) + TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); + + // Count scales in backpack by hue (update IDs/hues as needed) + // If all scales share the same item ID but different hues, adjust this. + var counts = []; + + for( var i = 0; i < ScaleTypes.length; i++ ) + { + var scaleInfo = ScaleTypes[i]; + + // Example: if all scales share a single ID (replace 0x26B4 with your scale item ID) + // counts[i] = pUser.ResourceCount( 0x26B4, scaleInfo.hue ); + + // If you have different IDs per scale type, change the above line as needed. + counts[i] = pUser.ResourceCount( 0x26b4, scaleInfo.hue );; // placeholder so script parses; you’ll replace with real logic + } + + var lines = []; + for( var j = 0; j < ScaleTypes.length; j++ ) + { + var sInfo = ScaleTypes[j]; + var label = GetDictionaryEntry( sInfo.nameDict, socket.language ); + lines.push( label + " (" + counts[j].toString() + ")" ); + } + + for( var k = 0; k < lines.length; k++ ) + { + var index = k % 10; + + if( index == 0 ) + { + if( k > 0 ) + { + myGump.AddButton( 370, 260, 4005, 4007, 0, ( k / 10 ) + 1, 0 ); + myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE + } + + myGump.AddPage(( k / 10 ) + 1 ); + + if( k > 0 ) + { + myGump.AddButton( 220, 260, 4014, 4015, 0, k / 10, 0 ); + myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE + } + } + + // Use a separate button range from ores to avoid conflicts: 1100+ + myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1100 + k ); + myGump.AddText( 255, 60 + ( index * 20 ), textHue, lines[k] ); + } + + myGump.Send( socket ); + myGump.Free(); } function FindNearbyAnvils( pUser, trgItem, pSock ) @@ -954,6 +1052,10 @@ function onTimer( pUser, timerID ) { Page8( socket, pUser ); // Ingot selection } + else if( timerID == 30 ) + { + Page30( socket, pUser ); // Scale selection + } else if( timerID == 999 ) { PageX( socket, pUser, 999 ); // Last Ten Blacksmith (if used) @@ -1023,6 +1125,14 @@ function onGumpPress( pSock, pButton, gumpData ) return; } + // Select Materials (scales) + if( pButton == 51 ) + { + pSock.CloseGump( gumpID, 0 ); + Page30( pSock, pUser ); + return; + } + // Smelt Item if( pButton == 52 ) { @@ -1040,6 +1150,65 @@ function onGumpPress( pSock, pButton, gumpData ) return; } + // Handle ore selection buttons (1000–1008) BEFORE the main switch + if( pButton >= 1000 && pButton <= 1008 ) + { + var index = pButton - 1000; // 0..8 + var oreInfo = OreTypes[index]; + var miningSkill = pUser.skills.mining; // you are already using skills.mining in smelting logic + + if( miningSkill < oreInfo.minMining ) + { + // Not enough mining skill for this ore + pSock.CloseGump( gumpID, 0 ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + // Re-open ore page after a short delay + pUser.StartTimer( ingotDelay, 8, true ); + return; + } + + // Set selected ore and hue + pUser.SetTempTag( "ORE", index ); + pUser.SetTempTag( "resourceHue", oreInfo.hue ); + pUser.SetTempTag( "MAKELAST", null ); + pUser.SetTempTag( "prevActionResult", null ); + + // Re-open ore page so they see the new counts/selection + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 8, true ); + return; + } + + // Handle scale selection buttons (1100–11XX) BEFORE the main switch + if (pButton >= 1100 && pButton < 1100 + ScaleTypes.length) + { + var sIndex = pButton - 1100; // 0..ScaleTypes.length-1 + var sInfo = ScaleTypes[sIndex]; + var smithSkill = pUser.skills.blacksmithing; // or mining / whatever you want to gate on + + if( smithSkill < sInfo.minSkill ) + { + // Not enough skill for this scale type + pSock.CloseGump( gumpID, 0 ); + pUser.SetTempTag( "prevActionResult", "FAILED" ); + pUser.StartTimer( ingotDelay, 30, true ); // reopen scale page after delay + return; + } + + // Store selection + pUser.SetTempTag( "Scale", sIndex ); + pUser.SetTempTag( "resourceHue", sInfo.hue ); + pUser.SetTempTag( "MAKELAST", null ); + pUser.SetTempTag( "prevActionResult", null ); + + // If you want a separate "make last" for scales, you could also SetTempTag("SCALEMAKELAST", ...) + // For now we just store the current selection. + + pSock.CloseGump( gumpID, 0 ); + pUser.StartTimer( ingotDelay, 30, true ); // reopen PageScales to show updated selection/notice + return; + } + // Last Ten page (if you wire it into the gump) if( pButton == 11000 ) { @@ -1108,30 +1277,46 @@ function onGumpPress( pSock, pButton, gumpData ) pUser.SetTempTag( "Harvest3Name", null ); pUser.SetTempTag( "Harvest4Name", null ); - if( entry.harvest && entry.harvest.length > 0 ) - { - if( entry.harvest.length >= 1 ) - pUser.SetTempTag( "Harvest", entry.harvest[0] ); - if( entry.harvest.length >= 2 ) - pUser.SetTempTag( "Harvest2", entry.harvest[1] ); - if( entry.harvest.length >= 3 ) - pUser.SetTempTag( "Harvest3", entry.harvest[2] ); - if( entry.harvest.length >= 4 ) - pUser.SetTempTag( "Harvest4", entry.harvest[3] ); - } - - // OPTIONAL custom names – these override the dictionary string - if( entry.harvestNames && entry.harvestNames.length > 0 ) - { - if( entry.harvestNames.length >= 1 ) - pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); - if( entry.harvestNames.length >= 2 ) - pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); - if( entry.harvestNames.length >= 3 ) - pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); - if( entry.harvestNames.length >= 4 ) - pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); - } + // If this entry uses dragon scales, override resource label + if( entry.useScales ) + { + // Use currently selected scale type (from Page30 selection) + var sIndex = pUser.GetTempTag( "Scale" ); + if( sIndex < 0 || sIndex >= ScaleTypes.length ) + sIndex = 0; + + var sInfo = ScaleTypes[sIndex]; + var sLabel = GetDictionaryEntry( sInfo.nameDict, pSock.language ); + pUser.SetTempTag( "HarvestName", sLabel ); + } + else + { + // Normal ingot-based items: use the harvest setup as before + if( entry.harvest && entry.harvest.length > 0 ) + { + if( entry.harvest.length >= 1 ) + pUser.SetTempTag( "Harvest", entry.harvest[0] ); + if( entry.harvest.length >= 2 ) + pUser.SetTempTag( "Harvest2", entry.harvest[1] ); + if( entry.harvest.length >= 3 ) + pUser.SetTempTag( "Harvest3", entry.harvest[2] ); + if( entry.harvest.length >= 4 ) + pUser.SetTempTag( "Harvest4", entry.harvest[3] ); + } + + // OPTIONAL custom names – these override the dictionary string + if( entry.harvestNames && entry.harvestNames.length > 0 ) + { + if( entry.harvestNames.length >= 1 ) + pUser.SetTempTag( "HarvestName", entry.harvestNames[0] ); + if( entry.harvestNames.length >= 2 ) + pUser.SetTempTag( "Harvest2Name", entry.harvestNames[1] ); + if( entry.harvestNames.length >= 3 ) + pUser.SetTempTag( "Harvest3Name", entry.harvestNames[2] ); + if( entry.harvestNames.length >= 4 ) + pUser.SetTempTag( "Harvest4Name", entry.harvestNames[3] ); + } + } if( entry.recipeID && entry.recipeID > 0 ) pUser.SetTempTag( "needRecipeID", entry.recipeID ); @@ -1149,7 +1334,16 @@ function onGumpPress( pSock, pButton, gumpData ) if( BlacksmithMap[pButton] != undefined ) { var entry2 = BlacksmithMap[pButton]; - var oreID = pUser.GetTempTag( "ORE" ); + var oreID; + if( entry2.useScales ) + { + // For dragon armor, index into oreMake[] by selected scale index + oreID = pUser.GetTempTag( "Scale" ); + } + else + { + oreID = pUser.GetTempTag( "ORE" ); + } var resourceHue = pUser.GetTempTag( "resourceHue" ); // Ensure oreID within range diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 45330cae4..f65735918 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -55,8 +55,17 @@ function CraftingGumpMenu( myGump, socket ) var veritegranite = pUser.ResourceCount( 0x1779, 0x089f ); var valoritegranite = pUser.ResourceCount( 0x1779, 0x08ab ); + var redScales = pUser.ResourceCount( 0x26b4, 0x0663 ); // red scales + var yellowScales = pUser.ResourceCount( 0x26b4, 0x084d); // yellow scales + var blackScales = pUser.ResourceCount( 0x26b4, 0x0455); // Black scales + var greenScales = pUser.ResourceCount( 0x26b4, 0x0851); // Green scales + var whiteScales = pUser.ResourceCount( 0x26b4, 0x02c2 ); // White scales + var blueScales = pUser.ResourceCount( 0x26b4, 0x0006); // Blue scales + var resourcename = 10291; + var resourcename2 = 10291; var resource = iron; + var resource2 = whiteScales; var groupList; var gumpMenuName = ""; var repair = 51; @@ -135,6 +144,37 @@ function CraftingGumpMenu( myGump, socket ) resource = iron; break; } + switch( pUser.GetTempTag( "Scale" )) + { + case 0: + resourcename2 = 20299; + resource2 = redScales; + break; + case 1: + resourcename2 = 20300; + resource2 = yellowScales; + break; + case 2: + resourcename2 = 20301; + resource2 = blackScales; + break; + case 3: + resourcename2 = 20302; + resource2 = greenScales; + break; + case 4: + resourcename2 = 20303; + resource2 = whiteScales; + break; + case 5: + resourcename2 = 20304; + resource2 = blueScales; + break; + default: + resourcename2 = 20299; + resource2 = redScales; + break; + } repair = 49; break; case 6: // Cooking @@ -326,6 +366,8 @@ function CraftingGumpMenu( myGump, socket ) if( craftingSkillUsed == 5 ) { + myGump.AddText( 50, 380, textHue, GetDictionaryEntry( resourcename2, socket.language ) + " (" + resource2.toString() + ")" ); + myGump.AddButton(15, 380, 4005, 4007, 1, 0, 51); // Material Selection Button // Blacksmithing myGump.AddButton(270, 342, 0xfa5, 1, 0, repair); // Repair Button myGump.AddHTMLGump(305, 345, 150, 18, 0, 0, "" + GetDictionaryEntry( 10212, socket.language ) + "" );// REPAIR ITEM diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 228033e0e..66f774315 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -1367,7 +1367,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 650 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1378,7 +1378,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 700 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1389,7 +1389,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 750 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1400,7 +1400,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 800 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1411,7 +1411,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 850 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1422,7 +1422,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 900 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1433,7 +1433,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 950 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } @@ -1444,7 +1444,7 @@ function onGumpPress( pSock, pButton, gumpData ) if( miningSkill < 990 ) { pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 8, true ); + pUser.StartTimer( ingotDelay, 20, true ); pUser.SetTempTag( "prevActionResult", "FAILED" ); return; } From c12365d4cdfc262739fa0f48d5d5bec4f8acd220 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sun, 7 Dec 2025 22:50:44 -0600 Subject: [PATCH 38/43] Update blacksmithing.js --- data/js/skill/craft/blacksmithing.js | 1 - 1 file changed, 1 deletion(-) diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index 8cd887418..ad4c220ee 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -30,7 +30,6 @@ const OreTypes = [ ]; const ScaleTypes = [ - // Example placeholders — replace with real values: { nameDict: 20299, hue: 0x0663, minSkill: 0 }, // Red { nameDict: 20300, hue: 0x084d, minSkill: 0 }, // Yellow { nameDict: 20301, hue: 0x0455, minSkill: 0 }, // Black From 3247890af877ee2120c130906552b4168db7f876 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 12 May 2026 16:14:31 -0500 Subject: [PATCH 39/43] fixes --- data/js/skill/craft/blacksmithing.js | 12 ++++++------ data/js/skill/craft/glassblowing.js | 2 +- data/js/skill/craft/itemdetailgump.js | 2 +- data/js/skill/craft/masonry.js | 2 +- data/js/skill/craft/recipe_data.js | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index ad4c220ee..158f6526e 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -50,7 +50,7 @@ const ScaleTypes = [ // | system used by the tailoring script. | // | | // | All craftable items are defined in tables (myPage, craftItems) and | -// | then mapped into a MasonryMap structure that controls: | +// | then mapped into a BlacksmithMap structure that controls: | // | - Which dictionary entry is shown per row | // | - Which "makeID" entry is used for each ore type | // | - Which page and timer ID to use when reopening the gump | @@ -59,11 +59,11 @@ const ScaleTypes = [ // | | // | The script also handles: | // | - iron selection (iron / colored ores) with skill requirements | -// | - Smelting iron items back into Granite | +// | - Smelting iron items back into ingots | // | - Repairing stone armor and weapons at an anvil | // | - Tool wear and runic hammer handling | // | - A "Make Last" feature | -// | - A "Last Ten Masonry" list (optional) | +// | - A "Last Ten Blacnksmithing" list (optional) | // o--------------------------------------------------------------------------o // | Data Tables | // o--------------------------------------------------------------------------o @@ -79,7 +79,7 @@ const ScaleTypes = [ // | | // | Each entry is a dictionary ID that will be used to look up the text | // | for that row, unless a customName is defined for that button in | -// | MasonryMap. | +// | BlacksmithMap. | // | | // | craftItems | // | craftItems[ironIndex][pageIndex][itemIndex] = makeID | @@ -93,7 +93,7 @@ const ScaleTypes = [ // | oreIndex 7 = Verite | // | oreIndex 8 = Valorite | // | | -// | For each granite type and page, this holds the createEntry ID used by | +// | For each ingot type and page, this holds the createEntry ID used by | // | MakeItem when the player crafts that item. The same index positions | // | on each page line up with the matching entries in myPage. | // o--------------------------------------------------------------------------o @@ -133,7 +133,7 @@ const ScaleTypes = [ // | 3. A fallback "[Unnamed Item: buttonID]" | // | | // | Recipes | -// | If recipeID is set on a MasonryMap entry, onGumpPress will call: | +// | If recipeID is set on a BlacksmithMap entry, onGumpPress will call: | // | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | // | to check if the player has learned that recipe. If not, the craft | // | attempt is blocked and a message is shown. | diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 02ac1a063..364e88a7d 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -67,7 +67,7 @@ const GlassBlowingMap = { // If you ever need a specific item to use 2 or more resources, just override its harvest array: // GlassBlowingMap[3017].harvest = [ glassHarvestDict, 10016 ]; // two harvest resources - +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) { if( !socket || !ValidateObject( pUser )) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 28fda39e6..845376fd9 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -112,7 +112,7 @@ function ItemDetailGump( pUser ) } else {// if all fails fallback to alchemy - mainSkill = mainSkill = parseInt( pUser.skills.alchemy ); + mainSkill = parseInt( pUser.skills.alchemy ); } // Helper to build harvest entries with both id + optional custom name diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 66f774315..912973f17 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -1,7 +1,7 @@ /// // @ts-check const textHue = 0x480; // Color of the text. -const masonryID = 4023; // Script ID used to identify and close this gump +const masonryID = 4037; // Script ID used to identify and close this gump const gumpDelay = 2000; // Timer for the gump to reappear after crafting. const ingotDelay = 200; // Timer for the gump to reappear after selecting an ingot. const repairDelay = 200; // Timer for the gump to reappear after repairing an item diff --git a/data/js/skill/craft/recipe_data.js b/data/js/skill/craft/recipe_data.js index 2cb20aeb2..fde1c2d01 100644 --- a/data/js/skill/craft/recipe_data.js +++ b/data/js/skill/craft/recipe_data.js @@ -6,7 +6,7 @@ function AddRecipe( pUser, iUsed, recipeID, recipeSectionID ) // Read Recipe var myData = ReadRecipeID( pUser ); - for( let i = 0; i < myData.length; i++ ) + for( var i = 0; i < myData.length; i++ ) { var myRecipeData = myData[i].split(","); @@ -35,7 +35,7 @@ function NeedRecipe( pSock, recipeID ) if( myData && myData.length > 0 ) { - for( let i = 0; i < myData.length; i++ ) + for( var i = 0; i < myData.length; i++ ) { var myRecipeData = myData[i].split(","); From 0142695b731b82e17d1bd44f268ecb887e3aee9f Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 13 May 2026 00:12:42 -0500 Subject: [PATCH 40/43] json tinkering --- data/js/jsdata/crafting/tinkering.json | 78 +++++++ data/js/jse_fileassociations.scp | 1 + data/js/skill/craft/craftmap_registry.js | 253 +++++++++++++++++++++++ data/js/skill/craft/tinkering.js | 56 ++++- 4 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 data/js/jsdata/crafting/tinkering.json create mode 100644 data/js/skill/craft/craftmap_registry.js diff --git a/data/js/jsdata/crafting/tinkering.json b/data/js/jsdata/crafting/tinkering.json new file mode 100644 index 000000000..1205f0f72 --- /dev/null +++ b/data/js/jsdata/crafting/tinkering.json @@ -0,0 +1,78 @@ +[ + { "makeID": 274, "label": "Axle", "dictID": 11801, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 273, "label": "Clock Frame", "dictID": 11802, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 270, "label": "Jointing Plane", "dictID": 11803, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 271, "label": "Moulding Plane", "dictID": 11804, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 272, "label": "Smoothing Plane", "dictID": 11805, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 218, "label": "Dovetail Saw", "dictID": 11820, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 215, "label": "Draw Knife", "dictID": 11821, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 252, "label": "Froe", "dictID": 11822, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 255, "label": "Hammer", "dictID": 11823, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 214, "label": "Hatchet", "dictID": 11824, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 258, "label": "Inshave", "dictID": 11825, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 260, "label": "Lockpick", "dictID": 11826, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 211, "label": "Mortar and Pestle", "dictID": 11827, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 259, "label": "Pick Axe", "dictID": 11828, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 217, "label": "Saw", "dictID": 11829, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 210, "label": "Scissors", "dictID": 11830, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 212, "label": "Scorp", "dictID": 11831, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 216, "label": "Sewing Kit", "dictID": 11832, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 254, "label": "Shovel", "dictID": 11833, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 257, "label": "Sledge Hammer", "dictID": 11834, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 256, "label": "Smith's Hammer", "dictID": 11835, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 253, "label": "Tongs", "dictID": 11836, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 213, "label": "Tool Kit (Tinker's tools)", "dictID": 11837, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 284, "label": "Fletcher's Tools", "dictID": 11838, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 224, "label": "Barrel Hoops", "dictID": 11860, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 221, "label": "Barrel Tap", "dictID": 11861, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 220, "label": "Clock parts", "dictID": 11862, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 219, "label": "Gears", "dictID": 11863, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 225, "label": "Hinge", "dictID": 11864, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 223, "label": "Sextant parts", "dictID": 11865, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 222, "label": "Springs", "dictID": 11866, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 226, "label": "Butcher Knife", "dictID": 11880, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 232, "label": "Cleaver", "dictID": 11881, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 230, "label": "Fork", "dictID": 11882, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 231, "label": "Fork", "dictID": 11883, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 235, "label": "Goblet", "dictID": 11884, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 233, "label": "Knife", "dictID": 11885, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 234, "label": "Knife", "dictID": 11886, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 236, "label": "Pewter Mug", "dictID": 11887, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 229, "label": "Plate", "dictID": 11888, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 237, "label": "Skinning Knife", "dictID": 11889, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 227, "label": "Spoon", "dictID": 11890, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 228, "label": "Spoon", "dictID": 11891, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 243, "label": "Bracelet", "dictID": 11900, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, + { "makeID": 241, "label": "Earrings", "dictID": 11901, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, + { "makeID": 239, "label": "Necklage (Golden beads)", "dictID": 11902, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, + { "makeID": 240, "label": "Necklace (Silver beads)", "dictID": 11903, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, + { "makeID": 242, "label": "Necklace (Round)", "dictID": 11904, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, + { "makeID": 238, "label": "Weddingband (newbiefied)", "dictID": 11905, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12006] }, + { "makeID": 245, "label": "Candelabra", "dictID": 11920, "page": 6, "timerID": 6, "harvest": [10015, 12000] }, + { "makeID": 248, "label": "Globe", "dictID": 11921, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 251, "label": "Heating stand", "dictID": 11922, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 247, "label": "Iron Key", "dictID": 11923, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 244, "label": "Keyring", "dictID": 11924, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 250, "label": "Lantern", "dictID": 11925, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 246, "label": "Scales", "dictID": 11926, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 249, "label": "Spy glass", "dictID": 11927, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 275, "label": "Axle and Gears", "dictID": 11940, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 276, "label": "Clock", "dictID": 11941, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, + { "makeID": 277, "label": "Clock", "dictID": 11942, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, + { "makeID": 278, "label": "Clock Parts", "dictID": 11943, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 279, "label": "Locked Box", "dictID": 11944, "page": 7, "timerID": 7, "harvest": [10634] }, + { "makeID": 280, "label": "Locked Chest", "dictID": 11945, "page": 7, "timerID": 7, "harvest": [10638] }, + { "makeID": 281, "label": "Potion Keg", "dictID": 11946, "page": 7, "timerID": 7, "harvest": [10642, 11861, 10612, 10928] }, + { "makeID": 282, "label": "Sextant", "dictID": 11947, "page": 7, "timerID": 7, "harvest": [11948] }, + { "makeID": 283, "label": "Sextant Parts", "dictID": 11948, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 310, "label": "Standing Candelabra", "dictID": 11961, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 315, "label": "Regular Candle", "dictID": 11962, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 312, "label": "Round Candle", "dictID": 11963, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 316, "label": "Skull with Candle", "dictID": 11964, "page": 8, "timerID": 8, "harvest": [12000, 12004] }, + { "makeID": 314, "label": "Small Candle", "dictID": 11965, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 311, "label": "Tall Candle", "dictID": 11966, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 313, "label": "Thick Candle", "dictID": 11967, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 261, "label": "Dart Trap", "dictID": 11980, "page": 9, "timerID": 9, "harvest": [10015, 12001] }, + { "makeID": 263, "label": "Explosion Trap", "dictID": 11981, "page": 9, "timerID": 9, "harvest": [10015, 12003] }, + { "makeID": 262, "label": "Poison Trap", "dictID": 11982, "page": 9, "timerID": 9, "harvest": [10015, 12002] } +] \ No newline at end of file diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 4a645f58c..74fe04152 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -244,6 +244,7 @@ 4035=skill/craft/cartography.js 4036=skill/craft/glassblowing.js 4037=skill/craft/masonry.js +4038=skill/craft/craftmap_registry.js 4050=skill/mining.js 4055=skill/snooping.js diff --git a/data/js/skill/craft/craftmap_registry.js b/data/js/skill/craft/craftmap_registry.js new file mode 100644 index 000000000..095740163 --- /dev/null +++ b/data/js/skill/craft/craftmap_registry.js @@ -0,0 +1,253 @@ +/// +// @ts-check + +var craftMapRegistry = {}; +var craftMapRegistryLoaded = {}; +var craftMapRegistryLoadError = {}; + +/** @type { ( craftName: string ) => object|null } */ +function CraftMapRegistry( craftName ) +{ + craftName = NormalizeCraftMapName( craftName ); + + if( craftName == "" ) + { + Console.Warning( "CraftMap system: Missing craft map name." ); + return null; + } + + if( !craftMapRegistryLoaded[craftName] ) + { + LoadCraftMapRegistry( craftName ); + } + + return craftMapRegistry[craftName] || null; +} + +/** @type { ( craftName: string ) => void } */ +function ReloadCraftMapRegistry( craftName ) +{ + craftName = NormalizeCraftMapName( craftName ); + + if( craftName == "" ) + { + craftMapRegistry = {}; + craftMapRegistryLoaded = {}; + craftMapRegistryLoadError = {}; + return; + } + + craftMapRegistry[craftName] = null; + craftMapRegistryLoaded[craftName] = false; + craftMapRegistryLoadError[craftName] = false; + + LoadCraftMapRegistry( craftName ); +} + +/** @type { ( craftName: string ) => void } */ +function LoadCraftMapRegistry( craftName ) +{ + craftName = NormalizeCraftMapName( craftName ); + + craftMapRegistry[craftName] = null; + craftMapRegistryLoaded[craftName] = false; + craftMapRegistryLoadError[craftName] = false; + + var fileName = craftName + ".json"; + + var craftMapFile = new UOXCFile(); + craftMapFile.Open( fileName, "r", "crafting", true ); + + if( craftMapFile == null || craftMapFile.Length() < 0 ) + { + Console.Error( "CraftMap system: Unable to open js/jsdata/crafting/" + fileName ); + craftMapRegistryLoadError[craftName] = true; + return; + } + + var fileText = ""; + while( !craftMapFile.EOF() ) + { + var rawLine = craftMapFile.ReadUntil( "\n" ); + if( rawLine != null && typeof( rawLine ) != "undefined" ) + { + fileText += rawLine; + } + } + + craftMapFile.Close(); + craftMapFile.Free(); + + fileText = SanitizeCraftMapJsonText( fileText ); + + if( fileText == "" ) + { + Console.Error( "CraftMap system: " + fileName + " is empty after sanitizing." ); + craftMapRegistryLoadError[craftName] = true; + return; + } + + var parsedCraftMap = null; + + try + { + parsedCraftMap = JSON.parse( fileText ); + } + catch( error ) + { + Console.Error( "CraftMap system: Failed to parse " + fileName + ": " + error ); + craftMapRegistryLoadError[craftName] = true; + return; + } + + if( !IsCraftMapArrayValue( parsedCraftMap ) ) + { + Console.Error( "CraftMap system: " + fileName + " must contain a JSON array." ); + craftMapRegistryLoadError[craftName] = true; + return; + } + + craftMapRegistry[craftName] = []; + + for( var i = 0; i < parsedCraftMap.length; i++ ) + { + var entry = parsedCraftMap[i]; + + if( !ValidateCraftMapEntry( entry, craftName, i ) ) + { + continue; + } + + craftMapRegistry[craftName].push( entry ); + } + + Console.Print( "CraftMap system: Loaded " + craftMapRegistry[craftName].length + " entries from " + fileName + ".\n" ); + + craftMapRegistryLoaded[craftName] = true; + craftMapRegistryLoadError[craftName] = false; +} + +/** @type { ( entry: object, craftName: string, entryIndex: number ) => boolean } */ +function ValidateCraftMapEntry( entry, craftName, entryIndex ) +{ + if( !entry || typeof entry != "object" || IsCraftMapArrayValue( entry ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' is not a valid object." ); + return false; + } + + if( typeof entry.makeID == "undefined" || isNaN( parseInt( entry.makeID, 10 ) ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' is missing valid makeID." ); + return false; + } + + if( typeof entry.page == "undefined" || isNaN( parseInt( entry.page, 10 ) ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' is missing valid page." ); + return false; + } + + if( typeof entry.timerID == "undefined" || isNaN( parseInt( entry.timerID, 10 ) ) ) + { + entry.timerID = entry.page; + } + + if( typeof entry.dictID != "undefined" && isNaN( parseInt( entry.dictID, 10 ) ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' has invalid dictID." ); + return false; + } + + if( typeof entry.harvest == "undefined" ) + { + entry.harvest = []; + } + + if( !IsCraftMapArrayValue( entry.harvest ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' has invalid harvest list." ); + return false; + } + + if( typeof entry.harvestNames != "undefined" && !IsCraftMapArrayValue( entry.harvestNames ) ) + { + Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' has invalid harvestNames list." ); + return false; + } + + entry.makeID = parseInt( entry.makeID, 10 ); + entry.page = parseInt( entry.page, 10 ); + entry.timerID = parseInt( entry.timerID, 10 ); + + if( typeof entry.dictID != "undefined" ) + { + entry.dictID = parseInt( entry.dictID, 10 ); + } + + return true; +} + +/** @type { ( craftName: string ) => string } */ +function NormalizeCraftMapName( craftName ) +{ + if( craftName == null || typeof( craftName ) == "undefined" ) + { + return ""; + } + + craftName = String( craftName ); + craftName = craftName.toLowerCase(); + craftName = craftName.replace( /[^a-z0-9_]/g, "" ); + + return craftName; +} + +/** @type { ( value: any ) => boolean } */ +function IsCraftMapArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} + +/** @type { ( text: string ) => string } */ +function TrimCraftMapString( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + { + return ""; + } + + return text.replace( /^\s+|\s+$/g, "" ); +} + +/** @type { ( text: string ) => string } */ +function SanitizeCraftMapJsonText( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + { + return ""; + } + + text = String( text ); + + if( text.length > 0 && text.charCodeAt( 0 ) == 65279 ) + { + text = text.substring( 1 ); + } + + text = text.split( "\r\n" ).join( "\n" ); + text = text.split( "\r" ).join( "\n" ); + text = text.split( String.fromCharCode( 160 ) ).join( " " ); + text = text.split( String.fromCharCode( 255 ) ).join( "" ); + text = text.split( "\t" ).join( " " ); + + text = TrimCraftMapString( text ); + + var lastBracket = text.lastIndexOf( "]" ); + if( lastBracket >= 0 ) + { + text = text.substring( 0, lastBracket + 1 ); + } + + return TrimCraftMapString( text ); +} \ No newline at end of file diff --git a/data/js/skill/craft/tinkering.js b/data/js/skill/craft/tinkering.js index c1ab673e5..c5eb1e409 100644 --- a/data/js/skill/craft/tinkering.js +++ b/data/js/skill/craft/tinkering.js @@ -26,7 +26,7 @@ const tinkeringSkillID = 37; // Index of "tinkering" i // | requiresGemTarget? - jewelry requiring manual gem selection | // o--------------------------------------------------------------------------o -const TinkeringMap = { +/*const TinkeringMap = { // Page 1 - Wooden Items 274: { dictID: 11801, page: 1, timerID: 1, harvest: [ 10014 ] }, // Axle 273: { dictID: 11802, page: 1, timerID: 1, harvest: [ 10014 ] }, // Clock Frame @@ -125,6 +125,7 @@ const TinkeringMap = { 262: { dictID: 11982, page: 9, timerID: 9, harvest: [ 10015, 12002 ] } // Poison Trap }; + // Fill in defaults (skill, etc) (function initTinkeringMap() { @@ -143,6 +144,50 @@ const TinkeringMap = { // entry.harvestNames = [ "Wood", "Ingots" ]; } })(); +*/ +const craftMapRegistryID = 4038; +var TinkeringMap = {}; + +/** @type { () => boolean } */ +function LoadTinkeringMap() +{ + TinkeringMap = {}; + + var tinkeringEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "tinkering" ); + + if( !tinkeringEntries ) + { + Console.Warning( "Tinkering: CraftMapRegistry returned null." ); + return false; + } + + if( !IsTinkeringArrayValue( tinkeringEntries )) + { + Console.Warning( "Tinkering: CraftMapRegistry did not return an array." ); + return false; + } + + for( var i = 0; i < tinkeringEntries.length; i++ ) + { + var entry = tinkeringEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) + continue; + + if( entry.skill === undefined ) + entry.skill = tinkeringSkillID; + + TinkeringMap[entry.makeID] = entry; + } + + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsTinkeringArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} // o--------------------------------------------------------------------------o // | PageX() - build a page of tinkering items | @@ -153,6 +198,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !TinkeringMap || Object.keys( TinkeringMap ).length == 0 ) + { + if( !LoadTinkeringMap() ) + { + socket.SysMessage( "Tinkering craft map failed to load." ); + return; + } + } + var pageItems; // Last Ten page (if you wire a tab to 999 later) From f52cf9fda76eab6910304d283cc93e502677f6a3 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 13 May 2026 15:43:34 -0500 Subject: [PATCH 41/43] cleanup all data driven --- data/js/jsdata/crafting/alchemy.json | 22 + data/js/jsdata/crafting/blacksmithing.json | 56 ++ data/js/jsdata/crafting/carpentry.json | 79 +++ data/js/jsdata/crafting/cartography.json | 6 + data/js/jsdata/crafting/cooking.json | 33 + data/js/jsdata/crafting/fletching.json | 18 + data/js/jsdata/crafting/glassblowing.json | 22 + data/js/jsdata/crafting/masonry.json | 61 ++ data/js/jsdata/crafting/resourcemap.json | 44 ++ data/js/jsdata/crafting/tailoring.json | 58 ++ data/js/jsdata/crafting/tinkering.json | 154 ++--- data/js/skill/craft/alchemy.js | 93 ++- data/js/skill/craft/blacksmithing.js | 711 +++++---------------- data/js/skill/craft/carpentry.js | 187 ++---- data/js/skill/craft/cartography.js | 74 +-- data/js/skill/craft/cooking.js | 105 ++- data/js/skill/craft/craftgump.js | 211 ++---- data/js/skill/craft/crafting_complete.js | 99 ++- data/js/skill/craft/craftmap_registry.js | 261 +++++++- data/js/skill/craft/fletching.js | 86 ++- data/js/skill/craft/glassblowing.js | 95 ++- data/js/skill/craft/masonry.js | 508 ++------------- data/js/skill/craft/tailoring.js | 127 ++-- data/js/skill/craft/tinkering.js | 135 ---- 24 files changed, 1358 insertions(+), 1887 deletions(-) create mode 100644 data/js/jsdata/crafting/alchemy.json create mode 100644 data/js/jsdata/crafting/blacksmithing.json create mode 100644 data/js/jsdata/crafting/carpentry.json create mode 100644 data/js/jsdata/crafting/cartography.json create mode 100644 data/js/jsdata/crafting/cooking.json create mode 100644 data/js/jsdata/crafting/fletching.json create mode 100644 data/js/jsdata/crafting/glassblowing.json create mode 100644 data/js/jsdata/crafting/masonry.json create mode 100644 data/js/jsdata/crafting/resourcemap.json create mode 100644 data/js/jsdata/crafting/tailoring.json diff --git a/data/js/jsdata/crafting/alchemy.json b/data/js/jsdata/crafting/alchemy.json new file mode 100644 index 000000000..800b02cc5 --- /dev/null +++ b/data/js/jsdata/crafting/alchemy.json @@ -0,0 +1,22 @@ +[ + { "makeID": 298, "label": "Lesser Heal", "dictID": 10910, "page": 1, "timerID": 1, "harvest": [10022], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 299, "label": "Heal", "dictID": 10911, "page": 1, "timerID": 1, "harvest": [10022], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 300, "label": "Greater Heal", "dictID": 10912, "page": 1, "timerID": 1, "harvest": [10022], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 305, "label": "Refresh", "dictID": 10908, "page": 1, "timerID": 1, "harvest": [10025], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 306, "label": "Total Refresh", "dictID": 10909, "page": 1, "timerID": 1, "harvest": [10025], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 292, "label": "Lesser Cure", "dictID": 10913, "page": 1, "timerID": 1, "harvest": [10020], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 293, "label": "Cure", "dictID": 10914, "page": 1, "timerID": 1, "harvest": [10020], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 294, "label": "Greater Cure", "dictID": 10915, "page": 1, "timerID": 1, "harvest": [10020], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 290, "label": "Agility", "dictID": 10916, "page": 2, "timerID": 2, "harvest": [10019], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 291, "label": "Greater Agility", "dictID": 10917, "page": 2, "timerID": 2, "harvest": [10019], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 295, "label": "Strength", "dictID": 10918, "page": 2, "timerID": 2, "harvest": [10021], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 296, "label": "Greater Strength", "dictID": 10919, "page": 2, "timerID": 2, "harvest": [10021], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 297, "label": "Night Sight", "dictID": 10920, "page": 2, "timerID": 2, "harvest": [10021], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 301, "label": "Lesser Poison", "dictID": 10921, "page": 3, "timerID": 3, "harvest": [10024], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 302, "label": "Poison", "dictID": 10922, "page": 3, "timerID": 3, "harvest": [10024], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 303, "label": "Greater Poison", "dictID": 10923, "page": 3, "timerID": 3, "harvest": [10024], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 304, "label": "Deadly Poison", "dictID": 10924, "page": 3, "timerID": 3, "harvest": [10024], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 307, "label": "Explosion", "dictID": 10925, "page": 4, "timerID": 4, "harvest": [10026], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 308, "label": "Greater Explosion", "dictID": 10926, "page": 4, "timerID": 4, "harvest": [10026], "craftComplete": { "type": "autoIdentifyPotion" } }, + { "makeID": 309, "label": "Conflagration", "dictID": 10927, "page": 4, "timerID": 4, "harvest": [10023], "craftComplete": { "type": "autoIdentifyPotion" } } +] diff --git a/data/js/jsdata/crafting/blacksmithing.json b/data/js/jsdata/crafting/blacksmithing.json new file mode 100644 index 000000000..859f5dadd --- /dev/null +++ b/data/js/jsdata/crafting/blacksmithing.json @@ -0,0 +1,56 @@ +[ + { "buttonID": 100, "label": "Ringmail Gloves", "dictID": 10217, "page": 1, "timerID": 1, "oreMake": [7, 506, 606, 706, 806, 906, 1206, 1006, 1106], "harvest": [10015] }, + { "buttonID": 101, "label": "Ringmail Leggings", "dictID": 10218, "page": 1, "timerID": 1, "oreMake": [9, 508, 608, 708, 808, 908, 1208, 1008, 1108], "harvest": [10015] }, + { "buttonID": 102, "label": "Ringmail Sleeves", "dictID": 10219, "page": 1, "timerID": 1, "oreMake": [8, 507, 607, 707, 807, 907, 1207, 1007, 1107], "harvest": [10015] }, + { "buttonID": 103, "label": "Ringmail Tunic", "dictID": 10220, "page": 1, "timerID": 1, "oreMake": [10, 509, 609, 709, 809, 909, 1209, 1009, 1109], "harvest": [10015] }, + { "buttonID": 104, "label": "Chainmail Coif", "dictID": 10221, "page": 1, "timerID": 1, "oreMake": [11, 510, 610, 710, 810, 910, 1210, 1010, 1110], "harvest": [10015] }, + { "buttonID": 105, "label": "Chainmail Leggings", "dictID": 10222, "page": 1, "timerID": 1, "oreMake": [12, 511, 611, 711, 811, 911, 1211, 1011, 1111], "harvest": [10015] }, + { "buttonID": 106, "label": "Chainmail Tunic", "dictID": 10223, "page": 1, "timerID": 1, "oreMake": [13, 512, 612, 7012, 812, 912, 1212, 1012, 1112], "harvest": [10015] }, + { "buttonID": 107, "label": "Platemail Arms", "dictID": 10224, "page": 1, "timerID": 1, "oreMake": [16, 515, 615, 715, 815, 915, 1215, 1015, 1115], "harvest": [10015] }, + { "buttonID": 108, "label": "Platemail Gloves", "dictID": 10225, "page": 1, "timerID": 1, "oreMake": [15, 514, 614, 714, 814, 914, 1214, 1014, 1114], "harvest": [10015] }, + { "buttonID": 109, "label": "Platemail Gorget", "dictID": 10226, "page": 1, "timerID": 1, "oreMake": [14, 513, 613, 713, 813, 913, 1213, 1013, 1113], "harvest": [10015] }, + { "buttonID": 110, "label": "Platemail Legs", "dictID": 10227, "page": 1, "timerID": 1, "oreMake": [17, 516, 616, 716, 816, 916, 1216, 1016, 1116], "harvest": [10015] }, + { "buttonID": 111, "label": "Platemail Tunic", "dictID": 10228, "page": 1, "timerID": 1, "oreMake": [18, 517, 617, 717, 817, 917, 1217, 1017, 1117], "harvest": [10015] }, + { "buttonID": 112, "label": "Female Plate", "dictID": 10229, "page": 1, "timerID": 1, "oreMake": [19, 518, 618, 718, 818, 918, 1218, 1018, 1118], "harvest": [10015] }, + { "buttonID": 113, "label": "Dragon Sleeves", "customName": "Dragon Sleeves", "page": 1, "timerID": 1, "oreMake": [367, 0, 0, 0, 0, 0, 0, 0, 0], "harvest": [10015], "useScales": true }, + { "buttonID": 114, "label": "Dragon Breast Plate", "customName": "Dragon Breast Plate", "page": 1, "timerID": 1, "oreMake": [368, 0, 0, 0, 0, 0, 0, 0, 0], "harvest": [10015], "useScales": true }, + { "buttonID": 115, "label": "Dragon Gloves", "customName": "Dragon Gloves", "page": 1, "timerID": 1, "oreMake": [369, 0, 0, 0, 0, 0, 0, 0, 0], "harvest": [10015], "useScales": true }, + { "buttonID": 116, "label": "Dragon Helmet", "customName": "Dragon Helmet", "page": 1, "timerID": 1, "oreMake": [370, 0, 0, 0, 0, 0, 0, 0, 0], "harvest": [10015], "useScales": true }, + { "buttonID": 117, "label": "Dragon Leggings", "customName": "Dragon leggings", "page": 1, "timerID": 1, "oreMake": [371, 0, 0, 0, 0, 0, 0, 0, 0], "harvest": [10015], "useScales": true }, + { "buttonID": 200, "label": "Bascinet", "dictID": 10230, "page": 2, "timerID": 2, "oreMake": [46, 520, 620, 720, 820, 920, 1220, 1020, 1120], "harvest": [10015] }, + { "buttonID": 201, "label": "Close Helmet", "dictID": 10231, "page": 2, "timerID": 2, "oreMake": [48, 522, 622, 722, 822, 922, 1222, 1022, 1122], "harvest": [10015] }, + { "buttonID": 202, "label": "Helmet", "dictID": 10232, "page": 2, "timerID": 2, "oreMake": [45, 519, 619, 719, 819, 919, 1219, 1019, 1119], "harvest": [10015] }, + { "buttonID": 203, "label": "Norse Helm", "dictID": 10233, "page": 2, "timerID": 2, "oreMake": [47, 521, 621, 721, 821, 921, 1221, 1021, 1121], "harvest": [10015] }, + { "buttonID": 204, "label": "Plate Helm", "dictID": 10234, "page": 2, "timerID": 2, "oreMake": [49, 523, 623, 723, 823, 923, 1223, 1023, 1123], "harvest": [10015] }, + { "buttonID": 300, "label": "Buckler", "dictID": 10235, "page": 3, "timerID": 3, "oreMake": [1, 500, 600, 700, 800, 900, 1200, 1000, 1100], "harvest": [10015] }, + { "buttonID": 301, "label": "Bronze Shield", "dictID": 10236, "page": 3, "timerID": 3, "oreMake": [2, 501, 601, 701, 801, 901, 1201, 1001, 1101], "harvest": [10015] }, + { "buttonID": 302, "label": "Heater Shield", "dictID": 10237, "page": 3, "timerID": 3, "oreMake": [6, 505, 605, 705, 805, 905, 1205, 1005, 1105], "harvest": [10015] }, + { "buttonID": 303, "label": "Metal Shield", "dictID": 10238, "page": 3, "timerID": 3, "oreMake": [3, 502, 602, 702, 802, 902, 1202, 1002, 1102], "harvest": [10015] }, + { "buttonID": 304, "label": "Metal Kite Shield", "dictID": 10239, "page": 3, "timerID": 3, "oreMake": [5, 504, 604, 704, 804, 904, 1204, 1004, 1104], "harvest": [10015] }, + { "buttonID": 305, "label": "Wooden Kite Shield", "dictID": 10293, "page": 3, "timerID": 3, "oreMake": [4, 503, 603, 703, 803, 903, 1203, 1003, 1103], "harvest": [10015] }, + { "buttonID": 400, "label": "Broadsword", "dictID": 10240, "page": 4, "timerID": 4, "oreMake": [25, 25, 25, 25, 25, 25, 25, 25, 25], "harvest": [10015] }, + { "buttonID": 401, "label": "Cutlass", "dictID": 10241, "page": 4, "timerID": 4, "oreMake": [21, 21, 21, 21, 21, 21, 21, 21, 21], "harvest": [10015] }, + { "buttonID": 402, "label": "Dagger", "dictID": 10242, "page": 4, "timerID": 4, "oreMake": [20, 20, 20, 20, 20, 20, 20, 20, 20], "harvest": [10015] }, + { "buttonID": 403, "label": "Katana", "dictID": 10243, "page": 4, "timerID": 4, "oreMake": [22, 22, 22, 22, 22, 22, 22, 22, 22], "harvest": [10015] }, + { "buttonID": 404, "label": "Kryss", "dictID": 10244, "page": 4, "timerID": 4, "oreMake": [23, 23, 23, 23, 23, 23, 23, 23, 23], "harvest": [10015] }, + { "buttonID": 405, "label": "Longsword", "dictID": 10245, "page": 4, "timerID": 4, "oreMake": [26, 26, 26, 26, 26, 26, 26, 26, 26], "harvest": [10015] }, + { "buttonID": 406, "label": "Scimitar", "dictID": 10246, "page": 4, "timerID": 4, "oreMake": [24, 24, 24, 24, 24, 24, 24, 24, 24], "harvest": [10015] }, + { "buttonID": 407, "label": "Viking Sword", "dictID": 10247, "page": 4, "timerID": 4, "oreMake": [27, 27, 27, 27, 27, 27, 27, 27, 27], "harvest": [10015] }, + { "buttonID": 500, "label": "Axe", "dictID": 10248, "page": 5, "timerID": 5, "oreMake": [29, 29, 29, 29, 29, 29, 29, 29, 29], "harvest": [10015] }, + { "buttonID": 501, "label": "Battle Axe", "dictID": 10249, "page": 5, "timerID": 5, "oreMake": [28, 28, 28, 28, 28, 28, 28, 28, 28], "harvest": [10015] }, + { "buttonID": 502, "label": "Double Axe", "dictID": 10250, "page": 5, "timerID": 5, "oreMake": [32, 32, 32, 32, 32, 32, 32, 32, 32], "harvest": [10015] }, + { "buttonID": 503, "label": "Executioner's Axe", "dictID": 10251, "page": 5, "timerID": 5, "oreMake": [30, 30, 30, 30, 30, 30, 30, 30, 30], "harvest": [10015] }, + { "buttonID": 504, "label": "Large Battle Axe", "dictID": 10252, "page": 5, "timerID": 5, "oreMake": [33, 33, 33, 33, 33, 33, 33, 33, 33], "harvest": [10015] }, + { "buttonID": 505, "label": "Two Handed Axe", "dictID": 10253, "page": 5, "timerID": 5, "oreMake": [31, 31, 31, 31, 31, 31, 31, 31, 31], "harvest": [10015] }, + { "buttonID": 506, "label": "War Axe", "dictID": 10254, "page": 5, "timerID": 5, "oreMake": [34, 34, 34, 34, 34, 34, 34, 34, 34], "harvest": [10015] }, + { "buttonID": 600, "label": "Bardiche", "dictID": 10255, "page": 6, "timerID": 6, "oreMake": [38, 38, 38, 38, 38, 38, 38, 38, 38], "harvest": [10015] }, + { "buttonID": 601, "label": "Halberd", "dictID": 10256, "page": 6, "timerID": 6, "oreMake": [39, 39, 39, 39, 39, 39, 39, 39, 39], "harvest": [10015] }, + { "buttonID": 602, "label": "Short Spear", "dictID": 10257, "page": 6, "timerID": 6, "oreMake": [35, 35, 35, 35, 35, 35, 35, 35, 35], "harvest": [10015] }, + { "buttonID": 603, "label": "Spear", "dictID": 10258, "page": 6, "timerID": 6, "oreMake": [36, 36, 36, 36, 36, 36, 36, 36, 36], "harvest": [10015] }, + { "buttonID": 604, "label": "War Fork", "dictID": 10259, "page": 6, "timerID": 6, "oreMake": [37, 37, 37, 37, 37, 37, 37, 37, 37], "harvest": [10015] }, + { "buttonID": 700, "label": "Hammer Pick", "dictID": 10260, "page": 7, "timerID": 7, "oreMake": [44, 44, 44, 44, 44, 44, 44, 44, 44], "harvest": [10015] }, + { "buttonID": 701, "label": "Mace", "dictID": 10261, "page": 7, "timerID": 7, "oreMake": [40, 40, 40, 40, 40, 40, 40, 40, 40], "harvest": [10015] }, + { "buttonID": 702, "label": "Maul", "dictID": 10262, "page": 7, "timerID": 7, "oreMake": [41, 41, 41, 41, 41, 41, 41, 41, 41], "harvest": [10015] }, + { "buttonID": 703, "label": "War Hammer", "dictID": 10263, "page": 7, "timerID": 7, "oreMake": [42, 42, 42, 42, 42, 42, 42, 42, 42], "harvest": [10015] }, + { "buttonID": 704, "label": "War Mace", "dictID": 10264, "page": 7, "timerID": 7, "oreMake": [43, 43, 43, 43, 43, 43, 43, 43, 43], "harvest": [10015] } +] diff --git a/data/js/jsdata/crafting/carpentry.json b/data/js/jsdata/crafting/carpentry.json new file mode 100644 index 000000000..10a2dc0a4 --- /dev/null +++ b/data/js/jsdata/crafting/carpentry.json @@ -0,0 +1,79 @@ +[ + { "buttonID": 100, "label": "Barrel Staves", "dictID": 10611, "page": 1, "timerID": 1, "makeID": 73, "harvest": [10014] }, + { "buttonID": 101, "label": "Barrel Lid", "dictID": 10612, "page": 1, "timerID": 1, "makeID": 74, "harvest": [10014] }, + { "buttonID": 102, "label": "Short Music Stand", "dictID": 10613, "page": 1, "timerID": 1, "makeID": 89, "harvest": [10014] }, + { "buttonID": 103, "label": "Tall Music Stand", "dictID": 10614, "page": 1, "timerID": 1, "makeID": 90, "harvest": [10014] }, + { "buttonID": 104, "label": "Easel South", "dictID": 10615, "page": 1, "timerID": 1, "makeID": 91, "harvest": [10014] }, + { "buttonID": 105, "label": "Easel East", "dictID": 10616, "page": 1, "timerID": 1, "makeID": 92, "harvest": [10014] }, + { "buttonID": 106, "label": "Bamboo Flute", "dictID": 10617, "page": 1, "timerID": 1, "makeID": 76, "harvest": [10014] }, + { "buttonID": 107, "label": "Log", "dictID": 10618, "page": 1, "timerID": 1, "makeID": 77, "harvest": [10014] }, + { "buttonID": 108, "label": "Board", "dictID": 10619, "page": 1, "timerID": 1, "makeID": 78, "harvest": [10014] }, + { "buttonID": 109, "label": "Blank Scroll", "dictID": 10620, "page": 1, "timerID": 1, "makeID": 79, "harvest": [10014, 10016] }, + { "buttonID": 110, "label": "Fishing Pole", "dictID": 10688, "page": 1, "timerID": 1, "makeID": 72, "harvest": [10014] }, + { "buttonID": 200, "label": "Stool", "dictID": 10621, "page": 2, "timerID": 2, "makeID": 50, "harvest": [10014] }, + { "buttonID": 201, "label": "Foot Stool", "dictID": 10622, "page": 2, "timerID": 2, "makeID": 51, "harvest": [10014] }, + { "buttonID": 202, "label": "Straw Chair", "dictID": 10623, "page": 2, "timerID": 2, "makeID": 52, "harvest": [10014] }, + { "buttonID": 203, "label": "Wooden Chair", "dictID": 10624, "page": 2, "timerID": 2, "makeID": 53, "harvest": [10014] }, + { "buttonID": 204, "label": "Vesper-Style Chair", "dictID": 10625, "page": 2, "timerID": 2, "makeID": 57, "harvest": [10014] }, + { "buttonID": 205, "label": "Trinsic-Style Chair", "dictID": 10626, "page": 2, "timerID": 2, "makeID": 58, "harvest": [10014] }, + { "buttonID": 206, "label": "Wooden Bench", "dictID": 10627, "page": 2, "timerID": 2, "makeID": 54, "harvest": [10014] }, + { "buttonID": 207, "label": "Wooden Throne", "dictID": 10628, "page": 2, "timerID": 2, "makeID": 55, "harvest": [10014] }, + { "buttonID": 208, "label": "Magincia-Style Throne", "dictID": 10629, "page": 2, "timerID": 2, "makeID": 56, "harvest": [10014] }, + { "buttonID": 209, "label": "Small Table", "dictID": 10630, "page": 2, "timerID": 2, "makeID": 59, "harvest": [10014] }, + { "buttonID": 210, "label": "Writing Table", "dictID": 10631, "page": 2, "timerID": 2, "makeID": 60, "harvest": [10014] }, + { "buttonID": 211, "label": "Large Table", "dictID": 10632, "page": 2, "timerID": 2, "makeID": 61, "harvest": [10014] }, + { "buttonID": 212, "label": "Yew-Wood Table", "dictID": 10633, "page": 2, "timerID": 2, "makeID": 62, "harvest": [10014] }, + { "buttonID": 300, "label": "Wooden Box", "dictID": 10634, "page": 3, "timerID": 3, "makeID": 63, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 301, "label": "Small Crate", "dictID": 10635, "page": 3, "timerID": 3, "makeID": 64, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 302, "label": "Medium Crate", "dictID": 10636, "page": 3, "timerID": 3, "makeID": 65, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 303, "label": "Large Crate", "dictID": 10637, "page": 3, "timerID": 3, "makeID": 67, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 304, "label": "Wooden Chest", "dictID": 10638, "page": 3, "timerID": 3, "makeID": 68, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 305, "label": "Wooden Shelf", "dictID": 10639, "page": 3, "timerID": 3, "makeID": 69, "harvest": [10014] }, + { "buttonID": 306, "label": "Armoire", "dictID": 10640, "page": 3, "timerID": 3, "makeID": 70, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 307, "label": "Armoire", "dictID": 10641, "page": 3, "timerID": 3, "makeID": 71, "harvest": [10014], "craftComplete": { "type": "lockableContainer" } }, + { "buttonID": 308, "label": "Open Keg", "dictID": 10642, "page": 3, "timerID": 3, "makeID": 66, "harvest": [10611, 10612, 11860] }, + { "buttonID": 400, "label": "Shepherd's Crook", "dictID": 10643, "page": 4, "timerID": 4, "makeID": 80, "harvest": [10014] }, + { "buttonID": 401, "label": "Quarter Staff", "dictID": 10644, "page": 4, "timerID": 4, "makeID": 81, "harvest": [10014] }, + { "buttonID": 402, "label": "Gnarled Staff", "dictID": 10645, "page": 4, "timerID": 4, "makeID": 82, "harvest": [10014] }, + { "buttonID": 403, "label": "Wooden Shield", "dictID": 10646, "page": 4, "timerID": 4, "makeID": 123, "harvest": [10014] }, + { "buttonID": 404, "label": "Club", "dictID": 10647, "page": 4, "timerID": 4, "makeID": 124, "harvest": [10014] }, + { "buttonID": 500, "label": "Wooden Shield", "dictID": 10648, "page": 5, "timerID": 5, "makeID": 75, "harvest": [10014] }, + { "buttonID": 600, "label": "Lap Harp", "dictID": 10649, "page": 6, "timerID": 6, "makeID": 83, "harvest": [10014, 10016] }, + { "buttonID": 601, "label": "Standing Harp", "dictID": 10650, "page": 6, "timerID": 6, "makeID": 84, "harvest": [10014, 10016] }, + { "buttonID": 602, "label": "Drum", "dictID": 10651, "page": 6, "timerID": 6, "makeID": 85, "harvest": [10014, 10016] }, + { "buttonID": 603, "label": "Lute", "dictID": 10652, "page": 6, "timerID": 6, "makeID": 86, "harvest": [10014, 10016] }, + { "buttonID": 604, "label": "Tambourine", "dictID": 10653, "page": 6, "timerID": 6, "makeID": 87, "harvest": [10014, 10016] }, + { "buttonID": 605, "label": "Tambourine", "dictID": 10654, "page": 6, "timerID": 6, "makeID": 88, "harvest": [10014, 10016] }, + { "buttonID": 700, "label": "Small Bed South", "dictID": 10655, "page": 7, "timerID": 7, "makeID": 93, "harvest": [10014, 10016] }, + { "buttonID": 701, "label": "Small Bed East", "dictID": 10656, "page": 7, "timerID": 7, "makeID": 93, "harvest": [10014, 10016] }, + { "buttonID": 702, "label": "Large Bed South", "dictID": 10657, "page": 7, "timerID": 7, "makeID": 94, "harvest": [10014, 10016] }, + { "buttonID": 703, "label": "Large Bed East", "dictID": 10658, "page": 7, "timerID": 7, "makeID": 93, "harvest": [10014, 10016] }, + { "buttonID": 704, "label": "Training Dummy South", "dictID": 10659, "page": 7, "timerID": 7, "makeID": 96, "harvest": [10014] }, + { "buttonID": 705, "label": "Training Dummy East", "dictID": 10660, "page": 7, "timerID": 7, "makeID": 95, "harvest": [10014] }, + { "buttonID": 706, "label": "Pickpocket Dip South", "dictID": 10661, "page": 7, "timerID": 7, "makeID": 97, "harvest": [10014] }, + { "buttonID": 707, "label": "Pickpocket Dip East", "dictID": 10662, "page": 7, "timerID": 7, "makeID": 98, "harvest": [10014] }, + { "buttonID": 708, "label": "Bulletin Board", "dictID": 10663, "page": 7, "timerID": 7, "makeID": 99, "harvest": [10014] }, + { "buttonID": 709, "label": "Pentagram", "dictID": 10664, "page": 7, "timerID": 7, "makeID": 100, "harvest": [10014, 10015] }, + { "buttonID": 710, "label": "Abbatoir", "dictID": 10665, "page": 7, "timerID": 7, "makeID": 101, "harvest": [10014, 10015] }, + { "buttonID": 800, "label": "Dressform Front", "dictID": 10666, "page": 8, "timerID": 8, "makeID": 115, "harvest": [10014, 10016] }, + { "buttonID": 801, "label": "Dressform Side", "dictID": 10667, "page": 8, "timerID": 8, "makeID": 116, "harvest": [10014, 10016] }, + { "buttonID": 802, "label": "Spinning Wheel East", "dictID": 10668, "page": 8, "timerID": 8, "makeID": 107, "harvest": [10014, 10016] }, + { "buttonID": 803, "label": "Spinning Wheel South", "dictID": 10669, "page": 8, "timerID": 8, "makeID": 108, "harvest": [10014, 10016] }, + { "buttonID": 804, "label": "Loom East", "dictID": 10670, "page": 8, "timerID": 8, "makeID": 109, "harvest": [10014, 10016] }, + { "buttonID": 805, "label": "Loom South", "dictID": 10671, "page": 8, "timerID": 8, "makeID": 110, "harvest": [10014, 10016] }, + { "buttonID": 806, "label": "Stone Oven East", "dictID": 10672, "page": 8, "timerID": 8, "makeID": 117, "harvest": [10014, 10015] }, + { "buttonID": 807, "label": "Stone Oven South", "dictID": 10673, "page": 8, "timerID": 8, "makeID": 118, "harvest": [10014, 10015] }, + { "buttonID": 808, "label": "Flour Mill East", "dictID": 10674, "page": 8, "timerID": 8, "makeID": 119, "harvest": [10014, 10015] }, + { "buttonID": 809, "label": "Flour Mill South", "dictID": 10675, "page": 8, "timerID": 8, "makeID": 120, "harvest": [10014, 10015] }, + { "buttonID": 810, "label": "Water Trough East", "dictID": 10676, "page": 8, "timerID": 8, "makeID": 121, "harvest": [10014] }, + { "buttonID": 811, "label": "Water Trough South", "dictID": 10677, "page": 8, "timerID": 8, "makeID": 122, "harvest": [10014] }, + { "buttonID": 900, "label": "Small Forge", "dictID": 10678, "page": 9, "timerID": 9, "makeID": 102, "harvest": [10014, 10015] }, + { "buttonID": 901, "label": "Large Forge East", "dictID": 10679, "page": 9, "timerID": 9, "makeID": 103, "harvest": [10014, 10015] }, + { "buttonID": 902, "label": "Large Forge South", "dictID": 10680, "page": 9, "timerID": 9, "makeID": 104, "harvest": [10014, 10015] }, + { "buttonID": 903, "label": "Anvil East", "dictID": 10681, "page": 9, "timerID": 9, "makeID": 105, "harvest": [10014, 10015] }, + { "buttonID": 904, "label": "Anvil South", "dictID": 10682, "page": 9, "timerID": 9, "makeID": 106, "harvest": [10014, 10015] }, + { "buttonID": 1000, "label": "Training Dummy East", "dictID": 10683, "page": 10, "timerID": 10, "makeID": 111, "harvest": [10014, 10016] }, + { "buttonID": 1001, "label": "Training Dummy South", "dictID": 10684, "page": 10, "timerID": 10, "makeID": 112, "harvest": [10014, 10016] }, + { "buttonID": 1002, "label": "Pickpocket Dip East", "dictID": 10685, "page": 10, "timerID": 10, "makeID": 113, "harvest": [10014, 10016] }, + { "buttonID": 1003, "label": "Pickpocket Dip South", "dictID": 10686, "page": 10, "timerID": 10, "makeID": 114, "harvest": [10014, 10016] } +] diff --git a/data/js/jsdata/crafting/cartography.json b/data/js/jsdata/crafting/cartography.json new file mode 100644 index 000000000..942206628 --- /dev/null +++ b/data/js/jsdata/crafting/cartography.json @@ -0,0 +1,6 @@ +[ + { "makeID": 2000, "label": "Local Map", "dictID": 13100, "page": 1, "timerID": 1, "harvest": [13004] }, + { "makeID": 2001, "label": "City Map", "dictID": 13101, "page": 1, "timerID": 1, "harvest": [13004] }, + { "makeID": 2002, "label": "Sea Chart", "dictID": 13102, "page": 1, "timerID": 1, "harvest": [13004] }, + { "makeID": 2003, "label": "World Map", "dictID": 13103, "page": 1, "timerID": 1, "harvest": [13004] } +] diff --git a/data/js/jsdata/crafting/cooking.json b/data/js/jsdata/crafting/cooking.json new file mode 100644 index 000000000..7ea76fd90 --- /dev/null +++ b/data/js/jsdata/crafting/cooking.json @@ -0,0 +1,33 @@ +[ + { "makeID": 1500, "label": "Sack of Flour", "dictID": 11606, "page": 1, "timerID": 1, "harvest": [11636] }, + { "makeID": 1501, "label": "Dough", "dictID": 11607, "page": 1, "timerID": 1, "harvest": [11637, 11638] }, + { "makeID": 1502, "label": "Sweet Dough", "dictID": 11608, "page": 1, "timerID": 1, "harvest": [11607, 11639] }, + { "makeID": 1503, "label": "Cake Mix", "dictID": 11609, "page": 1, "timerID": 1, "harvest": [11637, 11608] }, + { "makeID": 1504, "label": "Cookie Mix", "dictID": 11610, "page": 1, "timerID": 1, "harvest": [11639, 11608] }, + { "makeID": 1550, "label": "Unbaked Quiche", "dictID": 11611, "page": 2, "timerID": 2, "harvest": [11607, 11640] }, + { "makeID": 1551, "label": "Unbaked Meat Pie", "dictID": 11612, "page": 2, "timerID": 2, "harvest": [11607, 11641] }, + { "makeID": 1552, "label": "Uncooked Sausage Pizza", "dictID": 11613, "page": 2, "timerID": 2, "harvest": [11607, 11642] }, + { "makeID": 1553, "label": "Uncooked Cheese Pizza", "dictID": 11614, "page": 2, "timerID": 2, "harvest": [11607, 11643] }, + { "makeID": 1554, "label": "Unbaked Fruit Pie", "dictID": 11615, "page": 2, "timerID": 2, "harvest": [11607, 11644] }, + { "makeID": 1555, "label": "Unbaked Peach Cobbler", "dictID": 11616, "page": 2, "timerID": 2, "harvest": [11607, 11645] }, + { "makeID": 1556, "label": "Unbaked Apple Pie", "dictID": 11617, "page": 2, "timerID": 2, "harvest": [11607, 11646] }, + { "makeID": 1557, "label": "Unbaked Pumpkin Pie", "dictID": 11618, "page": 2, "timerID": 2, "harvest": [11607, 11647] }, + { "makeID": 1600, "label": "Bread Loaf", "dictID": 11619, "page": 3, "timerID": 3, "harvest": [11607] }, + { "makeID": 1601, "label": "Pan of Cookies", "dictID": 11620, "page": 3, "timerID": 3, "harvest": [11610] }, + { "makeID": 1602, "label": "Cake", "dictID": 11621, "page": 3, "timerID": 3, "harvest": [11609] }, + { "makeID": 1603, "label": "Muffins", "dictID": 11657, "page": 3, "timerID": 3, "harvest": [11608] }, + { "makeID": 1604, "label": "Baked Quiche", "dictID": 11622, "page": 3, "timerID": 3, "harvest": [11611] }, + { "makeID": 1605, "label": "Baked Meat Pie", "dictID": 11623, "page": 3, "timerID": 3, "harvest": [11612] }, + { "makeID": 1606, "label": "Sausage Pizza", "dictID": 11624, "page": 3, "timerID": 3, "harvest": [11613] }, + { "makeID": 1607, "label": "Cheese Pizza", "dictID": 11625, "page": 3, "timerID": 3, "harvest": [11614] }, + { "makeID": 1608, "label": "Baked Fruit Pie", "dictID": 11626, "page": 3, "timerID": 3, "harvest": [11615] }, + { "makeID": 1609, "label": "Baked Peach Cobbler", "dictID": 11627, "page": 3, "timerID": 3, "harvest": [11616] }, + { "makeID": 1610, "label": "Baked Apple Pie", "dictID": 11628, "page": 3, "timerID": 3, "harvest": [11617] }, + { "makeID": 1611, "label": "Baked Pumpkin Pie", "dictID": 11629, "page": 3, "timerID": 3, "harvest": [11618] }, + { "makeID": 1650, "label": "Cooked Bird", "dictID": 11630, "page": 4, "timerID": 4, "harvest": [11648] }, + { "makeID": 1651, "label": "Chicken Leg", "dictID": 11631, "page": 4, "timerID": 4, "harvest": [11649] }, + { "makeID": 1652, "label": "Fish Steak", "dictID": 11632, "page": 4, "timerID": 4, "harvest": [11650] }, + { "makeID": 1653, "label": "Fried Eggs", "dictID": 11633, "page": 4, "timerID": 4, "harvest": [11651] }, + { "makeID": 1654, "label": "Leg of Lamb", "dictID": 11634, "page": 4, "timerID": 4, "harvest": [11652] }, + { "makeID": 1655, "label": "Cut of Ribs", "dictID": 11635, "page": 4, "timerID": 4, "harvest": [11653] } +] diff --git a/data/js/jsdata/crafting/fletching.json b/data/js/jsdata/crafting/fletching.json new file mode 100644 index 000000000..4dbab290b --- /dev/null +++ b/data/js/jsdata/crafting/fletching.json @@ -0,0 +1,18 @@ +[ + { "makeID": 190, "label": "Kindling", "dictID": 11205, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 194, "label": "Shaft", "dictID": 11206, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 195, "label": "Five Shafts", "dictID": 11207, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 196, "label": "Twenty Shafts", "dictID": 11208, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 197, "label": "Fifty Shafts", "dictID": 11209, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 198, "label": "Arrow", "dictID": 11210, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 199, "label": "Five Arrows", "dictID": 11211, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 200, "label": "Twenty Arrows", "dictID": 11212, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 201, "label": "Fifty Arrows", "dictID": 11213, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 202, "label": "Bolt", "dictID": 11214, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 203, "label": "Five Bolts", "dictID": 11215, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 204, "label": "Twenty Bolts", "dictID": 11216, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 205, "label": "Fifty Bolts", "dictID": 11217, "page": 2, "timerID": 2, "harvest": [10029, 10028] }, + { "makeID": 191, "label": "Bow", "dictID": 11218, "page": 3, "timerID": 3, "harvest": [10014] }, + { "makeID": 192, "label": "Crossbow", "dictID": 11219, "page": 3, "timerID": 3, "harvest": [10014] }, + { "makeID": 193, "label": "Heavy Crossbow", "dictID": 11220, "page": 3, "timerID": 3, "harvest": [10014] } +] diff --git a/data/js/jsdata/crafting/glassblowing.json b/data/js/jsdata/crafting/glassblowing.json new file mode 100644 index 000000000..8cbc00648 --- /dev/null +++ b/data/js/jsdata/crafting/glassblowing.json @@ -0,0 +1,22 @@ +[ + { "makeID": 3000, "label": "empty bottle", "dictID": 13600, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3001, "label": "flask (small)", "dictID": 13601, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3002, "label": "flask (medium)", "dictID": 13602, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3003, "label": "flask (curved)", "dictID": 13603, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3004, "label": "flask (large #1)", "dictID": 13604, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3005, "label": "flask (large #2)", "dictID": 13605, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3006, "label": "flask (bubbling blue)", "dictID": 13606, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3007, "label": "flask (bubbling purple)", "dictID": 13607, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3008, "label": "flask (bubbling red)", "dictID": 13608, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3009, "label": "empty vials", "dictID": 13609, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3010, "label": "full vials", "dictID": 13610, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3011, "label": "spinning hourglass", "dictID": 13611, "page": 1, "timerID": 1, "harvest": [13504] }, + { "makeID": 3012, "label": "hollow prism", "customName": "hollow prism", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "ml" }, + { "makeID": 3013, "label": "gargoyle floor mirror", "customName": "gargoyle floor mirror", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3014, "label": "gargoyle wall mirror", "customName": "gargoyle wall mirror", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3015, "label": "empty venom vial", "customName": "empty venom vial", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3016, "label": "empty oil flask", "customName": "empty oil flask", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3017, "label": "workable glass", "customName": "workable glass", "page": 1, "timerID": 1, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3018, "label": "glass sword", "customName": "glass sword", "page": 2, "timerID": 2, "harvest": [13504], "minEra": "sa" }, + { "makeID": 3019, "label": "glass staff", "customName": "glass staff", "page": 2, "timerID": 2, "harvest": [13504], "minEra": "sa" } +] diff --git a/data/js/jsdata/crafting/masonry.json b/data/js/jsdata/crafting/masonry.json new file mode 100644 index 000000000..f38ef8237 --- /dev/null +++ b/data/js/jsdata/crafting/masonry.json @@ -0,0 +1,61 @@ +[ + { "buttonID": 100, "label": "Small Vase", "dictID": 14050, "page": 1, "timerID": 1, "graniteMake": [3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300], "harvest": [14011] }, + { "buttonID": 101, "label": "Large Vase", "dictID": 14051, "page": 1, "timerID": 1, "graniteMake": [3501, 3601, 3701, 3801, 3901, 4001, 4101, 4201, 4301], "harvest": [14011] }, + { "buttonID": 102, "label": "Small Urn", "dictID": 14052, "page": 1, "timerID": 1, "graniteMake": [3502, 3602, 3702, 3802, 3902, 4002, 4102, 4202, 4302], "harvest": [14011], "minEra": "se" }, + { "buttonID": 103, "label": "Tower Sculpture", "dictID": 14053, "page": 1, "timerID": 1, "graniteMake": [3503, 3603, 3703, 3803, 3903, 4003, 4103, 4203, 4303], "harvest": [14011], "minEra": "se" }, + { "buttonID": 104, "label": "Gargoyle Painting", "dictID": 14054, "page": 1, "timerID": 1, "graniteMake": [3504, 3604, 3704, 3804, 3904, 4004, 4104, 4204, 4304], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 105, "label": "Gargoyle Sculpture", "dictID": 14055, "page": 1, "timerID": 1, "graniteMake": [3505, 3605, 3705, 3805, 3905, 4005, 4105, 4205, 4305], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 106, "label": "Gargoyle Vase", "dictID": 14056, "page": 1, "timerID": 1, "graniteMake": [3506, 3606, 3706, 3806, 3906, 4006, 4106, 4206, 4306], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 107, "label": "Tall 18th Anniversary Vase", "dictID": 14057, "page": 1, "timerID": 1, "graniteMake": [3507, 3607, 3707, 3807, 3907, 4007, 4107, 4207, 4307], "harvest": [14011], "recipeID": 3500, "minEra": "tol" }, + { "buttonID": 108, "label": "Short 18th Anniversary Vase", "dictID": 14058, "page": 1, "timerID": 1, "graniteMake": [3508, 3608, 3708, 3808, 3908, 4008, 4108, 4208, 4308], "harvest": [14011], "recipeID": 3501, "minEra": "tol" }, + { "buttonID": 200, "label": "Stone Chair", "dictID": 14059, "page": 2, "timerID": 2, "graniteMake": [3509, 3609, 3709, 3809, 3909, 4009, 4109, 4209, 4309], "harvest": [14011] }, + { "buttonID": 201, "label": "Medium Stone Table", "dictID": 14060, "page": 2, "timerID": 2, "graniteMake": [3510, 3610, 3710, 3810, 3910, 4010, 4110, 4210, 4310], "harvest": [14011] }, + { "buttonID": 202, "label": "Large Stone Table", "dictID": 14061, "page": 2, "timerID": 2, "graniteMake": [3511, 3611, 3711, 3811, 3911, 4011, 4111, 4211, 4311], "harvest": [14011] }, + { "buttonID": 203, "label": "Stone Throne", "dictID": 14062, "page": 2, "timerID": 2, "graniteMake": [3512, 3612, 3712, 3812, 3912, 4012, 4112, 4212, 4312], "harvest": [14011] }, + { "buttonID": 204, "label": "Stone Bench", "dictID": 14063, "page": 2, "timerID": 2, "graniteMake": [3513, 3613, 3713, 3813, 3913, 4013, 4113, 4213, 4313], "harvest": [14011] }, + { "buttonID": 205, "label": "Ritual Table", "dictID": 14064, "page": 2, "timerID": 2, "graniteMake": [3514, 3614, 3714, 3814, 3914, 4014, 4114, 4214, 4314], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 300, "label": "Statue", "dictID": 14065, "page": 3, "timerID": 3, "graniteMake": [3515, 3615, 3715, 3815, 3915, 4015, 4115, 4215, 4315], "harvest": [14011] }, + { "buttonID": 301, "label": "Statue", "dictID": 14066, "page": 3, "timerID": 3, "graniteMake": [3516, 3616, 3716, 3816, 3916, 4016, 4116, 4216, 4316], "harvest": [14011] }, + { "buttonID": 302, "label": "Statue", "dictID": 14067, "page": 3, "timerID": 3, "graniteMake": [3517, 3617, 3717, 3817, 3917, 4017, 4117, 4217, 4317], "harvest": [14011] }, + { "buttonID": 303, "label": "Statue", "dictID": 14068, "page": 3, "timerID": 3, "graniteMake": [3518, 3618, 3718, 3818, 3918, 4018, 4118, 4218, 4318], "harvest": [14011] }, + { "buttonID": 304, "label": "Gargoyle Statue", "dictID": 14069, "page": 3, "timerID": 3, "graniteMake": [3519, 3619, 3719, 3819, 3919, 4019, 4119, 4219, 4319], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 305, "label": "Gryphon Statue", "dictID": 14070, "page": 3, "timerID": 3, "graniteMake": [3520, 3620, 3720, 3820, 3920, 4020, 4120, 4220, 4320], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 400, "label": "Stone Anvil East", "dictID": 14071, "page": 4, "timerID": 4, "graniteMake": [3521, 3621, 3721, 3821, 3921, 4021, 4121, 4221, 4321], "harvest": [14011], "recipeID": 3520, "minEra": "ml" }, + { "buttonID": 401, "label": "Stone Anvil South", "dictID": 14072, "page": 4, "timerID": 4, "graniteMake": [3522, 3622, 3722, 3822, 3922, 4022, 4122, 4222, 4322], "harvest": [14011], "recipeID": 3521, "minEra": "ml" }, + { "buttonID": 402, "label": "Large Gargish Bed East", "dictID": 14073, "page": 4, "timerID": 4, "graniteMake": [3523, 3623, 3723, 3823, 3923, 4023, 4123, 4223, 4323], "harvest": [14011, 10016], "minEra": "sa" }, + { "buttonID": 403, "label": "Large Gargish Bed South", "dictID": 14074, "page": 4, "timerID": 4, "graniteMake": [3524, 3624, 3724, 3824, 3924, 4024, 4124, 4224, 4324], "harvest": [14011, 10016], "minEra": "sa" }, + { "buttonID": 404, "label": "Gargish Cot East", "dictID": 14075, "page": 4, "timerID": 4, "graniteMake": [3525, 3625, 3725, 3825, 3925, 4025, 4125, 4225, 4325], "harvest": [14011, 10016], "minEra": "sa" }, + { "buttonID": 405, "label": "Gargish Cot South", "dictID": 14076, "page": 4, "timerID": 4, "graniteMake": [3526, 3626, 3726, 3826, 3926, 4026, 4126, 4226, 4326], "harvest": [14011, 10016], "minEra": "sa" }, + { "buttonID": 500, "label": "Gargish Stone Arms", "dictID": 14077, "page": 5, "timerID": 5, "graniteMake": [3527, 3627, 3727, 3827, 3927, 4027, 4127, 4227, 4327], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 501, "label": "Gargish Stone Chest", "dictID": 14078, "page": 5, "timerID": 5, "graniteMake": [3528, 3628, 3728, 3828, 3928, 4028, 4128, 4228, 4328], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 502, "label": "Gargish Stone Leggings", "dictID": 14079, "page": 5, "timerID": 5, "graniteMake": [3529, 3629, 3729, 3829, 3929, 4029, 4129, 4229, 4329], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 503, "label": "Gargish Stone Kilt", "dictID": 14080, "page": 5, "timerID": 5, "graniteMake": [3530, 3630, 3730, 3830, 3930, 4030, 4130, 4230, 4330], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 504, "label": "Gargish Stone Arms", "dictID": 14081, "page": 5, "timerID": 5, "graniteMake": [3531, 3631, 3731, 3831, 3931, 4031, 4131, 4231, 4331], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 505, "label": "Gargish Stone Chest", "dictID": 14082, "page": 5, "timerID": 5, "graniteMake": [3532, 3632, 3732, 3832, 3932, 4032, 4132, 4232, 4332], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 506, "label": "Gargish Stone Leggings", "dictID": 14083, "page": 5, "timerID": 5, "graniteMake": [3533, 3633, 3733, 3833, 3933, 4033, 4133, 4233, 4333], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 507, "label": "Gargish Stone Kilt", "dictID": 14084, "page": 5, "timerID": 5, "graniteMake": [3534, 3634, 3734, 3834, 3934, 4034, 4134, 4234, 4334], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 508, "label": "Large Stone Shield", "dictID": 14085, "page": 5, "timerID": 5, "graniteMake": [3535, 3635, 3735, 3835, 3935, 4035, 4135, 4235, 4335], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 509, "label": "Gargish Stone Amulet", "dictID": 14086, "page": 5, "timerID": 5, "graniteMake": [3536, 3636, 3736, 3836, 3936, 4036, 4136, 4236, 4336], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 600, "label": "Stone War Sword", "dictID": 14087, "page": 6, "timerID": 6, "graniteMake": [3537, 3637, 3737, 3837, 3937, 4037, 4137, 4237, 4337], "harvest": [14011], "minEra": "sa" }, + { "buttonID": 700, "label": "Rough Windowless", "dictID": 14088, "page": 7, "timerID": 7, "graniteMake": [3538, 3638, 3738, 3838, 3938, 4038, 4138, 4238, 4338], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 701, "label": "Rough Window", "dictID": 14089, "page": 7, "timerID": 7, "graniteMake": [3539, 3639, 3739, 3839, 3939, 4039, 4139, 4239, 4339], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 702, "label": "Rough Arch", "dictID": 14090, "page": 7, "timerID": 7, "graniteMake": [3540, 3640, 3740, 3840, 3940, 4040, 4140, 4240, 4340], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 703, "label": "Rough Pillar", "dictID": 14091, "page": 7, "timerID": 7, "graniteMake": [3541, 3641, 3741, 3841, 3941, 4041, 4141, 4241, 4341], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 704, "label": "Rough Rounded Arch", "dictID": 14092, "page": 7, "timerID": 7, "graniteMake": [3542, 3642, 3742, 3842, 3942, 4042, 4142, 4242, 4342], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 705, "label": "Rough Small Arch", "dictID": 14093, "page": 7, "timerID": 7, "graniteMake": [3543, 3643, 3743, 3843, 3943, 4043, 4143, 4243, 4343], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 706, "label": "Rough Angled Pillar", "dictID": 14094, "page": 7, "timerID": 7, "graniteMake": [3544, 3644, 3744, 3844, 3944, 4044, 4144, 4244, 4344], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 707, "label": "Short Rough", "dictID": 14095, "page": 7, "timerID": 7, "graniteMake": [3545, 3645, 3745, 3845, 3945, 4045, 4145, 4245, 4345], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 708, "label": "Stone Door S In", "dictID": 14096, "page": 7, "timerID": 7, "graniteMake": [3546, 3646, 3746, 3846, 3946, 4046, 4146, 4246, 4346], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 709, "label": "Stone Door E Out", "dictID": 14097, "page": 7, "timerID": 7, "graniteMake": [3547, 3647, 3747, 3847, 3947, 4047, 4147, 4247, 4347], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 710, "label": "Left Metal Door S In", "dictID": 14098, "page": 7, "timerID": 7, "graniteMake": [3548, 3648, 3748, 3848, 3948, 4048, 4148, 4248, 4348], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 711, "label": "Right Metal Door S In", "dictID": 14099, "page": 7, "timerID": 7, "graniteMake": [3549, 3649, 3749, 3849, 3949, 4049, 4149, 4249, 4349], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 800, "label": "Short Rough", "dictID": 14100, "page": 8, "timerID": 8, "graniteMake": [3550, 3650, 3750, 3850, 3950, 4050, 4150, 4250, 4350], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 801, "label": "Rough Steps", "dictID": 14101, "page": 8, "timerID": 8, "graniteMake": [3551, 3651, 3751, 3851, 3951, 4051, 4151, 4251, 4351], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 802, "label": "Rough Corner Steps", "dictID": 14102, "page": 8, "timerID": 8, "graniteMake": [3552, 3652, 3752, 3852, 3952, 4052, 4152, 4252, 4352], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 803, "label": "Rough Rounded Corner Step", "dictID": 14103, "page": 8, "timerID": 8, "graniteMake": [3553, 3653, 3753, 3853, 3953, 4053, 4153, 4253, 4353], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 804, "label": "Rough Inset Steps", "dictID": 14104, "page": 8, "timerID": 8, "graniteMake": [3554, 3654, 3754, 3854, 3954, 4054, 4154, 4254, 4354], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 805, "label": "Rough Rounded Inset Steps", "dictID": 14105, "page": 8, "timerID": 8, "graniteMake": [3555, 3655, 3755, 3855, 3955, 4055, 4155, 4255, 4355], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 900, "label": "Light Paver", "dictID": 14106, "page": 9, "timerID": 9, "graniteMake": [3556, 3656, 3756, 3856, 3956, 4056, 4156, 4256, 4356], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 901, "label": "Medium Paver", "dictID": 14107, "page": 9, "timerID": 9, "graniteMake": [3557, 3657, 3757, 3857, 3957, 4057, 4157, 4257, 4357], "harvest": [14011], "minEra": "tol" }, + { "buttonID": 902, "label": "Dark Paver", "dictID": 14108, "page": 9, "timerID": 9, "graniteMake": [3558, 3658, 3758, 3858, 3958, 4058, 4158, 4258, 4358], "harvest": [14011], "minEra": "tol" } +] diff --git a/data/js/jsdata/crafting/resourcemap.json b/data/js/jsdata/crafting/resourcemap.json new file mode 100644 index 000000000..37ba5bb56 --- /dev/null +++ b/data/js/jsdata/crafting/resourcemap.json @@ -0,0 +1,44 @@ +[ + { "resourceSet": "wood", "label": "Wood", "dictID": 10687, "items": [ + { "label": "Logs", "itemID": 7136, "hue": 0 }, + { "label": "Boards", "itemID": 7127, "hue": 0 } + ] }, + { "resourceSet": "tailoring", "label": "Tailoring Materials", "dictID": 11402, "items": [ + { "label": "Leather", "itemID": 4199, "hue": 0 }, + { "label": "Leather", "itemID": 4200, "hue": 0 }, + { "label": "Leather", "itemID": 4225, "hue": 0 }, + { "label": "Leather", "itemID": 4226, "hue": 0 }, + { "label": "Hides", "itemID": 4216, "hue": 0 }, + { "label": "Hides", "itemID": 4217, "hue": 0 } + ] }, + { "resourceSet": "ore", "label": "Ore", "tempTag": "ORE", "defaultIndex": 0, "items": [ + { "index": 0, "label": "Iron", "dictID": 10291, "itemID": 7154, "hue": 0, "minSkill": 0 }, + { "index": 1, "label": "Dull Copper", "dictID": 10203, "itemID": 7154, "hue": 2419, "minSkill": 650 }, + { "index": 2, "label": "Shadow Iron", "dictID": 10204, "itemID": 7154, "hue": 2406, "minSkill": 700 }, + { "index": 3, "label": "Copper", "dictID": 10205, "itemID": 7154, "hue": 2013, "minSkill": 750 }, + { "index": 4, "label": "Bronze", "dictID": 10206, "itemID": 7154, "hue": 1750, "minSkill": 800 }, + { "index": 5, "label": "Gold", "dictID": 10207, "itemID": 7154, "hue": 2213, "minSkill": 850 }, + { "index": 6, "label": "Agapite", "dictID": 10208, "itemID": 7154, "hue": 2425, "minSkill": 900 }, + { "index": 7, "label": "Verite", "dictID": 10209, "itemID": 7154, "hue": 2207, "minSkill": 950 }, + { "index": 8, "label": "Valorite", "dictID": 10210, "itemID": 7154, "hue": 2219, "minSkill": 990 } + ] }, + { "resourceSet": "granite", "label": "Granite", "tempTag": "Granite", "defaultIndex": 0, "items": [ + { "index": 0, "label": "Granite", "dictID": 14011, "itemID": 6009, "hue": 0 }, + { "index": 1, "label": "Dull Copper Granite", "dictID": 14012, "itemID": 6009, "hue": 2419 }, + { "index": 2, "label": "Shadow Iron Granite", "dictID": 14013, "itemID": 6009, "hue": 2406 }, + { "index": 3, "label": "Copper Granite", "dictID": 14014, "itemID": 6009, "hue": 2013 }, + { "index": 4, "label": "Bronze Granite", "dictID": 14015, "itemID": 6009, "hue": 1750 }, + { "index": 5, "label": "Gold Granite", "dictID": 14016, "itemID": 6009, "hue": 2213 }, + { "index": 6, "label": "Agapite Granite", "dictID": 14017, "itemID": 6009, "hue": 2425 }, + { "index": 7, "label": "Verite Granite", "dictID": 14018, "itemID": 6009, "hue": 2207 }, + { "index": 8, "label": "Valorite Granite", "dictID": 14019, "itemID": 6009, "hue": 2219 } + ] }, + { "resourceSet": "dragonScales", "label": "Dragon Scales", "tempTag": "Scale", "defaultIndex": 0, "items": [ + { "index": 0, "label": "Red Scales", "dictID": 20299, "itemID": 9908, "hue": 1635, "minSkill": 0 }, + { "index": 1, "label": "Yellow Scales", "dictID": 20300, "itemID": 9908, "hue": 2125, "minSkill": 0 }, + { "index": 2, "label": "Black Scales", "dictID": 20301, "itemID": 9908, "hue": 1109, "minSkill": 0 }, + { "index": 3, "label": "Green Scales", "dictID": 20302, "itemID": 9908, "hue": 2129, "minSkill": 0 }, + { "index": 4, "label": "White Scales", "dictID": 20303, "itemID": 9908, "hue": 706, "minSkill": 0 }, + { "index": 5, "label": "Blue Scales", "dictID": 20304, "itemID": 9908, "hue": 6, "minSkill": 0 } + ] } +] diff --git a/data/js/jsdata/crafting/tailoring.json b/data/js/jsdata/crafting/tailoring.json new file mode 100644 index 000000000..17e34d9b6 --- /dev/null +++ b/data/js/jsdata/crafting/tailoring.json @@ -0,0 +1,58 @@ +[ + { "makeID": 130, "label": "Skullcap", "dictID": 11415, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 131, "label": "Bandana", "dictID": 11416, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 132, "label": "Floppy Hat", "dictID": 11417, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 134, "label": "Wide-Brim Hat", "dictID": 11418, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 133, "label": "Cap", "dictID": 11419, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 136, "label": "Tall Straw Hat", "dictID": 11420, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 137, "label": "Straw Hat", "dictID": 11421, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 138, "label": "Wizard Hat", "dictID": 11422, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 139, "label": "Bonnet", "dictID": 11423, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 140, "label": "Feathered Hat", "dictID": 11424, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 141, "label": "Tricorne Hat", "dictID": 11425, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 135, "label": "Jester Hat", "dictID": 11470, "page": 1, "timerID": 1, "harvest": [10016] }, + { "makeID": 142, "label": "Doublet", "dictID": 11426, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 143, "label": "Shirt", "dictID": 11427, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 144, "label": "Fancy Shirt", "dictID": 11428, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 145, "label": "Tunic", "dictID": 11429, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 146, "label": "Surcoat", "dictID": 11430, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 147, "label": "Plain Dress", "dictID": 11431, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 148, "label": "Fancy Dress", "dictID": 11432, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 149, "label": "Cloak", "dictID": 11433, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 150, "label": "Robe", "dictID": 11434, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 151, "label": "Jester Suit", "dictID": 11435, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 180, "label": "Fur Cape", "dictID": 11436, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 152, "label": "Short Pants", "dictID": 11437, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 153, "label": "Long Pants", "dictID": 11438, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 154, "label": "Kilt", "dictID": 11439, "page": 2, "timerID": 2, "harvest": [10016] }, + { "makeID": 155, "label": "Skirt", "dictID": 11440, "page": 3, "timerID": 3, "harvest": [10016] }, + { "makeID": 156, "label": "Body Sash", "dictID": 11441, "page": 3, "timerID": 3, "harvest": [10016] }, + { "makeID": 157, "label": "Half Apron", "dictID": 11442, "page": 3, "timerID": 3, "harvest": [10016] }, + { "makeID": 158, "label": "Full Apron", "dictID": 11443, "page": 3, "timerID": 3, "harvest": [10016] }, + { "makeID": 159, "label": "Sandals", "dictID": 11444, "page": 4, "timerID": 4, "harvest": [10007] }, + { "makeID": 160, "label": "Shoes", "dictID": 11445, "page": 4, "timerID": 4, "harvest": [10007] }, + { "makeID": 161, "label": "Boots", "dictID": 11446, "page": 4, "timerID": 4, "harvest": [10007] }, + { "makeID": 162, "label": "Thigh Boots", "dictID": 11447, "page": 4, "timerID": 4, "harvest": [10007] }, + { "makeID": 163, "label": "Leather Gorget", "dictID": 11448, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 164, "label": "Leather Cap", "dictID": 11449, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 165, "label": "Leather Gloves", "dictID": 11450, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 166, "label": "Leather Sleeves", "dictID": 11451, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 167, "label": "Leather Leggings", "dictID": 11452, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 168, "label": "Leather Tunic", "dictID": 11453, "page": 5, "timerID": 5, "harvest": [10007] }, + { "makeID": 169, "label": "Studded Gorget", "dictID": 11454, "page": 6, "timerID": 6, "harvest": [10007] }, + { "makeID": 170, "label": "Studded Gloves", "dictID": 11455, "page": 6, "timerID": 6, "harvest": [10007] }, + { "makeID": 171, "label": "Studded Sleeves", "dictID": 11456, "page": 6, "timerID": 6, "harvest": [10007] }, + { "makeID": 172, "label": "Studded Leggings", "dictID": 11457, "page": 6, "timerID": 6, "harvest": [10007] }, + { "makeID": 173, "label": "Studded Tunic", "dictID": 11458, "page": 6, "timerID": 6, "harvest": [10007] }, + { "makeID": 174, "label": "Leather Shorts", "dictID": 11459, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 175, "label": "Leather Skirt", "dictID": 11460, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 176, "label": "Leather Bustier", "dictID": 11461, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 177, "label": "Studded Bustier", "dictID": 11462, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 178, "label": "Female Leather Armor", "dictID": 11463, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 179, "label": "Studded Armor", "dictID": 11464, "page": 7, "timerID": 7, "harvest": [10007] }, + { "makeID": 181, "label": "Bone Helm", "dictID": 11465, "page": 8, "timerID": 8, "harvest": [10007, 10008] }, + { "makeID": 182, "label": "Bone Gloves", "dictID": 11466, "page": 8, "timerID": 8, "harvest": [10007, 10008] }, + { "makeID": 183, "label": "Bone Arms", "dictID": 11467, "page": 8, "timerID": 8, "harvest": [10007, 10008] }, + { "makeID": 184, "label": "Bone Leggings", "dictID": 11468, "page": 8, "timerID": 8, "harvest": [10007, 10008] }, + { "makeID": 185, "label": "Bone Armor", "dictID": 11469, "page": 8, "timerID": 8, "harvest": [10007, 10008] } +] diff --git a/data/js/jsdata/crafting/tinkering.json b/data/js/jsdata/crafting/tinkering.json index 1205f0f72..0c1187f52 100644 --- a/data/js/jsdata/crafting/tinkering.json +++ b/data/js/jsdata/crafting/tinkering.json @@ -1,78 +1,78 @@ [ - { "makeID": 274, "label": "Axle", "dictID": 11801, "page": 1, "timerID": 1, "harvest": [10014] }, - { "makeID": 273, "label": "Clock Frame", "dictID": 11802, "page": 1, "timerID": 1, "harvest": [10014] }, - { "makeID": 270, "label": "Jointing Plane", "dictID": 11803, "page": 1, "timerID": 1, "harvest": [10014] }, - { "makeID": 271, "label": "Moulding Plane", "dictID": 11804, "page": 1, "timerID": 1, "harvest": [10014] }, - { "makeID": 272, "label": "Smoothing Plane", "dictID": 11805, "page": 1, "timerID": 1, "harvest": [10014] }, - { "makeID": 218, "label": "Dovetail Saw", "dictID": 11820, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 215, "label": "Draw Knife", "dictID": 11821, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 252, "label": "Froe", "dictID": 11822, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 255, "label": "Hammer", "dictID": 11823, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 214, "label": "Hatchet", "dictID": 11824, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 258, "label": "Inshave", "dictID": 11825, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 260, "label": "Lockpick", "dictID": 11826, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 211, "label": "Mortar and Pestle", "dictID": 11827, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 259, "label": "Pick Axe", "dictID": 11828, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 217, "label": "Saw", "dictID": 11829, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 210, "label": "Scissors", "dictID": 11830, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 212, "label": "Scorp", "dictID": 11831, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 216, "label": "Sewing Kit", "dictID": 11832, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 254, "label": "Shovel", "dictID": 11833, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 257, "label": "Sledge Hammer", "dictID": 11834, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 256, "label": "Smith's Hammer", "dictID": 11835, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 253, "label": "Tongs", "dictID": 11836, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 213, "label": "Tool Kit (Tinker's tools)", "dictID": 11837, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 284, "label": "Fletcher's Tools", "dictID": 11838, "page": 2, "timerID": 2, "harvest": [10015] }, - { "makeID": 224, "label": "Barrel Hoops", "dictID": 11860, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 221, "label": "Barrel Tap", "dictID": 11861, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 220, "label": "Clock parts", "dictID": 11862, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 219, "label": "Gears", "dictID": 11863, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 225, "label": "Hinge", "dictID": 11864, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 223, "label": "Sextant parts", "dictID": 11865, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 222, "label": "Springs", "dictID": 11866, "page": 3, "timerID": 3, "harvest": [10015] }, - { "makeID": 226, "label": "Butcher Knife", "dictID": 11880, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 232, "label": "Cleaver", "dictID": 11881, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 230, "label": "Fork", "dictID": 11882, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 231, "label": "Fork", "dictID": 11883, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 235, "label": "Goblet", "dictID": 11884, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 233, "label": "Knife", "dictID": 11885, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 234, "label": "Knife", "dictID": 11886, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 236, "label": "Pewter Mug", "dictID": 11887, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 229, "label": "Plate", "dictID": 11888, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 237, "label": "Skinning Knife", "dictID": 11889, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 227, "label": "Spoon", "dictID": 11890, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 228, "label": "Spoon", "dictID": 11891, "page": 4, "timerID": 4, "harvest": [10015] }, - { "makeID": 243, "label": "Bracelet", "dictID": 11900, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, - { "makeID": 241, "label": "Earrings", "dictID": 11901, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, - { "makeID": 239, "label": "Necklage (Golden beads)", "dictID": 11902, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, - { "makeID": 240, "label": "Necklace (Silver beads)", "dictID": 11903, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, - { "makeID": 242, "label": "Necklace (Round)", "dictID": 11904, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005] }, - { "makeID": 238, "label": "Weddingband (newbiefied)", "dictID": 11905, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12006] }, - { "makeID": 245, "label": "Candelabra", "dictID": 11920, "page": 6, "timerID": 6, "harvest": [10015, 12000] }, - { "makeID": 248, "label": "Globe", "dictID": 11921, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 251, "label": "Heating stand", "dictID": 11922, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 247, "label": "Iron Key", "dictID": 11923, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 244, "label": "Keyring", "dictID": 11924, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 250, "label": "Lantern", "dictID": 11925, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 246, "label": "Scales", "dictID": 11926, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 249, "label": "Spy glass", "dictID": 11927, "page": 6, "timerID": 6, "harvest": [10015] }, - { "makeID": 275, "label": "Axle and Gears", "dictID": 11940, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, - { "makeID": 276, "label": "Clock", "dictID": 11941, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, - { "makeID": 277, "label": "Clock", "dictID": 11942, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, - { "makeID": 278, "label": "Clock Parts", "dictID": 11943, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, - { "makeID": 279, "label": "Locked Box", "dictID": 11944, "page": 7, "timerID": 7, "harvest": [10634] }, - { "makeID": 280, "label": "Locked Chest", "dictID": 11945, "page": 7, "timerID": 7, "harvest": [10638] }, - { "makeID": 281, "label": "Potion Keg", "dictID": 11946, "page": 7, "timerID": 7, "harvest": [10642, 11861, 10612, 10928] }, - { "makeID": 282, "label": "Sextant", "dictID": 11947, "page": 7, "timerID": 7, "harvest": [11948] }, - { "makeID": 283, "label": "Sextant Parts", "dictID": 11948, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, - { "makeID": 310, "label": "Standing Candelabra", "dictID": 11961, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, - { "makeID": 315, "label": "Regular Candle", "dictID": 11962, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, - { "makeID": 312, "label": "Round Candle", "dictID": 11963, "page": 8, "timerID": 8, "harvest": [12000] }, - { "makeID": 316, "label": "Skull with Candle", "dictID": 11964, "page": 8, "timerID": 8, "harvest": [12000, 12004] }, - { "makeID": 314, "label": "Small Candle", "dictID": 11965, "page": 8, "timerID": 8, "harvest": [12000] }, - { "makeID": 311, "label": "Tall Candle", "dictID": 11966, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, - { "makeID": 313, "label": "Thick Candle", "dictID": 11967, "page": 8, "timerID": 8, "harvest": [12000] }, - { "makeID": 261, "label": "Dart Trap", "dictID": 11980, "page": 9, "timerID": 9, "harvest": [10015, 12001] }, - { "makeID": 263, "label": "Explosion Trap", "dictID": 11981, "page": 9, "timerID": 9, "harvest": [10015, 12003] }, - { "makeID": 262, "label": "Poison Trap", "dictID": 11982, "page": 9, "timerID": 9, "harvest": [10015, 12002] } -] \ No newline at end of file + { "makeID": 274, "label": "Axle", "dictID": 11801, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 273, "label": "Clock Frame", "dictID": 11802, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 270, "label": "Jointing Plane", "dictID": 11803, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 271, "label": "Moulding Plane", "dictID": 11804, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 272, "label": "Smoothing Plane", "dictID": 11805, "page": 1, "timerID": 1, "harvest": [10014] }, + { "makeID": 218, "label": "Dovetail Saw", "dictID": 11820, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 215, "label": "Draw Knife", "dictID": 11821, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 252, "label": "Froe", "dictID": 11822, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 255, "label": "Hammer", "dictID": 11823, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 214, "label": "Hatchet", "dictID": 11824, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 258, "label": "Inshave", "dictID": 11825, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 260, "label": "Lockpick", "dictID": 11826, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 211, "label": "Mortar and Pestle", "dictID": 11827, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 259, "label": "Pick Axe", "dictID": 11828, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 217, "label": "Saw", "dictID": 11829, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 210, "label": "Scissors", "dictID": 11830, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 212, "label": "Scorp", "dictID": 11831, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 216, "label": "Sewing Kit", "dictID": 11832, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 254, "label": "Shovel", "dictID": 11833, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 257, "label": "Sledge Hammer", "dictID": 11834, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 256, "label": "Smith's Hammer", "dictID": 11835, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 253, "label": "Tongs", "dictID": 11836, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 213, "label": "Tool Kit (Tinker's tools)", "dictID": 11837, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 284, "label": "Fletcher's Tools", "dictID": 11838, "page": 2, "timerID": 2, "harvest": [10015] }, + { "makeID": 224, "label": "Barrel Hoops", "dictID": 11860, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 221, "label": "Barrel Tap", "dictID": 11861, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 220, "label": "Clock parts", "dictID": 11862, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 219, "label": "Gears", "dictID": 11863, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 225, "label": "Hinge", "dictID": 11864, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 223, "label": "Sextant parts", "dictID": 11865, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 222, "label": "Springs", "dictID": 11866, "page": 3, "timerID": 3, "harvest": [10015] }, + { "makeID": 226, "label": "Butcher Knife", "dictID": 11880, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 232, "label": "Cleaver", "dictID": 11881, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 230, "label": "Fork", "dictID": 11882, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 231, "label": "Fork", "dictID": 11883, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 235, "label": "Goblet", "dictID": 11884, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 233, "label": "Knife", "dictID": 11885, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 234, "label": "Knife", "dictID": 11886, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 236, "label": "Pewter Mug", "dictID": 11887, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 229, "label": "Plate", "dictID": 11888, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 237, "label": "Skinning Knife", "dictID": 11889, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 227, "label": "Spoon", "dictID": 11890, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 228, "label": "Spoon", "dictID": 11891, "page": 4, "timerID": 4, "harvest": [10015] }, + { "makeID": 243, "label": "Bracelet", "dictID": 11900, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 241, "label": "Earrings", "dictID": 11901, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 239, "label": "Necklage (Golden beads)", "dictID": 11902, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 240, "label": "Necklace (Silver beads)", "dictID": 11903, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 242, "label": "Necklace (Round)", "dictID": 11904, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12005], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 238, "label": "Weddingband (newbiefied)", "dictID": 11905, "page": 5, "timerID": 5, "requiresGemTarget": true, "harvest": [10015, 12006], "craftComplete": { "type": "gemJewelry" } }, + { "makeID": 245, "label": "Candelabra", "dictID": 11920, "page": 6, "timerID": 6, "harvest": [10015, 12000] }, + { "makeID": 248, "label": "Globe", "dictID": 11921, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 251, "label": "Heating stand", "dictID": 11922, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 247, "label": "Iron Key", "dictID": 11923, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 244, "label": "Keyring", "dictID": 11924, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 250, "label": "Lantern", "dictID": 11925, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 246, "label": "Scales", "dictID": 11926, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 249, "label": "Spy glass", "dictID": 11927, "page": 6, "timerID": 6, "harvest": [10015] }, + { "makeID": 275, "label": "Axle and Gears", "dictID": 11940, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 276, "label": "Clock", "dictID": 11941, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, + { "makeID": 277, "label": "Clock", "dictID": 11942, "page": 7, "timerID": 7, "harvest": [11802, 11862] }, + { "makeID": 278, "label": "Clock Parts", "dictID": 11943, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 279, "label": "Locked Box", "dictID": 11944, "page": 7, "timerID": 7, "harvest": [10634] }, + { "makeID": 280, "label": "Locked Chest", "dictID": 11945, "page": 7, "timerID": 7, "harvest": [10638] }, + { "makeID": 281, "label": "Potion Keg", "dictID": 11946, "page": 7, "timerID": 7, "harvest": [10642, 11861, 10612, 10928] }, + { "makeID": 282, "label": "Sextant", "dictID": 11947, "page": 7, "timerID": 7, "harvest": [11948] }, + { "makeID": 283, "label": "Sextant Parts", "dictID": 11948, "page": 7, "timerID": 7, "harvest": [11801, 11863] }, + { "makeID": 310, "label": "Standing Candelabra", "dictID": 11961, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 315, "label": "Regular Candle", "dictID": 11962, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 312, "label": "Round Candle", "dictID": 11963, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 316, "label": "Skull with Candle", "dictID": 11964, "page": 8, "timerID": 8, "harvest": [12000, 12004] }, + { "makeID": 314, "label": "Small Candle", "dictID": 11965, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 311, "label": "Tall Candle", "dictID": 11966, "page": 8, "timerID": 8, "harvest": [10015, 12000] }, + { "makeID": 313, "label": "Thick Candle", "dictID": 11967, "page": 8, "timerID": 8, "harvest": [12000] }, + { "makeID": 261, "label": "Dart Trap", "dictID": 11980, "page": 9, "timerID": 9, "harvest": [10015, 12001] }, + { "makeID": 263, "label": "Explosion Trap", "dictID": 11981, "page": 9, "timerID": 9, "harvest": [10015, 12003] }, + { "makeID": 262, "label": "Poison Trap", "dictID": 11982, "page": 9, "timerID": 9, "harvest": [10015, 12002] } +] diff --git a/data/js/skill/craft/alchemy.js b/data/js/skill/craft/alchemy.js index 4069092f9..4e6fc1259 100644 --- a/data/js/skill/craft/alchemy.js +++ b/data/js/skill/craft/alchemy.js @@ -10,70 +10,42 @@ const displayUnlearnedRecipes = true; // For future recipe use const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const alchemySkillID = 0; // Skill ID: Alchemy -// o--------------------------------------------------------------------------o -// | AlchemyMap | -// o--------------------------------------------------------------------------o -// | Keyed by makeID (create entry ID). | -// | Each entry: | -// | dictID - dictionary entry for row text | -// | page - main category page (1..4) | -// | timerID - which page timer should reopen | -// | skill - skill used (default: alchemySkillID) | -// | recipeID?, minEra?, maxEra?, harvest?[] harvestNames? ["cloth" ] | -// | can be added later | -// o--------------------------------------------------------------------------o -// If you want to add multi-reagent potions later -// (e.g. harvest: [ garlic_dictNumber, ginseng_dictNumber ] or harvestNames: [ "garlic, "ginseng" ]), -// the same pattern will just work with no script changes. - -const AlchemyMap = { - // Page 1 - Curative / Refresh - 298: { dictID: 10910, page: 1, timerID: 1, harvest: [ 10022 ] }, // Lesser Heal - 299: { dictID: 10911, page: 1, timerID: 1, harvest: [ 10022 ] }, // Heal - 300: { dictID: 10912, page: 1, timerID: 1, harvest: [ 10022 ] }, // Greater Heal - 305: { dictID: 10908, page: 1, timerID: 1, harvest: [ 10025 ] }, // Refresh - 306: { dictID: 10909, page: 1, timerID: 1, harvest: [ 10025 ] }, // Total Refresh - 292: { dictID: 10913, page: 1, timerID: 1, harvest: [ 10020 ] }, // Lesser Cure - 293: { dictID: 10914, page: 1, timerID: 1, harvest: [ 10020 ] }, // Cure - 294: { dictID: 10915, page: 1, timerID: 1, harvest: [ 10020 ] }, // Greater Cure - - // Page 2 - Enhancement - 290: { dictID: 10916, page: 2, timerID: 2, harvest: [ 10019 ] }, // Agility - 291: { dictID: 10917, page: 2, timerID: 2, harvest: [ 10019 ] }, // Greater Agility - 295: { dictID: 10918, page: 2, timerID: 2, harvest: [ 10021 ] }, // Strength - 296: { dictID: 10919, page: 2, timerID: 2, harvest: [ 10021 ] }, // Greater Strength - 297: { dictID: 10920, page: 2, timerID: 2, harvest: [ 10021 ] }, // Night Sight - - // Page 3 - Poison - 301: { dictID: 10921, page: 3, timerID: 3, harvest: [ 10024 ] }, // Lesser Poison - 302: { dictID: 10922, page: 3, timerID: 3, harvest: [ 10024 ] }, // Poison - 303: { dictID: 10923, page: 3, timerID: 3, harvest: [ 10024 ] }, // Greater Poison - 304: { dictID: 10924, page: 3, timerID: 3, harvest: [ 10024 ] }, // Deadly Poison - - // Page 4 - Explosive - 307: { dictID: 10925, page: 4, timerID: 4, harvest: [ 10026 ] }, // Explosion - 308: { dictID: 10926, page: 4, timerID: 4, harvest: [ 10026 ] }, // Greater Explosion - 309: { dictID: 10927, page: 4, timerID: 4, harvest: [ 10023 ] } // Conflagration (or w/e 10927 is) -}; - -// Fill in defaults (skill, etc) -(function initAlchemyMap() +const craftMapRegistryID = 4038; +var AlchemyMap = {}; + +function LoadAlchemyMap() { - for( var key in AlchemyMap ) + AlchemyMap = {}; + + var alchemyEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "alchemy" ); + + if( !alchemyEntries || !IsAlchemyArrayValue( alchemyEntries ) ) { - if( !AlchemyMap.hasOwnProperty( key )) - continue; + Console.Warning( "Alchemy: Unable to load alchemy craft map data." ); + return false; + } - var entry = AlchemyMap[key]; + for( var i = 0; i < alchemyEntries.length; i++ ) + { + var entry = alchemyEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) + continue; if( entry.skill === undefined ) entry.skill = alchemySkillID; - // If you ever want to drive item detail resources here: - // entry.harvest = [ , , ... ]; - // For now, the detail gump will infer resources directly from DFN create entries. + AlchemyMap[entry.makeID] = entry; } -})(); + + Console.Print( "Alchemy: Loaded " + alchemyEntries.length + " craft map entries.\n" ); + return true; +} + +function IsAlchemyArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} // o--------------------------------------------------------------------------o // | PageX() - build a page of alchemy items | @@ -84,6 +56,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !AlchemyMap || Object.keys( AlchemyMap ).length == 0 ) + { + if( !LoadAlchemyMap() ) + { + socket.SysMessage( "Alchemy craft map failed to load." ); + return; + } + } + var pageItems; // Special Last Ten page diff --git a/data/js/skill/craft/blacksmithing.js b/data/js/skill/craft/blacksmithing.js index 158f6526e..55d97271d 100644 --- a/data/js/skill/craft/blacksmithing.js +++ b/data/js/skill/craft/blacksmithing.js @@ -17,404 +17,65 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); // regular weapons with ore colour applied const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); -const OreTypes = [ - { nameDict: 10291, hue: 0x0000, minMining: 0 }, // Iron - { nameDict: 10203, hue: 0x0973, minMining: 650 }, // Dull Copper - { nameDict: 10204, hue: 0x0966, minMining: 700 }, // Shadow Iron - { nameDict: 10205, hue: 0x07dd, minMining: 750 }, // Copper - { nameDict: 10206, hue: 0x06d6, minMining: 800 }, // Bronze - { nameDict: 10207, hue: 0x08a5, minMining: 850 }, // Gold - { nameDict: 10208, hue: 0x0979, minMining: 900 }, // Agapite - { nameDict: 10209, hue: 0x089f, minMining: 950 }, // Verite - { nameDict: 10210, hue: 0x08ab, minMining: 990 } // Valorite -]; - -const ScaleTypes = [ - { nameDict: 20299, hue: 0x0663, minSkill: 0 }, // Red - { nameDict: 20300, hue: 0x084d, minSkill: 0 }, // Yellow - { nameDict: 20301, hue: 0x0455, minSkill: 0 }, // Black - { nameDict: 20302, hue: 0x0851, minSkill: 0 }, // Green - { nameDict: 20303, hue: 0x02c2, minSkill: 0 }, // White - { nameDict: 20304, hue: 0x0006, minSkill: 0 } // Blue - // add more as required -]; - -// Optional: if you later decide to make some blacksmith items recipe-locked, we will use this map: -// BlacksmithMap[buttonID] = { dictID, page, timerID, oreMake: [makeIDByOre], recipeID?, minEra?, maxEra? } -// o--------------------------------------------------------------------------o -// | Script - blacksmithing.js | -// | System - Blacksmith Crafting Gump | -// o--------------------------------------------------------------------------o -// | Purpose - | -// | Provides the blacksmith crafting menu using the same data-driven | -// | system used by the tailoring script. | -// | | -// | All craftable items are defined in tables (myPage, craftItems) and | -// | then mapped into a BlacksmithMap structure that controls: | -// | - Which dictionary entry is shown per row | -// | - Which "makeID" entry is used for each ore type | -// | - Which page and timer ID to use when reopening the gump | -// | - Optional per-item recipe and era requirements | -// | - Optional per-item custom names for display | -// | | -// | The script also handles: | -// | - iron selection (iron / colored ores) with skill requirements | -// | - Smelting iron items back into ingots | -// | - Repairing stone armor and weapons at an anvil | -// | - Tool wear and runic hammer handling | -// | - A "Make Last" feature | -// | - A "Last Ten Blacnksmithing" list (optional) | -// o--------------------------------------------------------------------------o -// | Data Tables | -// o--------------------------------------------------------------------------o -// | myPage | -// | myPage[pageIndex] = [ dictID1, dictID2, ... ] | -// | pageIndex 0 => Page 1: Metal Armor | -// | pageIndex 1 => Page 2: Helmets | -// | pageIndex 2 => Page 3: Shields | -// | pageIndex 3 => Page 4: Bladed weapons | -// | pageIndex 4 => Page 5: Axes | -// | pageIndex 5 => Page 6: Polearms | -// | pageIndex 6 => Page 7: Bashing weapons | -// | | -// | Each entry is a dictionary ID that will be used to look up the text | -// | for that row, unless a customName is defined for that button in | -// | BlacksmithMap. | -// | | -// | craftItems | -// | craftItems[ironIndex][pageIndex][itemIndex] = makeID | -// | oreIndex 0 = Iron | -// | oreIndex 1 = Dull Copper | -// | oreIndex 2 = Shadow Iron | -// | oreIndex 3 = Copper | -// | oreIndex 4 = Bronze | -// | oreIndex 5 = Gold | -// | oreIndex 6 = Agapite | -// | oreIndex 7 = Verite | -// | oreIndex 8 = Valorite | -// | | -// | For each ingot type and page, this holds the createEntry ID used by | -// | MakeItem when the player crafts that item. The same index positions | -// | on each page line up with the matching entries in myPage. | -// o--------------------------------------------------------------------------o -// | BlacksmithMap | -// o--------------------------------------------------------------------------o -// | BlacksmithMap is built automatically from myPage and craftItems. | -// | | -// | BlacksmithMap[buttonID] = { | -// | dictID : number, // Base dictionary entry for the row | -// | page : number, // Main page (1..7, or 999 for Last Ten) | -// | timerID : number, // Timer ID to reopen same page | -// | oreMake : number[], // oreMake[oreIndex] = makeID | -// | customName: string?, // Optional override for display text | -// | recipeID : number?, // Optional recipe requirement | -// | minEra : string?, // Optional minimum shard era | -// | maxEra : string? // Optional maximum shard era | -// | }; | -// | | -// | Button ID mapping (same as original script): | -// | Page 1 (Metal Armors) : 100..108 | -// | Page 2 (Helmets) : 200..205 | -// | Page 3 (Shields) : 300..305 | -// | Page 4 (Bladed) : 400..407 | -// | Page 5 (Axes) : 500..506 | -// | Page 6 (PoleArms) : 600..604 | -// | Page 7 (Bashing): 700..704 | -// | | -// | Custom Names | -// | To override the display name for a specific row, set customName after | -// | the BlacksmithMap has been initialized, for example: | -// | | -// | BlacksmithMap[100].customName = "Hump vase"; | -// | | -// | PageX() will use this order of preference for text: | -// | 1. entry.customName (if set) | -// | 2. GetDictionaryEntry(entry.dictID) | -// | 3. A fallback "[Unnamed Item: buttonID]" | -// | | -// | Recipes | -// | If recipeID is set on a BlacksmithMap entry, onGumpPress will call: | -// | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | -// | to check if the player has learned that recipe. If not, the craft | -// | attempt is blocked and a message is shown. | -// | | -// | Era Gating | -// | The script reads the shard era using: | -// | const coreShardEra = EraStringToNum(GetServerSetting("CoreShardEra")); | -// | | -// | If an entry defines minEra or maxEra (strings like "lbr","aos","ml", | -// | "sa","hs","tol"), eraOK(entry) will ensure the current server era is | -// | within that range before allowing craft or display. | -// o--------------------------------------------------------------------------o -// | Notes | -// o--------------------------------------------------------------------------o -// | - To add new blacksmith items, update myPage and craftItems, then | -// | optionally decorate their BlacksmithMap entries with customName, | -// | recipeID, minEra, and maxEra. | -// o--------------------------------------------------------------------------o - -const myPage = [ - // Page 1 - Metal Armors - [10217, 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10225, 10226, 10227, 10228, 10229, 0, 0, 0, 0 ,0], - // Page 2 - Helmets - [10230, 10231, 10232, 10233, 10234], - // Page 3 - Shields - [10235, 10236, 10237, 10238, 10239, 10293], - // Page 4 - Bladed - [10240, 10241, 10242, 10243, 10244, 10245, 10246, 10247], - // Page 5 - Axes - [10248, 10249, 10250, 10251, 10252, 10253, 10254], - // Page 6 - PoleArms - [10255, 10256, 10257, 10258, 10259], - // Page 7 - Bashing - [10260, 10261, 10262, 10263, 10264] -]; - -const craftItems = [ - // Iron - [ - // Metal Armors - [ 7, 9, 8, 10, 11, 12, 13, 16, 15, 14, 17, 18, 19, 367, 368, 369, 370, 371 ], - // Helmets - [ 46, 48, 45, 47, 49 ], - // Shields - [ 1, 2, 6, 3, 5, 4 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Dull Copper - [ - // Metal Armors - [ 506, 508, 507, 509, 510, 511, 512, 515, 514, 513, 516, 517, 518 ], - // Helmets - [ 520, 522, 519, 521, 523 ], - // Shields - [ 500, 501, 505, 502, 504, 503 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Shadow Iron - [ - // Metal Armors - [ 606, 608, 607, 609, 610, 611, 612, 615, 614, 613, 616, 617, 618 ], - // Helmets - [ 620, 622, 619, 621, 623 ], - // Shields - [ 600, 601, 605, 602, 604, 603 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Copper - [ - // Metal Armors - [ 706, 708, 707, 709, 710, 711, 7012, 715, 714, 713, 716, 717, 718 ], - // Helmets - [ 720, 722, 719, 721, 723 ], - // Shields - [ 700, 701, 705, 702, 704, 703 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Bronze - [ - // Metal Armors - [ 806, 808, 807, 809, 810, 811, 812, 815, 814, 813, 816, 817, 818 ], - // Helmets - [ 820, 822, 819, 821, 823 ], - // Shields - [ 800, 801, 805, 802, 804, 803 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Gold - [ - // Metal Armors - [ 906, 908, 907, 909, 910, 911, 912, 915, 914, 913, 916, 917, 918 ], - // Helmets - [ 920, 922, 919, 921, 923 ], - // Shields - [ 900, 901, 905, 902, 904, 903 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Agapite - [ - // Metal Armors - [ 1206, 1208, 1207, 1209, 1210, 1211, 1212, 1215, 1214, 1213, 1216, 1217, 1218 ], - // Helmets - [ 1220, 1222, 1219, 1221, 1223 ], - // Shields - [ 1200, 1201, 1205, 1202, 1204, 1203 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Verite - [ - // Metal Armors - [ 1006, 1008, 1007, 1009, 1010, 1011, 1012, 1015, 1014, 1013, 1016, 1017, 1018 ], - // Helmets - [ 1020, 1022, 1019, 1021, 1023 ], - // Shields - [ 1000, 1001, 1005, 1002, 1004, 1003 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ], - - // Valorite - [ - // Metal Armors - [ 1106, 1108, 1107, 1109, 1110, 1111, 1112, 1115, 1114, 1113, 1116, 1117, 1118 ], - // Helmets - [ 1120, 1122, 1119, 1121, 1123 ], - // Shields - [ 1100, 1101, 1105, 1102, 1104, 1103 ], - // Bladed - [ 25, 21, 20, 22, 23, 26, 24, 27 ], - // Axes - [ 29, 28, 32, 30, 33, 31, 34 ], - // Polearms - [ 38, 39, 35, 36, 37 ], - // Bashing - [ 44, 40, 41, 42, 43 ] - ] -]; - -// BlacksmithMap[buttonID] = { -// dictID: , -// page: , -// timerID: , -// oreMake: [ makeIDForIron, makeIDForDullCopper, ... ], // index is oreID (0..8) -// // Optional later: -// // recipeID: , -// // minEra: "lbr" / "aos" / "ml" / "sa" / "hs" / "tol", -// // maxEra: ... -// }; - -const BlacksmithMap = {}; - -(function initBlacksmithMap() +const craftMapRegistryID = 4038; +var BlacksmithMap = {}; + +function LoadBlacksmithMap() { - // oreIndex: 0 = iron, 1 = dull copper, ... 8 = valorite - for( var oreIndex = 0; oreIndex < craftItems.length; oreIndex++ ) + BlacksmithMap = {}; + + var blacksmithEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "blacksmithing" ); + + if( !blacksmithEntries || !IsBlacksmithArrayValue( blacksmithEntries ) ) { - var oreRows = craftItems[oreIndex]; + Console.Warning( "Blacksmithing: Unable to load blacksmithing craft map data." ); + return false; + } - // pageIdx: 0..6 => pages 1..7 - for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) - { - var dictList = myPage[pageIdx]; - var makeList = oreRows[pageIdx]; + for( var i = 0; i < blacksmithEntries.length; i++ ) + { + var entry = blacksmithEntries[i]; - for( var i = 0; i < dictList.length && i < makeList.length; i++ ) - { - // Old script uses: - // page 1 => 100..112 - // page 2 => 200..204 - // page 3 => 300..305 - // etc. - var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; - var dictID = dictList[i]; - var makeID = makeList[i]; - - if( !BlacksmithMap[buttonID] ) - { - BlacksmithMap[buttonID] = { - dictID: dictID, - page: pageIdx + 1, - timerID: pageIdx + 1, - oreMake: [], - // recipeID: undefined, - // minEra: undefined, - // maxEra: undefined - skill: 7, // blacksmithing skill ID - harvest: [10015], // ingots dict - harvest2: [], // optional second resource - harvest3: [], // optional second resource - harvest4: [] // optional second resource - }; - } + if( !entry || typeof entry.buttonID == "undefined" ) + continue; - BlacksmithMap[buttonID].oreMake[oreIndex] = makeID; - } - } + if( entry.skill === undefined ) + entry.skill = 7; + + if( !entry.harvest ) + entry.harvest = [10015]; + + BlacksmithMap[entry.buttonID] = entry; } -})(); - -// 3) AFTER initBlacksmithMap, you can override entries: -// BlacksmithMap[400].customName = "Elven Broadsword"; -// BlacksmithMap[400].recipeID = 5101; // if you want it recipe-locked -// BlacksmithMap[400].minEra = "ml"; // if you want it ML and later only -BlacksmithMap[113].customName = "Dragon Sleeves"; -BlacksmithMap[113].useScales = true; -BlacksmithMap[114].customName = "Dragon Breast Plate"; -BlacksmithMap[114].useScales = true; -BlacksmithMap[115].customName = "Dragon Gloves"; -BlacksmithMap[115].useScales = true; -BlacksmithMap[116].customName = "Dragon Helmet"; -BlacksmithMap[116].useScales = true; -BlacksmithMap[117].customName = "Dragon leggings"; -BlacksmithMap[117].useScales = true; + + Console.Print( "Blacksmithing: Loaded " + blacksmithEntries.length + " craft map entries.\n" ); + return true; +} + +function IsBlacksmithArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} + +function GetBlacksmithResourceList( resourceSet ) +{ + return TriggerEvent( 4038, "GetCraftResourceList", resourceSet ); +} function PageX( socket, pUser, pageNum ) { if( !ValidateObject( pUser )) return; + if( !BlacksmithMap || Object.keys( BlacksmithMap ).length == 0 ) + { + if( !LoadBlacksmithMap() ) + { + socket.SysMessage( "Blacksmithing craft map failed to load." ); + return; + } + } + // Pages 1 - 7: normal crafting pages // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) @@ -548,122 +209,88 @@ function PageX( socket, pUser, pageNum ) function Page8( socket, pUser ) { - // Ingot choices page - var myGump = new Gump(); - pUser.SetTempTag( "page", 8 ); - - // Draw standard crafting frame (title, buttons, notices etc.) - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - - // Count ingots by hue - var iron = pUser.ResourceCount( 0x1BF2 ); - var dullcopper = pUser.ResourceCount( 0x1BF2, 0x0973 ); - var shadowiron = pUser.ResourceCount( 0x1BF2, 0x0966 ); - var copper = pUser.ResourceCount( 0x1BF2, 0x07dd ); - var bronze = pUser.ResourceCount( 0x1BF2, 0x06d6 ); - var gold = pUser.ResourceCount( 0x1BF2, 0x08a5 ); - var agapite = pUser.ResourceCount( 0x1BF2, 0x0979 ); - var verite = pUser.ResourceCount( 0x1BF2, 0x089f ); - var valorite = pUser.ResourceCount( 0x1BF2, 0x08ab ); - - var counts = [ iron, dullcopper, shadowiron, copper, bronze, gold, agapite, verite, valorite ]; - - var lines = []; - for( var i = 0; i < OreTypes.length; i++ ) - { - var oreInfo = OreTypes[i]; - var label = GetDictionaryEntry( oreInfo.nameDict, socket.language ); - lines.push( label + " (" + counts[i].toString() + ")" ); - } - - for( var j = 0; j < lines.length; j++ ) - { - var index = j % 10; - - if( index == 0 ) - { - if( j > 0 ) - { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( j / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE - } - - myGump.AddPage(( j / 10 ) + 1 ); - - if( j > 0 ) - { - myGump.AddButton( 220, 260, 4014, 4015, 0, j / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE - } - } - - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1000 + j ); - myGump.AddText( 255, 60 + ( index * 20 ), textHue, lines[j] ); - } - - myGump.Send( socket ); - myGump.Free(); + var oreResourceList = TriggerEvent( craftMapRegistryID, "GetCraftResourceList", "ore" ); + var oreItems = oreResourceList && oreResourceList.items ? oreResourceList.items : []; + + var myGump = new Gump(); + pUser.SetTempTag( "page", 8 ); + + TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); + + for( var i = 0; i < oreItems.length; i++ ) + { + var oreInfo = oreItems[i]; + var index = i % 10; + + if( index == 0 ) + { + if( i > 0 ) + { + myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); + myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + myGump.AddPage(( i / 10 ) + 1 ); + + if( i > 0 ) + { + myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); + myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + } + + var count = pUser.ResourceCount( oreInfo.itemID, oreInfo.hue || 0 ); + var label = GetDictionaryEntry( oreInfo.dictID, socket.language ); + + myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1000 + i ); + myGump.AddText( 255, 60 + ( index * 20 ), textHue, label + " (" + count.toString() + ")" ); + } + + myGump.Send( socket ); + myGump.Free(); } function Page30( socket, pUser ) { - var myGump = new Gump(); - pUser.SetTempTag( "page", 30 ); // page index for scales (use any unused index) - - // Base crafting frame (same as other pages) - TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); - - // Count scales in backpack by hue (update IDs/hues as needed) - // If all scales share the same item ID but different hues, adjust this. - var counts = []; - - for( var i = 0; i < ScaleTypes.length; i++ ) - { - var scaleInfo = ScaleTypes[i]; - - // Example: if all scales share a single ID (replace 0x26B4 with your scale item ID) - // counts[i] = pUser.ResourceCount( 0x26B4, scaleInfo.hue ); - - // If you have different IDs per scale type, change the above line as needed. - counts[i] = pUser.ResourceCount( 0x26b4, scaleInfo.hue );; // placeholder so script parses; you’ll replace with real logic - } - - var lines = []; - for( var j = 0; j < ScaleTypes.length; j++ ) - { - var sInfo = ScaleTypes[j]; - var label = GetDictionaryEntry( sInfo.nameDict, socket.language ); - lines.push( label + " (" + counts[j].toString() + ")" ); - } - - for( var k = 0; k < lines.length; k++ ) - { - var index = k % 10; - - if( index == 0 ) - { - if( k > 0 ) - { - myGump.AddButton( 370, 260, 4005, 4007, 0, ( k / 10 ) + 1, 0 ); - myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); // NEXT PAGE - } - - myGump.AddPage(( k / 10 ) + 1 ); - - if( k > 0 ) - { - myGump.AddButton( 220, 260, 4014, 4015, 0, k / 10, 0 ); - myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); // PREV PAGE - } - } - - // Use a separate button range from ores to avoid conflicts: 1100+ - myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1100 + k ); - myGump.AddText( 255, 60 + ( index * 20 ), textHue, lines[k] ); - } - - myGump.Send( socket ); - myGump.Free(); + var scaleResourceList = TriggerEvent( craftMapRegistryID, "GetCraftResourceList", "dragonScales" ); + var scaleItems = scaleResourceList && scaleResourceList.items ? scaleResourceList.items : []; + + var myGump = new Gump(); + pUser.SetTempTag( "page", 30 ); + + TriggerEvent( craftGumpID, "CraftingGumpMenu", myGump, socket ); + + for( var i = 0; i < scaleItems.length; i++ ) + { + var scaleInfo = scaleItems[i]; + var index = i % 10; + + if( index == 0 ) + { + if( i > 0 ) + { + myGump.AddButton( 370, 260, 4005, 4007, 0, ( i / 10 ) + 1, 0 ); + myGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + myGump.AddPage(( i / 10 ) + 1 ); + + if( i > 0 ) + { + myGump.AddButton( 220, 260, 4014, 4015, 0, i / 10, 0 ); + myGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + } + + var count = pUser.ResourceCount( scaleInfo.itemID, scaleInfo.hue || 0 ); + var label = GetDictionaryEntry( scaleInfo.dictID, socket.language ); + + myGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, 1100 + i ); + myGump.AddText( 255, 60 + ( index * 20 ), textHue, label + " (" + count.toString() + ")" ); + } + + myGump.Send( socket ); + myGump.Free(); } function FindNearbyAnvils( pUser, trgItem, pSock ) @@ -1149,62 +776,65 @@ function onGumpPress( pSock, pButton, gumpData ) return; } - // Handle ore selection buttons (1000–1008) BEFORE the main switch - if( pButton >= 1000 && pButton <= 1008 ) + // Handle ore selection buttons + if( pButton >= 1000 && pButton < 1100 ) { - var index = pButton - 1000; // 0..8 - var oreInfo = OreTypes[index]; - var miningSkill = pUser.skills.mining; // you are already using skills.mining in smelting logic + var oreIndex = pButton - 1000; + + var oreResourceList = TriggerEvent( craftMapRegistryID, "GetCraftResourceList", "ore" ); + var oreItems = oreResourceList && oreResourceList.items ? oreResourceList.items : []; + + var oreInfo = oreItems[oreIndex]; - if( miningSkill < oreInfo.minMining ) + if( !oreInfo) + return; + + if( pUser.skills.mining < ( oreInfo.minSkill || 0 )) { - // Not enough mining skill for this ore pSock.CloseGump( gumpID, 0 ); pUser.SetTempTag( "prevActionResult", "FAILED" ); - // Re-open ore page after a short delay pUser.StartTimer( ingotDelay, 8, true ); return; } - // Set selected ore and hue - pUser.SetTempTag( "ORE", index ); - pUser.SetTempTag( "resourceHue", oreInfo.hue ); + pUser.SetTempTag( "ORE", oreIndex ); + pUser.SetTempTag( "resourceHue", oreInfo.hue || 0 ); pUser.SetTempTag( "MAKELAST", null ); pUser.SetTempTag( "prevActionResult", null ); - // Re-open ore page so they see the new counts/selection - pSock.CloseGump( gumpID, 0 ); + pSock.CloseGump( gumpID, 0); pUser.StartTimer( ingotDelay, 8, true ); return; } // Handle scale selection buttons (1100–11XX) BEFORE the main switch - if (pButton >= 1100 && pButton < 1100 + ScaleTypes.length) + if( pButton >= 1100 && pButton < 1200 ) { - var sIndex = pButton - 1100; // 0..ScaleTypes.length-1 - var sInfo = ScaleTypes[sIndex]; - var smithSkill = pUser.skills.blacksmithing; // or mining / whatever you want to gate on + var scaleIndex = pButton - 1100; - if( smithSkill < sInfo.minSkill ) + var scaleResourceList = TriggerEvent( craftMapRegistryID, "GetCraftResourceList", "dragonScales" ); + var scaleItems = scaleResourceList && scaleResourceList.items ? scaleResourceList.items : []; + + var scaleInfo = scaleItems[scaleIndex]; + + if( !scaleInfo ) + return; + + if( pUser.skills.blacksmithing < ( scaleInfo.minSkill || 0 )) { - // Not enough skill for this scale type pSock.CloseGump( gumpID, 0 ); pUser.SetTempTag( "prevActionResult", "FAILED" ); - pUser.StartTimer( ingotDelay, 30, true ); // reopen scale page after delay + pUser.StartTimer( ingotDelay, 30, true ); return; } - // Store selection - pUser.SetTempTag( "Scale", sIndex ); - pUser.SetTempTag( "resourceHue", sInfo.hue ); + pUser.SetTempTag( "Scale", scaleIndex ); + pUser.SetTempTag( "resourceHue", scaleInfo.hue || 0 ); pUser.SetTempTag( "MAKELAST", null ); pUser.SetTempTag( "prevActionResult", null ); - // If you want a separate "make last" for scales, you could also SetTempTag("SCALEMAKELAST", ...) - // For now we just store the current selection. - pSock.CloseGump( gumpID, 0 ); - pUser.StartTimer( ingotDelay, 30, true ); // reopen PageScales to show updated selection/notice + pUser.StartTimer( ingotDelay, 30, true ); return; } @@ -1277,17 +907,24 @@ function onGumpPress( pSock, pButton, gumpData ) pUser.SetTempTag( "Harvest4Name", null ); // If this entry uses dragon scales, override resource label - if( entry.useScales ) - { - // Use currently selected scale type (from Page30 selection) - var sIndex = pUser.GetTempTag( "Scale" ); - if( sIndex < 0 || sIndex >= ScaleTypes.length ) - sIndex = 0; - - var sInfo = ScaleTypes[sIndex]; - var sLabel = GetDictionaryEntry( sInfo.nameDict, pSock.language ); - pUser.SetTempTag( "HarvestName", sLabel ); - } + if( entry.useScales ) + { + var scaleResourceList = TriggerEvent( craftMapRegistryID, "GetCraftResourceList", "dragonScales" ); + var scaleItems = scaleResourceList && scaleResourceList.items ? scaleResourceList.items : []; + + var sIndex = pUser.GetTempTag( "Scale" ); + + if( sIndex < 0 || sIndex >= scaleItems.length ) + sIndex = 0; + + var sInfo = scaleItems[sIndex]; + + if( sInfo ) + { + var sLabel = GetDictionaryEntry( sInfo.dictID, pSock.language ); + pUser.SetTempTag( "HarvestName", sLabel ); + } + } else { // Normal ingot-based items: use the harvest setup as before @@ -1346,7 +983,7 @@ function onGumpPress( pSock, pButton, gumpData ) var resourceHue = pUser.GetTempTag( "resourceHue" ); // Ensure oreID within range - if( oreID < 0 || oreID >= craftItems.length ) + if( oreID < 0 || oreID >= entry2.oreMake.length ) oreID = 0; // Era / recipe gating diff --git a/data/js/skill/craft/carpentry.js b/data/js/skill/craft/carpentry.js index 49eaeef76..5bd8822b6 100644 --- a/data/js/skill/craft/carpentry.js +++ b/data/js/skill/craft/carpentry.js @@ -12,173 +12,60 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); const carpentrySkillID = 11; // Carpentry skill ID const harvestDict = 10014; // Dictionary entry for "wood" (boards/logs) -//====================================================================================== -// Data tables -//====================================================================================== +const craftMapRegistryID = 4038; +var CarpentryMap = {}; -const myPage = [ - - // Page 1 - Other - [10611, 10612, 10613, 10614, 10615, 10616, 10617, 10618, 10619, 10620, 10688], - - // Page 2 - Furniture - [10621, 10622, 10623, 10624, 10625, 10626, 10627, 10628, 10629, 10630, 10631, 10632, 10633], - - // Page 3 - Containers - [10634, 10635, 10636, 10637, 10638, 10639, 10640, 10641, 10642], - - // Page 4 - Weapons - [10643, 10644, 10645, 10646, 10647], - - // Page 5 - Armor - [10648], - - // Page 6 - Instruments - [10649, 10650, 10651, 10652, 10653, 10654], - - // Page 7 - Misc. Add-Ons - [10655, 10656, 10657, 10658, 10659, 10660, 10661, 10662, 10663, 10664, 10665], - - // Page 8 - Tailoring and Cooking - [10666, 10667, 10668, 10669, 10670, 10671, 10672, 10673, 10674, 10675, 10676, 10677], - - // Page 9 - Anvil and Forges - [10678, 10679, 10680, 10681, 10682], - - // Page 10 - Training - [10683, 10684, 10685, 10686] -]; - -const craftItems = [ - // Page 1 (button 100..110) - [ 73, 74, 89, 90, 91, 92, 76, 77, 78, 79, 72 ], - - // Page 2 (200..212) - [ 50, 51, 52, 53, 57, 58, 54, 55, 56, 59, 60, 61, 62 ], - - // Page 3 (300..308) - [ 63, 64, 65, 67, 68, 69, 70, 71, 66 ], - - // Page 4 (400..404) - [ 80, 81, 82, 123, 124 ], - - // Page 5 (500) - [ 75 ], - - // Page 6 (600..605) - [ 83, 84, 85, 86, 87, 88 ], +function LoadCarpentryMap() +{ + CarpentryMap = {}; - // Page 7 (700..710) - [ 93, 93, 94, 93, 96, 95, 97, 98, 99, 100, 101 ], + var carpentryEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "carpentry" ); - // Page 8 (800..812) - [ 115, 116, 107, 108, 109, 110, 117, 118, 119, 120, 121, 122 ], + if( !carpentryEntries || !IsCarpentryArrayValue( carpentryEntries ) ) + { + Console.Warning( "Carpentry: Unable to load carpentry craft map data." ); + return false; + } - // Page 9 (900..904) - [ 102, 103, 104, 105, 106 ], + for( var i = 0; i < carpentryEntries.length; i++ ) + { + var entry = carpentryEntries[i]; - // Page 10 (1000..1003) - [ 111, 112, 113, 114 ] -]; + if( !entry || typeof entry.buttonID == "undefined" ) + continue; -// Map: buttonID carpentry entry -// buttonID: 100..110, 200..212, ... 1000..1003 -// CarpentryMap[buttonID] = { -// dictID: number, -// page: number, -// timerID: number, -// makeID: number, -// customName?: string, -// recipeID?: number, -// minEra?: string, -// maxEra?: string, -// skill: number, -// harvest: number[] // dictionary IDs for resources; labels can be overridden in ItemDetailGump -// }; -const CarpentryMap = {}; + if( entry.skill === undefined ) + entry.skill = carpentrySkillID; -(function initCarpentryMap() -{ - for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) - { - var dictList = myPage[pageIdx]; - var makeList = craftItems[pageIdx]; + if( !entry.harvest ) + entry.harvest = [ harvestDict ]; - for( var i = 0; i < dictList.length && i < makeList.length; i++ ) - { - // Button layout: - // page 1 => 100..110 - // page 2 => 200..212 - // page 3 => 300..308 - // ... - var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; - var dictID = dictList[i]; - var makeID = makeList[i]; - - CarpentryMap[buttonID] = { - dictID: dictID, - page: pageIdx + 1, - timerID: pageIdx + 1, - makeID: makeID, - // recipeID: undefined, - // minEra: undefined, - // maxEra: undefined - skill: carpentrySkillID, - harvest: [ harvestDict ] // default: wood - }; - } + CarpentryMap[entry.buttonID] = entry; } - // If you need per-entry overrides in future (recipes, extra resources, era gating), - // you can do: - // CarpentryMap[704].harvest = [ harvestDict, 11402 ]; // wood + cloth - // CarpentryMap[109].harvest = [ harvestDict ]; // Fishing Pole wood + cloth - // CarpentryMap[109].harvestNames = [ "", "Cloth" ]; // Fishing Pole wood + cloth - // CarpentryMap[308].harvest = [ 0 ]; // open keg Barrel Staves Barrel Hoops Barrel Lid - // CarpentryMap[308].harvestNames = [ "Barrel Staves", "Barrel Hoops", "Barrel Lid" ]; // open keg Barrel Staves Barrel Hoops Barrel Lid - // CarpentryMap[709].minEra = "ml"; -})(); - -CarpentryMap[109].harvest = [ harvestDict, 10016 ]; // Fishing Pole wood + cloth -CarpentryMap[308].harvest = [ 10611, 10612, 11860 ]; // open keg Barrel Staves Barrel Hoops Barrel Lid -CarpentryMap[600].harvest = [ harvestDict, 10016 ]; // lap harp wood + cloth -CarpentryMap[601].harvest = [ harvestDict, 10016 ]; // Standing Harp wood + cloth -CarpentryMap[602].harvest = [ harvestDict, 10016 ]; // Drum wood + cloth -CarpentryMap[603].harvest = [ harvestDict, 10016 ]; // Lute wood + cloth -CarpentryMap[604].harvest = [ harvestDict, 10016 ]; // Tambourine wood + cloth -CarpentryMap[605].harvest = [ harvestDict, 10016 ]; // Tambourine wood + cloth -CarpentryMap[700].harvest = [ harvestDict, 10016 ]; // Small Bed (S) wood + cloth -CarpentryMap[701].harvest = [ harvestDict, 10016 ]; // Small Bed (E) wood + cloth -CarpentryMap[702].harvest = [ harvestDict, 10016 ]; // Large Bed (S) wood + cloth -CarpentryMap[703].harvest = [ harvestDict, 10016 ]; // Large Bed (E) wood + cloth -CarpentryMap[709].harvest = [ harvestDict, 10015 ]; // Pentagram wood + ingots -CarpentryMap[710].harvest = [ harvestDict, 10015 ]; // Abbatoir wood + ingots -CarpentryMap[800].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth -CarpentryMap[801].harvest = [ harvestDict, 10016 ]; // Dressform wood + cloth -CarpentryMap[802].harvest = [ harvestDict, 10016 ]; // Spin Wheel (E) wood + cloth -CarpentryMap[803].harvest = [ harvestDict, 10016 ]; // Spin Wheel (S) wood + cloth -CarpentryMap[804].harvest = [ harvestDict, 10016 ]; // Loom (E) wood + cloth -CarpentryMap[805].harvest = [ harvestDict, 10016 ]; // Loom (S) wood + cloth -CarpentryMap[806].harvest = [ harvestDict, 10015 ]; // Stone Oven (E) wood + ingots -CarpentryMap[807].harvest = [ harvestDict, 10015 ]; // Stone Oven (S) wood + ingots -CarpentryMap[808].harvest = [ harvestDict, 10015 ]; // Flour Mill (E) wood + ingots -CarpentryMap[809].harvest = [ harvestDict, 10015 ]; // Flour Mill (S) wood + ingots -CarpentryMap[900].harvest = [ harvestDict, 10015 ]; // Small Forge wood + ingots -CarpentryMap[901].harvest = [ harvestDict, 10015 ]; // Large Forge (E) wood + ingots -CarpentryMap[902].harvest = [ harvestDict, 10015 ]; // Large Forge (S) wood + ingots -CarpentryMap[903].harvest = [ harvestDict, 10015 ]; // Anvil (E) wood + ingots -CarpentryMap[904].harvest = [ harvestDict, 10015 ]; // Anvil (S) wood + ingots -CarpentryMap[1000].harvest = [ harvestDict, 10016 ]; // Dummy (E) wood + cloth -CarpentryMap[1001].harvest = [ harvestDict, 10016 ]; // Dummy (S) wood + cloth -CarpentryMap[1002].harvest = [ harvestDict, 10016 ]; // Pickpocket (E) wood + cloth -CarpentryMap[1003].harvest = [ harvestDict, 10016 ]; // Pickpocket (S) wood + cloth + Console.Print( "Carpentry: Loaded " + carpentryEntries.length + " craft map entries.\n" ); + return true; +} +function IsCarpentryArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} function PageX( socket, pUser, pageNum ) { if( !socket || !ValidateObject( pUser )) return; + if( !CarpentryMap || Object.keys( CarpentryMap ).length == 0 ) + { + if( !LoadCarpentryMap() ) + { + socket.SysMessage( "Carpentry craft map failed to load." ); + return; + } + } + var pageItems = []; if( pageNum == 999 ) diff --git a/data/js/skill/craft/cartography.js b/data/js/skill/craft/cartography.js index 0a92dbd90..3f0bbeebf 100644 --- a/data/js/skill/craft/cartography.js +++ b/data/js/skill/craft/cartography.js @@ -10,51 +10,42 @@ const displayUnlearnedRecipes = true; // For future recipe use const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const cartographySkillID = 12; // Skill index for "cartography" in ItemDetailGump -////////////////////////////////////////////////////////////////////////////////////////// -// CartographyMap -// Keyed by makeID (create entry ID). -// Each entry: -// dictID - dictionary entry for row text (13100..13103) -// page - main category page (1..N) -// timerID - which page timer should reopen -// skill - skill used (default: cartographySkillID) -// recipeID? - optional recipe ID -// minEra/maxEra? - optional era gating -// harvest?[] - optional material dictionary IDs -// harvestNames?[] - optional custom material names -// -// NOTE: For the World Map row, we use base makeID 2003. -// At craft time, we still adjust to 2003..2007 depending on worldnumber, -// just like the original script did. -// -////////////////////////////////////////////////////////////////////////////////////////// - -const CartographyMap = { - // Page 1 - Maps - 2000: { dictID: 13100, page: 1, timerID: 1, harvest: [ 13004 ] }, // Local Map - 2001: { dictID: 13101, page: 1, timerID: 1, harvest: [ 13004 ] }, // City Map - 2002: { dictID: 13102, page: 1, timerID: 1, harvest: [ 13004 ] }, // Sea Chart - 2003: { dictID: 13103, page: 1, timerID: 1, harvest: [ 13004 ] } // World Map (base; world-specific in onGumpPress) -}; - -// Fill in defaults (skill, etc) -(function initCartographyMap() +const craftMapRegistryID = 4038; +var CartographyMap = {}; + +function LoadCartographyMap() { - for( var key in CartographyMap ) + CartographyMap = {}; + + var cartographyEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "cartography" ); + + if( !cartographyEntries || !IsCartographyArrayValue( cartographyEntries ) ) { - if( !CartographyMap.hasOwnProperty( key )) - continue; + Console.Warning( "Cartography: Unable to load cartography craft map data." ); + return false; + } - var entry = CartographyMap[key]; + for( var i = 0; i < cartographyEntries.length; i++ ) + { + var entry = cartographyEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) + continue; if( entry.skill === undefined ) entry.skill = cartographySkillID; - // If you later want harvest info for detail gump, you can do: - // CartographyMap[2000].harvest = [ ]; - // CartographyMap[2000].harvestNames = [ "Blank scroll" ]; + CartographyMap[entry.makeID] = entry; } -})(); + + Console.Print( "Cartography: Loaded " + cartographyEntries.length + " craft map entries.\n" ); + return true; +} + +function IsCartographyArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} /** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) @@ -62,6 +53,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !CartographyMap || Object.keys( CartographyMap ).length == 0 ) + { + if( !LoadCartographyMap() ) + { + socket.SysMessage( "Cartography craft map failed to load." ); + return; + } + } + var pageItems; // Special Last Ten page (if you ever want it for Cartography) diff --git a/data/js/skill/craft/cooking.js b/data/js/skill/craft/cooking.js index 236b78826..71cba8692 100644 --- a/data/js/skill/craft/cooking.js +++ b/data/js/skill/craft/cooking.js @@ -49,80 +49,44 @@ function FindNearbyHeatSources( pUser, trgItem, pSock ) return ( heatSources.indexOf( trgItem.id ) != -1 ); } -////////////////////////////////////////////////////////////////////////////////////////// -// CookingMap -// Keyed by makeID (create entry ID). -// Each entry: -// dictID - dictionary entry for the row text (11606..11635) -// page - main category page (1..4) -// timerID - which page timer should reopen -// skill - skill used (default: cookingSkillID) -// recipeID? - optional recipe ID (for recipe system) -// minEra/maxEra? - optional era gating -// harvest?[] - optional dictIDs for MATERIALS list in ItemDetailGump -// harvestNames?[] - optional custom material names (works with your new custom-name system) -// -////////////////////////////////////////////////////////////////////////////////////////// - -const CookingMap = { - // Page 1 - Ingredients - 1500: { dictID: 11606, page: 1, timerID: 1, harvest: [ 11636 ] }, // Sack of Flour - 1501: { dictID: 11607, page: 1, timerID: 1, harvest: [ 11637, 11638 ] }, // Dough - 1502: { dictID: 11608, page: 1, timerID: 1, harvest: [ 11607, 11639 ] }, // Sweet Dough - 1503: { dictID: 11609, page: 1, timerID: 1, harvest: [ 11637, 11608 ] }, // Cake Mix - 1504: { dictID: 11610, page: 1, timerID: 1, harvest: [ 11639, 11608 ] }, // Cookie Mix - - // Page 2 - Preparations - 1550: { dictID: 11611, page: 2, timerID: 2, harvest: [ 11607, 11640 ] }, // Unbaked Quiche - 1551: { dictID: 11612, page: 2, timerID: 2, harvest: [ 11607, 11641 ] }, // Unbaked Meat Pie - 1552: { dictID: 11613, page: 2, timerID: 2, harvest: [ 11607, 11642 ] }, // Uncooked Sausage Pizza - 1553: { dictID: 11614, page: 2, timerID: 2, harvest: [ 11607, 11643 ] }, // Uncooked Cheese Pizza - 1554: { dictID: 11615, page: 2, timerID: 2, harvest: [ 11607, 11644 ] }, // Unbaked Fruit Pie - 1555: { dictID: 11616, page: 2, timerID: 2, harvest: [ 11607, 11645 ] }, // Unbaked Peach Cobbler - 1556: { dictID: 11617, page: 2, timerID: 2, harvest: [ 11607, 11646 ] }, // Unbaked Apple Pie - 1557: { dictID: 11618, page: 2, timerID: 2, harvest: [ 11607, 11647 ] }, // Unbaked Pumpkin Pie - - // Page 3 - Baking - 1600: { dictID: 11619, page: 3, timerID: 3, harvest: [ 11607 ] }, // Bread Loaf - 1601: { dictID: 11620, page: 3, timerID: 3, harvest: [ 11610 ] }, // Pan of Cookies - 1602: { dictID: 11621, page: 3, timerID: 3, harvest: [ 11609 ] }, // Cake - 1603: { dictID: 11657, page: 3, timerID: 3, harvest: [ 11608 ] }, // Muffins - 1604: { dictID: 11622, page: 3, timerID: 3, harvest: [ 11611 ] }, // Baked Quiche - 1605: { dictID: 11623, page: 3, timerID: 3, harvest: [ 11612 ] }, // Baked Meat Pie - 1606: { dictID: 11624, page: 3, timerID: 3, harvest: [ 11613 ] }, // Sausage Pizza - 1607: { dictID: 11625, page: 3, timerID: 3, harvest: [ 11614 ] }, // Cheese Pizza - 1608: { dictID: 11626, page: 3, timerID: 3, harvest: [ 11615 ] }, // Baked Fruit Pie - 1609: { dictID: 11627, page: 3, timerID: 3, harvest: [ 11616 ] }, // Baked Peach Cobbler - 1610: { dictID: 11628, page: 3, timerID: 3, harvest: [ 11617 ] }, // Baked Apple Pie - 1611: { dictID: 11629, page: 3, timerID: 3, harvest: [ 11618 ] }, // Baked Pumpkin Pie - - // Page 4 - Barbecue - 1650: { dictID: 11630, page: 4, timerID: 4, harvest: [ 11648 ] }, // Cooked Bird - 1651: { dictID: 11631, page: 4, timerID: 4, harvest: [ 11649 ] }, // Chicken Leg - 1652: { dictID: 11632, page: 4, timerID: 4, harvest: [ 11650 ] }, // Fish Steak - 1653: { dictID: 11633, page: 4, timerID: 4, harvest: [ 11651 ] }, // Fried Eggs - 1654: { dictID: 11634, page: 4, timerID: 4, harvest: [ 11652 ] }, // Leg of Lamb - 1655: { dictID: 11635, page: 4, timerID: 4, harvest: [ 11653 ] } // Cut of Ribs -}; - -// Fill in defaults (skill, etc) -(function initCookingMap() +const craftMapRegistryID = 4038; +var CookingMap = {}; + +/** @type { () => boolean } */ +function LoadCookingMap() { - for( var key in CookingMap ) + CookingMap = {}; + + var cookingEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "cooking" ); + + if( !cookingEntries || !IsCookingArrayValue( cookingEntries ) ) { - if( !CookingMap.hasOwnProperty( key )) - continue; + Console.Warning( "Cooking: Unable to load cooking craft map data." ); + return false; + } - var entry = CookingMap[key]; + for( var i = 0; i < cookingEntries.length; i++ ) + { + var entry = cookingEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) + continue; if( entry.skill === undefined ) entry.skill = cookingSkillID; - // In future you can add: - // entry.harvest = [ dictID_for_flour, dictID_for_water ]; - // entry.harvestNames = [ "Flour", "Water" ]; + CookingMap[entry.makeID] = entry; } -})(); + + Console.Print( "Cooking: Loaded " + cookingEntries.length + " craft map entries.\n" ); + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsCookingArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} /** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) @@ -130,6 +94,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !CookingMap || Object.keys( CookingMap ).length == 0 ) + { + if( !LoadCookingMap() ) + { + socket.SysMessage( "Cooking craft map failed to load." ); + return; + } + } + var pageItems; // No "Last Ten" page here (but we keep the infrastructure if you want it later) diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index f65735918..9674ba742 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -25,48 +25,13 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); function CraftingGumpMenu( myGump, socket ) { var pUser = socket.currentChar; - - // Get player's resource counts - var iron = pUser.ResourceCount( 0x1BF2 ); - var dullcopper = pUser.ResourceCount( 0x1BF2, 0x0973 ); - var shadowiron = pUser.ResourceCount( 0x1BF2, 0x0966 ); - var copper = pUser.ResourceCount( 0x1BF2, 0x07dd ); - var bronze = pUser.ResourceCount( 0x1BF2, 0x06d6 ); - var gold = pUser.ResourceCount( 0x1BF2, 0x08a5 ); - var agapite = pUser.ResourceCount( 0x1BF2, 0x0979 ); - var verite = pUser.ResourceCount( 0x1BF2, 0x089f ); - var valorite = pUser.ResourceCount( 0x1BF2, 0x08ab ); - var logs = pUser.ResourceCount( 0x1BE0 ); - var boards = pUser.ResourceCount( 0x1bd7 ); - var leather = pUser.ResourceCount( 0x1067 ); - var leather1 = pUser.ResourceCount( 0x1068 ); - var leather2 = pUser.ResourceCount( 0x1081 ); - var leather3 = pUser.ResourceCount( 0x1082 ); - var hides = pUser.ResourceCount( 0x1078 ); - var hides1 = pUser.ResourceCount( 0x1079 ); - - var granite = pUser.ResourceCount( 0x1779 ); - var dullcoppergranite = pUser.ResourceCount( 0x1779, 0x0973 ); - var shadowirongranite = pUser.ResourceCount( 0x1779, 0x0966 ); - var coppergranite = pUser.ResourceCount( 0x1779, 0x07dd ); - var bronzegranite = pUser.ResourceCount( 0x1779, 0x06d6 ); - var goldgranite = pUser.ResourceCount( 0x1779, 0x08a5 ); - var agapitegranite = pUser.ResourceCount( 0x1779, 0x0979 ); - var veritegranite = pUser.ResourceCount( 0x1779, 0x089f ); - var valoritegranite = pUser.ResourceCount( 0x1779, 0x08ab ); - - var redScales = pUser.ResourceCount( 0x26b4, 0x0663 ); // red scales - var yellowScales = pUser.ResourceCount( 0x26b4, 0x084d); // yellow scales - var blackScales = pUser.ResourceCount( 0x26b4, 0x0455); // Black scales - var greenScales = pUser.ResourceCount( 0x26b4, 0x0851); // Green scales - var whiteScales = pUser.ResourceCount( 0x26b4, 0x02c2 ); // White scales - var blueScales = pUser.ResourceCount( 0x26b4, 0x0006); // Blue scales - var resourcename = 10291; var resourcename2 = 10291; - var resource = iron; - var resource2 = whiteScales; - var groupList; + var resource = 0; + var resource2 = 0; + var resourceSelection = null; + var resourceSelection2 = null; + var grouplist = []; var gumpMenuName = ""; var repair = 51; var craftingSkillUsed = pUser.GetTempTag( "CRAFT" ); @@ -74,10 +39,11 @@ function CraftingGumpMenu( myGump, socket ) switch( craftingSkillUsed ) { case 1: // Carpentry - grouplist = [10601, 10602, 10603, 10604, 10605, 10606, 10607, 10608, 10609, 10610]; //CATEGORIES - resourcename = 10687; - resource = ( logs + boards ); - gumpMenuName = 10600;//Carpentry + grouplist = [10601, 10602, 10603, 10604, 10605, 10606, 10607, 10608, 10609, 10610]; + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "wood", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 10687; + resource = resourceSelection ? resourceSelection.amount : 0; + gumpMenuName = 10600; repair = 51; break; case 2: // Alchemy @@ -85,96 +51,28 @@ function CraftingGumpMenu( myGump, socket ) gumpMenuName = 10901;//Alchemy Menu break; case 3: // Bowcraft/Fletching - grouplist = [11202, 11203, 11204]; //CATEGORIES - gumpMenuName = 11201;//Bowcraft Menu - resourcename = 10687; - resource = ( logs + boards ); - //repair = 51; + grouplist = [11202, 11203, 11204]; + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "wood", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 10687; + resource = resourceSelection ? resourceSelection.amount : 0; + gumpMenuName = 11201; break; case 4: // Tailoring - grouplist = [11404, 11405, 11406, 11407, 11408, 11410, 11411, 11412]; //CATEGORIES - gumpMenuName = 11401;//Tailoring Menu - resourcename = 11402; - resource = ( leather + leather1 + leather2 + leather3 + hides + hides1 ); - //repair = 51; + grouplist = [11404, 11405, 11406, 11407, 11408, 11410, 11411, 11412]; + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "tailoring", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 11402; + resource = resourceSelection ? resourceSelection.amount : 0; + gumpMenuName = 11401; break; case 5: // Blacksmithing - grouplist = [10279, 10280, 10281, 10282, 10283, 10284, 10285] //CATEGORIES - gumpMenuName = 10188;//Blacksmithing Menu - switch( pUser.GetTempTag( "ORE" )) - { - case 0: // Iron - resourcename = 10291; - resource = iron; - break; - case 1: // Dull Copper - resourcename = 10203; - resource = dullcopper; - break; - case 2: // Shadow Iron - resourcename = 10204; - resource = shadowiron; - break; - case 3: // Copper - resourcename = 10205; - resource = copper; - break; - case 4: // Bronze - resourcename = 10206; - resource = bronze; - break; - case 5: // Gold - resourcename = 10207; - resource = gold; - break; - case 6: // Agapite - resourcename = 10208; - resource = agapite; - break; - case 7: // Verite - resourcename = 10209; - resource = verite; - break; - case 8: // Valorite - resourcename = 10210; - resource = valorite; - break; - default: // Iron - resourcename = 10291; - resource = iron; - break; - } - switch( pUser.GetTempTag( "Scale" )) - { - case 0: - resourcename2 = 20299; - resource2 = redScales; - break; - case 1: - resourcename2 = 20300; - resource2 = yellowScales; - break; - case 2: - resourcename2 = 20301; - resource2 = blackScales; - break; - case 3: - resourcename2 = 20302; - resource2 = greenScales; - break; - case 4: - resourcename2 = 20303; - resource2 = whiteScales; - break; - case 5: - resourcename2 = 20304; - resource2 = blueScales; - break; - default: - resourcename2 = 20299; - resource2 = redScales; - break; - } + grouplist = [10279, 10280, 10281, 10282, 10283, 10284, 10285]; + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "ore", pUser ); + resourceSelection2 = TriggerEvent( 4038, "GetCraftResourceSelection", "dragonScales", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 10291; + resource = resourceSelection ? resourceSelection.amount : 0; + resourcename2 = resourceSelection2 ? resourceSelection2.dictID : 20299; + resource2 = resourceSelection2 ? resourceSelection2.amount : 0; + gumpMenuName = 10188; repair = 49; break; case 6: // Cooking @@ -183,6 +81,9 @@ function CraftingGumpMenu( myGump, socket ) break; case 7: // Tinkering grouplist = [11991, 11992, 11993, 11994, 11995, 11996, 11997, 11998, 11999]; // CATEGORIES + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "ore", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 10291; + resource = resourceSelection ? resourceSelection.amount : 0; gumpMenuName = 11990; // Tinkering Menu break; case 8: // Cartography @@ -199,51 +100,11 @@ function CraftingGumpMenu( myGump, socket ) gumpMenuName = 13501;//Cartography Menu break; case 10: // Masonry - grouplist = [14002, 14003, 14004, 14005, 14006, 14007, 14008, 14009, 14010] //CATEGORIES - gumpMenuName = 14001;//Masonry Menu - switch( pUser.GetTempTag( "Granite" )) - { - case 0: // Granite - resourcename = 14011; - resource = granite; - break; - case 1: // Dull Copper - resourcename = 14012; - resource = dullcoppergranite; - break; - case 2: // Shadow Iron - resourcename = 14013; - resource = shadowirongranite; - break; - case 3: // Copper - resourcename = 14014; - resource = coppergranite; - break; - case 4: // Bronze - resourcename = 14015; - resource = bronzegranite; - break; - case 5: // Gold - resourcename = 14016; - resource = goldgranite; - break; - case 6: // Agapite - resourcename = 14017; - resource = agapitegranite; - break; - case 7: // Verite - resourcename = 14018; - resource = veritegranite; - break; - case 8: // Valorite - resourcename = 14019; - resource = valoritegranite; - break; - default: // Iron - resourcename = 14011; - resource = irongranite; - break; - } + grouplist = [14002, 14003, 14004, 14005, 14006, 14007, 14008, 14009, 14010]; + resourceSelection = TriggerEvent( 4038, "GetCraftResourceSelection", "granite", pUser ); + resourcename = resourceSelection ? resourceSelection.dictID : 14011; + resource = resourceSelection ? resourceSelection.amount : 0; + gumpMenuName = 14001; repair = 49; break; } diff --git a/data/js/skill/craft/crafting_complete.js b/data/js/skill/craft/crafting_complete.js index 5f289098a..ce2051755 100644 --- a/data/js/skill/craft/crafting_complete.js +++ b/data/js/skill/craft/crafting_complete.js @@ -34,7 +34,16 @@ function onMakeItem( pSock, pCrafter, itemCrafted, craftEntryID ) // Apply special effect based on item crafted if( ValidateObject( itemCrafted )) { - // Jewelry, furniture, potions, maps + var craftMapEntry = TriggerEvent( 4038, "GetCraftMapEntryByMakeID", craftEntryID ); + if( craftMapEntry && craftMapEntry.craftComplete ) + { + if( HandleCraftCompleteType( pSock, pCrafter, itemCrafted, craftEntryID, craftMapEntry.craftComplete )) + { + return; + } + } + + // Fallback support for older entries not yet moved into JSON switch( craftEntryID ) { case 239: // necklace @@ -156,6 +165,92 @@ function onMakeItem( pSock, pCrafter, itemCrafted, craftEntryID ) ClearTagsAndScript( pCrafter ); } +/** @type { ( pSock: Socket, pCrafter: Character, itemCrafted: Item, craftEntryID: number, craftComplete: object ) => boolean } */ +function HandleCraftCompleteType( pSock, pCrafter, itemCrafted, craftEntryID, craftComplete ) +{ + if( !craftComplete || !craftComplete.type ) + { + return false; + } + + switch( craftComplete.type ) + { + case "gemJewelry": + ApplyGemJewelryName( pCrafter, itemCrafted ); + ClearTagsAndScript( pCrafter ); + return true; + + case "lockableContainer": + ApplyCraftedContainerLock( pSock, pCrafter, itemCrafted, craftEntryID ); + ClearTagsAndScript( pCrafter ); + return true; + + case "autoIdentifyPotion": + ApplyPotionAutoIdentify( itemCrafted ); + ClearTagsAndScript( pCrafter ); + return true; + + case "craftedMap": + CraftedMapCoords( pSock, itemCrafted ); + ClearTagsAndScript( pCrafter ); + return true; + } + + return false; +} + +/** @type { ( itemCrafted: Item ) => void } */ +function ApplyPotionAutoIdentify( itemCrafted ) +{ + itemCrafted.name = itemCrafted.name2; + itemCrafted.name2 = "#"; +} + +/** @type { ( pSock: Socket, pCrafter: Character, itemCrafted: Item, craftEntryID: number ) => void } */ +function ApplyCraftedContainerLock( pSock, pCrafter, itemCrafted, craftEntryID ) +{ + var createEntry = CreateEntries[craftEntryID]; + if( !createEntry ) + return; + + var skills = createEntry.skills; + if( !skills ) + return; + + for( var i = 0; i < skills.length; i++ ) + { + var skillReq = skills[i]; + var skillNumber = skillReq[0]; + var minSkill = skillReq[1]; + + if( skillNumber == 11 ) // Carpentry + { + if( pCrafter.skills.tinkering >= RandomNumber( minSkill / 2, 1000 )) + { + var newKey = CreateDFNItem( pSock, pCrafter, "0x100E", 1, "ITEM", true ); + newKey.container = itemCrafted; + newKey.PlaceInPack(); + newKey.name = "key for " + itemCrafted.name; + + newKey.more = itemCrafted.serial; + itemCrafted.more = itemCrafted.serial; + pSock.SysMessage( GetDictionaryEntry( 12009, pSock.language )); + } + break; + } + } +} + +/** @type { ( pCrafter: Character, itemCrafted: Item ) => void } */ +function ApplyGemJewelryName( pCrafter, itemCrafted ) +{ + var gemName = pCrafter.GetTempTag( "targetedSubResourceName" ); + if( gemName ) + { + itemCrafted.name = gemName + " " + itemCrafted.name; + } +} + function CraftedMapCoords( socket, mapItem ) { var pUser = socket.currentChar; @@ -194,7 +289,7 @@ function CraftedMapCoords( socket, mapItem ) mapItem.SetTag( "dimensions", size + "," + size ); // saves information for the map to be reopened mapItem.SetTag( "boundingbox", ( pUser.x - dist ) + "," + ( pUser.y - dist ) + "," + ( pUser.x + dist ) + "," + ( pUser.y + dist )); // saves information for the map to be reopened mapItem.SetTag( "Drawn", 1 ); - ClearTagsAndScript(pUser); + ClearTagsAndScript( pUser ); } function ApplyExceptionalArmorBonuses( pCrafter, itemCrafted, coreShardEraValue ) diff --git a/data/js/skill/craft/craftmap_registry.js b/data/js/skill/craft/craftmap_registry.js index 095740163..580f54860 100644 --- a/data/js/skill/craft/craftmap_registry.js +++ b/data/js/skill/craft/craftmap_registry.js @@ -4,6 +4,181 @@ var craftMapRegistry = {}; var craftMapRegistryLoaded = {}; var craftMapRegistryLoadError = {}; +var craftResourceMap = null; +var craftResourceMapLoaded = false; +var craftResourceMapLoadError = false; + +/** @type { () => object|null } */ +function LoadCraftResourceMap() +{ + if( craftResourceMapLoaded ) + return craftResourceMap; + + craftResourceMap = null; + craftResourceMapLoaded = false; + craftResourceMapLoadError = false; + + var resourceMapFile = new UOXCFile(); + resourceMapFile.Open( "resourcemap.json", "r", "crafting", true ); + + if( resourceMapFile == null || resourceMapFile.Length() < 0 ) + { + Console.Error( "CraftMap system: Unable to open js/jsdata/crafting/resourcemap.json" ); + craftResourceMapLoadError = true; + return null; + } + + var fileText = ""; + while( !resourceMapFile.EOF() ) + { + var rawLine = resourceMapFile.ReadUntil( "\n" ); + if( rawLine != null && typeof( rawLine ) != "undefined" ) + { + fileText += rawLine; + } + } + + resourceMapFile.Close(); + resourceMapFile.Free(); + + fileText = SanitizeCraftMapJsonText( fileText ); + + try + { + craftResourceMap = JSON.parse( fileText ); + } + catch( error ) + { + Console.Error( "CraftMap system: Failed to parse resourcemap.json: " + error ); + craftResourceMapLoadError = true; + return null; + } + + if( !IsCraftMapArrayValue( craftResourceMap ) ) + { + Console.Error( "CraftMap system: resourcemap.json must contain a JSON array." ); + craftResourceMapLoadError = true; + return null; + } + + craftResourceMapLoaded = true; + craftResourceMapLoadError = false; + + Console.Print( "CraftMap system: Loaded " + craftResourceMap.length + " resource maps.\n" ); + + return craftResourceMap; +} + +/** @type { ( resourceSet: string, pUser: Character ) => object|null } */ +function GetCraftResourceSelection( resourceSet, pUser ) +{ + var resourceMap = LoadCraftResourceMap(); + + if( !resourceMap ) + return null; + + for( var i = 0; i < resourceMap.length; i++ ) + { + var entry = resourceMap[i]; + + if( entry.resourceSet == resourceSet ) + return BuildCraftResourceSelection( entry, pUser ); + } + + return null; +} + +/** @type { ( resourceSet: string ) => object|null } */ +function GetCraftResourceList( resourceSet ) +{ + var resourceMap = LoadCraftResourceMap(); + + if( !resourceMap ) + return null; + + for( var i = 0; i < resourceMap.length; i++ ) + { + if( resourceMap[i].resourceSet == resourceSet ) + return resourceMap[i]; + } + + return null; +} + +/** @type { ( resourceEntry: object, pUser: Character ) => object|null } */ +function BuildCraftResourceSelection( resourceEntry, pUser ) +{ + if( !resourceEntry || !resourceEntry.items || !IsCraftMapArrayValue( resourceEntry.items ) ) + return null; + + var selectedIndex = resourceEntry.defaultIndex || 0; + + if( resourceEntry.tempTag ) + { + var tempIndex = pUser.GetTempTag( resourceEntry.tempTag ); + if( tempIndex || tempIndex == 0 ) + selectedIndex = tempIndex; + } + + var selectedResource = null; + + for( var i = 0; i < resourceEntry.items.length; i++ ) + { + var itemEntry = resourceEntry.items[i]; + + if( typeof itemEntry.index == "undefined" ) + { + selectedResource = itemEntry; + break; + } + + if( itemEntry.index == selectedIndex ) + { + selectedResource = itemEntry; + break; + } + } + + if( !selectedResource ) + selectedResource = resourceEntry.items[0]; + + return { + dictID: selectedResource.dictID || resourceEntry.dictID, + amount: CountCraftResourceAmount( selectedResource, pUser ), + resource: selectedResource + }; +} + +/** @type { ( resourceEntry: object, pUser: Character ) => number } */ +function CountCraftResourceAmount( resourceEntry, pUser ) +{ + if( !resourceEntry ) + return 0; + + if( resourceEntry.items && IsCraftMapArrayValue( resourceEntry.items ) ) + { + var totalAmount = 0; + + for( var i = 0; i < resourceEntry.items.length; i++ ) + { + totalAmount += CountCraftResourceAmount( resourceEntry.items[i], pUser ); + } + + return totalAmount; + } + + return pUser.ResourceCount( resourceEntry.itemID, resourceEntry.hue || 0 ); +} + +/** @type { () => void } */ +function ReloadCraftResourceMap() +{ + craftResourceMap = null; + craftResourceMapLoaded = false; + craftResourceMapLoadError = false; + + LoadCraftResourceMap(); +} /** @type { ( craftName: string ) => object|null } */ function CraftMapRegistry( craftName ) @@ -24,6 +199,70 @@ function CraftMapRegistry( craftName ) return craftMapRegistry[craftName] || null; } +/** @type { ( makeID: number ) => object|null } */ +function GetCraftMapEntryByMakeID( makeID ) +{ + makeID = parseInt( makeID, 10 ); + + if( isNaN( makeID )) + return null; + + var craftNames = [ + "alchemy", + "blacksmithing", + "carpentry", + "cartography", + "cooking", + "fletching", + "glassblowing", + "masonry", + "tailoring", + "tinkering" + ]; + + for( var i = 0; i < craftNames.length; i++ ) + { + var craftMap = CraftMapRegistry( craftNames[i] ); + + if( !craftMap ) + continue; + + for( var j = 0; j < craftMap.length; j++ ) + { + var entry = craftMap[j]; + + if( !entry ) + continue; + + if( entry.makeID == makeID ) + return entry; + + if( entry.oreMake && CraftMapArrayHasValue( entry.oreMake, makeID )) + return entry; + + if( entry.graniteMake && CraftMapArrayHasValue( entry.graniteMake, makeID )) + return entry; + } + } + + return null; +} + +/** @type { ( valueList: any, valueToFind: number ) => boolean } */ +function CraftMapArrayHasValue( valueList, valueToFind ) +{ + if( !IsCraftMapArrayValue( valueList )) + return false; + + for( var i = 0; i < valueList.length; i++ ) + { + if( parseInt( valueList[i], 10 ) == valueToFind ) + return true; + } + + return false; +} + /** @type { ( craftName: string ) => void } */ function ReloadCraftMapRegistry( craftName ) { @@ -136,9 +375,20 @@ function ValidateCraftMapEntry( entry, craftName, entryIndex ) return false; } - if( typeof entry.makeID == "undefined" || isNaN( parseInt( entry.makeID, 10 ) ) ) + var hasMakeID = (typeof entry.makeID != "undefined" && !isNaN(parseInt(entry.makeID, 10))); + var hasButtonID = (typeof entry.buttonID != "undefined" && !isNaN(parseInt(entry.buttonID, 10))); + var hasOreMake = (typeof entry.oreMake != "undefined" && IsCraftMapArrayValue(entry.oreMake)); + var hasGraniteMake = (typeof entry.graniteMake != "undefined" && IsCraftMapArrayValue(entry.graniteMake)); + + if (!hasMakeID && !hasButtonID) { - Console.Warning( "CraftMap system: Entry " + entryIndex + " in '" + craftName + "' is missing valid makeID." ); + Console.Warning("CraftMap system: Entry " + entryIndex + " in '" + craftName + "' is missing valid makeID or buttonID."); + return false; + } + + if (hasButtonID && !hasMakeID && !hasOreMake && !hasGraniteMake) + { + Console.Warning("CraftMap system: Entry " + entryIndex + " in '" + craftName + "' has buttonID but no makeID, oreMake, or graniteMake."); return false; } @@ -176,7 +426,12 @@ function ValidateCraftMapEntry( entry, craftName, entryIndex ) return false; } - entry.makeID = parseInt( entry.makeID, 10 ); + if( hasMakeID ) + entry.makeID = parseInt( entry.makeID, 10 ); + + if( hasButtonID ) + entry.buttonID = parseInt( entry.buttonID, 10 ); + entry.page = parseInt( entry.page, 10 ); entry.timerID = parseInt( entry.timerID, 10 ); diff --git a/data/js/skill/craft/fletching.js b/data/js/skill/craft/fletching.js index 51b73486c..c12724a50 100644 --- a/data/js/skill/craft/fletching.js +++ b/data/js/skill/craft/fletching.js @@ -10,63 +10,44 @@ const displayUnlearnedRecipes = true; // For future recipe use const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const fletchingSkillID = 8; // Index of "bowcraft" in ItemDetailGump skillNames[] -// o--------------------------------------------------------------------------o -// | FletchingMap | -// o--------------------------------------------------------------------------o -// | Keyed by makeID (create entry ID). | -// | Each entry: | -// | dictID - dictionary entry for row text (11205..11220) | -// | page - main category page (1..3) | -// | timerID - which page timer should reopen | -// | skill - skill used (default: fletchingSkillID) | -// | recipeID? - optional recipe ID | -// | minEra?, maxEra? - optional era gating | -// | harvest?[] - optional dictIDs for MATERIALS list | -// | harvestNames?[] - optional custom material names | -// o--------------------------------------------------------------------------o +const craftMapRegistryID = 4038; +var FletchingMap = {}; -const FletchingMap = { - // Page 1 - Materials - 190: { dictID: 11205, page: 1, timerID: 1, harvest: [ 10014 ] }, // Kindling - 194: { dictID: 11206, page: 1, timerID: 1, harvest: [ 10014 ] }, // Shaft - 195: { dictID: 11207, page: 1, timerID: 1, harvest: [ 10014 ] }, // Five Shafts - 196: { dictID: 11208, page: 1, timerID: 1, harvest: [ 10014 ] }, // Twenty Shafts - 197: { dictID: 11209, page: 1, timerID: 1, harvest: [ 10014 ] }, // Fifty Shafts - - // Page 2 - Ammunition - 198: { dictID: 11210, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Arrow - 199: { dictID: 11211, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Five Arrows - 200: { dictID: 11212, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Twenty Arrows - 201: { dictID: 11213, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Fifty Arrows - 202: { dictID: 11214, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Bolt - 203: { dictID: 11215, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Five Bolts - 204: { dictID: 11216, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Twenty Bolts - 205: { dictID: 11217, page: 2, timerID: 2, harvest: [ 10029, 10028 ] }, // Fifty Bolts - - // Page 3 - Weapons - 191: { dictID: 11218, page: 3, timerID: 3, harvest: [ 10014 ] }, // Bow - 192: { dictID: 11219, page: 3, timerID: 3, harvest: [ 10014 ] }, // Crossbow - 193: { dictID: 11220, page: 3, timerID: 3, harvest: [ 10014 ] } // Heavy Crossbow -}; - -// Fill in defaults (skill, etc) -(function initFletchingMap() +/** @type { () => boolean } */ +function LoadFletchingMap() { - for( var key in FletchingMap ) + FletchingMap = {}; + + var fletchingEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "fletching" ); + + if( !fletchingEntries || !IsFletchingArrayValue( fletchingEntries ) ) { - if( !FletchingMap.hasOwnProperty( key )) - continue; + Console.Warning( "Fletching: Unable to load fletching craft map data." ); + return false; + } + + for( var i = 0; i < fletchingEntries.length; i++ ) + { + var entry = fletchingEntries[i]; - var entry = FletchingMap[key]; + if( !entry || typeof entry.makeID == "undefined" ) + continue; if( entry.skill === undefined ) entry.skill = fletchingSkillID; - // In future you can do: - // entry.harvest = [ woodDictID, featherDictID ]; - // entry.harvestNames = [ "Wood", "Feathers" ]; + FletchingMap[entry.makeID] = entry; } -})(); + + Console.Print( "Fletching: Loaded " + fletchingEntries.length + " craft map entries.\n" ); + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsFletchingArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} // o--------------------------------------------------------------------------o // | PageX() - build a page of fletching items | @@ -77,6 +58,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !FletchingMap || Object.keys( FletchingMap ).length == 0 ) + { + if( !LoadFletchingMap() ) + { + socket.SysMessage( "Fletching craft map failed to load." ); + return; + } + } + var pageItems; // Last Ten page (only if you wire a tab to 999 later) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 364e88a7d..508c369fb 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -11,59 +11,47 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); const glassSkillID = 0; // alchmey skill const glassHarvestDict = 13504; // sand -////////////////////////////////////////////////////////////////////////////////////////// -// Glassblowing GlassBlowingMap -////////////////////////////////////////////////////////////////////////////////////////// - -const GlassBlowingMap = { - // Page 1 - Misc Glassware - 3000: { dictID: 13600, page: 1, timerID: 1 }, // empty bottle - 3001: { dictID: 13601, page: 1, timerID: 1 }, // flask (small) - 3002: { dictID: 13602, page: 1, timerID: 1 }, // flask (medium) - 3003: { dictID: 13603, page: 1, timerID: 1 }, // flask (curved) - 3004: { dictID: 13604, page: 1, timerID: 1 }, // flask (large #1) - 3005: { dictID: 13605, page: 1, timerID: 1 }, // flask (large #2) - 3006: { dictID: 13606, page: 1, timerID: 1 }, // flask (bubbling blue) - 3007: { dictID: 13607, page: 1, timerID: 1 }, // flask (bubbling purple) - 3008: { dictID: 13608, page: 1, timerID: 1 }, // flask (bubbling red) - 3009: { dictID: 13609, page: 1, timerID: 1 }, // empty vials - 3010: { dictID: 13610, page: 1, timerID: 1 }, // full vials - 3011: { dictID: 13611, page: 1, timerID: 1 }, // spinning hourglass - 3012: { customName: "hollow prism", page: 1, timerID: 1, minEra: "ml" }, // hollow prism - 3013: { customName: "gargoyle floor mirror", page: 1, timerID: 1, minEra: "sa" }, // Gargoyle Floor Mirror - 3014: { customName: "gargoyle wall mirror", page: 1, timerID: 1, minEra: "sa" }, // Gargoyle Wall Mirror - 3015: { customName: "empty venom vial", page: 1, timerID: 1, minEra: "sa" }, // Empty Venom Vial - 3016: { customName: "empty oil flask", page: 1, timerID: 1, minEra: "sa" }, // Empty Oil Flask - 3017: { customName: "workable glass", page: 1, timerID: 1, minEra: "sa" }, // Workable Glass - // Page 2 Glass Weapons - 3018: { customName: "glass sword", page: 2, timerID: 2, minEra: "sa" }, // Glass sword - 3019: { customName: "glass staff", page: 2, timerID: 2, minEra: "sa" } // Glass staff -}; - -// After the GlassBlowingMap literal -(function initGlassBlowingMap() +const craftMapRegistryID = 4038; +var GlassBlowingMap = {}; + +/** @type { () => boolean } */ +function LoadGlassBlowingMap() { - for( var key in GlassBlowingMap ) - { - if( !GlassBlowingMap.hasOwnProperty( key )) - continue; + GlassBlowingMap = {}; + + var glassEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "glassblowing" ); + + if( !glassEntries || !IsGlassBlowingArrayValue( glassEntries ) ) + { + Console.Warning( "Glassblowing: Unable to load glassblowing craft map data." ); + return false; + } - var entry = GlassBlowingMap[key]; + for( var i = 0; i < glassEntries.length; i++ ) + { + var entry = glassEntries[i]; - // Default skill (if not already set) - if( entry.skill === undefined ) - entry.skill = glassSkillID; + if( !entry || typeof entry.makeID == "undefined" ) + continue; - // Default harvest list (if not already set) - if( !entry.harvest ) - entry.harvest = [ glassHarvestDict ]; + if( entry.skill === undefined ) + entry.skill = glassSkillID; - // If you have special cases, you can override here, e.g.: - // if( key == "3017" ) { // workable glass - // entry.harvest = [ glassHarvestDict, 10016 ]; // sand + cloth - // } - } -})(); + if( !entry.harvest ) + entry.harvest = [ glassHarvestDict ]; + + GlassBlowingMap[entry.makeID] = entry; + } + + Console.Print( "Glassblowing: Loaded " + glassEntries.length + " craft map entries.\n" ); + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsGlassBlowingArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} // If you ever need a specific item to use 2 or more resources, just override its harvest array: // GlassBlowingMap[3017].harvest = [ glassHarvestDict, 10016 ]; // two harvest resources @@ -73,6 +61,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !GlassBlowingMap || Object.keys( GlassBlowingMap ).length == 0 ) + { + if( !LoadGlassBlowingMap() ) + { + socket.SysMessage( "Glassblowing craft map failed to load." ); + return; + } + } + var pageItems; // Special "Last Ten" page uses stored makeIDs directly @@ -416,7 +413,7 @@ function onGumpPress( socket, pButton, gumpData ) if( pButton >= 20000 && pButton < 30000 ) { var detailMakeID = pButton - 20000; - var entry = AlchemyMap[detailMakeID]; + var entry = GlassBlowingMap[detailMakeID]; if( entry ) { diff --git a/data/js/skill/craft/masonry.js b/data/js/skill/craft/masonry.js index 912973f17..a97b9e7f9 100644 --- a/data/js/skill/craft/masonry.js +++ b/data/js/skill/craft/masonry.js @@ -18,481 +18,61 @@ const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const allowColouredWeapons = GetServerSetting( "CraftColouredWeapons" ); const allowColouredBuildings = false; // Set to true if you want coloured stone walls, stairs, floors -// Optional: if you later decide to make some masonry items recipe-locked, we will use this map: -// MasonryMap[buttonID] = { dictID, page, timerID, graniteMake: [makeIDByOre], recipeID?, minEra?, maxEra? } -// o--------------------------------------------------------------------------o -// | Script - masonry.js | -// | System - Masonry Crafting Gump | -// o--------------------------------------------------------------------------o -// | Purpose - | -// | Provides the blacksmith crafting menu using the same data-driven | -// | system used by the tailoring script. | -// | | -// | All craftable items are defined in tables (myPage, craftItems) and | -// | then mapped into a MasonryMap structure that controls: | -// | - Which dictionary entry is shown per row | -// | - Which "makeID" entry is used for each ore type | -// | - Which page and timer ID to use when reopening the gump | -// | - Optional per-item recipe and era requirements | -// | - Optional per-item custom names for display | -// | | -// | The script also handles: | -// | - Granite selection (iron / colored ores) with skill requirements | -// | - Smelting stone items back into Granite | -// | - Repairing stone armor and weapons at an anvil | -// | - Tool wear and runic hammer handling | -// | - A "Make Last" feature | -// | - A "Last Ten Masonry" list (optional) | -// o--------------------------------------------------------------------------o -// | Data Tables | -// o--------------------------------------------------------------------------o -// | myPage | -// | myPage[pageIndex] = [ dictID1, dictID2, ... ] | -// | pageIndex 0 => Page 1: Metal Armor | -// | pageIndex 1 => Page 2: Helmets | -// | pageIndex 2 => Page 3: Shields | -// | pageIndex 3 => Page 4: Bladed weapons | -// | pageIndex 4 => Page 5: Axes | -// | pageIndex 5 => Page 6: Polearms | -// | pageIndex 6 => Page 7: Bashing weapons | -// | | -// | Each entry is a dictionary ID that will be used to look up the text | -// | for that row, unless a customName is defined for that button in | -// | MasonryMap. | -// | | -// | craftItems | -// | craftItems[graniteIndex][pageIndex][itemIndex] = makeID | -// | graniteIndex 0 = Iron | -// | graniteIndex 1 = Dull Copper | -// | graniteIndex 2 = Shadow Iron | -// | graniteIndex 3 = Copper | -// | graniteIndex 4 = Bronze | -// | graniteIndex 5 = Gold | -// | graniteIndex 6 = Agapite | -// | graniteIndex 7 = Verite | -// | graniteIndex 8 = Valorite | -// | | -// | For each granite type and page, this holds the createEntry ID used by | -// | MakeItem when the player crafts that item. The same index positions | -// | on each page line up with the matching entries in myPage. | -// o--------------------------------------------------------------------------o -// | MasonryMap | -// o--------------------------------------------------------------------------o -// | MasonryMap is built automatically from myPage and craftItems. | -// | | -// | MasonryMap[buttonID] = { | -// | dictID : number, // Base dictionary entry for the row | -// | page : number, // Main page (1..7, or 999 for Last Ten) | -// | timerID : number, // Timer ID to reopen same page | -// | graniteMake : number[], // graniteMake[graniteIndex] = makeID | -// | customName: string?, // Optional override for display text | -// | recipeID : number?, // Optional recipe requirement | -// | minEra : string?, // Optional minimum shard era | -// | maxEra : string? // Optional maximum shard era | -// | }; | -// | | -// | Button ID mapping (same as original script): | -// | Page 1 (Decorations) : 100..108 | -// | Page 2 (Furniture) : 200..205 | -// | Page 3 (Statues) : 300..305 | -// | Page 4 (Misc Addons) : 400..407 | -// | Page 5 (Stone Armor) : 500..506 | -// | Page 6 (Stone Weapons) : 600..604 | -// | Page 7 (Stone Walls): 700..704 | -// | Page 8 (Stone Stairs): 800..804 | -// | Page 9 (Stone Floors): 900..904 | -// | | -// | Custom Names | -// | To override the display name for a specific row, set customName after | -// | the MasonryMap has been initialized, for example: | -// | | -// | MasonryMap[100].customName = "Hump vase"; | -// | | -// | PageX() will use this order of preference for text: | -// | 1. entry.customName (if set) | -// | 2. GetDictionaryEntry(entry.dictID) | -// | 3. A fallback "[Unnamed Item: buttonID]" | -// | | -// | Recipes | -// | If recipeID is set on a MasonryMap entry, onGumpPress will call: | -// | TriggerEvent(4022, "NeedRecipe", pUser, recipeID) | -// | to check if the player has learned that recipe. If not, the craft | -// | attempt is blocked and a message is shown. | -// | | -// | Era Gating | -// | The script reads the shard era using: | -// | const coreShardEra = EraStringToNum(GetServerSetting("CoreShardEra")); | -// | | -// | If an entry defines minEra or maxEra (strings like "lbr","aos","ml", | -// | "sa","hs","tol"), eraOK(entry) will ensure the current server era is | -// | within that range before allowing craft or display. | -// o--------------------------------------------------------------------------o -// | Notes | -// o--------------------------------------------------------------------------o -// | - To add new Masonry items, update myPage and craftItems, then | -// | optionally decorate their MasonryMap entries with customName, | -// | recipeID, minEra, and maxEra. | -// o--------------------------------------------------------------------------o - -const myPage = [ - // Page 1 - Decorations - [ 14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, 14058 ], - // Page 2 - Furniture - [ 14059, 14060, 14061, 14062, 14063, 14064 ], - // Page 3 - Statues - [ 14065, 14066, 14067, 14068, 14069, 14070 ], - // Page 4 - Misc Addons - [ 14071, 14072, 14073, 14074, 14075, 14076 ], - // Page 5 - Stone Armor - [ 14077, 14078, 14079, 14080, 14081, 14082, 14083, 14084, 14085, 14086 ], - // Page 6 - Stone Weapons - [ 14087 ], - // Page 7 - Stone Walls - [ 14088, 14089, 14090, 14091, 14092, 14093, 14094, 14095, 14096,14097, 14098, 14099 ], - // Page 8 - Stone Stairs - [ 14100, 14101, 14102, 14103, 14104, 14105 ], - // Page 9 - Stone Floors - [ 14106, 14107, 14108 ] -]; - -const craftItems = [ - // Iron - [ - // Decorations - [ 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508 ], - // Furniture - [ 3509, 3510, 3511, 3512, 3513, 3514 ], - // Statues - [ 3515, 3516, 3517, 3518, 3519, 3520 ], - // Misc Addons - [ 3521, 3522, 3523, 3524, 3525, 3526 ], - // Stone Armor - [ 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536 ], - // Stone Weapons - [ 3537 ], - // Stone Walls - [ 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549 ], - // Stone Stairs - [ 3550, 3551, 3552, 3553, 3554, 3555 ], - // Stone Floors - [ 3556, 3557, 3558] - ], - - // Dull Copper - [ - // Decorations - [ 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608 ], - // Furniture - [ 3609, 3610, 3611, 3612, 3613, 3614 ], - // Statues - [ 3615, 3616, 3617, 3618, 3619, 3620 ], - // Misc Addons - [ 3621, 3622, 3623, 3624, 3625, 3626 ], - // Stone Armor - [ 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636 ], - // Stone Weapons - [ 3637 ], - // Stone Walls - [ 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649 ], - // Stone Stairs - [ 3650, 3651, 3652, 3653, 3654, 3655 ], - // Stone Floors - [ 3656, 3657, 3658] - ], - - // Shadow Iron - [ - // Decorations - [ 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708 ], - // Furniture - [ 3709, 3710, 3711, 3712, 3713, 3714 ], - // Statues - [ 3715, 3716, 3717, 3718, 3719, 3720 ], - // Misc Addons - [ 3721, 3722, 3723, 3724, 3725, 3726 ], - // Stone Armor - [ 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736 ], - // Stone Weapons - [ 3737 ], - // Stone Walls - [ 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749 ], - // Stone Stairs - [ 3750, 3751, 3752, 3753, 3754, 3755 ], - // Stone Floors - [ 3756, 3757, 3758] - ], - - // Copper - [ - // Decorations - [ 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808 ], - // Furniture - [ 3809, 3810, 3811, 3812, 3813, 3814 ], - // Statues - [ 3815, 3816, 3817, 3818, 3819, 3820 ], - // Misc Addons - [ 3821, 3822, 3823, 3824, 3825, 3826 ], - // Stone Armor - [ 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836 ], - // Stone Weapons - [ 3837 ], - // Stone Walls - [ 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849 ], - // Stone Stairs - [ 3850, 3851, 3852, 3853, 3854, 3855 ], - // Stone Floors - [ 3856, 3857, 3858] - ], - - // Bronze - [ - // Decorations - [ 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908 ], - // Furniture - [ 3909, 3910, 3911, 3912, 3913, 3914 ], - // Statues - [ 3915, 3916, 3917, 3918, 3919, 3920 ], - // Misc Addons - [ 3921, 3922, 3923, 3924, 3925, 3926 ], - // Stone Armor - [ 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936 ], - // Stone Weapons - [ 3937 ], - // Stone Walls - [ 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949 ], - // Stone Stairs - [ 3950, 3951, 3952, 3953, 3954, 3955 ], - // Stone Floors - [ 3956, 3957, 3958] - ], - - // Gold - [ - // Decorations - [ 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008 ], - // Furniture - [ 4009, 4010, 4011, 4012, 4013, 4014 ], - // Statues - [ 4015, 4016, 4017, 4018, 4019, 4020 ], - // Misc Addons - [ 4021, 4022, 4023, 4024, 4025, 4026 ], - // Stone Armor - [ 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036 ], - // Stone Weapons - [ 4037 ], - // Stone Walls - [ 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049 ], - // Stone Stairs - [ 4050, 4051, 4052, 4053, 4054, 4055 ], - // Stone Floors - [ 4056, 4057, 4058] - ], - - // Agapite - [ - // Decorations - [ 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108 ], - // Furniture - [ 4109, 4110, 4111, 4112, 4113, 4114 ], - // Statues - [ 4115, 4116, 4117, 4118, 4119, 4120 ], - // Misc Addons - [ 4121, 4122, 4123, 4124, 4125, 4126 ], - // Stone Armor - [ 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136 ], - // Stone Weapons - [ 4137 ], - // Stone Walls - [ 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149 ], - // Stone Stairs - [ 4150, 4151, 4152, 4153, 4154, 4155 ], - // Stone Floors - [ 4156, 4157, 4158] - ], - - // Verite - [ - // Decorations - [ 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208 ], - // Furniture - [ 4209, 4210, 4211, 4212, 4213, 4214 ], - // Statues - [ 4215, 4216, 4217, 4218, 4219, 4220 ], - // Misc Addons - [ 4221, 4222, 4223, 4224, 4225, 4226 ], - // Stone Armor - [ 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236 ], - // Stone Weapons - [ 4237 ], - // Stone Walls - [ 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249 ], - // Stone Stairs - [ 4250, 4251, 4252, 4253, 4254, 4255 ], - // Stone Floors - [ 4256, 4257, 4258] - ], - - // Valorite - [ - // Decorations - [ 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308 ], - // Furniture - [ 4309, 4310, 4311, 4312, 4313, 4314 ], - // Statues - [ 4315, 4316, 4317, 4318, 4319, 4320 ], - // Misc Addons - [ 4321, 4322, 4323, 4324, 4325, 4326 ], - // Stone Armor - [ 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336 ], - // Stone Weapons - [ 4337 ], - // Stone Walls - [ 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349 ], - // Stone Stairs - [ 4350, 4351, 4352, 4353, 4354, 4355 ], - // Stone Floors - [ 4356, 4357, 4358] - ] -]; - -// MasonryMap[buttonID] = { -// dictID: , -// page: , -// timerID: , -// graniteMake: [ makeIDForIron, makeIDForDullCopper, ... ], // index is graniteID (0..8) -// // Optional later: -// // recipeID: , -// // minEra: "lbr" / "aos" / "ml" / "sa" / "hs" / "tol", -// // maxEra: ... -// }; - -const MasonryMap = {}; - -(function initMasonryMap() +const craftMapRegistryID = 4038; +var MasonryMap = {}; +var craftItems = []; + +/** @type { () => boolean } */ +function LoadMasonryMap() { - // graniteIndex: 0 = iron, 1 = dull copper, ... 8 = valorite - for( var graniteIndex = 0; graniteIndex < craftItems.length; graniteIndex++ ) + MasonryMap = {}; + craftItems = []; + + var masonryEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "masonry" ); + + if( !masonryEntries || !IsMasonryArrayValue( masonryEntries ) ) { - var graniteRows = craftItems[graniteIndex]; + Console.Warning( "Masonry: Unable to load masonry craft map data." ); + return false; + } - // pageIdx: 0..6 => pages 1..9 - for( var pageIdx = 0; pageIdx < myPage.length; pageIdx++ ) - { - var dictList = myPage[pageIdx]; - var makeList = graniteRows[pageIdx]; + for( var i = 0; i < masonryEntries.length; i++ ) + { + var entry = masonryEntries[i]; - for( var i = 0; i < dictList.length && i < makeList.length; i++ ) - { - // Old script uses: - // page 1 => 100..112 - // page 2 => 200..204 - // page 3 => 300..305 - // etc. - var buttonID = ( ( pageIdx + 1 ) * 100 ) + i; - var dictID = dictList[i]; - var makeID = makeList[i]; - - if( !MasonryMap[buttonID] ) - { - MasonryMap[buttonID] = { - dictID: dictID, - page: pageIdx + 1, - timerID: pageIdx + 1, - graniteMake: [], - // recipeID: undefined, - // minEra: undefined, - // maxEra: undefined - skill: 11, // carpentry / masonry skill ID - harvest: [14011], // granite dict - harvest2: [], // optional second resource - harvest3: [], // optional second resource - harvest4: [] // optional second resource - }; - } + if( !entry || typeof entry.buttonID == "undefined" ) + continue; - MasonryMap[buttonID].graniteMake[graniteIndex] = makeID; - } - } + if( entry.skill === undefined ) + entry.skill = 11; + + MasonryMap[entry.buttonID] = entry; } -})(); - -// 3) AFTER initMasonryMap, you can override entries: -// Page 1 Starts buttonID 100 - 107 for map example -//MasonryMap[100].customName = "Elven Broadsword"; -//MasonryMap[100].recipeID = 5101; // if you want it recipe-locked -//MasonryMap[100].minEra = "ml"; // if you want it ML and later only - -//Page 1 starts at 100 -MasonryMap[102].minEra = "se"; // small urn -MasonryMap[103].minEra = "se"; // Tower Sculpture -MasonryMap[104].minEra = "sa"; // gargoyle painting -MasonryMap[105].minEra = "sa"; // gargoyle sculpture -MasonryMap[106].minEra = "sa"; // gargoyle vase -MasonryMap[107].minEra = "tol"; // Tall 18th Anniversary Vase -MasonryMap[107].recipeID = 3500; -MasonryMap[108].minEra = "tol"; // Short 18th Anniversary Vase -MasonryMap[108].recipeID = 3501; -//Page 2 starts at 200 -MasonryMap[205].minEra = "sa"; // ritual table -//Page 3 starts at 300 -MasonryMap[304].minEra = "sa"; // gargoyle statue -MasonryMap[305].minEra = "sa"; // gryphon statue -//Page 4 starts at 400 -MasonryMap[400].minEra = "ml"; // stone anvil (east) -MasonryMap[400].recipeID = 3520; -MasonryMap[401].minEra = "ml"; // stone anvil (south) -MasonryMap[401].recipeID = 3521; -MasonryMap[402].minEra = "sa"; // large gargish bed (east) -MasonryMap[402].harvest2 = [10016]; // Cloth -MasonryMap[403].minEra = "sa"; // large gargish bed (south) -MasonryMap[403].harvest2 = [10016]; // Cloth -MasonryMap[404].minEra = "sa"; // gargish cot (east) -MasonryMap[404].harvest2 = [10016]; // Cloth -MasonryMap[405].minEra = "sa"; // gargish cot (south) -MasonryMap[405].harvest2 = [10016]; // Cloth -//Page 5 starts at 500 -MasonryMap[500].minEra = "sa"; // gargish stone arms -MasonryMap[501].minEra = "sa"; // gargish stone chest -MasonryMap[502].minEra = "sa"; // gargish stone leggings -MasonryMap[503].minEra = "sa"; // gargish stone kilt -MasonryMap[504].minEra = "sa"; // gargish stone arms -MasonryMap[505].minEra = "sa"; // gargish stone chest -MasonryMap[506].minEra = "sa"; // gargish stone leggings -MasonryMap[507].minEra = "sa"; // gargish stone kilt -MasonryMap[508].minEra = "sa"; // large stone shield -MasonryMap[509].minEra = "sa"; // gargish stone amulet -//Page 6 starts at 600 -MasonryMap[600].minEra = "sa"; // stone war sword -//Page 7 starts at 700 -MasonryMap[700].minEra = "tol"; // Rough Windowless -MasonryMap[701].minEra = "tol"; // Rough Window -MasonryMap[702].minEra = "tol"; // Rough Arch -MasonryMap[703].minEra = "tol"; // Rough Pillar -MasonryMap[704].minEra = "tol"; // Rough Rounded Arch -MasonryMap[705].minEra = "tol"; // Rough Small Arch -MasonryMap[706].minEra = "tol"; // Rough Angled Pillar -MasonryMap[707].minEra = "tol"; // Short Rough -MasonryMap[708].minEra = "tol"; // Stone Door (S In) -MasonryMap[709].minEra = "tol"; // Stone Door (E Out) -MasonryMap[710].minEra = "tol"; // Left Metal Door (S In) -MasonryMap[711].minEra = "tol"; // Right Metal Door (S In) -//Page 8 starts at 800 -MasonryMap[800].minEra = "tol"; // short rough -MasonryMap[801].minEra = "tol"; // rough steps -MasonryMap[802].minEra = "tol"; // rough corner steps -MasonryMap[803].minEra = "tol"; // rough rounded corner step -MasonryMap[804].minEra = "tol"; // rough inset steps -MasonryMap[805].minEra = "tol"; // rough rounded inset steps -//Page 9 starts at 900 -MasonryMap[900].minEra = "tol"; // light paver -MasonryMap[901].minEra = "tol"; // medium paver -MasonryMap[902].minEra = "tol"; // dark paver + + Console.Print( "Masonry: Loaded " + masonryEntries.length + " craft map entries.\n" ); + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsMasonryArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} function PageX( socket, pUser, pageNum ) { if( !ValidateObject( pUser )) return; + if( !MasonryMap || Object.keys( MasonryMap ).length == 0 ) + { + if( !LoadMasonryMap() ) + { + socket.SysMessage( "Masonry craft map failed to load." ); + return; + } + } + // Pages 1 - 9: normal crafting pages // Page 999: optional "Last Ten Blacksmith" (if you decide to use it later) @@ -1267,7 +847,7 @@ function onGumpPress( pSock, pButton, gumpData ) var resourceHue = pUser.GetTempTag( "resourceHue" ); // Ensure graniteID within range - if( graniteID < 0 || graniteID >= craftItems.length ) + if( graniteID < 0 || graniteID >= entry2.graniteMake.length ) graniteID = 0; // Era / recipe gating diff --git a/data/js/skill/craft/tailoring.js b/data/js/skill/craft/tailoring.js index f07b50e95..f29dcf09f 100644 --- a/data/js/skill/craft/tailoring.js +++ b/data/js/skill/craft/tailoring.js @@ -11,101 +11,43 @@ const displayUnlearnedRecipes = true; // Show recipes player ha const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const tailoringSkillID = 34; // Tailoring skill index -////////////////////////////////////////////////////////////////////////////////////////// -// Tailoring CraftingMap -////////////////////////////////////////////////////////////////////////////////////////// - -// You can later add: -// skill, minEra, maxEra, recipeID, harvest, harvestNames, customName -// per entry, like in Alchemy / Tinkering. - -const CraftingMap = { - // Hats (Page 1) - 130: { dictID: 11415, page: 1, timerID: 1, harvest: [ 10016 ] }, - 131: { dictID: 11416, page: 1, timerID: 1, harvest: [ 10016 ] }, - 132: { dictID: 11417, page: 1, timerID: 1, harvest: [ 10016 ] }, - 134: { dictID: 11418, page: 1, timerID: 1, harvest: [ 10016 ] }, - 133: { dictID: 11419, page: 1, timerID: 1, harvest: [ 10016 ] }, - 136: { dictID: 11420, page: 1, timerID: 1, harvest: [ 10016 ] }, - 137: { dictID: 11421, page: 1, timerID: 1, harvest: [ 10016 ] }, - 138: { dictID: 11422, page: 1, timerID: 1, harvest: [ 10016 ] }, - 139: { dictID: 11423, page: 1, timerID: 1, harvest: [ 10016 ] }, - 140: { dictID: 11424, page: 1, timerID: 1, harvest: [ 10016 ] }, - 141: { dictID: 11425, page: 1, timerID: 1, harvest: [ 10016 ] }, - 135: { dictID: 11470, page: 1, timerID: 1, harvest: [ 10016 ] }, - - // Shirts & Pants (Page 2) - 142: { dictID: 11426, page: 2, timerID: 2, harvest: [ 10016 ] }, - 143: { dictID: 11427, page: 2, timerID: 2, harvest: [ 10016 ] }, - 144: { dictID: 11428, page: 2, timerID: 2, harvest: [ 10016 ] }, - 145: { dictID: 11429, page: 2, timerID: 2, harvest: [ 10016 ] }, - 146: { dictID: 11430, page: 2, timerID: 2, harvest: [ 10016 ] }, - 147: { dictID: 11431, page: 2, timerID: 2, harvest: [ 10016 ] }, - 148: { dictID: 11432, page: 2, timerID: 2, harvest: [ 10016 ] }, - 149: { dictID: 11433, page: 2, timerID: 2, harvest: [ 10016 ] }, - 150: { dictID: 11434, page: 2, timerID: 2, harvest: [ 10016 ] }, - 151: { dictID: 11435, page: 2, timerID: 2, harvest: [ 10016 ] }, - 180: { dictID: 11436, page: 2, timerID: 2, harvest: [ 10016 ] }, - 152: { dictID: 11437, page: 2, timerID: 2, harvest: [ 10016 ] }, - 153: { dictID: 11438, page: 2, timerID: 2, harvest: [ 10016 ] }, - 154: { dictID: 11439, page: 2, timerID: 2, harvest: [ 10016 ] }, - - // Misc (Page 3) - 155: { dictID: 11440, page: 3, timerID: 3, harvest: [ 10016 ] }, - 156: { dictID: 11441, page: 3, timerID: 3, harvest: [ 10016 ] }, - 157: { dictID: 11442, page: 3, timerID: 3, harvest: [ 10016 ] }, - 158: { dictID: 11443, page: 3, timerID: 3, harvest: [ 10016 ] }, - - // Footwear (Page 4) - 159: { dictID: 11444, page: 4, timerID: 4, harvest: [ 10007 ] }, - 160: { dictID: 11445, page: 4, timerID: 4, harvest: [ 10007 ] }, - 161: { dictID: 11446, page: 4, timerID: 4, harvest: [ 10007 ] }, - 162: { dictID: 11447, page: 4, timerID: 4, harvest: [ 10007 ] }, - - // Leather Armor (Page 5) - 163: { dictID: 11448, page: 5, timerID: 5, harvest: [ 10007 ] }, - 164: { dictID: 11449, page: 5, timerID: 5, harvest: [ 10007 ] }, - 165: { dictID: 11450, page: 5, timerID: 5, harvest: [ 10007 ] }, - 166: { dictID: 11451, page: 5, timerID: 5, harvest: [ 10007 ] }, - 167: { dictID: 11452, page: 5, timerID: 5, harvest: [ 10007 ] }, - 168: { dictID: 11453, page: 5, timerID: 5, harvest: [ 10007 ] }, - - // Studded Armor (Page 6) - 169: { dictID: 11454, page: 6, timerID: 6, harvest: [ 10007 ] }, - 170: { dictID: 11455, page: 6, timerID: 6, harvest: [ 10007 ] }, - 171: { dictID: 11456, page: 6, timerID: 6, harvest: [ 10007 ] }, - 172: { dictID: 11457, page: 6, timerID: 6, harvest: [ 10007 ] }, - 173: { dictID: 11458, page: 6, timerID: 6, harvest: [ 10007 ] }, - - // Female Armor (Page 7) - 174: { dictID: 11459, page: 7, timerID: 7, harvest: [ 10007 ] }, - 175: { dictID: 11460, page: 7, timerID: 7, harvest: [ 10007 ] }, - 176: { dictID: 11461, page: 7, timerID: 7, harvest: [ 10007 ] }, - 177: { dictID: 11462, page: 7, timerID: 7, harvest: [ 10007 ] }, - 178: { dictID: 11463, page: 7, timerID: 7, harvest: [ 10007 ] }, - 179: { dictID: 11464, page: 7, timerID: 7, harvest: [ 10007 ] }, - - // Bone Armor (Page 8) - 181: { dictID: 11465, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, - 182: { dictID: 11466, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, - 183: { dictID: 11467, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, - 184: { dictID: 11468, page: 8, timerID: 8, harvest: [ 10007, 10008 ] }, - 185: { dictID: 11469, page: 8, timerID: 8, harvest: [ 10007, 10008 ] } // can add recipeID/minEra here later -}; - -// Fill defaults (skill, etc.) -(function initTailoringMap() +const craftMapRegistryID = 4038; +var CraftingMap = {}; + +/** @type { () => boolean } */ +function LoadTailoringMap() { - for( var key in CraftingMap ) + CraftingMap = {}; + + var tailoringEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", "tailoring" ); + + if( !tailoringEntries || !IsTailoringArrayValue( tailoringEntries ) ) { - if( !CraftingMap.hasOwnProperty( key )) + Console.Warning( "Tailoring: Unable to load tailoring craft map data." ); + return false; + } + + for( var i = 0; i < tailoringEntries.length; i++ ) + { + var entry = tailoringEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) continue; - var entry = CraftingMap[key]; if( entry.skill === undefined ) entry.skill = tailoringSkillID; + + CraftingMap[entry.makeID] = entry; } -})(); + + return true; +} + +/** @type { ( value: any ) => boolean } */ +function IsTailoringArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} /** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ function PageX( socket, pUser, pageNum ) @@ -113,6 +55,15 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; + if( !CraftingMap || Object.keys( CraftingMap ).length == 0 ) + { + if( !LoadTailoringMap() ) + { + socket.SysMessage( "Tailoring craft map failed to load." ); + return; + } + } + var subPage = pUser.GetTempTag( "subPage" ) || 1; var pageItems; diff --git a/data/js/skill/craft/tinkering.js b/data/js/skill/craft/tinkering.js index c5eb1e409..1af465688 100644 --- a/data/js/skill/craft/tinkering.js +++ b/data/js/skill/craft/tinkering.js @@ -10,141 +10,6 @@ const displayUnlearnedRecipes = true; // For future recipe use const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); const tinkeringSkillID = 37; // Index of "tinkering" in ItemDetailGump.skillNames[] -// o--------------------------------------------------------------------------o -// | TinkeringMap | -// o--------------------------------------------------------------------------o -// | Keyed by makeID (create entry ID). | -// | Each entry: | -// | dictID - dictionary entry for row text (11801..11982) | -// | page - main category page (1..9) | -// | timerID - which page timer should reopen | -// | skill - skill used (default: tinkeringSkillID) | -// | recipeID? - optional recipe ID | -// | minEra?, maxEra? - optional era gating | -// | harvest?[] - optional dictIDs for MATERIALS list | -// | harvestNames?[] - optional custom material names | -// | requiresGemTarget? - jewelry requiring manual gem selection | -// o--------------------------------------------------------------------------o - -/*const TinkeringMap = { - // Page 1 - Wooden Items - 274: { dictID: 11801, page: 1, timerID: 1, harvest: [ 10014 ] }, // Axle - 273: { dictID: 11802, page: 1, timerID: 1, harvest: [ 10014 ] }, // Clock Frame - 270: { dictID: 11803, page: 1, timerID: 1, harvest: [ 10014 ] }, // Jointing Plane - 271: { dictID: 11804, page: 1, timerID: 1, harvest: [ 10014 ] }, // Moulding Plane - 272: { dictID: 11805, page: 1, timerID: 1, harvest: [ 10014 ] }, // Smoothing Plane - - // Page 2 - Tools - 218: { dictID: 11820, page: 2, timerID: 2, harvest: [ 10015 ] }, // Dovetail Saw - 215: { dictID: 11821, page: 2, timerID: 2, harvest: [ 10015 ] }, // Draw Knife - 252: { dictID: 11822, page: 2, timerID: 2, harvest: [ 10015 ] }, // Froe - 255: { dictID: 11823, page: 2, timerID: 2, harvest: [ 10015 ] }, // Hammer - 214: { dictID: 11824, page: 2, timerID: 2, harvest: [ 10015 ] }, // Hatchet - 258: { dictID: 11825, page: 2, timerID: 2, harvest: [ 10015 ] }, // Inshave - 260: { dictID: 11826, page: 2, timerID: 2, harvest: [ 10015 ] }, // Lockpick - 211: { dictID: 11827, page: 2, timerID: 2, harvest: [ 10015 ] }, // Mortar and Pestle - 259: { dictID: 11828, page: 2, timerID: 2, harvest: [ 10015 ] }, // Pick Axe - 217: { dictID: 11829, page: 2, timerID: 2, harvest: [ 10015 ] }, // Saw - 210: { dictID: 11830, page: 2, timerID: 2, harvest: [ 10015 ] }, // Scissors - 212: { dictID: 11831, page: 2, timerID: 2, harvest: [ 10015 ] }, // Scorp - 216: { dictID: 11832, page: 2, timerID: 2, harvest: [ 10015 ] }, // Sewing Kit - 254: { dictID: 11833, page: 2, timerID: 2, harvest: [ 10015 ] }, // Shovel - 257: { dictID: 11834, page: 2, timerID: 2, harvest: [ 10015 ] }, // Sledge Hammer - 256: { dictID: 11835, page: 2, timerID: 2, harvest: [ 10015 ] }, // Smith's Hammer - 253: { dictID: 11836, page: 2, timerID: 2, harvest: [ 10015 ] }, // Tongs - 213: { dictID: 11837, page: 2, timerID: 2, harvest: [ 10015 ] }, // Tool Kit (Tinker's tools) - 284: { dictID: 11838, page: 2, timerID: 2, harvest: [ 10015 ] }, // Fletcher's Tools - - // Page 3 - Parts - 224: { dictID: 11860, page: 3, timerID: 3, harvest: [ 10015 ] }, // Barrel Hoops - 221: { dictID: 11861, page: 3, timerID: 3, harvest: [ 10015 ] }, // Barrel Tap - 220: { dictID: 11862, page: 3, timerID: 3, harvest: [ 10015 ] }, // Clock parts - 219: { dictID: 11863, page: 3, timerID: 3, harvest: [ 10015 ] }, // Gears - 225: { dictID: 11864, page: 3, timerID: 3, harvest: [ 10015 ] }, // Hinge - 223: { dictID: 11865, page: 3, timerID: 3, harvest: [ 10015 ] }, // Sextant parts - 222: { dictID: 11866, page: 3, timerID: 3, harvest: [ 10015 ] }, // Springs - - // Page 4 - Utensils - 226: { dictID: 11880, page: 4, timerID: 4, harvest: [ 10015 ] }, // Butcher Knife - 232: { dictID: 11881, page: 4, timerID: 4, harvest: [ 10015 ] }, // Cleaver - 230: { dictID: 11882, page: 4, timerID: 4, harvest: [ 10015 ] }, // Fork - 231: { dictID: 11883, page: 4, timerID: 4, harvest: [ 10015 ] }, // Fork - 235: { dictID: 11884, page: 4, timerID: 4, harvest: [ 10015 ] }, // Goblet - 233: { dictID: 11885, page: 4, timerID: 4, harvest: [ 10015 ] }, // Knife - 234: { dictID: 11886, page: 4, timerID: 4, harvest: [ 10015 ] }, // Knife - 236: { dictID: 11887, page: 4, timerID: 4, harvest: [ 10015 ] }, // Pewter Mug - 229: { dictID: 11888, page: 4, timerID: 4, harvest: [ 10015 ] }, // Plate - 237: { dictID: 11889, page: 4, timerID: 4, harvest: [ 10015 ] }, // Skinning Knife - 227: { dictID: 11890, page: 4, timerID: 4, harvest: [ 10015 ] }, // Spoon - 228: { dictID: 11891, page: 4, timerID: 4, harvest: [ 10015 ] }, // Spoon - - // Page 5 - Jewelry (gem-targeted) - 243: { dictID: 11900, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Bracelet - 241: { dictID: 11901, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Earrings - 239: { dictID: 11902, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Golden beads) - 240: { dictID: 11903, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Silver beads) - 242: { dictID: 11904, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12005 ] }, // Necklace (Round) - 238: { dictID: 11905, page: 5, timerID: 5, requiresGemTarget: true, harvest: [ 10015, 12006 ] }, // Weddingband (newbiefied) - - // Page 6 - Miscellaneous - 245: { dictID: 11920, page: 6, timerID: 6, harvest: [ 10015, 12000 ] }, // Candelabra (also appears in Candles page in old script) - 248: { dictID: 11921, page: 6, timerID: 6, harvest: [ 10015 ] }, // Globe - 251: { dictID: 11922, page: 6, timerID: 6, harvest: [ 10015 ] }, // Heating stand - 247: { dictID: 11923, page: 6, timerID: 6, harvest: [ 10015 ] }, // Iron Key - 244: { dictID: 11924, page: 6, timerID: 6, harvest: [ 10015 ] }, // Keyring - 250: { dictID: 11925, page: 6, timerID: 6, harvest: [ 10015 ] }, // Lantern - 246: { dictID: 11926, page: 6, timerID: 6, harvest: [ 10015 ] }, // Scales - 249: { dictID: 11927, page: 6, timerID: 6, harvest: [ 10015 ] }, // Spy glass - - // Page 7 - Multi-Component Items - 275: { dictID: 11940, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Axle and Gears - 276: { dictID: 11941, page: 7, timerID: 7, harvest: [ 11802, 11862 ] }, // Clock - 277: { dictID: 11942, page: 7, timerID: 7, harvest: [ 11802, 11862 ] }, // Clock - 278: { dictID: 11943, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Clock Parts - 279: { dictID: 11944, page: 7, timerID: 7, harvest: [ 10634 ] }, // Locked Box - 280: { dictID: 11945, page: 7, timerID: 7, harvest: [ 10638 ] }, // Locked Chest - 281: { dictID: 11946, page: 7, timerID: 7, harvest: [ 10642, 11861, 10612, 10928 ] }, // Potion Keg - 282: { dictID: 11947, page: 7, timerID: 7, harvest: [ 11948 ] }, // Sextant - 283: { dictID: 11948, page: 7, timerID: 7, harvest: [ 11801, 11863 ] }, // Sextant Parts - - // Page 8 - Candles - // NOTE: in the original script, Candelabra (245) appears here too. - // To avoid conflicts (map is keyed by makeID), this page uses the - // actual candle-specific items only. - 310: { dictID: 11961, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Standing Candelabra - 315: { dictID: 11962, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Regular Candle - 312: { dictID: 11963, page: 8, timerID: 8, harvest: [ 12000 ] }, // Round Candle - 316: { dictID: 11964, page: 8, timerID: 8, harvest: [ 12000, 12004 ] }, // Skull with Candle - 314: { dictID: 11965, page: 8, timerID: 8, harvest: [ 12000 ] }, // Small Candle - 311: { dictID: 11966, page: 8, timerID: 8, harvest: [ 10015, 12000 ] }, // Tall Candle - 313: { dictID: 11967, page: 8, timerID: 8, harvest: [ 12000 ] }, // Thick Candle - - // Page 9 - Traps - 261: { dictID: 11980, page: 9, timerID: 9, harvest: [ 10015, 12001 ] }, // Dart Trap - 263: { dictID: 11981, page: 9, timerID: 9, harvest: [ 10015, 12003 ] }, // Explosion Trap - 262: { dictID: 11982, page: 9, timerID: 9, harvest: [ 10015, 12002 ] } // Poison Trap -}; - - -// Fill in defaults (skill, etc) -(function initTinkeringMap() -{ - for( var key in TinkeringMap ) - { - if( !TinkeringMap.hasOwnProperty( key )) - continue; - - var entry = TinkeringMap[key]; - - if( entry.skill === undefined ) - entry.skill = tinkeringSkillID; - - // In future you can do e.g.: - // entry.harvest = [ woodDictID, ingotDictID ]; - // entry.harvestNames = [ "Wood", "Ingots" ]; - } -})(); -*/ const craftMapRegistryID = 4038; var TinkeringMap = {}; From c4b5a1b0205ef597696dab80b24565effbb75d2e Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 13 May 2026 16:20:34 -0500 Subject: [PATCH 42/43] Update index.html --- docs/index.html | 450 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 450 insertions(+) diff --git a/docs/index.html b/docs/index.html index 287904d4d..343406068 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6040,6 +6040,456 @@

Rank System

Calculation of rank takes place as part of the crafting process. First, a range of potential ranks is determined based on the values of the MINRANK and MAXRANK tags for an item in the create DFNs. Then, for each skill required to craft the item, the system calculates a temporary rank based on the player's skill, random chance, and a UOX.INI setting (SKILLLEVEL=7) which acts as a global modifier to the system to make it easier (low SKILLLEVEL value) to get high rank items, or harder (high SKILLLEVEL value) to get high rank items. A value of 10 makes the difficulty roughly similar to the difficulty of the official UO shards around the LBR era.

When a temporary rank has been calculated for all skills required to craft the item, the average of all these is chosen as the item's final rank, and the modifiers are permanently applied to the item's properties.

+

JSON Crafting Data

+

In addition to the older DFN-based create system, UOX3 can use JSON files to control the visible crafting menu data. The JSON files do not replace the actual CreateEntry definitions that decide what item is made, what resources are consumed, and what skills are checked. Instead, they make the crafting menus easier to organize, customize and extend without editing the crafting scripts directly.

+ +

The JSON crafting files are stored in:

+

js/jsdata/crafting/

+ + + +
+
    +
  • alchemy.json - Alchemy menu entries
  • +
  • blacksmithing.json - Blacksmithing menu entries
  • +
  • carpentry.json - Carpentry menu entries
  • +
  • cartography.json - Cartography menu entries
  • +
  • cooking.json - Cooking menu entries
  • +
  • fletching.json - Bowcraft/Fletching menu entries
  • +
  • glassblowing.json - Glassblowing menu entries
  • +
  • masonry.json - Masonry menu entries
  • +
  • tailoring.json - Tailoring menu entries
  • +
  • tinkering.json - Tinkering menu entries
  • +
  • resourcemap.json - Shared resource definitions used by crafting menus
  • +
+
+ +

Why Use JSON Crafting Data?

+

The JSON crafting system makes crafting easier to maintain. Shard admins can move items between pages, rename menu entries, add custom labels, add era limits, add recipe requirements, define item detail resources and configure some special post-crafting behavior without digging through the crafting scripts.

+ +
    +
  • Move an item to a different crafting page by changing its page value.
  • +
  • Change the order of items by changing their position or button mapping in the JSON file.
  • +
  • Use dictID for dictionary-based names, or customName for a custom display name.
  • +
  • Add recipe locks with recipeID.
  • +
  • Add expansion or era limits with minEra and maxEra.
  • +
  • Show custom resource names in the item detail gump with harvest and harvestNames.
  • +
  • Define special post-craft behavior with craftComplete.
  • +
  • Update resource lists, hues, dictionary labels and skill gates through resourcemap.json.
  • +
+ + + +
+
{
+	"makeID": 274,
+	"label": "Axle",
+	"dictID": 11801,
+	"page": 1,
+	"timerID": 1,
+	"harvest": [10014]
+}
+ +

This entry adds a craftable item to the menu. The makeID points to the CreateEntry that actually creates the item. The dictID is used for the displayed name, page decides which menu page the item appears on and timerID decides which page reopens after crafting.

+
+ +

Craft Entry Fields

+

Each crafting JSON file is an array of craft entries. Most entries use only a few fields, but more can be added when needed.

+ + + +
+
+

makeID: number
+ The CreateEntry ID used when the player crafts the item. This must match a valid entry from the create system.

+
+ +
+

buttonID: number
+ Optional menu button ID used by crafting skills that need one visible row to map to different makeIDs based on the selected resource. Blacksmithing and Masonry commonly use this style.

+
+ +
+

dictID: number
+ Dictionary entry used for the menu text. This allows the crafting menu to use UOX3 dictionary files for display names.

+
+ +
+

label: text
+ A readable label for admins editing the JSON file. This is useful so the item can be identified without looking up the dictionary ID. It does not have to be the final in-game item name.

+
+ +
+

customName: text
+ Overrides the dictionary text shown in the crafting menu. Use this for custom items that do not have a dictionary entry.

+
+ +
+

page: number
+ The crafting page the entry appears on. Changing this value moves the item to another page in the crafting menu.

+
+ +
+

timerID: number
+ The page/timer value used when the crafting menu reopens after crafting or after a failed attempt.

+
+ +
+

skill: number
+ Optional skill ID override used by the item detail gump and menu logic. If omitted, the crafting script uses the default skill for that craft.

+
+ +
+

harvest: number array
+ Dictionary IDs used to show resource names in the item detail gump. This does not consume resources by itself; the actual resource requirements still come from the CreateEntry.

+
+ +
+

harvestNames: text array
+ Optional custom resource labels for the item detail gump. Use this when a resource name should be clearer than the dictionary entry.

+
+ +
+

recipeID: number
+ Optional recipe requirement. If set, the player must know the recipe before crafting the item.

+
+ +
+

minEra: text
+ Optional minimum shard era required before the entry appears or can be crafted.

+
+ +
+

maxEra: text
+ Optional maximum shard era allowed before the entry is hidden or blocked.

+
+ +
+

requiresGemTarget: true/false
+ Used by Tinkering jewelry entries that require the player to target a gem before crafting.

+
+ +
+

oreMake: number array
+ Used by Blacksmithing entries where one visible menu row can craft different CreateEntries based on the selected ore type.

+
+ +
+

graniteMake: number array
+ Used by Masonry entries where one visible menu row can craft different CreateEntries based on the selected granite type.

+
+ +
+

craftComplete: object
+ Optional post-crafting behavior. This lets the JSON entry request special handling after the item is successfully crafted.

+
+
+ +

Era Restrictions

+

Craft entries can be limited by shard era. This is useful for keeping newer content hidden on older-era shards.

+ + + +
+
{
+	"makeID": 3018,
+	"label": "Glass Sword",
+	"customName": "glass sword",
+	"page": 2,
+	"timerID": 2,
+	"minEra": "sa",
+	"harvest": [13504]
+}
+ +

This entry only appears when the shard era is Stygian Abyss or later.

+
+ +

Common era values include:

+

t2a, uor, lbr, aos, se, ml, sa, hs, tol

+ +

Recipe Locked Crafting

+

An entry with a recipeID requires the player to know that recipe before the item can be crafted. This allows custom shards to add rare recipe scrolls or progression-based unlocks without changing the menu script.

+ + + +
+
{
+	"makeID": 3500,
+	"label": "Tall 18th Anniversary Vase",
+	"dictID": 14057,
+	"page": 1,
+	"timerID": 1,
+	"recipeID": 3500,
+	"minEra": "tol",
+	"harvest": [14011]
+}
+ +

This item requires recipe 3500 and only appears in Time of Legends or later.

+
+ +

Custom Names

+

If an item does not have a dictionary entry, or if a shard wants a different name shown in the menu, use customName.

+ + + +
+
{
+	"makeID": 3012,
+	"label": "Hollow Prism",
+	"customName": "hollow prism",
+	"page": 1,
+	"timerID": 1,
+	"minEra": "ml",
+	"harvest": [13504]
+}
+ +

The menu will display hollow prism instead of looking up a dictionary entry.

+
+ +

Item Detail Resources

+

The harvest field controls what resource names are shown in the item detail gump. This is for display only. The real resource amounts and item IDs still come from the CreateEntry in the create system.

+ + + +
+
{
+	"makeID": 281,
+	"label": "Potion Keg",
+	"dictID": 11946,
+	"page": 7,
+	"timerID": 7,
+	"harvest": [10642, 11861, 10612, 10928]
+}
+ +

This lets the item detail gump show multiple needed material labels, such as barrel parts and potion-related materials.

+
+ + + +
+
{
+	"makeID": 308,
+	"label": "Open Keg",
+	"dictID": 10642,
+	"page": 3,
+	"timerID": 3,
+	"harvest": [10611, 10612, 11860],
+	"harvestNames": ["Barrel Staves", "Barrel Lid", "Barrel Hoops"]
+}
+ +

Use harvestNames when the default dictionary label is not clear enough for players or admins.

+
+ +

Post-Crafting Behavior

+

Some crafted items need special behavior after they are made. The JSON system supports this through the craftComplete object.

+ + + +
+
+

gemJewelry
+ Used for gem-based jewelry. The crafted jewelry is named after the gem used.

+
+ +
+

lockableContainer
+ Used for crafted containers that can receive a lock and key if the crafter has enough Tinkering skill.

+
+ +
+

autoIdentifyPotion
+ Used for alchemy potions. Crafted potions are automatically identified for the crafter.

+
+ +
+

craftedMap
+ Used for crafted maps. The map receives drawn map data based on the crafter's Cartography skill and position.

+
+
+ + + +
+
{
+	"makeID": 243,
+	"label": "Bracelet",
+	"dictID": 11900,
+	"page": 5,
+	"timerID": 5,
+	"requiresGemTarget": true,
+	"harvest": [10015, 12005],
+	"craftComplete": { "type": "gemJewelry" }
+}
+ +

This entry crafts a bracelet, requires a gem target and uses the selected gem name as part of the crafted item's name.

+
+ +

Blacksmithing and Masonry Resource Variants

+

Some crafting menus have one visible menu row, but the final CreateEntry changes depending on the selected resource. Blacksmithing uses oreMake, while Masonry uses graniteMake.

+ + + +
+
{
+	"buttonID": 100,
+	"label": "Ringmail Gloves",
+	"dictID": 10289,
+	"page": 1,
+	"timerID": 1,
+	"oreMake": [1, 101, 201, 301, 401, 501, 601, 701, 801],
+	"harvest": [10015]
+}
+ +

The first value is used for iron, the second for dull copper, the third for shadow iron and so on. The resource order comes from resourcemap.json.

+
+ +

Resource Map

+

The file resourcemap.json defines resource sets used by the crafting menus. It controls the resource display name, item ID, hue, selected resource index and optional skill requirement for resource selection menus.

+ + + +
+
{
+	"resourceSet": "ore",
+	"label": "Ore",
+	"tempTag": "ORE",
+	"defaultIndex": 0,
+	"items": [
+		{ "index": 0, "label": "Iron", "dictID": 10291, "itemID": 7154, "hue": 0, "minSkill": 0 },
+		{ "index": 1, "label": "Dull Copper", "dictID": 10203, "itemID": 7154, "hue": 2419, "minSkill": 650 },
+		{ "index": 2, "label": "Shadow Iron", "dictID": 10204, "itemID": 7154, "hue": 2406, "minSkill": 700 }
+	]
+}
+ +

This defines selectable ore types for crafting menus. The menu can count the player's matching resources by using the item ID and hue from the selected entry.

+
+ + + +
+
+

resourceSet: text
+ Unique name for this resource group. Examples: ore, granite, dragonScales, wood, tailoring.

+
+ +
+

label: text
+ Readable label for admins editing the resource map.

+
+ +
+

dictID: number
+ Optional default dictionary entry for the resource set.

+
+ +
+

tempTag: text
+ Temp tag used to remember the player's selected resource. Examples: ORE, Granite, Scale.

+
+ +
+

defaultIndex: number
+ Which resource index is used if the player has not selected anything yet.

+
+ +
+

items: array
+ List of resources in the set. Each item can define index, label, dictID, itemID, hue and minSkill.

+
+ +
+

itemID: number
+ Item ID used when counting the player's resources.

+
+ +
+

hue: number
+ Item hue used when counting the player's resources. Use 0 for normal uncolored resources.

+
+ +
+

minSkill: number
+ Optional skill requirement for selecting this resource. For ores this is usually Mining skill. For scales this can be Blacksmithing skill or left at 0.

+
+
+ +

Grouped Resources

+

Some resource sets count more than one item ID. For example, wood can count both logs and boards, and tailoring can count leather and hides. These grouped resources do not need an index for every item because the menu adds them together.

+ + + +
+
{
+	"resourceSet": "wood",
+	"label": "Wood",
+	"dictID": 10687,
+	"items": [
+		{ "label": "Logs", "itemID": 7136, "hue": 0 },
+		{ "label": "Boards", "itemID": 7127, "hue": 0 }
+	]
+}
+ +

This lets the crafting menu show one wood count made from both logs and boards.

+
+ +

Adding a New Crafting Entry

+

Most new craftables can be added with the following steps:

+
    +
  1. Add or confirm the item exists in the CreateEntry system.
  2. +
  3. Add a dictionary entry for the menu label, or decide on a customName.
  4. +
  5. Add a new entry to the correct crafting JSON file.
  6. +
  7. Set makeID, page and timerID.
  8. +
  9. Add harvest entries so the item detail gump shows useful material names.
  10. +
  11. Add optional fields such as recipeID, minEra, maxEra or craftComplete.
  12. +
  13. Reload scripts or restart UOX3, then test the crafting menu and item detail gump.
  14. +
+ + + +
+
{
+	"makeID": 5000,
+	"label": "Mythril Gearbox",
+	"customName": "mythril gearbox",
+	"page": 7,
+	"timerID": 7,
+	"recipeID": 5000,
+	"minEra": "ml",
+	"harvest": [10015, 11863],
+	"harvestNames": ["Mythril Ingots", "Gears"]
+}
+ +

This entry adds a custom item to a crafting page, gives it a custom menu name, requires a recipe, limits it to Mondain's Legacy or later and gives clearer resource names in the detail gump.

+
+ +

Adding a New Resource

+

To add a new selectable resource such as a new ore, granite or scale type, add a new item entry to the correct resource set in resourcemap.json. The new entry should have a unique index, display label, dictionary ID, item ID, hue and skill requirement.

+ + + +
+
{
+	"index": 9,
+	"label": "Mythril",
+	"dictID": 25000,
+	"itemID": 7154,
+	"hue": 2200,
+	"minSkill": 1000
+}
+ +

After adding this to the ore resource set, the ore selection menu can show Mythril and count Mythril ingots by item ID and hue.

+
+ +

Important Notes

+
    +
  • The JSON files control menu data, not the low-level item creation rules.
  • +
  • The actual crafted item, resource consumption, skill checks, sounds and delays still come from the CreateEntry system.
  • +
  • makeID, oreMake and graniteMake values must point to valid CreateEntries.
  • +
  • label is for admin readability. Use dictID or customName for menu display text.
  • +
  • craftComplete only supports behavior types that the crafting complete script knows how to handle.
  • +
  • If an entry does not appear, check its page, minEra, maxEra and recipe requirement.
  • +
  • If resource counts look wrong, check the itemID and hue in resourcemap.json.
  • +
From 40876a824c5f8f6b32666d7d531a180d45c8fc95 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 14 May 2026 14:43:11 -0500 Subject: [PATCH 43/43] custom crafting --- data/js/jsdata/crafting/artcraft.json | 18 + data/js/jsdata/crafting/crafttools.json | 103 +++ data/js/jsdata/crafting/customcrafts.json | 44 ++ data/js/jse_fileassociations.scp | 1 + data/js/skill/craft/crafttool.js | 358 ++++----- data/js/skill/craft/customcraft.js | 846 ++++++++++++++++++++++ data/js/skill/craft/itemdetailgump.js | 25 +- 7 files changed, 1227 insertions(+), 168 deletions(-) create mode 100644 data/js/jsdata/crafting/artcraft.json create mode 100644 data/js/jsdata/crafting/crafttools.json create mode 100644 data/js/jsdata/crafting/customcrafts.json create mode 100644 data/js/skill/craft/customcraft.js diff --git a/data/js/jsdata/crafting/artcraft.json b/data/js/jsdata/crafting/artcraft.json new file mode 100644 index 000000000..7de867713 --- /dev/null +++ b/data/js/jsdata/crafting/artcraft.json @@ -0,0 +1,18 @@ +[ + { + "makeID": 6000, + "label": "Charcoal Sketch", + "customName": "charcoal sketch", + "page": 1, + "timerID": 1, + "harvest": [ 10016 ] + }, + { + "makeID": 6001, + "label": "Canvas Painting", + "customName": "canvas painting", + "page": 2, + "timerID": 2, + "harvest": [ 10016, 10015 ] + } +] diff --git a/data/js/jsdata/crafting/crafttools.json b/data/js/jsdata/crafting/crafttools.json new file mode 100644 index 000000000..1b15fa2b1 --- /dev/null +++ b/data/js/jsdata/crafting/crafttools.json @@ -0,0 +1,103 @@ +[ + { + "craft": "carpentry", + "craftIndex": 1, + "scriptID": 4025, + "legacyScriptID": 4006, + "maxPage": 10, + "toolIDs": [ 4134, 4135, 4136, 4137, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4324, 4325, 4326 ] + }, + { + "craft": "alchemy", + "craftIndex": 2, + "scriptID": 4028, + "legacyScriptID": 4007, + "maxPage": 4, + "toolIDs": [ 3739 ] + }, + { + "craft": "fletching", + "craftIndex": 3, + "scriptID": 4029, + "legacyScriptID": 4005, + "maxPage": 3, + "toolIDs": [ 4130, 7121, 7124 ] + }, + { + "craft": "tailoring", + "craftIndex": 4, + "scriptID": 4030, + "legacyScriptID": 4004, + "maxPage": 8, + "toolIDs": [ 3997 ] + }, + { + "craft": "blacksmithing", + "craftIndex": 5, + "scriptID": 4023, + "legacyReturnTrue": true, + "maxPage": 7, + "specialPages": [ + { + "page": 8, + "function": "Page8" + } + ], + "toolIDs": [ 4027, 4028, 5091, 5092 ] + }, + { + "craft": "cooking", + "craftIndex": 6, + "scriptID": 4034, + "legacyScriptID": 104, + "maxPage": 4, + "toolIDs": [ 4163, 2431, 2530, 4158 ] + }, + { + "craft": "tinkering", + "craftIndex": 7, + "scriptID": 4032, + "legacyScriptID": 4003, + "maxPage": 9, + "sectionIDs": [ "tinkerstools" ], + "toolIDs": [ 7864, 7865, 7866, 7867, 7868 ] + }, + { + "craft": "cartography", + "craftIndex": 8, + "scriptID": 4035, + "maxPage": 1, + "sectionIDs": [ "mapmakerspen" ] + }, + { + "craft": "glassblowing", + "craftIndex": 9, + "scriptID": 4036, + "maxPage": 1, + "sectionIDs": [ "blowpipe" ], + "requiredTag": "GlassBlowing", + "requiredTagMessage": 6300 + }, + { + "craft": "masonry", + "craftIndex": 10, + "scriptID": 4037, + "maxPage": 9, + "sectionIDs": [ "malletandchisel" ], + "requiredTag": "StoneCrafting", + "requiredTagMessage": 6297, + "specialPages": [ + { + "page": 20, + "function": "Page20" + } + ] + }, + { + "craft": "artcraft", + "craftIndex": 100, + "scriptID": 4040, + "maxPage": 2, + "sectionIDs": [ "paintbrush" ] + } +] \ No newline at end of file diff --git a/data/js/jsdata/crafting/customcrafts.json b/data/js/jsdata/crafting/customcrafts.json new file mode 100644 index 000000000..7b1a6ed15 --- /dev/null +++ b/data/js/jsdata/crafting/customcrafts.json @@ -0,0 +1,44 @@ +[ + { + "craft": "artcraft", + "mapFile": "artcraft", + "skillID": 0, + "maxPage": 2, + "menuName": "Art Craft", + "showLastTen": true, + + "allowRepair": true, + "repairText": "Restore Artwork", + "repairTargetText": "Select the artwork you want to restore.", + "repairSuccessText": "You carefully restore the artwork.", + "repairFailedText": "You fail to restore the artwork.", + "repairFullText": "That artwork does not need restoration.", + "repairWrongMaterialText": "That is not artwork you can restore.", + "repairSkillName": "itemid", + "repairMinSkill": 250, + "repairMaterialType": "cloth", + "repairSound": 42, + + "allowRecycle": true, + "recycleText": "Recover Materials", + "recycleTargetText": "Select the artwork you want to recover materials from.", + "recycleSuccessText": "You recover usable materials from the artwork.", + "recycleWrongMaterialText": "You cannot recover materials from that.", + "recycleMaterialType": "cloth", + "recycleResourceID": "0x0EED", + "recycleResourceHue": 0, + "recycleResourceAmount": 1, + "recycleResourceName": "reclaimed art supplies", + + "categories": [ + { + "page": 1, + "label": "Drawings" + }, + { + "page": 2, + "label": "Paintings" + } + ] + } +] \ No newline at end of file diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 74fe04152..6a4116b84 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -245,6 +245,7 @@ 4036=skill/craft/glassblowing.js 4037=skill/craft/masonry.js 4038=skill/craft/craftmap_registry.js +4040=skill/craft/customcraft.js 4050=skill/mining.js 4055=skill/snooping.js diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 34dc95c0f..a2f01ae33 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -11,6 +11,178 @@ const CookingID = 4034; const CartographyID = 4035; const GlassblowingID = 4036; const MasonryID = 4037; +var craftToolMap = null; +var craftToolMapLoaded = false; +var craftToolMapLoadError = false; + +/** @type { () => object|null } */ +function LoadCraftToolMap() +{ + if( craftToolMapLoaded ) + return craftToolMap; + + craftToolMap = null; + craftToolMapLoaded = false; + craftToolMapLoadError = false; + + var craftToolFile = new UOXCFile(); + craftToolFile.Open( "crafttools.json", "r", "crafting", true ); + + if( craftToolFile == null || craftToolFile.Length() < 0 ) + { + Console.Error( "CraftTool system: Unable to open js/jsdata/crafting/crafttools.json" ); + craftToolMapLoadError = true; + return null; + } + + var fileText = ""; + while( !craftToolFile.EOF() ) + { + var rawLine = craftToolFile.ReadUntil( "\n" ); + if( rawLine != null && typeof( rawLine ) != "undefined" ) + { + fileText += rawLine; + } + } + + craftToolFile.Close(); + craftToolFile.Free(); + + fileText = SanitizeCraftToolJsonText( fileText ); + + try + { + craftToolMap = JSON.parse( fileText ); + } + catch( error ) + { + Console.Error( "CraftTool system: Failed to parse crafttools.json: " + error ); + Console.Error( "CraftTool system: crafttools.json length after sanitize: " + fileText.length ); + Console.Error( "CraftTool system: last char code: " + fileText.charCodeAt( fileText.length - 1 )); + craftToolMapLoadError = true; + return null; + } + + if( !IsCraftToolArrayValue( craftToolMap )) + { + Console.Error( "CraftTool system: crafttools.json must contain a JSON array." ); + craftToolMapLoadError = true; + return null; + } + + craftToolMapLoaded = true; + Console.Print( "CraftTool system: Loaded " + craftToolMap.length + " craft tool entries.\n" ); + + return craftToolMap; +} + +/** @type { ( pUser: Character, iUsed: Item ) => object|null } */ +function GetCraftToolEntry( pUser, iUsed ) +{ + var toolMap = LoadCraftToolMap(); + + if( !toolMap ) + return null; + + for( var i = 0; i < toolMap.length; i++ ) + { + var entry = toolMap[i]; + + if( CraftToolMatchesEntry( iUsed, entry )) + return entry; + } + + return null; +} + +/** @type { ( iUsed: Item, entry: object ) => boolean } */ +function CraftToolMatchesEntry( iUsed, entry ) +{ + if( !entry ) + return false; + + if( entry.sectionIDs && IsCraftToolArrayValue( entry.sectionIDs )) + { + for( var i = 0; i < entry.sectionIDs.length; i++ ) + { + if( iUsed.sectionID == entry.sectionIDs[i] ) + return true; + } + } + + if( entry.toolIDs && IsCraftToolArrayValue( entry.toolIDs )) + { + for( var j = 0; j < entry.toolIDs.length; j++ ) + { + if( iUsed.id == entry.toolIDs[j] ) + return true; + } + } + + return false; +} + +/** @type { ( value: any ) => boolean } */ +function IsCraftToolArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} + +/** @type { ( text: string ) => string } */ +function SanitizeCraftToolJsonText( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + return ""; + + text = String( text ); + + if( text.length > 0 && text.charCodeAt( 0 ) == 65279 ) + text = text.substring( 1 ); + + text = text.split( "\r\n" ).join( "\n" ); + text = text.split( "\r" ).join( "\n" ); + text = text.split( String.fromCharCode( 160 ) ).join( " " ); + text = text.split( String.fromCharCode( 255 ) ).join( "" ); + text = text.split( "\t" ).join( " " ); + + text = TrimCraftToolString( text ); + + var lastBracket = text.lastIndexOf( "]" ); + if( lastBracket >= 0 ) + text = text.substring( 0, lastBracket + 1 ); + + return TrimCraftToolString( text ); +} + +/** @type { ( text: string ) => string } */ +function TrimCraftToolString( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + return ""; + + return text.replace( /^\s+|\s+$/g, "" ); +} + +/** @type { ( specialPages: object ) => object|null } */ +function BuildSpecialPageMap( specialPages ) +{ + if( !specialPages || !IsCraftToolArrayValue( specialPages )) + return null; + + var pageMap = {}; + + for( var i = 0; i < specialPages.length; i++ ) + { + var entry = specialPages[i]; + + if( entry && typeof entry.page != "undefined" && entry["function"] ) + { + pageMap[entry.page] = entry["function"]; + } + } + + return pageMap; +} /** * Ensure the tool is usable: charges > 0, in range, not locked down, @@ -104,30 +276,6 @@ function openCraftMenu(pUser, socket, scriptID, craftIndex, maxPage, specialPage } } -// Tool ID helpers for readability -function isCarpentryTool( id ) -{ - return (( id >= 0x1026 && id <= 0x1029 ) || - ( id >= 0x102C && id <= 0x102F ) || - ( id >= 0x1030 && id <= 0x1035 ) || - ( id >= 0x10E4 && id <= 0x10E6 )); -} - -function isFletchingTool( id ) -{ - return ( id == 0x1022 || id == 0x1BD1 || id == 0x1BD4 ); -} - -function isBlacksmithTool( id ) -{ - return ( id == 0x0FBB || id == 0x0FBC || id == 0x13E3 || id == 0x13E4 ); -} - -function isCookingTool( id ) -{ - return ( id == 0x1043 || id == 0x097F || id == 0x09E2 || id == 0x103E ); -} - // --------------------------------------------------------------------------- // Main entry // --------------------------------------------------------------------------- @@ -144,165 +292,43 @@ function onUseChecked( pUser, iUsed ) // Save tool on socket so skill gumps can reference it socket.tempObj = iUsed; - var id = iUsed.id; - // ------------------------------------------------------------------- - // Carpentry - // ------------------------------------------------------------------- - if( isCarpentryTool( id )) - { - if( enableUOX3Craft == 1 ) - { - // Old UOX3 carpentry gump - TriggerEvent( 4006, "onUseChecked", pUser, iUsed ); - return false; - } + var craftToolEntry = GetCraftToolEntry( pUser, iUsed ); - // New carpentry menu – Pages 1–10 - openCraftMenu( pUser, socket, CarpentryID, 1, 10 ); + if( !craftToolEntry ) return false; - } - - // ------------------------------------------------------------------- - // Alchemy (mortar and pestle) - // ------------------------------------------------------------------- - if( id == 0x0E9B ) - { - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4007, "onUseChecked", pUser, iUsed ); - return false; - } - - // New alchemy menu – Pages 1–4 - openCraftMenu( pUser, socket, AlchemyID, 2, 4 ); - return false; - } - // ------------------------------------------------------------------- - // Bowcraft / Fletching - // ------------------------------------------------------------------- - if( isFletchingTool( id )) + if( craftToolEntry.requiredTag && pUser.GetTag( craftToolEntry.requiredTag ) == 0 ) { - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4005, "onUseChecked", pUser, iUsed ); - return false; - } - - // New fletching menu – Pages 1–3 - openCraftMenu( pUser, socket, FletchingID, 3, 3 ); - return false; - } - - // ------------------------------------------------------------------- - // Tailoring (sewing kit) - // ------------------------------------------------------------------- - if( id == 0x0F9D ) - { - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4004, "onUseChecked", pUser, iUsed ); - return false; - } + if( craftToolEntry.requiredTagMessage ) + socket.SysMessage( GetDictionaryEntry( craftToolEntry.requiredTagMessage, socket.language )); - // New tailoring menu – Pages 1–8 - openCraftMenu( pUser, socket, TailoringID, 4, 8 ); return false; } - // ------------------------------------------------------------------- - // Blacksmithing (tongs, smith hammers) - // ------------------------------------------------------------------- - if( isBlacksmithTool( id )) + if( enableUOX3Craft == 1 ) { - if( enableUOX3Craft == 1 ) - { - // Fall back to original blacksmith behavior when enabled + if( craftToolEntry.legacyReturnTrue ) return true; - } - - // New blacksmithing menu – Pages 1–7 = PageX, page 8 = Page8 - openCraftMenu( pUser, socket, BlacksmithingID, 5, 7, { 8: "Page8" } ); - return false; - } - // ------------------------------------------------------------------- - // Cooking (skillet, flour sifter, rolling pin, etc.) - // ------------------------------------------------------------------- - if( isCookingTool( id )) - { - if( enableUOX3Craft == 1 ) + if( craftToolEntry.legacyScriptID ) { - // Old-school cooking: use raw food with heat sources, or legacy script - TriggerEvent( 104, "onUseChecked", pUser, iUsed ); + TriggerEvent( craftToolEntry.legacyScriptID, "onUseChecked", pUser, iUsed ); return false; } - - // New cooking menu – Pages 1–4 - openCraftMenu( pUser, socket, CookingID, 6, 4 ); - return false; } - // ------------------------------------------------------------------- - // Tinkering (tinker's tools) - // ------------------------------------------------------------------- - if( iUsed.sectionID == "tinkerstools" || // optional if you use sectionID - id == 0x1EB8 || id == 0x1EB9 || id == 0x1EBA || id == 0x1EBB || id == 0x1EBC ) - { - if( enableUOX3Craft == 1 ) - { - TriggerEvent( 4003, "onUseChecked", pUser, iUsed ); - return false; - } - - // New tinkering menu – Pages 1–9 - openCraftMenu( pUser, socket, TinkeringID, 7, 9 ); - return false; - } - - // ------------------------------------------------------------------- - // Cartography (mapmaker's pen) - // ------------------------------------------------------------------- - if( iUsed.sectionID == "mapmakerspen" ) - { - // Only one page currently – PageX with page 1 - openCraftMenu( pUser, socket, CartographyID, 8, 1 ); - return false; - } - - // ------------------------------------------------------------------- - // Glassblowing (blow pipe) - // ------------------------------------------------------------------- - if( iUsed.sectionID == "blowpipe" ) - { - if( pUser.GetTag( "GlassBlowing" ) == 0 ) - { - // NOTE: fixed .Language -> .language here - socket.SysMessage( GetDictionaryEntry( 6300, socket.language )); // You haven't learned glassblowing. - return false; - } - - // New glassblowing menu – Page 1 only for now - openCraftMenu( pUser, socket, GlassblowingID, 9, 1 ); - return false; - } - - // ------------------------------------------------------------------- - // Masonry (mallet and chisel) - // ------------------------------------------------------------------- - if( iUsed.sectionID == "malletandchisel" ) - { - if( pUser.GetTag( "StoneCrafting" ) == 0 ) - { - socket.SysMessage( GetDictionaryEntry( 6297, socket.language )); // You haven't learned masonry. - return false; - } - - // Masonry: Pages 1–9 = PageX, Page 20 = Page20 - openCraftMenu( pUser, socket, MasonryID, 10, 9, { 20: "Page20" } ); - return false; - } + if( craftToolEntry.craft ) + pUser.SetTempTag( "CUSTOMCRAFT", craftToolEntry.craft ); + + openCraftMenu( + pUser, + socket, + craftToolEntry.scriptID, + craftToolEntry.craftIndex, + craftToolEntry.maxPage, + BuildSpecialPageMap( craftToolEntry.specialPages ) + ); return false; } \ No newline at end of file diff --git a/data/js/skill/craft/customcraft.js b/data/js/skill/craft/customcraft.js new file mode 100644 index 000000000..8ddb3ac58 --- /dev/null +++ b/data/js/skill/craft/customcraft.js @@ -0,0 +1,846 @@ +/// +// @ts-check + +var textHue = 0x480; +var customCraftID = 4040; +var craftMapRegistryID = 4038; +var itemDetailsScriptID = 4026; +var itemsPerPage = 10; +var displayUnlearnedRecipes = true; +var coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); + +var customCraftDefinitions = null; +var customCraftDefinitionsLoaded = false; +var customCraftDefinitionsLoadError = false; +var CustomCraftMap = {}; + +/** @type { () => object|null } */ +function LoadCustomCraftDefinitions() +{ + if( customCraftDefinitionsLoaded ) + return customCraftDefinitions; + + customCraftDefinitions = null; + customCraftDefinitionsLoaded = false; + customCraftDefinitionsLoadError = false; + + var customCraftFile = new UOXCFile(); + customCraftFile.Open( "customcrafts.json", "r", "crafting", true ); + + if( customCraftFile == null || customCraftFile.Length() < 0 ) + { + Console.Error( "CustomCraft system: Unable to open js/jsdata/crafting/customcrafts.json" ); + customCraftDefinitionsLoadError = true; + return null; + } + + var fileText = ""; + while( !customCraftFile.EOF() ) + { + var rawLine = customCraftFile.ReadUntil( "\n" ); + if( rawLine != null && typeof( rawLine ) != "undefined" ) + { + fileText += rawLine; + } + } + + customCraftFile.Close(); + customCraftFile.Free(); + + fileText = SanitizeCustomCraftJsonText( fileText ); + + try + { + customCraftDefinitions = JSON.parse( fileText ); + } + catch( error ) + { + Console.Error( "CustomCraft system: Failed to parse customcrafts.json: " + error ); + customCraftDefinitionsLoadError = true; + return null; + } + + if( !IsCustomCraftArrayValue( customCraftDefinitions )) + { + Console.Error( "CustomCraft system: customcrafts.json must contain a JSON array." ); + customCraftDefinitionsLoadError = true; + return null; + } + + customCraftDefinitionsLoaded = true; + Console.Print( "CustomCraft system: Loaded " + customCraftDefinitions.length + " custom craft definitions.\n" ); + + return customCraftDefinitions; +} + +/** @type { ( craftName: string ) => object|null } */ +function GetCustomCraftDefinition( craftName ) +{ + var definitions = LoadCustomCraftDefinitions(); + + if( !definitions ) + return null; + + for( var i = 0; i < definitions.length; i++ ) + { + if( definitions[i] && definitions[i].craft == craftName ) + return definitions[i]; + } + + return null; +} + +/** @type { ( pUser: Character ) => object|null } */ +function GetActiveCustomCraftDefinition( pUser ) +{ + var craftName = pUser.GetTempTag( "CUSTOMCRAFT" ); + + if( !craftName ) + return null; + + return GetCustomCraftDefinition( craftName ); +} + +/** @type { ( craftDefinition: object ) => boolean } */ +function LoadCustomCraftMap( craftDefinition ) +{ + CustomCraftMap = {}; + + if( !craftDefinition ) + return false; + + var mapFile = craftDefinition.mapFile || craftDefinition.craft; + var craftEntries = TriggerEvent( craftMapRegistryID, "CraftMapRegistry", mapFile ); + + if( !craftEntries || !IsCustomCraftArrayValue( craftEntries )) + { + Console.Warning( "CustomCraft system: Unable to load custom craft map data for " + mapFile + "." ); + return false; + } + + for( var i = 0; i < craftEntries.length; i++ ) + { + var entry = craftEntries[i]; + + if( !entry || typeof entry.makeID == "undefined" ) + continue; + + if( entry.skill === undefined && typeof craftDefinition.skillID != "undefined" ) + entry.skill = craftDefinition.skillID; + + CustomCraftMap[entry.makeID] = entry; + } + + Console.Print( "CustomCraft system: Loaded " + craftEntries.length + " entries for " + mapFile + ".\n" ); + return true; +} + +/** @type { ( socket: Socket, pUser: Character, pageNum: number ) => void } */ +function PageX( socket, pUser, pageNum ) +{ + if( !socket || !ValidateObject( pUser )) + return; + + var craftDefinition = GetActiveCustomCraftDefinition( pUser ); + + if( !craftDefinition ) + { + socket.SysMessage( "Custom craft definition was not found." ); + return; + } + + if( !CustomCraftMap || Object.keys( CustomCraftMap ).length == 0 ) + { + if( !LoadCustomCraftMap( craftDefinition )) + { + socket.SysMessage( "Custom craft map failed to load." ); + return; + } + } + + var pageItems = []; + + if( pageNum == 999 ) + { + var lastTenRaw = pUser.GetTempTag( "LastTenCustomCraft_" + craftDefinition.craft ) || ""; + var split = lastTenRaw.split( "," ); + + for( var i = 0; i < split.length; i++ ) + { + var value = parseInt( split[i], 10 ); + if( !isNaN( value ) && CustomCraftMap[value] ) + pageItems.push( value ); + } + } + else + { + for( var makeIDStr in CustomCraftMap ) + { + if( !CustomCraftMap.hasOwnProperty( makeIDStr )) + continue; + + var makeID = parseInt( makeIDStr, 10 ); + var data = CustomCraftMap[makeID]; + + if( data.page == pageNum && EraOK( data )) + { + var needsRecipe = data.recipeID; + var showAll = displayUnlearnedRecipes; + + if( !needsRecipe || showAll || HasLearnedRecipe( pUser, needsRecipe )) + pageItems.push( makeID ); + } + } + + pageItems.sort( function( a, b ) + { + var entryA = CustomCraftMap[a]; + var entryB = CustomCraftMap[b]; + + if( entryA && entryB ) + { + if( entryA.sortOrder != undefined && entryB.sortOrder != undefined ) + return entryA.sortOrder - entryB.sortOrder; + + if( entryA.dictID && entryB.dictID ) + return entryA.dictID - entryB.dictID; + } + + return a - b; + }); + } + + var subPage = pUser.GetTempTag( "subPage" ) || 1; + var totalSubPages = Math.ceil( pageItems.length / itemsPerPage ); + + if( totalSubPages < 1 ) + totalSubPages = 1; + + if( subPage < 1 ) + subPage = 1; + + if( subPage > totalSubPages ) + subPage = totalSubPages; + + pUser.SetTempTag( "page", pageNum ); + pUser.SetTempTag( "subPage", subPage ); + + var startIndex = ( subPage - 1 ) * itemsPerPage; + var endIndex = Math.min( startIndex + itemsPerPage, pageItems.length ); + + var customGump = new Gump(); + BuildCustomCraftFrame( customGump, socket, pUser, craftDefinition, pageNum ); + + for( var j = startIndex; j < endIndex; j++ ) + { + var index = j - startIndex; + var makeEntryID = pageItems[j]; + var entry = CustomCraftMap[makeEntryID]; + var entryText = GetCustomCraftEntryText( entry, socket ); + + customGump.AddButton( 220, 60 + ( index * 20 ), 4005, 4007, 1, 0, makeEntryID ); + customGump.AddText( 255, 60 + ( index * 20 ), textHue, entryText ); + customGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 20000 + makeEntryID ); + } + + if( pageItems.length == 0 ) + customGump.AddText( 220, 60, textHue, "No items available on this page." ); + + if( subPage > 1 ) + { + customGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + customGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); + } + + if( subPage < totalSubPages ) + { + customGump.AddButton( 370, 260, 4005, 4007, 1, 0, 9000 + ( subPage + 1 )); + customGump.AddHTMLGump( 405, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10100, socket.language ) + "" ); + } + + customGump.Send( socket ); + customGump.Free(); +} + +/** @type { ( customGump: Gump, socket: Socket, pUser: Character, craftDefinition: object, pageNum: number ) => void } */ +function BuildCustomCraftFrame( customGump, socket, pUser, craftDefinition, pageNum ) +{ + customGump.AddPage( 0 ); + customGump.AddBackground( 0, 0, 530, 437, 5054 ); + customGump.AddTiledGump( 10, 10, 510, 22, 2624 ); + customGump.AddTiledGump( 10, 292, 150, 45, 2624 ); + customGump.AddTiledGump( 165, 292, 355, 45, 2624 ); + customGump.AddTiledGump( 10, 342, 510, 85, 2624 ); + customGump.AddTiledGump( 10, 37, 200, 250, 2624 ); + customGump.AddTiledGump( 215, 37, 305, 250, 2624 ); + customGump.AddCheckerTrans( 10, 10, 510, 417 ); + + var menuName = craftDefinition.menuName || craftDefinition.craft || "Custom Craft"; + + customGump.AddHTMLGump( 0, 12, 530, 20, 0, 0, "
" + menuName + "
" ); + customGump.AddHTMLGump( 0, 37, 220, 22, 0, 0, "
" + GetDictionaryEntry( 10286, socket.language ) + "
" ); + customGump.AddHTMLGump( 230, 37, 280, 22, 0, 0, "
" + GetDictionaryEntry( 10287, socket.language ) + "
" ); + customGump.AddHTMLGump( 10, 302, 150, 25, 0, 0, "
" + GetDictionaryEntry( 10288, socket.language ) + "
" ); + + var categories = craftDefinition.categories || []; + + for( var i = 0; i < categories.length; i++ ) + { + var category = categories[i]; + var categoryPage = category.page || ( i + 1 ); + var categoryText = category.label || ( "Page " + categoryPage ); + + customGump.AddButton( 20, 60 + ( i * 20 ), 4005, 4007, 1, 0, 10000 + categoryPage ); + customGump.AddText( 55, 60 + ( i * 20 ), textHue, categoryText ); + } + + if( craftDefinition.showLastTen ) + { + customGump.AddButton( 20, 250, 4005, 4007, 1, 0, 10999 ); + customGump.AddText( 55, 250, textHue, "Last Ten" ); + } + + if( craftDefinition.allowRepair ) + { + customGump.AddButton( 20, 345, 4005, 4007, 1, 0, 90001 ); + customGump.AddText( 55, 345, textHue, GetCustomCraftText( craftDefinition, "repairText", "Repair Item" ) ); + } + + if( craftDefinition.allowRecycle ) + { + customGump.AddButton( 20, 365, 4005, 4007, 1, 0, 90002 ); + customGump.AddText( 55, 365, textHue, GetCustomCraftText( craftDefinition, "recycleText", "Recycle Item" ) ); + } +} + +/** @type { ( entry: object, socket: Socket ) => string } */ +function GetCustomCraftEntryText( entry, socket ) +{ + if( !entry ) + return "[Missing Entry]"; + + if( entry.customName ) + return entry.customName; + + if( entry.dictID ) + { + var dictText = GetDictionaryEntry( entry.dictID, socket.language ); + if( dictText && dictText != "" ) + return dictText; + } + + if( entry.label ) + return entry.label; + + return "[Unnamed Item: " + entry.makeID + "]"; +} + +/** @type { ( pSock: Socket, pButton: number, gumpData: any ) => void } */ +function onGumpPress( pSock, pButton, gumpData ) +{ + if( !pSock ) + return; + + var pUser = pSock.currentChar; + + if( !ValidateObject( pUser )) + return; + + var craftDefinition = GetActiveCustomCraftDefinition( pUser ); + + if( !craftDefinition ) + return; + + if( !CustomCraftMap || Object.keys( CustomCraftMap ).length == 0 ) + { + if( !LoadCustomCraftMap( craftDefinition )) + return; + } + + if( pButton == 0 ) + { + pSock.CloseGump( customCraftID + 0xffff, 0 ); + return; + } + + if( craftDefinition.allowRepair && pButton == 90001 ) + { + pSock.CustomTarget( 0, GetCustomCraftText( craftDefinition, "repairTargetText", "Select the item you want to repair." ) ); + return; + } + + if( craftDefinition.allowRecycle && pButton == 90002 ) + { + pSock.CustomTarget( 1, GetCustomCraftText( craftDefinition, "recycleTargetText", "Select the item you want to recycle." ) ); + return; + } + + if( pButton >= 10000 && pButton < 11000 ) + { + if( pButton == 10999 ) + PageX( pSock, pUser, 999 ); + else + PageX( pSock, pUser, pButton - 10000 ); + + return; + } + + if( pButton >= 8000 && pButton < 9000 ) + { + pUser.SetTempTag( "subPage", pButton - 8000 ); + PageX( pSock, pUser, pUser.GetTempTag( "page" ) || 1 ); + return; + } + + if( pButton >= 9000 && pButton < 10000 ) + { + pUser.SetTempTag( "subPage", pButton - 9000 ); + PageX( pSock, pUser, pUser.GetTempTag( "page" ) || 1 ); + return; + } + + if( pButton >= 20000 ) + { + ShowCustomCraftItemDetails( pSock, pUser, pButton - 20000 ); + return; + } + + var entry = CustomCraftMap[pButton]; + + if( !entry ) + return; + + if( !EraOK( entry )) + { + pSock.SysMessage( "That item is not available in this era." ); + return; + } + + if( entry.recipeID && !HasLearnedRecipe( pUser, entry.recipeID )) + { + TriggerEvent( 4022, "NeedRecipe", pSock, entry.recipeID ); + return; + } + + pUser.SetTempTag( "MAKELAST", pButton ); + StoreLastTenCustomCraft( pUser, craftDefinition, pButton ); + + pSock.CloseGump( customCraftID + 0xffff, 0 ); + MakeItem( pSock, pUser, pButton ); + pUser.StartTimer( 2000, entry.timerID || entry.page || 1, true ); +} + +/** @type { ( pSock: Socket, pUser: Character, makeID: number ) => void } */ +function ShowCustomCraftItemDetails( pSock, pUser, makeID ) +{ + var entry = CustomCraftMap[makeID]; + + if( !entry ) + return; + + pUser.SetTempTag( "ITEMDETAILS", makeID ); + pUser.SetTempTag( "Skill", entry.skill || 0 ); + pUser.SetTempTag( "needRecipeID", entry.recipeID || 0 ); + + ClearCustomCraftHarvestTags( pUser ); + + if( entry.harvest && IsCustomCraftArrayValue( entry.harvest )) + { + for( var i = 0; i < entry.harvest.length && i < 4; i++ ) + { + var tagName = ( i == 0 ? "Harvest" : "Harvest" + ( i + 1 )); + pUser.SetTempTag( tagName, entry.harvest[i] ); + } + } + + if( entry.harvestNames && IsCustomCraftArrayValue( entry.harvestNames )) + { + for( var j = 0; j < entry.harvestNames.length && j < 4; j++ ) + { + var nameTag = ( j == 0 ? "HarvestName" : "Harvest" + ( j + 1 ) + "Name" ); + pUser.SetTempTag( nameTag, entry.harvestNames[j] ); + } + } + + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); +} + +/** @type { ( pUser: Character, craftDefinition: object, makeID: number ) => void } */ +function StoreLastTenCustomCraft( pUser, craftDefinition, makeID ) +{ + if( !craftDefinition || !craftDefinition.showLastTen ) + return; + + var tagName = "LastTenCustomCraft_" + craftDefinition.craft; + var rawValue = pUser.GetTempTag( tagName ) || ""; + var split = rawValue.split( "," ); + var newList = [ makeID.toString() ]; + + for( var i = 0; i < split.length; i++ ) + { + var value = parseInt( split[i], 10 ); + + if( !isNaN( value ) && value != makeID && newList.length < 10 ) + newList.push( value.toString() ); + } + + pUser.SetTempTag( tagName, newList.join( "," ) ); +} + +/** @type { ( timerObj: Character, timerID: number ) => void } */ +function onTimer( timerObj, timerID ) +{ + if( !ValidateObject( timerObj )) + return; + + var socket = timerObj.socket; + + if( !socket ) + return; + + PageX( socket, timerObj, timerID ); +} + +/** @type { ( entry: object ) => boolean } */ +function EraOK( entry ) +{ + if( !entry ) + return false; + + if( entry.minEra && coreShardEra < EraStringToNum( entry.minEra )) + return false; + + if( entry.maxEra && coreShardEra > EraStringToNum( entry.maxEra )) + return false; + + return true; +} + +/** @type { ( pUser: Character, recipeID: number ) => boolean } */ +function HasLearnedRecipe( pUser, recipeID ) +{ + if( !recipeID || recipeID <= 0 ) + return true; + + return TriggerEvent( 4022, "NeedRecipe", pUser.socket, recipeID ); +} + +/** @type { ( pUser: Character ) => void } */ +function ClearCustomCraftHarvestTags( pUser ) +{ + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + pUser.SetTempTag( "HarvestName", null ); + pUser.SetTempTag( "Harvest2Name", null ); + pUser.SetTempTag( "Harvest3Name", null ); + pUser.SetTempTag( "Harvest4Name", null ); +} + +/** @type { ( value: any ) => boolean } */ +function IsCustomCraftArrayValue( value ) +{ + return Object.prototype.toString.call( value ) == "[object Array]"; +} + +/** @type { ( text: string ) => string } */ +function SanitizeCustomCraftJsonText( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + return ""; + + text = String( text ); + + if( text.length > 0 && text.charCodeAt( 0 ) == 65279 ) + text = text.substring( 1 ); + + text = text.split( "\r\n" ).join( "\n" ); + text = text.split( "\r" ).join( "\n" ); + text = text.split( String.fromCharCode( 160 ) ).join( " " ); + text = text.split( String.fromCharCode( 255 ) ).join( "" ); + text = text.split( "\t" ).join( " " ); + + text = TrimCustomCraftString( text ); + + var lastBracket = text.lastIndexOf( "]" ); + if( lastBracket >= 0 ) + text = text.substring( 0, lastBracket + 1 ); + + return TrimCustomCraftString( text ); +} + +/** @type { ( text: string ) => string } */ +function TrimCustomCraftString( text ) +{ + if( text == null || typeof( text ) == "undefined" ) + return ""; + + return text.replace( /^\s+|\s+$/g, "" ); +} + +/** @type { () => void } */ +function ReloadCustomCraftDefinitions() +{ + customCraftDefinitions = null; + customCraftDefinitionsLoaded = false; + customCraftDefinitionsLoadError = false; + + LoadCustomCraftDefinitions(); +} + +/** @type { ( craftDefinition: object, keyName: string, fallbackText: string ) => string } */ +function GetCustomCraftText( craftDefinition, keyName, fallbackText ) +{ + if( craftDefinition && craftDefinition[keyName] ) + return craftDefinition[keyName]; + + return fallbackText; +} + +/** @type { ( pSock: Socket, pUser: Character, targetObj: Item, craftDefinition: object ) => boolean } */ +function CheckCustomCraftTargetItem( pSock, pUser, targetObj, craftDefinition ) +{ + if( !ValidateObject( targetObj ) || !targetObj.isItem ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "invalidTargetText", "That is not a valid item." )); + return false; + } + + var ownerObj = GetPackOwner( targetObj, 0 ); + if( !ValidateObject( ownerObj ) || ownerObj.serial != pUser.serial ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "mustBeInPackText", "That item must be in your backpack." )); + return false; + } + + return true; +} + +/** @type { ( pUser: Character, stationIDs: any ) => boolean } */ +function HasNearbyCustomCraftStation( pUser, stationIDs ) +{ + if( !stationIDs || !IsCustomCraftArrayValue( stationIDs )) + return true; + + var nearbyStation = AreaItemFunction( "FindNearbyCustomCraftStation", pUser, 3, stationIDs ); + return nearbyStation != 0; +} + +/** @type { ( pUser: Character, trgItem: Item, stationIDs: any ) => boolean } */ +function FindNearbyCustomCraftStation( pUser, trgItem, stationIDs ) +{ + if( !ValidateObject( trgItem ) || !trgItem.isItem ) + return false; + + for( var i = 0; i < stationIDs.length; i++ ) + { + if( trgItem.id == stationIDs[i] ) + return true; + } + + return false; +} + +/** @type { ( pSock: Socket, pUser: Character, targetObj: Item, craftDefinition: object ) => void } */ +function RepairCustomCraftItem( pSock, pUser, targetObj, craftDefinition ) +{ + if( !CheckCustomCraftTargetItem( pSock, pUser, targetObj, craftDefinition )) + return; + + if( craftDefinition.repairStationIDs && !HasNearbyCustomCraftStation( pUser, craftDefinition.repairStationIDs )) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairNoStationText", "You need to be near the proper crafting station to repair that." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + if( craftDefinition.repairMaterialType ) + { + var materialType = TriggerEvent( 2506, "GetItemMaterialType", targetObj ); + if( materialType != craftDefinition.repairMaterialType ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairWrongMaterialText", "That item cannot be repaired with this craft." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + } + + if( targetObj.maxhp <= 0 ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairInvalidDurabilityText", "That item cannot be repaired." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + if( targetObj.health >= targetObj.maxhp ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairFullText", "That item is already fully repaired." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + var repairSkillID = craftDefinition.repairSkillID; + var repairSkillName = craftDefinition.repairSkillName; + var repairSkill = 0; + var repairSkillCap = 1000; + + if( typeof repairSkillID != "undefined" ) + { + repairSkill = pUser.skills[repairSkillID]; + repairSkillCap = pUser.skillCaps[repairSkillID]; + } + else if( repairSkillName ) + { + repairSkill = pUser.skills[repairSkillName]; + repairSkillCap = pUser.skillCaps[repairSkillName]; + } + + var minSkill = craftDefinition.repairMinSkill || 0; + if( repairSkill < minSkill ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairTooDifficultText", "You are not skilled enough to repair that." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + var missingHP = targetObj.maxhp - targetObj.health; + var repairDifficulty = Math.floor(( missingHP * 1000 ) / targetObj.maxhp ); + var minDifficulty = repairDifficulty - 250; + + if( minDifficulty < 0 ) + minDifficulty = 0; + + var maxDifficulty = repairDifficulty + 250; + if( maxDifficulty > repairSkillCap ) + maxDifficulty = repairSkillCap; + + if( RandomNumber( minDifficulty, 1000 ) < repairSkill ) + { + if( typeof repairSkillID != "undefined" ) + pUser.CheckSkill( repairSkillID, minDifficulty, maxDifficulty ); + + if( GetServerSetting( "ItemRepairDurabilityLoss" )) + targetObj.maxhp -= 1; + + targetObj.health = targetObj.maxhp; + + if( craftDefinition.repairSound ) + pSock.SoundEffect( craftDefinition.repairSound, true ); + + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairSuccessText", "You repair the item." )); + } + else + { + var damageLoss = craftDefinition.repairFailureDamage || 1; + targetObj.health -= damageLoss; + + if( targetObj.health <= 0 ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairDestroyedText", "The item has been destroyed." )); + targetObj.Delete(); + } + else + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "repairFailedText", "You fail to repair the item." )); + } + } + + RestartCustomCraftGump( pUser, craftDefinition ); +} + +/** @type { ( pSock: Socket, pUser: Character, targetObj: Item, craftDefinition: object ) => void } */ +function RecycleCustomCraftItem( pSock, pUser, targetObj, craftDefinition ) +{ + if( !CheckCustomCraftTargetItem( pSock, pUser, targetObj, craftDefinition )) + return; + + if( craftDefinition.recycleStationIDs && !HasNearbyCustomCraftStation( pUser, craftDefinition.recycleStationIDs )) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "recycleNoStationText", "You need to be near the proper crafting station to recycle that." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + if( craftDefinition.recycleMaterialType ) + { + var materialType = TriggerEvent( 2506, "GetItemMaterialType", targetObj ); + if( materialType != craftDefinition.recycleMaterialType ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "recycleWrongMaterialText", "That item cannot be recycled with this craft." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + } + + var recycleResourceID = craftDefinition.recycleResourceID || 0; + if( recycleResourceID == 0 ) + { + pSock.SysMessage( GetCustomCraftText( craftDefinition, "recycleNoResourceText", "This craft does not define a recycled resource." )); + RestartCustomCraftGump( pUser, craftDefinition ); + return; + } + + var resourceAmount = craftDefinition.recycleResourceAmount || 1; + var resourceHue = craftDefinition.recycleResourceHue || 0; + + if( craftDefinition.recycleUseTargetHue ) + resourceHue = targetObj.colour; + + if( craftDefinition.recycleFromCreateEntry ) + { + var createEntry = null; + + if( targetObj.entryMadeFrom != null && targetObj.entryMadeFrom != 0 ) + createEntry = CreateEntries[targetObj.entryMadeFrom]; + + if( createEntry && createEntry.resources && createEntry.resources.length > 0 ) + { + resourceAmount = Math.max( 1, Math.floor( createEntry.resources[0][0] / 2 )); + } + } + + targetObj.Delete(); + + var newResource = CreateDFNItem( pSock, pUser, recycleResourceID.toString(), resourceAmount, "ITEM", true, resourceHue ); + + if( ValidateObject( newResource ) && craftDefinition.recycleResourceName ) + newResource.name = craftDefinition.recycleResourceName; + + pSock.SysMessage( GetCustomCraftText( craftDefinition, "recycleSuccessText", "You recycle the item." )); + RestartCustomCraftGump( pUser, craftDefinition ); +} + +/** @type { ( pUser: Character, craftDefinition: object ) => void } */ +function RestartCustomCraftGump( pUser, craftDefinition ) +{ + if( !ValidateObject( pUser )) + return; + + var timerID = pUser.GetTempTag( "page" ) || 1; + var delay = craftDefinition.actionDelay || 200; + + pUser.StartTimer( delay, timerID, true ); +} + +/** @type { ( pSock: Socket, pUser: Character, targetObj: any, targetID: number ) => void } */ +function onCallback0( pSock, pUser, targetObj, targetID ) +{ + var craftDefinition = GetActiveCustomCraftDefinition( pUser ); + + if( !craftDefinition || !craftDefinition.allowRepair ) + return; + + RepairCustomCraftItem( pSock, pUser, targetObj, craftDefinition ); +} + +/** @type { ( pSock: Socket, pUser: Character, targetObj: any, targetID: number ) => void } */ +function onCallback1( pSock, pUser, targetObj, targetID ) +{ + var craftDefinition = GetActiveCustomCraftDefinition( pUser ); + + if( !craftDefinition || !craftDefinition.allowRecycle ) + return; + + RecycleCustomCraftItem( pSock, pUser, targetObj, craftDefinition ); +} \ No newline at end of file diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 845376fd9..04a804705 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -12,6 +12,7 @@ const Cooking = 4034; const Cartography = 4035; const Glassblowing = 4036; const Masonry = 4037; +const CustomCraft = 4040; const exceptionalWearablesOnly = true; @@ -101,9 +102,16 @@ function ItemDetailGump( pUser ) var recipeID = pUser.GetTempTag( "needRecipeID" ); - if( detailTag !== null ) + if (detailTag !== null) { - createEntry = CreateEntries[ detailTag ]; + try + { + createEntry = CreateEntries[detailTag]; + } + catch (error) + { + createEntry = null; + } } if( skillTag >= 0 && skillTag < skillNames.length ) @@ -158,6 +166,14 @@ function ItemDetailGump( pUser ) if( createEntry == null ) { + ItemDetailsGump( itemGump, pUser ); + + itemGump.AddHTMLGump( 170, 130, 320, 20, false, false, "Missing CreateEntry" ); + itemGump.AddHTMLGump( 170, 150, 320, 20, false, false, "CreateEntry ID " + detailTag + " was not found." ); + itemGump.AddHTMLGump( 170, 170, 320, 40, false, false, "Check the makeID in the crafting JSON file. and make sure you add it to create dfn files" ); + + itemGump.Send( socket ); + itemGump.Free(); return; } @@ -585,6 +601,11 @@ function onGumpPress( pSock, pButton, gumpData ) break; } break; + case 100: // Custom Craft + pUser.SetTempTag( "ITEMDETAILS", null ); + pSock.CloseGump( gumpID, 0 ); + TriggerEvent( CustomCraft, "PageX", pSock, pUser, pUser.GetTempTag( "page" ) || 1 ); + break; } } }