about summary refs log tree commit diff
path: root/src/game
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
commit8b3c16e6152a527f9aec1a88a9eed74119de7000 (patch)
treef0bde5cea15e696e42cade06a3b12ff6b13acc57 /src/game
parent9899666a7ce6679a3b9667ab09f615f4d0769c16 (diff)
downloadzcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.tar.gz
zcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.zip
major engine cleanup. dependency on baselib removed. engine is now C code (not ansi tho). some other cruft removed aswell
Diffstat (limited to 'src/game')
-rw-r--r--src/game/client/game_client.cpp110
-rw-r--r--src/game/client/mapres_image.cpp4
-rw-r--r--src/game/client/mapres_tilemap.cpp6
-rw-r--r--src/game/client/menu.cpp136
-rw-r--r--src/game/game.h14
-rw-r--r--src/game/mapres_col.cpp9
-rw-r--r--src/game/mapres_col.h4
-rw-r--r--src/game/math.h29
-rw-r--r--src/game/server/game_server.cpp14
-rw-r--r--src/game/server/game_server.h38
-rw-r--r--src/game/vmath.h181
11 files changed, 371 insertions, 174 deletions
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp
index 37bf3c65..e5969fcf 100644
--- a/src/game/client/game_client.cpp
+++ b/src/game/client/game_client.cpp
@@ -1,18 +1,19 @@
-#include <baselib/math.h>
-//#include <baselib/keys.h>
+#include <game/math.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <engine/config.h>
-#include <engine/client/ui.h>
+
+extern "C" {
+	#include <engine/client/ui.h>
+	#include <engine/config.h>
+};
+
 #include "../game.h"
 #include "mapres_image.h"
 #include "mapres_tilemap.h"
 #include "data.h"
 #include "menu.h"
 
-using namespace baselib;
-
 data_container *data = 0x0;
 
 static int charids[16] = {2,10,0,4,12,6,9,1,3,15,13,11,7,5,8,14};
@@ -463,7 +464,7 @@ static void render_loading(float percent)
 
 	const char *caption = "Loading";
 	
-	tw = gfx_pretty_text_width(48.0f, caption);
+	tw = gfx_pretty_text_width(48.0f, caption, -1);
 	ui_do_label(x+w/2-tw/2, y+20, caption, 48.0f);
 
 	gfx_texture_set(-1);
@@ -475,7 +476,7 @@ static void render_loading(float percent)
 	gfx_swap();
 }
 
-void modc_init()
+extern "C" void modc_init()
 {
 	// load the data container
 	data = load_data_from_memory(internal_data);
@@ -513,7 +514,7 @@ void modc_init()
 	}
 }
 
-void modc_entergame()
+extern "C" void modc_entergame()
 {
 	col_init(32);
 	img_init();
@@ -534,7 +535,7 @@ void modc_entergame()
 		killmsgs[i].tick = -100000;
 }
 
-void modc_shutdown()
+extern "C" void modc_shutdown()
 {
 }
 
@@ -545,7 +546,7 @@ static void process_events(int s)
 	int num = snap_num_items(s);
 	for(int i = 0; i < num; i++)
 	{
-		snap_item item;
+		SNAP_ITEM item;
 		const void *data = snap_get_item(s, i, &item);
 		
 		if(item.type == EVENT_DAMAGEINDICATION)
@@ -679,7 +680,7 @@ static void process_events(int s)
 	must_process_events = false;
 }
 
-void modc_newsnapshot()
+extern "C" void modc_newsnapshot()
 {
 	if(must_process_events)
 		process_events(SNAP_PREV);
@@ -1377,9 +1378,9 @@ int emoticon_selector_render()
 	if (length(emoticon_selector_mouse) < 50)
 		selected_emoticon = -1;
 	else
-		selected_emoticon = selected_angle / (2*pi) * 12;
+		selected_emoticon = (int)(selected_angle / (2*pi) * 12.0f);
 
-	if (inp_key_pressed(baselib::input::mouse_1))
+	if (inp_key_pressed(KEY_MOUSE_1))
 	{
 		mouse_down = true;
 	}
@@ -1441,7 +1442,7 @@ void render_game()
 	anim_eval(&data->animations[ANIM_BASE], 0, &idlestate);
 	anim_eval_add(&idlestate, &data->animations[ANIM_IDLE], 0, 1.0f);	
 
-	if (inp_key_down(input::esc))
+	if (inp_key_down(KEY_ESC))
 	{
 		if (chat_active)
 			chat_active = false;
@@ -1451,7 +1452,7 @@ void render_game()
 	
 	if (!menu_active)
 	{
-		if(inp_key_down(input::enter))
+		if(inp_key_down(KEY_ENTER))
 		{
 			if(chat_active)
 			{
@@ -1479,8 +1480,8 @@ void render_game()
 		
 		if(chat_active)
 		{
-			int c = input::last_char(); // TODO: bypasses the engine interface
-			int k = input::last_key(); // TODO: bypasses the engine interface
+			int c = inp_last_char();
+			int k = inp_last_key();
 		
 			if (!(c >= 0 && c < 32))
 			{
@@ -1492,7 +1493,7 @@ void render_game()
 				}
 			}
 
-			if(k == input::backspace)
+			if(k == KEY_BACKSPACE)
 			{
 				if(chat_input_len > 0)
 				{
@@ -1506,8 +1507,7 @@ void render_game()
 	
 	if (!menu_active)
 	{
-		input::clear_char(); // TODO: bypasses the engine interface
-		input::clear_key(); // TODO: bypasses the engine interface
+		inp_clear();
 	}
 	
 	// fetch new input
@@ -1581,7 +1581,7 @@ void render_game()
 		int num = snap_num_items(SNAP_CURRENT);
 		for(int i = 0; i < num; i++)
 		{
-			snap_item item;
+			SNAP_ITEM item;
 			const void *data = snap_get_item(SNAP_CURRENT, i, &item);
 			
 			if(item.type == OBJTYPE_PLAYER)
@@ -1611,7 +1611,7 @@ void render_game()
 	
 	if(config.debug)
 	{
-		if(!chat_active && inp_key_pressed(input::f8))
+		if(!chat_active && inp_key_pressed(KEY_F8))
 			zoom = 1.0f;
 	}
 	
@@ -1678,7 +1678,7 @@ void render_game()
 	int num = snap_num_items(SNAP_CURRENT);
 	for(int i = 0; i < num; i++)
 	{
-		snap_item item;
+		SNAP_ITEM item;
 		const void *data = snap_get_item(SNAP_CURRENT, i, &item);
 		
 		if(item.type == OBJTYPE_PLAYER)
@@ -1781,19 +1781,19 @@ void render_game()
 				continue;
 			
 			float font_size = 48.0f;
-			float killername_w = gfx_pretty_text_width(font_size, client_datas[killmsgs[r].killer].name);
-			float victimname_w = gfx_pretty_text_width(font_size, client_datas[killmsgs[r].victim].name);
+			float killername_w = gfx_pretty_text_width(font_size, client_datas[killmsgs[r].killer].name, -1);
+			float victimname_w = gfx_pretty_text_width(font_size, client_datas[killmsgs[r].victim].name, -1);
 			
 			float x = startx;
 			
 			// render victim name
 			x -= victimname_w;
-			gfx_pretty_text(x, y, font_size, client_datas[killmsgs[r].victim].name);
+			gfx_pretty_text(x, y, font_size, client_datas[killmsgs[r].victim].name, -1);
 			
 			// render victim tee
 			x -= 24.0f;
 			int skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].victim].team : killmsgs[r].victim;
-			render_tee(&idlestate, skin, EMOTE_NORMAL, vec2(1,0), vec2(x, y+28));
+			render_tee(&idlestate, skin, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
 			x -= 32.0f;
 
 			// render weapon
@@ -1811,12 +1811,12 @@ void render_game()
 			// render killer tee
 			x -= 24.0f;
 			skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].killer].team : killmsgs[r].killer;
-			render_tee(&idlestate, skin, EMOTE_NORMAL, vec2(1,0), vec2(x, y+28));
+			render_tee(&idlestate, skin, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
 			x -= 32.0f;
 			
 			// render killer name
 			x -= killername_w;
-			gfx_pretty_text(x, y, font_size, client_datas[killmsgs[r].killer].name);
+			gfx_pretty_text(x, y, font_size, client_datas[killmsgs[r].killer].name, -1);
 			
 			y += 44;
 		}
@@ -1833,7 +1833,7 @@ void render_game()
 			// render chat input
 			char buf[sizeof(chat_input)+16];
 			sprintf(buf, "Chat: %s_", chat_input);
-			gfx_pretty_text(x, y, 10, buf, 380);
+			gfx_pretty_text(x, y, 10.0f, buf, 380);
 			starty = y;
 		}
 		
@@ -1846,7 +1846,7 @@ void render_game()
 			if(client_tick() > chat_lines[r].tick+50*15)
 				break;
 
-			int lines = int(gfx_pretty_text_width(10, chat_lines[r].text)) / 380 + 1;
+			int lines = int(gfx_pretty_text_width(10, chat_lines[r].text, -1)) / 380 + 1;
 			
 			gfx_pretty_text(x, y - 8 * (lines - 1), 10, chat_lines[r].text, 380);
 			y -= 8 * lines;
@@ -1873,15 +1873,15 @@ void render_game()
 				time = (client_tick()-gameobj->round_start_tick)/client_tickspeed();
 			
 			sprintf(buf, "%d:%02d", time /60, time %60);
-			float w = gfx_pretty_text_width(16, buf);
-			gfx_pretty_text(200-w/2, 2, 16, buf);
+			float w = gfx_pretty_text_width(16, buf, -1);
+			gfx_pretty_text(200-w/2, 2, 16, buf, -1);
 		}
 
 		if(gameobj->sudden_death)
 		{
 			const char *text = "Sudden Death";
-			float w = gfx_pretty_text_width(16, text);
-			gfx_pretty_text(200-w/2, 2, 16, text);
+			float w = gfx_pretty_text_width(16, text, -1);
+			gfx_pretty_text(200-w/2, 2, 16, text, -1);
 		}
 	}
 
@@ -1916,7 +1916,7 @@ void render_game()
 	}
 	
 	// render score board
-	if(inp_key_pressed(baselib::input::tab) || // user requested
+	if(inp_key_pressed(KEY_TAB) || // user requested
 		(local_player && local_player->health == -1) || // player dead
 		(gameobj && gameobj->game_over) // game over
 		)
@@ -1943,13 +1943,13 @@ void render_game()
 			
 			if(gameobj->game_over)
 			{
-				float tw = gfx_pretty_text_width( 64, "Game Over");
-				gfx_pretty_text(x+w/2-tw/2, y, 64, "Game Over");
+				float tw = gfx_pretty_text_width( 64, "Game Over", -1);
+				gfx_pretty_text(x+w/2-tw/2, y, 64, "Game Over", -1);
 			}
 			else
 			{
-				float tw = gfx_pretty_text_width( 64, "Score Board");
-				gfx_pretty_text(x+w/2-tw/2, y, 64, "Score Board");
+				float tw = gfx_pretty_text_width( 64, "Score Board", -1);
+				gfx_pretty_text(x+w/2-tw/2, y, 64, "Score Board", -1);
 			}
 			y += 64.0f;
 
@@ -1958,7 +1958,7 @@ void render_game()
 			int num_players = 0;
 			for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
 			{
-				snap_item item;
+				SNAP_ITEM item;
 				const void *data = snap_get_item(SNAP_CURRENT, i, &item);
 				
 				if(item.type == OBJTYPE_PLAYER)
@@ -1983,9 +1983,9 @@ void render_game()
 			}
 
 			// render headlines
-			gfx_pretty_text(x+10, y, 32, "Score");
-			gfx_pretty_text(x+125, y, 32, "Name");
-			gfx_pretty_text(x+w-70, y, 32, "Ping");
+			gfx_pretty_text(x+10, y, 32, "Score", -1);
+			gfx_pretty_text(x+125, y, 32, "Name", -1);
+			gfx_pretty_text(x+w-70, y, 32, "Ping", -1);
 			y += 38.0f;
 
 			// render player scores
@@ -2005,12 +2005,12 @@ void render_game()
 				}
 				
 				sprintf(buf, "%4d", player->score);
-				gfx_pretty_text(x+60-gfx_pretty_text_width(font_size,buf), y, font_size, buf);
-				gfx_pretty_text(x+128, y, font_size, client_datas[player->clientid].name);
+				gfx_pretty_text(x+60-gfx_pretty_text_width(font_size,buf,-1), y, font_size, buf, -1);
+				gfx_pretty_text(x+128, y, font_size, client_datas[player->clientid].name, -1);
 				
 				sprintf(buf, "%4d", player->latency);
-				float tw = gfx_pretty_text_width(font_size, buf);
-				gfx_pretty_text(x+w-tw-35, y, font_size, buf);
+				float tw = gfx_pretty_text_width(font_size, buf, -1);
+				gfx_pretty_text(x+w-tw-35, y, font_size, buf, -1);
 
 				// render avatar
 				render_tee(&idlestate, player->clientid, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28));
@@ -2023,13 +2023,13 @@ void render_game()
 			{
 				char buf[64];
 				sprintf(buf, "Time Limit: %d min", gameobj->time_limit);
-				gfx_pretty_text(x+w/2, y, 32, buf);
+				gfx_pretty_text(x+w/2, y, 32, buf, -1);
 			}
 			if(gameobj && gameobj->score_limit)
 			{
 				char buf[64];
 				sprintf(buf, "Score Limit: %d", gameobj->score_limit);
-				gfx_pretty_text(x+40, y, 32, buf);
+				gfx_pretty_text(x+40, y, 32, buf, -1);
 			}			
 		}
 		/*
@@ -2129,7 +2129,7 @@ void render_game()
 
 
 
-void modc_render()
+extern "C" void modc_render()
 {
 	// this should be moved around abit
 	if(client_state() == CLIENTSTATE_ONLINE)
@@ -2145,7 +2145,7 @@ void modc_render()
 	else // if (client_state() != CLIENTSTATE_CONNECTING && client_state() != CLIENTSTATE_LOADING)
 	{
 		if (music_menu_id == -1)
-			music_menu_id = snd_play(music_menu, SND_LOOP);
+			music_menu_id = snd_play(music_menu, SND_LOOP, 1.0f, 0.0f);
 		
 		//netaddr4 server_address;
 		if(modmenu_render(false) == -1)
@@ -2158,7 +2158,7 @@ void menu_do_disconnected();
 void menu_do_connecting();
 void menu_do_connected();
 
-void modc_statechange(int state, int old)
+extern "C" void modc_statechange(int state, int old)
 {
 	if(state == CLIENTSTATE_OFFLINE)
 	 	menu_do_disconnected();
@@ -2168,7 +2168,7 @@ void modc_statechange(int state, int old)
 		menu_do_connected();
 }
 
-void modc_message(int msg)
+extern "C" void modc_message(int msg)
 {
 	if(msg == MSG_CHAT)
 	{
diff --git a/src/game/client/mapres_image.cpp b/src/game/client/mapres_image.cpp
index ab624949..b1817583 100644
--- a/src/game/client/mapres_image.cpp
+++ b/src/game/client/mapres_image.cpp
@@ -1,5 +1,5 @@
-#include <baselib/system.h>
-#include "../../engine/interface.h"
+#include <engine/system.h>
+#include <engine/interface.h>
 #include "mapres_image.h"
 #include "../mapres.h"
 
diff --git a/src/game/client/mapres_tilemap.cpp b/src/game/client/mapres_tilemap.cpp
index f4088fa8..961fe7fc 100644
--- a/src/game/client/mapres_tilemap.cpp
+++ b/src/game/client/mapres_tilemap.cpp
@@ -1,10 +1,8 @@
-#include "../../engine/interface.h"
+#include <engine/interface.h>
+#include <engine/config.h>
 #include "mapres_tilemap.h"
 #include "mapres_image.h"
 #include "../mapres.h"
-#include "../../engine/config.h"
-
-#include <baselib/opengl.h>
 
 int tilemap_init()
 {
diff --git a/src/game/client/menu.cpp b/src/game/client/menu.cpp
index fe544151..1e7f1edc 100644
--- a/src/game/client/menu.cpp
+++ b/src/game/client/menu.cpp
@@ -3,34 +3,26 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include <baselib/system.h>
-#include <baselib/stream/file.h>
-#include <baselib/stream/line.h>
-
-
-#include <baselib/system.h>
-#include <baselib/config.h>
-#include <baselib/input.h>
-#include <baselib/network.h>
-#include <baselib/math.h>
+#include <game/math.h>
+
+extern "C" {
+	#include <engine/system.h>
+	#include <engine/interface.h>
+	#include <engine/versions.h>
+	#include <engine/config.h>
+	#include <engine/client/ui.h>
+}
 
-#include <engine/interface.h>
-#include <engine/versions.h>
-#include <engine/config.h>
 #include "../mapres.h"
 
-#include <engine/client/ui.h>
 #include "mapres_image.h"
 #include "mapres_tilemap.h"
-#include <engine/config.h>
 
 #include "data.h"
 #include <mastersrv/mastersrv.h>
 
 extern data_container *data;
 
-using namespace baselib;
-
 /********************************************************
  MENU                                                  
 *********************************************************/
@@ -234,7 +226,7 @@ void draw_teewars_button(void *id, const char *text, int checked, float x, float
 {
 	const float font_size = h-6.0f;//42.0f;
 
-	float text_width = gfx_pretty_text_width(font_size, text);
+	float text_width = gfx_pretty_text_width(font_size, text, -1);
 	gui_tileset_enum tileset;
 
 	if (ui_active_item() == id)
@@ -285,7 +277,7 @@ int ui_do_key_reader(void *id, float x, float y, float w, float h, int key)
 
 	if(ui_active_item() == id)
 	{
-		int k = input::last_key();
+		int k = inp_last_key();
 		if (k)
 		{
 			new_key = k;
@@ -310,11 +302,11 @@ int ui_do_key_reader(void *id, float x, float y, float w, float h, int key)
 		box_type = GUI_BOX_SCREEN_TEXTBOX;
 	draw_box(box_type, tileset_regular, x, y, w, h);
 	
-	const char *str = input::key_name(key);
+	const char *str = inp_key_name(key);
 	ui_do_label(x + 10, y, str, 36);
 	if (ui_active_item() == id)
 	{
-		float w = gfx_pretty_text_width(36.0f, str);
+		float w = gfx_pretty_text_width(36.0f, str, -1);
 		ui_do_label(x + 10 + w, y, "_", 36);
 	}
 
@@ -390,8 +382,8 @@ int ui_do_edit_box(void *id, float x, float y, float w, float h, char *str, int
 
 	if(ui_last_active_item() == id)
 	{
-		int c = input::last_char();
-		int k = input::last_key();
+		int c = inp_last_char();
+		int k = inp_last_key();
 		int len = strlen(str);
 
 		if (inside && ui_mouse_button(0))
@@ -424,22 +416,22 @@ int ui_do_edit_box(void *id, float x, float y, float w, float h, char *str, int
 			}
 		}
 
-		if (k == input::backspace && at_index > 0)
+		if (k == KEY_BACKSPACE && at_index > 0)
 		{
 			memmove(str + at_index - 1, str + at_index, len - at_index + 1);
 			at_index--;
 		}
-		else if (k == input::delet && at_index < len)
+		else if (k == KEY_DEL && at_index < len)
 			memmove(str + at_index, str + at_index + 1, len - at_index);
-		else if (k == input::enter)
+		else if (k == KEY_ENTER)
 			ui_clear_last_active_item();
-		else if (k == input::left && at_index > 0)
+		else if (k == KEY_LEFT && at_index > 0)
 			at_index--;
-		else if (k == input::right && at_index < len)
+		else if (k == KEY_RIGHT && at_index < len)
 			at_index++;
-		else if (k == input::home)
+		else if (k == KEY_HOME)
 			at_index = 0;
-		else if (k == input::end)
+		else if (k == KEY_END)
 			at_index = len;
 
 		r = 1;
@@ -639,7 +631,7 @@ static int do_server_list(float x, float y, int *scroll_index, int *selected_ind
 	const float real_width = item_width + 20;
 	const float real_height = item_height * visible_items + spacing * (visible_items - 1);
 
-	server_info *servers;
+	SERVER_INFO *servers;
 	int num_servers = client_serverbrowse_getlist(&servers);
 
 	int r = -1;
@@ -652,7 +644,7 @@ static int do_server_list(float x, float y, int *scroll_index, int *selected_ind
 			//ui_do_image(empty_item_texture, x, y + i * item_height + i * spacing, item_width, item_height);
 		else
 		{
-			server_info *item = &servers[item_index];
+			SERVER_INFO *item = &servers[item_index];
 
 			bool clicked = false;
 			clicked = ui_do_button(item, item->name, 0, x, y + i * item_height + i * spacing, item_width, item_height,
@@ -693,7 +685,7 @@ enum
 };
 
 static int screen = SCREEN_MAIN;
-static configuration config_copy;
+static CONFIGURATION config_copy;
 
 const float column1_x = 250;
 const float column2_x = column1_x + 170;
@@ -726,7 +718,7 @@ static int main_render()
 
 	if (last_selected_index != selected_index && selected_index != -1)
 	{
-		server_info *servers;
+		SERVER_INFO *servers;
 		client_serverbrowse_getlist(&servers);
 
 		strcpy(address, servers[selected_index].address);
@@ -735,7 +727,7 @@ static int main_render()
 	static int refresh_button, join_button, quit_button;
 	static int use_lan = 0;
 
-	if (ui_do_button(&refresh_button, "Refresh", 0, 20, 460, 170, 48, draw_teewars_button))
+	if (ui_do_button(&refresh_button, "Refresh", 0, 20, 460, 170, 48, draw_teewars_button, 0))
 		client_serverbrowse_refresh(use_lan);
 	
 	ui_do_label(60, 420, "Search LAN ", 36);
@@ -744,18 +736,18 @@ static int main_render()
 	if (use_lan != last_lan)
 		client_serverbrowse_refresh(use_lan);
 
-	if (ui_do_button(&join_button, "Join", 0, 620, 420, 128, 48, draw_teewars_button))
+	if (ui_do_button(&join_button, "Join", 0, 620, 420, 128, 48, draw_teewars_button, 0))
 	{
 		client_connect(address);
 
 		return 1;
 	}
 
-	if (ui_do_button(&quit_button, "Quit", 0, 620, 490, 128, 48, draw_teewars_button))
+	if (ui_do_button(&quit_button, "Quit", 0, 620, 490, 128, 48, draw_teewars_button, 0))
 		return -1;
 
 	static int settings_button;
-	if (ui_do_button(&settings_button, "Settings", 0, 400, 490, 170, 48, draw_teewars_button))
+	if (ui_do_button(&settings_button, "Settings", 0, 400, 490, 170, 48, draw_teewars_button, 0))
 	{
 		config_copy = config;
 		screen = SCREEN_SETTINGS_GENERAL;
@@ -782,7 +774,7 @@ static int settings_general_render()
 	return 0;
 }
 
-typedef void (*assign_func_callback)(configuration *config, int value);
+typedef void (*assign_func_callback)(CONFIGURATION *config, int value);
 
 struct key_thing
 {
@@ -844,7 +836,7 @@ static int settings_controls_render()
 static const int MAX_RESOLUTIONS = 128;
 static int settings_video_render_select_mode()
 {
-	static video_mode modes[MAX_RESOLUTIONS];
+	static VIDEO_MODE modes[MAX_RESOLUTIONS];
 	static int num_modes = -1;
 	
 	if(num_modes == -1)
@@ -878,7 +870,7 @@ static int settings_video_render_select_mode()
 		sprintf(buf, "%c %dx%d %d bit %c", s?'>':' ', modes[index].width, modes[index].height, depth, s?'<':' ');
 		
 		if(ui_do_button((void*)&modes[index], buf, 0,
-			column1_x, row1_y + 40 * i, 250, 32.0f, draw_teewars_button))
+			column1_x, row1_y + 40 * i, 250, 32.0f, draw_teewars_button, 0))
 		{
 			// select
 			config_set_gfx_color_depth(&config_copy, depth);
@@ -889,7 +881,7 @@ static int settings_video_render_select_mode()
 	}
 	
 	static int back_button = 0;
-	if(ui_do_button(&back_button, "Back", 0, column3_x, row7_y, 150, 32, draw_teewars_button))
+	if(ui_do_button(&back_button, "Back", 0, column3_x, row7_y, 150, 32, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_VIDEO;
 
 	return 0;
@@ -907,7 +899,7 @@ static int settings_video_render_custom()
 	config_set_gfx_high_detail(&config_copy, ui_do_check_box(&config_copy.gfx_high_detail, column3_x, row3_y + 5, 32, 32, config_copy.gfx_high_detail));
 
 	static int back_button = 0;
-	if(ui_do_button(&back_button, "Back", 0, column3_x, row7_y, 150, 32, draw_teewars_button))
+	if(ui_do_button(&back_button, "Back", 0, column3_x, row7_y, 150, 32, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_VIDEO;
 		
 	return 0;
@@ -921,7 +913,7 @@ static int settings_video_render()
 	char buf[128];
 	sprintf(buf, "%dx%d %d bit", config_copy.gfx_screen_width, config_copy.gfx_screen_height, config_copy.gfx_color_depth);
 	static int select_button = 0;
-	if(ui_do_button(&select_button, buf, 0, column2_x, row1_y, 300, 32, draw_teewars_button))
+	if(ui_do_button(&select_button, buf, 0, column2_x, row1_y, 300, 32, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_VIDEO_SELECT_MODE;
 		
 	// we need to draw these bottom up, to make overlapping work correctly
@@ -962,7 +954,7 @@ static int settings_video_render()
 	}
 
 	static int custom_button=0;
-	if(ui_do_button(&custom_button, "Customize", 0, column3_x, row4_y, 130, 32, draw_teewars_button))
+	if(ui_do_button(&custom_button, "Customize", 0, column3_x, row4_y, 130, 32, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_VIDEO_CUSTOM;
 	
 	ui_do_label(column1_x, row6_y + 50, "(A restart of the game is required for these settings to take effect.)", 20);
@@ -998,13 +990,13 @@ static int settings_render(bool ingame)
 
 	static int general_button, controls_button, video_button, sound_button;
 
-	if (ui_do_button(&general_button, "General", 0, 30, 200, 170, 48, draw_teewars_button))
+	if (ui_do_button(&general_button, "General", 0, 30, 200, 170, 48, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_GENERAL;
-	if (ui_do_button(&controls_button, "Controls", 0, 30, 250, 170, 48, draw_teewars_button))
+	if (ui_do_button(&controls_button, "Controls", 0, 30, 250, 170, 48, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_CONTROLS;
-	if (ui_do_button(&video_button, "Video", 0, 30, 300, 170, 48, draw_teewars_button))
+	if (ui_do_button(&video_button, "Video", 0, 30, 300, 170, 48, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_VIDEO;
-	if (ui_do_button(&sound_button, "Sound", 0, 30, 350, 170, 48, draw_teewars_button))
+	if (ui_do_button(&sound_button, "Sound", 0, 30, 350, 170, 48, draw_teewars_button, 0))
 		screen = SCREEN_SETTINGS_SOUND;
 
 	switch (screen)
@@ -1019,7 +1011,7 @@ static int settings_render(bool ingame)
 
 	// SAVE BUTTON
 	static int save_button;
-	if (ui_do_button(&save_button, "Save", 0, 482, 490, 128, 48, draw_teewars_button))
+	if (ui_do_button(&save_button, "Save", 0, 482, 490, 128, 48, draw_teewars_button, 0))
 	{
 		// did we change our name?
 		if (ingame && strcmp(config.player_name, config_copy.player_name) != 0)
@@ -1036,7 +1028,7 @@ static int settings_render(bool ingame)
 	
 	// CANCEL BUTTON
 	static int cancel_button;
-	if (ui_do_button(&cancel_button, "Cancel", 0, 620, 490, 150, 48, draw_teewars_button))
+	if (ui_do_button(&cancel_button, "Cancel", 0, 620, 490, 150, 48, draw_teewars_button, 0))
 	{
 		snd_set_master_volume(config.volume / 255.0f);
 		screen = SCREEN_MAIN;
@@ -1080,18 +1072,18 @@ static int ingame_main_render()
 	
 	ui_do_image(data->images[IMAGE_BANNER].id, 214, 150, 384, 96);
 
-	if (ui_do_button(&menu_resume, "Resume Game", 0, column1_x, row2_y, 250, 48, draw_teewars_button))
+	if (ui_do_button(&menu_resume, "Resume Game", 0, column1_x, row2_y, 250, 48, draw_teewars_button, 0))
 	{
 		return 1;
 	}
 
-	if (ui_do_button(&menu_quit, "Disconnect", 0, column1_x, row4_y, 250, 48, draw_teewars_button))
+	if (ui_do_button(&menu_quit, "Disconnect", 0, column1_x, row4_y, 250, 48, draw_teewars_button, 0))
 	{
 		client_disconnect();
 		return 1;
 	}
 
-	if (ui_do_button(&menu_settings, "Settings", 0, column1_x, row3_y, 250, 48, draw_teewars_button))
+	if (ui_do_button(&menu_settings, "Settings", 0, column1_x, row3_y, 250, 48, draw_teewars_button, 0))
 	{
 		config_copy = config;
 		screen = SCREEN_SETTINGS_GENERAL;
@@ -1109,6 +1101,8 @@ static int kerning_render()
 
 	if (!loaded)
 	{
+		// TODO: fix me
+		/*
 		file_stream file;
 
 		if (file.open_r("kerning.txt"))
@@ -1138,6 +1132,7 @@ static int kerning_render()
 
 			file.close();
 		}
+		*/
 
 		loaded = true;
 	}
@@ -1226,8 +1221,10 @@ static int kerning_render()
 
 	// SAVE BUTTON
 	static int save_button;
-	if (ui_do_button(&save_button, "Save", 0, 482, 520, 128, 48, draw_teewars_button))
+	if (ui_do_button(&save_button, "Save", 0, 482, 520, 128, 48, draw_teewars_button, 0))
 	{
+		// TODO: fix or remove me
+		/*
 		file_stream file;
 
 		if (file.open_w("kerning.txt"))
@@ -1257,13 +1254,14 @@ static int kerning_render()
 
 			file.close();
 		}
+		*/
 
 		//screen = 0;
 	}
 	
 	// CANCEL BUTTON
 	static int cancel_button;
-	if (ui_do_button(&cancel_button, "Cancel", 0, 620, 520, 150, 48, draw_teewars_button))
+	if (ui_do_button(&cancel_button, "Cancel", 0, 620, 520, 150, 48, draw_teewars_button, 0))
 		screen = SCREEN_MAIN;
 
 	return 0;
@@ -1287,18 +1285,18 @@ int render_popup(const char *caption, const char *text, const char *button_text)
 	draw_round_rect(x, y, w, h, 40.0f);
 	gfx_quads_end();
 
-	tw = gfx_pretty_text_width(48.0f, caption);
+	tw = gfx_pretty_text_width(48.0f, caption, -1);
 	ui_do_label(x+w/2-tw/2, y+20, caption, 48.0f);
 	
-	tw = gfx_pretty_text_width(32.0f, text);
+	tw = gfx_pretty_text_width(32.0f, text, -1);
 	ui_do_label(x+w/2-tw/2, y+130, text, 32.0f);
 
 	if(button_text)
 	{
 		static int back_button = 0;
-		if(ui_do_button(&back_button, button_text, 0, x+w/2-100, y+220, 200, 48, draw_teewars_button))
+		if(ui_do_button(&back_button, button_text, 0, x+w/2-100, y+220, 200, 48, draw_teewars_button, 0))
 			return 1;
-		if(inp_key_down(input::esc) || inp_key_down(input::enter))
+		if(inp_key_down(KEY_ESC) || inp_key_down(KEY_ENTER))
 			return 1;
 	}
 		
@@ -1391,11 +1389,8 @@ static int menu_render(bool ingame)
 	}
 }
 
-void modmenu_init()
+extern "C" void modmenu_init() // TODO: nastyness
 {
-	input::enable_char_cache();
-	input::enable_key_cache();
-
 	// TODO: should be removed
     current_font->font_texture = gfx_load_texture("data/big_font.png");
 }
@@ -1404,7 +1399,7 @@ void modmenu_shutdown()
 {
 }
 
-int modmenu_render(bool ingame)
+extern "C" int modmenu_render(int ingame) // TODO: nastyness
 {
 	static int mouse_x = 0;
 	static int mouse_y = 0;
@@ -1426,9 +1421,9 @@ int modmenu_render(bool ingame)
         my = (mouse_y/(float)gfx_screenheight())*600.0f;
             
         int buttons = 0;
-        if(inp_key_pressed(input::mouse_1)) buttons |= 1;
-        if(inp_key_pressed(input::mouse_2)) buttons |= 2;
-        if(inp_key_pressed(input::mouse_3)) buttons |= 4;
+        if(inp_key_pressed(KEY_MOUSE_1)) buttons |= 1;
+        if(inp_key_pressed(KEY_MOUSE_2)) buttons |= 2;
+        if(inp_key_pressed(KEY_MOUSE_3)) buttons |= 4;
             
         ui_update(mx,my,mx*3.0f,my*3.0f,buttons);
     }
@@ -1442,10 +1437,7 @@ int modmenu_render(bool ingame)
     gfx_quads_drawTL(mx,my,24,24);
     gfx_quads_end();
 
-	input::clear_char();
-	input::clear_key();
-	
-	//if(r)
+	inp_clear();
 
 	return r;
 }
diff --git a/src/game/game.h b/src/game/game.h
index 855e964b..45a19105 100644
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -1,20 +1,20 @@
-#include <baselib/system.h>
-#include <baselib/math.h>
+#include <engine/system.h>
+#include <game/math.h>
 #include <math.h>
 #include "../engine/interface.h"
 #include "mapres_col.h"
 
-inline baselib::vec2 get_direction(int angle)
+inline vec2 get_direction(int angle)
 {
 	float a = angle/256.0f;
-	return baselib::vec2(cosf(a), sinf(a));
+	return vec2(cosf(a), sinf(a));
 }
 
-inline float get_angle(baselib::vec2 dir)
+inline float get_angle(vec2 dir)
 {
 	float a = atan(dir.y/dir.x);
 	if(dir.x < 0)
-		a = a+baselib::pi;
+		a = a+pi;
 	return a;
 }
 
@@ -23,7 +23,7 @@ inline float get_angle(baselib::vec2 dir)
 #define max(a, b) ( a > b ? a : b)
 
 inline bool col_check_point(float x, float y) { return col_check_point((int)x, (int)y) != 0; }
-inline bool col_check_point(baselib::vec2 p) { return col_check_point(p.x, p.y); }
+inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); }
 
 // Network stuff
 
diff --git a/src/game/mapres_col.cpp b/src/game/mapres_col.cpp
index d2f9d0c6..b25225e2 100644
--- a/src/game/mapres_col.cpp
+++ b/src/game/mapres_col.cpp
@@ -1,12 +1,11 @@
-#include <baselib/system.h>
-#include <baselib/vmath.h>
-#include <baselib/math.h>
+#include <engine/system.h>
+#include <game/vmath.h>
+#include <game/math.h>
+#include <math.h>
 #include "../engine/interface.h"
 #include "mapres_col.h"
 #include "mapres.h"
 
-using namespace baselib;
-
 /*
 	Simple collision rutines!
 */
diff --git a/src/game/mapres_col.h b/src/game/mapres_col.h
index 83690577..bc23d4d6 100644
--- a/src/game/mapres_col.h
+++ b/src/game/mapres_col.h
@@ -1,4 +1,4 @@
-#include <baselib/vmath.h>
+#include <game/vmath.h>
 
 struct mapres_collision
 {
@@ -9,4 +9,4 @@ struct mapres_collision
 
 int col_init(int dividor);
 int col_check_point(int x, int y);
-bool col_intersect_line(baselib::vec2 pos0, baselib::vec2 pos1, baselib::vec2 *out);
+bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out);
diff --git a/src/game/math.h b/src/game/math.h
new file mode 100644
index 00000000..7ef3baad
--- /dev/null
+++ b/src/game/math.h
@@ -0,0 +1,29 @@
+#ifndef BASE_MATH_H
+#define BASE_MATH_H
+
+template <typename T>
+inline T clamp(T val, T min, T max)
+{
+	if(val < min)
+		return min;
+	if(val > max)
+		return max;
+	return val;
+}
+
+inline float sign(float f)
+{
+	return f<0.0f?-1.0f:1.0f;
+}
+
+template<typename T, typename TB>
+inline T mix(const T a, const T b, TB amount)
+{
+	return a + (b-a)*amount;
+}
+const float pi = 3.1415926535897932384626433f;
+
+template <typename T> inline T min(T a, T b) { return a<b?a:b; }
+template <typename T> inline T max(T a, T b) { return a>b?a:b; }
+
+#endif // BASE_MATH_H
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index ddb3d9ab..f7bf976e 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -8,10 +8,8 @@
 
 data_container *data = 0x0;
 
-using namespace baselib;
-
 // --------- DEBUG STUFF ---------
-const int debug_bots = 0;
+const int debug_bots = 3;
 
 // --------- PHYSICS TWEAK! --------
 const float ground_control_speed = 7.0f;
@@ -653,7 +651,7 @@ void projectile::snap(int snapping_client)
 //////////////////////////////////////////////////
 // projectile_backpackrocket
 //////////////////////////////////////////////////
-projectile_backpackrocket::projectile_backpackrocket(baselib::vec2 pos, baselib::vec2 target, int owner, entity* powner)
+projectile_backpackrocket::projectile_backpackrocket(vec2 pos, vec2 target, int owner, entity* powner)
 : projectile(WEAPON_PROJECTILETYPE_ROCKET, owner, pos, vec2(0,0), 100, powner, 0, 0, 0, -1, WEAPON_ROCKET_BACKPACK)
 {
 	stage = 0;
@@ -1157,7 +1155,7 @@ void player::tick()
 {
 	// do latency stuff
 	{
-		client_info info;
+		CLIENT_INFO info;
 		if(server_getclientinfo(client_id, &info))
 		{
 			latency_accum += info.latency;
@@ -1201,9 +1199,9 @@ void player::tick()
 	
 	if(!grounded && vel.y > 0)
 	{
-		if(col_check_point((int)(pos.x-phys_size/2)-4, (int)(pos.y)))
+		if(input.left && col_check_point((int)(pos.x-phys_size/2)-4, (int)(pos.y)))
 			wall_sliding = -1;
-		if(col_check_point((int)(pos.x+phys_size/2)+4, (int)(pos.y)))
+		if(input.right && col_check_point((int)(pos.x+phys_size/2)+4, (int)(pos.y)))
 			wall_sliding = 1;
 	}
 
@@ -2037,7 +2035,7 @@ void mods_client_enter(int client_id)
 	world.insert_entity(&players[client_id]);
 	players[client_id].respawn();
 	
-	client_info info; // fetch login name
+	CLIENT_INFO info; // fetch login name
 	if(server_getclientinfo(client_id, &info))
 	{
 		strcpy(players[client_id].name, info.name);
diff --git a/src/game/server/game_server.h b/src/game/server/game_server.h
index 6361b3ea..3722713b 100644
--- a/src/game/server/game_server.h
+++ b/src/game/server/game_server.h
@@ -42,7 +42,7 @@ public:
 	float proximity_radius;
 	unsigned flags;
 	int objtype;
-	baselib::vec2 pos;
+	vec2 pos;
 
 	enum
 	{
@@ -65,7 +65,7 @@ public:
 		
 	virtual void snap(int snapping_client) {}
 		
-	virtual bool take_damage(baselib::vec2 force, int dmg, int from, int weapon) { return true; }
+	virtual bool take_damage(vec2 force, int dmg, int from, int weapon) { return true; }
 };
 
 
@@ -86,8 +86,8 @@ public:
 	bool reset_requested;
 	
 	game_world();
-	int find_entities(baselib::vec2 pos, float radius, entity **ents, int max);
-	int find_entities(baselib::vec2 pos, float radius, entity **ents, int max, const int* types, int maxtypes);
+	int find_entities(vec2 pos, float radius, entity **ents, int max);
+	int find_entities(vec2 pos, float radius, entity **ents, int max, const int* types, int maxtypes);
 
 	void insert_entity(entity *ent);
 	void destroy_entity(entity *ent);
@@ -156,7 +156,7 @@ public:
 		WEAPON_PROJECTILETYPE_SHOTGUN	= 2,
 	};
 	
-	baselib::vec2 vel;
+	vec2 vel;
 	entity *powner; // this is nasty, could be removed when client quits
 	int lifespan;
 	int owner;
@@ -168,7 +168,7 @@ public:
 	int bounce;
 	float force;
 	
-	projectile(int type, int owner, baselib::vec2 pos, baselib::vec2 vel, int span, entity* powner,
+	projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner,
 		int damage, int flags, float force, int sound_impact, int weapon);
 	virtual void reset();
 	virtual void tick();
@@ -180,12 +180,12 @@ class projectile_backpackrocket : public projectile
 	int stage;
 	int start_tick;
 	int deply_ticks;
-	baselib::vec2 target;
-	baselib::vec2 start;
-	baselib::vec2 midpoint;
-	baselib::vec2 direction;
+	vec2 target;
+	vec2 start;
+	vec2 midpoint;
+	vec2 direction;
 public:
-	projectile_backpackrocket(baselib::vec2 pos, baselib::vec2 target, int owner, entity* powner);
+	projectile_backpackrocket(vec2 pos, vec2 target, int owner, entity* powner);
 	virtual void tick();
 };
 
@@ -225,9 +225,9 @@ public:
 	int last_action;
 	
 	// we need a defered position so we can handle the physics correctly
-	baselib::vec2 defered_pos;
-	baselib::vec2 vel;
-	baselib::vec2 direction;
+	vec2 defered_pos;
+	vec2 vel;
+	vec2 direction;
 
 	//
 	int client_id;
@@ -244,7 +244,7 @@ public:
 	int armor;
 
 	// ninja
-	baselib::vec2 activationdir;
+	vec2 activationdir;
 	int ninjaactivationtick;
 	int extrapowerflags;
 	int currentcooldown;
@@ -278,8 +278,8 @@ public:
 	int hook_state;
 	int hook_tick;
 	player *hooked_player;
-	baselib::vec2 hook_pos;
-	baselib::vec2 hook_dir;
+	vec2 hook_pos;
+	vec2 hook_dir;
 
 	//
 	player();
@@ -305,7 +305,7 @@ public:
 	
 	void die(int killer, int weapon);
 	
-	virtual bool take_damage(baselib::vec2 force, int dmg, int from, int weapon);
+	virtual bool take_damage(vec2 force, int dmg, int from, int weapon);
 	virtual void snap(int snaping_client);
 };
 
@@ -317,7 +317,7 @@ class flag : public entity
 public:
 	static const int phys_size = 14;
 	player *carrying_player;
-	baselib::vec2 vel;
+	vec2 vel;
 	
 	int team;
 	int spawntick;
diff --git a/src/game/vmath.h b/src/game/vmath.h
new file mode 100644
index 00000000..d7b502b1
--- /dev/null
+++ b/src/game/vmath.h
@@ -0,0 +1,181 @@
+#ifndef BASE_VMATH_H
+#define BASE_VMATH_H
+
+//#include <engine/system.h>
+
+// ------------------------------------
+
+template<typename T>
+class vector2_base
+{
+public:
+	union { T x,u; };
+	union { T y,v; };
+	
+	vector2_base() {}
+	vector2_base(float nx, float ny)
+	{
+		x = nx;
+		y = ny;
+	}
+	
+	vector2_base operator -() const { return vector2_base(-x, -y); }
+	vector2_base operator -(const vector2_base &v) const { return vector2_base(x-v.x, y-v.y); }
+	vector2_base operator +(const vector2_base &v) const { return vector2_base(x+v.x, y+v.y); }
+	vector2_base operator *(const T v) const { return vector2_base(x*v, y*v); }
+	
+	const vector2_base &operator =(const vector2_base &v) { x = v.x; y = v.y; return *this; }
+
+	const vector2_base &operator +=(const vector2_base &v) { x += v.x; y += v.y; return *this; }
+	const vector2_base &operator -=(const vector2_base &v) { x -= v.x; y -= v.y; return *this; }
+	const vector2_base &operator *=(const T v) { x *= v; y *= v; return *this;	}
+
+	bool operator ==(const vector2_base &v) const { return x == v.x && y == v.y; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+
+template<typename T>
+inline T length(const vector2_base<T> &a)
+{
+	return sqrtf(a.x*a.x + a.y*a.y);
+}
+
+template<typename T>
+inline T distance(const vector2_base<T> a, const vector2_base<T> &b)
+{
+	return length(a-b);
+}
+
+template<typename T>
+inline T dot(const vector2_base<T> a, const vector2_base<T> &b)
+{
+	return a.x*b.x + a.y*b.y;
+}
+
+template<typename T>
+inline vector2_base<T> normalize(const vector2_base<T> &v)
+{
+	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y));
+	return vector2_base<T>(v.x*l, v.y*l);
+}
+
+typedef vector2_base<float> vec2;
+typedef vector2_base<bool> bvec2;
+typedef vector2_base<int> ivec2;
+	
+// ------------------------------------
+template<typename T>
+class vector3_base
+{
+public:
+	union { T x,r; };
+	union { T y,g; };
+	union { T z,b; };
+
+	vector3_base() {}
+	vector3_base(float nx, float ny, float nz)
+	{
+		x = nx;
+		y = ny;
+		z = nz;
+	}
+	
+	const vector3_base &operator =(const vector3_base &v) { x = v.x; y = v.y; z = v.z; return *this; }
+
+	vector3_base operator -(const vector3_base &v) const { return vector3_base(x-v.x, y-v.y, z-v.z); }
+	vector3_base operator -() const { return vector3_base(-x, -y, -z); }
+	vector3_base operator +(const vector3_base &v) const { return vector3_base(x+v.x, y+v.y, z+v.z); }
+	vector3_base operator *(const T v) const { return vector3_base(x*v, y*v, z*v); }
+	vector3_base operator *(const vector3_base &v) const { return vector3_base(x*v.x, y*v.y, z*v.z); }
+	vector3_base operator /(const T v) const { return vector3_base(x/v, y/v, z/v); }
+	
+	const vector3_base &operator +=(const vector3_base &v) { x += v.x; y += v.y; z += v.z; return *this; }
+	const vector3_base &operator -=(const vector3_base &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
+	const vector3_base &operator *=(const T v) { x *= v; y *= v; z *= v; return *this;	}
+
+	bool operator ==(const vector3_base &v) const { return x == v.x && y == v.y && z == v.z; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+template<typename T>
+inline T length(const vector3_base<T> &a)
+{
+	return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z);
+}
+
+template<typename T>
+inline T distance(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return length(a-b);
+}
+
+template<typename T>
+inline T dot(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return a.x*b.x + a.y*b.y + a.z*b.z;
+}
+
+template<typename T>
+inline vector3_base<T> normalize(const vector3_base<T> &v)
+{
+	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y + v.z*v.z));
+	return vector3_base<T>(v.x*l, v.y*l, v.z*l);
+}
+
+template<typename T>
+inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return vector3_base<T>(
+		a.y*b.z - a.z*b.y,
+		a.z*b.x - a.x*b.z,
+		a.x*b.y - a.y*b.x);
+}
+
+typedef vector3_base<float> vec3;
+typedef vector3_base<bool> bvec3;
+typedef vector3_base<int> ivec3;
+
+// ------------------------------------
+
+template<typename T>
+class vector4_base
+{
+public:
+	union { T x,r; };
+	union { T y,g; };
+	union { T z,b; };
+	union { T w,a; };
+
+	vector4_base() {}
+	vector4_base(float nx, float ny, float nz, float nw)
+	{
+		x = nx;
+		y = ny;
+		z = nz;
+		w = nw;
+	}
+	
+	vector4_base operator +(const vector4_base &v) const { return vector4_base(x+v.x, y+v.y, z+v.z, w+v.w); }
+	vector4_base operator -(const vector4_base &v) const { return vector4_base(x-v.x, y-v.y, z-v.z, w-v.w); }
+	vector4_base operator -() const { return vector4_base(-x, -y, -z, -w); }
+	vector4_base operator *(const T v) const { return vector4_base(x*v, y*v, z*v, w*v); }
+	
+	const vector4_base &operator =(const vector4_base &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; }
+
+	const vector4_base &operator +=(const vector4_base &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
+	const vector4_base &operator -=(const vector4_base &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
+	const vector4_base &operator *=(const T v) { x *= v; y *= v; z *= v; w *= v; return *this;	}
+
+	bool operator ==(const vector4_base &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+typedef vector4_base<float> vec4;
+typedef vector4_base<bool> bvec4;
+typedef vector4_base<int> ivec4;
+
+#endif