Jump to content

Need help with ListenForEvents


Recommended Posts

I'm working on a mod that the current health of all connected players onscreen inside a badge. however, I'm pretty(read:completely) new to modding and I'm unsure how ListenForEvent works. 

For example, I have this code:

AddClassPostConstruct("widgets/statusdisplays", function(self)
    self.badgearray= {}
    for i=0,5 do -- make 6 of these
        self.badgearray[i]=self:AddChild(custombadge(self,self.owner))
        self.badgearray[i]:SetPosition((-100-spacing*i),100,0)


        self.badgearray[i]:HideBadge(GlOBAL.Allplayers[i])-- call this on any login
        self.badgearray[i]:SetPercent(GlOBAL.Allplayers[i].components.health.GetPercent)-- call this when GLOBAL.Allplayers[i] sends a deltahealth
        
    end
end)

 

Where custombadge has the functions HideBadge() and SetPercent(). 

I would like to , whenever a player's health changes, call the function SetPercent() in a corresponding badge. in addition, I would like to call the function HideBadge()  whenever a player logs in or out, as well as on initialization. 

 

If anyone could help, I would greatly appreciate it. 

 

Link to comment
Share on other sites

there's a "Health Info" mod that might be helpful. My guess as to the event you need to call for the health delta (at least when taking damage) would be whatever is called when the character's hurt sound is played. I'm guessing this is in the player_common.lua file

Link to comment
Share on other sites

Health component's DoDelta pushes healthdelta event:

self.inst:PushEvent("healthdelta", { oldpercent = old_percent, newpercent = self:GetPercent(), overtime = overtime, cause = cause, afflicter = afflicter, amount = amount })

Thus you might try something like:

GLOBAL.AllPlayers[i]:ListenForEvent("healthdelta", function(inst, data)
    self.badgearray[i]:SetPercent(data.newpercent) -- call this when GLOBAL.Allplayers[i] sends a deltahealth
end)

player_common pushes many events: playeractivated, playerdeactivated, playerentered, ms_playerjoined, playerexited, ms_playerleft, ms_playerspawn; I am not sure however, when are which pushed, you might want to try them out / look at other parts of the game's code or other mods how they handle them.

Also, it should be noted, most of this will only work on server/host, since only server/host knows about all joined players and has access to their health.

 

Edited by Muche
Link to comment
Share on other sites

14 hours ago, Muche said:

Health component's DoDelta pushes healthdelta event:

self.inst:PushEvent("healthdelta", { oldpercent = old_percent, newpercent = self:GetPercent(), overtime = overtime, cause = cause, afflicter = afflicter, amount = amount })

Thus you might try something like:


GLOBAL.AllPlayers[i]:ListenForEvent("healthdelta", function(inst, data)
    self.badgearray[i]:SetPercent(data.newpercent) -- call this when GLOBAL.Allplayers[i] sends a deltahealth
end)

player_common pushes many events: playeractivated, playerdeactivated, playerentered, ms_playerjoined, playerexited, ms_playerleft, ms_playerspawn; I am not sure however, when are which pushed, you might want to try them out / look at other parts of the game's code or other mods how they handle them.

Also, it should be noted, most of this will only work on server/host, since only server/host knows about all joined players and has access to their health.

 

Thanks Muche, thats super informative. if only the server has access to this information, would it be prudent to only listen for these as host, and then have the host push out its own event that other players can listen for? 

 

Link to comment
Share on other sites

1 hour ago, brianchenito said:

Thanks Muche, thats super informative. if only the server has access to this information, would it be prudent to only listen for these as host, and then have the host push out its own event that other players can listen for? 

 

Yeah, the mastersim listens and then shoves out a net variable that the clients listen for and display.

Link to comment
Share on other sites

Events are for communication within a server/host or a client. For communication from a server/host to a client net_variables are used, For communication from a client to a server/host RPCs are used.

I'd recommend reading

 

 

Link to comment
Share on other sites

-- modmain.lua, example

-- Because testing, badges will be numbers and not widgets
local function onstatusdisplaysconstruct(self)
	-- Create badges for all possible players
	-- 1 to 6, because AllPlayers table starts in 1
	self.badgearray = {}
	for i = 1, GLOBAL.TheNet:GetDefaultMaxPlayers(), 1 do
		self.badgearray[i] = 0
	end

	-- Make function to update all badges and attach it to the player entity
	-- Get net variable value or a default value to attach to the badge
	self.owner.RebuildCustomHPBadges = function()
		for i, v in ipairs(GLOBAL.AllPlayers) do
			local notpercent = v.customhpbadgepercent and v.customhpbadgepercent:value() or v.replica.health:GetPercent()
			self.badgearray[i] = notpercent / 100
		end
		-- Instead of updating widgets, print values on console...
		for i, v in ipairs(self.badgearray) do
			print("Player "..tostring(i).." has "..tostring(v).." percent ")
		end
	end
end

-- Apply function on construction of class statusdisplays
AddClassPostConstruct("widgets/statusdisplays", onstatusdisplaysconstruct)

-- Set the net variable to the ceiling of the health percent times 100 (0, 0.01, 0.1, 0.99, 1.0) turn into (0, 1, 10, 99, 100)
local function onhealthdelta(inst, data)
	inst.customhpbadgepercent:set(math.ceil(data.newpercent * 100))
end

-- When somebody's health changes, it triggers the badges reconstruction
local function oncustomhpbadgedirty(inst)
	GLOBAL.ThePlayer.RebuildCustomHPBadges()
end

local function customhppostinit(inst)
	-- Net variable that stores between 0-255; more info in netvars.lua
	-- GUID of entity, unique identifier of variable, event pushed when variable changes
	-- Event is pushed to the entity it refers to, server and client side wise
	inst.customhpbadgepercent = GLOBAL.net_byte(inst.GUID, "customhpbadge.percent", "customhpbadgedirty")

	-- Server (master simulation) reacts to health and changes the net variable
	if GLOBAL.TheWorld.ismastersim then
		inst:ListenForEvent("healthdelta", onhealthdelta)
		-- Hack to trigger deltas for when somebody joins for first time, to update their badges
		inst.components.health:DoDelta(0)
	end

	-- Dedicated server is dummy player, only players hosting or clients have the badges
	-- Only them react to the event pushed when the net variable changes
	if not GLOBAL.TheNet:IsDedicated() then
		inst:ListenForEvent("customhpbadgedirty", oncustomhpbadgedirty)
	end
end

-- Apply function on player entity post initialization
AddPlayerPostInit(customhppostinit)

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...