/******************************************************************************************
	CRTEST PS   (c) 1999-2001 ISL

	puzzles.h:			Puzzle stuff
******************************************************************************************/


// NB NB NB - This header is also loaded by cr_lev
// (so be careful about referring to any non-puzzly structures)

#ifndef _PUZZLES_H_
#define _PUZZLES_H_


#ifndef __LIGHTS_H__
#include "lights.h"
#endif

typedef struct TAGACTION_VECTOR
{
	int posx;
	int posy;
	int posz;
	int extra;
}STRACTION_VECTOR;

// Used for speed and existence
typedef struct TAGACTION_SETOBJECTPARAMETER
{
// Target-type is filled in postload,
// once we've established whether we're talking about a platform, or a tex-anim,
	int target_type;
	void *target;	// filled in postload to match the tag
	int tag;
	int value;
}STRACTION_SETOBJECTPARAMETER;


#define TARGET_IS_TEXANIM	1
#define TARGET_IS_PLATFORM	2
#define TARGET_IS_LANDSCAPE	3
#define TARGET_IS_LIGHT		4
#define TARGET_IS_SCENIC	5
#define TARGET_IS_ENEMY		6

#define	TARGET_IS_VENT		7


#define PUZZLE_DSEVENT_BUZZER	(1)
#define PUZZLE_DSEVENT_MOTOR	(2)
#define PUZZLE_DSEVENT_QUEUE	(4)


typedef struct TAGACTION_FOURSHORTS
{
	short values[4];
}STRACTION_FOURSHORTS;

typedef struct TAGACTION_FIVESHLONGS
{
	long values[5];
}STRACTION_FIVESHLONGS;

typedef struct TAGACTION_SETVAR
{
	unsigned int variable_no;
	int value;
}STRACTION_SETVAR;
typedef struct TAGACTION_TASK_COMPLETED
{
	unsigned int what;
	int yesno;
}STRACTION_TASK_COMPLETED;
typedef struct TAGACTION_GOTO_LEVEL
{
// note - we have 13-character level names
	char level_name[16];	// Coo, this isn't a CRC, for fairly obvious reasons
	int position_marker_tag;
	int level_number;
}STRACTION_GOTO_LEVEL;

typedef struct TAGACTION_SET_SCENIC_ANIM
{
	int tag;
	void *target;

	short anim;
	short dummy;	// RFW - dummy added 22 Aug 00. This was screwing up scenic anims when Tom compiled it up

	int flags;	// 255 of blending, plus loop & queue flags on top
	int target_type;
}STRACTION_SET_SCENIC_ANIM;

#define LEADACTIONFLAG_RESTORE 1
typedef struct TAGACTION_LEAD_ACTION
{
	int posmark_tag;
	void *target;

	unsigned char anim;
	unsigned char flags;
	unsigned char dummyc2;
	unsigned char dummyc3;

	int speed;

	int dummy1;
	int dummy2;
}STRACTION_LEAD_ACTION;

enum
{
	USEOBJECT_MECHANISM_MANUAL,		// Calls the inventory_use, with the equipped item, when you press X
	USEOBJECT_MECHANISM_EQUIPPED	// Calls the inventory_use routine, with the equipped item, when the condition is JUST met, OR when you press X
};

typedef struct TAGACTION_OBJECT_USABLE
{
	int mechanism;
	int dummy[4];
}STRACTION_OBJECT_USABLE;

typedef struct TAGACTION_PLAY_SAMPLE
{
	unsigned long crc;
	long tag;
	short vol;
	short state;
}STRACTION_PLAY_SAMPLE;


typedef struct TAGCONDITION_IN_BOX
{
	int posx;
	int posy;
	int posz;
	int sizex;
	int sizey;
	int sizez;


	char yes;
	char dummy[3];
}STRCONDITION_IN_BOX;
typedef struct TAGCONDITION_BUTTON_PRESSED
{
	int button;
	int pad;
	int yesno;
}STRCONDITION_BUTTON_PRESSED;
typedef struct TAGCONDITION_OBJECTPARAMETER
{
	int target_type;	// filled in post-load
	void *target;
	int tag;
	int value;
}STRCONDITION_OBJECTPARAMETER;
typedef struct TAGCONDITION_TASK_COMPLETED
{
	unsigned int what;
	int yesno;
}STRCONDITION_TASK_COMPLETED;
typedef struct TAGCONDITION_NEAR_POINT
{
	int posmark_tag;
	int posx;
	int posy;
	int posz;
	int range;
	int	face_angle;	// 0 means doesn't matter

	char yes;
	char dummy[3];
}STRCONDITION_NEAR_POINT;

enum
{
	CONDVAR_EQUAL,
	CONDVAR_NEQUAL,
	CONDVAR_GREATER,
	CONDVAR_LESS
};
typedef struct TAGCONDITION_VARIABLE
{
	int variable_no;
	int value;
	int what;
}STRCONDITION_VARIABLE;

typedef struct TAGACTION
{
	short	timer;
	short	delay;
	short	type;
	short	flags;	// these go up to "1<<11"
	union
	{
		STRACTION_VECTOR				vector;
		STRACTION_FOURSHORTS			fourshorts;
		STRACTION_SETVAR				setvar;
		STRACTION_GOTO_LEVEL			gotolevel;
		STRACTION_SETOBJECTPARAMETER	setobjparam;
		STRACTION_SET_SCENIC_ANIM		scenicanim;
		STRACTION_TASK_COMPLETED		task;
		STRACTION_OBJECT_USABLE			usable;
		STRACTION_LEAD_ACTION			lead;
		STRACTION_PLAY_SAMPLE			playsample;
		STRACTION_FIVESHLONGS			fivelongs;
	}data;
}ACTION;
typedef struct TAGCONDITION
{
	UBYTE	type;
	char dummy[3];
	union
	{
		STRCONDITION_IN_BOX				in_box;
		STRCONDITION_BUTTON_PRESSED		button_pressed;
		STRCONDITION_OBJECTPARAMETER	objparam;
		STRCONDITION_TASK_COMPLETED		task;
		STRCONDITION_NEAR_POINT			nearpoint;
		STRCONDITION_VARIABLE			varval;
	}data;
}CONDITION;

typedef struct TAGPUZZLE
{
	struct TAGPUZZLE	*next;

	unsigned char		numconditions;

	unsigned char		andor:1;
	unsigned char		just:1;
	unsigned char		justyesno:1;
	unsigned char		oldjust:1;
	unsigned char		dummyflag:4;

	short				numtimes;
	CONDITION			*conditions;

	short				numactions;
	short				checkactions;

	ACTION				*actions;
}PUZZLE;


// Note for future reference!
// Add new conditions to the END of the list! (Otherwise existing levels get horribly confused)
enum
{
	CONDITION_PLAYER_IN_BOX,
	CONDITION_BUTTON_PRESSED,
	CONDITION_OBJECT_ENABLED,

	CONDITION_TASK_COMPLETED,
	CONDITION_AT_POINT,

	CONDITION_NEAR_POINT,
	CONDITION_FROM_TIME,

	CONDITION_SWITCH_STATE,
	CONDITION_SWITCH_JUST_ON,
	CONDITION_SWITCH_JUST_OFF,

	CONDITION_VARIABLE_VALUE,
	CONDITION_STARTED_AT,
	CONDITION_CHECK_STATUS,

	CONDITION_RANDOM,

	NUM_CONDITION_TYPES
};

// Note for future reference!
// Add new actions to the END of the list! (Otherwise existing levels get horribly confused)
enum
{
	ACTION_CAMERA_SNAPTO,
	ACTION_CAMERA_MOVETO,
	ACTION_CAMERA_LOOK_SNAPTO,
	ACTION_CAMERA_LOOK_MOVETO,
	ACTION_SET_ADDITIONAL_DISTANCE,
	ACTION_SET_ADDITIONAL_HEIGHT,
	ACTION_SET_CAMERA_ANGLE,
	ACTION_SET_RAILCAM_ALIGNED,
	ACTION_SET_FOLLOW_CAM,

	ACTION_SET_VARIABLE,
	ACTION_SET_PLATFORM_SPEED,
	ACTION_GOTO_LEVEL,
	ACTION_SET_EXISTENCE,
	ACTION_SET_SORTDEPTH,
	ACTION_SET_TEXANIM_SPEED,
	ACTION_SET_CONVEYOR_SPEED,

	ACTION_SET_TERRAIN,
	ACTION_SET_SCENIC_ANIM,

	ACTION_SET_CAMERA_SWEEP,
	ACTION_SET_RAILCAM_NONALIGNED,

	ACTION_TASK_COMPLETED,
	ACTION_LIGHT_ALERT,
	ACTION_OBJECT_USABLE,
	ACTION_SET_SWITCH_STATE,

	ACTION_SET_PLATFORM_SPINSPEED,
	ACTION_SET_PLATFORM_POINT,
	ACTION_SET_LEAD_ACTION,
	ACTION_SET_HUT_CAM,
	ACTION_SET_SAMPLE_STATE,
	ACTION_SET_CAMERA_ANGLE_START,
	ACTION_SET_DS_EVENT,
	NUM_ACTION_TYPES
};


#define CONDITION_AND	0
#define CONDITION_OR	1

#define CONDITION_JUSTNOT	0
#define CONDITION_JUSTYES	1
#define CONDITION_JUSTNO	2


#define ACTION_RANDOMISE_DELAY			(1<<9)	// "action_special" in glover, with the same purpose

enum
{
	COND_CHECKSTATUS_CHICKENCONTROL,
};

#define MAX_PUZZLE_VARS 64
typedef struct PUZZLEVARSSTR
{
	PUZZLE *puzzles;

	char usable_object_area;
	char dummy[3];

	int n_vars;
	int var_crcs[MAX_PUZZLE_VARS];
	int variables[MAX_PUZZLE_VARS];
}PUZZLEVARSSTR;




#define BFF_PUZ_ID (('P'<<0) | ('U'<<8) | ('Z'<<16) | (0<<24))

typedef struct TAGPUZZLIST
{
	unsigned long id;			// standard BFF header
	unsigned long len;
	unsigned long name_crc;

	struct TAGPUZZLE *puzzles;	// (offset or pointer) to puzzle linked list
}PUZZ_LIST;



extern PUZZLEVARSSTR PuzzleVars;
void puzzleInitLevel();
void puzzleLinkBFF(PUZZ_LIST *lev);

void puzzleCheckPuzzles();

// The last thing that happens before the level starts running...
void puzzleRestorePuzzleState();
// And the thing that happens before shutting the level down
void puzzleSavePuzzleState();






// ========= This could use its own header file at some point ==============

#define BFF_LEVINFO_ID (('L'<<0) | ('E'<<8) | ('V'<<16) | (5<<24))

#define POSMARKFLAG_IS_INTERESTING	1
typedef struct POSMARK
{
	int x,y,z;	// Note - this IS cast to (VECTOR *) for maths purposes
	short ya;
	short flags;
	int tag;
}POSMARK;


typedef struct tag_VENT
{
	int	x,y,z;
	int	vx,vy,vz;
	int	type;
	int	decay;
	int	emit;
	int	height;
	int	scale;
	int	tag,flags;
}VENT;

extern VENT	*vents;
extern int		n_vents;

#define LEVINFO_CHARACTERS_CURRENTCHICKEN	1
#define	LEVINFO_CHARACTERS_OTHERCHICKEN		2
#define	LEVINFO_CHARACTERS_RATS				4

#define LEVINFO_TESTCHAR_GINGER		0
#define	LEVINFO_TESTCHAR_ROCKY		1
#define	LEVINFO_TESTCHAR_NICK		2
#define	LEVINFO_TESTCHAR_FETCHER	3

enum {
	LEVNUMBER_UNSPECIFIED,	// eg - all testlevels

	LEVNUMBER_A1_HUT17,
	LEVNUMBER_A1_FOWLER,
	LEVNUMBER_A1_WORKHUT1,
	LEVNUMBER_A1_EGGHUT,
	LEVNUMBER_A1_COOP1_N,
	LEVNUMBER_A1_HOUSEXT_N,
	LEVNUMBER_A1_GARDEN_N,
	LEVNUMBER_A1_DOGCHASE,

	LEVNUMBER_A2_HUT17,
	LEVNUMBER_A2_FOWLER,
	LEVNUMBER_A2_WORKHUT1,
	LEVNUMBER_A2_EGGHUT,
	LEVNUMBER_A2_COOP1_D,
	LEVNUMBER_A2_HOUSEXT_D,
	LEVNUMBER_A2_GARDEN_D,
	LEVNUMBER_A2_COOP2_D,
	LEVNUMBER_A2_EGGROOM,
	LEVNUMBER_A2_WORKHUT2,
	LEVNUMBER_A2_ENGINEHUT,
	LEVNUMBER_A2_SCENIC1,
	LEVNUMBER_A2_SCENIC2,
	LEVNUMBER_A2_COOP3_D,
	LEVNUMBER_A2_WORKHUT3,
	LEVNUMBER_A2_WINGSHUT,
	LEVNUMBER_A2_SCENIC3,
	LEVNUMBER_A2_SCENIC4,
	LEVNUMBER_A2_TOOLEXT_D,
	LEVNUMBER_A2_BARNEXT_D,
	LEVNUMBER_A2_OLDBARN_D,
	LEVNUMBER_A2_TOOLSHED_D,
	LEVNUMBER_A2_FIREWORKS,
	LEVNUMBER_A2_CATAPULT,
	LEVNUMBER_A2_SEESAW,
	LEVNUMBER_A2_VANCHASE,
	LEVNUMBER_A2_COGCHASE,

	LEVNUMBER_A3_BLADEROOM,
	LEVNUMBER_A3_CLAWGAME,
	LEVNUMBER_A3_GRAVYROOM,
	LEVNUMBER_A3_GRAVYGUN,
	LEVNUMBER_A3_CONVEYORS,
	LEVNUMBER_A3_PIEGAME,
	LEVNUMBER_A3_COGCHASE,

	LEVNUMBER_A4_HUT17,
	LEVNUMBER_A4_FOWLER,
	LEVNUMBER_A4_WORKHUT1,
	LEVNUMBER_A4_EGGHUT,
	LEVNUMBER_A4_COOP1_N,
	LEVNUMBER_A4_HOUSEXT_N,
	LEVNUMBER_A4_GARDEN_N,
	LEVNUMBER_A4_KITCHEN,
	LEVNUMBER_A4_LOUNGE,
	LEVNUMBER_A4_EGGROOM,
	LEVNUMBER_A4_PIEBARN,
	LEVNUMBER_A4_COOP2_N,
	LEVNUMBER_A4_WORKHUT2,
	LEVNUMBER_A4_ENGINEHUT,
	LEVNUMBER_A4_SCENIC1,
	LEVNUMBER_A4_SCENIC2,
	LEVNUMBER_A4_COOP3_N,
	LEVNUMBER_A4_WORKHUT3,
	LEVNUMBER_A4_WINGSHUT,
	LEVNUMBER_A4_SCENIC3,
	LEVNUMBER_A4_SCENIC4,
	LEVNUMBER_A4_COOP4_N,
	LEVNUMBER_A4_WORKHUT4,
	LEVNUMBER_A4_CONSTRUCT,
	LEVNUMBER_A4_SCENIC5,
	LEVNUMBER_A4_SCENIC6,
	LEVNUMBER_A4_TOOLEXT_N,
	LEVNUMBER_A4_BARNEXT_N,
	LEVNUMBER_A4_OLDBARN_N,
	LEVNUMBER_A4_TOOLSHED_N,
	LEVNUMBER_A4_TOOLSHED_A,
	LEVNUMBER_A4_TUNNEL,
	LEVNUMBER_A4_FLYMACHINE,

	LEVNUMBER_TRAINING_1,
	LEVNUMBER_TRAINING_2,
	LEVNUMBER_TRAINING_3,
	LEVNUMBER_TRAINING_4,
	LEVNUMBER_TRAINING_5,
	LEVNUMBER_TRAINING_6,
	LEVNUMBER_TRAINING_7,
	LEVNUMBER_TRAINING_8,


	LEVNUMBER_NUM_LEVELS
};

typedef struct LEVINFO
{
	unsigned long id;		// Standard BFF header
	unsigned long len;
	unsigned long crc;

	int n_posmarks;
	POSMARK *posmarks;	// offset for post-load conversion


	unsigned int ambient_colour;

//	int n_box_lights;
//	BOXLIGHT *boxlights;

	int n_lights;
	EXLIGHT_TYPE *lights;

	int		n_vents;
	VENT	*vents;

	int initial_fov;

	int	initial_cam_distance;
	int	initial_cam_height;

	int	cam_start_angle;
	int	cam_transition_speed;

	char	characters_here;
	char	testing_character;
	char	level_number;
	char	tune_number;	// = (XA track * 8) + channel. Not Rob Lord's tune number. Lookup's in CR_LEV::Levinfo.c. Also Fowler's will need to be act-dependant.

	unsigned int bg_colour;

	unsigned int dummies[7];

}LEVINFO;

//	Added for camera cases
#define BFF_CAMINFO_ID (('C'<<0) | ('A'<<8) | ('M'<<16) | (0<<24))

typedef struct RAILDATA
{
	int	pointX,pointY,pointZ;
}RAILDATA;

typedef struct RAILRECORD
{
	RAILDATA*	data;
}RAILRECORD;



typedef struct CASEDATA
{
	int	camX,camY,camZ;
	int	viewX,viewY,viewZ;	
}CASEDATA;

typedef struct CASERECORD
{
	CASEDATA	data[8];
}CASERECORD;

typedef struct tagCAMINFO
{
	unsigned long id;		// Standard BFF header
	unsigned long len;
	unsigned long crc;
	unsigned long numCases;
	CASERECORD	*rec;
	unsigned long numRailCases;
	unsigned long numRails[10];
	//RAILRECORD	*rail;
	RAILDATA	*data;

}CAMINFO;




void levinfoLinkBFF(LEVINFO *info);

extern LEVINFO *levinfo;
POSMARK *levinfoFindMarker(int tag);
int levinfoGetAct(int level);
void levinfoSetupBackground();
void posmarkFindInteresting(VECTOR *character_pos, int character_dir, VECTOR **best, int *max_range);

#endif
