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, 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 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