From f43f68521d84bae12f03ca1dc001f9ff44593a66 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:24:28 -0600 Subject: [PATCH 01/10] Update Glassblowing - [UPD] Updated Glass blowing to use new system that tailoring is using. - [ADD] Added New Glassblowing Items and Weapons all Era Gated - [FIX] Fixed create menu for glassblowing needed the color or it didnt see the sand item. --- data/dfndata/create/glassblowing.dfn | 120 +++- data/dfndata/items/skills/tools/alchemy.dfn | 101 ++++ data/js/skill/craft/craftgump.js | 12 +- data/js/skill/craft/glassblowing.js | 573 ++++++++++++++------ data/js/skill/craft/itemdetailgump.js | 72 ++- 5 files changed, 678 insertions(+), 200 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/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 2e894f588..36decbc85 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -19,6 +19,7 @@ const Glassblowing = 4036; // 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 ) { @@ -139,6 +140,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; } @@ -342,7 +348,7 @@ function onGumpPress( pSock, pButton, gumpData ) TriggerEvent( Tinkering, "PageX", pSock, pUser, 1 ); break; case 8: - TriggerEvent(Cartography, "PageX", pSock, pUser, 1); + TriggerEvent( Cartography, "PageX", pSock, pUser, 1 ); break; case 9: TriggerEvent( Glassblowing, "PageX", pSock, pUser, 1 ); @@ -378,6 +384,8 @@ function onGumpPress( pSock, pButton, gumpData ) case 7: TriggerEvent( Tinkering, "PageX", pSock, pUser, 2 ); break; + case 9: + TriggerEvent( Glassblowing, "PageX", pSock, pUser, 2 ); default: break; } @@ -554,4 +562,4 @@ function onGumpPress( pSock, pButton, gumpData ) case 52: // Smelt Item break; } -} +} \ No newline at end of file diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 304b41a31..4c13dd96f 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -1,215 +1,448 @@ /// // @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 scriptID = 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" ) ); ////////////////////////////////////////////////////////////////////////////////////////// -// 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 CraftingMap +////////////////////////////////////////////////////////////////////////////////////////// + +const CraftingMap = { + // 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 -const myPage = [ - // Page 1 - Misc - [13600, 13601, 13602, 13603, 13604, 13605, 13606, 13607, 13608, 13609, 13610, 13611 ] -]; +}; 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; + + /** @type {number[]} */ + var pageItems; + + // Special "Last Ten" page uses stored makeIDs directly + if( pageNum == 999 ) { - var index = i % 10; - if ( index == 0 ) + var lastTenRaw = pUser.GetTag( "LastTenGlassblowing" ); + 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 + { + // Build list of makeIDs for this page from CraftingMap + var makeIDs = []; + for( var makeIDStr in CraftingMap ) + { + if( !CraftingMap.hasOwnProperty( makeIDStr )) + continue; + + var makeID = parseInt( makeIDStr ); + var data = CraftingMap[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++ ) + { + 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 ))) { - 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 CraftingMap ) { - 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( !CraftingMap.hasOwnProperty( makeIDStr2 )) + continue; + + var makeID2 = parseInt( makeIDStr2 ); + var data3 = CraftingMap[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; }); - myGump.AddText( 255, 60 + ( index * 20 ), LabelHue, GetDictionaryEntry( myPage[pageNum - 1][i], socket.language ) ); + pageItems = []; + for( var m = 0; m < makeIDs.length; m++ ) + { + var id2 = makeIDs[m]; + var data4 = CraftingMap[id2]; + if( !data4 ) + continue; - myGump.AddButton( 480, 60 + ( index * 20 ), 4011, 4012, 1, 0, 2000 + ( 100 * pageNum ) + i ); + var needsRecipe2 = data4.recipeID; + var showAll2 = displayUnlearnedRecipes; + + 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 = CraftingMap[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 + "]"; + } } - } - 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: // 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; + // 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 ); } - if( makeID != 0 ) + // Prev subpage + if( subPage > 1 ) { - pUser.AddScriptTrigger(4033); // crafting_complete.js for applying map settings - 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 ); + glassGump.AddButton( 220, 260, 4014, 4015, 1, 0, 8000 + ( subPage - 1 )); + glassGump.AddHTMLGump( 255, 263, 100, 18, false, false, "" + GetDictionaryEntry( 10101, socket.language ) + "" ); } - else if( itemDetailsID != 0 ) + + // Next subpage + if( subPage < totalSubPages ) { - pUser.SetTempTag( "ITEMDETAILS", itemDetailsID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + 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 = scriptID + 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( CraftingMap[pButton] != undefined ) + { + makeID = pButton; + var data = CraftingMap[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, scriptID ); + return; + } + + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) + { + var detailMakeID = pButton - 20000; + if( CraftingMap[detailMakeID] ) + { + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); + } + return; + } +} + +// Last Ten +function AddToLastTen( pUser, makeID ) +{ + var raw = pUser.GetTag( "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.SetTag( "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 diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 78a460347..21b8a57a9 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -1708,63 +1708,103 @@ function ItemDetailGump( pUser ) case 3000: // empty bottle createEntry = CreateEntries[3000]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3001: // flask (small) createEntry = CreateEntries[3001]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3002: // flask (medium) createEntry = CreateEntries[3002]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3003: // flask (curved) createEntry = CreateEntries[3003]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3004: // flask (large #1) createEntry = CreateEntries[3004]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3005: // flask (large #2) createEntry = CreateEntries[3005]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3006: // flask (bubbling blue) createEntry = CreateEntries[3006]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3007: // flask (bubbling purple) createEntry = CreateEntries[3007]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3008: // flask (bubbling red) createEntry = CreateEntries[3008]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3009: // empty vials createEntry = CreateEntries[3009]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3010: // full vials createEntry = CreateEntries[3010]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); + mainSkill = parseInt( pUser.skills.alchemy ); break; case 3011: // spinning hourglass createEntry = CreateEntries[3011]; HARVEST = [13504]; - mainSkill = parseInt(pUser.skills.alchemy); - break; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3012: // hollow prism + createEntry = CreateEntries[3012]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3013: // Gargoyle Floor Mirror + createEntry = CreateEntries[3013]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3014: // Gargoyle wall Mirror + createEntry = CreateEntries[3014]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3015: // Empty Venom Vial + createEntry = CreateEntries[3015]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3016: // Empty Oil Flask + createEntry = CreateEntries[3016]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3017: // Workable Glass + createEntry = CreateEntries[3017]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3018: // Glass Sword + createEntry = CreateEntries[3018]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; + case 3019: // Glass Staff + createEntry = CreateEntries[3019]; + HARVEST = [13504]; + mainSkill = parseInt( pUser.skills.alchemy ); + break; default: break; } @@ -2090,7 +2130,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" )) @@ -2114,6 +2154,6 @@ function onGumpPress( pSock, pButton, gumpData ) break; } break; - } + } } -} +} \ No newline at end of file From 0970e7ae7010b3c025fba241e2abe6770f93d4f0 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:14:44 -0600 Subject: [PATCH 02/10] update --- data/js/skill/craft/craftgump.js | 2 +- data/js/skill/craft/glassblowing.js | 14 +++---- data/js/skill/craft/itemdetailgump.js | 56 +++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 36decbc85..07237c6e5 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -255,7 +255,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 4c13dd96f..f0b424bc2 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -36,7 +36,6 @@ const CraftingMap = { // 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 - }; function PageX( socket, pUser, pageNum ) @@ -44,13 +43,12 @@ function PageX( socket, pUser, pageNum ) if( !socket || !ValidateObject( pUser )) return; - /** @type {number[]} */ var pageItems; // Special "Last Ten" page uses stored makeIDs directly if( pageNum == 999 ) { - var lastTenRaw = pUser.GetTag( "LastTenGlassblowing" ); + var lastTenRaw = pUser.GetTempTag( "LastTenGlassblowing" ); var split = lastTenRaw.split( "," ); pageItems = []; @@ -327,7 +325,7 @@ function onGumpPress( socket, pButton, gumpData ) // Close gump if( pButton == 0 ) { - pUser.SetTempTag( "MAKELAST_GLASS", null ); + pUser.SetTempTag( "MakeLast_Glass", null ); pUser.SetTempTag( "CRAFT", null ); socket.CloseGump( gumpID, 0 ); return; @@ -339,7 +337,7 @@ function onGumpPress( socket, pButton, gumpData ) // Make Last if( pButton == 5000 ) { - var last = pUser.GetTempTag( "MAKELAST_GLASS" ); + var last = pUser.GetTempTag( "MakeLast_Glass" ); if( last ) pButton = last; else @@ -365,7 +363,7 @@ function onGumpPress( socket, pButton, gumpData ) return; } - pUser.SetTempTag( "MAKELAST_GLASS", makeID ); + pUser.SetTempTag( "MakeLast_Glass", makeID ); MakeItem( socket, pUser, makeID ); AddToLastTen( pUser, makeID ); @@ -400,7 +398,7 @@ function onGumpPress( socket, pButton, gumpData ) // Last Ten function AddToLastTen( pUser, makeID ) { - var raw = pUser.GetTag( "LastTenGlassblowing" ) || ""; + var raw = pUser.GetTempTag( "LastTenGlassblowing" ); var list = raw.split( "," ); for( var i = 0; i < list.length; i++ ) @@ -420,7 +418,7 @@ function AddToLastTen( pUser, makeID ) newList.push( entry ); } - pUser.SetTag( "LastTenGlassblowing", newList.join( "," ) ); + pUser.SetTempTag( "LastTenGlassblowing", newList.join( "," ) ); } function HasLearnedRecipe( pUser, recipeID ) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 21b8a57a9..7ef245655 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -21,6 +21,7 @@ function ItemDetailGump( pUser ) var createEntry = null; var HARVEST; var mainSkill; + var recipeID = 0; // default: no recipe required switch( pUser.GetTempTag( "ITEMDETAILS" )) { //Start Blacksmith @@ -1814,6 +1815,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 @@ -1857,7 +1866,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 ) @@ -1952,6 +1961,22 @@ 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( pUser ); itemGump.Free(); } @@ -1972,18 +1997,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, "*" ); } @@ -2156,4 +2181,19 @@ function onGumpPress( pSock, pButton, gumpData ) break; } } +} + +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 From 799f61644eb5bd4a279e9ca0f2e2e40c362b6839 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:30:08 -0600 Subject: [PATCH 03/10] Update craftgump.js --- data/js/skill/craft/craftgump.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/js/skill/craft/craftgump.js b/data/js/skill/craft/craftgump.js index 07237c6e5..b5300ee24 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -146,7 +146,7 @@ function CraftingGumpMenu( myGump, socket ) grouplist.push( 13503 ); // Glass Weapons } gumpMenuName = 13501;//Cartography Menu - break; + break; } myGump.AddPage( 0 ); From af957f3c05441a6cb64b3b38f7fe05b13aca225f Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:53:06 -0600 Subject: [PATCH 04/10] Update crafttool.js --- data/js/skill/craft/crafttool.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 99410252a..988e39e91 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -23,6 +23,7 @@ function onUseChecked( pUser, iUsed ) var gumpID6 = Cooking + 0xffff; var gumpID7 = Tinkering + 0xffff; var gumpID8 = Cartography + 0xffff; + var gumpID9 = Glassblowing + 0xffff; if( socket && ValidateObject( iUsed ) && iUsed.isItem ) { @@ -68,7 +69,7 @@ function onUseChecked( pUser, iUsed ) if( enableUOX3Craft == 1 ) { TriggerEvent( 4006, "onUseChecked", pUser, iUsed ); - return; + return false; } socket.CloseGump( gumpID, 0 ); pUser.SetTempTag( "CRAFT", 1 ) @@ -96,7 +97,7 @@ function onUseChecked( pUser, iUsed ) if( enableUOX3Craft == 1 ) { TriggerEvent( 4007, "onUseChecked", pUser, iUsed ); - return; + return false; } socket.CloseGump( gumpID2, 0 ); pUser.SetTempTag( "CRAFT", 2 ) @@ -118,7 +119,7 @@ function onUseChecked( pUser, iUsed ) if( enableUOX3Craft == 1 ) { TriggerEvent( 4005, "onUseChecked", pUser, iUsed ); - return; + return false; } socket.CloseGump( gumpID3, 0 ); pUser.SetTempTag( "CRAFT", 3 ) @@ -139,7 +140,7 @@ function onUseChecked( pUser, iUsed ) if( enableUOX3Craft == 1 ) { TriggerEvent( 4004, "onUseChecked", pUser, iUsed ); - return; + return false; } socket.CloseGump( gumpID4, 0 ); pUser.SetTempTag( "CRAFT", 4 ) @@ -193,7 +194,7 @@ function onUseChecked( pUser, iUsed ) { //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; + return false; } socket.CloseGump( gumpID6, 0 ); pUser.SetTempTag( "CRAFT", 6 ) @@ -215,7 +216,7 @@ function onUseChecked( pUser, iUsed ) if( enableUOX3Craft == 1 ) { TriggerEvent( 4003, "onUseChecked", pUser, iUsed ); - return; + return false; } socket.CloseGump( gumpID7, 0 ); pUser.SetTempTag( "CRAFT", 7 ) @@ -255,14 +256,15 @@ function onUseChecked( pUser, iUsed ) if( pUser.GetTag( "GlassBlowing" ) == 0 ) { socket.SysMessage( GetDictionaryEntry( 6300, socket.Language ));// You havent learned glassblowing. - return; + return false; } - // Cartography - socket.CloseGump( gumpID8, 0 ); + // Glassblowing + socket.CloseGump( gumpID9, 0 ); pUser.SetTempTag( "CRAFT", 9 ); switch( tempPage ) { case 1: // Page 1 + case 2: // Page 2 TriggerEvent( Glassblowing, "PageX", socket, pUser, tempPage); break; default: TriggerEvent( Glassblowing, "PageX", socket, pUser, 1); From 406455772faf5137c96e369d2e3f3e8c0a37800e Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 18 Nov 2025 00:15:42 -0600 Subject: [PATCH 05/10] fixes --- data/js/item/glassblowingbook.js | 8 ++++---- data/js/item/sandminingbook.js | 2 +- data/js/skill/craft/craftgump.js | 4 ++-- data/js/skill/craft/crafttool.js | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) 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 b5300ee24..f664dcd88 100644 --- a/data/js/skill/craft/craftgump.js +++ b/data/js/skill/craft/craftgump.js @@ -352,8 +352,8 @@ function onGumpPress( pSock, pButton, gumpData ) break; case 9: TriggerEvent( Glassblowing, "PageX", pSock, pUser, 1 ); - break; - default: + break; + default: break; } case 2: diff --git a/data/js/skill/craft/crafttool.js b/data/js/skill/craft/crafttool.js index 988e39e91..ea103bad3 100644 --- a/data/js/skill/craft/crafttool.js +++ b/data/js/skill/craft/crafttool.js @@ -255,7 +255,7 @@ function onUseChecked( pUser, iUsed ) { if( pUser.GetTag( "GlassBlowing" ) == 0 ) { - socket.SysMessage( GetDictionaryEntry( 6300, socket.Language ));// You havent learned glassblowing. + socket.SysMessage( GetDictionaryEntry( 6300, socket.language ));// You havent learned glassblowing. return false; } // Glassblowing @@ -265,9 +265,9 @@ function onUseChecked( pUser, iUsed ) { case 1: // Page 1 case 2: // Page 2 - TriggerEvent( Glassblowing, "PageX", socket, pUser, tempPage); + TriggerEvent( Glassblowing, "PageX", socket, pUser, tempPage ); break; - default: TriggerEvent( Glassblowing, "PageX", socket, pUser, 1); + default: TriggerEvent( Glassblowing, "PageX", socket, pUser, 1 ); break; } } From 748b54e8583b212d7fa82a752b602fc6631fbabf Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 18 Nov 2025 21:00:48 -0600 Subject: [PATCH 06/10] fixes --- data/js/skill/craft/glassblowing.js | 4 ++-- data/js/skill/craft/itemdetailgump.js | 3 ++- data/js/skill/craft/tailoring.js | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index f0b424bc2..fbc659fda 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -48,7 +48,7 @@ function PageX( socket, pUser, pageNum ) // Special "Last Ten" page uses stored makeIDs directly if( pageNum == 999 ) { - var lastTenRaw = pUser.GetTempTag( "LastTenGlassblowing" ); + var lastTenRaw = pUser.GetTempTag( "LastTenGlassblowing" ) || ""; var split = lastTenRaw.split( "," ); pageItems = []; @@ -398,7 +398,7 @@ function onGumpPress( socket, pButton, gumpData ) // Last Ten function AddToLastTen( pUser, makeID ) { - var raw = pUser.GetTempTag( "LastTenGlassblowing" ); + var raw = pUser.GetTempTag( "LastTenGlassblowing" ) || ""; var list = raw.split( "," ); for( var i = 0; i < list.length; i++ ) diff --git a/data/js/skill/craft/itemdetailgump.js b/data/js/skill/craft/itemdetailgump.js index 7ef245655..92bce924b 100644 --- a/data/js/skill/craft/itemdetailgump.js +++ b/data/js/skill/craft/itemdetailgump.js @@ -2176,7 +2176,8 @@ function onGumpPress( pSock, pButton, gumpData ) TriggerEvent( Glassblowing, "PageX", pSock, pUser, pUser.GetTempTag( "page" )); break; default: TriggerEvent( Glassblowing, "PageX", pSock, pUser, 1 ); - break; + } + break; } break; } diff --git a/data/js/skill/craft/tailoring.js b/data/js/skill/craft/tailoring.js index 66cf7874f..521c7aaa9 100644 --- a/data/js/skill/craft/tailoring.js +++ b/data/js/skill/craft/tailoring.js @@ -168,7 +168,7 @@ function PageX( socket, pUser, pageNum ) if( pageNum == 999 ) { - let lastTenRaw = pUser.GetTag( "LastTenTailoring" ) || ""; + let lastTenRaw = pUser.GetTempTag( "LastTenTailoring" ) || ""; let split = lastTenRaw.split( "," ); pageItems = []; @@ -701,7 +701,7 @@ function onCallback2( socket, ourObj ) 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 @@ -723,7 +723,7 @@ function AddToLastTen( pUser, makeID ) newList.push( entry ); } - pUser.SetTag( "LastTenTailoring", newList.join( "," )); + pUser.SetTempTag( "LastTenTailoring", newList.join( "," )); } function HasLearnedRecipe( pUser, recipeID ) From a57cd809abfe3b4fbf7e7c1885c7e0cbf9ee55b9 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:18:26 -0600 Subject: [PATCH 07/10] Update glassblowing.js --- data/js/skill/craft/glassblowing.js | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index fbc659fda..4e1b3a458 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -10,10 +10,10 @@ const displayUnlearnedRecipes = true; // Show recipes player has not learned const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" ) ); ////////////////////////////////////////////////////////////////////////////////////////// -// Glassblowing CraftingMap +// Glassblowing GlassBlowingMap ////////////////////////////////////////////////////////////////////////////////////////// -const CraftingMap = { +const GlassBlowingMap = { // Page 1 - Misc Glassware 3000: { dictID: 13600, page: 1, timerID: 1 }, // empty bottle 3001: { dictID: 13601, page: 1, timerID: 1 }, // flask (small) @@ -61,15 +61,15 @@ function PageX( socket, pUser, pageNum ) } else { - // Build list of makeIDs for this page from CraftingMap + // Build list of makeIDs for this page from GlassBlowingMap var makeIDs = []; - for( var makeIDStr in CraftingMap ) + for( var makeIDStr in GlassBlowingMap ) { - if( !CraftingMap.hasOwnProperty( makeIDStr )) + if( !GlassBlowingMap.hasOwnProperty( makeIDStr )) continue; var makeID = parseInt( makeIDStr ); - var data = CraftingMap[makeID]; + var data = GlassBlowingMap[makeID]; if( !data || data.page != pageNum ) continue; @@ -84,7 +84,7 @@ function PageX( socket, pUser, pageNum ) for( var k = 0; k < makeIDs.length; k++ ) { var id = makeIDs[k]; - var data2 = CraftingMap[id]; + var data2 = GlassBlowingMap[id]; if( !data2 ) continue; @@ -103,13 +103,13 @@ function PageX( socket, pUser, pageNum ) pageNum = 1; makeIDs = []; - for( var makeIDStr2 in CraftingMap ) + for( var makeIDStr2 in GlassBlowingMap ) { - if( !CraftingMap.hasOwnProperty( makeIDStr2 )) + if( !GlassBlowingMap.hasOwnProperty( makeIDStr2 )) continue; var makeID2 = parseInt( makeIDStr2 ); - var data3 = CraftingMap[makeID2]; + var data3 = GlassBlowingMap[makeID2]; if( !data3 || data3.page != 1 ) continue; @@ -121,7 +121,7 @@ function PageX( socket, pUser, pageNum ) for( var m = 0; m < makeIDs.length; m++ ) { var id2 = makeIDs[m]; - var data4 = CraftingMap[id2]; + var data4 = GlassBlowingMap[id2]; if( !data4 ) continue; @@ -174,7 +174,7 @@ function PageX( socket, pUser, pageNum ) var entryText; var buttonID = makeID; - var data5 = CraftingMap[makeID]; + var data5 = GlassBlowingMap[makeID]; if( !data5 ) { @@ -345,10 +345,10 @@ function onGumpPress( socket, pButton, gumpData ) } // Craft buttons use makeID directly - if( CraftingMap[pButton] != undefined ) + if( GlassBlowingMap[pButton] != undefined ) { makeID = pButton; - var data = CraftingMap[makeID]; + var data = GlassBlowingMap[makeID]; timerID = data.timerID || 1; if( !eraOK( data )) @@ -386,7 +386,7 @@ function onGumpPress( socket, pButton, gumpData ) if( pButton >= 20000 && pButton < 30000 ) { var detailMakeID = pButton - 20000; - if( CraftingMap[detailMakeID] ) + if( GlassBlowingMap[detailMakeID] ) { pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); From edabbf0f6c6f4d356494f44fa71a3716ac307f85 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:36:26 -0600 Subject: [PATCH 08/10] Update glassblowing.js --- data/js/skill/craft/glassblowing.js | 84 +++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 4e1b3a458..965979f32 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -8,6 +8,8 @@ const craftGumpID = 4027; // TriggerEvent ID used to build the craf 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 ////////////////////////////////////////////////////////////////////////////////////////// // Glassblowing GlassBlowingMap @@ -38,6 +40,34 @@ const GlassBlowingMap = { 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 + // } + } +})(); + +// 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 ) { if( !socket || !ValidateObject( pUser )) @@ -383,16 +413,50 @@ function onGumpPress( socket, pButton, gumpData ) } // Detail buttons: 20000 + makeID - if( pButton >= 20000 && pButton < 30000 ) - { - var detailMakeID = pButton - 20000; - if( GlassBlowingMap[detailMakeID] ) - { - pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); - TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); - } - return; - } + // Detail buttons: 20000 + makeID + if( pButton >= 20000 && pButton < 30000 ) + { + var detailMakeID = pButton - 20000; + var entry = GlassBlowingMap[detailMakeID]; + + if ( entry ) + { + // Always set which item the detail script should show + pUser.SetTempTag( "ITEMDETAILS", detailMakeID ); + + // ---- SKILL ---- + // Use entry.skill if present, otherwise 0 + pUser.SetTempTag( "Skill", entry.skill || 0); + + // ---- HARVESTS ---- + // Clear out old values first + pUser.SetTempTag( "Harvest", null ); + pUser.SetTempTag( "Harvest2", null ); + pUser.SetTempTag( "Harvest3", null ); + pUser.SetTempTag( "Harvest4", null ); + + // Fill from entry.harvest array if it exists + 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] ); + } + + // Now fire the generic detail gump + TriggerEvent(itemDetailsScriptID, "ItemDetailGump", pUser); + } + return; + } + } // Last Ten From 7d33acba1063c17d3e7f5a4b3d3f2c4fe306283a Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:32:10 -0600 Subject: [PATCH 09/10] Update glassblowing.js --- data/js/skill/craft/glassblowing.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 965979f32..9457708e8 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -449,6 +449,11 @@ function onGumpPress( socket, pButton, gumpData ) 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 ); } // Now fire the generic detail gump @@ -456,7 +461,6 @@ function onGumpPress( socket, pButton, gumpData ) } return; } - } // Last Ten From af42a096deba2f27b1c40064025788ae840b7d24 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:05:02 -0600 Subject: [PATCH 10/10] Update glassblowing.js --- data/js/skill/craft/glassblowing.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/js/skill/craft/glassblowing.js b/data/js/skill/craft/glassblowing.js index 9457708e8..19cc5f95a 100644 --- a/data/js/skill/craft/glassblowing.js +++ b/data/js/skill/craft/glassblowing.js @@ -1,7 +1,7 @@ /// // @ts-check const textHue = 0x480; // Color hue for all text in the crafting gump -const scriptID = 4036; // Script ID used to identify and close this 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 @@ -313,7 +313,7 @@ function onGumpPress( socket, pButton, gumpData ) return; } - var gumpID = scriptID + 0xffff; + var gumpID = glassblowingID + 0xffff; // Subpage back / forward if( pButton >= 8001 && pButton < 9000 ) @@ -408,7 +408,7 @@ function onGumpPress( socket, pButton, gumpData ) } } - pUser.StartTimer( gumpDelay, timerID, scriptID ); + pUser.StartTimer( gumpDelay, timerID, glassblowingID ); return; } @@ -457,7 +457,7 @@ function onGumpPress( socket, pButton, gumpData ) } // Now fire the generic detail gump - TriggerEvent(itemDetailsScriptID, "ItemDetailGump", pUser); + TriggerEvent( itemDetailsScriptID, "ItemDetailGump", pUser ); } return; }