Rizalgar Posted December 12, 2018 Share Posted December 12, 2018 (edited) Ok, I'm back with another problem! So I am trying to make "armor sets" i.e. when you wear two or more pieces of iron armor, it will add a "disease" spell that gives a buff. ( I used disease cuz making it as a spell just adds the spell to the player, which is useless since it doesn't make it a passive constant effect. ) Note that I am attaching this script to a ring, so that it is always running as long as I have it equipped. I initially tried scripting sets for each armor piece but oh god that would've been a mess and a half. I also don't think it would work but I could be wrong.I also tried using "RemoveSpellEffects" but it didn't work either. Ok, here's the script. /////|||||\\\\\ Begin SetRing Short State If ( State == 0 ) Set State to 1EndIf If ( State == 1 ) If ( HasItemEquipped, "adamantium_bracers_left" == 1 ) If ( HasItemEquipped, "adamantium_bracers_right" == 1 ) Set State to 10 Else Set State to 20 EndIf EndIfEndIf If ( State == 10 ) Player->AddSpell, "Ad2Set"EndIf ElseIf ( State == 20 ) Player->RemoveSpell, "Ad2Set"EndIf End SetRing /////|||||\\\\\ I have tried many variations to this. the closest I got was after doing the add, was to make an opposite HasItemEquipped that would remove the spell. But even then, it was buggy at best. I.e if you put the left bracer on then the right, but removed the left first, the spell would stay, but if you removed the right first it would remove the spell. Edit --- Maybe if at the State == 20 I used a GetSpellEffects call to check if the player has the effect before trying to remove it? I'ma give it a shot and see what happens. Edit 2 --- Nope. Adding the GetSpellEffects call above the spell removal after State == 20 just nullifies the effect altogether. Sigh Edited December 12, 2018 by Rizalgar Link to comment Share on other sites More sharing options...
cyran0 Posted December 12, 2018 Share Posted December 12, 2018 I understand your script has undergone several revisions, but there is no reason to expect your posted script to update the player's status after the initial check to add or remove the spell. Once the state has been set to 10 or 20 it remains so indefinitely... adding or removing the spell continuously. You should assign a different state to the script to prevent that from happening, and at some point it needs to be set back to either 0 or 1 so it will check again to see what armor the player is wearing. This is a local script assigned to a ring that the player wears. Since you want/need it to run continuously you might as well make it a global script unless you want the ring to be associated with the armor set buff. In either case, introducing a timer so the script runs it course only once a second or one every five seconds will reduce the burden of the script running all the time. I gather you intend to expand this script to include more than the two pieces of the same armor (and perhaps other types of armor as well). You might find it easier (and more flexible) to check as each armor piece is equipped and removed to update a local variable. Once those checks are complete (during one 'state') a new state checks the value of the variable and adds or removes the spell, and the state is reset to check again. I say more flexible because you could assign different values to the different pieces of armor, e.g. each gauntlet is worth 1, boots and each pauldron worth 2, helm and greaves worth 3 and cuirass worth 4. The strength of the buff could improve as the total increases. Of course, that can still be true if each piece of armor is 'worth' 1. Alternately, if you what certain combinations to have a special buff, you can assign a unique value to each (1, 2, 4, 8, 16, 32...) so the sum of any combination is unique and recognizable. Link to comment Share on other sites More sharing options...
Rizalgar Posted December 12, 2018 Author Share Posted December 12, 2018 Cyran you're my freakin hero. It seems so painfully obvious now. I'll type out a quick revision and see what I can get working Link to comment Share on other sites More sharing options...
Rizalgar Posted December 12, 2018 Author Share Posted December 12, 2018 Hmmm. Seems like no matter what I do it won't remove the spell. Here's the updated script. I'm going to get some sleep. Maybe I can figure it out with a fresh take on it and a clear head. I'm sure this script just looks dumb as hell. I'm telling you though I've tried so many different methods and I'm just tired lol. Begin _RizAllinOnSets Short State Short Timer Set Timer to ( Timer + GetSecondsPassed ) If Timer > 5 Set State to 1 EndIf If ( State == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_left" == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_right" == 1 ) Set State to 2 Else Set State to 3 EndIf EndIf EndIf If ( State == 2 ) Player->AddSpell "_RizAd2Set" Set State to 0 EndIf If ( State == 3 ) Player->RemoveSpellEffects, "_RizAd2Set" Set State to 0 EndIf Set Timer to 0 End _RizAllinOnSets Link to comment Share on other sites More sharing options...
cyran0 Posted December 12, 2018 Share Posted December 12, 2018 In your test are you removing the left bracer? If so, the second condition is not satisfied and the script does not process the third layer of this nested if-block where 'state' is set. Try removing just the right bracer to see if it works? Obviously, the solution is to add an 'else' path off of the second condition ( If ( Player->HasItemEquipped, "adamantium_bracer_left" == 1 ) ). I recall a discussion in the old forum about issues with removing diseases, but I am pretty certain it had to do with removing spell effects not RemoveSpell. You are not getting much value out of your timer. It should be set up like a menumode check with an immediate 'return' until the condition you want is satisfied. The script hops over the timer to check the value of state three times - all the way to the end. If fact, I don't understand how your script managed to add the spell (disease) in the first place since it sets the timer to 0 every frame. Try this: set timer to ( timer + GetSecondsPassed ) if ( timer < 5 ) return endif set timer to 0 There are other structural changes I might suggest for the script, but first let's see if we can get it working. Link to comment Share on other sites More sharing options...
Rizalgar Posted December 13, 2018 Author Share Posted December 13, 2018 (edited) Ah ok, I'll check that and see what happens. I'm new to timers, I've honestly never used one so wasn't sure how to properly set it up. I remember looking at it for about 5 seconds from MSFD but that's about it lol. I'll see what I can come up with Edit -- Removal of the right bracer with a slight tweak removes the spell, but not the left. I think my problem is still the timer. I tried add an "If ( Player->HasItemEquipped, "adamantium_bracer_left" == 0 ) after the nested blocks before Set State to 3 but nothing, won't remove at all with that method and I know why I don't know what made me think it would work. I did just think of something I think would be much simpler. I'ma give It a go and let ya know Edit -- Ok, with what all I've tried. No matter what I do, no matter what If statements I throw in for the left bracer removal, no matter what state I put it in, it will not remove the disease. I'm beginning to think it may just be a bug with OpenMW since it is still in early release. I can get the disease removed as long as I remove any other piece BEFORE I remove the left bracer. So I could just be dumb, and it could not be calling the left bracer properly, but I think I may let this one go for now. It just seems that you have to remove the gear in the ascending order in which you put it on. But that I think jsut furthers your point of how the blocks are nested and its reading them in that order. IDK. I'm still tired. Edited December 13, 2018 by Rizalgar Link to comment Share on other sites More sharing options...
cyran0 Posted December 13, 2018 Share Posted December 13, 2018 I tried add an "If ( Player->HasItemEquipped, "adamantium_bracer_left" == 0 ) after the nested blocks before Set State to 3 but nothing, won't remove at all with that method and I know why I don't know what made me think it would work. I did just think of something I think would be much simpler. I'ma give It a go and let ya know That was my fault - I misled you. I was trying to describe where the script needed to be modified not how it was to be modified. It is easier to show you what I mean rather than explain it, but I will try to do both: If ( State == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_left" == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_right" == 1 ) ; we only get this far if player has left bracer equipped Set State to 2 Else ; this is true only if the player has the left bracer but not the right bracer Set State to 3 EndIf Else ; if the player does not have the left bracer we still need to set state to 3 Set State to 3 EndIf EndIf It is easier to overlook that hole in the logic when the code is not indented. I meant to say last time that you might try introducing messageboxes at critical parts of your script. This provides real-time feedback as the script runs and lets you know where there is an error in the code. Link to comment Share on other sites More sharing options...
Rizalgar Posted December 13, 2018 Author Share Posted December 13, 2018 try introducing messageboxes at critical parts of your script. This provides real-time feedback as the script runs and lets you know where there is an error in the code. Ah yeah I thought about that but never implemented it. I'll give that code of yours a shot and see what happens. Will return Link to comment Share on other sites More sharing options...
Rizalgar Posted December 13, 2018 Author Share Posted December 13, 2018 (edited) If ( State == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_left" == 1 ) If ( Player->HasItemEquipped, "adamantium_bracer_right" == 1 ) ; we only get this far if player has left bracer equipped Set State to 2 Else ; this is true only if the player has the left bracer but not the right bracer Set State to 3 EndIf Else ; if the player does not have the left bracer we still need to set state to 3 Set State to 3 EndIf EndIf Works perfectly. I understand now, having seen it, I know exactly what you mean. You have to call the else to each if block and endif each one accordingly, if that makes any sense to you. Now then, when can we get married? Edit --- It almost works perfectly, with a full 8 set bonus I get every buff when equipped, but the removal is a different story. Now, depending on which pieces are removed, depends on which spells get removed, based on the block call. It's not really too much an issue, since with all 8 pieces removed I lose every buff. I just think the only way to truly rememedy that would be to make the individual 8 set block call multiple times in shuffled orders so that each and every time a piece is equipped or removed it will add or remove the appropriate spell. Talk about time consuming! Edited December 13, 2018 by Rizalgar Link to comment Share on other sites More sharing options...
cyran0 Posted December 13, 2018 Share Posted December 13, 2018 It is not just time-consuming to write it is also time-consuming to run. HasItemEquipped is probably not as resourse-hungry a command as GetItemCount, but it takes more time to process than a simple variable check. You want to avoid multiple checks of the same item in a given cycle. That can be done if you incorporate something I suggested earlier: update a variable after checking each piece of armor and assign the buff based on that value. You wrote 'buffs' - I assume that means the more pieces of armor the player has of a set the more buffs are applied. Here is a sketch of what I am describing: short armorCount if ( state == 1 ) set armorCount to 0 if ( ( player->HasItemEquipped "adamantium_bracer_left" ) >= 1 ) ; greater than or equal to is more reliable even if is should be impossible set armorCount to ( armorCount + 1 ) endif if ( ( player->HasItemEquipped "adamantium_bracer_right" ) >= 1 ) set armorCount to ( armorCount + 1 ) endif ; etcetera... set state to 2 endif if ( state == 2 ) if ( armorCount >= 2 ) player->AddSpell "RidAz2Set" endif if ( armorCount >= 3 ) player->AddSpell "RidAz3Set" endif ; etcetera... if ( armorCount <= 1 ) ; no sets, remove spells set state to 3 else set state to 0 endif endif if ( state == 3 ) player->RemoveSpell "RidAz2Set" player->RemoveSpell "RidAz3Set" ; etcetera... there is no danger from removing a spell that the player may not have set state to 0 endif If you are not stacking buff but rather assign a single stronger spell as the player accumulates pieces of the armor set the code might look like this: if ( state == 2 ) set state to 0 ; do this now - it will be updated if the player does not have an armor set if ( armorCount >= 8 ) player->AddSpell "RidAz8Set" elseif ( armorCount >= 7 ) player->AddSpell "RidAz7Set" ; etcetera... elseif ( armorCount >= 2 ) player->AddSpell "RidAz2Set" else ; no sets, remove spells set state to 3 ; see I told you ;) endif endif You could also use the binary (bit-packing) solution I mentioned if you want to assign buffs depending on specific combinations of armor. It can be very efficient. I once check the player's inventory for over 8000 possible combinations of equipment and tailored an NPC's dialogue to acknowledge the contents with 150 lines of code and 9 dialogue entries. Link to comment Share on other sites More sharing options...
Recommended Posts