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

[1.0] onDeath loot handled in Lua

Red

Cyntara.org
Staff member
Global Moderator
Premium User
Joined
Aug 9, 2008
Messages
4,455
Solutions
2
Reaction score
921
Location
United States
Hey guys,

A few weeks ago I worked on converting onDeath events to Lua for more flexibility. The first of my endeavors was working with items.
This is the result. It does not work.
Selected items are not sent to the corpse. I've got no idea what's wrong with the code or even how to get it to work. So I decided to leave it here. If someone can get it working, hopefully it can be added to the official repository.
I know lots of servers want to change the default way items are handled on death.

Code:
function onDeath(cid, corpse, killer, mostDamage, unjustified, mostDamage_unjustified)
   local player = Player(cid)
   if not player then
     return
   end

   local corpse = Container(corpse)
   if not getPlayerFlagValue(cid, PlayerFlag_NotGenerateLoot) and player:getVocation() ~= VOCATION_NONE then
     local amulet = player:getSlotItem(CONST_SLOT_NECKLACE)
     if amulet and amulet:getId() == ITEM_AMULETOFLOSS and player:getSkull() ~= SKULL_RED and player:getSkull() ~= SKULL_BLACK then
       local blessings = 0
       for i = 1, 5 do
         if player:hasBlessing(i) then
           blessings = blessings + 1
         end
       end

       if blessings < 5 then
         player:removeItem(ITEM_AMULETOFLOSS, 1, -1, false)
       end
     else
       local item
       for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
         item = player:getSlotItem(i)
         if item then
           -- is player:getDeathPenalty() the correct function?
           if (player:getSkull() == SKULL_RED or player:getSkull() == SKULL_BLACK) or math.random(1, item:isContainer() and 10 or 100) <= player:getDeathPenalty() then
             item:moveTo(corpse) -- item(s) won't send to corpse
           end
         end
       end
     end
   end

   if not player:getSlotItem(CONST_SLOT_BACKPACK) then
     player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK)
   end
end

Cheers,
Red
 
Note: I've also tried a small rework to replace "corpse."
Code:
          if (player:getSkull() == SKULL_RED or player:getSkull() == SKULL_BLACK) or math.random(1, item:isContainer() and 10 or 100) <= 10 then
             local body = Tile(player:getPosition()):getTopDownItem()
             item:moveTo(Container(body)) -- this returns nil
           end

So no dice there, either. Just a separate thought.
Red
 
I'm not so into newest TFS, but onDeath, I believe that mean YOUR character's death.
the function you're looking for is onKill, which calls the things you KILLED :D

Correct functions and how to use it, you can find in your servers sources =)

edit: I'm tired as fuck, can barely read..
I'm starting to believe it's something else you're looking for.. not sure thou
 
Your info is good Legerian. onKill() is sufficient. That's why I asked the OP to test onDeath() is being called. It could be defined as a facade for onKill(), but it might not exist at all.
 
if you want to apply your script to all monsters use onKill, it will be more efficient

onDeath has to be registered directly on creature (as it's done in login.lua for players)
example:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Frostwing" nameDescription="the frostwing" race="undead" experience="7500" speed="260" manacost="0">
   <health now="18000" max="18000"/>
   <look type="248" corpse="7091"/>
   <targetchange interval="5000" chance="12"/>
   <strategy attack="100" defense="0"/>
   <script>
   <event name ="AI_monster_death"/>
   <event name ="AI_monster_think"/>
   <event name ="AI_monster_kill"/>
   <event name ="AI_monster_hit"/>
   </script>
...

also keep in mind "corpse" is same thing as "item" in action/movement(you may read it's .uid, .actionid, .itemid and .type)

Code:
  function onDeath(cid, corpse, deathList)
     doAddContainerItem(corpse, 2365, 2)
     return true
   end

Code:
<event type="death" name="AI_monster_death" script="AI_monster.lua"/>

wow! I've tested it now. It even shows added items in loot message!
16:03 Loot of the frostwing: 79 gold coins, a green mushroom, a golden mug, a backpack of holding, a backpack of holding
 
Last edited:
It's meant to be for players, and the onDeath event is called. He's just having troubles with moving the items with item:moveTo(position) and position is supposed to be the corpse container.

You could use corpse:addItemEx(item:clone()) to clone the slot items, and then use item:remove() to remove the items from the player.
 
oh...
if it's this way just use doPlayerTakeItem(cid, id, amount) and doAddContainerItem(corpse, id, amount)
 
It's meant to be for players, and the onDeath event is called. He's just having troubles with moving the items with item:moveTo(position) and position is supposed to be the corpse container.

You could use corpse:addItemEx(item:clone()) to clone the slot items, and then use item:remove() to remove the items from the player.

Thank you! This seems like the proper solution to the issue. I only have one more concern with the code.
My player is fully blessed and player:getDeathPenalty() returns "1."
Code:
math.random(1, item:isContainer() and 10 or 100) <= player:getDeathPenalty()

Do you believe a proper solution would be to change the code to:
Code:
math.random(1, item:isContainer() and 10 or 100) < player:getDeathPenalty()

The code is written the way it is because I was trying to almost literally translate the source code:
Code:
if (playerSkull == SKULL_RED || playerSkull == SKULL_BLACK || uniform_random(1, (item->getContainer() ? 100 : 1000)) <= getDropPercent())

But getDropPercent returns "0" in the source.
tl;dr - do you think it's an issue with the Lua function or should I just change the operator?

EDIT: Or I could just as easily define deathPenalty and convert "1" to "0" with a simple ternary statement.

oh...
if it's this way just use doPlayerTakeItem(cid, id, amount) and doAddContainerItem(corpse, id, amount)

I'm sure your solution works as well, but I feel I'll have better luck getting the code into the official repository if I use metatables.
Red
 
Last edited:
Back
Top Bottom