First commit
This commit is contained in:
47
app/SabrehavenServer/data/talkactions/scripts/469.lua
Normal file
47
app/SabrehavenServer/data/talkactions/scripts/469.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
local area = {
|
||||
fromPos = {x = 33144, y = 32863, z = 7},
|
||||
toPos = {x = 33154, y = 32873, z = 7}
|
||||
}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if player:getPosition():isInRange(area.fromPos, area.toPos) then
|
||||
local tile1 = Tile(Position(33147, 32868, 7))
|
||||
if tile1 then
|
||||
local stoneRailing = tile1:getItemById(2212)
|
||||
if stoneRailing ~= nil then
|
||||
stoneRailing:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
stoneRailing:remove()
|
||||
broadcastMessage("The player " .. player:getName() .. " have opened The Serpentine Tower!", MESSAGE_STATUS_WARNING)
|
||||
end
|
||||
end
|
||||
|
||||
local tile2 = Tile(Position(33149, 32866, 7))
|
||||
if tile2 then
|
||||
local stoneRailing = tile2:getItemById(2210)
|
||||
if stoneRailing ~= nil then
|
||||
stoneRailing:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
stoneRailing:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local tile3 = Tile(Position(33151, 32868, 7))
|
||||
if tile3 then
|
||||
local stoneRailing = tile3:getItemById(2211)
|
||||
if stoneRailing ~= nil then
|
||||
stoneRailing:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
stoneRailing:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local tile4 = Tile(Position(33149, 32870, 7))
|
||||
if tile4 then
|
||||
local stoneRailing = tile4:getItemById(2209)
|
||||
if stoneRailing ~= nil then
|
||||
stoneRailing:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
stoneRailing:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
66
app/SabrehavenServer/data/talkactions/scripts/add_skill.lua
Normal file
66
app/SabrehavenServer/data/talkactions/scripts/add_skill.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
local function getSkillId(skillName)
|
||||
if skillName == "club" then
|
||||
return SKILL_CLUB
|
||||
elseif skillName == "sword" then
|
||||
return SKILL_SWORD
|
||||
elseif skillName == "axe" then
|
||||
return SKILL_AXE
|
||||
elseif skillName:sub(1, 4) == "dist" then
|
||||
return SKILL_DISTANCE
|
||||
elseif skillName:sub(1, 6) == "shield" then
|
||||
return SKILL_SHIELD
|
||||
elseif skillName:sub(1, 4) == "fish" then
|
||||
return SKILL_FISHING
|
||||
else
|
||||
return SKILL_FIST
|
||||
end
|
||||
end
|
||||
|
||||
local function getExpForLevel(level)
|
||||
level = level - 1
|
||||
return ((50 * level * level * level) - (150 * level * level) + (400 * level)) / 3
|
||||
end
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
if split[2] == nil then
|
||||
player:sendCancelMessage("Insufficient parameters.")
|
||||
return false
|
||||
end
|
||||
|
||||
local target = Player(split[1])
|
||||
if target == nil then
|
||||
player:sendCancelMessage("A player with that name is not online.")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Trim left
|
||||
split[2] = split[2]:gsub("^%s*(.-)$", "%1")
|
||||
|
||||
local count = 1
|
||||
if split[3] ~= nil then
|
||||
count = tonumber(split[3])
|
||||
end
|
||||
|
||||
local ch = split[2]:sub(1, 1)
|
||||
for i = 1, count do
|
||||
if ch == "l" or ch == "e" then
|
||||
target:addExperience(getExpForLevel(target:getLevel() + 1) - target:getExperience(), false)
|
||||
elseif ch == "m" then
|
||||
target:addManaSpent(target:getVocation():getRequiredManaSpent(target:getBaseMagicLevel() + 1) - target:getManaSpent())
|
||||
else
|
||||
local skillId = getSkillId(split[2])
|
||||
target:addSkillTries(skillId, target:getVocation():getRequiredSkillTries(skillId, target:getSkillLevel(skillId) + 1) - target:getSkillTries(skillId))
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
21
app/SabrehavenServer/data/talkactions/scripts/add_tutor.lua
Normal file
21
app/SabrehavenServer/data/talkactions/scripts/add_tutor.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
function onSay(player, words, param)
|
||||
if player:getAccountType() <= ACCOUNT_TYPE_TUTOR then
|
||||
return true
|
||||
end
|
||||
|
||||
local target = Player(param)
|
||||
if target == nil then
|
||||
player:sendCancelMessage("A player with that name is not online.")
|
||||
return false
|
||||
end
|
||||
|
||||
if target:getAccountType() ~= ACCOUNT_TYPE_NORMAL then
|
||||
player:sendCancelMessage("You can only promote a normal player to a tutor.")
|
||||
return false
|
||||
end
|
||||
|
||||
target:setAccountType(ACCOUNT_TYPE_TUTOR)
|
||||
target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have been promoted to a tutor by " .. player:getName() .. ".")
|
||||
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have promoted " .. target:getName() .. " to a tutor.")
|
||||
return false
|
||||
end
|
@@ -0,0 +1,29 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local effect = tonumber(param)
|
||||
local position = player:getPosition()
|
||||
local toPositionLow = {z = position.z}
|
||||
local toPositionHigh = {z = position.z}
|
||||
|
||||
toPositionLow.x = position.x - 7
|
||||
toPositionHigh.x = position.x + 7
|
||||
for i = -5, 5 do
|
||||
toPositionLow.y = position.y + i
|
||||
toPositionHigh.y = toPositionLow.y
|
||||
position:sendDistanceEffect(toPositionLow, effect)
|
||||
position:sendDistanceEffect(toPositionHigh, effect)
|
||||
end
|
||||
|
||||
toPositionLow.y = position.y - 5
|
||||
toPositionHigh.y = position.y + 5
|
||||
for i = -6, 6 do
|
||||
toPositionLow.x = position.x + i
|
||||
toPositionHigh.x = toPositionLow.x
|
||||
position:sendDistanceEffect(toPositionLow, effect)
|
||||
position:sendDistanceEffect(toPositionHigh, effect)
|
||||
end
|
||||
return false
|
||||
end
|
57
app/SabrehavenServer/data/talkactions/scripts/ban.lua
Normal file
57
app/SabrehavenServer/data/talkactions/scripts/ban.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
local banDays = 7
|
||||
|
||||
function onSay(cid, words, param)
|
||||
local player = Player(cid)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local name = param
|
||||
local reason = ''
|
||||
local banInfo = ''
|
||||
local banTime = 0
|
||||
local banMultiplier = 0
|
||||
local params = param:split(',')
|
||||
if params ~= nil then
|
||||
name = params[1]
|
||||
reason = string.trim(params[2])
|
||||
banInfo = string.trim(params[3])
|
||||
print(banInfo)
|
||||
end
|
||||
if banInfo then
|
||||
if banInfo:find('h') then
|
||||
banTime = banInfo:sub(0, banInfo:find('h') - 1)
|
||||
banMultiplier = 3600
|
||||
elseif banInfo:find('d') then
|
||||
banTime = banInfo:sub(0, banInfo:find('d') - 1)
|
||||
banMultiplier = 86400
|
||||
else
|
||||
banTime = banDays
|
||||
banMultiplier = 86400
|
||||
end
|
||||
banTime = banTime * banMultiplier
|
||||
end
|
||||
|
||||
local accountId = getAccountNumberByPlayerName(name)
|
||||
if accountId == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
local resultId = db.storeQuery("SELECT 1 FROM `account_bans` WHERE `account_id` = " .. accountId)
|
||||
if resultId ~= false then
|
||||
result.free(resultId)
|
||||
return false
|
||||
end
|
||||
|
||||
local timeNow = os.time()
|
||||
db:query("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" ..
|
||||
accountId .. ", " .. db.escapeString(reason) .. ", " .. timeNow .. ", " .. timeNow + banTime .. ", " .. player:getGuid() .. ")")
|
||||
|
||||
local target = Player(name)
|
||||
if target ~= nil then
|
||||
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, target:getName() .. " has been banned.")
|
||||
target:remove()
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, name .. " has been banned.")
|
||||
end
|
||||
end
|
11
app/SabrehavenServer/data/talkactions/scripts/broadcast.lua
Normal file
11
app/SabrehavenServer/data/talkactions/scripts/broadcast.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
function onSay(player, words, param)
|
||||
if not getPlayerFlagValue(player, PlayerFlag_CanBroadcast) then
|
||||
return true
|
||||
end
|
||||
|
||||
print("> " .. player:getName() .. " broadcasted: \"" .. param .. "\".")
|
||||
for _, targetPlayer in ipairs(Game.getPlayers()) do
|
||||
targetPlayer:sendTextMessage(MESSAGE_STATUS_WARNING, param)
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,4 @@
|
||||
function onSay(player, words, param)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "Buying a house is available only through auction which is available at website: https://tibianus.com/house.php")
|
||||
return false
|
||||
end
|
25
app/SabrehavenServer/data/talkactions/scripts/buyprem.lua
Normal file
25
app/SabrehavenServer/data/talkactions/scripts/buyprem.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
local config = {
|
||||
days = 90,
|
||||
maxDays = 365,
|
||||
price = 10000
|
||||
}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if configManager.getBoolean(configKeys.FREE_PREMIUM) then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getPremiumDays() <= config.maxDays then
|
||||
if player:removeMoney(config.price) then
|
||||
player:addPremiumDays(config.days)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have bought " .. config.days .." days of premium account.")
|
||||
else
|
||||
player:sendCancelMessage("You don't have enough money, " .. config.maxDays .. " days premium account costs " .. config.price .. " gold coins.")
|
||||
player:getPosition():sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
else
|
||||
player:sendCancelMessage("You can not buy more than " .. config.maxDays .. " days of premium account.")
|
||||
player:getPosition():sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
return false
|
||||
end
|
25
app/SabrehavenServer/data/talkactions/scripts/chameleon.lua
Normal file
25
app/SabrehavenServer/data/talkactions/scripts/chameleon.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
local condition = Condition(CONDITION_OUTFIT, CONDITIONID_COMBAT)
|
||||
condition:setTicks(-1)
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local itemType = ItemType(param)
|
||||
if itemType:getId() == 0 then
|
||||
itemType = ItemType(tonumber(param))
|
||||
if itemType:getId() == 0 then
|
||||
player:sendCancelMessage("There is no item with that id or name.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
condition:setOutfit(itemType:getId())
|
||||
player:addCondition(condition)
|
||||
return false
|
||||
end
|
19
app/SabrehavenServer/data/talkactions/scripts/changesex.lua
Normal file
19
app/SabrehavenServer/data/talkactions/scripts/changesex.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
local premiumDaysCost = 3
|
||||
|
||||
function onSay(player, words, param)
|
||||
if player:getGroup():getAccess() then
|
||||
player:setSex(player:getSex() == PLAYERSEX_FEMALE and PLAYERSEX_MALE or PLAYERSEX_FEMALE)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have changed your sex.")
|
||||
return false
|
||||
end
|
||||
|
||||
if player:getPremiumDays() >= premiumDaysCost then
|
||||
player:removePremiumDays(premiumDaysCost)
|
||||
player:setSex(player:getSex() == PLAYERSEX_FEMALE and PLAYERSEX_MALE or PLAYERSEX_FEMALE)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have changed your sex for ".. premiumDaysCost .." days of your premium account.")
|
||||
else
|
||||
player:sendCancelMessage("You do not have enough premium days, changing sex costs ".. premiumDaysCost .." days of your premium account.")
|
||||
player:getPosition():sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
return false
|
||||
end
|
15
app/SabrehavenServer/data/talkactions/scripts/clean.lua
Normal file
15
app/SabrehavenServer/data/talkactions/scripts/clean.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local itemCount = cleanMap()
|
||||
if itemCount > 0 then
|
||||
player:sendTextMessage(MESSAGE_STATUS_WARNING, "Cleaned " .. itemCount .. " item" .. (itemCount > 1 and "s" or "") .. " from the map.")
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,17 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
if param == "shutdown" then
|
||||
Game.setGameState(GAME_STATE_SHUTDOWN)
|
||||
else
|
||||
Game.setGameState(GAME_STATE_CLOSED)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server is now closed.")
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,59 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
|
||||
local itemType = ItemType(split[1])
|
||||
if itemType:getId() == 0 then
|
||||
itemType = ItemType(tonumber(split[1]))
|
||||
if itemType:getId() == 0 then
|
||||
player:sendCancelMessage("There is no item with that id or name.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local keynumber = 0
|
||||
local count = tonumber(split[2])
|
||||
if count ~= nil then
|
||||
if itemType:isStackable() then
|
||||
count = math.min(10000, math.max(1, count))
|
||||
elseif itemType:isKey() then
|
||||
keynumber = count
|
||||
count = 1
|
||||
elseif not itemType:hasSubType() then
|
||||
count = math.min(100, math.max(1, count))
|
||||
else
|
||||
count = math.max(1, count)
|
||||
end
|
||||
else
|
||||
count = 1
|
||||
end
|
||||
|
||||
local result = player:addItem(itemType:getId(), count)
|
||||
if result ~= nil then
|
||||
if not itemType:isStackable() then
|
||||
if type(result) == "table" then
|
||||
for _, item in ipairs(result) do
|
||||
if itemType:isKey() then
|
||||
item:setAttribute(ITEM_ATTRIBUTE_KEYNUMBER, keynumber)
|
||||
end
|
||||
item:decay()
|
||||
end
|
||||
else
|
||||
if itemType:isKey() then
|
||||
result:setAttribute(ITEM_ATTRIBUTE_KEYNUMBER, keynumber)
|
||||
end
|
||||
result:decay()
|
||||
end
|
||||
end
|
||||
|
||||
player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
|
||||
end
|
||||
return false
|
||||
end
|
62
app/SabrehavenServer/data/talkactions/scripts/deathlist.lua
Normal file
62
app/SabrehavenServer/data/talkactions/scripts/deathlist.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
local function getArticle(str)
|
||||
return str:find("[AaEeIiOoUuYy]") == 1 and "an" or "a"
|
||||
end
|
||||
|
||||
local function getMonthDayEnding(day)
|
||||
if day == "01" or day == "21" or day == "31" then
|
||||
return "st"
|
||||
elseif day == "02" or day == "22" then
|
||||
return "nd"
|
||||
elseif day == "03" or day == "23" then
|
||||
return "rd"
|
||||
else
|
||||
return "th"
|
||||
end
|
||||
end
|
||||
|
||||
local function getMonthString(m)
|
||||
return os.date("%B", os.time{year = 1970, month = m, day = 1})
|
||||
end
|
||||
|
||||
function onSay(player, words, param)
|
||||
local resultId = db.storeQuery("SELECT `id`, `name` FROM `players` WHERE `name` = " .. db.escapeString(param))
|
||||
if resultId ~= false then
|
||||
local targetGUID = result.getDataInt(resultId, "id")
|
||||
local targetName = result.getDataString(resultId, "name")
|
||||
result.free(resultId)
|
||||
local str = ""
|
||||
local breakline = ""
|
||||
|
||||
local resultId = db.storeQuery("SELECT `time`, `level`, `killed_by`, `is_player` FROM `player_deaths` WHERE `player_id` = " .. targetGUID .. " ORDER BY `time` DESC")
|
||||
if resultId ~= false then
|
||||
repeat
|
||||
if str ~= "" then
|
||||
breakline = "\n"
|
||||
end
|
||||
local date = os.date("*t", result.getDataInt(resultId, "time"))
|
||||
|
||||
local article = ""
|
||||
local killed_by = result.getDataString(resultId, "killed_by")
|
||||
if result.getDataInt(resultId, "is_player") == 0 then
|
||||
article = getArticle(killed_by) .. " "
|
||||
killed_by = string.lower(killed_by)
|
||||
end
|
||||
|
||||
if date.day < 10 then date.day = "0" .. date.day end
|
||||
if date.hour < 10 then date.hour = "0" .. date.hour end
|
||||
if date.min < 10 then date.min = "0" .. date.min end
|
||||
if date.sec < 10 then date.sec = "0" .. date.sec end
|
||||
str = str .. breakline .. " " .. date.day .. getMonthDayEnding(date.day) .. " " .. getMonthString(date.month) .. " " .. date.year .. " " .. date.hour .. ":" .. date.min .. ":" .. date.sec .. " Died at Level " .. result.getDataInt(resultId, "level") .. " by " .. article .. killed_by .. "."
|
||||
until not result.next(resultId)
|
||||
result.free(resultId)
|
||||
end
|
||||
|
||||
if str == "" then
|
||||
str = "No deaths."
|
||||
end
|
||||
player:popupFYI("Deathlist for player, " .. targetName .. ".\n\n" .. str)
|
||||
else
|
||||
player:sendCancelMessage("A player with that name does not exist.")
|
||||
end
|
||||
return false
|
||||
end
|
17
app/SabrehavenServer/data/talkactions/scripts/down.lua
Normal file
17
app/SabrehavenServer/data/talkactions/scripts/down.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
position.z = position.z + 1
|
||||
|
||||
local tile = Tile(position)
|
||||
if tile == nil or tile:getGround() == nil then
|
||||
player:sendCancelMessage("You cannot teleport there.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:teleportTo(position)
|
||||
return false
|
||||
end
|
@@ -0,0 +1,28 @@
|
||||
function onSay(player, words, param)
|
||||
local party = player:getParty()
|
||||
if not party then
|
||||
player:sendCancelMessage("You are not part of a party.")
|
||||
return false
|
||||
end
|
||||
|
||||
if party:getLeader() ~= player then
|
||||
player:sendCancelMessage("You are not the leader of the party.")
|
||||
return false
|
||||
end
|
||||
|
||||
if party:isSharedExperienceActive() then
|
||||
if player:getCondition(CONDITION_INFIGHT) then
|
||||
player:sendCancelMessage("You are in fight. Experience sharing not disabled.")
|
||||
else
|
||||
party:setSharedExperience(false)
|
||||
end
|
||||
else
|
||||
if player:getCondition(CONDITION_INFIGHT) then
|
||||
player:sendCancelMessage("You are in fight. Experience sharing not enabled.")
|
||||
else
|
||||
party:setSharedExperience(true)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
22
app/SabrehavenServer/data/talkactions/scripts/ghost.lua
Normal file
22
app/SabrehavenServer/data/talkactions/scripts/ghost.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GAMEMASTER then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
local isGhost = not player:isInGhostMode()
|
||||
|
||||
player:setGhostMode(isGhost)
|
||||
if isGhost then
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You are now invisible.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You are visible again.")
|
||||
position:sendMagicEffect(CONST_ME_TELEPORT)
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,48 @@
|
||||
local config = {
|
||||
['exp'] = {skillKey = 17585, timeKey = 17589},
|
||||
['skill'] = {skillKey = 17586, timeKey = 17590},
|
||||
['magic'] = {skillKey = 17587, timeKey = 17591},
|
||||
['loot'] = {skillKey = 17588, timeKey = 17592} -- TODO
|
||||
}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
if split[3] == nil then
|
||||
player:sendCancelMessage("Insufficient parameters [(exp,skill,loot,magic),percentage,hours].")
|
||||
return false
|
||||
end
|
||||
|
||||
local skillName = split[1]
|
||||
local percentage = tonumber(split[2])
|
||||
local hours = tonumber(split[3])
|
||||
|
||||
local globalStorage = config[skillName]
|
||||
if not globalStorage then
|
||||
player:sendCancelMessage("Skill name value must be one of the following: exp, skill, loot, magic.")
|
||||
return false
|
||||
end
|
||||
|
||||
if percentage <= 0 then
|
||||
player:sendCancelMessage("Percentage value must be higher than 0. For example, 50% means 1.5x higher rate.")
|
||||
return false
|
||||
end
|
||||
|
||||
if hours <= 0 then
|
||||
player:sendCancelMessage("Hours value must be higher than 0.")
|
||||
return false
|
||||
end
|
||||
|
||||
setGlobalStorageValue(globalStorage.skillKey, percentage)
|
||||
setGlobalStorageValue(globalStorage.timeKey, os.time() + hours * 60 * 60)
|
||||
broadcastMessage(player:getName() .. " have activated the global " .. percentage .. "% " .. skillName .. " rate boost for next " .. hours .. " " .. (hours == 1 and "hour" or "hours") .. ".", MESSAGE_STATUS_WARNING)
|
||||
|
||||
return false
|
||||
end
|
@@ -0,0 +1,20 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
local target = Player(split[1])
|
||||
if target == nil then
|
||||
player:sendCancelMessage("Player not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
if target:getGroup():getAccess() then
|
||||
player:sendCancelMessage("You cannot impersonate this player.")
|
||||
return false
|
||||
end
|
||||
|
||||
target:say(split[2], TALKTYPE_SAY)
|
||||
return false
|
||||
end
|
39
app/SabrehavenServer/data/talkactions/scripts/info.lua
Normal file
39
app/SabrehavenServer/data/talkactions/scripts/info.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
function onSay(player, words, param)
|
||||
if player:getAccountType() == ACCOUNT_TYPE_NORMAL then
|
||||
return true
|
||||
end
|
||||
|
||||
local target = Player(param)
|
||||
if not target then
|
||||
player:sendCancelMessage("Player not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
if target:getAccountType() > player:getAccountType() then
|
||||
player:sendCancelMessage("You can not get info about this player.")
|
||||
return false
|
||||
end
|
||||
|
||||
local targetIp = target:getIp()
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Name: " .. target:getName())
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Access: " .. (target:getGroup():getAccess() and "1" or "0"))
|
||||
if player:getGroup():getAccess() then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Level: " .. target:getLevel())
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Magic Level: " .. target:getMagicLevel())
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Speed: " .. target:getSpeed())
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Position: " .. string.format("(%0.5d / %0.5d / %0.3d)", target:getPosition().x, target:getPosition().y, target:getPosition().z))
|
||||
end
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "IP: " .. Game.convertIpToString(targetIp))
|
||||
|
||||
local players = {}
|
||||
for _, targetPlayer in ipairs(Game.getPlayers()) do
|
||||
if targetPlayer:getIp() == targetIp and targetPlayer ~= target then
|
||||
players[#players + 1] = targetPlayer:getName() .. " [" .. targetPlayer:getLevel() .. "]"
|
||||
end
|
||||
end
|
||||
|
||||
if #players > 0 then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Other players on same IP: " .. table.concat(players, ", ") .. ".")
|
||||
end
|
||||
return false
|
||||
end
|
36
app/SabrehavenServer/data/talkactions/scripts/ipban.lua
Normal file
36
app/SabrehavenServer/data/talkactions/scripts/ipban.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
local ipBanDays = 7
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local resultId = db.storeQuery("SELECT `account_id`, `lastip` FROM `players` WHERE `name` = " .. db.escapeString(param))
|
||||
if resultId == false then
|
||||
return false
|
||||
end
|
||||
|
||||
local targetIp = result.getDataLong(resultId, "lastip")
|
||||
result.free(resultId)
|
||||
|
||||
local targetPlayer = Player(param)
|
||||
if targetPlayer then
|
||||
targetIp = targetPlayer:getIp()
|
||||
targetPlayer:remove()
|
||||
end
|
||||
|
||||
if targetIp == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
resultId = db.storeQuery("SELECT 1 FROM `ip_bans` WHERE `ip` = " .. targetIp)
|
||||
if resultId ~= false then
|
||||
result.free(resultId)
|
||||
return false
|
||||
end
|
||||
|
||||
local timeNow = os.time()
|
||||
db.query("INSERT INTO `ip_bans` (`ip`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" ..
|
||||
targetIp .. ", '', " .. timeNow .. ", " .. timeNow + (ipBanDays * 86400) .. ", " .. player:getGuid() .. ")")
|
||||
return false
|
||||
end
|
19
app/SabrehavenServer/data/talkactions/scripts/kick.lua
Normal file
19
app/SabrehavenServer/data/talkactions/scripts/kick.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local target = Player(param)
|
||||
if target == nil then
|
||||
player:sendCancelMessage("Player not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
if target:getGroup():getAccess() then
|
||||
player:sendCancelMessage("You cannot kick this player.")
|
||||
return false
|
||||
end
|
||||
|
||||
target:remove()
|
||||
return false
|
||||
end
|
75
app/SabrehavenServer/data/talkactions/scripts/kills.lua
Normal file
75
app/SabrehavenServer/data/talkactions/scripts/kills.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
function onSay(player, words, param)
|
||||
if Game.getWorldType() == WORLD_TYPE_PVP_ENFORCED then
|
||||
player:showTextDialog(1998, "Your character has not murders history.", false)
|
||||
return false
|
||||
end
|
||||
|
||||
local today = os.time()
|
||||
local skullTicks = player:getPlayerKillerEnd()
|
||||
local lastDay = 0
|
||||
local lastWeek = 0
|
||||
local lastMonth = 0
|
||||
local egibleMurders = 0
|
||||
local dayTimestamp = today - (24 * 60 * 60)
|
||||
local weekTimestamp = today - (7 * 24 * 60 * 60)
|
||||
local monthTimestamp = today - (30 * 24 * 60 * 60)
|
||||
|
||||
local killsDayRedSkull = configManager.getNumber(configKeys.KILLS_DAY_RED_SKULL)
|
||||
local killsWeekRedSkull = configManager.getNumber(configKeys.KILLS_WEEK_RED_SKULL)
|
||||
local killsMonthRedSkull = configManager.getNumber(configKeys.KILLS_MONTH_RED_SKULL)
|
||||
|
||||
local killsDayBanishment = configManager.getNumber(configKeys.KILLS_DAY_BANISHMENT)
|
||||
local killsWeekBanishment = configManager.getNumber(configKeys.KILLS_WEEK_BANISHMENT)
|
||||
local killsMonthBanishment = configManager.getNumber(configKeys.KILLS_MONTH_BANISHMENT)
|
||||
|
||||
for _, timestamp in pairs(player:getMurderTimestamps()) do
|
||||
if timestamp > dayTimestamp then
|
||||
lastDay = lastDay + 1
|
||||
end
|
||||
|
||||
if timestamp > weekTimestamp then
|
||||
lastWeek = lastWeek + 1
|
||||
end
|
||||
|
||||
egibleMurders = lastMonth + 1
|
||||
|
||||
if timestamp <= monthTimestamp then
|
||||
egibleMurders = lastMonth
|
||||
end
|
||||
|
||||
lastMonth = egibleMurders
|
||||
end
|
||||
|
||||
local message = ""
|
||||
message = message .. "Default murders\n"
|
||||
message = message .. "- Daily kills for red skull " .. killsDayRedSkull .. "\n"
|
||||
message = message .. "- Weekly kills for red skull " .. killsWeekRedSkull .. "\n"
|
||||
message = message .. "- Monthly kills for red skull " .. (killsMonthRedSkull >= 99999 and "unlimited" or tostring(killsMonthRedSkull)) .. "\n"
|
||||
|
||||
message = message .. "- Daily kills for banishment " .. killsDayBanishment .. "\n"
|
||||
message = message .. "- Weekly kills for banishment " .. killsWeekBanishment .. "\n"
|
||||
message = message .. "- Monthly kills for banishment " .. (killsMonthBanishment >= 99999 and "unlimited" or tostring(killsMonthBanishment)) .. "\n"
|
||||
|
||||
message = message .. "\n"
|
||||
|
||||
message = message .. "Last murders within 24 hours " .. lastDay .. "\n"
|
||||
message = message .. "Last murders within a week " .. lastDay .. "\n"
|
||||
message = message .. "Last murders within a month " .. lastDay .. "\n"
|
||||
|
||||
message = message .. "\n"
|
||||
|
||||
message = message .. "Players you may kill for a red skull:\n"
|
||||
message = message .. "- Within 24 hours " .. killsDayRedSkull - lastDay .. " murders.\n"
|
||||
message = message .. "- Within a week " .. killsWeekRedSkull - lastWeek .. " murders.\n"
|
||||
message = message .. "- Within a month " .. killsMonthRedSkull - lastDay .. " murders.\n"
|
||||
|
||||
message = message .. "\n"
|
||||
|
||||
message = message .. "Players you may kill for a banishment:\n"
|
||||
message = message .. "- Within 24 hours " .. killsDayBanishment - lastDay .. " murders.\n"
|
||||
message = message .. "- Within a week " .. killsWeekBanishment - lastWeek .. " murders.\n"
|
||||
message = message .. "- Within a month " .. killsMonthBanishment - lastDay .. " murders.\n"
|
||||
|
||||
player:showTextDialog(1998, message, false)
|
||||
return false
|
||||
end
|
21
app/SabrehavenServer/data/talkactions/scripts/leavehouse.lua
Normal file
21
app/SabrehavenServer/data/talkactions/scripts/leavehouse.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
function onSay(player, words, param)
|
||||
local position = player:getPosition()
|
||||
local tile = Tile(position)
|
||||
local house = tile and tile:getHouse()
|
||||
if house == nil then
|
||||
player:sendCancelMessage("You are not inside a house.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
return false
|
||||
end
|
||||
|
||||
if house:getOwnerGuid() ~= player:getGuid() then
|
||||
player:sendCancelMessage("You are not the owner of this house.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
return false
|
||||
end
|
||||
|
||||
house:setOwnerGuid(0)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully left your house.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
return false
|
||||
end
|
15
app/SabrehavenServer/data/talkactions/scripts/looktype.lua
Normal file
15
app/SabrehavenServer/data/talkactions/scripts/looktype.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local lookType = tonumber(param)
|
||||
if lookType >= 0 and lookType ~= 1 and lookType ~= 135 and lookType ~= 411 and lookType ~= 415 and lookType ~= 424 and (lookType <= 160 or lookType >= 192) and lookType ~= 439 and lookType ~= 440 and lookType ~= 468 and lookType ~= 469 and (lookType < 474 or lookType > 485) and lookType ~= 501 and lookType ~= 518 and lookType ~= 519 and lookType ~= 520 and lookType ~= 524 and lookType ~= 525 and lookType ~= 536 and lookType ~= 543 and lookType ~= 549 and lookType ~= 576 and lookType ~= 581 and lookType ~= 582 and lookType ~= 597 and lookType ~= 616 and lookType ~= 623 and lookType ~= 625 and (lookType <= 637 or lookType >= 644) and (lookType <= 644 or lookType >= 647) and (lookType <= 651 or lookType >= 664) and lookType <= 699 then
|
||||
local playerOutfit = player:getOutfit()
|
||||
playerOutfit.lookType = lookType
|
||||
player:setOutfit(playerOutfit)
|
||||
else
|
||||
player:sendCancelMessage("A look type with that id does not exist.")
|
||||
end
|
||||
return false
|
||||
end
|
33
app/SabrehavenServer/data/talkactions/scripts/loot_test.lua
Normal file
33
app/SabrehavenServer/data/talkactions/scripts/loot_test.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
local config = {
|
||||
['exp'] = {skillKey = 17585, timeKey = 17589},
|
||||
['skill'] = {skillKey = 17586, timeKey = 17590},
|
||||
['magic'] = {skillKey = 17587, timeKey = 17591},
|
||||
['loot'] = {skillKey = 17588, timeKey = 17592} -- TODO
|
||||
}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local i = 0
|
||||
local function generateMonsterLoad()
|
||||
if (i <= 1000) then
|
||||
Game.createMonster("cyclops", {x = 32316, y = 31942, z = 7})
|
||||
local monster = Game.isMonsterThere({x = 32316, y = 31942, z = 7}, "cyclops")
|
||||
monster:addHealth(-monster:getMaxHealth())
|
||||
addEvent(generateMonsterLoad, 1000)
|
||||
i = i + 1
|
||||
print(i)
|
||||
end
|
||||
end
|
||||
|
||||
addEvent(generateMonsterLoad, 1000)
|
||||
|
||||
return false
|
||||
end
|
||||
|
@@ -0,0 +1,8 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
player:getPosition():sendMagicEffect(tonumber(param))
|
||||
return false
|
||||
end
|
40
app/SabrehavenServer/data/talkactions/scripts/mccheck.lua
Normal file
40
app/SabrehavenServer/data/talkactions/scripts/mccheck.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Multiclient Check List:")
|
||||
|
||||
local ipList = {}
|
||||
local players = Game.getPlayers()
|
||||
for i = 1, #players do
|
||||
local tmpPlayer = players[i]
|
||||
local ip = tmpPlayer:getIp()
|
||||
if ip ~= 0 then
|
||||
local list = ipList[ip]
|
||||
if not list then
|
||||
ipList[ip] = {}
|
||||
list = ipList[ip]
|
||||
end
|
||||
list[#list + 1] = tmpPlayer
|
||||
end
|
||||
end
|
||||
|
||||
for ip, list in pairs(ipList) do
|
||||
local listLength = #list
|
||||
if listLength > 1 then
|
||||
local tmpPlayer = list[1]
|
||||
local message = ("%s: %s [%d]"):format(Game.convertIpToString(ip), tmpPlayer:getName(), tmpPlayer:getLevel())
|
||||
for i = 2, listLength do
|
||||
tmpPlayer = list[i]
|
||||
message = ("%s, %s [%d]"):format(message, tmpPlayer:getName(), tmpPlayer:getLevel())
|
||||
end
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, message .. ".")
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
114
app/SabrehavenServer/data/talkactions/scripts/minimap_scan.lua
Normal file
114
app/SabrehavenServer/data/talkactions/scripts/minimap_scan.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
local distanceBetweenPositionsX = 8
|
||||
local distanceBetweenPositionsY = 8
|
||||
local addEventDelay = 500
|
||||
local teleportsPerEvent = 1
|
||||
local maxEventExecutionTime = 2000
|
||||
|
||||
local function teleportToClosestPosition(player, x, y, z)
|
||||
-- direct to position
|
||||
local tile = Tile(x, y, z)
|
||||
|
||||
if not tile or not tile:getGround() or tile:hasFlag(TILESTATE_TELEPORT) or not player:teleportTo(tile:getPosition()) then
|
||||
for distance = 1, 3 do
|
||||
-- try to find some close tile
|
||||
for changeX = -distance, distance, distance do
|
||||
for changeY = -distance, distance, distance do
|
||||
tile = Tile(x + changeX, y + changeY, z)
|
||||
if tile and tile:getGround() and not tile:hasFlag(TILESTATE_TELEPORT) and player:teleportTo(tile:getPosition()) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function sendScanProgress(player, minX, maxX, minY, maxY, x, y, z, lastProgress)
|
||||
local progress = math.floor(((y - minY + (((x - minX) / (maxX - minX)) * distanceBetweenPositionsY)) / (maxY - minY)) * 100)
|
||||
if progress ~= lastProgress then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Scan progress: ~' .. progress .. '%')
|
||||
end
|
||||
|
||||
return progress
|
||||
end
|
||||
|
||||
local function minimapScan(cid, minX, maxX, minY, maxY, x, y, z, lastProgress)
|
||||
local player = Player(cid)
|
||||
|
||||
if not player then
|
||||
--print('Minimap scan stopped - player logged out', cid, minX, maxX, minY, maxY, x, y, z)
|
||||
return
|
||||
end
|
||||
|
||||
local scanStartTime = os.mtime()
|
||||
local teleportsDone = 0
|
||||
while true do
|
||||
if scanStartTime + maxEventExecutionTime < os.mtime() then
|
||||
lastProgress = sendScanProgress(player, minX, maxX, minY, maxY, x, y, z, lastProgress)
|
||||
addEvent(minimapScan, addEventDelay, cid, minX, maxX, minY, maxY, x, y, z, lastProgress)
|
||||
break
|
||||
end
|
||||
|
||||
x = x + distanceBetweenPositionsX
|
||||
if x > maxX then
|
||||
x = minX
|
||||
y = y + distanceBetweenPositionsY
|
||||
if y > maxY then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Scan finished: ' .. os.time())
|
||||
--print('Minimap scan complete', player:getName(), minX, maxX, minY, maxY, x, y, z)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if teleportToClosestPosition(player, x, y, z) then
|
||||
teleportsDone = teleportsDone + 1
|
||||
lastProgress = sendScanProgress(player, minX, maxX, minY, maxY, x, y, z, lastProgress)
|
||||
|
||||
--print('Minimap scan teleport', player:getName(), minX, maxX, minY, maxY, x, y, z, progress, teleportsDone)
|
||||
if teleportsDone == teleportsPerEvent then
|
||||
addEvent(minimapScan, addEventDelay, cid, minX, maxX, minY, maxY, x, y, z, progress)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function minimapStart(player, minX, maxX, minY, maxY, x, y, z)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Scan started: ' .. os.time())
|
||||
--print('Minimap scan start', player:getName(), minX, maxX, minY, maxY, x, y, z)
|
||||
minimapScan(player:getId(), minX, maxX, minY, maxY, minX - 5, minY, z)
|
||||
end
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local positions = param:split(',')
|
||||
if #positions ~= 5 then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Command requires 5 parameters: /minimap minX, maxX, minY, maxY, z')
|
||||
return false
|
||||
end
|
||||
|
||||
for key, position in pairs(positions) do
|
||||
local value = tonumber(position)
|
||||
|
||||
if not value then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Invalid parameter ' .. key .. ': ' .. position)
|
||||
return false
|
||||
end
|
||||
|
||||
positions[key] = value
|
||||
end
|
||||
|
||||
minimapStart(player, positions[1], positions[2], positions[3], positions[4], positions[1] - distanceBetweenPositionsX, positions[3], positions[5])
|
||||
return false
|
||||
end
|
31
app/SabrehavenServer/data/talkactions/scripts/online.lua
Normal file
31
app/SabrehavenServer/data/talkactions/scripts/online.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
local maxPlayersPerMessage = 10
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local hasAccess = player:getGroup():getAccess()
|
||||
local players = Game.getPlayers()
|
||||
local onlineList = {}
|
||||
|
||||
for _, targetPlayer in ipairs(players) do
|
||||
if hasAccess or not targetPlayer:isInGhostMode() then
|
||||
table.insert(onlineList, ("%s [%d]"):format(targetPlayer:getName(), targetPlayer:getLevel()))
|
||||
end
|
||||
end
|
||||
|
||||
local playersOnline = #onlineList
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, ("%d players online."):format(playersOnline))
|
||||
|
||||
for i = 1, playersOnline, maxPlayersPerMessage do
|
||||
local j = math.min(i + maxPlayersPerMessage - 1, playersOnline)
|
||||
local msg = table.concat(onlineList, ", ", i, j) .. "."
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
|
||||
end
|
||||
return false
|
||||
end
|
13
app/SabrehavenServer/data/talkactions/scripts/openserver.lua
Normal file
13
app/SabrehavenServer/data/talkactions/scripts/openserver.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
Game.setGameState(GAME_STATE_NORMAL)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server is now open.")
|
||||
return false
|
||||
end
|
30
app/SabrehavenServer/data/talkactions/scripts/owner.lua
Normal file
30
app/SabrehavenServer/data/talkactions/scripts/owner.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local tile = Tile(player:getPosition())
|
||||
local house = tile and tile:getHouse()
|
||||
if house == nil then
|
||||
player:sendCancelMessage("You are not inside a house.")
|
||||
return false
|
||||
end
|
||||
|
||||
if param == "" or param == "none" then
|
||||
house:setOwnerGuid(0)
|
||||
return false
|
||||
end
|
||||
|
||||
local targetPlayer = Player(param)
|
||||
if targetPlayer == nil then
|
||||
player:sendCancelMessage("Player not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
house:setOwnerGuid(targetPlayer:getGuid())
|
||||
return false
|
||||
end
|
@@ -0,0 +1,308 @@
|
||||
local weaponSkillsConfig = {
|
||||
[WEAPON_SWORD] = SKILL_SWORD,
|
||||
[WEAPON_CLUB] = SKILL_CLUB,
|
||||
[WEAPON_AXE] = SKILL_AXE,
|
||||
[WEAPON_DISTANCE] = SKILL_DISTANCE
|
||||
}
|
||||
|
||||
local skillNameConfig = {
|
||||
[SKILL_SWORD] = "Sword Fighting",
|
||||
[SKILL_CLUB] = "Club Fighting",
|
||||
[SKILL_AXE] = "Axe Fighting",
|
||||
[SKILL_DISTANCE] = "Distance Fighting",
|
||||
[SKILL_FIST] = "Fist Fighting"
|
||||
}
|
||||
|
||||
local function ltrim(s)
|
||||
if s == nil then
|
||||
return s
|
||||
end
|
||||
|
||||
return s:match'^%s*(.*)'
|
||||
end
|
||||
|
||||
local function getWeapon(player)
|
||||
local itemLeft = player:getSlotItem(CONST_SLOT_LEFT)
|
||||
if itemLeft and itemLeft:getType():getWeaponType() ~= WEAPON_NONE and itemLeft:getType():getWeaponType() ~= WEAPON_SHIELD and itemLeft:getType():getWeaponType() ~= WEAPON_AMMO and itemLeft:getType():getWeaponType() ~= WEAPON_WAND then
|
||||
return itemLeft:getType()
|
||||
end
|
||||
|
||||
local itemRight = player:getSlotItem(CONST_SLOT_RIGHT)
|
||||
if itemRight and itemRight:getType():getWeaponType() ~= WEAPON_NONE and itemRight:getType():getWeaponType() ~= WEAPON_SHIELD and itemRight:getType():getWeaponType() ~= WEAPON_AMMO and itemRight:getType():getWeaponType() ~= WEAPON_WAND then
|
||||
return itemRight:getType()
|
||||
end
|
||||
end
|
||||
|
||||
local function getAmmunition(player)
|
||||
local item = player:getSlotItem(CONST_SLOT_AMMO)
|
||||
if item and item:getType():getWeaponType() == WEAPON_AMMO then
|
||||
return item:getType()
|
||||
end
|
||||
end
|
||||
|
||||
local function getAttack(weapon, ammunition)
|
||||
local attack = 7
|
||||
if weapon ~= nil then
|
||||
attack = weapon:getAttack()
|
||||
if weapon:getWeaponType() == WEAPON_DISTANCE and weapon:getAmmoType() ~= 0 then
|
||||
if ammunition ~= nil and ammunition:getAmmoType() == weapon:getAmmoType() then
|
||||
attack = attack + ammunition:getAttack()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return attack
|
||||
end
|
||||
|
||||
local function getDamageFormula(attack, attackSkill, fightMode)
|
||||
local damage = attack
|
||||
if fightMode == FIGHTMODE_ATTACK then
|
||||
damage = math.floor(damage + 2 * damage / 10)
|
||||
elseif fightMode == FIGHTMODE_DEFENSE then
|
||||
damage = math.floor(damage - 4 * damage / 10)
|
||||
end
|
||||
|
||||
local formula = math.floor((5 * (attackSkill) + 50) * damage)
|
||||
return formula
|
||||
end
|
||||
|
||||
local function getDamage(attack, attackSkill, fightMode, random1, random2)
|
||||
local formula = getDamageFormula(attack, attackSkill, fightMode)
|
||||
local randResult = math.floor(random1 % 100);
|
||||
local damage = -math.floor((math.ceil(formula * ((random2 % 100 + randResult) / 2) / 10000.)));
|
||||
return damage
|
||||
end
|
||||
|
||||
local function setVocationDamageIncrease(vocationId, damage)
|
||||
if vocationId == 4 or vocationId == 8 then
|
||||
local knightCloseAttackDamageIncreasePercent = configManager.getNumber(configKeys.KNIGHT_CLOSE_ATTACK_DAMAGE_INCREASE_PERCENT)
|
||||
if knightCloseAttackDamageIncreasePercent ~= -1 then
|
||||
damage = math.floor(damage + damage * knightCloseAttackDamageIncreasePercent / 100);
|
||||
end
|
||||
elseif vocationId == 3 or vocationId == 7 then
|
||||
local paladinRangeAttackDamageIncreasePercent = configManager.getNumber(configKeys.PALADIN_RANGE_ATTACK_DAMAGE_INCREASE_PERCENT)
|
||||
if paladinRangeAttackDamageIncreasePercent ~= -1 then
|
||||
damage = math.floor(damage + damage * paladinRangeAttackDamageIncreasePercent / 100);
|
||||
end
|
||||
end
|
||||
|
||||
return damage
|
||||
end
|
||||
|
||||
local function getDefense(creature, random1, random2)
|
||||
local totalDefense = creature:getType():getDefense() + 1
|
||||
local defenseSkill = creature:getType():getSkill()
|
||||
local formula = math.floor((5 * (defenseSkill) + 50) * totalDefense)
|
||||
local randresult = math.floor(random1 % 100)
|
||||
|
||||
return math.floor(formula * ((random2 % 100 + randresult) / 2) / 10000.)
|
||||
end
|
||||
|
||||
local function rshift(x, by)
|
||||
return math.floor(x / 2 ^ by)
|
||||
end
|
||||
|
||||
local function getArmor(creature, rand)
|
||||
local armor = creature:getType():getArmor()
|
||||
if armor > 1 then
|
||||
return rand % rshift(armor, 1) + rshift(armor, 1);
|
||||
end
|
||||
|
||||
return armor
|
||||
end
|
||||
|
||||
local function setPhysicalDamageBlock(creature, isCloseRange, damage, random1, random2, randomArmor)
|
||||
if bit.band(creature:getType():getCombatImmunities(), COMBAT_PHYSICALDAMAGE) == COMBAT_PHYSICALDAMAGE then
|
||||
return 0
|
||||
end
|
||||
|
||||
if isCloseRange then
|
||||
damage = damage + getDefense(creature, random1, random2)
|
||||
end
|
||||
|
||||
if damage >= 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
if damage < 0 then
|
||||
damage = damage + getArmor(creature, randomArmor)
|
||||
if damage >= 0 then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return damage
|
||||
end
|
||||
|
||||
local function isThrowableHit(weapon, ammunition, skillValue, rand)
|
||||
local distance = 75 -- we consider distance is always the best
|
||||
local hitChance = 75 -- throwables and such
|
||||
|
||||
if weapon:getAmmoType() ~= 0 then
|
||||
hitChance = 90 -- bows and crossbows
|
||||
if ammunition == nil or ammunition:getAmmoType() ~= weapon:getAmmoType() then
|
||||
hitChance = -1 -- no ammo or invalid ammo
|
||||
end
|
||||
end
|
||||
|
||||
if rand % distance <= skillValue then
|
||||
return rand % 100 <= hitChance
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function getTotalDamage(creature, weapon, ammunition, vocation, attack, skillValue, fightMode)
|
||||
local damage = setVocationDamageIncrease(vocation:getId(), getDamage(attack, skillValue, fightMode, os.rand(), os.rand()))
|
||||
local minDamage = setVocationDamageIncrease(vocation:getId(), getDamage(attack, skillValue, fightMode, 0, 0))
|
||||
local maxDamage = setVocationDamageIncrease(vocation:getId(), getDamage(attack, skillValue, fightMode, 99, 99))
|
||||
|
||||
if weapon ~= nil and weapon:getWeaponType() == WEAPON_DISTANCE then
|
||||
if isThrowableHit(weapon, ammunition, skillValue, os.rand()) then
|
||||
damage = setPhysicalDamageBlock(creature, false, damage, os.rand(), os.rand(), os.rand())
|
||||
else
|
||||
damage = 0
|
||||
end
|
||||
minDamage = 0
|
||||
if isThrowableHit(weapon, ammunition, skillValue, 0) then
|
||||
maxDamage = setPhysicalDamageBlock(creature, false, maxDamage, 0, 0, 0)
|
||||
else
|
||||
maxDamage = 0
|
||||
end
|
||||
else
|
||||
damage = setPhysicalDamageBlock(creature, true, damage, os.rand(), os.rand(), os.rand())
|
||||
minDamage = setPhysicalDamageBlock(creature, true, minDamage, 99, 99, rshift(creature:getType():getArmor(), 1) + 1)
|
||||
maxDamage = setPhysicalDamageBlock(creature, true, maxDamage, 0, 0, 0)
|
||||
end
|
||||
|
||||
local container = {}
|
||||
container[0] = damage
|
||||
container[1] = minDamage
|
||||
container[2] = maxDamage
|
||||
return container
|
||||
end
|
||||
|
||||
function onSay(player, words, param)
|
||||
local split = param:split(",")
|
||||
local creatureName = ltrim(split[1])
|
||||
local skillValueNumber = ltrim(split[2])
|
||||
local vocationName = ltrim(split[3])
|
||||
local weaponName = ltrim(split[4])
|
||||
local ammunitionName = ltrim(split[5])
|
||||
|
||||
local creature = Creature("Troll")
|
||||
if creatureName ~= nil then
|
||||
creature = Creature(creatureName)
|
||||
if creature == nil then
|
||||
player:sendCancelMessage("The monster does not exist.")
|
||||
return false
|
||||
end
|
||||
else
|
||||
creatureName = creature:getName()
|
||||
end
|
||||
|
||||
local weapon = getWeapon(player)
|
||||
if weaponName ~= nil then
|
||||
weapon = ItemType(weaponName)
|
||||
if weapon == nil or weapon:getWeaponType() == WEAPON_NONE or weapon:getWeaponType() == WEAPON_SHIELD or weapon:getWeaponType() == WEAPON_AMMO or weapon:getWeaponType() == WEAPON_WAND then
|
||||
player:sendCancelMessage("The weapon does not exist.")
|
||||
return false
|
||||
end
|
||||
else
|
||||
if weapon ~= nil then
|
||||
weaponName = weapon:getName()
|
||||
end
|
||||
end
|
||||
|
||||
local ammunition = getAmmunition(player)
|
||||
if ammunitionName ~= nil then
|
||||
ammunition = ItemType(ammunitionName)
|
||||
if ammunition == nil or ammunition:getWeaponType() ~= WEAPON_AMMO then
|
||||
player:sendCancelMessage("The ammunition does not exist.")
|
||||
return false
|
||||
end
|
||||
else
|
||||
if ammunition ~= nil then
|
||||
ammunitionName = ammunition:getName()
|
||||
end
|
||||
end
|
||||
|
||||
local skillType = SKILL_FIST
|
||||
local attack = getAttack(weapon, ammunition)
|
||||
if weapon ~= nil then
|
||||
skillType = weaponSkillsConfig[weapon:getWeaponType()]
|
||||
end
|
||||
|
||||
local skillValue = player:getSkillLevel(skillType)
|
||||
if skillValueNumber ~= nil then
|
||||
if tonumber(skillValueNumber) > 0 then
|
||||
if tonumber(skillValueNumber) <= 300 then
|
||||
skillValue = tonumber(skillValueNumber)
|
||||
else
|
||||
player:sendCancelMessage("The skill value has to be no bigger than 300.")
|
||||
return false
|
||||
end
|
||||
else
|
||||
player:sendCancelMessage("The skill value has to be a number and greater than zero.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local vocation = player:getVocation()
|
||||
if vocationName ~= nil then
|
||||
vocation = Vocation(vocationName)
|
||||
if vocation == nil then
|
||||
player:sendCancelMessage("The vocation does not exist.")
|
||||
return false
|
||||
end
|
||||
else
|
||||
vocationName = vocation:getName()
|
||||
end
|
||||
|
||||
local commandStr = "Executing command: !physicaldamage " .. creatureName .. ", " .. skillValue .. ", " .. vocationName .. ""
|
||||
|
||||
if weapon ~= nil then
|
||||
commandStr = commandStr .. ", " .. weaponName
|
||||
end
|
||||
|
||||
if ammunition ~= nil and weapon ~= nil and weapon:getWeaponType() == WEAPON_DISTANCE then
|
||||
commandStr = commandStr .. ", " .. ammunitionName
|
||||
end
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, commandStr)
|
||||
|
||||
local offensiveDamageContainer = getTotalDamage(creature, weapon, ammunition, vocation, attack, skillValue, FIGHTMODE_ATTACK)
|
||||
local balancedDamageContainer = getTotalDamage(creature, weapon, ammunition, vocation, attack, skillValue, FIGHTMODE_BALANCED)
|
||||
local defensiveDamageContainer = getTotalDamage(creature, weapon, ammunition, vocation, attack, skillValue, FIGHTMODE_DEFENSE)
|
||||
|
||||
local message = ""
|
||||
message = message .. "Vocation: " .. vocation:getName() .. "\n"
|
||||
message = message .. "Skill Name: " .. skillNameConfig[skillType] .. ", Skill Value: " .. skillValue .. "\n"
|
||||
message = message .. "Weapon: " .. (weaponName or 'none') .. " (atk: " .. attack .. ")\n"
|
||||
message = message .. "Creature: " .. creatureName .. " (arm: " .. creature:getType():getArmor() .. ", def: " .. creature:getType():getDefense() .. ", skill: " .. creature:getType():getSkill() .. ")\n"
|
||||
message = message .. "\nOffensive Fighting Damage\n"
|
||||
message = message .. "Min: " .. offensiveDamageContainer[1] .. ", Max: " .. offensiveDamageContainer[2] .. "\n"
|
||||
message = message .. "\nBalanced Fighting Damage\n"
|
||||
message = message .. "Min: " .. balancedDamageContainer[1] .. ", Max: " .. balancedDamageContainer[2] .. "\n"
|
||||
message = message .. "\nDefensive Fighting Damage\n"
|
||||
message = message .. "Min: " .. defensiveDamageContainer[1] .. ", Max: " .. defensiveDamageContainer[2] .. "\n"
|
||||
|
||||
message = message .. "\nFirst 100 Hits Damage Simulator in Offensive Fighting\n"
|
||||
local creatureHealth = creature:getType():getMaxHealth()
|
||||
local creatureHitsTillDeath = 1
|
||||
for i=1,100 do
|
||||
local damageContainer = getTotalDamage(creature, weapon, ammunition, vocation, attack, skillValue, FIGHTMODE_ATTACK)
|
||||
message = message .. "Hit: " .. i .. ", Damage: " .. damageContainer[0] .. "\n"
|
||||
creatureHealth = creatureHealth + damageContainer[0]
|
||||
if creatureHealth > 0 then
|
||||
creatureHitsTillDeath = creatureHitsTillDeath + 1
|
||||
end
|
||||
end
|
||||
|
||||
if creatureHealth <= 0 then
|
||||
message = message .. "\nIt would take you approximately " .. creatureHitsTillDeath .. " hits to slain " .. creature:getName() .. ".\n"
|
||||
else
|
||||
message = message .. "\nIt would take you more than 100 hits to slain " .. creature:getName() .. ".\n"
|
||||
end
|
||||
player:showTextDialog(weapon and weapon:getId() or 2950, message, false)
|
||||
return false
|
||||
end
|
@@ -0,0 +1,20 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
local monster = Game.createMonster(param, position)
|
||||
if monster ~= nil then
|
||||
monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
position:sendMagicEffect(CONST_ME_MAGIC_RED)
|
||||
else
|
||||
player:sendCancelMessage("There is not enough room.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
return false
|
||||
end
|
20
app/SabrehavenServer/data/talkactions/scripts/place_npc.lua
Normal file
20
app/SabrehavenServer/data/talkactions/scripts/place_npc.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
local npc = Game.createNpc(param, position)
|
||||
if npc ~= nil then
|
||||
npc:setMasterPos(position)
|
||||
position:sendMagicEffect(CONST_ME_MAGIC_RED)
|
||||
else
|
||||
player:sendCancelMessage("There is not enough room.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,20 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
local monster = Game.createMonster(param, position)
|
||||
if monster ~= nil then
|
||||
monster:setMaster(player)
|
||||
position:sendMagicEffect(CONST_ME_MAGIC_RED)
|
||||
else
|
||||
player:sendCancelMessage("There is not enough room.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
end
|
||||
return false
|
||||
end
|
10
app/SabrehavenServer/data/talkactions/scripts/position.lua
Normal file
10
app/SabrehavenServer/data/talkactions/scripts/position.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
function onSay(player, words, param)
|
||||
if player:getGroup():getAccess() and param ~= "" then
|
||||
local split = param:split(",")
|
||||
player:teleportTo(Position(split[1], split[2], split[3]))
|
||||
else
|
||||
local position = player:getPosition()
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your current position is: " .. position.x .. ", " .. position.y .. ", " .. position.z .. ".")
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,34 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local searchItemId = tonumber(param)
|
||||
|
||||
for _, house in pairs(Game.getHouses()) do
|
||||
for _, tile in pairs(house:getTiles()) do
|
||||
for _, item in pairs(tile:getItems()) do
|
||||
if item ~= nil then
|
||||
local isFound = false
|
||||
if item:isContainer() then
|
||||
local items = item:getItemsById(searchItemId)
|
||||
isFound = #items > 0
|
||||
else
|
||||
isFound = item:getId() == searchItemId
|
||||
end
|
||||
|
||||
if isFound then
|
||||
local position = item:getPosition()
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Item position is: " .. position.x .. ", " .. position.y .. ", " .. position.z .. ".")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
13
app/SabrehavenServer/data/talkactions/scripts/raid.lua
Normal file
13
app/SabrehavenServer/data/talkactions/scripts/raid.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
Game.startRaid(param)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Raid with name " .. param .. " started.")
|
||||
return false
|
||||
end
|
68
app/SabrehavenServer/data/talkactions/scripts/reload.lua
Normal file
68
app/SabrehavenServer/data/talkactions/scripts/reload.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
local reloadTypes = {
|
||||
["all"] = { targetType = RELOAD_TYPE_ALL, name = "all" },
|
||||
|
||||
["action"] = { targetType = RELOAD_TYPE_ACTIONS, name = "actions" },
|
||||
["actions"] = { targetType = RELOAD_TYPE_ACTIONS, name = "actions" },
|
||||
|
||||
["chat"] = { targetType = RELOAD_TYPE_CHAT, name = "chatchannels" },
|
||||
["channel"] = { targetType = RELOAD_TYPE_CHAT, name = "chatchannels" },
|
||||
["chatchannels"] = { targetType = RELOAD_TYPE_CHAT, name = "chatchannels" },
|
||||
|
||||
["config"] = { targetType = RELOAD_TYPE_CONFIG, name = "config" },
|
||||
["configuration"] = { targetType = RELOAD_TYPE_CONFIG, name = "config" },
|
||||
|
||||
["creaturescript"] = { targetType = RELOAD_TYPE_CREATURESCRIPTS, name = "creature scripts" },
|
||||
["creaturescripts"] = { targetType = RELOAD_TYPE_CREATURESCRIPTS, name = "creature scripts" },
|
||||
|
||||
["events"] = { targetType = RELOAD_TYPE_EVENTS, name = "events" },
|
||||
|
||||
["global"] = { targetType = RELOAD_TYPE_GLOBAL, name = "global.lua" },
|
||||
|
||||
["globalevent"] = { targetType = RELOAD_TYPE_GLOBALEVENTS, name = "globalevents" },
|
||||
["globalevents"] = { targetType = RELOAD_TYPE_GLOBALEVENTS, name = "globalevents" },
|
||||
|
||||
["items"] = { targetType = RELOAD_TYPE_ITEMS, name = "items" },
|
||||
|
||||
["monster"] = { targetType = RELOAD_TYPE_MONSTERS, name = "monsters" },
|
||||
["monsters"] = { targetType = RELOAD_TYPE_MONSTERS, name = "monsters" },
|
||||
|
||||
["move"] = { targetType = RELOAD_TYPE_MOVEMENTS, name = "movements" },
|
||||
["movement"] = { targetType = RELOAD_TYPE_MOVEMENTS, name = "movements" },
|
||||
["movements"] = { targetType = RELOAD_TYPE_MOVEMENTS, name = "movements" },
|
||||
|
||||
["npc"] = { targetType = RELOAD_TYPE_NPCS, name = "npcs" },
|
||||
["npcs"] = { targetType = RELOAD_TYPE_NPCS, name = "npcs" },
|
||||
|
||||
["quest"] = { targetType = RELOAD_TYPE_QUESTS, name = "quests" },
|
||||
["quests"] = { targetType = RELOAD_TYPE_QUESTS, name = "quests" },
|
||||
|
||||
["raid"] = { targetType = RELOAD_TYPE_RAIDS, name = "raids" },
|
||||
["raids"] = { targetType = RELOAD_TYPE_RAIDS, name = "raids" },
|
||||
|
||||
["spell"] = { targetType = RELOAD_TYPE_SPELLS, name = "spells" },
|
||||
["spells"] = { targetType = RELOAD_TYPE_SPELLS, name = "spells" },
|
||||
|
||||
["talk"] = { targetType = RELOAD_TYPE_TALKACTIONS, name = "talk actions" },
|
||||
["talkaction"] = { targetType = RELOAD_TYPE_TALKACTIONS, name = "talk actions" },
|
||||
["talkactions"] = { targetType = RELOAD_TYPE_TALKACTIONS, name = "talk actions" }
|
||||
}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GAMEMASTER then
|
||||
return false
|
||||
end
|
||||
|
||||
local reloadType = reloadTypes[param and param:lower()]
|
||||
if not reloadType then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reload type not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
Game.reload(reloadType.targetType)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, string.format("Reloaded %s.", reloadType.name))
|
||||
return true
|
||||
end
|
@@ -0,0 +1,22 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
local tile = Tile(position)
|
||||
local house = tile and tile:getHouse()
|
||||
if house == nil then
|
||||
player:sendCancelMessage("You are not inside a house.")
|
||||
position:sendMagicEffect(CONST_ME_POFF)
|
||||
return false
|
||||
end
|
||||
|
||||
house:setOwnerGuid(0)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully removed this house.")
|
||||
return false
|
||||
end
|
@@ -0,0 +1,27 @@
|
||||
function onSay(player, words, param)
|
||||
if player:getAccountType() <= ACCOUNT_TYPE_TUTOR then
|
||||
return true
|
||||
end
|
||||
|
||||
local resultId = db.storeQuery("SELECT `name`, `account_id`, (SELECT `type` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `account_type` FROM `players` WHERE `name` = " .. db.escapeString(param))
|
||||
if resultId == false then
|
||||
player:sendCancelMessage("A player with that name does not exist.")
|
||||
return false
|
||||
end
|
||||
|
||||
if result.getDataInt(resultId, "account_type") ~= ACCOUNT_TYPE_TUTOR then
|
||||
player:sendCancelMessage("You can only demote a tutor to a normal player.")
|
||||
return false
|
||||
end
|
||||
|
||||
local target = Player(param)
|
||||
if target ~= nil then
|
||||
target:setAccountType(ACCOUNT_TYPE_NORMAL)
|
||||
else
|
||||
db.query("UPDATE `accounts` SET `type` = " .. ACCOUNT_TYPE_NORMAL .. " WHERE `id` = " .. result.getDataInt(resultId, "account_id"))
|
||||
end
|
||||
|
||||
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have demoted " .. result.getDataString(resultId, "name") .. " to a normal player.")
|
||||
result.free(resultId)
|
||||
return false
|
||||
end
|
@@ -0,0 +1,33 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
position:getNextPosition(player:getDirection())
|
||||
|
||||
local tile = Tile(position)
|
||||
if not tile then
|
||||
player:sendCancelMessage("Object not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
local thing = tile:getTopVisibleThing(player)
|
||||
if not thing then
|
||||
player:sendCancelMessage("Thing not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
if thing:isCreature() then
|
||||
thing:remove()
|
||||
elseif thing:isItem() then
|
||||
if thing == tile:getGround() then
|
||||
player:sendCancelMessage("You may not remove a ground tile.")
|
||||
return false
|
||||
end
|
||||
thing:remove(tonumber(param) or -1)
|
||||
end
|
||||
|
||||
position:sendMagicEffect(CONST_ME_MAGIC_RED)
|
||||
return false
|
||||
end
|
23
app/SabrehavenServer/data/talkactions/scripts/save.lua
Normal file
23
app/SabrehavenServer/data/talkactions/scripts/save.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
function onSay(player, words, param)
|
||||
|
||||
local function timeSave(delay, msg)
|
||||
broadcastMessage(msg, MESSAGE_STATUS_WARNING)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
|
||||
addEvent(saveServer, delay)
|
||||
end
|
||||
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
if isNumber(param) then
|
||||
local delay = tonumber(param) * 1000
|
||||
timeSave(delay, "Saving server in " .. tonumber(param) .. " seconds.")
|
||||
else
|
||||
saveServer()
|
||||
end
|
||||
end
|
19
app/SabrehavenServer/data/talkactions/scripts/sellhouse.lua
Normal file
19
app/SabrehavenServer/data/talkactions/scripts/sellhouse.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
function onSay(player, words, param)
|
||||
local tradePartner = Player(param)
|
||||
if not tradePartner or tradePartner == player then
|
||||
player:sendCancelMessage("Trade player not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
local house = player:getTile():getHouse()
|
||||
if not house then
|
||||
player:sendCancelMessage("You must stand in your house to initiate the trade.")
|
||||
return false
|
||||
end
|
||||
|
||||
local returnValue = house:startTrade(player, tradePartner)
|
||||
if returnValue ~= RETURNVALUE_NOERROR then
|
||||
player:sendCancelMessage(returnValue)
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,279 @@
|
||||
local area = {
|
||||
fromPos = {x = 33140, y = 32859, z = 7},
|
||||
toPos = {x = 33155, y = 32874, z = 4}
|
||||
}
|
||||
|
||||
local availablePlayerTeleportPositions = {
|
||||
Position(33139, 32859, 7),
|
||||
Position(33139, 32860, 7),
|
||||
Position(33139, 32861, 7),
|
||||
Position(33139, 32862, 7),
|
||||
Position(33139, 32863, 7),
|
||||
Position(33139, 32864, 7),
|
||||
Position(33139, 32865, 7),
|
||||
Position(33139, 32866, 7),
|
||||
Position(33139, 32867, 7),
|
||||
Position(33139, 32868, 7),
|
||||
Position(33139, 32869, 7),
|
||||
Position(33139, 32870, 7),
|
||||
Position(33139, 32871, 7),
|
||||
Position(33139, 32872, 7),
|
||||
Position(33139, 32873, 7),
|
||||
Position(33139, 32874, 7),
|
||||
Position(33139, 32875, 7),
|
||||
Position(33140, 32875, 7),
|
||||
Position(33143, 32875, 7),
|
||||
Position(33144, 32875, 7),
|
||||
Position(33146, 32875, 7),
|
||||
Position(33148, 32875, 7),
|
||||
Position(33149, 32875, 7),
|
||||
Position(33150, 32875, 7),
|
||||
Position(33155, 32875, 7),
|
||||
Position(33156, 32875, 7),
|
||||
Position(33156, 32874, 7),
|
||||
Position(33156, 32873, 7),
|
||||
Position(33156, 32872, 7),
|
||||
Position(33156, 32871, 7),
|
||||
Position(33156, 32870, 7),
|
||||
Position(33156, 32869, 7),
|
||||
Position(33156, 32868, 7),
|
||||
Position(33156, 32867, 7),
|
||||
Position(33156, 32866, 7),
|
||||
Position(33156, 32865, 7),
|
||||
Position(33156, 32864, 7),
|
||||
Position(33156, 32863, 7),
|
||||
Position(33156, 32862, 7),
|
||||
Position(33156, 32861, 7),
|
||||
Position(33156, 32860, 7),
|
||||
Position(33156, 32859, 7),
|
||||
Position(33156, 32858, 7)
|
||||
}
|
||||
|
||||
local downstairsIds = {451, 466, 465, 467}
|
||||
|
||||
local earthquakeEffects = {CONST_ME_POFF, CONST_ME_EXPLOSIONHIT, CONST_ME_EXPLOSIONAREA, CONST_ME_FIREAREA, CONST_ME_ENERGYHIT, CONST_ME_BLOCKHIT}
|
||||
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
if player:getAccountType() < ACCOUNT_TYPE_GOD then
|
||||
return false
|
||||
end
|
||||
|
||||
teleportPlayersToSerpentineTower()
|
||||
addEvent(wave1, 20000)
|
||||
addEvent(wave2, 40000)
|
||||
addEvent(wave3, 100000)
|
||||
addEvent(wave4, 160000)
|
||||
addEvent(wave5, 170000)
|
||||
addEvent(wave6, 175000)
|
||||
addEvent(wave7, 180000)
|
||||
addEvent(wave8, 195000)
|
||||
addEvent(wave9, 205000)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function teleportPlayersToSerpentineTower()
|
||||
for _, player in ipairs(Game.getPlayers()) do
|
||||
player:setStorageValue(17596, 1)
|
||||
local teleportPosition = availablePlayerTeleportPositions[math.random(#availablePlayerTeleportPositions)]
|
||||
player:teleportTo(teleportPosition)
|
||||
player:getPosition():sendMonsterSay("accersi " .. player:getName())
|
||||
end
|
||||
end
|
||||
|
||||
function wave1()
|
||||
broadcastMessage("LOOK AT MY EYES! ... THE EYES! ... LET ME OUT! ...", MESSAGE_STATUS_WARNING)
|
||||
earthquakeTower(area.fromPos, area.toPos)
|
||||
end
|
||||
|
||||
function wave2()
|
||||
broadcastMessage("Ankrahmun: The Academy of Magic Arts are reporting that Ankrahmun city is experiencing issues! Please stay safe in the protection zones, NOW!", MESSAGE_STATUS_WARNING)
|
||||
earthquakeTower(area.fromPos, area.toPos)
|
||||
end
|
||||
|
||||
function wave3()
|
||||
broadcastMessage("Ankrahmun: All Tibianus PEOPLE. THIS IS NOT A PRACTICE. Leave our city NOW!", MESSAGE_STATUS_WARNING)
|
||||
earthquakeTower(area.fromPos, area.toPos)
|
||||
end
|
||||
|
||||
function wave4()
|
||||
broadcastMessage("THE EYES ARE EVERYWHERE!", MESSAGE_STATUS_WARNING)
|
||||
earthquakeTower(area.fromPos, area.toPos)
|
||||
end
|
||||
|
||||
function wave5()
|
||||
Position(33149, 32868, 7):sendMonsterSay("accersi Tothdral")
|
||||
local tothdral = Creature("Tothdral")
|
||||
tothdral:teleportTo(Position(33149, 32867, 7))
|
||||
tothdral:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
end
|
||||
|
||||
function wave6()
|
||||
Position(33147, 32870, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33151, 32870, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33151, 32866, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33147, 32866, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
|
||||
local tile = Tile(Position(33149, 32868, 7))
|
||||
if tile then
|
||||
local obelisk = tile:getItemById(2199)
|
||||
if obelisk ~= nil then
|
||||
obelisk:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
|
||||
obelisk:remove()
|
||||
local hole = Game.createItem(5731, 1, tile:getPosition())
|
||||
hole:setAttribute(ITEM_ATTRIBUTE_MOVEMENTID, 17596)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function wave7()
|
||||
Position(33147, 32870, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33151, 32870, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33151, 32866, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33147, 32866, 7):sendMonsterSay("The Serpentine Tower Secret Is Real!")
|
||||
Position(33149, 32868, 7):sendMonsterSay("LET ME OUT!")
|
||||
end
|
||||
|
||||
function wave8()
|
||||
broadcastMessage("Ankrahmun: WE ARE LOST FOREVER!", MESSAGE_STATUS_WARNING)
|
||||
for xx = area.fromPos.x, area.toPos.x do
|
||||
for yy = area.fromPos.y, area.toPos.y do
|
||||
local position = Position(xx, yy, 7)
|
||||
local tile = Tile(position)
|
||||
if tile then
|
||||
local ground = tile:getGround()
|
||||
if ground ~= nil and ground:getId() == 231 then
|
||||
ground:transform(2144)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Game.createItem(2199, 1, Position(33140, 32859, 7))
|
||||
Position(33140, 32859, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33140, 32874, 7))
|
||||
Position(33140, 32874, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33155, 32874, 7))
|
||||
Position(33155, 32874, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33155, 32859, 7))
|
||||
Position(33155, 32859, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33149, 32863, 7))
|
||||
Position(33149, 32863, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33153, 32866, 7))
|
||||
Position(33153, 32866, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33153, 32871, 7))
|
||||
Position(33153, 32871, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33149, 32873, 7))
|
||||
Position(33149, 32873, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33145, 32871, 7))
|
||||
Position(33145, 32871, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
Game.createItem(2199, 1, Position(33145, 32866, 7))
|
||||
Position(33145, 32866, 7):sendMagicEffect(CONST_ME_TELEPORT)
|
||||
end
|
||||
|
||||
function wave9()
|
||||
broadcastMessage("Ankrahmun: PROTEGO MAXIMA!", MESSAGE_STATUS_WARNING)
|
||||
|
||||
for _, player in ipairs(Game.getPlayers()) do
|
||||
player:teleportTo(player:getTown():getTemplePosition())
|
||||
end
|
||||
end
|
||||
|
||||
function earthquakeTower(frompos, topos)
|
||||
for zz = frompos.z, topos.z, -1 do
|
||||
if zz == 6 then
|
||||
topos.x = topos.x + 1
|
||||
topos.y = topos.y + 1
|
||||
end
|
||||
|
||||
for xx = frompos.x, topos.x do
|
||||
for yy = frompos.y, topos.y do
|
||||
local position = Position(xx, yy, zz)
|
||||
removeFloorItems(position)
|
||||
copyHigherFloorItems(position)
|
||||
end
|
||||
end
|
||||
|
||||
if zz == 6 then
|
||||
topos.x = topos.x - 1
|
||||
topos.y = topos.y - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function removeFloorItems(position)
|
||||
local tile = Tile(position)
|
||||
if tile then
|
||||
-- If any creature is in area then teleport it to safe zone to properly work with tile items
|
||||
local creature = tile:getTopCreature()
|
||||
if creature then
|
||||
local teleportPosition = availablePlayerTeleportPositions[math.random(#availablePlayerTeleportPositions)]
|
||||
creature:teleportTo(teleportPosition)
|
||||
creature:getPosition():sendMonsterSay("The Gods Protecting You!")
|
||||
Game.sendMagicEffect(teleportPosition, 11)
|
||||
if creature:isPlayer() then
|
||||
if creature:getStorageValue(17596) ~= 2 then
|
||||
creature:setStorageValue(17596, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local currentFloorItem = tile:getItemByType(0)
|
||||
while currentFloorItem ~= nil do
|
||||
currentFloorItem:remove()
|
||||
currentFloorItem = tile:getItemByType(0)
|
||||
end
|
||||
|
||||
local items = tile:getItems()
|
||||
if items ~= nil then
|
||||
for _, item in pairs(items) do
|
||||
item:remove()
|
||||
end
|
||||
end
|
||||
|
||||
-- Create sand floor only for ground level
|
||||
if position.z == 7 then
|
||||
Game.createTile(position)
|
||||
Game.createItem(231, 1, position)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function copyHigherFloorItems(position)
|
||||
local higherFloorPosition = {x = position.x, y = position.y, z = position.z - 1}
|
||||
local tile = Tile(higherFloorPosition)
|
||||
if tile then
|
||||
local higherFloorItem = tile:getItemByType(0)
|
||||
while(higherFloorItem ~= nil) do
|
||||
if position.z ~= 7 or isInArray(downstairsIds, higherFloorItem:getId()) == false then
|
||||
Game.createItem(higherFloorItem:getId(), 1, position)
|
||||
end
|
||||
|
||||
higherFloorItem:remove()
|
||||
higherFloorItem = tile:getItemByType(0)
|
||||
end
|
||||
|
||||
local items = tile:getItems()
|
||||
if items ~= nil then
|
||||
for _, item in pairs(items) do
|
||||
if position.z ~= 7 or isInArray(downstairsIds, item:getId()) == false then
|
||||
Game.createItem(item:getId(), 1, position)
|
||||
end
|
||||
|
||||
item:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local effectRandomness = math.random(5)
|
||||
if effectRandomness == 5 then
|
||||
local earthquakeEffect = earthquakeEffects[math.random(#earthquakeEffects)]
|
||||
tile:getPosition():sendMagicEffect(earthquakeEffect)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: Implement that bitch npc is busy and says that I don't understand what is happening. The Academy of Magic Arts are not commenting the current situation.
|
@@ -0,0 +1,8 @@
|
||||
function onSay(player, words, param)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server Info:"
|
||||
.. "\nExp rate: " .. Game.getExperienceStage(player:getLevel())
|
||||
.. "\nSkill rate: " .. configManager.getNumber(configKeys.RATE_SKILL)
|
||||
.. "\nMagic rate: " .. configManager.getNumber(configKeys.RATE_MAGIC)
|
||||
.. "\nLoot rate: " .. configManager.getNumber(configKeys.RATE_LOOT))
|
||||
return false
|
||||
end
|
@@ -0,0 +1,15 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
if split[2] == nil then
|
||||
player:sendCancelMessage("Insufficient parameters.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:setStorageValue(tonumber(split[1]), tonumber(split[2]))
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "[Storage Value] " .. split[1] .. " changed it's value to " .. split[2] .. ".")
|
||||
return false
|
||||
end
|
@@ -0,0 +1,24 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local creature = Creature(param)
|
||||
if not creature then
|
||||
player:sendCancelMessage("A creature with that name could not be found.")
|
||||
return false
|
||||
end
|
||||
|
||||
local oldPosition = creature:getPosition()
|
||||
local newPosition = creature:getClosestFreePosition(player:getPosition(), false)
|
||||
if newPosition.x == 0 then
|
||||
player:sendCancelMessage("You can not teleport " .. creature:getName() .. ".")
|
||||
return false
|
||||
elseif creature:teleportTo(newPosition) then
|
||||
if not creature:isInGhostMode() then
|
||||
oldPosition:sendMagicEffect(CONST_ME_POFF)
|
||||
newPosition:sendMagicEffect(CONST_ME_TELEPORT)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
@@ -0,0 +1,8 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
player:teleportTo(player:getTown():getTemplePosition())
|
||||
return false
|
||||
end
|
@@ -0,0 +1,28 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local steps = tonumber(param)
|
||||
if not steps then
|
||||
return false
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
position:getNextPosition(player:getDirection(), steps)
|
||||
|
||||
position = player:getClosestFreePosition(position, false)
|
||||
if position.x == 0 then
|
||||
player:sendCancelMessage("You cannot teleport there.")
|
||||
return false
|
||||
end
|
||||
|
||||
local tile = Tile(position)
|
||||
if tile == nil or tile:getGround() == nil then
|
||||
player:sendCancelMessage("You cannot teleport there.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:teleportTo(position)
|
||||
return false
|
||||
end
|
@@ -0,0 +1,14 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local target = Creature(param)
|
||||
if target == nil then
|
||||
player:sendCancelMessage("Creature not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:teleportTo(target:getPosition())
|
||||
return false
|
||||
end
|
@@ -0,0 +1,9 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local split = param:split(",")
|
||||
local position = {x = split[1], y = split[2], z = split[3]}
|
||||
return player:teleportTo(position)
|
||||
end
|
@@ -0,0 +1,18 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local town = Town(param)
|
||||
if town == nil then
|
||||
town = Town(tonumber(param))
|
||||
end
|
||||
|
||||
if town == nil then
|
||||
player:sendCancelMessage("Town not found.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:teleportTo(town:getTemplePosition())
|
||||
return false
|
||||
end
|
16
app/SabrehavenServer/data/talkactions/scripts/unban.lua
Normal file
16
app/SabrehavenServer/data/talkactions/scripts/unban.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local resultId = db.storeQuery("SELECT `account_id`, `lastip` FROM `players` WHERE `name` = " .. db.escapeString(param))
|
||||
if resultId == false then
|
||||
return false
|
||||
end
|
||||
|
||||
db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. result.getDataInt(resultId, "account_id"))
|
||||
db.asyncQuery("DELETE FROM `ip_bans` WHERE `ip` = " .. result.getDataInt(resultId, "lastip"))
|
||||
result.free(resultId)
|
||||
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, param .. " has been unbanned.")
|
||||
return false
|
||||
end
|
17
app/SabrehavenServer/data/talkactions/scripts/up.lua
Normal file
17
app/SabrehavenServer/data/talkactions/scripts/up.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGroup():getAccess() then
|
||||
return true
|
||||
end
|
||||
|
||||
local position = player:getPosition()
|
||||
position.z = position.z - 1
|
||||
|
||||
local tile = Tile(position)
|
||||
if tile == nil or tile:getGround() == nil then
|
||||
player:sendCancelMessage("You cannot teleport there.")
|
||||
return false
|
||||
end
|
||||
|
||||
player:teleportTo(position)
|
||||
return false
|
||||
end
|
8
app/SabrehavenServer/data/talkactions/scripts/uptime.lua
Normal file
8
app/SabrehavenServer/data/talkactions/scripts/uptime.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
function onSay(player, words, param)
|
||||
local uptime = getWorldUpTime()
|
||||
|
||||
local hours = math.floor(uptime / 3600)
|
||||
local minutes = math.floor((uptime - (3600 * hours)) / 60)
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Uptime: " .. hours .. " hours and " .. minutes .. " minutes.")
|
||||
return false
|
||||
end
|
10
app/SabrehavenServer/data/talkactions/scripts/vial.lua
Normal file
10
app/SabrehavenServer/data/talkactions/scripts/vial.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
function onSay(player, words, param)
|
||||
if player:getStorageValue(17742) ~= 1 then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Vials auto removing enabled.")
|
||||
player:setStorageValue(17742, 1)
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Vials auto removing disabled.")
|
||||
player:setStorageValue(17742, 0)
|
||||
end
|
||||
return false
|
||||
end
|
60
app/SabrehavenServer/data/talkactions/scripts/war.lua
Normal file
60
app/SabrehavenServer/data/talkactions/scripts/war.lua
Normal file
@@ -0,0 +1,60 @@
|
||||
function onSay(player, words, param)
|
||||
if not player:getGuild() or player:getGuildLevel() < 3 then
|
||||
player:sendCancelMessage("You cannot execute this talkaction.")
|
||||
return true
|
||||
end
|
||||
|
||||
local t = param:split(",")
|
||||
|
||||
if not t[2] then
|
||||
player:sendCancelMessage("Not enough param(s).")
|
||||
return true
|
||||
end
|
||||
|
||||
local enemyGuildName = string.trim(t[2])
|
||||
|
||||
local enemyGuild = Guild(getGuildId(enemyGuildName))
|
||||
if not enemyGuild then
|
||||
player:sendCancelMessage("Guild \"" .. enemyGuildName .. "\" does not exists or nobody is online from the guild.")
|
||||
return true
|
||||
end
|
||||
|
||||
if enemyGuild:getId() == player:getGuild():getId() then
|
||||
player:sendCancelMessage("You cannot perform war action on your own guild.")
|
||||
return true
|
||||
end
|
||||
|
||||
local warCommand = string.trim(t[1])
|
||||
|
||||
if isInArray({"accept", "reject", "cancel"}, warCommand) then
|
||||
local pendingWarId, bounty = 0
|
||||
|
||||
if warCommand == "cancel" then
|
||||
pendingWarId, bounty = guildwars:getPendingInvitation(player:getGuild():getId(), enemyGuild:getId())
|
||||
else
|
||||
pendingWarId, bounty = guildwars:getPendingInvitation(enemyGuild:getId(), player:getGuild():getId())
|
||||
end
|
||||
|
||||
if pendingWarId == 0 then
|
||||
player:sendCancelMessage("Currently there's no pending invitation for a war with " .. enemyGuild:getName() .. ".")
|
||||
return true
|
||||
end
|
||||
|
||||
if warCommand == "reject" then
|
||||
guildwars:rejectWar(pendingWarId, player:getGuild(), enemyGuild, bounty)
|
||||
elseif warCommand == "cancel" then
|
||||
guildwars:cancelWar(pendingWarId, player:getGuild(), enemyGuild, bounty)
|
||||
else
|
||||
guildwars:startWar(player, pendingWarId, player:getGuild(), enemyGuild, bounty)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if warCommand == "invite" then
|
||||
guildwars:invite(player, player:getGuild(), enemyGuild, tonumber(t[3] and string.trim(t[3]) or 100), tonumber(t[4] and string.trim(t[4]) or 0))
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
130
app/SabrehavenServer/data/talkactions/scripts/znoteshop.lua
Normal file
130
app/SabrehavenServer/data/talkactions/scripts/znoteshop.lua
Normal file
@@ -0,0 +1,130 @@
|
||||
-- Znote Shop v1.0 for Znote AAC on TFS 1.1
|
||||
function onSay(player, words, param)
|
||||
local storage = 54073 -- Make sure to select non-used storage. This is used to prevent SQL load attacks.
|
||||
local cooldown = 15 -- in seconds.
|
||||
|
||||
if player:getStorageValue(storage) <= os.time() then
|
||||
player:setStorageValue(storage, os.time() + cooldown)
|
||||
|
||||
local type_desc = {
|
||||
"itemids",
|
||||
"pending premium (skip)",
|
||||
"pending gender change (skip)",
|
||||
"pending character name change (skip)",
|
||||
"Outfit and addons",
|
||||
"Mounts",
|
||||
"Instant house purchase"
|
||||
}
|
||||
print("Player: " .. player:getName() .. " triggered !shop talkaction.")
|
||||
-- Create the query
|
||||
local orderQuery = db.storeQuery("SELECT `id`, `type`, `itemid`, `count` FROM `znote_shop_orders` WHERE `account_id` = " .. player:getAccountId() .. ";")
|
||||
local served = false
|
||||
|
||||
-- Detect if we got any results
|
||||
if orderQuery ~= false then
|
||||
repeat
|
||||
-- Fetch order values
|
||||
local q_id = result.getNumber(orderQuery, "id")
|
||||
local q_type = result.getNumber(orderQuery, "type")
|
||||
local q_itemid = result.getNumber(orderQuery, "itemid")
|
||||
local q_count = result.getNumber(orderQuery, "count")
|
||||
|
||||
print("Processing type "..q_type..": ".. type_desc[q_type])
|
||||
|
||||
-- ORDER TYPE 1 (Regular item shop products)
|
||||
if q_type == 1 then
|
||||
served = true
|
||||
-- Get wheight
|
||||
if player:getFreeCapacity() >= ItemType(q_itemid):getWeight(q_count) then
|
||||
db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";")
|
||||
player:addItem(q_itemid, q_count)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. q_count .. " x " .. ItemType(q_itemid):getName() .. "!")
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_WARNING, "Need more CAP!")
|
||||
end
|
||||
end
|
||||
|
||||
-- ORDER TYPE 5 (Outfit and addon)
|
||||
if q_type == 5 then
|
||||
served = true
|
||||
|
||||
local itemid = q_itemid
|
||||
local outfits = {}
|
||||
|
||||
if itemid > 1000 then
|
||||
local first = math.floor(itemid/1000)
|
||||
table.insert(outfits, first)
|
||||
itemid = itemid - (first * 1000)
|
||||
end
|
||||
table.insert(outfits, itemid)
|
||||
|
||||
for _, outfitId in pairs(outfits) do
|
||||
-- Make sure player don't already have this outfit and addon
|
||||
if not player:hasOutfit(outfitId, q_count) then
|
||||
db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";")
|
||||
player:addOutfit(outfitId)
|
||||
player:addOutfitAddon(outfitId, q_count)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new outfit!")
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this outfit and addon!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ORDER TYPE 6 (Mounts)
|
||||
if q_type == 6 then
|
||||
served = true
|
||||
-- Make sure player don't already have this outfit and addon
|
||||
if not player:hasMount(q_itemid) then
|
||||
db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";")
|
||||
player:addMount(q_itemid)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received a new mount!")
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_WARNING, "You already have this mount!")
|
||||
end
|
||||
end
|
||||
|
||||
-- ORDER TYPE 7 (Direct house purchase)
|
||||
if q_type == 7 then
|
||||
served = true
|
||||
local house = House(q_itemid)
|
||||
-- Logged in player is not neccesarily the player that bough the house. So we need to load player from db.
|
||||
print(q_count)
|
||||
local buyerQuery = db.storeQuery("SELECT `name` FROM `players` WHERE `id` = "..q_count.." LIMIT 1")
|
||||
|
||||
if buyerQuery ~= false then
|
||||
local buyerName = result.getDataString(buyerQuery, "name")
|
||||
result.free(buyerQuery)
|
||||
if house then
|
||||
db.query("DELETE FROM `znote_shop_orders` WHERE `id` = " .. q_id .. ";")
|
||||
house:setOwnerGuid(q_count)
|
||||
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought the house "..house:getName().." on "..buyerName..", be sure to have the money for the rent in the bank.")
|
||||
print("Process complete. [".. buyerName .."] has recieved house: ["..house:getName().."]")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Add custom order types here
|
||||
-- Type 1 is for itemids (Already coded here)
|
||||
-- Type 2 is for premium (Coded on web)
|
||||
-- Type 3 is for gender change (Coded on web)
|
||||
-- Type 4 is for character name change (Coded on web)
|
||||
-- Type 5 is for character outfit and addon (Already coded here)
|
||||
-- Type 6 is for mounts (Already coded here)
|
||||
-- So use type 7+ for custom stuff, like etc packages.
|
||||
-- if q_type == 7 then
|
||||
-- end
|
||||
until not result.next(orderQuery)
|
||||
result.free(orderQuery)
|
||||
if not served then
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have no orders to process in-game.")
|
||||
end
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have no orders.")
|
||||
end
|
||||
else
|
||||
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Can only be executed once every " .. cooldown .. " seconds. Remaining cooldown: " .. player:getStorageValue(storage) - os.time())
|
||||
end
|
||||
return false
|
||||
end
|
Reference in New Issue
Block a user