• Reference
  • LUA API
  • Example
  • NPC Communication

Communication with NPC

In practice, we often encounter situations where we need to talk to NPCs, so here is a simple implementation of the "NPC Talk" function.

Brief Introduction

  1. camera follows unit movement
  2. Automatic selection of the unit to be operated
  3. Click on each NPC to bring up the information screen (dialogue screen) of the corresponding NPC
  4. Press ECS to close the information screen (dialogue screen)

Code

Methods

do
	local boolNPCTalk = false -- Determining if you are in a conversation
	
	-- Display unit information
	function showUnitInfo(unit)
		-- get data
		local unitKey = unit:get_key()
		local headIconID = unit:get_icon()
		local bodyIconID = cli.get_unit_type_kv(unitKey, "UIKey")
		local unitName = unit:get_name()
		local unitDesc = cli.get_unit_desc(unitKey) --?? why descrip is not print? but it show on the UI
		local talkContent = cli.get_unit_type_kv(unitKey, "talk")
		-- write data
		local player = cli.player(1)
		local imageKeyHead = "8f8e2abf-d3e8-46f4-9390-f4aea1b16a64"
		cli.ui:set_image(imageKeyHead, headIconID, player)
		local imageKeyBody = "79c1cd94-b894-4a4c-81e0-6a10120e7872"
		cli.ui:set_image(imageKeyBody, bodyIconID, player)
		local textKeyName = "04df68a1-a9cb-432d-af29-b1a4560f1efc"
		cli.ui:set_text(textKeyName, unitName, player)
		local textKeyNameDesc = "dfe6540f-6633-461d-beb5-43e66807c621"
		cli.ui:set_text(textKeyNameDesc, unitDesc, player)
		local textKeyTalkContent = "e705e844-217e-41ac-ab91-6aba6e3b6b84"
		cli.ui:set_text(textKeyTalkContent, talkContent, player)
	end
 
	-- Communication with NPC
	function conversationWithNPC(unitSend, unitAccept)
		local playerSend = unitSend:get_player()
		if boolNPCTalk then
			playerSend:msg("No new conversation is currently available!")
		else
			boolNPCTalk = true -- into conversation
			showUnitInfo(unitAccept)
			local talkElement = "58abace0-a760-4e6d-a116-f924e878e314"
			cli.ui:set_enable(talkElement, true, playerSend)
			-- poll judge distance
			cli.timer(1, 0, function(timer)
				local boolSwich = false -- whether to leave the chat area
				-- judge distance
				local pointUnitSent = unitSend:get_point()
				local pointUnitAccept = unitAccept:get_point()
				local distance = pointUnitSent * pointUnitAccept
				if distance >= 500 then
					boolSwich = true
					playerSend:msg("Too far away, conversation ends!")
				end
				if not boolNPCTalk then
					boolSwich = true
				end
				-- gc
				if boolSwich then
					hideConversationUI(playerSend) -- hide conversation UI
					boolNPCTalk = false
					timer:remove()
				end
			end)
		end
	end
	
	-- Game initialization setup
	function GameInit()
		local player = cli.player(1)
		local unit = cli.actor_unit(20)
		player:select(unit)
		player:camera_focus(unit)
	end
	
	-- Hide conversation UI
	function hideConversationUI(player)
		local talkElement = "58abace0-a760-4e6d-a116-f924e878e314"
		cli.ui:set_enable(talkElement, false, player)
	end

Events

	-- Game initialisation events
	cli.game:event("Game-Init", function()
		GameInit() -- game init
	end)
	
	-- Player selected unit event
	cli.game:event("Unit-SingleSelect", function(tri, ...)
		local args = {...}
		local unit = cli.actor_unit(20)
		local player = unit:get_player()
		if args[2]:get_key() ~= unit:get_key() and
		args[1]:get_id() == player:get_id()
		then
			player:select(unit)
			local unitPoint = unit:get_point()
			local args2Point = args[2]:get_point()
			local distance = unitPoint * args2Point
			if distance < 400 then
				conversationWithNPC(cli.actor_unit(20), args[2]) -- go conversation
			else
				player:msg("Too far away to talk!")
			end
		end
	end)
	
	-- Keyboard press events
	cli.game:event("Keyboard-Down", function(tri, ...)
		local args = {...}
		if args[1]:get_id() == 1 and args[2] == KEY["ESC"] then
			boolNPCTalk = false
		end
	end)
end

Download

link unvailable for now.