• 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!

CreatureEvent [TFS 1.2] Revive system + resurrection spell by Zbizu

Status
Not open for further replies.

zbizu

Legendary OT User
Joined
Nov 22, 2010
Messages
3,323
Solutions
26
Reaction score
2,690
Location
Poland
based on @Colors revive system

F8XBPaw.jpg


6JozE6f.jpg


QG9cjNK.jpg


groups.xml:
Code:
	<group id="0" name="player_dead" flags="13194139558159" access="0" maxdepotitems="0" maxvipentries="0" />

creaturescripts.xml:
Code:
<event type="preparedeath" name="modalDeath" script="modaldeath.lua"/>
    <event type="modalwindow" name="deathMW" script="modaldeath.lua"/>
    <event type="login" name="loginDeath" script="modaldeath.lua"/>

modaldeath.lua:
Code:
-- revive system by zbizu
-- config
	local deathStorage = 250120
	local counterStorage = 250121 -- res expiration timestamp
	local deathGroupId = 0
	local reviveStone = 2674 -- red apple, change it
	local resTime = 30 * 60 -- 30 minutes
	local showCountdown = true -- shows timer above dead player
-- end of config

local condition = Condition(CONDITION_OUTFIT)
condition:setTicks(-1)

function Player:setHealth(value)
	if not self:isPlayer() then return false end
	self:addHealth(value - self:getHealth())
return true
end

function Player:setMana(value)
	if not self:isPlayer() then return false end
	self:addMana(value - self:getMana(), false)
return true
end


function buildModalWindow(cid)
	local player = Player(cid)
	local resitem = player:getItemCount(reviveStone)
	
	local modal = ModalWindow(999, "You are dead", "Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto the world in exchange for a small sacrifice. " .. (resitem > 0 and "\n\n" .. ItemType(reviveStone):getName() .. " x" .. resitem or "") .. "\n\nIf you choose to return, logout or your time run\nout, death penatly will be applied.")

	modal:addButton(1, "Return")
	modal:setDefaultEnterButton(1)
	modal:addButton(2, "Wait")
	modal:setDefaultEscapeButton(2)

	if resitem > 0 then
		modal:addButton(3, "Use Item")
	end

	return modal:sendToPlayer(player)
end

function Player:isDead()
	return self:getGroup():getId() == deathGroupId
end

function Player:die()
	self:toggleDeath()
	self:setStorageValue(counterStorage, -1)
	self:setStorageValue(deathStorage, 1)
	self:addHealth(-(self:getMaxHealth()))
	return true
end

function sendDeathWindowOnMove(cid, lockPos)
	local player = Player(cid)
	if not player then return false end
	if not player:isDead() then
		return false
	end
	
	if os.time() > player:getStorageValue(counterStorage) then
		player:die()
		return true
	end
	
	addEvent(sendDeathWindowOnMove, 100, cid, lockPos)
	
	if player:getPosition() ~= lockPos then
		player:teleportTo(lockPos)
		buildModalWindow(cid)
	end
	
	return true
end

function sendReviveCountdown(cid)
	if not showCountdown then return false end
	local player = Player(cid)
	if not player then return false end
	if not player:isDead() then
		return false
	end
	
	local timeleft = os.date("!%X",player:getStorageValue(counterStorage) - os.time()):split(":")
	
	
	player:say(timeleft[2] .. ":" .. timeleft[3], TALKTYPE_MONSTER_SAY)
	addEvent(sendReviveCountdown, 1000, cid)
	return true
end

function Player:toggleDeath(countdown)
	if self:isDead() then
		self:setGroup(Group(1))
		self:setHiddenHealth(false)
		self:setHealth(math.ceil(self:getMaxHealth() * 0.3))
		self:setMana(math.ceil(self:getMaxMana() * 0.3))
		self:removeCondition(CONDITION_OUTFIT)
		return true
	end
	
	if countdown then
		self:setStorageValue(counterStorage, os.time() + countdown)
	end
	
	self:setGroup(Group(deathGroupId))
	self:setHiddenHealth(true)
	buildModalWindow(self:getId())
	
	local pos = self:getPosition()
	sendDeathWindowOnMove(self:getId(), pos)
	sendReviveCountdown(self:getId())
	
	local npos = Position(pos.x + 1, pos.y, pos.z)
	if not Tile(npos) then
		Game.createTile(npos)
	end
	
	self:teleportTo(npos, true)
	return true
end

function onLogin(player)
	player:registerEvent("modalDeath")
	player:registerEvent("deathMW")
	player:registerEvent("loginDeath")

	if player:isDead() then
		if player:getStorageValue(counterStorage) == -1 then
			player:toggleDeath()
			return true
		end
		
		if os.time() > player:getStorageValue(counterStorage) then
			player:die()
			return true
		end
		
		player:setHiddenHealth(true)
		sendDeathWindowOnMove(player:getId(), player:getPosition())
		sendReviveCountdown(player:getId())
	end

	return true
end

function onPrepareDeath(creature, killer)
-- pvp kills may act weird
	if not creature:isPlayer() then
		return true
	end
	
	if creature:getStorageValue(deathStorage) == 1 then
		creature:setStorageValue(deathStorage, -1)
		return true
	end
	
	creature:toggleDeath(resTime)
	condition:setOutfit(creature:getSex() == PLAYERSEX_FEMALE and 3065 or 3058)
	creature:addCondition(condition)
	return false
end

function onModalWindow(player, modalWindowId, buttonId, choiceId)
	if modalWindowId ~= 999 then
		return false
	end
	
	if not player:isDead() then
		return false
	end
	
	if buttonId == 1 then
		player:die()
		return true
	elseif buttonId == 2 then
		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You decided to wait for a healer. Move in any direction to send revival window again.")
		return true
	elseif buttonId == 3 then
		if player:getItemCount(reviveStone) == 0 then
			player:sendCancelMessage("You don't have any item to revive yourself.")
			return true
		end
		
		player:getItemById(reviveStone, true):remove(1)
		player:toggleDeath()
		local revst = ItemType(reviveStone)
		player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You revived yourself with " .. revst:getArticle() .. " " .. revst:getName() .. ".")
	end
	return true
end
 
Last edited:
resurrection spell (spells/scripts/res.lua):
Code:
local deathGroupId = 0
function Player:isDead()
	return self:getGroup():getId() == deathGroupId
end

function onCastSpell(creature, var, isHotkey)
	local position = creature:getPosition()
	local manaCost = math.ceil(creature:getMaxMana() * 0.3)
	if creature:getMana() < manaCost then
		creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA)
		position:sendMagicEffect(CONST_ME_POFF)
		return false
	end

	local target = Player(variantToNumber(var))
	if not target then
		creature:sendCancelMessage("Incorrect target.")
		position:sendMagicEffect(CONST_ME_POFF)
		return false
	end
	
	if creature:getPosition():isSightClear(target:getPosition()) then
		if target:isDead() then
			creature:addMana(-manaCost, false)
			creature:addManaSpent(manaCost)
			
			target:setGroup(Group(1))
			target:setHiddenHealth(false)
			
			target:addMana(math.ceil(target:getMaxMana() * 0.3) - target:getMana(), false)
			target:addHealth(math.ceil(target:getMaxHealth() * 0.3) - target:getHealth())
			target:removeCondition(CONDITION_OUTFIT)
			
			target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have been resurrected by " .. creature:getName() .. ".")
			return true
		end
		creature:sendCancelMessage("You cannot resurrect this target.")
		position:sendMagicEffect(CONST_ME_POFF)
		return false
	end
	
	creature:sendCancelMessage("Target unreachable.")
	position:sendMagicEffect(CONST_ME_POFF)
	return false
end

spells.xml:
Code:
	<instant group="healing" spellid="84" name="Resurrect Friend" words="exura mort sio" lvl="200" mana="0" prem="1" aggressive="0" blockwalls="1" needtarget="1" playernameparam="1" params="1" exhaustion="15000" groupcooldown="1000" needlearn="0" script="res.lua">
		<vocation name="Druid" />
		<vocation name="Elder Druid" />
	</instant>
 
Last edited:
oh nice job i'll try it out =)
 
Good thing that finally someone did (or show) something nice with the system :p
Just one question, I see that you took the part where I teleported the player to the temple, now how the player is getting off the monster targets?
 
Good thing that finally someone did (or show) something nice with the system :p
Just one question, I see that you took the part where I teleported the player to the temple, now how the player is getting off the monster targets?

The player can wait until someone kill monsters around.
Resurrected player respawn with 30% of his max hp and mp, sometimes it's enough to run away.
Otherwise death is death, they should accept their fate and return to temple ^^ Let's not ruin the game.

btw. copied group flags from @Colors script and I still have no idea what are first(or last) two flags:
13194139558159 - dead player flags
it's 1100 0000 (flags 36-43) ... 0110 0001 0000 1111 (flags 0-15)
1100 <- flag 43 and 42 are enabled, tfs has 37 flags as far as I know

edit: area spell
nCPtQMf.jpg


spells.xml:
Code:
	<instant group="healing" spellid="82" name="Mass Resurrection" words="exura mort mas res" lvl="300" mana="0" prem="1" aggressive="0" exhaustion="120000" groupcooldown="1000" needlearn="0" script="area_res.lua">
		<vocation name="Druid" />
		<vocation name="Elder Druid" />
	</instant>

spells/scripts/area_res.lua:
Code:
local deathGroupId = 0
function Player:isDead()
	return self:getGroup():getId() == deathGroupId
end

function onTargetCreature(creature, target)
	local player = creature:getPlayer()
	local position = player:getPosition()

	if not target then return true end
	if not target:isPlayer() then return true end
	if not target:isDead() then return true end
	if not player:getPosition():isSightClear(target:getPosition()) then
		return true
	end
	
	target:setGroup(Group(1))
	target:setHiddenHealth(false)
	
	target:addMana(math.ceil(target:getMaxMana() * 0.3) - target:getMana(), false)
	target:addHealth(math.ceil(target:getMaxHealth() * 0.3) - target:getHealth())
	target:removeCondition(CONDITION_OUTFIT)
	
	target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have been resurrected by " .. creature:getName() .. ".")
	return true
end

local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))
combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature")

function onCastSpell(creature, var)
	local manaCost = math.ceil(creature:getMaxMana() * 0.7)
	
	if creature:getMana() < manaCost then
		creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA)
		position:sendMagicEffect(CONST_ME_POFF)
		return false
	end
	
	creature:addMana(-manaCost, false)
	creature:addManaSpent(manaCost)
	return combat:execute(creature, var)
end


btw. anyone has idea how to reset closest monsters targetting?
 
Last edited:
The player can wait until someone kill monsters around.
Resurrected player respawn with 30% of his max hp and mp, sometimes it's enough to run away.
Otherwise death is death, they should accept their fate and return to temple ^^ Let's not ruin the game.

btw. copied group flags from @Colors script and I still have no idea what are first(or last) two flags:
13194139558159 - dead player flags
it's 1100 0000 (flags 36-43) ... 0110 0001 0000 1111 (flags 0-15)
1100 <- flag 43 and 42 are enabled, tfs has 37 flags as far as I know

edit: area spell
nCPtQMf.jpg


spells.xml:
Code:
    <instant group="healing" spellid="82" name="Mass Resurrection" words="exura mort mas res" lvl="300" mana="0" prem="1" aggressive="0" exhaustion="120000" groupcooldown="1000" needlearn="0" script="area_res.lua">
        <vocation name="Druid" />
        <vocation name="Elder Druid" />
    </instant>

spells/scripts/area_res.lua:
Code:
local deathGroupId = 0
function Player:isDead()
    return self:getGroup():getId() == deathGroupId
end

function onTargetCreature(creature, target)
    local player = creature:getPlayer()
    local position = player:getPosition()

    if not target then return true end
    if not target:isPlayer() then return true end
    if not target:isDead() then return true end
    if not player:getPosition():isSightClear(target:getPosition()) then
        return true
    end
   
    target:setGroup(Group(1))
    target:setHiddenHealth(false)
   
    target:addMana(math.ceil(target:getMaxMana() * 0.3) - target:getMana(), false)
    target:addHealth(math.ceil(target:getMaxHealth() * 0.3) - target:getHealth())
    target:removeCondition(CONDITION_OUTFIT)
   
    target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have been resurrected by " .. creature:getName() .. ".")
    return true
end

local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, 0)
combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE)
combat:setArea(createCombatArea(AREA_CIRCLE3X3))
combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature")

function onCastSpell(creature, var)
    local manaCost = math.ceil(creature:getMaxMana() * 0.7)
   
    if creature:getMana() < manaCost then
        creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA)
        position:sendMagicEffect(CONST_ME_POFF)
        return false
    end
   
    creature:addMana(-manaCost, false)
    creature:addManaSpent(manaCost)
    return combat:execute(creature, var)
end


btw. anyone has idea how to reset closest monsters targetting?

Maybe on the creaturescript, making the group for dead player untargetable (flags maybe?) if flags doesn't works, maybe the creaturescript making the group used for dead player untargetable :p
 
Maybe on the creaturescript, making the group for dead player untargetable (flags maybe?) if flags doesn't works, maybe the creaturescript making the group used for dead player untargetable :p
and register event for closest targets only, great idea!
 
and register event for closest targets only, great idea!

I'm not even a newbie scripter, but i think this does the trick:

(From Colors thread/script)
Code:
player:addHealth(-player:getHealth())

If what i think is right, this sets the player HP to 0 while you choice an option, making the monsters change target since the "dead" player have 0 HP..
Just a small idea, not sure about it xD

Edit:

If player teleports/revive then this gives back the hp

Code:
if buttonId == 1 then
player:applyDeathAttributes(false)
player:removeCondition(CONDITION_OUTFIT)
player:teleportTo(Town(choiceId):getTemplePosition())
player:addHealth(player:getMaxHealth())
player:addMana(player:getMaxMana())
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "[onModalWindow] USED THE FUCKING REVIVE.")
end

I hope this make it easier :p
 
Last edited:
I need to do the trick without actually killing the player, 0 hp kills the player so I don't think it's possible
First post updated. Fixed monsters issue and hp.
 
Last edited:
I need to do the trick without actually killing the player, 0 hp kills the player so I don't think it's possible
I already told you what you changed what is causing this issue, you got it wrong.

And the death flag:
Can not be attacked
Ignored by monsters
Can not use combat
Can not attack players
Can not attack monsters
Cannot use spells
Cannot pickup items
Can not move items
Can not move creatures
 
@zbizu Is there a way to bypass when in pvp arena?
 
Last edited:
@Caduceus
below
Code:
function onPrepareDeath(creature, killer)
add position checking (if statement) and put return true inside
 
There is somthing wrong here.

Code:
function onPrepareDeath(creature, killer)
-- not sure if counts kill on pvp
    if not creature:isPlayer() then
        return true
    end
   
    if creature:getStorageValue(deathStorage) == 1 then
        creature:setStorageValue(deathStorage, -1)
        return true
    end
   
    creature:toggleDeath(resTime)
    condition:setOutfit(creature:getSex() == PLAYERSEX_FEMALE and 3065 or 3058)
    creature:addCondition(condition)
    return false
end
 
Hello guys! Did anyone fix the problem where the creatures keep attacking you while you are waiting for res?
 
Hello guys! Did anyone fix the problem where the creatures keep attacking you while you are waiting for res?
The solution is in this thread. Try learning some scripting instead of asking for spoonfed.
 
Status
Not open for further replies.
Back
Top