====== Drop basins with viewer comments ====== This VCI drops "basins" with comments that include string "basin". * Why basin? It's a reference to a classic Japanese TV show. === Example data === https://virtualcast.jp/products/220a18dd3f7064ad9508e3a633bb66b94ab0ea6c89dbf998aa2017a6b5f4f9d7 ===== SubItem configuration ===== {{vci:sample:message:vcitarai.png?direct&600|}}\\ Place basins T1 ~ T16 as grabbable SubItems with a scale of 0.01. {{vci:sample:message:vcitaraicoll.png?direct&400|}} 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 ===== -- 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 [[en:vci:script:tips:stringsearch]]. ==== 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.