This paper was created by Marzo Sette Torres Junior, 2005-05-04.

SUMMARY
-------
	Intrinsic function 0x6E1 sets the position of the planets in the orrery. Proposed name is
	UI_set_orrery_state. It accepts two parameters: one is the location of planet Britannia
	(up to 24 units of distance) and the other is the orrery state, ranging from 0 to 9. Thus,
	the function declaration is along the lines of "UI_set_orrery_state(pos, orrery_state)".

	UI_set_orrery_state has the following properties (obtained from the original game):
		1) All duplicates of a planet that are at less than 15 units away are deleted
		  (There Can Be Only One! planet); conversely, all planets 15 or more units
		  away from planet Britannia are duplicated near it.
		2) The moons and the sun are left alone wherever they are.
		3) If planet Britannia is more than 24 units away from the place specified, an
		   error occurs. In all other cases, all planets are placed in their correct
		   relative positions relative to planet Britannia.

	I have compiled the offsets relative to planet Britannia of all normal values of the 2nd
	parameter (orrery_state); it is supplied in UCC form below.
	
THE FULL EXPLANATION
--------------------

In the original game, the position of the planets in the orrery (in Moonglow) was dependent on how
close you were to completing the game; it actually was dependent on which flags on a given set were
set to true, in a way that the planets would all be lined up at the very end. In Exult, this doesn't
happen because the required intrinsic function is not implemented. The function that updates the
orrery is function 0x63 (which I'll call UI_set_orrery_state), and is called by a single function
in the entire BG usecode: function 0x6E1. It is obvious from the usecode that UI_set_orrery_state
has two parameters: a 3D vector and an integer parameter.

Function 0x6E1 (which I'll call Orrery_Egg) is called from two places: one is an egg, the other is the
orrery viewer function 0x302 (which I'll call Orrery_Viewer). From the extracted usecode, one can see
that Orrery_Viewer calls Orrery_Egg in calle form with item = 0 and event = 3 (= egg). In UCC terms,
it is "event = 3; 0x0000->Orrery_Egg();" (there must be a "extern Orrery_Egg 0x6E1;" before the call).

In Orrery_Egg, there is a check to see if item = 0; if it is, then it creates a position vector with the
components [0x0B4C, 0x058C, 0x0000]. If item is not 0 (in which case it is the egg), Orrery_Egg calls
UI_get_object_position(item). In both cases, the resulting vector is the same: the orrery egg is located
at [0x0B4C, 0x058C, 0x0000], which is at the base of the "Britannia" planet in the orrery. This position
vector is passed to UI_set_orrery_state. Since UI_set_orrery_state requires a position vector, it is
only logical to assume that it sets the positions of the planets as offsets from this position. This is
actually the case here: the UI_set_orrery_state function is expecting to find the planet Britannia
(shape 765) at or near the specified position, and sets the position of all planets relative to planet
Britannia. This was determined with hack mover (!) and the orrery viewer. What I was able to determine
the properties stated above; for completness, here they are again:
	1) All duplicates of a planet that are at less than 15 units away are deleted; conversely, all
	   planets 15 or more units away from planet Britannia are duplicated near it.
	2) The moons and the sun are left alone wherever they are.
	3) If planet Britannia is more than 24 units away from the place specified, an error occurs. In
	   all other cases, all planets are placed in their correct relative positions relative to planet
	   Britannia.

The other parameter of UI_set_orrery_state a number calculated from a set of flags of the game, and
it ranges from 0 to 9 (the intrinsic *does* accept values higher than 9, but weird things happen... for
example, passing a 10 = 0xA results in a configuration were all planets are in the wrong orbits). I will
call this number orrery_state. Using rip/wud/wuc, I editted the usecode to see what were the effects of
changing this parameter. For the curious, I changed the "pushf flag:XXXX" commands by "pushi 0001H"
commands, one at a time and starting from the top. Since these two opcodes have the same byte length, I
didn't have to change anything else. In all cases, I took screenshots (I can send to anyone interested;
not that I suppose anyone will be, but the offer is here anyway :-)). For each of the screenshots, I
went to Exult and tried to reproduce (with the aid of Exult Studio) the positions of the planets. The
result is the table at the end of the file. The "frame" column indicates the planet, since they are all
the same shape. The table supplies the absolute position of the planets, not their relative positions;
but I am supplying here the offsets in UCC vector form:

	if (orrery_state == 0){
		abs_pos_X = [ 2,  3,  1,  6,  7, 8, -4,  9];
		abs_pos_Y = [-3, -3, -6, -2, -1, 1,  8, -2];}
	else if (orrery_state ==  1)
		abs_pos_X = [ 3,  4, -5, 3, 7, 4, -8, 8];
		abs_pos_Y = [-1, -1, -3, 6, 2, 7,  4, 5];}
	else if (orrery_state ==  2)
		abs_pos_X = [3, 3, -3, -5, 2, -2, -9, 2];
		abs_pos_Y = [1, 2,  4,  4, 7,  8,  1, 9];}
	else if (orrery_state ==  3)
		abs_pos_X = [1, 1, 4, -5, -4, -7, -9, -4];
		abs_pos_Y = [3, 4, 3, -3,  6,  4, -1,  9];}
	else if (orrery_state ==  4)
		abs_pos_X = [-2, -2,  5,  5, -7, -8, -8, -8];
		abs_pos_Y = [ 3,  4, -2, -4,  2,  1, -4,  6];}
	else if (orrery_state ==  5)
		abs_pos_X = [-4, -5, -5, 6, -7, -7, -7, -10];
		abs_pos_Y = [ 1,  1, -3, 3, -2, -4, -6,   1];}
	else if (orrery_state ==  6)
		abs_pos_X = [-4, -5, -3, -3, -6, -5, -7, -10];
		abs_pos_Y = [ 9, -1,  4,  6, -4, -6, -6,  -2];}
	else if (orrery_state ==  7)
		abs_pos_X = [-4, -4, 4, -6, -5, -3, -4, -8];
		abs_pos_Y = [ 8, -3, 3,  1, -5, -7, -8, -6];}
	else if (orrery_state ==  8)
		abs_pos_X = [-3, -3, -3,  6, -1,  0, -1, -5];
		abs_pos_Y = [ 7, -4, -5, -2, -7, -8, -9, -9];}
	else if (orrery_state ==  9)
		abs_pos_X = [0,  0,  1,  1,  1,  1,  1,  -1];
		abs_pos_Y = [6, -5, -6, -6, -7, -8, -9, -10];}

I suppose it can be easily converted to C++ for UI_set_orrery_state. With the above arrays, a loop would
suffice to set the position of all planets; for example, if orrery_state = 3, the [ X, Y ] offset for
the planet with frame 4 (the fifth planet) would be [ abs_pos_X[5], abs_pos_Y[5] ] = [ -4, 6 ] (the
index is [5] and not [4] because UCC arrays are 1-based).


Here is the position table I obtained by the methods outlined above; planet Britannia was at its default 
position in all cases:
|===============================================================================================|
|	orrery_state: 0	|	orrery_state: 1	|	orrery_state: 2	|	orrery_state: 3	|
|===============================================================================================|
|FRAME	X	Y	|	X	Y	|	X	Y	|	X	Y	|
|------------------------------------------------------------------------------------------------
|  0	2894	1417	|	2895	1419	|	2895	1421	|	2893	1423	|
|  1	2895	1417	|	2896	1419	|	2895	1422	|	2893	1424	|
|  2	2893	1414	|	2887	1417	|	2889	1424	|	2896	1423	|
|  3	2898	1418	|	2895	1426	|	2887	1424	|	2887	1417	|
|  4	2899	1419	|	2899	1422	|	2894	1427	|	2888	1426	|
|  5	2900	1421	|	2896	1427	|	2890	1428	|	2885	1424	|
|  6	2888	1428	|	2884	1424	|	2883	1421	|	2883	1419	|
|  7	2901	1418	|	2900	1425	|	2894	1429	|	2888	1429	|
|===============================================================================================|
|===============================================================================================|
|	orrery_state: 4	|	orrery_state: 5	|	orrery_state: 6	|	orrery_state: 7	|
|=======================|=======================================================================|
|FRAME	X	Y	|	X	Y	|	X	Y	|	X	Y	|
|-----------------------|------------------------------------------------------------------------
|  0	2890	1423	|	2888	1421	|	2888	1419	|	2888	1418	|
|  1	2890	1424	|	2887	1421	|	2887	1419	|	2888	1417	|
|  2	2897	1418	|	2887	1417	|	2889	1424	|	2896	1423	|
|  3	2897	1416	|	2898	1423	|	2889	1426	|	2886	1421	|
|  4	2885	1422	|	2885	1418	|	2886	1416	|	2887	1415	|
|  5	2884	1421	|	2885	1416	|	2887	1414	|	2889	1413	|
|  6	2884	1416	|	2885	1414	|	2885	1414	|	2888	1412	|
|  7	2884	1426	|	2882	1421	|	2882	1418	|	2884	1414	|
|===============================================================================================|
|===============================================|
|	orrery_state: 8	|	orrery_state: 9	|
|===============================================|
|FRAME	X	Y	|	X	Y	|
|-----------------------------------------------|
|  0	2889	1417	|	2892	1416	|
|  1	2889	1416	|	2892	1415	|
|  2	2889	1415	|	2893	1414	|
|  3	2898	1418	|	2893	1414	|
|  4	2891	1413	|	2893	1413	|
|  5	2892	1412	|	2893	1412	|
|  6	2891	1411	|	2893	1411	|
|  7	2887	1411	|	2891	1410	|
|===============================================|
