diff --git a/data/dictionaries/dictionary.CSY b/data/dictionaries/dictionary.CSY index f32bf29a4..8f378692a 100644 --- a/data/dictionaries/dictionary.CSY +++ b/data/dictionaries/dictionary.CSY @@ -5346,5 +5346,42 @@ 19140=Nejprve je třeba změkčit nečistoty. 19141=Zasadíte semeno do misky s hlínou. 19142=Musíte použít semínko na misku s nečistotami! +// [19201-19300] Speciální pohyby +19201=K provedení tohoto útoku potřebujete %i zbraň +19202=K provedení tohoto útoku potřebujete %i many +19203=Váš útok proniká jejich pancířem! +19204=Úder pronikl do vašeho brnění! +19205=Váš cíl krvácí! +19206=Ty krvácíš! +19207=Hodně krvácíte +19208=%i silně krvácí +19209=Máte otřes mozku! +19210=Cítíte se dezorientovaný! +19211=Zasadil jsi zdrcující ránu! +19212=Zdrcujícím útokem dostáváte další poškození! +19213=Nemůžete odzbrojit svého protivníka. +19214=Váš cíl již není ozbrojen! +19215=Odzbrojte svou zbraň! +19216=Vaše zbraň byla odzbrojena! +19217=Nemůžete provést tento útok během jízdy nebo letu! +19218=Tento útok funguje pouze na namontované nebo létající cíle +19219=Síla vašeho útoku je vytlačila z jejich koně! +19220=Byli jste sraženi z vašeho koně %i! +19221=Vaše zbraň musí mít dávku jedu, aby mohla provést infekční útok! +19222=Váš přesný zásah zvýšil úroveň jedu o 1 +19223=Jed se zdá být extra účinný! +19224=Otrávili jste svůj cíl: %i +19225=%i : otrávil tě! +19226=Zasadil jsi smrtelnou ránu! +19227=Byl jsi smrtelně zraněn! +19228=Váš cíl odolává paralýze. +19229=Odporujete paralýze. +19230=Útok vás dočasně paralyzoval! +19231=Chybí vám požadované utajení k provedení tohoto útoku +19232=Úder a schováš se ve stínu! +19233=Jste omráčeni útokem a váš útočník zmizí! +19234=Váš zmatek pominul, nyní můžete vyzbrojit zbraň! +19235=Už nejsi smrtelně zraněný. +19236=Krvácející rány se zahojily, už nekrvácíte! } EOF diff --git a/data/dictionaries/dictionary.ENG b/data/dictionaries/dictionary.ENG index f63ea6d16..e4e08becc 100644 --- a/data/dictionaries/dictionary.ENG +++ b/data/dictionaries/dictionary.ENG @@ -5347,5 +5347,42 @@ 19140=The dirt needs to be softened first. 19141=You plant the seed in the bowl of dirt. 19142=You must use a seed on a bowl of dirt! +// [19201-19300] Special Moves +19201=You need %i weapon skill to perform that attack +19202=You need %i mana to perform that attack +19203=Your attack penetrates their armor! +19204=The blow penetrated your armor! +19205=Your target is bleeding! +19206=You are bleeding! +19207=You are bleeding profusely +19208=%i is bleeding profusely +19209=You have delivered a concussion! +19210=You feel disoriented! +19211=You have delivered a crushing blow! +19212=You take extra damage from the crushing attack! +19213=You cannot disarm your opponent. +19214=Your target is already unarmed! +19215=You disarm their weapon! +19216=Your weapon has been disarmed! +19217=You cannot perform that attack while mounted or flying! +19218=This attack only works on mounted or flying targets +19219=The force of your attack has dislodged them from their mount! +19220=You have been knocked off of your mount by %i ! +19221=Your weapon must have a dose of poison to perform an infectious strike! +19222=Your precise strike has increased the level of the poison by 1 +19223=The poison seems extra effective! +19224=You have poisoned your target : %i +19225=%i : poisoned you! +19226=You deliver a mortal wound! +19227=You have been mortally wounded! +19228=Your target resists paralysis. +19229=You resist paralysis. +19230=The attack has temporarily paralyzed you! +19231=You lack the required stealth to perform that attack +19232=You strike and hide in the shadows! +19233=You are dazed by the attack and your attacker vanishes! +19234=Your confusion has passed, you may now arm a weapon! +19235=You are no longer mortally wounded. +19236=The bleeding wounds have healed, you are no longer bleeding! } EOF diff --git a/data/dictionaries/dictionary.FRE b/data/dictionaries/dictionary.FRE index e15ef13b8..3ca36b929 100644 --- a/data/dictionaries/dictionary.FRE +++ b/data/dictionaries/dictionary.FRE @@ -5502,5 +5502,42 @@ 19140=La saleté doit d'abord être ramollie. 19141=Vous plantez la graine dans le bol de terre. 19142=Vous devez utiliser une graine sur un bol de terre ! +// [19201-19300] Coups spéciaux +19201=Vous avez besoin de %i compétence d'arme pour effectuer cette attaque +19202=Vous avez besoin de %i mana pour effectuer cette attaque +19203=Votre attaque pénètre leur armure ! +19204=Le coup a pénétré votre armure ! +19205=Votre cible saigne ! +19206=Vous saignez ! +19207=Vous saignez abondamment +19208=%i saigne abondamment +19209=Vous avez provoqué une commotion cérébrale ! +19210=Vous vous sentez désorienté ! +19211=Vous avez porté un coup fatal ! +19212=Vous subissez des dégâts supplémentaires grâce à l'attaque écrasante ! +19213=Vous ne pouvez pas désarmer votre adversaire. +19214=Votre cible n'est déjà pas armée ! +19215=Vous désarmez votre arme ! +19216=Votre arme a été désarmée ! +19217=Vous ne pouvez pas effectuer cette attaque en étant monté ou en vol ! +19218=Cette attaque ne fonctionne que sur des cibles montées ou volantes +19219=La force de votre attaque les a déloges de leur monture ! +19220=Vous avez été renversé de votre monture par %i ! +19221=Votre arme doit contenir une dose de poison pour effectuer une frappe contagieuse ! +19222=Votre frappe précise a augmenté le niveau du poison de 1 +19223=Le poison semble très efficace ! +19224=Vous avez empoisonné votre cible : %i +19225=%i : vous a empoisonné ! +19226=Vous infligez une blessure mortelle ! +19227=Vous avez été mortellement blessé ! +19228=Votre cible résiste à la paralysie. +19229=Vous résistez à la paralysie. +19230=L'attaque vous a temporairement paralysé ! +19231=Vous n'avez pas la furtivité requise pour effectuer cette attaque +19232=Vous frappez et vous cachez dans l'ombre ! +19233=Vous êtes étourdi par l'attaque et votre attaquant disparaît ! +19234=Votre confusion est passée, vous pouvez maintenant armer une arme ! +19235=Vous n'êtes plus mortellement blessé. +19236=Les plaies saignantes ont guéri, vous ne saignez plus ! } EOF diff --git a/data/dictionaries/dictionary.GER b/data/dictionaries/dictionary.GER index ae581671c..c8cd466f3 100644 --- a/data/dictionaries/dictionary.GER +++ b/data/dictionaries/dictionary.GER @@ -5346,5 +5346,42 @@ 19140=Der Schmutz muss zuerst aufgeweicht werden. 19141=Sie pflanzen den Samen in die Schüssel mit Erde. 19142=Sie müssen einen Samen auf eine Schüssel voller Erde verwenden! +// [19201-19300] Spezialbewegungen +19201=Sie benötigen %i Waffenfähigkeit, um diesen Angriff auszuführen +19202=Du brauchst %i Mana, um diesen Angriff auszuführen +19203=Dein Angriff durchdringt ihre Rüstung! +19204=Der Schlag hat deine Rüstung durchdrungen! +19205=Dein Ziel blutet! +19206=Du blutest! +19207=Sie bluten stark +19208=%i blutet stark +19209=Sie haben sich eine Gehirnerschütterung zugezogen! +19210=Sie fühlen sich desorientiert! +19211=Du hast einen vernichtenden Schlag versetzt! +19212=Du erleidest zusätzlichen Schaden durch den vernichtenden Angriff! +19213=Sie können Ihren Gegner nicht entwaffnen. +19214=Ihr Ziel ist bereits unbewaffnet! +19215=Du entwaffnest ihre Waffe! +19216=Deine Waffe wurde entschärft! +19217=Sie können diesen Angriff nicht ausführen, während Sie reiten oder fliegen! +19218=Dieser Angriff funktioniert nur bei berittenen oder fliegenden Zielen +19219=Die Wucht deines Angriffs hat sie von ihrem Reittier gestoßen! +19220=Du wurdest von %i von deinem Reittier gestoßen! +19221=Ihre Waffe muss über eine Giftdosis verfügen, um einen ansteckenden Schlag auszuführen! +19222=Dein präziser Schlag hat die Giftstufe um 1 erhöht +19223=Das Gift scheint besonders wirksam zu sein! +19224=Sie haben Ihr Ziel vergiftet: %i +19225=%i: hat dich vergiftet! +19226=Du fügst eine tödliche Wunde zu! +19227=Du wurdest tödlich verwundet! +19228=Ihr Ziel widersteht einer Lähmung. +19229=Sie widerstehen einer Lähmung. +19230=Der Angriff hat Sie vorübergehend gelähmt! +19231=Ihnen fehlt die erforderliche Tarnung, um diesen Angriff auszuführen +19232=Du schlägst zu und versteckst dich im Schatten! +19233=Sie sind durch den Angriff benommen und Ihr Angreifer verschwindet! +19234=Ihre Verwirrung ist vorüber, Sie können jetzt eine Waffe bewaffnen! +19235=Sie sind nicht mehr tödlich verwundet. +19236=Die blutenden Wunden sind verheilt, Sie bluten nicht mehr! } EOF diff --git a/data/dictionaries/dictionary.ITA b/data/dictionaries/dictionary.ITA index 4ab0bff98..388de2822 100644 --- a/data/dictionaries/dictionary.ITA +++ b/data/dictionaries/dictionary.ITA @@ -5346,5 +5346,42 @@ 19140=Lo sporco deve prima essere ammorbidito. 19141=Pianta il seme nella ciotola di terra. 19142=Devi usare un seme su una ciotola di terra! +// [19201-19300] Mosse speciali +19201=Hai bisogno di %i abilità con l'arma per eseguire quell'attacco +19202=Hai bisogno di %i mana per eseguire quell'attacco +19203=Il tuo attacco penetra la loro armatura! +19204=Il colpo ha penetrato la tua armatura! +19205=Il tuo bersaglio sta sanguinando! +19206=Stai sanguinando! +19207=Stai sanguinando copiosamente +19208=%i sta sanguinando copiosamente +19209=Hai provocato una commozione cerebrale! +19210=Ti senti disorientato! +19211=Hai sferrato un colpo devastante! +19212=Subisci danni extra dall'attacco devastante! +19213=Non puoi disarmare il tuo avversario. +19214=Il tuo bersaglio è già disarmato! +19215=Disarma la loro arma! +19216=La tua arma è stata disarmata! +19217=Non puoi eseguire quell'attacco mentre sei a cavallo o mentre voli! +19218=Questo attacco funziona solo su bersagli montati o volanti +19219=La forza del tuo attacco li ha spostati dalla loro cavalcatura! +19220=Sei stato buttato giù dalla tua cavalcatura da %i! +19221=La tua arma deve avere una dose di veleno per eseguire un colpo infettivo! +19222=Il tuo colpo preciso ha aumentato il livello del veleno di 1 +19223=Il veleno sembra estremamente efficace! +19224=Hai avvelenato il tuo bersaglio: %i +19225=%i: ti ha avvelenato! +19226=Hai procurato una ferita mortale! +19227=Sei stato ferito a morte! +19228=Il tuo bersaglio resiste alla paralisi. +19229=Resisti alla paralisi. +19230=L'attacco ti ha temporaneamente paralizzato! +19231=Non hai la furtività necessaria per eseguire quell'attacco +19232=Colpisci e ti nascondi nell'ombra! +19233=Sei stordito dall'attacco e il tuo aggressore svanisce! +19234=La tua confusione è passata, ora puoi armare un'arma! +19235=Non sei più ferito a morte. +19236=Le ferite sanguinanti sono guarite, non stai più sanguinando! } EOF diff --git a/data/dictionaries/dictionary.POL b/data/dictionaries/dictionary.POL index ed50092f8..63070210e 100644 --- a/data/dictionaries/dictionary.POL +++ b/data/dictionaries/dictionary.POL @@ -5346,5 +5346,42 @@ 19140=Najpierw należy zmiękczyć brud. 19141=Zasiewasz ziarno w misce z ziemią. 19142=Musisz użyć nasion na misce ziemi! +// [19201-19300] Ruchy specjalne +19201=Potrzebujesz %i umiejętności posługiwania się bronią, aby wykonać ten atak +19202=Potrzebujesz %i many, aby wykonać ten atak +19203=Twój atak przebija ich zbroję! +19204=Cios przebił twoją zbroję! +19205=Twój cel krwawi! +19206=Krwawisz! +19207=Obficie krwawisz +19208=%i obficie krwawi +19209=Doznałeś wstrząsu mózgu! +19210=Czujesz się zdezorientowany! +19211=Zadałeś miażdżący cios! +19212=Otrzymujesz dodatkowe obrażenia od miażdżącego ataku! +19213=Nie możesz rozbroić przeciwnika. +19214=Twój cel jest już nieuzbrojony! +19215=Rozbrajasz ich broń! +19216=Twoja broń została rozbrojona! +19217=Nie możesz wykonać tego ataku na koniu lub w locie! +19218=Ten atak działa tylko na cele konne lub latające +19219=Siła twojego ataku zrzuciła ich z wierzchowca! +19220=Zostałeś strącony z wierzchowca przez %i! +19221=Twoja broń musi zawierać dawkę trucizny, aby wykonać zaraźliwy atak! +19222=Twoje precyzyjne uderzenie zwiększyło poziom trucizny o 1 +19223=Trucizna wydaje się wyjątkowo skuteczna! +19224=Otrułeś swój cel: %i +19225=%i: otrułem cię! +19226=Zadajesz śmiertelną ranę! +19227=Zostałeś śmiertelnie ranny! +19228=Twój cel jest odporny na paraliż. +19229=Jesteś odporny na paraliż. +19230=Atak chwilowo cię sparaliżował! +19231=Brakuje Ci wymaganej umiejętności ukrywania się, aby wykonać ten atak +19232=Uderzasz i chowasz się w cieniu! +19233=Jesteś oszołomiony atakiem i twój napastnik znika! +19234=Twoje zamieszanie minęło, możesz teraz uzbroić broń! +19235=Nie jesteś już śmiertelnie ranny. +19236=Krwawiące rany się zagoiły, już nie krwawisz! } EOF diff --git a/data/dictionaries/dictionary.PTG b/data/dictionaries/dictionary.PTG index aaa586b1c..d7287d3c3 100644 --- a/data/dictionaries/dictionary.PTG +++ b/data/dictionaries/dictionary.PTG @@ -5346,5 +5346,42 @@ 19140=A sujeira precisa ser amolecida primeiro. 19141=Você planta a semente na tigela de terra. 19142=Você deve usar uma semente em uma tigela de terra! +// [19201-19300] Movimentos Especiais +19201=Você precisa de %i habilidade com arma para realizar esse ataque +19202=Você precisa de %i mana para realizar esse ataque +19203=Seu ataque penetra na armadura deles! +19204=O golpe penetrou em sua armadura! +19205=Seu alvo está sangrando! +19206=Você está sangrando! +19207=Você está sangrando muito +19208=%i está sangrando profusamente +19209=Você causou uma concussão! +19210=Você se sente desorientado! +19211=Você desferiu um golpe esmagador! +19212=Você sofre dano extra com o ataque esmagador! +19213=Você não pode desarmar seu oponente. +19214=Seu alvo já está desarmado! +19215=Você desarma a arma deles! +19216=Sua arma foi desarmada! +19217=Você não pode realizar esse ataque enquanto estiver montado ou voando! +19218=Este ataque só funciona em alvos montados ou voadores +19219=A força do seu ataque os desalojou da montaria! +19220=Você foi derrubado da montaria por %i! +19221=Sua arma deve ter uma dose de veneno para realizar um ataque infeccioso! +19222=Seu ataque preciso aumentou o nível do veneno em 1 +19223=O veneno parece extremamente eficaz! +19224=Você envenenou seu alvo: %i +19225=%i: envenenou você! +19226=Você causou um ferimento mortal! +19227=Você foi mortalmente ferido! +19228=Seu alvo resiste à paralisia. +19229=Você resiste à paralisia. +19230=O ataque paralisou você temporariamente! +19231=Você não tem a furtividade necessária para realizar esse ataque +19232=Você ataca e se esconde nas sombras! +19233=Você fica atordoado com o ataque e seu atacante desaparece! +19234=Sua confusão passou, agora você pode armar uma arma! +19235=Você não está mais mortalmente ferido. +19236=As feridas sangrentas sararam, você não está mais sangrando! } EOF diff --git a/data/dictionaries/dictionary.SPA b/data/dictionaries/dictionary.SPA index 3a1d28694..f5c16bf63 100644 --- a/data/dictionaries/dictionary.SPA +++ b/data/dictionaries/dictionary.SPA @@ -5346,5 +5346,42 @@ 19140=Primero es necesario ablandar la suciedad. 19141=Plantas la semilla en el cuenco de tierra. 19142=¡Debes usar una semilla en un recipiente con tierra! +// [19201-19300] Movimientos especiales +19201=Necesitas %i habilidad con arma para realizar ese ataque +19202=Necesitas %i mana para realizar ese ataque +19203=¡Tu ataque penetra su armadura! +19204=¡El golpe atravesó tu armadura! +19205=¡Tu objetivo está sangrando! +19206=¡Estás sangrando! +19207=Estas sangrando profusamente +19208=%i está sangrando profusamente +19209=¡Has causado una conmoción cerebral! +19210=¡Te sientes desorientado! +19211=¡Has asestado un golpe aplastante! +19212=¡Recibes daño extra por el ataque aplastante! +19213=No puedes desarmar a tu oponente. +19214=¡Tu objetivo ya está desarmado! +19215=¡Desarmas su arma! +19216=¡Tu arma ha sido desarmada! +19217=¡No puedes realizar ese ataque mientras estás montado o volando! +19218=Este ataque sólo funciona en objetivos montados o voladores +19219=¡La fuerza de tu ataque los ha desalojado de su montura! +19220=¡%i te ha derribado de tu montura! +19221=¡Tu arma debe tener una dosis de veneno para realizar un ataque infeccioso! +19222=Tu golpe preciso ha aumentado el nivel del veneno en 1 +19223=¡El veneno parece extra efectivo! +19224=Has envenenado a tu objetivo: %i +19225=%i: ¡te envenenó! +19226=¡Has causado una herida mortal! +19227=¡Has sido herido de muerte! +19228=Tu objetivo resiste la parálisis. +19229=Resistes la parálisis. +19230=¡El ataque te ha paralizado temporalmente! +19231=Te falta el sigilo necesario para realizar ese ataque +19232=¡Atacas y te escondes en las sombras! +19233=¡Estás aturdido por el ataque y tu atacante desaparece! +19234=¡Tu confusión ha pasado, ahora puedes armar un arma! +19235=Ya no estás herido de muerte. +19236=Las heridas sangrantes han sanado, ¡ya no sangras! } EOF diff --git a/data/dictionaries/dictionary.ZRO b/data/dictionaries/dictionary.ZRO index af75b17d7..dba5d4de1 100644 --- a/data/dictionaries/dictionary.ZRO +++ b/data/dictionaries/dictionary.ZRO @@ -5341,5 +5341,42 @@ 19140=The dirt needs to be softened first. 19141=You plant the seed in the bowl of dirt. 19142=You must use a seed on a bowl of dirt! +// [19201-19300] Special Moves +19201=You need %i weapon skill to perform that attack +19202=You need %i mana to perform that attack +19203=Your attack penetrates their armor! +19204=The blow penetrated your armor! +19205=Your target is bleeding! +19206=You are bleeding! +19207=You are bleeding profusely +19208=%i is bleeding profusely +19209=You have delivered a concussion! +19210=You feel disoriented! +19211=You have delivered a crushing blow! +19212=You take extra damage from the crushing attack! +19213=You cannot disarm your opponent. +19214=Your target is already unarmed! +19215=You disarm their weapon! +19216=Your weapon has been disarmed! +19217=You cannot perform that attack while mounted or flying! +19218=This attack only works on mounted or flying targets +19219=The force of your attack has dislodged them from their mount! +19220=You have been knocked off of your mount by %i ! +19221=Your weapon must have a dose of poison to perform an infectious strike! +19222=Your precise strike has increased the level of the poison by 1 +19223=The poison seems extra effective! +19224=You have poisoned your target : %i +19225=%i : poisoned you! +19226=You deliver a mortal wound! +19227=You have been mortally wounded! +19228=Your target resists paralysis. +19229=You resist paralysis. +19230=The attack has temporarily paralyzed you! +19231=You lack the required stealth to perform that attack +19232=You strike and hide in the shadows! +19233=You are dazed by the attack and your attacker vanishes! +19234=Your confusion has passed, you may now arm a weapon! +19235=You are no longer mortally wounded. +19236=The bleeding wounds have healed, you are no longer bleeding! } EOF diff --git a/data/js/combat/blockequip.js b/data/js/combat/blockequip.js new file mode 100644 index 000000000..48c82f700 --- /dev/null +++ b/data/js/combat/blockequip.js @@ -0,0 +1,20 @@ +function onEquipAttempt( pEquipper, iEquipped ) +{ + var blockEquip = pEquipper.GetTempTag( "blockEquip" ); + if( blockEquip == true ) + { + iEquipped.SetTempTag( "charSer", pEquipper.serial.toString() ); + iEquipped.StartTimer( 10 ,1, true ); + return false; + } + + return true; +} + +function onTimer( timerObj, timerID ) +{ + var mChar = CalcCharFromSer(parseInt( timerObj.GetTempTag( "charSer" ))) + timerObj.container = mChar.pack; + timerObj.Refresh(); + timerObj.SetTempTag( "charSer", null ); +} \ No newline at end of file diff --git a/data/js/combat/special_moves.js b/data/js/combat/special_moves.js new file mode 100644 index 000000000..49dd46e2b --- /dev/null +++ b/data/js/combat/special_moves.js @@ -0,0 +1,883 @@ +function onSpecialMove( pUser, abilityID ) +{ + // Define the array of restricted ability IDs + var restrictedAbilities = [14, 15, 16, 17,18,19,20,21,22,23,24,25,29]; + + // Check if the abilityID is in the array of restricted abilities + if( restrictedAbilities.indexOf( abilityID ) != -1 ) + { + pUser.SysMessage( "This ability is not yet available." ); + TriggerEvent( 2206, "DeactivateSpecialMove", pUser, abilityID ); + return false; + } + + // Check Skills + if( !checkRequiredSkill( pUser, abilityID )) + return true; + + // Check Mana + if( !CheckMana( pUser, abilityID )) + return true; + + if( abilityID >= 1 ) + pUser.SetTempTag( "abilityID", abilityID ); + + return true; +} + +function checkSkillRequirement( pUser, requiredSkillLevel, requiredSkill, skillMessage, abilityID ) +{ + var pSock = pUser.socket; + if( pUser.skills[requiredSkill] < requiredSkillLevel ) + { + pSock.SysMessage( GetDictionaryEntry( 19201, pSock.language), skillMessage); // You need %i weapon skill to perform that attack + + TriggerEvent( 2206, "DeactivateSpecialMove", pUser, abilityID ); + return false; + } + return true; +} + +// archery 31 swordsmansip 40 macefighting 41 fencing 42 wrestling 43 +// Define the RequiredSkill function +function checkRequiredSkill( pUser, abilityID ) +{ + // Define weapon types and their skill requirements and if primary or secondary ability + var weaponTypes = { + "0x0df0": { primary: 13, secondary: 11, reqSkill: 41 }, + "0x0df1": { primary: 13, secondary: 11, reqSkill: 41 }, // Black Staves // WhirlwindAttack, ParalyzingBlow + + "0x0df2": { primary: 6, secondary: 5, reqSkill: 41 }, + "0x0df3": { primary: 6, secondary: 5, reqSkill: 41 }, + "0x0df4": { primary: 6, secondary: 5, reqSkill: 41 }, + "0x0df5": { primary: 6, secondary: 5, reqSkill: 41 }, // wands // Dismount, Disarm + + "0x0e81": { primary: 4, secondary: 5, reqSkill: 41 }, + "0x0e82": { primary: 4, secondary: 5, reqSkill: 41 }, // Shepherd's Crooks // CrushingBlow, Disarm + + "0x0e85": { primary: 7, secondary: 5, reqSkill: 40 }, + "0x0e86": { primary: 7, secondary: 5, reqSkill: 40 }, // pickaxe // DoubleStrike, Disarm + + "0x0e87": { primary: 2, secondary: 6, reqSkill: 42 }, + "0x0e88": { primary: 2, secondary: 6, reqSkill: 42 }, // Pitchforks // BleedAttack, Dismount + + "0x0e89": { primary: 7, secondary: 3, reqSkill: 41 }, + "0x0e8a": { primary: 7, secondary: 3, reqSkill: 41 }, // Quarter Staves // DoubleStrike, ConcussionBlow + + "0x0ec2": { primary: 2, secondary: 8, reqSkill: 40 }, + "0x0ec3": { primary: 2, secondary: 8, reqSkill: 40 }, // Cleavers // BleedAttack, InfectiousStrike + + "0x0ec4": { primary: 12, secondary: 2, reqSkill: 40 }, + "0x0ec5": { primary: 12, secondary: 2, reqSkill: 40 }, // Skinning Knives // ShadowStrike, BleedAttack + + "0x0f43": { primary: 1, secondary: 5, reqSkill: 40 }, + "0x0f44": { primary: 1, secondary: 5, reqSkill: 40 }, // hatchets // ArmorIgnore, Disarm + + "0x0f45": { primary: 2, secondary: 9, reqSkill: 40 }, + "0x0f46": { primary: 2, secondary: 9, reqSkill: 40 }, // Executioner Axes // BleedAttack, MortalStrike + + "0x0f47": { primary: 2, secondary: 3, reqSkill: 40 }, + "0x0f48": { primary: 2, secondary: 3, reqSkill: 40 }, // Battle Axes // BleedAttack, ConcussionBlow + + "0x0f49": { primary: 4, secondary: 6, reqSkill: 40 }, + "0x0f4a": { primary: 4, secondary: 6, reqSkill: 40 }, // Axes // CrushingBlow, Dismount + + "0x0f4b": { primary: 7, secondary: 13, reqSkill: 40 }, + "0x0f4c": { primary: 7, secondary: 13, reqSkill: 40 }, // Double Axe // DoubleStrike, WhirlwindAttack + + "0x0f4e": { primary: 11, secondary: 6, reqSkill: 40 }, + "0x0f4e": { primary: 11, secondary: 6, reqSkill: 40 }, // Bardiches // ParalyzingBlow, Dismount + + "0x0f4f": { primary: 3, secondary: 9, reqSkill: 31 }, + "0x0f50": { primary: 3, secondary: 9, reqSkill: 31 }, // Crossbows // ConcussionBlow, MortalStrike + + "0x0f51": { primary: 8, secondary: 12, reqSkill: 40 }, + "0x0f52": { primary: 8, secondary: 12, reqSkill: 40 }, // Daggers // InfectiousStrike, ShadowStrike + + "0x0f5c": { primary: 3, secondary: 5, reqSkill: 41 }, + "0x0f5d": { primary: 3, secondary: 5, reqSkill: 41 }, // Maces // ConcussionBlow, Disarm + + "0x0f5e": { primary: 4, secondary: 1, reqSkill: 40 }, + "0x0f5f": { primary: 4, secondary: 1, reqSkill: 40 }, // Broadswords // CrushingBlow, ArmorIgnore + + "0x13b7": { primary: 1, secondary: 3, reqSkill: 40 }, + "0x13b8": { primary: 1, secondary: 3, reqSkill: 40 }, + "0x0f60": { primary: 1, secondary: 3, reqSkill: 40 }, + "0x0f61": { primary: 1, secondary: 3, reqSkill: 40 }, // Longswords // ArmorIgnore, ConcussionBlow + + "0x0f62": { primary: 1, secondary: 11, reqSkill: 42 }, + "0x0f63": { primary: 1, secondary: 11, reqSkill: 42 }, // Spears // ArmorIgnore, ParalyzingBlow + + "0x0fb4": { primary: 4, secondary: 12, reqSkill: 41 }, + "0x0fb5": { primary: 4, secondary: 12, reqSkill: 41 }, // Sledge hammers // CrushingBlow, ShadowStrike + + "0x13af": { primary: 1, secondary: 2, reqSkill: 40 }, + "0x13b0": { primary: 1, secondary: 2, reqSkill: 40 }, // War Axes // ArmorIgnore, BleedAttack + + "0x13b1": { primary: 11, secondary: 9, reqSkill: 31 }, + "0x13b2": { primary: 11, secondary: 9, reqSkill: 31 }, // Bows // ParalyzingBlow, MortalStrike + + "0x13b3": { primary: 12, secondary: 6, reqSkill: 41 }, + "0x13b4": { primary: 12, secondary: 6, reqSkill: 41 }, // Clubs // ShadowStrike, Dismount + + "0x13b5": { primary: 7, secondary: 11, reqSkill: 40 }, + "0x13b6": { primary: 7, secondary: 11, reqSkill: 40 }, // Scimitars // DoubleStrike, ParalyzingBlow + + "0x13b9": { primary: 11, secondary: 4, reqSkill: 40 }, + "0x13ba": { primary: 11, secondary: 4, reqSkill: 40 }, // Viking Swords // ParalyzingBlow, CrushingBlow + + "0x13fc": { primary: 10, secondary: 6, reqSkill: 31 }, + "0x13fd": { primary: 10, secondary: 6, reqSkill: 31 }, // Heavy Crossbows // MovingShot, Dismount + + "0x13e3": { primary: 4, secondary: 12, reqSkill: 41 }, + "0x13e4": { primary: 4, secondary: 12, reqSkill: 41 }, // Smith's Hammers // CrushingBlow, ShadowStrike + + "0x13f6": { primary: 8, secondary: 5, reqSkill: 40 }, + "0x13f7": { primary: 8, secondary: 5, reqSkill: 40 }, // Butcher Knives // InfectiousStrike,Disarm + + "0x13f8": { primary: 3, secondary: 0, reqSkill: 41 }, + "0x13f9": { primary: 3, secondary: 0, reqSkill: 41 }, // Gnarled Staves // ConcussionBlow,ForceOfNature + + "0x13fa": { primary: 13, secondary: 2, reqSkill: 40 }, + "0x13fb": { primary: 13, secondary: 2, reqSkill: 40 }, // Large Battle Axes // WhirlwindAttack,BleedAttack + + "0x13fe": { primary: 7, secondary: 1, reqSkill: 40 }, + "0x13ff": { primary: 7, secondary: 1, reqSkill: 40 }, // Katana // DoubleStrike,ArmorIgnore + + "0x1400": { primary: 1, secondary: 8, reqSkill: 42 }, + "0x1401": { primary: 1, secondary: 8, reqSkill: 42 }, // Kryss // ArmorIgnore,InfectiousStrike + + "0x1402": { primary: 12, secondary: 9, reqSkill: 42 }, + "0x1403": { primary: 12, secondary: 9, reqSkill: 42 }, // Short Spears // ShadowStrike,MortalStrike + + "0x1404": { primary: 2, secondary: 5, reqSkill: 42 }, + "0x1405": { primary: 2, secondary: 5, reqSkill: 42 }, // War Forks // BleedAttack,Disarm + + "0x1406": { primary: 4, secondary: 9, reqSkill: 41 }, + "0x1407": { primary: 4, secondary: 9, reqSkill: 41 }, // War Maces // CrushingBlow,MortalStrike + + "0x1438": { primary: 13, secondary: 4, reqSkill: 41 }, + "0x1439": { primary: 13, secondary: 4, reqSkill: 41 }, // War Hammers // WhirlwindAttack,CrushingBlow + + "0x143a": { primary: 7, secondary: 3, reqSkill: 41 }, + "0x143b": { primary: 7, secondary: 3, reqSkill: 41 }, // Mauls // DoubleStrike,ConcussionBlow + + "0x143c": { primary: 1, secondary: 9, reqSkill: 41 }, + "0x143d": { primary: 1, secondary: 9, reqSkill: 41 }, // Hammer Picks // ArmorIgnore,MortalStrike + + "0x143e": { primary: 13, secondary: 3, reqSkill: 40 }, + "0x143f": { primary: 13, secondary: 3, reqSkill: 40 }, // Halberds // WhirlwindAttack,ConcussionBlow + + "0x1440": { primary: 2, secondary: 12, reqSkill: 40 }, + "0x1441": { primary: 2, secondary: 12, reqSkill: 40 }, // Cutlasses // BleedAttack,ShadowStrike + + "0x1442": { primary: 7, secondary: 12, reqSkill: 40 }, + "0x1443": { primary: 7, secondary: 12, reqSkill: 40 } // Two Handed Axes // DoubleStrike,ShadowStrike + }; + + // Get items in user's hands + var itemRHand = pUser.FindItemLayer( 0x01 ); + var itemLHand = pUser.FindItemLayer( 0x02 ); + + // Check if either hand has an item + if( itemRHand != null ) + { + // Check item in the right hand + if( weaponTypes[itemRHand.sectionID] ) + { + var weapon = weaponTypes[itemRHand.sectionID]; + + if( abilityID == weapon.primary ) + { + return checkSkillRequirement( pUser, 700, weapon.reqSkill, "70", abilityID ); + } + else if( abilityID == weapon.secondary ) + { + return checkSkillRequirement( pUser, 900, weapon.reqSkill, "90", abilityID ); + } + } + } + else if( itemLHand != null ) + { + // Check item in the left hand + if( weaponTypes[itemLHand.sectionID] ) + { + var weapon = weaponTypes[itemLHand.sectionID]; + + if( abilityID == weapon.primary ) + { + return checkSkillRequirement( pUser, 700, weapon.reqSkill, "70", abilityID ); + } + else if( abilityID == weapon.secondary ) + { + return checkSkillRequirement( pUser, 900, weapon.reqSkill, "90", abilityID ); + } + } + } + else// checking if both hands null if so, it is a wrestling skill + { + if( abilityID == 5 ) + { + return checkSkillRequirement( pUser, 700, 43, "70" ); + } + else if( abilityID == 11 ) + { + return checkSkillRequirement( pUser, 900, 43, "90" ); + } + } + + return true; +} + +function getAbilityManaTable() +{// Mana is Based off 2003 AOS and 2005 ML + return { + 0: { manaAmount: 0 }, // Cancel Ability Attempt + 1: { manaAmount: 30 }, // Armor Ignore // Start AOS abiltiies + 2: { manaAmount: 30 }, // Bleed Attack + 3: { manaAmount: 30 }, // Concusion Blow + 4: { manaAmount: 30 }, // Crushing Blow + 5: { manaAmount: 20 }, // Disarm + 6: { manaAmount: 20 }, // Dismount + 7: { manaAmount: 30 }, // Double Strike + 8: { manaAmount: 20 }, // Infecting + 9: { manaAmount: 30 }, // Mortal Strike + 10: { manaAmount: 20 }, // Moving Shot + 11: { manaAmount: 35 }, // Paralyzing Blow + 12: { manaAmount: 25 }, // Shadow Strike + 13: { manaAmount: 25 } // Whirlwind Attack // End AOS abilities + /* 14-29 are not available + 14: { manaAmount: 30 }, // Riding Swipe // Start SE abiltiies + 15: { manaAmount: 30 }, // Frenzied Whirlwind + 16: { manaAmount: 30 }, // Block + 17: { manaAmount: 30 }, // Defense Mastery + 18: { manaAmount: 30 }, // Nerve Strike + 19: { manaAmount: 30 }, // Talon Strike + 20: { manaAmount: 30 }, // Feint + 21: { manaAmount: 30 }, // Dual Wield + 22: { manaAmount: 30 }, // Double shot + 23: { manaAmount: 30 }, // Armor Peirce // End SE abilities + 24: { manaAmount: 25 }, // Bladeweave // Start ML abilities + 25: { manaAmount: 15 }, // Force Arrow + 26: { manaAmount: 15 }, // Lightning Arrow + 27: { manaAmount: 25 }, // Psychic Attack + 28: { manaAmount: 35 }, // Serpent Arrow + 29: { manaAmount: 35 } // Force of Nature // End ML abilities*/ + }; +} + +function CheckMana( pUser, abilityID ) +{ + var pSock = pUser.socket; + var abilitieMana = getAbilityManaTable(); + var NextUse = pUser.GetTempTag( "doubleMana" ); + var iTime = GetCurrentClock(); + var Delay = 3000; // If ability is performed within 3 seconds of the last ability, it will then cost double mana + var requiredMana = abilitieMana[abilityID].manaAmount; + + if( NextUse == null ) + { + NextUse = 0; + } + + var isDoubleMana = ( iTime - NextUse ) < Delay; + if( isDoubleMana ) + { + requiredMana *= 2; + } + + if( pUser.mana < requiredMana ) + { + pSock.SysMessage( GetDictionaryEntry( 19202, pSock.language), requiredMana); // You need %i mana to perform that attack + TriggerEvent( 2206, "DeactivateSpecialMove", pUser, abilityID ); + return false; + } + else + { + return true; + } +} + +function DeductMana( pUser, abilityID ) +{ + var abilitieMana = getAbilityManaTable(); + var NextUse = pUser.GetTempTag( "doubleMana" ); + var iTime = GetCurrentClock(); + var Delay = 3000; // If ability is performed within 3 seconds of the last ability, it will then cost double mana + var requiredMana = abilitieMana[abilityID].manaAmount; + + if( NextUse == null ) + { + NextUse = 0; + } + + var isDoubleMana = ( iTime - NextUse ) < Delay; + if( isDoubleMana ) + { + requiredMana *= 2; + } + + pUser.mana -= requiredMana; + pUser.SetTempTag( "doubleMana", iTime.toString() ); +} + +function onCombatDamageCalc( pAttacker, pDefender, fightSkill, hitLoc ) +{ + var abilityID = pAttacker.GetTempTag( "abilityID" ); + var baseDamage = pAttacker.attack; + + if( baseDamage == -1 ) // No damage if weapon breaks + return 0; + + var damage = ApplyDamageBonuses( 1, pAttacker, pDefender, fightSkill, hitLoc, baseDamage ); + + if( damage < 1 ) + return 0; + + // Check if attacker has armor ignore enabled + if( abilityID == 1 ) // armorignore + { + // Armor Ignore ignores defense modifiers, but deals only 90% of potential damage + damage *= 0.9; + + if( fightSkill == 31 ) // Archery + { + // Cap damage from Armor Strike attack at 30 for archery weapons + if( damage > 30 ) + damage = 30; + } + else + { + // For all othe rfighting skills, cap damage from Armor Strike at 35 + if( damage > 35 ) + damage = 35; + } + } + else if( abilityID == 12 )// shadowstrike + { + damage *= 1.25; + } + else if( abilityID == 4 )// crushingblow + { + damage *= 1.5; + } + else if( abilityID == 3 )// ConcussionBlow + { + if( pDefender.maxhp > 0) + { + var hitsPercent = ( pDefender.hp / pDefender.maxhp ) * 100.0; + + var manaPercent = 0; + + if( pDefender.maxmana > 0 ) + manaPercent = ( pDefender.mana / pDefender.maxmana ) * 100.0; + + damage += Math.min(Math.floor(Math.abs(hitsPercent - manaPercent) / 4), 20); + } + } + else + { + // Otherwise, apply normal defense modifiers + damage = ApplyDefenseModifiers( 1, pAttacker, pDefender, fightSkill, hitLoc, damage, true ); + } + + // If damage after defense modifiers is below 0, do a small random amount of damage still + if( damage <= 0 ) + damage = RandomNumber( 0, 4 ); + + // If defender is a player, damage is divided by this modifier from uox.ini + if( pAttacker.npc && !pDefender.npc ) + damage /= GetServerSetting( "NPCDAMAGERATE" ); + + return damage; +} + +function onCombatHit( pAttacker, pDefender ) +{ + var abilityID = pAttacker.GetTempTag( "abilityID" ); + + onAbility( pAttacker, pDefender, abilityID ); +} + +function onAttack( pAttacker, pDefender ) +{ + var abilityID = pAttacker.GetTempTag( "abilityID" ); + + onAbility( pAttacker, pDefender, abilityID ); +} + +function onAbility( pAttacker, pDefender, abilityID ) +{ + var pSockAttacker = pAttacker.socket; + var pSockDefender = pDefender.socket; + + if( abilityID == 1 ) // armnor ignore + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 1 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19203, pSockAttacker.language ));// Your attack penetrates their armor! + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19204, pSockDefender.language ));// The blow penetrated your armor! + + pDefender.SoundEffect( 0x0056, true ); + pDefender.StaticEffect( 0x3728, 0x09, 0x06 ); + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 2 ) // bleedattack + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 2 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19205, pSockAttacker.language ));// Your target is bleeding! + if( pSockDefender != null ) + { + pSockDefender.SysMessage(GetDictionaryEntry(19206, pSockDefender.language));// You are bleeding! + + pSockDefender.TextMessage(GetDictionaryEntry(19207, pSockDefender.language), false, 0x21);// You are bleeding profusely + pSockDefender.TextMessage(pDefender.name, GetDictionaryEntry(19208, pSockDefender.language), true, 0x21, 1);// %i is bleeding profusely + } + + pDefender.StartTimer( 2000, 9300, 7001 ); // Start 2 second timer for blood and damage last total 10 seconds + pDefender.SetTempTag( "doBleed", true ); + + if( pDefender.socket) + TriggerEvent(50104, "AddBuff", pDefender, 1039, 1075829, 1075830, 10, " 1, 10 ,2" ); + + pAttacker.SoundEffect( 0x133, true ); + pDefender.StaticEffect( 0x377A, 0x09, 0x32 ); + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 3 ) // ConcussionBlow + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 3 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19209, pSockAttacker.language ));// You have delivered a concussion! + + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19210, pSockDefender.language ));// You feel disoriented! + + pAttacker.SoundEffect( 0x213, true ); + pDefender.StaticEffect( 0x377A, 0x09, 0x32 ); + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 4 ) // crushingblow + { + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 4 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19211, pSockAttacker.language ));// You have delivered a crushing blow! + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19212, pSockDefender.language ));// You take extra damage from the crushing attack! + + pAttacker.SoundEffect( 0x1E1, true ); + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 5 ) // Disarm + { + var itemRHand = pDefender.FindItemLayer( 0x01 ); + var itemLHand = pDefender.FindItemLayer( 0x02 ); + + if( pDefender.pack == null || itemLHand != null && itemLHand.movable >= 2 || itemRHand != null && itemRHand.movable >= 2 ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19213, pSockAttacker.language ));// You cannot disarm your opponent. + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return false; + } + + if( itemLHand != null && itemLHand.type == 9 || itemRHand != null && itemRHand.type == 9 ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19214, pSockAttacker.language ));// Your target is already unarmed! + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return false; + } + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 5 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pAttacker.SoundEffect( 0x3B9, true ); + pDefender.StaticEffect( 0x37BE, 0x09, 0x32 ); + + pSockAttacker.SysMessage( GetDictionaryEntry( 19215, pSockAttacker.language ));// You disarm their weapon! + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19216, pSockDefender.language ));// Your weapon has been disarmed! + + if( itemLHand != null ) + { + itemLHand.container = pDefender.pack; + } + + if( itemRHand != null ) + { + itemRHand.container = pDefender.pack; + } + + pDefender.AddScriptTrigger(7002);//block equip for 5 seconds script added + pDefender.SetTempTag( "blockEquip", true ); + pDefender.StartTimer( 5000, 9100, 7001 ); + + TriggerEvent(50104, "AddBuff", pDefender, 0x3ea, 1075637, 0, 5, " " ); + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 6 ) // Dismount + { + // Check to see if player is mount or flying. + if( pAttacker.isonhorse || pAttacker.isflying ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19217, pSockAttacker.language ));// You cannot perform that attack while mounted or flying! + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return true; + } + + // Only Can work on players or npcs that is mounted + if( !pDefender.isonhorse || !pDefender.isflying ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19218, pSockAttacker.language ));// This attack only works on mounted or flying targets + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return true; + } + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 6 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + //Lesser Hiryu have an 80% chance of missing this attack needs added + + //This is the Dismount Information sent to Attacker and Defender + pDefender.SoundEffect( 0x140, true ); + pDefender.StaticEffect( 0x3728, 0x09, 0x06 ); + pSockAttacker.SysMessage( GetDictionaryEntry( 19219, pSockAttacker.language ));// The force of your attack has dislodged them from their mount! + pDefender.Dismount(); + + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19220, pSockDefender.language ), pAttacker.name );// You have been knocked off of your mount by %i ! + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 7 ) // Double Strike + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 7 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 8 ) // Infectious Strike + { + var itemRHand = pAttacker.FindItemLayer(0x01); + var itemLHand = pAttacker.FindItemLayer(0x02); + + if( itemLHand != null && itemLHand.poison <= 0 || itemRHand != null && itemRHand.poison <= 0 ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19221, pSockAttacker.language ));// Your weapon must have a dose of poison to perform an infectious strike! + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return; + } + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 8 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + var level = 0; + var chance = Math.random(); + if( pAttacker.skills[30] >= 0 && pAttacker.skills[30] <= 199 ) + { + level = 1; + } + else if( pAttacker.skills[30] >= 200 && pAttacker.skills[30] <= 399 ) + { + level = 2; + } + else if( pAttacker.skills[30] >= 400 && pAttacker.skills[30] <= 599 ) + { + level = 3; + } + else if( pAttacker.skills[30] >= 600 && pAttacker.skills[30] <= 1000 ) + { + level = 4; + } + + // Adjust the poison level based on chance + if( chance < 0.2 ) + { + level--; // Decrease the level by 1 + if( level < 0 ) + { + level = 1; // Ensure the level doesn't go below 0 and is always set to least 1 + } + } + else if( chance > 0.8 ) + { + level++; // Increase the level by 1 + pSockAttacker.SysMessage( GetDictionaryEntry( 19222, pSockAttacker.language ));// Your precise strike has increased the level of the poison by 1 + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19223, pSockDefender.language ));// The poison seems extra effective! + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19224, pSockAttacker.language), pDefender.name);// You have poisoned your target : + if( pSockDefender != null ) + pSockDefender.SysMessage( pAttacker.name, GetDictionaryEntry( 19225, pSockDefender.language ));// %i : poisoned you! + + pDefender.poison = level; + + pAttacker.SoundEffect( 0xDD, true ); + pDefender.StaticEffect( 0x3728, 0x09, 0x32 ); + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 9 ) // Mortal Strike + { + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 9 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19226, pSockAttacker.language ));// You deliver a mortal wound! + + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19227, pSockDefender.language ));// You have been mortally wounded! + + pAttacker.SoundEffect( 0x1E1, true ); + pDefender.StaticEffect( 0x37B9, 0x09, 0x32 ); + + pDefender.SetTempTag( "blockHeal", true ); + + var seconds = 6000; // We want this applied to players even if they are "offline" (aka disconnected but not vanished from view yet) + if( pDefender.npc ) + { + seconds = 12000; + } + pDefender.StartTimer(seconds, 9200, true ); + + if( pDefender.socket ) + TriggerEvent( 50104, "AddBuff", pDefender, 1027, 1075810, 1075811, 6, " " ); + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 10 ) // Moving Shot + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 10 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 11 ) // ParalyzingBlow + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 11 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pAttacker.SoundEffect( 0x204, true ); + pDefender.StaticEffect( 0x376A, 0x09, 0x32 ); + var isImmune = pDefender.GetTempTag( "isImmune" ) + + if( isImmune != null && isImmune == true ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19228, pSockAttacker.language ));// Your target resists paralysis. + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19229, pSockDefender.language ));// You resist paralysis. + return true; + } + + var seconds = 3000; // We want this applied to players even if they are "offline" (aka disconnected but not vanished from view yet) + if( pDefender.npc ) + { + seconds = 6000; + } + else if( pDefender.socket ) + { + pSockDefender.TextMessage( GetDictionaryEntry( 19230, pSockDefender.language ), false, 0x3b2, 0, pDefender.serial );// The attack has temporarily paralyzed you! + } + + pDefender.SetTempTag( "isImmune", true ); + pDefender.StartTimer( seconds + 8000, 9000, 7001 ); + pDefender.StartTimer( seconds, 8000, 7001 ); + pDefender.frozen = true; + + if( pAttacker.socket ) + { + pSockAttacker.SysMessage( GetDictionaryEntry( 17702, pAttacker.socket.language), false, 0x3b2, 0, pAttacker.serial );// You deliver a paralyzing blow! + } + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } + else if( abilityID == 12 ) // shadowstrike + { + if( pAttacker.skills[47] < 800 ) // Stealth + { + pSockAttacker.SysMessage( GetDictionaryEntry( 19231, pSockAttacker.language ));// "You lack the required stealth to perform that attack + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + return true; + } + + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 12 ) + TriggerEvent( 2206, "DeactivateSpecialMove", pAttacker, abilityID ); + + //checking mana + if( CheckMana( pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + pSockAttacker.SysMessage( GetDictionaryEntry( 19232, pSockAttacker.language ));// You strike and hide in the shadows! + if( pSockDefender != null ) + pSockDefender.SysMessage( GetDictionaryEntry( 19233, pSockDefender.language ));// You are dazed by the attack and your attacker vanishes! + + pAttacker.StaticEffect( 0x376A, 0x09, 0x06 ); + + pDefender.SoundEffect( 0x482, true ); + pDefender.StaticEffect( 0x37BE, 0x09, 0x06 ); + + pAttacker.atWar = false; + pDefender.atWar = false; + pAttacker.visible = 1; + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID ); + } + else if( abilityID == 13 ) // Whirlwind Attack + { + // Clear out any current ability the player is doing when he switches abilities + if( abilityID != 13 ) + TriggerEvent(2206, "DeactivateSpecialMove", pAttacker, abilityID); + + //checking mana + if( CheckMana(pAttacker, abilityID )) + { + DeductMana( pAttacker, abilityID ); + } + + TriggerEvent( 2206, "ClearSpecialMove", pAttacker, abilityID );// Clear the Ability after success + } +} + +function onTimer( timerObj, timerID ) +{ + var socket = timerObj.socket; + var abilityID = timerObj.GetTempTag( "abilityID" ); + var damage = 31; + + if( timerObj == null || timerObj.dead) + { + timerObj.frozen = false; + timerObj.SetTempTag( "isImmune", null ); + timerObj.RemoveScriptTrigger( 7002 ); + timerObj.SetTempTag( "blockEquip", null ); + timerObj.SetTempTag( "blockHeal", null ); + timerObj.KillJSTimer( 9400, 7001 ); + timerObj.SetTempTag( "doBleed", null ); + TriggerEvent( 2206, "ClearSpecialMove", timerObj, abilityID ); + return; + } + else if( timerID == 8000 ) + { + timerObj.frozen = false; + } + else if( timerID == 9000 ) + { + timerObj.SetTempTag( "isImmune", null ); + } + else if( timerID == 9100 ) + { + timerObj.RemoveScriptTrigger( 7002 ); + timerObj.SetTempTag( "blockEquip", null ); + if( socket != null ) + socket.SysMessage( GetDictionaryEntry( 19234, socket.language ));// Your confusion has passed, you may now arm a weapon! + } + else if( timerID == 9200 ) + { + timerObj.SetTempTag("blockHeal", null ); + socket.SysMessage( GetDictionaryEntry( 19235, socket.language ));// You are no longer mortally wounded. + } + + if( timerID >= 9300 && timerID < 9310 ) + { + var damage = RandomNumber( 1, 10 ); + //timerObj.StaticEffect( 0x122A, 0, 15); // blood effect got to figure how to add it to ground. + timerObj.health -= damage; + timerObj.StartTimer( 2000, 9300 + 1, 7001 );//restart timer every 2 seconds until it shuts off + } + else if( timerID == 9310 ) + { + timerObj.SetTempTag( "doBleed", null ); + timerObj.KillJSTimer( 9400, 7001 ); + if( socket != null ) + socket.SysMessage( GetDictionaryEntry( 19236, socket.language ));// The bleeding wounds have healed, you are no longer bleeding! + } +} diff --git a/data/js/item/potion.js b/data/js/item/potion.js index 141b9fefb..23f3de1b4 100644 --- a/data/js/item/potion.js +++ b/data/js/item/potion.js @@ -172,7 +172,7 @@ function onUseChecked( pUser, iUsed ) case 4: // Heal Potion if( pUser.health < pUser.maxhp ) { - if( pUser.poison > 0 ) + if( pUser.poison > 0 || pUser.GetTempTag( "blockHeal" ) == true ) { pUser.SysMessage( GetDictionaryEntry( 9058, socket.language )); // You can not heal yourself in your current state. return; diff --git a/data/js/jse_fileassociations.scp b/data/js/jse_fileassociations.scp index 1f4d1773f..84b69d1f9 100644 --- a/data/js/jse_fileassociations.scp +++ b/data/js/jse_fileassociations.scp @@ -100,6 +100,7 @@ 2203=server/misc/charges_left_tooltip.js 2204=server/network/0xDF_buffBar.js 2205=server/misc/spawnergump.js +2206=server/network/0xbf_special_move.js // Server Data [2500-2749] 2500=server/data/weapontypes.js @@ -336,6 +337,8 @@ // Combat Scripts [7000-7499] //------------------------------------------- 7000=combat/peacemake_effect.js +7001=combat/special_moves.js +7002=combat/blockequip.js 7003=combat/leechstats.js //------------------------------------------- @@ -343,6 +346,7 @@ //------------------------------------------- 8000=player/death/return_stolen_items.js 8001=player/young_player.js +8002=player/death/resurrectpenalty.js // House Scripts [15000-15500] 15000=server/house/house.js diff --git a/data/js/player/death/resurrectpenalty.js b/data/js/player/death/resurrectpenalty.js new file mode 100644 index 000000000..33301b094 --- /dev/null +++ b/data/js/player/death/resurrectpenalty.js @@ -0,0 +1,134 @@ +function ResurrectFamePenalty( pUser ) +{ + if( pUser.fame > 0 ) + { + // Calculate 10% of the fame + var amount = Math.floor( pUser.fame / 10 ); + pUser.fame -= amount; + } +} + +// Penalty to karma is disabled by default, but can be enabled +// via a TriggerEvent call in js/item/shrines.js (onGumpPress) +function ResurrectKarmaPenalty( pUser ) +{ + if( pUser.karma > 0 ) + { + // Calculate 10% of the karma + var amount = Math.floor( pUser.karma / 10 ); + pUser.karma -= amount; + } +} + +function ResurrectMurderPenalty( pUser ) +{ + // Ensure the pUser has committed at least 5 short-term murders + if( pUser.murdercount >= 5 ) + { + // Calculate the loss percentage + var loss = ( 100.0 - ( 4.0 + ( pUser.murdercount / 5.0 ))) / 100.0; + + // Clamp the loss percentage between 85% and 95% + if( loss < 0.85 ) + { + loss = 0.85; // Minimum 15% reduction + } + else if( loss > 0.95 ) + { + loss = 0.95; // Maximum 5% reduction + } + + // Apply penalties to strength, intelligence, and dexterity + if( pUser.strength * loss > 10 ) + { + pUser.strength = RandomNumber( 10, pUser.strength * loss ); + } + if( pUser.intelligence * loss > 10 ) + { + pUser.intelligence = RandomNumber( 10, pUser.intelligence * loss ); + } + if( pUser.dexterity * loss > 10 ) + { + pUser.dexterity = RandomNumber( 10, pUser.dexterity * loss ); + } + + // ResurrectSkillPenalty( pUser ); + } +} + +// Penalty to skills is disabled by default, but can be enabled +// by uncommenting call in ResurrectMurderPenalty (for murderers) or +// for all players via a TriggerEvent call in js/item/shrines.js (onGumpPress) +function ResurrectSkillPenalty( pUser ) +{ + // Define the reduction range (89% to 91%) + var reductionMin = 89; + var reductionMax = 91; + + var originalSkills = []; // Array to store original skill values + + // Apply a 10% reduction to all 64 skills + for( var skillID = 0; skillID < 64; skillID++ ) + { + var baseSkill = pUser.Skills[ skillID ]; // Get skill value + var reducedSkill = RandomNumber( + (baseSkill * reductionMin) / 100, + (baseSkill * reductionMax) / 100 + ); + originalSkills.push( baseSkill ); // Store original skill value + pUser.Skills[ skillID ] = reducedSkill; // Apply the reduced skill value + } + + pUser.SetTag( "originalSkills", originalSkills.join( "," )); + + // Start the recovery timer + pUser.StartTimer( 15000, 0, false ); // 15 seconds interval, calls back to the current script + pUser.SetTag( "recoveryCount", 0 ); // Track recovery intervals +} + +// Skill Recovery handler triggered by StartTimer +function onTimer( timerObj, timerID ) +{ + if( timerID == 0 ) + { + var recoveryCount = timerObj.GetTag( "recoveryCount" ); + var maxRecoveryCount = 100; // 100 intervals = 25 minutes + + // Parse the original skills from the tag + var originalSkills = timerObj.GetTag( "originalSkills" ).split( "," ); + + // Iterate through all skills and gradually restore + for( var skillID = 0; skillID < 64; skillID++ ) + { + var reducedSkill = timerObj.Skills[skillID]; + var originalSkill = parseInt( originalSkills[skillID] ); + + if( reducedSkill < originalSkill ) + { + // Randomize recovery by adding between 0.1% and 0.11% of the original value + var recoveryStep = RandomNumber( + (originalSkill * 0.1) / 100, + (originalSkill * 0.11) / 100 + ); + timerObj.Skills[ skillID ] = Math.min( originalSkill, reducedSkill + recoveryStep ); + } + } + + recoveryCount++; + timerObj.SetTag( "recoveryCount", recoveryCount ); + + // If recovery is not complete, restart the timer + if( recoveryCount < maxRecoveryCount ) + { + timerObj.StartTimer( 15000, 0, false ); // 15 seconds interval + } + else + { + // Recovery complete + timerObj.SetTag( "recoveryCount", null ); + timerObj.SetTag( "originalSkills", null ); + } + } +} + +function _restorecontext_() {} diff --git a/data/js/server/global.js b/data/js/server/global.js index c68a778fc..aebb80ae4 100644 --- a/data/js/server/global.js +++ b/data/js/server/global.js @@ -2,6 +2,8 @@ // Supported Events trigger for every character/item, use with care function onLogin( socket, pChar ) { + const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); + // Display Admin Welcome Gump for characters on admin account, until a choice has been made if( pChar.accountNum == 0 ) { @@ -37,6 +39,11 @@ function onLogin( socket, pChar ) TriggerEvent( 8001, "CheckYoungStatus", socket, pChar, true ); } + if( coreShardEra >= EraStringToNum( "aos" ) && ( !pChar.npc && !pChar.HasScriptTrigger( 7001 )))// Attach the special moves Book + { + pChar.AddScriptTrigger( 7001 ); + } + // Re-adds Buff for disguise kit if player still has time left. var currentTime = GetCurrentClock(); var disguiseKitTime = pChar.GetJSTimer( 1, 5023 ); @@ -70,6 +77,8 @@ function onLogout( pSock, pChar ) function onCreatePlayer( pChar ) { + const coreShardEra = EraStringToNum( GetServerSetting( "CoreShardEra" )); + // If player character is created on a Young account, give them Young-specific items if( pChar.account.isYoung ) { @@ -81,6 +90,12 @@ function onCreatePlayer( pChar ) TriggerEvent( 8001, "GiveYoungPlayerItems", pChar.socket, pChar ); } + + //Attach the special moves Book + if( coreShardEra >= EraStringToNum( "aos" ) && ( !pChar.npc && !pChar.HasScriptTrigger( 7001 ))) + { + pChar.AddScriptTrigger( 7001 ); + } } // Generic global-script function to look up data in /shared/jsWorldData/ folder diff --git a/data/js/server/network/0xbf_special_move.js b/data/js/server/network/0xbf_special_move.js new file mode 100644 index 000000000..1fc8dae05 --- /dev/null +++ b/data/js/server/network/0xbf_special_move.js @@ -0,0 +1,34 @@ +function ClearSpecialMove( pUser, abilityID ) +{ + var socket = pUser.socket; + var toSend = new Packet; + + toSend.ReserveSize( 7 ) + toSend.WriteByte( 0, 0xbf ); // Packet + toSend.WriteShort( 1, 0x07 ); // Length + toSend.WriteShort( 3, 0x21 ); // SubCmd + toSend.WriteByte( 5, abilityID ); // Ability ID + toSend.WriteByte( 6, 0 ); // On/off + socket.Send( toSend ); + toSend.Free(); + + pUser.SetTempTag( "abilityID", null ); + pUser.SetTempTag( "doubleMana", null ); +} + +function DeactivateSpecialMove( pUser, abilityID ) +{ + var socket = pUser.socket; + var toSend = new Packet; + + toSend.ReserveSize( 7 ) + toSend.WriteByte( 0, 0xbf ); // Packet + toSend.WriteShort( 1, 0x07 ); // Length + toSend.WriteShort( 3, 0x21 ); // SubCmd + toSend.WriteByte( 5, abilityID ); // Ability ID + toSend.WriteByte( 6, 0); // On/off + socket.Send( toSend ); + toSend.Free(); + + pUser.SetTempTag( "abilityID", null ); +} diff --git a/data/js/skill/healing.js b/data/js/skill/healing.js index 78010b144..668ae4646 100644 --- a/data/js/skill/healing.js +++ b/data/js/skill/healing.js @@ -241,6 +241,32 @@ function onCallback1( socket, ourObj ) } else // Heal { + + if( ourObj.GetTempTag( "blockHeal" ) == true ) + { + if( ourObj != mChar && ourObj.socket ) + { + socket.SysMessage( "You cannot heal that target in their current state." ); + } + else + { + socket.SysMessage( GetDictionaryEntry( 9058, socket.language ));// You can not heal yourself in your current state. + } + } + else if( ourObj.GetTempTag( "doBleed" ) == true ) + { + if( ourObj != mChar && ourObj.socket ) + { + socket.SysMessage( "You bind the wound and stop the bleeding" ); + } + else + { + socket.SysMessage( "The bleeding wounds have healed, you are no longer bleeding!" ); + } + ourObj.KillJSTimer( 9300, 7001 ); + ourObj.SetTempTag( "doBleed", null ); + } + // Consume some bandages if( bItem.amount > 1 ) { diff --git a/source/Changelog.txt b/source/Changelog.txt index c8c59c777..6e47b0d6c 100644 --- a/source/Changelog.txt +++ b/source/Changelog.txt @@ -1,6 +1,9 @@ 21/01/2025 - Dragon Slayer Fixed damage dealt in combat was incorrectly modified while applying defense modifiers. (combat.cpp) +15/12/2024 - Dragon Slayer + Added Ressurrect Penalty Script (js/player/death/resurrectpenalty.js) that controls any type of penalty you want on the char after resurrecting via shrines + 07/12/2024 - Dragon Slayer Updated the packet 0xf1 to reflect the current CUO Web Ping while maintaining backward compatibility with older ping statuses. (0xf1_freeshardServerPoll.js) (Thanks Karasho and Xuri) @@ -79,6 +82,13 @@ 27/05/2024 - Dragon Slayer Added Missing Wand ID's to combat weapon type in core and in js. +25/05/2024 - Dragon Slayer + Added special_moves.js There is 12 special aos moves you can find on uoguide.com. + Added blockequip.js This script is used to block reqeuiping weapons. + Thanks to Xuri for making unequipattemp work for chars and not just items. + Added OnCombatHit + -Triggers for character with event attached when someone has taken damage. + 13/05/2024 - Dragon Slayer Added New Shield Type 107 so shield ID's no longer have to be in hard code for shields to work properly diff --git a/source/cChar.cpp b/source/cChar.cpp index 319737117..7fee0ca7a 100644 --- a/source/cChar.cpp +++ b/source/cChar.cpp @@ -2885,6 +2885,7 @@ CItem *CChar::GetItemAtLayer( ItemLayers Layer ) //| Purpose - Wears the item toWear and adjusts the stats if any are //| required to change. Returns true if successfully equipped //o------------------------------------------------------------------------------------------------o +void Bounce( CSocket *bouncer, CItem *bouncing, UI08 mode = 5 ); bool CChar::WearItem( CItem *toWear ) { // Run event prior to equipping item, allowing script to prevent equip @@ -2902,6 +2903,27 @@ bool CChar::WearItem( CItem *toWear ) } } + scriptTriggers.clear(); + scriptTriggers.shrink_to_fit(); + scriptTriggers = this->GetScriptTriggers(); + for( auto i : scriptTriggers ) + { + cScript *tScript = JSMapping->GetScript( i ); + if( tScript != nullptr ) + { + // If script returns false, prevent item from being equipped + if( tScript->OnEquipAttempt( this, toWear ) == 0 ) + { + CSocket *mSock = this->GetSocket(); + if( mSock != nullptr ) + { + Bounce( mSock, toWear ); + } + return false; + } + } + } + bool rValue = true; ItemLayers tLayer = toWear->GetLayer(); if( tLayer != IL_NONE ) // Layer == 0 is a special case, for things like trade windows and such @@ -2987,6 +3009,22 @@ bool CChar::TakeOffItem( ItemLayers Layer ) } } + scriptTriggers.clear(); + scriptTriggers.shrink_to_fit(); + scriptTriggers = this->GetScriptTriggers(); + for( auto i : scriptTriggers ) + { + cScript *tScript = JSMapping->GetScript( i ); + if( tScript != nullptr ) + { + // If script returns false, prevent item from being equipped + if( tScript->OnUnequipAttempt( this, itemLayers[Layer] ) == 0 ) + { + return false; + } + } + } + if( Layer == IL_PACKITEM ) // It's our pack! { SetPackItem( nullptr ); diff --git a/source/cScript.cpp b/source/cScript.cpp index 058650050..bcc7c9d10 100644 --- a/source/cScript.cpp +++ b/source/cScript.cpp @@ -3909,6 +3909,37 @@ SI08 cScript::OnCombatEnd( CChar *currChar, CChar *targChar ) return TryParseJSVal( rval ); } +//o------------------------------------------------------------------------------------------------o +//| Function - cScript::OnCombatHit() +//o------------------------------------------------------------------------------------------------o +//| Purpose - Triggers for character with event attached when someone has taken damage. +//| +//o------------------------------------------------------------------------------------------------o +SI08 cScript::OnCombatHit( CChar *attacker, CChar *defender ) +{ + const SI08 RV_NOFUNC = -1; + if( !ValidateObject( attacker ) || !ValidateObject( defender )) + return RV_NOFUNC; + + if( !ExistAndVerify( seOnCombatHit, "onCombatHit" )) + return RV_NOFUNC; + + jsval rval, params[2]; + JSObject *attObj = JSEngine->AcquireObject( IUE_CHAR, attacker, runTime ); + JSObject *defObj = JSEngine->AcquireObject( IUE_CHAR, defender, runTime ); + + params[0] = OBJECT_TO_JSVAL( attObj ); + params[1] = OBJECT_TO_JSVAL( defObj ); + JSBool retVal = JS_CallFunctionName( targContext, targObject, "onCombatHit", 2, params, &rval ); + if( retVal == JS_FALSE ) + { + SetEventExists( seOnCombatHit, false ); + return RV_NOFUNC; + } + + return TryParseJSVal( rval ); +} + //o------------------------------------------------------------------------------------------------o //| Function - cScript::OnDeathBlow() //| Date - 8th February, 2006 diff --git a/source/cScript.h b/source/cScript.h index a2813ba72..a37af9705 100644 --- a/source/cScript.h +++ b/source/cScript.h @@ -97,6 +97,7 @@ enum ScriptEvent seOnCombatStart, // ** allows overriding what happens when combat is initiated seOnAICombatTarget, // ** allows overriding target selection taking place for regular AI behaviours seOnCombatEnd, // ** allows overriding what happens when combat ends + seOnCombatHit, // ** allows overriding what happens when combat hits seOnDeathBlow, seOnCombatDamageCalc, seOnDamage, @@ -281,6 +282,7 @@ class cScript SI08 OnSkillGump( CChar *mChar ); SI08 OnUseBandageMacro( CSocket *mSock, CChar *targChar, CItem *bandageItem ); SI08 OnAICombatTarget( CChar *attacker, CChar *target ); + SI08 OnCombatHit( CChar *attacker, CChar *defender ); SI08 OnCombatStart( CChar *attacker, CChar *defender ); SI08 OnCombatEnd( CChar *attacker, CChar *defender ); diff --git a/source/combat.cpp b/source/combat.cpp index a0b5abc06..d923465d8 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -3023,6 +3023,15 @@ bool CHandleCombat::HandleCombat( CSocket *mSock, CChar& mChar, CChar *ourTarg ) // Show hit messages, if enabled DoHitMessage( &mChar, ourTarg, hitLoc, ourDamage ); + for( auto scriptTrig : scriptTriggers ) + { + cScript *toExecute = JSMapping->GetScript( scriptTrig ); + if( toExecute != nullptr ) + { + toExecute->OnCombatHit( &mChar, ourTarg ); + } + } + // Interrupt Spellcasting if( !ourTarg->IsNpc() && targSock != nullptr ) {