Mercurial > sumwars
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öscht ServerWObject * \param object Zeiger auf das Objekt, welches gelö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