Table of Contents

Drop basins with viewer comments

This VCI drops “basins” with comments that include string “basin”.

Example data

https://virtualcast.jp/products/220a18dd3f7064ad9508e3a633bb66b94ab0ea6c89dbf998aa2017a6b5f4f9d7

SubItem configuration


Place basins T1 ~ T16 as grabbable SubItems with a scale of 0.01.

Create a transparent collider at the hight of 20 (fixed) to keep the basins from falling

VCI cannot dynamically generate items. (as of 5th May 2019)
Therefore, place the items far away at the beginning, then move and scale them larger to make them look like they are spawning.

In this example, we will place a transparent collider at the hight of 20 and put 16 basins in a line at the height of 20.05. To make them invisible when seen from bellow, set the scale of the basins at the beginning to 0.01.
Name the SubItems in a way that is easy to process with “for” statement.

VCI script

main.lua
-- The number of the basin to fall next
local _basinNum = 1
 
--Trigger with a comment "basin" or "Basin"
function onMessage(sender, name, message)
 
    -- content of the comment
    print(sender["name"].."「"..message.."」")
 
    --true if the comment includes either "basin" or "Basin"
    local basin = false
    if string.find(message,"basin") ~= nil then
        basin = true
    end
    if string.find(message,"Basin") ~= nil then
        basin = true
    end
 
    if basin == true then
        print("Drop a basin")
        local pos = Vector3.__new(0, 5, 0)
        BasinFire(pos)
    end
end
vci.message.On('comment', onMessage)
 
-- Drop a basin at the position "pos"
function BasinFire(pos)
    local basin = "T"..tostring(_basinNum)
    _basinNum = _basinNum + 1
    if _basinNum > 16 then
        _basinNum = 1
    end
    pos.y = pos.y + 0.5 * _basinNum
    vci.assets.GetTransform(basin).SetLocalPosition(pos)
    vci.assets.GetTransform(basin).SetLocalScale(Vector3.one)
    print("The position to drop a basin: "..tostring(pos))
end
 
-- For debugging
function onGrab(targe)
    if targe == "DebugSwitch" then
        print("Debug switch")
        local pos = Vector3.__new(0, 5, 0)
        BasinFire(pos)
    end
end

VCI Script (Description)

The script is separated into two sections: the comment receiver and the loop process for the basin.

Comment receiver section

    --true if the comment includes either "basin" or "Basin"
    local basin = false
    if string.find(message,"basin") ~= nil then
        basin = true
    end
    if string.find(message,"Basin") ~= nil then
        basin = true
    end

You cannot send same comments consecutively in nico live.
Therefore, you will almost always have to use partial match when integrating comments in VCI.
By using a function “string.find()”, you can judge if the search string is included in the search target or not.
However, the return value of the find function is a number type when a match is found, and nil when a match is not found.
To be able to handle both types, *flag true when the return value of the find function is not nil.

If you want to match for more complex patterns, refer to How to search strings.

Drop process

function BasinFire(pos)
    local basin = "T"..tostring(_basinNum)
    _basinNum = _basinNum + 1
    if _basinNum > 16 then
        _basinNum = 1
    end
    pos.y = pos.y + 0.5 * _basinNum
    vci.assets.GetTransform(basin).SetLocalPosition(pos)
    vci.assets.GetTransform(basin).SetLocalScale(Vector3.one)
    print("The position to drop a basin: "..tostring(pos))
end

The drop process is to simply drop the basins in order of T1 to T16, and go back to T1. It looks pretty natural.
The twist here is that the drop height of each basin is offset with 0.5 * _basinNum so that they do not overlap with each other when comments came consecutively.

In this example, we set the drop position of the basin to (x=0, z=0). However, you can change the drop position by

- Creating a SubItem for the target
- Move the SubItem to scan for the position of the player and when the SubItem collides, drop the basin on that position.