diff --git a/Rules.make b/Rules.make
index 4f85f6d84..b1b43bf6d 100644
--- a/Rules.make
+++ b/Rules.make
@@ -1,6 +1,6 @@
 ##   ___________		     _________		      _____  __
 ##   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
-##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \   __\   __\ 
 ##    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
 ##    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
 ##	  \/		    \/	   \/	     \/		   \/
@@ -8,244 +8,71 @@
 ##			  T H E   W A R   B E G I N S
 ##	   FreeCraft - A free fantasy real time strategy game engine
 ##	
-##	Rules.make	-	Make RULES (GNU MAKE).
-##
-##	(c) Copyright 1998-2000 by Lutz Sammer
-##
-##	$Id$
-##
 
-############################################################################
-#	Configurable:
-#			Choose what you want to include and the correct 
-#			version.  Minimal is now the default.
-############################################################################
+# Compile commands
+CC=gcc
+RM=rm -f
+MAKE=make
 
-# Uncomment next to get guile with gtk (and choose your gtklib version)
-
-#GUILEGTK	= -DGUILE_GTK $(shell gtk-config --cflags)
-#GUILEGTK	= -DGUILE_GTK -I/usr/X11R6/include -I/usr/lib/glib/include
-#GUILEGTKLIB	= -lguilegtk-1.0 $(shell gtk-config --libs)
-#GUILEGTKLIB	= -lguilegtk-1.2 $(shell gtk-config --libs)
-#GUILEGTKLIB	= -L/opt/gnome/lib -lguilegtk-1.1 \
-			$(shell /opt/gnome/bin/gtk-config --libs)
-
-#------------------------------------------------------------------------------
-
-# Uncomment next for a version with guile (GNU scheme interpreter)
-#	(and choose your guile version)
-
-# guile 1.2	old version
-# 	If you have unreferenced "gh_vector_ref" define LIBGUILE12
-#GUILE		= -DLIBGUILE12 -DUSE_CCL $(GUILEGTK)
-#GUILELIB	= $(GUILEGTKLIB) -lguile -ldl
-
-# guile 1.3	latest version
-#	-lreadline -lncurses are needed with the distribution SuSe 5.3
-#GUILE_CFLAGS	= $(shell guile-config compile)
-#GUILE		= -DUSE_CCL $(GUILEGTK) $(GUILE_CFLAGS)
-#GUILELIB	= $(GUILEGTKLIB) -lguile -lqthreads -ldl -lm
-#GUILELIB	= $(GUILEGTKLIB) $(shell guile-config link) -lreadline -lncurses
-#GUILELIB	= $(GUILEGTKLIB) $(shell guile-config link)
-
-# guile
-#CCL	= $(GUILE)
-#CCLLIB	= $(GUILELIB)
-
-#------------------------------------------------------------------------------
-# Comment next for a version without SIOD (scheme interpreter)
-#
-
-# Try to use siod (currently default)
-CCL	= -DUSE_CCL2
-CCLLIB	= -lm
-
-#------------------------------------------------------------------------------
-
-# Uncomment next to add threaded sound support 
-#	You should have a thread safe X11 (libc6 or glibc)
-
-#THREAD		= -D_REENTRANT -DUSE_THREAD
-#THREADLIB	= -lpthread
-
-#------------------------------------------------------------------------------
-
-# Choose correct version of glib (needed for gtk)
-
-# Where do you have installed your glib?
-#GLIB		=	-DUSE_GLIB -I/usr/lib/glib/include/
-#GLIBLIB 	=	-lglib
-
-# Should work with >= 1.2
-#GLIB_CFLAGS	=	$(shell glib-config glib --cflags)
-#GLIBLIB 	=	$(shell glib-config glib --libs)
-#GLIB		=	-DUSE_GLIB $(GLIB_CFLAGS)
-
-#------------------------------------------------------------------------------
-#	Video driver part
-#------------------------------------------------------------------------------
-
-# Uncomment the next for the normal X11 support.
+# Use SIOD support
+CCL		= -DUSE_CCL2
+CCLLIB		= -lm -ldl
 
+# Video support
 VIDEO		= -DUSE_X11
-VIDEOLIB	= -lXext -lX11 -ldl 
-
-# Uncomment the next to get the support for SDL.
-
-# Old SDL <1.0.0
-#SDL_CFLAGS	=	
-#SDLLIB		= -lSDL -ldl -lpthread
-
-# New SDL >=1.0.0
-SDL_CFLAGS	= $(shell sdl-config --cflags)
-#SDLLIB		= $(shell sdl-config --static-libs)
-SDLLIB		= $(shell sdl-config --libs)
-
-# Without SDL Sound
-#SDL		= -DUSE_SDL $(SDL_CFLAGS)
-# With SDL Sound
-SDL		= -DUSE_SDL -DUSE_SDLA $(SDL_CFLAGS)
-
-# Uncomment the next for the SDL X11/SVGALIB support.
-
-VIDEO		= $(SDL)
-VIDEOLIB	= $(SDLLIB) -lXext -lX11 -lXxf86dga -lXxf86vm -lvga -lvgagl -ldl -lesd -lm
-
-# Choose next to get svgalib support.
-
-#VIDEO		= -DUSE_SVGALIB
-#VIDEOLIB	= -lvga -lm -ldl
-
-# Uncomment the next for the win32/cygwin support.
-
-#VIDEO		= -DUSE_WIN32 $(SDL)
-#VIDEOLIB	= $(SDLLIB)
-
-# Uncomment the next for the win32/mingw32 support.
-
-#VIDEO		= -DUSE_WIN32 $(SDL)
-#VIDEOLIB	= $(SDLLIB) -lwsock32 -Wl,--stack,33554432
-
-#------------------------------------------------------------------------------
-#	Sound driver part
-#------------------------------------------------------------------------------
-
-# Comment next if you want to remove sound support.
+VIDEOLIB	= -lXext -lX11 -ldl
 
+# Sound support
 DSOUND		= -DWITH_SOUND
 
-#------------------------------------------------------------------------------
-
-# Choose which compress you like
-#	The win32 port didn't support BZ2LIB
-
-# None
-#ZDEFS		=
-#ZLIBS		=
-# GZ compression
-ZDEFS		= -DUSE_ZLIB
-ZLIBS		= -lz
-# BZ2 compression
-#ZDEFS		= -DUSE_BZ2LIB
-#ZLIBS		= -lbz2
-# GZ + BZ2 compression
-#ZDEFS		= -DUSE_ZLIB -DUSE_BZ2LIB
-#ZLIBS		= -lz -lbz2
-
-#------------------------------------------------------------------------------
-
-# May be required on some distributions for libpng and libz!
-# extra linker flags and include directory
-# -L/usr/lib 
+# Compression support
+ZDEFS		= -DUSE_ZLIB -DUSE_BZ2LIB
+ZLIBS		= -lz -lbz2
 
 XLDFLAGS	= -L/usr/X11R6/lib -L/usr/local/lib \
 		  -L$(TOPDIR)/libpng-1.0.5 -L$(TOPDIR)/zlib-1.1.3
 XIFLAGS		= -I/usr/X11R6/include -I/usr/local/include \
 		  -I$(TOPDIR)/libpng-1.0.5 -I$(TOPDIR)/zlib-1.1.3
 
-#------------------------------------------------------------------------------
- 
-# Uncomment next to profile
-#PROFILE=	-pg
+#####################################################################
+# Don't change anything below here unless you know what you're doing!
 
-# Version
 VERSION=	'-DVERSION="1.17pre1-build7"'
+PROFILE=
 
-############################################################################
-# below this, nothing should be changed!
-
-# Libraries needed to build tools
 TOOLLIBS=$(XLDFLAGS) -lpng -lz -lm $(THREADLIB)
-
-# Libraries needed to build freecraft
 CLONELIBS=$(XLDFLAGS) -lpng -lz -lm \
-	$(THREADLIB) $(CCLLIB) $(GLIBLIB) $(VIDEOLIB) $(ZLIBS)
-
+	$(THREADLIB) $(CCLLIB) $(VIDEOLIB) $(ZLIBS)
 DISTLIST=$(TOPDIR)/distlist
 TAGS=$(TOPDIR)/src/tags
 
-# LINUX
+# Linux
+EXE=
 OUTFILE=$(TOPDIR)/freecraft
 ARCH=linux
 OE=o
-EXE=
 
-# WIN32
-#OUTFILE=$(TOPDIR)/freecraft$(EXE)
-#ARCH=win32
-#OE=o
-#EXE=.exe
-
-## architecture-dependant objects
 #ARCHOBJS=stdmman.$(OE) svgalib.$(OE) unix_lib.$(OE) bitm_lnx.$(OE)
-
-## include flags
 IFLAGS=	-I$(TOPDIR)/src/include $(XIFLAGS)
-## define flags
-DEBUG=	-DDEBUG #-DNEW_AI # -DFLAG_DEBUG
-DFLAGS=	$(THREAD) $(CCL) $(VERSION) $(GLIB) $(VIDEO) $(ZDEFS) $(DSOUND) \
-	$(DEBUG) -DUNIT_ON_MAP # -DNEW_NAMES
-
-## choose optimise level
-#CFLAGS=-g -O0 $(PROFILE) -pipe -Wall -Werror $(IFLAGS) $(DFLAGS)
-#CFLAGS=-g -O1 $(PROFILE) -pipe -Wall -Werror $(IFLAGS) $(DFLAGS)
-#CFLAGS=-g -O2 $(PROFILE) -pipe -Wall -Werror $(IFLAGS)  $(DFLAGS)
-CFLAGS=-g -O3 $(PROFILE) -pipe -Wall -Werror $(IFLAGS)  $(DFLAGS)
-#CFLAGS=-g -O3 $(PROFILE) -pipe -Wall $(IFLAGS)  $(DFLAGS)
-#CFLAGS=-g -O6 -pipe -fconserve-space -fexpensive-optimizations -ffast-math  $(IFLAGS) $(DFLAGS)
-#-- Production
-#CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math  $(IFLAGS) $(DFLAGS)
-CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math  $(IFLAGS) $(DFLAGS) -static
-
-CC=gcc
-RM=rm -f
-MAKE=make
-
-## JOHNS: my ctags didn't support
-#CTAGSFLAGS=-i defmpstuvFS -a -f 
+DFLAGS=	$(THREAD) $(CCL) $(VERSION) \
+	$(VIDEO) $(ZDEFS) $(DSOUND) \
+	$(DEBUG) 
+CFLAGS=-g  $(IFLAGS) $(DFLAGS)  -DSLOW_INPUT -DUNIT_ON_MAP
 CTAGSFLAGS=-i defptvS -a -f 
 
-#
-#	Locks versions with symbolic name
-#
+# Locks versions with a symbolic name
 LOCKVER=	rcs -q -n$(NAME)
 
 %.o: %.c
 	$(CC) -c $(CFLAGS) $< -o $@
 	@ar cru $(TOPDIR)/src/libclone.a $@
 
-#------------
-#	Source code documentation
-#
+# Source code documentation
 DOXYGEN=	doxygen
 DOCIFY=		docify
 DOCPP=		doc++
-# Still didn't work
-#DOCIFY=		/root/doc++-3.4.2/src/docify
-#DOCPP=		/root/doc++-3.4.2/src/doc++
 
 %.doc: %.c
 	@$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-c.doc 2>/dev/null
-
 %.doc: %.h
 	@$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-h.doc 2>/dev/null
diff --git a/src/action/Makefile b/src/action/Makefile
index 228793b98..b30220756 100644
--- a/src/action/Makefile
+++ b/src/action/Makefile
@@ -1,6 +1,6 @@
 ##   ___________		     _________		      _____  __
 ##   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
-##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\
 ##    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
 ##    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
 ##	  \/		    \/	   \/	     \/		   \/
@@ -27,6 +27,7 @@ OBJS	= command.$(OE) actions.$(OE) action_die.$(OE) action_patrol.$(OE) \
 	action_board.$(OE) action_unload.$(OE) action_repair.$(OE) \
 	action_harvest.$(OE) action_minegold.$(OE) action_hauloil.$(OE) \
 	action_returngoods.$(OE) action_research.$(OE) action_demolish.$(OE) \
-	action_build.$(OE) action_train.$(OE) action_upgradeto.$(OE)  
+	action_build.$(OE) action_train.$(OE) action_upgradeto.$(OE) \
+	action_spellcast.$(OE)
 
 include $(TOPDIR)/Common.mk
diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index c0741c76a..5c0757887 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -73,6 +73,7 @@ local void DoActionAttackGeneric(Unit* unit,const Animation* attack)
 
     if( flags&AnimationMissile ) {	// time to fire projectil
 	FireMissile(unit);
+	unit->Invisible = 0; // unit is invisible untill attacks
     }
 }
 
diff --git a/src/action/action_demolish.cpp b/src/action/action_demolish.cpp
index f4a68d271..392c6f694 100644
--- a/src/action/action_demolish.cpp
+++ b/src/action/action_demolish.cpp
@@ -130,7 +130,8 @@ global void HandleActionDemolish(Unit* unit)
             n=SelectUnits(x-2,y-2, x+2, y+2,table);
 	    // FIXME: Don't hit flying units!
             for( i=0; i<n; ++i ) {
-                HitUnit(table[i],DEMOLISH_DAMAGE);
+	    	if ( table[i]->Type->LandUnit )
+                   HitUnit(table[i],DEMOLISH_DAMAGE);
             }
 
 	    //
diff --git a/src/action/action_die.cpp b/src/action/action_die.cpp
index 86c8e4047..a0fec658b 100644
--- a/src/action/action_die.cpp
+++ b/src/action/action_die.cpp
@@ -46,6 +46,14 @@
 */
 global int HandleActionDie(Unit* unit)
 {
+    if ( unit->Revealer )
+    {
+    unit->HP--;
+    if( unit->HP == 0 )
+      ReleaseUnit(unit);
+    return 0;
+    }
+
     //
     //	Show death animation
     //
diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index d1fdf115c..14097367c 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -94,6 +94,10 @@ global int UnitShowAnimation(Unit* unit,const Animation* animation)
 */
 local void HandleUnitAction(Unit* unit)
 {
+    if ( unit->Revealer )
+    {
+    unit->Command.Action = UnitActionDie;
+    }
     //
     //	If current action is breakable proceed with next one.
     //
@@ -237,6 +241,10 @@ local void HandleUnitAction(Unit* unit)
 	    HandleActionDemolish(unit);
 	    break;
 
+	case UnitActionSpellCast:
+	    HandleActionSpellCast(unit);
+	    break;
+
 	default:
 	    DebugLevel1Fn("Unknown action %d\n",unit->Command.Action);
 	    break;
diff --git a/src/action/command.cpp b/src/action/command.cpp
index f48e8213a..1ec131893 100644
--- a/src/action/command.cpp
+++ b/src/action/command.cpp
@@ -33,6 +33,7 @@
 #include "map.h"
 #include "upgrade.h"
 #include "pathfinder.h"
+#include "spells.h"
 
 /*----------------------------------------------------------------------------
 --	Functions
@@ -829,4 +830,66 @@ global void CommandDemolish(Unit* unit,int x,int y,Unit* dest,int flush)
     unit->SavedCommand.Action=UnitActionStill;	// clear saved action
 }
 
+/**
+**	Demolish at position
+**
+**	@param unit	pointer to unit.
+**	@param x	X map position to spell cast on.
+**	@param y	Y map position to spell cast on.
+**	@param dest	Spell cast on unit (if exist).
+**	@param spellid  Spell type id.
+**	@param flush	if true, flush command queue.
+*/
+global void CommandSpellCast(Unit* unit,int x,int y,Unit* dest,int spellid,int flush)
+{
+    Command* command;
+    const SpellType* spell;
+    
+    IfDebug(
+	if( x<0 || y<0 || x>=TheMap.Width || y>=TheMap.Height ) {
+	    DebugLevel0("Internal movement error\n");
+	    return;
+	}
+	if( unit->Type->Vanishes ) {
+	    DebugLevel0("Internal error\n");
+	    abort();
+	}
+    );
+
+    DebugLevel3(__FUNCTION__": %Zd spell-casts on %Zd\n"
+	,UnitNumber(unit),dest ? UnitNumber(dest) : 0);
+
+    if( unit->Type->Building ) {
+	// FIXME: should find a better way for pending commands.
+	command=&unit->PendCommand;
+    } else if( !(command=GetNextCommand(unit,flush)) ) {
+	return;
+    }
+
+    spell = SpellTypeById( spellid );
+
+    command->Action=UnitActionSpellCast;
+    ResetPath(*command);
+    
+    if (dest)
+      dest->Refs++;
+    
+    command->Data.Move.Goal=dest;
+    command->Data.Move.Range=spell->Range;
+    command->Data.Move.SX=unit->X;
+    command->Data.Move.SY=unit->Y;
+    command->Data.Move.DX=x;
+    command->Data.Move.DY=y;
+    command->Data.Move.SpellId = spellid;
+    
+    /*
+    command->Data.Spell.Goal=dest;
+    command->Data.Spell.Range=spell->Range;
+    command->Data.Spell.DX=x;
+    command->Data.Spell.DY=y;
+    */
+    
+    unit->SavedCommand.Action=UnitActionStill;	// clear saved action
+}
+
 //@}
diff --git a/src/include/actions.h b/src/include/actions.h
index 9b356c72c..fc42bb51d 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -88,6 +88,8 @@ extern void CommandCancelResearch(Unit* unit);
 //extern void CommandUpgradeUnit(Unit* unit,int what,int flush);
     /// Prepare command demolish
 extern void CommandDemolish(Unit* unit,int x,int y,Unit* dest,int flush);
+    /// Prepare command spellcast
+extern void CommandSpellCast(Unit* unit,int x,int y,Unit* dest,int spellid, int flush);
 
 /*----------------------------------------------------------------------------
 --	Actions:	in action_<name>.c
@@ -135,6 +137,8 @@ extern void HandleActionUpgrade(Unit* unit);
 extern void HandleActionResearch(Unit* unit);
     /// Handle command demolish
 extern void HandleActionDemolish(Unit* unit);
+    /// Handle command spellcast
+extern void HandleActionSpellCast(Unit* unit);
 
 /*----------------------------------------------------------------------------
 --	Actions:	actions.c
diff --git a/src/include/cursor.h b/src/include/cursor.h
index a6163c596..f86d17fbb 100644
--- a/src/include/cursor.h
+++ b/src/include/cursor.h
@@ -82,6 +82,7 @@ extern CursorType Cursors[CursorMax];	/// cursor types description
 
 extern enum CursorState_e CursorState;	/// cursor state
 extern int CursorAction;		/// action for selection
+extern int CursorValue;			/// value for CursorAction (spell type f.e.)
 extern UnitType* CursorBuilding;	/// building cursor
 
 extern CursorType* GameCursor;		/// cursor type
diff --git a/src/include/interface.h b/src/include/interface.h
index 3d3b74b81..2faddf600 100644
--- a/src/include/interface.h
+++ b/src/include/interface.h
@@ -47,7 +47,7 @@ enum _button_cmd_ {
     B_AttackGround,			/// order attack ground
     B_Return,				/// order return goods
     B_Demolish,				/// order demolish/explode
-    B_Magic,				/// order cast spell
+    B_SpellCast,			/// order cast spell
     B_Research,				/// order reseach
     B_UpgradeTo,			/// order upgrade
     B_Unload,				/// order unload unit
diff --git a/src/include/missile.h b/src/include/missile.h
index a601dd494..4ec1cbf10 100644
--- a/src/include/missile.h
+++ b/src/include/missile.h
@@ -69,7 +69,7 @@ struct _missile_type_ {
 };
 
     /// how many missile type are maximal supported
-#define MissileTypeMax			0x1E
+#define MissileTypeMax			0x22
 
     /// mark a free missile slot
 #define MissileFree			(MissileType*)0
@@ -96,11 +96,18 @@ typedef struct _missile_ {
     UnitStats*	SourceStats;		/// stats of unit that fires
     Player*	SourcePlayer;		/// player of unit that fires
 
+    Unit* TargetUnit;                   /// target unit, used for spells
+
+    int 	Damage;                 /// direct damage that missile applies
+    
     int		D;			/// for point to point missiles
     int		Dx;			/// delta x
     int		Dy;			/// delta y
     int		Xstep;			/// X step
     int		Ystep;			/// Y step
+    
+    int TTL;				/// time to live (ticks) used for spells
+    int (*Controller)( void* this_missile );    /// used to controll spells
 } Missile;
 
 /*----------------------------------------------------------------------------
diff --git a/src/include/network.h b/src/include/network.h
index 1515fa80e..cfdbd4a14 100644
--- a/src/include/network.h
+++ b/src/include/network.h
@@ -105,7 +105,8 @@ extern void SendCommandResearch(Unit* unit,Upgrade* what,int flush);
 extern void SendCommandCancelResearch(Unit* unit);
     /// Send demolish command
 extern void SendCommandDemolish(Unit* unit,int x,int y,Unit* dest,int flush);
-
+    /// Send spell cast command
+extern void SendCommandSpellCast(Unit* unit,int x,int y,Unit* dest,int spellid,int flush);
 //@}
 
 #endif	// !__NETWORK_H__
diff --git a/src/include/spells.h b/src/include/spells.h
new file mode 100644
index 000000000..ce48411c6
--- /dev/null
+++ b/src/include/spells.h
@@ -0,0 +1,112 @@
+//   ___________		     _________		      _____  __
+//   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
+//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
+//        \/		    \/	   \/	     \/		   \/
+//  ______________________                           ______________________
+//                        T H E   W A R   B E G I N S
+//	   FreeCraft - A free fantasy real time strategy game engine
+//
+/**@name spells.h	-	The Spells. */
+/*
+**	(c) Copyright 1999,2000 by Vladi Belperchinov-Shabanski
+**
+**	$Id$
+*/
+
+#ifndef __SPELLS_H__
+#define __SPELLS_H__
+
+//@{
+
+/*----------------------------------------------------------------------------
+--	Includes
+----------------------------------------------------------------------------*/
+#include <stdio.h>
+
+#include "freecraft.h"
+#include "sound_id.h"
+#include "sound.h"
+#include "unittype.h"
+#include "unit.h"
+
+/*----------------------------------------------------------------------------
+--	Definitons
+----------------------------------------------------------------------------*/
+
+
+typedef enum _spell_action_type_ {
+	SpellActionNone,
+// 	---human paladins---
+	SpellActionHolyVision,
+	SpellActionHealing,
+	SpellActionExorcism,
+// 	---human mages---
+	SpellActionFireball,
+	SpellActionSlow,
+	SpellActionFlameShield,
+	SpellActionInvisibility,
+	SpellActionPolymorph,
+	SpellActionBlizzard,
+// 	---orc ogres---
+	SpellActionEyeOfKilrogg,
+	SpellActionBloodlust,
+	SpellActionRunes,
+// 	---orc death knights---
+	SpellActionDeathCoil,
+	SpellActionHaste,
+	SpellActionRaiseDead,
+	SpellActionWhirlwind,
+	SpellActionUnholyArmor,
+	SpellActionDeathAndDecay
+} SpellActionType;
+
+typedef struct _spell_type_ {
+
+  int  Id;              /// index in the table (set by InitSpells())
+  char Ident[64];	/// spell name (ident)
+  
+  int  Range;		/// spell range
+  int  ManaCost;	/// required mana for each cast
+  int  TTL;		/// time to live (ticks)
+
+  SpellActionType  Action;  /// SpellAction*
+  
+  char SoundIdent[64];  /// sound string id
+  SoundId SoundId;      /// sound id 
+  
+} SpellType;
+
+/*----------------------------------------------------------------------------
+--	Variables
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+--	Functions
+----------------------------------------------------------------------------*/
+  
+  /// init spell tables
+extern global void InitSpells();
+  
+  /// done spell tables
+extern global void DoneSpells();
+
+  /// return spell id by ident string
+extern global int SpellIdByIdent( const char* Ident );
+  
+  /// return spell type by ident string
+extern global const SpellType* SpellTypeByIdent( const char* Ident );
+  
+  /// return spell type by ident string
+extern global const SpellType* SpellTypeById( int Id );
+
+/*  /// returns != 0 if spell can be casted by this unit, enough mana?
+extern global int CanCastSpell( Unit* unit, int SpellId );
+*/
+  /// fire spell on target unit or place at x,y
+extern global int SpellCast( int SpellId, Unit* unit, Unit* target, int x, int y );
+
+//@}
+
+#endif	// !__BUTTON_H__
diff --git a/src/include/unit.h b/src/include/unit.h
index df18c135f..c7290a5d8 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -1,6 +1,6 @@
 //   ___________		     _________		      _____  __
 //   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
-//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\
 //    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
 //    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
 //	  \/		    \/	   \/	     \/		   \/
@@ -62,6 +62,8 @@ enum _unit_action_ {
     UnitActionAttackGround,		/// unit attacks ground
     UnitActionDie,			/// unit dies
 
+    UnitActionSpellCast,		/// unit casts spell
+
     UnitActionTrain,			/// building is training
     UnitActionUpgradeTo,		/// building is upgrading itself
     // UnitActionUpgrade,		/// building is researching upgrade
@@ -130,6 +132,7 @@ struct _command_ {
 	    unsigned	SY;		/// Source
 	    unsigned	DX;
 	    unsigned	DY;		/// Destination
+	    int         SpellId;	/// spell type id
 	} Move;				/// move:
 	struct {
 	    unsigned	Fast : 1;	/// Can fast move
@@ -152,7 +155,7 @@ struct _command_ {
 	struct {
 	    unsigned	Ticks;		/// Ticks to complete
 	    unsigned	Count;		/// Units in training queue
-	    // FIXME: cade: later we should train more units or automatic
+	    // FIXME: vladi: later we should train more units or automatic
 #define MAX_UNIT_TRAIN	6
 	    UnitType*	What[MAX_UNIT_TRAIN];	/// Unit trained
 	} Train;			/// train:
@@ -230,7 +233,7 @@ struct _unit_ {
     UnitType*	Type;			/// pointer to unit type (peon,...)
     Player*     Player;			/// owner of this unit
     UnitStats*	Stats;			/// current unit stats
-    
+ 
 //	DISPLAY:
     char	IX;
     char	IY;			/// image displacement to map position
@@ -252,10 +255,11 @@ struct _unit_ {
     unsigned	HP;			/// hit points
 
     unsigned	Bloodlust;		/// ticks bloodlust
-    unsigned	Haste;			/// ticks haste
-    unsigned	Slow;			/// ticks slow
+    unsigned	Haste;			/// ticks haste (disables slow)
+    unsigned	Slow;			/// ticks slow (disables haste)
     unsigned	Invisible;		/// ticks invisible
-    unsigned	Shield;			/// ticks shield
+    unsigned	FlameShield;		/// ticks flame shield
+    unsigned	UnholyArmor;		/// ticks unholy armor
 
     unsigned	GroupId;		/// unit belongs to this group id
 
@@ -273,6 +277,10 @@ struct _unit_ {
 					** ,used for fancy buildings
 					*/
     unsigned 	Rs : 8;
+    unsigned	Revealer;               // hack -- `revealer' is unit that
+                                        // has to keep FOW revealed for some
+					// time, this unit cannot be used in
+					// usual manner
 
 #define MAX_UNITS_ONBOARD 6		/// max number of units in transporter
     // FIXME: use the new next pointer
diff --git a/src/map/map_fog.cpp b/src/map/map_fog.cpp
index b60394a2e..b4d4d1558 100644
--- a/src/map/map_fog.cpp
+++ b/src/map/map_fog.cpp
@@ -358,11 +358,13 @@ global void MapUpdateVisible(void)
 #ifdef NEW_FOW
 	MapMarkSight(unit->Player,unit->X+unit->Type->TileWidth/2
 		,unit->Y+unit->Type->TileHeight/2
-		,unit->Stats->SightRange);
+		,unit->Stats->SightRange*(unit->Revealer == 0) 
+		                    + 12*(unit->Revealer != 0));
 #else
 	MapMarkSight(unit->X+unit->Type->TileWidth/2
 		,unit->Y+unit->Type->TileHeight/2
-		,unit->Stats->SightRange);
+		,unit->Stats->SightRange*(unit->Revealer == 0) 
+		                    + 12*(unit->Revealer != 0));
 #endif
     }
 }
diff --git a/src/network/network.cpp b/src/network/network.cpp
index 8b72fecd1..4daf48736 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -113,6 +113,7 @@ enum _message_type_ {
     MessageCommandResearch,		/// unit command research
     MessageCommandCancelResearch,	/// unit command cancel research
     MessageCommandDemolish,		/// unit command demolish
+    MessageCommandSpellCast		/// unit command spell cast
 };
 
 /**
@@ -710,6 +711,30 @@ global void SendCommandDemolish(Unit* unit,int x,int y,Unit* attack,int flush)
     }
 }
 
+/**
+**	Send command: Unit spell cast on position/unit.
+**
+**	@param unit	pointer to unit.
+**	@param x	X map tile position where to cast spell.
+**	@param y	Y map tile position where to cast spell.
+**	@param attack	Cast spell on unit (if exist).
+**	@param spellid  Spell type id.
+**	@param flush	Flag flush all pending commands.
+*/
+global void SendCommandSpellCast(Unit* unit,int x,int y,Unit* dest,int spellid,int flush)
+{
+    CommandLog("spell-cast",unit,flush,1,x,y,dest,NULL); //FIXME: vladi: spellid?
+    if( NetworkFildes==-1 ) {
+	CommandSpellCast(unit,x,y,dest,spellid,flush);
+    } else {
+        // FIXME: WARNING: vladi: this is weird, we should have and
+	// integer argument to all this or just few bytes buffer or 
+	// something... I'll pass spell id's as pointers until...
+	UnitType* ut = (UnitType*)spellid;
+	NetworkSendCommand(MessageCommandSpellCast,unit,x,y,dest,ut,flush);
+    }
+}
+
 //@}
 
 //----------------------------------------------------------------------------
@@ -1718,6 +1743,12 @@ local void ParseNetworkCommand(const NetworkCommandQueue* ncq)
 	    }
 	    CommandDemolish(unit,x,y,dest,status);
 	    break;
+	case MessageCommandSpellCast:
+	    // FIXME: WARNING: vladi: currently network protocol
+	    // cannot carry required information for spell cast
+	    // it is required to handle dest unit and aditional
+	    // integer value!
+	    break;
     }
 }
 
diff --git a/src/stratagus/Makefile b/src/stratagus/Makefile
index e84763a60..ff4382b7f 100644
--- a/src/stratagus/Makefile
+++ b/src/stratagus/Makefile
@@ -24,6 +24,7 @@ MODULE  = clone
 OBJS	= clone.$(OE) unit.$(OE) unit_draw.$(OE) unitcache.$(OE) \
 	  unit_find.$(OE) missile.$(OE) construct.$(OE)\
 	  player.$(OE) pud.$(OE) ccl.$(OE) interface.$(OE) iolib.$(OE) \
-	  mainloop.$(OE) goal.$(OE) selection.$(OE) groups.$(OE)
+	  mainloop.$(OE) goal.$(OE) selection.$(OE) groups.$(OE) \
+	  spells.$(OE)
 
 include $(TOPDIR)/Common.mk
diff --git a/src/stratagus/interface.cpp b/src/stratagus/interface.cpp
index c7d9cd9c8..dac0be544 100644
--- a/src/stratagus/interface.cpp
+++ b/src/stratagus/interface.cpp
@@ -318,7 +318,27 @@ local int InputKey(int key)
                   SpeedResearch=1;     /// speed factor for researching
                   SetMessage( "NORMAL DEBUG SPEED" );
                   }
-
+                if (strcmp(Input, "make it so") == 0)
+                  {
+                  SpeedMine=10;         /// speed factor for mine gold
+                  SpeedGold=10;         /// speed factor for getting gold
+                  SpeedChop=10;         /// speed factor for chop
+                  SpeedWood=10;         /// speed factor for getting wood
+                  SpeedHaul=10;         /// speed factor for haul oil
+                  SpeedOil=10;          /// speed factor for getting oil
+                  SpeedBuild=10;        /// speed factor for building
+                  SpeedTrain=10;        /// speed factor for training
+                  SpeedUpgrade=10;      /// speed factor for upgrading
+                  SpeedResearch=10;     /// speed factor for researching
+                  ThisPlayer->Resources[GoldCost] += 32000;
+                  ThisPlayer->Resources[WoodCost] += 32000;
+                  ThisPlayer->Resources[OilCost]  += 32000;
+                  ThisPlayer->Resources[OreCost]  += 32000;
+                  ThisPlayer->Resources[StoneCost]+= 32000;
+                  ThisPlayer->Resources[CoalCost] += 32000;
+		  MustRedraw|=RedrawResources;
+                  SetMessage( "SO!" );
+                  } else
 		// FIXME: only to selected players
 		NetworkChatMessage(Input);
 #if defined(USE_CCL) || defined(USE_CCL2)
diff --git a/src/stratagus/oldmissile.cpp b/src/stratagus/oldmissile.cpp
index 8b38fb8ed..55ae18372 100644
--- a/src/stratagus/oldmissile.cpp
+++ b/src/stratagus/oldmissile.cpp
@@ -95,6 +95,10 @@
 **	Missile don't move, than checks the source unit for HP.
 */
 #define MissileClassFire			12
+/**
+**	Missile is controlled completely by Controller() function. (custom)
+*/
+#define MissileClassCustom			13
 
 /*----------------------------------------------------------------------------
 --	Variables
@@ -135,6 +139,9 @@ local const char* MissileTypeWcNames[] = {
     "missile-cannon-tower-explosion",
     "missile-daemon-fire",
     "missile-green-cross",
+    "missile-blizzard-hit",
+    "missile-death-coil",
+    "missile-custom",
     "missile-none",
 };
 
@@ -178,7 +185,7 @@ global MissileType MissileTypes[MissileTypeMax] = {
     "fireball.png",
     32,32,
     { "fireball hit" },
-    MissileClassFireball,	
+    MissileClassPointToPoint,	
     1,
     },
 { MissileTypeType,
@@ -194,15 +201,16 @@ global MissileType MissileTypes[MissileTypeMax] = {
     "blizzard.png",
     32,32,
     { NULL },
-    MissileClassBlizzard,	
+    MissileClassBlizzard,
     1,
+    "missile-blizzard-hit", NULL
     },
 { MissileTypeType,
     "missile-death-and-decay",
     "death and decay.png",
     32,32,
     { NULL },
-    MissileClassDeathDecay,	
+    MissileClassStayWithDelay,	
     1,
     },
 { MissileTypeType,
@@ -227,7 +235,7 @@ global MissileType MissileTypes[MissileTypeMax] = {
     "heal effect.png",
     48,48,
     { NULL },
-    MissileClassPointToPoint,	
+    MissileClassStayWithDelay,	
     1,
     },
 { MissileTypeType,
@@ -244,7 +252,7 @@ global MissileType MissileTypes[MissileTypeMax] = {
     16,16,
     { NULL },
     MissileClassStayWithDelay,	
-    1,
+    5,
     },
 { MissileTypeType,
     "missile-whirlwind",
@@ -320,7 +328,7 @@ global MissileType MissileTypes[MissileTypeMax] = {
     48,48,
     { NULL },
     MissileClassFire,	
-    8,
+    8, 
     },
 { MissileTypeType,
     "missile-impact",
@@ -395,6 +403,38 @@ global MissileType MissileTypes[MissileTypeMax] = {
     MissileClassNone,		
     1,
     },
+{ MissileTypeType,
+    "missile-blizzard-hit",
+    "blizzard.png",
+    32,32,
+    { NULL },
+    MissileClassStayWithDelay,
+    1,
+    },
+{ MissileTypeType,
+    "missile-death-coil",
+    "touch of death.png",
+    32,32,
+    { NULL },
+    MissileClassPointToPoint,
+    1,
+    },
+{ MissileTypeType,
+    "missile-custom",
+    NULL,
+    32,32,
+    { NULL },
+    MissileClassCustom,		
+    1,
+    },
+{ MissileTypeType,
+    "missile-none",
+    NULL,
+    32,32,
+    { NULL },
+    MissileClassNone,		
+    1,
+    },
 };
 
 /*
@@ -409,7 +449,7 @@ local int NumMissiles;			/// currently used missiles
 local Missile Missiles[MAX_MISSILES];	/// all missiles on map
 
     /// lookup table for missile names
-local hashtable(MissileType*,61) MissileHash;
+local hashtable(MissileType*,65) MissileHash;
 
 /*----------------------------------------------------------------------------
 --	Functions
@@ -531,6 +571,11 @@ found:
     missile->SourceStats=NULL;
     missile->SourcePlayer=NULL;
 
+    missile->Damage = 0;
+    missile->TargetUnit = NULL;
+    missile->TTL = -1;
+    missile->Controller = NULL;
+
     return missile;
 }
 
@@ -762,6 +807,9 @@ global void DrawMissiles(void)
 	if( missile->Type==MissileFree ) {
 	    continue;
 	}
+	if( missile->Type->Class == MissileClassCustom ) {
+	    continue; // custom missiles are handled by Controller() only
+	}
 	// Draw only visibile missiles
 	if (MissileVisible(missile)) {
 	    x=missile->X-MapX*TileSizeX+TheUI.MapX;
@@ -830,7 +878,15 @@ local int PointToPointMissile(Missile* missile)
 	}
 
 	// FIXME: could be better written
-	MissileNewHeadingFromXY(missile,dx*xstep,dy*ystep);
+	if( missile->Type->Class == MissileClassWhirlwind )
+	  {
+	  // must not call MissileNewHeading nor frame change
+	  }
+	else
+	if( missile->Type->Class == MissileClassBlizzard )
+	  missile->Frame = 0;
+	else
+	  MissileNewHeadingFromXY(missile,dx*xstep,dy*ystep);
 
 	if( dy==0 ) {		// horizontal line
 	    if( dx==0 ) {
@@ -943,7 +999,9 @@ global void MissileHit(const Missile* missile)
     x=missile->X+missile->Type->Width/2;
     y=missile->Y+missile->Type->Height/2;
     if( missile->Type->ImpactMissile ) {
-	MakeMissile(missile->Type->ImpactMissile,x,y,0,0);
+	Missile* mis = MakeMissile(missile->Type->ImpactMissile,x,y,0,0);
+	mis->Damage = missile->Damage; // direct damage, spells mostly
+	mis->SourceUnit = missile->SourceUnit;
     }
     if( !missile->SourceType ) {	// no target
 	return;
@@ -961,19 +1019,27 @@ global void MissileHit(const Missile* missile)
 	    DebugLevel3Fn("Missile on wall?\n");
 	    // FIXME: don't use UnitTypeByIdent here, this is slow!
 	    if( HumanWallOnMap(x,y) ) {
-		HitWall(x,y,CalculateDamageStats(missile->SourceStats,
-			UnitTypeByIdent("unit-human-wall")->Stats));
+                if ( missile->Damage )
+		  HitWall(x,y,missile->Damage); // direct damage, spells mostly
+		else
+		  HitWall(x,y,CalculateDamageStats(missile->SourceStats,
+			  UnitTypeByIdent("unit-human-wall")->Stats));
 	    } else {
-		HitWall(x,y,CalculateDamageStats(missile->SourceStats,
-			UnitTypeByIdent("unit-orc-wall")->Stats));
+                if ( missile->Damage )
+		  HitWall(x,y,missile->Damage); // direct damage, spells mostly
+		else
+		  HitWall(x,y,CalculateDamageStats(missile->SourceStats,
+			  UnitTypeByIdent("unit-orc-wall")->Stats));
 	    }
 	    return;
 	}
 	DebugLevel3Fn("Oops nothing to hit (%d,%d)?\n",x,y);
 	return;
     }
-
-    HitUnit(goal,CalculateDamage(missile->SourceStats,goal));
+    if ( missile->Damage )
+      HitUnit(goal,missile->Damage); // direct damage, spells mostly
+    else
+      HitUnit(goal,CalculateDamage(missile->SourceStats,goal));
 }
 
 /**
@@ -992,6 +1058,25 @@ global void MissileActions(void)
 	if( missile->Wait-- ) {
 	    continue;
 	}
+	
+	if ( missile->TTL != -1 ) {
+	  missile->TTL--; // overall time to live if specified
+	}
+	
+	if ( missile->Controller ) {
+	  missile->Controller( missile );
+	}
+
+	if ( missile->TTL == 0 ) {
+	  missile->Type=MissileFree;
+	  continue;
+	}
+
+	if ( missile->Type->Class == MissileClassCustom ) {
+	  missile->Wait=missile->Type->Speed;
+	  continue; // custom missiles are handled by Controller() only
+	}
+	
 	if (MissileVisible(missile)) {
 	    // check before movement
 	    MustRedraw|=RedrawMap;
@@ -1088,6 +1173,31 @@ global void MissileActions(void)
 		}
 		break;
 
+	    case MissileClassBlizzard:
+		missile->Wait=missile->Type->Speed;
+		if( PointToPointMissile(missile) ) {
+		    //
+		    //	Animate hit
+		    //
+		    missile->Frame+=4;	// FIXME: frames pro row
+		    if( (missile->Frame&127)
+			    >=VideoGraphicFrames(missile->Type->Sprite) ) {
+			MissileHit(missile);
+			missile->Type=MissileFree;
+		    }
+		}
+		break;
+	    case MissileClassWhirlwind:
+		missile->Wait=missile->Type->Speed;
+		missile->Frame++;
+		if ( missile->Frame > 3 )
+		  missile->Frame = 0;
+	        //NOTE: vladi: whirlwind moves slowly, i.e. it stays
+	        //      5 ticks at the same pixels...
+	        if ( missile->TTL < 1 || missile->TTL % 10 == 0 )
+		  PointToPointMissile(missile);
+		break;
+		
 	    case MissileClassStayWithDelay:
 		missile->Wait=missile->Type->Speed;
 		if( ++missile->Frame
diff --git a/src/stratagus/selection.cpp b/src/stratagus/selection.cpp
index 13f509b16..83869e472 100644
--- a/src/stratagus/selection.cpp
+++ b/src/stratagus/selection.cpp
@@ -89,6 +89,11 @@ global void ChangeSelectedUnits(Unit** units,int count)
  */
 global int SelectUnit(Unit* unit)
 {
+    if ( unit->Revealer )
+    {
+	return 0; // Revealers cannot be selected
+    }
+    
     if( NumSelected == MaxSelectable ) {
         return 0;
     }
diff --git a/src/stratagus/spells.cpp b/src/stratagus/spells.cpp
new file mode 100644
index 000000000..640c2672f
--- /dev/null
+++ b/src/stratagus/spells.cpp
@@ -0,0 +1,793 @@
+//   ___________                     _________                _____  __
+//   \_   _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
+//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
+//        \/                        \/     \/          \/                        \/
+//  ______________________                           ______________________
+//                        T H E   W A R   B E G I N S
+//         FreeCraft - A free fantasy real time strategy game engine
+//
+/**@name action_spellcast.c     -       The spell cast action. */
+/*
+**      (c) Copyright 1998-2000 by Vladi Belperchinov-Shabanski
+**
+**      $Id$
+*/
+/*
+**      And when we cast our final spell
+**      And we meet in our dreams
+**      A place that no one else can go
+**      Don't ever let your love die
+**      Don't ever go breaking this spell
+*/
+
+//@{
+
+/*----------------------------------------------------------------------------
+--      Notes
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+--      Includes
+----------------------------------------------------------------------------*/
+#include "spells.h"
+#include "sound.h"
+#include "missile.h"
+#include "map.h"
+#include "ui.h"
+
+/*----------------------------------------------------------------------------
+--      Definitons
+----------------------------------------------------------------------------*/
+
+#define FIREBALL_DAMAGE		20
+#define WHIRLWIND_DAMAGE1	 4 // the center of the whirlwind
+#define WHIRLWIND_DAMAGE2	 1 // the periphery of the whirlwind
+#define BLIZZARD_DAMAGE		10
+#define DEATHANDDECAY_DAMAGE	10
+#define RUNE_DAMAGE		50
+
+/*----------------------------------------------------------------------------
+--      Variables
+----------------------------------------------------------------------------*/
+
+/*
+  NOTE: vladi:
+  
+  The point to have variable unosrted list of spell types and
+  dynamic id's and in the same time -- SpellAction id's is that
+  spell actions are hardcoded and cannot be changed at all.
+  On the other hand we can have different spell types as with
+  different range, cost and time to live (possibly and other 
+  parameters as extensions)
+*/
+
+global SpellType SpellTypeTable[] = {
+
+//TTL's below are in ticks: approx: 500=13sec, 1000=25sec, 2000=50sec
+
+//id, ident,                range, mana, ttl, spell action,           sound ident,   sound id
+//      ---human paladins---
+{ 0, "spell-holy-vision",   1024,  70,  -1, SpellActionHolyVision   , "holy vision",    NULL },
+{ 0, "spell-healing",          4,   6,  -1, SpellActionHealing      , "healing",        NULL },
+{ 0, "spell-exorcism",        10,   4,  -1, SpellActionExorcism     , "exorcism",       NULL },
+//      ---human mages---                                                ---human mages---          
+{ 0, "spell-fireball",         8, 100, 999, SpellActionFireball     , "fireball",       NULL },
+{ 0, "spell-slow",            10,  50,1000, SpellActionSlow         , "slow",           NULL },
+{ 0, "spell-flame-shield",     6,  80, 600, SpellActionFlameShield  , "flame shield",   NULL },
+{ 0, "spell-invisibility",     6, 200,2000, SpellActionInvisibility , "invisibility",   NULL },
+{ 0, "spell-polymorph",       10, 200,  -1, SpellActionPolymorph    , "polymorph",      NULL },
+{ 0, "spell-blizzard",        12,   5,  -1, SpellActionBlizzard     , "blizzard",       NULL },
+//      ---orc ogres---                                                  ---orc ogres---            
+{ 0, "spell-eye-of-kilrogg",1024,  70,  -1, SpellActionEyeOfKilrogg , "eye of kilrogg", NULL },
+{ 0, "spell-bloodlust",        6,  50,1000, SpellActionBloodlust    , "bloodlust",      NULL },
+{ 0, "spell-runes",           10,  50,2000, SpellActionRunes        , "runes",          NULL },
+//      ---orc death knights---                                          ---orc death knights-      
+{ 0, "spell-death-coil",      10, 100,  -1, SpellActionDeathCoil    , "death coil",     NULL },
+{ 0, "spell-haste",            6,  50,1000, SpellActionHaste        , "haste",          NULL },
+{ 0, "spell-raise-dead",       6,  50,  -1, SpellActionRaiseDead    , "raise dead",     NULL },
+{ 0, "spell-whirlwind",       12, 100, 800, SpellActionWhirlwind    , "whirlwind",      NULL },
+{ 0, "spell-unholy-armor",     6, 100, 500, SpellActionUnholyArmor  , "unholy armor",   NULL },
+{ 0, "spell-death-and-decay", 12,   5,  -1, SpellActionDeathAndDecay, "death and decay",NULL },
+//      ---eot marker---                                                 ---eot marker---          
+{-1, "",                       1,   1,  -1, SpellActionNone         , "",                      }
+};
+
+local int SpellTypeCount;
+
+MissileType* missile_healing   = NULL;
+MissileType* missile_spell     = NULL;
+MissileType* missile_exorcism  = NULL;
+MissileType* missile_explosion = NULL;
+MissileType* missile_rune      = NULL;
+ 
+/*----------------------------------------------------------------------------
+--      Functions (Spells Controllers/Callbacks)
+----------------------------------------------------------------------------*/
+
+/*
+** Missile controllers should return 0 to continue 
+** or 1 to cancel the spell/missile
+*/
+
+/*
+** Fireball controller
+*/
+global int SpellFireballController( void* missile )
+{
+  Unit* table[MAX_UNITS];
+  int i;
+  int n;
+  
+  Missile* mis = (Missile*)missile;
+  
+  //NOTE: vladi: TTL is used as counter for explosions
+  //      first 6 counts there are no explosions, then on each second
+  //      and at the target destination
+  if ( (mis->TTL < 993 && mis->TTL % 2 == 0) || (mis->X == mis->DX && mis->Y == mis->DY) ) // approx.
+    {
+    //+TileSize/2 to align gfx to baseline
+    int x = mis->X + TileSizeX/2;
+    int y = mis->Y + TileSizeY/2;
+    MakeMissile( missile_explosion, x, y, x, y );
+    
+    x = x / TileSizeX;
+    y = y / TileSizeY;
+    
+    //Effect of the explosion on units.
+    //NOTE: vladi: this is slightly different than original
+    //      now it hits all units in range 1
+    n = SelectUnits(x-1,y-1, x+1, y+1,table);
+    for( i=0; i<n; ++i )
+      HitUnit(table[i],FIREBALL_DAMAGE);
+    }
+  return 0;	   
+};
+
+/*
+** Death-Coil controller
+*/
+global int SpellDeathCoilController( void* missile )
+{
+  Unit* table[MAX_UNITS];
+  int i;
+  int n;
+  
+  Missile* mis = (Missile*)missile;
+  mis->SourceUnit->Refs--;  
+  if ( mis->TargetUnit )
+    mis->TargetUnit->Refs--;  
+  if ( mis->X == mis->DX && mis->Y == mis->DY )
+    { // missile has reached target unit/spot
+    if ( !mis->SourceUnit->Destroyed )
+      { // source unit still exists
+      if ( mis->TargetUnit && !mis->TargetUnit->Destroyed )
+        { // target unit still exists
+	int hp = mis->TargetUnit->HP;
+	hp -= 50;
+	mis->SourceUnit->HP += 50;
+	if ( hp <= 0 )
+	  {
+	  mis->TargetUnit->HP = 0;
+	  DestroyUnit( mis->TargetUnit );
+	  }
+	else
+	  mis->TargetUnit->HP = hp;  
+	if ( mis->SourceUnit->HP > mis->SourceUnit->Stats->HitPoints )  
+	  mis->SourceUnit->HP = mis->SourceUnit->Stats->HitPoints;
+	}
+      else
+        { // no target unit -- try enemies in range 5x5
+	int ec = 0; // enemy count
+	int x = mis->DX / TileSizeX;
+	int y = mis->DY / TileSizeY;
+	n = SelectUnits(x-2,y-2, x+2, y+2,table);
+	if ( n > 0 )
+	  {
+	  // calculate organic enemy count
+	  for( i=0; i<n; ++i )
+	    ec += ( IsEnemy(mis->SourceUnit->Player,table[i]) 
+	            && table[i]->Type->Organic != 0);
+	  if ( ec > 0 )
+	    { // yes organic enemies found
+  	    for( i=0; i<n; ++i )
+	      if ( IsEnemy(mis->SourceUnit->Player,table[i]) 
+	            && table[i]->Type->Organic != 0 )
+	        { 
+		// disperse dabage between them
+		int hp = table[i]->HP;
+		hp -= 50/ec; //NOTE: 1 is the minimal damage
+		if ( hp <= 0 )
+		  {
+		  table[i]->HP = 0;
+		  DestroyUnit( table[i] ); // too much damage
+		  }
+		else
+		  table[i]->HP = hp;
+		}
+  	    mis->SourceUnit->HP += 50;
+	    if ( mis->SourceUnit->HP > mis->SourceUnit->Stats->HitPoints )  
+	      mis->SourceUnit->HP = mis->SourceUnit->Stats->HitPoints;
+	    }
+	  }  
+	}	
+      }
+    }
+  return 0;	   
+}
+
+/*
+** Whirlwind controller
+*/
+/*
+  FIXME: vladi: whirlwind is particulary bad! :)
+  we need slow smooth missile movement that we don't
+  have yet... should be fixed later
+*/
+global int SpellWhirlwindController( void* missile )
+{
+  Unit* table[MAX_UNITS];
+  int i;
+  int n;
+  int x;
+  int y;
+  
+  Missile* mis = (Missile*)missile;
+  x = mis->X / TileSizeX;
+  y = mis->Y / TileSizeY;
+  
+  n = SelectUnitsOnTile( x, y, table);
+  for( i=0; i<n; ++i ) {
+    HitUnit(table[i],WHIRLWIND_DAMAGE1);
+  }
+  n = SelectUnits( x - 1, y - 1, x + 1, y + 1, table);
+  for( i=0; i<n; ++i ) {
+    HitUnit(table[i],WHIRLWIND_DAMAGE2);
+  }
+  //printf( "Whirlwind: %d, %d, TTL: %d\n", mis->X, mis->Y, mis->TTL );
+  if ( mis->TTL % 100 == 0 ) // changes direction every 3 seconds (approx.)
+    { // missile has reached target unit/spot
+    int nx, ny;
+    do
+      {
+      // find new destination in the map
+      nx = x  +  rand() % 5 - 2;
+      ny = y  +  rand() % 5 - 2;
+      }
+    while(  nx < 0 && ny < 0 && nx >= TheMap.Width && ny >= TheMap.Height );
+    mis->X = mis->DX;
+    mis->Y = mis->DY;
+    mis->DX = nx * TileSizeX + TileSizeX/2;
+    mis->DY = ny * TileSizeY + TileSizeY/2;
+    //printf( "Whirlwind new direction: %d, %d, TTL: %d\n", mis->X, mis->Y, mis->TTL );
+    }
+  return 0;
+}
+
+/*
+** Runes controller
+*/
+global int SpellRunesController( void* missile )
+{
+  Unit* table[MAX_UNITS];
+  int i;
+  int n;
+  int x;
+  int y;
+  
+  Missile* mis = (Missile*)missile;
+  x = mis->X / TileSizeX;
+  y = mis->Y / TileSizeY;
+  
+  n = SelectUnitsOnTile( x, y, table);
+  for( i=0; i<n; ++i ) {
+    if ( table[i]->Type->LandUnit )
+      HitUnit(table[i],RUNE_DAMAGE);
+  }
+  
+  if ( mis->TTL % 100 == 0 || mis->TTL == 0 )
+    { // show rune every 4 seconds (approx.)
+    MakeMissile( missile_rune, mis->X, mis->Y, mis->X, mis->Y );
+    }
+  return 0;
+}
+/*----------------------------------------------------------------------------
+--      Functions
+----------------------------------------------------------------------------*/
+
+/*
+**      Spells constructor, inits spell id's and sounds
+**
+*/
+global void InitSpells()
+{
+  int z = 0;
+  while( SpellTypeTable[z].Id != -1 )
+    {
+    SpellTypeTable[z].Id = z;
+    //FIXME: vladi: this won't work 'cos sound init is called after InitSpells()
+    SpellTypeTable[z].SoundId = SoundIdForName(SpellTypeTable[z].SoundIdent);
+    if( SpellTypeTable[z].SoundId == NULL )
+      {
+      DebugLevel0Fn( "cannot get SoundId for `%s'\n", SpellTypeTable[z].SoundIdent ); //FIXME: vladi: some log level func instead of printf?
+      }
+    z++;
+    }
+  SpellTypeCount = z;  
+  
+  missile_healing   = MissileTypeByIdent( "missile-heal-effect" );
+  missile_spell     = MissileTypeByIdent( "missile-normal-spell" );
+  missile_exorcism  = MissileTypeByIdent( "missile-exorcism" );
+  missile_explosion = MissileTypeByIdent( "missile-explosion" );
+  missile_rune      = MissileTypeByIdent( "missile-rune" );
+}
+  
+/*
+**      Spells destructor (currently does nothing)
+**
+*/
+global void DoneSpells()
+{
+  // nothing yet
+}
+
+/*
+**      Get spell id by ident
+**
+**      @param Id  Spell ident.
+**
+**      @return spell id (index in spell type table)
+*/
+global int SpellIdByIdent( const char* Ident )
+{
+  int z = 0;
+  while( SpellTypeTable[z].Id != -1 )
+    {
+    if ( strcmp( SpellTypeTable[z].Ident, Ident ) == 0 )
+      return z;
+    z++;  
+    }  
+  return -1;  
+}
+  
+/*
+**      Get spell type struct ptr by ident
+**
+**      @param Id  Spell ident.
+**
+**      @return spell type struct ptr
+*/
+global const SpellType* SpellTypeByIdent( const char* Ident )
+{
+  int z = SpellIdByIdent( Ident );
+  return z != -1 ? &(SpellTypeTable[z]) : NULL;
+}
+  
+/*
+**      Get spell type struct ptr by id
+**
+**      @param Id  Spell id (index in the spell type table).
+**
+**      @return spell type struct ptr
+*/
+global const SpellType* SpellTypeById( int Id )
+{
+  DebugCheck( Id < 0 || Id >= SpellTypeCount );
+  if ( Id < 0 || Id >= SpellTypeCount ) return NULL;
+  return &(SpellTypeTable[ Id ]);
+}
+
+/*
+**      Check if unit can cast spell
+**
+**      @param unit     Unit that has to be checked.
+**      @param SpellId  Spell id (index in the spell type table).
+**
+**      @return 0 if unit cannot or 1 (=!0) if unit can cast this spell type
+global int CanCastSpell( Unit* unit, int SpellId )
+{
+  const SpellType* spell = SpellTypeById( SpellId );
+  DebugCheck( spell == NULL );
+  if ( !unit->Type->CanCastSpell ) return 0; // NOTE: this must not happen
+  if ( unit->Mana < spell->ManaCost ) return 0;
+  return 1;
+}
+*/
+
+/*
+**      Spell cast!
+**
+**      @param SpellId  Spell id (index in the spell type table).
+**      @param unit     Unit that casts the spell.
+**      @param target   Target unit that spell is addressed to
+**      @param X        X coord of target spot when/if target does not exist
+**      @param Y        Y coord of target spot when/if target does not exist
+**
+**      @return 0 if spell should/can continue or =! 0 to stop
+**
+*/
+global int SpellCast( int SpellId, Unit* unit, Unit* target, int x, int y )
+{
+  int repeat = 0;
+  const SpellType* spell = SpellTypeById( SpellId );
+/*  
+  this does not work when no target unit
+  DebugLevel0Fn("Spell cast: %d (%s), %s -> %s (%d,%d)", 
+                 SpellId, spell->Ident, unit->Type->Name, target->Type->Name, x, y );
+  printf("Spell cast: %d (%s), %s -> %s (%d,%d)\n", 
+                 SpellId, spell->Ident, unit->Type->Name, target->Type->Name, x, y );
+*/
+  // the unit can collect mana during the move to target, so check is here...
+
+  #define PLAY_FIREWORKS(s) \
+	{ \
+	PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	MakeMissile( s, x*TileSizeX+TileSizeX/2,   \
+	                y*TileSizeX+TileSizeX/2,   \
+	                x*TileSizeX+TileSizeX/2,   \
+	                y*TileSizeX+TileSizeX/2 ); \
+	}		
+    
+  switch( spell->Action )
+    {
+    case SpellActionNone:
+         DebugLevel0Fn( "No spell action" );
+         break;
+//  ---human paladins---
+    case SpellActionHolyVision:
+	 unit->Mana -= spell->ManaCost; // get mana cost
+         {
+	 Unit* u = MakeUnit(UnitTypeByIdent("unit-daemon"), unit->Player);
+	 u->Revealer = 1;
+	 u->HP = 2;
+	 u->X = x;
+	 u->Y = y;
+	 }
+         break;
+    case SpellActionHealing:
+	 // only can heal organic units
+	 if (target && target->Type->Organic) 
+	   {
+	   while( target->HP < target->Stats->HitPoints 
+	          && unit->Mana > spell->ManaCost )
+	      {
+	      unit->Mana -= spell->ManaCost; // get mana cost
+	      target->HP++;
+	      }
+	   PLAY_FIREWORKS(missile_healing);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionExorcism:
+	 // exorcism works only on undead units
+	 if ( target && target->Type->IsUndead ) 
+	   {
+	   while( target->HP > 0 && unit->Mana > spell->ManaCost )
+	      {
+	      unit->Mana -= spell->ManaCost; // get mana cost
+	      target->HP--;
+	      }
+	   PLAY_FIREWORKS(missile_exorcism);   
+	   }
+	 else
+	   {
+	   //FIXME: vladi: exorcism effect should be disperced on near units
+	   }  
+         DebugCheck( unit->Mana < 0 );  
+         break;
+//  ---human mages---
+    case SpellActionFireball:
+    	   { //NOTE: fireball can be casted on spot
+	   Missile* mis;
+	   int sx = unit->X;
+	   int sy = unit->Y;
+	   int dx = x;
+	   int dy = y;
+	   
+	   if ( target )
+	     {
+	     dx = target->X;
+	     dy = target->Y;
+	     }
+	   
+	   unit->Mana -= spell->ManaCost;
+
+  	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent("missile-fireball"), 
+	                sx*TileSizeX+TileSizeX/2,   
+	                sy*TileSizeX+TileSizeX/2,   
+	                dx*TileSizeX+TileSizeX/2,   
+	                dy*TileSizeX+TileSizeX/2 ); 
+	   
+	   mis->TTL = spell->TTL;
+	   mis->Controller = SpellFireballController;
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionSlow:
+	 if (target && !target->Type->Building && target->Slow < spell->TTL) 
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->Slow = spell->TTL; // about 25 sec
+	   target->Haste = 0;
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionFlameShield:
+	 if ( target && target->Type->Organic && target->Type->LandUnit  
+	      && target->FlameShield < spell->TTL ) 
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->FlameShield = spell->TTL; // about 15 sec
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionInvisibility:
+	 if (target && target->Type->Organic && target->Invisible < spell->TTL ) 
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->Invisible = spell->TTL; // about 50 sec
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionPolymorph:
+	 if ( target && target->Type->Organic ) 
+	   {
+	   int x = target->X;
+	   int y = target->Y;
+	   Player* pl = target->Player;
+	   
+	   // as said somewhere else -- no corpses :)
+	   RemoveUnit( target );
+	   UnitLost( target );
+	   ReleaseUnit( target );
+	   MakeUnitAndPlace( x, y, UnitTypeByIdent("unit-critter"), pl );
+	   
+	   unit->Mana -= spell->ManaCost;
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionBlizzard:
+    	 {
+	 /*
+	   NOTE: vladi: blizzard differs than original in this way:
+	         original: launches 50 shards at 5 random spots x 10 for 25 mana
+		 here:     launches 10 shards at 10 random spots x 1 for 5 mana
+		 reason: it cannot be done w/o aditional spells list... perhasp
+		         could be managed with fake spell with controller, but
+			 for now it is leaved as it is...
+	 */
+	 int shards = 10;
+	 while( shards-- )
+	   {
+	   Missile* mis;
+	   int sx, sy, dx, dy;
+
+	   do
+	     {
+	     // find new destination in the map
+	     dx = x  +  rand() % 5 - 2;
+	     dy = y  +  rand() % 5 - 2;
+	     }
+	   while(  dx < 0 && dy < 0 && dx >= TheMap.Width && dy >= TheMap.Height );
+           sx = dx - 1 - rand() % 4;
+	   sy = dy - 1 - rand() % 4;
+ 	 
+	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent( "missile-blizzard" ), 
+		              sx*TileSizeX+TileSizeX/2,   
+	                      sy*TileSizeX+TileSizeX/2,   
+	                      dx*TileSizeX+TileSizeX/2,   
+	                      dy*TileSizeX+TileSizeX/2 ); 
+	   mis->Damage = BLIZZARD_DAMAGE;
+	   //FIXME: not correct -- blizzard should continue even if mage is 
+	   //       destroyed (though it will be quite short time...)
+	   mis->SourceUnit = unit; 
+	   mis->SourceType = unit->Type;
+	   }
+	   
+	 unit->Mana -= spell->ManaCost;
+	 if ( unit->Mana > spell->ManaCost )
+	   repeat = 1;
+	 }
+         break;
+//  ---orc ogres---
+    case SpellActionEyeOfKilrogg:
+	 MakeUnitAndPlace( x, y, UnitTypeByIdent("unit-eye-of-kilrogg"), 
+	                   unit->Player );
+	   
+	 unit->Mana -= spell->ManaCost;
+	   
+         PLAY_FIREWORKS(missile_spell);   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionBloodlust:
+	 if (target && target->Type->Organic && target->Bloodlust < spell->TTL )
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->Bloodlust = spell->TTL; // about 25 sec
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionRunes:
+	   {
+	   //FIXME: vladi: runes should be set in formation as in original
+	   //FIXME: vladi: runes should be set on empty tile (ground or water)
+	   Missile* mis;
+	   unit->Mana -= spell->ManaCost;
+	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent( "missile-custom" ), 
+		              x*TileSizeX+TileSizeX/2,   
+	                      y*TileSizeX+TileSizeX/2,   
+	                      x*TileSizeX+TileSizeX/2,   
+	                      y*TileSizeX+TileSizeX/2 );
+	   mis->TTL = spell->TTL;
+	   mis->Controller = SpellRunesController;
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+//  ---orc death knights---
+    case SpellActionDeathCoil:
+    	 if( (target && target->Type->Organic) || (!target) )  
+	   { //NOTE: fireball can be casted on spot
+	   Missile* mis;
+	   int sx = unit->X;
+	   int sy = unit->Y;
+	   int dx = x;
+	   int dy = y;
+	   
+	   if ( target )
+	     {
+	     dx = target->X;
+	     dy = target->Y;
+	     }
+	   
+	   unit->Mana -= spell->ManaCost;
+
+  	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent("missile-death-coil"), 
+	                sx*TileSizeX+TileSizeX/2,   
+	                sy*TileSizeX+TileSizeX/2,   
+	                dx*TileSizeX+TileSizeX/2,   
+	                dy*TileSizeX+TileSizeX/2 ); 
+	   
+	   unit->Refs++;
+	   mis->SourceUnit = unit;
+	   if (target)
+	     {
+	     mis->TargetUnit = target;
+  	     target->Refs++;
+	     }
+	   mis->Controller = SpellDeathCoilController;
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionHaste:
+	 if (target && !target->Type->Building && target->Haste < spell->TTL) 
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->Slow = 0;
+	   target->Haste = spell->TTL; // about 25 sec
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionRaiseDead:
+	   {
+	   int i;
+
+	   for( i=0; i<NumUnits; ++i ) {
+	       // FIXME: this tries to draw all corps, ohje
+	       if( (Units[i]->Type->Vanishes || Units[i]->Command.Action==UnitActionDie)
+	           && Units[i]->X == x && Units[i]->Y == y ) {
+ 	           //FIXME: URGENT: remove corpse
+		   //RemoveUnit( Units[i] );
+	           //UnitLost( Units[i] );
+	           //ReleaseUnit( Units[i] );
+	           MakeUnitAndPlace( x, y, UnitTypeByIdent("unit-skeleton"), 
+	                             unit->Player );
+  	           unit->Mana -= spell->ManaCost;
+	           break;
+	        }
+	   }
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionWhirlwind:
+           {
+	   Missile* mis;
+	   unit->Mana -= spell->ManaCost;
+
+  	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent("missile-whirlwind"), 
+	                x*TileSizeX+TileSizeX/2,   
+	                y*TileSizeX+TileSizeX/2,   
+	                x*TileSizeX+TileSizeX/2,   
+	                y*TileSizeX+TileSizeX/2 ); 
+	   
+	   mis->TTL = spell->TTL;
+	   mis->Controller = SpellWhirlwindController;
+	   }
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionUnholyArmor:
+	 if (target && !target->Type->Building && target->UnholyArmor < spell->TTL) 
+	   {
+	   // get mana cost
+	   unit->Mana -= spell->ManaCost;
+	   target->UnholyArmor = spell->TTL; // about 13 sec
+	   
+	   PLAY_FIREWORKS(missile_spell);   
+	   }   
+         DebugCheck( unit->Mana < 0 );  
+         break;
+    case SpellActionDeathAndDecay:
+    	 {
+	 /*
+	   See notes about Blizzard spell above...
+	 */
+	 int shards = 10; // blizzard thing, yep :)
+	 while( shards-- )
+	   {
+	   Missile* mis;
+	   int dx, dy;
+
+	   do
+	     {
+	     // find new destination in the map
+	     dx = x  +  rand() % 5 - 2;
+	     dy = y  +  rand() % 5 - 2;
+	     }
+	   while(  dx < 0 && dy < 0 && dx >= TheMap.Width && dy >= TheMap.Height );
+ 	 
+	   PlayGameSound(SoundIdForName(spell->SoundIdent),MaxSampleVolume); \
+	   mis = MakeMissile( MissileTypeByIdent( "missile-death-and-decay" ), 
+		              dx*TileSizeX+TileSizeX/2,   
+	                      dy*TileSizeX+TileSizeX/2,   
+	                      dx*TileSizeX+TileSizeX/2,   
+	                      dy*TileSizeX+TileSizeX/2 ); 
+	   mis->Damage = DEATHANDDECAY_DAMAGE;
+	   //FIXME: not correct -- blizzard should continue even if mage is 
+	   //       destroyed (though it will be quite short time...)
+	   mis->SourceUnit = unit; 
+	   mis->SourceType = unit->Type;
+	   }
+	   
+	 unit->Mana -= spell->ManaCost;
+	 if ( unit->Mana > spell->ManaCost )
+	   repeat = 1;
+	 }
+         break;
+    default:
+         DebugLevel0Fn( "Unknown spell action" );
+	 break;
+    }
+  #undef PLAY_FIREWORKS
+  DebugCheck( unit->Mana < 0 );  
+  return repeat;
+}
+
+  
+//@}
+
diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp
index 9a3dd76bb..06597fb4d 100644
--- a/src/stratagus/stratagus.cpp
+++ b/src/stratagus/stratagus.cpp
@@ -71,6 +71,7 @@ extern int getopt(int argc, char *const*argv, const char *opt);
 #include "sound.h"
 #include "network.h"
 #include "pathfinder.h"
+#include "spells.h"
 
 /*----------------------------------------------------------------------------
 --	Variables
@@ -204,6 +205,7 @@ global void FreeCraftInit(void)
     LoadTileset();
     InitUnitButtons();
     LoadMissileSprites();
+    InitSpells();
     LoadUnitSprites();
     LoadConstructions();
     LoadDecorations();
diff --git a/src/ui/botpanel.cpp b/src/ui/botpanel.cpp
index 6c21220b3..9a2c58c3a 100644
--- a/src/ui/botpanel.cpp
+++ b/src/ui/botpanel.cpp
@@ -50,6 +50,7 @@
 #include "map.h"
 #include "unit.h"
 #include "font.h"
+#include "spells.h"
 
 /*----------------------------------------------------------------------------
 --      Defines
@@ -142,12 +143,12 @@ int AddButton( int pos, int level, const char* IconIdent,
       ba->ValueStr = strdup( value );
       switch( action )
 	{
-	case B_Magic:	 ba->Value = UpgradeIdByIdent( value ); break;
-	case B_Train:	 ba->Value = UnitTypeIdByIdent( value ); break;
-	case B_Research: ba->Value = UpgradeIdByIdent( value ); break;
-	case B_UpgradeTo: ba->Value = UnitTypeIdByIdent( value ); break;
-	case B_Build:	 ba->Value = UnitTypeIdByIdent( value ); break;
-	default:	ba->Value = atoi( value ); break;
+	case B_SpellCast:	ba->Value = SpellIdByIdent( value ); break;
+	case B_Train:		ba->Value = UnitTypeIdByIdent( value ); break;
+	case B_Research:	ba->Value = UpgradeIdByIdent( value ); break;
+	case B_UpgradeTo:	ba->Value = UnitTypeIdByIdent( value ); break;
+	case B_Build:		ba->Value = UnitTypeIdByIdent( value ); break;
+        default:		ba->Value = atoi( value ); break;
 	}
   } else {
       ba->ValueStr = NULL;
@@ -297,9 +298,11 @@ global void DrawButtonPanel(void)
 		    case B_Research:
 			SetCosts(0,Upgrades[v].Costs);
 			break;
-		    case B_Magic:
-			// FIXME: correct costs!!!
-			SetCosts(11,NULL);
+		    case B_SpellCast:
+		        {
+			const SpellType* spell = SpellTypeById( v );
+			SetCosts(spell->ManaCost,NULL);
+			}
 			break;
 
 		    default:
@@ -521,7 +524,7 @@ global void UpdateButtonPanel(void)
 			    allow=UpgradeIdentAllowed( ThisPlayer,
 				UnitButtonTable[z]->ValueStr )=='A';
 		    }
-		} else if ( UnitButtonTable[z]->Action == B_Magic ) {
+		} else if ( UnitButtonTable[z]->Action == B_SpellCast ) {
 		    DebugLevel3("Magic: %d,%c\n",
 			    CheckDependByIdent( ThisPlayer,
 				UnitButtonTable[z]->ValueStr ),
@@ -600,9 +603,11 @@ global void DoButtonButtonClicked(int button)
 	case B_Repair:
 	case B_AttackGround:
 	case B_Demolish:
+        case B_SpellCast:
 	    CursorState=CursorStateSelect;
 	    GameCursor=&Cursors[CursorTypeYellowHair];
 	    CursorAction=CurrentButtons[button].Action;
+	    CursorValue=CurrentButtons[button].Value;
             CurrentButtonLevel=9;	// level 9 is cancel-only
             UpdateButtonPanel();
 	    MustRedraw|=RedrawCursor;
diff --git a/src/ui/button_table.cpp b/src/ui/button_table.cpp
index a54827f63..e6467e3b6 100644
--- a/src/ui/button_table.cpp
+++ b/src/ui/button_table.cpp
@@ -353,20 +353,20 @@ global ButtonAction AllButtons[] = {
 
 // paladin specific actions --------------------------------------------
 {   7, 0, { "icon-holy-vision" },
-    B_Magic,		0, "upgrade-holy-vision",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-holy-vision",
+    CheckTrue,		NULL,
     'v', "HOLY ~!VISION",
     "unit-paladin"
 },
 {   8, 0, { "icon-heal" },
-    B_Magic,		0, "upgrade-healing",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-healing",
+    CheckUpgrade,		"upgrade-healing",
     'h', "~!HEALING (per 1 HP)",
     "unit-paladin"
 },
 {   9, 0, { "icon-exorcism" },
-    B_Magic,		0, "upgrade-exorcism",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-exorcism",
+    CheckUpgrade,		"upgrade-exorcism",
     'e', "~!EXORCISM",
     "unit-paladin"
 },
@@ -378,38 +378,38 @@ global ButtonAction AllButtons[] = {
     "unit-mage,unit-khadgar"
 },
 {   4, 0, { "icon-fireball" },
-    B_Magic,		0, "upgrade-fireball",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-fireball",
+    CheckTrue,		NULL,
     'f', "~!FIREBALL",
     "unit-mage,unit-khadgar"
 },
 {   5, 0, { "icon-slow" },
-    B_Magic,		0, "upgrade-slow",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-slow",
+    CheckUpgrade,		"upgrade-slow",
     'o', "SL~!OW",
     "unit-mage"
 },
 {   6, 0, { "icon-flame-shield" },
-    B_Magic,		0, "upgrade-flame-shield",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-flame-shield",
+    CheckUpgrade,		"upgrade-flame-shield",
     'l', "F~!LAME SHIELD",
     "unit-mage"
 },
 {   7, 0, { "icon-invisibility" },
-    B_Magic,		0, "upgrade-invisibility",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-invisibility",
+    CheckUpgrade,		"upgrade-invisibility",
     'i', "~!INVISIBILITY",
     "unit-mage"
 },
 {   8, 0, { "icon-polymorph" },
-    B_Magic,		0, "upgrade-polymorph",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-polymorph",
+    CheckUpgrade,		"upgrade-polymorph",
     'p', "~!POLYMORPH",
     "unit-mage"
 },
 {   9, 0, { "icon-blizzard" },
-    B_Magic,		0, "upgrade-blizzard",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-blizzard",
+    CheckUpgrade,		"upgrade-blizzard",
     'b', "~!BLIZZARD",
     "unit-mage"
 },
@@ -1080,37 +1080,38 @@ global ButtonAction AllButtons[] = {
 
 // ogre-mage specific actions --------------------------------------------
 {   7, 0, { "icon-eye-of-kilrogg" },
-    B_Magic,		0, "upgrade-eye-of-kilrogg",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-eye-of-kilrogg",
+    CheckTrue,		NULL,
     'k', "EYE OF ~!KILROGG",
     "unit-ogre-mage"
 },
 {   8, 0, { "icon-bloodlust" },
-    B_Magic,		0, "upgrade-bloodlust",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-bloodlust",
+    CheckUpgrade,		"upgrade-bloodlust",
     'b', "~!BLOODLUST",
     "unit-ogre-mage"
 },
 {   9, 0, { "icon-runes" },
-    B_Magic,		0, "upgrade-runes",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-runes",
+    CheckTrue,		"upgrade-runes",
     'r', "~!RUNES",
     "unit-ogre-mage"
 },
+// cho'gall specific actions --- same as ogre mage but it has them always --
 {   7, 0, { "icon-eye-of-kilrogg" },
-    B_Magic,		0, "upgrade-eye-of-kilrogg",
+    B_SpellCast,		0, "spell-eye-of-kilrogg",
     CheckTrue,		NULL,
     'k', "EYE OF ~!KILROGG",
     "unit-cho'gall"
 },
 {   8, 0, { "icon-bloodlust" },
-    B_Magic,		0, "upgrade-bloodlust",
+    B_SpellCast,		0, "spell-bloodlust",
     CheckTrue,		NULL,
     'b', "~!BLOODLUST",
     "unit-cho'gall"
 },
 {   9, 0, { "icon-runes" },
-    B_Magic,		0, "upgrade-runes",
+    B_SpellCast,		0, "spell-runes",
     CheckTrue,		NULL,
     'r', "~!RUNES",
     "unit-cho'gall"
@@ -1123,38 +1124,38 @@ global ButtonAction AllButtons[] = {
     "unit-death-knight" ",unit-gul'dan" ",unit-teron-gorefiend"
 },
 {   4, 0, { "icon-death-coil" },
-    B_Magic,		0, "upgrade-death-coil",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-death-coil",
+    CheckTrue,		NULL,
     'c', "DEATH ~!COIL",
     "unit-death-knight" ",unit-gul'dan" ",unit-teron-gorefiend"
 },
 {   5, 0, { "icon-haste" },
-    B_Magic,		0, "upgrade-haste",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-haste",
+    CheckUpgrade,		"upgrade-haste",
     'h', "~!HASTE",
     "unit-death-knight"
 },
 {   6, 0, { "icon-raise-dead" },
-    B_Magic,		0, "upgrade-raise-dead",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-raise-dead",
+    CheckUpgrade,		"upgrade-raise-dead",
     'r', "~!RAISE DEAD",
     "unit-death-knight"
 },
 {   7, 0, { "icon-whirlwind" },
-    B_Magic,		0, "upgrade-whirlwind",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-whirlwind",
+    CheckUpgrade,		"upgrade-whirlwind",
     'w', "~!WHIRLWIND",
     "unit-death-knight"
 },
 {   8, 0, { "icon-unholy-armor" },
-    B_Magic,		0, "upgrade-unholy-armor",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-unholy-armor",
+    CheckUpgrade,		"upgrade-unholy-armor",
     'u', "~!UNHOLY ARMOR",
     "unit-death-knight"
 },
 {   9, 0, { "icon-death-and-decay" },
-    B_Magic,		0, "upgrade-death-and-decay",
-    NULL,		NULL,
+    B_SpellCast,		0, "spell-death-and-decay",
+    CheckUpgrade,		"upgrade-death-and-decay",
     'd', "~!DEATH AND DECAY",
     "unit-death-knight"
 },
diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp
index ddb68ea7b..807487909 100644
--- a/src/ui/mainscr.cpp
+++ b/src/ui/mainscr.cpp
@@ -1,6 +1,6 @@
 //   ___________		     _________		      _____  __
 //   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
-//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\
 //    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
 //    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
 //	  \/		    \/	   \/	     \/		   \/
@@ -513,7 +513,7 @@ global void ShiftMessages(void)
       {
       strcpy( Messages[z], "" );
       }
-  MessagesCount--;    
+  MessagesCount--;
 }
 
 /**
@@ -534,7 +534,7 @@ global void ShiftMessagesEvent(void)
       MessagesEventX[z] = -1;
       MessagesEventY[z] = -1;
       }
-  MessagesCount--;    
+  MessagesCount--;
 }
 
 /**
@@ -571,7 +571,7 @@ global void SetMessage( char* fmt, ... )
     va_end( va );
     if ( MessagesCount == MESSAGES_MAX )
       ShiftMessages();
-    strcpy( Messages[ MessagesCount ], temp );  
+    strcpy( Messages[ MessagesCount ], temp );
     MessagesCount++;
     MustRedraw|=RedrawMessage|RedrawMap;
     MessageFrameTimeout = FrameCounter + MESSAGES_TIMEOUT;
@@ -596,16 +596,16 @@ global void SetMessage2( int x, int y, char* fmt, ... )
     va_end( va );
     if ( MessagesCount == MESSAGES_MAX )
       ShiftMessages();
-    strcpy( Messages[ MessagesCount ], temp );  
+    strcpy( Messages[ MessagesCount ], temp );
     MessagesCount++;
-    
+ 
     if ( MessagesEventCount == MESSAGES_MAX )
       ShiftMessagesEvent();
     strcpy( MessagesEvent[ MessagesEventCount ], temp );
     MessagesEventX[ MessagesEventCount ] = x;
     MessagesEventY[ MessagesEventCount ] = y;
     MessagesEventCount++;
-    
+ 
     MustRedraw|=RedrawMessage|RedrawMap;
     MessageFrameTimeout = FrameCounter + MESSAGES_TIMEOUT;
 }
@@ -664,8 +664,8 @@ global void CenterOnMessage(void)
     MessagesEventIndex = 0;
   if ( MessagesEventIndex >= MessagesEventCount )
     return;
-  MapCenter( MessagesEventX[ MessagesEventIndex ], 
-             MessagesEventY[ MessagesEventIndex ] );  
+  MapCenter( MessagesEventX[ MessagesEventIndex ],
+             MessagesEventY[ MessagesEventIndex ] );
   SetMessage( "*Event: %s", MessagesEvent[ MessagesEventIndex ] );
   MessagesEventIndex++;
 }
diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp
index 4cc775eb6..06c575e07 100644
--- a/src/ui/mouse.cpp
+++ b/src/ui/mouse.cpp
@@ -771,6 +771,43 @@ local void SendUnload(int x,int y)
     }
 }
 
+/**
+**	Send the current selected group for spell cast.
+**
+**	To empty field:
+**	To unit:
+**		Spell cast on unit or on map spot.
+**
+**	@param x	X map tile position.
+**	@param y	Y map tile position.
+**
+**	@see Selected, @see NumSelected
+*/
+local void SendSpellCast(int x,int y)
+{
+    int i;
+    Unit* unit;
+    Unit* dest;
+    
+    dest=UnitOnMapTile(x,y);
+    DebugLevel3Fn("SpellCast on: %p (%d,%d)\n", dest, x, y);
+    /*	NOTE: Vladi:
+        This is a high-level function, it sends target spot and unit
+	(if exists). All checks are performed at spell cast handle 
+	function which will cancel function if cannot be executed
+    */
+    for( i=0; i<NumSelected; i++ ) {
+        unit=Selected[i];
+	if( !unit->Type->CanCastSpell ) 
+	  continue; // this unit cannot cast spell
+	if( dest && unit == dest ) 
+	  continue; // no unit can cast spell on himself
+	// CursorValue here holds the spell type id  
+	SendCommandSpellCast(unit,x,y,dest,CursorValue,!(KeyModifiers&ModifierShift));
+    }
+}
+
+
 /**
 **	Send a command to selected units.
 **
@@ -808,6 +845,9 @@ local void SendCommand(int x,int y)
 	case B_Demolish:
 	    SendDemolish(x,y);
 	    break;
+        case B_SpellCast:    
+	    SendSpellCast(x,y);
+	    break;
 	default:
 	    DebugLevel1("Unsupported send action %d\n",CursorAction);
 	    break;
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 45e17bdc8..6112576cd 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -271,6 +271,7 @@ global Unit* MakeUnit(UnitType* type,Player* player)
     unit->Reset=1;
 
     unit->Rs=MyRand()%100; // used for random fancy buildings and other things
+    unit->Revealer = 0; // FOW revealer
 
     unit->Command.Action=UnitActionStill;
     unit->PendCommand.Action=UnitActionStill;
@@ -735,6 +736,9 @@ global int UnitVisible(const Unit* unit)
 **
 **	NOTE: we could build a table of all magic units reducing cpu use.
 */
+//FIXME: vladi: the doc says incrementing mana is done by 1 per second
+//       the spells effect can be decremented at the same time and this
+//       will reduse calls to this function to one time per second only!
 global void UnitIncrementMana(void)
 {
     Unit** table;
@@ -758,6 +762,20 @@ global void UnitIncrementMana(void)
 		MustRedraw|=RedrawInfoPanel;
 	    }
 	}
+	
+	//
+	// decrease spells effects time
+	//
+	if ( unit->Bloodlust > 0 )
+	  unit->Bloodlust--;
+	if ( unit->Haste > 0 )
+	  unit->Haste--;
+	if ( unit->Slow > 0 ) 
+	  unit->Slow--;
+	if ( unit->Invisible > 0 )
+	  unit->Invisible--;
+	if ( unit->UnholyArmor > 0 )
+	  unit->UnholyArmor--;
     }
 }
 
@@ -2018,7 +2036,9 @@ global void DestroyUnit(Unit* unit)
 
     // FIXME: units in transporters should die without corpes...
     if( unit->Type->Transporter ) { // Transporters loose their units
-        DestroyAllInside(unit);
+        //FIXME: vladi: it could be usefull if transport is near land
+	//       to unload instead of destroying all units in it... ?
+	DestroyAllInside(unit);
     }
 
     RemoveUnit(unit);
@@ -2578,12 +2598,13 @@ global void SaveUnit(const Unit* unit,FILE* file)
     fprintf(file,"\t%d ",unit->Player->Player);
     fprintf(file,"%d ",unit->Mana);
     fprintf(file,"%d ",unit->HP);
-    fprintf(file,"(%d %d %d %d %d)\n"
+    fprintf(file,"(%d %d %d %d %d %d)\n"
 	    ,unit->Bloodlust
 	    ,unit->Haste
 	    ,unit->Slow
 	    ,unit->Invisible
-	    ,unit->Shield);
+	    ,unit->FlameShield
+	    ,unit->UnholyArmor);
     fprintf(file,"\t%d ",unit->GroupId);
     fprintf(file,"%d\n",unit->Value);
 
diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp
index 1b419ce69..4141eb73d 100644
--- a/src/unit/unit_draw.cpp
+++ b/src/unit/unit_draw.cpp
@@ -60,10 +60,6 @@ global int ShowHealthHorizontal=1;
 global int ShowManaHorizontal=1;
     /// Flag: show bars and dot energy only for selected
 global int ShowEnergySelectedOnly; 
-    /// Flag: show health bar always full sized
-global int ShowFullSizedHealthBar=1;
-    /// Flag: show mana bar always full sized
-global int ShowFullSizedManaBar=1;
 
 // FIXME: not all variables of this file are here
 // FIXME: perhaps split this file into two?
@@ -277,6 +273,11 @@ global Decoration ShadowSprite = {
     "graphic/unit shadow.png",	0,42, 32,32
 };
 
+/**
+**	Sprite to display the active spells on units.
+*/
+global Graphic* SpellSprites;
+
 #if defined(USE_CCL) || defined(USE_CCL2)
 
 /**
@@ -334,6 +335,7 @@ global void LoadDecorations(void)
 		,ManaSprite.Width,ManaSprite.Height);
     ShadowSprite.Sprite=LoadSprite(ShadowSprite.File
 		,ShadowSprite.Width,ShadowSprite.Height);
+    SpellSprites=LoadSprite("graphic/bloodlust,haste,slow,invis.,shield.png",16,16);		
 }
 
 /**
@@ -348,8 +350,6 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
 {
     int f;
     int color;
-    int deco_x;
-    int deco_y;
     UnitStats* stats;
 
 
@@ -360,13 +360,11 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
 	return;
     }
 
-    // FIXME: Should split this into small functions?
-
     //
-    //	Health bar of the unit.
+    //	Health bar on left side of unit.
     //
     stats=unit->Stats;
-    if( ShowHealthBar ) {
+    if( !type->Critter && ShowHealthBar ) {
 	if( stats->HitPoints
 		&& !(ShowNoFull && unit->HP==stats->HitPoints) ) {
 	    f=(100*unit->HP)/stats->HitPoints;
@@ -377,31 +375,26 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
 	    } else {
 		color=ColorRed;
 	    }
-	    if( ShowHealthHorizontal )  {
-		deco_x=x+((type->TileWidth*TileSizeX-type->BoxWidth)/2)-1;
-		deco_y=y+(type->TileHeight*TileSizeY-type->BoxHeight)/2
-			+type->BoxHeight;
-		if( !ShowFullSizedHealthBar ) {
+	    if ( ShowHealthHorizontal == 0)  {
+		    VideoFillRectangleClip(color
+			,x+(type->TileWidth*TileSizeX
+				-type->BoxWidth)/2
+			,y+(type->TileHeight*TileSizeY
+				-type->BoxHeight)/2
+			,2,(f*type->BoxHeight)/100);
+	    }  else  {
 		    VideoFillRectangleClip(ColorBlack
-			,deco_x,deco_y,type->BoxWidth+2,4);
-		} else {
-		    VideoDrawRectangleClip(ColorBlack
-			,deco_x,deco_y,(f*type->BoxWidth)/100+1,3);
-		}
-		VideoFillRectangleClip(color
-		    ,deco_x+1,deco_y+1,(f*type->BoxWidth)/100,2);
-	    } else {
-		deco_x=x+(type->TileWidth*TileSizeX-type->BoxWidth)/2-3;
-		deco_y=y+(type->TileHeight*TileSizeY-type->BoxHeight)/2;
-		if( ShowFullSizedHealthBar ) {
-		    VideoFillRectangleClip(ColorBlack
-			,deco_x,deco_y,4,type->BoxHeight+1);
-		} else {
-		    VideoDrawRectangleClip(ColorBlack
-			,deco_x,deco_y,3,(f*type->BoxHeight)/100);
-		}
-		VideoFillRectangleClip(color
-		    ,deco_x+1,deco_y+1,2,(f*type->BoxHeight)/100-1);
+			,x+((type->TileWidth*TileSizeX-type->BoxWidth)/2)-1
+			,(y+(type->TileHeight*TileSizeY-type->BoxHeight)/2)
+				+type->BoxHeight+1
+			,((f*type->BoxHeight)/100)+2
+			,5);
+		    VideoFillRectangleClip(color
+			,x+((type->TileWidth*TileSizeX-type->BoxWidth)/2)
+			,(y+(type->TileHeight*TileSizeY-type->BoxHeight)/2)
+				+type->BoxHeight+2
+			,(f*type->BoxHeight)/100
+			,3);
 	    }
 	}
     }
@@ -409,9 +402,11 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
     //
     //	Health dot on left side of unit.
     //
-    if( ShowHealthDot ) {
+    if( !type->Critter && ShowHealthDot ) {
 	if( stats->HitPoints
 		&& !(ShowNoFull && unit->HP==stats->HitPoints) ) {
+	    int x1;
+	    int y1;
 	    int n;
 
 	    f=(100*unit->HP)/stats->HitPoints;
@@ -426,61 +421,55 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
 	    }
 	    DebugCheck( n<0 );
 	    if( HealthSprite.HotX<0 ) {
-		deco_x=x+HealthSprite.HotX
+		x1=x+HealthSprite.HotX
 			+(type->TileWidth*TileSizeX
 			+type->BoxWidth+1)/2;
 	    } else {
-		deco_x=x-HealthSprite.HotX
+		x1=x-HealthSprite.HotX
 			+(type->TileWidth*TileSizeX
 			-type->BoxWidth+1)/2;
 	    }
 	    if( HealthSprite.HotY<0 ) {
-		deco_y=y+HealthSprite.HotY
+		y1=y+HealthSprite.HotY
 			+(type->TileHeight*TileSizeY
 			+type->BoxHeight+1)/2;
 	    } else {
-		deco_y=y-HealthSprite.HotY
+		y1=y-HealthSprite.HotY
 			+(type->TileHeight*TileSizeY
 			-type->BoxHeight+1)/2;
 	    }
-	    VideoDrawClip(HealthSprite.Sprite,n,deco_x,deco_y);
+	    VideoDrawClip(HealthSprite.Sprite,n,x1,y1);
 	}
     }
 
     //
-    //	Mana bar for the unit.
+    //	Mana bar on right side of unit.
     //
     if( ShowManaBar ) {
 	if( type->CanCastSpell
 		&& !(ShowNoFull && unit->Mana==255) ) {
-	    if( ShowManaHorizontal )  {
-		f=(100*unit->Mana)/255;
-		deco_x=x+((type->TileWidth*TileSizeX-type->BoxWidth)/2)-1;
-		deco_y=y+(type->TileHeight*TileSizeY-type->BoxHeight)/2
-			+type->BoxHeight+4;
-		if( ShowFullSizedManaBar ) {
-		    VideoFillRectangleClip(ColorBlack
-			,deco_x,deco_y,type->BoxHeight+2,4);
-		} else {
-		    VideoDrawRectangleClip(ColorBlack
-			,deco_x,deco_y,(f*type->BoxHeight)/100+1,3);
-		}
-		VideoFillRectangleClip(ColorBlue
-		    ,deco_x+1,deco_y+1,(f*type->BoxHeight)/100,2);
-	    } else {
-		deco_x=x+(type->TileWidth*TileSizeX+type->BoxWidth)/2;
-		deco_y=y+(type->TileHeight*TileSizeY-type->BoxHeight)/2;
+	    if ( ShowManaHorizontal == 0)  {
 	    	f=(100*unit->Mana)/255;
-		if( ShowFullSizedManaBar ) {
+		    VideoFillRectangleClip(ColorBlue
+			,x+(type->TileWidth*TileSizeX
+				+type->BoxWidth)/2
+			,y+(type->TileHeight*TileSizeY
+				-type->BoxHeight)/2
+			,2,(f*type->BoxHeight)/100);
+	    }  else  {
+		    f=(100*unit->Mana)/255;
 		    VideoFillRectangleClip(ColorBlack
-			,deco_x,deco_y,4,type->BoxHeight+1);
-		} else {
-		    VideoDrawRectangleClip(ColorBlack
-			,deco_x,deco_y,3,(f*type->BoxHeight)/100);
-		}
-		VideoFillRectangleClip(ColorBlue
-		    ,deco_x+1,deco_y+1,2,(f*type->BoxHeight)/100-1);
+			,x+((type->TileWidth*TileSizeX-type->BoxWidth)/2)-1
+			,(y+(type->TileHeight*TileSizeY-type->BoxHeight)/2)+type->BoxHeight+6
+			,(type->BoxHeight)+2
+			,5);
+		    VideoFillRectangleClip(ColorBlue
+			,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2
+			,(y+(type->TileHeight*TileSizeY-type->BoxHeight)/2)+type->BoxHeight+7
+			,(f*type->BoxHeight)/100
+			,3);
 	    }
+
 	}
     }
 
@@ -490,6 +479,8 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
     if( ShowManaDot ) {
 	if( type->CanCastSpell
 		&& !(ShowNoFull && unit->Mana==255) ) {
+	    int x1;
+	    int y1;
 	    int n;
 
 	    f=(100*unit->Mana)/255;
@@ -507,27 +498,41 @@ local void DrawDecoration(Unit* unit,const UnitType* type,int x,int y)
 		n=4;
 	    }
 	    if( ManaSprite.HotX<0 ) {
-		deco_x=x+ManaSprite.HotX
+		x1=x+ManaSprite.HotX
 			+(type->TileWidth*TileSizeX
 			+type->BoxWidth+1)/2;
 	    } else {
-		deco_x=x-ManaSprite.HotX
+		x1=x-ManaSprite.HotX
 			+(type->TileWidth*TileSizeX
 			-type->BoxWidth+1)/2;
 	    }
 	    if( ManaSprite.HotY<0 ) {
-		deco_y=y+ManaSprite.HotY
+		y1=y+ManaSprite.HotY
 			+(type->TileHeight*TileSizeY
 			+type->BoxHeight+1)/2;
 	    } else {
-		deco_y=y-ManaSprite.HotY
+		y1=y-ManaSprite.HotY
 			+(type->TileHeight*TileSizeY
 			-type->BoxHeight+1)/2;
 	    }
-	    VideoDrawClip(ManaSprite.Sprite,n,deco_x,deco_y);
+	    VideoDrawClip(ManaSprite.Sprite,n,x1,y1);
 	}
     }
 
+    //
+    // Draw spells decoration
+    //
+    if ( unit->Bloodlust > 0 )
+      VideoDrawClip( SpellSprites, 0, x, y );
+    if ( unit->Haste > 0 ) // same slot as slow
+      VideoDrawClip( SpellSprites, 1, x+16, y );
+    if ( unit->Slow > 0 ) // same slot as haste
+      VideoDrawClip( SpellSprites, 2, x+16, y );
+    if ( unit->Invisible > 0 )
+      VideoDrawClip( SpellSprites, 3, x+16+16, y );
+    if ( unit->UnholyArmor > 0 )
+      VideoDrawClip( SpellSprites, 4, x+16+16+16, y );
+    
     // FIXME: group number could also be shown
 }
 
@@ -559,7 +564,6 @@ local void DrawShadow(Unit* unit,UnitType* type,int x,int y)
 	    ,x+ShadowSprite.HotX,y+ShadowSprite.HotY);
 }
 
-#if 0
 /**
 **	Draw path from current postion to the destination of the move.
 **
@@ -681,134 +685,15 @@ global void DrawPath(Unit* unit)
 	    ,6,6);
     }
 }
-#endif
 
 /**
 **	Show the current order of an unit.
 **
 **	@param unit	Pointer to the unit.
+**
 */
 local void ShowOrder(const Unit* unit)
 {
-#ifdef NEW_ORDERS
-    int x1;
-    int y1;
-    int x2;
-    int y2;
-    int color;
-    const Unit* goal;
-    int i;
-
-    if( unit->Destroyed ) {
-	return;
-    }
-    x1=Map2ScreenX(unit->X)+unit->IX+unit->Type->TileWidth*TileSizeX/2;
-    y1=Map2ScreenY(unit->Y)+unit->IY+unit->Type->TileHeight*TileSizeY/2;
-    VideoFillCircleClip(ColorGreen,x1,y1,1);
-
-    for( i=0; i<=unit->OrderCount; ++i ) {
-	if( (goal=unit->Orders[i].Goal) ) {
-	    x2=Map2ScreenX(goal->X)+goal->IX+goal->Type->TileWidth*TileSizeX/2;
-	    y2=Map2ScreenY(goal->Y)+goal->IY+goal->Type->TileHeight*TileSizeY/2;
-	} else {
-	    x2=Map2ScreenX(unit->Orders[i].X)+TileSizeX/2;
-	    y2=Map2ScreenY(unit->Orders[i].Y)+TileSizeY/2;
-	}
-	switch( unit->Orders[i].Action ) {
-	    case UnitActionNone:
-		color=ColorGray;
-		break;
-
-	    case UnitActionStill:
-		color=ColorGray;
-		break;
-
-	    case UnitActionStandGround:
-		color=ColorGray;
-		break;
-
-	    case UnitActionFollow:
-	    case UnitActionMove:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionPatrol:
-		VideoDrawLineClip(ColorGreen,x1,y1,x2,y2);
-		color=ColorBlue;
-		break;
-
-	    case UnitActionRepair:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionAttack:
-	    case UnitActionAttackGround:
-		color=ColorRed;
-		break;
-
-	    case UnitActionBoard:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionUnload:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionDie:
-		color=ColorGray;
-		break;
-
-	    case UnitActionTrain:
-		color=ColorGray;
-		break;
-
-	    case UnitActionUpgradeTo:
-		color=ColorGray;
-		break;
-
-	    case UnitActionResearch:
-		color=ColorGray;
-		break;
-
-	    case UnitActionBuild:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionBuilded:
-		color=ColorGray;
-		break;
-
-	    case UnitActionHarvest:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionMineGold:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionHaulOil:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionReturnGoods:
-		color=ColorGreen;
-		break;
-
-	    case UnitActionDemolish:
-		color=ColorRed;
-		break;
-
-	    default:
-		color=ColorGray;
-		DebugLevel1Fn("Unknown action %d\n",unit->Orders[i].Action);
-		break;
-	}
-	VideoDrawLineClip(color,x1,y1,x2,y2);
-	VideoFillCircleClip(color,x2,y2,2);
-	x1=x2;
-	y1=y2;
-    }
-#else
     int x1;
     int y1;
     int x2;
@@ -925,7 +810,6 @@ local void ShowOrder(const Unit* unit)
     VideoFillCircleClip(color,x2,y2,2);
 
     //DrawPath(unit);
-#endif
 }
 
 /*
@@ -933,7 +817,6 @@ local void ShowOrder(const Unit* unit)
 **
 **	1) Must draw underground/underwater units. (FUTURE extension)
 **	2) Must draw buildings and corpse.
-**	FIXME: Bridges?
 **	3) Must draw land/sea units.
 **	4) Must draw decoration units. (FUTURE extension)
 **	5) Must draw low air units.
@@ -998,34 +881,6 @@ local void DrawBuilding(Unit* unit)
     DrawSelection(unit,type,x,y);
 #endif
 
-#ifdef NEW_ORDERS
-    //
-    //	Buildings under construction/upgrade/ready.
-    //
-    if( unit->Orders[0].Action==UnitActionBuilded ) {
-	if( unit->Constructed || VideoGraphicFrames(type->Sprite)<=1 ) {
-	    DrawConstruction(type->OverlapFrame
-		,frame&127
-		,x+(type->TileWidth*TileSizeX)/2
-		,y+(type->TileHeight*TileSizeY)/2);
-	} else {
-	    DrawUnitType(type,frame,x,y);
-	}
-    } else if( unit->Orders[0].Action==UnitActionUpgradeTo ) {
-	// FIXME: update frame hard coded.
-	DrawUnitType(unit->Orders[0].Type,(frame&128)+1,x,y);
-    } else {
-	DrawUnitType(type,frame,x,y);
-    }
-
-    // FIXME: johns: ugly check here should be removed!
-    if( unit->Orders[0].Action!=UnitActionDie ) {
-	DrawDecoration(unit,type,x,y);
-#if 0
-	DrawSelection(unit,type,x,y);
-#endif
-    }
-#else
     //
     //	Buildings under construction/upgrade/ready.
     //
@@ -1044,12 +899,16 @@ local void DrawBuilding(Unit* unit)
 	DrawUnitType(type,frame,x,y);
     }
 
+#if 0
     // FIXME: johns: ugly check here should be removed!
     if( unit->Command.Action!=UnitActionDie ) {
 	DrawDecoration(unit,type,x,y);
-#if 0
 	DrawSelection(unit,type,x,y);
-#endif
+    }
+#else
+    // FIXME: johns: ugly check here should be removed!
+    if( unit->Command.Action!=UnitActionDie ) {
+	DrawDecoration(unit,type,x,y);
     }
 #endif
 }
@@ -1067,6 +926,8 @@ local void DrawUnit(Unit* unit)
     UnitType* type;
     UnitStats* stats;
 
+    if ( unit->Revealer ) return; // Revealers are not drawn
+
     type=unit->Type;
 
     x=Map2ScreenX(unit->X)+unit->IX;
@@ -1124,17 +985,10 @@ local void DrawUnit(Unit* unit)
 	ShowOrder(unit);
     }
 
-#ifdef NEW_ORDERS
-    // FIXME: johns: ugly check here should be removed!
-    if( unit->Orders[0].Action!=UnitActionDie ) {
-	DrawDecoration(unit,type,x,y);
-    }
-#else
     // FIXME: johns: ugly check here should be removed!
     if( unit->Command.Action!=UnitActionDie ) {
 	DrawDecoration(unit,type,x,y);
     }
-#endif
 }
 
 /**
@@ -1159,17 +1013,9 @@ global void DrawUnits(void)
     for( i=0; i<NumUnits; ++i ) {
 	unit=Units[i];
 	// FIXME: this tries to draw all corps, ohje
-#ifdef NEW_ORDERS
-	if( (unit->Type->Vanishes || unit->Orders[0].Action==UnitActionDie)
-		&& UnitVisible(unit) ) {
+	if( unit->Type->Vanishes || unit->Command.Action==UnitActionDie ) {
 	    DrawUnit(unit);
 	}
-#else
-	if( (unit->Type->Vanishes || unit->Command.Action==UnitActionDie)
-		&& UnitVisible(unit) ) {
-	    DrawUnit(unit);
-	}
-#endif
     }
     //
     //	2b) buildings
diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp
index b3697ec95..ae62e710a 100644
--- a/src/unit/unit_find.cpp
+++ b/src/unit/unit_find.cpp
@@ -67,7 +67,10 @@
 */
 global int SelectUnits(int x1,int y1,int x2,int y2,Unit** table)
 {
-    return UnitCacheSelect(x1,y1,x2,y2,table);
+    if ( x1 == x2 && y1 == y2 )
+      return UnitCacheOnTile(x1,y1,table);
+    else
+      return UnitCacheSelect(x1,y1,x2,y2,table);
 }
 
 /**
diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp
index cd3c5dd2e..e6aa0a30d 100644
--- a/src/video/cursor.cpp
+++ b/src/video/cursor.cpp
@@ -124,6 +124,7 @@ global CursorType Cursors[CursorMax] = {
 
 global enum CursorState_e CursorState;	/// cursor state
 global int CursorAction;		/// action for selection
+global int CursorValue;			/// value for CursorAction (spell type f.e.)
 global UnitType* CursorBuilding;	/// building cursor
 
 global CursorType* GameCursor;		/// cursor type