Help with spell scripts...

Post » Tue Jun 19, 2012 6:17 pm

I have an aimed concentration spell the player can cast at things. This spell has a simple scripted effect attached to it, which basically checks to see if the target has already been hit, and adds an ability to them if not.

Spoiler
Scriptname phiTameBeastTriggerS extends ActiveMagicEffect

Spell Property phiTaming auto

Event OnEffectStart(Actor akTarget, Actor akCaster)
if akTarget.HasSpell(phiTaming) != 1
akTarget.AddSpell(phiTaming)
endif
EndEvent

This seems to compile fine. At least it gives no errors; the compile dialogue simply goes away with no notification whatsoever. Is this normal? How can I tell if something has actually compiled or not?

OK, so now the target has my phiTaming spell on them, which like I said is an Ability with another scripted spell effect. This is where I am having serious difficulty.

Spoiler
Scriptname phiTameBeastTimerS extends ActiveMagicEffect  MagicEffect Property phiTameBeastSet autoSpell Property phiTaming autoActor phiSpellTargetfloat timer1float timer2Event OnEffectStart(Actor akTarget, Actor akCaster) ; this should only run once when I add the spell	phiSpellTarget = akTarget	RegisterForUpdate(0.1)EndEventEvent OnUpdate()	timer1 += GetSecondsPassed ; this doesn't work at all	if phiSpellTarget.HasMagicEffect(phiTameBeastSet)		timer1=0		timer2 += GetSecondsPassed		if timer2 >= 10	   	 phiTameBeastTracker1.phiTameBeastRef1 = phiSpellTarget			phiTameBeastTracker1.phitargeted = 1			phiSpellTarget.RemoveSpell(phiTaming)		endif	else		if timer1 >= 3			phiSpellTarget.RemoveSpell(phiTaming)		endif	endifEndEvent

Basically as you can see, if you are at all familiar with Oblivion scripting and logic which I would sell my first born to have back over this Papyrus language (ahem), I am trying to track a couple timers and take appropriate actions.

The first timer1 is supposed to increment every update, unless the player is casting the original ability spell at this actor, in which case I reset it to 0. Basically this is so that if the actor goes for 3 seconds without being hit by my original concentration spell, I want this timer effect spell to be removed.

Next, timer2 is supposed to increment whenever the actor IS being hit with my original concentration spell, and if that count gets to 10, it sets a couple variables (phiTameBeastRef1 and phitargeted) in my placeholder quest phiTameBeastTracker1, then removes itself.

Like I said this seems logical according to Oblivion standards, but refuses to compile with the following:

Spoiler
Starting 1 compile threads for 1 files...
Starting 1 compile threads for 1 files...
Compiling "phiTameBeastTimerS"...
\Source\phiTameBeastTimerS.psc(19,11): variable GetSecondsPassed is undefined
\Source\phiTameBeastTimerS.psc(19,8): cannot add a float to a none (cast missing or types unrelated)
\Source\phiTameBeastTimerS.psc(22,12): variable GetSecondsPassed is undefined
\Source\phiTameBeastTimerS.psc(22,9): cannot add a float to a none (cast missing or types unrelated)
\Source\phiTameBeastTimerS.psc(24,3): variable phiTameBeastTracker1 is undefined
\Source\phiTameBeastTimerS.psc(24,24): none is not a known user-defined type
\Source\phiTameBeastTimerS.psc(24,23): type mismatch while assigning to a none (cast missing or types unrelated)
\Source\phiTameBeastTimerS.psc(25,3): variable phiTameBeastTracker1 is undefined
\Source\phiTameBeastTimerS.psc(25,24): none is not a known user-defined type
\Source\phiTameBeastTimerS.psc(25,23): type mismatch while assigning to a none (cast missing or types unrelated)
No output generated for phiTameBeastTimerS.psc, compilation failed.

Batch compile of 1 files finished. 0 succeeded, 1 failed.
Failed on phiTameBeastTimerS.psc

I am guessing this is because GetSecondsPassed is not valid in Papyrus, which frags the brains of the rest of the logic loops. However, I see no effective way to handle timers in Papyrus.

So, I guess that would be my question. How is one supposed to accomplish something like this timer function, which seems relatively simple and straightforward, in this new Rube-Goldbergian language format? =P
User avatar
aisha jamil
 
Posts: 3436
Joined: Sun Jul 02, 2006 11:54 am

Post » Tue Jun 19, 2012 8:27 pm

Use several STATEs with RegisterForUpdate(1) and (3), or Utility.Wait(), or use GetSecondsPassed as conditions for your ME in the Spell.

At least one of these should work !
User avatar
Emily Rose
 
Posts: 3482
Joined: Sat Feb 17, 2007 5:56 pm

Post » Tue Jun 19, 2012 5:48 am

You're making better progress than I am(I read all your threads..). I have yet made a working script by my hand, and I've made 6 of them..

Just saying as some kind of encouragement: You're getting there.
User avatar
Farrah Barry
 
Posts: 3523
Joined: Mon Dec 04, 2006 4:00 pm

Post » Tue Jun 19, 2012 11:53 am

@Terra Nova, thanks for the encouragement. It made me feel kinda happy! =)

@Seigneur Voland: Wait definitely won't work for what I'm trying to do. That just pauses the script. I need it to actually COUNT the time passing and increment a variable while it does so.

I was reading the wiki page on states, and it doesn't mention you can register different states for different update intervals. This might also cause problems even if that is possible (?) as you can only be in one state at a time. Good to know, though I can't think of any applications off the top of my head.

I managed to simplify the script by just using a 1sec registered update interval and incrementing my timers with =+ 1 instead of GetSecondsPassed since the later is obsolete. (I could probably do something like Register for a .2sec update and have my variables increment with =+ .2 for greater precision, but this is just to try and get it to compile!) I also changed them to int instead of float, however if I did want greater precision I'd have to switch these timers back to float since int is for whole numbers...

Spoiler
Scriptname phiTameBeastTimerS extends ActiveMagicEffect  MagicEffect Property phiTameBeastSet autoSpell Property phiTaming autoActor phiSpellTargetint timer1 = 0int timer2 = 0Event OnEffectStart(Actor akTarget, Actor akCaster)	phiSpellTarget = akTarget	RegisterForUpdate(1)EndEventEvent OnUpdate()	timer1 += 1	if phiSpellTarget.HasMagicEffect(phiTameBeastSet)		timer1 = 0		timer2 += 1		if timer2 >= 10			phiTameBeastTracker1.phiTameBeastRef1 = phiSpellTarget			phiTameBeastTracker1.phitargeted = 1			phiSpellTarget.RemoveSpell(phiTaming)		endif	else		if timer1 >= 3			phiSpellTarget.RemoveSpell(phiTaming)		endif	endifEndEvent

Anyway, now I am having a new problem which seems to be related to how I am trying to set an int and Actor variable in my quest script from this spell effect script (phiTameBeastTracker1 is the name of my quest with a script on it that basically just declares these two variables):

Spoiler
Starting 1 compile threads for 1 files...
Compiling "phiTameBeastTimerS"...
\Source\phiTameBeastTimerS.psc(20,3): variable phiTameBeastTracker1 is undefined
\Source\phiTameBeastTimerS.psc(20,24): none is not a known user-defined type
\Source\phiTameBeastTimerS.psc(20,23): type mismatch while assigning to a none (cast missing or types unrelated)
\Source\phiTameBeastTimerS.psc(21,3): variable phiTameBeastTracker1 is undefined
\Source\phiTameBeastTimerS.psc(21,24): none is not a known user-defined type
\Source\phiTameBeastTimerS.psc(21,23): type mismatch while assigning to a none (cast missing or types unrelated)
No output generated for phiTameBeastTimerS.psc, compilation failed.

Batch compile of 1 files finished. 0 succeeded, 1 failed.
Failed on phiTameBeastTimerS.psc

This indicates to me that indeed, the old Oblivion method of "set myquest.myquestvariable to something" does not work anymore. The problem is, I don't see how else to do what I am trying to do.

I NEED the quest to get passed these variables as it will be responsible for operating on this reference. The int is just to track whether I already have something tamed or not, but without being able to send the quest script the reference to the thing I just tamed, I won't be able to proceed to do stuff to it (like control its AI, etc.)

The reason I can't just handle this part through another ability spell is because I need to be able to get the base object, disable the current reference, and spawn a NEW version from that base. Also, if it dies I need to be able to respawn it, however without being able to track the base reference through a separate script, my reference is lost on death.

EDIT: I am thinking this is where I would need to use a quest alias, as then I could (hopefully) declare that as an actor property in this spell script, letting me use that name instead of phiTameBeastTracker1.phiTameBeastRef1, and that would shuffle the reference to the quest script. Still, I don't think there is an alias for an integer, so the problem of how to pass that variable remains. Also, I am very foggy on the proper use of alias...
User avatar
Trista Jim
 
Posts: 3308
Joined: Sat Aug 25, 2007 10:39 pm

Post » Tue Jun 19, 2012 11:38 am

Nothing from the Legacy Language(Oblivion) works in papyrus. You will continue to hit a dead end by trying to circumvent its use.

For 2 lines, 20 and 21, you need to cast them(this is a guess though) As the are not casted, they keep coming up as a none,

Example of casting would be:
Event OnHit(ObjectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)		  actor actorRef = akAggressor as Actor   	    if IceStrike            (akAggressor as Actor).DamageAV("health", 10)        endif             

You need to define what is phiTameBeastTracker 1 as this is a variable according to your script.

http://www.creationkit.com/Cast_Reference

Edit: I provided a better example of casting >>;;
User avatar
Melanie
 
Posts: 3448
Joined: Tue Dec 26, 2006 4:54 pm

Post » Tue Jun 19, 2012 5:14 am

I'm going to be honest, I've read all the available material and I still don't really understand the point of casting like this. In your example above, you do "actor actorRef = akAggressor as Actor" which just seems redundant to me, since it seems like it should be implied that akAgressor is an actor by the fact the OnHit event has already defined it as type ObjectReference. I guess it's one of those "just have to do it" syntax things, but presently I wouldn't be able to explain why. /shrug

Anyway, I am guessing the reason my script is complaining about setting a "none" is because I haven't "hooked in" my quest script. So, Papyrus thinks I'm trying to set a variable or something. I also had messed up and defined only the variables in that quest script. I went back and re-compiled that with the property functions included, which should make those variables public. The quest script now looks like this:

Spoiler
Scriptname phiTameBeastTracker1S extends QuestActorBase phiTameBeastBase1Actor phiTameBeastRef1int phitargeted = 0ActorBase property phiTameBeastBase1 autoActor property phiTameBeastRef1 autoint property phitargeted auto

I tried to do this:
(phiTameBeastTracker1.phiTameBeastRef1 as Actor) = phiSpellTarget
(phiTameBeastTracker1.phitargeted as int) = 1

However, now the compile complains saying:
\Source\phiTameBeastTimerS.psc(20,52): required (...)+ loop did not match anything at input '='
\Source\phiTameBeastTimerS.psc(21,45): required (...)+ loop did not match anything at input '='

So, it seems I am still not clear on how to set variables from other scripts using properties to make them "public."

User avatar
Mrs. Patton
 
Posts: 3418
Joined: Fri Jan 26, 2007 8:00 am

Post » Tue Jun 19, 2012 4:04 pm

Ok I suggest taking a step back. The new papyrus script is I assure you much better than the old oblivion script. However it is harder to use for someone with no experience of real object orientated programing. Its multithreaded nature also makes precise timing difficult. Do not try and simply plonk in old oblivion scripting logic. What overall should the spells be doing, try and give us the overview of why you want these timers. I understand why you find learning papyrus hard if you have had little exposure to real programing, but veloce me if you stick with it it is worth it.
User avatar
sophie
 
Posts: 3482
Joined: Fri Apr 20, 2007 7:31 pm

Post » Tue Jun 19, 2012 2:01 pm

I suppose "worth" is a subjective term. =P

Aside from my "Rube-Goldbergian" reference I thought I was doing a pretty good job in this thread avoiding making my TRUE feelings about all this public! Unless of course you're one of those guys that embraced the Borgian mind-reading human wireless technology, in which case ____ ____ ____ ____! XD

In any case, I am simple going by what is published on the wiki. I realize most "legacy" script functions are obsolete, however without examples I don't care what anyone says, it's like trying to translate without a Rosetta Stone. Or maybe a partial Rosetta Stone, like when Daniel Jackson told the team he'dbe able to translate the dial home address in Stargate only to find the bottom half of the cartouche broken off, leaving them stranded on an alien world...

Anyway, the timer part I thought I had explained and is not the problem anymore.

My question now is, how can I set a reference variable I have defined as a property in a quest script from a separate spell script? Before it was as simple as using "set myquest.myvariable to something" in my spell script. Obviously this won't work, but the Papyrus documentation gives ZERO clear examples how to accomplish such a basic and essential function.
User avatar
Lalla Vu
 
Posts: 3411
Joined: Wed Jul 19, 2006 9:40 am

Post » Tue Jun 19, 2012 7:36 pm

http://www.creationkit.com/Variables_and_Properties_%28Papyrus%29

scroll down til you see "Getting properties from a Quest script".

As for my example.. it's not redundant as it appears. It has to be written like that because the player is akaggressor. You have to cast it to actor, so that things you want to happen to someone attacking you is inflicted on THEM and not yourself. ala the spell damges THEM upon hitting YOU. Uncasted, the affects after the if statements will be applied to the player instead.
User avatar
Makenna Nomad
 
Posts: 3391
Joined: Tue Aug 29, 2006 10:05 pm

Post » Tue Jun 19, 2012 11:15 am

@Econundrum: I hope you recognize that my above response was meant to be in jest. I've been told I have an awkward sense of humor! I assure you no offense was intended (unless you are Borg, in which case you probably weren't offended!) I don't know TOO many Borg who post here, so chances are you were just being helpful. I do appreciate that. ;)

@Terra Nova: Aha! I missed that gem. I knew it was just a matter of properly "registering" my quest as a property so my spell knows what to do with it!

So, I declared "phiTameBeastTracker1S Property phiTameBeastTracker1 auto" up at the top of my spell effect script with my other variables, where 'phiTameBeastTracker1S' is the name of my quest's SCRIPT (not the quest itself, which is important and partly what threw me), and 'phiTameBeastTracker1' is whatever you want to use to refer to this placeholder questscript when you set questvariable.value later in the script. (I used the actual name of the quest which shouldn't matter since I'm not also declaring this variable a property in my local-only spell script, though it might be good practice to give references like this a unique name.)

The contents of the above quest script contain the following declaration of variables and their auto function (basic set/get) declaration as properties:

Spoiler
Scriptname phiTameBeastTracker1S extends Quest

ActorBase phiTameBeastBase1
Actor phiTameBeastRef1
int phitargeted = 0

ActorBase property phiTameBeastBase1 auto
Actor property phiTameBeastRef1 auto
int property phitargeted auto

Now I am able to set/get these variables from my spell script using the syntax "phiTameBeastTracker1.phiTameBeastRef1 = phiSpellTarget" "phiTameBeastTracker1.phitargeted = 1" etc.
User avatar
Josee Leach
 
Posts: 3371
Joined: Tue Dec 26, 2006 10:50 pm

Post » Tue Jun 19, 2012 8:48 am

Quite frankly I only have a mild understanding of what you're doing and what you're trying to do, but it seems like your scripts resemble mine in some ways.

Have you solved your issue? Or are you still unable to do something properly? If you're still having some issues I may be able to help, but in that case, it'd be helpful if you could re-state exactly what it is you're trying to do, and post all of the scripts that you are using. If you have indeed already solved your problem, feel free to ignore this.
User avatar
Kirsty Wood
 
Posts: 3461
Joined: Tue Aug 15, 2006 10:41 am


Return to V - Skyrim