Gardden Posted November 17, 2019 Share Posted November 17, 2019 Hello! I'm trying to create a spell that works like the Quen sign from The Witcher game series. The spell will work like a stoneflesh spell, boosting the player's damage resistance, and also reflects some of the damage back to the attacker.For now it lasts for 30 seconds, but I wanted to make it also dispell once the player is hit a certain number of times (like 3, for example). I have zero knowledge in scripting, can someone help me make this work? Thanks! Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 17, 2019 Share Posted November 17, 2019 Make a quest that you will start when your spell is cast. So you may need to make another magic effect for your spell to hold a small script which tells the quest to start. Not tested for function or compilation Scriptname SomeMagicEffectScript Extends ActiveMagiceEffect Quest Property myQuest Auto Event OnEffectStart(Actor akTarget, Actor akCaster) If !myQuest.IsRunning() ;is quest not running myQuest.Start() ;start quest EndIf EndEvent On the quest, create an alias that points to the player. Attach a script to this player alias which will use the OnHit event to track how many times the player gets hit. When the correct number is reached, dispel the spell and stop the quest. Not tested for function or compilation Scriptname SomeAliasScript Extends ReferenceAlias Quest Property myQuest Auto Spell Property mySpell Auto Int Property numHitsRequired = 3 Auto Int numHitsCurrent = 0 Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) numHitsCurrent += 1 If numHitsCurrent == numHitsRequired (Self.GetReference() as Actor).DispelSpell(mySpell) myQuest.Stop() EndIf EndEvent ;note - no need to reset the numHitsCurrent variable as it will be reset each time the quest is started. But, keep in mind that the OnHit event can register multiple hits from the same source. This is especially true of weapons with enchantments. Each enchantment effect will count as a hit. Also, lets leave some wiggle room for others who may know of different or better ways to do what you are asking. :D Link to comment Share on other sites More sharing options...
ReDragon2013 Posted November 17, 2019 Share Posted November 17, 2019 (edited) As IsharaMeradin has written, there is another way to reach your aim. Your spell is using different magicEffects.. one of these effects should be a scripted effect, which has a special keyword attachednext script may help to explain the structure, I am not sure about caster or target.. try out! gardPlayerStoneEffectScript Scriptname gardPlayerStoneEffectScript extends ActiveMagicEffect ; https://forums.nexusmods.com/index.php?/topic/8152913-help-with-creating-a-script-for-a-spell/ ; spell should be casted as cloak effect with duration limit of 30 sec Spell PROPERTY mySpell auto ; the spell that was casted with this magic effect Keyword PROPERTY myKeywo auto ; a unique keyword which should be attached to this effect Int PROPERTY iMaxHits = 3 auto ; [default=3] Int PROPERTY iHitCounter auto Hidden ; [default=0] ; -- EVENTs -- 3 + "Waiting" EVENT OnEffectStart(Actor akTarget, Actor akCaster) IF (akTarget == akCaster) && (akTarget == Game.GetPlayer()) ELSE akTarget.DispelSpell( mySpell ) RETURN ; - STOP - not the player, remove this spell immediately ENDIF ;--------------------- IF akTarget.HasEffectKeyword(myKeywo) RETURN ; - STOP - effect is already running ENDIF ;--------------------- gotoState("Waiting") ; ### STATE ### Debug.Trace(" Effect started.. " +self) ; for debugging only ENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) Debug.Trace(" Effect has been finished.. " +self) ; for debugging only ENDEVENT EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ; received when this "object" is hit by a source (weapon, spell, explosion) or projectile attack IF ( b4 ) RETURN ; - STOP - hit blocked ENDIF ;--------------------- IF (akSource as Weapon) gotoState("Waiting") ; ### STATE ### myF_Action() Utility.Wait(0.25) gotoState("") ; ### STATE ### RETURN ; - STOP - take the weapon effect only, not the enchantment hit ENDIF ;--------------------- myF_Action() ENDEVENT ;=========================== state Waiting ; look at papyrus source script "ActiveMagicEffect.psc" ;============ EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) ENDEVENT ;======= endState ; -- FUNCTION -- ; https://www.creationkit.com/index.php?title=ActiveMagicEffect_Script ;-------------------- FUNCTION myF_Action() ;-------------------- iHitCounter+= 1 ; counter +1 IF (iHitCounter >= iMaxHits) GetTargetActor().DispelSpell( mySpell ) ; GetCasterActor() ENDIF ENDFUNCTION I think each way is good there is no way better. Edited November 17, 2019 by ReDragon2013 Link to comment Share on other sites More sharing options...
Gardden Posted November 17, 2019 Author Share Posted November 17, 2019 Thank you both for answering my topi, it's much appreciated! :D Unfortunately, I could not get it to work :(I'm sure it's a problem on my end. Here's what I did: Option 1 (IsharaMeradin) Created a new Magic Effect (W_SignQuenEffect_1Script) Archetype: ScriptCasting Type: Fire and ForgetDelivery: Self Added your script to Papyrus Script: Scriptname W_QuenSign01EffectScript extends activemagiceffect {Script for Sign Quen Quest} Quest Property W_QuenSign01Quest Auto Event OnEffectStart(Actor akTarget, Actor akCaster) If !W_QuenSign01Quest.IsRunning() ;is quest not running W_QuenSign01Quest.Start() ;start quest EndIfEndEvent Created a new quest (W_QuenSign01Quest) Have "start game enabled" selectedOn Aliases, have an Alias named "player" with specific reference set to "PlayerRef" Added you script to Alias Papyrus Scripts: Scriptname W_QuenSign01Script extends ReferenceAlias {Stops Quen Sign Effects after player is hit a certain amount of times.} Quest Property W_QuenSign01Quest AutoSpell Property W_SignQuen01 AutoInt Property numHitsRequired = 3 AutoInt numHitsCurrent = 0 Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) numHitsCurrent += 1 If numHitsCurrent == numHitsRequired (Self.GetReference() as Actor).DispelSpell(W_SignQuen01) W_QuenSign01Quest.Stop() EndIfEndEvent Added the magic effect to the Spell (W_SignQuen01) Option 2 (ReDragon2013) Created a new Magic Effect (W_SignQuenEffect_1Script) Archetype: CloakCasting Type: Concentration (required for cloak)Delivery: Aimed (required for cloak) Added you script to it's Parpyrus Scripts: Scriptname W__QuenSignEffectScript01 extends activemagiceffect {Quen Sign OnHit script} Spell PROPERTY W_SignQuen01 autoKeyword PROPERTY W_QuenSignKeyword auto Int PROPERTY iMaxHits = 3 auto ; [default=3] Int PROPERTY iHitCounter auto Hidden ; [default=0] ; -- EVENTs -- 3 + "Waiting" EVENT OnEffectStart(Actor akTarget, Actor akCaster)IF (akTarget == akCaster) && (akTarget == Game.GetPlayer())ELSE akTarget.DispelSpell(W_SignQuen01) RETURN ; - STOP - not the player, remove this spell immediatelyENDIF;---------------------IF akTarget.HasEffectKeyword(W_QuenSignKeyword) RETURN ; - STOP - effect is already runningENDIF;--------------------- gotoState("Waiting") ; ### STATE ### Debug.Trace(" Effect started.. " +self) ; for debugging onlyENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) Debug.Trace(" Effect has been finished.. " +self) ; for debugging onlyENDEVENT EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4); received when this "object" is hit by a source (weapon, spell, explosion) or projectile attackIF ( b4 ) RETURN ; - STOP - hit blockedENDIF;---------------------IF (akSource as Weapon) gotoState("Waiting") ; ### STATE ### myF_Action() Utility.Wait(0.25) gotoState("") ; ### STATE ### RETURN ; - STOP - take the weapon effect only, not the enchantment hitENDIF;--------------------- myF_Action()ENDEVENT ;===========================state Waiting ; look at papyrus source script "ActiveMagicEffect.psc";============EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)ENDEVENT;=======endState ; -- FUNCTION --; https://www.creationkit.com/index.php?title=ActiveMagicEffect_Script ;--------------------FUNCTION myF_Action();-------------------- iHitCounter += 1 ; counter +1 IF (iHitCounter >= iMaxHits) GetTargetActor().DispelSpell(W_SignQuen01) ; GetCasterActor() ENDIFENDFUNCTION When I tried to cast the spell, i got a CTD. But it's not because of the script, I tested it without the scrip. This Quen Spell is marked as a Lesser Power, because the player will get it from a Perk (a spell flagged as "spell" won't show up in the menu after you get the perk). Maybe a lesser power can't cast a concentration/aimed spell?Before it as flagged as "fire and forget" and "self" Hope it didn't get confusing, haha Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 18, 2019 Share Posted November 18, 2019 On my option, you do not check the "start game enabled" box. The magic effect you created to hold the one script is to be added to your spell (lesser power). Thus it will run when the spell is cast. One thing that you did not mention with either option is filling in the properties. Without filling in the properties, the script(s) cannot be expected to behave properly. Link to comment Share on other sites More sharing options...
Gardden Posted November 18, 2019 Author Share Posted November 18, 2019 Ha! You were right, I didn't fill the properties (I didn't even kown that I was supposed to do that, lol) It's now working flawlessly :DI also removed the "start game enabled" option as you said. Thanks you so much! I've been trying the whole day to make it work, lol I also filled the properties for ReDragon2013, but instead of make it a cloak spell, I left it with "fire and forget" "self" to avoid the CTD. It also works fine as far as I can tell from the tests I've done. :D Link to comment Share on other sites More sharing options...
TruePooshmeu Posted November 19, 2019 Share Posted November 19, 2019 What's the benefit of creating a quest for a script attached to a spell? Why not creating a spell, an attach a script to the magic effect and using an event like "OnEffectStart" or "OnAnimationEvent" Now that I've read basically everything there is to be read about scripting, I'm about to create a thread with several intermediate to advanced question and this one if one of them. I see that mods like this are always made with quests, like combat mods and stamina mods, but.... why making a quest that is always active instead of creating a script attached to an object? why making something that will always be active and will consume more resources than making scripts based on events? for mods that affect only the player stamina for example, why not attaching the script to the player reference? why the player actor has no scripts at all? Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 19, 2019 Share Posted November 19, 2019 What's the benefit of creating a quest for a script attached to a spell? Why not creating a spell, an attach a script to the magic effect and using an event like "OnEffectStart" or "OnAnimationEvent" Now that I've read basically everything there is to be read about scripting, I'm about to create a thread with several intermediate to advanced question and this one if one of them. I see that mods like this are always made with quests, like combat mods and stamina mods, but.... why making a quest that is always active instead of creating a script attached to an object? why making something that will always be active and will consume more resources than making scripts based on events? for mods that affect only the player stamina for example, why not attaching the script to the player reference? why the player actor has no scripts at all? Depends upon what one is doing to be honest. Perhaps there is data being used within the script that needs to be maintained across spell casts. This cannot be done solely within the magic effect script. Every spell cast is a new instance of the magic effect and the script has no clue about data on the previous instances. A quest allows one to retain and maintain information across multiple spell casts. A spell with a magic effect having a script using OnEffectStart or OnAnimationEvent is totally fine. It depends upon the mod author's vision for their mod as to what they may need to use. Waiting to see your thread... Would prefer to reply to your questions there rather than hijacking someone else's thread. Objects get unloaded as the player leaves the area and there are a lot of script functions that will not run when the 3D is not loaded. Some stuff can be put on an object, but often times doing so makes the object persistent. Which again takes up resources. Better to put things on a quest that can be stopped and thus less likely to cause issues when the mod is removed (even tho it shouldn't be removed mid-game but people will be people). The player should never have a script attached directly. If every mod that needed a script on the player were to attach directly, only the last such mod loaded would be able to work properly. Link to comment Share on other sites More sharing options...
TruePooshmeu Posted November 20, 2019 Share Posted November 20, 2019 (edited) Sorry but since his problem was solved... Much thanks for your good willing to help me and a bunch of other new modders around here. "The player should never have a script attached directly. If every mod that needed a script on the player were to attach directly, only the last such mod loaded would be able to work properly" Why? And does other base objects works like this?, an activator for example, if I attach more than one script to the activator, only the last one will work properly? (Can't see why I would make more than one script instead of using states or different events though, but then the vanilla may already have some scripts attached to the object I'm trying to attach a script). Edit: there's one thing I'm 99% sure but better safe than sorry. About base objects, references and object references. Let's see if I got it right... And my questions will depend on this answer... A base object is whatever there is in the object windows, a reference is ONLY a base object that is placed in a specific location of world and has a X, Y, Z coordinate. So let's say I create a book, and place it in 2 dungeons, one book in each dungeon, my book is a base object, and has 2 references. A script(that extends book) attached to my book will work in both books, but if I want a script to only affect one of the books I must extend ObjectReference script and attach this script to the book? Is that right? Edited November 20, 2019 by TruePooshmeu Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 20, 2019 Share Posted November 20, 2019 Create two plugins. Edit the same record on each plugin but edit something different. Load both side by side in SSEEdit. You will see that the last one loaded gets to have its data while the other one is unable to. This is why there are a plethora of patch plugins to make two or more mods work together. If you are making a mod and want to have two or more scripts on a single object, you can do so. But if a second mod applies a script to the same object, only the last loaded mod gets to have its script attached. Another reason for using quests, assign the object to an alias, put the script on the alias and now no need to worry about another mod editing the same object and effectively removing the script. You are correct about the books example. Link to comment Share on other sites More sharing options...
Recommended Posts