helix icon indicating copy to clipboard operation
helix copied to clipboard

Add OnAreaLeft, OnAreaAdded and OnAreaRemoved hooks

Open OffLegAz opened this issue 3 years ago • 6 comments

OffLegAz avatar Jun 20 '21 13:06 OffLegAz

Hooks are expensive which is why we keep them to a minimum

alexgrist avatar Jun 20 '21 22:06 alexgrist

Hooks are expensive which is why we keep them to a minimum

No doubt they are, but let's assume I have more than 1 area type, for example, 5, and I have to do something with them every area tick. And so, will it be worth creating 4 additional timers, rather than using OnAreaThink hook?

OffLegAz avatar Jun 20 '21 22:06 OffLegAz

Hooks are expensive which is why we keep them to a minimum

No doubt they are, but let's assume I have more than 1 area type, for example, 5, and I have to do something with them every area tick. And so, will it be worth creating 4 additional timers, rather than using OnAreaThink hook?

If you needed to create 4 timers you're probably doing it wrong

alexgrist avatar Jun 20 '21 22:06 alexgrist

Hooks are expensive which is why we keep them to a minimum

No doubt they are, but let's assume I have more than 1 area type, for example, 5, and I have to do something with them every area tick. And so, will it be worth creating 4 additional timers, rather than using OnAreaThink hook?

If you needed to create 4 timers you're probably doing it wrong

I don't think so. I was making forbidden area type, like in some videogames - if you leave the battle area, you are being told to turn back and if you ignore it for 10 seconds you die. I found out that area plugin has no hooks to identify if player left or just walked in area and came to this decision. But, actually, after talking about this PR I understood, that it would be better not to shoot from the hip, as I did here, and instead of making hook in timer, make 2 in AreaThink function. I will make make another commit soon, if I will not fall asleep

OffLegAz avatar Jun 20 '21 23:06 OffLegAz

if (CLIENT) then
	local nextThink = 0
	function PLUGIN:Think()
		if (nextThink > CurTime()) then return end
		nextThink = CurTime() + 0.33

		local client = LocalPlayer()
		if (!client:Alive() or !client:GetCharacter()) then return end

		local overlappingBoxes = {}
		local position = client:GetPos() + client:OBBCenter()

		for id, info in pairs(ix.area.stored) do
			if (position:WithinAABox(info.startPosition, info.endPosition)) then
				overlappingBoxes[#overlappingBoxes + 1] = id
			end
		end

		if (#overlappingBoxes > 0) then
			local oldID = client:GetArea()
			local id = overlappingBoxes[1]

			if (oldID != id) then
				hook.Run("OnAreaChanged", client.ixArea, id)
				client.ixArea = id
			end

			client.ixInArea = true
		else
			client.ixInArea = false
		end
	end
end

For the client-side, you can do.

For example, did the player leave the area? We do this.

if (client.battle_area_timer and client.battle_area_timer < CurTime()) then
	client:Kill()
	return
end

if (client.ixInArea) then
	local area = ix.area.stored[client:GetArea()]

	if (area and area["type"] == "my_area") then
		//
	end
elseif (!client.battle_area_timer) then // Example
	client.battle_area_timer = CurTime() + 10
end

-- Works in both directions.

Heyter avatar Jun 21 '21 22:06 Heyter

if (CLIENT) then
	local nextThink = 0
	function PLUGIN:Think()
		if (nextThink > CurTime()) then return end
		nextThink = CurTime() + 0.33

		local client = LocalPlayer()
		if (!client:Alive() or !client:GetCharacter()) then return end

		local overlappingBoxes = {}
		local position = client:GetPos() + client:OBBCenter()

		for id, info in pairs(ix.area.stored) do
			if (position:WithinAABox(info.startPosition, info.endPosition)) then
				overlappingBoxes[#overlappingBoxes + 1] = id
			end
		end

		if (#overlappingBoxes > 0) then
			local oldID = client:GetArea()
			local id = overlappingBoxes[1]

			if (oldID != id) then
				hook.Run("OnAreaChanged", client.ixArea, id)
				client.ixArea = id
			end

			client.ixInArea = true
		else
			client.ixInArea = false
		end
	end
end

For the client-side, you can do.

For example, did the player leave the area? We do this.

if (client.battle_area_timer and client.battle_area_timer < CurTime()) then
	client:Kill()
	return
end

if (client.ixInArea) then
	local area = ix.area.stored[client:GetArea()]

	if (area and area["type"] == "my_area") then
		//
	end
elseif (!client.battle_area_timer) then // Example
	client.battle_area_timer = CurTime() + 10
end

-- Works in both directions.

I've finished the plugin already. In the message where I was talking about forbidden area type, I've ment that there is currently only one way of cheking if player came in area more than 1 time or left it compleately, because of conditions OnAreaChanged is being called.

OffLegAz avatar Jun 22 '21 09:06 OffLegAz