How to drop items in Crayta

Introduction

Something we had to do for High Noon was implement a feature where the player would drop all of their collected gold when they died. We re-used the existing pickup logic for this, including some custom changes so that the dropped items wouldn’t respawn on a new round, and could only be picked up once.

Getting started

I’m assuming we’re in an empty world here, so the first step is to install the Inventory package from the community tab in your editor. If you’re creating a game from an existing template like Capture the Flag, this package will already be installed.

If you’re on a blank game, add the User Inventory template to the user template, and the Player Inventory View template to the player.

Next, add a trigger to the map, add the pickupSpawnerScript to it, any entity, and the inventoryItemSpecScript script. I used the ammo entity. Feel free to customize the properties on the pickupSpawnerScript at this point. For this example, we’re going to turn on “useOnCollision”, and “showOnInit”, and turn off “enableCollisionOnChildren” to keep things simple.

Now, create a template out of the result, and place a few instances of the template around the map. What we’re going to do is define a space to drop these off, and they’ll all fall on the ground.

Dropping items

Paint a square of the map a new color, to designate it as the dropoff zone, then add a trigger that covers the entirety. This is going to be our test zone.

Create a new script and add it to the player template, call it “dropItemsScript”, or whatever you fancy.

    local DropItemsScript = {}

    -- Define what template we want to drop from the inventory
    DropItemsScript.Properties = {
        { name = "templateToDrop", type = "template" }
    }

    function DropItemsScript:DropItems()
        -- The player's inventory exists on the user
        local user = self:GetEntity():GetUser()
        local inventory = user.inventoryScript

        -- Get the item we want to drop out of the inventory, this item will contain
        -- the number of items the user is carrying
        local item = inventory:FindItemForTemplate(self.properties.templateToDrop)

        -- If the user isn't carrying this item, we have nothing to drop
        if not item then return end

        -- We want to drop the items around the user, so store the user's position before starting to drop items
        local pos = self:GetEntity():GetPosition()

        -- We want to drop the items one at a time, so we can calculate new positions for all of them
        for i=1,item.count do

            -- Calculate a new position in in a circle around the user, at a max distance of 500
            local maxDistance = 500
            local newPosition = pos + (Vector.New(math.random(), math.random(), 0) * maxDistance) - Vector.New(maxDistance / 2, maxDistance / 2, 0)
            local drop = GetWorld():Spawn(self.properties.templateToDrop, newPosition, Rotation.Zero)

            -- Tell the pickup spawner script we don't went this item to respawn after being picked up
            drop.pickupSpawnerScript.properties.singlePickup = true

            -- show the pickup
            drop.pickupSpawnerScript:ShowPickup()
        end

        -- Remove all the items from the inventory
        inventory:RemoveFromItem(item, item.count)

    end

    return DropItemsScript

Notice we have a property on this script, you’ll want to set this to the ammoPickup we created earlier.

The property that we set called “singlePickup” doesn’t exist in the pickup spawner script, so we’ll have to add that. Open up the pickupSpawnerScript and add the property

{ name = "singlePickup", type = "boolean", default = false }

Now modify PickupSpawnerScript:Pickup(player) with

if self.properties.singlePickup then
    self:GetEntity():Destroy()
end

At the very bottom of the method.

Finally, in the trigger you added for your dropoff zone, set the OnTriggerEnter function to the DropItems method on the player.

You can check out a working example of this here: https://launch.crayta.com/play/dfr6rten