• 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!

Magic Find

Kody

New Member
Joined
Jul 31, 2010
Messages
11
Reaction score
1
I'm new to making ot servers, and otland.. So if this isnt the right spot to put this... well.. im sorry. lol... anyway... I play this server called "NoxiousOT" and sometimes when you kill a monster, the word RARE pops up on the body for a second. then when you loot. maybe one of the items will be a rare, as in... A item with Attack speed, or More attack on it as normal... idk how to put it... all i know.. is that i want to use that for my server. can anyone help me out on where to find it? and how to set it up? I've searched everything on this website. and cant find it XD just other servers with it...:ninja:
 
create file rare.xml file in /mods and paste this

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 = {7, 20}, -- additional percent bonus
	chance = {
		[1] = 3333,
		[2] = 25000
	}
}
tiers['legendary'] = {
	color = 149,
	extra = {20, 35},
	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 = {6, 20},
	types = {MELEE, DISTANCE, WAND}
}
attr['fortified'] = {
	attr = 'extraDefense',
	base = 'defense',
	name = 'Defense',
	percent = {7, 25},
	types = {MELEE, SHIELD}
}
attr['deadly'] = {
	attr = 'extraAttack',
	base = 'attack',
	name = 'Attack',
	types = {MELEE},
	percent = {7, 25}
}
attr['strong'] = {
	attr = 'armor',
	name = 'Armor',
	percent = {7, 20},
	types = {ARMOR}
}
attr['hawkeye\'s'] = {
	attr = 'hitChance',
	name = 'Hit Chance',
	percent = {10, 25},
	types = {DISTANCE}
}
--[[ // not available without source edit
attr['farsight'] = {
	attr = 'shootRange',
	name = 'Shoot Range',
	percent = {17, 34},
	types = {DISTANCE, WAND}
}
]]
attr['charged'] = {
	attr = 'charges',
	name = 'Charges',
	percent = {30, 45},
	types = {CHARGES}
}
attr['divine'] = {
	attr = 'duration',
	name = 'Duration',
	percent = {35, 50},
	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 = 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 = 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
						doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))
 
						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>
 
Last edited:
ThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyouThankyou
 
Back
Top