Function DeleteArrows()
	For a.Arrow = Each Arrow
		If a\state <> ARROW_INIT Then
			FreeEntity a\model : FreeEntity a\targetpivot : FreeEntity a\startpivot : Delete a : Return
		EndIf
	Next
End Function

Function UpdateArrow(a.Arrow)
	loc.Planet = archer\loc
	a\ticks = a\ticks + 1
	
	Select a\state
		Case ARROW_INIT
			startx# = EntityX(archer\arrow,True) : starty# = EntityY(archer\arrow,True) : startz# = EntityZ(archer\arrow,True)
			pitch# = EntityPitch(archer\arrow,True) : yaw# = EntityYaw(archer\arrow,True) : roll# = EntityRoll(archer\arrow,True)

			scale# = plrscl# * bowscl#
			If archer\loc <> Null Then
				scale# = archer\loc\radius# * plrscl# * bowscl#
			EndIf
				
			;Create the pivots
			a\startpivot = CreatePivot(archer\loc\moonpivot) : a\targetpivot = CreatePivot(a\startpivot);CopyEntity(g_planhigh, a\startpivot)
			PositionEntity a\startpivot,startx,starty,startz,True
			PositionEntity a\targetpivot,startx,starty,startz,True
			RotateEntity a\targetpivot,pitch,yaw,roll,True
			RotateEntity a\startpivot,pitch,yaw,roll,True
			
					;ScaleSprite a\targetpivot,sprdist/10,sprdist/10
			
			;Create a copy of the arrow
			a\model = CopyEntity(archer\arrow, a\startpivot)
			ScaleEntity a\model,scale#,scale#,scale#
			EntityFX a\model,1
			
			;EntityType a\model,TYPE_ARROW
			;EntityRadius a\model,10
			
			;Put it where the original arrow is
			PositionEntity a\model,startx,starty,startz,True
			RotateEntity a\model,pitch,yaw,roll,True
			
			;Set up sound effects
			twang = Load3DSound("sounds\circuit.mp3")
			EmitSound twang, a\model
			
			;Copy the flare sprite
			a\flare=CopyEntity(archer\arrowflare, a\model)
			PositionEntity a\flare,0,0,0
			PositionEntity a\flare,0,0,1
			ScaleSprite a\flare,0.5 * scale#,0.5 * scale#

			MoveEntity a\targetpivot,0,0,sprdist
			
			;Find the planet whose sprite is closest to the target
			aimed.Planet = Null : itsdist# = 0
			For p.Planet = Each Planet
				If p\sprite <> 0 Then
					sdist# = Abs(EntityDistance(a\targetpivot, p\sprite))
					DebugLog "dist from target pivot to " + p\name + "'s sprite is " + sdist
					If aimed = Null Then	; initial case
						aimed = p : itsdist# = sdist#
					ElseIf sdist < itsdist And p <> loc And SameSystem(p, loc) = False Then
						DebugLog p\name + "'s sprite is closer than " + aimed\name + "'s"
						aimed = p : itsdist# = sdist#
					EndIf
				EndIf
			Next
			
			;Also find the two planets that are actually closest
			;nearest.Planet = mercury : median.Planet = mercury
			;		If p\camdist < nearest\camdist Then
			;			DebugLog p\name + " is actually closer than " + nearest\name
			;			median = nearest : nearest = p
			;		ElseIf p\camdist < median\camdist Then
			;			DebugLog p\name + " is actually next closer than " + median\name
			;			median = p
			;		EndIf
			
			DebugLog "closest sprite is " + aimed\name + " at " + whereis(aimed\sprite)
			;DebugLog "closest planets are " + nearest\name + " and " + median\name
			DebugLog "target pivot is " + whereis(a\targetpivot)
			DebugLog "arrow starts at " + whereis(a\startpivot)
			DebugLog "arrow actually at " + whereis(a\model)
			
			;EntityParent g_planhigh,aimed\sprite
			;PositionEntity g_planhigh,0,0,0
			
			;Determine how long the arrow should live (actually twice this number)
			a\maxticks = 2 * c_gameRate		; seconds
			
			a\state = ARROW_ARC
			
		Case ARROW_ARC

			percentage# = (a\maxticks - a\ticks) / (a\maxticks)		;  1.0 to 0.0
			normz# 		= -1.0 + (2.0 * percentage)					; -1.0 to 1.0
			
			; desired flight path is y = 1/2x^2 + 1 from z= -1 to z= 1
			; this yields dx/dz = 0, dy/dz = z, dz/dz = 1  (pre-transformation)
			; total travel time should be half of the lifetime of the arrow
			
			dz# = sprdist / a\maxticks 			; arrow horizontal path
			dy# = normz * dz					; arrow vertical arc
			
			;x# = EntityX(a\model,True) : y# = EntityY(a\model,True) : z# = EntityZ(a\model,True)
			MoveEntity a\model, 0,dy/4,dz
			
			scale# = archer\loc\radius * plrscl * bowscl
			ScaleSprite a\flare,2*(3-percentage) * scale,2*(3-percentage) * scale
			
			If ArrowImpactFrom(a, loc) Then
				FreeEntity a\model : FreeEntity a\targetpivot : FreeEntity a\startpivot : Delete a : Return
			EndIf
			
			If a\ticks > a\maxticks Then
				a\ticks = a\maxticks
				a\state = ARROW_SPACE
			EndIf
		Case ARROW_SPACE
		
			If a\ticks > a\maxticks Then
				FreeEntity a\model : FreeEntity a\startpivot : Delete a : Return
			EndIf
			
			percentage# = (a\maxticks - a\ticks) / a\maxticks		; 1.0 to 0.0
			normz# 		= 2.0 - percentage							; 1.0 to 2.0
			
			; desired flight path is y = 1/2x^2 + 1 from z= -1 To z= 1
			; this yields dx/dz = 0, dy/dz = z, dz/dz = 1  (pre-transformation)
			; remaining travel time is half of the lifetime of the arrow
			
			dz# = sprdist / a\maxticks 			; arrow horizontal path
			dy# = -normz * dz					; arrow vertical arc
			
			MoveEntity a\model, 0,dy/4,dz
			
			If ArrowImpactFrom(a, loc) Then
				FreeEntity a\model : FreeEntity a\targetpivot : FreeEntity a\startpivot : Delete a : Return
			EndIf
			
			Return
			
			;UpdateFlare(cam, a\model, archer\model, 1)
			If a\ticks Mod 4 = 0 Then Return	; drop a glittery sprite
			
		Case ARROW_IMPACT
	
			FreeEntity a\model : FreeEntity a\targetpivot : FreeEntity a\startpivot : Delete a : Return
	End Select
End Function

Function ArrowImpactFrom(a.Arrow, from.Planet)
	hit.Planet = Null
	
	For p.Planet = Each Planet
		dist# = Abs(EntityDistance(a\model, p\model))
		If dist < p\radius Then
			hit = p
			Exit
		ElseIf p\sprite <> 0 And p <> from And SameSystem(p, from) = False Then
			sdist# = Abs(EntityDistance(a\model, p\sprite))
			If sdist < 5 Then
				hit = p
				Exit
			EndIf
		EndIf
	Next
	
	If hit = Null Then
		Return False
	Else
		CreateLink(from, hit)
		FlushKeys : FlushMouse
		Return True
	EndIf
End Function

; ==============================================================================