Advertisement
Guest User

autoattack.lua

a guest
Dec 24th, 2015
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 24.68 KB | None | 0 0
  1. -- cfg
  2. local togglestorage = 2557 -- must be the same as in talkaction
  3. local dualWielding = false -- if two weapons are equipped, works with fist fighting also if both hands are empty
  4.  
  5. -- normal attack values: 2000, 1, 1
  6. local speedMelee = 450
  7. local dmgMelee = 0.25
  8. local dmgMeleeAmount = 4
  9.  
  10. local speedDist = 450
  11. local dmgDist = 0.25
  12. local dmgDistAmount = 4
  13.  
  14. local speedMagic = 450
  15. local dmgMagic = 0.25
  16. local dmgMagicAmount = 4
  17. -- end of cfg
  18.  
  19. function Player:getBaseVoc()
  20.     if self:getVocation():getDemotion() then
  21.         return self:getVocation():getDemotion():getId()
  22.     end
  23.     return self:getVocation():getId()
  24. end
  25.  
  26. local wandElement = {
  27.     ["earth"] = COMBAT_EARTHDAMAGE,
  28.     ["ice"] = COMBAT_ICEDAMAGE,
  29.     ["energy"] = COMBAT_ENERGYDAMAGE,
  30.     ["fire"] = COMBAT_FIREDAMAGE,
  31.     ["death"] = COMBAT_DEATHDAMAGE,
  32.     ["holy"] = COMBAT_HOLYDAMAGE
  33. }
  34.  
  35. local shootTypes = {
  36.     ["spear"] = CONST_ANI_SPEAR,
  37.     ["bolt"] = CONST_ANI_BOLT,
  38.     ["arrow"] = CONST_ANI_ARROW,
  39.     ["fire"] = CONST_ANI_FIRE,
  40.     ["energy"] = CONST_ANI_ENERGY,
  41.     ["poisonarrow"] = CONST_ANI_POISONARROW,
  42.     ["burstarrow"] = CONST_ANI_BURSTARROW,
  43.     ["throwingstar"] = CONST_ANI_THROWINGSTAR,
  44.     ["throwingknife"] = CONST_ANI_THROWINGKNIFE,
  45.     ["smallstone"] = CONST_ANI_SMALLSTONE,
  46.     ["death"] = CONST_ANI_DEATH,
  47.     ["largerock"] = CONST_ANI_LARGEROCK,
  48.     ["snowball"] = CONST_ANI_SNOWBALL,
  49.     ["powerbolt"] = CONST_ANI_POWERBOLT,
  50.     ["poison"] = CONST_ANI_POISON,
  51.     ["infernalbolt"] = CONST_ANI_INFERNALBOLT,
  52.     ["huntingspear"] = CONST_ANI_HUNTINGSPEAR,
  53.     ["enchantedspear"] = CONST_ANI_ENCHANTEDSPEAR,
  54.     ["redstar"] = CONST_ANI_REDSTAR,
  55.     ["greenstar"] = CONST_ANI_GREENSTAR,
  56.     ["royalspear"] = CONST_ANI_ROYALSPEAR,
  57.     ["sniperarrow"] = CONST_ANI_SNIPERARROW,
  58.     ["onyxarrow"] = CONST_ANI_ONYXARROW,
  59.     ["piercingbolt"] = CONST_ANI_PIERCINGBOLT,
  60.     ["whirlwindsword"] = CONST_ANI_WHIRLWINDSWORD,
  61.     ["whirlwindaxe"] = CONST_ANI_WHIRLWINDAXE,
  62.     ["whirlwindclub"] = CONST_ANI_WHIRLWINDCLUB,
  63.     ["etherealspear"] = CONST_ANI_ETHEREALSPEAR,
  64.     ["ice"] = CONST_ANI_ICE,
  65.     ["earth"] = CONST_ANI_EARTH,
  66.     ["holy"] = CONST_ANI_HOLY,
  67.     ["suddendeath"] = CONST_ANI_SUDDENDEATH,
  68.     ["flasharrow"] = CONST_ANI_FLASHARROW,
  69.     ["flammingarrow"] = CONST_ANI_FLAMMINGARROW,
  70.     ["shiverarrow"] = CONST_ANI_SHIVERARROW,
  71.     ["energyball"] = CONST_ANI_ENERGYBALL,
  72.     ["smallice"] = CONST_ANI_SMALLICE,
  73.     ["smallholy"] = CONST_ANI_SMALLHOLY,
  74.     ["smallearth"] = CONST_ANI_SMALLEARTH,
  75.     ["eartharrow"] = CONST_ANI_EARTHARROW,
  76.     ["explosion"] = CONST_ANI_EXPLOSION,
  77.     ["cake"] = CONST_ANI_CAKE,
  78.     ["tarsalarrow"] = CONST_ANI_TARSALARROW,
  79.     ["vortexbolt"] = CONST_ANI_VORTEXBOLT,
  80.     ["prismaticbolt"] = CONST_ANI_PRISMATICBOLT,
  81.     ["crystallinearrow"] = CONST_ANI_CRYSTALLINEARROW,
  82.     ["drillbolt"] = CONST_ANI_DRILLBOLT,
  83.     ["envenomedarrow"] = CONST_ANI_ENVENOMEDARROW,
  84.     ["gloothspear"] = CONST_ANI_GLOOTHSPEAR,
  85.     ["simplearrow"] = CONST_ANI_SIMPLEARROW,
  86. }
  87.  
  88. local meleeweapons = {WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}
  89. local wp_skillType = {
  90.     [WEAPON_SWORD] = SKILL_SWORD,
  91.     [WEAPON_CLUB] = SKILL_CLUB,
  92.     [WEAPON_AXE] = SKILL_AXE
  93. }
  94.  
  95. -- get shootType, executed on server startup and reload
  96. local wp_shooteffects = {}
  97. local wp_ammotype = {}
  98. local wp_hitChance = {}
  99.  
  100. function registerShootEffectsFromItems()
  101.     local file = 'data/items/items.xml'
  102.     local itemId = 0
  103.     for line in io.lines(file) do
  104.         for mi,id,mid,name in line:gmatch('<(%a-)%s*id%s*=%s*"(%d+)"%s*(.-)%s*name%s*=%s*"(.-)"') do
  105.             if mi == 'item' then
  106.                 itemId = tonumber(id)
  107.             end
  108.         end
  109.  
  110.         for key,value in line:gmatch('<attribute key="(.-)" value="(.-)"') do
  111.             if key == "shootType" then
  112.                 wp_shooteffects[itemId] = value
  113.             end
  114.            
  115.             if key == "ammoType" then
  116.                 wp_ammotype[itemId] = (value == "bolt" and 1 or 2)
  117.             end
  118.            
  119.             if key == "maxHitChance" then
  120.                 wp_hitChance[itemId] = value
  121.             end
  122.         end
  123.     end
  124.  
  125.     return true
  126. end
  127. registerShootEffectsFromItems()
  128.  
  129. local wp_otherInfo = {}
  130. local wp_vocInfo = {}
  131. function registerWeapons()
  132.     local file = 'data/weapons/weapons.xml'
  133.     local lastId = 0
  134.    
  135.     for line in io.lines(file) do
  136.         for wp,id,mid,typ in line:gmatch('<(%a-)%s*id%s*=%s*"(%d+)"%s*(.-)%s*type%s*=%s*"(.-)"') do
  137.             lastId = tonumber(id)
  138.             if wp == 'wand' then
  139.                 for lv, mana, minv, maxv in mid:gmatch('"(%d+)".-"(%d+)".-"(%d+)".-"(%d+)"') do
  140.                     wp_otherInfo[lastId] = {element = wandElement[typ], level = tonumber(lv), mana = tonumber(mana), min = tonumber(minv), max = tonumber(maxv)}
  141.                 end
  142.             end
  143.         end
  144.        
  145.         for wp,id in line:gmatch('<(%a-)%s*id%s*=%s*"(%d+)"') do
  146.             lastId = tonumber(id)
  147.             if wp == 'melee' then
  148.                 if line:match('action%s*=%s*"removecharge"') then
  149.                     wp_otherInfo[lastId] = {removecharges = true}
  150.                 end
  151.             elseif wp == 'distance' then
  152.                 if line:match('action%s*=%s*"removecount"') then
  153.                     wp_otherInfo[lastId] = {breakchance = 100}
  154.                 else
  155.                     for brkc in line:gmatch('breakchance%s*=%s*"(%d+)"') do
  156.                         wp_otherInfo[lastId] = {breakchance = tonumber(brkc)}
  157.                     end
  158.                 end
  159.             end
  160.         end
  161.        
  162.         if not wp_vocInfo[lastId] then
  163.             wp_vocInfo[lastId] = {}
  164.         end
  165.        
  166.         for voc in line:gmatch('<vocation%s*name%s*=%s*"(.-)"') do
  167.             table.insert(wp_vocInfo[lastId], Vocation(voc):getId())
  168.         end
  169.     end
  170.     return true
  171. end
  172. registerWeapons()
  173.  
  174. local dist_wps = {5, 6}
  175. function Player:getShootRange(slot)
  176.     local slotItem = player:getSlotItem(slot)
  177.     if not slotItem then
  178.         return 1
  179.     end
  180.    
  181.     local slotwp = slotItem:getType():getWeaponType()
  182.     if isInArray(dist_wps, slotwp) then
  183.         local range = slotItem:getAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)
  184.         if range == 0 then
  185.             return slotItem:getType():getShootRange()
  186.         end
  187.         return range
  188.     end
  189.    
  190.     return 1
  191. end
  192.  
  193. function Creature:getMonsterEfficiently(range)
  194.     local spectators = Game.getSpectators(self:getPosition(), false, false, 0, range, 0, range)
  195.     local targets = {}
  196.     for i = 1, #spectators do
  197.         if spectators[i]:isMonster() then
  198.             if self:getPosition():isSightClear(spectators[i]:getPosition()) then
  199.                 table.insert(targets, spectators[i])
  200.             end
  201.         end
  202.     end
  203.    
  204.     local mostAttractive = 0
  205.     local bestTargets = {}
  206.     for i = 1, #targets do
  207.         local current = targets[i]
  208.         local hp = math.floor((current:getHealth() * 100) / current:getMaxHealth())
  209.         local points = 0
  210.         if hp < 95 then
  211.             points = 3
  212.         elseif hp < 85 then
  213.             points = 5
  214.         elseif hp < 70 then
  215.             points = 7
  216.         elseif hp < 50 then
  217.             points = 15
  218.         elseif hp < 30 then
  219.             points = 20
  220.         elseif hp < 15 then
  221.             points = 25
  222.         elseif hp < 7 then
  223.             points = 30
  224.         end
  225.         local extraPoints = 10 - current:getPosition():getDistance(self:getPosition())
  226.         local totalPTS = points + extraPoints
  227.         if totalPTS > mostAttractive then
  228.             mostAttractive = totalPTS
  229.             bestTargets = {}
  230.             table.insert(bestTargets, current)
  231.         elseif totalPTS == mostAttractive then
  232.             table.insert(bestTargets, current)
  233.         end
  234.     end
  235.    
  236.     local lowest = -1
  237.     local maintarget = 1
  238.     for i = 1, #bestTargets do
  239.         if lowest == -1 then
  240.             lowest = bestTargets[i]:getHealth()
  241.         else
  242.             if bestTargets[i]:getHealth() < lowest then
  243.                 lowest = bestTargets[i]:getHealth()
  244.                 maintarget = i
  245.             end
  246.         end
  247.     end
  248.     return bestTargets[maintarget]
  249. end
  250.  
  251. local hand_wps = {WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE, WEAPON_DISTANCE, WEAPON_WAND}
  252. function ItemType:isHandHeldWeapon()
  253.     return isInArray(hand_wps, self:getWeaponType())
  254. end
  255.  
  256. -- should be parsed from vocations.xml on startup
  257. -- I'm too tired of writing parsers tho
  258. local atkFac = {
  259.     [0] = {melee=1.0, dist=1.0},
  260.     [1] = {melee=1.0, dist=1.0},
  261.     [2] = {melee=1.0, dist=1.0},
  262.     [3] = {melee=1.0, dist=1.0},
  263.     [4] = {melee=1.0, dist=1.0},
  264.     -- probably not in use
  265.     [5] = {melee=1.0, dist=1.0},
  266.     [6] = {melee=1.0, dist=1.0},
  267.     [7] = {melee=1.0, dist=1.0},
  268.     [8] = {melee=1.0, dist=1.0}
  269. }
  270.  
  271. function getMaxWeaponDamage(level, attackSkill, attackValue, attackFactor)
  272.     return math.ceil((2 * (attackValue * (attackSkill + 5.8) / 25 + (level - 1) / 10)) / attackFactor)
  273. end
  274.  
  275. function canShootTo(pos, pos2, range)
  276.     return pos:getDistance(pos2) <= range and pos:isSightClear(pos2)
  277. end
  278.  
  279. function missShoot(pos)
  280.     local npos = Position(pos.x + math.random(-1, 1), pos.y + math.random(-1, 1), pos.z + math.random(-1, 1))
  281.    
  282.     local tile = Tile(npos)
  283.     if not tile then
  284.         return pos
  285.     end
  286.    
  287.     if tile:hasFlag(TILESTATE_PROTECTIONZONE) or not pos:isSightClear(npos) then
  288.         return pos
  289.     end
  290.    
  291.     if not tile:hasFlag(TILESTATE_BLOCKSOLID) then
  292.         return npos
  293.     end
  294.    
  295.     return pos
  296. end
  297.  
  298. local combat = Combat()
  299. combat:setParameter(COMBAT_PARAM_BLOCKARMOR, 1)
  300. combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_POISONDAMAGE)
  301. combat:setFormula(COMBAT_FORMULA_SKILL, 1 * dmgDist, 0, 1 * dmgDist, 0)
  302.  
  303. local condition = Condition(CONDITION_POISON)
  304. condition:setParameter(CONDITION_PARAM_DELAYED, 1)
  305. condition:addDamage(10, 2000, -1)
  306. combat:setCondition(condition)
  307.  
  308. function autoShoot(cid, target, type, min, max, effect, shootType, range, origin, maxHitChance, secondaryType, secondaryMin, secondaryMax)
  309.     local p = Player(cid)
  310.     local m = Monster(target)
  311.     if not range then
  312.         range = 1
  313.     end
  314.    
  315.     local burst = false
  316.     local poison = false
  317.     local extraDmg = false
  318.     if secondaryType then
  319.         if secondaryType == -1 then
  320.             burst = true
  321.         elseif secondaryType == -2 then
  322.             poison = true
  323.         else
  324.             extraDmg = true
  325.         end
  326.     end
  327.    
  328.     local miss = false
  329.     if origin then
  330.         if origin == ORIGIN_RANGED and maxHitChance then
  331.             if maxHitChance < 1 then
  332.                 miss = true
  333.             else
  334.                 if maxHitChance < math.random(1, 100) then
  335.                     miss = true
  336.                 end
  337.             end
  338.         end
  339.     end
  340.  
  341.     if p then
  342.         local ppos = p:getPosition()
  343.         if Tile(ppos):hasFlag(TILESTATE_PROTECTIONZONE) then
  344.             return true
  345.         end
  346.        
  347.         if m then
  348.             local npos = m:getPosition()
  349.             if canShootTo(ppos, npos, range) then
  350.                 if miss then
  351.                     npos = missShoot(npos)
  352.                     ppos:sendDistanceEffect(npos, shootType)
  353.                 else
  354.                     if shootType then
  355.                         ppos:sendDistanceEffect(npos, shootType)
  356.                     end
  357.                    
  358.                     if not burst then
  359.                         doTargetCombatHealth(cid, target, type, min, max, effect, origin)
  360.                         if extraDmg then
  361.                             doTargetCombatHealth(cid, target, secondaryType, secondaryMin, secondaryMax, effect, origin)
  362.                         end
  363.                     end
  364.                 end
  365.                
  366.                 if poison then
  367.                     local var = Variant(m:getId())
  368.                     combat:execute(p, var)
  369.                 end
  370.                
  371.                 if burst then
  372.                     for x = -1, 1 do
  373.                     for y = -1, 1 do
  374.                         local bPos = Position(npos.x + x, npos.y + y, npos.z)
  375.                         local bTile = Tile(bPos)
  376.                         if bTile then
  377.                             local bM = bTile:getCreatures()
  378.                             if bM then
  379.                                 for i = 1, #bM do
  380.                                     if bM[i]:isMonster() then
  381.                                         doTargetCombatHealth(cid, bM[i]:getId(), type, min, max, effect, origin)
  382.                                     end
  383.                                 end
  384.                             end
  385.                            
  386.                             if not bTile:hasFlag(TILESTATE_BLOCKSOLID) then
  387.                                 bPos:sendMagicEffect(CONST_ME_FIREAREA)
  388.                             end
  389.                         end
  390.                     end
  391.                     end
  392.                 end
  393.             else
  394.                 m = Monster(p:getMonsterEfficiently(range))
  395.                 if m then
  396.                     npos = m:getPosition()
  397.                     if canShootTo(ppos, npos, range) then
  398.                         if miss then
  399.                             npos = missShoot(npos)
  400.                             ppos:sendDistanceEffect(npos, shootType)
  401.                         else
  402.                             if shootType then
  403.                                 ppos:sendDistanceEffect(npos, shootType)
  404.                             end
  405.                            
  406.                             if not burst then
  407.                                 doTargetCombatHealth(cid, m:getId(), type, min, max, effect, origin)
  408.                                 if extraDmg then
  409.                                     doTargetCombatHealth(cid, m:getId(), secondaryType, secondaryMin, secondaryMax, effect, origin)
  410.                                 end
  411.                             end
  412.                         end
  413.                        
  414.                         if poison then
  415.                             local var = Variant(m:getId())
  416.                             combat:execute(p, var)
  417.                         end
  418.                
  419.                         if burst then
  420.                             for x = -1, 1 do
  421.                             for y = -1, 1 do
  422.                                 local bPos = Position(npos.x + x, npos.y + y, npos.z)
  423.                                 local bTile = Tile(bPos)
  424.                                 if bTile then
  425.                                     local bM = bTile:getCreatures()
  426.                                     if bM then
  427.                                         for i = 1, #bM do
  428.                                             if bM[i]:isMonster() then
  429.                                                 doTargetCombatHealth(cid, bM[i]:getId(), type, min, max, effect, origin)
  430.                                             end
  431.                                         end
  432.                                     end
  433.                                    
  434.                                     if not bTile:hasFlag(TILESTATE_BLOCKSOLID) then
  435.                                         bPos:sendMagicEffect(CONST_ME_FIREAREA)
  436.                                     end
  437.                                 end
  438.                             end
  439.                             end
  440.                         end
  441.                     end
  442.                 end
  443.             end
  444.         else
  445.             m = Monster(p:getMonsterEfficiently(range))
  446.             if m then
  447.                 local npos = m:getPosition()
  448.                 if canShootTo(ppos, npos, range) then
  449.                     if miss then
  450.                         npos = missShoot(npos)
  451.                         ppos:sendDistanceEffect(npos, shootType)
  452.                     else
  453.                         if shootType then
  454.                             ppos:sendDistanceEffect(npos, shootType)
  455.                         end
  456.                        
  457.                         if not burst then
  458.                             doTargetCombatHealth(cid, m:getId(), type, min, max, effect, origin)
  459.                             if extraDmg then
  460.                                 doTargetCombatHealth(cid, m:getId(), secondaryType, secondaryMin, secondaryMax, effect, origin)
  461.                             end
  462.                         end
  463.                     end
  464.  
  465.                     if poison then
  466.                         local var = Variant(m:getId())
  467.                         combat:execute(p, var)
  468.                     end
  469.                        
  470.                     if burst then
  471.                         for x = -1, 1 do
  472.                         for y = -1, 1 do
  473.                             local bPos = Position(npos.x + x, npos.y + y, npos.z)
  474.                             local bTile = Tile(bPos)
  475.                             if bTile then
  476.                                 local bM = bTile:getCreatures()
  477.                                 if bM then
  478.                                     for i = 1, #bM do
  479.                                         if bM[i]:isMonster() then
  480.                                             doTargetCombatHealth(cid, bM[i]:getId(), type, min, max, effect, origin)
  481.                                         end
  482.                                     end
  483.                                 end
  484.                                
  485.                                 if not bTile:hasFlag(TILESTATE_BLOCKSOLID) then
  486.                                     bPos:sendMagicEffect(CONST_ME_FIREAREA)
  487.                                 end
  488.                             end
  489.                         end
  490.                         end
  491.                     end
  492.                 end
  493.             end
  494.         end
  495.     end
  496. end
  497.  
  498. function Player:autoAttack(slot)
  499.     local range = 1
  500.     local slotType = -1
  501.     local slotItem = 0
  502.    
  503.     if slot ~= -1 then
  504.         slotItem = self:getSlotItem(slot)
  505.         if slotItem then
  506.             slotType = slotItem:getType():getWeaponType()
  507.             if slotType == WEAPON_DISTANCE or slotType == WEAPON_WAND then
  508.                 local attrRange = slotItem:getAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)
  509.                 local itemRange = slotItem:getType():getShootRange()
  510.                 range = attrRange > 0 and attrRange or itemRange
  511.             end
  512.         end
  513.     end
  514.    
  515.     local target = self:getMonsterEfficiently(range)
  516.     if not target then
  517.         return true
  518.     end
  519.    
  520.     if slot == -1 then
  521.         local tid = target:getId()
  522.         local cid = self:getId()
  523.         if self:getPosition():isSightClear(target:getPosition()) then
  524.             for i = 1, dmgMeleeAmount do
  525.                 addEvent(autoShoot, i * speedMelee, cid, tid, COMBAT_PHYSICALDAMAGE, -1, math.floor(-getMaxWeaponDamage(self:getLevel(), self:getEffectiveSkillLevel(SKILL_FIST), 7, atkFac[self:getBaseVoc()].melee) * dmgMelee), nil, nil, range, ORIGIN_MELEE)
  526.             end
  527.             self:addSkillTries(SKILL_FIST, 1)
  528.         end
  529.         return true
  530.     end
  531.  
  532.     local itid = slotItem:getId()
  533.     if slotType == WEAPON_WAND then
  534.         local wand = wp_otherInfo[itid]
  535.        
  536.         if wp_vocInfo[itid] then
  537.             if not isInArray(wp_vocInfo[itid], self:getBaseVoc()) then
  538.                 return true
  539.             end
  540.         end
  541.        
  542.         if wand.level then
  543.             if self:getLevel() < wand.level then
  544.                 return true
  545.             end
  546.         end
  547.        
  548.         if self:getPosition():isSightClear(target:getPosition()) then
  549.             if wand.mana then
  550.                 if self:getMana() < wand.mana then
  551.                     return true
  552.                 end
  553.                
  554.                 self:addMana(-wand.mana)
  555.                 self:addManaSpent(wand.mana)
  556.             end
  557.            
  558.             local tid = target:getId()
  559.             local cid = self:getId()
  560.  
  561.             for i = 1, dmgMagicAmount do
  562.                 addEvent(autoShoot, i * speedMagic, cid, tid, wand.element, math.floor(-wand.min * dmgMagic), math.floor(-wand.max * dmgMagic), nil, shootTypes[wp_shooteffects[itid]], range)
  563.             end
  564.         end
  565.         return true
  566.     end
  567.    
  568.     if slotType == WEAPON_DISTANCE then
  569.         if not self:getPosition():isSightClear(target:getPosition()) then
  570.             return true
  571.         end
  572.  
  573.         if wp_vocInfo[itid] then
  574.             if #wp_vocInfo[itid] > 0 then
  575.                 if not isInArray(wp_vocInfo[itid], self:getBaseVoc()) then
  576.                     return true
  577.                 end
  578.             end
  579.         end
  580.        
  581.         local level = self:getLevel()
  582.         local skill = self:getEffectiveSkillLevel(SKILL_DISTANCE)
  583.        
  584.         -- bows and crossbows
  585.         if wp_ammotype[itid] then
  586.             local ammo = self:getSlotItem(CONST_SLOT_AMMO)
  587.             if not ammo then
  588.                 return true
  589.             end
  590.            
  591.             if ammo:getType():getWeaponType() ~= WEAPON_AMMO then
  592.                 return true
  593.             end
  594.            
  595.             local ammotype = 0
  596.             if ammo:getName():match("bolt") then
  597.                 ammotype = 1
  598.             elseif ammo:getName():match("arrow") then
  599.                 ammotype = 2
  600.             end
  601.            
  602.             if wp_ammotype[itid] ~= ammotype then
  603.                 return true
  604.             end
  605.  
  606.             local ammoAtk = ammo:getAttribute(ITEM_ATTRIBUTE_ATTACK)
  607.             if ammoAtk == 0 then
  608.                 ammoAtk = ammo:getType():getAttack()
  609.             end
  610.            
  611.             local wpAtk = slotItem:getAttribute(ITEM_ATTRIBUTE_ATTACK)
  612.             if wpAtk == 0 then
  613.                 wpAtk = slotItem:getType():getAttack()
  614.             end
  615.            
  616.             local atk = (wpAtk or 0) + (ammoAtk or 0)
  617.             local secondaryType = ammo:getType():getElementType()
  618.             local secondaryAtk = ammo:getType():getElementDamage()
  619.            
  620.             if secondaryType then
  621.                 secondaryAtk = secondaryAtk + (wpAtk or 0)
  622.             end
  623.            
  624.             local maxDmg = getMaxWeaponDamage(level, skill, atk, atkFac[self:getBaseVoc()].dist) * dmgDist
  625.             local secondaryMaxDmg = 0
  626.             if secondaryType then
  627.                 secondaryMaxDmg = getMaxWeaponDamage(level, skill, secondaryAtk, atkFac[self:getBaseVoc()].dist) * dmgDist
  628.             end
  629.            
  630.             if level < slotItem:getType():getRequiredLevel() then
  631.                 maxDmg = maxDmg * 0.5
  632.                 if secondaryType then
  633.                     secondaryMaxDmg = secondaryMaxDmg * 0.5
  634.                 end
  635.             end
  636.            
  637.             if level < ammo:getType():getRequiredLevel() then
  638.                 maxDmg = maxDmg * 0.5
  639.                 if secondaryType then
  640.                     secondaryMaxDmg = secondaryMaxDmg * 0.5
  641.                 end
  642.             end
  643.            
  644.             maxDmg = math.ceil(maxDmg)
  645.             if secondaryType then
  646.                 secondaryMaxDmg = math.ceil(secondaryMaxDmg)
  647.             end
  648.            
  649.             local minDmg = math.ceil(maxDmg * 0.3)
  650.             local secondaryMinDmg = 0
  651.            
  652.             if secondaryType then
  653.                 secondaryMinDmg = math.ceil(secondaryMaxDmg * 0.3)
  654.             end
  655.            
  656.             local hitChance = ammo:getAttribute(ITEM_ATTRIBUTE_HITCHANCE)
  657.             if hitChance == 0 then
  658.                 hitChance = (wp_hitChance[ammo:getId()] or 90)
  659.             end
  660.            
  661.             local distance = self:getPosition():getDistance(target:getPosition())
  662.             hitChance = math.ceil(math.min((range/distance) * ((hitChance/100) * skill), hitChance))
  663.             local wpHitChance = slotItem:getAttribute(ITEM_ATTRIBUTE_HITCHANCE)
  664.             if wpHitChance == 0 then
  665.                 wpHitChance = slotItem:getType():getHitChance()
  666.             end
  667.            
  668.             hitChance = hitChance + (wpHitChance or 0)
  669.             local tid = target:getId()
  670.             local cid = self:getId()
  671.            
  672.             -- burst and poison arrows
  673.             if ammo:getId() == 2546 then
  674.                 secondaryType = -1
  675.             elseif ammo:getId() == 2545 then
  676.                 secondaryType = -2
  677.             end
  678.            
  679.             for i = 1, dmgDistAmount do
  680.                 addEvent(autoShoot, i * speedDist, cid, tid, COMBAT_PHYSICALDAMAGE, math.floor(-minDmg * dmgDist), math.floor(-maxDmg * dmgDist), nil, shootTypes[wp_shooteffects[ammo:getId()]], range, ORIGIN_RANGED, hitChance, secondaryType, math.floor(-secondaryMinDmg * dmgDist), math.floor(-secondaryMaxDmg * dmgDist))
  681.             end
  682.            
  683.             local breakChance = wp_otherInfo[ammo:getId()]
  684.             if breakChance then
  685.                 if math.random(1, 100) <= breakChance.breakchance then
  686.                     ammo:remove(1)
  687.                 end
  688.             else
  689.                 ammo:remove(1)
  690.             end
  691.            
  692.             self:addSkillTries(SKILL_DISTANCE, 1)
  693.             return true
  694.         end
  695.        
  696.         -- spears, knives and stars
  697.         local hitChance = slotItem:getAttribute(ITEM_ATTRIBUTE_HITCHANCE)
  698.         if hitChance == 0 then
  699.             hitChance = (wp_hitChance[itid] or 75)
  700.         end
  701.        
  702.         local distance = self:getPosition():getDistance(target:getPosition())
  703.         hitChance = math.ceil(math.min((range/distance) * ((hitChance/100) * skill), hitChance))
  704.        
  705.         local wpAtk = slotItem:getAttribute(ITEM_ATTRIBUTE_ATTACK)
  706.         if wpAtk == 0 then
  707.             wpAtk = slotItem:getType():getAttack()
  708.         end
  709.        
  710.         local atk = (wpAtk or 0)
  711.         local secondaryType = slotItem:getType():getElementType()
  712.         local secondaryAtk = slotItem:getType():getElementDamage()
  713.        
  714.         local maxDmg = getMaxWeaponDamage(level, skill, atk, atkFac[self:getBaseVoc()].dist) * dmgDist
  715.         local secondaryMaxDmg = 0
  716.         if secondaryType then
  717.             secondaryMaxDmg = getMaxWeaponDamage(level, skill, secondaryAtk, atkFac[self:getBaseVoc()].dist) * dmgDist
  718.         end
  719.        
  720.         if level < slotItem:getType():getRequiredLevel() then
  721.             maxDmg = maxDmg * 0.5
  722.             if secondaryType then
  723.                 secondaryMaxDmg = secondaryMaxDmg * 0.5
  724.             end
  725.         end
  726.        
  727.         maxDmg = math.ceil(maxDmg)
  728.         if secondaryType then
  729.             secondaryMaxDmg = math.ceil(secondaryMaxDmg)
  730.         end
  731.        
  732.         local minDmg = math.ceil(maxDmg * 0.3)
  733.         local secondaryMinDmg = 0
  734.        
  735.         if secondaryType then
  736.             secondaryMinDmg = math.ceil(secondaryMaxDmg * 0.3)
  737.         end
  738.        
  739.         -- viper star
  740.         if itid == 7366 then
  741.             secondaryType = -2
  742.         end
  743.        
  744.         local tid = target:getId()
  745.         local cid = self:getId()
  746.            
  747.         for i = 1, dmgDistAmount do
  748.             addEvent(autoShoot, i * speedDist, cid, tid, COMBAT_PHYSICALDAMAGE, math.floor(-minDmg * dmgDist), math.floor(-maxDmg * dmgDist), nil, shootTypes[wp_shooteffects[slotItem:getId()]], range, ORIGIN_RANGED, hitChance, secondaryType, math.floor(-secondaryMinDmg * dmgDist), math.floor(-secondaryMaxDmg * dmgDist))
  749.         end
  750.        
  751.         local breakChance = wp_otherInfo[itid] 
  752.         if breakChance then
  753.             if math.random(1, 100) <= breakChance.breakchance then
  754.                 slotItem:remove(1)
  755.             end
  756.         else
  757.             slotItem:remove(1)
  758.         end
  759.        
  760.         self:addSkillTries(SKILL_DISTANCE, 1)
  761.         return true
  762.     end
  763.    
  764.     if isInArray(meleeweapons, slotType) then
  765.         local wpSkill = wp_skillType[slotType]
  766.         local level = self:getLevel()
  767.         local skill = self:getEffectiveSkillLevel(wpSkill)
  768.        
  769.         if wp_vocInfo[itid] then
  770.             if #wp_vocInfo[itid] > 0 then
  771.                 if not isInArray(wp_vocInfo[itid], self:getBaseVoc()) then
  772.                     return true
  773.                 end
  774.             end
  775.         end
  776.        
  777.         local wpAtk = slotItem:getAttribute(ITEM_ATTRIBUTE_ATTACK)
  778.         if wpAtk == 0 then
  779.             wpAtk = slotItem:getType():getAttack()
  780.         end
  781.        
  782.         local atk = (wpAtk or 0)
  783.         local secondaryType = slotItem:getType():getElementType()
  784.         local secondaryAtk = slotItem:getType():getElementDamage()
  785.        
  786.         local maxDmg = getMaxWeaponDamage(level, skill, atk, atkFac[self:getBaseVoc()].melee) * dmgMelee
  787.         local secondaryMaxDmg = 0
  788.         if secondaryType then
  789.             secondaryMaxDmg = getMaxWeaponDamage(level, skill, secondaryAtk, atkFac[self:getBaseVoc()].melee) * dmgMelee
  790.         end
  791.        
  792.         if level < slotItem:getType():getRequiredLevel() then
  793.             maxDmg = maxDmg * 0.5
  794.             if secondaryType then
  795.                 secondaryMaxDmg = secondaryMaxDmg * 0.5
  796.             end
  797.         end
  798.        
  799.         maxDmg = math.ceil(maxDmg)
  800.         if secondaryType then
  801.             secondaryMaxDmg = math.ceil(secondaryMaxDmg)
  802.         end
  803.        
  804.         local minDmg = math.ceil(maxDmg * 0.3)
  805.         local secondaryMinDmg = 0
  806.        
  807.         if secondaryType then
  808.             secondaryMinDmg = math.ceil(secondaryMaxDmg * 0.3)
  809.         end
  810.        
  811.         local tid = target:getId()
  812.         local cid = self:getId()
  813.        
  814.         for i = 1, dmgMeleeAmount do
  815.             addEvent(autoShoot, i * speedMelee, cid, tid, COMBAT_PHYSICALDAMAGE, math.floor(-minDmg * dmgMelee), math.floor(-maxDmg * dmgMelee), nil, shootTypes[wp_shooteffects[slotItem:getId()]], range, ORIGIN_MELEE, hitChance, secondaryType, math.floor(-secondaryMinDmg * dmgMelee), math.floor(-secondaryMaxDmg * dmgMelee))
  816.         end
  817.        
  818.         local charges = slotItem:getCharges()
  819.         if charges > 0 then
  820.             if charges == 1 then
  821.                 local broken = slotItem:getType():getDecayId()
  822.                 if broken == -1 then
  823.                     slotItem:remove()
  824.                 else
  825.                     slotItem:transform(broken)
  826.                     slotItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, 0)
  827.                 end
  828.             else
  829.                 slotItem:setAttribute(ITEM_ATTRIBUTE_CHARGES, charges - 1)
  830.             end
  831.         end
  832.        
  833.         self:addSkillTries(skill, 1)
  834.         return true
  835.     end
  836.     return true
  837. end
  838.  
  839. local slotA = 6 -- wp
  840. local slotB = 5 -- shield
  841.  
  842. function autoAttackCheck(cid)
  843.     local player = Player(cid)
  844.     if not player then
  845.         return true
  846.     end
  847.  
  848.     addEvent(autoAttackCheck, 2000, cid)
  849.     if player:getStorageValue(togglestorage) == 1 then
  850.         if not Tile(player:getPosition()):hasFlag(TILESTATE_PROTECTIONZONE) then
  851.             if not player:getTarget() then
  852.                 local itemA = player:getSlotItem(slotA)
  853.                 local itemB = player:getSlotItem(slotB)
  854.                
  855.                 local equippedWeapons = 0
  856.                 if itemA then
  857.                     if itemA:getType():isHandHeldWeapon() then
  858.                         equippedWeapons = equippedWeapons + 1
  859.                     end
  860.                 end
  861.                
  862.                 if itemB then
  863.                     if itemB:getType():isHandHeldWeapon() then
  864.                         equippedWeapons = equippedWeapons + 1
  865.                     end
  866.                 end
  867.                
  868.                 if equippedWeapons == 0 then
  869.                     player:autoAttack(-1)
  870.                     if dualWielding then
  871.                         player:autoAttack(-1)
  872.                     end
  873.                     return true
  874.                 end
  875.                
  876.                 if equippedWeapons == 1 or not dualWielding then
  877.                     if itemA then
  878.                         if itemA:getType():isHandHeldWeapon() then
  879.                             player:autoAttack(slotA)
  880.                             return true
  881.                         end
  882.                     end
  883.                    
  884.                     player:autoAttack(slotB)
  885.                     return true
  886.                 end
  887.  
  888.                 player:autoAttack(slotA)
  889.                 player:autoAttack(slotB)
  890.                 return true        
  891.             end
  892.         end
  893.     end
  894. end
  895.  
  896. function onLogin(player)
  897.     local cid = player:getId() -- required for compability with timers
  898.     addEvent(autoAttackCheck, 2000, cid)
  899.     return true
  900. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement