• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Spell TFS 1.1 Double Shot

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
1,557
Solutions
11
Reaction score
774
Hello Otland. I come to release a spell that took me a long time to make, I'm not uber scripter like andu :D But my script was in fact inspired by andu and his creative "Seven Arrows" remake. My spell works like this. ANY DISTANCE WEAPON in the game can be used to shoot a second shot of whatever you are using.

Example if you have an arbelest with an infernal bolt and are hunting, you use this spell it will check to make sure you are using compatible bow/crossbow, with arrows/bolts then shoot the infernal bolt for another shot, damage is based off of distance skill, and it also factors in weapons attack and monsters armor just like a real shot would.



It doesn't however miss target unless the monsters armor is high enough, it would be easy to alter for it to miss based off of monsters shielding too. However you will never see the animation miss. Critical hits and other special bonuses and configurations aren't in this spell however, I have also programmed in all the throwable items such as throwing knife, spears, throwing stars, ect. The only one missing is small stone, and thats because on my server I use a slingshot with small stones as ammo, so mine isn't quite done yet.

DAMAGE TYPE:
Spell also has the damage type programmed in for ammunition that does different damage than phyisical, example envenomed arrow does earth damage, so when you shoot a second envenomed arrow it also does earth based damage.



EDIT:Did some optimizing (could make better use of tables still) Updated it to 1.1. Uses less code, fixed a couple bugs I didn't know existed, should work great, hope you guys enjoy! :D


And Now for the script: spells/scripts/attack/doubleshot.lua
 
Last edited:
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_DRAWBLOOD)
combat:setParameter(COMBAT_PARAM_BLOCKARMOR, 1)
combat:setParameter(COMBAT_PARAM_BLOCKSHIELD, 1)

local Crossbows = {2455, 5803, 8849, 8850, 8851, 8852, 8853, 18453, 16111, 22419, 22420, 22421}
local Bows = {2456, 7438, 8854, 8855, 8856, 8857, 8858, 10295, 13873, 15643, 15644, 18454, 22416, 22417, 22418}
local Arrows = {2544, 2545, 2546, 7365, 7364, 7838, 7840, 7839, 7850, 15648, 18437, 18304}
local Bolts = {2543, 2547, 6529, 7363, 15649, 18435, 18436}
local Throwables = {2111, 2389, 3965, 7367, 7378, 2399, 7368, 7366, 2410}

local animation = {
[2543] = CONST_ANI_BOLT,
[2547] = CONST_ANI_POWERBOLT,
[6529] = CONST_ANI_INFERNALBOLT,
[7363] = CONST_ANI_PIERCINGBOLT,
[15649] = CONST_ANI_VORTEXBOLT,
[18435] = CONST_ANI_PRISMATICBOLT,
[18436] = CONST_ANI_DRILLBOLT,

[2544] = CONST_ANI_ARROW,
[2545] = CONST_ANI_POISONARROW,
[2546] = CONST_ANI_BURSTARROW,
[7365] = CONST_ANI_ONYXARROW,
[7364] = CONST_ANI_SNIPERARROW,
[7838] = CONST_ANI_FLASHARROW,
[7840] = CONST_ANI_FLAMMINGARROW,
[7839] = CONST_ANI_SHIVERARROW,
[7850] = CONST_ANI_EARTHARROW,
[15648] = CONST_ANI_TARSALARROW,
[18437] = CONST_ANI_ENVENOMEDARROW,
[18304] = CONST_ANI_CRYSTALLINEARROW,

[2111] = CONST_ANI_SNOWBALL,
[2389] = CONST_ANI_SPEAR,
[3965] = CONST_ANI_HUNTINGSPEAR,
[7367] = CONST_ANI_ENCHANTEDSPEAR,
[7378] = CONST_ANI_ROYALSPEAR,
[2399] = CONST_ANI_THROWINGSTAR,
[7368] = CONST_ANI_REDSTAR,
[7366] = CONST_ANI_GREENSTAR,
[2410] = CONST_ANI_THROWINGKNIFE
}

local damageType = {
[2544] = COMBAT_PHYSICALDAMAGE,
[2545] = COMBAT_PHYSICALDAMAGE,
[2546] = COMBAT_FIREDAMAGE,
[7365] = COMBAT_PHYSICALDAMAGE,
[7364] = COMBAT_PHYSICALDAMAGE,
[7838] = COMBAT_ENERGYDAMAGE,
[7840] = COMBAT_FIREDAMAGE,
[7839] = COMBAT_ICEDAMAGE,
[7850] = COMBAT_EARTHDAMAGE,
[15648] = COMBAT_EARTHDAMAGE,
[18437] = COMBAT_EARTHDAMAGE,
[18304] = COMBAT_EARTHDAMAGE,
[2111] = COMBAT_PHYSICALDAMAGE,
[2389] = COMBAT_PHYSICALDAMAGE,
[3965] = COMBAT_PHYSICALDAMAGE,
[7367] = COMBAT_PHYSICALDAMAGE,
[7378] = COMBAT_PHYSICALDAMAGE,
[2399] = COMBAT_PHYSICALDAMAGE,
[7368] = COMBAT_PHYSICALDAMAGE,
[7366] = COMBAT_PHYSICALDAMAGE,
[2410] = COMBAT_PHYSICALDAMAGE,
[2543] = COMBAT_PHYSICALDAMAGE,
[2547] = COMBAT_PHYSICALDAMAGE,
[6529] = COMBAT_PHYSICALDAMAGE,
[7363] = COMBAT_PHYSICALDAMAGE,
[15649] = COMBAT_PHYSICALDAMAGE,
[18435] = COMBAT_PHYSICALDAMAGE,
[18436] = COMBAT_PHYSICALDAMAGE,
[2111] = COMBAT_PHYSICALDAMAGE,
[2389] = COMBAT_PHYSICALDAMAGE,
[3965] = COMBAT_PHYSICALDAMAGE,
[7367] = COMBAT_PHYSICALDAMAGE,
[7378] = COMBAT_PHYSICALDAMAGE,
[2399] = COMBAT_PHYSICALDAMAGE,
[7368] = COMBAT_PHYSICALDAMAGE,
[7366] = COMBAT_PHYSICALDAMAGE,
[2410] = COMBAT_PHYSICALDAMAGE,
[1294] = COMBAT_PHYSICALDAMAGE
}
local magicEffect = 0
local dmgType = 0

local function doDoubleShotCombat(player, var)
    function getDistanceDamage(player, skill, attackValue, attackFactor)
        local level = player:getLevel()
            min = -(attackValue)
            max = -(attackValue + (level/5) + (skill/2) * 2.5)
        return min, max
    end
    local item = player:getSlotItem(CONST_SLOT_AMMO)
    combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "getDistanceDamage")
    combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, magicEffect)
    combat:setParameter(COMBAT_PARAM_TYPE, dmgType)
    combat:execute(player, var)
    item:remove(1)
    return true
end

local function doDoubleShot(player, var)
local leftHand = pushThing(player:getSlotItem(CONST_SLOT_LEFT)).itemid
local rightHand = pushThing(player:getSlotItem(CONST_SLOT_RIGHT)).itemid
local ammoSlot = pushThing(player:getSlotItem(CONST_SLOT_AMMO)).itemid
    dmgType = damageType[ammoSlot]
    if(isInArray(Crossbows, leftHand) or isInArray(Crossbows, rightHand)) then
        if(isInArray(Bolts, ammoSlot)) then
            magicEffect = animation[ammoSlot]
            return doDoubleShotCombat(player, var)
        else
            return player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You need bolts")
        end
    elseif(isInArray(Bows, leftHand) or isInArray(Bows, rightHand)) then
        if(isInArray(Arrows, ammoSlot)) then
            magicEffect = animation[ammoSlot]
            return doDoubleShotCombat(player, var)
        else
            return player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You need arrows")
        end
    elseif(isInArray(Throwables, leftHand) or isInArray(Throwables, rightHand)) then
        if(isInArray(Throwables, leftHand)) then
            magicEffect = animation[leftHand]
        else
            magicEffect = animation[rightHand]
        end
        return doDoubleShotCombat(player, var)
    end
    return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need a distance weapon")
end

function onCastSpell(player, var)
    return doDoubleShot(player, var)
end

then in spells.xml add

Code:
    <instant name="Double Shot" words="exevo double shot" lvl="10" mana="50" prem="0" range="5" needtarget="1" blockwalls="1" needweapon="1" exhaustion="2000" group="attack" groupcooldown="500" icon="107" needlearn="0"  script="attack/doubleshot.lua">
    <vocation name="Paladin"/>
    <vocation name="Royal Paladin"/>
    </instant>

PS. CREDITS TO FLATLANDER for helping me with the tables
 
Last edited:
Will try it in an hour, looks good, well done!

Kind Regards,
Eldin.
Thanks :D

I was for sure you were going to try it out. I see you on all the same threads I am on :D

It's nice man, worked hard on it... Best part is its a base, now if I want to make a spell that does all kinds of stuff or set conditions or w/e, I can make it work with any distance weapon :D
 
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_DRAWBLOOD)
combat:setParameter(COMBAT_PARAM_BLOCKARMOR, 1)


function onGetFormulaValues(cid, level, skill, weaponAttack, ammoAttack)
    if (weaponAttack ~= 0 and ammoAttack ~= 0) then
        min = -((weaponAttack + ammoAttack) + ((level/10)) + (skill/10) * 0.7)
        max = -((weaponAttack + ammoAttack) + ((level/10)) + (skill/10) * 1.1)
    else
        min = -((ammoAttack*1.2) + ((level/10) + (skill/10)) * 0.7)
        max = -((ammoAttack*1.2) + ((level/10) + (skill/10)) * 1.1)
    end
    return min, max
    end

combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
combat:getCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")



Crossbows = {2455, 5803, 8849, 8850, 8851, 8852, 8853, 18453, 16111, 22419, 22420, 22421}
Bows = {2456, 7438, 8854, 8855, 8856, 8857, 8858, 10295, 13873, 15643, 15644, 18454, 22416, 22417, 22418}
Arrows = {2544, 2545, 2546, 7365, 7364, 7838, 7840, 7839, 7850, 15648, 18437, 18304}
Bolts = {2543, 2547, 6529, 7363, 15649, 18435, 18436}
Throwables = {2111, 2389, 3965, 7367, 7378, 2399, 7368, 7366, 2410}

crossbowAnimation = {
[2543] = CONST_ANI_BOLT,
[2547] = CONST_ANI_POWERBOLT,
[6529] = CONST_ANI_INFERNALBOLT,
[7363] = CONST_ANI_PIERCINGBOLT,
[15649] = CONST_ANI_VORTEXBOLT,
[18435] = CONST_ANI_PRISMATICBOLT,
[18436] = CONST_ANI_DRILLBOLT
}

bowAnimation = {
[2544] = CONST_ANI_ARROW,
[2545] = CONST_ANI_POISONARROW,
[2546] = CONST_ANI_BURSTARROW,
[7365] = CONST_ANI_ONYXARROW,
[7364] = CONST_ANI_SNIPERARROW,
[7838] = CONST_ANI_FLASHARROW,
[7840] = CONST_ANI_FLAMMINGARROW,
[7839] = CONST_ANI_SHIVERARROW,
[7850] = CONST_ANI_EARTHARROW,
[15648] = CONST_ANI_TARSALARROW,
[18437] = CONST_ANI_ENVENOMEDARROW,
[18304] = CONST_ANI_CRYSTALLINEARROW
}

throwAnimation = {
[2111] = CONST_ANI_SNOWBALL,
[2389] = CONST_ANI_SPEAR,
[3965] = CONST_ANI_HUNTINGSPEAR,
[7367] = CONST_ANI_ENCHANTEDSPEAR,
[7378] = CONST_ANI_ROYALSPEAR,
[2399] = CONST_ANI_THROWINGSTAR,
[7368] = CONST_ANI_REDSTAR,
[7366] = CONST_ANI_GREENSTAR,
[2410] = CONST_ANI_THROWINGKNIFE
}

damageType = {
[2544] = COMBAT_PHYSICALDAMAGE,
[2545] = COMBAT_PHYSICALDAMAGE,
[2546] = COMBAT_FIREDAMAGE,
[7365] = COMBAT_PHYSICALDAMAGE,
[7364] = COMBAT_PHYSICALDAMAGE,
[7838] = COMBAT_ENERGYDAMAGE,
[7840] = COMBAT_FIREDAMAGE,
[7839] = COMBAT_ICEDAMAGE,
[7850] = COMBAT_EARTHDAMAGE,
[15648] = COMBAT_EARTHDAMAGE,
[18437] = COMBAT_EARTHDAMAGE,
[18304] = COMBAT_EARTHDAMAGE,
[2111] = COMBAT_PHYSICALDAMAGE,
[2389] = COMBAT_PHYSICALDAMAGE,
[3965] = COMBAT_PHYSICALDAMAGE,
[7367] = COMBAT_PHYSICALDAMAGE,
[7378] = COMBAT_PHYSICALDAMAGE,
[2399] = COMBAT_PHYSICALDAMAGE,
[7368] = COMBAT_PHYSICALDAMAGE,
[7366] = COMBAT_PHYSICALDAMAGE,
[2410] = COMBAT_PHYSICALDAMAGE,
[2543] = COMBAT_PHYSICALDAMAGE,
[2547] = COMBAT_PHYSICALDAMAGE,
[6529] = COMBAT_PHYSICALDAMAGE,
[7363] = COMBAT_PHYSICALDAMAGE,
[15649] = COMBAT_PHYSICALDAMAGE,
[18435] = COMBAT_PHYSICALDAMAGE,
[18436] = COMBAT_PHYSICALDAMAGE,
[2111] = COMBAT_PHYSICALDAMAGE,
[2389] = COMBAT_PHYSICALDAMAGE,
[3965] = COMBAT_PHYSICALDAMAGE,
[7367] = COMBAT_PHYSICALDAMAGE,
[7378] = COMBAT_PHYSICALDAMAGE,
[2399] = COMBAT_PHYSICALDAMAGE,
[7368] = COMBAT_PHYSICALDAMAGE,
[7366] = COMBAT_PHYSICALDAMAGE,
[2410] = COMBAT_PHYSICALDAMAGE,
[1294] = COMBAT_PHYSICALDAMAGE
}


function onCastSpell(cid, var)
local player = Player(cid)
-- local casPos = player:getPosition()
-- local tarPos = player:getTarget():getPosition()
local leftHand = pushThing(player:getSlotItem(CONST_SLOT_LEFT)).itemid
local rightHand = pushThing(player:getSlotItem(CONST_SLOT_RIGHT)).itemid
local ammoSlot = pushThing(player:getSlotItem(CONST_SLOT_AMMO)).itemid
local magicEffect = 0
local dmgType = 0
local tmp = 0
local weaponAttack = 0
local ammoAttack = 0

    if(not player) then
        return false
    end
  
        if(isInArray(Crossbows, leftHand) or isInArray(Crossbows, rightHand)) then
            if(isInArray(Crossbows, leftHand)) then
                    weaponAttack = ItemType(leftHand):getAttack()
                    else
                    weaponAttack = ItemType(rightHand):getAttack()
                        end
    if(isInArray(Bolts, ammoSlot))then
            ammoAttack = ItemType(ammoSlot):getAttack()
            magicEffect = crossbowAnimation[ammoSlot]
            dmgType = damageType[ammoSlot]
            temp = 1
            else
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You need bolts")
            return false
            end
    elseif(isInArray(Bows, leftHand) or isInArray(Bows, rightHand)) then
    if(isInArray(Arrows, ammoSlot)) then
            ammoAttack = ItemType(ammoSlot):getAttack()
            magicEffect = bowAnimation[ammoSlot]
            dmgType = damageType[ammoSlot]
            temp = 1
            else
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You need arrows")
            return false
            end
    elseif(leftHand == 5907 or rightHand ==5907) then
    if(ammoSlot == 1294) then
            ammoAttack = ItemType(ammoSlot):getAttack()
            magicEffect = CONST_ANI_SMALLSTONE
            dmgType = damageType[ammoSlot]
            temp = 1
            else
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You need stones")
            return false
            end
    elseif(isInArray(Throwables, leftHand) or isInArray(Throwables, rightHand)) then
        if(isInArray(Throwables, leftHand)) then
            magicEffect = throwAnimation[leftHand]
            dmgType = damageType[leftHand]
            else
            magicEffect = throwAnimation[rightHand]
            dmgType = damageType[rightHand]
            end
            temp = 1
            else
            temp = 2
            end
          
  
    if(temp == 1) then
        if ammoAttack == nil then return ammoAttack == 0 end
        if weaponAttack == nil then return weaponAttack == 0 end
            combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, magicEffect)
            combat:setParameter(COMBAT_PARAM_TYPE, dmgType)
            combat:execute(cid, var)
            player:removeItem(ammoSlot,1)
            return true
    elseif(temp ~= 1) then
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need a distance weapon")
            return false
    else
            return false
            end
            end

What's wrong with my formula for damage in this script, I can't get it to work right.. Any idea's @Flatlander
I am obviously trying to pull the attack from the weapon and from the ammo for my formula but my console reads

Lua Script Error: [Test Interface]
data/spells/scripts/rapididshotdevelopment.lua
data/spells/scripts/rapididshotdevelopment.lua:18: attempt to call method 'getCa
llback' (a nil value)
stack traceback:
[C]: in function 'getCallback'
data/spells/scripts/rapididshotdevelopment.lua:18: in main chunk
[Warning - Event::checkScript] Can not load script: scripts/rapididshotdevelopme
nt.lua
data/spells/scripts/rapididshotdevelopment.lua:107: ')' expected near 'then'

works fine if I remove
combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
combat:getCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
and put
combat:setFormula(COMBAT_FORMULA_SKILL, 1.5,1.5,1.5,1.8)
 
Does anyone know what I am doing wrong with my

function onGetFormulaValues(cid, level, skill, weaponAttack, ammoAttack)
if (weaponAttack ~= 0 and ammoAttack ~= 0) then
min = -((weaponAttack + ammoAttack) + ((level/10)) + (skill/10) * 0.7)
max = -((weaponAttack + ammoAttack) + ((level/10)) + (skill/10) * 1.1)
else
min = -((ammoAttack*1.2) + ((level/10) + (skill/10)) * 0.7)
max = -((ammoAttack*1.2) + ((level/10) + (skill/10)) * 1.1)
end
return min, max
end

combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
combat:getCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")

@Limos @Ninja Maybe one of you could help? Please?
 
Remove
Code:
combat:getCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
getCallback does not exist, Metatable:Combat
 
Remove
Code:
combat:getCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")
getCallback does not exist, Metatable:Combat
Removed it and moved the setCallback to just above

combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, magicEffect)

now error reads.


Lua Script Error: [Spell Interface]
(Unknown scriptfile)
attempt to call a nil value
[Warning - CallBack::loadCallBack] Event onGetFormulaValues not found.

Lua Script Error: [Spell Interface]
(Unknown scriptfile)
attempt to call a nil value
 
CALLBACK_PARAM_SKILLVALUE uses 4 parameters, so remove one (level) and use player:getLevel() instead.
 
Alright I removed it and put it like you said, but still same error, I think its because I didn't do it right trying to set the values for weaponAttack and ammoAttack maybe? Or do I even need them as parameters since its already defined else where in the script?
 
Ok I found how to fix it, lots of problems, but I got it working now :D formula is based off weapon attack, ammo attack, level and distance level :D
 
amazing spell :eek:

but it's a bit OP imo.. with lvl 200 skill 100 and inf bolt you hit ~650~ per 2 seconds.. and with exori gran con ~180~
so think for more balance you should consider a lower value here (COMBAT_FORMULA_SKILL, 1.2,1.2,1.3,1.3)

anyway, great job and thank you for sharing.

yours,
 
Use what ever formula you want, the benefit is all the checks for the ammo and removing it and using the correct animations and all that good stuff..... I don't even use formula like that, I do mine differently, it wasn't tested on vocations made like tibia, so I mean, it works for me, but it does do a good medium for the average hit of what you hit with your weapon and ammo. That being said, I tested it thoroughly for that. If I hit highest of 300 w/ x weapon and x ammo, but average I hit 100'sh, sometimes even lower (<---that's the part I don't like), sometimes higher, but with highest of 300, using my spell then you will hit around 150'sh, that's how it is based to be, but this is factored in the same way tibia factors in their attacks with attack value, skill level, and player level, (i don't recall adding in attack factor mattering, but that's simple add in)....

You are very welcome sir :D
 
BUMP

Everyone who gets a notification for this, just letting you guys know, a couple bugs were fixed, code was optimized some (alot less lines now), and I updated it to 1.1

The spell itself is still missing quite a few distance weapons, but it's easy to add.
 
Hey,
I added bow and arrow (ids 3447 for arrow, 3350 for bow) and it still says that I need to equip weapon (even if that's good weapon).

Could you help me (after all this time? :) )
 
Hey,
I added bow and arrow (ids 3447 for arrow, 3350 for bow) and it still says that I need to equip weapon (even if that's good weapon).

Could you help me (after all this time? :) )

this spell does not damage at all, any ideas using tfs 1.2

Sorry guys been away a long time. I'm planning on updating this tho just give a little bit of time. Updates usually bring improvements from me as well so plz be patient.
 
Back
Top