Jump to content

remove item from floor


The_Real_Al

Recommended Posts

This is Al and you're listening to QWESBISO:

 

I'm trying to make an item somewhat sticky. That is, i would like it to return to the inventory immediately after dropping. That's how i would do it:

Mytable = {}Mytable.myFunction = function()    myAxe = getPlayer():getInventory():FindAndReturn("Axe");        if getPlayer():getInventory():contains(myAxe) == true then        return        elseif getPlayer():getInventory():contains(myAxe) ~= true then            getPlayer():getInventory():setDrawDirty(true);            myAxe:getContainer():Remove(myAxe);            --            There be dragons                getPlayer():getInventory():addItem(myAxe);        endendEvents.OnPlayerUpdate.Add(Mytable.myFunction);

 

Works well except for removing the item from the ground. After looking into ISGrabItemAction.lua i've tried the following:

myAxe:getSquare():getWorldObjects():remove(myAxe);   myAxe:getSquare():getObjects():remove(myAxe);

No luck. What am i missing?

Link to comment
Share on other sites

Just a small suggestion for your code, if you don't mind (please don't take this as an offense ;)):

 

 

Mytable = {}function Mytable.myFunction()    -- make this local    local inv = getSpecificPlayer(0):getInventory();    local myAxe = inv:FindAndReturn("Axe");    if inv:contains(myAxe) then        return;    elseif not inv:contains(myAxe) then        inv:setDrawDirty(true);        myAxe:getContainer():Remove(myAxe);        -- Dragons are here        inv:addItem(myAxe);    endendEvents.OnPlayerUpdate.Add(Mytable.myFunction);
 

 

You should make variables in functions always local. I stored "getSpecificPlayer(0):getInventory()" as a local variable which makes the code a bit easier to read.

 

 

 if getPlayer():getInventory():contains(myAxe) == true then
 

 

can be written as

 

 if getPlayer():getInventory():contains(myAxe) then
 

 

because lua treats every value other than nil and false as true

 

Same thing goes for

 

    elseif not inv:contains(myAxe) then
 

 

"not" inverts the if statement. Imagine it as "if not true do ..."

Link to comment
Share on other sites

Not at all. You've been a huge help all along. Just tell me if i wear you out with all these amateurish mistakes and questions. :-)

 

I usually use local variables but in that special case i want to make sure that this specific item is carried over into another table. Appears to me as the easiest way as long as i don't name it something too simple like 'item' (or 'myAxe' for that matter). But if there is a better or casual way to do this, please, fire away. My first idea was to use getModData() until i read that it's only good for strings and numbers.

 

At first i thought that the syntax is pretty unforgiving, but the more i dive into it the more i figure that it's also a matter of style and convention. That said, i agree on the readability-part. The sentence 'lua treats every value other than nil and false as true' i read in the manual. Good to see it in context.

 

I'm actually trying myself on a custom profession and the idea is to give it a weapon which you cannot unequip. With your suggestions as follows:

MightyPirate.startItems = function()    local MPProfession = getSpecificPlayer(0):getDescriptor():getProfession()    if    MPProfession == "pirate" then        getPlayer():getInventory():AddItem("MightyPirate.PirateHook");--        print("Arm yer pegleg");    endendMightyPirate.defineMPHook = function()    if    MPProfession == "pirate" then        MPHook = getPlayer():getInventory():FindAndReturn("PirateHook")--    print("Hook defined")    endendMightyPirate.restoreMPHook = function()    if    MPProfession == "pirate" then            local player = getPlayer();        local inv = player:getInventory();        local priHand = player:getPrimaryHandItem();                if MPHook == priHand then--            print("present Hook")        return            elseif MPHook ~= priHand and inv:contains(MPHook) then            player:setPrimaryHandItem(MPHook);--            print("Equipped Hook")            elseif MPHook ~= priHand and not inv:contains(MPHook) then                        inv:setDrawDirty(true);            inv:addItem(MPHook);            MPHook:getWorldItem():getSquare():getWorldObjects():remove(MPHook:getWorldItem())            MPHook:getWorldItem():getSquare():getObjects():remove(MPHook:getWorldItem());            player:setPrimaryHandItem(MPHook)            getPlayerData(0).playerInventory:refreshBackpacks();            getPlayerData(0).lootInventory:refreshBackpacks();--            print("Restored Hook")        end    endend Events.OnNewGame.Add(MightyPirate.startItems);Events.OnGameStart.Add(MightyPirate.defineMPHook);Events.OnPlayerUpdate.Add(MightyPirate.restoreMPHook);

 

That works quite well. Whenever you try to unequip or drop the item, it's immediately returned to your inventory and primary hand. However, even to me this seems bulky.

 

An 'OnUnequip' event is already in the lua-suggestions but not yet implemented afaict. That would mean i could drop the 'OnPlayerUpdate'.

 

Is there a way to stop a timed action automatically when it handles a specific item?

 

Also, any other way to assign a specific item from the inventory to a variable? 'FindAndReturn' seems handy if there is only one of it guaranteed.

 

Also also, does it make sense to write a line like 'if ... then return' in the beginning of a block without anything actually happening? That would end the block and hereby save resources, right?

Link to comment
Share on other sites

It would probably be easier to overwrite the vanilla itemmenu and prevent it from displaying the "unequipd" context for your item. Another idea would be to spam " player:setPrimaryHandItem(MPHook);" in an OnPlayerUpdate event ... not sure if that would be any less wonkier though :D

 

 

Is there a way to stop a timed action automatically when it handles a specific item?

Which TimedAction are you talking about? You could write your own TimedAction that does the same as the vannila one, but rules out your item.

 


Also, any other way to assign a specific item from the inventory to a variable? 'FindAndReturn' seems handy if there is only one of it guaranteed.

 

You can use the "AddItem" function that you call in your "OnNewGame" event.

 

MightyPirate = {};MightyPirate.mightyHook = nil; function MightyPirate.startItems()    local mightyProfession = getSpecificPlayer(0):getDescriptor():getProfession();    if mightyProfession == "pirate" then        -- store Item in global table        MightyPirate.mightyHook = getSpecificPlayer(0):getInventory():AddItem("MightyPirate.PirateHook");    endend

 

Just remember that you will have to load the item on the next OnGameLoad / Start event. There I'd just use the FindAndReturn function.

 


Also also, does it make sense to write a line like 'if ... then return' in the beginning of a block without anything actually happening? That would end the block and hereby save resources, right?

 

In most cases it won't make a difference in terms of performance, but I tend to do it anyway. The sooner you break out of a function the better. I especially use it in big functions where (e.g. new context menus), where I do several checkpoints that decide wether the function should be stopped (return) or continue. But don't overdo it.

 

There are two general rules for optimisation:

1. Don't do it.

2. Don't do it now.

 

;)

 


 

Just another thing on code convention (as before these are just my preferences):

 

If you use global variables in your code they still should be contained in your main table. E.g.:

MightyPirate = {}MightyPirate.mpHook = nil; function MightyPirate.doStuff()   if not MightyPirate.mpHook then       ...   endend

 

I would also keep variables lowercase and only the global table uppercase... that's the Java convention, but you also can immediatly see which variables are global and which are local. The uppercase MPHook had me confused for the first few seconds :)

Link to comment
Share on other sites

easier to overwrite the vanilla itemmenu ... (or) ... spam " player:setPrimaryHandItem(MPHook);" in an OnPlayerUpdate

Easier? Sir, this humour is buoyant and most delectable, indeed. I believe i could, but messing with forces i don't yet fully understand is scary. Plus, i would need to not only tinker with the inventory context menu but also with drag/drop. A lot of mess when a single 'OnUnequip' event - as already mentioned in the lua-suggestions thread - would do the trick.

 

The setPrimaryItem() on OnPlayerUpdate is already in, but unfortunately this alone doesn't care for the location of the item. In other words you can easily assign and use an item in your hands which is stuffed into a container on the other side the map. The rest of the function tries to prevent just that.

 

 

Which TimedAction are you talking about? You could write your own TimedAction that does the same as the vannila one, but rules out your item.

That would be ISDropItemAction.lua. But i believe i would rather need to overwrite the function that actually calls it because doing my own Timed Action wouldn't stop ISDropItemAction from performing. Which brings me full circle back to the context menu and drag/drop.

 

Edit: Nevermind the bollocks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...