Can you store spells as a global variableobject?

Post » Tue Jun 19, 2012 7:30 pm

I am attempting to make a small PokeMod where the player gets one of three starter pokemon from a Prof. Hist in the Whiterun Jarl's Hall. Making the pokemon itself and its movelist has been educational and fun so far, but I have an issue when it comes to the player choosing which move his pokemon will forget in order to maintain the four move maximum. Here is how I have it structured in my head, if you know a better way to do it please tell me.

Basically what I need is four global variables labeled MoveSlot1, MoveSlot2, etc. each of which has stored the spell in that slot. Now,let's say the player reaches a new level (let's say 13) where Roselia (the pokemon) would learn a new move (Mega Drain) but already has four moves. What I am thinking is that there is a Story Manager event when the player levels, inducing a RoseliaLvlUp quest to start. This quest begins and then does a series of checks to see what level the player is through a series of if statements. When it reaches if Game.GetPlayer().getAV("Level")==13 it will cause the quest to go to stage 13. At stage 13 there is a ForceGreet dialogue option for Roselia (so she walks up to you after reaching this level) where Roselia says "Roselia is trying to learn a new move Mega Drain, but, Roselia already knows four moves! Would you like Roselia to forget a move in order to learn Mega Drain?" to which the player has five responses, the first four retrieve the name of the spells in each MoveSlot and display them and the last says "do not forget a move".
If the player chooses one of the four moves, I need the game to actually know which move is in which slot, remove the spell from that slot, remove it from Roselia, and then add Mega Drain to both the MoveSlot and to Roselia.

Unforunately, all of this is predicated on the idea that I can store the MoveSlots globally, which I have no idea how to do.

Any help is appreciated, sorry for the Wall of Text.
User avatar
Alkira rose Nankivell
 
Posts: 3417
Joined: Tue Feb 27, 2007 10:56 pm

Post » Wed Jun 20, 2012 8:21 am

Isn't it possible to create a dialogue that swaps out perks on an actor based on whether or not they have a certain other perk or if a certain dialogue option is chosen?

I know Perks are a great way to move abilities/powers and have them scale up or down, or even be removed. Perhaps maybe even using spells instead of perks since spells are easily 'swapped out' in papyrus.

Something like:

	If Player.GetEquippedSpell(0) == MySpell_1            Player.EquipSpell(MySpell_2, 0)                    EndIf

Sorry for not having a direct answer. Hope it helps.
User avatar
Hazel Sian ogden
 
Posts: 3425
Joined: Tue Jul 04, 2006 7:10 am

Post » Tue Jun 19, 2012 7:39 pm

What you can do is create a quest and set it as run on start, then add a script to it something like:
ScriptName  Extends QuestString Property MoveSlot1 AutoString Property MoveSlot2 AutoString Property MoveSlot3 AutoString Property MoveSlot4 Auto

And then in whatever script you need to access these globals create a property with the type as the first script
 Property globalVars Auto
Then right click the script and set the globalVars property to point to your global quest

Then you can go globalVars.MoveSlot1 and access that variable.
User avatar
Nicholas
 
Posts: 3454
Joined: Wed Jul 04, 2007 12:05 am

Post » Wed Jun 20, 2012 4:29 am

What you can do is create a quest and set it as run on start, then add a script to it something like:
 ScriptName  Extends Quest String Property MoveSlot1 Auto String Property MoveSlot2 Auto String Property MoveSlot3 Auto String Property MoveSlot4 Auto 
And then in whatever script you need to access these globals create a property with the type as the first script
  Property globalVars Auto 
Then right click the script and set the globalVars property to point to your global quest Then you can go globalVars.MoveSlot1 and access that variable.

I don't understand a word of that. At this point, I would like to scream profanities. But the filters...oh well.
User avatar
Steven Nicholson
 
Posts: 3468
Joined: Mon Jun 18, 2007 1:24 pm

Post » Wed Jun 20, 2012 12:53 am

Okay, here is how I'm interpreting what you're saying. In the scripts section of my Quest for roselia levelling up, I have a script which has spell properties MoveSlot1 MoveSlot2, etc.

Then, in dialogue I am trying to make this script work:
Scriptname PokeAddMove extends ObjectReference Quest Property Pokemon  Auto SPELL Property NewSpell  Auto Actor Property PokemonReference  Auto function ReplaceMove()   if Pokemon.MoveSlot1 != 0	  PokemonReference.removeSpell(MoveSlot1)	  Pokemon.MoveSlot1.SetValue(NewSpell)	  PokemonReference.addSpell(MoveSlot1)     else	  Pokemon.MoveSlot1.SetValue(NewSpell)	  PokemonReference.addSpell(MoveSlot1)     endIfendFunction

but I get these errors:
Starting 1 compile threads for 1 files...Compiling "PokeAddMove"...c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(11,14): MoveSlot1 is not a property on script quest or one of its parentsc:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(11,24): cannot compare a none to a int (cast missing or types unrelated)c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(12,35): variable MoveSlot1 is undefinedc:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(13,14): MoveSlot1 is not a property on script quest or one of its parentsc:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(13,24): none is not a known user-defined typec:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(14,32): variable MoveSlot1 is undefinedc:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(17,14): MoveSlot1 is not a property on script quest or one of its parentsc:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(17,24): none is not a known user-defined typec:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PokeAddMove.psc(18,32): variable MoveSlot1 is undefined

How am I misinterpreting what you said?
User avatar
Matthew Warren
 
Posts: 3463
Joined: Fri Oct 19, 2007 11:37 pm

Post » Wed Jun 20, 2012 8:21 am

You need to do a bit of casting in there. Have a read of this, hopefully it will help - http://www.cipscis.com/skyrim/tutorials/externalaccess.aspx

Cipscis
User avatar
Sierra Ritsuka
 
Posts: 3506
Joined: Mon Dec 11, 2006 7:56 am

Post » Wed Jun 20, 2012 1:12 am

You need to do a bit of casting in there. Have a read of this, hopefully it will help - http://www.cipscis.com/skyrim/tutorials/externalaccess.aspx

Cipscis

So, I didn't understand a lot of that, but what I got is that instead of saying Pokemon.MoveSlot1 (where pokemon is the quest) I should just import the script that is attached to my LevelUp quest that has all of the MoveSlot properties defined.
Is that right?

EDIT: Upon trying either adding the script wherein the properties of the moveslot are kept (QF_Roselia) as in import or as preceding .MoveSlot1 resulted in an error stating that I cannot do it because it is the same name as a known script. There is still something I'm not getting.
User avatar
Sabrina Schwarz
 
Posts: 3538
Joined: Fri Jul 14, 2006 10:02 am

Post » Wed Jun 20, 2012 2:01 am

Okay, upon re-reading that it seemed I needed to EXTEND the parent script, rather than importing it. Okay, so I did that, I made a new parent script with empty MoveSlot properties and a reference to the pokemon actor. Then I wrote this:

Scriptname PKMoveTrader extends PokeParentRoselia SPELL Property NewMove  Auto function ReplaceMove()   if MoveSlot1 as bool != 0		  PokemonReference.removeSpell(MoveSlot1)		  MoveSlot1 = NewMove		  PokemonReference.addSpell(MoveSlot1)    else		  MoveSlot1 = NewMove		  PokemonReference.addSpell(MoveSlot1)    endIfendFunction

It compiles just fine, but I'm concerned that it won't actually write MoveSlot1's new value to the parent script's properties, which I need it to do if I'm going to fetch that value the next time the pokemon learns a new move.
User avatar
Music Show
 
Posts: 3512
Joined: Sun Sep 09, 2007 10:53 am

Post » Wed Jun 20, 2012 5:01 am

Okay hm... Say I have this script, in a magic effect, I want it to be able to save some variable for use with another script, say the actor that cast the spell. To do this, I could go and create a new quest, I'm going to name it MyGlobalsQuest. I would then go to the scripts tab of the quest, and add a new script to it.

Here would be my quest script:
ScriptName MyGlobalsQuestScript Extends QuestActor Property SavedActor Auto
In my example I would leave this property as <> or set it to None


Here would be my magic effect script:
ScriptName MyMagicEffectScript Extends ActiveMagicEffect;I create a property with its type as the name of my quests script, and then I name this property globalVarsMyGlobalsQuestScript Property globalVars AutoEvent OnEffectStart(Actor akTarget, Actor akCaster)  ;I can now access the variable 'SavedActor' from my MyGlobalsQuestScript script  globalVars.SavedActor = akCasterEndEvent
After you write this script, you need to go and right click on it and set the property to your quest
User avatar
Luna Lovegood
 
Posts: 3325
Joined: Thu Sep 14, 2006 6:45 pm

Post » Tue Jun 19, 2012 8:28 pm

Okay hm... Say I have this script, in a magic effect, I want it to be able to save some variable for use with another script, say the actor that cast the spell. To do this, I could go and create a new quest, I'm going to name it MyGlobalsQuest. I would then go to the scripts tab of the quest, and add a new script to it. Here would be my quest script:
 ScriptName MyGlobalsQuestScript Extends Quest Actor Property SavedActor Auto 
In my example I would leave this property as <> or set it to None Here would be my magic effect script:
 ScriptName MyMagicEffectScript Extends ActiveMagicEffect ;I create a property with its type as the name of my quests script, and then I name this property globalVars MyGlobalsQuestScript Property globalVars Auto Event OnEffectStart(Actor akTarget, Actor akCaster) ;I can now access the variable 'SavedActor' from my MyGlobalsQuestScript script globalVars.SavedActor = akCaster EndEvent 
After you write this script, you need to go and right click on it and set the property to your quest

I don't see how that's different from what I tried earlier, and that didn't work.
Unless choosing globalVars as your property name is somehow syntactically important?
User avatar
Cccurly
 
Posts: 3381
Joined: Mon Apr 09, 2007 8:18 pm

Post » Tue Jun 19, 2012 10:07 pm

Ok so your Moves are actual spells. I'm guessing you use addspell or cast to make the pokeman able to use the moves. My approach would be a script attached to the Pokemon itself that already has ALL possible Moves/Spells available as properties, storing the selected set of four in a Spell Array. That script should provide a function to change a spell in the array (alonmgside calling removeSpell and Addspell of course), aswell as a function to get the current spells in the array.

Using a quest and dialog for the actual level up process is a second step then. What you do there is get the selected spells from the pokemon to be able to make according topics in the dialog available. When you selected a new spell and the array is filled already you then get prompted to select an existing move to be replaced. Upon making a choice the script fragment of that topic calls the function on the pokemon to change the spell.
User avatar
Maria Leon
 
Posts: 3413
Joined: Tue Aug 14, 2007 12:39 am

Post » Tue Jun 19, 2012 5:21 pm

Ok so your Moves are actual spells. I'm guessing you use addspell or cast to make the pokeman able to use the moves. My approach would be a script attached to the Pokemon itself that already has ALL possible Moves/Spells available as properties, storing the selected set of four in a Spell Array. That script should provide a function to change a spell in the array (alonmgside calling removeSpell and Addspell of course), aswell as a function to get the current spells in the array.

Using a quest and dialog for the actual level up process is a second step then. What you do there is get the selected spells from the pokemon to be able to make according topics in the dialog available. When you selected a new spell and the array is filled already you then get prompted to select an existing move to be replaced. Upon making a choice the script fragment of that topic calls the function on the pokemon to change the spell.

This seems like a sensible approach. I'll try it after class.
User avatar
Josh Lozier
 
Posts: 3490
Joined: Tue Nov 27, 2007 5:20 pm

Post » Tue Jun 19, 2012 8:35 pm

Ok rethought actually this script should be all that's needed to be attached to the Pokemon Actor:
Spoiler

ScriptName Pokemon Extends ActorSpell[] LearnedMoves = new Spell[4]Int NumberOfLearnedMoves = 0 ConditionalFunction LearnMove(Spell newMove, Spell oldMove = None) Global    int MoveCounter = 0    While (MoveCounter < 4)	    if ((LearnedMoves[MoveCounter] == oldMove))		    if(oldMove != None)			    self.RemoveSpell(oldMove)		    EndIf		    LearnedMoves[MoveCount] = newMove		    self.AddSpell(newMove)		    NumberOfLearnedMoves += 1		    MoveCounter = 4	    EndIf    EndWhileEndFunction

When setting up your quest dialog use the conditions to only make a topic available if the player doesn't have that spell already. Actually you'll need two topics per spell. One for the case that the number of learnedSpells is below 4 that in it's fragment calls the LearnMove funtion on the pokemon. The other one for the case that number of learned spells is 4 already and leads to the selection of a move to be replaced by the new one.

To command your pokemon you could use a spell/power in conjunction with a dialog quest similar to how Artisanix does it in his Director's Tools.
User avatar
Skrapp Stephens
 
Posts: 3350
Joined: Mon Aug 06, 2007 5:04 am

Post » Wed Jun 20, 2012 6:41 am

So i see how i could just add if statements (if Game.GetPlayer().GetLevel()==13 for example) to make it such that newMove is always the correct move. What I don't see is how I can pass in the correct move from dialogue to be oldMove.

EDIT: I guess I could name four topics 1. , 2. , etc. and then have a dialogue script that sets a true global variable to a value 0-3 depending on which slot they chose. The pokemon script then uses this global variable as a property called MoveSlotNum, and then LearnedMoves[MoveSlotNum] = newMove
User avatar
Charleigh Anderson
 
Posts: 3398
Joined: Fri Feb 02, 2007 5:17 am

Post » Wed Jun 20, 2012 5:51 am

I'll need to add the "Mighty Moron Power Rangers", whose only purpose in life is beating down anything with "Pokemon" in it's code...

Or create an NPC named "Muten Roshi" who casts a dual-handed spell combined with the shout "Kame - Hame - Hah!"
User avatar
Brooke Turner
 
Posts: 3319
Joined: Wed Nov 01, 2006 11:13 am

Post » Tue Jun 19, 2012 7:44 pm

Okay, so I did what I said and have all of the topics (corresponding to choosing a particular moveslot) do a PKMoveSlotNum.setValue with the appropriate value (0-3). On the pokemon I have this script:
Scriptname PKRoseLevel extends Actor GlobalVariable Property PKMoveSlotNum  Auto SPELL Property Absorb  Auto SPELL Property MegaDrain  Auto SPELL Property Growth  Auto SPELL Property StunSpore  Auto SPELL Property PoisonSting  Auto Spell[] LearnedMoves = new Spell[4]Spell oldMove = LearnedMoves[PKMoveSlotNum]Spell Function newMove()   if Game.GetPlayer().GetLevel() == 4	  return Growth   endIf   if Game.GetPlayer().GetLevel() == 7	  return PoisonSting   endIf   if Game.GetPlayer().GetLevel() == 10	  return StunSpore   endIf   if Game.GetPlayer().GetLevel() == 13	  return MegaDrain   endIfendFunctionFunction LearnMove() Global				    if(oldMove != None)						    self.RemoveSpell(oldMove)				    EndIf				    LearnedMoves[PKMoveSlotNum] = newMove()				    self.AddSpell(newMove())EndFunction

but I get errors on these lines
Spell[] LearnedMoves = new Spell[4]Spell oldMove = LearnedMoves[PKMoveSlotNum]

Here are the errors. I don't really know what they mean (I'm not a programmer)


c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(16,23): no viable alternative at input 'new'
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(16,32): required (...)+ loop did not match anything at input '['
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(16,8): Unknown user flag Spell
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(17,16): no viable alternative at input 'LearnedMoves'
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(17,28): required (...)+ loop did not match anything at input '['
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\PKRoseLevel.psc(17,6): Unknown user flag LearnedMoves
No output generated for PKRoseLevel, compilation failed.

Anyone know how to fix the script I have above?
User avatar
stevie trent
 
Posts: 3460
Joined: Thu Oct 11, 2007 3:33 pm

Post » Tue Jun 19, 2012 9:44 pm

I think you have to do the new command inside a function or event, like OnInit()
User avatar
Louise
 
Posts: 3407
Joined: Wed Nov 01, 2006 1:06 pm

Post » Tue Jun 19, 2012 6:54 pm

I think you have to do the new command inside a function or event, like OnInit()

Oh yes my bad. What he says is right. You cannot apply values to variable if they're declared outside of functions.
User avatar
Stephanie I
 
Posts: 3357
Joined: Thu Apr 05, 2007 3:28 pm

Post » Tue Jun 19, 2012 11:03 pm

Oh yes my bad. What he says is right. You cannot apply values to variable if they're declared outside of functions.

Actually you can with constants, like

int N = 100

But arrays are a special case...it has to use "new" to create an array object, which I don't think works the same way.
User avatar
des lynam
 
Posts: 3444
Joined: Thu Jul 19, 2007 4:07 pm

Post » Wed Jun 20, 2012 8:47 am

Okay, while I know how arrays work in concept, I can't figure out how to implement them in this godawful language, so I gave up on that. My script is now the following:

Scriptname PKRoseLevel extends Actor GlobalVariable Property PKMoveSlotNum  Auto SPELL Property Absorb  Auto SPELL Property MegaDrain  Auto SPELL Property Growth  Auto SPELL Property StunSpore  Auto SPELL Property PoisonSting  Auto SPELL Property LeechSeed  Auto SPELL Property MagicalLeaf  Auto SPELL Property GrassWhistle  Auto SPELL Property GigaDrain  Auto SPELL Property ToxicSpikes  Auto SPELL Property SweetScent  Auto SPELL Property Ingrain  Auto SPELL Property Toxic  Auto SPELL Property PetalDance  Auto SPELL Property Aromatherapy  Auto SPELL Property Synthesis  Auto SPELL Property MoveSlot1  Auto SPELL Property MoveSlot2 Auto SPELL Property MoveSlot3  Auto SPELL Property MoveSlot4  Auto ;Uses playerlevel to decide what move to learnSpell Function newMove()   if Game.GetPlayer().GetLevel() == 4	  return Growth   endIf   if Game.GetPlayer().GetLevel() == 7	  return PoisonSting   endIf   if Game.GetPlayer().GetLevel() == 10	  return StunSpore   endIf   if Game.GetPlayer().GetLevel() == 13	  return MegaDrain   endIf    if Game.GetPlayer().GetLevel() == 16	  return LeechSeed   endIf     if Game.GetPlayer().GetLevel() == 19	  return MagicalLeaf   endIf     if Game.GetPlayer().GetLevel() == 22	  return GrassWhistle   endIf     if Game.GetPlayer().GetLevel() == 25	  return GigaDrain   endIf    if Game.GetPlayer().GetLevel() == 28	  return ToxicSpikes   endIf     if Game.GetPlayer().GetLevel() == 31	  return SweetScent   endIf     if Game.GetPlayer().GetLevel() == 34	  return Ingrain   endIf     if Game.GetPlayer().GetLevel() == 37	  return Toxic   endIf    if Game.GetPlayer().GetLevel() == 40	  return PetalDance   endIf    if Game.GetPlayer().GetLevel() == 43	  return Aromatherapy   endIf    if Game.GetPlayer().GetLevel() == 46	  return MegaDrain   endIfendFunction;Uses the player decided moveslot to figure out what spell to replaceSpell Function oldMove()   if PKMoveSlotNum.GetValue() == 0	  return MoveSlot1   endIf   if PKMoveSlotNum.GetValue()  == 1	  return MoveSlot2   endIf   if PKMoveSlotNum.GetValue()  == 2	  return MoveSlot3   endIf   if PKMoveSlotNum.GetValue()  == 3	  return MoveSlot4   endIfendFunctionFunction LearnMove();This decides if there is a move in the slot, and then takes it off if they do.   if(oldMove() != None)	  self.RemoveSpell(oldMove())    EndIf;adds the newspell     self.AddSpell(newMove());these replace the correct spellslot with the new spell   if PKMoveSlotNum.GetValue()  == 0	 MoveSlot1 = newMove()   endIf   if PKMoveSlotNum.GetValue()  == 1	 MoveSlot2 = newMove()      endIf   if PKMoveSlotNum.GetValue()  == 2	  MoveSlot3 = newMove()	     endIf   if PKMoveSlotNum.GetValue()  == 3	  MoveSlot4 = newMove()   endIfEndFunction

What I need to know now is how can I run these functions from a dialogue choice.

By this I mean the following:
The player levels up to level, say, 13. This trips a SM Node on lvlup with conditions that it has to be one of the move learning levels. This triggers the RoseliaLevelUp quest to initiate. It sets itself to the actual move learning quest stage, in which there is a ForceGreet dialogue branch from the Pokemon. The pokemon talks to you, and eventually you choose a moveslot. This choice gets passed into a global variable PKMoveSlotNum, and then I need to run LearnMove on my pokemon. What I don't know how to do precisely is get from the dialogue option where I choose a moveslot to actually running the function. How can I do that?
User avatar
victoria johnstone
 
Posts: 3424
Joined: Sat Oct 14, 2006 9:56 am

Post » Wed Jun 20, 2012 8:19 am

So this ties into your other topic? OK, so your script is named PKRoseLevel. That means, in the papyrus fragment of your topic info, you have something like this:

PKRoseLevel property MyActor autoMyActor.OldMove()

Remember to set the property to the player, or whoever your script is attached to.
User avatar
Sammygirl
 
Posts: 3378
Joined: Fri Jun 16, 2006 6:15 pm

Post » Wed Jun 20, 2012 7:06 am

This is what I tried.

PKRoseLevel property RoseliaActor autoRoseliaActor.LearnMove()

This is what I got.


Starting 1 compile threads for 1 files...
Compiling "TIF__01000D8F"...
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\TIF__01000D8F.psc(18,0): no viable alternative at input 'PKRoseLevel'
c:\program files\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\TIF__01000D8F.psc(18,21): no viable alternative at input 'RoseliaActor'
No output generated for TIF__01000D8F, compilation failed.

Batch compile of 1 files finished. 0 succeeded, 1 failed.
Failed on TIF__01000D8F
User avatar
Solène We
 
Posts: 3470
Joined: Tue Mar 27, 2007 7:04 am

Post » Wed Jun 20, 2012 3:30 am

OK, instead of using a property, try this:

PKRoseLevel RoseliaActor = (akSpeaker as PKRoseLevel)RoseliaActor.LearnMove()

I'm assuming here that you're talking to the NPC with the PKRoseLevel script.
User avatar
Alberto Aguilera
 
Posts: 3472
Joined: Wed Aug 29, 2007 12:42 am


Return to V - Skyrim