Simple If Check Fails - My Problem?

Post » Sat Aug 31, 2013 1:08 am

I've been getting enough reports on this to warrant me taking a poke; I have a script on a trapdoor in Falskaar that controls transport to and from Skyrim. It simply checks a few things and handles the player's input properly. First it checks if a quest is completed, then if the player has enough money to make the trip. Here is the script:

Spoiler
Scriptname FSKR_BoatTravelSCRIPT extends ObjectReference  ObjectReference Property PlayerRef AutoMessage Property AskWulf Auto ;the player still needs to talk to Wulf to establish transportMessage Property NoMoney Auto ;the player cannot afford passage on Wulf's shipObjectReference Property Place1 Auto ;where to stand while showing time passObjectReference Property Place2 Auto ;where to stand when completedImageSpaceModifier Property ISFade Auto ;the ISM to display at end of timelapseQuest Property FSSQ02 AutoMiscObject Property Gold001 AutoGlobalVariable Property FSBoatPrice Auto ;the price of travelling on the boatGlobalVariable Property TimeScale AutoInt Speed ; int to save players set timescaleMessage Property Arrival Auto; Message to display at the end of the cutsceneMessage Property Confirm Auto; Is the player sure they wish to travel on the boat?Quest Property FSFF02 Auto ; for one time misc obj Event OnInit() BlockActivation(True)EndEvent Event OnActivate(ObjectReference akActionRef) If (akActionRef == PlayerRef)  If ((PlayerRef as Actor).IsInCombat() == 0)   If FSSQ02.GetStage() <= 5    AskWulf.Show()    If FSSQ02.IsObjectiveDisplayed(1) == 0     FSSQ02.SetObjectiveDisplayed(1)    EndIf   ElseIf FSSQ02.GetStage() == 10    If PlayerRef.GetItemCount(Gold001) >= (FSBoatPrice.GetValue())        ; <--- The line that fails for no reason. Global is set correctly (Verified ingame) and player has enough gold!     Int iButton = Confirm.Show((FSBoatPrice.GetValue()))     If iButton != -1      If iButton == 0 ;travel on the boat       Game.DisablePlayerControls(True, True, True, True, True, False, True, False)       Speed = (TimeScale.GetValue() as Int)   ;    Utility.Wait(0.5)       PlayerRef.MoveTo(Place1)       Utility.Wait(0.5)       TimeScale.SetValue(10000)       Utility.WaitGameTime(14)       TimeScale.SetValue(Speed)       Utility.Wait(2)       Arrival.Show()       ISFade.Apply()       Utility.Wait(1.5)       PlayerRef.MoveTo(Place2)       Utility.Wait(1.5)       Game.EnablePlayerControls()       PlayerRef.RemoveItem(Gold001, (FSBoatPrice.GetValue() as Int))       If FSFF02.GetStage() < 2        FSFF02.SetStage(2)       EndIf      ElseIf iButton == 1 ; close the menu       ;do nothing      EndIf     EndIf    Else     NoMoney.Show((FSBoatPrice.GetValue()))    EndIf   EndIf  EndIf Else  Self.Activate(akActionRef, True) EndIfEndEvent

People are reporting that, even with large amounts of gold, the 'You do not have enough money' message is popping up. They've checked the global that it compares to, and the global is set correctly. So the money check line "If PlayerRef.GetItemCount(Gold001) >= (FSBoatPrice.GetValue())" is failing for no apparent reason.

Can anyone think of any reasons why this would fail, and if my script it as fault or not? Not everyone reports this, it works for a vast majority of people. But enough have reported it that I'd like to fix it if I can.

Thanks,

AV

User avatar
Meghan Terry
 
Posts: 3414
Joined: Sun Aug 12, 2007 11:53 am

Post » Sat Aug 31, 2013 1:59 am

ObjectReference Property PlayerRef Auto
ObjectReference ?!!
I always do it this way:
Actor Property PlayerRef Auto
Also, can you put in a debug message for this: Int iButton = Confirm.Show((FSBoatPrice.GetValue()))
debug.messagebox("Global = " + FSBoatPrice.GetValue())
User avatar
Bambi
 
Posts: 3380
Joined: Tue Jan 30, 2007 1:20 pm

Post » Fri Aug 30, 2013 4:05 pm

Toss in some output messages and see where it fails.
User avatar
Alex Blacke
 
Posts: 3460
Joined: Sun Feb 18, 2007 10:46 pm

Post » Sat Aug 31, 2013 2:00 am

Like I said, it's showing the NoMoney msg, so I know exactly where it's failing. The If line that checks the money is what's failing. (Though the way it pasted the script above isn't very easy to read, sorry about that!) After that check there are no other checks beyond those that deal with the message, the one that isn't being displayed.

And as I said the people having the issue have verified that the global is the correct value (it even displays it in the message at the correct value, which is what tipped them off that it was broken. They'll have like 80k and it says "You do not have the 500 gold required".). So the global isn't wrong, the check simply fails, so it else's to the other message.

I'm wondering why that check fails. I could always try debug messages, but I don't know what they'll get me, and I can't reproduce the error so I'd have to release a version (Maybe a test version or something) with them to get feedback from the people.

As for OBJ vs Actor on the playerref variable, I think I've always done ObjectRef. In addition, GetItemCount must be run on an ObjRef, so that's why.

User avatar
kasia
 
Posts: 3427
Joined: Sun Jun 18, 2006 10:46 pm

Post » Fri Aug 30, 2013 3:45 pm

I have absolutely no idea what may be going on, but what I would try is to set up a temporary function-scope variable like this:
Event OnActivate(ObjectReference akActionRef)	Int Price = FSBoatPrice.GetValue()	.	.	.
and only use that Price variable thereafter, just to rule out any possible rogue issues with the global. (And as a bonus, it might also make the script just slightly more efficient.)

If you don't like that, you could also try using "as Int" in your comparison, just to be on the safe side, as I am under the impression, that the global is stored as a float, and you have not used that type conversion systematically in the script. (Using the temporary Int variable would also address that, in case it might have any bearing on the issue.)
User avatar
Jennie Skeletons
 
Posts: 3452
Joined: Wed Jun 21, 2006 8:21 am

Post » Fri Aug 30, 2013 12:41 pm

"As for OBJ vs Actor on the playerref variable, I think I've always done ObjectRef. In addition, GetItemCount must be run on an ObjRef, so that's why."

Nope, not for me anyway...I use it all the time on ACTOR REFs, not ObjectRefs:

Actor Property PlayerRef Auto

if PlayerRef.GetItemCount(what ever) > 0

works for me...

User avatar
Russell Davies
 
Posts: 3429
Joined: Wed Nov 07, 2007 5:01 am

Post » Fri Aug 30, 2013 5:15 pm

Yes it would, because actors are a subset of object references.

But, if you had a look at the compiled script using PapyrusAssembler, you might see, that it would be equivalent to
Actor Property PlayerRef Autoif (PlayerRef as ObjectReference).GetItemCount(what ever) > 0
as the compiler would automatically insert that type cast to match the required native argument type. Using ObjectReference from the start simply bypasses that mostly harmless but unnecessary type cast shuffling.

P.S.
But of course, if you also use functions, that require an Actor argument, then it makes sense to use the Actor type, or you would have to do an explicit type cast yourself the other way around every time you use such functions.
User avatar
Vicki Blondie
 
Posts: 3408
Joined: Fri Jun 16, 2006 5:33 am

Post » Sat Aug 31, 2013 12:15 am

Have you tried something like transferring the player's gold to a container and then call the function on that container?
I know it makes no sense, but doing things like this (that I have discovered thru a GOOGOLPLEXIAN hours of trial and error) has often solved mysterious issues... for me anyway.
I have found a lot of undocumented quirks that work like this.
User avatar
matt oneil
 
Posts: 3383
Joined: Tue Oct 09, 2007 12:54 am

Post » Fri Aug 30, 2013 11:48 pm

This may be slightly outside the issue.

However, I have sometimes (briefly, not seriously) wondered if there are any specific pros and cons to using a global vs. placing in some master script a property, that would be available to other scripts in the mod. The former would need to be edited as an item. The latter would need to be initialized through a property setting.

Personally, I might opt to go for the property, as at least its type would be self-evident, though I may be missing something else relevant to consider.
User avatar
Silvia Gil
 
Posts: 3433
Joined: Mon Nov 20, 2006 9:31 pm


Return to V - Skyrim