190 lines
6.9 KiB
Lua
190 lines
6.9 KiB
Lua
--[[
|
||
Illarion Server
|
||
|
||
This program is free software: you can redistribute it and/or modify it under
|
||
the terms of the GNU Affero General Public License as published by the Free
|
||
Software Foundation, either version 3 of the License, or (at your option) any
|
||
later version.
|
||
|
||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||
details.
|
||
|
||
You should have received a copy of the GNU Affero General Public License along
|
||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
]]
|
||
-- Collection of helper functions for the handling of characters
|
||
|
||
local common = require("base.common")
|
||
local pulsegwynt = require("magic.nature.effects.pulsegwynt")
|
||
local testing = require("base.testing")
|
||
|
||
local M = {}
|
||
|
||
local HITPOINTS = "hitpoints"
|
||
|
||
--- Get the current hitpoints of the character
|
||
-- @param User the character that is queried
|
||
-- @return the hitpoints of the character
|
||
function M.GetHP(User)
|
||
return User:increaseAttrib(HITPOINTS, 0)
|
||
end
|
||
|
||
--- Change the hitpoints value of a character.
|
||
-- @param User The characters that receives the hitpoints change.
|
||
-- @param Value The value the hitpoints are changed by.
|
||
-- @return true in case the character is alive after the change of the hitpoints
|
||
function M.ChangeHP(defender, valueChange)
|
||
|
||
local partner, partnerDamage
|
||
|
||
if valueChange < 0 and valueChange ~= -10000 then -- The character is taking damage, not being healed and it isnt an instakill
|
||
|
||
valueChange, partner, partnerDamage = pulsegwynt.impactOnDamageTaken(defender, valueChange)
|
||
-- If bonded with someone via nature magics deepweave spell Pulsegwynt, they take part of the damage for you
|
||
if partner then
|
||
partner:increaseAttrib(HITPOINTS, partnerDamage)
|
||
end
|
||
end
|
||
|
||
-- A bond is broken if you or your partners health is reduced to 20% or lower
|
||
if partner and (M.GetHP(partner) < pulsegwynt.healthLimit or M.GetHP(defender)-valueChange < pulsegwynt.healthLimit) then
|
||
pulsegwynt.breakBond(defender, partner)
|
||
end
|
||
|
||
if testing.active and valueChange < 0 and valueChange ~= -10000 then
|
||
defender:talk(Character.say,"#me takes "..-valueChange.." damage.", "#me takes "..-valueChange.." damage.")
|
||
if partner then
|
||
partner:talk(Character.say,"#me takes "..-partnerDamage.." damage.", "#me takes "..-partnerDamage.." damage.")
|
||
end
|
||
end
|
||
|
||
return defender:increaseAttrib(HITPOINTS, valueChange) > 0
|
||
end;
|
||
|
||
--- Check if a character would surive if a amount of hitpoints get reduced
|
||
-- @param User The character that is tested
|
||
-- @param Value The value of hitpoints that are supposed to be reduced
|
||
-- @return true in case the character would survive
|
||
function M.WouldDie(User, Value)
|
||
return M.GetHP(User) <= Value;
|
||
end;
|
||
|
||
--- Check if a character is dead.
|
||
-- @param User the character to check
|
||
-- @return true in case the character is dead
|
||
function M.IsDead(User)
|
||
return M.GetHP(User) == 0
|
||
end
|
||
|
||
--- Check if the character is at the brink of death. Means that the character
|
||
-- has only one hitpoint left.
|
||
-- @param User The character to check
|
||
-- @return true in case the character is at the brink of death
|
||
function M.AtBrinkOfDeath(User)
|
||
return M.WouldDie(User, 1);
|
||
end;
|
||
|
||
--- Bring a character to the brink of death. Means that he has only one hitpoint
|
||
-- left.
|
||
-- @param User The character to bring to the brink of death
|
||
function M.ToBrinkOfDeath(User)
|
||
M.ChangeHP(User, 1 - M.GetHP(User));
|
||
end;
|
||
|
||
local overTimeLTEs = {1, 3, 9, 10} -- health, mana and stamina drains over time need to be removed on death, no matter what the killing blow is
|
||
|
||
local recentlyKilled = {}
|
||
|
||
--- Kill a character.
|
||
-- @param User The character to kill
|
||
-- @return true in case the player was killed successfully
|
||
function M.Kill(user)
|
||
|
||
local timeStamp = world:getTime("unix")
|
||
|
||
for _, lte in pairs(overTimeLTEs) do
|
||
local foundEffect = user.effects:find(lte)
|
||
if foundEffect then
|
||
user.effects:removeEffect(lte)
|
||
end
|
||
end
|
||
|
||
if recentlyKilled[user.id] and recentlyKilled[user.id]+5 >= timeStamp then --It's been 5 or less seconds since this character was killed
|
||
return --ensures that if a DoT was applied right after or in the same blow as a killing blow, it wont reskill you
|
||
end
|
||
|
||
common.TalkNLS(user, Character.say,"#me geht t<>dlich getroffen zu Boden.","#me goes down, fatally injured.")
|
||
M.ChangeHP(user, -10000)
|
||
recentlyKilled[user.id] = timeStamp
|
||
return true
|
||
end
|
||
|
||
function M.WasKilledRecently(user)
|
||
|
||
local timeStamp = world:getTime("unix")
|
||
|
||
if recentlyKilled[user.id] and recentlyKilled[user.id]+5 >= timeStamp then
|
||
return true
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
--- Change the movepoints of a character by the value handed over.
|
||
-- @param User The character thats movepoints are supposed to change
|
||
-- @param Value The amount of movepoints that are added
|
||
function M.ChangeMovepoints(User, Value)
|
||
User.movepoints = User.movepoints + Value;
|
||
end;
|
||
|
||
--- Change the fighting points of a character by the value handed over.
|
||
-- @param User The character thats fightingpoints are supposed to change
|
||
-- @param Value The amount of fightingpoints that are added
|
||
-- @info This is currently set to change the movepoints also because the
|
||
-- fighting points do not seem to work on the current server
|
||
function M.ChangeFightingpoints(User, Value)
|
||
User.fightpoints = User.fightpoints + Value;
|
||
end;
|
||
|
||
--- Check if the character is a player character.
|
||
-- @param User The character to check
|
||
-- @return true in case the character is a player character
|
||
function M.IsPlayer(User)
|
||
return User:getType() == Character.player;
|
||
end;
|
||
|
||
-- Kills immediately after a defined period of time
|
||
-- @param Character The character (e.g. summoned monster) supposed to die
|
||
-- @param deathAfter The period of time after which the character dies in 1/10 sec
|
||
-- @param deathGfx The GFX shown on the characters' death, nil for no GFX
|
||
-- @param deathSound The sound played on characters' death, nil for no sound
|
||
-- @param blood Boolean determining if blood is dropped or not
|
||
function M.DeathAfterTime(Character,deathAfter,deathGfx,deathSound,blood)
|
||
local find = Character.effects:find(36)
|
||
if find then
|
||
return
|
||
else
|
||
local myEffect = LongTimeEffect(36,deathAfter)
|
||
if deathGfx ~= nil then
|
||
myEffect:addValue("deathGfx",deathGfx)
|
||
end
|
||
if deathSound ~= nil then
|
||
myEffect:addValue("deathSound",deathSound)
|
||
end
|
||
if blood then
|
||
myEffect:addValue("blood",1)
|
||
end
|
||
Character.effects:addEffect(myEffect)
|
||
end
|
||
end
|
||
|
||
-- Get a string that is nicely usable for a character reference in the logfile
|
||
-- @param character the character
|
||
-- @return the reference string to the character for the logfile
|
||
function M.LogText(character)
|
||
return string.format("%s (%u)", character.name, character.id);
|
||
end
|
||
|
||
return M
|