Ir para conteúdo

[TFS 1.1] Random Item Stats


Furabio

Posts Recomendados

normal item:

15:19 You see a morning star (Atk:25, Def:11).
It weighs 54.00 oz.

rare:

15:19 You see a [sharpened] morning star (Atk:29, Def:11).
It weighs 54.00 oz.
[atk: +18%]

creaturescripts.xml:

<event type="login" name="randomstats_register" script="randomstats.lua"/>
<event type="kill" name="randomstats_loot" script="randomstats.lua"/>

randomstats.lua:

local rare_popup = true
local rare_text = "*rare*"
local rare_effect = true
local rare_effect_id = CONST_ME_MAGIC_GREEN

local tiers = {
	[1] = {
		prefix = 'rare',
		showattr = true, -- attr prefix will be shown instead
		extra = {0, 0},
		chance = {
			[1] = 10000, -- chance for basic stat
			[2] = 5000 -- chance for second stat
		}
	},

	[2] = {
		prefix = 'epic',
		extra = {7, 20}, -- additional percent bonus
		chance = {
			[1] = 3333,
			[2] = 25000
		}
	},

	[3] = {
		prefix = 'legendary',
		extra = {20, 35},
		chance = {
			[1] = 1000,
			[2] = 100000 -- 2 bonuses always
		}
	},
}

--! attributes
local attr = {
	atk = {
		name = 'atk',
		prefix = 'sharpened',
		percent = {7, 25},
	},
	def = {
		name = 'def',
		prefix = 'fortified',
		percent = {7, 25},
	},
	extradef = {
		name = 'extra def',
		prefix = 'balanced',
		percent = {7, 25},
	},
	arm = {
		name = 'arm',
		prefix = 'flawless',
		percent = {7, 20},
	},
	hitchance = {
		name = 'accuracy',
		prefix = 'accurate',
		percent = {10, 25},
	},
	shootrange = {
		name = 'range',
		prefix = 'powerful',
		percent = {17, 34},
	},
	charges = {
		name = 'charges',
		prefix = 'charged',
		percent = {30, 45},
	},
	duration = {
		name = 'time',
		prefix = 'unique',
		percent = {35, 50},
	},

	--[[ not available in 1.1
	attackSpeed = {},
	extraAttack = {},
	]]
}

local stats = {
	[1] = {ITEM_ATTRIBUTE_ATTACK, attr.atk},
	[2] = {ITEM_ATTRIBUTE_DEFENSE, attr.def},
	[3] = {ITEM_ATTRIBUTE_EXTRADEFENSE, attr.extradef},
	[4] = {ITEM_ATTRIBUTE_ARMOR, attr.arm},
	[5] = {ITEM_ATTRIBUTE_HITCHANCE, attr.hitchance},
	[6] = {ITEM_ATTRIBUTE_SHOOTRANGE, attr.shootrange},
	[7] = {ITEM_ATTRIBUTE_CHARGES, attr.charges},
	[8] = {ITEM_ATTRIBUTE_DURATION, attr.duration},
	-- not available in 1.1
	-- [9] = {ITEM_ATTRIBUTE_ATTACKSPEED, attr.attackSpeed},
	-- [10] = {ITEM_ATTRIBUTE_EXTRAATTACK, attr.extraAttack},
}

function stat_getItemDuration(item)
	local it_id = item:getId()
	local tid = ItemType(it_id):getTransformEquipId()
	if tid > 0 then
		item:transform(tid)
		local vx = item:getAttribute(ITEM_ATTRIBUTE_DURATION)
		item:transform(it_id)
		item:removeAttribute(ITEM_ATTRIBUTE_DURATION)
		return vx
	end
	return 0
end

function loot_attrToVal(item, attr)
	local id = ItemType(item:getId())
	local v = {
		[ITEM_ATTRIBUTE_ATTACK] = id:getAttack(),
		[ITEM_ATTRIBUTE_DEFENSE] = id:getDefense(),
		[ITEM_ATTRIBUTE_EXTRADEFENSE] = id:getExtraDefense(),
		[ITEM_ATTRIBUTE_ARMOR] = id:getArmor(),
		[ITEM_ATTRIBUTE_HITCHANCE] = id:getHitChance(),
		[ITEM_ATTRIBUTE_SHOOTRANGE] = id:getShootRange(),
		[ITEM_ATTRIBUTE_CHARGES] = id:getCharges(),
		[ITEM_ATTRIBUTE_DURATION] = stat_getItemDuration(item),

		-- not available in 1.1
		-- [ITEM_ATTRIBUTE_ATTACKSPEED] = item:getAttackSpeed(),
		-- [ITEM_ATTRIBUTE_EXTRAATTACK] = item:getExtraAttack(),
	}
	return v[attr]
end

function assign_loot_Stat(c)
	local rares = 0
	local h = c:getItemHoldingCount()
	if h > 0 then
		for i = 1, h do
			local available_stats = {}
			local it_u = c:getItem(i - 1)
			local it_id = ItemType(it_u:getId())
			if it_u:isContainer() then
				local crares = assign_loot_Stat(it_u)
				rares = rares + crares
			else
				if not it_id:isStackable() then
					local wp = it_id:getWeaponType()
					if wp > 0 then
						if wp == WEAPON_SHIELD then -- type shield
							table.insert(available_stats, stats[2])
						elseif wp == WEAPON_DISTANCE then -- type bow
							table.insert(available_stats, stats[1])
							table.insert(available_stats, stats[5])
							table.insert(available_stats, stats[6])
							-- not available in 1.1
							-- table.insert(available_stats, stats[9])
						elseif wp == WEAPON_WAND then -- type wand
							table.insert(available_stats, stats[6])
						-- not available in 1.1
						-- table.insert(available_stats, stats[9])
						elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, wp) then -- melee weapon

							if it_id:getAttack() > 0 then
								table.insert(available_stats, stats[1])
							end
							
							if it_id:getDefense() > 0 then
								table.insert(available_stats, stats[2])
							end
							
							if it_id:getExtraDefense() ~= 0 then
								table.insert(available_stats, stats[3])
							end
							-- not available in 1.1
							-- table.insert(available_stats, stats[10])
						end
					else -- armors, amulets, runes and rings
						if it_id:getArmor() > 0 then
							table.insert(available_stats, stats[4])
						end

						if it_id:getCharges() > 0 then
							table.insert(available_stats, stats[7])
						end

						local eq_id = it_id:getTransformEquipId()
						if eq_id > 0 then
							table.insert(available_stats, stats[8])
						end
					end
				end
			end

			if #available_stats > 0 then
				-- skips it all if it's empty
				local tier = math.random(1, #tiers)
				if #tiers[tier].chance > 0 then
					local statsStored = 0
					local stats_used = {}
					for stat = 1, #tiers[tier].chance do
						if #available_stats > 0 then
							-- stops if no more stats available
							if stat - 1 == statsStored then
								-- checks when it's time to stop adding stats
								if math.random(1, 100000) <= tiers[tier].chance[stat] then
									statsStored = statsStored + 1

									local selected_stat = math.random(1, #available_stats)
									table.insert(stats_used, available_stats[selected_stat])
									table.remove(available_stats, selected_stat)
								end
							end
						end
					end

					if #stats_used > 0 then
						rares = rares + 1
						local stat_desc = {}
						for stat = 1, #stats_used do
							local v = math.random(
								stats_used[stat][2].percent[1],
								stats_used[stat][2].percent[2]
							) + math.random(
								tiers[tier].extra[1],
								tiers[tier].extra[2]
							)
							local basestat = loot_attrToVal(it_u, stats_used[stat][1])
							it_u:setAttribute(stats_used[stat][1], basestat + math.abs(basestat * v / 100))
							table.insert(stat_desc, '[' .. stats_used[stat][2].name .. ': +' .. v .. '%]')
						end

						if tiers[tier].showattr then
							for stat = 1, #stats_used do
								it_u:setAttribute(ITEM_ATTRIBUTE_NAME, "[" .. stats_used[stat][2].prefix .. "]" .. it_u:getAttribute(ITEM_ATTRIBUTE_NAME))
							end
							it_u:setAttribute(ITEM_ATTRIBUTE_NAME, it_u:getAttribute(ITEM_ATTRIBUTE_NAME) .. " " .. it_id:getName())
						else
							it_u:setAttribute(ITEM_ATTRIBUTE_NAME, tiers[tier].prefix .. " " .. it_id:getName())
						end

						it_u:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, table.concat(stat_desc, "\n"))
					end
				end
			end
		end
	end
	return rares
end

function find_loot_Container(pos)
	local rares = 0
	local c = Tile(pos):getTopDownItem()
	if c ~= nil then
		if c:isContainer() then
			rares = rares + assign_loot_Stat(c)
			if rares > 0 then
				if rare_popup then
					local spectators = Game.getSpectators(pos, false, true, 7, 7, 5, 5)
					for i = 1, #spectators do
						spectators[i]:say(rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], pos)
					end
				end

				if rare_effect then
					pos:sendMagicEffect(rare_effect_id)
				end
			end
			return true
		end
	end
end

function onKill(player, target, lastHit)
	if (not isSummon(target)) then
		addEvent(find_loot_Container, 2, target:getPosition())
	end
	return true
end

function onLogin(player)
	player:registerEvent("randomstats_loot")
	return true
end

Créditos : zbisu

Link para o comentário
Compartilhar em outros sites

  • 1 month later...
  • 7 years later...
×
×
  • Criar Novo...