• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Solved OnStatsChange. Attacker issue.

Lording

Well-Known Member
Joined
Jan 9, 2008
Messages
802
Reaction score
78
Lua:
function onStatsChange(cid, attacker, type, combat, value)
    if (type == STATSCHANGE_HEALTHLOSS) and isPlayer(cid) then
        if getCreatureHealth(cid) <= value then
on this function there seems to be only one attacker, is possible to take more attackers if there were in fight?
I'm trying to make players receive exp and divide with atleast two players but statschange it's only giving to last hitter.
 
It's a war server(without hotkeys) so I'm trying to avoid players to relog each death, open backpacks and so.

At the moment this is the script I made(dont laugh =P):
Lua:
local expe = math.random(20000,99000)
local fak = math.random (100000,330000)
local lul = "00000"
local fik = "Owned!"
local lele = math.random(10,20)
local mons = "Own3d!"
local lavel = math.random(59,61)
local lawl = "l"
local maxExpLoss = 330000 -- Max exp for random
local minExpLoss = 100000 -- Min exp for random

local maxExpLossBless = 190000 -- Max exp for random
local minExpLossBless = 50000 -- Min exp for random


local bless = {1, 2, 3, 4, 5}


function onStatsChange(cid, attacker, type, combat, value)
    if (type == STATSCHANGE_HEALTHLOSS) and isPlayer(cid) then
        if getCreatureHealth(cid) <= value then
            doSendAnimatedText(getThingPosition(cid), fik, COLOR_RED)
            corpse = doCreateItem(corpse_ids[getPlayerSex(cid)], 1, getThingPos(cid))
            doItemSetAttribute(corpse, "description", "You recognize "..getCreatureName(cid)..". He was killed by "..(isMonster(attacker) and "a "..string.lower(getCreatureName(attacker)) or isCreature(attacker) and getCreatureName(attacker) or "a field item")..".")
            doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You are dead.")
            setPlayerStorageValue(cid, 6776, 0)
            setPlayerStorageValue(cid, 6001, -1)
            setPlayerStorageValue(cid, 6002, -1)
            setPlayerStorageValue(cid, 6003, -1)
            setPlayerStorageValue(cid, 6004, -1)
            setPlayerStorageValue(cid, 6005, -1)
            setPlayerStorageValue(cid, 77888, -1)
            setPlayerStorageValue(cid, 6006, -1)
            setPlayerStorageValue(cid, 6007, -1)
            doPlayerAddSoul(cid, - getPlayerSoul(cid))
            doPlayerSetPzLocked(cid, false)
            doRemoveConditions(cid,false)
            doPlayerSetPzLocked(cid, FALSE)
            doCreatureAddHealth(cid, getCreatureMaxHealth(cid))
            doCreatureAddMana(cid, (getCreatureMaxMana(cid) - getCreatureMana(cid)))


    if (getPlayerStorageValue(cid, 77888) == 1) then
            doPlayerAddExperience(cid, - math.random(minExpLossBless, maxExpLossBless))
            doSendAnimatedText(getThingPosition(cid), math.random(minExpLossBless, maxExpLossBless), COLOR_BLUE)
            else
            doPlayerAddExperience(cid, - math.random(minExpLoss, maxExpLoss))
            doSendAnimatedText(getThingPosition(cid), math.random(minExpLoss, maxExpLoss), COLOR_RED)
    end

if isPlayer(cid) and isMonster(attacker) then
doSendAnimatedText(getThingPosition(attacker), lawl, COLOR_WHITE)
end


local maxExp = 150000 -- Max exp for random
local minExp = 20000 -- Min exp for random

        if isPlayer(attacker) and getPlayerLevel(attacker) <= lavel and (not isMonster(attacker) == TRUE) then
        doPlayerAddExperience(attacker, math.random(minExp, maxExp))
        doSendAnimatedText(getThingPosition(attacker), math.random(minExp, maxExp), COLOR_WHITE)
        else
        doSendAnimatedText(getThingPosition(attacker), lul, COLOR_WHITE)
        end

        if isPlayer(attacker) and not isMonster(attacker) then
        setPlayerStorageValue(attacker, 6700, getPlayerStorageValue(attacker, 6700) + 1)
        setPlayerStorageValue(attacker, 6776, getCreatureStorage(attacker, 6776) + 1)
        doPlayerSetPzLocked(attacker, true)
                doPlayerAddSoul(attacker, 1)
        doPlayerAddItem(attacker, 2152, 10)
        --doSendAnimatedText(getThingPosition(attacker), exp, COLOR_WHITE)
        else
        doSendAnimatedText(getThingPosition(attacker), mons, COLOR_WHITE)

               end

    return false
end
    end


    return true
end

@Xikini @Evil Puncker
 
Last edited:
dont laugh =P
don't worry, we are all here to learn with each other

try this one:
Lua:
local expe = math.random(20000,99000)
local fak = math.random (100000,330000)
local fik = "Owned!"
local lele = math.random(10,20)
local mons = "Own3d!"
local lavel = math.random(59,61)
local maxExpLoss = 330000 -- Max exp for random
local minExpLoss = 100000 -- Min exp for random

local maxExpLossBless = 190000 -- Max exp for random
local minExpLossBless = 50000 -- Min exp for random

local maxExp = 150000 -- Max exp for random
local minExp = 20000 -- Min exp for random

local corpse_ids = {
    [0] = 3065,
    [1] = 3058
}

function onPrepareDeath(cid, deathList)
        if isPlayer(cid) and isPlayer(deathList[1]) then
            -- here is the part that gives exp to everyone involved in the kill
            for d = 1, #deathList do
                doPlayerAddExperience(deathList[d], math.random(minExp, maxExp))
                doSendAnimatedText(getThingPosition(deathList[d]), math.random(minExp, maxExp), COLOR_WHITE)
            end
            -- end of the part that gives exp to everyone involved in the kill

            doSendAnimatedText(getThingPosition(cid), fik, COLOR_RED)
            corpse = doCreateItem(corpse_ids[getPlayerSex(cid)], 1, getThingPosition(cid))
            doItemSetAttribute(corpse, "description", "You recognize "..getCreatureName(cid)..". He was killed by "..(isMonster(deathList[1]) and "a "..string.lower(getCreatureName(deathList[1])) or isCreature(deathList[1]) and getCreatureName(deathList[1]) or "a field item")..".")
            setPlayerStorageValue(cid, 6776, 0)
            setPlayerStorageValue(cid, 6001, -1)
            setPlayerStorageValue(cid, 6002, -1)
            setPlayerStorageValue(cid, 6003, -1)
            setPlayerStorageValue(cid, 6004, -1)
            setPlayerStorageValue(cid, 6005, -1)
            setPlayerStorageValue(cid, 77888, -1)
            setPlayerStorageValue(cid, 6006, -1)
            setPlayerStorageValue(cid, 6007, -1)
            doPlayerAddSoul(cid, - getPlayerSoul(cid))
            doPlayerSetPzLocked(cid, false)
            doRemoveConditions(cid, false)
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You are dead.")
            doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
            doCreatureAddHealth(cid, getCreatureMaxHealth(cid) - getCreatureHealth(cid))
            doCreatureAddMana(cid, getCreatureMaxMana(cid) - getCreatureMana(cid))
            return false
        end

        if getPlayerStorageValue(cid, 77888) == 1 then
            doPlayerAddExperience(cid, - math.random(minExpLossBless, maxExpLossBless))
            doSendAnimatedText(getThingPosition(cid), math.random(minExpLossBless, maxExpLossBless), COLOR_BLUE)
        else
            doPlayerAddExperience(cid, - math.random(minExpLoss, maxExpLoss))
            doSendAnimatedText(getThingPosition(cid), math.random(minExpLoss, maxExpLoss), COLOR_RED)
        end

        if isPlayer(deathList[1]) then
            setPlayerStorageValue(deathList[1], 6700, getPlayerStorageValue(deathList[1], 6700) + 1)
            setPlayerStorageValue(deathList[1], 6776, getCreatureStorage(deathList[1], 6776) + 1)
            doPlayerSetPzLocked(deathList[1], true)
            doPlayerAddSoul(deathList[1], 1)
            doPlayerAddItem(deathList[1], 2152, 10)
            --doSendAnimatedText(getThingPosition(deathList[1]), exp, COLOR_WHITE)
        else
            doSendAnimatedText(getThingPosition(deathList[1]), mons, COLOR_WHITE)
        end
    return true
end
 
Last edited by a moderator:
Character is dying, it's not preventing death somehow.
Noticed soul wasn't being added neither

Removed anyother "statschange" from creaturescripts.xml just for testing and happened the same

Lua:
<?xml version="1.0" encoding="UTF-8"?>
<creaturescripts>
    <!-- Player Login -->
    <event type="login" name="PlayerLogin" event="script" value="login.lua"/>

    <!-- Server Events -->
    <event type="channeljoin" name="GuildEvents" event="script" value="guild.lua"/>
    <event type="mailreceive" name="Mail" event="script" value="mail.lua"/>
    <event type="reportbug" name="ReportBug" script="reportbug.lua"/>
    <event type="advance" name="AdvanceSave" event="script" value="advancesave.lua"/>
    <event type="look" name="FragLook" event="script" value="frags.lua"/>
    <event type="target" name="LMSTarget" event="script" value="lms.lua"/>
    <event type="login" name="LMSLogout" event="script" value="lms.lua"/>
    <event type="logout" name="LegOut" script="logout.lua"/>
    <event type="login" name="Skills" script="skills.lua"/>
    <event type="preparedeath" name="Oldwarz" script="statschange.lua"/>
    <event type="think" name="Skoll" event="script" value="jail.lua"/>
</creaturescripts>
 
Last edited:
have you changed the creatures.xml to preparedeath? and registered it to login.lua?

I've edited the script from the post #4 once again, try again, if that doesn't work, try starting from a small script and then go adding part by part and testing it:

Lua:
function onPrepareDeath(cid, deathList)
        if isPlayer(cid) and not isMonster(deathList[1]) then
            doCreatureAddHealth(cid, getCreatureMaxHealth(cid) - getCreatureHealth(cid))
            doCreatureAddMana(cid, (getCreatureMaxMana(cid) - getCreatureMana(cid)))
            doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))

            for d = 1, #deathList do
                doPlayerAddExperience(deathList[d], - math.random(100000, 330000))
                doSendAnimatedText(getThingPosition(deathList[d]), math.random(100000, 330000), COLOR_BLUE)
            end
        end
    return true
end

it will be easier to pinpoint the error
 
evilpuncker.png

First test from 4th post script.

This was the console error:

Lua:
[Error - CreatureScript Interface]
data/creaturescripts/scripts/statschange.lua:onPrepareDeath
Description:
data/creaturescripts/scripts/statschange.lua:37: attempt to index global 'corpse_ids' (a nil value)






evilpuncker2.png

First test from short script
No errors in console.
 
Last edited:
Let's focus on the part that you quoted start and end to give exp(this seems to be one mistake


Lua:
            -- here is the part that gives exp to everyone involved in the kill
            for d = 1, #deathList do
                if getPlayerStorageValue(deathList[d], 77888) == 1 then
                    doPlayerAddExperience(deathList[d], - math.random(minExpLossBless, maxExpLossBless))
                    doSendAnimatedText(getThingPosition(deathList[d]), math.random(minExpLossBless, maxExpLossBless), COLOR_BLUE)
                else
                    doPlayerAddExperience(deathList[d], - math.random(minExpLoss, maxExpLoss))
                    doSendAnimatedText(getThingPosition(deathList[d]), math.random(minExpLoss, maxExpLoss), COLOR_RED)
                end
            end
            -- end of the part that gives exp to everyone involved in the kill

If you see there is a "-" that part on the original script was made to "remove" exp from death player I guess cid.
(You can notice for the ExpLoss/ExpLossBless)

And the original exp part was some lines down that one


Code:
        local maxExp = 150000 -- Max exp for random
        local minExp = 20000 -- Min exp for random

        if isPlayer(deathList[1]) and getPlayerLevel(deathList[1]) <= lavel and (not isMonster(deathList[1]) == true) then
            doPlayerAddExperience(deathList[1], math.random(minExp, maxExp))
            doSendAnimatedText(getThingPosition(deathList[1]), math.random(minExp, maxExp), COLOR_WHITE)
        else
            doSendAnimatedText(getThingPosition(deathList[1]), lul, COLOR_WHITE)
        end
You can locate for the Max/Min Exp


It was confused thanks to my weird codes. when I changed the first part from deathlist to cid worked without weird bugs but no exp gained
 
Last edited:
It's now working as it should, deathlist getting experience but character is at temple with 0 hp can't move and bodies are created in temple instead of the place in map
 
14:41 You are dead.
14:41 You are dead.
14:41 You are dead.
14:41 You are dead.
It keep giving exp to deathlist and 0 hp in temple
 
14:41 You are dead.
14:41 You are dead.
14:41 You are dead.
14:41 You are dead.
It keep giving exp to deathlist and 0 hp in temple

okay my bad, seems like the only way to go is to use onstatschange, because onpreparedeath is executed when character is already dead:

but them we go back to your first issue that is to find a way to give exp to everyone involved in the kill (deathList) but since onstatschange doesn't return a damage map, this is not possible, I don't know what else we can do
 
is there a way to give exp to everyone who is actually targetting the cid?
there was some interesting files but I wasn't experienced enough to make it work. maybe with your knowledge you can manage to archieve this.
Lua:
LEVEL_MINIMUM = 50
LEVEL_MAXIMUM = 75

timeOnline = {}
timeAlive = {}
damageReceived = {}
lastHitOnGuy = {}
lastKiller = {}

killsIpCounter = {}
killsAccountCounter = {}

function resetTimeAlive(cid)
    timeAlive[getPlayerGUID(cid)] = os.time()
end

function getTimeAlive(cid)
    if(timeAlive[getPlayerGUID(cid)] == nil) then
        resetTimeAlive(cid)
    end
    return os.time() - timeAlive[getPlayerGUID(cid)]
end

function removePlayerTimeAliveCounter(cid)
    timeAlive[getPlayerGUID(cid)] = nil
end

function resetDamageCounter(cid)
    damageReceived[getPlayerGUID(cid)] = {}
    damageReceived[getPlayerGUID(cid)][0] = 0
    lastHitOnGuy[getPlayerGUID(cid)] = 0
    lastKiller[getPlayerGUID(cid)] = 0
end

function removeDamageCounter(cid)
    local playerGUID = getPlayerGUID(cid)
    -- remove from all players that this player did hit
    for _, playerCid in pairs(getPlayersOnline()) do
        if(damageReceived[getPlayerGUID(playerCid)] ~= nil) then
            if(damageReceived[getPlayerGUID(playerCid)][playerGUID] ~= nil) then
                table.remove(damageReceived[getPlayerGUID(playerCid)], playerGUID)
            end
        end
    end
    damageReceived[getPlayerGUID(cid)] = nil
    lastHitOnGuy[getPlayerGUID(cid)] = nil
    lastKiller[getPlayerGUID(cid)] = nil
end

function addHitToDamageCounter(damaged, damager, value)
    if(isPlayer(damaged)) then
        local damagerGUID = 0
        -- if 'damager' is monster or field (fire field etc.) then save it as guid 0
        if(isPlayer(damager)) then
            --damagerGUID = lastKiller[killerGUID]
            damagerGUID = getPlayerGUID(damager)
        end
        local damagedGUID = getPlayerGUID(damaged)
        if(damageReceived[damagedGUID] == nil) then
            resetDamageCounter(damaged)
        end
        if(damageReceived[damagedGUID][damagerGUID] == nil) then
            damageReceived[damagedGUID][damagerGUID] = value
        else
            damageReceived[damagedGUID][damagerGUID] = damageReceived[damagedGUID][damagerGUID] + value
        end
        lastHitOnGuy[damagedGUID] = damagerGUID
    end
end

function getDamageCounterTable(cid)
    if(damageReceived[getPlayerGUID(cid)] == nil) then
        resetDamageCounter(cid)
    end
    return damageReceived[getPlayerGUID(cid)]
end


function reduceDamageOverTime(cid)
    local damagedGUID = getPlayerGUID(cid)
    if(damageReceived[damagedGUID] ~= nil) then
        for damagerGUID, damage in pairs(damageReceived[damagedGUID]) do
            damageReceived[damagedGUID][damagerGUID] = damage / 2
        end
    end
end

function addKillToKillsCounter(cid, target)
    if(isPlayer(cid) and isPlayer(target) and not isBot(cid) and not isBot(target)) then
        local playerGUID = getPlayerGUID(cid)
        local targetIP = getPlayerIp(target)
        local targetAccountID = getPlayerAccountId(target)
        if(killsIpCounter[playerGUID] == nil) then
            killsIpCounter[playerGUID] = {}
        end
        if(killsIpCounter[playerGUID][targetIP] == nil) then
            killsIpCounter[playerGUID][targetIP] = {}
        end
        if(killsAccountCounter[playerGUID] == nil) then
            killsAccountCounter[playerGUID] = {}
        end
        if(killsAccountCounter[playerGUID][targetAccountID] == nil) then
            killsAccountCounter[playerGUID][targetAccountID] = {}
        end
        table.insert(killsIpCounter[playerGUID][targetIP], os.time())
        table.insert(killsAccountCounter[playerGUID][targetAccountID], os.time())
    end
end

local killsPerHourPerIp = 10
local killsPerFiveMinutesPerIp = 2

local killsPerHourPerAccount = 10
local killsPerFiveMinutesPerAccount = 2

function getKillExpRatio(cid, target)
    local ratio = 1000
    local msges = {}
    local playerGUID = getPlayerGUID(cid)
    local targetIP = getPlayerIp(target)
    local targetAccountID = getPlayerAccountId(target)
    if(killsIpCounter[playerGUID] == nil) then
        killsIpCounter[playerGUID] = {}
    end
    if(killsIpCounter[playerGUID][targetIP] == nil) then
        killsIpCounter[playerGUID][targetIP] = {}
    end
    if(killsAccountCounter[playerGUID] == nil) then
        killsAccountCounter[playerGUID] = {}
    end
    if(killsAccountCounter[playerGUID][targetAccountID] == nil) then
        killsAccountCounter[playerGUID][targetAccountID] = {}
    end
    local killsIp = killsIpCounter[playerGUID][targetIP]
    local killsAccount = killsAccountCounter[playerGUID][targetAccountID]
    local killsInLastHourPerIp = 0
    local killsInLastFiveMinutesPerIp = 0
    local killsInLastHourPerAccount = 0
    local killsInLastFiveMinutesPerAccount = 0
    local timeNow = os.time()
    local toRemoveFromTable = {}
    for _, killIpTime in pairs(killsIp) do
        if(killIpTime + 3600 > timeNow) then
            killsInLastHourPerIp = killsInLastHourPerIp + 1
            if(killIpTime + 300 > timeNow) then
                killsInLastFiveMinutesPerIp = killsInLastFiveMinutesPerIp + 1
            end
        else
            table.insert(toRemoveFromTable, _)
        end
    end
    for _, removeID in pairs(toRemoveFromTable) do
        table.remove(killsIpCounter[playerGUID][targetIP], removeID)
    end
    if(#killsIpCounter[playerGUID][targetIP] == 0) then
        table.remove(killsIpCounter[playerGUID], targetIP)
    end

    toRemoveFromTable = {}
    for _, killAccountTime in pairs(killsAccount) do
        if(killAccountTime + 3600 > timeNow) then
            killsInLastHourPerAccount = killsInLastHourPerAccount + 1
            if(killAccountTime + 300 > timeNow) then
                killsInLastFiveMinutesPerAccount = killsInLastFiveMinutesPerAccount + 1
            end
        else
            table.insert(toRemoveFromTable, _)
        end
    end
    for _, removeID in pairs(toRemoveFromTable) do
        table.remove(killsAccountCounter[playerGUID][targetAccountID], removeID)
    end
    if(#killsAccountCounter[playerGUID][targetAccountID] == 0) then
        table.remove(killsAccountCounter[playerGUID], targetAccountID)
    end

    if(not isBot(target)) then
        -- check rules
        if(getPlayerIp(cid) == 0 or getPlayerIp(target) == 0) then
            ratio = 0
            table.insert(msges, "offline kill block")
        end
        if(getPlayerIp(cid) == getPlayerIp(target)) then
            ratio = 0
            table.insert(msges, "MC kill block")
        end
        if(killsInLastHourPerIp > killsPerHourPerIp) then
            ratio = 0
            table.insert(msges, "IP hour limit")
        end
        if(killsInLastFiveMinutesPerIp > killsPerFiveMinutesPerIp) then
            ratio = 0
            table.insert(msges, "IP five minutes limit")
        end
        if(killsInLastHourPerAccount > killsPerHourPerAccount) then
            ratio = 0
            table.insert(msges, "account hour limit")
        end
        if(killsInLastFiveMinutesPerAccount > killsPerFiveMinutesPerAccount) then
            ratio = 0
            table.insert(msges, "account five minutes limit")
        end
    end
    if(not isBot(target)) then
        ratio = ratio * (10 / (10 +(killsInLastFiveMinutesPerIp + killsInLastFiveMinutesPerAccount / 2)))
    end
    ratio = ratio * math.min(getPlayerLevel(target) / getPlayerLevel(cid), 1.2)
    if(getDeaths(target) > getFrags(target) * 5 or getFrags(target) < 3) then
        ratio = ratio * 0.4
        table.insert(msges, "newbie or very bad player")
    elseif(getDeaths(target) > getFrags(target) * 4) then
        ratio = ratio * 0.6
        table.insert(msges, "bad player")
    elseif(getDeaths(target) * 2 < getFrags(target) and getTmpFrags(target) > 15 and getLastFrags(target) > 5) then
        ratio = ratio * 1.4
        table.insert(msges, "very good player")
    elseif(getDeaths(target) < getFrags(target) and getTmpFrags(target) > 5 and getLastFrags(target) > 0) then
        ratio = ratio * 1.2
        table.insert(msges, "good player")
    end
    if(#msges > 0) then
        return ratio / 1000, table.concat(msges, ", ")
    else
        return ratio / 1000, ""
    end
end

function war_doPlayerAddExperience(cid, value)
    if(value > 0) then
        if(getPlayerExperience(cid) + value <= getExperienceForLevel(LEVEL_MAXIMUM)) then
            doPlayerAddExperience(cid, value)
        else
            doPlayerAddExperience(cid, getExperienceForLevel(LEVEL_MAXIMUM) - getPlayerExperience(cid))
        end
    end
end

function war_doPlayerRemoveExperience(cid, value)
    if(value > 0) then
        if(getPlayerExperience(cid) - value >= getExperienceForLevel(LEVEL_MINIMUM)) then
            doPlayerAddExperience(cid, -value)
        else
            doPlayerAddExperience(cid, getExperienceForLevel(LEVEL_MINIMUM) - getPlayerExperience(cid))
        end
    end
end

function war_saveTimeAliveRecord(cid)
    if(getTimeAlive(cid) > 10 and then
        db.executeQuery("INSERT INTO `zotsme_alive_records` (`id`, `player_id`, `date`, `alive_time`, `kills`, `assists`) VALUES (NULL, " .. getPlayerGUID(cid) .. ", " .. os.time() .. ", " .. getTimeAlive(cid) .. ", " .. getLastFrags(cid) .. ", " .. getLastAssists(cid) .. ");")
    end
end

function recalculateHPandMana(cid)
    if(isPlayer(cid)) then
        local voc = getPlayerVocation(cid)
        local lvl = getPlayerLevel(cid)
        if(voc == 1 or voc == 2) then
            setCreatureMaxHealth(cid, 185 + ((lvl - 8) * 5))
            setCreatureMaxMana(cid, 35 + ((lvl - 8) * 30))
        elseif(voc == 3) then
            setCreatureMaxHealth(cid, 185 + ((lvl - 8) * 10))
            setCreatureMaxMana(cid, 35 + ((lvl - 8) * 15))
        else
            setCreatureMaxHealth(cid, 185 + ((lvl - 8) * 15))
            setCreatureMaxMana(cid, 35 + ((lvl - 8) * 5))
        end
        doCreatureAddHealth(cid, getCreatureMaxHealth(cid)-getCreatureHealth(cid), 0, 0, 1)
        doCreatureAddMana(cid, getCreatureMaxMana(cid)-getCreatureMana(cid))
    end
end
This is a lib.

And the next one is the code.
Code:
function removePzBlock(cid)
    if(isPlayer(cid) and getTileInfo(getThingPosition(cid)).protection) then
        doRemoveConditions(cid)
        doPlayerSetPzLocked(cid, false)
    end
end

function onPrepareDeath(cid, deathList)
    local killerGUID = lastHitOnGuy[getPlayerGUID(cid)]
    local damageDealed = getDamageCounterTable(cid)
    local totalDamage = 1
    local expLost = round((math.floor(getPlayerExperience(cid) - getExperienceForLevel(LEVEL_MINIMUM)) / 5) * 2.5, 0)
    local attackersNumber = 0
    if(expLost < 250000) then
        expLost = 250000
    end
    local expRealLost = round((expLost / 2) * ((LEVEL_MINIMUM+150) / (getPlayerLevel(cid)+150)), 0)
    for guid, damage in pairs(damageDealed) do
        if(damage > 1) then
            totalDamage = totalDamage + damage
            attackersNumber = attackersNumber + 1
        end
    end
    local killRatio = 1
    if(attackersNumber <= 4) then -- guy + 2 summons
        killRatio = 0.8
    end
    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You lost " .. round(expRealLost, 0) .. " experience points, because of death after attack of " .. attackersNumber .. " players that dealed " .. round(totalDamage, 0) .. " damage.")
    local expGiven = 0
    for guid, damage in pairs(damageDealed) do
        if(damage > 1) then
            local attacker = getPlayerByGUID(guid)
            if(isPlayer(attacker)) then -- if is still online
                local damagePercent = (damage / totalDamage) * 100
                local roundedDamagePercent = round(damagePercent, 2)
                local expRatio, text = getKillExpRatio(attacker, cid)
                expRatio = expRatio * killRatio
                if(damagePercent > math.random(60, 90)) then
                    expRatio = expRatio * 0.8
                end
                local expGained = math.floor(((expLost * damagePercent / 100) * expRatio) / 2)
                --print(getCreatureName(attacker) .. " dostal " .. expGained .. " exp")
                if(text ~= "" and damagePercent > 0.1) then
                    doPlayerSendTextMessage(attacker, MESSAGE_STATUS_CONSOLE_BLUE, "You received " .. round(expGained, 0) .. " exp (exp-ratio: " .. round(expRatio * 100, 2) .. " %, damage: " .. roundedDamagePercent .. "%) for killing " .. getCreatureName(cid) .. ", because of: " .. text)
                elseif(expGained > 0) then
                    doPlayerSendTextMessage(attacker, MESSAGE_STATUS_CONSOLE_BLUE, "You received " .. round(expGained, 0) .. " exp (exp-ratio: " .. round(expRatio * 100, 2) .. " %, damage: " .. roundedDamagePercent .. " %) for killing " .. getCreatureName(cid) .. ".")
                end
                if(expRatio > 0) then -- frag not blocked
                    war_doPlayerAddExperience(attacker, expGained)
                    expGiven = expGiven + expGained
                    if(expGained > 10000) then
                        addKillToKillsCounter(attacker, cid)
                    end
                    if(guid == killerGUID) then
                        local extraExp = 30000 * expRatio
                        doSendAnimatedText(getThingPosition(attacker), round(expGained+extraExp, 0), COLOR_WHITE)
                        expGiven = expGiven + extraExp
                        war_doPlayerAddExperience(attacker, extraExp)
                         -- add frag
                        doPlayerAddSoul(attacker, 1)
                        setFrags(attacker, getFrags(attacker)+1)
                        setTmpFrags(attacker, getTmpFrags(attacker)+1)
                        setLastFrags(attacker, getLastFrags(attacker)+1)
                        for _, pid in pairs(getPlayersOnline()) do
                            doPlayerSendChannelMessage(pid, "System", getCreatureName(attacker) .. " (" .. getPlayerLevel(attacker) .. ") killed " .. getCreatureName(cid) .. " (" .. getPlayerLevel(cid) .. ")", 15,5)
                        end
                        doPlayerSendTextMessage(attacker, MESSAGE_STATUS_CONSOLE_BLUE, "You did last hit on " .. getCreatureName(cid) .. ". You receive frag and extra " .. round(extraExp,0) .. " exp.")
                        -- drop body
                        if(getPlayerSex(cid) == 0) then -- female
                            local corpse = doCreateItem(6081, 1, getThingPosition(cid))
                            if(corpse and type(corpse) == "number") then
                                doItemSetAttribute(corpse, "name", "dead body. You recognize " .. getCreatureName(cid) .. ". She was killed by " .. getCreatureName(attacker) .. ".")
                                doDecayItem(corpse)
                            end
                        else -- male
                            local corpse = doCreateItem(6080, 1, getThingPosition(cid))
                            if(corpse and type(corpse) == "number") then
                                doItemSetAttribute(corpse, "name", "dead body. You recognize " .. getCreatureName(cid) .. ". He was killed by " .. getCreatureName(attacker) .. ".")
                                doDecayItem(corpse)
                            end
                        end
                    elseif(expGained > 0) then
                        doSendAnimatedText(getThingPosition(attacker), round(expGained, 0), COLOR_WHITE)
                        if(expGained > 2000) then
                            setAssists(attacker, getAssists(attacker)+1)
                            setTmpAssists(attacker, getTmpAssists(attacker)+1)
                            setLastAssists(attacker, getLastAssists(attacker)+1)
                            doPlayerSendTextMessage(attacker, MESSAGE_STATUS_CONSOLE_BLUE, "You did hit on " .. getCreatureName(cid) .. ". You receive assist.")
                        end
                    end
                end
            end
        end
    end
    -- add to records on www
    print("Padl: " .. getCreatureName(cid) .. "(" .. getPlayerLevel(cid) .. ") stracil: " .. expRealLost .. " (full: " .. expLost .. " ), rozdal: " .. round(expGiven,0))
    war_doPlayerRemoveExperience(cid, expRealLost)
    setDeaths(cid, getDeaths(cid)+1)
    setTmpDeaths(cid, getTmpDeaths(cid)+1)
    if(lastKiller[killerGUID] ~= nil and lastKiller[killerGUID] == getPlayerGUID(cid)) then
        -- lastKiller[killerGUID] zabil tego kto zabil ostatnio ciebie, zemsta?
    end
    if(lastKiller[getPlayerGUID(cid)] ~= nil and lastKiller[getPlayerGUID(cid)] == killerGUID) then
        -- znowu ten sam zabil co wczesniej, cos zrobic?
    end
    -- save alive time
    war_saveTimeAliveRecord(cid)
    db.executeQuery("UPDATE `players` SET `kills` = " .. getFrags(cid) .. ", `tmp_kills` = " .. getTmpFrags(cid) .. ", `deaths` = " .. getDeaths(cid) .. ", `tmp_deaths` = " .. getTmpDeaths(cid) .. ", `assists` = " .. getAssists(cid) .. ", `tmp_assists` = " .. getTmpAssists(cid) .. " WHERE `id` = " .. getPlayerGUID(cid) .. ";")
    setLastAssists(cid, 0)
    setLastFrags(cid, 0)
    resetTimeAlive(cid)
    resetDamageCounter(cid)
    lastKiller[getPlayerGUID(cid)] = killerGUID
 
    -- return false i lecz gracza co pada i tp do swiatyni
    doSendMagicEffect(getThingPosition(cid), CONST_ME_YALAHARIGHOST)
    doTeleportThing(cid, getTownTemplePosition(math.random(1, 5)))
    -- HP i MANA fix
    recalculateHPandMana(cid)
    doRemoveConditions(cid)
    doPlayerSetPzLocked(cid, false)
    addEvent(removePzBlock, 1000, cid)
    addEvent(removePzBlock, 5500, cid)
    -- dodanie skull za ilosc fragow
    return true
end

Last one is statschange

Code:
function onStatsChange(cid, attacker, type, combat, value)
    if(type == STATSCHANGE_HEALTHLOSS or type == STATSCHANGE_MANALOSS) then
        addHitToDamageCounter(cid, attacker, value)
    end
    return true
end

It seems to be all written in lua by Gesior.
Maybe we can manage to make it work and leave it for other users because i've see many threads related to this issue (0hp in temple).



------------------Update-------------------
Just found a code that works with preparedeath. Player is getting tped to temple without dying.


Code:
function onPrepareDeath(cid, deathList)
    if getPlayerLevel(cid) < 200 then
        doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
        doCreatureAddHealth(cid, getCreatureMaxHealth(cid), 65535, 256, true)
        doCreatureAddMana(cid, getCreatureMaxMana(cid))
        doRemoveConditions(cid, false)
        return false
    end
    return true
end
We can just adapt this to yours and test
Post automatically merged:



Update; And it worked! thank you @Evil Puncker
 
Last edited:
Well.. deathlist receiving experience, cid not "dying" and can move on(just tped).
only thing missing is dead body in the right place, it's being created in temple.

Ok now body is on right place. Everything works!
 
okay my bad, seems like the only way to go is to use onstatschange, because onpreparedeath is executed when character is already dead:

but them we go back to your first issue that is to find a way to give exp to everyone involved in the kill (deathList) but since onstatschange doesn't return a damage map, this is not possible, I don't know what else we can do
Actually it isn't exactly true, return false in onPrepareDeath stop the player from dying however it didn't work because doCreatureAddHealth at this stage needs to be called with force parameter set to true and which parameter it is depends on which server version exactly it is.
example:
Code:
doCreatureAddHealth(uid, health[, hitEffect[, hitColor[, force]]])
 
Back
Top