changeset 4:66b3e9199244 branch_net

=eventsystem fuer objekte und Projektile
author wuha
date Sun, 21 Sep 2008 21:58:33 +0000
parents b330c4597cbf
children 038918a365d3
files src/core/action.cpp src/core/action.h src/core/charconv.h src/core/creature.cpp src/core/creature.h src/core/dmgprojectile.cpp src/core/dmgprojectile.h src/core/gridunit.cpp src/core/monster.cpp src/core/networkstruct.h src/core/player.cpp src/core/projectile.cpp src/core/projectile.h src/core/region.cpp src/core/region.h src/core/serverwobject.cpp src/core/serverwobject.h src/core/world.cpp src/core/world.h
diffstat 19 files changed, 1523 insertions(+), 361 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/action.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/action.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -1707,3 +1707,33 @@
     #endif
 }
 
+void Action::toString(CharConv* cv)
+{
+
+	/*
+	*((short*) buf) = (short) m_type;
+	*((float* ) (buf+sizeof(short))) = m_elapsed_time / m_time;
+	return buf+sizeof(short)+sizeof(float);
+	*/
+	cv->toBuffer((short) m_type);
+	cv->toBuffer(m_time);
+	cv->toBuffer((char) m_action_equip);
+	cv->toBuffer(m_animation_number);
+	cv->toBuffer(m_elapsed_time);	
+
+	
+}
+
+void Action::fromString(CharConv* cv)
+{
+	short tmp;
+	char ctmp;
+	cv->fromBuffer(tmp);
+	m_type = (ActionType) tmp;
+	cv->fromBuffer(m_time);
+	cv->fromBuffer(ctmp);
+	m_action_equip = (ActionEquip) ctmp;
+	cv->fromBuffer(m_animation_number);
+	cv->fromBuffer(m_elapsed_time);
+}
+
--- a/src/core/action.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/action.h	Sun Sep 21 21:58:33 2008 +0000
@@ -383,19 +383,8 @@
 	 * \param buf Ausgabepuffer
 	 * \return Zeiger hinter den beschriebenen Datenbereich
 	 */
-	void toString(CharConv* cv)
-	{
-		/*
-		*((short*) buf) = (short) m_type;
-		*((float* ) (buf+sizeof(short))) = m_elapsed_time / m_time;
-		return buf+sizeof(short)+sizeof(float);
-		*/
-		cv->toBuffer((short) m_type);
-		cv->toBuffer(m_elapsed_time / m_time);
-		cv->toBuffer((char) m_action_equip);
-		cv->toBuffer((char) m_animation_number);		
-
-	}
+	void toString(CharConv* cv);
+	
 
 	/**
 	 * \fn void fromString(CharConv* cv)
@@ -403,20 +392,8 @@
 	 * \param buf Objekt als String
 	 * \return Zeiger hinter den gelesenen Datenbereich
 	 */
-	void fromString(CharConv* cv)
-	{
-		short tmp;
-		char ctmp;
-		cv->fromBuffer(tmp);
-		m_type = (ActionType) tmp;
-		cv->fromBuffer(m_elapsed_time);
-		cv->fromBuffer(ctmp);
-		m_action_equip = (ActionEquip) ctmp;
-		cv->fromBuffer(m_animation_number);
-		
-		
-		m_time=1;
-	}
+	void fromString(CharConv* cv);
+	
 
 	//Fields
 	/**
--- a/src/core/charconv.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/charconv.h	Sun Sep 21 21:58:33 2008 +0000
@@ -114,6 +114,16 @@
 	{
 		return &m_bitstream;
 	}
+	
+	int readBits()
+	{
+		return m_bitstream.GetReadOffset();
+	}
+	
+	int writeBits()
+	{
+		return m_bitstream.GetNumberOfBitsUsed();
+	}
 			
 	
 	private:
--- a/src/core/creature.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/creature.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -117,6 +117,8 @@
 
 	//Lebenspunkts auf 1 (debugging)
 	m_dyn_attr.m_health = 1;
+	
+	m_event_mask =0;
 
 	return tmp;
 }
@@ -142,7 +144,7 @@
 		}
 	}
 
-	DEBUG("destroy");
+	DEBUG5("destroy");
 
 	ServerWObject::destroy();
     return true;
@@ -159,6 +161,8 @@
 	DEBUG5("object died: %p",this);
 	m_action.m_time =1000;
 	m_action.m_elapsed_time =0;
+	
+	m_event_mask |= Event::DATA_ACTION | Event::DATA_STATE;
 }
 
 void Creature::initAction()
@@ -199,6 +203,7 @@
 			// Timer ist frei, Timer starten
 			m_timer1 = time;
 			m_timer1_max = time;
+			m_event_mask |= Event::DATA_TIMER;
 		}
 		else
 		{
@@ -215,6 +220,7 @@
 			// Timer ist frei, Timer starten
 			m_timer2 = time;
 			m_timer2_max = time;
+			m_event_mask |= Event::DATA_TIMER;
 		}
 		else
 		{
@@ -248,7 +254,7 @@
 			m_action.m_time = 1000000 / getBaseAttrMod()->m_walk_speed;
 			getMoveInfo()->m_speed_x *= getBaseAttr()->m_step_length/m_action.m_time;
 			getMoveInfo()->m_speed_y *= getBaseAttr()->m_step_length/m_action.m_time;
-
+			m_event_mask |= Event::DATA_MOVE_INFO;
 			//collisionDetection(m_action.m_time);
 
 			DEBUG5("walk time %f walk speed %i",m_action.m_time,getBaseAttrMod()->m_walk_speed);
@@ -305,6 +311,7 @@
 	{
 	}
 
+	m_event_mask |= Event::DATA_ACTION;
 }
 
 void Creature::performAction(float &time)
@@ -352,7 +359,10 @@
 		p2 = rezt * m_action.m_elapsed_time;
 	}
 
-	DEBUG5("perform Action %i for %f msec, %f / %f done", m_action.m_type,dtime,m_action.m_elapsed_time,m_action.m_time);
+	if (!getWorld()->isServer() && m_action.m_type != Action::NOACTION)
+	{
+		DEBUG5("perform Action %i for %f msec, %f / %f done", m_action.m_type,dtime,m_action.m_elapsed_time,m_action.m_time);
+	}
 
 
 	//Behandlung des Laufens
@@ -390,7 +400,7 @@
 	}
 
 	// Testen ob der kritische Prozentsatz durch das aktuelle Zeitquantum ueberschritten wurde
-	if (p1<pct && pct <=p2)
+	if (p1<pct && pct <=p2 && getWorld()->isServer())
 	{
 		DEBUG5("critical point %f %f %f",p1,pct,p2);
 
@@ -488,7 +498,9 @@
 	{
 		DEBUG5("finished action");
 		if (m_action.m_type != Action::WALK)
+		{
 			m_action.m_prev_type = m_action.m_type;
+		}
 
 		DEBUG5("distance to goal %f",sqr(m_command.m_goal_coordinate_x -getGeometry()->m_shape.m_coordinate_x) +  sqr(m_command.m_goal_coordinate_y -getGeometry()->m_shape.m_coordinate_y));
 
@@ -498,17 +510,27 @@
 				  m_action.m_type == Action::WALK && sqr(getGeometry()->m_shape.m_radius) > sqr(m_command.m_goal_coordinate_x -getGeometry()->m_shape.m_coordinate_x) +  sqr(m_command.m_goal_coordinate_y -getGeometry()->m_shape.m_coordinate_y) && !(m_command.m_type == Action::CHARGE || m_command.m_type == Action::STORM_CHARGE))
 		{
 			DEBUG5("finished command");
+			if (m_command.m_type != Action::NOACTION)
+			{
+				m_event_mask |= Event::DATA_COMMAND;
+			}
 			m_command.m_type = Action::NOACTION;
 			m_action.m_elapsed_time=0;
 			m_command.m_damage_mult = 1;
+			
 
 			// Schaden neu berechnen
 			recalcDamage();
 		}
 
 		// Aktion ist beendet
+		if (m_action.m_type != Action::NOACTION)
+		{
+			m_event_mask |= Event::DATA_ACTION;
+		}
 		m_action.m_type = Action::NOACTION;
 		m_action.m_elapsed_time =0;
+		m_event_mask |= Event::DATA_ACTION;
 	}
 
 
@@ -537,7 +559,9 @@
 	if (Action::getActionInfo(m_action.m_type)->m_distance == Action::MELEE)
 	{
 		if (cgoal && m_action.m_type!=Action::AROUND_BLOW &&  m_action.m_type!=Action::WHIRL_BLOW)
+		{
 			cgoal->takeDamage(&m_damage);
+		}
 	}
 
 
@@ -678,6 +702,7 @@
 		case Action::REGENERATE:
 			// 50% der Lebenspunkte wieder auffuellen
 			m_dyn_attr.m_health = std::min(m_dyn_attr.m_health+0.5f*m_base_attr_mod.m_max_health,m_base_attr_mod.m_max_health);
+			m_event_mask |= Event::DATA_HP;
 			break;
 
 		case Action::ANGER:
@@ -688,6 +713,7 @@
 			cbam.m_darmor = -m_base_attr_mod.m_armor /2;
 			applyBaseAttrMod(&cbam);
 			m_dyn_attr.m_status_mod_time[Damage::BERSERK] = 30000;
+			m_event_mask |= Event::DATA_STATUS_MODS;
 			break;
 
 		case Action::FURY:
@@ -699,6 +725,7 @@
 			cbam.m_dattack_speed = 1000;
 			applyBaseAttrMod(&cbam);
 			m_dyn_attr.m_status_mod_time[Damage::BERSERK] = 30000;
+			m_event_mask |= Event::DATA_STATUS_MODS;
 			break;
 
 		// Magierfaehigkeiten
@@ -1385,7 +1412,9 @@
 		cbam.m_dstrength = getBaseAttr()->m_strength / 10;
 		cbam.m_time = 10000;
 		if (checkAbility(Action::MONSTER_SLAYER))
+		{
 			cbam.m_dattack_speed = 200;
+		}
 		applyBaseAttrMod(&cbam);
 
 	}
@@ -1428,6 +1457,7 @@
 			{
 				getMoveInfo()->m_speed_x =0;
 				getMoveInfo()->m_speed_y =0;
+				m_event_mask |= Event::DATA_MOVE_INFO;
 				break;
 			}
 
@@ -1438,6 +1468,7 @@
 				m_command.m_goal_object_id = (*i)->getId();
 				getMoveInfo()->m_speed_x =0;
 				getMoveInfo()->m_speed_y =0;
+				m_event_mask |= Event::DATA_MOVE_INFO;
 				return;
 			}
 			else
@@ -1469,6 +1500,7 @@
 
 			getMoveInfo()->m_speed_x =0;
 			getMoveInfo()->m_speed_y =0;
+			m_event_mask |= Event::DATA_MOVE_INFO;
 		}
 
 	}
@@ -1584,7 +1616,10 @@
 		getMoveInfo()->m_speed_x *= d*getBaseAttr()->m_step_length/m_action.m_time;
 		getMoveInfo()->m_speed_y *= d*getBaseAttr()->m_step_length/m_action.m_time;
 		DEBUG5("speed %f %f",getMoveInfo()->m_speed_x,getMoveInfo()->m_speed_y);
+		
+
 	}
+	m_event_mask |= Event::DATA_MOVE_INFO;
 
 }
 
@@ -1604,6 +1639,10 @@
 
 		// Naechstes Kommando auf nichts setzen
 		m_next_command.m_type = Action::NOACTION;
+		
+		m_event_mask |= Event::DATA_COMMAND;
+		m_event_mask |= Event::DATA_NEXT_COMMAND;
+			
 	}
 
 	// Kommando ausrechnen das evtl aus einem Statusmod resultiert
@@ -1623,13 +1662,18 @@
 	// wenn kein Kommando existiert keine Aktion ausfuehren, beenden
 	if (m_command.m_type == Action::NOACTION)
 	{
-
+		if (m_action.m_type!= Action::NOACTION)
+		{
+			m_event_mask |= Event::DATA_ACTION;
+		}
 		m_action.m_type = Action::NOACTION;
 		return;
 
 	}
 
+
 	DEBUG5("calc action for command %i",m_command.m_type);
+	m_event_mask |= Event::DATA_ACTION;
 
 
 	// Reichweite der Aktion berechnen
@@ -1677,6 +1721,7 @@
 			m_action.m_type = Action::NOACTION;
 			m_action.m_elapsed_time =0;
 			m_command.m_damage_mult=1;
+			m_event_mask |= Event::DATA_COMMAND;
 			return;
 		}
 
@@ -1688,6 +1733,7 @@
 			m_action.m_type = Action::NOACTION;
 			m_command.m_damage_mult=1;
 			m_action.m_elapsed_time =0;
+			m_event_mask |= Event::DATA_COMMAND;
 			return;
 		}
 
@@ -1737,14 +1783,22 @@
 		if ((sqr(r) > sqr(cx-x)+sqr(cy-y)))
 		{
 			// Ziel ist in Reichweite, geplante Aktion ausfuehren
-			m_action.m_type = m_command.m_type;
-			m_action.m_goal_object_id = m_command.m_goal_object_id;
-			m_action.m_goal_coordinate_x = goalx;
-			m_action.m_goal_coordinate_y = goaly;
-
+			if (m_command.m_type != Action::WALK)
+			{
+				m_action.m_type = m_command.m_type;
+				m_action.m_goal_object_id = m_command.m_goal_object_id;
+				m_action.m_goal_coordinate_x = goalx;
+				m_action.m_goal_coordinate_y = goaly;
+			}
+			else
+			{
+				m_action.m_type = Action::NOACTION;	
+			}
+			
 			// Kommando damit abgeschlossen
 			m_command.m_type = Action::NOACTION;
 			m_command.m_damage_mult = 1;
+			m_event_mask |= Event::DATA_COMMAND;
 		}
 		else
 		{
@@ -1777,6 +1831,7 @@
 					d *= sqrt(m_command.m_damage_mult);
 					getMoveInfo()->m_speed_x *= d;
 					getMoveInfo()->m_speed_y *= d;
+					m_event_mask |= Event::DATA_MOVE_INFO;
 					DEBUG(" dir %f %f dmg mult %f",getMoveInfo()->m_speed_x,getMoveInfo()->m_speed_y,m_command.m_damage_mult);
 				}
 				else
@@ -1800,8 +1855,10 @@
 						m_action.m_type = Action::NOACTION;
 						m_action.m_elapsed_time =0;
 						m_command.m_damage_mult = 1;
+						m_event_mask |= Event::DATA_COMMAND;
+
 					}
-
+					m_event_mask |= Event::DATA_MOVE_INFO;
 
 				}
 
@@ -1826,6 +1883,12 @@
 
 		m_command.m_type = Action::NOACTION;
 		m_command.m_damage_mult = 1;
+		m_event_mask |= Event::DATA_COMMAND;
+	}
+	
+	if (m_action.m_type !=0)
+	{
+		DEBUG5("calc action: %i at %f %f, dir %f %f",m_action.m_type, getGeometry()->m_shape.m_coordinate_x,	getGeometry()->m_shape.m_coordinate_y, getMoveInfo()->m_speed_x,getMoveInfo()->m_speed_y);
 	}
 
 }
@@ -1833,7 +1896,8 @@
 void Creature::calcStatusModCommand()
 {
 	// Statusmod verwirrt
-	if (m_dyn_attr.m_status_mod_time[Damage::CONFUSED]>0)
+	// diese Aktion nur vom Server ausloesen lassen
+	if (m_dyn_attr.m_status_mod_time[Damage::CONFUSED]>0 && getWorld()->isServer())
 	{
 		// eigene Position
 		float x=getGeometry()->m_shape.m_coordinate_x;
@@ -1927,6 +1991,7 @@
 			m_command.m_goal_coordinate_y =y;
 			m_command.m_goal_object_id =0;
 			m_command.m_range = getBaseAttr()->m_attack_range;
+			m_event_mask |= Event::DATA_COMMAND;
 
 			// Im Falle von Beserker nur Nahkampf
 			if (m_dyn_attr.m_status_mod_time[Damage::BERSERK]>0)
@@ -1944,6 +2009,7 @@
 			m_command.m_type = Action::WALK;
 			getMoveInfo()->m_speed_x =sx;
 			getMoveInfo()->m_speed_y = sy;
+			m_event_mask |= Event::DATA_COMMAND | Event::DATA_MOVE_INFO;
 			return;
 		}
 
@@ -2023,6 +2089,7 @@
 			// nichts machen
 			m_command.m_type = Action::NOACTION;
 		}
+		m_event_mask |= Event::DATA_COMMAND;
 	}
 }
 
@@ -2164,10 +2231,12 @@
 		m_action.m_type = Action::NOACTION;
 		m_action.m_elapsed_time =0;
 		m_command.m_damage_mult=1;
+		m_event_mask |= Event::DATA_COMMAND | Event::DATA_ACTION;
 		return;
 	}
 	else
 	{
+		m_event_mask |= Event::DATA_MOVE_INFO;
 		// TODO: Wende über 90 Grad behandeln
 		if (getMoveInfo()->m_speed_x*dir[0]+getMoveInfo()->m_speed_y*dir[1]>0)
 		{
@@ -2180,9 +2249,8 @@
 			getMoveInfo()->m_speed_x = dir[0] /l;
 			getMoveInfo()->m_speed_y = dir[1]/l;
 		}
-		DEBUG5("direction: %f %f",dir[0]/l,dir[1]/l);
+		
 	}
-
 }
 
 bool Creature::update (float time)
@@ -2237,12 +2305,17 @@
 			// aktuelle Aktion abbrechen nach auslaufen von Berserker / verwirrt
 			// (da die Aktion idr ungewollt bzw ungeplant ist)
 			if (i==Damage::BERSERK || i==Damage::CONFUSED)
+			{
 				m_command.m_type = Action::NOACTION;
+				m_event_mask |= Event::DATA_COMMAND;
+			}
 		}
 
 		m_dyn_attr.m_status_mod_immune_time[i] -= time;
 		if (m_dyn_attr.m_status_mod_immune_time[i]<0)
+		{
 			m_dyn_attr.m_status_mod_immune_time[i]=0;
+		}
 
 	}
 
@@ -2251,7 +2324,9 @@
 	{
 		m_dyn_attr.m_effect_time[i] -= time;
 		if (m_dyn_attr.m_effect_time[i]<0)
+		{
 			m_dyn_attr.m_effect_time[i]=0;
+		}
 	}
 
 	// Zeit fuer temporaere Effekte reduzieren und ggf deaktivieren
@@ -2288,61 +2363,69 @@
 
 
 	// besondere zeitabhaengige Effekte berechnen
-	if (m_base_attr_mod.m_special_flags & FLAMEARMOR)
+	if (getWorld()->isServer())
 	{
-		// Flammenruestung
-
-		// Schaden fuer Flammenruestung setzen
-		Damage d;
-		d.m_min_damage[Damage::FIRE] = time*m_base_attr_mod.m_magic_power*0.0003;
-		d.m_max_damage[Damage::FIRE] = time*m_base_attr_mod.m_magic_power*0.0005;
-		d.m_multiplier[Damage::FIRE]=1;
-
-		list<ServerWObject*> res;
-		res.clear();
-		list<ServerWObject*>::iterator it;
-
-		// Kreis um eigenen Mittelpunkt mit Radius eigener Radius plus 1
-		Shape s;
-		s.m_coordinate_x = getGeometry()->m_shape.m_coordinate_x;
-		s.m_coordinate_y = getGeometry()->m_shape.m_coordinate_y;
-		s.m_type = Shape::CIRCLE;
-		s.m_radius = getGeometry()->m_shape.m_radius+1;
-		Creature* cr;
-		short reg = getGridLocation()->m_region;
-
-		// Alle Objekte im Kreis suchen
-		getWorld()->getSWObjectsInShape(&s, reg, &res,Geometry::LAYER_AIR,CREATURE,this);
-		for (it=res.begin();it!=res.end();++it)
+		if (m_base_attr_mod.m_special_flags & FLAMEARMOR)
 		{
-			// Schaden austeilen
-			if ((*it)->getTypeInfo()->m_type != TypeInfo::TYPE_FIXED_OBJECT)
+			// Flammenruestung
+	
+			// Schaden fuer Flammenruestung setzen
+			Damage d;
+			d.m_min_damage[Damage::FIRE] = time*m_base_attr_mod.m_magic_power*0.0003;
+			d.m_max_damage[Damage::FIRE] = time*m_base_attr_mod.m_magic_power*0.0005;
+			d.m_multiplier[Damage::FIRE]=1;
+	
+			list<ServerWObject*> res;
+			res.clear();
+			list<ServerWObject*>::iterator it;
+	
+			// Kreis um eigenen Mittelpunkt mit Radius eigener Radius plus 1
+			Shape s;
+			s.m_coordinate_x = getGeometry()->m_shape.m_coordinate_x;
+			s.m_coordinate_y = getGeometry()->m_shape.m_coordinate_y;
+			s.m_type = Shape::CIRCLE;
+			s.m_radius = getGeometry()->m_shape.m_radius+1;
+			Creature* cr;
+			short reg = getGridLocation()->m_region;
+	
+			// Alle Objekte im Kreis suchen
+			getWorld()->getSWObjectsInShape(&s, reg, &res,Geometry::LAYER_AIR,CREATURE,this);
+			for (it=res.begin();it!=res.end();++it)
 			{
-				cr = (Creature*) (*it);
-				cr->takeDamage(&d);
-
+				// Schaden austeilen
+				if ((*it)->getTypeInfo()->m_type != TypeInfo::TYPE_FIXED_OBJECT)
+				{
+					cr = (Creature*) (*it);
+					cr->takeDamage(&d);
+	
+				}
 			}
+	
 		}
-
 	}
-
+	
 	// Statusmods behandeln
 	if (getState()==STATE_ACTIVE)
 	{
-		// Vergiftet
-		if (m_dyn_attr.m_status_mod_time[Damage::POISONED]>0)
+		if (getWorld()->isServer())
 		{
-			// Schaden pro Sekunde 1/60 der HP
-			DEBUG5("poisoned");
-			m_dyn_attr.m_health -= time*m_base_attr_mod.m_max_health / 60000;
-		}
-
-		// brennend
-		if (m_dyn_attr.m_status_mod_time[Damage::BURNING]>0)
-		{
-			// Schaden pro Sekunde 1/90 der HP (bei 0 Feuerresistenz)
-			DEBUG5("burning");
-			m_dyn_attr.m_health -= (100-m_base_attr_mod.m_resistances[Damage::FIRE])*time*m_base_attr_mod.m_max_health / 9000000;
+			// Vergiftet
+			if (m_dyn_attr.m_status_mod_time[Damage::POISONED]>0)
+			{
+				// Schaden pro Sekunde 1/60 der HP
+				DEBUG5("poisoned");
+				m_dyn_attr.m_health -= time*m_base_attr_mod.m_max_health / 60000;
+				m_event_mask |= Event::DATA_HP;
+			}
+	
+			// brennend
+			if (m_dyn_attr.m_status_mod_time[Damage::BURNING]>0)
+			{
+				// Schaden pro Sekunde 1/90 der HP (bei 0 Feuerresistenz)
+				DEBUG5("burning");
+				m_dyn_attr.m_health -= (100-m_base_attr_mod.m_resistances[Damage::FIRE])*time*m_base_attr_mod.m_max_health / 9000000;
+				m_event_mask |= Event::DATA_HP;
+			}
 		}
 
 		// eingefroren
@@ -2418,6 +2501,8 @@
 					setState(STATE_DEAD);
 					m_action.m_type = Action::DEAD;
 					m_action.m_time = 1000;
+					
+					m_event_mask |= Event::DATA_STATE | Event::DATA_ACTION;
 				}
 				break;
 
@@ -2547,6 +2632,7 @@
 
 	// Erfahrung dazu addieren
 	m_dyn_attr.m_experience += exp;
+	m_event_mask |= Event::DATA_EXPERIENCE;
 
 	// Solange Level aufsteigen, bis exp < max_exp
 	while (m_dyn_attr.m_experience>= m_base_attr.m_max_experience)
@@ -2557,6 +2643,7 @@
 
 void Creature::gainLevel()
 {
+	m_event_mask |= Event::DATA_LEVEL;
 
 }
 
@@ -3372,6 +3459,7 @@
 		d->m_multiplier[Damage::PHYSICAL] *= 3;
 	}
 
+	
 	// Berechnen des Schadens
 
 	// physischer Schaden
@@ -3430,7 +3518,10 @@
 				t = (d->m_status_mod_power[i]-m_base_attr_mod.m_willpower)*1.0 / m_base_attr_mod.m_willpower;
 				t *= 3000;
 				if (t>m_dyn_attr.m_status_mod_time[i])
+				{
 					m_dyn_attr.m_status_mod_time[i] =t;
+					m_event_mask |= Event::DATA_STATUS_MODS;
+				}
 
 				DEBUG("applying status mod %i for %f ms",i,t);
 			}
@@ -3445,6 +3536,7 @@
 	if (dmg>0)
 	{
 		m_dyn_attr.m_effect_time[CreatureDynAttr::BLEEDING] = max(m_dyn_attr.m_effect_time[CreatureDynAttr::BLEEDING],150.0f);
+		m_event_mask |= Event::DATA_HP | Event::DATA_EFFECTS;
 	}
 
 	// Statikschild wenn mehr als 2% der Lebenspunkte verloren
@@ -3471,7 +3563,14 @@
 	m_dyn_attr.m_health += mod->m_dhealth;
 
 	if (m_dyn_attr.m_health>m_base_attr_mod.m_max_health)
+	{
 		m_dyn_attr.m_health=m_base_attr_mod.m_max_health;
+	}
+	
+	if (mod->m_dhealth !=0)
+	{
+		m_event_mask |= Event::DATA_HP;
+	}
 
 
 	for (int i = 0;i< NR_STATUS_MODS;i++)
@@ -3480,6 +3579,7 @@
 		{
 			m_dyn_attr.m_status_mod_immune_time[i] = max(m_dyn_attr.m_status_mod_immune_time[i],mod->m_dstatus_mod_immune_time[i]);
 			m_dyn_attr.m_status_mod_time[i]=0;
+			m_event_mask |= Event::DATA_STATUS_MODS;
 		}
 	}
 }
@@ -3504,6 +3604,20 @@
 		DEBUG("magic power mod %i",mod->m_dmagic_power);
 	}
 	m_base_attr_mod.m_attack_speed +=mod->m_dattack_speed;
+	
+	// Modifikationen feststellen
+	if (mod->m_dwalk_speed!=0)
+	{
+		m_event_mask |= Event::DATA_WALK_SPEED;
+	}
+	if (mod->m_dattack_speed !=0)
+	{
+		m_event_mask |= Event::DATA_ATTACK_SPEED;
+	}
+	if (mod->m_dmax_health !=0)
+	{
+		m_event_mask |= Event::DATA_MAX_HP;
+	}
 
 	// einige Untergrenzen pruefen
 	m_base_attr_mod.m_strength = max(m_base_attr_mod.m_strength,(short) 1);
@@ -3525,11 +3639,20 @@
 	for (i=0;i<6;i++)
 	{
 		m_base_attr_mod.m_abilities[i] |= mod->m_xabilities[i];
+		if (mod->m_xabilities[i]!=0)
+		{
+			m_event_mask |= Event::DATA_ABILITIES;
+		}
 	}
 
 	// Flags mit OR hinzufuegen
 	m_base_attr_mod.m_special_flags |= mod->m_xspecial_flags;
 	m_base_attr_mod.m_immunity |= mod->m_ximmunity;
+	
+	if (mod->m_xspecial_flags!=0)
+	{
+		m_event_mask |= Event::DATA_FLAGS;
+	}
 
 	// Wenn add == true in die Liste der wirksamen Modifikationen aufnehmen
 	if (mod->m_time!=0 && add)
@@ -3559,6 +3682,20 @@
 	m_base_attr_mod.m_attack_speed -=mod->m_dattack_speed;
 	m_base_attr_mod.m_max_health -= mod->m_dstrength*5;
 	m_base_attr_mod.m_attack_speed -= mod->m_ddexterity*3;
+	
+	// Modifikationen feststellen
+	if (mod->m_dwalk_speed!=0)
+	{
+		m_event_mask |= Event::DATA_WALK_SPEED;
+	}
+	if (mod->m_dattack_speed !=0)
+	{
+		m_event_mask |= Event::DATA_ATTACK_SPEED;
+	}
+	if (mod->m_dmax_health !=0)
+	{
+		m_event_mask |= Event::DATA_MAX_HP;
+	}
 
 	for (i=0;i<4;i++)
 	{
@@ -3571,12 +3708,18 @@
 	for (i=0;i<6;i++)
 	{
 		if ( mod->m_xabilities[i]!=0)
+		{
 			ret = true;
+			m_event_mask |= Event::DATA_ABILITIES;
+		}
 	}
 
 	// Wenn Flags veraendert wurden neu berechnen
 	if (mod->m_xspecial_flags!=0)
+	{
+		m_event_mask |= Event::DATA_FLAGS;
 		ret = true;
+	}
 
 	if( mod->m_ximmunity!=0)
 		ret = true;
@@ -3788,6 +3931,22 @@
 	
 	cv->toBuffer(getBaseAttrMod()->m_special_flags);
 	
+	cv->toBuffer(getBaseAttr()->m_step_length);
+	cv->toBuffer(getBaseAttrMod()->m_attack_speed);
+	cv->toBuffer(getBaseAttrMod()->m_walk_speed);
+	cv->toBuffer(m_timer1);
+	cv->toBuffer(m_timer1_max);
+	cv->toBuffer(m_timer2);
+	cv->toBuffer(m_timer2_max);
+	for (int i=0; i<6; i++)
+	{
+		cv->toBuffer(getBaseAttrMod()->m_abilities[i]);	
+	}
+
+	cv->toBuffer(getMoveInfo()->m_speed_x);
+	cv->toBuffer(getMoveInfo()->m_speed_y);
+		
+
 }
 
 void Creature::fromString(CharConv* cv)
@@ -3830,6 +3989,20 @@
 	
 	cv->fromBuffer(getBaseAttrMod()->m_special_flags);
 	
+	cv->fromBuffer(getBaseAttr()->m_step_length);
+	cv->fromBuffer(getBaseAttrMod()->m_attack_speed);
+	cv->fromBuffer(getBaseAttrMod()->m_walk_speed);
+	cv->fromBuffer(m_timer1);
+	cv->fromBuffer(m_timer1_max);
+	cv->fromBuffer(m_timer2);
+	cv->fromBuffer(m_timer2_max);
+	for (int i=0; i<6; i++)
+	{
+		cv->fromBuffer(getBaseAttrMod()->m_abilities[i]);	
+	}
+	
+	cv->fromBuffer(getMoveInfo()->m_speed_x);
+	cv->fromBuffer(getMoveInfo()->m_speed_y);
 }
 
 bool Creature::checkAbility(Action::ActionType at)
@@ -3899,3 +4072,254 @@
 	return 0;
 }
 
+
+void Creature::writeEvent(Event* event, CharConv* cv)
+{
+	if (event->m_data & Event::DATA_COMMAND)
+	{
+		m_command.toString(cv);
+	}
+	
+	if (event->m_data & Event::DATA_ACTION)
+	{
+		m_action.toString(cv);
+		cv->toBuffer(getGeometry()->m_shape.m_coordinate_x);
+		cv->toBuffer(getGeometry()->m_shape.m_coordinate_y);
+		
+
+		if (m_action.m_type!=0)
+			DEBUG5("sending action: %i at %f %f, dir %f %f",m_action.m_type, getGeometry()->m_shape.m_coordinate_x,	getGeometry()->m_shape.m_coordinate_y, getMoveInfo()->m_speed_x,getMoveInfo()->m_speed_y);
+	}
+	
+	if (event->m_data & Event::DATA_HP)
+	{
+		cv->toBuffer(getDynAttr()->m_health);
+	}
+	
+	if (event->m_data & Event::DATA_MAX_HP)
+	{
+		cv->toBuffer(getBaseAttrMod()->m_max_health);
+	}
+	
+	if (event->m_data & Event::DATA_EFFECTS)
+	{
+		for (int i=0;i<NR_EFFECTS;i++)
+		{
+			cv->toBuffer(m_dyn_attr.m_effect_time[i]);
+		}
+	}
+
+	if (event->m_data & Event::DATA_STATUS_MODS)
+	{
+		char c=0;
+		for (int i=0;i<NR_STATUS_MODS;i++)
+		{
+			if (m_dyn_attr.m_status_mod_time[i]>0)
+			{
+				c |= (1 <<i );
+			}
+		}
+		cv->toBuffer(c);
+		
+		for (int i=0;i<NR_STATUS_MODS;i++)
+		{
+			if (m_dyn_attr.m_status_mod_time[i]>0)
+			{
+				cv->toBuffer(m_dyn_attr.m_status_mod_time[i]);
+			}	
+		}
+	}
+	
+	if (event->m_data & Event::DATA_TIMER)
+	{
+		cv->toBuffer(m_timer1_max);
+		cv->toBuffer(m_timer2_max);
+	}
+	
+	if (event->m_data & Event::DATA_STATE)
+	{
+		cv->toBuffer((char) getState());
+	}
+	
+	if (event->m_data & Event::DATA_WALK_SPEED)
+	{
+		cv->toBuffer(getBaseAttrMod()->m_walk_speed);
+	}
+	
+	if (event->m_data & Event::DATA_ATTACK_SPEED)
+	{
+		cv->toBuffer(getBaseAttrMod()->m_attack_speed);
+	}
+	
+	if (event->m_data & Event::DATA_NEXT_COMMAND)
+	{
+		m_next_command.toString(cv);
+	}
+	
+	if (event->m_data & Event::DATA_ABILITIES)
+	{
+		for (int i=0; i<6; i++)
+		{
+			cv->toBuffer(getBaseAttrMod()->m_abilities[i]);	
+		}	
+	}
+	
+	if (event->m_data & Event::DATA_FLAGS )
+	{
+		cv->toBuffer(getBaseAttrMod()->m_special_flags);
+	}
+	
+	if (event->m_data & Event::DATA_EXPERIENCE)
+	{
+		cv->toBuffer(getDynAttr()->m_experience);
+	}
+	
+	if (event->m_data & Event::DATA_MOVE_INFO)
+	{
+		cv->toBuffer(getMoveInfo()->m_speed_x);	
+		cv->toBuffer(getMoveInfo()->m_speed_y);	
+	}
+	
+	if (event->m_data & Event::DATA_LEVEL)
+	{
+		cv->toBuffer(getBaseAttr()->m_level);	
+	}
+}
+
+
+void Creature::processEvent(Event* event, CharConv* cv)
+{
+	DEBUG5("object %i processing Event %i data %i",getId(),event->m_type, event->m_data);
+	if (event->m_data & Event::DATA_COMMAND)
+	{
+		m_command.fromString(cv);
+		DEBUG5("got Command %i",m_command.m_type);
+	}
+	
+	char tmp = m_action.m_type;
+	float posx = getGeometry()->m_shape.m_coordinate_x;
+	float posy = getGeometry()->m_shape.m_coordinate_y;
+	float movex = getMoveInfo()->m_speed_x;
+	float movey = getMoveInfo()->m_speed_y;
+	
+	
+	if (event->m_data & Event::DATA_ACTION)
+	{
+		
+		
+		m_action.fromString(cv);
+		
+		float x,y;
+		cv->fromBuffer(x);
+		cv->fromBuffer(y);
+		moveTo(x,y);
+		if (m_action.m_type!=0)
+			DEBUG5("new Action %i at %f %f",m_action.m_type,x,y);
+	}
+	
+	
+	
+	if (event->m_data & Event::DATA_HP)
+	{
+		cv->fromBuffer(getDynAttr()->m_health);
+	}
+	
+	if (event->m_data & Event::DATA_MAX_HP)
+	{
+		cv->fromBuffer(getBaseAttrMod()->m_max_health);
+	}
+	
+	if (event->m_data & Event::DATA_EFFECTS)
+	{
+		for (int i=0;i<NR_EFFECTS;i++)
+		{
+			cv->fromBuffer(m_dyn_attr.m_effect_time[i]);
+		}
+	}
+
+	if (event->m_data & Event::DATA_STATUS_MODS)
+	{
+		char ctmp;
+		cv->fromBuffer<char>(ctmp);
+		for (int i=0;i<NR_STATUS_MODS;i++)
+		{
+			if (ctmp & (1 <<i ))
+			{
+				cv->fromBuffer<float>(m_dyn_attr.m_status_mod_time[i]);
+			}
+		}
+	}
+	
+	if (event->m_data & Event::DATA_TIMER)
+	{
+		cv->fromBuffer(m_timer1_max);
+		cv->fromBuffer(m_timer2_max);
+		m_timer1 = m_timer1_max;
+		m_timer2 = m_timer2_max;
+			
+	}
+	
+	if (event->m_data & Event::DATA_STATE)
+	{
+		State oldstate = getState();
+		char ctmp;
+		cv->fromBuffer(ctmp);
+		
+		if (oldstate != STATE_DIEING && oldstate != STATE_DEAD && (ctmp==STATE_DIEING || ctmp == STATE_DEAD))
+		{
+			die();
+		}
+		setState((State) ctmp);
+		DEBUG5("object %i changed state from %i to %i",getId(),oldstate,ctmp);
+		
+		
+	}
+	
+	if (event->m_data & Event::DATA_WALK_SPEED)
+	{
+		cv->fromBuffer(getBaseAttrMod()->m_walk_speed);
+	}
+	
+	if (event->m_data & Event::DATA_ATTACK_SPEED)
+	{
+		cv->fromBuffer(getBaseAttrMod()->m_attack_speed);
+	}
+	
+	if (event->m_data & Event::DATA_NEXT_COMMAND)
+	{
+		m_next_command.fromString(cv);
+	}
+	
+	if (event->m_data & Event::DATA_ABILITIES)
+	{
+		for (int i=0; i<6; i++)
+		{
+			cv->fromBuffer(getBaseAttrMod()->m_abilities[i]);	
+		}	
+	}
+	
+	if (event->m_data & Event::DATA_FLAGS )
+	{
+		cv->fromBuffer(getBaseAttrMod()->m_special_flags);
+	}
+	
+	if (event->m_data & Event::DATA_EXPERIENCE)
+	{
+		cv->fromBuffer(getDynAttr()->m_experience);
+	}
+	
+	if (event->m_data & Event::DATA_MOVE_INFO)
+	{
+		cv->fromBuffer(getMoveInfo()->m_speed_x);	
+		cv->fromBuffer(getMoveInfo()->m_speed_y);
+		DEBUG5("old action: %i at %f %f, dir %f %f",tmp,posx,posy,movex,movey);
+		DEBUG5("received action: %i at %f %f, dir %f %f",m_action.m_type, getGeometry()->m_shape.m_coordinate_x,	getGeometry()->m_shape.m_coordinate_y, getMoveInfo()->m_speed_x,getMoveInfo()->m_speed_y);
+	}
+	
+	if (event->m_data & Event::DATA_LEVEL)
+	{
+		cv->fromBuffer(getBaseAttr()->m_level);	
+	}
+}
+
+
--- a/src/core/creature.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/creature.h	Sun Sep 21 21:58:33 2008 +0000
@@ -430,7 +430,19 @@
 	void collisionDetection(float time);
 	
 	
+	/**
+	 * \fn virtual void writeEvent(Event* event, CharConv* cv)
+	 * \brief Schreibt die Daten zu einem Event in den Bitstream
+	 * \param event Event das beschrieben wird
+	 * \param cv Bitstream
+	 */
+	virtual void writeEvent(Event* event, CharConv* cv);
 	
+	/**
+	 * \fn virtual void processEvent(Event* event, CharConv* cv)
+	 * \brief Fuehrt die Wirkung eines Events auf das Objekt aus. Weitere Daten werden aus dem Bitstream gelesen
+	 */
+	virtual void processEvent(Event* event, CharConv* cv);
 	
 			
 
--- a/src/core/dmgprojectile.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/dmgprojectile.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -169,63 +169,67 @@
 				if (m_timer >= m_timer_limit)
 				{
 					m_state = DESTROYED;
-					Shape s;
-					s.m_coordinate_x = x;
-					s.m_coordinate_y = y;
-					s.m_type = Shape::CIRCLE;
-					s.m_radius = m_geometry.m_radius;
-
-					// Alle Objekte im Explosionsradius suchen
-					hitobj.clear();
-					m_world->getSWObjectsInShape(&s,m_region,&hitobj,getGeometry()->m_layer,WorldObject::CREATURE,0);
-					for (i=hitobj.begin();i!=hitobj.end();++i)
+					
+					if (m_world->isServer())
 					{
-						// Schaden austeilen
+						Shape s;
+						s.m_coordinate_x = x;
+						s.m_coordinate_y = y;
+						s.m_type = Shape::CIRCLE;
+						s.m_radius = m_geometry.m_radius;
+	
+						// Alle Objekte im Explosionsradius suchen
+						hitobj.clear();
+						m_world->getSWObjectsInShape(&s,m_region,&hitobj,getGeometry()->m_layer,WorldObject::CREATURE,0);
+						for (i=hitobj.begin();i!=hitobj.end();++i)
+						{
+							// Schaden austeilen
 							(*i)->takeDamage(&m_damage);
-					}
-
-					if (m_flags & MULTI_EXPLODES)
-					{
-						// Flag mehrfach explodierend gesetzt
-						DEBUG("multiexploding");
-						d= 1/sqrt(sqr(m_speed_x)+sqr(m_speed_y));
-						dir[0] = m_speed_x * d;
-						dir[1] = m_speed_y * d;
-
-						// Schaden halbieren
-						Damage dmg;
-						memcpy(&dmg,&m_damage,sizeof(Damage));
-						for (int i=0;i<4;i++)
+						}
+	
+						if (m_flags & MULTI_EXPLODES)
 						{
-							dmg.m_multiplier[i] *= 0.5;
+							// Flag mehrfach explodierend gesetzt
+							DEBUG("multiexploding");
+							d= 1/sqrt(sqr(m_speed_x)+sqr(m_speed_y));
+							dir[0] = m_speed_x * d;
+							dir[1] = m_speed_y * d;
+	
+							// Schaden halbieren
+							Damage dmg;
+							memcpy(&dmg,&m_damage,sizeof(Damage));
+							for (int i=0;i<4;i++)
+							{
+								dmg.m_multiplier[i] *= 0.5;
+							}
+	
+							// vier neue Projektile erzeugen
+							DmgProjectile* pr;
+							pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
+							memcpy(pr->getDamage(),&dmg,sizeof(Damage));
+							pr->setFlags(DmgProjectile::EXPLODES);
+							pr->setMaxRadius(1);
+							m_world->insertProjectile(pr,x+dir[0]*s.m_radius,y+dir[1]*s.m_radius,m_region);
+	
+							pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
+							memcpy(pr->getDamage(),&dmg,sizeof(Damage));
+							pr->setFlags(DmgProjectile::EXPLODES);
+							pr->setMaxRadius(1);
+							m_world->insertProjectile(pr,x-dir[1]*s.m_radius,y+dir[0]*s.m_radius,m_region);
+	
+							pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
+							memcpy(pr->getDamage(),&dmg,sizeof(Damage));
+							pr->setFlags(DmgProjectile::EXPLODES);
+							pr->setMaxRadius(1);
+							m_world->insertProjectile(pr,x-dir[0]*s.m_radius,y-dir[1]*s.m_radius,m_region);
+	
+							pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
+							memcpy(pr->getDamage(),&dmg,sizeof(Damage));
+							pr->setFlags(DmgProjectile::EXPLODES);
+							pr->setMaxRadius(1);
+							m_world->insertProjectile(pr,x+dir[1]*s.m_radius,y-dir[0]*s.m_radius,m_region);
+	
 						}
-
-						// vier neue Projektile erzeugen
-						DmgProjectile* pr;
-						pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
-						memcpy(pr->getDamage(),&dmg,sizeof(Damage));
-						pr->setFlags(DmgProjectile::EXPLODES);
-						pr->setMaxRadius(1);
-						m_world->insertProjectile(pr,x+dir[0]*s.m_radius,y+dir[1]*s.m_radius,m_region);
-
-						pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
-						memcpy(pr->getDamage(),&dmg,sizeof(Damage));
-						pr->setFlags(DmgProjectile::EXPLODES);
-						pr->setMaxRadius(1);
-						m_world->insertProjectile(pr,x-dir[1]*s.m_radius,y+dir[0]*s.m_radius,m_region);
-
-						pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
-						memcpy(pr->getDamage(),&dmg,sizeof(Damage));
-						pr->setFlags(DmgProjectile::EXPLODES);
-						pr->setMaxRadius(1);
-						m_world->insertProjectile(pr,x-dir[0]*s.m_radius,y-dir[1]*s.m_radius,m_region);
-
-						pr = new DmgProjectile(m_world,m_type,m_creator_fraction, m_world->getValidProjectileId());
-						memcpy(pr->getDamage(),&dmg,sizeof(Damage));
-						pr->setFlags(DmgProjectile::EXPLODES);
-						pr->setMaxRadius(1);
-						m_world->insertProjectile(pr,x+dir[1]*s.m_radius,y-dir[0]*s.m_radius,m_region);
-
 					}
 				}
 				break;
@@ -255,7 +259,9 @@
 					m_geometry.m_radius -= 2* dtime/(m_timer_limit);
 				}
 				if (m_timer >= m_timer_limit)
+				{
 						m_state = DESTROYED;
+				}
 
 
 
@@ -448,6 +454,7 @@
 				m_speed_x=newdir[0];
 				m_speed_y=newdir[1];
 			}
+			m_event_mask |= Event::DATA_SPEED;
 		}
 		hitobj.clear();
 		
@@ -513,7 +520,10 @@
 				m_state = DESTROYED;
 				m_timer=0;
 			}
-			hit->takeDamage(&m_damage);
+			if (m_world->isServer())
+			{
+				hit->takeDamage(&m_damage);
+			}
 
 		}
 		else
@@ -535,6 +545,8 @@
 
 			m_timer=0;
 			m_timer_limit=200;
+			
+			m_event_mask |= Event::DATA_PROJ_STATE | Event::DATA_TYPE | Event::DATA_MAX_RADIUS;
 		}
 
 		// true, wenn das Projektil zu einem weiteren Ziel weiterspringt
@@ -542,7 +554,7 @@
 		if (m_flags & BOUNCING)
 			bounce = true;
 
-		if (m_flags & PROB_BOUNCING)
+		if (m_flags & PROB_BOUNCING && m_world->isServer())
 		{
 			// zufaelliges weiterspringen, Chance 50%
 			if (rand()<RAND_MAX*0.5)
@@ -621,6 +633,7 @@
 				m_speed_x = dir[0] *speed;
 				m_speed_y = dir[1] *speed;
 
+				m_event_mask |= Event::DATA_SPEED;
 
 				DEBUG5("koord %f %f to %f %f",xnew,ynew,x2,y2);
 				DEBUG5("dir %f %f",dir[0],dir[1]);
@@ -677,7 +690,7 @@
 	// Radius erhoehen
 	m_geometry.m_radius += m_max_radius* dtime/(m_timer_limit);
 
-	if (m_type == FIRE_WAVE || m_type == ICE_RING)
+	if ((m_type == FIRE_WAVE || m_type == ICE_RING) && m_world->isServer())
 	{
 		// Schaden an die neu getroffenen Lebewesen austeilen
 		rnew = m_geometry.m_radius;
@@ -743,6 +756,8 @@
 			m_timer =0;
 			m_timer_limit=5000;
 			m_state = STABLE;
+			
+			m_event_mask |= Event::DATA_PROJ_STATE | Event::DATA_PROJ_TIMER;
 		}
 	}
 
@@ -765,7 +780,7 @@
 	float x2,y2;
 	DmgProjectile* pr;
 
-	if (m_timer >= m_timer_limit)
+	if (m_timer >= m_timer_limit && m_world->isServer())
 	{
 		// Timer Limit erreicht
 		m_state = DESTROYED;
@@ -894,6 +909,7 @@
 			m_timer =0;
 			m_timer_limit=200;
 			m_state = VANISHING;
+			m_event_mask |= Event::DATA_PROJ_STATE | Event::DATA_PROJ_TIMER;
 		}
 
 		if (m_type == LIGHTNING || m_type ==LIGHT_BEAM  || m_type ==ELEM_EXPLOSION || m_type ==ACID || m_type ==DIVINE_BEAM  || m_type ==HYPNOSIS)
@@ -913,5 +929,130 @@
 }
 
 
+void DmgProjectile::toString(CharConv* cv)
+{
+	cv->toBuffer((char) m_type);
+	cv->toBuffer((char) m_creator_fraction);
+	cv->toBuffer( m_id);
+	cv->toBuffer((char) m_state);
+	cv->toBuffer(m_geometry.m_coordinate_x);
+	cv->toBuffer(m_geometry.m_coordinate_y);
+	cv->toBuffer(m_geometry.m_radius);
+	cv->toBuffer(m_geometry.m_angle);
+	cv->toBuffer(m_geometry.m_layer);
+	cv->toBuffer(m_timer);
+	cv->toBuffer(m_timer_limit);
+	cv->toBuffer(m_speed_x);
+	cv->toBuffer(m_speed_y);
+	cv->toBuffer(m_flags);
+	cv->toBuffer(m_max_radius);
+	cv->toBuffer(m_goal_object);
+
+}
+
+void DmgProjectile::fromString(CharConv* cv)
+{
+	// Typ, Fraktion und ID werden schon vorher eingelesen..
+	
+	char tmp;
+	cv->fromBuffer<char>(tmp);
+	m_state = (ProjectileState) tmp;
+	cv->fromBuffer<float>(m_geometry.m_coordinate_x);
+	cv->fromBuffer<float>(m_geometry.m_coordinate_y);
+	cv->fromBuffer<float>(m_geometry.m_radius);
+	cv->fromBuffer<float>(m_geometry.m_angle);
+	cv->fromBuffer<short>(m_geometry.m_layer);
+	cv->fromBuffer<float>(m_timer);
+	cv->fromBuffer<float>(m_timer_limit);
+	cv->fromBuffer(m_speed_x);
+	cv->fromBuffer(m_speed_y);
+	cv->fromBuffer(m_flags);
+	cv->fromBuffer(m_max_radius);
+	cv->fromBuffer(m_goal_object);
+}
+
+void DmgProjectile::writeEvent(Event* event, CharConv* cv)
+{
+	if (event->m_data & Event::DATA_SPEED)
+	{
+		cv->toBuffer(m_geometry.m_coordinate_x);
+		cv->toBuffer(m_geometry.m_coordinate_y);
+		cv->toBuffer(m_speed_x);
+		cv->toBuffer(m_speed_y);
+	}
+	
+	if (event->m_data & Event::DATA_PROJ_STATE)
+	{
+		cv->toBuffer((char) m_state);
+	}
+	
+	if (event->m_data & Event::DATA_GOAL_OBJECT)
+	{
+		cv->toBuffer(m_goal_object);
+	}
+	
+	if (event->m_data & Event::DATA_TYPE)
+	{
+		cv->toBuffer((char) m_type);
+	}
+	
+	if (event->m_data & Event::DATA_PROJ_TIMER)
+	{
+		cv->toBuffer(m_timer_limit);
+	}
+	
+	if (event->m_data & Event::DATA_MAX_RADIUS)
+	{
+		cv->toBuffer(m_max_radius);
+		cv->toBuffer<float>(m_geometry.m_radius);
+	}
+}
+
+void DmgProjectile::processEvent(Event* event, CharConv* cv)
+{
+	if (event->m_data & Event::DATA_SPEED)
+	{
+		cv->fromBuffer(m_geometry.m_coordinate_x);
+		cv->fromBuffer(m_geometry.m_coordinate_y);
+		cv->fromBuffer(m_speed_x);
+		cv->fromBuffer(m_speed_y);
+		
+		if (m_speed_y!=0 || m_speed_x !=0)
+		{
+			m_geometry.m_angle = atan2(m_speed_y,m_speed_x);
+		}
+	}
+	
+	if (event->m_data & Event::DATA_PROJ_STATE)
+	{
+		char ctmp;
+		cv->fromBuffer(ctmp);
+		m_state = (ProjectileState) ctmp;
+	}
+	
+	if (event->m_data & Event::DATA_GOAL_OBJECT)
+	{
+		cv->fromBuffer(m_goal_object);
+	}
+	
+	if (event->m_data & Event::DATA_TYPE)
+	{
+		char ctmp;
+		cv->fromBuffer(ctmp);
+		m_type = (ProjectileType) ctmp;
+	}
+	
+	if (event->m_data & Event::DATA_PROJ_TIMER)
+	{
+		cv->fromBuffer(m_timer_limit);
+		m_timer =0;
+	}
+	
+	if (event->m_data & Event::DATA_MAX_RADIUS)
+	{
+		cv->fromBuffer(m_max_radius);
+		cv->fromBuffer<float>(m_geometry.m_radius);
+	}
+}
 
 
--- a/src/core/dmgprojectile.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/dmgprojectile.h	Sun Sep 21 21:58:33 2008 +0000
@@ -7,6 +7,7 @@
 #include "worldobject.h"
 #include <algorithm>
 #include <math.h>
+#include "event.h"
 
 class World;
 class ServerWObject;
@@ -149,6 +150,37 @@
 		m_goal_object = id;
 	}
 	
+	/**
+	 * \fn void toString(CharConv* cv)
+	 * \brief Konvertiert das Objekt in einen String und schreibt ihn in der Puffer
+	 * \param buf Ausgabepuffer
+	 * \return Zeiger hinter den beschriebenen Datenbereich
+	 */
+	virtual void toString(CharConv* cv);
+			
+			
+	/**
+	 * \fn void fromString(CharConv* cv)
+	 * \brief Erzeugt das Objekt aus einem String
+	 * \param buf Objekt als String
+	 * \return Zeiger hinter den gelesenen Datenbereich
+	 */
+	virtual void fromString(CharConv* cv);
+	
+	/**
+	 * \fn virtual void writeEvent(Event* event, CharConv* cv)
+	 * \brief Schreibt die Daten zu einem Event in den Bitstream
+	 * \param event Event das beschrieben wird
+	 * \param cv Bitstream
+	 */
+	virtual void writeEvent(Event* event, CharConv* cv);
+	
+	/**
+	 * \fn virtual void processEvent(Event* event, CharConv* cv)
+	 * \brief Fuehrt die Wirkung eines Events auf das Objekt aus. Weitere Daten werden aus dem Bitstream gelesen
+	 */
+	virtual void processEvent(Event* event, CharConv* cv);
+	
 	
 	private:
 		
--- a/src/core/gridunit.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/gridunit.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -198,7 +198,7 @@
 	}
 
 	// Objekt nicht gefunden, Fehler anzeigen
-	ERRORMSG("Object %s not found ind group %i",object->getNameId().c_str(),g);
+	ERRORMSG("Object %s not found in group %i",object->getNameId().c_str(),g);
 	return false;
 
 }
--- a/src/core/monster.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/monster.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -171,6 +171,8 @@
 		cmd->m_goal_coordinate_y = m_ai.m_command.m_goal_coordinate_y;
 		cmd->m_goal_object_id = m_ai.m_command.m_goal_object_id;
 		cmd->m_range = m_ai.m_command.m_range;
+		
+		m_event_mask |= Event::DATA_COMMAND;
 
 	}
 	else
@@ -340,60 +342,62 @@
 
 void Monster::die()
 {
-	DEBUG("die");
-	Geometry* geom = getGeometry();
-	//Zeiger auf letzten Angreifer per ID  holen
-
-	int id = getDynAttr()->m_last_attacker_id;
-	//schauen ob dieser noch lebt, wenn ja gainExperience bei ihm aufrufen mit der _experience dieser Instanz
-
-	// Object per ID von der World holen
-	ServerWObject* object;
-	object = getWorld()->getSWObject(id,getGridLocation()->m_region);
-
-	if (object!=0)
+	DEBUG5("die");	
+	if (getWorld()->isServer())
 	{
-		if (object->getState() == STATE_ACTIVE && object->getTypeInfo()->m_type==TypeInfo::TYPE_PLAYER)
+		Geometry* geom = getGeometry();
+		//Zeiger auf letzten Angreifer per ID  holen
+	
+		int id = getDynAttr()->m_last_attacker_id;
+		//schauen ob dieser noch lebt, wenn ja gainExperience bei ihm aufrufen mit der _experience dieser Instanz
+	
+		// Object per ID von der World holen
+		ServerWObject* object;
+		object = getWorld()->getSWObject(id,getGridLocation()->m_region);
+	
+		if (object!=0)
 		{
-			Creature* pl = (Creature*) object;
-
-			// Für Erfahrungspunkte bitte noch eine vernünftige Formel einfallen lassen...
-			//pl->gainExperience((int) ceil(pow(1.5,getLevel()-1)*4));
-			// Verteilen der Exp auf Spieler in der Nähe
-			// TODO: XP nur auf spieler in der Party verteilen
-
-			pl->gainExperience((int) ceil(pow(1.5,min(pl->getBaseAttrMod()->m_level,getBaseAttr()->m_level)-1)*2));
-
-			list<ServerWObject*> ret;
-			Shape s;
-			s.m_type = Shape::CIRCLE;
-			s.m_radius = 20;
-			s.m_coordinate_x = geom->m_shape.m_coordinate_x;
-			s.m_coordinate_y = geom->m_shape.m_coordinate_y;
-
-			getWorld()->getSWObjectsInShape(&s, getGridLocation()->m_region, &ret, Geometry::LAYER_AIR, CREATURE);
-
-			list<ServerWObject*>::iterator i;
-			
-			for (i=ret.begin();i!=ret.end();i++)
+			if (object->getState() == STATE_ACTIVE && object->getTypeInfo()->m_type==TypeInfo::TYPE_PLAYER)
 			{
-				pl = (Creature*) (*i);
-				pl->gainExperience((int) ceil(pow(1.5,getBaseAttr()->m_level-1)*2/ret.size()));
+				Creature* pl = (Creature*) object;
+	
+				// Für Erfahrungspunkte bitte noch eine vernünftige Formel einfallen lassen...
+				//pl->gainExperience((int) ceil(pow(1.5,getLevel()-1)*4));
+				// Verteilen der Exp auf Spieler in der Nähe
+				// TODO: XP nur auf spieler in der Party verteilen
+	
+				pl->gainExperience((int) ceil(pow(1.5,min(pl->getBaseAttrMod()->m_level,getBaseAttr()->m_level)-1)*2));
+	
+				list<ServerWObject*> ret;
+				Shape s;
+				s.m_type = Shape::CIRCLE;
+				s.m_radius = 20;
+				s.m_coordinate_x = geom->m_shape.m_coordinate_x;
+				s.m_coordinate_y = geom->m_shape.m_coordinate_y;
+	
+				getWorld()->getSWObjectsInShape(&s, getGridLocation()->m_region, &ret, Geometry::LAYER_AIR, CREATURE);
+	
+				list<ServerWObject*>::iterator i;
+				
+				for (i=ret.begin();i!=ret.end();i++)
+				{
+					pl = (Creature*) (*i);
+					pl->gainExperience((int) ceil(pow(1.5,getBaseAttr()->m_level-1)*2/ret.size()));
+				}
+	
 			}
-
+		}
+	
+		ServerItem* si;
+		for (int i=0;i<4;i++)
+		{
+			si = ItemFactory::createItem(m_drop_slots[i]);
+			if (si!=0)
+			{
+				getRegion()->dropItem(si,getGeometry()->m_shape.m_coordinate_x,getGeometry()->m_shape.m_coordinate_y);
+			}
 		}
 	}
-
-	ServerItem* si;
-	for (int i=0;i<4;i++)
-	{
-		si = ItemFactory::createItem(m_drop_slots[i]);
-		if (si!=0)
-		{
-			getRegion()->dropItem(si,getGeometry()->m_shape.m_coordinate_x,getGeometry()->m_shape.m_coordinate_y);
-		}
-	}
-
 	Creature::die();
 }
 
--- a/src/core/networkstruct.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/networkstruct.h	Sun Sep 21 21:58:33 2008 +0000
@@ -62,7 +62,7 @@
  /**
   * \brief Normale Daten vom Server zum Client
   */
-	PTYPE_S2C_DATA ,
+	PTYPE_S2C_EVENT ,
  
  /**
   * \brief Kommando vom Client zum Server
--- a/src/core/player.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/player.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -173,7 +173,6 @@
 					com->m_goal_object_id = command->m_id;
 					com->m_range = 0.5;
 					DEBUG5("action range %f",getCommand()->m_range);
-
 				}
 						/*
 				if (wo->getObjectType().getObjectType()==OBJECTTYPE_TRADER)
@@ -205,6 +204,7 @@
 					
 					meleedir = true;
 				}
+				m_event_mask |= Event::DATA_NEXT_COMMAND;
 			}
 		}
 		else
@@ -323,6 +323,7 @@
 		}
 	}
 	
+	m_event_mask |= Event::DATA_NEXT_COMMAND;
 	DEBUG5("resulting command %i goal %f %f id %i",com->m_type,com->m_goal_coordinate_x,com->m_goal_coordinate_y, com->m_goal_object_id);
 }
 
@@ -622,10 +623,12 @@
 			getBaseAttr()->m_strength++;
 			getBaseAttr()->m_max_health += 5;
 			getDynAttr()->m_health +=5;
+			m_event_mask |= Event::DATA_HP | Event::DATA_MAX_HP;
 			break;
 		case (CreatureBaseAttr::DEXTERITY):
 			getBaseAttr()->m_dexterity++;
 			getBaseAttr()->m_attack_speed +=3;
+			m_event_mask |= Event::DATA_ATTACK_SPEED;
 			break;
 		case (CreatureBaseAttr::WILLPOWER):
 			getBaseAttr()->m_willpower++;
@@ -640,6 +643,8 @@
 
 void Player::gainLevel()
 {
+	Creature::gainLevel();
+	
 	// Level um 1 erhöhen
 	getBaseAttr()->m_level++;
 
@@ -671,6 +676,7 @@
 	// Schaden neu berechnen
 	recalcDamage();
 
+	m_event_mask |= Event::DATA_LEVEL | Event::DATA_HP | Event::DATA_MAX_HP | Event::DATA_EXPERIENCE;
 }
 
 
@@ -1440,6 +1446,11 @@
 		{
 			getBaseAttrMod()->m_attack_speed += si->m_weapon_attr ->m_dattack_speed;
 			getBaseAttrMod()->m_attack_range = si->m_weapon_attr ->m_attack_range;
+			
+			if (si->m_weapon_attr ->m_dattack_speed!=0)
+			{
+				m_event_mask |= Event::DATA_ATTACK_SPEED;
+			}
 		}
 	}
 
@@ -1538,17 +1549,7 @@
 	cv->toBuffer((char*) m_name.c_str(),32);
 	
 	cv->toBuffer(getBaseAttr()->m_level);
-	cv->toBuffer(getBaseAttr()->m_step_length);
-	cv->toBuffer(getBaseAttrMod()->m_attack_speed);
-	cv->toBuffer(getBaseAttrMod()->m_walk_speed);
-	cv->toBuffer(m_timer1);
-	cv->toBuffer(m_timer1_max);
-	cv->toBuffer(m_timer2);
-	cv->toBuffer(m_timer2_max);
-	for (int i=0; i<6; i++)
-	{
-		cv->toBuffer(getBaseAttrMod()->m_abilities[i]);	
-	}
+	
 		
 
 	/*
@@ -1578,17 +1579,7 @@
 	m_name = tmp;
 	
 	cv->fromBuffer(getBaseAttr()->m_level);
-	cv->fromBuffer(getBaseAttr()->m_step_length);
-	cv->fromBuffer(getBaseAttrMod()->m_attack_speed);
-	cv->fromBuffer(getBaseAttrMod()->m_walk_speed);
-	cv->fromBuffer(m_timer1);
-	cv->fromBuffer(m_timer1_max);
-	cv->fromBuffer(m_timer2);
-	cv->fromBuffer(m_timer2_max);
-	for (int i=0; i<6; i++)
-	{
-		cv->fromBuffer(getBaseAttrMod()->m_abilities[i]);	
-	}
+	
 	
 }
 
--- a/src/core/projectile.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/projectile.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -16,40 +16,5 @@
 	m_id = id;
 }
 
-void Projectile::toString(CharConv* cv)
-{
-
-	cv->toBuffer((char) m_type);
-	cv->toBuffer((char) m_state);
-	cv->toBuffer( m_id);
-	cv->toBuffer(m_geometry.m_coordinate_x);
-	cv->toBuffer(m_geometry.m_coordinate_y);
-	cv->toBuffer(m_geometry.m_radius);
-	cv->toBuffer(m_geometry.m_angle);
-	cv->toBuffer(m_geometry.m_layer);
-	cv->toBuffer(m_timer);
-	cv->toBuffer(m_timer_limit);
-
-}
-
-void Projectile::fromString(CharConv* cv)
-{
-	
-	char tmp;
-	cv->fromBuffer<char>(tmp);
-	m_type = (ProjectileType) tmp;
-	cv->fromBuffer<char>(tmp);
-	m_state = (ProjectileState) tmp;
-	cv->fromBuffer<int>(m_id);
-	cv->fromBuffer<float>(m_geometry.m_coordinate_x);
-	cv->fromBuffer<float>(m_geometry.m_coordinate_y);
-	cv->fromBuffer<float>(m_geometry.m_radius);
-	cv->fromBuffer<float>(m_geometry.m_angle);
-	cv->fromBuffer<short>(m_geometry.m_layer);
-	cv->fromBuffer<float>(m_timer);
-	cv->fromBuffer<float>(m_timer_limit);
-		
-
-}
 
 
--- a/src/core/projectile.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/projectile.h	Sun Sep 21 21:58:33 2008 +0000
@@ -161,22 +161,7 @@
 	}
 	
 	
-	/**
-	 * \fn void toString(CharConv* cv)
-	 * \brief Konvertiert das Objekt in einen String und schreibt ihn in der Puffer
-	 * \param buf Ausgabepuffer
-	 * \return Zeiger hinter den beschriebenen Datenbereich
-	 */
-	virtual void toString(CharConv* cv);
-			
-			
-	/**
-	 * \fn void fromString(CharConv* cv)
-	 * \brief Erzeugt das Objekt aus einem String
-	 * \param buf Objekt als String
-	 * \return Zeiger hinter den gelesenen Datenbereich
-	 */
-	virtual void fromString(CharConv* cv);
+	
 	
 	/**
 	 * \fn int getId()
@@ -187,6 +172,22 @@
 		return m_id;
 	}
 	
+	/**
+	 * \fn int getEventMask()
+	 * \brief Gibt die Bitmaske der Events aus#
+	 */
+	int getEventMask()
+	{
+		return m_event_mask;
+	}
+	
+	/**
+	 * \fn void clearEventMask()
+	 */
+	void clearEventMask()
+	{
+		m_event_mask =0;
+	}
 	
 	/**
 	 * \fn virtual void update()
@@ -239,6 +240,12 @@
 	  */
 	 int m_id;
 	 
+	 /**
+	  * \var int m_event_mask
+	  * \brief Bitmaske mit den beim aktuellen updaten aufgetretenen Events
+	  */
+	 int m_event_mask;
+	 
 
 };
 
--- a/src/core/region.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/region.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -2,7 +2,7 @@
 #include "world.h"
 
 
-Region::Region(short dimx, short dimy, short id)
+Region::Region(short dimx, short dimy, short id, World* world, bool server)
 {
 	DEBUG5("creating region");
 	m_data_grid = new Matrix2d<Gridunit>(dimx,dimy);
@@ -25,6 +25,12 @@
 	m_drop_items = new map<int,DropItem*>;
 	
 	m_id = id;
+	
+	m_events = new list<Event>;
+	
+	m_server = server;
+	
+	m_world = world;
 }
 
 Region::~Region()
@@ -61,6 +67,9 @@
 	delete m_data_grid;
 	delete m_tiles;
 	delete m_drop_items;
+	
+	delete m_events;
+	
 }
 
 ServerWObject* Region::getSWObject ( int id)
@@ -83,6 +92,26 @@
 	}
 }
 
+DmgProjectile* Region::getProjectile(int id)
+{
+	map<int,DmgProjectile*>::iterator iter;
+	
+	// Objekt im Binärbaum suchen
+	iter = m_projectiles->find(id);
+	
+	// Testen ob ein Objekt gefunden wurde
+	if (iter == m_projectiles->end())
+	{
+		// keins gefunden, NULL ausgeben
+		return 0;
+	}
+	else
+	{
+		// Zeiger auf Objekt ausgeben
+		return iter->second;
+	}
+}
+
 bool Region::getFreePlace(Shape* shape, short layer, float& x, float&y)
 {
 	// Menge der bereits getesteten Felder
@@ -537,14 +566,7 @@
 bool Region::insertSWObject (ServerWObject* object, float x, float y)
 {
 	bool result = true;
-	if (object->getTypeInfo()->m_type == WorldObject::TypeInfo::TYPE_PLAYER)
-	{
-		DEBUG5("player entered Region");
-		result &= (m_players->insert(make_pair(object->getId(),object))).second;
-		
-		// Daten der Region zum Server senden
-		//object->setState(WorldObject::STATE_REGION_ENTERED);
-	}
+	
 	
 	object->getGridLocation()->m_region = m_id;
 	 
@@ -561,7 +583,26 @@
 	 
 	 // Wenn das Element bereits existiert ist die Antwort false
 	if (result==false)
+	{
 		return result;
+	}
+	
+	if (object->getTypeInfo()->m_type == WorldObject::TypeInfo::TYPE_PLAYER)
+	{
+		DEBUG5("player entered Region");
+		result &= (m_players->insert(make_pair(object->getId(),object))).second;
+		
+		// Daten der Region zum Server senden
+		//object->setState(WorldObject::STATE_REGION_ENTERED);
+	}
+	else
+	{
+		// fuer Nicht Spieler Event erzeugen, dass das Objekt erschaffen wurde
+		Event event;
+		event.m_type = Event::OBJECT_CREATED;
+		event.m_id = object->getId();
+		insertEvent(event);	
+	}
 	 
 	 // Koordinaten setzen
 	object->getGeometry()->m_shape.m_coordinate_x=x;
@@ -601,6 +642,13 @@
 	object->getGeometry()->m_coordinate_x = x;
 	object->getGeometry()->m_coordinate_y = y;
 	object->setRegion( m_id);
+	
+	// Event erzeugen: neues Projektil in der Region
+	Event event;
+	event.m_type = Event::PROJECTILE_CREATED;
+	event.m_id = object->getId();
+	insertEvent(event);
+	
 	return true;
 }
 
@@ -693,7 +741,7 @@
 	 
 	int x = object->getGridLocation()->m_grid_x;
 	int y = object->getGridLocation()->m_grid_y;
-	DEBUG("changing object in grid tile %i %i",x,y);
+	DEBUG5("changing object in grid tile %i %i",x,y);
 	 
 	Gridunit *gu = (m_data_grid->ind(x,y));
 	result = gu->moveObject(object,group);
@@ -703,6 +751,16 @@
 	
 }
 
+void Region::deleteProjectile(DmgProjectile* proj)
+{
+	int id = proj->getId();
+	
+	if (m_projectiles->count(id)!=0)
+	{
+		m_projectiles->erase(m_projectiles->find(id));
+	}
+}
+
 void Region::update(float time)
 {
 	DEBUG5("\nUpdate aller WeltObjekte starten\n");
@@ -711,7 +769,23 @@
 	map<int,ServerWObject*>::iterator iter;
 	ServerWObject* object;
 	WorldObject::Geometry* wob;
-		 
+	map<int,DmgProjectile*>::iterator it3;
+	
+	
+	// alle bisherigen Events loeschen
+	m_events->clear();
+	
+	// alle Eventsmasken loeschen
+	for (iter =m_objects->begin(); iter!=m_objects->end(); ++iter)
+	{
+		iter->second->clearEventMask();
+	}
+	
+	for (it3 = m_projectiles->begin(); it3 !=m_projectiles->end();++it3)
+	{
+		it3->second->clearEventMask();
+	}
+	
 	// Durchmustern aller ServerWObjects
 	for (iter =m_objects->begin(); iter!=m_objects->end(); )
 	{
@@ -720,13 +794,25 @@
 		DEBUG5("\nObjekt: %f %f key: %i layer %x",wob->m_shape.m_coordinate_x,wob->m_shape.m_coordinate_y ,object->getId(),object->getGeometry()->m_layer);	
 		if (object->getDestroyed()==true)
 		{
-			
-			DEBUG5("Objekt gelöscht: %i \n",object->getId());
-			object->destroy();
-			deleteSWObject(object);
-			delete object;
-			m_objects->erase(iter++);
-			continue;
+			// Objekte selbststaendig loeschen darf nur der Server
+			if (m_server)
+			{
+				DEBUG5("Objekt gelöscht: %i \n",object->getId());
+				Event event;
+				event.m_type = Event::OBJECT_DESTROYED;
+				event.m_id = object->getId();
+				insertEvent(event);
+				
+				++iter;
+				object->destroy();
+				deleteSWObject(object);
+				delete object;
+				continue;
+			}
+			else
+			{
+				++iter;
+			}
 		}
 		else
 		{
@@ -739,7 +825,6 @@
 	DEBUG5("Update aller WeltObjekte abgeschlossen\n\n");
 	
 	// alle Projektile updaten
-	map<int,DmgProjectile*>::iterator it3;
 	DmgProjectile* pr =0;
 	
 	for (it3 = m_projectiles->begin(); it3 !=m_projectiles->end();)
@@ -747,10 +832,23 @@
 		pr = (it3->second);
 		if (pr->getState() == Projectile::DESTROYED)
 		{
-			DEBUG5("deleting projectile %p",pr);
-			m_projectiles->erase(it3++);
-			delete pr;
-			DEBUG5("loesche projektil");
+			// Projektile selbststaendig loeschen darf nur der Server
+			if (m_server)
+			{
+				Event event;
+				event.m_type = Event::PROJECTILE_DESTROYED;
+				event.m_id = pr->getId();
+				insertEvent(event);
+				
+				DEBUG5("deleting projectile %p",pr);
+				m_projectiles->erase(it3++);
+				delete pr;
+				DEBUG5("loesche projektil");
+			}
+			else
+			{
+			 	++it3;
+			}
 			
 		}
 		else
@@ -760,6 +858,43 @@
 		}
 	}
 	DEBUG5("update projektile abgeschlossen");
+	
+	if (m_server)
+	{
+		// Events fuer geaenderte Objekte / Projektile erzeugen
+		for (iter =m_objects->begin(); iter!=m_objects->end(); ++iter)
+		{
+			object = iter->second;
+			
+			// Events durch Spieler werden global behandelt, daher hier nicht beruecksichtigen
+			if (object->getTypeInfo()->m_type == WorldObject::TypeInfo::TYPE_PLAYER)
+			{
+				continue;
+			}
+			
+			if (object->getEventMask() !=0)
+			{
+				Event event;
+				event.m_type = Event::OBJECT_STAT_CHANGED;
+				event.m_data = object->getEventMask();
+				event.m_id = object->getId();
+				insertEvent(event);
+			}
+		}
+		
+		for (it3 = m_projectiles->begin(); it3 !=m_projectiles->end();++it3)
+		{
+			pr = (it3->second);
+			if (pr->getEventMask() !=0)
+			{
+				Event event;
+				event.m_type = Event::PROJECTILE_STAT_CHANGED;
+				event.m_data = pr->getEventMask();
+				event.m_id = pr->getId();
+				insertEvent(event);
+			}
+		}
+	}
 }
 
 void Region::getRegionData(CharConv* cv)
@@ -805,8 +940,86 @@
 		DEBUG5("object: %s",(jt->second)->getNameId().c_str());
 	}
 	
+	// Anzahl der Projektile eintragen
+	cv->toBuffer<short>((short) m_projectiles->size());
+	DEBUG("projectiles: %i",m_projectiles->size());
+	
+	// Projektile in den Puffer eintragen
+	map<int,DmgProjectile*>::iterator kt;
+	for (kt = m_projectiles->begin(); kt != m_projectiles->end(); ++kt)
+	{
+		kt->second->toString(cv);	
+	}
+	
+}
+
+
+void Region::createObjectFromString(CharConv* cv, map<int,ServerWObject*>* players)
+{
+	char type;
+	char subt[11];
+	subt[10] ='\0';
+	int id;
+	
+	ServerWObject* obj;
+	float x,y;
 	
 	
+	DEBUG5("read offset: %i",cv->getBitStream()->GetReadOffset());
+
+	cv->fromBuffer(type);
+	cv->fromBuffer(subt,10);
+	cv->fromBuffer(id);
+		
+	DEBUG5("object %s id %i",subt,id);
+		
+		// alle Objekte ausser den Spielern werden neu angelegt
+		// die Spieler existieren schon
+	if (type != WorldObject::TypeInfo::TYPE_PLAYER)
+	{
+		obj = ObjectFactory::createObject((WorldObject::TypeInfo::ObjectType) type, std::string(subt),id);
+	}
+	else
+	{
+		if (players->count(id) ==0)
+		{
+			ERRORMSG("player (%s) with id %i does not exist",subt,id);
+		}
+		obj = (*players)[id];
+	}
+		
+	obj->fromString(cv);
+		
+	x = obj->getGeometry()->m_shape.m_coordinate_x;
+	y = obj->getGeometry()->m_shape.m_coordinate_y;
+		
+		
+	insertSWObject(obj,x,y);
+}
+
+
+void Region::createProjectileFromString(CharConv* cv)
+{
+	
+	char type,frac;
+	int id;
+	DmgProjectile* proj;
+	float x,y;
+	
+	cv->fromBuffer(type);
+	cv->fromBuffer(frac);
+	cv->fromBuffer(id);
+	
+	DEBUG5("new projectile %i frac %i id %i",type,frac,id);
+		
+	proj = new DmgProjectile(m_world, (Projectile::ProjectileType) type, (WorldObject::TypeInfo::Fraction) frac, id);
+		
+	proj->fromString(cv);
+		
+	x = proj->getGeometry()->m_coordinate_x;
+	y = proj->getGeometry()->m_coordinate_y;
+		
+	insertProjectile(proj,x,y);
 }
 
 void Region::setRegionData(CharConv* cv,map<int,ServerWObject*>* players)
@@ -833,35 +1046,6 @@
 	}
 	m_static_objects->clear();
 	
-	char type;
-	char subt[11];
-	subt[10] ='\0';
-	int id;
-	
-	// statische Objekte einlesen
-	short nr_stat;
-	cv->fromBuffer<short>(nr_stat);
-	DEBUG("static objects: %i",nr_stat);
-	
-	ServerWObject* obj;
-	float x,y;
-	for (int i=0; i<nr_stat;i++)
-	{
-		cv->fromBuffer(type);
-		cv->fromBuffer(subt,10);
-		cv->fromBuffer(id);
-		
-		obj = ObjectFactory::createObject((WorldObject::TypeInfo::ObjectType) type, std::string(subt),id);
-			
-		obj->fromString(cv);
-		
-		x = obj->getGeometry()->m_shape.m_coordinate_x;
-		y = obj->getGeometry()->m_shape.m_coordinate_y;
-		
-		insertSWObject(obj,x,y);
-		
-	}
-		
 	// alle bisherigen nichtstatischen Objekte entfernen
 	// die SpielerObjekte bleiben erhalten, alle anderen werden geloescht
 	map<int,ServerWObject*>::iterator jt;
@@ -877,6 +1061,18 @@
 	m_objects->clear();
 	m_players->clear();
 	
+	// statische Objekte einlesen
+	short nr_stat;
+	cv->fromBuffer<short>(nr_stat);
+	DEBUG("static objects: %i",nr_stat);
+	
+	for (int i=0; i<nr_stat;i++)
+	{
+		createObjectFromString(cv,players);
+	}
+		
+	
+	
 	// neue Objekte einlesen
 	short nr_nonstat;
 	cv->fromBuffer<short>(nr_nonstat);
@@ -884,37 +1080,7 @@
 	
 	for (int i=0; i<nr_nonstat;i++)
 	{
-		DEBUG5("read offset: %i",cv->getBitStream()->GetReadOffset());
-
-		cv->fromBuffer(type);
-		cv->fromBuffer(subt,10);
-		cv->fromBuffer(id);
-		
-		DEBUG("object %s id %i",subt,id);
-		
-		// alle Objekte ausser den Spielern werden neu angelegt
-		// die Spieler existieren schon
-		if (type != WorldObject::TypeInfo::TYPE_PLAYER)
-		{
-			obj = ObjectFactory::createObject((WorldObject::TypeInfo::ObjectType) type, std::string(subt),id);
-		}
-		else
-		{
-			if (players->count(id) ==0)
-			{
-				ERRORMSG("player (%s) with id %i does not exist",subt,id);
-			}
-			obj = (*players)[id];
-		}
-		
-		obj->fromString(cv);
-		
-		x = obj->getGeometry()->m_shape.m_coordinate_x;
-		y = obj->getGeometry()->m_shape.m_coordinate_y;
-		
-		
-		insertSWObject(obj,x,y);
-		
+		createObjectFromString(cv,players);
 	}
 	
 	/*
@@ -930,8 +1096,21 @@
 		DEBUG("%s id %i at %f %f",mt->second->getTypeInfo()->m_subtype.c_str(),mt->second->getId(), mt->second->getGeometry()->m_shape.m_coordinate_x,mt->second->getGeometry()->m_shape.m_coordinate_y);
 	}
 	*/
+	
+	// Anzahl der Projektile einlesen
+	short nr_proj;
+	cv->fromBuffer<short>(nr_proj);
+	DEBUG("projectiles: %i",nr_proj);
+	// Projektile einlesen
+	for (int i=0; i<nr_proj;i++)
+	{
+		createProjectileFromString(cv);
+	}
+	
 }
 
+
+
 void Region::setTile(Tile tile,short x, short y)
 {
 	*(m_tiles->ind(x,y)) = (char) tile;
--- a/src/core/region.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/region.h	Sun Sep 21 21:58:33 2008 +0000
@@ -5,6 +5,7 @@
 #include "serverwobject.h"
 #include "tiles.h"
 #include "dropitem.h"
+#include "event.h"
 
 
 #include <string>
@@ -49,12 +50,12 @@
 {
 	public:
 		/**
-	 	 * \fn Region(short dimx, short dimy, short id)
+		 * \fn Region(short dimx, short dimy, short id, bool server)
 		 * \brief Konstruktor
 		 * \param dimx Ausdehnung in x-Richtung
 	 	 * \param dimy Ausdehnung in y-Richtung
 	 	 */
-		Region(short dimx, short dimy, short id);
+		Region(short dimx, short dimy, short id, World* world, bool server);
 		
 		
 		/**
@@ -185,6 +186,12 @@
 		bool  insertProjectile(DmgProjectile* object, float x, float y);
 		
 		/**
+		 * \fn DmgProjectile* getProjectile(int id)
+		 * \brief Gibt das Projektil mit der angegebenen ID aus
+		 */
+		DmgProjectile* getProjectile(int id);
+		
+		/**
 		 * \fn deleteServerWObject(ServerWObject* object)
 		 * \brief L&ouml;scht ServerWObject
 		 * \param object Zeiger auf das Objekt, welches gel&ouml;scht werden soll
@@ -206,6 +213,26 @@
 		bool moveSWObject(ServerWObject* object, float x, float y);
 		
 		/**
+		 * \fn void createObjectFromString(CharConv* cv, map<int,ServerWObject*>* players)
+		 * \brief liest die Daten zu einem Objekt aus dem Bitstream und erzeugt es
+		 * \param cv Bitstream aus dem die Daten gelesen werden
+		 * \param players Spielerdaten (Spieler werden nicht neu erzeugt sondern nur in die Region verschoben)
+		 */
+		void createObjectFromString(CharConv* cv, map<int,ServerWObject*>* players);
+		
+		/**
+		 * \fn void createProjectileFromString(CharConv* cv)
+		 * \brief liest die Daten zu einem Projektil aus dem Bitstream und erzeugt es
+		 */
+		void createProjectileFromString(CharConv* cv);
+		
+		/**
+		 * \fn void deleteProjectile(DmgProjectile* proj)
+		 * \brief Entfernt das Projektil aus der Region
+		 */
+		void deleteProjectile(DmgProjectile* proj);
+		
+		/**
 		 * \fn update(float time)
 		 * \brief Lässt für alle Objekte in der Welt die angegebene Zeitspanne verstreichen
 		 * \param time Zeit um die in der Welt vergeht in Millisekunden
@@ -296,10 +323,30 @@
 			return m_drop_items;
 		}
 		
+		/**
+		 * \fn map<int,DmgProjectile*>* getProjectiles()
+		 */
 		map<int,DmgProjectile*>* getProjectiles()
 		{
 			return m_projectiles;
 		}
+		
+		/**
+		 * \fn void insertEvent(Event &event)
+		 * \brief Fuegt ein neues Event in die Eventliste ein
+		 */
+		void insertEvent(Event &event)
+		{
+			m_events->push_back(event);
+		}
+		
+		/**
+		 * \fn list<Event>* getEvents()
+		 */
+		list<Event>* getEvents()
+		{
+			return m_events;
+		}
 				
 	private:
 	/**
@@ -368,6 +415,24 @@
 	 */
 	short m_id;
 	
+	/**
+	 * \var std::queue<Event> m_events
+	 * \brief Liste der lokalen Events beim aktuellen update
+	 */
+	list<Event>* m_events;
+	
+	/**
+	 * \var bool m_server
+	 * \brief true, wenn der Rechner der Server ist
+	 */
+	bool m_server;
+	
+	/**
+	 * \var World* m_world
+	 * \brief Zeiger auf die Welt
+	 */
+	World* m_world;
+	
 };
 
 #include "gridunit.h"
--- a/src/core/serverwobject.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/serverwobject.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -61,7 +61,7 @@
 
 bool  ServerWObject::destroy()
 {
-	DEBUG("destroy");
+	DEBUG5("destroy");
 	return true;
 }
 
--- a/src/core/serverwobject.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/serverwobject.h	Sun Sep 21 21:58:33 2008 +0000
@@ -23,6 +23,7 @@
 #include <string>
 #include "worldobject.h"
 #include "damage.h"
+#include "event.h"
 
 class World;
 class Region;
@@ -203,8 +204,49 @@
 	virtual void takeDamage(Damage* damage)
 	{
 	}
+	
+	/**
+	 * \fn virtual void writeEvent(Event* event, CharConv* cv)
+	 * \brief Schreibt die Daten zu einem Event in den Bitstream
+	 * \param event Event das beschrieben wird
+	 * \param cv Bitstream
+	 */
+	virtual void writeEvent(Event* event, CharConv* cv)
+	{
+	}
+	
+	/**
+	 * \fn virtual void processEvent(Event* event, CharConv* cv)
+	 * \brief Fuehrt die Wirkung eines Events auf das Objekt aus. Weitere Daten werden aus dem Bitstream gelesen
+	 */
+	virtual void processEvent(Event* event, CharConv* cv)
+	{
+	}
+	
+	/**
+	 * \fn int getEventMask()
+	 * \brief Gibt die Bitmaske der Events aus#
+	 */
+	int getEventMask()
+	{
+		return m_event_mask;
+	}
+	
+	/**
+	 * \fn void clearEventMask()
+	 */
+	void clearEventMask()
+	{
+		m_event_mask =0;
+	}
 
-	
+	protected:
+		
+		/**
+		* \var int m_event_mask
+		* \brief Bitmaske mit den Events die das Objekt seit dem letzten Update erlebt hat
+		*/
+		int m_event_mask;
 
 //Private stuff
 private:
@@ -233,6 +275,8 @@
 	 * \brief Zeiger auf das World Objekt, in dem das aktuelle Objekt eingeordnet ist
 	 */
 	World* m_world;
+	
+	
 };
 
 #include "world.h"
--- a/src/core/world.cpp	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/world.cpp	Sun Sep 21 21:58:33 2008 +0000
@@ -53,6 +53,8 @@
 		 m_regions[i]=0;
 	 
 	 m_local_player =0;
+	 
+	 m_events = new list<Event>;
 	
 }
 
@@ -103,7 +105,7 @@
 	}
 	else if(type==2)
 	{
-		Region* reg = new Region(25,25,region);
+		Region* reg = new Region(25,25,region,this, m_server);
 		short rid = insertRegion(reg,region);
 
 
@@ -326,6 +328,7 @@
 	delete[] m_parties; 
 	delete m_player_slots;
 	delete m_players;
+	delete m_events;
 }	
 
 
@@ -932,8 +935,16 @@
 			}
 			else
 			{
-				// anderer Spieler wurde in unbekannte Region eingefuegt, ignorieren
-				player->setState(WorldObject::STATE_INACTIVE);
+				if (data_missing != 0)
+				{
+					// Region unbekannt, ignorieren
+					player->setState(WorldObject::STATE_INACTIVE);
+				}
+				else
+				{
+					// Spieler in die Region einfuegen
+					player->setState(WorldObject::STATE_ENTER_REGION);	
+				}
 			}
 		
 		}
@@ -950,6 +961,16 @@
 		insertSWObject(player, x,y,region);
 		player->setState(WorldObject::STATE_ACTIVE);
 		
+		if (m_server)
+		{
+			Event event;
+			event.m_type = Event::PLAYER_CHANGED_REGION;
+			event.m_id = player->getId();
+			event.m_data =region ;
+			
+			insertEvent(event);
+		}
+		
 	}
 }
 
@@ -1008,6 +1029,7 @@
 		pl->getGeometry()->m_shape.m_coordinate_y = 11;
 		
 		insertPlayerIntoRegion(pl,pl->getGridLocation()->m_region);
+		
 
 		if (m_server)
 		{
@@ -1135,6 +1157,8 @@
 
 void World::update(float time)
 {
+	m_events->clear();
+	
 	DEBUG5("update %f",time);
 	for (int i=0;i<WORLD_MAX_REGIONS;i++)
 	{
@@ -1234,7 +1258,7 @@
 		}
 		
 		
-		if (m_server && slot != -1)
+		if (m_server && slot != LOCAL_SLOT)
 		{
 			// Nachrichten fuer die Spieler abholen und Verteilen
 			PackageHeader headerp;
@@ -1280,6 +1304,21 @@
 			}
 		}
 		
+		if (m_server)
+		{
+			// Events fuer die Spieler generieren
+			if (pl->getEventMask() !=0)
+			{
+				Event event;
+				event.m_type = Event::OBJECT_STAT_CHANGED;
+				event.m_data = pl->getEventMask();
+				event.m_id = pl->getId();
+				insertEvent(event);	
+				
+				pl->clearEventMask();
+			}
+		}
+		
 	}
 	
 	if (!m_server)
@@ -1295,6 +1334,7 @@
 			Packet* data;
 			CharConv* cv;
 			
+			// Nachrichten vom Server empfangen
 			while (m_network->numberSlotMessages()>0)
 			{
 				m_network->popSlotMessage( data ,slot);
@@ -1355,7 +1395,7 @@
 					// Region anlegen wenn sie noch nicht existiert
 					if (m_regions[headerp.m_number] ==0)
 					{
-						m_regions[headerp.m_number] = new Region(dimx,dimy,headerp.m_number);	
+						m_regions[headerp.m_number] = new Region(dimx,dimy,headerp.m_number,this,m_server);	
 					}
 					
 					// Daten schreiben
@@ -1375,12 +1415,213 @@
 					insertPlayer(m_local_player, LOCAL_SLOT);
 				}
 				
+				if (headerp.m_content == PTYPE_S2C_EVENT)
+				{
+					Region* reg = m_local_player->getRegion();
+					
+					for (int n=0; n< headerp.m_number;n++)
+					{
+						processEvent(reg,cv);
+					}
+
+				}
+				
 				delete cv;
 			}
+		
+		}
+	}
+	
+	
+	if (m_server)
+	{
+		// Nachrichten ueber die Events zur den Clients senden
+		short nr_events;
+		Region* reg;
+		list<Event>::iterator lt;
+		for (it = m_player_slots->begin(); it != m_player_slots->end(); ++it)
+		{
+			slot = it->first;
+			pl = static_cast<Player*>(it->second);
+			
+			if (slot != LOCAL_SLOT)
+			{
+				// Anzahl der Events
+				nr_events = m_events->size();
+				reg = pl->getRegion();
+				if (pl->getState() != WorldObject::STATE_ACTIVE && pl->getState() != WorldObject::STATE_DEAD && pl->getState() != WorldObject::STATE_DIEING)
+				{
+					reg =0;
+				}
+				
+				if (reg !=0)
+				{
+					nr_events += reg->getEvents()->size();
+				}
+				
+				CharConv msg;
+				PackageHeader header;
+				header.m_content = PTYPE_S2C_EVENT;
+				header.m_number =nr_events;
+				
+				header.toString(&msg);
+				
+				// globale Events
+				for (lt = m_events->begin(); lt != m_events->end(); ++lt)
+				{
+					writeEvent(reg,&(*lt),&msg);
+				}
+				
+				// Events der Region in der der Spieler ist
+				if (reg !=0)
+				{
+					for (lt = reg->getEvents()->begin(); lt != reg->getEvents()->end(); ++lt)
+					{
+						writeEvent(reg,&(*lt),&msg);
+					}
+				}
+				
+				m_network->pushSlotMessage(msg.getBitStream(),slot);
+				
+			}
+		}
+		
+		
+	}
+}
+
+void World::writeEvent(Region* region,Event* event, CharConv* cv)
+{
+	event->toString(cv);
+	
+	DEBUG5("sending event %i  id %i  data %i",event->m_type, event->m_id, event->m_data);
+	
+	
+	ServerWObject* object;
+	DmgProjectile* proj;
+	if (event->m_type == Event::OBJECT_CREATED)
+	{
+		object =region->getSWObject(event->m_id);
+		object->toString(cv);
+	}
+	
+	if (event->m_type == Event::OBJECT_STAT_CHANGED)
+	{
+		object =region->getSWObject(event->m_id);
+		object->writeEvent(event,cv);
+	}
+	
+	if (event->m_type == Event::PROJECTILE_CREATED)
+	{
+		proj = region->getProjectile(event->m_id);
+		proj->toString(cv);
+	}
+	
+	if (event->m_type == Event::PROJECTILE_STAT_CHANGED)
+	{
+		proj = region->getProjectile(event->m_id);
+		proj->writeEvent(event,cv);
+	}
+	
+	if (event->m_type == Event::PLAYER_CHANGED_REGION)
+	{
+		object = (*m_players)[event->m_id];
+		cv->toBuffer(object->getGeometry()->m_shape.m_coordinate_x);
+		cv->toBuffer(object->getGeometry()->m_shape.m_coordinate_y);
+				
+	}
+}
+
+
+void World::processEvent(Region* region,CharConv* cv)
+{
+	Event event;
+	event.fromString(cv);
+	
+	DEBUG5("got event %i  id %i  data %i",event.m_type, event.m_id, event.m_data);
+	
+	ServerWObject* object;
+	DmgProjectile* proj;
+	
+	if (event.m_type == Event::OBJECT_CREATED)
+	{
+		region->createObjectFromString(cv, m_players);
+	}
+	
+	if (event.m_type == Event::OBJECT_STAT_CHANGED)
+	{
+		object =region->getSWObject(event.m_id);
+		if (object !=0)
+		{
+		
+			object->processEvent(&event,cv);
+		}
+		else
+		{
+			// Event erhalten zu dem kein Objekt gehoert
+			DEBUG("object %i for event does not exist",event.m_id);
+		}
+	}
+	
+	if (event.m_type == Event::OBJECT_DESTROYED)
+	{
+		object =region->getSWObject(event.m_id);
+		if (object !=0)
+		{
+			object->destroy();
+			region->deleteSWObject(object);
+			delete object;
+		}
+		else
+		{
+			// Event erhalten zu dem kein Objekt gehoert
+		}
+	}
+	
+	if (event.m_type == Event::PROJECTILE_CREATED)
+	{
+		region->createProjectileFromString(cv);
+	}
+	
+	if (event.m_type == Event::PROJECTILE_STAT_CHANGED)
+	{
+		proj = region->getProjectile(event.m_id);
+		if (proj !=0)
+		{
+			proj->processEvent(&event,cv);
+		}
+	}
+	
+	if (event.m_type == Event::PROJECTILE_DESTROYED)
+	{
+		proj = region->getProjectile(event.m_id);
+		if (proj != 0)
+		{
+			region->deleteProjectile(proj);
+			delete proj;
+		}
+		
+	}
+	
+	if (event.m_type == Event::PLAYER_CHANGED_REGION)
+	{
+		if (m_players->count (event.m_id)>0)
+		{
+			object = (*m_players)[event.m_id];
+			
+			cv->fromBuffer(object->getGeometry()->m_shape.m_coordinate_x);
+			cv->fromBuffer(object->getGeometry()->m_shape.m_coordinate_y);
+			
+			// Lokaler Spieler wird schon vorher in die Region eingefuegt
+			if (object != m_local_player)
+			{
+				insertPlayerIntoRegion(object,event.m_data);
+			}
 		}
 	}
 }
 
+
 void World::handleDataRequest(ClientDataRequest* request, int slot )
 {
 	// Spieler von dem die Anfrage ausging
--- a/src/core/world.h	Sat Sep 20 15:43:41 2008 +0000
+++ b/src/core/world.h	Sun Sep 21 21:58:33 2008 +0000
@@ -29,6 +29,7 @@
 #include <cstdlib>
 #include <algorithm>
 #include <iostream>
+#include <queue>
 
 #include "serverwobject.h"
 #include "dmgprojectile.h"
@@ -40,6 +41,7 @@
 #include "party.h"
 #include "itemfactory.h"
 #include "objectfactory.h"
+#include "event.h"
 
 /**
  * \def WORLD_MAX_REGIONS
@@ -354,6 +356,23 @@
 	 * \brief Aktualisiert die Spielerobjekte
 	 */
 	void updatePlayers();
+	
+	/**
+	 * \fn void writeEvent(Region* region, Event* event, CharConv* cv)
+	 * \brief Schreib die Daten zu dem Event in den Bitstream
+	 * \param region Region in der das Event aufgetreten ist
+	 * \param event Event das geschrieben wird
+	 * \param cv Bitstream zum Schreiben
+	 */
+	void writeEvent(Region* region, Event* event, CharConv* cv);
+	
+	/**
+	 * \fn void processEvent(CharConv* cv)
+	 * \brief Liest ein Event aus dem Bitstream und fuehrt es aus
+	 * \param region Region in der das Event aufgetreten ist
+	 * \param cv Bitstream
+	 */
+	void processEvent(Region* region,CharConv* cv);
 
 	/**
 	 * \fn void calcBlockArray(PathfindInfo* p)
@@ -459,8 +478,23 @@
 	 */
 	void handleDataRequest(ClientDataRequest* request, int slot  = LOCAL_SLOT);
 
-	// debug only
-
+	/**
+	 * \fn void insertEvent(Event &event)
+	 * \brief Fuegt ein neues Event in die Eventliste ein
+	 */
+	void insertEvent(Event &event)
+	{
+		m_events->push_back(event);
+	}
+	
+	/**
+	 * \fn bool isServer()
+	 * \brief gibt true aus, wenn die Welt der Server ist
+	 */
+	bool isServer()
+	{
+		return m_server;
+	}
 
 //Private stuff
 private:
@@ -527,5 +561,11 @@
 	 * \brief Liste der Spieler die sich gerade einloggen wollen
 	 */
 	list<int> m_logins;
+	
+	/**
+	 * \var list<Event> m_events
+	 * \brief Liste der globalen Events beim aktuellen update
+	 */
+	list<Event>* m_events;
 };
 #endif //WORLD_H