struct InputEventData native
{
	native uint8	type;
	native uint8	subtype;
	native int16	data1;		// keys / mouse/joystick buttons
	native int16	data2;
	native int16	data3;
	native int 		x;			// mouse/joystick x move
	native int 		y;			// mouse/joystick y move
	
	enum EGenericEvent
	{
		NoEvent,
		KeyDown,		// data1: scan code, data2: Qwerty ASCII code
		KeyUp,		// same
		Mouse,		// x, y: mouse movement deltas
		GUI_Event,	// subtype specifies actual event
		DeviceChange,// a device has been connected or removed
	}
	
	enum EGUIEvent
	{
		GUI_None,
		GUI_KeyDown,			// data1: unshifted ASCII, data2: shifted ASCII, data3: modifiers
		GUI_KeyRepeat,		// same
		GUI_KeyUp,			// same
		GUI_Char,			// data1: translated character (for user text input), data2: alt down?
		GUI_FirstMouseEvent,
			GUI_MouseMove,
			GUI_LButtonDown,
			GUI_LButtonUp,
			GUI_LButtonDblClick,
			GUI_MButtonDown,
			GUI_MButtonUp,
			GUI_MButtonDblClick,
			GUI_RButtonDown,
			GUI_RButtonUp,
			GUI_RButtonDblClick,
			GUI_WheelUp,			// data3: shift/ctrl/alt
			GUI_WheelDown,		// "
			GUI_WheelRight,		// "
			GUI_WheelLeft,		// "
			GUI_BackButtonDown,
			GUI_BackButtonUp,
			GUI_FwdButtonDown,
			GUI_FwdButtonUp,
		GUI_LastMouseEvent,
	};
	
	const KEY_ESCAPE = 0x01;
}

struct TexMan
{
	enum EUseTypes
	{
		Type_Any,
		Type_Wall,
		Type_Flat,
		Type_Sprite,
		Type_WallPatch,
		Type_Build,
		Type_SkinSprite,
		Type_Decal,
		Type_MiscPatch,
		Type_FontChar,
		Type_Override,	// For patches between TX_START/TX_END
		Type_Autopage,	// Automap background - used to enable the use of FAutomapTexture
		Type_SkinGraphic,
		Type_Null,
		Type_FirstDefined,
	};

	enum EFlags
	{
		TryAny = 1,
		Overridable = 2,
		ReturnFirst = 4,
		AllowSkins = 8,
		ShortNameOnly = 16,
		DontCreate = 32
	};
	
	enum ETexReplaceFlags
	{
		NOT_BOTTOM			= 1,
		NOT_MIDDLE			= 2,
		NOT_TOP				= 4,
		NOT_FLOOR			= 8,
		NOT_CEILING			= 16,
		NOT_WALL			= 7,
		NOT_FLAT			= 24
	};

	native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny);
	native static void ReplaceTextures(String from, String to, int flags);
	native static int, int GetSize(TextureID tex);
	native static Vector2 GetScaledSize(TextureID tex);
}

enum DrawTextureTags
{
	TAG_USER = (1<<30),
	DTA_Base = TAG_USER + 5000,
	DTA_DestWidth,		// width of area to draw to
	DTA_DestHeight,		// height of area to draw to
	DTA_Alpha,			// alpha value for translucency
	DTA_FillColor,		// color to stencil onto the destination (RGB is the color for truecolor drawers, A is the palette index for paletted drawers)
	DTA_TranslationIndex, // translation table to recolor the source
	DTA_AlphaChannel,	// bool: the source is an alpha channel; used with DTA_FillColor
	DTA_Clean,			// bool: scale texture size and position by CleanXfac and CleanYfac
	DTA_320x200,		// bool: scale texture size and position to fit on a virtual 320x200 screen
	DTA_Bottom320x200,	// bool: same as DTA_320x200 but centers virtual screen on bottom for 1280x1024 targets
	DTA_CleanNoMove,	// bool: like DTA_Clean but does not reposition output position
	DTA_CleanNoMove_1,	// bool: like DTA_CleanNoMove, but uses Clean[XY]fac_1 instead
	DTA_FlipX,			// bool: flip image horizontally	//FIXME: Does not work with DTA_Window(Left|Right)
	DTA_ShadowColor,	// color of shadow
	DTA_ShadowAlpha,	// alpha of shadow
	DTA_Shadow,			// set shadow color and alphas to defaults
	DTA_VirtualWidth,	// pretend the canvas is this wide
	DTA_VirtualHeight,	// pretend the canvas is this tall
	DTA_TopOffset,		// override texture's top offset
	DTA_LeftOffset,		// override texture's left offset
	DTA_CenterOffset,	// bool: override texture's left and top offsets and set them for the texture's middle
	DTA_CenterBottomOffset,// bool: override texture's left and top offsets and set them for the texture's bottom middle
	DTA_WindowLeft,		// don't draw anything left of this column (on source, not dest)
	DTA_WindowRight,	// don't draw anything at or to the right of this column (on source, not dest)
	DTA_ClipTop,		// don't draw anything above this row (on dest, not source)
	DTA_ClipBottom,		// don't draw anything at or below this row (on dest, not source)
	DTA_ClipLeft,		// don't draw anything to the left of this column (on dest, not source)
	DTA_ClipRight,		// don't draw anything at or to the right of this column (on dest, not source)
	DTA_Masked,			// true(default)=use masks from texture, false=ignore masks
	DTA_HUDRules,		// use fullscreen HUD rules to position and size textures
	DTA_HUDRulesC,		// only used internally for marking HUD_HorizCenter
	DTA_KeepRatio,		// doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3
	DTA_RenderStyle,	// same as render style for actors
	DTA_ColorOverlay,	// DWORD: ARGB to overlay on top of image; limited to black for software
	DTA_Internal1,
	DTA_Internal2,
	DTA_Internal3,
	DTA_Fullscreen,		// Draw image fullscreen (same as DTA_VirtualWidth/Height with graphics size.)

	// floating point duplicates of some of the above:
	DTA_DestWidthF,
	DTA_DestHeightF,
	DTA_TopOffsetF,
	DTA_LeftOffsetF,
	DTA_VirtualWidthF,
	DTA_VirtualHeightF,
	DTA_WindowLeftF,
	DTA_WindowRightF,

	// For DrawText calls only:
	DTA_TextLen,		// stop after this many characters, even if \0 not hit
	DTA_CellX,			// horizontal size of character cell
	DTA_CellY,			// vertical size of character cell
};

struct Screen native
{
	native static Color PaletteColor(int index);
	native static int GetWidth();
	native static int GetHeight();
	native static void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1);
	native static void Dim(Color col, double amount, int x, int y, int w, int h);

	native static void DrawHUDTexture(TextureID tex, double x, double y);
	native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
	native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
	native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
	native static void DrawFrame(int x, int y, int w, int h);
}

struct Font native
{
	enum EColorRange
	{
		CR_UNDEFINED = -1,
		CR_BRICK,
		CR_TAN,
		CR_GRAY,
		CR_GREY = CR_GRAY,
		CR_GREEN,
		CR_BROWN,
		CR_GOLD,
		CR_RED,
		CR_BLUE,
		CR_ORANGE,
		CR_WHITE,
		CR_YELLOW,
		CR_UNTRANSLATED,
		CR_BLACK,
		CR_LIGHTBLUE,
		CR_CREAM,
		CR_OLIVE,
		CR_DARKGREEN,
		CR_DARKRED,
		CR_DARKBROWN,
		CR_PURPLE,
		CR_DARKGRAY,
		CR_CYAN,
		NUM_TEXT_COLORS
	};
	
	const TEXTCOLOR_BRICK			= "\034A";
	const TEXTCOLOR_TAN				= "\034B";
	const TEXTCOLOR_GRAY			= "\034C";
	const TEXTCOLOR_GREY			= "\034C";
	const TEXTCOLOR_GREEN			= "\034D";
	const TEXTCOLOR_BROWN			= "\034E";
	const TEXTCOLOR_GOLD			= "\034F";
	const TEXTCOLOR_RED				= "\034G";
	const TEXTCOLOR_BLUE			= "\034H";
	const TEXTCOLOR_ORANGE			= "\034I";
	const TEXTCOLOR_WHITE			= "\034J";
	const TEXTCOLOR_YELLOW			= "\034K";
	const TEXTCOLOR_UNTRANSLATED	= "\034L";
	const TEXTCOLOR_BLACK			= "\034M";
	const TEXTCOLOR_LIGHTBLUE		= "\034N";
	const TEXTCOLOR_CREAM			= "\034O";
	const TEXTCOLOR_OLIVE			= "\034P";
	const TEXTCOLOR_DARKGREEN		= "\034Q";
	const TEXTCOLOR_DARKRED			= "\034R";
	const TEXTCOLOR_DARKBROWN		= "\034S";
	const TEXTCOLOR_PURPLE			= "\034T";
	const TEXTCOLOR_DARKGRAY		= "\034U";
	const TEXTCOLOR_CYAN			= "\034V";

	const TEXTCOLOR_NORMAL			= "\034-";
	const TEXTCOLOR_BOLD			= "\034+";

	const TEXTCOLOR_CHAT			= "\034*";
	const TEXTCOLOR_TEAMCHAT		= "\034!";
	

	native int GetCharWidth(int code);
	native int StringWidth(String code);
	native int GetHeight();
	native String GetCursor();

	native static int FindFontColor(Name color);
	native static Font FindFont(Name fontname);
	native static Font GetFont(Name fontname);
	native BrokenLines BreakLines(String text, int maxlen);
}

struct Translation
{
	Color colors[256];
	
	native int AddTranslation();
	native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass);
	static int MakeID(int group, int num)
	{
		return (group << 16) + num;
	}
}

struct Console native
{
	native static void HideConsole();
	native static void MidPrint(Font fontname, string textlabel, bool bold = false);
	native static vararg void Printf(string fmt, ...);
}

struct DamageTypeDefinition native
{
	native static bool IgnoreArmor(Name type);
}

struct CVar native
{
	enum ECVarType
	{
		CVAR_Bool,
		CVAR_Int,
		CVAR_Float,
		CVAR_String,
		CVAR_Color,
	};

	native static CVar FindCVar(Name name);
	native int GetInt();
	native double GetFloat();
	native String GetString();
	native void SetInt(int v);
	native void SetFloat(double v);
	native void SetString(String s);
	native int GetRealType();
	native int ResetToDefault();
}

struct GIFont
{
	Name fontname;
	Name color;
};

struct GameInfoStruct native
{
	// will be extended as needed.
	native Name backpacktype;
	native double Armor2Percent;
	native String ArmorIcon1;
	native String ArmorIcon2;
	native int gametype;
	native bool norandomplayerclass;
	native Array<Name> infoPages;
	native String mBackButton;
	native GIFont mStatscreenMapNameFont;
	native GIFont mStatscreenEnteringFont;
	native GIFont mStatscreenFinishedFont;
	native double gibfactor;
}

class Object native
{
	native bool bDestroyed;

	// These really should be global functions...
	native static int G_SkillPropertyInt(int p);
	native static double G_SkillPropertyFloat(int p);
	native static vector3, int G_PickDeathmatchStart();
	native static vector3, int G_PickPlayerStart(int pnum, int flags = 0);
	native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM);
	native static void S_PauseSound (bool notmusic, bool notsfx);
	native static void S_ResumeSound (bool notsfx);
	native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false);
	native static uint BAM(double angle);
	native static void SetMusicVolume(float vol);
	native static uint MSTime();

	native Name GetClassName();
	native void Destroy();

	// This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown.
	virtual void OnDestroy() {}
}

class BrokenLines : Object native
{
	native int Count();
	native int StringWidth(int line);
	native String StringAt(int line);
}

class Thinker : Object native
{
	enum EStatnums
	{
 		// Thinkers that don't actually think
		STAT_INFO,								// An info queue
		STAT_DECAL,								// A decal
		STAT_AUTODECAL,							// A decal that can be automatically deleted
		STAT_CORPSEPOINTER,						// An entry in Hexen's corpse queue
		STAT_TRAVELLING,						// An actor temporarily travelling to a new map
		STAT_STATIC,

		// Thinkers that do think
		STAT_FIRST_THINKING=32,
		STAT_SCROLLER=STAT_FIRST_THINKING,		// A DScroller thinker
		STAT_PLAYER,							// A player actor
		STAT_BOSSTARGET,						// A boss brain target
		STAT_LIGHTNING,							// The lightning thinker
		STAT_DECALTHINKER,						// An object that thinks for a decal
		STAT_INVENTORY,							// An inventory item
		STAT_LIGHT,								// A sector light effect
		STAT_LIGHTTRANSFER,						// A sector light transfer. These must be ticked after the light effects.
		STAT_EARTHQUAKE,						// Earthquake actors
		STAT_MAPMARKER,							// Map marker actors

		STAT_DEFAULT = 100,						// Thinkers go here unless specified otherwise.
		STAT_SECTOREFFECT,						// All sector effects that cause floor and ceiling movement
		STAT_ACTORMOVER,						// actor movers
		STAT_SCRIPTS,							// The ACS thinker. This is to ensure that it can't tick before all actors called PostBeginPlay
		STAT_BOT,								// Bot thinker
		MAX_STATNUM = 127
	}

	const TICRATE = 35;
	
	virtual native void Tick();
	virtual native void PostBeginPlay();
	virtual native void ChangeStatNum(int stat);
}

class ThinkerIterator : Object native
{

	native static ThinkerIterator Create(class<Object> type = "Actor", int statnum=Thinker.MAX_STATNUM+1);
	native Thinker Next(bool exact = false);
	native void Reinit();
}

class ActorIterator : Object native
{
	native static ActorIterator Create(int tid, class<Actor> type = "Actor");
	native Actor Next();
	native void Reinit();
}

class BlockThingsIterator : Object native
{
	native Actor thing;
	native Vector3 position;
	native int portalflags;
	
	native static BlockThingsIterator Create(Actor origin, double checkradius = -1, bool ignorerestricted = false);
	native static BlockThingsIterator CreateFromPos(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted);
	native bool Next();
}

struct DropItem native
{
	native readonly DropItem Next;
	native readonly name Name;
	native readonly int Probability;
	native int Amount;
}

class SpotState : Object native
{
	native static SpotState GetSpotState();
	native SpecialSpot GetNextInList(class<Actor> type, int skipcounter);
	native SpecialSpot GetSpotWithMinMaxDistance(Class<Actor> type, double x, double y, double mindist, double maxdist);
	
}

struct LevelLocals native
{
	enum EUDMF
	{
		UDMF_Line,
		UDMF_Side,
		UDMF_Sector,
		//UDMF_Thing // not implemented
	};

	native readonly int time;
	native readonly int maptime;
	native readonly int totaltime;
	native readonly int starttime;
	native readonly int partime;
	native readonly int sucktime;
	native readonly int cluster;
	native readonly int clusterflags;
	native readonly int levelnum;
	native readonly String LevelName;
	native readonly String MapName;
	native String NextMap;
	native String NextSecretMap;
	native String F1Pic;
	native readonly int maptype;
	native readonly String Music;
	native readonly int musicorder;
	native int total_secrets;
	native int found_secrets;
	native int total_items;
	native int found_items;
	native int total_monsters;
	native int killed_monsters;
	native double gravity;
	native double aircontrol;
	native double airfriction;
	native int airsupply;
	native double teamdamage;
	native bool monsterstelefrag;
	native bool actownspecial;
	native bool sndseqtotalctrl;
	native bool allmap;
	native bool missilesactivateimpact;
	native bool monsterfallingdamage;
	native bool checkswitchrange;
	native bool polygrind;
	native bool nomonsters;
	native bool frozen;
	native bool infinite_flight;
	native bool no_dlg_freeze;
// level_info_t *info cannot be done yet.

	native String GetUDMFString(int type, int index, Name key);
	native int GetUDMFInt(int type, int index, Name key);
	native double GetUDMFFloat(int type, int index, Name key);
	native bool ExecuteSpecial(int special, Actor activator, line linedef, bool lineside, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0);

}

struct StringTable native
{
	native static String Localize(String val, bool prefixed = true);
}

// a few values of this need to be readable by the play code.
// Most are handled at load time and are omitted here.
struct DehInfo native
{
	native int MaxSoulsphere;
	native uint8 ExplosionStyle;
	native double ExplosionAlpha;
	native int NoAutofreeze;
	native int BFGCells;
	native int BlueAC;
}

struct State native
{
	native State NextState;
	native int sprite;
	native int16 Tics;
	native uint16 TicRange;
	native uint8 Frame;		
	native uint8 UseFlags;	
	native int Misc1;
	native int Misc2;
	native uint16 bSlow;
	native uint16 bFast;
	native bool bFullbright;
	native bool bNoDelay;
	native bool bSameFrame;
	native bool bCanRaise;
	native bool bDehacked;
	
	native int DistanceTo(state other);
	native bool ValidateSpriteFrame();
	native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0));
}

struct F3DFloor native
{
}

struct Wads
{
	enum WadNamespace
	{
		ns_hidden = -1,

		ns_global = 0,
		ns_sprites,
		ns_flats,
		ns_colormaps,
		ns_acslibrary,
		ns_newtextures,
		ns_bloodraw,
		ns_bloodsfx,
		ns_bloodmisc,
		ns_strifevoices,
		ns_hires,
		ns_voxels,

		ns_specialzipdirectory,
		ns_sounds,
		ns_patches,
		ns_graphics,
		ns_music,

		ns_firstskin,
	}

	native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false);
}

struct TerrainDef native
{
	native Name TerrainName;
	native int Splash;
	native int DamageAmount;
	native Name DamageMOD;
	native int DamageTimeMask;
	native double FootClip;
	native float StepVolume;
	native int WalkStepTics;
	native int RunStepTics;
	native Sound LeftStepSound;
	native Sound RightStepSound;
	native bool IsLiquid;
	native bool AllowProtection;
	native double Friction;
	native double MoveFactor;
};

enum EPickStart
{
	PPS_FORCERANDOM			= 1,
	PPS_NOBLOCKINGCHECK		= 2,
}

// Although String is a builtin type, this is a convenient way to attach methods to it.
struct StringStruct native
{
	native static vararg String Format(String fmt, ...);
	native vararg void AppendFormat(String fmt, ...);

	native void Replace(String pattern, String replacement);
	native String Left(int len);
	native String Mid(int pos = 0, int len = 2147483647);
	native void Truncate(int newlen);
	native String CharAt(int pos);
	native int CharCodeAt(int pos);
	native String Filter();
}

class Floor : Thinker native
{
	// only here so that some constants and functions can be added. Not directly usable yet.
	enum EFloor
	{
		floorLowerToLowest,
		floorLowerToNearest,
		floorLowerToHighest,
		floorLowerByValue,
		floorRaiseByValue,
		floorRaiseToHighest,
		floorRaiseToNearest,
		floorRaiseAndCrush,
		floorRaiseAndCrushDoom,
		floorCrushStop,
		floorLowerInstant,
		floorRaiseInstant,
		floorMoveToValue,
		floorRaiseToLowestCeiling,
		floorRaiseuint8xture,

		floorLowerAndChange,
		floorRaiseAndChange,

		floorRaiseToLowest,
		floorRaiseToCeiling,
		floorLowerToLowestCeiling,
		floorLoweruint8xture,
		floorLowerToCeiling,

		donutRaise,

		buildStair,
		waitStair,
		resetStair,

		// Not to be used as parameters to DoFloor()
		genFloorChg0,
		genFloorChgT,
		genFloorChg
	};

	native static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false);
}

class Ceiling : Thinker native
{
	enum ECeiling
	{
		ceilLowerByValue,
		ceilRaiseByValue,
		ceilMoveToValue,
		ceilLowerToHighestFloor,
		ceilLowerInstant,
		ceilRaiseInstant,
		ceilCrushAndRaise,
		ceilLowerAndCrush,
		ceil_placeholder,
		ceilCrushRaiseAndStay,
		ceilRaiseToNearest,
		ceilLowerToLowest,
		ceilLowerToFloor,

		// The following are only used by Generic_Ceiling
		ceilRaiseToHighest,
		ceilLowerToHighest,
		ceilRaiseToLowest,
		ceilLowerToNearest,
		ceilRaiseToHighestFloor,
		ceilRaiseToFloor,
		ceilRaiseuint8xture,
		ceilLoweruint8xture,

		genCeilingChg0,
		genCeilingChgT,
		genCeilingChg
	}

	enum ECrushMode
	{
		crushDoom = 0,
		crushHexen = 1,
		crushSlowdown = 2
	}
	
	native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom);
	
}

struct LookExParams
{
	double Fov;
	double minDist;
	double maxDist;
	double maxHeardist;
	int flags;
	State seestate;
};
