Starwhip Posted January 9, 2020 Share Posted January 9, 2020 I have a good amount of programming experience outside of Papyrus so I have a decent idea of what I want to do, just not how I want to do it: I'm looking to create a script/program/series of scripts that periodically increments a counter and causes the player to cast a spell upon reaching a threshold, resetting the counter to zero, and continuing. Certain basic items in player inventory will cause the counter to increment faster. What I have working so far: While it's not super pretty and I'm sure breaks a lot of modding convention, I set up a quest to start the script on a new game. It calls RegisterForSingleUpdate, and on the OnUpdate Event, It increments the counter and then calls for another update. What I haven't been able to get working: From what I can tell, I can't have this particular script check for items or cast spells because the script would have to extend ObjectReference for the former or something else I haven't researched for the latter. It currently extends Quest in order to run on game creation. Basically my code looks like this right now: ScriptName Blah extends Quest ObjectReference Property MountainFlower01Blue auto Event OnInit() RegisterForSingleUpdate(10) EndEvent Event OnUpdate() Debug.Notification(Game.GetPlayer().GetItemCount(MountainFlower01Blue)) RegisterForSingleUpdate(10) EndEvent If I can do this, what am I doing wrong? Any solutions/tips would be appreciated. Will I need several scripts managing these things somehow? Is this possible in Papyrus?Have I just missed something glaringly obvious since it's 2am? :mellow: Link to comment Share on other sites More sharing options...
PeterMartyr Posted January 9, 2020 Share Posted January 9, 2020 Multiple Inheritance? Most probable not :) It not Java Mate LOL It just simple coding language, each child can only extend one parent or super class. For what your trying to achieve I have never done it, but what I would do is check out how the game handles step and fetch this many items quests, the best plan to not reinvent the wheel but shameless copy bethesda. Cheers you made me smile. Think of Papyrus like some variant of Microsoft Code, since C# still isn't a true Object Oriented Language either. Link to comment Share on other sites More sharing options...
Starwhip Posted January 9, 2020 Author Share Posted January 9, 2020 (edited) Multiple Inheritance? Most probable not :smile: It not Java Mate LOL It just simple coding language, each child can only extend one parent or super class. For what your trying to achieve I have never done it, but what I would do is check out how the game handles step and fetch this many items quests, the best plan to not reinvent the wheel but shameless copy bethesda. Cheers you made me smile. Think of Papyrus like some variant of Microsoft Code, since C# still isn't a true Object Oriented Language either. Yeah, thinking it over I think I might be able to tie it to a quest or set of quests:Counter script updates, sets quest stage. That triggers another script to read player inventory and bump quest stage further based on the result. Final quest stage will fire a script to do the desired actions before setting the quest back to the starting stage, and since the counter will keep going it should be a continuous loop. EDIT: In this case, the counter script doesn't need to track anything itself, it will just act as the method of moving the whole "program" along Edited January 9, 2020 by Starwhip Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 9, 2020 Share Posted January 9, 2020 (edited) use a player alias inside the quest, with script as follow, should be adjusted to reach your aim starwPlayerAliasScript Scriptname starwPlayerAliasScript extends ReferenceAlias ; https://forums.nexusmods.com/index.php?/topic/8301768-multiple-inheritance-in-papyrus-possible-solutions/ ; scripts that periodically increments a counter and causes the player to cast a spell upon reaching a threshold ; resetting the counter to zero, and continuing. Spell PROPERTY mySpell auto ; the spell periodically to cast Keyword PROPERTY myKwd auto ; a keyword attached to a magiceffect of spell from above Flora Property MountainFlower01Blue auto Int PROPERTY iCounter auto Hidden ; [default=0] Int iVer ; -- FUNCTIONs -- 2 ;------------------ FUNCTION myF_Cast() ;------------------ objectReference playerRef = self.GetReference() IF playerRef.HasKeyword(myKwd) || (playerRef as Actor).IsInCombat() RETURN ; - STOP - spell is still working on player (if using a cloak spell) /or/ player is in combat ENDIF ;--------------------- iCounter = iCounter + 1 int i = playerRef.GetItemCount(MountainFlower01Blue as Form) IF (i > 10) iCounter = iCounter + 5 ENDIF IF (iCounter >= 50) mySpell.Cast(playerRef, playerRef) Debug.Notification("Spell casted..") iCounter = 0 ENDIF ENDFUNCTION ;------------------ FUNCTION myF_Init() ;------------------ iVer = 1 UnRegisterForUpdateGameTime() RegisterForSingleUpateGameTime(0.0) ENDFUNCTION ; -- EVENTs -- EVENT OnInit() ; new game or quest applies first time on saved game ; Received immediately after quest has finished initialization iVer = -1 Debug.Trace(" OnInit() - has been reached.. " +self) myF_Init() ENDEVENT EVENT OnPlayerLoadGame() ; every time saved game will be started ; Received immediately after the player has loaded a save game. A good time to check for additional content. Debug.Trace(" OnPlayeroadGame() - has been reached.. " +self) IF (iVer == -1) ELSE myF_Init() ENDIF ENDEVENT EVENT OnUpdateGameTime() Utility.Wait(5.0) ; wait for 5 sec, (Do not wait to long here !!!) quest q = self.GetOwningQuest() IF (q) && q.IsRunning() myF_Cast() RegisterForSingleUpdateGameTime(0.0) ENDIF ENDEVENT ; ******************************************************************************* ; *** other events, which could be useful to handle *** ; ******************************************************************************* EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) ; Event received when this object is hit by a source (weapon, spell, explosion) or projectile attack ENDEVENT EVENT OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect) ; Event received when a magic affect is being applied to this object ENDEVENT EVENT OnSpellCast(Form akSpell) ; Event received when a spell is cast by this object ENDEVENT EVENT OnCombatStateChanged(Actor akTarget, int aeCombatState) ; Event that is triggered when this actors combat state against the target changes ; State is as follows: ; 0 - not in combat ; 1 - in combat ; 2 - searching ENDEVENT EVENT OnPlayerBowShot(Weapon akWeapon, Ammo akAmmo, float afPower, bool abSunGazing) ; Received when the player fires a bow. akWeapon will be a bow, akAmmo is the ammo or None, ; afPower will be 1.0 for a full-power shot, less for a dud, and abSunGazing will be true if the player is looking at the sun. ENDEVENT Edited January 9, 2020 by ReDragon2013 Link to comment Share on other sites More sharing options...
Starwhip Posted January 9, 2020 Author Share Posted January 9, 2020 use a player alias inside the quest, with script as follow, should be adjusted to reach your aim Compiled this script to a new quest with the player alias, it runs the counter at least. The check for item count does not work, and I have the spell section commented out for the moment. I've tried making the initial declaration ObjectReference instead of Flora, and I've tried removing the cast to Form in GetItemCount(). Do I need to set something up outside of the script for the item checks and spell casting to work? Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 10, 2020 Share Posted January 10, 2020 The item check in ReDragon2013's script won't work because the property for the blue mountain flower is set as Flora. The player can not pick up the plant itself. The player gets the Ingredient object instead. I'm unsure of the exact ID name for the auto fill to work, but the property should be something like: Ingredient Property BlueMountainFlower Auto Then later when doing the item check, there is no need to cast to Form. Just pass in the ingredient variable: int i = PlayerRef.GetItemCount(BlueMountainFlower) Link to comment Share on other sites More sharing options...
Starwhip Posted January 10, 2020 Author Share Posted January 10, 2020 (edited) The item check in ReDragon2013's script won't work because the property for the blue mountain flower is set as Flora. The player can not pick up the plant itself. The player gets the Ingredient object instead. I'm unsure of the exact ID name for the auto fill to work, but the property should be something like: Ingredient Property BlueMountainFlower Auto Then later when doing the item check, there is no need to cast to Form. Just pass in the ingredient variable: int i = PlayerRef.GetItemCount(BlueMountainFlower)No dice. I think the issue isn't the properties or the GetItemCount function, just that the script cannot find the player properly.My ref alias for the player is currently set up like this, and is probably wrong. The script extends ReferenceAlias, calls objectReference playerRef = self.GetReference(), and then uses playerRef for future calls. I tested Game.GetPlayer() as a substitute but that does not work either. Edited January 10, 2020 by Starwhip Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 10, 2020 Share Posted January 10, 2020 Be sure to test on a new game rather than one that has had your mod active. This is to rule out data that may have been baked into the save file from interfering with your testing. Also, your image shows that you have not assigned any data to the properties. If you had there would be a little pencil at the bottom of the plus icon next to the script name. Highlight the script, click the properties button and assign the correct data to the properties. Otherwise, the property variables will be without a value and the script will not perform the way that you want. Link to comment Share on other sites More sharing options...
foamyesque Posted January 10, 2020 Share Posted January 10, 2020 Ishara's correct. It's a classic script toubleshooting thing that catches, in particular, people coming in from a programming background: Simply compiling the code up does not necessarily create a complete script. If a script needs to interact with a game object, you need to feed it the link between that game object and whatever variable you've coded in.There's three ways of doing that: You pull the information out of a function or event that can provide it, you attach the script to it directly or through an alias, or you fill properties. They aren't just a weird name for variables. In your particular case I would put the script on a player alias. ReferenceAliases like that will receive basically the same events as the Actor they're attached to, as well as certain ones tied to whatever the quest the alias belongs to. This will include an OnInit() event that will fire when the quest is first loaded (which will be a double-fire for a start-game-enabled quest, but that's only relevant if your OnInit() stuff pipes information to a script outside the quest). And no, you can only ever inherit from one line of inheritance at a time. One of the handiest references on the CK wiki is this one, which shows the inheritance tree: https://www.creationkit.com/index.php?title=Category:Script_Objects It's also possible your quest isn't starting or the player alias isn't being filled -- I have found using a forced reference to PlayerRef seems to behave better than the UniqueActor for making player aliases -- and to check that, you want the 'sqv QuestName' console command. It'll spit back the quest status and stage and the objectIDs of everything in aliases, among others. Also as Ishara said, when testing mods, and especially when making changes to mods, start new games. I've used 'coc whiterun' so many times to start a new one for a test that I can recite Adriane's conversation with Idolaf word for word. :p Link to comment Share on other sites More sharing options...
Starwhip Posted January 10, 2020 Author Share Posted January 10, 2020 Be sure to test on a new game rather than one that has had your mod active. This is to rule out data that may have been baked into the save file from interfering with your testing. Also, your image shows that you have not assigned any data to the properties. If you had there would be a little pencil at the bottom of the plus icon next to the script name. Highlight the script, click the properties button and assign the correct data to the properties. Otherwise, the property variables will be without a value and the script will not perform the way that you want. Ah, this has done it. Was missing this in the original script as well, it probably would have worked otherwise :P Solution for anyone coming across this thread via Google-fu: Make sure you go to where your script is attached in the Creation Kit, select it, press Properties, and fill your script-defined properties with objects from the Creation Kit. Link to comment Share on other sites More sharing options...
Recommended Posts