When to use Elseif, and when to use Else If?

Post » Wed Jan 15, 2014 4:16 am

My scripts are turning into a labyrinth of conditions, and I'm getting myself all confused again. :bonk:

Is there a layman's explanation for when I should use Elseif and when I should use Else If? When I looked online the only explanations seemed to be in pseudo code which really didn't help!

The latest script for my Advanced Shrines mod is being problematic, in that I'm getting lost...I thought I had it all sorted, as it all looks fine to me in Sublime text, but I'm still getting a missing endif on line 107 on compile.

I suspect that it's because I'm using a mixture of Elseifs and Else If, and for any given use I really don't know why I'm using one and not the other... :ermm:

Spoiler

Scriptname ShrineDonationArkay extends ObjectReference

import debug

Perk Property Merchant Auto
MiscObject Property Gold001 Auto
Spell Property TempleBlessing Auto
Message Property BlessingMessage Auto
Message Property AltarRemoveMsg Auto
Message Property _ShrineDonationZenitharMessage Auto
message property need100Gold auto ;You do not have 100 gold to offer as a donation!
message property need500Gold auto ;You do not have 500 gold to offer as a donation!
Idle Property IdlePray Auto
Actor property PlayerRef auto

import utility

Actor myTarget

Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
myTarget = akActionRef as Actor
int MyButton = _ShrineDonationArkayMessage.Show()
if ( MyButton == 0)
;make the player pray - very small chance of being granted blessing
int iRand = RandomInt(1,10)
if iRand > 9
TryBlessing(100)
elseif debug.notification("You pray to Arkay, but he does not respond on this occasion.")
endif
Game.ForceThirdPerson()
PlayerRef.PlayIdle(IdlePray)
Utility.Wait(4.0)
Debug.SendAnimationEvent(PlayerRef, "IdleForceDefaultState")
Game.ForceFirstPerson()

elseIf ( MyButton == 1)
If PlayerRef.GetItemCount(Gold001) < 100
need100Gold.Show()
else
PlayerRef.RemoveItem(Gold001, 100)
int iRand = RandomInt(1,10)
if iRand > 7
TryBlessing(100)
elseif debug.notification("You make your donation, but Arkay does not respond on this occasion.")
endif
endif
elseIf( MyButton == 2)
If PlayerRef.GetItemCount(Gold001) < 500
;make the transaction fail
need500Gold.Show()
Else
PlayerRef.RemoveItem(Gold001, 500)
TryBlessing(500)
endif
elseIf (MyButton == 3)
;do nothing
endif
endif
EndEvent


function TryBlessing(int iDonationAmount)
If PlayerRef.HasPerk(Necromancy)
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Else
If PlayerRef.HasPerk(Necromancy)
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Else
If PlayerRef.HasSpell(VampireHuntersSight)
debug.messagebox("You are a vile undead creature of the night! Arkay rejects your offering! Your spirit must return to the grave, or you must return to the world of the living before it is too late!")

Else
If (Game.QueryStat("Undead Killed") > 500)
if iDonationAmount == 100
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
PlayerRef.AddItem(Gold001, 100)
ApplyBlessing()
elseif iDonationAmount == 500
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
PlayerRef.AddItem(Gold001, 500)
ApplyBlessing()
else
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
ApplyBlessing()
endif

Else
If (Game.QueryStat("Undead Killed") > 250)
if iDonationAmount == 100
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - he grants a blessing for just 50 gold! Continue to return the undead back to the cycle!")
PlayerRef.AddItem(Gold001, 50)
ApplyBlessing()
elseif iDonationAmount == 500
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - he grants a blessing for just 250 gold! Continue to return the undead back to the cycle!")
PlayerRef.AddItem(Gold001, 250)
ApplyBlessing()
else
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - on this occasion he grants his blessing for free! Continue to return the undead back to the cycle!")
ApplyBlessing()
endif

Else
ApplyBlessing()
debug.messagebox("You have shown respect for the balance of life and death - Arkay grants his blessing! Arkay wills you to help return those undead spirits back to the cycle, and frowns upon acts of necromancy.")
endif
endFunction

function ApplyBlessing()
Game.ForceThirdPerson()
PlayerRef.PlayIdle(IdlePray)
TempleBlessing.Cast(myTarget, myTarget)
AltarRemoveMsg.Show()
BlessingMessage.Show()
Utility.Wait(4.0)
Debug.SendAnimationEvent(PlayerRef, "IdleForceDefaultState")
Game.ForceFirstPerson()
endFunction

User avatar
Christina Trayler
 
Posts: 3434
Joined: Tue Nov 07, 2006 3:27 am

Post » Wed Jan 15, 2014 12:00 am

First of all I believe you meant ElseIf and Else If in the title.

Let's take this piece as an example with comments ifX and elsix added by me:

If PlayerRef.HasPerk(Necromancy) ;if1
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Else ;else1
If PlayerRef.HasPerk(Necromancy) ;if2
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Else ;else2
If PlayerRef.HasSpell(VampireHuntersSight) ;if3
debug.messagebox("You are a vile undead creature of the night! Arkay rejects your offering! Your spirit must return to the grave, or you must return to the world of the living before it is too late!")

In this the indentation is wrong, each elsix should be at same indentation as ifX (same X) and each if should have it's own EndIf, which I don't see...your code shouldn't compile (unless papyrus is not like other programing languages)

Some would argue that is more clear to not use elseIf and many languages don't have it, but instead they have other constructions like switch...without both would be harder.

if (c1)

do1()

else

if (c2)

do2()

endIf ;2

endIf ;1

woulf be equivalent with using an elseIf and a single endIf

Remember: each "If" should have an "EndIf" and "ElseIf" in between are part of that construction. If you have "Else If" you have a new "If" which need another "EndIf". Also, each "if" may have a single "else" but many "elseIf"s...but you have to be careful so their conditions should be mutually exclusive: otherwise some branches won't be reachable, not a problem for a compiler

User avatar
GPMG
 
Posts: 3507
Joined: Sat Sep 15, 2007 10:55 am

Post » Wed Jan 15, 2014 1:56 am

ElseIf

is used if you want to add a condition that does something if

If

hasn't been filled. F.E.

If you have 100 €     I want 50€
ElseIf you have 500€
I want 250€
EndIf
Else

is used if you have more then one ElseIf's and want to set up commands that do not fill the previously given ElseIf conditions, like...

If you have 100 €
I want 50€
ElseIf you have 500€
I want 250€
Else I don't want anything or all, because you have nothing, more or less!EndIf

...so spoken to your TryBlessing function, most of the Else arguments must be replaced with ElseIf.

User avatar
Scott Clemmons
 
Posts: 3333
Joined: Sun Sep 16, 2007 5:35 pm

Post » Wed Jan 15, 2014 4:43 am

Yes, I do of course mean elseif and else if. :blush:

So, correct me if I'm wrong, then I should be using elseifs within each collection of conditions?

If PlayerRef.HasPerk(Necromancy) ;if1
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Elseif ;still part of if1
If PlayerRef.HasPerk(Necromancy) ;if2
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")

****NEW ENDIF REQUIRED HERE?****
Elseif ;still part of if1
If PlayerRef.HasSpell(VampireHuntersSight) ;if3
debug.messagebox("You are a vile undead creature of the night! Arkay rejects your offering! Your spirit must return to the grave, or you must return to the world of the living before it is too late!")

*****NEW ENDIF REQUIRED HERE?****

I'm also getting confused as to when a condition ends...when I want it to end if that particular condition isn't met and not go any further (ie the script effecively stops running there), and when the condition allows further conditions to be checked with the potential for the script still to change something in the game.

User avatar
Charlie Ramsden
 
Posts: 3434
Joined: Fri Jun 15, 2007 7:53 pm

Post » Wed Jan 15, 2014 9:51 am

Mofakin, thank you very much - that explanation actually makes some sense to me!

User avatar
Angela
 
Posts: 3492
Joined: Mon Mar 05, 2007 8:33 am

Post » Wed Jan 15, 2014 8:55 am

Think of it this way -

when using elseif, you're still constructing the same single if-block, which will only require one endif:

if  a == 0elseif  b == 0elseif  c == 0elseif  d == 0endif

when using else if, you are creating new separate if-blocks each time you use "if" by itself, which all need to be ended with their own endif command:

if  a == 0else  if b == 0  else    if c == 0    else      if d == 0      endif    endif  endifendif

Usually, if there is only a single "if" under your else, it's better (meaning simpler and more straitforward) to just use elseif. If you are going to check multiple "ifs" in your else-block, then you will want to use an else if construction, e.g.:

if  a == 0else ;only check these three if a doens't equal zero  if b == 0  endif  if c == 0  endif  if d == 0  endifendif
User avatar
Add Me
 
Posts: 3486
Joined: Thu Jul 05, 2007 8:21 am

Post » Wed Jan 15, 2014 12:56 am

Ok, so...I thought I was almost there, following Mofakin's logic...but it still fails to compile...

Spoiler

Scriptname ShrineDonationArkay extends ObjectReference

import debug

Perk Property Merchant Auto
MiscObject Property Gold001 Auto
Spell Property TempleBlessing Auto
Message Property BlessingMessage Auto
Message Property AltarRemoveMsg Auto
Message Property _ShrineDonationZenitharMessage Auto
message property need100Gold auto ;You do not have 100 gold to offer as a donation!
message property need500Gold auto ;You do not have 500 gold to offer as a donation!
Idle Property IdlePray Auto
Actor property PlayerRef auto

import utility

Actor myTarget

Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
myTarget = akActionRef as Actor
int MyButton = _ShrineDonationZenitharMessage.Show()
if ( MyButton == 0)
;make the player pray - very small chance of being granted blessing
int iRand = RandomInt(1,10)
if iRand > 9
TryBlessing(100)
elseif debug.notification("You pray to Arkay, but he does not respond on this occasion.")
endif
Game.ForceThirdPerson()
PlayerRef.PlayIdle(IdlePray)
Utility.Wait(4.0)
Debug.SendAnimationEvent(PlayerRef, "IdleForceDefaultState")
Game.ForceFirstPerson()

elseIf ( MyButton == 1)
If PlayerRef.GetItemCount(Gold001) < 100
need100Gold.Show()
else
PlayerRef.RemoveItem(Gold001, 100)
int iRand = RandomInt(1,10)
if iRand > 7
TryBlessing(100)
elseif debug.notification("You make your donation, but Arkay does not respond on this occasion.")
endif
endif
elseIf( MyButton == 2)
If PlayerRef.GetItemCount(Gold001) < 500
;make the transaction fail
need500Gold.Show()
Else
PlayerRef.RemoveItem(Gold001, 500)
TryBlessing(500)
endif
elseIf (MyButton == 3)
;do nothing
endif
endif
EndEvent


function TryBlessing(int iDonationAmount)
If PlayerRef.HasPerk(Necromancy)
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Elseif PlayerRef.HasPerk(Necromancy)
debug.messagebox("You have travelled too far down the path of Necromancy! Arkay rejects your offering!")
Elseif PlayerRef.HasSpell(VampireHuntersSight)
debug.messagebox("You are a vile undead creature of the night! Arkay rejects your offering! Your spirit must return to the grave, or you must return to the world of the living before it is too late!")

Else If (Game.QueryStat("Undead Killed") > 500)
if iDonationAmount == 100
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
PlayerRef.AddItem(Gold001, 100)
ApplyBlessing()
elseif iDonationAmount == 500
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
PlayerRef.AddItem(Gold001, 500)
ApplyBlessing()
else
debug.messagebox("You have returned many undead back to the cycle, which pleases Arkay greatly - he grants a blessing for free!")
ApplyBlessing()
endif

ElseIf
(Game.QueryStat("Undead Killed") > 250)
if iDonationAmount == 100
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - he grants a blessing for just 50 gold! Continue to return the undead back to the cycle!")
PlayerRef.AddItem(Gold001, 50)
ApplyBlessing()
elseif iDonationAmount == 500
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - he grants a blessing for just 250 gold! Continue to return the undead back to the cycle!")
PlayerRef.AddItem(Gold001, 250)
ApplyBlessing()
else
debug.messagebox("You have killed a number of undead and returned them to the cycle - this is encouraged by Arkay - on this occasion he grants his blessing for free! Continue to return the undead back to the cycle!")
ApplyBlessing()
endif

Else
ApplyBlessing()
debug.messagebox("You have shown respect for the balance of life and death - Arkay grants his blessing! Arkay wills you to help return those undead spirits back to the cycle, and frowns upon acts of necromancy.")
endif
endFunction

function ApplyBlessing()
Game.ForceThirdPerson()
PlayerRef.PlayIdle(IdlePray)
TempleBlessing.Cast(myTarget, myTarget)
AltarRemoveMsg.Show()
BlessingMessage.Show()
Utility.Wait(4.0)
Debug.SendAnimationEvent(PlayerRef, "IdleForceDefaultState")
Game.ForceFirstPerson()
endFunction

c:\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\shrinedonationarkay.psc(71,7): required (...)+ loop did not match anything at input 'If'
c:\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\shrinedonationarkay.psc(85,8): no viable alternative at input '\\r\\n'
c:\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\shrinedonationarkay.psc(104,1): mismatched input 'endFunction' expecting ENDIF

User avatar
Clea Jamerson
 
Posts: 3376
Joined: Tue Jun 20, 2006 3:23 pm

Post » Wed Jan 15, 2014 1:52 am

ElseIf requires a condition right after it, not another if.

"Else" means in case the condition is not true do something (which may start with another "if").

"ElseIf" is just a mean to allow you to group many conditions in a single "If" construction. They are dealt with one after another at same level, once one condition is true the block under it will execute (till next else/elseIf/endIf) and no other "ElseIf" blocks will be consider regardless if their condition is true.

User avatar
maria Dwyer
 
Posts: 3422
Joined: Sat Jan 27, 2007 11:24 am

Post » Wed Jan 15, 2014 4:05 am

You need another endif at the end of your TryBlessing function. To make debugging these statements easier, I'd suggest using clearly standardized indentation of the kind I put in my last post - it makes it much easier to figure out when you are missing an endif when they're all lined up like that.

However, you should probably change some things - for instance, these kind of statements don't make any sense:

elseif debug.notification("You make your donation, but Arkay does not respond on this occasion.")

because debug.notification is not a condition that can be checked. Anytime you have "if" or "elseif" (or "else if") it should immediately be followed by something that can be evaluated as a boolean TRUE or FALSE. On the other hand, it would be okay to put a debug after "else" (without any ifs), because else doesn't require any conditions, it just performs whatever commands come after it.

User avatar
Juan Suarez
 
Posts: 3395
Joined: Sun Nov 25, 2007 4:09 am

Post » Wed Jan 15, 2014 2:19 am

Thanks!

That's why I'm using Sublime text, as that should make things easier to spot.

Whoops - I think I might need to have a break, and look with fresh eyes tomorrow...that definitely doesn't make sense, but I read through that section multiple times looking for anything awry...I think it's because during the process of coding I've had to shuffle things around to fix other errors...

User avatar
Emmie Cate
 
Posts: 3372
Joined: Sun Mar 11, 2007 12:01 am


Return to V - Skyrim