Fimbulvetr Posted September 28, 2016 Share Posted September 28, 2016 (edited) Hi all, I've been trying to create a character mod which is based around the concept of having no offensive capabilities, thus relying on others, but in turn granting them bonuses and protection. One ability I'm experimenting with is an aura around the character, and half of all damage that would be dealt to other players within range is dealt to the Guardian instead. However, while I've managed to create a radius reducing incoming damage by 50%, I'm not sure I've implemented it in a sanitary manner. Additionally, I'm having difficulty listening for healthdeltas happening to buffed players and having the damage transferred to the Guardian. Could somebody among you take a quick look at what I've managed so far and offer some advice? I recognise there are some fundamental gaps in my knowledge of the api and of lua, and I'd greatly appreciate any answers that you could give me. The following is in my character.lua Spoiler -- Guarding Aura local function guardingaura(inst) if not inst:HasTag("playerghost") then -- Guardian must be alive for k, v in pairs(AllPlayers) do if v ~= inst then if v:HasTag("Safeguarded") then -- Remove buff from players no longer in range if inst:GetDistanceSqToInst(v) > 60 then v:RemoveTag("Safeguarded") v.components.health:SetAbsorptionAmount(0) -- Incoming damage gets set back to 100% How does this affect armour or changes in AbsorptionAmount outside this function? v.components.health:StopRegen() inst.components.talker:Say( "Be careful " .. v.userid .. "!" ) -- I haven't gotten to testing if this string concatenation actually works the way I think it will end else -- Add buff to non-buffed players in range if inst:GetDistanceSqToInst(v) < 60 then v:AddTag("Safeguarded") v.components.health:SetAbsorptionAmount(0.5) -- Incoming damage gets reduced by 50% v.components.health:StartRegen(1, 10) v.DoTaskInTime(0, painaura(v)) -- Attach ListenForEvent("healthdelta") function to the newly safeguarded player inst.components.talker:Say( "I'll keep you safe!" ) end end end end end end -- Shared Pain Aura local function painaura(inst) while inst:HasTag("Safeguarded") do -- Should break if player is no longer buffed by guardingaura inst:ListenForEvent("healthdelta", function(inst, amount) -- I'm not familiar with this notation, is it similar to lambda functions in Python? if amount < 0 then -- Only care about damage: negative changes for k, v in pairs(AllPlayers) do if (v:HasTag("Guardian")) and (inst:GetDistanceSqToInst(v) < 60) then -- I wasn't sure how to affect the Guardian so I created an unique tag for them -- Included the range check here on the off-chance that more than one person plays this character v.components.health:DoDelta(amount) v.components.sanity:DoDelta(amount * 0.5) end end end end) end end local common_postinit = function(inst) -- Guarding Aura inst:HasTag("Guardian") inst:DoPeriodicTask(0.5,guardingaura) end So, my first question would be, is the a good method to implement the concept? The PeriodicTask firing every half-second makes me think not, at least in terms of performance, but I couldn't think of another way of doing it. Secondly, could somebody explain how changing components.health:SetAbsorptionAmount() will work? Will it work neatly like I hope, or will it get messy with any other effects which change the amount? What about armour, and equipping armour both in and outside of the aura? Similarly, will this effect persist after logout, or could it start stacking in an unfortunate manner? In the testing that I did with a friend, I couldn't see any problems with it the way it is, but that doesn't mean they aren't there. Is the notation "v.DoTaskInTime(0, painaura(v))" correct for adding the ListenForEvent to other players, and will the while loop built into the painaura function interrupt the ListenForEvent and exit the function the way I hope it will? And finally, I believe my implementation of listening for players' health changes is really messy, but I don't really know how to improve upon it. As a first proof-of-concept, have I written the ListenForEvent function correctly? I couldn't find a whole lot in the existing files or on the forum to describe the correct way to construct one, so I'm a bit shaky about the whole thing. I've not been able to coordinate with a friend yet to test calling the painaura function and see if the ListenForEvent internal function actually works yet, so apologies if there's something obviously wrong with it that proper debugging would show up. Thank you in advance to anyone who reads this, I'm a bit lost on my own right now! Also, sorry there's no syntax highlighting like in other topics, I couldn't find the option of Lua. Edited September 28, 2016 by Fimbulvetr Formatting Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/ Share on other sites More sharing options...
Serpens Posted September 28, 2016 Share Posted September 28, 2016 (edited) I would suggest you to use and change the code for auras from this mod (see components folder)... I just see it seems the aura script is not finished But it may be a good start to work with edit: Ah in prefabs are the auras http://steamcommunity.com/sharedfiles/filedetails/?id=687719731 And I also suggest you to NOT use the absorb variable from the health component. This variable is meant to be used in character creation only. Unfortunately there is no way implemented by developers, to increase armor for a player without any tool like an armor. I used it in my mod "Home Base Bonus" though, but I added alot of precautions, to make sure it will be compatible to other mods. But most likely it is not compatible to most mods that also change this value, cause the authors of sad mods did not care about that. --> just don't use it and find another way. I did not find a perfect way of doing it, that's why I used absorb, but maybe you could mod the DoDelta function of the health component. You get the amount and cause, and if it is the kind of health change you want to change, you just reduce the amount and then call the original DoDelta function....(like this http://forums.kleientertainment.com/topic/70041-how-to-properly-save-this-overriden-component/?do=findComment&comment=819345 ) While thinkging about how to do this properly, I found "self.redirect" in that function. So the devs already implemented a way to redirect damage. Also in combat component is something with redirect... So if I were you, I would search all scripts for "redirect" and see how this works and if you can use this for your aura For searching all lua scripts at once, I use Notepad++ To highlight code, just use the "code" tag for string concencation use ..tostring(variable).. so in case something is nil, it won't throw an error. Edited September 29, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-819739 Share on other sites More sharing options...
Fimbulvetr Posted September 29, 2016 Author Share Posted September 29, 2016 (edited) Thank you very much for your reply. I suspected using the absorption variable wasn't a good idea. I took your advice and looked into the redirect functions mentioned in the game scripts, but I couldn't really determine how they were used, since they just seemed to refer to themselves over and over. I did however have an idea from the GetAttacked function in the combat component, the first place I found a redirect function, and have produced the following using the component overwriting technique described in the topic you linked and elsewhere in the forum: Spoiler character.lua -- Guarding Aura Radius Function local function guardingaura(inst) if not inst:HasTag("playerghost") then for k, v in pairs(AllPlayers) do if v ~= inst then if v:HasTag("Safeguarded") then if inst:GetDistanceSqToInst(v) > 60 then v:RemoveTag("Safeguarded") inst.components.talker:Say( "Be careful " .. tostring(v.name) .. "!" ) -- I took your advice here and it seems to function as expected. end else if inst:GetDistanceSqToInst(v) < 60 then v:AddTag("Safeguarded") inst.components.talker:Say( "I'll keep you safe!" ) end end end end end end Spoiler modmain.lua -- Guarding Aura Damage Reduction Function AddComponentPostInit("combat", function(inst) if not GLOBAL.TheWorld.ismastersim then return end local old_GetAttacked = inst.GetAttacked function inst:GetAttacked(attacker, damage, weapon, stimuli) half_damage = math.floor(damage * 0) -- Using 0 as positive control, will normally be 0.5 if not inst.HasTag("Safeguarded") then return old_GetAttacked(attacker, damage, weapon, stimuli) else return old_GetAttacked(attacker, half_damage, weapon, stimuli) end end end) I feel I'm along the right track for implementing the damage mitigation, which I did originally want to be limited to combat damage, however I'm currently encountering a crash due to the HasTag("Safeguarded") field in modmain.lua, because it has a nil value. I assumed evaluating the boolean expression "not var" would equal True if var had a nil value? Am I wrong there, or does the Safeguarded tag need to be declared to exist elsewhere in modmain? I think the tag system is one of the easier ways of excluding all entities not in range and all non-player entities within range, but besides the current issue of actually getting it to work, is it a viable option for use? Though I'm confident my server can handle whatever I throw at it, I'm always conscious of optimising my code for performance. Thank you again! (Also, whether I use the posting tool for adding code, or manually add the BBCode either side without specifying syntax, there is no highlighting for Lua so I apologise if it looks messy). Edited September 29, 2016 by Fimbulvetr Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820188 Share on other sites More sharing options...
Fimbulvetr Posted September 29, 2016 Author Share Posted September 29, 2016 Actually, I realise my mistake: inst refers to the combat component, so I'm erroneously checking for a HasTag variable on the combat component and not on an entity, so I'll go try fix that and report back! Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820196 Share on other sites More sharing options...
Serpens Posted September 29, 2016 Share Posted September 29, 2016 when you hit the code thing from forum on the bottom right you can choose which language. But since t´here is no lua, it does not really matter. I always use default, which is html You have to invoke AddTag and HasTag with ":" , so it has to be inst:HasTag (if inst it the thing you want to check) Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820254 Share on other sites More sharing options...
Fimbulvetr Posted September 29, 2016 Author Share Posted September 29, 2016 I've succeeded in implementing the damage reduction part of the aura! Thank you so much for your help so far! Spoiler modmain.lua -- Guarding Aura Damage Reduction Function local function GuardianAuraInit(component) local old_DoDelta = component.DoDelta component.DoDelta = function(self, amount, overtime, cause, ignore_invincible) local half_damage = math.floor(amount * 0.5) if not self.inst:HasTag("Safeguarded") then return old_DoDelta(self, amount, overtime, cause, ignore_invincible) end if amount > 0 then return old_DoDelta(self, amount, overtime, cause, ignore_invincible) end if amount < 0 then return old_DoDelta(self, half_damage, overtime, cause, ignore_invincible) end end end AddComponentPostInit("health", GuardianAuraInit) Spoiler character.lua -- Guarding Aura Transfer Damage Function local function painfunction(inst) while inst:HasTag("Safeguarded") do inst:ListenForEvent("healthdelta", function(inst, amount) local half_amount = math.floor(amount * 0.5) if amount < 0 then for k, v in pairs(AllPlayers) do if (v:HasTag("Guardian")) and (inst:GetDistanceSqToInst(v) < 60) then v.components.health:DoDelta(amount) v.components.sanity:DoDelta(half_amount) end end end end) end end -- Guarding Aura Radius Function local function guardingaura(inst) if not inst:HasTag("playerghost") then for k, v in pairs(AllPlayers) do if v ~= inst then if v:HasTag("Safeguarded") then if inst:GetDistanceSqToInst(v) > 60 then v:RemoveTag("Safeguarded") inst.components.talker:Say( "Be careful " .. tostring(v.name) .. "!" ) end else if inst:GetDistanceSqToInst(v) < 60 then v:AddTag("Safeguarded") v.DoTaskInTime(0, painfunction(v)) inst.components.talker:Say( "I'll keep you safe!" ) end end end end end end local common_postinit = function(inst) -- Guarding Aura inst:HasTag("Guardian") inst:DoPeriodicTask(0.5,guardingaura) end However, the code as it is will still cause a crash by running the server out of memory. I think this is because it's attaching the ListenForEvent to the character every half-second, but it's hard to say since it froze the game instantly. I can't see any other infinite loop or anything that would cause an out-of-memory process crash, could you cast your eye over it and possibly tell me what I've done wrong? I'd be very appreciative; I'm so close to actually succeeding! Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820280 Share on other sites More sharing options...
Serpens Posted September 29, 2016 Share Posted September 29, 2016 Yes it is because ListenForEvent. You don't have to call it more than once It will Listen to the event until you remove the listening thing. So the solution would be to just add one time the "ListenForEvent" in your character. And in the function for that event, you check if character has the Tag. If not, just return. Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820284 Share on other sites More sharing options...
Fimbulvetr Posted September 29, 2016 Author Share Posted September 29, 2016 (edited) I see, then should this run properly? I won't be able to test it with someone till tomorrow. -- Guarding Aura Transfer Damage Function local function painfunction(inst) while inst:HasTag("Safeguarded") do -- I feel like I can clean this up, if not inst:HasTag("Listening") then -- I just sketched it in quickly for concept. inst:AddTag("Listening") inst:ListenForEvent("healthdelta", function(inst, amount) local half_amount = math.floor(amount * 0.5) if amount < 0 then for k, v in pairs(AllPlayers) do if (v:HasTag("Guardian")) and (inst:GetDistanceSqToInst(v) < 60) then v.components.health:DoDelta(amount) v.components.sanity:DoDelta(half_amount) end end end end end) end end -- Guarding Aura Radius Function local function guardingaura(inst) if not inst:HasTag("playerghost") then for k, v in pairs(AllPlayers) do if v ~= inst then if v:HasTag("Safeguarded") then if inst:GetDistanceSqToInst(v) > 60 then v:RemoveTag("Safeguarded") v.components.health:StopRegen() inst.components.talker:Say( "Be careful " .. tostring(v.name) .. "!" ) end else if inst:GetDistanceSqToInst(v) < 60 then v:AddTag("Safeguarded") v.components.health:StartRegen(1, 5) if not v:HasTag("Listening") then v.DoTaskInTime(0, painfunction(v)) end inst.components.talker:Say( "I'll keep you safe!" ) end end end end end end -- This initializes for both the server and client. Tags can be added here. local common_postinit = function(inst) -- Guarding Aura inst:HasTag("Guardian") inst:DoPeriodicTask(0.5,guardingaura) end If so, then thank you very much for your help, I've learned an awful lot in this process. Although, I still feel like my implementation is a bit clunky performance-wise, given that it runs in a DoPeriodicTask event in 0.5 second intervals, but despite that I'm quite proud that I managed this. One last question, if you don't mind. I never really planned on releasing this character, it was for my own use only. However, if I were to release it for posterity, would this mod be useable by all or just by hosts, since it references the AllPlayers table? EDIT: Another thing, the radius of this "aura" is 59/60, but the radius of a light aura I've been using for testing alongside it is inst.Light:SetRadius(8). How are these distances measured, and is there a way of converting between them so I can get the horizons to match? I've eyeballed it to be similar, but I'm just curious. Thank you very much for passing on your knowledge and insight! Edited September 29, 2016 by Fimbulvetr Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820298 Share on other sites More sharing options...
Serpens Posted September 29, 2016 Share Posted September 29, 2016 (edited) @Fimbulvetr think every character mod is a "all_client_require" mod. Or what was your question? about your code: In your common function, you wrote "HasTag". This will return true or false, but won't do anything. Maybe you ment "AddTag" ? And for things like an aura, it is much better to use components, since you can save stuff in this component. And the listening thing can be improved alot. I will write you some code now (but you are learning very fast, much faster than most users I saw! ;)) Edited September 30, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820326 Share on other sites More sharing options...
Serpens Posted September 30, 2016 Share Posted September 30, 2016 (edited) @Fimbulvetr so I put the auro into a component now. This means you can also give it to every other player if you like to, e.g by adding it via "AddPlayerPostInit" in modmain. Add the following code into a components folder (scripts/components) and name the file "guardingaura.lua". -- Guarding Aura Transfer Damage Function local function painfunction(inst,data) -- search game scripts how the function should look like. In this case it does not give amount directly, it gives data. And data contains amount local half_amount = math.floor(data.amount * 0.5) if data.amount < 0 then for k, v in pairs(AllPlayers) do if (v.components and v.components.guardingaura and v.components.guardingaura.auratask) and not v:HasTag("playerghost") then -- no need to check distance again, since the eventcallback is removed if too far away -- print("GuardingAura: avoid damage for "..tostring(inst)..". give "..tostring(data.amount).." to "..tostring(v)) v.components.health:DoDelta(data.amount) v.components.sanity:DoDelta(half_amount) end end end end -- Guarding Aura Radius Function local function guardingaura(inst,self) if not inst:HasTag("playerghost") then self.talkerinfocounter = self.talkerinfocounter + 1 if self.talkerinfocounter > self.talkerinfoperiod * 2 then self.talkerinfocounter = self.talkerinfoperiod + 1 -- just to prevent self.talkerinfocounter to be very very high number. Dont know if this is needed end for k, v in pairs(AllPlayers) do -- for testing, you can replace AllPlayers with Ents to get everything on map, therefore also the additional check for the health component if v.components and v.components.health then if v ~= inst then if inst:GetDistanceSqToInst(v) > self.radius then -- if not in range if table.contains(self.guardedplayers,v) then -- print("GuardingAura: removed "..tostring(v)) RemoveByValue(self.guardedplayers,v) v:RemoveEventCallback("healthdelta",painfunction) v.components.health:StopRegen() if self.talkerinfocounter >= self.talkerinfoperiod then inst.components.talker:ShutUp() inst.components.talker:Say( "Be careful " .. tostring(v.name) .. "!" ) self.talkerinfocounter = 0 end end else -- if in range if not table.contains(self.guardedplayers,v) then -- print("GuardingAura: added "..tostring(v)) table.insert(self.guardedplayers,v) v.components.health:StartRegen(1, 5) v:ListenForEvent("healthdelta",painfunction) if self.talkerinfocounter >= self.talkerinfoperiod then inst.components.talker:ShutUp() inst.components.talker:Say( "I'll keep you safe!" ) self.talkerinfocounter = 0 end end end end end end end end -- another way to find things in range is: -- --local PlayersInRange = TheSim:FindEntities(x, y, z, radius, musthavetags, canthavetags, musthaveoneoftags) and searching for tag "player". x y z are the coordinates of the point from which you want to search. you get them with: local x, y, z = inst.Transform:GetWorldPosition() ... and I think the unit of radius is differnt to the GetDistanceSq function ... sq... is it the square root of the distance? That would explain alot. Cause normally distance from the screen right to left is ~ 20. -- but since you don't find things that are not in range, we would not be able to remove the listening. -- instead of adding an removing listeing, we could also check in the listener function if requirements are fullfilled. But since I see no way to give additional arguments to the function, this is not that easy in this case, so we add/remove listenener instead local GuardingAura = Class(function(self, inst) self.inst = inst self.radius = 60 self.tickperiod = 0.5 self.talkerinfoperiod = 10 -- don't talk, if the last time is less then x*tickperiod seconds ago self.talkerinfocounter = 0 self.auratask = nil self.guardedplayers = {} -- this way we avoid using tags, since I just learned that the tags number per inst is limited to 32, after that the game will crash O.ô end) function GuardingAura:StartAura() if not self.auratask then self.auratask = self.inst:DoPeriodicTask(self.tickperiod,guardingaura,0,self) -- print("GuardingAura: aura started") end end function GuardingAura:StopAura() if self.auratask then self.auratask:Cancel() self.auratask = nil -- print("GuardingAura: aura stopped") end end return GuardingAura I already test it for you with "Ents" instaed of AllPlayers and it works You can also test it this way and can enable the prints to see output in logfile. And add this to your modmain,lua: local function OnPlayerSpawn(inst) if not (GLOBAL.TheNet:GetIsServer() or GLOBAL.TheNet:IsDedicated()) then -- don't add components for clients, only for server return end if inst.prefab == "wilson" then -- or the prefab of your character inst:AddComponent("guardingaura") inst:DoTaskInTime(0,function() inst.components.guardingaura:StartAura() end) -- do it with DoTaskInTime because that way it is called after the component is fully initialized, just a precaution... end end AddPlayerPostInit(OnPlayerSpawn) since I used a component, you can also change the settings of the aura without editing the file itself. so in OnPlayerSpawn function in modmain you can also add after the component is added things like inst.components.guardingaura.radius = 100 to change the radius. You can change the radius also while the game is running doing this. Edited September 30, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820374 Share on other sites More sharing options...
Fimbulvetr Posted September 30, 2016 Author Share Posted September 30, 2016 (edited) I'm very taken aback that you took so much time to do all that for me of your own accord, especially since you undertake to help so many on the forum, and I can only offer my sincerest thanks. The mechanism you've written to implement the feature is quite an improvement over what I created, and is actually very logical and easy to understand, and customize if desired. I feel slightly chagrined that I never thought to create an entirely new component, for all the looking through existing ones I was doing, and I've certainly learned a lot from you! (The RemoveEventCallback function was something I really should have looked for prior to bothering you!) If you don't mind me asking even more, I have a couple of questions regarding the component you've created. The first is quite simple and may just be a difference in how Lua does things compared to what I'm used to, but in functions that act on the guardedplayers table, is the notation FunctionToExecute(table_to_act_on, key_to_look_for)? I'm just not 100% sure I understand what I'm reading fully. Similarly, what is the purpose of the third and fourth arguments of the DoPeriodicTask function? If I had to guess I'd say limiting the number of repeats, but it's hard to know. Previously, I would have checked such on the dontstarveapi website, but that doesn't seem to work anymore. Is there a somewhat complete API documentation anywhere, or do we learn by deconvoluting the existing code? Lastly, I don't think I understand the purpose of the talkerinfocounter. At first I thought it was to stop the character spamming their lines if players were quickly entering and/ or leaving the radius, but then it seemed more like it meant "only talk once every 5 seconds minimum", but I think I could be mistaken there too since it would miss an event if a player passed in and out of the monitored area in <5 seconds. Could you explain the reasoning behind it? Knowing how to do something is relatively easy, but understanding why we do something isn't always clear when reading through the existing code, and I think is very important. Oh, regarding the mod being "All_clients_require" (which I know is due to others requiring the art assets), my question really was based on something I read here on the forum, where it was suggested that only hosts could access the AllPlayers table, which would mean the character couldn't be used by clients with my implementation, since it was all located in the character prefab as opposed to being a new component which is freely accessible, so I guess the issue is now moot. Again, thank you so much for all your help, you've really went to great lengths to assist me and text doesn't really do justice to the expression of my gratitude. Edited September 30, 2016 by Fimbulvetr Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820546 Share on other sites More sharing options...
Serpens Posted September 30, 2016 Share Posted September 30, 2016 (edited) Quote The first is quite simple and may just be a difference in how Lua does things compared to what I'm used to, but in functions that act on the guardedplayers table, is the notation FunctionToExecute(table_to_act_on, key_to_look_for)? I'm just not 100% sure I understand what I'm reading fully. Yes, you can look up those functions in util.lua in the script files of the game. Also modutil.lua is helpful Quote Similarly, what is the purpose of the third and fourth arguments of the DoPeriodicTask function? If I had to guess I'd say limiting the number of repeats, but it's hard to know. Previously, I would have checked such on the dontstarveapi website, but that doesn't seem to work anymore. Is there a somewhat complete API documentation anywhere, or do we learn by deconvoluting the existing code? This function is written in entityscript.lua If you see a function anywhere and you want to know what it does, just open notepad++ and search through all lua files in the scripts folder. Most of the time you will find the function somewhere (but sometimes not, then it is hardcoded I guess). The third argument is the "delay", so when it runs the first time. And every additional argument is brough to the called function. To cancel a Periodic task, name it like I did, e.g "task" and then do the Cancel() stuff Quote Lastly, I don't think I understand the purpose of the talkerinfocounter. At first I thought it was to stop the character spamming their lines if players were quickly entering and/ or leaving the radius, but then it seemed more like it meant "only talk once every 5 seconds minimum", but I think I could be mistaken there too since it would miss an event if a player passed in and out of the monitored area in <5 seconds. Could you explain the reasoning behind it? Knowing how to do something is relatively easy, but understanding why we do something isn't always clear when reading through the existing code, and I think is very important. it is exactly what you thought. I thought it would be toooo much talking, if many players are going in and out and in and out ..in a short time. Your char would not stop talking and talking all the time. That's why I implemented this. And yes, that way it happens, that char says nothing, if a character is near. Of course you can remove it, but I think useres that will use this with more than 1 other player, will hate you then =P Or maybe you can improve it that way, that the counter works, if it is the same player. So for every player, there could be an extra counter. Quote Oh, regarding the mod being "All_clients_require" (which I know is due to others requiring the art assets), my question really was based on something I read here on the forum, where it was suggested that only hosts could access the AllPlayers table, which would mean the character couldn't be used by clients with my implementation, since it was all located in the character prefab as opposed to being a new component which is freely accessible, so I guess the issue is now moot. This is a really important topic. Clients don't have access to many things, eg. to AllPlayers obviously and also to most components! But normally this is not needed, since the important stuff is handled by the server. If you take a look at any prefab from the game, you will see in the fn() function Quote inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end TheWorld.ismastersim checks if it is the server that is running this. If not, then it returns here. So all that comes later, is not added to clients (mostly components). I did not get completely what "Pristine" thing is for. But just remember that you have to put both in your prefab in this order. You don't need the Pristine thing elsewhere. Only in prefabs. Instead of TheWorld.istmastersim you can also check TheNet:GetIsServer(). Sometimes you want to check if it is server, before the world is created, that's why you use "TheNet" instead. You also have to take this into account when putting code in modmain. That's why I put the TheNetGetIsServer() stuff in the code above. Because components are only for server. (I just learned the the additional check for "IsDedicated()" is not needed, so only use "GetIsServer". To find out what is for clients and what for server you can only take a look at game scripts and mods of other users. Or just try and error... E.g string changes or adding recipes has to be done for both, client and server. If you try to access a component as a client, you will most likely get an error about component being nil. For some important components like health, builder and so on, there is a "replica" file in the components folder. I did not get exactly how it works, but this is accesable for clients. So if you mod one of those components, you most likely have to mod also the replica, see here:http://forums.kleientertainment.com/topic/70550-solved-recipes-availability-while-running-game/?do=findComment&comment=820391 If you miss adding a string or recipe to client, your game will do the most craziest stuff At the moment I have a mod where the hunger is 234234 and I start burning when near a researchlab but it is work in progress... To find out if your mod works also for clients, you can start a game with caves active. Then you will act as a pseudo client for most things. But unfortunaltey not for everything. So to be 100% sure, you have to make a dedicated server and join there, see this guide:https://steamcommunity.com/sharedfiles/filedetails/?id=635281092 edit: since here is much information, I will write the words " Tutorial modding " in case someone is searching for such stuff ^^ Edited September 30, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820566 Share on other sites More sharing options...
Fimbulvetr Posted September 30, 2016 Author Share Posted September 30, 2016 You really have provided me with an abundance of information, thank you! I'm going to go play with these new tools and try and improve what I'm capable of producing. You've said so much here, I definitely think that it explains a lot to anyone who wants to know more about it will benefit from your teachings. There is little I can do to show my gratitude to the effort you've gone to here, and I don't know how proliferative I'll ever be with regards releasing mods, but you'll certainly be attached to the credits section of each one! Link to comment https://forums.kleientertainment.com/forums/topic/70520-monitoring-other-players-health-and-a-couple-of-other-questions/#findComment-820670 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now