Jump to content

Multi Equip/Unequip spell adding/removal


Rizalgar

Recommended Posts

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 1

EndIf

 

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

EndIf

EndIf

 

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 by Rizalgar
Link to comment
Share on other sites

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

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

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

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 by Rizalgar
Link to comment
Share on other sites

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

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

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 by Rizalgar
Link to comment
Share on other sites

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...