//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/doors.h                                                  $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 6:47 PM                                               $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// Doors are environment objects that slide open when activated by triggers
// or when used by the player.
//

#ifndef __DOORS_H__
#define __DOORS_H__

#include "g_local.h"
#include "entity.h"
#include "trigger.h"
#include "scriptslave.h"

extern Event EV_Door_TryOpen;
extern Event EV_Door_GoDown;
extern Event EV_Door_GoUp;
extern Event EV_Door_HitBottom;
extern Event EV_Door_HitTop;
extern Event EV_Door_Fire;
extern Event EV_Door_Link;
extern Event EV_Door_SetSpeed;
extern Event EV_Door_Lock;
extern Event EV_Door_Unlock;

class Door;
typedef SafePtr<Door> DoorPtr;

class Door : public ScriptSlave
{
protected:
	str sound_stop;
	str sound_move;
	str sound_message;
	str sound_locked;
	float lastblocktime;
	float angle;
	Vector dir;
	Vector doormin;
	Vector doormax;
	float diropened;
	int state;
	int previous_state;
	int trigger;
	int nextdoor;
	DoorPtr master;

	void            OpenEnd( Event* ev );
	void            CloseEnd( Event* ev );
	void            Close( Event* ev );
	void            Open( Event* ev );
	void            DoorUse( Event* ev );
	void            DoorFire( Event* ev );
	void            DoorBlocked( Event* ev );
	void            FieldTouched( Event* ev );
	void            TryOpen( Event* ev );
	void            SpawnTriggerField( Vector fmins, Vector fmaxs );
	qboolean        DoorTouches( Door* e1 );
	void            LinkDoors( Event* ev );
	void            SetTime( Event* ev );
	void            LockDoor( Event* ev );
	void            UnlockDoor( Event* ev );

public:
	CLASS_PROTOTYPE( Door );

	qboolean locked;

	Door();
	qboolean        isOpen( void );
	qboolean        CanBeOpenedBy( Entity* ent );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void Door::Archive( Archiver& arc )
{
	ScriptSlave::Archive( arc );

	arc.WriteString( sound_stop );
	arc.WriteString( sound_move );
	arc.WriteString( sound_message );
	arc.WriteString( sound_locked );
	arc.WriteFloat( lastblocktime );
	arc.WriteFloat( angle );
	arc.WriteVector( dir );
	arc.WriteVector( doormin );
	arc.WriteVector( doormax );
	arc.WriteFloat( diropened );
	arc.WriteInteger( state );
	arc.WriteInteger( previous_state );
	arc.WriteInteger( trigger );
	arc.WriteInteger( nextdoor );
	arc.WriteSafePointer( master );
	arc.WriteBoolean( locked );
}

inline void Door::Unarchive( Archiver& arc )
{
	ScriptSlave::Unarchive( arc );

	arc.ReadString( &sound_stop );
	arc.ReadString( &sound_move );
	arc.ReadString( &sound_message );
	arc.ReadString( &sound_locked );
	lastblocktime = arc.ReadFloat();
	angle = arc.ReadFloat();
	arc.ReadVector( &dir );
	arc.ReadVector( &doormin );
	arc.ReadVector( &doormax );
	diropened = arc.ReadFloat();
	state = arc.ReadInteger();
	previous_state = arc.ReadInteger();
	trigger = arc.ReadInteger();
	nextdoor = arc.ReadInteger();
	arc.ReadSafePointer( &master );
	locked = arc.ReadBoolean();
}


class SlidingDoor : public Door
{
protected:
	float totalmove;
	float lip;
	Vector pos1;
	Vector pos2;

public:
	CLASS_PROTOTYPE( SlidingDoor );

	void     DoOpen( Event* ev );
	void     DoClose( Event* ev );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );

	SlidingDoor();
};

inline void SlidingDoor::Archive( Archiver& arc )
{
	Door::Archive( arc );

	arc.WriteFloat( totalmove );
	arc.WriteFloat( lip );
	arc.WriteVector( pos1 );
	arc.WriteVector( pos2 );
}

inline void SlidingDoor::Unarchive( Archiver& arc )
{
	Door::Unarchive( arc );

	totalmove = arc.ReadFloat();
	lip = arc.ReadFloat();
	arc.ReadVector( &pos1 );
	arc.ReadVector( &pos2 );
}

class RotatingDoor : public Door
{
protected:
	float angle;
	Vector startangle;
	int init_door_direction;

public:
	CLASS_PROTOTYPE( RotatingDoor );

	void     DoOpen( Event* ev );
	void     DoClose( Event* ev );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );

	RotatingDoor();
};

inline void RotatingDoor::Archive( Archiver& arc )
{
	Door::Archive( arc );

	arc.WriteFloat( angle );
	arc.WriteVector( startangle );
	arc.WriteInteger( init_door_direction );
}

inline void RotatingDoor::Unarchive( Archiver& arc )
{
	Door::Unarchive( arc );

	angle = arc.ReadFloat();
	arc.ReadVector( &startangle );
	init_door_direction = arc.ReadInteger();
}

class ScriptDoor : public Door
{
protected:
	ThreadPtr doorthread;
	str initthreadname;
	str openthreadname;
	str closethreadname;
	float doorsize;
	Vector startangle;
	Vector startorigin;
	Vector movedir;

public:
	CLASS_PROTOTYPE( ScriptDoor );

	void     DoInit( Event* ev );
	void     DoOpen( Event* ev );
	void     DoClose( Event* ev );
	void     SetOpenThread( Event* ev );
	void     SetCloseThread( Event* ev );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
	ScriptDoor();
};

inline void ScriptDoor::Archive( Archiver& arc )
{
	Door::Archive( arc );

	arc.WriteSafePointer( doorthread );
	arc.WriteString( initthreadname );
	arc.WriteString( openthreadname );
	arc.WriteString( closethreadname );
	arc.WriteFloat( doorsize );
	arc.WriteVector( startangle );
	arc.WriteVector( startorigin );
	arc.WriteVector( movedir );
}

inline void ScriptDoor::Unarchive( Archiver& arc )
{
	Door::Unarchive( arc );

	arc.ReadSafePointer( &doorthread );
	arc.ReadString( &initthreadname );
	arc.ReadString( &openthreadname );
	arc.ReadString( &closethreadname );
	doorsize = arc.ReadFloat();
	arc.ReadVector( &startangle );
	arc.ReadVector( &startorigin );
	arc.ReadVector( &movedir );
}


#endif /* doors.h */
