Jump to content

DOWNLOAD MODS

Are you looking for something shiny for your load order? We have many exclusive mods and resources you won't find anywhere else. Start your search now...

LEARN MODDING

Ready to try your hand at making your own mod creations? Visit the Enclave, the original ES/FO modding school, and learn the tricks of the trade from veteran modders...

JOIN THE ALLIANCE

Membership is free and registering unlocks image galleries, project hosting, live chat, unlimited downloads, & more...

General Script Questions #2


WillieSea
 Share

Recommended Posts

I'm trying to get a switch to open three normal doors (specifically, the iron doors found in Ayleid ruins) when pressed, but it doesn't want to work. I tried setting up a daisy-chain like this:

1. Switch opens Door A

2. Door A opens Door B

3. Door B opens Door C

The result was that only Door A opened. I then tried scripting the switch specifically to open the three doors, but now none of them open. The script I'm using is:


scn ARSwitch01GB3DoorScript

short busy

ref target

ref mySelf

begin onactivate


if busy == 0

set target to getParentRef

set mySelf to getSelf

target.activate mySelf 1

playgroup forward 0

set busy to 1

GB02DoorA.Activate

GB02DoorB.Activate

GB02DoorC.Activate

endif

end

begin gameMode

if isAnimPlaying == 0 && busy == 1

set busy to 0

endif

end

^That's a modified version of the ARSwitch01SCRIPT from vanilla Oblivion. What do I need to change to get this working?

Link to comment
Share on other sites

Okay, I have a new problem that really doesn't make sense to me. I've placed an activator that is supposed to make an XMarker cast a spell on the Player. I've used XMarkers for that before, so I know that's possible. The script I'm using is:


scn GBWelkyndBalaMagickaScript

Ref Caster

Begin onactivate Player

Set Caster to GetParentRef ; the XMarker has been set as the parent in the Enable Parent tab of ref edit dialogue

If Player.IsSpellTarget GBWelkyndBalaMagicka == 0

	 Caster.Cast GBWelkyndBalaMagicka Player

Messagebox "This block is running." ; debug message to make sure this part is working

Else

	 MessageBox "You have already been granted the power of this stone."

Endif

End

When I activate the object, I get the "This block is running" message, but the spell never gets cast. I initially scripted it so the object itself would cast the spell, but nothing happened then either. Any ideas on why this isn't working?

Link to comment
Share on other sites

  • 2 weeks later...

My scripting skills have been maxed. I am trying to iterate through an array, and determine when an NPC is talking. I've managed to do that. I can determine when an NPC is talking, but the problem I am having is that I also want to determine when all the NPC's have stopped talking. I can't figure that out. Here's a snippet from the script where I'm stuck:


Let HighAINPC := ar_Construct Array

Let HighAINPC := GetHighActors

ForEach ActorRef <- HighAINPC

  Let CurrentActor := ActorRef["value"]

  Let TalkingActor := CurrentActor.GetCurrentAIPackage == 6

  If TalkingActor

		 Set NPCIsTalking to 1

  Endif

Loop

As you can see, I can determine when an NPC is talking, but I can't figure out how to determine when those NPC's found by "GetHighActors" have stopped talking. All I want to do is set "NPCIsTalking" to 0 when there are no more NPC's talking that have been found by "GetHighActors". Any help would be greatly appreciated. The only thing I can guess at for a solution would be to create an array that tracks all the NPC's found by "GetHighActors", and then set a flag if they have stopped talking. That said, I can't figure out how to do that either. And there could be a simpler way. I don't know.

Thanks for any help.

Link to comment
Share on other sites

Thanks, WillieSea. But that won't work. I did think about that. Let me explain the script:


Let HighAINPC := ar_Construct Array ---> Initializes an array

Let HighAINPC := GetHighActors ---> Sets the array to the function, which returns an array, in which a reference is set as an element for every NPC in the current cell and adjacent surrounding cells.

ForEach ActorRef <- HighAINPC ---> Starts a loop that walks through every single element in the array set by "GetHighActors"

Let CurrentActor := ActorRef["value"] ---> special function that sets "CurrentActor" to the first ref returned by "GetHighActors"

Let TalkingActor := CurrentActor.GetCurrentAIPackage == 6 ---> Sets TalkingActor to the first actor that is talking

If TalkingActor

				 Set NPCIsTalking to 1

Endif

Loop

So, if I were to use the "else" condition, if the very first actor returned by "gethighactors" was talking, but the next actor wasn't, it would set "NPCIsTalking" to 0, even though the first actor may still be talking. What I'm doing is writing a buffer purging script. Because of the bug with that function (thanks Bethesda), if an actor is talking while that function is called, the voice sound get cut off. So all you get is lips moving, but no sound. With this section of script, I'm trying to determine if one or more actors are talking, and when the last actor has stopped talking. When that happens, NPCIsTalking should get set to zero, and the rest of my script will continue, allowing buffers to be purged circumventing the "sound" bug. I understand you are not familiar with OBSE functions and scripting additions, but do you think you could tap into your "real" programming language skills to help.

Thanks a bunch

Edited by Malonn
Link to comment
Share on other sites

Reset the variable before you start the loop.

Let HighAINPC := ar_Construct Array

Let HighAINPC := GetHighActors

Set NPCIsTalking to 0

ForEach ActorRef <- HighAINPC

I am guessing here the loop runs once for each NPC in the area, then goes off and does stuff. It then runs through the script again, so if you reset the check variable back to zero, if it does not find anyone talking, it should remain zero after the loop is done.

Link to comment
Share on other sites

ALLLRIGHTY THEN! Something as simple as that. Thanks a million, WillieSea! I spent a whole day trying to figure that out. I was going to give up and try an Event Handler (another goodie from the OBSE people), but you have saved me from that extra scripting. Thanks again, WS.

Link to comment
Share on other sites

Got a bit of a problem; I have an Ayleid switch (ARSwitch01) in one cell that's supposed to open a linked gate (ARGate01) in another cell, but it's not doing it. The gate is set as a persistent ref, so that isn't the issue. For some reason, the switch's script isn't acting on the linked gate.

The dungeon I'm working on has a light world/dark world theme using the Ayleid ruins tileset and King Dutka's Drow ruins tileset. Cell01a (Ayleid) has a gate that is activated by a switch in Cell01b (Drow). Likewise, there is another gate in Cell01b that has a corresponding switch in Cell01a.

The idea is to have the Player teleport between the two cells in order to fully advance through either one. All subsequent levels are intended to have this setup, so a generic, non-dedicated script is needed. Is there a way I can modify the vanilla ARSwitch01Script to use the following setup:

1. Player presses switch.

2. Switch fires a script containing a GameMode block with an "Activate" command that won't run until GetInSameCell returns a value of 1.

3. When the Player teleports into the cell with the linked gate, the GetInSameCell function now returns a value of 1 and the gate is activated.

4. Another flag is now also set to 1 so the script will stop running.

Update: I re-scripted the switch to run as described above, but it's still not working completely right. :wallbash: What's happening now is this:

1. Player presses switch in Cell01a.

2. Linked gate does nothing when player teleports into Cell01b.

3. Player teleports back to Cell01a and presses the switch again.

4. Linked gate opens when Player enters Cell01b.

5. From this point on, the gate in Cell01b will work normally every time the Player pushes the switch in Cell01a.

This is almost right, but not quite. I need the gate to start working without the player having to press the switch twice.

My current script is:


scn ARSwitch01BlarneyGateScript


short Blarney

ref target

ref mySelf


begin onactivate


if busy == 0

set target to getParentRef

set mySelf to getSelf

playgroup forward 0

set Blarney to 1

endif


end


begin gameMode


if isAnimPlaying == 0 && Blarney == 1

if (GetInSameCell player)

target.activate mySelf 1

set Blarney to 0

Endif

endif


end

What do I need to change here to get this thing working?

Help me Batmer, you're my only hope!

Edited by The Vyper
Link to comment
Share on other sites

The 'activate' (will not work) has problems when the object being activated is not loaded into memory. That is why it works after visiting the cell, the object has now been loaded to memory.

Instead of using activate, why don't you use SetOpenState? It does not need the object loaded into memory.

Link to comment
Share on other sites

The 'activate' (will not work) has problems when the object being activated is not loaded into memory. That is why it works after visiting the cell, the object has now been loaded to memory.

Instead of using activate, why don't you use SetOpenState? It does not need the object loaded into memory.

My understanding of the OpenState functions is that they only work on doors, but ARGate01 is an activator. Even so, I tried using SetOpenState anyway and got the same result: nothing. I re-checked the wiki to make sure I was using it right and noticed this part:

Will animate open/closed if the door is loaded.

My understanding of GameMode blocks is that they run every frame until told to stop. I thought setting references and shorts in onactivate blocks would cause subsequent blocks to use those settings. If that's true, then the 'activate' command wouldn't occur until both Blarney and GetInCell Player equal 1, which should only happen if the Player enters Cell01b after activating the switch. In that case, the gate in question would be loaded when the 'activate' call is made by the GameMode block.

I know one switch (activator) can be set to activate an activator in another cell because at least two Oblivion realms do this. Random World 2 has four small towers, each with a switch inside it that activates a war gate outside. Random World 4 has two small towers; one has a switch that extends a bridge (activator) linking the two, the other has a switch that extends two bridges linking to the sigil tower. The scripts on the associated switches use the same variables and generic language as ARSwitch01Script and it works fine.

There has to be some way of making this work, but I just can't figure it out. Should I just scrap the mod and move on?

Link to comment
Share on other sites

The key word here is 'animate'. It will set the door open or closed if not loaded, it will just not animate.

Will animate open/closed if the door is loaded.

But your right, it will not work on an activator.

What I suggest is setting a global in the switch script.

Then in the room with the 'door', you can have a trigger zone that checks for the global. If its set, you then activate the gate.

Link to comment
Share on other sites

What I suggest is setting a global in the switch script.

Then in the room with the 'door', you can have a trigger zone that checks for the global. If its set, you then activate the gate.

Good idea. :thumbup: Unfortunately, I got the same result: no gate activation. :shrug: I give up. :whiteflag: I'm going to have to find some other way of making this light world/dark world setup work. Luckily, I have some ideas on that front.

Link to comment
Share on other sites

  • 5 weeks later...

I'm working on an update for my Ayleid Power Stones mod that I hope to release sometime next month. In the current version of APS, there are five levels of power stones that all use the same mesh (the same way sigil stones do). The Player activates an activator (that also uses the power stone mesh) and a leveled list is added to the Player's inventory. Here's the script:


ScriptName APSActivatorScript


short StartDay

Begin onactivate Player


Message " "

Message " "

Player.AddItem APSMasterList 1 ;a nested leveled list that will add a level appropriate stone to the Player inventory

PlaySound ITMGenericUp

Set StartDay to GameDaysPassed

Disable

End


Begin GameMode

If ( GameDaysPassed - StartDay ) >= 7 && GetDisabled == 1

Enable

EndIf


End

I want to change things up a bit. For this version, I want to include 5 different colored stones; one color for each level of stone (5 in all). For this to work, I'll need to place all five power stone activators in the exact same spot in each cell they're in, set them to "initially disabled", and script each one with an onload block that checks the Player's level to ensure only the level appropriate activator gets enabled. That, I can do.

Here's an example of what I want to happen:

  1. Player enters Vilverin01 on Sundas and grabs a level 3 stone, then leaves Vilverin entirely. It will be seven days until the stone "regenerates" and can be taken again.

  2. Player levels up on Morndas, enabling him/her to get level 4 stones.

  3. Player returns to Vilverin01 right after leveling up and finds no power stone.

  4. Player proceeds to Vilverin02 (previously unvisited) and finds a second power stone, this one level 4.

  5. Player finds another power stone (also level 4) in Vilverin03.

No. 3 is where I run into a problem. How can I script the stones so that a level appropriate activator will be enabled in a particular cell onload only if the previous level activator was not activated/enabled within the past seven days?

I need to script this as generically as possible (like the script above) so that what happens with the power stones in one Ayleid ruin would not keep the power stones in any other Ayleid ruin from spawning. Is that even possible without A} using persistent references and B} making ruin-specific activators?

Link to comment
Share on other sites

I am not really sure I follow what you want.

I think you want the stone to enable based on the players level when they enter the cell.

Since each script attached to each object will retain its own set of values, you just have the on-load check when it was 'enabled' last and if the time requirement has elapsed or has never been set, then you disable all stones but the one you want based on the players level.

Link to comment
Share on other sites

I am not really sure I follow what you want.

Yeah, I was in a rush and wasn't sure if I was explaining things right.

I think you want the stone to enable based on the players level when they enter the cell.

Yes, but only if it hasn't been enabled and activated within the last seven days.

Since each script attached to each object will retain its own set of values, you just have the on-load check when it was 'enabled' last and if the time requirement has elapsed or has never been set, then you disable all stones but the one you want based on the players level.

That's easy enough, but doesn't quite solve the potential problem I foresee:

  1. A level 4 Player character enters Cell01 on day 1. The level 1 stone is enabled and taken by the character.

  2. On day 2, character levels up (character is now level 5; level 2 stones will now be enabled onload).

  3. On day 2 (or any day before day 7), Character enters Cell01 again.

At this point, less than seven days have passed since the Player grabbed the level 1 stone in Cell01. However, since the Player's level has now increased to the point where level 2 stones will be enabled, I need to find some way to keep the level 2 stone from being enabled in Cell01 until day 7.

What makes this harder is that I need it to be generic. By that, I mean a single setup that can be used across multiple cells without requiring unique scripts for each cell.

Is there any way to set things up so that the setup & scripts used in Cell01 can also be used (without modification) in multiple other cells? If needed, I could resort to placing a single activator and use the SetTexturePath OBSE function to change its color depending on Player level, but I don't like making OBSE dependent mods.

Link to comment
Share on other sites

Unfortunately, Oblivion does not allow much in the way of 'reusability' like you are trying, there really are not any commands for it. (The later games do, especially Skyrim.)

I am not sure how you would make a 'copy & paste' feature like you want that would work in all cells.

Link to comment
Share on other sites

Unfortunately, Oblivion does not allow much in the way of 'reusability' like you are trying, there really are not any commands for it. (The later games do, especially Skyrim.)

I am not sure how you would make a 'copy & paste' feature like you want that would work in all cells.

:( That's what I was afraid of. Oh well, it never hurts to ask. :) Looks like I'll have to make a single color for all levels or use the SetTexturePath command in OBSE.

Link to comment
Share on other sites

  • 1 month later...

Edit: Solved Okay, new question. I'm trying to script an activator to work in the following manner:

1. Player activates the activator.

2. A messagebox appears, giving the Player a number of options to select from.

3. Once the Player chooses an option, the activator disables itself for three days.

4. Once three days have passed, the activator re-enables itself.

The script I have so far is:


scn TestMultiChoiceActivatorScript

short Chosen

short Button

Begin onactivate Player

Messagebox "Choose item" "Sword" "Shield" "Bow" "Axe" "Mace"

End

Begin GameMode

Set Button to GetButtonPressed

If Button == 0 && Chosen < 1

Player.AddItem VypSwordLL 1 ;IDs ending in LL are custom leveled lists

Set Chosen to 1

ElseIf Button == 1

Player.AddItem VypShieldLL 1

Set Chosen to 1

ElseIf Button == 2

Player.AddItem VpyBowLL 1

Set Chosen to 1

ElseIf Button == 3

Player.AddItem VypAxeLL 1

Set Chosen to 1

ElseIf Button == 4

Player.AddItem VypMace 1

Set Chosen to 1

Else

Return

Endif

End


As currently written, that script will only work once, but I need it to work once every three days. How can I set this up so that I can place multiple instances of the activator without needing a unique script for each placement?

Edited by The Vyper
Link to comment
Share on other sites

  • 1 month later...

I has question!

 

So I'm making a few special sets of weapons that I would like to do different things. For example, one set of balloon-like weapons that create a splash of confetti when an actor is hit. I really don't know where to start with that one.

 

I'd also like these weapons to have custom noises, too. I'd like my balloon weapons to make a rubber squeaky-toy sound when you hit something. I already know how to load custom sounds into the CS, and made my weapon make a custom sound when equipped. But the hitting sound doesn't seem to work yet. It's probably a problem in my script.

 

My script for the sound is. 

 

 

scn aaaPinkieItemAddSoundScript
 
Begin OnHit
PlaySound aapinkiegiggle
 
End
 
Begin OnEquip
PlaySound aapinkiepiestyle
 
End
 
 
Whichever way I sort the OnHit and OnEquip boxes, the same thing happens. The OnEquip sound is heard, but the OnHit sound is not. 
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...