380 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			380 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local monsterOfTheDay = {
 | 
						|
	[8430] = { monster = 'Crocodile' },
 | 
						|
	[8431] = { monster = 'Tarantula' },
 | 
						|
	[8432] = { monster = 'Carniphila' },
 | 
						|
	[8433] = { monster = 'Merlkin' },
 | 
						|
	[8434] = { monster = 'Kongra' },
 | 
						|
	[8435] = { monster = 'Sibang' },
 | 
						|
	[8436] = { monster = 'Thornback Tortoise' },
 | 
						|
	[8437] = { monster = 'Gargoyle' },
 | 
						|
	[8438] = { monster = 'Quara Constrictor Scout' },
 | 
						|
	[8439] = { monster = 'Quara Hydromancer Scout' },
 | 
						|
	[8440] = { monster = 'Quara Mantassin Scout' },
 | 
						|
	[8441] = { monster = 'Quara Pincher Scout' },
 | 
						|
	[8442] = { monster = 'Quara Predator Scout' },
 | 
						|
	[8443] = { monster = 'Ancient Scarab' },
 | 
						|
	[8444] = { monster = 'Wyvern' },
 | 
						|
	[8445] = { monster = 'Bonebeast' },
 | 
						|
	[8446] = { monster = 'Dragon' },
 | 
						|
	[8447] = { monster = 'Quara Constrictor' },
 | 
						|
	[8448] = { monster = 'Quara Hydromancer' },
 | 
						|
	[8449] = { monster = 'Quara Mantassin' },
 | 
						|
	[8450] = { monster = 'Quara Pincher' },
 | 
						|
	[8451] = { monster = 'Quara Predator' },
 | 
						|
	[8452] = { monster = 'Giant Spider' },
 | 
						|
	[8453] = { monster = 'Banshee' },
 | 
						|
	[8454] = { monster = 'Lich' },
 | 
						|
	[8455] = { monster = 'Acolyte of The Cult' },
 | 
						|
	[8456] = { monster = 'Adept of The Cult' },
 | 
						|
	[8457] = { monster = 'Enlightened of The Cult' },
 | 
						|
	[8458] = { monster = 'Novice of The Cult' },
 | 
						|
	[8459] = { monster = 'Hydra' },
 | 
						|
	[8460] = { monster = 'Serpent Spawn' },
 | 
						|
	[8461] = { monster = 'Behemoth' },
 | 
						|
	[8462] = { monster = 'Dragon Lord' },
 | 
						|
	[8463] = { monster = 'Hand of Cursed Fate' },
 | 
						|
	[8464] = { monster = 'Juggernaut' },
 | 
						|
	[8465] = { monster = 'Frost Troll' },
 | 
						|
	[8466] = { monster = 'Swamp Troll' },
 | 
						|
	[8467] = { monster = 'Rat' },
 | 
						|
	[8468] = { monster = 'Cave Rat' },
 | 
						|
	[8469] = { monster = 'Wolf' },
 | 
						|
	[8470] = { monster = 'Winter Wolf' },
 | 
						|
	[8471] = { monster = 'Wasp' },
 | 
						|
	[8472] = { monster = 'Larva' },
 | 
						|
	[8473] = { monster = 'Dwarf' },
 | 
						|
	[8474] = { monster = 'Skeleton' },
 | 
						|
	[8475] = { monster = 'Ghoul' },
 | 
						|
	[8476] = { monster = 'Elf' },
 | 
						|
	[8477] = { monster = 'Elf Scout' },
 | 
						|
	[8478] = { monster = 'Elf Arcanist' },
 | 
						|
	[8479] = { monster = 'Bug' },
 | 
						|
	[8480] = { monster = 'Smuggler' },
 | 
						|
	[8481] = { monster = 'Wild Warrior' },
 | 
						|
	[8482] = { monster = 'Bandit' },
 | 
						|
	[8483] = { monster = 'Hyaena' },
 | 
						|
	[8484] = { monster = 'Lion' },
 | 
						|
	[8485] = { monster = 'Bear' },
 | 
						|
	[8486] = { monster = 'Slime' },
 | 
						|
	[8487] = { monster = 'Beholder' },
 | 
						|
	[8488] = { monster = 'Elder Beholder' },
 | 
						|
	[8489] = { monster = 'Green Djinn' },
 | 
						|
	[8490] = { monster = 'Blue Djinn' },
 | 
						|
	[8491] = { monster = 'Marid' },
 | 
						|
	[8492] = { monster = 'Efreet' },
 | 
						|
	[8493] = { monster = 'Pirate Skeleton' },
 | 
						|
	[8494] = { monster = 'Pirate Marauder' },
 | 
						|
	[8495] = { monster = 'Pirate Cutthroat' },
 | 
						|
	[8496] = { monster = 'Pirate Ghost' },
 | 
						|
	[8497] = { monster = 'Pirate Buccaneer' },
 | 
						|
	[8498] = { monster = 'Pirate Corsair' },
 | 
						|
	[8499] = { monster = 'Orc Spearman' },
 | 
						|
	[8500] = { monster = 'Orc Shaman' },
 | 
						|
	[8501] = { monster = 'Orc Rider' },
 | 
						|
	[8502] = { monster = 'Orc Warrior' },
 | 
						|
	[8503] = { monster = 'Orc Berserker' },
 | 
						|
	[8504] = { monster = 'Minotaur Archer' },
 | 
						|
	[8505] = { monster = 'Minotaur Guard' },
 | 
						|
	[8506] = { monster = 'Minotaur Mage' },
 | 
						|
	[8507] = { monster = 'Lizard Templar' },
 | 
						|
	[8508] = { monster = 'Lizard Sentinel' },
 | 
						|
	[8509] = { monster = 'Lizard Snakecharmer' },
 | 
						|
	[8510] = { monster = 'Dwarf Soldier' },
 | 
						|
	[8511] = { monster = 'Dwarf Guard' },
 | 
						|
	[8512] = { monster = 'Dwarf Geomancer' },
 | 
						|
	[8513] = { monster = 'Ghost' },
 | 
						|
	[8514] = { monster = 'Demon Skeleton' },
 | 
						|
	[8515] = { monster = 'Vampire' },
 | 
						|
	[8516] = { monster = 'Orc Leader' },
 | 
						|
	[8517] = { monster = 'Orc Warlord' },
 | 
						|
	[8518] = { monster = 'Hero' },
 | 
						|
	[8519] = { monster = 'Necromancer' },
 | 
						|
	[8520] = { monster = 'Priestess' },
 | 
						|
	[8521] = { monster = 'Nightmare' },
 | 
						|
	[8522] = { monster = 'Warlock' },
 | 
						|
	[8523] = { monster = 'Demon' },
 | 
						|
	[8524] = { monster = 'Troll' },
 | 
						|
	[8525] = { monster = 'Goblin' },
 | 
						|
	[8526] = { monster = 'Rotworm' },
 | 
						|
	[8527] = { monster = 'Carrion Worm' },
 | 
						|
	[8528] = { monster = 'Cyclops' },
 | 
						|
	[8529] = { monster = 'Amazon' },
 | 
						|
	[8530] = { monster = 'Minotaur' },
 | 
						|
	[8531] = { monster = 'Orc' }
 | 
						|
}
 | 
						|
 | 
						|
local trainingStatues = {17724, 17725, 17726, 17727, 17728}
 | 
						|
 | 
						|
function Player:onLook(thing, position, distance)
 | 
						|
	local description = "You see " .. thing:getDescription(distance)
 | 
						|
	
 | 
						|
	if thing:isItem() and thing:getId() == 2028 then
 | 
						|
		if isInArray(trainingStatues, thing:getActionId()) then
 | 
						|
			local trainingTime = math.min(43200 / 2, self:getOfflineTrainingTime() / 1000)
 | 
						|
			local text = "You have"
 | 
						|
			local hours = math.floor(trainingTime / 3600)
 | 
						|
			if hours > 1 then
 | 
						|
				text = string.format("%s %d hours", text, hours)
 | 
						|
			elseif hours == 1 then
 | 
						|
				text = string.format("%s 1 hour", text)
 | 
						|
			end
 | 
						|
 | 
						|
			local minutes = math.floor((trainingTime % 3600) / 60)
 | 
						|
			if minutes ~= 0 then
 | 
						|
				if hours ~= 0 then
 | 
						|
					text = string.format("%s and", text)
 | 
						|
				end
 | 
						|
 | 
						|
				if minutes > 1 then
 | 
						|
					text = string.format("%s %d minutes", text, minutes)
 | 
						|
				else
 | 
						|
					text = string.format("%s 1 minute", text)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			text = string.format(" %s offline training time remaining.", text)
 | 
						|
			
 | 
						|
			description = string.format(description .. "%s", text)
 | 
						|
		end
 | 
						|
	end
 | 
						|
			
 | 
						|
	if self:getGroup():getAccess() then
 | 
						|
		if thing:isItem() then
 | 
						|
			description = string.format("%s\nItem ID: %d", description, thing:getId())
 | 
						|
 | 
						|
			local actionId = thing:getActionId()
 | 
						|
			if actionId ~= 0 then
 | 
						|
				description = string.format("%s, Action ID: %d", description, actionId)
 | 
						|
			end
 | 
						|
 | 
						|
			local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_MOVEMENTID)
 | 
						|
			if uniqueId > 0 and uniqueId < 65536 then
 | 
						|
				description = string.format("%s, Movement ID: %d", description, uniqueId)
 | 
						|
			end
 | 
						|
 | 
						|
			local itemType = thing:getType()
 | 
						|
 | 
						|
			local transformEquipId = itemType:getTransformEquipId()
 | 
						|
			local transformDeEquipId = itemType:getTransformDeEquipId()
 | 
						|
			if transformEquipId ~= 0 then
 | 
						|
				description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
 | 
						|
			elseif transformDeEquipId ~= 0 then
 | 
						|
				description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
 | 
						|
			end
 | 
						|
 | 
						|
			local decayId = itemType:getDecayId()
 | 
						|
			if decayId ~= -1 then
 | 
						|
				description = string.format("%s\nDecays to: %d", description, decayId)
 | 
						|
			end
 | 
						|
			if thing:getAttribute(ITEM_ATTRIBUTE_DECAYSTATE) == 1 then
 | 
						|
				description = string.format("%s\nDecaying in %d minutes (%d seconds).", description, thing:getAttribute(ITEM_ATTRIBUTE_DURATION) / 1000 / 60, thing:getAttribute(ITEM_ATTRIBUTE_DURATION) / 1000)
 | 
						|
			end
 | 
						|
		elseif thing:isCreature() then
 | 
						|
			local str = "%s\nHealth: %d / %d"
 | 
						|
			if thing:isPlayer() and thing:getMaxMana() > 0 then
 | 
						|
				str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
 | 
						|
			end
 | 
						|
			description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
 | 
						|
		end
 | 
						|
 | 
						|
		local position = thing:getPosition()
 | 
						|
		description = string.format(
 | 
						|
			"%s\nPosition: %d, %d, %d",
 | 
						|
			description, position.x, position.y, position.z
 | 
						|
		)
 | 
						|
 | 
						|
		if thing:isCreature() then
 | 
						|
			if thing:isPlayer() then
 | 
						|
				description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	self:sendTextMessage(MESSAGE_INFO_DESCR, description)
 | 
						|
end
 | 
						|
 | 
						|
function Player:onLookInBattleList(creature, distance)
 | 
						|
	local description = "You see " .. creature:getDescription(distance)
 | 
						|
	if self:getGroup():getAccess() then
 | 
						|
		local str = "%s\nHealth: %d / %d"
 | 
						|
		if creature:isPlayer() and creature:getMaxMana() > 0 then
 | 
						|
			str = string.format("%s, Mana: %d / %d", str, creature:getMana(), creature:getMaxMana())
 | 
						|
		end
 | 
						|
		description = string.format(str, description, creature:getHealth(), creature:getMaxHealth()) .. "."
 | 
						|
 | 
						|
		local position = creature:getPosition()
 | 
						|
		description = string.format(
 | 
						|
			"%s\nPosition: %d, %d, %d",
 | 
						|
			description, position.x, position.y, position.z
 | 
						|
		)
 | 
						|
 | 
						|
		if creature:isPlayer() then
 | 
						|
			description = string.format("%s\nIP: %s", description, Game.convertIpToString(creature:getIp()))
 | 
						|
		end
 | 
						|
	end
 | 
						|
	self:sendTextMessage(MESSAGE_INFO_DESCR, description)
 | 
						|
end
 | 
						|
 | 
						|
function Player:onLookInTrade(partner, item, distance)
 | 
						|
	self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance))
 | 
						|
end
 | 
						|
 | 
						|
function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
function Player:onItemMoved(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
 | 
						|
end
 | 
						|
 | 
						|
function Player:onMoveCreature(creature, fromPosition, toPosition)
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
function Player:onReportBug(message, position, category)
 | 
						|
	if self:getAccountType() == ACCOUNT_TYPE_NORMAL then
 | 
						|
		return false
 | 
						|
	end
 | 
						|
 | 
						|
	local name = self:getName()
 | 
						|
	local file = io.open("data/reports/bugs/" .. name .. " report.txt", "a")
 | 
						|
 | 
						|
	if not file then
 | 
						|
		self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "There was an error when processing your report, please contact a gamemaster.")
 | 
						|
		return true
 | 
						|
	end
 | 
						|
 | 
						|
	io.output(file)
 | 
						|
	io.write("------------------------------\n")
 | 
						|
	io.write("Name: " .. name)
 | 
						|
	if category == BUG_CATEGORY_MAP then
 | 
						|
		io.write(" [Map position: " .. position.x .. ", " .. position.y .. ", " .. position.z .. "]")
 | 
						|
	end
 | 
						|
	local playerPosition = self:getPosition()
 | 
						|
	io.write(" [Player Position: " .. playerPosition.x .. ", " .. playerPosition.y .. ", " .. playerPosition.z .. "]\n")
 | 
						|
	io.write("Comment: " .. message .. "\n")
 | 
						|
	io.close(file)
 | 
						|
 | 
						|
	self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "Your report has been sent to " .. configManager.getString(configKeys.SERVER_NAME) .. ".")
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
function Player:onTurn(direction)
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
function Player:onTradeRequest(target, item)
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
function Player:onTradeAccept(target, item, targetItem)
 | 
						|
	return true
 | 
						|
end
 | 
						|
 | 
						|
local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
 | 
						|
soulCondition:setTicks(4 * 60 * 1000)
 | 
						|
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
 | 
						|
 | 
						|
local function useStamina(player)
 | 
						|
	local staminaMinutes = player:getStamina()
 | 
						|
	if staminaMinutes == 0 then
 | 
						|
		return
 | 
						|
	end
 | 
						|
 | 
						|
	local playerId = player:getId()
 | 
						|
	local currentTime = os.time()
 | 
						|
	local timePassed = currentTime - nextUseStaminaTime[playerId]
 | 
						|
	if timePassed <= 0 then
 | 
						|
		return
 | 
						|
	end
 | 
						|
 | 
						|
	if timePassed > 60 then
 | 
						|
		if staminaMinutes > 2 then
 | 
						|
			staminaMinutes = staminaMinutes - 2
 | 
						|
		else
 | 
						|
			staminaMinutes = 0
 | 
						|
		end
 | 
						|
		nextUseStaminaTime[playerId] = currentTime + 120
 | 
						|
	else
 | 
						|
		staminaMinutes = staminaMinutes - 1
 | 
						|
		nextUseStaminaTime[playerId] = currentTime + 60
 | 
						|
	end
 | 
						|
	player:setStamina(staminaMinutes)
 | 
						|
end
 | 
						|
 | 
						|
function Player:onGainExperience(source, exp, rawExp)
 | 
						|
	if not source or source:isPlayer() then
 | 
						|
		return exp
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Soul regeneration
 | 
						|
	local vocation = self:getVocation()
 | 
						|
	if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
 | 
						|
		soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
 | 
						|
		self:addCondition(soulCondition)
 | 
						|
	end
 | 
						|
 | 
						|
	-- Apply experience stage multiplier
 | 
						|
	if (vocation:getId() > 0 or self:getLevel() < 8) then
 | 
						|
		exp = exp * Game.getExperienceStage(self:getLevel())
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Stamina modifier
 | 
						|
	if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
 | 
						|
		useStamina(self)
 | 
						|
 | 
						|
		if self:getStorageValue(17582) > os.time() then
 | 
						|
			exp = exp * 1.1
 | 
						|
		end
 | 
						|
		
 | 
						|
		local staminaMinutes = self:getStamina()
 | 
						|
		if staminaMinutes <= 840 then
 | 
						|
			exp = exp * 0.5
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if getGlobalStorageValue(17589) > os.time() then
 | 
						|
		exp = exp * (1 + getGlobalStorageValue(17585) / 100) 
 | 
						|
	end
 | 
						|
	
 | 
						|
	if source:isMonster() and not source:getMaster() then
 | 
						|
		if getGlobalStorageValue(8420) > 0 then
 | 
						|
			if source:getName():lower() == monsterOfTheDay[getGlobalStorageValue(8420)].monster:lower() then
 | 
						|
				exp = exp * (1 + getGlobalStorageValue(8421) / 100)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if self:isPremium() then
 | 
						|
		exp = exp * (1 + 10 / 100) 
 | 
						|
	end
 | 
						|
	
 | 
						|
	return exp
 | 
						|
end
 | 
						|
 | 
						|
function Player:onLoseExperience(exp)
 | 
						|
	return exp
 | 
						|
end
 | 
						|
 | 
						|
function Player:onGainSkillTries(skill, tries)
 | 
						|
	if APPLY_SKILL_MULTIPLIER == false then
 | 
						|
		return tries
 | 
						|
	end
 | 
						|
 | 
						|
	if skill == SKILL_MAGLEVEL then
 | 
						|
		tries = tries * configManager.getNumber(configKeys.RATE_MAGIC)
 | 
						|
		
 | 
						|
		if getGlobalStorageValue(17591) > os.time() then
 | 
						|
			tries = tries * (1 + getGlobalStorageValue(17587) / 100) 
 | 
						|
		end
 | 
						|
		
 | 
						|
		return tries
 | 
						|
	end
 | 
						|
	
 | 
						|
	tries = tries * configManager.getNumber(configKeys.RATE_SKILL)
 | 
						|
	
 | 
						|
	if getGlobalStorageValue(17590) > os.time() then
 | 
						|
		tries = tries * (1 + getGlobalStorageValue(17586) / 100) 
 | 
						|
	end
 | 
						|
	
 | 
						|
	return tries
 | 
						|
end
 |