00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "net/tmwserv/beinghandler.h"
00023
00024 #include "net/tmwserv/protocol.h"
00025
00026 #include "net/messagein.h"
00027
00028 #include "being.h"
00029 #include "beingmanager.h"
00030 #include "game.h"
00031 #include "localplayer.h"
00032 #include "log.h"
00033 #include "main.h"
00034 #include "npc.h"
00035 #include "particle.h"
00036 #include "sound.h"
00037
00038 #include "gui/ok_dialog.h"
00039
00040 #include "utils/gettext.h"
00041
00042 #include "net/tmwserv/gameserver/player.h"
00043
00044 namespace TmwServ {
00045
00046 BeingHandler::BeingHandler()
00047 {
00048 static const Uint16 _messages[] = {
00049 GPMSG_BEING_ATTACK,
00050 GPMSG_BEING_ENTER,
00051 GPMSG_BEING_LEAVE,
00052 GPMSG_BEINGS_MOVE,
00053 GPMSG_BEINGS_DAMAGE,
00054 GPMSG_BEING_ACTION_CHANGE,
00055 GPMSG_BEING_LOOKS_CHANGE,
00056 GPMSG_BEING_DIR_CHANGE,
00057 0
00058 };
00059 handledMessages = _messages;
00060 }
00061
00062 void BeingHandler::handleMessage(MessageIn &msg)
00063 {
00064 switch (msg.getId())
00065 {
00066 case GPMSG_BEING_ENTER:
00067 handleBeingEnterMessage(msg);
00068 break;
00069 case GPMSG_BEING_LEAVE:
00070 handleBeingLeaveMessage(msg);
00071 break;
00072 case GPMSG_BEINGS_MOVE:
00073 handleBeingsMoveMessage(msg);
00074 break;
00075 case GPMSG_BEING_ATTACK:
00076 handleBeingAttackMessage(msg);
00077 break;
00078 case GPMSG_BEINGS_DAMAGE:
00079 handleBeingsDamageMessage(msg);
00080 break;
00081 case GPMSG_BEING_ACTION_CHANGE:
00082 handleBeingActionChangeMessage(msg);
00083 break;
00084 case GPMSG_BEING_LOOKS_CHANGE:
00085 handleBeingLooksChangeMessage(msg);
00086 break;
00087 case GPMSG_BEING_DIR_CHANGE:
00088 handleBeingDirChangeMessage(msg);
00089 break;
00090 }
00091 }
00092
00093 static void handleLooks(Player *being, MessageIn &msg)
00094 {
00095
00096 static int const nb_slots = 4;
00097 static int const slots[nb_slots] =
00098 { Being::WEAPON_SPRITE, Being::HAT_SPRITE, Being::TOPCLOTHES_SPRITE,
00099 Being::BOTTOMCLOTHES_SPRITE };
00100
00101 int mask = msg.readInt8();
00102
00103 if (mask & (1 << 7))
00104 {
00105
00106 for (int i = 0; i < nb_slots; ++i)
00107 {
00108 being->setSprite(slots[i], 0);
00109 }
00110 }
00111
00112
00113 for (int i = 0; i < nb_slots; ++i)
00114 {
00115 if (!(mask & (1 << i))) continue;
00116 int id = msg.readInt16();
00117 being->setSprite(slots[i], id);
00118 }
00119 }
00120
00121 void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
00122 {
00123 int type = msg.readInt8();
00124 int id = msg.readInt16();
00125 Being::Action action = (Being::Action)msg.readInt8();
00126 int px = msg.readInt16();
00127 int py = msg.readInt16();
00128 Being *being;
00129
00130 switch (type)
00131 {
00132 case OBJECT_PLAYER:
00133 {
00134 std::string name = msg.readString();
00135 if (player_node->getName() == name)
00136 {
00137 being = player_node;
00138 being->setId(id);
00139 }
00140 else
00141 {
00142 being = beingManager->createBeing(id, Being::PLAYER, 0);
00143 being->setName(name);
00144 }
00145 Player *p = static_cast< Player * >(being);
00146 int hs = msg.readInt8(), hc = msg.readInt8();
00147 p->setHairStyle(hs, hc);
00148 p->setGender(msg.readInt8() == GENDER_MALE ?
00149 GENDER_MALE : GENDER_FEMALE);
00150 handleLooks(p, msg);
00151 } break;
00152
00153 case OBJECT_MONSTER:
00154 case OBJECT_NPC:
00155 {
00156 int subtype = msg.readInt16();
00157 being = beingManager->createBeing(id, type == OBJECT_MONSTER ?
00158 Being::MONSTER : Being::NPC, subtype);
00159 std::string name = msg.readString();
00160 if (name.length() > 0) being->setName(name);
00161 } break;
00162
00163 default:
00164 return;
00165 }
00166
00167 being->setPosition(px, py);
00168 being->setDestination(px, py);
00169 being->setAction(action);
00170 }
00171
00172 void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
00173 {
00174 Being *being = beingManager->findBeing(msg.readInt16());
00175 if (!being)
00176 return;
00177
00178 beingManager->destroyBeing(being);
00179 }
00180
00181 void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
00182 {
00183 while (msg.getUnreadLength())
00184 {
00185 int id = msg.readInt16();
00186 int flags = msg.readInt8();
00187 Being *being = beingManager->findBeing(id);
00188 int sx = 0;
00189 int sy = 0;
00190 int dx = 0;
00191 int dy = 0;
00192 int speed = 0;
00193
00194 printf("handleBeingsMoveMessage for %p (%s | %s)\n",
00195 (void*) being,
00196 (flags & MOVING_POSITION) ? "pos" : "",
00197 (flags & MOVING_DESTINATION) ? "dest" : "");
00198
00199 if (flags & MOVING_POSITION)
00200 {
00201 Uint16 sx2, sy2;
00202 msg.readCoordinates(sx2, sy2);
00203 sx = sx2 * 32 + 16;
00204 sy = sy2 * 32 + 16;
00205 speed = msg.readInt8();
00206 }
00207 if (flags & MOVING_DESTINATION)
00208 {
00209 dx = msg.readInt16();
00210 dy = msg.readInt16();
00211 if (!(flags & MOVING_POSITION))
00212 {
00213 sx = dx;
00214 sy = dy;
00215 }
00216 }
00217 if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
00218 {
00219 continue;
00220 }
00221 if (speed)
00222 {
00223
00224
00225
00226
00227
00228 const float tilesPerSecond = 100.0f / speed;
00229 being->setWalkSpeed((int) (tilesPerSecond * 32));
00230 }
00231
00232
00233 if (being == player_node)
00234 continue;
00235
00236
00237 if (being->getType() == Being::PLAYER && abs(being->getPixelX() - dx) +
00238 abs(being->getPixelY() - dy) < 2 * 32 &&
00239 (dx != being->getDestination().x && dy != being->getDestination().y))
00240 {
00241 being->setDestination(being->getPixelX(),being->getPixelY());
00242 continue;
00243 }
00244 if (abs(being->getPixelX() - sx) +
00245 abs(being->getPixelY() - sy) > 10 * 32)
00246 {
00247
00248 being->setPosition(sx, sy);
00249 being->setDestination(dx, dy);
00250 }
00251 else if (!(flags & MOVING_POSITION))
00252 {
00253 being->setDestination(dx, dy);
00254 }
00255 else if (!(flags & MOVING_DESTINATION))
00256 {
00257 being->adjustCourse(sx, sy);
00258 }
00259 else
00260 {
00261 being->adjustCourse(sx, sy, dx, dy);
00262 }
00263 }
00264 }
00265
00266 void BeingHandler::handleBeingAttackMessage(MessageIn &msg)
00267 {
00268 Being *being = beingManager->findBeing(msg.readInt16());
00269 const int direction = msg.readInt8();
00270 const int attackType = msg.readInt8();
00271
00272 if (!being)
00273 return;
00274
00275 switch (direction)
00276 {
00277 case DIRECTION_UP: being->setDirection(Being::UP); break;
00278 case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
00279 case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
00280 case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
00281 }
00282
00283 being->setAction(Being::ATTACK, attackType);
00284 }
00285
00286 void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
00287 {
00288 while (msg.getUnreadLength())
00289 {
00290 Being *being = beingManager->findBeing(msg.readInt16());
00291 int damage = msg.readInt16();
00292 if (being)
00293 {
00294 being->takeDamage(0, damage, Being::HIT);
00295 }
00296 }
00297 }
00298
00299 void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg)
00300 {
00301 Being *being = beingManager->findBeing(msg.readInt16());
00302 Being::Action action = (Being::Action) msg.readInt8();
00303 if (!being)
00304 return;
00305
00306 being->setAction(action);
00307
00308 if (action == Being::DEAD && being == player_node)
00309 {
00310 static char const *const deadMsg[] =
00311 {
00312 _("You are dead."),
00313 _("We regret to inform you that your character was killed in battle."),
00314 _("You are not that alive anymore."),
00315 _("The cold hands of the grim reaper are grabbing for your soul."),
00316 _("Game Over!"),
00317 _("No, kids. Your character did not really die. It... err... went to a better place."),
00318 _("Your plan of breaking your enemies weapon by bashing it with your throat failed."),
00319 _("I guess this did not run too well."),
00320 _("Do you want your possessions identified?"),
00321 _("Sadly, no trace of you was ever found..."),
00322 _("Annihilated."),
00323 _("Looks like you got your head handed to you."),
00324 _("You screwed up again, dump your body down the tubes and get you another one.")
00325
00326 };
00327 std::string message(deadMsg[rand()%13]);
00328 message.append(_(" Press OK to respawn"));
00329 OkDialog *dlg = new OkDialog(_("You died"), message);
00330 dlg->addActionListener(&(Net::GameServer::Player::respawnListener));
00331 }
00332 }
00333
00334 void BeingHandler::handleBeingLooksChangeMessage(MessageIn &msg)
00335 {
00336 Being *being = beingManager->findBeing(msg.readInt16());
00337 if (!being || being->getType() != Being::PLAYER)
00338 return;
00339 Player *player = static_cast<Player *>(being);
00340 handleLooks(player, msg);
00341 if (msg.getUnreadLength())
00342 {
00343 int style = msg.readInt16();
00344 int color = msg.readInt16();
00345 player->setHairStyle(style, color);
00346 player->setGender((Gender)msg.readInt16());
00347 }
00348 }
00349
00350 void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg)
00351 {
00352 Being *being = beingManager->findBeing(msg.readInt16());
00353 if (!being)
00354 return;
00355 int data = msg.readInt8();
00356 switch (data)
00357 {
00358 case DIRECTION_UP: being->setDirection(Being::UP); break;
00359 case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
00360 case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
00361 case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
00362 }
00363 }
00364
00365 }