Jump to content

[LE] Script: comparing skills - Help!


nayakri

Recommended Posts

I did a bit of searching before posting here but found nothing useful.

 

So, I was trying to put one of my quest into my College Mod, but having completely ZERO experience with Papyrus Script, I found myself almost entirely unable to get some of my ideas alive. Considering how close I am to smashing my keyboard, I beg you for help with these awful, rude and annoying scripts. Here is my main problem:

 

Checking player's best skill when giving him/her reward.

What I want to do: without spoilers, player manages to finish his task and is given Apprentice Robes (I'll make it more special later on). BUT these Apprentice Robes are supposed to be based on his/hers best skill (Destruction, Illusion, Alteration, Conjuration, Restoration).

I guessed I need to make a loop - but I have no idea how to do it with these variables (not to mention I don't remember how I was making loops in C++, especially I have no idea about it in Papyrus).

My best idea that actually worked... to some extent:

float Destruction
float Illusion
float Alteration
float Restoration
float Conjuration

if (Game.GetPlayer().GetActorValue(Destruction > Illusion))
Game.GetPlayer().AddItem(<itemname>, 1)
endif

And here... I stopped. As I said, I don't know how to turn it into a loop to check all possible skills (spaming the whole space with "if" doesn't seem right... though I'll do it if I'll have no other option). Do I even have to make it a loop? Is there a better way to do this?

If someone decides to help me - Thank you!

Edited by nayakri
Link to comment
Share on other sites

All of the following could be put inside of an event or function. If necessary you can declare variables in the empty state and define them within an event or function as needed.

 

 

Actor PlayerRef = Game.GetPlayer()
Float Dav = PlayerRef.GetActorValue("Destruction")
Float Iav = PlayerRef.GetActorValue("Illusion")
Float Aav = PlayerRef.GetActorValue("Alteration")
Float Rav = PlayerRef.GetActorValue("Restoration")
Float Cav = PlayerRef.GetActorValue("Conjuration")
 
If (Dav > Iav) && (Dav > Aav) && (Dav > Rav) && (Dav > Cav)
  ;destruction highest
ElseIf (Iav > Dav) && (Iav > Aav) && (Iav > Rav) && (Iav > Cav)
  ;illusion highest
ElseIf (Aav > Dav) && (Aav > Iav) && (Aav > Rav) && (Aav > Rav)
  ;alteration highest
ElseIf (Rav > Dav) && (Rav > Iav) && (Rav > Aav) && (Rav > Cav)
  ;restoration highest
ElseIf (Cav > Dav) && (Cav > Iav) && (Cav > Aav) && (Cav > Rav)
  ;conjuration highest
Else
  ;there is no highest, could be a tie though
EndIf

 

 

There may be a better way, lets leave room for that possibility.

 

Link to comment
Share on other sites

In this particular case, with a short and known set of things to compare, and with specific things to do in each case, I believe Meradin's approach is probably the best.

 

For generic find-the-maximum value problems, I prefer iterate-through-array, with one variable storing the current maximum value and another storing the array index at which that value was found. You can then use either in further logic outside of the loop.

Link to comment
Share on other sites

I like IsharaMeradin's solution but I would make a few small changes.

  • Use base actor values so that any enchanted items don't affect the choice.
  • Check with >= to ensure that some skill is chosen even if there are multiples with the same value,
  • and since duplicates are allowed arrange the tests to put the "most important" first.

 

 

Armor Property IllusionReward Auto
Armor Property AlterationReward Auto
Armor Property RestorationReward Auto
Armor Property DestructionReward Auto
Armor Property ConjurationReward Auto

Actor PlayerRef = Game.GetPlayer()
Float Iav = PlayerRef.GetBaseActorValue("Illusion")
Float Aav = PlayerRef.GetBaseActorValue("Alteration")
Float Rav = PlayerRef.GetBaseActorValue("Restoration")
Float Cav = PlayerRef.GetBaseActorValue("Conjuration")
Float Dav = PlayerRef.GetBaseActorValue("Destruction")
 
If (Dav >= Iav) && (Dav >= Aav) && (Dav >= Rav) && (Dav >= Cav)
  ; nothing is higher than destruction so use it even if others are just as good
  PlayerRef.AddItem(DestructionReward, 1)
ElseIf (Cav >= Dav) && (Cav > Iav) && (Cav > Aav) && (Cav > Rav)
  ; nothing is higher than conjuration so use it instead of illusion, alteration, or restoration
  PlayerRef.AddItem(ConjurationReward, 1)
ElseIf (Iav >= Dav) && (Iav >= Aav) && (Iav >= Rav) && (Iav >= Cav)
  ; nothing is higher than illusion so use it even if alteration or restoration are just as good
  PlayerRef.AddItem(IllusionReward, 1)
ElseIf (Aav >= Dav) && (Aav >= Iav) && (Aav >= Rav) && (Aav >= Rav)
  ; nothing is higher than alteration so use it even if restoration is just as good
  PlayerRef.AddItem(AlterationReward, 1)
Else ; no need to check, restoration is the only one left
  ; nothing is higher than restoration (and nothing else is even equal since we got this far)
  PlayerRef.AddItem(RestorationReward, 1)
EndIf

 



And here's an array implementation of the same idea (although I haven't tried to compile it so there might be a syntax error or two).

 

string[] Property Skill Auto
{This should be filled in the CK with the five magic school skill names.
Put the most important skill first and the least important last.}

Armor[] Property Reward Auto
{This should be filled in the CK with the five reward items in the same order as the skills.}

Actor PlayerRef = Game.GetPlayer()
int best_value = -1
int best_skill = -1

int i = Skill.length
while i > 0
   int tmp = PlayerRef.GetBaseActorValue(Skill[i]) 
   if tmp >= best_value
      best_value = tmp
      best_index = i
   endif
endwhile  

PlayerRef.AddItem(Reward[i],1)

 


The array version could actually be used to reward any collection of skills not just the 5 schools of magic. And if you wanted the reward to be leveled as well as determined by the skill just create create leveled item lists for each skill and change the Reward declaration to "LeveledItem[] Property Reward Auto" instead of the Armor array.

Link to comment
Share on other sites

The one issue with the array loop is that -- unlike the explicit if-elseif block -- it doesn't break out ties and handles them strictly as first-encountered-wins. If you want to do something with that the code logic blows up dramatically :sad:

 

EDIT:

 

Also, you forgot to decrement your loop counter in the sample code @cdcooley :smile:

Edited by foamyesque
Link to comment
Share on other sites

I think getting a tie would be very rare since your skill are developing all the time, but I managed to solve it on my own.

 

I thank you all for help - I consider this problem solved. Now, I simply have to find out why the quest doesn't trigger in the game (I believe that's because of mods, another my mod isn't working as well)...

 

Well. On to taking my exam and then to clearing my game off every mod... This is going to be a long day.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...