carbondz2010 Posted December 8, 2019 Share Posted December 8, 2019 Hello, i trying to make activator which spawn object on it, everything is working, but only when i do activate, the conditional is must not filled. this is my code : Armor Property WOPshield2 Auto MiscObject Property WOPSoul Auto ObjectReference Property WOPshield3 Auto Event OnActivate(ObjectReference akActionRef)If (Game.GetPlayer().GetItemCount(WOPshield2) == 0) && (Game.GetPlayer().GetItemCount(WOPSoul) == 0) Debug.MessageBox("Player has no requirement item on inventory")Else Game.GetPlayer().RemoveItem(WOPshield2,1) && Game.GetPlayer().RemoveItem(WOPSoul,1) WOPshield3.Enable()EndifEndEvent when i only have this "Game.GetPlayer().RemoveItem(WOPshield2,1)" the item in my inventory is removed, but "WOPshield3.Enable()" is spawn means the "Else" is working.but i dont have this "Game.GetPlayer().RemoveItem(WOPSoul,1)". Why the conditional filled and not showing the message box "Debug.MessageBox("Player has no requirement item on inventory")" ? Did my "&&" operand wrong? Thanks Link to comment Share on other sites More sharing options...
IsharaMeradin Posted December 8, 2019 Share Posted December 8, 2019 The && is used for conditions rather than actual function calls. It is used correctly in the IF statement but you cannot use it in the second location. If you want both items to be removed under the same condition, put each RemoveItem function call on a separate line. Your code modified: Armor Property WOPshield2 Auto MiscObject Property WOPSoul Auto ObjectReference Property WOPshield3 Auto Event OnActivate(ObjectReference akActionRef) If (Game.GetPlayer().GetItemCount(WOPshield2) == 0) && (Game.GetPlayer().GetItemCount(WOPSoul) == 0) Debug.MessageBox("Player has no requirement item on inventory") Else Game.GetPlayer().RemoveItem(WOPshield2,1) Game.GetPlayer().RemoveItem(WOPSoul,1) WOPshield3.Enable() Endif EndEvent I would make a small adjustment to help speed up the script by not calling out to the game script to get the player information every single time. Get it once, store it in a variable and use that. Thankfully, the OnActivate event already has a parameter containing the one who activated the object. Compare it once to Game.GetPlayer() and as long as it is a match use the akActionRef parameter when you need the player. Your code further adjusted: Armor Property WOPshield2 Auto MiscObject Property WOPSoul Auto ObjectReference Property WOPshield3 Auto Event OnActivate(ObjectReference akActionRef) If akActionRef == Game.GetPlayer() If (akActionRef.GetItemCount(WOPshield2) == 0) && (akActionRef.GetItemCount(WOPSoul) == 0) Debug.MessageBox("Player has no requirement item on inventory") Else akActionRef.RemoveItem(WOPshield2,1) akActionRef.RemoveItem(WOPSoul,1) WOPshield3.Enable() EndIf Endif EndEvent Link to comment Share on other sites More sharing options...
ReDragon2013 Posted December 9, 2019 Share Posted December 9, 2019 this code with AND If (akActionRef.GetItemCount(WOPshield2) == 0) && (akActionRef.GetItemCount(WOPSoul) == 0)has to be coded with OR If (akActionRef.GetItemCount(WOPshield2) == 0) || (akActionRef.GetItemCount(WOPSoul) == 0)to make activation right.. Link to comment Share on other sites More sharing options...
carbondz2010 Posted December 9, 2019 Author Share Posted December 9, 2019 (edited) Thanks The && is used for conditions rather than actual function calls. thanks for replying, as you said that "&&" is for conditional, but the condition still run to "else" if I have only one item between WOPshield2 and WOPSoul in my inventory,when i dont have both item, "debug.messagebox" working, this code with AND If (akActionRef.GetItemCount(WOPshield2) == 0) && (akActionRef.GetItemCount(WOPSoul) == 0)has to be coded with OR If (akActionRef.GetItemCount(WOPshield2) == 0) || (akActionRef.GetItemCount(WOPSoul) == 0)to make activation right.. I need both item to do "else" not one of them with "or" Edited December 9, 2019 by carbondz2010 Link to comment Share on other sites More sharing options...
ReDragon2013 Posted December 9, 2019 Share Posted December 9, 2019 (edited) You wrote: "I need both item to do 'else' not one of them with 'or'" IF ( TRUE) ; true condition ELSE ; false condition ENDIFYou don't really understand how multiple if conditions are working !!!AND IF (TRUE) && (TRUE) ; == TRUE ; true condition is taken ELSE ENDIF IF (TRUE) && (False) ; == False ELSE ; false condition is taken ENDIF IF (False) && (TRUE) ; == False ELSE ; false condition is taken ENDIF IF (False) && (False) ; == False ELSE ; false condition is taken ENDIF OR IF (TRUE) || (TRUE) ; == TRUE ; true condition is taken ELSE ENDIF IF (TRUE) || (False) ; == TRUE ; true condition is taken ELSE ENDIF IF (False) || (TRUE) ; == TRUE ; true condition is taken ELSE ENDIF IF (False) || (False) ; == False ELSE ; false condition is taken ENDIF Edited December 9, 2019 by ReDragon2013 Link to comment Share on other sites More sharing options...
Grospolina Posted December 9, 2019 Share Posted December 9, 2019 I need both item to do "else" not one of them with "or"If that's the case, then ReDragon2013 is correct. You could invert it to make it easier to read. e.g. If (akActionRef.GetItemCount(WOPshield2) > 0) && (akActionRef.GetItemCount(WOPSoul) > 0) ; need at least 1 of each akActionRef.RemoveItem(WOPshield2,1) akActionRef.RemoveItem(WOPSoul,1) WOPshield3.Enable() Else Debug.MessageBox("Player has no requirement item on inventory") EndifWhen you do the inverse of multiple conditionals, you have to swap AND with OR. e.g. If (akActionRef.GetItemCount(WOPshield2) <= 0) || (akActionRef.GetItemCount(WOPSoul) <= 0) ; is the opposite of If (akActionRef.GetItemCount(WOPshield2) > 0) && (akActionRef.GetItemCount(WOPSoul) > 0) Link to comment Share on other sites More sharing options...
Cheyron Posted December 10, 2019 Share Posted December 10, 2019 you may want to get into the habit of storing values that functions return so you dont have to keep calling a function multiple times for the same value needed... depending on your code it can cause a performance imapct... especially if you are doing it in loops. Game.GetPlayer() is not cpu intense but it is better to give your cpu as little work to do as possible... so when you write code that would be cpu intense you are in habit of being economical If (Game.GetPlayer().GetItemCount(WOPshield2) == 0) && (Game.GetPlayer().GetItemCount(WOPSoul) == 0) to Actor p = Game.GetPlayer()If (p.GetItemCount(WOPshield2) == 0) && (p.GetItemCount(WOPSoul) == 0) like for example would you do this... if a+b < 5 && a + b > 0 or... int c = a + bIf c < 5 && c > 0 accessing a class with . operator is same as doing addition, you calculate the function address and then have the cpu jump to the function and execute it then it has to return back to where it was Link to comment Share on other sites More sharing options...
maxarturo Posted December 11, 2019 Share Posted December 11, 2019 you may want to get into the habit of storing values that functions return so you dont have to keep calling a function multiple times for the same value needed... depending on your code it can cause a performance imapct... especially if you are doing it in loops. Game.GetPlayer() is not cpu intense but it is better to give your cpu as little work to do as possible... so when you write code that would be cpu intense you are in habit of being economical If (Game.GetPlayer().GetItemCount(WOPshield2) == 0) && (Game.GetPlayer().GetItemCount(WOPSoul) == 0) to Actor p = Game.GetPlayer()If (p.GetItemCount(WOPshield2) == 0) && (p.GetItemCount(WOPSoul) == 0) like for example would you do this... if a+b < 5 && a + b > 0 or... int c = a + bIf c < 5 && c > 0 accessing a class with . operator is same as doing addition, you calculate the function address and then have the cpu jump to the function and execute it then it has to return back to where it was CheyronDoes this also applies for this: If ( akActionRef == Game.GetPlayer() ) ( akActionRef as Actor ).DamageActorValue("Health", ( akActionRef as Actor ).GetActorValue("Health") * 0.50) Link to comment Share on other sites More sharing options...
Cheyron Posted December 11, 2019 Share Posted December 11, 2019 you may want to get into the habit of storing values that functions return so you dont have to keep calling a function multiple times for the same value needed... depending on your code it can cause a performance imapct... especially if you are doing it in loops. Game.GetPlayer() is not cpu intense but it is better to give your cpu as little work to do as possible... so when you write code that would be cpu intense you are in habit of being economical If (Game.GetPlayer().GetItemCount(WOPshield2) == 0) && (Game.GetPlayer().GetItemCount(WOPSoul) == 0) to Actor p = Game.GetPlayer()If (p.GetItemCount(WOPshield2) == 0) && (p.GetItemCount(WOPSoul) == 0) like for example would you do this... if a+b < 5 && a + b > 0 or... int c = a + bIf c < 5 && c > 0 accessing a class with . operator is same as doing addition, you calculate the function address and then have the cpu jump to the function and execute it then it has to return back to where it was CheyronDoes this also applies for this: If ( akActionRef == Game.GetPlayer() ) ( akActionRef as Actor ).DamageActorValue("Health", ( akActionRef as Actor ).GetActorValue("Health") * 0.50) I think that will just tell the compiler what code to create for the cpu… maybe the compiler creates two variables with same casted value or maybe it knows those values are equal and it only creates one variable for the casted object... im not sure actually, it depends on the compiler... even in your example I would declare a variable to hold this casted value and only do it once. Good code should never have the same thing written twice is what I have heard before... if you write the same code over and over then you should make a function or whatever, etc... I have more experience with languages like c# and the .NET compiler is very smart and you can write bad code and the compiler will fix/optimize it for you when it compiles it... so depends on language and I don't know much about papyrus but I know for most languages the . operator is used to access a class which is the same as addition to a base address and an offset for that property or function... so that means using the dot operator when you don't need to creates more arithmetic for the cpu to compute Game.GetPlayer() is the same as jumpTo gameBase + getPlayerOffset ...then cpu has to go wherever that is and it has to keep track of where it is when it jumps so it can return back to the same place... it's just more work... small scripts or what have you... the difference is not comprehendible by humans but it can add up in loops and become noticeable in some cases for example. Video games calculate enough as is so even your tiny scripts you should write optimized and not be sloppy/lazy... not saying that is the case here. Just be in the habit of not telling the cpu to do the same thing twice because skyrim has enough work for the cpu already haha. Link to comment Share on other sites More sharing options...
maxarturo Posted December 11, 2019 Share Posted December 11, 2019 (edited) Cheyron The reason that i'm asking is because i noticed something weird. To begin with: I do use the "Store Value" to make the script more flexible and faster to execute, especially when it comes to look for the Player Ref. Example: If ( akActionRef == Game.GetPlayer() ) SoundFX.Play(akActionRef) akActionRef.removeItem(MyKey, 1) ... etc But, in this specific line of codes when i replace the "Game.GetPlayer()" with the "Store Value" i see a noticable delay in the execution as opposed to the execution with "Game.GetPlayer()" which runs as it's suppose to. Example: If ( akActionRef == Game.GetPlayer() ) ( akActionRef as Actor ).DamageActorValue("Health", ( akActionRef as Actor ).GetActorValue("Health") * 0.50) ( akActionRef as Actor ).DamageActorValue("Magicka", ( akActionRef as Actor ).GetActorValue("Magicka") * 0.50) ( akActionRef as Actor ).DamageActorValue("Stamina", ( akActionRef as Actor ).GetActorValue("Stamina") * 0.50) ... etc Edit: I forgot to add that this does not compile, if anyone might be wondering. akActionRef.DamageActorValue("Stamina", akActionRef.GetActorValue("Stamina") * 0.50) Edited December 11, 2019 by maxarturo Link to comment Share on other sites More sharing options...
Recommended Posts