diff --git a/data/dictionaries/dictionary.CSY b/data/dictionaries/dictionary.CSY index 8ba662739..1432e6569 100644 --- a/data/dictionaries/dictionary.CSY +++ b/data/dictionaries/dictionary.CSY @@ -4880,6 +4880,9 @@ 15058=Síla 15059=Hbitost 15060=Inteligence +15990=Nemáte povoleno tam cestovat. +15991=Nemůžete se odtud teleportovat do cíle. +15991=Nemůžete zde označit runu. // 17000 - Nabídka nápovědy pro střepy 17000=Nabídka nápovědy 17001=Obecné otázky ke hře diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index f2b64f794..d32a5dce6 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -4880,6 +4880,10 @@ 15058=Strength 15059=Dexterity 15060=Intelligence +//15990 Travel Restrictions +15990=You are not allowed to travel there. +15991=You cannot teleport from here to the destination. +15991=You can not mark a rune here. // 17000 - Shard Help Menu 17000=Help Menu 17001=General Gameplay Questions diff --git a/data/dictionaries/dictionary.FRE b/data/dictionaries/dictionary.FRE index cc528125c..6de7030e3 100644 --- a/data/dictionaries/dictionary.FRE +++ b/data/dictionaries/dictionary.FRE @@ -5036,6 +5036,9 @@ 15058=Force 15059=Dexterité 15060=Intelligence +15990=Vous n'êtes pas autorisé à y voyager. +15991=Vous ne pouvez pas vous téléporter d'ici vers la destination. +15991=Vous ne pouvez pas marquer une rune ici. // 17000 - Shard Help Menu 17000=Menu Aide 17001=Questions générales sur le jeu diff --git a/data/dictionaries/dictionary.GER b/data/dictionaries/dictionary.GER index 47f9faeec..84f0183a9 100644 --- a/data/dictionaries/dictionary.GER +++ b/data/dictionaries/dictionary.GER @@ -4880,6 +4880,9 @@ 15058=Stärke 15059=Geschicklichkeit 15060=Intelligenz +15990=Sie dürfen nicht dorthin reisen. +15991=Sie können sich nicht von hier zum Ziel teleportieren. +15991=Sie können hier keine Rune markieren. // 17000 - Shard Help Menu 17000=Menü "Hilfe 17001=Allgemeine Fragen zum Gameplay diff --git a/data/dictionaries/dictionary.ITA b/data/dictionaries/dictionary.ITA index a74ce17fe..8f14c1bcb 100644 --- a/data/dictionaries/dictionary.ITA +++ b/data/dictionaries/dictionary.ITA @@ -4880,6 +4880,9 @@ 15058=Forza 15059=Destrezza 15060=Intelligenza +15990=Non ti è consentito viaggiare lì. +15991=Non puoi teletrasportarti da qui alla destinazione. +15991=Non puoi contrassegnare una runa qui. // 17000 - Shard Help Menu 17000=Menu Aiuto 17001=Domande generali sul gioco diff --git a/data/dictionaries/dictionary.POL b/data/dictionaries/dictionary.POL index 98e4bde25..4beaa7478 100644 --- a/data/dictionaries/dictionary.POL +++ b/data/dictionaries/dictionary.POL @@ -4880,6 +4880,9 @@ 15058=Wytrzymałość 15059=Zręczność 15060=Inteligencja +15990=Nie wolno ci tam podróżować. +15991=Nie możesz się stąd teleportować do miejsca docelowego. +15991=Nie możesz tutaj zaznaczyć runy. // 17000 - Shard Help Menu 17000=Menu Pomoc 17001=Ogólne pytania dotyczące rozgrywki diff --git a/data/dictionaries/dictionary.PTG b/data/dictionaries/dictionary.PTG index 804ba82ca..4b0334a79 100644 --- a/data/dictionaries/dictionary.PTG +++ b/data/dictionaries/dictionary.PTG @@ -4880,6 +4880,9 @@ 15058=Força 15059=Dexteridade 15060=Intelligence +15990=Você não tem permissão para viajar para lá. +15991=Você não pode se teletransportar daqui para o destino. +15991=Você não pode marcar uma runa aqui. // 17000 - Shard Help Menu 17000=Menu Ajuda 17001=Questões gerais de jogabilidade diff --git a/data/dictionaries/dictionary.SPA b/data/dictionaries/dictionary.SPA index 1d3a1327a..a7ad3d552 100644 --- a/data/dictionaries/dictionary.SPA +++ b/data/dictionaries/dictionary.SPA @@ -4880,6 +4880,9 @@ 15058=Fuerza 15059=Destreza 15060=Inteligencia +15990=No tienes permitido viajar allí. +15991=No puedes teletransportarte desde aquí al destino. +15991=No puedes marcar una runa aquí. // 17000 - Shard Help Menu 17000=Menú de ayuda 17001=Preguntas generales sobre el juego diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index e55e7d6f2..e672c8bca 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -4836,6 +4836,9 @@ 15058=Strength 15059=Dexterity 15060=Intelligence +15990=You are not allowed to travel there. +15991=You cannot teleport from here to the destination. +15991=You can not mark a rune here. // 17000 - Shard Help Menu 17000=Help Menu 17001=General Gameplay Questions diff --git a/data/js/item/moongate.js b/data/js/item/moongate.js index 4555fc426..431b6d921 100644 --- a/data/js/item/moongate.js +++ b/data/js/item/moongate.js @@ -338,21 +338,7 @@ function onGumpPress( srcSock, myButton ) return; } - // Teleport player's followers - var followerList = srcChar.GetFollowerList(); - for( var i = 0; i < followerList.length; i++ ) - { - var tempFollower = followerList[i]; - // Only teleport pet if set to follow and within range - if( ValidateObject( tempFollower ) && tempFollower.wandertype == 1 && tempFollower.InRange( srcChar, 24 )) - { - tempFollower.Teleport( targetLocation[0], targetLocation[1], targetLocation[2], targetLocation[3] ); - tempFollower.Follow( srcChar ); - } - } - - // Teleport player - srcChar.Teleport( targetLocation[0], targetLocation[1], targetLocation[2], targetLocation[3] ); + TriggerEvent( 6003, "CheckTeleport", srcChar, targetLocation[0], targetLocation[1], targetLocation[2], targetLocation[3], 0 ) } function DisplayTravelGump( srcSock, pUser ) diff --git a/data/js/item/runebook.js b/data/js/item/runebook.js index 1716c9730..0d8e0455b 100644 --- a/data/js/item/runebook.js +++ b/data/js/item/runebook.js @@ -6,7 +6,7 @@ // Runebooks can either be crafted via the Inscription skill, or added by GMs using this command: // 'add item runebook -var maxCharges = 10; // Default maximum amount of charges a runebook can hold +var maxCharges = 16; // Default maximum amount of charges a runebook can hold const showCoords = true; // Show regular coordinates in tooltip above latitude/longitude values const scriptID = 5029; // Script ID assigned to this script in jse_fileassociations.scp const useDelay = 7000; // 7 seconds between each time a runebook can be used @@ -644,6 +644,20 @@ function onGumpPress( pSocket, myButton, gumpData ) function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) { + var runeBook = pSocket.tempObj2; + var runeNum = pSocket.tempInt2; + var runeData = runeBook.GetTag( "rune" + runeNum + "Data" ); + var splitData = runeData.split( "," ); + var targLocX = parseInt(splitData[2]); + var targLocY = parseInt(splitData[3]); + var targWorld = parseInt(splitData[5]); + var targInstanceID = 0; + + if( splitData[6] ) + { + targInstanceID = parseInt(splitData[6]); + } + // Are we already casting? if( pUser.GetTimer( Timer.SPELLTIME ) != 0 ) { @@ -666,6 +680,12 @@ function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) return; } + //Checks if they can travell in the region. + if( TriggerEvent( 6002, "CheckTravelRestrictions", pUser, spellNum, targLocX, targLocY, targWorld, targInstanceID )) + { + return; + } + // Is the spell we're trying to cast enabled? var mSpell = Spells[spellNum]; if( !mSpell.enabled ) @@ -697,7 +717,7 @@ function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) } // Does player have enough reagents to cast the spell? - if( checkReagentReq && !CheckReagents( pUser, mSpell )) + if( checkReagentReq && !TriggerEvent( 6004, "CheckReagents", pUser, mSpell)) return; // Make sure player has enough of the required stats to cast the spell @@ -764,7 +784,7 @@ function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) pUser.TextMessage( mSpell.mantra ); if( checkReagentReq ) { - DeleteReagents( pUser, mSpell ); + TriggerEvent( 6004, "DeleteReagents", pUser, mSpell ); } pUser.SpellFail(); pUser.isCasting = false; @@ -782,7 +802,7 @@ function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) // Delete reagents if needed if( checkReagentReq ) { - DeleteReagents( pUser, mSpell ); + TriggerEvent( 6004, "DeleteReagents", pUser, mSpell ); } pUser.TextMessage( mSpell.mantra ); @@ -791,67 +811,6 @@ function CastSpell( pSocket, pUser, spellNum, checkReagentReq ) pUser.StartTimer( delay, spellNum, true ); } -function CheckReagents( pUser, mSpell ) -{ - var failedCheck = 0; - if( mSpell.ash > 0 && pUser.ResourceCount( 0x0F8C ) < mSpell.ash ) - { - failedCheck = 1; - } - if( mSpell.drake > 0 && pUser.ResourceCount( 0x0F86 ) < mSpell.drake ) - { - failedCheck = 1; - } - if( mSpell.garlic > 0 && pUser.ResourceCount( 0x0F84 ) < mSpell.garlic ) - { - failedCheck = 1; - } - if( mSpell.ginseng > 0 && pUser.ResourceCount( 0x0F85 ) < mSpell.ginseng ) - { - failedCheck = 1; - } - if( mSpell.moss > 0 && pUser.ResourceCount( 0x0F7B ) < mSpell.moss ) - { - failedCheck = 1; - } - if( mSpell.pearl > 0 && pUser.ResourceCount( 0x0F7A ) < mSpell.pearl ) - { - failedCheck = 1; - } - if( mSpell.shade > 0 && pUser.ResourceCount( 0x0F88 ) < mSpell.shade ) - { - failedCheck = 1; - } - if( mSpell.silk > 0 && pUser.ResourceCount( 0x0F8D ) < mSpell.silk ) - { - failedCheck = 1; - } - if( failedCheck == 1 ) - { - if( pUser.socket != null ) - { - pUser.socket.SysMessage( GetDictionaryEntry( 702, pUser.socket.language )); // You do not have enough reagents to cast that spell. - } - return false; - } - else - { - return true; - } -} - -function DeleteReagents( pUser, mSpell ) -{ - pUser.UseResource( mSpell.pearl, 0x0F7A ); - pUser.UseResource( mSpell.moss, 0x0F7B ); - pUser.UseResource( mSpell.garlic, 0x0F84 ); - pUser.UseResource( mSpell.ginseng, 0x0F85 ); - pUser.UseResource( mSpell.drake, 0x0F86 ); - pUser.UseResource( mSpell.shade, 0x0F88 ); - pUser.UseResource( mSpell.ash, 0x0F8C ); - pUser.UseResource( mSpell.silk, 0x0F8D ); -} - function onTimer( timerObj, timerID ) { if( timerID == 100 ) @@ -909,21 +868,7 @@ function onTimer( timerObj, timerID ) // Handle effect of spell if( spellNum == 32 ) // Recall spell { - // Teleport player's followers - var followerList = timerObj.GetFollowerList(); - for( var i = 0; i < followerList.length; i++ ) - { - var tempFollower = followerList[i]; - // Only teleport player's pets if they are set to follow - if( ValidateObject( tempFollower ) && tempFollower.wandertype == 1 && tempFollower.InRange( timerObj, 24 )) - { - tempFollower.Teleport( targLocX, targLocY, targLocZ, targWorld, targInstanceID ); - tempFollower.Follow( timerObj ); - } - } - - // Teleport player - timerObj.Teleport( targLocX, targLocY, targLocZ, targWorld, targInstanceID ); + TriggerEvent( 6003, "CheckTeleport", timerObj, targLocX, targLocY, targLocZ, targWorld, targInstanceID ) } else { diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 6d18a60e1..09e9ec47e 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -309,6 +309,9 @@ //------------------------------------------- 6000=magic/helper/check_resist.js 6001=magic/helper/calc_final_spell_damage.js +6002=magic/helper/check_travel_restrictions.js +6003=magic/helper/check_teleport.js +6004=magic/helper/check_reagents.js //------------------------------------------- // Combat Scripts [7000-7499] diff --git a/data/js/magic/clumsy.js b/data/js/magic/clumsy.js index 5eb21c8cb..176cde5ad 100644 --- a/data/js/magic/clumsy.js +++ b/data/js/magic/clumsy.js @@ -138,7 +138,7 @@ function onSpellCast( mSock, mChar, directCast, spellNum ) { //Check for enough reagents // type == 0 -> SpellBook - if( spellType == 0 && !CheckReagents( mChar, mSpell )) + if( spellType == 0 && !TriggerEvent( 6004, "CheckReagents", pUser, mSpell)) { mChar.SetTimer( Timer.SPELLTIME, 0 ); mChar.isCasting = false; @@ -194,7 +194,7 @@ function onSpellCast( mSock, mChar, directCast, spellNum ) if( spellType == 0 ) { - DeleteReagents( mChar, mSpell ); + TriggerEvent( 6004, "DeleteReagents", pUser, mSpell ); mChar.SpellFail(); mChar.SetTimer( Timer.SPELLTIME, 0 ); mChar.isCasting = false; @@ -246,67 +246,6 @@ function onSpellCast( mSock, mChar, directCast, spellNum ) return true; } -function CheckReagents( mChar, mSpell ) -{ - var failedCheck = 0; - if( mSpell.ash > 0 && mChar.ResourceCount( 0x0F8C ) < mSpell.ash ) - { - failedCheck = 1; - } - if( mSpell.drake > 0 && mChar.ResourceCount( 0x0F86 ) < mSpell.drake ) - { - failedCheck = 1; - } - if( mSpell.garlic > 0 && mChar.ResourceCount( 0x0F84 ) < mSpell.garlic ) - { - failedCheck = 1; - } - if( mSpell.ginseng > 0 && mChar.ResourceCount( 0x0F85 ) < mSpell.ginseng ) - { - failedCheck = 1; - } - if( mSpell.moss > 0 && mChar.ResourceCount( 0x0F7B ) < mSpell.moss ) - { - failedCheck = 1; - } - if( mSpell.pearl > 0 && mChar.ResourceCount( 0x0F7A ) < mSpell.pearl ) - { - failedCheck = 1; - } - if( mSpell.shade > 0 && mChar.ResourceCount( 0x0F88 ) < mSpell.shade ) - { - failedCheck = 1; - } - if( mSpell.silk > 0 && mChar.ResourceCount( 0x0F8D ) < mSpell.silk ) - { - failedCheck = 1; - } - if( failedCheck == 1 ) - { - if( mChar.socket != null ) - { - mChar.socket.SysMessage( GetDictionaryEntry( 702, mChar.socket.language )); // You do not have enough reagents to cast that spell. - } - return false; - } - else - { - return true; - } -} - -function DeleteReagents( mChar, mSpell ) -{ - mChar.UseResource( mSpell.pearl, 0x0F7A ); - mChar.UseResource( mSpell.moss, 0x0F7B ); - mChar.UseResource( mSpell.garlic, 0x0F84 ); - mChar.UseResource( mSpell.ginseng, 0x0F85 ); - mChar.UseResource( mSpell.drake, 0x0F86 ); - mChar.UseResource( mSpell.shade, 0x0F88 ); - mChar.UseResource( mSpell.ash, 0x0F8C ); - mChar.UseResource( mSpell.silk, 0x0F8D ); -} - function onTimer( mChar, timerID ) { mChar.isCasting = false; @@ -379,7 +318,7 @@ function onSpellSuccess( mSock, mChar, ourTarg ) } if( !mChar.npc && spellType == 0 ) { - DeleteReagents( mChar, mSpell ); + TriggerEvent( 6004, "DeleteReagents", pUser, mSpell ); } if( !mChar.InRange( ourTarg, 10 )) diff --git a/data/js/magic/helper/check_reagents.js b/data/js/magic/helper/check_reagents.js new file mode 100644 index 000000000..7ad178590 --- /dev/null +++ b/data/js/magic/helper/check_reagents.js @@ -0,0 +1,60 @@ +function CheckReagents( mChar, mSpell ) +{ + var failedCheck = 0; + if( mSpell.ash > 0 && mChar.ResourceCount( 0x0F8C ) < mSpell.ash ) + { + failedCheck = 1; + } + if( mSpell.drake > 0 && mChar.ResourceCount( 0x0F86 ) < mSpell.drake ) + { + failedCheck = 1; + } + if( mSpell.garlic > 0 && mChar.ResourceCount( 0x0F84 ) < mSpell.garlic ) + { + failedCheck = 1; + } + if( mSpell.ginseng > 0 && mChar.ResourceCount( 0x0F85 ) < mSpell.ginseng ) + { + failedCheck = 1; + } + if( mSpell.moss > 0 && mChar.ResourceCount( 0x0F7B ) < mSpell.moss ) + { + failedCheck = 1; + } + if( mSpell.pearl > 0 && mChar.ResourceCount( 0x0F7A ) < mSpell.pearl ) + { + failedCheck = 1; + } + if( mSpell.shade > 0 && mChar.ResourceCount( 0x0F88 ) < mSpell.shade ) + { + failedCheck = 1; + } + if( mSpell.silk > 0 && mChar.ResourceCount( 0x0F8D ) < mSpell.silk ) + { + failedCheck = 1; + } + if( failedCheck == 1 ) + { + if( mChar.socket != null ) + { + mChar.socket.SysMessage( GetDictionaryEntry( 702, mChar.socket.language )); // You do not have enough reagents to cast that spell. + } + return false; + } + else + { + return true; + } +} + +function DeleteReagents( mChar, mSpell ) +{ + mChar.UseResource( mSpell.pearl, 0x0F7A ); + mChar.UseResource( mSpell.moss, 0x0F7B ); + mChar.UseResource( mSpell.garlic, 0x0F84 ); + mChar.UseResource( mSpell.ginseng, 0x0F85 ); + mChar.UseResource( mSpell.drake, 0x0F86 ); + mChar.UseResource( mSpell.shade, 0x0F88 ); + mChar.UseResource( mSpell.ash, 0x0F8C ); + mChar.UseResource( mSpell.silk, 0x0F8D ); +} \ No newline at end of file diff --git a/data/js/magic/helper/check_teleport.js b/data/js/magic/helper/check_teleport.js new file mode 100644 index 000000000..fe83386af --- /dev/null +++ b/data/js/magic/helper/check_teleport.js @@ -0,0 +1,19 @@ +// Helper function to use when teleporting +function CheckTeleport( targPlayer, targLocX, targLocY, targLocZ, targWorld, targInstanceID ) +{ + // Teleport player's followers + var followerList = targPlayer.GetFollowerList(); + for( var i = 0; i < followerList.length; i++ ) + { + var tempFollower = followerList[i]; + // Only teleport player's pets if they are set to follow + if( ValidateObject( tempFollower ) && tempFollower.wandertype == 1 && tempFollower.InRange( timerObj, 24 )) + { + tempFollower.Teleport( targLocX, targLocY, targLocZ, targWorld, targInstanceID ); + tempFollower.Follow( targPlayer ); + } + } + + // Teleport player + targPlayer.Teleport( targLocX, targLocY, targLocZ, targWorld, targInstanceID ); +} \ No newline at end of file diff --git a/data/js/magic/helper/check_travel_restrictions.js b/data/js/magic/helper/check_travel_restrictions.js new file mode 100644 index 000000000..7034c52f0 --- /dev/null +++ b/data/js/magic/helper/check_travel_restrictions.js @@ -0,0 +1,28 @@ +function CheckTravelRestrictions( targPlayer, spellNum, targX, targY, targWorld, targInstanceID ) +{ + const targRegion = CalcTownRegionFromXY( targX, targY, targWorld, targInstanceID ); + + const travelRules = { + 32: { type: 'canRecall', message: 15990 }, // You are not allowed to travel there. // Recall spell + 52: { type: 'canGate', message: 15990 }, // You are not allowed to travel there. // Gate spell + 22: { type: 'canTeleport', message: 15991 }, // You cannot teleport from here to the destination. // Teleport spell + 45: { type: 'canMark', message: 15992 } // You can not mark a rune here. // Mark spell + }; + + const travelType = travelRules[spellNum]; + + if( travelType) + { + if( spellNum !== 45 && !targRegion[travelType.type] ) + { + pSocket.SysMessage( GetDictionaryEntry( travelType.message, pSocket.language )); + return false; + } + else if( !targPlayer.region[travelType.type] ) + { + pSocket.SysMessage( GetDictionaryEntry( travelType.message, pSocket.language )); + return false; + } + } + return true; +} \ No newline at end of file diff --git a/source/SEFunctions.cpp b/source/SEFunctions.cpp index a0dc90074..338a4a33f 100644 --- a/source/SEFunctions.cpp +++ b/source/SEFunctions.cpp @@ -3512,6 +3512,38 @@ JSBool SE_GetTownRegion( JSContext *cx, [[maybe_unused]] JSObject *obj, uintN ar return JS_TRUE; } +//o------------------------------------------------------------------------------------------------o +//| Function - SE_GetTownRegionFromXY() +//o------------------------------------------------------------------------------------------------o +//| Purpose - Returns region object associated with a specific location +//o------------------------------------------------------------------------------------------------o +JSBool SE_GetTownRegionFromXY( JSContext *cx, [[maybe_unused]] JSObject *obj, uintN argc, jsval *argv, jsval *rval ) +{ + if( argc != 4 ) + { + ScriptError( cx, "GetTownRegion: Invalid number of parameters (4)" ); + return JS_FALSE; + } + + SI16 locX = static_cast( JSVAL_TO_INT( argv[0] )); + SI16 locY = static_cast( JSVAL_TO_INT( argv[1] )); + UI08 locWorldNumber = static_cast( JSVAL_TO_INT( argv[2] )); + UI16 locInstanceId = static_cast( JSVAL_TO_INT( argv[3] )); + + auto townReg = CalcRegionFromXY( locX, locY, locWorldNumber, locInstanceId, nullptr ); + if( townReg != nullptr ) + { + JSObject *myObj = JSEngine->AcquireObject( IUE_REGION, townReg, JSEngine->FindActiveRuntime( JS_GetRuntime( cx ))); + *rval = OBJECT_TO_JSVAL( myObj ); + } + else + { + *rval = JSVAL_NULL; + } + + return JS_TRUE; +} + //o------------------------------------------------------------------------------------------------o //| Function - SE_GetSpawnRegion() //| Date - June 22, 2020 diff --git a/source/SEFunctions.h b/source/SEFunctions.h index e70e686f7..904a1fabd 100644 --- a/source/SEFunctions.h +++ b/source/SEFunctions.h @@ -140,6 +140,7 @@ SEngineFunc SE_ResourceRegion; SEngineFunc SE_Moon; SEngineFunc SE_GetTownRegion; +SEngineFunc SE_GetTownRegionFromXY; SEngineFunc SE_GetSpawnRegion; SEngineFunc SE_GetSpawnRegionCount; diff --git a/source/cScript.cpp b/source/cScript.cpp index 42f6e113a..7e1e9d065 100644 --- a/source/cScript.cpp +++ b/source/cScript.cpp @@ -132,6 +132,7 @@ static JSFunctionSpec my_functions[] = { "Moon", SE_Moon, 2, 0, 0 }, { "GetTownRegion", SE_GetTownRegion, 1, 0, 0 }, + { "GetTownRegionFromXY", SE_GetTownRegionFromXY, 4, 0, 0 }, { "GetSpawnRegion", SE_GetSpawnRegion, 4, 0, 0 }, { "GetSpawnRegionCount", SE_GetSpawnRegionCount, 0, 0, 0 },