allomerus Posted June 9, 2012 Share Posted June 9, 2012 (edited) Hello everybody! Beware, this is going to be long. I'm working on a rather large-scale mod that will introduce all my current and ulterior custom weapon models in a dungeon-like area, just to make people actually work for them. As I want every of these items to be acquired with a little sweat and a lot fo blood (mwaaahaha), I plan to make one of my daggers actually curse the player with an undispellable ability (as qualified in the CS), while also providing the player a way to « atone » for the very sin of picking it up by scrificing daedra hearts. When the atonement is finished (which implies the slaughter of hundreds of daedra), the blade grants the player the ability to devour daedra hearts for himselfm. increasing his magicka, health and fatigue by some small, to-be-determined amount. While the « cursing » mechanic works flawlessly, the part of the script which allows the player to slowly make the curse weaker (it has 10 stages) does not work. What I intended to do is that the player, when casting the « Sacrifice Daedra Heart » lesser power, increases a variable (HeartSacrifice) by 1. Another script is triggered when HeartSacrifice reaches a certain value, removing the greater version of the ability and adding a lesser one in its place. But the HeartSacrifice value does not seem to be functional. I cannot, for an example, use the « set Heartsacrifice to x » command, because the engine does seem to think it does not exist. So, basically, if someone around here is handy with scripts, I'd like you to have a look at this, and maybe tell me what I'm doing wrong. That's a week of off-work pain : ( People providing actual solutions will end up in my credits list, of course. FIRST SCRIPT - Object script, tied to the blade itself (AlloThalassianStiletto) As far as I know, this one works flawlessly. It's a curse-on-equip type of PITA blade-of-doom. Scn AlloThalassianStilettoScr ref Player Short ThalStilCurseCured Short ThalStilCurseStriken begin OnEquip If ThalStilCurseStriken == 1 Return Elseif ThalStilCurseStriken == 0 If ThalStilCurseCured == 1 Return ElseIf ThalStilCurseCured == 0 Player.AddSpellNS AlloThalStilCurse10 Set ThalStilCurseStriken to 1 endif endif end Where ThalStilCurseCured is checked at the very end on the « master » script when the 10th stage of the curse is removed. SECOND SCRIPT - Quest script, also the « Master script », the one that proceeds to the switching between stages of the curse, taunts the player in the name of another entity, and monitors the HeartSacrifice variable. Scn AlloThalStilCurseQuest Ref Player Short Curse10 Short Curse9 Short Curse8 Short Curse7 Short Curse6 Short Curse5 Short Curse4 Short Curse3 Short Curse2 Short Curse1 Short HeartSacrifice Short ThalStilCurseCured Begin gamemode If ( ThalStilCurseCured == 1 ) return Elseif Player.HasSpell AlloThalStilCurse10 == 0 Return Elseif ( Curse10 == 1 ) Return ElseIf Player.HasSpell AlloThalStilCurse10 Player.AddSpellNS AlloThalStilSacrifice Message "The Sun's fury is upon you!" Set HeartSacrifice to 0 Set Curse10 to 1 Endif ***Stuff stops working from this very point*** If ( Curse10 == 0 ) Return Elseif ( Curse10 == 1 ) If ( HeartSacrifice < 10) Return Elseif ( HeartSacrifice >= 10) Set Curse9 to 1 player.removespellNS AlloThalStilCurse10 Player.addspellNS AlloThalStilCurse9 Message "You are slowly sating the blade's thirst." Set Curse10 to 0 Endif Endif If ( Curse9 == 0 ) return Elseif ( Curse9 == 1 ) If ( HeartSacrifice < 25) Return Elseif ( HeartSacrifice >= 25) Set Curse8 to 1 Player.removespellNS AlloThalStilCurse9 Player.addspellNS AlloThalStilCurse8 Message "The Thalassian blade demands more souls!" Set Curse9 to 0 Endif Endif If ( Curse8 == 0 ) Return Elseif ( Curse8 == 1 ) If ( HeartSacrifice < 45) Return Elseif ( HeartSacrifice >= 45) Set Curse7 to 1 Player.removespellNS AlloThalStilCurse8 Player.addspellNS AlloThalStilCurse7 Message "Sacrifice again, or the Sun shall forever be your enemy!" Set Curse8 to 0 Endif Endif If ( Curse7 == 0 ) Return Elseif ( Curse7 == 1 ) If ( HeartSacrifice < 70) Return Elseif ( HeartSacrifice >= 70) Set Curse6 to 1 Player.removespellNS AlloThalStilCurse7 Player.addspellNS AlloThalStilCurse6 Message "Your time, your very life belongs to us." Set Curse7 to 0 Endif Endif If ( Curse6 == 0 ) Return Elseif ( Curse6 == 1 ) If ( HeartSacrifice < 100) Return Elseif ( HeartSacrifice >= 100) Set Curse5 to 1 Player.removespellNS AlloThalStilCurse6 Player.addspellNS AlloThalStilCurse5 Message "Fight to the death. It is your only hope." Set Curse6 to 0 Endif Endif If ( Curse5 == 0 ) Return Elseif ( Curse5 == 1 ) If ( HeartSacrifice < 135) Return Elseif ( HeartSacrifice >= 135) Set Curse4 to 1 Player.removespellNS AlloThalStilCurse5 Player.addspellNS AlloThalStilCurse4 Message "The Sun is a demanding master." Set Curse5 to 0 Endif Endif If ( Curse4 == 0 ) Return Elseif ( Curse4 == 1 ) If ( HeartSacrifice < 175) Return Elseif ( HeartSacrifice >= 175) Set Curse3 to 1 Player.removespellNS AlloThalStilCurse4 Player.addspellNS AlloThalStilCurse3 Message "Your sacrifices will be rewarded, in the end." Set Curse4 to 0 Endif Endif If ( Curse3 == 0 ) Return Elseif ( Curse3 == 1 ) If ( HeartSacrifice < 230) Return Elseif ( HeartSacrifice >= 230) Set Curse2 to 1 Player.removespellNS AlloThalStilCurse3 Player.addspellNS AlloThalStilCurse2 Message "You serve our vengeance well, mortal." Set Curse3 to 0 Endif Endif If ( Curse2 == 0 ) Return Elseif ( Curse2 == 1 ) If ( HeartSacrifice < 280) Return Elseif ( HeartSacrifice >= 280) Set Curse1 to 1 Player.removespellNS AlloThalStilCurse2 Player.addspellNS AlloThalStilCurse1 Message "You turned your doom into a crusade. Impressive." Set Curse2 to 0 Endif Endif If ( Curse1 == 0 ) Return Elseif ( Curse1 == 1 ) If ( HeartSacrifice < 335) Return Elseif ( HeartSacrifice >= 335) Player.RemovespellNS AlloThalStilCurse1 Player.RemoveSpellNS AlloThalStilSacrifice Player.addspellNS AlloThalStilDevour Message "You are free. May you devour our enemies' souls forever!" Set ThalStilCurseCured to 1 Set Curse1 to 0 Endif Endif End Where : AlloThalStilSacrifice is the script contained in the spell which sacrifices daedra hearts, AlloThalStilDevour the script the script tied to the reward spell that allows the player to devour hearts to boost his power,AlloThalStilCurse(x number) the curse « ability » itself. THIRD SCRIPT - Magic effect script, that is tied to the spell that sacrifices daedra hearts. Note that the part that removes the heart is perfectly functional. So it's not a matter of unmatched condition, it's really about recognizing the variable I believe. Scn AlloThalStilSacrificeScr Ref Item short HeartSacrifice begin ScriptEffectStart If Player.GetEquipped AlloThalassianStiletto == 0 message "You must be wielding the Thalassian Blade" return Else If Player.getequipped AlloThalassianStiletto Set Item to DaedraHeart If Player.getItemcount item == 0 return Else If Player.getItemcount item >= 1 Set HeartSacrifice to ( Heartsacrifice + 1 ) removeitemNS Item 1 Endif Endif Endif Endif end begin scripteffectfinish return end I really don't know what's wrong. Please, you're my only hope! Thanks a lot for your time - especially if you've just read all that text! Edited June 9, 2012 by allomerus Link to comment Share on other sites More sharing options...
cfh85 Posted June 9, 2012 Share Posted June 9, 2012 (edited) EDIT; this doesn't show any of the times i used tabs :( so I had to use " . " First script.Scn AlloThalassianStilettoScr Short DoOnce ; This ensures the curse is only added once Begin OnEquip If DoOnce == 1..... ReturnElse..... Player.AddSpellNS AlloThalStilCurse10..... Set DoOnce to 1..... SetStage cursedbladequest 10 ; create a quest to run the main script - this may not be needed. someone with more experience could tell youendif End No major change. it's just shorter and easier for you or others to read at a later date Next you need to create a Global. On TES CS on the top bar click Gameplay then Global. Call this HeartSacrifice. Set it as a float with a start of 0. This can be replaced with a quest if you prefer - which wont need to leave journal updates but can. Scn AlloThalStilCurseQuest ; attach this script to a quest called CursedBladeQuest or change ALL references to it in the scripts Float Curse ; make a global called HeartSacrifice Begin gamemode ..... If (Player.HasSpell AlloThalStilCurse10) && (GetStage cursedbladequest == 10) && (Curse == 0)......... Player.AddSpellNS AlloThalStilSacrifice......... Message "The Sun's fury is upon you!"......... Set HeartSacrifice to 0......... Set Curse to 1 ..... Elseif (Curse == 1) && ( HeartSacrifice >= 10)......... player.removespellNS AlloThalStilCurse10......... Player.addspellNS AlloThalStilCurse9......... Message "You are slowly sating the blade's thirst."......... Set Curse to 2..... Elseif ( Curse == 2 ) && ( HeartSacrifice >= 25)......... Player.removespellNS AlloThalStilCurse9......... Player.addspellNS AlloThalStilCurse8......... Message "The Thalassian blade demands more souls!"......... Set Curse to 3..... Elseif ( Curse == 3 ) && ( HeartSacrifice >= 45)......... Player.removespellNS AlloThalStilCurse8......... Player.addspellNS AlloThalStilCurse7......... Message "Sacrifice again, or the Sun shall forever be your enemy!"......... Set Curse to 4..... Elseif ( Curse == 4 ) && ( HeartSacrifice >= 70)......... Player.removespellNS AlloThalStilCurse7......... Player.addspellNS AlloThalStilCurse6......... Message "Your time, your very life belongs to us."......... Set Curse to 5..... Elseif ( Curse == 5 ) && ( HeartSacrifice >= 100)......... Player.removespellNS AlloThalStilCurse6......... Player.addspellNS AlloThalStilCurse5......... Message "Fight to the death. It is your only hope."......... Set Curse to 6..... Elseif ( Curse == 6 ) && ( HeartSacrifice >= 135)......... Player.removespellNS AlloThalStilCurse5......... Player.addspellNS AlloThalStilCurse4......... Message "The Sun is a demanding master."......... Set Curse to 7..... Elseif ( Curse == 7 ) && ( HeartSacrifice >= 175)......... Player.removespellNS AlloThalStilCurse4......... Player.addspellNS AlloThalStilCurse3......... Message "Your sacrifices will be rewarded, in the end."......... Set Curse to 8..... Elseif ( Curse == 8 ) && ( HeartSacrifice >= 230)......... Player.removespellNS AlloThalStilCurse3......... Player.addspellNS AlloThalStilCurse2......... Message "You serve our vengeance well, mortal."......... Set Curse to 9..... Elseif ( Curse == 9 ) && ( HeartSacrifice >= 280)......... Player.removespellNS AlloThalStilCurse2......... Player.addspellNS AlloThalStilCurse1......... Message "You turned your doom into a crusade. Impressive."......... Set Curse to 10..... Elseif ( Curse == 10 ) && ( HeartSacrifice >= 335)......... Player.RemovespellNS AlloThalStilCurse1......... Player.RemoveSpellNS AlloThalStilSacrifice......... Player.addspellNS AlloThalStilDevour......... Message "You are free. May you devour our enemies' souls forever!"......... Set Curse to 11......... SetStage CurseBladeQuest 20......... StopQuest CurseBladeQuest..... Endif End Scn AlloThalStilSacrificeScr Ref Item begin ScriptEffectStart ..... If Player.GetEquipped AlloThalassianStiletto == 0......... message "You must be wielding the Thalassian Blade"......... return..... ElseIf Player.getequipped AlloThalassianStiletto......... Set Item to DaedraHeart......... If Player.getItemcount item == 0......... return......... Else......... Set HeartSacrifice to ( Heartsacrifice + 1 )......... removeitemNS Item 1......... Endif..... EndifEnd Let me know if this works.A few notes.Use the TAB button!!!notice how I Structured it using the tab button? If's within ifs are set forward as are actions. then you return back for the endif. this allows you to see which ifs go with elseif, else & endif etc. Structure makes it so much easier for you, and more importantly others to read. I hope this works. BTW is there any difference in the spells??. Most importantly :unsure: how do you use the white boxes that you posted the scripts in? Edited June 9, 2012 by cfh85 Link to comment Share on other sites More sharing options...
Striker879 Posted June 9, 2012 Share Posted June 9, 2012 Precede your script code with a ['code'] (without the quote marks needed so it will show in this post) and end the script code block with a ['/code'] (again without the quote marks). Tabs will then work within the code tags. Link to comment Share on other sites More sharing options...
allomerus Posted June 9, 2012 Author Share Posted June 9, 2012 (edited) @ cfh85 Thanks for the info, I'll try to understand it without mucking it all up : ) One question thought: I was told that continuous « gamemode » scripts were supposed to contain as many « return » functions as possible, so that they clutter the engine's RAM as little as possible. What I know is that Oblivion's engine processes scripts entirely even thought an « if » condition is not met at the beginning, thus my tendency to fraction the 10 stages of the curse and add return blocks at the beginning of each of them. If what I know is right, your proposal will cause the computer to read all the script until the quest is complete, and (note that I play on an old dinosaur with « crapbucket » graphics settings) I am very concerned with any performance hits.Is there a way to make it lighter, or am I just rambling about stuff I don't know? Thanks again! Edited June 9, 2012 by allomerus Link to comment Share on other sites More sharing options...
cfh85 Posted June 10, 2012 Share Posted June 10, 2012 Float fQuestDelayTime Begin gamemode Set fQuestDelayTime to 1 ; a lot f scripts use values like 0.01 which will process the script 100 times a second - once a second is enough for what you want If Curse == 11 ;this will stop the script once you've finished (as should ending the quest I think return ElseIf (Player.HasSpell AlloThalStilCurse10) && (GetStage cursedbladequest == 10) && (Curse == 0) Player.AddSpellNS AlloThalStilSacrifice Message "The Sun's fury is upon you!" Set HeartSacrifice to 0 Set Curse to 1 Elseif (Curse == 1) && ( HeartSacrifice >= 10) player.removespellNS AlloThalStilCurse10 Player.addspellNS AlloThalStilCurse9 Message "You are slowly sating the blade's thirst." Set Curse to 2 Elseif ( Curse == 2 ) && ( HeartSacrifice >= 25) Player.removespellNS AlloThalStilCurse9 Player.addspellNS AlloThalStilCurse8 Message "The Thalassian blade demands more souls!" Set Curse to 3 Elseif ( Curse == 3 ) && ( HeartSacrifice >= 45) Player.removespellNS AlloThalStilCurse8 Player.addspellNS AlloThalStilCurse7 Message "Sacrifice again, or the Sun shall forever be your enemy!" Set Curse to 4 Elseif ( Curse == 4 ) && ( HeartSacrifice >= 70) Player.removespellNS AlloThalStilCurse7 Player.addspellNS AlloThalStilCurse6 Message "Your time, your very life belongs to us." Set Curse to 5 Elseif ( Curse == 5 ) && ( HeartSacrifice >= 100) Player.removespellNS AlloThalStilCurse6 Player.addspellNS AlloThalStilCurse5 Message "Fight to the death. It is your only hope." Set Curse to 6 Elseif ( Curse == 6 ) && ( HeartSacrifice >= 135) Player.removespellNS AlloThalStilCurse5 Player.addspellNS AlloThalStilCurse4 Message "The Sun is a demanding master." Set Curse to 7 Elseif ( Curse == 7 ) && ( HeartSacrifice >= 175) Player.removespellNS AlloThalStilCurse4 Player.addspellNS AlloThalStilCurse3 Message "Your sacrifices will be rewarded, in the end." Set Curse to 8 Elseif ( Curse == 8 ) && ( HeartSacrifice >= 230) Player.removespellNS AlloThalStilCurse3 Player.addspellNS AlloThalStilCurse2 Message "You serve our vengeance well, mortal." Set Curse to 9 Elseif ( Curse == 9 ) && ( HeartSacrifice >= 280) Player.removespellNS AlloThalStilCurse2 Player.addspellNS AlloThalStilCurse1 Message "You turned your doom into a crusade. Impressive." Set Curse to 10 Elseif ( Curse == 10 ) && ( HeartSacrifice >= 335) Player.RemovespellNS AlloThalStilCurse1 Player.RemoveSpellNS AlloThalStilSacrifice Player.addspellNS AlloThalStilDevour Message "You are free. May you devour our enemies' souls forever!" SetStage CurseBladeQuest 20 StopQuest CurseBladeQuest Set Curse to 11 Endif End I don't think there is any benefit to splitting the script up into so many sections of 'if' s, the game still has to try to read each one to determine if they are valid. they game isn't that different from people - if it's easy for you to understand and quick for you to read and find the relevant action it should be the same for the game.fQuestTimeDelay is used to ensure that scripts process fast enough for certain actions. Given the nature of what you're doing it can be used to slow it down. Will it hurt if the spell isn't changed for a second after the sacrifice? or 2 or 3 even? I'm extremely new to modding, so I may of made so stupid mistake. Hopefully someone else with more experience can confirm or correct it Link to comment Share on other sites More sharing options...
allomerus Posted June 10, 2012 Author Share Posted June 10, 2012 You're not making a huge mistake, it's just that - or at least it's what I was told - the If script will be read thoroughly, unless there is a return command somewhere inside it, in which case it will return to the beginning, So basically, 10 split « if » clusters using return commands will weigh less on the engine than a whole paragraph. On the other hand, of course, so many split clusters, each with their return commands, can complicate things... Anyway, I'm presently reading about the CS and globals and stuff, your help is really appreciated : ) Link to comment Share on other sites More sharing options...
WarRatsG Posted June 11, 2012 Share Posted June 11, 2012 The number of If blocks doesn't matter, so long as they are optimized and don't run too often. I think the problem with HeartSacrifice is that you have actually created two separate variables, both called "HeartSacrifice". Even though they have the same name, the engine recognises them as 2 different values, as they are in 2 separate scripts. To fix this, you must turn HeartSacrifice into one of 2 things: A) Cross-Script VariablesB) Global Variable A Cross Script Variable is just a variable from another script, generally a quest script. Here is an example of how it works: First, a quest script with the variable you want. The Quest is called "Quest" (this is important) Scn QuestSCRIPT Short RunObjectScript Begin GameMode If Player.GetEquipped AlloThalassianStiletto Set RunObjectScript to 1 endif End Second is an object script that runs automatically. Scn ObjectSCRIPT Short RunNow Begin GameMode Set RunNow to Quest.RunObjectScript ;You have the name of the quest, the "." and the name of the variable. The game now recognises this variable. If RunNow == 0 Return Else Player.UnequipItem AlloThalassianStiletto Set Quest.RunObjectScript to 0 endif End Alternatively, you can use a global variable. It is not tied to any script, and simply acts as a variable across all scripts (like timescale). To create a global variable, find "Gameplay" at the top of the screen and click on it, then click "Globals". From there you right click and hit "new".All scripts will now work as if you had declared that variable at the start of the script. It will have the same value across all scripts. Link to comment Share on other sites More sharing options...
allomerus Posted June 12, 2012 Author Share Posted June 12, 2012 Well, It works! Thanks a lot everyone, I'll make sure you recieve credit for your help! Link to comment Share on other sites More sharing options...
cfh85 Posted June 12, 2012 Share Posted June 12, 2012 what scripts did you finally use? If you don't mind I'd like to use them... I'm thinking a staff that can close any oblivion gate you enter. I figure if you've sacrificed enough daedra hearts you deserve it :D Link to comment Share on other sites More sharing options...
Recommended Posts