GetActorValuePercentage not working properly in Papyrus (log

Post » Wed Jun 20, 2012 9:10 am

So having an issue here with a mod I am working on. What happens is when the player is below 40% stamina while wearing heavy armor, they experience an exhaustion effect (primarily controlled via perks and spell effects. They can "influence" this through perks, so it happens at 30%, 20%, etc. On top of that, the player takes stamina damage per hit, which is increased if they have certain perks.

I have that part all working perfectly fine, at least so I think. I've not noticed any real issues with it, though I suppose it would help to actually look into someway to verify my numbers in-game instead of making rough judgements from stamina and damage taken. Anyways, that's not the point.

The issue is, I'm syncing it up with an Image Space effect on the hud that flashes when a player is hit while in this "exhausted" state.

The effect shows up fine when the player is below 40% stamina, but I can't get it to recognize "lower" stamina percentage levels.

Here's the code snippet:

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)if HeavyArmorCuirassEquipped == true && abHitBlocked == false  Game.GetPlayer().DamageActorValue("stamina", 5)  StaminaDamageValue = http://forums.bethsoft.com/topic/1363712-getactorvaluepercentage-not-working-properly-in-papyrus-logic-issue/5   if Game.GetPlayer().HasPerk(CPO_HA_PERK_TargetedDefense01)    Game.GetPlayer().DamageActorValue("stamina", 1)    StaminaDamageValue = http://forums.bethsoft.com/topic/1363712-getactorvaluepercentage-not-working-properly-in-papyrus-logic-issue/6	 if Game.GetPlayer().HasPerk(CPO_HA_PERK_TargetedDefense02)	  Game.GetPlayer().DamageActorValue("stamina", 1)	  StaminaDamageValue = http://forums.bethsoft.com/topic/1363712-getactorvaluepercentage-not-working-properly-in-papyrus-logic-issue/7	   if Game.GetPlayer().HasPerk(CPO_HA_PERK_TargetedDefense03)	    Game.GetPlayer().DamageActorValue("stamina", 1)	    StaminaDamageValue = http://forums.bethsoft.com/topic/1363712-getactorvaluepercentage-not-working-properly-in-papyrus-logic-issue/8	   endif	 endif   endif  if Game.GetPlayer().GetActorValuePercentage("stamina") < 0.1 && Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit03)   defaultDesaturateIMod.Apply(0.4)  elseif Game.GetPlayer().GetActorValuePercentage("stamina") < 0.2 && Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit02)   defaultDesaturateIMod.Apply(0.4)  elseif Game.GetPlayer().GetActorValuePercentage("stamina") < 0.3 && Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit01)   defaultDesaturateIMod.Apply(0.4)  elseif Game.GetPlayer().GetActorValuePercentage("stamina") < 0.4   defaultDesaturateIMod.Apply(0.4)  endifendifEndEvent

The only thing that ever "fires" is the very bottom desaturatemod effect. The top 3 ones never trigger, or rather, I always get the effect to happen below 40% instead of only below 10, 20, etc. I thought the elseif's never fired, unless the above condition was false, AND it's condition was true? Why is my effect triggering at 40% then, reguardless of the perk and stamina conditons above it being true?
User avatar
Ana
 
Posts: 3445
Joined: Sat Jul 01, 2006 4:29 am

Post » Wed Jun 20, 2012 8:59 pm

Logic issue. Try:

  if Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit03)	if Game.GetPlayer().GetActorValuePercentage("stamina") < 0.1	  defaultDesaturateIMod.Apply(0.4)	endif  elseif Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit02)	if Game.GetPlayer().GetActorValuePercentage("stamina") < 0.2	  defaultDesaturateIMod.Apply(0.4)	endif  elseif Game.GetPlayer().HasPerk(CPO_HA_PERK_WeightedSpirit01)	if Game.GetPlayer().GetActorValuePercentage("stamina") < 0.3	  defaultDesaturateIMod.Apply(0.4)	endif  elseif Game.GetPlayer().GetActorValuePercentage("stamina") < 0.4	defaultDesaturateIMod.Apply(0.4)  endif
User avatar
Terry
 
Posts: 3368
Joined: Mon Jul 09, 2007 1:21 am

Post » Wed Jun 20, 2012 9:46 pm

Thanks, I'll try that. Though wouldn't that essentially do the same thing the "&&" (and) conditons do?
User avatar
Emzy Baby!
 
Posts: 3416
Joined: Wed Oct 18, 2006 5:02 pm

Post » Thu Jun 21, 2012 12:25 am

here's your logic issue:

the game will read an If/EsleIf stack from the top down.

therefore it will ALWAYS fire stamina < 0.4 first, since that condition is met first if you consider that a player with healthy stamina will be above all those conditions, until it drops to below 40%, in which it will skip the first 3 conditions (since they are not yet met) and fire.

even if the conditions are met (like the player now has the associated perks), the bottom 40% will fire first since it does not have a condition that excludes the perks.


if you want the 40% effect to apply only when the player does not have the perks you need to add a condition

&& !game.GetPlayer.HasPerk(etc) or restructure your if stack like the user suggested above


also, calling the GetPlayer() function that many times is not necessary. you should call the function once and store the returned value into an actor variable


actor PlayerRef = Game.GetPlayer()


then all your subsequent player calls would be:

PlayerRef.HasPerk(etc)



this way it refers to the returned value rather than re-calling the function every single time (it runs faster)
User avatar
Flesh Tunnel
 
Posts: 3409
Joined: Mon Sep 18, 2006 7:43 pm

Post » Wed Jun 20, 2012 8:22 pm

Very different.

In your code, if the player has the WeightedSpirit03 perk and is at 35% stamina, then the last line will run and apply the IMod.
In this new code, nothing will happen at all in this scenery.


EDIT: Nevermind. Amethyst was faster and probably explained it better than me.
User avatar
Stefanny Cardona
 
Posts: 3352
Joined: Tue Dec 19, 2006 8:08 pm

Post » Wed Jun 20, 2012 2:54 pm

Oh I see, I was under the impression that if the first if-statment wasn't true, then it would check the first elseif, then the 2nd, etc until it found something true, going down the line. I wasn't aware it just instantly grabbed whichever statement ended up being true first in-general vs whichever one is true first logically.

And I'll try that PlayerRef thing.

I tried doing it before but I'd always get script errors whenever I'd try compiling (and it looked just like that), so I just stuck with spelling it out for each function. I'll try it again and see if it works. Hopefully so :)
User avatar
Horse gal smithe
 
Posts: 3302
Joined: Wed Jul 05, 2006 9:23 pm

Post » Wed Jun 20, 2012 3:17 pm

Oh I see, I was under the impression that if the first if-statment wasn't true, then it would check the first elseif, then the 2nd, etc until it found something true, going down the line.

In fact this is how it works. But in the case I exposed above (player has WeightedSpirit03 and 35% stamina) the first statement would not be true, so it would try the 2nd, etc, until the last one. That last one would be true, resulting in screen flashing for a player full perked and with 35% stamina, which is wrong.
User avatar
Kelly Upshall
 
Posts: 3475
Joined: Sat Oct 28, 2006 6:26 pm

Post » Wed Jun 20, 2012 11:11 pm

Ahhhh of course! I can't believe I didn't see that it would do that :tongue:

Funny how such issues often have such simple reasons/problems :v
User avatar
Megan Stabler
 
Posts: 3420
Joined: Mon Sep 18, 2006 2:03 pm

Post » Wed Jun 20, 2012 9:33 am

Also, doing the PlayerRef thing, just like before, fails to compile with an error about unknown type "Game".

If I just declaire the variable by itself (actor PlayerRef) and then set the value through OnInit it works though...
User avatar
Brittany Abner
 
Posts: 3401
Joined: Wed Oct 24, 2007 10:48 pm

Post » Wed Jun 20, 2012 12:33 pm

you should be declaring the actor variable inside your onHit event

Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)Actor PlayerRef = Game.GetPlayer()
User avatar
quinnnn
 
Posts: 3503
Joined: Sat Mar 03, 2007 1:11 pm


Return to V - Skyrim