
#include "glover.h"

#ifdef CAMEO_DISPLAY
 #define CAMEO_PRINTF PRINTF
#else
 #define CAMEO_PRINTF
#endif

#if GOLDCD==NO

//	#define FAST_SPBOSS_CAMEO
//	#define FAST_CARNIVAL_CAMEO
//	#define FAST_PIRATES_CAMEO
#endif


#define EVILGLOVE_SPELL 0
#define EVILGLOVE_LAUGH 1
#define EVILGLOVE_VANISH 2
#define EVILGLOVE_SPELLLOOP 3
#define EVILGLOVE_SPELLEND 4
#define EVILGLOVE_IDLE 5
#define EVILGLOVE_LAUGHLOOP 6
// new, added by fred - the new obe's in my worlds\generic dir
#define EVILGLOVE_SPELLSTART 7
#define EVILGLOVE_FLY 8

typedef enum
{
	CAMEO_CAM_CLAIM,
	CAMEO_CAM_POS,
	CAMEO_CAM_TARGPOS,
	CAMEO_CAM_TARGNME,
	CAMEO_CAM_SPIN,
	CAMEO_CAM_HEIGHT,
	CAMEO_CAM_DRAG,

	CAMEO_NME_MOVETO,
	CAMEO_NME_FLYTO,
	CAMEO_NME_MOVEFORE,
	CAMEO_NME_ANIM,
	CAMEO_NME_JUDDER,
	CAMEO_NME_AIM,
	CAMEO_NME_SPIN,
	CAMEO_NME_DOING,

	CAMEO_NME_SCALE,
	CAMEO_NME_ACTIVATE,

	CAMEO_PLAT_MOVETO,

	CAMEO_FX_LIGHTNING,
	CAMEO_FX_FLASH,
	CAMEO_FX_STARRING,
	CAMEO_FX_LIFEGLOW,
	CAMEO_FX_FLAMETHROW,

	CAMEO_CA_SPRING,
	CAMEO_PI_MONKEY,
	CAMEO_SPELL,
	CAMEO_LEVELEND,

	CAMEO_SFX,

	CAMEO_FORCE_SIZE = 127
}CAMINSTR;

#define CAMEO_DONE_TIMER 32766

#define SET_INSTR_DONE(i) {(i)->timer = CAMEO_DONE_TIMER;}
#define IS_INSTR_DONE(i) ((i)->timer == CAMEO_DONE_TIMER)


typedef struct CAMEO_INST_GENTAG
{
	CAMINSTR type;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT values[8];

}CAMEO_INST_GEN;

typedef struct CAMEO_NME_MOVETOTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT x;
	SHORT y;
	SHORT z;
	SHORT speed;
}CAMEO_NME_MOVETOINST;
typedef struct CAMEO_NME_FLYTOTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT x;
	SHORT y;
	SHORT z;
	SHORT speed;
	SHORT info;
}CAMEO_NME_FLYTOINST;
typedef struct CAMEO_NME_MOVEFORETAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT speed;
}CAMEO_NME_MOVEFOREINST;
typedef struct CAMEO_NME_SPINTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT axis;
	SHORT speed;
}CAMEO_NME_SPININST;

typedef struct CAMEO_NME_ANIMTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT anim;
	SHORT loop;
	SHORT queue;
	SHORT speed;
}CAMEO_NME_ANIMINST;
typedef struct CAMEO_NME_JUDDERTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT anim;
	SHORT framestart;
	SHORT frameend;
}CAMEO_NME_JUDDERINST;
typedef struct CAMEO_NME_DOINGTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT doing;
}CAMEO_NME_DOINGINST;
typedef struct CAMEO_NME_ACTIVATETAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT active;
}CAMEO_NME_ACTIVATEINST;
typedef struct CAMEO_NME_SCALETAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT scale;
	SHORT speed;
}CAMEO_NME_SCALEINST;

typedef struct CAMEO_NME_AIMTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT tx;
	SHORT ty;
	SHORT tz;
	SHORT speed;
}CAMEO_NME_AIMINST;


typedef struct CAMEO_PLAT_MOVETOTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT tag;
	SHORT x;
	SHORT y;
	SHORT z;
	SHORT speed;
}CAMEO_PLAT_MOVETOINST;

typedef struct CAMEO_FX_LIGHTNINGTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT v1x;
	SHORT v1y;
	SHORT v1z;
	SHORT v2x;
	SHORT v2y;
	SHORT v2z;
// two spare, folks...
}CAMEO_FX_LIGHTNINGINST;
typedef struct CAMEO_FX_FLASHTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT r;
	SHORT g;
	SHORT b;
}CAMEO_FX_FLASHINST;
typedef struct CAMEO_FX_STARRINGTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
	SHORT n;
}CAMEO_FX_STARRINGINST;
typedef struct CAMEO_FX_FLAMETHROWTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
	SHORT direction;
}CAMEO_FX_FLAMETHROWINST;
typedef struct CAMEO_FX_LIFEGLOWTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
	SHORT rad;
	SHORT hei;
}CAMEO_FX_LIFEGLOWINST;


typedef struct CAMEO_CA_SPRINGTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
}CAMEO_CA_SPRINGINST;

typedef struct CAMEO_SPELLTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT src_tag;
	SHORT dest_tag;
	SHORT type;
}CAMEO_SPELLINST;


typedef struct CAMEO_CAM_TARGNMETAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
	SHORT speed;
}CAMEO_CAM_TARGNMEINST;

typedef struct CAMEO_CAM_TARGPOSTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
	SHORT speed;
}CAMEO_CAM_TARGPOSINST;
typedef struct CAMEO_CAM_POSTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT x;
	SHORT y;
	SHORT z;
	SHORT speed;
}CAMEO_CAM_POSINST;
typedef struct CAMEO_CAM_CLAIMTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

}CAMEO_CAM_CLAIMINST;
typedef struct CAMEO_CAM_DRAGTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT min;
	SHORT max;
	SHORT y_add;
	SHORT speed;

}CAMEO_CAM_DRAGINST;
typedef struct CAMEO_CAM_SPINTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT spin;
	SHORT range;
	SHORT speed;
}CAMEO_CAM_SPININST;
typedef struct CAMEO_CAM_HEIGHTTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT y;
	SHORT speed;
}CAMEO_CAM_HEIGHTINST;

typedef struct CAMEO_PI_MONKEYTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;
}CAMEO_PI_MONKEYINST;


typedef struct CAMEOTAG
{
	struct CAMEOTAG *next;
	int timer;
	int num_instrs;
	CAMEO_INST_GEN *instrs;
}CAMEO;

typedef struct CAMEO_SFXTAG
{
	CAMINSTR inst;

	SHORT start;
	SHORT duration;
	SHORT timer;

	SHORT nme;	// non-zero to use nme pos
	SHORT bank;
	SHORT sfx;
	SHORT interval;
}CAMEO_SFXINST;



// 0's the dino
// 1's the evil glove
// and there's a tagged platform for the iceblock

// top of slope's (-272,  7,-143)
// bot of slope's (-263,327, 816)

//#define PREH_CAM_LEN 260
//#define PREH_VANISH_T 200
//#define PREH_FREE_T  150
#define PREH_CAM_LEN 300
#define PREH_VANISH_T 240
#define PREH_FREE_T  190
#define PREH_SPELL_T 80

CAMEO_INST_GEN cameo_prehist_insts[] =
{

//	{CAMEO_CAM_POS,			  0,1,0,	{300, -250, 300, -1}},
	{CAMEO_CAM_CLAIM,		  0,PREH_CAM_LEN,0},

// permanant overview camera
//	{CAMEO_CAM_POS,			  0,1,0,	{-60,  50,300, -1}},
//	{CAMEO_CAM_TARGPOS,		  1,40,0,   {-263,280,650, -1}},

	{CAMEO_CAM_POS,			  0,1,0,	{-280,  40,270, -1}},
	{CAMEO_CAM_POS,			  1,50,0,	{-600,  50,500, 8}},


// camera sequence. 1/8 turn from front to dino's right quarter
// pull back in time for glove's arrival. wait for cameo end
// pull towards startpoint
	{CAMEO_CAM_TARGPOS,		  0,30,0,   {-263,180,816, -1}},
	{CAMEO_CAM_TARGPOS,		  30,PREH_VANISH_T-30,0,   {-263,180,700, 4}},

	
	{CAMEO_CAM_POS,			  PREH_VANISH_T,PREH_CAM_LEN - PREH_VANISH_T,0,   {-500,-100,0, 8}},
	{CAMEO_CAM_TARGPOS,		  PREH_VANISH_T,PREH_CAM_LEN - PREH_VANISH_T,0,   {-263,0,-50, 12}},

// dinosaur
	{CAMEO_NME_MOVETO,		  0,1,0,	{11,	-263,218,816, -1}},	// note, his centre ain't at his feet
	{CAMEO_NME_ANIM,		  0,1,0,	{11, NMEANIM_IDLE,0,0,0}},	// zero speed. ie, it's static...
	{CAMEO_NME_ANIM,		  PREH_FREE_T,1,0,	{11, NMEANIM_IDLE,0,0,4096}},	// set him animating

// melting iceblock platform ( ? switch so it works as an object ? )
// (don't start moving until the gloves actually in the casting bit of its anim)

//	{CAMEO_PLAT_MOVETO,		  0,1,0,	{1,	-200,150,816, -1}},
//	{CAMEO_PLAT_MOVETO,		  PREH_SPELL_T+25,PREH_FREE_T - PREH_SPELL_T-25,0,	{1,	-200,350,816, 4}},

	{CAMEO_PLAT_MOVETO,		  0,1,0,	{1,	-260,180,790, -1}},
	{CAMEO_PLAT_MOVETO,		  PREH_SPELL_T+25,PREH_FREE_T - PREH_SPELL_T-25,0,	{1,	-260,500,790, 4}},

	{CAMEO_NME_ACTIVATE,	  PREH_FREE_T,1,0,	{1,0}},
// at preh_free_t, de-activate the iceblock

// flame emission stops a tad short of free time...
	{CAMEO_FX_FLAMETHROW,	  PREH_SPELL_T+20,PREH_FREE_T - PREH_SPELL_T-40,0,	{-263,218,620,0}},
	{CAMEO_SFX,				  PREH_SPELL_T+20,PREH_FREE_T - PREH_SPELL_T-40,0,	{12,0,SFX_GE_CRUMPET_ATTACK,8}},
// evil-glove-tastic...
// appears, idles, laughs...
	{CAMEO_NME_ACTIVATE,	  0,1,0,	{12,0}},
	{CAMEO_NME_MOVETO,		  0,1,0,	{12,	-263,218,600, -1}},
	{CAMEO_NME_AIM,			  0,70,0,	{12, -263,218,800, -1}},

	{CAMEO_FX_STARRING,		  30,1,0,	{-263,210,600, 7}},
	{CAMEO_NME_ACTIVATE,	  30,1,0,	{12,1}},
	{CAMEO_NME_ANIM,		  30,1,0,	{12, EVILGLOVE_IDLE,1,0,4096}},	// loop,queue
	{CAMEO_SFX,				  30,1,0,   {12,0,SFX_CAST_SPELL_4,0}},		// appears in a star-ring


	{CAMEO_NME_ANIM,		  50,1,0,	{12, EVILGLOVE_LAUGH,0,0,4096}},
	{CAMEO_NME_ANIM,		  50,1,0,	{12, EVILGLOVE_IDLE,1,1,4096}},

	{CAMEO_SFX,				  50+20, 1,0,	{12,0,SFX_GE_BADGLOVE_LAUGH,0}},

// ...spends a long time casting fire at the iceblock...
	{CAMEO_NME_ANIM,		  PREH_SPELL_T,1,0,	{12, EVILGLOVE_SPELLSTART,0,0,4096}},
	{CAMEO_NME_ANIM,		  PREH_SPELL_T,1,0,	{12, EVILGLOVE_SPELLLOOP,1,1,4096}},
// (he wants to loop in it for a while...)
	{CAMEO_NME_ANIM,		  PREH_FREE_T,1,0,	{12, EVILGLOVE_SPELLEND,0,0,4096}},
	{CAMEO_NME_ANIM,		  PREH_FREE_T,1,0,	{12, EVILGLOVE_LAUGH,0,1,4096}},
	{CAMEO_SFX,				  PREH_FREE_T+20,1,0,	{12,0,SFX_GE_BADGLOVE_LAUGH,0}},
	{CAMEO_NME_ANIM,		  PREH_FREE_T,1,0,	{12, EVILGLOVE_IDLE, 1,1,4096}},	// loop,queue

// glove prepares to vanish
	{CAMEO_NME_ANIM,		  PREH_VANISH_T - 20,12,0,	{12, EVILGLOVE_VANISH,0,0,4096}},
	{CAMEO_FX_LIFEGLOW,		  PREH_VANISH_T - 20,30,0,	{-263,210,600, 25,15}},

	{CAMEO_SFX,				  PREH_VANISH_T-20, 1,0, {12,0,SFX_CAST_SPELL_3,0}},
	{CAMEO_SFX,				  PREH_VANISH_T-1, 1,0,  {12,0,SFX_HAND_FINGERCLICK,0}},

// glove vanishes
	{CAMEO_FX_FLASH,		  PREH_VANISH_T-1,20,0,	{255,200,80}},
	{CAMEO_NME_ACTIVATE,	  PREH_VANISH_T,1,0,	{12,0}},

};


CAMEO cameo_prehist =
{
	NULL,
	0,
	sizeof(cameo_prehist_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_prehist_insts[0]
};


// positions... (invert y & z)
// 0 = ENEMY KLOSET 0 50 200 0 3
// 1 = ENEMY EVIL_GLOVE 0 49 -8 0 0
// 2 = jackbox.psa 0 40 0 


#define CARN_CAM_LEN 280
#define CARN_SPROING_T 80
#define CARN_SPELL_T 180
#define CARN_VANISH_T 240
CAMEO_INST_GEN cameo_carnival_insts[] =
{
#ifdef FAST_CARNIVAL_CAMEO
	{CAMEO_NME_ACTIVATE,	  0,1,0,	{1,0}},
	{CAMEO_NME_ACTIVATE,	  0,1,0,	{300,0}},
//	{CAMEO_NME_ACTIVATE,	  0,1,0,	{301,0}},
	{CAMEO_NME_SCALE,		  0,1,0,	{10,256,-1}},
	{CAMEO_NME_AIM,			  0,1,0,	{10, 0,0,0, -1}}
#else

//	{CAMEO_NME_ACTIVATE,	  0,1,0,	{301,0}},	// disable the nose

// Evil glove:-

	{CAMEO_NME_ACTIVATE,	  0,1,0,	{1,0}},	// glove starts disabled
// Jackbox plays anim:-
	{CAMEO_NME_ANIM,		   0,1,0,	{300, 0,0,0,4096}},	// no loop, no queue, 96-frame animation (it's a bloody cameo obj, & doesn't have a tag)


// sproing! ... enter the glove & the spring


	{CAMEO_NME_AIM,			  0,10,0,	    {1, -100,0,-100, -1}},
	{CAMEO_NME_AIM,			  0,10,0,	    {300, -100,0,-100, -1}},

	{CAMEO_NME_ACTIVATE,	  CARN_SPROING_T,1,0,	{1,1}},
	{CAMEO_CA_SPRING,		  CARN_SPROING_T,CARN_VANISH_T-90,0,	{0,-10,0}},

	{CAMEO_NME_ANIM,		  CARN_SPROING_T,1,0,	{1, EVILGLOVE_LAUGH,1,0,4096}},
	{CAMEO_SFX,				  CARN_SPROING_T+20,1,0,	{1,0,SFX_GE_BADGLOVE_LAUGH,0}},


	{CAMEO_NME_ANIM,		  CARN_SPELL_T,1,0,	{1, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  CARN_SPELL_T,1,0,	{1, EVILGLOVE_IDLE,1,1,4096}},
	

// glove prepares to vanish
	{CAMEO_NME_ANIM,		  CARN_VANISH_T - 20,1,0,	{1, EVILGLOVE_VANISH,0,0,4096}},
	{CAMEO_FX_LIFEGLOW,		  CARN_VANISH_T - 20,30,0,	{0,-49,8,25,15}},

// glove (& box, & spring) vanishes
	{CAMEO_FX_FLASH,		  CARN_VANISH_T-1,20,0,	{255,200,80}},
	{CAMEO_NME_ACTIVATE,	  CARN_VANISH_T,1,0,	{1,0}},
	{CAMEO_NME_ACTIVATE,	  CARN_VANISH_T,1,0,	{300,0}},

	{CAMEO_SFX,				  CARN_SPELL_T+20, 1,0, {1,0,SFX_CAST_SPELL_2,0}},
	{CAMEO_SFX,				  CARN_VANISH_T-20, 1,0, {1,0,SFX_CAST_SPELL_3,0}},
	{CAMEO_SFX,				  CARN_VANISH_T-1, 1,0, {1,0,SFX_HAND_FINGERCLICK,0}},

	{CAMEO_CAM_CLAIM,		  0,CARN_CAM_LEN,0},

// permanant overview camera
//	{CAMEO_CAM_POS,			  0,1,0,	{250, -200, 250, -1}},
//	{CAMEO_CAM_TARGPOS,		  1,40,0,   {0,-25,-100, -1}},

	{CAMEO_CAM_POS,			  0,1,0,   {-100, -50, 100, -1}},
	{CAMEO_CAM_TARGPOS,		  0,1,0,   {0,-10,0, -1}},

	{CAMEO_SPELL,			  CARN_SPELL_T+20,1,0, {1,10,SPELL_CARNIVAL_CAMEO}},


	{CAMEO_CAM_SPIN,		  10,CARN_SPROING_T-10+1,0,	{-16,280, 2}},	// spin,range,speed
	{CAMEO_CAM_HEIGHT,		  10,CARN_SPROING_T-10+1,0,	{ -100, 1}},

	{CAMEO_CAM_TARGPOS,		  10,CARN_SPROING_T -10+1,0,   {0, -80, 0, 1}},

	{CAMEO_CAM_SPIN,		  CARN_SPROING_T,CARN_SPELL_T-CARN_SPROING_T+1,0,	{-16,280, 2}},	// spin,range,speed
	{CAMEO_CAM_HEIGHT,		  CARN_SPROING_T,CARN_SPELL_T-CARN_SPROING_T+1,0,	{ -200, 1}},

	{CAMEO_CAM_TARGPOS,		  CARN_SPROING_T+70,CARN_SPELL_T-(CARN_SPROING_T+70),0,   {-100,-25,-100, 2}},


// Kloset:-
// wait (NO ANIM), scaleup, wait, start animating
	{CAMEO_NME_MOVETO,		  0,1,0,		{10,	-130,-35,-130, -1}},	// stand on the floor when small
	{CAMEO_NME_AIM,			  0,70,0,	    {10, 0,0,0, -1}},
	{CAMEO_NME_SCALE,		  0,1,0,		{10,64,-1}},
	{CAMEO_NME_ANIM,		  0,1,0,		{10,	NMEANIM_IDLE,1,0,0}},	// loop,queue, zero speed

	{CAMEO_NME_ANIM,		  CARN_SPELL_T+40,1,0,		{10,	NMEANIM_IDLE,1,0,4096}},	// starts animating

	{CAMEO_NME_MOVETO,		  CARN_SPELL_T+40,CARN_CAM_LEN - (CARN_SPELL_T+40),0,	{10,	-130,-50,-130, 3}},
	{CAMEO_NME_SCALE,		  CARN_SPELL_T+40,CARN_CAM_LEN - (CARN_SPELL_T+40),0,	{10,256,5}}

#endif
};



CAMEO cameo_carnival =
{
	NULL,
	0,
	sizeof(cameo_carnival_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_carnival_insts[0]
};



CAMEO_INST_GEN cameo_atlantis_insts[] =
{
// Boss enemies appearing in sequence:-
	{CAMEO_NME_ACTIVATE,	 0,1,0,		{10,	0}},
	{CAMEO_NME_ACTIVATE,	 0,1,0,		{11,	0}},
	{CAMEO_NME_ACTIVATE,	 0,1,0,		{12,	0}},
	{CAMEO_NME_ACTIVATE,	 80,1,0,	{10,	1}},
	{CAMEO_NME_ACTIVATE,	120,1,0,	{11,	1}},
	{CAMEO_NME_ACTIVATE,    160,1,0,	{12,	1}},

// Lightning & star-rings at impact point
	{CAMEO_FX_LIGHTNING,	 70,10,0,	{-120,-5,-120, 0,-36,0}},
	{CAMEO_FX_LIGHTNING,	110,10,0,	{-120,-5,-120, 0,-84,0}},
	{CAMEO_FX_LIGHTNING,	150,10,0,	{-120,-5,-120, 0,-110,0}},

	{CAMEO_SFX,				 65,20,0,	{3,1,SFX_AT_FRANKIE_ATTACK_LOOPED,8}},
	{CAMEO_SFX,				105,20,0,	{3,1,SFX_AT_FRANKIE_ATTACK_LOOPED,8}},
	{CAMEO_SFX,				145,20,0,	{3,1,SFX_AT_FRANKIE_ATTACK_LOOPED,8}},

	{CAMEO_FX_STARRING,		 70,1,0,	{0,-36,0,	7}},
	{CAMEO_FX_STARRING,		110,1,0,	{0,-84,0,	7}},
	{CAMEO_FX_STARRING,		150,1,0,	{0,-110,0,	7}},

// Screen flashes
	{CAMEO_FX_FLASH,		 75,10,0,	{255,255,255}},
	{CAMEO_FX_FLASH,		 80,20,0,	{100,255,255}},

	{CAMEO_FX_FLASH,		115,10,0,	{255,255,255}},
	{CAMEO_FX_FLASH,		120,20,0,	{255,100,100}},

	{CAMEO_FX_FLASH,		155,10,0,	{255,255,255}},
	{CAMEO_FX_FLASH,		160,20,0,	{255,255,100}},

// evil glove anims:-
// (hohoho, three spell-casts, hohoho, vanish)
	{CAMEO_NME_ANIM,		   0,1,0,	{3, EVILGLOVE_LAUGH,1,0,4096}},
	{CAMEO_SFX,				   20,1,0,	{3,0,SFX_GE_BADGLOVE_LAUGH,0}},


// tbd - turn & aim at the boss...
	{CAMEO_NME_AIM,			   0,70,0,	{3, 0,-36,0, 32}},

	{CAMEO_NME_ANIM,		   50,1,0,	{3, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		   50,1,0,	{3, EVILGLOVE_IDLE,1,1,4096}},



	{CAMEO_NME_ANIM,		  90,1,0,	{3, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  90,1,0,	{3, EVILGLOVE_IDLE,1,1,4096}},


	{CAMEO_NME_ANIM,		  130,1,0,	{3, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  130,1,0,	{3, EVILGLOVE_IDLE,1,1,4096}},



	{CAMEO_NME_ANIM,		  200,1,0,	{3, EVILGLOVE_VANISH,0,0,4096}},

//	{CAMEO_NME_MOVETO,		  220,1,0,	{3,	0,3000,0, -1}},
	{CAMEO_NME_ACTIVATE,	  220,1,0,		{3,	0}},

	{CAMEO_FX_FLASH,		  219,20,0,	{255,200,80}},
	{CAMEO_FX_LIFEGLOW,		  200,30,0,	{-120,-5,-120,25,15}},

	{CAMEO_SFX,				  200, 1,0, {3,0,SFX_CAST_SPELL_3,0}},
	{CAMEO_SFX,				  219, 1,0, {3,0,SFX_HAND_FINGERCLICK,0}},

// camera

// evilglove is at -120 5 120
	{CAMEO_CAM_CLAIM,		  0,280,0},
//	{CAMEO_CAM_POS,			  0,3,0,	{0,-110,-500, -1}},
	{CAMEO_CAM_POS,			  0,3,0,	{-120+150,-110,-120, -1}},

//	{CAMEO_CAM_SPIN,		  0,60,0,	{16,300, 3}},	// spin,range,speed
	{CAMEO_CAM_SPIN,		  1,60,0,	{16,150, 10}},	// spin,range,speed
	{CAMEO_CAM_TARGNME,		  0,60,0,   {3, -1}},		// target the evilglove

	{CAMEO_CAM_SPIN,		 60,180,0,	{16,450, 3}},
	{CAMEO_CAM_TARGPOS,		 60,180,0,	{0,-30,0, 3}},


// hoop   POS  -431.820038 55.148422 -2.324539

	{CAMEO_CAM_TARGNME,		 240,20,0,  {-1, 20}},		// target the goodglove
	{CAMEO_CAM_POS,			 240,20,0,	{-300,-110,0, 20}},

//	{CAMEO_CAM_SPIN,		 220,40,0,	{16,250, 3}}

};


CAMEO cameo_atlantis =
{
	NULL,
	0,
	sizeof(cameo_atlantis_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_atlantis_insts[0]
//	36,&cameo_atlantis_insts[0]
};

// ======================================================================================

#define FEAR_HOHOHO_TIME (100+100)

#define FEAR_SPELL_TIME (150+100)
#define FEAR_PLAT_TIME  (300+100)

#define FEAR_BYEBYE_TIME (220+100)

#define FEAR_CAMEO_TIME (400+100)

CAMEO_INST_GEN cameo_fear_insts[] =
{
// Frankie animations

	{CAMEO_NME_AIM,			  0,1,0,	{12, 0,0,400, -1}},	// face away from the evil glove

	{CAMEO_NME_ANIM,		  0,1,0,	{12, NMEANIM_IDLE,			1,0,4096}},

	{CAMEO_NME_ANIM,		 FEAR_SPELL_TIME+35,1,0,	{12, NMEANIM_SPECIAL1,		0,0,4096}},	// reanimated by lightening
	{CAMEO_NME_ANIM,		 FEAR_SPELL_TIME+35,1,0,	{12, NMEANIM_RUN,			1,1,4096}},	// walks with lightening

//	{CAMEO_NME_MOVETO,		 FEAR_SPELL_TIME+40,40,0,	{12, 0,-40,-400, 2}},	// walks to the platform
	{CAMEO_NME_AIM,			 FEAR_SPELL_TIME+40,100,0,	{12, 0,-43,-215, 60}},
/*	{CAMEO_NME_MOVEFORE,	 FEAR_SPELL_TIME+40,100,0,	{12, 3}},		// walks to the platform */
	{CAMEO_NME_MOVEFORE,	 FEAR_SPELL_TIME+40,60,0,	{12, 3}},		// walks to the platform

	{CAMEO_SFX,				 FEAR_PLAT_TIME, 40,0,  {0,1,SFX_FRANKIE_ATTACK_LOOPED,8}},


	{CAMEO_NME_ANIM,		 FEAR_PLAT_TIME,1,0,		{12, NMEANIM_STARTATTACK,	0,1,4096}},	// grabs platform
	{CAMEO_NME_ANIM,		 FEAR_PLAT_TIME,1,0,		{12, NMEANIM_ACTION1,		1,1,4096}},	// holds platform

	{CAMEO_NME_ANIM,		 FEAR_PLAT_TIME+60,1,0,		{12, NMEANIM_ENDATTACK,		0,1,4096}},	// lets go
	{CAMEO_NME_ANIM,		 FEAR_PLAT_TIME+60,1,0,		{12, NMEANIM_WALK,			1,1,4096}},	// plods around

	{CAMEO_NME_AIM,			 FEAR_PLAT_TIME+60,50,0,	{12, 0,-43,0, 40}},
//	{CAMEO_NME_MOVETO,		 FEAR_PLAT_TIME+65,40,0,	{12, 0,-40,0, 2}},	// walks back to the middle
	{CAMEO_NME_MOVEFORE,	 FEAR_PLAT_TIME+70,40,0,	{12, 3}},	// walks back to the middle
	


// lightning

// from the evilglove upwards
/*	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+20,15,0,	{ 0,-413,-421,  0,-600,0}}, */
	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+20,15,0,	{ 0,-313,-313,  0,-600,0}}, 

	{CAMEO_SFX,				FEAR_SPELL_TIME+20, 15,0,  {0,1,SFX_FRANKIE_ATTACK_LOOPED,8}},

// from the sky down to frank

	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+35,20,0,	{    0,-600,-200,  0,0,0}},
	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+35,20,0,	{    0,-600, 200,  0,0,0}},
	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+35,20,0,	{ -200,-600,   0,  0,0,0}},
	{CAMEO_FX_LIGHTNING,	FEAR_SPELL_TIME+35,20,0,	{  200,-600,   0,  0,0,0}},

	{CAMEO_SFX,				FEAR_SPELL_TIME+35, 20,0,  {0,1,SFX_FRANKIE_ATTACK_LOOPED,8}},

	{CAMEO_FX_STARRING,		FEAR_SPELL_TIME+35,1,0,	{0,-50,0,	7}},
	{CAMEO_FX_STARRING,		FEAR_SPELL_TIME+42,1,0,	{0,-50,0,	7}},
	{CAMEO_FX_STARRING,		FEAR_SPELL_TIME+50,1,0,	{0,-50,0,	7}},

// Screen flashes
	{CAMEO_FX_FLASH,		 FEAR_HOHOHO_TIME+0,5,0,	{255,255,255}},
	{CAMEO_FX_FLASH,		 FEAR_HOHOHO_TIME+10,5,0,	{255,255,255}},

	{CAMEO_FX_FLASH,		 FEAR_SPELL_TIME+20,5,0,	{128,255,255}},
	{CAMEO_FX_FLASH,		 FEAR_SPELL_TIME+35,5,0,	{64,255,255}},

	{CAMEO_SFX,				FEAR_HOHOHO_TIME+0, 1,0,  {0,1,SFX_THUNDER,0}},
	{CAMEO_SFX,				FEAR_HOHOHO_TIME+10, 1,0,  {0,1,SFX_THUNDER,0}},
	{CAMEO_SFX,				FEAR_SPELL_TIME+20, 1,0,  {0,1,SFX_THUNDER,0}},
	{CAMEO_SFX,				FEAR_SPELL_TIME+35, 1,0,  {0,1,SFX_THUNDER,0}},


// evil glove anims:-
// (hohoho, spell-casts, hohoho, vanish)
	{CAMEO_NME_AIM,			  0,1,0,	{13, 0,0,0, -1}},
	{CAMEO_NME_ANIM,		  0,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},
	{CAMEO_NME_ANIM,		  FEAR_HOHOHO_TIME,1,0,	{13, EVILGLOVE_LAUGH,1,0,4096}},
	{CAMEO_SFX,				  FEAR_HOHOHO_TIME+20,1,0,	{13,0,SFX_GE_BADGLOVE_LAUGH,0}},


	{CAMEO_NME_ANIM,		  FEAR_SPELL_TIME,1,0,	{13, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  FEAR_SPELL_TIME,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},

	{CAMEO_NME_ANIM,		  FEAR_BYEBYE_TIME,1,0,	{13, EVILGLOVE_VANISH,0,0,4096}},

	{CAMEO_NME_ACTIVATE,	  FEAR_BYEBYE_TIME+20,1,0,	{13,	0}},

	{CAMEO_FX_FLASH,		  FEAR_BYEBYE_TIME+19,20,0,	{255,200,80}},
	{CAMEO_FX_LIFEGLOW,		  FEAR_BYEBYE_TIME,30,0,	{-120,-5,-120,25,15}},

	{CAMEO_SFX,				  FEAR_BYEBYE_TIME,    1,0, {13,0,SFX_CAST_SPELL_3,0}},
	{CAMEO_SFX,				  FEAR_BYEBYE_TIME+19, 1,0, {13,0,SFX_HAND_FINGERCLICK,0}},


// Camera work

// Starts above frankie, spins to upwards "ain't he big" shot
	{CAMEO_CAM_CLAIM,		  0,FEAR_CAMEO_TIME + 10,0},

/*	{CAMEO_CAM_POS,			  0,3,0,	{   0,-110,-250, -1}}, */
	{CAMEO_CAM_POS,			  0,3,0,	{   0,-110, 250, -1}}, 
	{CAMEO_CAM_TARGPOS,		  0,3,0,	{   0, -50,0, -1}},

	{CAMEO_CAM_HEIGHT,		  3,FEAR_HOHOHO_TIME-43,0,	{ -20, 1}},
	{CAMEO_CAM_TARGPOS,		  3,FEAR_HOHOHO_TIME-43,0,	{   0, -60,0, 1}},
	{CAMEO_CAM_SPIN,		  3,FEAR_HOHOHO_TIME-43,0,	{26,130, 1}},



// zip, up to the glove who's going "hohoho" looking down.

//	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME-40,80,0,	{0,-402,-360, 20}},	// below & in front of the evilglove
	{CAMEO_CAM_TARGNME,		 FEAR_HOHOHO_TIME-40,30,0,	{13, 10}},		// target the evilglove

	
	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME-40,30,0,	{0,-60,115, 2}},	// move upwards a bit

	/*	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME-10,50,0,	{0,-402,-360, -1}},	// below & in front of the evilglove */
	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME-10,50,0,	{0,-302,-260, -1}},	// below & in front of the evilglove
	{CAMEO_CAM_TARGNME,		 FEAR_HOHOHO_TIME-10,50,0,	{13, -1}},		// target the evilglove
//	{CAMEO_CAM_TARGPOS,		 60,20,0,	{   0,-413,0, -1}},

// switch round so we can see evilglove, ballbutton, and frankie
// (this is just before the glove chucks his lightening around)
/*	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME+40,1,0,	{0,-550,-490, -1}},	// above & behindthe evilglove */
	{CAMEO_CAM_POS,			 FEAR_HOHOHO_TIME+40,1,0,	{0,-450,-390, -1}},	// above & behindthe evilglove 
	{CAMEO_CAM_TARGNME,		 FEAR_HOHOHO_TIME+40,1,0,	{12, -1}},			// targeted on Frankie

// sit the camera on the lowest of the moving platforms, looking at frank

/*	{CAMEO_CAM_POS,			 FEAR_PLAT_TIME-40,1,0,	{0,-100,-490, -1}}, */
	{CAMEO_CAM_POS,			 FEAR_PLAT_TIME-40,1,0,	{0,-120,-320, -1}}, 
//	{CAMEO_CAM_POS,			 FEAR_CAMEO_TIME-40,40,0,	{0,-400,-320, 2}}, 
	{CAMEO_CAM_POS,			 FEAR_CAMEO_TIME-40,40+10,0,	{196,-353,98, 8}}, 
	{CAMEO_CAM_TARGPOS,		 FEAR_CAMEO_TIME-40,40+10,0,	{-129,187,-62, 8}},


};



CAMEO cameo_fear =
{
	NULL,
	0,
	sizeof(cameo_fear_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_fear_insts[0]
};

// ======================================================================================

#define PI_SPELL1_T		 50
#define PI_SPELL2_T		100
#define PI_PANP_T		140
#define PI_PANT_T		160
#define PI_SPELL3_T		200

#define PI_VANISH_T		300
#define PI_CAM_LEN		330

#define FROG_Y			85
#define MONKEY_Y		60

CAMEO_INST_GEN cameo_pirates_insts[] =
{
#ifdef FAST_PIRATES_CAMEO
	{CAMEO_NME_ACTIVATE,	  0,1,0,	 {13,0}},

//	{CAMEO_PI_MONKEY,		  0,2,0,	{11}},
//	{CAMEO_NME_DOING,		  0,2,0,	{11,0}},
//	{CAMEO_NME_MOVETO,		  0,2,0,	{11,  33,MONKEY_Y,-150, -1}},
	{CAMEO_PI_MONKEY,		  0,2,0,	{12}},
	{CAMEO_NME_DOING,		  0,2,0,	{12,0}},
	{CAMEO_NME_MOVETO,		  0,2,0,	{12, 133,MONKEY_Y,-150, -1}},

	{CAMEO_NME_MOVETO,		  0,2,0,	{10,  20, 60,30, -1}},
	{CAMEO_NME_SCALE,		  0,2,0,	{10,400,-1}},

#else




// Frogs
//	{CAMEO_NME_MOVETO,		  0,10,0,			{11,  33,FROG_Y,-150, -1}},
	{CAMEO_NME_MOVETO,		  0,10,0,			{12, 133,FROG_Y,-150, -1}},
	
	
//	{CAMEO_NME_MOVETO,		  PI_SPELL1_T+35,10,0,	{11,  33,MONKEY_Y,-150, -1}},
//	{CAMEO_PI_MONKEY,		  PI_SPELL1_T+35,20,0,	{11}},
//	{CAMEO_NME_DOING,		  PI_SPELL1_T+35, 1,0,	{11,0}},


// This lot is now done by the spell-impact routine
//	{CAMEO_NME_MOVETO,		  PI_SPELL2_T+35,10,0,	{12, 133,MONKEY_Y,-150, -1}},
//	{CAMEO_PI_MONKEY,		  PI_SPELL2_T+35,20,0,	{12}},
//	{CAMEO_SFX,				  PI_SPELL2_T+35, 1,0, {13,0,SFX_CAST_SPELL_5,0}},
//	{CAMEO_NME_DOING,		  PI_SPELL2_T+35, 1,0,	{12,0}},
//	{CAMEO_FX_FLASH,		  PI_SPELL2_T+35,20,0,	{0,255,0}},


//	{CAMEO_FX_FLASH,		  PI_SPELL1_T+35,20,0,	{0,255,0}},
	{CAMEO_FX_FLASH,		  PI_SPELL3_T+60,20,0,	{0,255,255}},

// spank
	{CAMEO_NME_MOVETO,		  0,10,0,				{10, 20,-5,30, -1}},
	{CAMEO_NME_SCALE,		  0,1,0,				{10,64,-1}},
	{CAMEO_NME_MOVETO,		  PI_SPELL3_T+60,100,0,	{10, 20,60,30, 2}},
	{CAMEO_NME_SCALE,		  PI_SPELL3_T+60,100,0,	{10,400,10}},
	{CAMEO_SFX,				  PI_SPELL3_T+60, 1,0, {13,0,SFX_CAST_SPELL_4,0}},


// evil glove:-
	{CAMEO_NME_MOVETO,		  0,10,0,			{13, 122,77,-320, -1}},
	{CAMEO_NME_AIM,			  0,10,0,			{13, 122,77, 100, -1}},
	{CAMEO_NME_ANIM,		  0,1,0,			{13, EVILGLOVE_IDLE,1,0,4096}},


// (hohoho, two spell-casts, hohoho, vanish)
//	{CAMEO_NME_ANIM,		  PI_SPELL1_T,1,0,	{13, EVILGLOVE_SPELL,0,0,4096}},
//	{CAMEO_NME_ANIM,		  PI_SPELL1_T,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},
	{CAMEO_NME_ANIM,		  PI_SPELL1_T,1,0,	{13, EVILGLOVE_LAUGH,0,1,4096}},
	{CAMEO_SFX,				  PI_SPELL1_T+20,1,0,	{13,0,SFX_GE_BADGLOVE_LAUGH,0}},

	{CAMEO_NME_ANIM,		  PI_SPELL1_T,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},


	{CAMEO_NME_ANIM,		  PI_SPELL2_T,1,0,	{13, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  PI_SPELL2_T,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},

	{CAMEO_NME_ANIM,		  PI_SPELL3_T,1,0,	{13, EVILGLOVE_SPELL,0,0,4096}},
	{CAMEO_NME_ANIM,		  PI_SPELL3_T,1,0,	{13, EVILGLOVE_IDLE,1,1,4096}},

// glove prepares to vanish
	{CAMEO_NME_ANIM,		  PI_VANISH_T - 20,1,0,	{13, EVILGLOVE_VANISH,0,0,4096}},
	{CAMEO_FX_LIFEGLOW,		  PI_VANISH_T - 20,30,0,	{122,77,-320,25,15}},
	{CAMEO_FX_FLASH,		  PI_VANISH_T-1,20,0,	{255,200,80}},
	{CAMEO_NME_ACTIVATE,	  PI_VANISH_T,1,0,	 {13,0}},


	{CAMEO_SFX,				  PI_VANISH_T-20,    1,0, {13,0,SFX_CAST_SPELL_3,0}},
	{CAMEO_SFX,				  PI_VANISH_T-1,     1,0, {13,0,SFX_HAND_FINGERCLICK,0}},


//	{CAMEO_SPELL,			  PI_SPELL1_T+20,1,0, {13,11,SPELL_PIRATES_UNFROG}},	// +20
	{CAMEO_SPELL,			  PI_SPELL2_T+20,1,0, {13,12,SPELL_PIRATES_UNFROG}},
	{CAMEO_SPELL,			  PI_SPELL3_T+20,1,0, {13,10,SPELL_PIRATES_SPANK}},


	{CAMEO_SFX,				  PI_SPELL2_T+20,    1,0, {13,0,SFX_CAST_SPELL_2,0}},
	{CAMEO_SFX,				  PI_SPELL3_T+20,    1,0, {13,0,SFX_CAST_SPELL_2,0}},


	{CAMEO_CAM_CLAIM,		  0,PI_CAM_LEN,0},
//	{CAMEO_CAM_POS,			  0,1,0,   {-135,  -80, -106, -1}},
//	{CAMEO_CAM_TARGPOS,		  0,1,0,   { 126,   77, -216, -1}},


	{CAMEO_CAM_POS,			  0,1,0,   {  0,  -70, -150, -1}},
	{CAMEO_CAM_TARGNME,		  0,1,0,   { 13, -1}},
	{CAMEO_CAM_POS,			  PI_SPELL1_T,PI_SPELL2_T - PI_SPELL1_T,0,   {-135,  -80, -106, 2}},
	{CAMEO_CAM_TARGPOS,		  PI_SPELL1_T,PI_SPELL2_T - PI_SPELL1_T,0,   { 126,   77, -216, 2}},


	{CAMEO_CAM_POS,			  PI_PANP_T,PI_SPELL3_T - PI_PANP_T, 0, { 110, 70,-430, 10}},
	{CAMEO_CAM_TARGNME,		  PI_PANT_T,PI_SPELL3_T - PI_PANT_T, 0, { 10, 10}},

#endif
};



CAMEO cameo_pirates =
{
	NULL,
	0,
	sizeof(cameo_pirates_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_pirates_insts[0]
};

// ======================================================================================


// evilglove zooms under camera
// huge door starts to open
// evilglove performs some acrobatics
// evilglove goes under & into the evil robot
// comedy engine-start moment
// camera pulls right back through the panel


// glove's 13, robot's 12
#define SPACE_CAMEO_TIME 750

#define CENTRE_X      -300
#define EVIL_ROBOT_Z -3000
#define EVIL_ROBOT_Y -350

#define TIME_FAR_Z	 180
#define TIME_NEAR_Z	 300
#define TIME_UNDER_ROBOT 520
#define TIME_COMEDY   580

// note this should be after the evil glove deactivates...
// (under_robot + 50)
#define TIME_PULLBACK 650


#define LOOP_FAR_Z   -2400
#define LOOP_NEAR_Z  -1000

CAMEO_INST_GEN cameo_space_insts[] =
{
	{CAMEO_NME_ACTIVATE,	  0,1,0,	{300,0}},	// turn the dome explosion off

#ifdef FAST_SPBOSS_CAMEO
	{CAMEO_NME_ACTIVATE,	  1,  1,0,	{13,0}},
	{CAMEO_NME_DOING,		  2,  1,0,	{12,21}},

#else

	{CAMEO_CAM_CLAIM,		  0,SPACE_CAMEO_TIME,0},

// Camera follows the glove around

	{CAMEO_CAM_POS,			  0,1,0,	{CENTRE_X-5, -400-50,-50, -1}},
	{CAMEO_CAM_TARGPOS,		  0,30,0,	{CENTRE_X,   -380-50,-200, -1}},

	{CAMEO_CAM_TARGNME,		  30,10,0,	{13, 1}},		// target the evilglove as it goes under us
	{CAMEO_CAM_TARGNME,		  40,10,0,	{13, 2}},
	{CAMEO_CAM_TARGNME,		  50,10,0,	{13, 4}},
	{CAMEO_CAM_TARGNME,		  60,TIME_UNDER_ROBOT-60 - 100,0,	{13, -1}},


//	{CAMEO_CAM_TARGPOS,		  TIME_UNDER_ROBOT-100, SPACE_CAMEO_TIME-(TIME_UNDER_ROBOT-100), 0,
//														{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z, 15}},	//-1}},

	{CAMEO_SFX,				  0,TIME_COMEDY,0,	{13,1,SFX_JETPACK,12}},

	{CAMEO_CAM_TARGPOS,		  TIME_UNDER_ROBOT-100, TIME_PULLBACK-(TIME_UNDER_ROBOT-100), 0,
														{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z, 15}},	//-1}},
	{CAMEO_CAM_TARGPOS,		  TIME_PULLBACK, SPACE_CAMEO_TIME-(TIME_PULLBACK), 0,
														{ER_FINAL_X,ER_FINAL_Y,EVIL_ROBOT_Z, 3}},	//-1}},

// this should be identical
//	{CAMEO_CAM_TARGPOS,		  SPACE_CAMEO_TIME-20, 20, 0, {-300,-300,-250, 500}},


// camera position stuff...
	{CAMEO_CAM_DRAG,		  0,260,0,   {100, 300, 80, 9}},
	{CAMEO_CAM_DRAG,		  260,TIME_UNDER_ROBOT-100-260,0, {100, 300, 100, 9}},			// and after that, it stays still...

	{CAMEO_CAM_POS,			  TIME_UNDER_ROBOT-100, TIME_PULLBACK-(TIME_UNDER_ROBOT-100), 0,
														{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z+1000, 12}},			// move to face the robot head on

//	{CAMEO_CAM_POS,			  TIME_PULLBACK,   10, 0,	{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z+3000, 6}},
//	{CAMEO_CAM_POS,			  TIME_PULLBACK+10,10, 0,	{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z+3000, 12}},
//	{CAMEO_CAM_POS,			  TIME_PULLBACK+20,10, 0,	{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z+3000, 18}},
	{CAMEO_CAM_POS,			  TIME_PULLBACK,   10, 0,	{ER_FINAL_X,ER_FINAL_Y,ER_FINAL_Z, 6}},
	{CAMEO_CAM_POS,			  TIME_PULLBACK+10,10, 0,	{ER_FINAL_X,ER_FINAL_Y,ER_FINAL_Z, 12}},
	{CAMEO_CAM_POS,			  TIME_PULLBACK+20,10, 0,	{ER_FINAL_X,ER_FINAL_Y,ER_FINAL_Z, 18}},

	{CAMEO_CAM_POS,			  TIME_PULLBACK+30,SPACE_CAMEO_TIME - (TIME_PULLBACK+30), 0, 
														{-300,-300,-400, 32}},

//	{CAMEO_CAM_POS,			  TIME_PULLBACK+30,SPACE_CAMEO_TIME - (TIME_PULLBACK+30), 0, 
//														{ER_FINAL_X,ER_FINAL_Y,ER_FINAL_Z, 36}},
//														{CENTRE_X,EVIL_ROBOT_Y-100,EVIL_ROBOT_Z+3000, 32}},


// place the evil robot properly


	{CAMEO_NME_MOVETO,		  0,1,0,	{12,	CENTRE_X, EVIL_ROBOT_Y,EVIL_ROBOT_Z, -1}},
	{CAMEO_NME_AIM,			  0,1,0,	{12,	CENTRE_X, EVIL_ROBOT_Y,0, -1}},
	{CAMEO_NME_ANIM,		  0,1,0,	{12,	NMEANIM_IDLE,1,0,0}},	// loop,queue, zero speed

// actually, this ain't so hot.. It needs to jiggle around
//	{CAMEO_NME_ANIM,		  TIME_COMEDY,   1,0,	{12,	NMEANIM_IDLE,1,0,4096}},
/*
	{CAMEO_NME_JUDDER,		  TIME_COMEDY,   8,0,	{12,	NMEANIM_IDLE,17,23}},
	{CAMEO_NME_ANIM,		  TIME_COMEDY+8, 1,0,	{12,	NMEANIM_IDLE,1,0,0}},

	{CAMEO_NME_JUDDER,		  TIME_COMEDY+40,   8,0,	{12,	NMEANIM_IDLE,17,23}},
	{CAMEO_NME_ANIM,		  TIME_COMEDY+48,   1,0,	{12,	NMEANIM_IDLE,1,0,0}},

	{CAMEO_NME_JUDDER,		  TIME_COMEDY+80,   5,0,	{12,	NMEANIM_IDLE,17,23}},
	{CAMEO_NME_ANIM,		  TIME_COMEDY+85,   1,0,	{12,	NMEANIM_IDLE,1,0,4096}},
*/
	{CAMEO_NME_DOING,		  TIME_COMEDY,     1,0,	{12,20}},
	{CAMEO_NME_DOING,		  TIME_COMEDY+40,  1,0,	{12,20}},
	{CAMEO_NME_DOING,		  TIME_COMEDY+80,  1,0,	{12,20}},
	{CAMEO_NME_DOING,		  TIME_COMEDY+95,  1,0,	{12,21}},

	{CAMEO_SFX,				TIME_COMEDY, 1,0, {0,1,SFX_ENGINE_FAIL,0}},
	{CAMEO_SFX,				TIME_COMEDY+40, 1,0, {0,1,SFX_ENGINE_FAIL,0}},
	{CAMEO_SFX,				TIME_COMEDY+80, 1,0, {0,1,SFX_ENGINE_START,0}},
	{CAMEO_SFX,				TIME_COMEDY+95, SPACE_CAMEO_TIME - (TIME_COMEDY+95),0, {0,1,SFX_ENGINE_RUNNING,8}},

//	{CAMEO_SFX,				TIME_COMEDY+100, 1,0, {0,1,SFX_ENGINE_RUNNING}},
//	{CAMEO_SFX,				TIME_COMEDY+105, 1,0, {0,1,SFX_ENGINE_RUNNING}},
//	{CAMEO_SFX,				TIME_COMEDY+110, 1,0, {0,1,SFX_ENGINE_RUNNING}},

// tbd - set the under-enemy sparklers going...


// Make the evil glove do his aerobatic display...
	{CAMEO_NME_MOVETO,		  0,1,0,	{13,	CENTRE_X,   -80-300,100, -1}},

	{CAMEO_NME_FLYTO,		  1,TIME_FAR_Z-1,   0,	{13,   CENTRE_X,     -200-300,LOOP_FAR_Z+800, 8,1}},	// special case for evilglove flight
	{CAMEO_NME_FLYTO,		  TIME_FAR_Z,    15+1,0,	{13,   CENTRE_X-300, -800-300,LOOP_FAR_Z,     8,1}},	// far of loop
	{CAMEO_NME_FLYTO,		  TIME_FAR_Z+15, 15+1,0,	{13,   CENTRE_X-600,-1200-300,LOOP_FAR_Z+800, 8,1}},	// top of loop

	{CAMEO_NME_SPIN,          TIME_FAR_Z+10,100,0, {13, 2, 40}},


	{CAMEO_NME_FLYTO,		  TIME_FAR_Z+30, TIME_NEAR_Z - (TIME_FAR_Z+30)+1,0,
													{13,   CENTRE_X-900,  -80-200,LOOP_NEAR_Z+400, 8,1}},	// floor
	{CAMEO_NME_FLYTO,		  TIME_NEAR_Z,   20+1,0,	{13,   CENTRE_X-400,  -80-200,LOOP_NEAR_Z,     8,1}},	// across
	{CAMEO_NME_FLYTO,		  TIME_NEAR_Z+20,20+1,0,	{13,       CENTRE_X,  -80-300,LOOP_NEAR_Z+400, 8,1}},	// across


	{CAMEO_NME_FLYTO,		  TIME_NEAR_Z+40,10+1,0,  {13,       CENTRE_X,          -40,EVIL_ROBOT_Z, 8,1}},		// under robot
	{CAMEO_NME_FLYTO,		  TIME_NEAR_Z+50,10+1,0,  {13,       CENTRE_X,          -40,EVIL_ROBOT_Z,10,1}},		// under robot
	{CAMEO_NME_FLYTO,		  TIME_NEAR_Z+60,TIME_UNDER_ROBOT-(TIME_NEAR_Z+60)+1,0, 
													{13,       CENTRE_X,          -40,EVIL_ROBOT_Z,14,1}},		// under robot

	{CAMEO_NME_FLYTO,		  TIME_UNDER_ROBOT,50,0,{13,      CENTRE_X, EVIL_ROBOT_Y,EVIL_ROBOT_Z-200, 8,1}},	// under robot
	{CAMEO_NME_ACTIVATE,	  TIME_UNDER_ROBOT+50,1,0,	{13,	0}},

//	{CAMEO_NME_ANIM,		  0,1,0,	{13, EVILGLOVE_IDLE,1,0,0}},	// loop,queue, zero speed
	{CAMEO_NME_ANIM,		  0,1,0,	{13, EVILGLOVE_FLY,1,0,0}},	// loop,queue, zero speed
#endif
};


extern CAMEO cameo_space_end;

CAMEO cameo_space =
{
	&cameo_space_end,
	0,
	sizeof(cameo_space_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_space_insts[0]
};

// ======================================================================================

// The spaceboss has just hit the tarmac in flames.
// Flash the screen, and get rid of the panel
// Camera rises
// Big spherical explosion
// Evilglove comes out of the explosion in a flaming manner (note - needs evilglove's position to match spbosses)

//#define SPEND_LEN 350
#define SPEND_LEN 330
#define SPEND_GLOVE_EMERGES 50

CAMEO_INST_GEN cameo_space_end_insts[] =
{
	{CAMEO_CAM_CLAIM,		  0,SPEND_LEN,0},


	{CAMEO_FX_FLASH,		  0,6,0,	{255,255,255}},
	{CAMEO_FX_FLASH,		  4,6,0,	{255,255,0}},
	{CAMEO_FX_FLASH,		  8,6,0,	{  0,255,255}},


// Turn the dome explosion on (It'll already have been placed correctly)
	{CAMEO_NME_ACTIVATE,	  0,1,0,	{300,1}},

//	{CAMEO_NME_SCALE,		  0,1,0,	{300, 6000,-1}},
//	{CAMEO_NME_SCALE,		  1,300,0,	{300,32767,500}},


//	{CAMEO_NME_SCALE,		  0,1,0,	{300,  10,-1}},
//	{CAMEO_NME_SCALE,		  1,300,0,	{300,8000,200}},

	{CAMEO_NME_SCALE,		  0,1,0,	{300,10,-1}},
	{CAMEO_NME_SCALE,		  1,100,0,	{300,8000,50}},


	{CAMEO_SFX,				10, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				14, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				16, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				20, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				24, 1,0, {0,0,SFX_GE_CRUMPET_ATTACK,0}},
	{CAMEO_SFX,				26, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				29, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				32, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				33, 1,0, {0,0,SFX_GE_CRUMPET_ATTACK,0}},
	{CAMEO_SFX,				38, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},
	{CAMEO_SFX,				44, 1,0, {0,0,SFX_GE_SAMTEX_EXPLODE,0}},



	{CAMEO_FX_FLASH,		  60,20,0,	{255,255,255}},
	{CAMEO_NME_ACTIVATE,	  60,1,0,	{300,0}},




// Move the camera upwards, target on the evil glove

//	{CAMEO_CAM_POS,			  0,SPEND_LEN,0,	{CENTRE_X, -1500,-1950, 10}},
	{CAMEO_CAM_POS,			  0,SPEND_LEN,0,	{CENTRE_X, -1500,-1850, 10}},
	
	{CAMEO_CAM_TARGNME,		  0,SPEND_LEN,0,	{13, -1}},	// it starts at the same point as the evil boss...


// Set the evil glove back in it's normal animation with zero speed...

//	{CAMEO_NME_ANIM,		  0,1,0,						{13,	NMEANIM_IDLE,1,0,0}},	// loop,queue, zero speed
	{CAMEO_NME_ANIM,		  0,1,0,	{13, EVILGLOVE_FLY,1,0,0}},	// loop,queue, zero speed
	{CAMEO_NME_ACTIVATE,	  SPEND_GLOVE_EMERGES,  1,0,	{13,1}},

	{CAMEO_NME_SPIN,          0,SPEND_LEN,0, {13, 2, 40}},

	{CAMEO_NME_FLYTO,		  SPEND_GLOVE_EMERGES,80,0,
							{13,      CENTRE_X, -500,-2000, 8,2}},

	{CAMEO_NME_FLYTO,		  SPEND_GLOVE_EMERGES + 80,SPEND_LEN - (SPEND_GLOVE_EMERGES+80),0,
							{13,      CENTRE_X, -5000,-2000, 8,2}},


	{CAMEO_SFX,				  SPEND_GLOVE_EMERGES,SPEND_LEN - (SPEND_GLOVE_EMERGES),0,	{13,0,SFX_GE_CRUMPET_ATTACK,12}},

//	{CAMEO_LEVELEND,	SPEND_LEN-1,1,0}
	{CAMEO_LEVELEND,	SPEND_LEN-33,1,0}	// fadeout length is 32
};

CAMEO cameo_space_end =
{
	NULL,
	0,
	sizeof(cameo_space_end_insts) / sizeof(CAMEO_INST_GEN),
	&cameo_space_end_insts[0]
};


// ======================================================================================

void UpdateCameo(CAMEO *cameo);

CAMEO *cameolist = &cameo_atlantis;
int cameo_running;

VECTOR cameo_cam_pos;
VECTOR cameo_cam_targ;
SHORT cameo_spin_angle;
int cameo_spin_range;

char cameo_litenin_on = 0;
char cameo_spring_on = 0;
SVECTOR cameo_litenin_pos[8];

// ======================================================================================
NEWMODEL *spring_psa;

inline void cameoBeginFile()
{
	cameo_running = 0;
	cameolist = NULL;
}

// deal with any extra shapes we need
void cameoEndFile()
{
	LOADEDMODEL *model;

	spring_psa = NULL;

	switch(level)
	{
		case CARNIVALBOSS:
			model = EnsureModelLoaded(0,"SPRING",256);
			spring_psa = model->psa;
			break;
	}

}

void cameoFreeCameos()
{
/*
	CAMEO_DEFSTR *cam,*next;
	for(cam = cameolist;cam;)
	{
		next = cam->next;
		FREE(cam);
		cam = next;
	}
	cameolist = NULL;
*/
}

int cameoParseTokenCameo(short token,UBYTE **data)
{
	switch(token)
	{
// note - if the start cameo does things by index, this'll be back-to-front
	case TOKEN_CAMEO:
	{
/*
		current_cameo = MALLOC(sizeof(CAMEO_DEFSTR),"cameo");
		current_cameo->num_instrs = 0;
		current_cameo->next = cameolist;
		cameolist = current_cameo;
*/
		return YES;
	}

	case TOKEN_CAMEO_INSTRUCTION:
	{
		int itype;
/*
		CAMEO_INSTSTR *inst;


		if(current_cameo->num_instrs>=CAMEO_MAX_INSTRS)
		{
			CAMEO_PRINTF("*** CAMEO INSTR OVERFLOW ***\n");
			current_cameo->num_instrs=CAMEO_MAX_INSTRS -1;
		}

		inst = &current_cameo->instrs[current_cameo->num_instrs];
		current_cameo->num_instrs++;
*/
		itype = *(short *)(*data);
		*data += 2;

//		inst->type = itype;
		switch(itype)
		{
			case CAMEO_INSTRUCTION_ANIMATION:
				*data += 10;
				break;

			case CAMEO_INSTRUCTION_TARGET_CAMERA:
				*data += 14;
				break;

			case CAMEO_INSTRUCTION_DISABLE_ACTOR:
				*data += 2;
				break;

			case CAMEO_INSTRUCTION_MOVE_ACTOR:
				*data += 18;
				break;

			case CAMEO_INSTRUCTION_ROTATE_ACTOR:
				*data += 6;
				break;

			case CAMEO_INSTRUCTION_TIE_ACTOR_TO_SPHERE:
				*data += 6;
				break;

			case CAMEO_INSTRUCTION_LIGHTNING:
				*data += 4;
				break;
			default:
				CAMEO_PRINTF("*** unknown cameo instruction ***\n");
				return NO;
		}
		*data += 4;
		return YES;
	}
	}
	return NO;
}

// ======================================================================================

void cameoStart(int num)
{
	CAMEO *cameo;
	int j;

	CAMEO_PRINTF("STARTING CAMEO %d\n",num);

//	printf("cam size %d\n",sizeof(cameo_carnival_insts));
	switch(level)
	{
		case ATLANTISBOSS:
			cameolist = &cameo_atlantis;
			break;
		case CARNIVALBOSS:
			cameolist = &cameo_carnival;
			break;
		case PREHISTORICBOSS:
			cameolist = &cameo_prehist;
			break;
		case FEARBOSS:
			cameolist = &cameo_fear;
			break;
		case PIRATESBOSS:
		{
//			ENEMYPOS *nme;
			cameolist = &cameo_pirates;
//			nme = loadlndFindEnemy(11);
//			nme->flags |= NMEFLAG_FROGGED;
//			nme = loadlndFindEnemy(12);
//			nme->flags |= NMEFLAG_FROGGED;
			break;
		}

		case SPACEBOSS2:
			cameolist = &cameo_space;
			cameo_space_end.timer = 0;
			break;
/*
		case FEARTEST:	// a bit of a cludge, but I want to test prboss before I get it...
		{
			DYNCOLLBOX *box;
			int i;
			for(i = 0; i < 8;i++)
			{
				loadlndFindPlatform(i+100, NULL, &box);
			}



			break;
		}
*/

		default:
			CAMEO_PRINTF("%d is not a cameo level (%d %d)\n",level,ATLANTISBOSS,CARNIVALBOSS);
			return;
	}

	cameo = cameolist;
	for(j = 0;j < num && cameo;j++)
		cameo = cameo->next;

	if(!cameo)
	{
		CAMEO_PRINTF("cameo not found\n");
		return;
	}

	CAMEO_PRINTF(" (Cameo Activated\n");

	cameo->timer = 1;

	for(j = 0;j < cameo->num_instrs;j++)
	{
		cameo->instrs[j].timer = 0;
		if(cameo->instrs[j].start == 0)
		{
			CAMEO_PRINTF("Cameo Action %i is an initial one\n",j);
			cameo->instrs[j].timer = 1;
		}
	}
}

// ======================================================================================
// Cameo Enemy Instructions...

ENEMYPOS * cameoFindNme(int tag)
{
	ENEMYPOS *nme;
	nme = loadlndFindEnemy(tag);

	if(!nme)
	{
		DB("UNTAGGED CAMEO NME %d\n",tag);
		CRASH;
	}
	return nme;
}

void cameoNmeMoveto(CAMEO *cameo,CAMEO_NME_MOVETOINST *inst)
{
	ENEMYPOS *enemy;
	VECTOR dest;
	enemy = cameoFindNme(inst->nme);
	{
		dest.vx = inst->x << 12;
		dest.vy = inst->y << 12;
		dest.vz = inst->z << 12;
		VectorMoveTo(&enemy->pos,&dest,inst->speed<<12);
	}
}

// Evil glove on the SpaceBoss2 anims
// (should use the spell-movement code...)
void cameoNmeFlyto(CAMEO *cameo,CAMEO_NME_FLYTOINST *inst)
{
	ENEMYPOS *nme;
	VECTOR dest;
	SHORT angs[2];
	static VECTOR ref1 = {-11,5,0};
	static VECTOR ref2 = { 10,5,0};
	int oya;

	nme = cameoFindNme(inst->nme);
	dest.vx = inst->x << 12;
	dest.vy = inst->y << 12;
	dest.vz = inst->z << 12;

//	DB("evil glove %d %d %d\n",nme->pos.vx>>12,nme->pos.vy>>12,nme->pos.vz>>12);

/*
	VectorMoveTo(&enemy->pos,&dest,inst->speed<<12);
	enemy->xa = 0x400;
*/

	oya = nme->ya;
	angs[0] = (nme->xa) & 4095;
	angs[1] = (0x800+nme->ya) & 4095;

	pickupHomer(&nme->pos, &angs[0], &dest, 0x20, inst->speed);

	nme->xa = (angs[0]) & 4095;
	nme->ya = (0x800+angs[1]) & 4095;


// gimme some tilt...
	oya = (nme->ya - oya) & 4095;
	if(oya > 2048) oya |= (~4095);
	if(oya > 16) oya = 16;
	if(oya < -16) oya = -16;
	nme->za = AngleHomer(nme->za, -(oya * 32), 8);


	switch(inst->info)
	{
	case 0:
		break;
	case 1:
		EnemyRotatePoint(nme,&ref1,&dest,-1);
		dest.vx = (dest.vx << 12) + nme->pos.vx + ( (RANDOM256() -128 )<<6);
		dest.vy = (dest.vy << 12) + nme->pos.vy + ( (RANDOM256() -128 )<<6);
		dest.vz = (dest.vz << 12) + nme->pos.vz + ( (RANDOM256() -128 )<<6);
		New_Debris(DEBRIS_OPEC_HOVER,&dest,256);

		EnemyRotatePoint(nme,&ref2,&dest,-1);
		dest.vx = (dest.vx << 12) + nme->pos.vx + ( (RANDOM256() -128 )<<6);
		dest.vy = (dest.vy << 12) + nme->pos.vy + ( (RANDOM256() -128 )<<6);
		dest.vz = (dest.vz << 12) + nme->pos.vz + ( (RANDOM256() -128 )<<6);
		New_Debris(DEBRIS_OPEC_HOVER,&dest,256);
		break;
	case 2:
		dirtyFlames(&nme->pos, 1, 6,800);

		break;
	}


//	nme->za = (nme->za + 0x40) & 4095;
// ummm....
// what we want is some ickle vapour trails...
/*
	if(!(nme->ticker & 1))
	{
		New_Debris(DEBRIS_FASTFLAME,&nme->pos,512);
	}
*/

}

void cameoNmeMoveFore(CAMEO *cameo,CAMEO_NME_MOVEFOREINST *inst)
{
	ENEMYPOS *enemy;
	VECTOR dest;
	enemy = cameoFindNme(inst->nme);

	NME_GoForwards(enemy, inst->speed<<12);
}

void cameoNmeSpin(CAMEO *cameo,CAMEO_NME_SPININST *inst)
{
	ENEMYPOS *nme;
	VECTOR dest;
	nme = cameoFindNme(inst->nme);

	switch(inst->axis)
	{
	case 0:
		nme->xa += inst->speed;
		break;
	case 1:
		nme->ya += inst->speed;
		break;
	case 2:
		nme->za += inst->speed;
		break;
	}
}

void cameoNmeAnim(CAMEO *cameo,CAMEO_NME_ANIMINST *inst)
{
	ENEMYPOS *enemy;
	enemy = cameoFindNme(inst->nme);
	
	AddToQueue(&enemy->anim,inst->anim,inst->loop,inst->queue,inst->speed);
}

void cameoNmeJudder(CAMEO *cameo,CAMEO_NME_JUDDERINST *inst)
{
	ENEMYPOS *enemy;
	int frame;
	enemy = cameoFindNme(inst->nme);

//		return anim->animInfo->frame + anim->animInfo->segInfo[anim->currentAnimation].segStart;
	AddToQueue(&enemy->anim,inst->anim,0,0,0);	// force the anim to be non-animating

	frame = random(inst->frameend - inst->framestart) + inst->framestart;

	enemy->anim.animInfo->frame = frame;
	enemy->anim.animInfo->frameFixed = frame<<12;
}
void cameoNmeDoing(CAMEO *cameo,CAMEO_NME_DOINGINST *inst)
{
	ENEMYPOS *enemy;
	int frame;
	enemy = cameoFindNme(inst->nme);

	enemy->doing = inst->doing;
	enemy->ticker = 0;
}


void cameoNmeAim(CAMEO *cameo,CAMEO_NME_AIMINST *inst)
{
	ENEMYPOS *enemy;
	int dx,dz;
	int ta;
	enemy = cameoFindNme(inst->nme);

	dx = (inst->tx <<12) - enemy->pos.vx;
	dz = (inst->tz <<12) - enemy->pos.vz;
	ta = (calc_angle(dx,dz) + 2048) & 4095;

//	printf("aim: dx,dx = %d %d. ya = %d, ta = %d\n",dx,dz,enemy->ya,ta);

	enemy->ya = AngleHomer(enemy->ya, ta, inst->speed);
	if(enemy->ya == ta)
	{
		SET_INSTR_DONE(inst);
	}
}

void cameoNmeScale(CAMEO *cameo,CAMEO_NME_SCALEINST *inst)
{
	ENEMYPOS *enemy;
	int now;
	enemy = cameoFindNme(inst->nme);

	now = enemy->psa->globalscale.vx;

	now = IntHomer(now,inst->scale,inst->speed);

	enemy->psa->globalscale.vx = now;
	enemy->psa->globalscale.vy = now;
	enemy->psa->globalscale.vz = now;

	if(now == inst->scale)
	{
		SET_INSTR_DONE(inst);
	}
}

void cameoNmeActivate(CAMEO *cameo,CAMEO_NME_ACTIVATEINST *inst)
{
	ENEMYPOS *enemy;
	DYNCOLLBOX *pBox;
//	enemy = cameoFindNme(inst->nme);
	enemy = loadlndFindEnemy(inst->nme);


	if(enemy)
	{
		if(inst->active)
		{
			enemy->flags |= (NMEFLAG_ACTIVE + NMEFLAG_ENABLED);
		}
		else
		{
			enemy->flags &= ~(NMEFLAG_ACTIVE + NMEFLAG_ENABLED);
		}
	}

	loadlndFindPlatform(inst->nme, NULL, &pBox);
	if(pBox)
	{
		if(inst->active)
		{
			pBox->active = 1;
		}
		else
		{
			pBox->active = 0;
		}
	}
}

void cameoSfx(CAMEO *cameo,CAMEO_SFXINST *inst)
{
	int bank;
	ENEMYPOS * nme;

	if(inst->interval)
	{
		if(inst->timer % inst->interval)
		{
			return;
		}
	}

	if(inst->bank)
	{
		bank = levelFX;
	}
	else
	{
		bank = globalFX;
	}

	if(level == SPACEBOSS2)
	{
		if(inst->sfx == SFX_JETPACK)
		{
			static int temp = DEFAULT_PITCH<<8;

			temp += (RANDOM256()-128) <<4;
			if(temp < (DEFAULT_PITCH-128)<< 8)
				temp = (DEFAULT_PITCH-128)<< 8;
			if(temp > (DEFAULT_PITCH+128)<< 8)
				temp = (DEFAULT_PITCH+128)<< 8;

			sfxSetSamplePitch(levelFX, SFX_JETPACK, (temp>>8));
		}

		if(inst->sfx == SFX_ENGINE_RUNNING)
		{
			sfxSetSampleVolume(levelFX, SFX_ENGINE_RUNNING, DEFAULT_VOLUME * (inst->duration - inst->timer) / inst->duration);

		}
	}


	if(inst->nme)
	{
		nme = cameoFindNme(inst->nme);
		sfxPlayNME3D(bank,inst->sfx, nme);
	}
	else
	{
		sfxPlay(bank,inst->sfx);
	}
}


void cameoSpell(CAMEO *cameo,CAMEO_SPELLINST *inst)
{
	ENEMYPOS *src_nme;
	ENEMYPOS *dest_nme;
	int i;
	int ya;
	SPELLSTR *spell;
	VECTOR src_pos;


	src_nme = cameoFindNme(inst->src_tag);
	dest_nme = cameoFindNme(inst->dest_tag);

	ya = src_nme->ya + 0x800;
	src_pos.vx = src_nme->pos.vx + 10 * rsin(ya);
	src_pos.vy = src_nme->pos.vy;
	src_pos.vz = src_nme->pos.vz + 10 * rcos(ya);

//	pickupFireSpell(type,&pos,GloveCtrl.direction,nme,SPELLACTION_NMETRANS);

	if(inst->type == SPELL_CARNIVAL_CAMEO)
	{
		for(i = 0; i < 4; i++)
		{
			spell = pickupFireSpell(inst->type,&src_pos,ya,dest_nme,SPELLACTION_NMETRANS);
			if(i & 1)
				spell->angles[1] = (ya + 0x200) & 4095;
			else
				spell->angles[1] = (ya - 0x200) & 4095;

			if(i & 2)
				spell->angles[0] = -0x200;
			else
				spell->angles[0] = 0x200;
		}
	}
	else
	{
		spell = pickupFireSpell(inst->type,&src_pos,ya,dest_nme,SPELLACTION_NMETRANS);
		spell->angles[1] = ya;
	}
}

void cameoPiMonkey(CAMEO *cameo,CAMEO_PI_MONKEYINST *inst)
{
	ENEMYPOS *enemy;
	enemy = cameoFindNme(inst->nme);
	enemy->flags &= ~(NMEFLAG_FROGGED);
}

void cameoCaSpring(CAMEO *cameo,CAMEO_CA_SPRINGINST *inst)
{
	NEWMODEL *psa = spring_psa;
	int range;
	int xvalue;
	int yvalue;
	int angvalue;
	int angle;
	ENEMYPOS *enemy;

	enemy = cameoFindNme(1);

	angle = (inst->timer * 500) & 4095;

	cameo_spring_on = 1;

	if(inst->timer < 80)
	{
		range = 16 + 256 * (80 - inst->timer) / 80;
	}
	else
	{
		range = 16;
	}

	psa->position.vx= inst->x;
	psa->position.vy= inst->y;
	psa->position.vz= inst->z;

/*
// angle checking...
	psa->globalscale.vx = 512;
	psa->globalscale.vy = 512;
	psa->globalscale.vz = 512;
	psa->world.rotate.vx += 0x100;
	psa->world.rotate.vy = 1024;
	psa->world.rotate.vz = 1024;
*/


	yvalue = 16 + range + rsin(angle) * range / 4096;
	psa->globalscale.vy = yvalue;

	xvalue = 256 - rsin(angle) * 32 / 4096;	// replace with single shift
	psa->globalscale.vx = xvalue;



	angle = (inst->timer * 250) & 4095;
	angvalue = (rcos(angle) / 32) & 4095;

	psa->world.rotate.vx = angvalue + 1024;
//	psa->world.rotate.vy = 1024;
	psa->world.rotate.vy = (enemy->ya + 1024) & 4095;
	psa->world.rotate.vz = 1024;


// stick the evil glove on top of the spring
//	enemies[1].pos.vy = (inst->y << 12) - (yvalue << 10);
	
	enemy->pos.vy = (inst->y << 12) - ((yvalue * rcos(angvalue)) >> 2);
	enemy->pos.vx = (inst->x << 12) - ((yvalue * rsin(angvalue)) >> 2);
	enemy->pos.vz = (inst->z << 12);
	enemy->xa = 0;
//	enemy->ya = 0;
	enemy->za = -angvalue;

}

// ======================================================================================
// Cameo Platform Instructions...

void cameoPlatMoveto(CAMEO *cameo,CAMEO_PLAT_MOVETOINST *inst)
{
	DYNCOLLBOX *box;
	VECTOR dest;
	VECTOR pos;

	dest.vx = inst->x << 12;
	dest.vy = inst->y << 12;
	dest.vz = inst->z << 12;

	loadlndFindPlatform(inst->tag, NULL, &box);

	pos.vx = box->cumPos.vx;
	pos.vy = box->cumPos.vy;
	pos.vz = box->cumPos.vz;

	VectorMoveTo(&pos,&dest,inst->speed<<12);
	platformMoveDynamicBox(box, pos.vx, pos.vy, pos.vz);
	
}

// ======================================================================================
// Cameo Camera Instructions...

void cameoCamTargNme(CAMEO *cameo,CAMEO_CAM_TARGNMEINST *inst)
{
	ENEMYPOS *enemy;
	VECTOR *targ;
	switch(inst->nme)
	{
		case -1:
			targ = &glovePos;
			break;
		case -2:
			targ = &ballPos;
			break;
		default:
			enemy = cameoFindNme(inst->nme);
			targ = &enemy->pos;
			break;
	}

	VectorMoveTo(&cameo_cam_targ,targ,((int)inst->speed)<<12);
}
void cameoCamTargPos(CAMEO *cameo,CAMEO_CAM_TARGPOSINST *inst)
{
	VECTOR temp;
	temp.vx = inst->x << 12;
	temp.vy = inst->y << 12;
	temp.vz = inst->z << 12;

	VectorMoveTo(&cameo_cam_targ,&temp,inst->speed<<12);
}
void cameoCamHeight(CAMEO *cameo,CAMEO_CAM_HEIGHTINST *inst)
{
	VECTOR temp;
	temp.vx = cameo_cam_pos.vx;
	temp.vy = inst->y << 12;
	temp.vz = cameo_cam_pos.vz;

	VectorMoveTo(&cameo_cam_pos,&temp,inst->speed<<12);
}
void cameoCamPos(CAMEO *cameo,CAMEO_CAM_POSINST *inst)
{
	VECTOR temp;
	temp.vx = inst->x << 12;
	temp.vy = inst->y << 12;
	temp.vz = inst->z << 12;

	if(inst->speed < 0)
	{
		cameo_cam_pos = temp;
	}
	else
	{
		VectorMoveTo(&cameo_cam_pos,&temp,inst->speed<<12);
	}
}

void cameoCamDrag(CAMEO *cameo,CAMEO_CAM_DRAGINST *inst)
{
	VECTOR dvec;
	int mag;

	SUBVECTOR(&dvec,&cameo_cam_targ,&cameo_cam_pos);
	mag = Magnitude(&dvec);
	dvec.vy -= ((int)(inst->y_add))<<12;

	MakeUnit(&dvec);

	if(mag > (inst->max<<12))
	{
		mag = mag - (inst->max<<12);

		if (mag > ((int)inst->speed)<<12)
			mag = ((int)inst->speed)<<12;
/*
		DB("vec %d %d %d, drag move in mag %d (instspeed = %d)\n",
			dvec.vx,dvec.vy,dvec.vz,
			mag>>12, inst->speed
			);
*/
		dvec.vx = dvec.vx >> 4;
		dvec.vy = dvec.vy >> 4;
		dvec.vz = dvec.vz >> 4;
		mag = mag >> 4;

		cameo_cam_pos.vx += (dvec.vx * mag) >> 4;
		cameo_cam_pos.vy += (dvec.vy * mag) >> 4;
		cameo_cam_pos.vz += (dvec.vz * mag) >> 4;
	}

	if(mag < (inst->min<<12))
	{
//		DB("drag move out\n");
		mag = (inst->min<<12) - mag;
		if (mag > inst->speed<<12)
			mag = (inst->speed<<12);

		cameo_cam_pos.vx -= (dvec.vx * mag) >> 12;
		cameo_cam_pos.vy -= (dvec.vy * mag) >> 12;
		cameo_cam_pos.vz -= (dvec.vz * mag) >> 12;
	}

}


void cameoCamSpin(CAMEO *cameo,CAMEO_CAM_SPININST *inst)
{
	VECTOR d;


	if(inst->timer == 1)
	{
		d.vx = cameo_cam_pos.vx - cameo_cam_targ.vx;
		d.vz = cameo_cam_pos.vz - cameo_cam_targ.vz;
		d.vy = 0;
		cameo_spin_angle = calc_angle(d.vx,d.vz) & 4095;
		cameo_spin_range = Magnitude(&d) >> 12;
	}

	cameo_spin_range = IntHomer(cameo_spin_range,inst->range,inst->speed);
	cameo_spin_angle += inst->spin;

//	printf("spin r=%d a=%d\n",cameo_spin_range,cameo_spin_angle);

	d.vx = (rsin(cameo_spin_angle) * cameo_spin_range);	// no need to shift down 12, coz range is a small that needs bigging
	d.vz = (rcos(cameo_spin_angle) * cameo_spin_range);
		
	cameo_cam_pos.vx = (cameo_cam_targ.vx + d.vx);
// leave the height alone
	cameo_cam_pos.vz = (cameo_cam_targ.vz + d.vz);
}

void cameoCamClaim(CAMEO *cameo,CAMEO_CAM_CLAIMINST *inst)
{
	if(inst->timer == 1)
	{
		cameo_cam_targ.vx = CamVars.camera.vrx << 12;
		cameo_cam_targ.vy = CamVars.camera.vry << 12;
		cameo_cam_targ.vz = CamVars.camera.vrz << 12;

		cameo_cam_pos.vx = CamVars.camera.vpx << 12;
		cameo_cam_pos.vy = CamVars.camera.vpy << 12;
		cameo_cam_pos.vz = CamVars.camera.vpz << 12;

	}

	CamVars.flags2 |= CAMFLAG_CAMEO_POS + CAMFLAG_CAMEO_TARG;
}

void cameoFxLightning(CAMEO *cameo,CAMEO_FX_LIGHTNINGINST *inst)
{
	cameo_litenin_pos[cameo_litenin_on*2].vx = inst->v1x;
	cameo_litenin_pos[cameo_litenin_on*2].vy = inst->v1y;
	cameo_litenin_pos[cameo_litenin_on*2].vz = inst->v1z;
	cameo_litenin_pos[cameo_litenin_on*2+1].vx = inst->v2x;
	cameo_litenin_pos[cameo_litenin_on*2+1].vy = inst->v2y;
	cameo_litenin_pos[cameo_litenin_on*2+1].vz = inst->v2z;
	cameo_litenin_on++;
}
void cameoFxFlash(CAMEO *cameo,CAMEO_FX_FLASHINST *inst)
{
// timer is passed on to the overlay code, & then fast-forwarded
	effectsStartOverlay(inst->duration, (inst->r<<16) | (inst->g<<8) | inst->b);
	inst->timer = inst->duration;	// strictly, should be "-1", but the limit check does ">=", so that's ok.
}

void cameoFxStarRing(CAMEO *cameo,CAMEO_FX_STARRINGINST *inst)
{
	VECTOR temp;
	temp.vx = inst->x << 12;
	temp.vy = inst->y << 12;
	temp.vz = inst->z << 12;

	New_StarRingDebris(&temp,inst->n);
}

void cameoFxLifeGlow(CAMEO *cameo,CAMEO_FX_LIFEGLOWINST *inst)
{
	VECTOR pos;
	pos.vx = (inst->x << 12) + rsin((sinewave1>>16) & 4095) * inst->rad;
	pos.vz = (inst->z << 12) + rcos((sinewave1>>16) & 4095) * inst->rad;
	pos.vy = (inst->y << 12) + rsin((sinewave2>>16) & 4095) * inst->hei;
	New_Debris(DEBRIS_LIFEGLOW,&pos,0);
}

void cameoFxFlameThrow(CAMEO *cameo,CAMEO_FX_FLAMETHROWINST *inst)
{
	VECTOR pos;
	if(!(inst->timer & 1))
	{
		pos.vx = (inst->x << 12);
		pos.vz = (inst->z << 12);
		pos.vy = (inst->y << 12);
		New_Debris(DEBRIS_FLAME,&pos,inst->direction + ((rsin(inst->timer << 8))>>6) );
	}
}

// ======================================================================================

// note this needs to come after "update puzzles" at the moment, because
// it's there that the camera-overrides-flag gets zeroed.

void cameoUpdateCameos()
{
	CAMEO *cameo;
	int num = 0;

	cameo_litenin_on = 0;
	cameo_spring_on = 0;
	CamVars.flags2 &= ~(CAMFLAG_CAMEO_POS + CAMFLAG_CAMEO_TARG);	// any cam-claim instrs will grab it

//	printf("glv %d %d %d\n",glovePos.vx>>12,glovePos.vy>>12,glovePos.vz>>12);

	for(cameo = cameolist;cameo;cameo = cameo->next)
	{
		if(cameo->timer)
		{
			UpdateCameo(cameo);
			num++;
		}
	}
	if(num)
		cameo_running = YES;
	else
		cameo_running = NO;
}

// for the odd occasion when the cameos need to draw something specific


void cameoDrawCameos()
{
	int i;
// note, it's draw-cameo's that enters with the matrix set to world, but
// can change it before exit
	for(i = 0; i < cameo_litenin_on; i++)
	{
		effectsDrawLightningStrand(&cameo_litenin_pos[i*2],&cameo_litenin_pos[i*2+1],0x808000);
		effectsDrawLightningStrand(&cameo_litenin_pos[i*2],&cameo_litenin_pos[i*2+1],0x808000);
	}

	if(spring_psa && cameo_spring_on)
	{
		objectSetAnimation(spring_psa,0);
		objectDraw(spring_psa);
	}

}

void UpdateCameo(CAMEO *cameo)
{
	int j;
	int still_running = 0;
	int num = 0;
	CAMEO_INST_GEN * inst;

	CAMEO_PRINTF("cam:");

	inst = &cameo->instrs[0];
	for(j = 0;j < cameo->num_instrs;j++)
	{
		if(inst->timer && !IS_INSTR_DONE(inst))
		{
			CAMEO_PRINTF("r");
			switch(inst->type)
			{
				case CAMEO_CAM_CLAIM:
					cameoCamClaim(cameo,(CAMEO_CAM_CLAIMINST *)inst);
					break;
				case CAMEO_CAM_SPIN:
					cameoCamSpin(cameo,(CAMEO_CAM_SPININST *)inst);
					break;
				case CAMEO_CAM_HEIGHT:
					cameoCamHeight(cameo,(CAMEO_CAM_HEIGHTINST *)inst);
					break;


				case CAMEO_CAM_TARGNME:
					cameoCamTargNme(cameo,(CAMEO_CAM_TARGNMEINST *)inst);
					break;
				case CAMEO_CAM_TARGPOS:
					cameoCamTargPos(cameo,(CAMEO_CAM_TARGPOSINST *)inst);
					break;
				case CAMEO_CAM_POS:
					cameoCamPos(cameo,(CAMEO_CAM_POSINST *)inst);
					break;
				case CAMEO_CAM_DRAG:
					cameoCamDrag(cameo,(CAMEO_CAM_DRAGINST *)inst);
					break;


				case CAMEO_NME_MOVETO:
					cameoNmeMoveto(cameo,(CAMEO_NME_MOVETOINST *)inst);
					break;
				case CAMEO_NME_FLYTO:
					cameoNmeFlyto(cameo,(CAMEO_NME_FLYTOINST *)inst);
					break;
				case CAMEO_NME_MOVEFORE:
					cameoNmeMoveFore(cameo,(CAMEO_NME_MOVEFOREINST *)inst);
					break;
				case CAMEO_NME_SPIN:
					cameoNmeSpin(cameo,(CAMEO_NME_SPININST *)inst);
					break;

				case CAMEO_NME_ANIM:
					cameoNmeAnim(cameo,(CAMEO_NME_ANIMINST *)inst);
					break;
				case CAMEO_NME_JUDDER:
					cameoNmeJudder(cameo,(CAMEO_NME_JUDDERINST *)inst);
					break;
				case CAMEO_NME_DOING:
					cameoNmeDoing(cameo,(CAMEO_NME_DOINGINST *)inst);
					break;

				case CAMEO_NME_AIM:
					cameoNmeAim(cameo,(CAMEO_NME_AIMINST *)inst);
					break;
				case CAMEO_NME_SCALE:
					cameoNmeScale(cameo,(CAMEO_NME_SCALEINST *)inst);
					break;
				case CAMEO_NME_ACTIVATE:
					cameoNmeActivate(cameo,(CAMEO_NME_ACTIVATEINST *)inst);
					break;

				case CAMEO_PLAT_MOVETO:
					cameoPlatMoveto(cameo,(CAMEO_PLAT_MOVETOINST *)inst);
					break;
				case CAMEO_FX_LIGHTNING:	// skipped for now...
					cameoFxLightning(cameo,(CAMEO_FX_LIGHTNINGINST *)inst);
					break;
				case CAMEO_FX_FLASH:
					cameoFxFlash(cameo,(CAMEO_FX_FLASHINST *)inst);
					break;
				case CAMEO_FX_STARRING:
					cameoFxStarRing(cameo,(CAMEO_FX_STARRINGINST *)inst);
					break;
				case CAMEO_FX_LIFEGLOW:
					cameoFxLifeGlow(cameo,(CAMEO_FX_LIFEGLOWINST *)inst);
					break;
				case CAMEO_FX_FLAMETHROW:
					cameoFxFlameThrow(cameo,(CAMEO_FX_FLAMETHROWINST *)inst);
					break;

				case CAMEO_CA_SPRING:
					cameoCaSpring(cameo,(CAMEO_CA_SPRINGINST *)inst);
					break;

				case CAMEO_PI_MONKEY:
					cameoPiMonkey(cameo,(CAMEO_PI_MONKEYINST *)inst);
					break;

				case CAMEO_SPELL:
					cameoSpell(cameo,(CAMEO_SPELLINST *)inst);
					break;

				case CAMEO_SFX:
					cameoSfx(cameo,(CAMEO_SFXINST *)inst);
					break;


				case CAMEO_LEVELEND:	// as used on the space boss final cameo
					MenuFadeOut();	// immediate fade
//					gameCtrl.nextLevel = HUB8;
					NextLevelBasics();
					gameCtrl.dropOutFlag=GAME_COMPLETED;
					break;
				default:
					break;

			}

			if(!IS_INSTR_DONE(inst))
			{
				inst->timer++;
				if(inst->timer >= inst->duration)
				{
					SET_INSTR_DONE(inst);
				}
			}
		}
#ifdef CAMEO_DISPLAY
		else
		{
			if(!inst->timer)
				CAMEO_PRINTF("-");
			else
				CAMEO_PRINTF("X");
		}
#endif

		inst++;
	}

	CAMEO_PRINTF("\n");


	inst = &cameo->instrs[0];
	for(j = 0;j < cameo->num_instrs;j++)
	{
		if(!IS_INSTR_DONE(inst))
		{
			still_running = 1;
		}

		if(!inst->timer)
		{
			if(
				((inst->start > -1) && (inst->start == cameo->timer))
				||
				((inst->start < -1) && IS_INSTR_DONE(&cameo->instrs[-inst->start]))
			  )
			{
				CAMEO_PRINTF("Triggering Cameo Action %i\n",j);
				inst->timer = 1;
				num++;
			}
		}

		inst++;
	}

	if(!still_running)
	{
		DB("end of cameo\n");
		cameo->timer = 0;

		CamVars.flags &= ~(FIXEDLOOKAT);

	}
	else
	{
		cameo->timer++;
		GloveCtrl.padDisableTimer = 2;
//		GloveCtrl.disableTimer = 2;
//		DisableControl(2);	// disable hand control for the next couple of ticks
	}
}

// ======================================================================================


