[Mod] Random Item Stats

Discussion in 'Mods & Lua Functions' started by Cykotitan, Jun 1, 2011.

  1. imkingran

    imkingran Learning everyday. Premium User

    Joined:
    Jan 15, 2014
    Messages:
    1,151
    Are you getting any errors in the console?

    Double check the code in this area, since I'm not using 0.4 so I'm not quite sure if it's written correctly:
    Code:
                local ammy = getPlayerSlotItem(cid, CONST_SLOT_NECKLACE)
                if ammy then
                    if ammy.itemid == bonusAmuletId then
                        rate = rate * 1.5 -- If he's wearing the amulet then give him 50% extra chance
                    end
                end
    If you don't get any errors in the console then use the function print() to find out where the problem is:
    Code:
    local bonusAmuletId = 11393
    function onKill(cid, target, damage, flags)
        if( (damage == true or bit.band(flags, 1) == 1) and isMonster(target) )then -- 0.3/4
            local v = getMonsterInfo(getCreatureName(target))
            if( v and v.lookCorpse ~= 0 )then
                local s = getCreatureStorage(cid, extra_loot_key) -- This will be (-1) since you're not using it so the addEvent will return 'rare' and not 's' [s == -1 and rate or s]
                local ammy = getPlayerSlotItem(cid, CONST_SLOT_NECKLACE)
                if ammy then
                    print('Amulet found | Amulet ID: ' .. ammy.itemid) -- print
                    if ammy.itemid == bonusAmuletId then
                        rate = rate * 1.5 -- If he's wearing the amulet then give him 50% extra chance
                    end
                else
                    print('Amulet not found') -- print
                end
                print('Rate: ' .. rate)
                addEvent(dropLoot, 0, getThingPos(target), v, s == -1 and rate or s, getCreatureMaster(target), cid, target)
            end
        end
        return true
    end
     
    zabuzo and newby like this.
  2. newby

    newby Member

    Joined:
    Jun 11, 2016
    Messages:
    55
    Bloody hell, thank you

    Your code was printing:
    Code:
    Amulet found | Amulet ID: 11393
    Rate: 1.5
    Amulet found | Amulet ID: 0
    Rate: 1.5
    
    Thanks to imkingran i've fixed this and i would like to share to everybody
    @Extrodus
    You helps me, i would like to help you
    It should be to useful to blazera.net:

    Code:
    local bonusAmuletId = 11393
    function onKill(cid, target, damage, flags)
        if( (damage == true or bit.band(flags, 1) == 1) and isMonster(target) )then -- 0.3/4
            local v = getMonsterInfo(getCreatureName(target))
            if( v and v.lookCorpse ~= 0 )then
                local s = getCreatureStorage(cid, extra_loot_key) -- This will be (-1) since you're not using it so the addEvent will return 'rare' and not 's' [s == -1 and rate or s]
                local ammy = getPlayerSlotItem(cid, CONST_SLOT_NECKLACE)
                local rate = getConfigInfo('rateLoot')
                if ammy.itemid ~= 0 then
                    --print('Amulet found | Amulet ID: ' .. ammy.itemid) -- print
                    if ammy.itemid == bonusAmuletId then
                        rate = rate * 1.5 -- If he's wearing the amulet then give him 50% extra chance
                    end
                --else
                --    print('Amulet not found') -- print
                end
                --print('Rate: ' .. rate)
                addEvent(dropLoot, 0, getThingPos(target), v, s == -1 and rate or s, getCreatureMaster(target), cid, target)
            end
        end
        return true
    end
    
     
    imkingran and zabuzo like this.
  3. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
    @imkingran do you know how to remove percentage?
    http://pastebin.com/BvnDST54

    I mean
    Code:
    You see a bone club (Atk:12, Def:8).
    Not more (its how working on script)
    Code:
    You see a deadly bone club (Atk:12 +5, Def:8). [Attack: +38%]
    And be it (how i want)
    Code:
    You see a deadly bone club (Atk:12 +38, Def:8). [Attack: +38]
    It's just change something here?
    I think is here, but idk and i scare to do some shits
    PHP:
                            local percent, new, tmp math.random(n.percent[1] + (v.extra[1] or 0), n.percent[2] + (v.extra[2] or 0))
                            -- 
    hacks
                            
    if( n.attr == 'duration' )then
                                tmp 
    getItemInfo(f.transformEquipTo)
                                if 
    tmp.transformDeEquipTo ~= item then
                                    
    break
                                
    end
                                
    new = roundtmp.decayTime * (percent 100) * 1000 )
                            elseif( 
    n.attr == 'attackSpeed' )then
                                
    new = roundvocation_base_attackspeed / (percent 100) )
                            elseif( 
    n.attr == 'hitChance' then
                                
    new = round(
                                    
    f.hitChance == -and
                                        
    percent
                                    
    or
                                        
    f.hitChance * (percent 100)
                                )
                            else
                                new = 
    round(
                                    
    n.base and
                                        
    f[n['attr']] + f[n['base']] * (percent 100)
                                    or
                                        
    f[n['attr']] * (percent 100)
                                )
                                if( new == 
    f[n[n.base and 'base' or 'attr']] )then -- no improvement
                                    
    break
                                
    end
                            end
                            doItemSetAttribute
    (tmpItemn.attr:lower(), new)
                            
    local name getItemAttribute(tmpItem'name')
                            if( 
    v.attrNames or not name )then
                                local name 
    = (v.attrNames and used[#used] or k) .. ' ' .. (name or f.name)
                                
    doItemSetAttribute(tmpItem'name'name)
                                if( 
    f.article ~= '' )then
                                    local article 
    getArticle(name)
                                    if( 
    article ~= f.article )then
                                        doItemSetAttribute
    (tmpItem'article'article)
                                    
    end
                                end
                            end
                            local desc 
    getItemAttribute(tmpItem'description') or f.description
                            doItemSetAttribute
    (tmpItem'description''[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))
     
  4. imkingran

    imkingran Learning everyday. Premium User

    Joined:
    Jan 15, 2014
    Messages:
    1,151
    Didn't test buy try this: (edited from your pastebin link)

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <mod name="Random Item Stats" enabled="1">
    <config name="itemstats_conf"><![CDATA[
    -- //
        extra_loot_key = 123 --: optional storage for higher loot rate
        vocation_base_attackspeed = getVocationInfo(1).attackSpeed --: used for attackSpeed stat
    -- //
     
    tiers, attr = {}, {}
     
    tiers['rare'] = {
        color = 66, -- color of 'RARE' text
        extra = {0, 0},
        attrNames = true, -- show attribute names instead of rare
        chance = {
            [1] = 10000,
            [2] = 5000 -- chance for 2nd stat
        }
    }
    tiers['epic'] = {
        color = 35,
        extra = {6, 8}, -- additional percent bonus
        chance = {
            [1] = 3333,
            [2] = 25000
        }
    }
    tiers['legendary'] = {
        color = 149,
        extra = {10, 20},
        chance = {
            [1] = 1000,
            [2] = 100000 -- 2 bonuses always
        }
    }
     
    MELEE = 0
    DISTANCE = 1
    ARMOR = 2
    SHIELD = 3
    WAND = 4
    DURATION_RING = 5
    CHARGES = 6
     
    --! attributes
    attr['quick'] = {
        attr = 'attackSpeed',
        name = 'Attack Speed',
        percent = {25, 45},
        usePercents = true,
        types = {MELEE, DISTANCE, WAND}
    }
    attr['fortified'] = {
        attr = 'extraDefense',
        base = 'defense',
        name = 'Defense',
        percent = {25, 35},
        usePercents = true,   
        types = {MELEE, SHIELD}
    }
    attr['deadly'] = {
        attr = 'extraAttack',
        base = 'attack',
        name = 'Attack',
        types = {MELEE},
        usePercents = false,
        percent = {25, 50}
    }
    attr['strong'] = {
        attr = 'armor',
        name = 'Armor',
        percent = {25, 50},
        usePercents = true,
        types = {ARMOR}
    }
    attr['hawkeye\'s'] = {
        attr = 'hitChance',
        name = 'Hit Chance',
        percent = {35, 55},
        usePercents = true,
        types = {DISTANCE}
    }
    --[[ // not available without source edit
    attr['farsight'] = {
        attr = 'shootRange',
        name = 'Shoot Range',
        percent = {10, 20},
        types = {DISTANCE, WAND}
    }
    ]]
    attr['charged'] = {
        attr = 'charges',
        name = 'Charges',
        percent = {40, 80},
        types = {CHARGES}
    }
    attr['divine'] = {
        attr = 'duration',
        name = 'Duration',
        percent = {40, 80},
        types = {DURATION_RING}
    }
    --/ attributes
     
    rate = getConfigInfo('rateLoot')
     
    if( getConfigInfo('monsterLootMessage') ~= 0 )then
        print('[Notice] Set monsterLootMessage = 0 to prevent duplicate loot messages')
    end
    ]]></config>
     
    <event type="kill" name="itemstats" event="script"><![CDATA[
    domodlib('itemstats_conf')
     
    function round(n, s)
        return tonumber(('%.' .. (s or 0) .. 'f'):format(n))
    end
     
    function getContentDescription(uid, sep)
        local ret, i, containers = '', 0, {}
        while( i < getContainerSize(uid) )do
            local v, s = getContainerItem(uid, i), ''
            local k = getItemInfo(v.itemid)
            k.name = getItemAttribute(v.uid, 'name') or k.name
            if( k.name ~= '' )then
                if( v.type > 1 and k.stackable and k.showCount )then
                    s = v.type .. ' ' .. k.plural
                else
                    local article = getItemAttribute(v.uid, 'article') or k.article
                    s = (article == '' and '' or article .. ' ') .. k.name
                end
                ret = ret .. (i == 0 and not sep and '' or ', ') .. s
                if( isContainer(v.uid) and getContainerSize(v.uid) ~= 0 )then
                    table.insert(containers, v.uid)
                end
            else
                ret = ret .. (i == 0 and not sep and '' or ', ') .. 'an item of type ' .. v.itemid .. ', please report it to gamemaster'
            end
            i = i + 1
        end
        for i = 1, #containers do
            ret = ret .. getContentDescription(containers[i], true)
        end
        return ret
    end
     
    local function send(cid, corpse, monster)
        if( isPlayer(cid) )then
            local ret = corpse and isContainer(corpse) and getContentDescription(corpse)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'))
            local party = getPlayerParty(cid)
            if( party )then
                for _, pid in ipairs(getPartyMembers(party)) do
                    doPlayerSendChannelMessage(pid, '', 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'), TALKTYPE_CHANNEL_W, CHANNEL_PARTY)
                end
            end
        end
    end
     
    local function createLoot(i, ext)
        local item = type(i.id) == 'table' and i.id[math.random(#i.id)] or i.id
        local random = math.ceil(math.random(100000) / ext)
        local tmpItem, f
     
        if( random < i.chance )then
            if i.subType == -1 then
                f = getItemInfo(item)
            end
            tmpItem = doCreateItemEx(item,
                i.subType ~= -1 and i.subType or
                f.stackable and random % i.count + 1 or
                f.charges ~= 0 and f.charges or
                1
            )
        end
     
        if( not tmpItem )then
            return
        end
     
        if( i.actionId ~= -1 )then
            doItemSetAttribute(tmpItem, 'aid', i.actionId)
        end
     
        if( i.uniqueId ~= -1 )then
            doItemSetAttribute(tmpItem, 'uid', i.uniqueId)
        end
     
        if( i.text ~= '' )then
            doItemSetAttribute(tmpItem, 'text', i.text)
        end
     
        local ret, done
     
        for k, v in pairs(tiers) do
            local cur, used = {}, {}
            for i = 1, #v.chance do
                if( math.random(100000) <= v.chance[i] )then
                    if( f )then
                        f = getItemInfo(item)
                    end
                    if( not f.stackable )then
                        for m, n in pairs(attr) do
                            if( not table.find(used, m) and
                            (
                                ( table.find(n.types, MELEE) and table.find({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, f.weaponType) ) or
                                ( table.find(n.types, DISTANCE) and f.weaponType == WEAPON_DIST and f.ammoType ~= 0 ) or
                                ( table.find(n.types, ARMOR) and f.armor ~= 0 and f.wieldPosition ~= CONST_SLOT_NECKLACE ) or
                                ( table.find(n.types, SHIELD) and f.defense ~= 0 and f.weaponType == WEAPON_SHIELD ) or
                                ( table.find(n.types, WAND) and f.weaponType == WEAPON_WAND ) or
                                ( table.find(n.types, DURATION_RING) and f.wieldPosition == CONST_SLOT_RING and f.transformEquipTo ~= 0 ) or
                                ( table.find(n.types, CHARGES) and table.find({CONST_SLOT_RING, CONST_SLOT_NECKLACE}, f.wieldPosition) and f.charges ~= 0 )
                            ) )then
                                table.insert(cur, m)
                            end
                        end
     
                        if( #cur ~= 0 )then
                            local n = cur[math.random(#cur)]
                            table.insert(used, n)
     
                            n = attr[n]
                            local percent, new, tmp = n.usePercents and math.random(n.percent[1] + (v.extra[1] or 0), n.percent[2] + (v.extra[2] or 0)) or math.random(n.percent[1] + (v.extra[1] or 0), n.percent[2] + (v.extra[2] or 0)) * 100
                            -- hacks
                            if( n.attr == 'duration' )then
                                tmp = getItemInfo(f.transformEquipTo)
                                if tmp.transformDeEquipTo ~= item then
                                    break
                                end
                                new = round( tmp.decayTime * (1 + percent / 100) * 1000 )
                            elseif( n.attr == 'attackSpeed' )then
                                new = round( vocation_base_attackspeed / (1 + percent / 100) )
                            elseif( n.attr == 'hitChance' ) then
                                new = round(
                                    f.hitChance == -1 and
                                        percent
                                    or
                                        f.hitChance * (1 + percent / 100)
                                )
                            else
                                new = round(
                                    n.base and
                                        f[n['attr']] + f[n['base']] * (percent / 100)
                                    or
                                        f[n['attr']] * (1 + percent / 100)
                                )
     
                                if( new == f[n[n.base and 'base' or 'attr']] )then -- no improvement
                                    break
                                end
                            end
     
                            doItemSetAttribute(tmpItem, n.attr:lower(), new)
     
                            local name = getItemAttribute(tmpItem, 'name')
                            if( v.attrNames or not name )then
                                local name = (v.attrNames and used[#used] or k) .. ' ' .. (name or f.name)
                                doItemSetAttribute(tmpItem, 'name', name)
     
                                if( f.article ~= '' )then
                                    local article = getArticle(name)
                                    if( article ~= f.article )then
                                        doItemSetAttribute(tmpItem, 'article', article)
                                    end
                                end
                            end
     
                            local desc = getItemAttribute(tmpItem, 'description') or f.description
                            if n.usePercents then
                                doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))
                            else
                                doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. ']' .. (desc == '' and '' or '\n' .. desc))
                            end
     
                            ret = k
                        end
                        cur = {}
                        if( #v.chance == i )then
                            done = true
                        end
                    end
                else
                    done = i ~= 1
                    break
                end
            end
            if( done )then
                break
            end
        end
     
        return tmpItem, ret
    end
     
    local function createChildLoot(parent, i, ext, pos)
        if( not i or #i == 0 )then
            return true
        end
     
        local size, cap = 0, getContainerCap(parent)
        for k = 1, #i do
            if( size == cap )then
                break
            end
            local tmp, ret = createLoot(i[k], ext)
            if( tmp )then
                if( isContainer(tmp) )then
                    if( createChildLoot(tmp, i[k].child, ext, pos) )then
                        doAddContainerItemEx(parent, tmp)
                        size = size + 1
                    else
                        doRemoveItem(tmp)
                    end
                else
                    if( ret )then
                        doSendMagicEffect(pos, CONST_ME_MAGIC_GREEN)
                        doSendAnimatedText(pos, ret:upper(), tiers[ret].color)
                    end
                    doAddContainerItemEx(parent, tmp)
                    size = size + 1
                end
            end
        end
     
        return size > 0
    end
     
    local function dropLoot(pos, v, ext, master, cid, target)
        local corpse
        if( not master or master == target )then -- 0.3/4
            corpse = getTileItemById(pos, v.lookCorpse).uid
            if( isContainer(corpse) )then
                for i = 1, getContainerSize(corpse) do
                    doRemoveItem(getContainerItem(corpse, 0).uid)
                end
                local size, cap = 0, getContainerCap(corpse)
                for i = 1, #v.loot do
                    if( size == cap )then
                        break
                    end
                    local tmp, ret = createLoot(v.loot[i], ext)
                    if( tmp )then
                        if( isContainer(tmp) )then
                            if( createChildLoot(tmp, v.loot[i].child, ext, pos) )then
                                doAddContainerItemEx(corpse, tmp)
                                size = size + 1
                            else
                                doRemoveItem(tmp)
                            end
                        else
                            if( ret )then
                                doSendMagicEffect(pos, CONST_ME_MAGIC_GREEN)
                                doSendAnimatedText(pos, ret:upper(), tiers[ret].color)
                            end
                            doAddContainerItemEx(corpse, tmp)
                            size = size + 1
                        end
                    end
                end
            end
        end
        send(cid, corpse, v.description)
    end
     
    function onKill(cid, target, damage, flags)
        if( (damage == true or bit.band(flags, 1) == 1) and isMonster(target) )then -- 0.3/4
            local v = getMonsterInfo(getCreatureName(target))
            if( v and v.lookCorpse ~= 0 )then
                local s = getCreatureStorage(cid, extra_loot_key)
                addEvent(dropLoot, 0, getThingPos(target), v, s == -1 and rate or s, getCreatureMaster(target), cid, target)
            end
        end
        return true
    end
    ]]></event>
     
    <event type="login" name="itemstats_login" event="buffer"><![CDATA[
        registerCreatureEvent(cid, 'itemstats')
    ]]></event>
     
    </mod>

    I added the option usePercents = boolean (true/false) to the table so you can decide which one use % and which one doesn't.
    Code:
    attr['deadly'] = {
        attr = 'extraAttack',
        base = 'attack',
        name = 'Attack',
        types = {MELEE},
        usePercents = false,
        percent = {25, 50}
    }
     
    zabuzo likes this.
  5. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
    Wtf :O

    Code:
    03:44 You see an epic longsword (Atk:17 +952, Def:14).
    It weighs 42.00 oz.
    [Attack: +5600]
    [Attack Speed: +48%]
    
    03:44 You see an epic short sword (Atk:11, Def:11 +418).
    It weighs 35.00 oz.
    [Defense: +3800]
    
     
  6. gmstrikker

    gmstrikker Member

    Joined:
    Jul 30, 2014
    Messages:
    313
    There is something wrong here:
    Code:
                           if n.usePercents then
                                doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))
                            else
                                doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. ']' .. (desc == '' and '' or '\n' .. desc))
                            end
    
    I'm sorry, but i don't know how to fix
     
    zabuzo likes this.
  7. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
    @imkingran know? anybody know?
     
  8. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81


    Why +952 atk, +418 def in epic items?
    It shouldn't be 6~8

    Like is in the script?
    Code:
    tiers['epic'] = {
        color = 35,
        extra = {6, 8}, -- additional percent bonus
        chance = {
            [1] = 3333,
            [2] = 25000
        }
    }
    
     
  9. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
  10. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
  11. zabuzo

    zabuzo Member

    Joined:
    Jun 10, 2016
    Messages:
    81
    bump it \/

     

Share This Page