Difference between revisions of "Flying"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>8asrun6aer
m
Tag: Manual revert
 
(14 intermediate revisions by 3 users not shown)
Line 2: Line 2:
Flying isn't normally something players can do.  Here's a script to allow that.
Flying isn't normally something players can do.  Here's a script to allow that.


This isn't so much of a snippet of code as it is the complete code for allowing a player to fly in a more or less natural way.  The script below uses velocity functions that prevent wall, ceiling, floor, and obstacle clipping.  Setting up when and how to allow the player to fly ( via casted spell or constant ability) is up to you - the modder.  But for this article, we'll be setting up a new constant Player Ability which will allow the player to initiate flying at any time by pressing a key.
This isn't so much of a snippet of code as it is the complete code for allowing a player to fly in a more or less natural way.  The script below uses velocity functions that prevent wall, ceiling, floor, and obstacle clipping.  Setting up when and how to allow the player to fly (via casted spell or constant ability) is up to you - the modder.  But for this article, we'll be setting up a new constant Player Ability which will allow the player to initiate flying at any time by pressing a key.


Not only can you grant the ability to fly to users of your mod with such a script, but you can use this script yourself as a modder to test every inch of your newly modded world space in a live environment.
Not only can you grant the ability to fly to users of your mod with such a script, but you can use this script yourself as a modder to test every inch of your newly modded world space in a live environment.


The main principle here is avoiding using the [[SetPos]] method of flying, and thus avoid clipping.  Instead, this script works with a player's x,y,z velocities.
The main principle here is avoiding using the [[SetPos]] method of flying, and thus avoid clipping or ghosting through walls.  Instead, this script works with a player's x,y,z velocities.


If you see any part of the example script that can be made more efficient or made easier to read, feel free to edit.  Ideally, this should be made a community-authored script helping modders create efficient and realistic player flying effects.
If you see any part of the example script that can be made more efficient or made easier to read, feel free to edit.  Ideally, this should be made a community-authored script helping modders create efficient and realistic player flying effects.
Line 17: Line 17:
This script assigns the "/" key to begin and end flying mode.  You can change this at or around line 62 in this script where it assigns this key value to the 'cstmControlActivateFlyMode' variable (for a list of valid keyboard key ID's to use instead, see [[GetControl]]).
This script assigns the "/" key to begin and end flying mode.  You can change this at or around line 62 in this script where it assigns this key value to the 'cstmControlActivateFlyMode' variable (for a list of valid keyboard key ID's to use instead, see [[GetControl]]).


While flying, use the regular forward/backward/strafe keys for movement.  Should the player ever reassign directional control keys, flight controls will be reset only after the player reloads the game.
While flying, use the regular forward/backward/strafe keys for movement.  Should the player ever reassign directional control keys, flight controls will be reset only after the player reloads the game.  This directional control reassignment on game-load happens around line 56.


Use the mouse to control flight direction.
Use the mouse to control flight direction/heading.  While facing in a downward angle and moving backwards, the player will ascend as this effect should help players with keeping track of combat targets on the ground.




== The Script ==
== The Script ==
Before continuing, you'll want to create a new Global value.  In the TES CS, go to Gameplay -> Globals menu, right-click in the list of globals, select "New", and for the Form ID, enter ''cstmGlobalPlayerIsFlying'' as a ''short'' with value ''0''.  This ''cstmGlobalPlayerIsFlying'' global variable holds the flying state of the player.  It's global so that this state can be easily checked or altered in other scripts.
Before continuing, you'll want to create a new [[Globals|Global]] variable.  In the [[The_Elder_Scrolls_Construction_Set|TES CS]] main menu, go to Gameplay -> Globals menu, right-click in the list of globals, select "New", and for the Form ID, enter ''cstmGlobalPlayerIsFlying'' as a ''short'' with value ''0''.  This ''cstmGlobalPlayerIsFlying'' global variable holds the flying state of the player.  It's meant to be global so that the player's flying state can be easily checked or altered in other scripts.


Also, note the only code block used by this script is the ''ScriptEffectUpdate'' block.  The ''ScriptEffectFinish'' block is irrelevant to constant abilities, and the ''ScriptEffectStart'' block would make this script too dependent on initial new game environments.
Also, note the only code block used by this example magic effect script is the [[ScriptEffectUpdate]] block.  The [[ScriptEffectFinish]] block is irrelevant to constant abilities, and the [[ScriptEffectStart]] block would make this script too dependent on initial new game environments.  Though if made part of a regular duration spell effect, you could use [[ScriptEffectStart]] for set up, and [[ScriptEffectFinish]] for cleanup.


To easily distinguish local variables for the sake of readability in this example script, each new local variable name begins with 'cstm'.  Also, the script is heavily commented to hopefully make each step more clear.
To easily distinguish local variables for the sake of readability in this example script, each local variable name begins with 'cstm'.  Also, the script is heavily commented to hopefully make each step more clear.




<pre>
<pre>
scn cstmFlightScript
scn cstmFlightScript


; *************
; *************
Line 43: Line 44:
;*******************************
;*******************************
float cstmXVelocity ; velocity towards x 0 point
float cstmXVelocity ; velocity towards x 0 point
float cstmYVelocity ; velocity towards z 0 point
float cstmYVelocity ; velocity towards y 0 point
float cstmZVelocity ; velocity towards y 0 point
float cstmZVelocity ; velocity towards z 0 point
float cstmZGravityModifyer ; counteracts effects of world gravity on Z
float cstmPitch ; up/down angle player is facing
float cstmPitch ; up/down angle player is facing
float cstmZPitchModifyer ; modifies applied up/down speed based on the angle player is facing up or down
float cstmHeading ; 0-360 degrees from North player is facing
float cstmHeading ; 0-360 degrees from North player is facing
float cstmSpeed ; updated rate of player movement in any given direction
float cstmSpeed ; updated rate of player movement in any given direction
float cstmSpeedMax ; max forward speed




Line 119: Line 117:
; Invalid states are if player is not in air, is swimming, etc
; Invalid states are if player is not in air, is swimming, etc
;*******************************
;*******************************
if ( Player.IsInAir != 1 || Player.IsSwimming )
if ( Player.IsInAir != 1 )
set cstmGlobalPlayerIsFlying to 0
set cstmGlobalPlayerIsFlying to 0
; flying stopped, skip rest of script update
; flying stopped, skip rest of script update
Line 138: Line 136:
</pre>
</pre>


Pausing here for a second.  This script damages the player's fatigue while flying to avoid encouraging the player to fly over every dangerous situation in the game.  If you're only testing a new map you've just made, you'll want to comment out this part as it'll only get in the way.  Otherwise, think twice about letting the player fly around without a care in the world.
Pausing here for a second.  This script damages the player's fatigue while flying to avoid encouraging the player to fly over every dangerous situation in the game.  You may also replace this to damage magika instead if you like.  If you're only testing a new map you've just made, or if you're making this script part of a regular short-duration spell, you'll want to comment out or delete this section of the script as it'll only be an inconvenience.  Otherwise, think twice about letting the player fly around without a care in the world.


<pre>
<pre>
Line 171: Line 169:


<pre>
<pre>
;*******************************
;*******************************
; Movement
; Movement
;*******************************
;*******************************
set cstmHeading to Player.GetAngle z
set cstmHeading to Player.GetAngle z
set cstmSpeedMax to 600 ; adjust to control how fast a player flies, but keep high to have any noticeable effect
set cstmPitch to ( Player.GetAngle x ) * -1
set cstmPitch to Player.GetAngle x
set cstmSpeed to 600
set cstmZPitchModifyer to ( cstmPitch / 90 ) * -1
if ( isKeyPressed2 cstmControlForward )
if ( isKeyPressed2 cstmControlForward )
; going forward
; going forward
set cstmSpeed to cstmSpeedMax
; modify heading if strafing forward
if ( cstmZPitchModifyer < 0 )
set cstmZPitchModifyer to cstmZPitchModifyer * 2.0 ; move faster going down
else
set cstmZPitchModifyer to cstmZPitchModifyer * 0.7 ; move slower going up
endif
; modify heading if strafing
if ( isKeyPressed2 cstmControlStrafeLeft )
if ( isKeyPressed2 cstmControlStrafeLeft )
set cstmHeading to cstmHeading - 45
let cstmHeading += 320
elseif ( isKeyPressed2 cstmControlStrafeRight )
elseif ( isKeyPressed2 cstmControlStrafeRight )
set cstmHeading to cstmHeading + 45
let cstmHeading += 45
endif
endif
set cstmXVelocity to cos cstmPitch * sin cstmHeading * cstmSpeed
set cstmYVelocity to cos cstmPitch * cos cstmHeading * cstmSpeed
set cstmZVelocity to sin cstmPitch * cstmSpeed
elseif ( isKeyPressed2 cstmControlBackward )
elseif ( isKeyPressed2 cstmControlBackward )
; reverse speed
; going backward
set cstmSpeed to ( cstmSpeedMax -200 ) * -1
; modify heading if strafing backward
if ( cstmZPitchModifyer < 0 )
set cstmZPitchModifyer to cstmZPitchModifyer * 0.7 ; move slower going up
else
set cstmZPitchModifyer to cstmZPitchModifyer * 2.0 ; move faster going down
endif
; modify reverse heading if strafing
if ( isKeyPressed2 cstmControlStrafeLeft )
if ( isKeyPressed2 cstmControlStrafeLeft )
set cstmHeading to cstmHeading + 45
let cstmHeading += 225
elseif ( isKeyPressed2 cstmControlStrafeRight )
elseif ( isKeyPressed2 cstmControlStrafeRight )
set cstmHeading to cstmHeading - 45
let cstmHeading += 135
else
let cstmHeading += 180
endif
endif
set cstmXVelocity to cos cstmPitch * sin cstmHeading * cstmSpeed
set cstmYVelocity to cos cstmPitch * cos cstmHeading * cstmSpeed
set cstmZVelocity to sin cstmPitch * cstmSpeed * -1
else
else
; modify in-place heading if strafing, otherwise hover in place
; modify in-place heading if strafing, otherwise hover in place
if ( isKeyPressed2 cstmControlStrafeLeft )
if ( isKeyPressed2 cstmControlStrafeLeft )
set cstmSpeed to cstmSpeedMax - 200
let cstmHeading += 270
set cstmHeading to cstmHeading - 90
elseif ( isKeyPressed2 cstmControlStrafeRight )
elseif ( isKeyPressed2 cstmControlStrafeRight )
set cstmSpeed to cstmSpeedMax - 200
let cstmHeading += 90
set cstmHeading to cstmHeading + 90
else
else
set cstmSpeed to 0 ; just hovering in place
set cstmSpeed to 0 ; just hovering in place
endif
endif
set cstmXVelocity to sin cstmHeading * cstmSpeed
set cstmYVelocity to cos cstmHeading * cstmSpeed
set cstmZVelocity to ( ( GetLocalGravity z ) / ( 21 + ( 1 / 3 ) ) ) * cstmSecondsPassed
endif
endif
; normalize heading to 0-360 degree allowable range
if ( cstmHeading < 0 )
set cstmHeading to cstmHeading + 360
elseif ( cstmHeading > 360 )
set cstmHeading to cstmHeading - 360
endif
; use maths to adjust x,y direction of travel based on heading
set cstmXVelocity to sin cstmHeading * cstmSpeed
set cstmYVelocity to cos cstmHeading * cstmSpeed
; Set up/down velocity adjusting for gravity's influence and player's pitch
set cstmZGravityModifyer to ( ( GetLocalGravity z ) / ( 21 + ( 1 / 3 ) ) ) * cstmSecondsPassed ; see GetLocalGravity elderscrolls.com article for this formula
set cstmZVelocity to ( cstmZPitchModifyer * cstmSpeed ) + cstmZGravityModifyer


; player essentially "falls" to their new x,y,z coords
; player essentially "falls" to their new x,y,z coords
Line 246: Line 224:
</pre>
</pre>


Once the script is saved, create a new [[Spell|Ability Spell]].  Set the ''Type'' of the spell to ''Ability''.  Then, add a new effect to this new ability spell.  For this new effect, set the ''Range'' to ''Self'', the ''Duration'' to ''0'', the ''Script'' to ''cstmFlightScript'', the ''Effect Name'' to something readable in-game like ''Flying'', and click ''OK''.  You can then make this a ''PC Start'' spell, or [[Race_creation_tutorial#Specials|add it as a default ability for any race]].
== Making This a Permanent Ability ==
Once the script is saved as a "Magic Effect" script-type, create a new [[Spell|Ability Spell]].  Set the ''Type'' of the spell to ''Ability''.  Then, add a new effect to this new ability spell.  For this new effect, set the ''Range'' to ''Self'', the ''Duration'' to ''0'', the ''Effect Type'' to ''Script Effect'', the ''Script'' to ''cstmFlightScript'', the ''Script Effect Name'' to something readable in-game like ''Flying'', and click ''OK''.  You can then make this a ''PC Start'' spell, or [[Race_creation_tutorial#Specials|add it as a default ability for any race]].


== Notes ==
== Notes ==
# This script requires that the player be in the air in order to activate flying.  In other words, the player must be jumping or falling before flying can be activated.  This catch is necessary to not produce the same wall/ceiling clipping that the customary [[SetPos]] method does, and for initially adjusting player velocities.
# This script requires that the player be in the air in order to activate flying.  In other words, the player must be jumping or falling before flying can be activated.  This catch is necessary to not produce the same wall/ceiling clipping that the customary [[SetPos]] method does, and for initially adjusting player velocities.  Though you can automate triggering a jump and activating flying if you wishYou could also [[SetPos]] 5 or so units in the air and fly from there, but the danger there is clipping in tight interior spaces.
# Sometimes, activating flying only causes the player to rise 20 or so feet and then fallClick the ''activate'' key a few more times to really activate flying.  The exact location of this bug in this script is not yet known, but likely somewhere in the initial flight activation check area (line ~69).
# A player can fly over castle walls in exterior world spaces.  Because they didn't enter the castle grounds through the front door, they'll be bewildered by how every building within the castle walls is nothing but a fake graphics placeholder.  There are "Open Cities" mods out there that should correct that.
# A player can fly over castle walls in exterior world spaces.  Because they didn't enter the castle grounds through the front door, they'll be bewildered by how every building within the castle walls is nothing but a fake graphics placeholder.  Although as yet untested with this script, you may want to mention to your mod users any "Open Cities" mods that may be out there to correct this issue.
# Though modified heavily from the original code and using different procedural flow with new methods and solutions for flying controls and effects, some of the basic flight concepts of the above script were based on the flying script packaged with the "A Chingari and Ismelda Demon Race:Demon Race v3-0-3" mod found at the [[TESNexus]] site. (Note that the mod contains adult content, and cannot be linked to from this site. If you choose to find it by searching TES Nexus, you accept that you may be subject to said adult content.)
#  For bugs, better equations, etc, see the [[Talk:Flying|Discussion]] page on this topic.


[[Category: Useful Code]]
[[Category: Useful Code]]

Latest revision as of 14:12, 21 December 2023

Introduction[edit | edit source]

Flying isn't normally something players can do. Here's a script to allow that.

This isn't so much of a snippet of code as it is the complete code for allowing a player to fly in a more or less natural way. The script below uses velocity functions that prevent wall, ceiling, floor, and obstacle clipping. Setting up when and how to allow the player to fly (via casted spell or constant ability) is up to you - the modder. But for this article, we'll be setting up a new constant Player Ability which will allow the player to initiate flying at any time by pressing a key.

Not only can you grant the ability to fly to users of your mod with such a script, but you can use this script yourself as a modder to test every inch of your newly modded world space in a live environment.

The main principle here is avoiding using the SetPos method of flying, and thus avoid clipping or ghosting through walls. Instead, this script works with a player's x,y,z velocities.

If you see any part of the example script that can be made more efficient or made easier to read, feel free to edit. Ideally, this should be made a community-authored script helping modders create efficient and realistic player flying effects.

Requirements[edit | edit source]

  • This script uses OBSE 20 functions. In order for the script to run, the player will need OBSE version 20 installed.


In-Game Controls[edit | edit source]

This script assigns the "/" key to begin and end flying mode. You can change this at or around line 62 in this script where it assigns this key value to the 'cstmControlActivateFlyMode' variable (for a list of valid keyboard key ID's to use instead, see GetControl).

While flying, use the regular forward/backward/strafe keys for movement. Should the player ever reassign directional control keys, flight controls will be reset only after the player reloads the game. This directional control reassignment on game-load happens around line 56.

Use the mouse to control flight direction/heading. While facing in a downward angle and moving backwards, the player will ascend as this effect should help players with keeping track of combat targets on the ground.


The Script[edit | edit source]

Before continuing, you'll want to create a new Global variable. In the TES CS main menu, go to Gameplay -> Globals menu, right-click in the list of globals, select "New", and for the Form ID, enter cstmGlobalPlayerIsFlying as a short with value 0. This cstmGlobalPlayerIsFlying global variable holds the flying state of the player. It's meant to be global so that the player's flying state can be easily checked or altered in other scripts.

Also, note the only code block used by this example magic effect script is the ScriptEffectUpdate block. The ScriptEffectFinish block is irrelevant to constant abilities, and the ScriptEffectStart block would make this script too dependent on initial new game environments. Though if made part of a regular duration spell effect, you could use ScriptEffectStart for set up, and ScriptEffectFinish for cleanup.

To easily distinguish local variables for the sake of readability in this example script, each local variable name begins with 'cstm'. Also, the script is heavily commented to hopefully make each step more clear.


scn cstmFlightScript


; *************
; note about globals used
; *************
; cstmGlobalPlayerIsFlying - indicates current flying state, accessible globally


;*******************************
; Positional data variables
;*******************************
float cstmXVelocity ; velocity towards x 0 point
float cstmYVelocity ; velocity towards y 0 point
float cstmZVelocity ; velocity towards z 0 point
float cstmPitch ; up/down angle player is facing
float cstmHeading ; 0-360 degrees from North player is facing
float cstmSpeed ; updated rate of player movement in any given direction


;*******************************
; Directional keys
;*******************************
short cstmControlForward
short cstmControlBackward
short cstmControlStrafeLeft
short cstmControlStrafeRight
short cstmControlActivateFlyMode ; key which activates or deactivates flying


;*******************************
; Values for damaging fatigue while flying
;*******************************
float cstmCurrentEncumbranceValue ; player's current encumbrance
float cstmMaxEncumbranceValue ; player's maximum encumbrance
float cstmFlyingFatigueDamage ; comulative amount of damage to fatigue in one second


;*******************************
; Misc
;*******************************
float cstmSecondsPassed ; seconds passed since last scripteffectupdate



Begin ScriptEffectStart
End


Begin ScriptEffectUpdate

	;*******************************
	; Reset Key bindings on game load
	;*******************************
	if ( GetGameRestarted || GetGameLoaded )
		set cstmControlForward to GetControl 0
		set cstmControlBackward to GetControl 1
		set cstmControlStrafeLeft to GetControl 2
		set cstmControlStrafeRight to GetControl 3
		set cstmControlActivateFlyMode to 53 ; forwardslash key
	endif
	
	
	;*******************************
	; Check current flying state, or for flying activation/deactivation
	;*******************************
	if ( cstmGlobalPlayerIsFlying == 0 )
		if ( iskeypressed2 cstmControlActivateFlyMode )
			; player activated flying
			set cstmGlobalPlayerIsFlying to 1
		else
			; not flying right now, skip rest of script update
			return
		endif
	elseif ( iskeypressed2 cstmControlActivateFlyMode )
		; player pressed flight activate button again to end flying
		set cstmGlobalPlayerIsFlying to 0
		; flying stopped, skip rest of script update
		return
	endif

	
	;*******************************
	; Check player state to see if flying should stop
	; Invalid states are if player is not in air, is swimming, etc
	;*******************************
	if ( Player.IsInAir != 1 )
		set cstmGlobalPlayerIsFlying to 0
		; flying stopped, skip rest of script update
		return
	endif


	;*******************************
	; Presetup
	;*******************************	
	set cstmSecondsPassed to ScriptEffectElapsedSeconds
	resetFallDamageTimer ; reset damage to be taken by falls or stopped flight based on current height

	
	;*******************************
	; Damage fatigue while flying
	;*******************************

Pausing here for a second. This script damages the player's fatigue while flying to avoid encouraging the player to fly over every dangerous situation in the game. You may also replace this to damage magika instead if you like. If you're only testing a new map you've just made, or if you're making this script part of a regular short-duration spell, you'll want to comment out or delete this section of the script as it'll only be an inconvenience. Otherwise, think twice about letting the player fly around without a care in the world.

	if ( Player.getAV fatigue <= 0 )
		set cstmGlobalPlayerIsFlying to 0
		message "You are too weak to fly."
		; flying stopped, skip rest of script update
		return
	endif
	
	set cstmCurrentEncumbranceValue to Player.getAV encumbrance
	set cstmMaxEncumbranceValue to Player.getBaseAV encumbrance
	; check if player is carrying too much to fly, or if max encumbrance is less than 1 for some reason
	if ( ( cstmCurrentEncumbranceValue >= cstmMaxEncumbranceValue ) || ( cstmMaxEncumbranceValue < 1 ) )
		set cstmGlobalPlayerIsFlying to 0
		message "You are too encumbered to fly."
		; flying stopped, skip rest of script update
		return
	endif
	
	; Player takes about 15-45 fatigue damage per second while flying depending on how weighted down they are by encumbrance
	; Since ModAV2 rounds down to an integer, damage is fractionally accumulated until at least 1 full point is tallied during any fraction of a second
	set cstmFlyingFatigueDamage to cstmFlyingFatigueDamage + ( ( ( ( cstmCurrentEncumbranceValue / cstmMaxEncumbranceValue ) * 30 ) + 15 ) * cstmSecondsPassed )
	if ( cstmFlyingFatigueDamage >= 1 )
		Player.ModAV2 fatigue -1
		set cstmFlyingFatigueDamage to 0
	endif

Now for the most important part of flying - controlling speed, heading, and pitch while negating gravity.

	;*******************************
	; Movement
	;*******************************
	set cstmHeading to Player.GetAngle z
	set cstmPitch to ( Player.GetAngle x ) * -1
	set cstmSpeed to 600
	
	if ( isKeyPressed2 cstmControlForward )
		; going forward
		; modify heading if strafing forward
		if ( isKeyPressed2 cstmControlStrafeLeft )
			let cstmHeading += 320
		elseif ( isKeyPressed2 cstmControlStrafeRight )
			let cstmHeading += 45
		endif
		set cstmXVelocity to cos cstmPitch * sin cstmHeading * cstmSpeed
		set cstmYVelocity to cos cstmPitch * cos cstmHeading * cstmSpeed
		set cstmZVelocity to sin cstmPitch * cstmSpeed
	elseif ( isKeyPressed2 cstmControlBackward )
		; going backward
		; modify heading if strafing backward
		if ( isKeyPressed2 cstmControlStrafeLeft )
			let cstmHeading += 225
		elseif ( isKeyPressed2 cstmControlStrafeRight )
			let cstmHeading += 135
		else
			let cstmHeading += 180
		endif
		set cstmXVelocity to cos cstmPitch * sin cstmHeading * cstmSpeed
		set cstmYVelocity to cos cstmPitch * cos cstmHeading * cstmSpeed
		set cstmZVelocity to sin cstmPitch * cstmSpeed * -1
	else
		; modify in-place heading if strafing, otherwise hover in place
		if ( isKeyPressed2 cstmControlStrafeLeft )
			let cstmHeading += 270
		elseif ( isKeyPressed2 cstmControlStrafeRight )
			let cstmHeading += 90
		else
			set cstmSpeed to 0 ; just hovering in place
		endif
		set cstmXVelocity to sin cstmHeading * cstmSpeed
		set cstmYVelocity to cos cstmHeading * cstmSpeed
		set cstmZVelocity to ( ( GetLocalGravity z ) / ( 21 + ( 1 / 3 ) ) ) * cstmSecondsPassed
	endif

	; player essentially "falls" to their new x,y,z coords
	Player.SetVelocity cstmXVelocity, cstmYVelocity, cstmZVelocity
	
End


Begin ScriptEffectFinish
End

Making This a Permanent Ability[edit | edit source]

Once the script is saved as a "Magic Effect" script-type, create a new Ability Spell. Set the Type of the spell to Ability. Then, add a new effect to this new ability spell. For this new effect, set the Range to Self, the Duration to 0, the Effect Type to Script Effect, the Script to cstmFlightScript, the Script Effect Name to something readable in-game like Flying, and click OK. You can then make this a PC Start spell, or add it as a default ability for any race.

Notes[edit | edit source]

  1. This script requires that the player be in the air in order to activate flying. In other words, the player must be jumping or falling before flying can be activated. This catch is necessary to not produce the same wall/ceiling clipping that the customary SetPos method does, and for initially adjusting player velocities. Though you can automate triggering a jump and activating flying if you wish. You could also SetPos 5 or so units in the air and fly from there, but the danger there is clipping in tight interior spaces.
  2. A player can fly over castle walls in exterior world spaces. Because they didn't enter the castle grounds through the front door, they'll be bewildered by how every building within the castle walls is nothing but a fake graphics placeholder. There are "Open Cities" mods out there that should correct that.
  3. Though modified heavily from the original code and using different procedural flow with new methods and solutions for flying controls and effects, some of the basic flight concepts of the above script were based on the flying script packaged with the "A Chingari and Ismelda Demon Race:Demon Race v3-0-3" mod found at the TESNexus site. (Note that the mod contains adult content, and cannot be linked to from this site. If you choose to find it by searching TES Nexus, you accept that you may be subject to said adult content.)
  4. For bugs, better equations, etc, see the Discussion page on this topic.