nicknightyx Posted March 5, 2018 Share Posted March 5, 2018 (edited) Hi there, I'm working on a character mod and I'm trying to make it non-stunlockable under certain circumstance. I gave it a try and got an error. Would you please point out what went wrong with my code? Thanks! Part of the character.lua: (I referred to combat.lua for this stunlock code) Spoiler local function bskns(inst, attacker) if inst.components.health.currenthealth > 0 then attacker.components.combat:SetPlayerStunlock(PLAYERSTUNLOCK.NEVER) end end inst:ListenForEvent("attacked",bskns) These are the mod file and the server log file. This mod works just fine before this non-stunlockable stuff. server_log.txt Part of the server log: Spoiler [00:00:51]: [string "../mods/hisoka 3-9 non_stun/scripts/prefabs..."]:59: attempt to index field 'components' (a nil value) LUA ERROR stack traceback: ../mods/hisoka 3-9 non_stun/scripts/prefabs/hisoka.lua:59 in (local) fn (Lua) <57-61> inst = 123462 - hisoka (valid:true) attacker = table: 0CADD980 scripts/entityscript.lua:1035 in (method) PushEvent (Lua) <1022-1049> self (valid:true) = DynamicShadow = DynamicShadow (375A5830) inlimbo = false GetMoistureRateScale = function - scripts/prefabs/player_common.lua:146 SetCameraDistance = function - scripts/prefabs/player_common.lua:954 ScreenFlash = function - scripts/prefabs/player_common.lua:1016 player_classified = 123463 - player_classified (valid:true) playercolour = table: 091AAD90 vitality = 413 ShowWardrobePopUp = function - scripts/prefabs/player_common.lua:942 Light = Light (375A58B0) _isrezattuned = false OnRemoveEntity = function - scripts/prefabs/player_common.lua:630 pendingtasks = table: 07AE5218 ShowHUD = function - scripts/prefabs/player_common.lua:936 ShowGiftItemPopUp = function - scripts/prefabs/player_common.lua:948 sg = sg="wilson", state="idle", time=0.47, tags = "idle,canrotate," IsHUDVisible = function - scripts/prefabs/player_common.lua:926 ApplyScale = function - scripts/prefabs/player_common.lua:1031 SetGhostMode = function - scripts/prefabs/player_common.lua:543 ShowActions = function - scripts/prefabs/player_common.lua:930 OnWakeUp = function - scripts/prefabs/player_common.lua:803 Transform = Transform (375A5610) actionreplica = table: 07AE49F8 event_listening = table: 07AE54E8 actioncomponents = table: 07AE49D0 lower_components_shadow = table: 07AE4CC8 GetMaxMoisture = function - scripts/prefabs/player_common.lua:136 class_B = 1 CanUseTouchStone = function - scripts/prefabs/player_common.lua:86 updatecomponents = table: 08B150E0 ShakeCamera = function - scripts/prefabs/player_common.lua:974 OnDespawn = function - scripts/prefabs/player_common.lua:825 persists = false MiniMapEntity = MiniMapEntity (375A5930) IsFreezing = function - scripts/prefabs/player_common.lua:106 _OnLoad = function - ../mods/hisoka 3-9 non_stun/scripts/prefabs/hisoka.lua:26 replica = table: 07AE4A20 GetTemperature = function - scripts/prefabs/player_common.lua:96 GUID = 123462 ghostenabled = false EnableMovementPrediction = function - scripts/prefabs/player_common.lua:499 worldstatewatching = table: 08B138F8 SetCameraZoomed = function - scripts/prefabs/player_common.lua:960 speed = 222 Network = Network (375A5710) GetMoisture = function - scripts/prefabs/player_common.lua:126 OnPreLoad = function - scripts/prefabs/player_common.lua:704 LightWatcher = LightWatcher (375A5630) inherentactions = table: 1AA5C4E8 spawntime = 0.13333334028721 dychealthbar = 123556 - dyc_healthbar (valid:true) combat = false SnapCamera = function - scripts/prefabs/player_common.lua:966 name = Nick _OnSave = function - ../mods/hisoka 3-9 non_stun/scripts/prefabs/hisoka.lua:273 prefab = hisoka point = 21 _OnPreLoad = function - ../mods/hisoka 3-9 non_stun/scripts/prefabs/hisoka.lua:207 class_D = 3 ScreenFade = function - scripts/prefabs/player_common.lua:1007 OnSleepIn = function - scripts/prefabs/player_common.lua:775 OnSave = function - scripts/prefabs/player_common.lua:678 GetSandstormLevel = function - scripts/prefabs/player_common.lua:156 OnLoad = function - scripts/prefabs/player_common.lua:714 entity = Entity (08C80C48) ggtm = 3 children = table: 0CFD4EE8 IsCarefulWalking = function - scripts/prefabs/player_common.lua:160 intelligence = 107 AttachClassified = function - scripts/prefabs/player_common.lua:619 strength = 426 IsActionsVisible = function - scripts [00:00:51]: [string "../mods/hisoka 3-9 non_stun/scripts/prefabs..."]:59: attempt to index field 'components' (a nil value) LUA ERROR stack traceback: ../mods/hisoka 3-9 non_stun/scripts/prefabs/hisoka.lua:59 in (local) fn (Lua) <57-61> scripts/entityscript.lua:1035 in (method) PushEvent (Lua) <1022-1049> scripts/components/combat.lua:463 in () ? (Lua) <405-480> =(tail call):-1 in () (tail) <-1--1> scripts/components/combat.lua:844 in (method) DoAttack (Lua) <794-868> scripts/stategraphs/SGBeefalo.lua:465 in (field) fn (Lua) <465-465> scripts/stategraph.lua:568 in (method) UpdateState (Lua) <536-580> scripts/stategraph.lua:607 in (method) Update (Lua) <599-627> scripts/stategraph.lua:125 in (method) Update (Lua) <109-148> scripts/update.lua:218 in () ? (Lua) <149-228> Regards, Edited March 6, 2018 by nicknightyx Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/ Share on other sites More sharing options...
IronHunter Posted March 5, 2018 Share Posted March 5, 2018 The problem with ListenForEvents is they activate after the event has happened. In this case your character was already hit and stunned, to properly do this you'll have to do a component override for combat:GetAttacked. --The basic premise is like this. Used in modmain.lua AddComponentPostInit("combat", function(self) local oldGetAttacked = self.GetAttacked function self:GetAttacked(attacker, damage, weapon, stimuli) if self.inst.prefab == "yourchar" then --do something here end return oldGetAttacked(self, attacker, damage, weapon, stimuli) end end) The Second problem is this doesn't really work against damage sources lacking the combat component. e.g. explosives, this will cause a crash. A third problem is your code permanently sets the stunlock to never on the enemy that hits you. You'll likely want to revert it back after you are hit, as this can be wierd with multiple players. Depending on whether you want to retain the hit animations or not, there are a few ways for you to experiment with this, one simple solution is to just blank the hit and make a fake hit with health:DoDelta and making your character play the state, instead. Alternatively you could make a custom eventhandler copy of the "Attacked" event with modified code regarding the stunlock, then rebuild a custom getattacked function that pushes this event for your character, and return the original for any character but yourself. There are a lot of ways to go about programming this depending on how deep you want to modify things. Hope this helps, I don't have time right now to tinker. Cheers, Iron_Hunter Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011264 Share on other sites More sharing options...
nicknightyx Posted March 5, 2018 Author Share Posted March 5, 2018 13 hours ago, IronHunter said: Iron_Hunter Thanks a ton! You don't have to tinker anything right now, I have some plain questions for you instead XD. 1. Since I'm learning coding, I want to really understand your code, would you kindly explain something to me please? (i) The "AddComponentPostInit("combat", function(self)" is adding a component called "combat" not having to create another combat.lua under the component folder, right? But what does the "self" mean? Does it mean this component specifically works for myself? I have seen "inst:DoPeriodicTask(5,function()", so what's the difference between them? (ii) The "self" appeared 4 times, "self.GetAttacked", "function self", "self.inst.prefab", "return oldGetAttacked(self..." would you please tell me what do they mean respectively? (iii) Lastly, why do we want to "return oldGetAttacked" ? 2. And for the second problem you mentioned, is there any way that we can fix it? Because even if I steer clear of gun powder it's pretty tough to avoid the meteorites and falling rocks in cave. Maybe something like "if not attacker.prefab == rocks then [do something] end" ? Do you think it would work? 3. For the third problem, were you saying that for example one spider hit me and I wasn't stunlocked when some requirements were met then all other spider will no longer stunlock me or other players even when those requirements are not met? Well this is really serious, I'm thinking if we can just skip the stunlock animation or "stategraph" of my character so that it can move freely when it's taking damage. Can you help? 4. What do you mean by retaining the hit animation? If I understood you correctly, the hit animation is exactly what I want to get rid of. Now that you see what I'm really trying to do here, maybe you know some more efficient ways to get there? Really appreciate you answering some newbies like myself. God bless you. Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011509 Share on other sites More sharing options...
IronHunter Posted March 5, 2018 Share Posted March 5, 2018 Spoiler 28 minutes ago, nicknightyx said: Thanks a ton! You don't have to tinker anything right now, I have some plain questions for you instead XD. 1. Since I'm learning coding, I want to really understand your code, would you kindly explain something to me please? (i) The "AddComponentPostInit("combat", function(self)" is adding a component called "combat" not having to create another combat.lua under the component folder, right? But what does the "self" mean? Does it mean this component specifically works for myself? I have seen "inst:DoPeriodicTask(5,function()", so what's the difference between them? (ii) The "self" appeared 4 times, "self.GetAttacked", "function self", "self.inst.prefab", "return oldGetAttacked(self..." would you please tell me what do they mean respectively? (iii) Lastly, why do we want to "return oldGetAttacked" ? 2. And for the second problem you mentioned, is there any way that we can fix it? Because even if I steer clear of gun powder it's pretty tough to avoid the meteorites and falling rocks in cave. Maybe something like "if not attacker.prefab == rocks then [do something] end" ? Do you think it would work? 3. For the third problem, were you saying that for example one spider hit me and I wasn't stunlocked when some requirements were met then all other spider will no longer stunlock me or other players even when those requirements are not met? Well this is really serious, I'm thinking if we can just skip the stunlock animation or "stategraph" of my character so that it can move freely when it's taking damage. Can you help? 4. What do you mean by retaining the hit animation? If I understood you correctly, the hit animation is exactly what I want to get rid of. Now that you see what I'm really trying to do here, maybe you know some more efficient ways to get there? Really appreciate you answering some newbies like myself. God bless you. 1(i) Spoiler AddComponentPostInit is a function in modutil.lua that runs a function when the chosen component is defined. Allowing you to inject or modify the component. Self is the variable in the function we made that is passed the self variable from the combat component by default. It simply refers to the self aspect of the component. If you look at the component combat, you'll see it defines stuff as self.variablename, self can be actually anything as long as you call the variables using the same variable. Inst:DoPeridicTask is refering to inst variable of the created entity, inst is just the name that is commonly used amongst the prefabs. These variables act as pointers pointing at specific code for their respective files. 1(ii) Spoiler self.GetAttacked refers to the Getattacked function inside the combat component. We first call this to store a pointer variable to the old version of the getattacked. function(self), is just used as a variable name to maintain conformity with the components variable name. It makes it easier to infer what it does, from the combat component. self.inst.prefab, self.inst refers to the inst that has this component. When you AddComponent("combat") which is enabled by default for custom characters, it'll automatically assign self.inst to your character. This is again another pointer variable for easy access to data. .prefab part of this returns the prefab of self.inst for example self.inst.prefab where self.inst == wilson will return wilson. 1(iii) Spoiler the return oldgetAttacked is important for compatibility with other entities that use the combat component. If the if statement fails we return the oldgetattacked function which we saved a pointer variable for. 2 Spoiler Instead of trying to change the stunlock of sources of damage, instead just change how your character handles being stunned. It is probably easier for you to make a modified copy of the getattacked function and return the old one for anything but yourself. This modified function will instead pushevent for a modified/custom eventhandler("attacked") 3 Spoiler The problem is very noticeable against tough enemies that can easily hit multiple players, like deerclops. After he hits you he would never stunlock any other player, not just your character. If you desire that route, then you would have to do some clever hack to revert the effect before getattacked is called for other players. It'll likely have sync issues too. 4 Spoiler If you don't care about hit animation or you don't care about being frozen in one spot after being hit? If its the former you could just make a modified copy of getattacked that doesn't push the event "attacked", as that is what handles the animations and stunlock simultaneously. If you prefer keeping animations but want to get rid of the frozen in one spot after being hit, because getting struck by lightning etc, then you just need to make a custom modified event handler without the stunlock portion of code. That is pushed by your custom getattacked function, instead of the old one. Learning how to inject but not overide code is pretty important for anything but the simplest mods. It maintains compatibility with other mods better and has less conflict. If you have any other questions I'll do what I can to answer them. Sorry for the wall of text, I could go into more detail if needed. Cheers, Iron_Hunter Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011517 Share on other sites More sharing options...
nicknightyx Posted March 6, 2018 Author Share Posted March 6, 2018 2 hours ago, IronHunter said: Iron_Hunter Thanks again! I'm kind of getting your code now. I added some conditions to the non-stunlockable code and tested it and it worked! Maybe I'm too excited but I now don't think the two problems are that big deal which are: for other players that won't be stunlocked by the enemies that has hit me and for the game will crash if I am hurt by explosives, I think I can just live with that. And I would like to retain the frozen stun and lightning stun. Let me test if the temperature damage and monster meat damage would crash the game. Regards, Nick Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011554 Share on other sites More sharing options...
nicknightyx Posted March 7, 2018 Author Share Posted March 7, 2018 (edited) On 3/5/2018 at 5:29 PM, IronHunter said: Iron_Hunter Hi Iron_Hunter, I have another piece of code that I don't get. Would you please take a look at it? Thanks! Spoiler [modmain.lua] function combat(inst) inst.writing = false local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, 1, {"_writeable"}) for k,v in pairs(ents) do inst.writing = true end if not inst.writing then blablabla end end AddModRPCHandler("hisoka", "combat", combat) I especially don't understand the inst.writing part, is it necessary? What does it do? Regards, Nick Edited March 7, 2018 by nicknightyx Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011875 Share on other sites More sharing options...
IronHunter Posted March 7, 2018 Share Posted March 7, 2018 3 minutes ago, nicknightyx said: Hi Iron_Hunter, I have another piece of code that I don't get. Would you please take a look at it? Thanks! Hide contents [modmain.lua] function combat(inst) inst.writing = false local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, 1, {"_writeable"}) for k,v in pairs(ents) do inst.writing = true end if not inst.writing then blablabla end end AddModRPCHandler("hisoka", "combat", combat) I especially don't understand the inst.writing part, is it necessary? What does it do? Regards, Nick Inst.writing is a variable on a entity inst. I don't know what the context of this code snippet is suppose to do. It seems really inefficient checking for all entities within 1 unit of inst position that have the "_writing" tag only to set the variable true afterward. Could you give me more info what this is suppose to accomplish. Either link the source mod or describe it etc. Cheers, Iron_Hunter Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011877 Share on other sites More sharing options...
nicknightyx Posted March 7, 2018 Author Share Posted March 7, 2018 4 minutes ago, IronHunter said: Cheers, Iron_Hunter I got this code originally from a mod called "Musha", because I don't understand the inst.writing part, I copy it into my mod every time I want to use " inst.components.keyhandler:AddActionListener("hisoka", TUNING.HISOKA.KEY3, "combat") " in case it's important. modmain.lua hisoka.lua Thanks, Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011879 Share on other sites More sharing options...
IronHunter Posted March 7, 2018 Share Posted March 7, 2018 3 minutes ago, nicknightyx said: I got this code originally from a mod called "Musha", because I don't understand the inst.writing part, I copy it into my mod every time I want to use " inst.components.keyhandler:AddActionListener("hisoka", TUNING.HISOKA.KEY3, "combat") " in case it's important. modmain.lua hisoka.lua Thanks, When I get some free time I'll take a look into this. Cheers, Iron_Hunter Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011882 Share on other sites More sharing options...
nicknightyx Posted March 7, 2018 Author Share Posted March 7, 2018 2 hours ago, IronHunter said: Cheers, Iron_Hunter I tried deleting the whole inst.writing thing and it worked as fine. Not necessary to look into it and thanks for your time. XD Link to comment https://forums.kleientertainment.com/forums/topic/88319-solved-need-some-help-with-stunlock-code-here/#findComment-1011912 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