Doorbell script

Post » Fri May 27, 2011 11:50 pm

I'd like some help creating a script for a doorbell for my latest mod WIP. Basically, the player cannot enter the house by activating the door, as it is locked. I have managed to script it so it says "Please ring the bell!" on activation.

Now for the doorbell script, where I am having troubles understanding what functions to use, how to order them etc.

Basically, when activated, the doorbell should do the following:

- play a doorbell sound (I am currently using the Sixth House bell sound)
- present a message box saying "come in?", with two buttons: "yes" and "no".
- when selecting "yes", the player should be teleported inside the house. When "no", the message box disappears.
- The same process should happen every time the doorbell is activated, i.e. there are no limitations etc.

I'm completely new to scripting - trying to figure this out on my own and reading "Scripting for Dummies", I have so far come up with the following:
begin aiy_doorbell_scriptShort controlvarShort buttonif ( MenuMode == 1 )	Returnendifif ( OnActivate == 1 )	PlaySound "Sixth_Bell"	MessageBox "Come in?", "Yes", "No"	Set controlvar to 1endifif ( controlvar == 1 )	set button to GetButtonPressed	if ( button == -1 )		return	elseif ( button == 1 )	PositionCell "Unim's House - Interior"	elseif ( button == 2 )		return		endifendif	 end


Firstly, I have no idea if this is right, at all. Especially the message box and buttons and controlvar parts (still don't fully understand the meaning of controlvar). Also, I need to know the correct way how to teleport the player to the interior of the house, which is the correct cell ID to use or how to obtain the coordinates?

Finally - the doorbell is an ashlander chime, which originally had the SignRotate script on it to make it sway. Without it, it looks rather static. How can I add this script back into my script - can I just add in onto the beginning or end?

Thanks for any help. :blush:
User avatar
Ashley Campos
 
Posts: 3415
Joined: Fri Sep 22, 2006 9:03 pm

Post » Fri May 27, 2011 12:35 pm

Your script looks pretty good, just a few bits I'd clean up (mostly indenting and some of your ifs):
begin aiy_doorbell_scriptShort controlvarShort buttonif ( MenuMode  )	Returnendifif ( controlvar == 1 )	set button to GetButtonPressed	if ( button == -1 )		return	elseif ( button == 1 )		"player"->PositionCell pX pY pZ rZ "Unim's House - Interior" ;you need to position the player (otherwise the doorbell will move), and give coordinates for where they should go		set controlvar to 0	else ;use else here, just in case something funny happens		set controlvar to 0		return		endifelse	if ( onactivate  )		PlaySound "Sixth_Bell"		MessageBox "Come in?", "Yes", "No"		Set controlvar to 1	endifendifend


As for merging the scripts, I think you can put the rotate one up at the top (under the if(menumode) block). It depends on how complex the signrotate script is.
User avatar
Andrew Tarango
 
Posts: 3454
Joined: Wed Oct 17, 2007 10:07 am

Post » Fri May 27, 2011 7:30 am

Great, thanks for your help!

How do I find out what coordinates I need to put in? If the doormarker is the place the player should teleport to, are they the "X Y Z" numbers in the box that comes up when you double click on it? (I also don't know what "rZ" is).
Is there any reason why the "controlvar" section is before the "onactivate" section? - So I know for future scripts :)
User avatar
Javier Borjas
 
Posts: 3392
Joined: Tue Nov 13, 2007 6:34 pm

Post » Fri May 27, 2011 8:38 pm

Great, thanks for your help!

How do I find out what coordinates I need to put in? If the doormarker is the place the player should teleport to, are they the "X Y Z" numbers in the box that comes up when you double click on it? (I also don't know what "rZ" is).
Is there any reason why the "controlvar" section is before the "onactivate" section? - So I know for future scripts :)

First up, a note on GetButtonPressed:
- It returns -1 if no button has been pressed, 0 if first button was pressed, 1 if second button was pressed, and so on.
- Therefore if 'Yes' is the first button you need to check for button == 0

ControlVar is controlling the flow of the script. In this case ControlVar is used to tell the script that the doorbell has been activated, the message box has been displayed and we are waiting for a player response.
In this case OnActivate could go before ControlVar but that would not be optimal as the script would be checking if the door had been activated even while we are waiting for player to select an option. When the message box is displayed the player cannot activate the door so it would be pointless to check for it.

Here is how I would write the script (and I haven't had a chance to check it so I hope it is ok!):
begin aiy_doorbell_scriptShort buttonif ( MenuMode  )	Returnendifif ( button == -1 )	set button to GetButtonPressed	if ( button == 0 )		"player"->PositionCell X_Pos Y_Pos Z_Pos Z_Angle "Unim's House - Interior"	endif	elseif ( onactivate  )	PlaySound "Sixth_Bell"	MessageBox "Come in?", "Yes", "No"	Set button to -1else	; Sign rotate code goes here	endifend


Here I have used the button variable to do the same function as Controlvar. When the script is running normally and player has not activated doorbell, it will run through and check the following conditions:

(Pseudo Code)1. Does button == -1 ?No - next condition2. Has player activated doorbell ?No - next condition3. Else..Player has not activated doorbell, button is not set to -1, make the doorbell sway in the wind.



If player activates doorbell, script goes like this:

(Pseudo Code)1. Does button == -1 ?No - not yet2. Has player activated doorbell?Yes - Do the code under OnActivate3. Else..Else condition not true so the doorbell sway code does not run.



Now... The next frame the script will run like this:

(Pseudo Code)1. Does button == -1 ?Yes - do the code under this condition 2. Elseif ( OnActivate )The first condition was satisfied so this section will not run3. Else..Again, the first condition was satisfied so this section will not run.



Now the script will continue to wait until player has pressed a button. Either button will change the value of the button variable to greater than -1, so the script will return to normal execution.

And yes, you can copy the coordinates from the door marker. rZ is the Z angle, so the script knows which way to make the player face.

I hope you understood some of that. I find it quite hard to explain this stuff!
User avatar
Miragel Ginza
 
Posts: 3502
Joined: Thu Dec 21, 2006 6:19 am

Post » Fri May 27, 2011 11:27 am

Thanks! I found it harder to understand your script but your explanations did help (and I can understand why it's hard to explain, especially to people like me who have no clue :D)


I've tried both scripts now (without the SignRotate) and both work fine. (Except I had the Interior cell name wrong - just had to be "Unim's House", without the "Interior" stuck on... during testing I always got teleported to somewhere in the West Gash :laugh:). I'm currently using Horny Quintus', since it's shorter and I'd like to add the SignRotate to it, but I've saved yours to a text file peachykeen, for future reference (as I found it easier to comprehend :))

Just need to add the SignRotate script now, had an error message but I think I may have deleted an essential part of the script, trying again.

Edit: Still an error. This is what the script would look like:

begin aiy_doorbell_scriptShort buttonif ( MenuMode  )	Returnendifif ( button == -1 )	set button to GetButtonPressed	if ( button == 0 )		"player"->PositionCell -1.000 22.000 0.000 0.0 "Unim's House"	endif	elseif ( onactivate  )	PlaySound "Sixth_Bell"	MessageBox "Come in?", "Yes", "No"	Set button to -1else	float 	  timer	float    swingTime	float    swingSpeed	float	startAngle	DontSaveObject	set startAngle to GetStartingAngle, y	if ( MenuMode == 1 )		return	endif	if ( GetDistance, Player > 2000 )		return	endif		set swingTime to 1		;set swingSpeed to 30		set timer to ( timer + GetSecondsPassed )		;rotate forward 		if ( timer < swingTime )			Rotate	y, 2		;rotate backward 		elseif ( timer < (swingTime * 3)  )                 	Rotate	y, -2                		;forward again 		elseif ( timer < (swingTime * 4 ) )                     	Rotate	y, 2		;reset timer back to zero		else           	set timer to 0           	SetAngle, y, GetStartingAngle, y		endifendifend


The error message is "You need to enter an axis (X,Y,Z) on line 60?" (line 60 is the "SetAngle, y, GetStartingAngle, y" at the bottom).
Which is weird, because a few minutes ago the error message was slightly different (but about the same line).
User avatar
Amie Mccubbing
 
Posts: 3497
Joined: Thu Aug 31, 2006 11:33 pm

Post » Fri May 27, 2011 12:08 pm

Couple things:
- Your error message is related to the fact you're trying to pass a function as a variable value. Use a temporary variable, and:
Set angleY To GetStartingAngle YSetAngle Y angleY

That'll make the compiler happy.

Second, while the Quintus' script is shorter, it's in terrible form. Using button and OnActivate as branches of a single if/elseif is just asking for trouble. That's why I set mine up the way I did. While that version may work (for the moment), it will cause problems if you try to change it much or need to expand on it in the future.

In particular, using button as both a input-tracking and state-tracking variable is a bad idea. In the menus (pause, options, etc) and dialogue, GetButtonState can return seemingly random results. Certain menus don't trip MenuMode (pause, IIRC).
In addition, the button is never reset properly. If the player escapes the messagebox, the script may continue checking what the value is long after the box is gone. If the player enters menu mode, picks an option, then leaves, the script will similarly break and enter an infinite loop (until it picks up the input from a different messagebox and will position you in the house the next time a mod pops a message). All in all, I wouldn't use it. It may work, but it smells of bad code.

begin aiy_doorbell_scriptShort controlvarShort button; all variables MUST be declared at the top of the scriptFloat timerFloat swingTimeFloat swingSpeedFloat	startAngleif ( MenuMode  )	ReturnendifDontSaveObject; we can optimize here by only setting these two when they haven't been set yet.; since we set both at the same time, if one hasn't been set, neither haveif ( swingTime != 1 )	set startAngle to GetStartingAngle, y	set swingTime to 1endif; using a GetDistance "player" check might skip this part sometimes, but GetDistance is *the slowest* function in the language; use it sparingly, if at all. you could try checking every couple seconds or every couple frames, but it doesn't matter too much.set timer to ( timer + GetSecondsPassed );rotate forward if ( timer < swingTime )	Rotate y, 2	;rotate backward elseif ( timer < (swingTime * 3)  )	Rotate y, -2	;forward again elseif ( timer < (swingTime * 4 ) )	Rotate y, 2	;reset timer back to zeroelse	set timer to 0	;set startY To GetStartingAngle Y ; this check is already done (right after DontSaveObject)	SetAngle Y startAngle endif; using a separate, safe control variable and button variable is Good Form. You're unlikely to run into any problems this way, and its not sketchy.if ( controlvar == 1 )	set button to GetButtonPressed	if ( button == -1 )		return	elseif ( button == 0 )		"player"->PositionCell posX posY posZ rotationZ "Unim's House - Interior" ;you need to position the player (otherwise the doorbell will move), and give coordinates for where they should go		set controlvar to 0	else ;use else here, just in case something funny happens		set controlvar to 0 ;make sure to properly, explicitly reset button no matter how you leave the loop! Quintus' example had a few ways this might not happen		return		endifelse	if ( onactivate  )  ; put onActivate here to save time, if the messagebox is up, we don't need to worry about activation		PlaySound "Sixth_Bell"		MessageBox "Come in?", "Yes", "No"		Set controlvar to 1	endifendifend

Now, that should be more reliable and more optimized. It should also be easier to understand and expand on later (if you need to). There wasn't much technically wrong with Quintus', but it wasn't the most reliable way to handle this. I don't have the CS here, so that might not compile, just post any errors you run into.

And the posX, posY, posZ, rotationZ values should be replaced with the values of the door marker (position and rotation Z).
Also, I noticed you're using a lot of tabs in the line. Use tabs at the beginning of the line for indenting only. Tab and space are different characters, and while MWScript probably won't complain, there's a lot of little things that can break a script. Just use a single space between parameters and functions and param lists.
User avatar
KiiSsez jdgaf Benzler
 
Posts: 3546
Joined: Fri Mar 16, 2007 7:10 am

Post » Fri May 27, 2011 11:17 pm

Ok, I see. So many things to think about :P I've added your script onto the doorbell now and it all seems to be working fine! Thanks for explaining and helping :wavey:
User avatar
luis ortiz
 
Posts: 3355
Joined: Sun Oct 07, 2007 8:21 pm

Post » Fri May 27, 2011 7:39 pm

In particular, using button as both a input-tracking and state-tracking variable is a bad idea. In the menus (pause, options, etc) and dialogue, GetButtonState can return seemingly random results. Certain menus don't trip MenuMode (pause, IIRC).
In addition, the button is never reset properly. If the player escapes the messagebox, the script may continue checking what the value is long after the box is gone. If the player enters menu mode, picks an option, then leaves, the script will similarly break and enter an infinite loop (until it picks up the input from a different messagebox and will position you in the house the next time a mod pops a message). All in all, I wouldn't use it. It may work, but it smells of bad code.

Well that's news to me. Thanks peachykeen, I wasn't aware of those problems. I'll keep them in mind in future. And apologies to Aila for giving bad advice.
User avatar
Lucky Boy
 
Posts: 3378
Joined: Wed Jun 06, 2007 6:26 pm

Post » Fri May 27, 2011 1:22 pm

And apologies to Aila for giving bad advice.

No problem at all :)
User avatar
Kate Murrell
 
Posts: 3537
Joined: Mon Oct 16, 2006 4:02 am

Post » Fri May 27, 2011 2:54 pm

Well that's news to me. Thanks peachykeen, I wasn't aware of those problems. I'll keep them in mind in future. And apologies to Aila for giving bad advice.

No worries. :) Most of what I brought up is some stuff we found out a while back, a few people who noticed message boxes doing funny things after you open the menus and played with some scripts. What exactly happens, nobody really knows, but it's just for safety's sake. ;)
All in all, your script was fine and obviously worked right.
User avatar
Zosia Cetnar
 
Posts: 3476
Joined: Thu Aug 03, 2006 6:35 am


Return to III - Morrowind