mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-11-28 15:46:49 +01:00
introduce changes from streamside fork
This commit is contained in:
@@ -2,7 +2,12 @@ local drunk = Condition(CONDITION_DRUNK)
|
||||
drunk:setParameter(CONDITION_PARAM_TICKS, 60000)
|
||||
|
||||
local poison = Condition(CONDITION_POISON)
|
||||
poison:setTiming(100)
|
||||
poison:setParameter(CONDITION_PARAM_DELAYED, true)
|
||||
poison:setParameter(CONDITION_PARAM_MINVALUE, -50)
|
||||
poison:setParameter(CONDITION_PARAM_MAXVALUE, -120)
|
||||
poison:setParameter(CONDITION_PARAM_STARTVALUE, -5)
|
||||
poison:setParameter(CONDITION_PARAM_TICKINTERVAL, 5000)
|
||||
poison:setParameter(CONDITION_PARAM_FORCEUPDATE, true)
|
||||
|
||||
local messages = {
|
||||
[FLUID_WATER] = "Gulp.",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
function onLogin(player)
|
||||
if player:getLastLoginSaved() <= 0 or player:getStorageValue(30017) == 1 then
|
||||
player:setStorageValue(30017, 0) -- reset storage for first items
|
||||
|
||||
if player:getLastLoginSaved() <= 0 then
|
||||
-- Items
|
||||
if player:getSex() == PLAYERSEX_FEMALE then
|
||||
player:addItem(3562, 1, true, -1, CONST_SLOT_ARMOR)
|
||||
|
||||
28
data/events/events.xml
Normal file
28
data/events/events.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<events>
|
||||
<!-- Creature methods -->
|
||||
<event class="Creature" method="onChangeOutfit" enabled="0" />
|
||||
<event class="Creature" method="onAreaCombat" enabled="0" />
|
||||
<event class="Creature" method="onTargetCombat" enabled="0" />
|
||||
|
||||
<!-- Party methods -->
|
||||
<event class="Party" method="onJoin" enabled="0" />
|
||||
<event class="Party" method="onLeave" enabled="0" />
|
||||
<event class="Party" method="onDisband" enabled="0" />
|
||||
<event class="Party" method="onShareExperience" enabled="1" />
|
||||
|
||||
<!-- Player methods -->
|
||||
<event class="Player" method="onLook" enabled="1" />
|
||||
<event class="Player" method="onLookInBattleList" enabled="1" />
|
||||
<event class="Player" method="onLookInTrade" enabled="1" />
|
||||
<event class="Player" method="onMoveItem" enabled="1" />
|
||||
<event class="Player" method="onItemMoved" enabled="0" />
|
||||
<event class="Player" method="onMoveCreature" enabled="0" />
|
||||
<event class="Player" method="onReportBug" enabled="1" />
|
||||
<event class="Player" method="onTurn" enabled="0" />
|
||||
<event class="Player" method="onTradeRequest" enabled="0" />
|
||||
<event class="Player" method="onTradeAccept" enabled="0" />
|
||||
<event class="Player" method="onGainExperience" enabled="1" />
|
||||
<event class="Player" method="onLoseExperience" enabled="0" />
|
||||
<event class="Player" method="onGainSkillTries" enabled="1" />
|
||||
</events>
|
||||
11
data/events/scripts/creature.lua
Normal file
11
data/events/scripts/creature.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
function Creature:onChangeOutfit(outfit)
|
||||
return true
|
||||
end
|
||||
|
||||
function Creature:onAreaCombat(tile, isAggressive)
|
||||
return RETURNVALUE_NOERROR
|
||||
end
|
||||
|
||||
function Creature:onTargetCombat(target)
|
||||
return RETURNVALUE_NOERROR
|
||||
end
|
||||
35
data/events/scripts/party.lua
Normal file
35
data/events/scripts/party.lua
Normal file
@@ -0,0 +1,35 @@
|
||||
function Party:onJoin(player)
|
||||
return true
|
||||
end
|
||||
|
||||
function Party:onLeave(player)
|
||||
return true
|
||||
end
|
||||
|
||||
function Party:onDisband()
|
||||
return true
|
||||
end
|
||||
|
||||
function Party:onShareExperience(exp)
|
||||
local sharedExperienceMultiplier = 1.20 --20%
|
||||
local vocationsIds = {}
|
||||
|
||||
local vocationId = self:getLeader():getVocation():getBase():getId()
|
||||
if vocationId ~= VOCATION_NONE then
|
||||
table.insert(vocationsIds, vocationId)
|
||||
end
|
||||
|
||||
for _, member in ipairs(self:getMembers()) do
|
||||
vocationId = member:getVocation():getBase():getId()
|
||||
if not table.contains(vocationsIds, vocationId) and vocationId ~= VOCATION_NONE then
|
||||
table.insert(vocationsIds, vocationId)
|
||||
end
|
||||
end
|
||||
|
||||
local size = #vocationsIds
|
||||
if size > 1 then
|
||||
sharedExperienceMultiplier = 1.0 + ((size * (5 * (size - 1) + 10)) / 100)
|
||||
end
|
||||
|
||||
return (exp * sharedExperienceMultiplier) / (#self:getMembers() + 1)
|
||||
end
|
||||
169
data/events/scripts/player.lua
Normal file
169
data/events/scripts/player.lua
Normal file
@@ -0,0 +1,169 @@
|
||||
function Player:onLook(thing, position, distance)
|
||||
local description = "You see " .. thing:getDescription(distance)
|
||||
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)
|
||||
|
||||
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
|
||||
exp = exp * Game.getExperienceStage(self:getLevel())
|
||||
|
||||
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
|
||||
return tries * configManager.getNumber(configKeys.RATE_MAGIC)
|
||||
end
|
||||
return tries * configManager.getNumber(configKeys.RATE_SKILL)
|
||||
end
|
||||
@@ -40,4 +40,8 @@ table.contains = function(array, value)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function isNumber(str)
|
||||
return tonumber(str) ~= nil
|
||||
end
|
||||
@@ -9,3 +9,4 @@ dofile('data/lib/core/player.lua')
|
||||
dofile('data/lib/core/position.lua')
|
||||
dofile('data/lib/core/teleport.lua')
|
||||
dofile('data/lib/core/tile.lua')
|
||||
dofile('data/lib/core/vocation.lua')
|
||||
@@ -9,7 +9,7 @@ function Game.removeItemsOnMap(position)
|
||||
local i = 0
|
||||
while i < tileCount do
|
||||
local tileItem = tile:getThing(i)
|
||||
if tileItem and not tileItem:isCreature() and ItemType(tileItem:getId()):isMovable() then
|
||||
if tileItem and tileItem:getType():isMovable() then
|
||||
tileItem:remove()
|
||||
else
|
||||
i = i + 1
|
||||
@@ -24,10 +24,8 @@ function Game.transformItemOnMap(position, itemId, toItemId, subtype)
|
||||
|
||||
local tile = Tile(position)
|
||||
local item = tile:getItemById(itemId)
|
||||
if item ~= nil then
|
||||
item:transform(toItemId, subtype)
|
||||
item:decay()
|
||||
end
|
||||
item:transform(toItemId, subtype)
|
||||
item:decay()
|
||||
return item
|
||||
end
|
||||
|
||||
|
||||
@@ -21,3 +21,45 @@ end
|
||||
function Tile.isTile(self)
|
||||
return true
|
||||
end
|
||||
|
||||
function Tile.relocateTo(self, toPosition, pushMove, monsterPosition)
|
||||
if self:getPosition() == toPosition then
|
||||
return false
|
||||
end
|
||||
|
||||
if not Tile(toPosition) then
|
||||
return false
|
||||
end
|
||||
|
||||
for i = self:getThingCount() - 1, 0, -1 do
|
||||
local thing = self:getThing(i)
|
||||
if thing then
|
||||
if thing:isItem() then
|
||||
if ItemType(thing.itemid):isMovable() then
|
||||
thing:moveTo(toPosition)
|
||||
end
|
||||
elseif thing:isCreature() then
|
||||
if monsterPosition and thing:isMonster() then
|
||||
thing:teleportTo(monsterPosition, pushMove)
|
||||
else
|
||||
thing:teleportTo(toPosition, pushMove)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function Tile:getPlayers()
|
||||
local players = {}
|
||||
local creatures = self:getCreatures()
|
||||
if (creatures) then
|
||||
for i = 1, #creatures do
|
||||
if (creatures[i]:isPlayer()) then
|
||||
table.insert(players, creatures[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return players
|
||||
end
|
||||
7
data/lib/core/vocation.lua
Normal file
7
data/lib/core/vocation.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
function Vocation.getBase(self)
|
||||
local base = self
|
||||
while base:getDemotion() do
|
||||
base = base:getDemotion()
|
||||
end
|
||||
return base
|
||||
end
|
||||
@@ -81,8 +81,7 @@ function onStepIn(creature, item, position, fromPosition)
|
||||
return false
|
||||
end
|
||||
|
||||
doRelocate(position, relPos)
|
||||
|
||||
Tile(item:getPosition()):relocateTo(relPos)
|
||||
if item:getId() == 293 then
|
||||
item:transform(294)
|
||||
item:decay()
|
||||
|
||||
65
data/talkactions/scripts/reload.lua
Normal file
65
data/talkactions/scripts/reload.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
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" },
|
||||
|
||||
["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
|
||||
23
data/talkactions/scripts/save.lua
Normal file
23
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
data/talkactions/scripts/sellhouse.lua
Normal file
19
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
|
||||
@@ -27,7 +27,9 @@
|
||||
<talkaction words="/removetutor" separator=" " script="remove_tutor.lua" />
|
||||
<talkaction words="/looktype" separator=" " script="looktype.lua" />
|
||||
<talkaction words="/summon" separator=" " script="place_summon.lua" />
|
||||
<talkaction words="/chameleon" separator=" " script="chameleon.lua" />
|
||||
<talkaction words="/reload" separator=" " script="reload.lua" />
|
||||
<talkaction words="/save" script="save.lua" />
|
||||
<talkaction words="/chameleon" separator=" " script="chameleon.lua" />
|
||||
<talkaction words="/addskill" separator=" " script="add_skill.lua" />
|
||||
<talkaction words="/mccheck" script="mccheck.lua" />
|
||||
<talkaction words="/ghost" script="ghost.lua" />
|
||||
@@ -37,6 +39,7 @@
|
||||
<!-- player talkactions -->
|
||||
<talkaction words="!buypremium" script="buyprem.lua"/>
|
||||
<talkaction words="!buyhouse" script="buyhouse.lua"/>
|
||||
<talkaction words="!sellhouse" separator=" " script="sellhouse.lua" />
|
||||
<talkaction words="!leavehouse" script="leavehouse.lua"/>
|
||||
<talkaction words="!changesex" script="changesex.lua"/>
|
||||
<talkaction words="!uptime" script="uptime.lua"/>
|
||||
|
||||
Reference in New Issue
Block a user