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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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/38] 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