


#ifndef __PUZZLES_H__
#define __PUZZLES_H__


// ============== Variables for other rous to pick up on ============

typedef struct TAGPUZZLEVARS
{
	char any_camera_overrides;

	char camera_parallel_flag;

	int camera_additional_distance;
	int camera_additional_height;
	int camera_fixed_endtime; // uses iframe
	int user_variables[32];	// level-specific veriables for easy feature-adding

	char ball_trigger;	// Action teleport needs to know which it was that caused the action
	char hand_trigger;
}PUZZLEVARS;
extern PUZZLEVARS PuzzleVars;

// =================== Enums =========================

#define CONDITION_AND	0
#define CONDITION_OR	1

enum
{
	ACTION_START_MOVE,		//0
	ACTION_START_SPIN,		//1
	ACTION_START_ORBIT,		//2
	ACTION_SET_NEXT_POINT,	//3
	ACTION_SET_NEXT_SPIN,	//4
	ACTION_SET_SPIN_WAIT,	//5
	ACTION_SET_SPIN_AXIS,	//6
	ACTION_SET_STATE,		//7

	ACTION_SET_CONVEYOR,	//8
	ACTION_SET_EXISTANCE,	//9
	ACTION_SET_GRAVITY,		//10
	ACTION_SET_VAR,			//11
	ACTION_ADDTO_VAR,		//12
	ACTION_SUBFROM_VAR,		//13
	ACTION_DROP_PICKUP,		//14
	ACTION_ADD_NME,			//15

	ACTION_MOVE_PLAT,		//16
	ACTION_LOOK_AT_PLAT,	//17
	ACTION_LOOK_AT_POINT,	//18
	ACTION_SET_CAMERA_POS,	//19
	ACTION_SET_CAM_DIST,	//20
	ACTION_SET_CAM_HEIGHT,	//21
	ACTION_NME_GOTO_ACTION,	//22
	ACTION_SET_WIND,		//23

	ACTION_DROP_GARIBS,		//24
	ACTION_CAM_HEIGHT,		//25
	ACTION_CAM_DISTANCE,	//26
	ACTION_CAM_PARALLEL,	//27
	ACTION_CAM_FIXEDPOS,	//28
	ACTION_CAM_FIXEDROT,	//29
	ACTION_CAM_CORNER,		//30
	ACTION_CAM_IGNORE_SLOPES,//31

	ACTION_CAM_CIRCLE,		//32
	ACTION_SET_WATERLEVEL,	//33
	ACTION_EARTHQUAKE,		//34
	ACTION_SET_LEVEL_GRAVITY,//35
	ACTION_START_CAMEO,		//36
	ACTION_SET_PLAT_DIR,	//37
	ACTION_UNFREEZE_BALL,	//38
	ACTION_START_SOUND,		//39

	ACTION_SET_BACKDROP,	//40
	ACTION_SET_FOG,			//41
	ACTION_ADD_TO_SCORE,	//42
	ACTION_SET_TERRAIN,		//43
	ACTION_DESTROY,			//44
	ACTION_TELEPORT_TO,		// 45
	ACTION_DUMMY1,			// 46
	ACTION_DUMMY2,			// 47
	ACTION_DUMMY3,
	ACTION_DUMMY4,
	NUM_ACTION_TYPES
};

enum
{
	CONDITION_AT_POINT,			//0
	CONDITION_AT_SPIN,			//1
	CONDITION_AT_ORBIT,			//2
	CONDITION_JUST_AT_POINT,	//3
	CONDITION_JUST_AT_SPIN,		//4
	CONDITION_JUST_AT_ORBIT,	//5
	CONDITION_HAND_ON,			//6
	CONDITION_HAND_JUST_ON,		//7

	CONDITION_BALL_ON,			//8
	CONDITION_BALL_JUST_ON,		//9
	CONDITION_NME_ON,			//10
	CONDITION_NME_JUST_ON,		//11
	CONDITION_HAND_TOUCHING,	//12
	CONDITION_HAND_JUST_TOUCHED,	//13
	CONDITION_BALL_TOUCHING,		//14
	CONDITION_BALL_JUST_TOUCHED,	//15

	CONDITION_NME_TOUCHING,			//16
	CONDITION_NME_JUST_TOUCHED,		//17
	CONDITION_VAR_EQUAL,			//18
	CONDITION_VAR_NOT_EQUAL,		//19
	CONDITION_VAR_GREATER_THAN,		//20
	CONDITION_VAR_LESS_THAN,		//21
	CONDITION_CONFINED,				//22
	CONDITION_JUST_CONFINED,		//23

	CONDITION_NME_DEAD,				//24
	CONDITION_HAND_CROSSES_LINE,	//25
	CONDITION_HAND_IN_BOX,			//26
	CONDITION_HAND_IN_RANGE,		//27
	CONDITION_BALL_IN_BOX,			//28
	CONDITION_BALL_IN_RANGE,		//29
	CONDITION_CAM_IN_BOX,			//30
	CONDITION_CAM_IN_RANGE,			//31

	CONDITION_HAND_IN_CYLINDER,		//32
	CONDITION_DESTROYED,			//33
	CONDITION_COLLECTED,			//34
	CONDITION_PICKUP_ON,			//35
	CONDITION_JUST_AT_ROT,			//36
	CONDITION_DUMMY0,				//37
	CONDITION_DUMMY1,
	CONDITION_DUMMY2,
	CONDITION_DUMMY3,
	CONDITION_DUMMY4,
	NUM_CONDITION_TYPES
};



#define ACTION_GO_ONE_CYCLE		(1<<0)
#define ACTION_GO_ONE_STEP		(1<<1)
#define ACTION_GO_NOW			(1<<2)
#define	ACTION_SET_FAN			(1<<3)
#define ACTION_SET_TELEPORT		(1<<4)
#define ACTION_SET_CATAPULT		(1<<5)
#define ACTION_SET_ELECTRIC		(1<<6)
#define ACTION_USE_VAR			(1<<7)
#define ACTION_SET_VENT			(1<<8)
#define ACTION_SPECIAL			(1<<9)
#define ACTION_SET_BUZZER		(1<<10)
#define ACTION_STOPPED			(1<<11)


// =================== Actions =======================
/*
typedef struct TAGACTION_DROP_GARIBS
{
	char times;	// number of times to do the drop (!?)
	char group;
	SHORT yval;	// if not zero, place at this yvalue
}STRACTION_DROP_GARIBS;
*/
typedef struct TAGACTION_AMOUNT
{
	int value;	// on occasion, this can fill an int (action_set_backdrop)
}STRACTION_AMOUNT;

/*
typedef struct TAGACTION_START_MOVE
{
	unsigned char flags;
	unsigned char platform_tag;
	SHORT max_speed;
}STRACTION_START_MOVE;
*/

typedef struct TAGACTION_VECTOR_TV
{
	SVECTOR vec;
	SHORT value;
	SHORT tag;
	DYNCOLLBOX *pBox;
//	SHORT flags;
}STRACTION_VECTOR_TV;

typedef struct TAGACTION_QUAKE
{
	SHORT info[4];
	SHORT value;
	SHORT tag;
//	SHORT flags;
}STRACTION_QUAKE;

typedef struct TAGACTION_SOUND
{
	SHORT info[6];
	SVECTOR vec;
	SHORT value;
	SHORT tag;
}STRACTION_SOUND;

typedef struct TAGACTION_VECTOR
{
	SVECTOR vec;
}STRACTION_VECTOR;

typedef struct TAGACTION_FOG
{
	SHORT info[5];
}STRACTION_FOG;

typedef struct TAGACTION_FIXEDROT
{
	SHORT value;
	SHORT speed;
}STRACTION_FIXEDROT;

typedef struct TAGACTION_VAL_TAG_FLAGS
{
	int value;
	SHORT tag;

	char found;

	DYNCOLLBOX *pBox;
	ENEMYPOS *nme;

//	SHORT flags;
}STRACTION_VAL_TAG_FLAGS;

typedef struct TAGACTION_DESTRUCT
{
	void	*pModel;
	short	pieces;
	short	tag;
}STRACTION_DESTRUCT;

typedef struct TAGACTION_TELEPORT
{
	VECTOR	dest;
	short	flags;
	short	disappear;
	short	appear;
}STRACTION_TELEPORT;


// examples from LND files
//  ACTION DROP_GARIBS  3 0.000000 0 0 
//  ACTION START_MOVE  35 1.000000 6 10 
//  ACTION START_MOVE  50 1.000000 6 10 
//  ACTION SET_CAMERA_POS  0 0.000000 218.000000 297.000000 -2216.000000 0 0 
//  ACTION LOOK_AT_POINT  0 70.000000 91.000000 242.000000 -2632.000000 0 0 


typedef struct TAGACTION
{
	short	timer;
	short	delay;
	short	type;
	short	flags;	// these go up to "1<<11"
	union
	{
// twelves
		STRACTION_VECTOR_TV			vector_tv;
		STRACTION_VAL_TAG_FLAGS		val_tag_flags;
		STRACTION_QUAKE				quake;

// chris's destruct thing
		STRACTION_DESTRUCT			destruct;

// twos
		STRACTION_VECTOR			vector;
		STRACTION_AMOUNT			amount;
		STRACTION_SOUND				sound;
		STRACTION_FOG				fog;
		STRACTION_FIXEDROT			fixedrot;
		STRACTION_TELEPORT			teleport;


//		STRACTION_DROP_GARIBS		drop_garibs;
//		STRACTION_DISTANCE			distance;
//		STRACTION_START_MOVE		start_move;
//		STRACTION_SET_CAMERA_POS	set_camera_pos;
//		STRACTION_LOOK_AT_POINT		look_at_point;
	}data;
}ACTION;


// =================== Conditions =======================

// The n64 source for this one always returns false...
typedef struct TAGCONDITION_TAG
{
	short tag;
	DYNCOLLBOX *pBox;	// deduced from "tag" first time round the loop
}STRCONDITION_TAG;

// check = 0,1: garibs, 2:any uncollected from a given group, 3:all collected from a given group
// (most of the conditions are just a garib/platform tag, and a detailed "check type" value (usually 0/1 for "not" condition)
// (at point/just at point use "check" as a path-point number
typedef struct TAGCONDITION_TAGCHECK
{
	short tag;
	short check;
	DYNCOLLBOX *pBox;	// deduced from "tag" first time round the loop
	ENEMYPOS *nme;

}STRCONDITION_TAGCHECK;

// hand in box, ball in box, camera in box
typedef struct TAGCONDITION_IN_BOX
{
	SVECTOR pos;
	SVECTOR size;
	char yes;
}STRCONDITION_IN_BOX;
typedef struct TAGCONDITION_IN_RANGE
{
	SVECTOR pos;
	SHORT range;
}STRCONDITION_IN_RANGE;
typedef struct TAGCONDITION_IN_CYLINDER
{
	SVECTOR pos;
	SHORT radius;
	SHORT height;
}STRCONDITION_IN_CYLINDER;
typedef struct TAGCONDITION_CROSSES_LINE
{
	SVECTOR p1;
	SVECTOR p2;
	SHORT swing;
}STRCONDITION_CROSSES_LINE;

// used for "at point" and "just at point"
/*
typedef struct TAGCONDITION_AT_POINT
{
	unsigned char platform_tag;
	short path_point;
}STRCONDITION_AT_POINT;
*/

typedef struct TAGCONDITION
{
	UBYTE	type;
	union
	{
		STRCONDITION_TAG			tag;
		STRCONDITION_TAGCHECK		tagcheck;
		STRCONDITION_IN_BOX			in_box;
		STRCONDITION_IN_CYLINDER	in_cylinder;
		STRCONDITION_IN_RANGE		in_range;
		STRCONDITION_CROSSES_LINE	crosses_line;
//		STRCONDITION_AT_POINT		at_point;
	}data;
}CONDITION;

//  CONDITION DESTROYED  76 0 
//  CONDITION HAND_IN_BOX  -307.000000 28.000000 -416.932190 608.419189 142.795013 423.932190 
//  CONDITION JUST_AT_POINT  153 1 


// =================== Top-Level stuff =======================

// we don't want a linked list, we want a structure that's loaded as part of a LEV
typedef struct TAGPUZZLE
{
	struct TAGPUZZLE	*next;

	unsigned char		numconditions;
	unsigned char		andor;
	short				numtimes;
	CONDITION			*conditions;

	short				numactions;
	short				checkactions;

	ACTION				*actions;
}PUZZLE;

// =================== prototypes =======================

// beginning & end of the file-parse
void puzzleBeginFile();
void puzzleEndFile();

// after the end of playing the level
void puzzleFreePuzzles();

// during the file parse
int puzzleParseTokenPuzzle(short token,UBYTE **data);

// sometime during the update
// (note that it puts (ummm, will put) in requests to change the camera pos/dist, so
// within the rendering code wouldn't be a good idea)
void puzzleCheckPuzzles();

void puzzleSetExistence(int tag, int value);
void puzzleCreatePickup(int type, VECTOR *pPos);
void puzzleStartMove(int tag, int flags, int value);
void puzzleStartSpin(int tag, int value);
int  puzzleJustAtPoint(DYNCOLLBOX *, int);
int puzzleAtPoint(DYNCOLLBOX *pBox, int point);

extern PUZZLE *puzzles;

#endif

