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/playerhandler.h"
00023
00024 #include "net/tmwserv/connection.h"
00025 #include "net/tmwserv/protocol.h"
00026
00027 #include "net/tmwserv/gameserver/internal.h"
00028 #include "net/tmwserv/gameserver/player.h"
00029
00030 #include "net/messagein.h"
00031 #include "net/messageout.h"
00032
00033 #include "effectmanager.h"
00034 #include "engine.h"
00035 #include "localplayer.h"
00036 #include "log.h"
00037 #include "particle.h"
00038 #include "npc.h"
00039
00040 #include "gui/buy.h"
00041 #include "gui/chat.h"
00042 #include "gui/gui.h"
00043 #include "gui/npclistdialog.h"
00044 #include "gui/npc_text.h"
00045 #include "gui/ok_dialog.h"
00046 #include "gui/sell.h"
00047 #include "gui/skill.h"
00048 #include "gui/viewport.h"
00049
00050
00051 OkDialog *weightNotice = NULL;
00052 OkDialog *deathNotice = NULL;
00053
00054 extern NpcListDialog *npcListDialog;
00055 extern NpcTextDialog *npcTextDialog;
00056 extern BuyDialog *buyDialog;
00057 extern SellDialog *sellDialog;
00058 extern Window *buySellDialog;
00059
00060
00061
00062
00063 static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32;
00064
00068
00069 namespace {
00070 struct WeightListener : public gcn::ActionListener
00071 {
00072 void action(const gcn::ActionEvent &event)
00073 {
00074 weightNotice = NULL;
00075 }
00076 } weightListener;
00077 }
00078
00082
00083 namespace {
00084 struct DeathListener : public gcn::ActionListener
00085 {
00086 void action(const gcn::ActionEvent &event)
00087 {
00088 player_node->revive();
00089 deathNotice = NULL;
00090 npcListDialog->setVisible(false);
00091 npcTextDialog->setVisible(false);
00092 buyDialog->setVisible(false);
00093 sellDialog->setVisible(false);
00094 current_npc = 0;
00095 }
00096 } deathListener;
00097 }
00098
00099 Net::PlayerHandler *playerHandler;
00100
00101 namespace TmwServ {
00102
00103 PlayerHandler::PlayerHandler()
00104 {
00105 static const Uint16 _messages[] = {
00106 GPMSG_PLAYER_MAP_CHANGE,
00107 GPMSG_PLAYER_SERVER_CHANGE,
00108 GPMSG_PLAYER_ATTRIBUTE_CHANGE,
00109 GPMSG_PLAYER_EXP_CHANGE,
00110 GPMSG_LEVELUP,
00111 GPMSG_LEVEL_PROGRESS,
00112 GPMSG_RAISE_ATTRIBUTE_RESPONSE,
00113 GPMSG_LOWER_ATTRIBUTE_RESPONSE,
00114 0
00115 };
00116 handledMessages = _messages;
00117 playerHandler = this;
00118 }
00119
00120 void PlayerHandler::handleMessage(MessageIn &msg)
00121 {
00122 switch (msg.getId())
00123 {
00124 case GPMSG_PLAYER_MAP_CHANGE:
00125 handleMapChangeMessage(msg);
00126 break;
00127
00128 case GPMSG_PLAYER_SERVER_CHANGE:
00129 {
00130 std::string token = msg.readString(32);
00131 std::string address = msg.readString();
00132 int port = msg.readInt16();
00133 logger->log("Changing server to %s:%d", address.c_str(), port);
00134 } break;
00135
00136 case GPMSG_PLAYER_ATTRIBUTE_CHANGE:
00137 {
00138 logger->log("ATTRIBUTE UPDATE:");
00139 while (msg.getUnreadLength())
00140 {
00141 int stat = msg.readInt8();
00142 int base = msg.readInt16();
00143 int value = msg.readInt16();
00144 logger->log("%d set to %d %d", stat, base, value);
00145
00146 if (stat == BASE_ATTR_HP)
00147 {
00148 player_node->setMaxHp(base);
00149 player_node->setHp(value);
00150 }
00151 else if (stat < NB_CHARACTER_ATTRIBUTES)
00152 {
00153 if (stat >= CHAR_SKILL_BEGIN && stat < CHAR_SKILL_END
00154 && player_node->getAttributeBase(stat) < base
00155 && player_node->getAttributeBase(stat) > -1)
00156 {
00157 Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0);
00158 player_node->controlParticle(effect);
00159 }
00160
00161 player_node->setAttributeBase(stat, base);
00162 player_node->setAttributeEffective(stat, value);
00163 }
00164 else
00165 {
00166 logger->log("Warning: server wants to update unknown "
00167 "attribute %d to %d", stat, value);
00168 }
00169 }
00170 } break;
00171
00172 case GPMSG_PLAYER_EXP_CHANGE:
00173 {
00174 logger->log("EXP Update");
00175 while (msg.getUnreadLength())
00176 {
00177 int skill = msg.readInt8();
00178 int current = msg.readInt32();
00179 int next = msg.readInt32();
00180
00181 if (skill < CHAR_SKILL_NB)
00182 {
00183 player_node->setExperience(skill, current, next);
00184 }
00185 else
00186 {
00187 logger->log("Warning: server wants to update experience of unknown "
00188 "skill %d to %d / %d", skill, current, next);
00189 }
00190 }
00191 } break;
00192
00193 case GPMSG_LEVELUP:
00194 {
00195 player_node->setLevel(msg.readInt16());
00196 player_node->setCharacterPoints(msg.readInt16());
00197 player_node->setCorrectionPoints(msg.readInt16());
00198 Particle* effect = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0);
00199 player_node->controlParticle(effect);
00200 } break;
00201
00202
00203 case GPMSG_LEVEL_PROGRESS:
00204 {
00205 logger->log("Level Progress Update");
00206 player_node->setLevelProgress(msg.readInt8());
00207 } break;
00208
00209
00210 case GPMSG_RAISE_ATTRIBUTE_RESPONSE:
00211 {
00212 int errCode = msg.readInt8();
00213 int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
00214 switch (errCode)
00215 {
00216 case ATTRIBMOD_OK:
00217 {
00218
00219 } break;
00220 case ATTRIBMOD_INVALID_ATTRIBUTE:
00221 {
00222 logger->log("Warning: Server denied increase of attribute %d (unknown attribute) ", attrNum);
00223 } break;
00224 case ATTRIBMOD_NO_POINTS_LEFT:
00225 {
00226
00227
00228
00229 logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
00230 int attrValue = player_node->getAttributeBase(attrNum) - 1;
00231 player_node->setCharacterPoints(0);
00232 player_node->setAttributeBase(attrNum, attrValue);
00233 } break;
00234 case ATTRIBMOD_DENIED:
00235 {
00236
00237 logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
00238 int points = player_node->getCharacterPoints() - 1;
00239 player_node->setCharacterPoints(points);
00240 int attrValue = player_node->getAttributeBase(attrNum) - 1;
00241 player_node->setAttributeBase(attrNum, attrValue);
00242 } break;
00243 }
00244 } break;
00245
00246 case GPMSG_LOWER_ATTRIBUTE_RESPONSE:
00247 {
00248 int errCode = msg.readInt8();
00249 int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
00250 switch (errCode)
00251 {
00252 case ATTRIBMOD_OK:
00253 {
00254
00255 } break;
00256 case ATTRIBMOD_INVALID_ATTRIBUTE:
00257 {
00258 logger->log("Warning: Server denied reduction of attribute %d (unknown attribute) ", attrNum);
00259 } break;
00260 case ATTRIBMOD_NO_POINTS_LEFT:
00261 {
00262
00263
00264
00265 logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
00266 int attrValue = player_node->getAttributeBase(attrNum) + 1;
00267 player_node->setCorrectionPoints(0);
00268 player_node->setAttributeBase(attrNum, attrValue);
00269 break;
00270 } break;
00271 case ATTRIBMOD_DENIED:
00272 {
00273
00274 logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
00275 int charaPoints = player_node->getCharacterPoints() - 1;
00276 player_node->setCharacterPoints(charaPoints);
00277 int correctPoints = player_node->getCorrectionPoints() + 1;
00278 player_node->setCorrectionPoints(correctPoints);
00279 int attrValue = player_node->getAttributeBase(attrNum) + 1;
00280 player_node->setAttributeBase(attrNum, attrValue);
00281 } break;
00282 }
00283
00284 } break;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 }
00303 }
00304
00305 void PlayerHandler::handleMapChangeMessage(MessageIn &msg)
00306 {
00307 const std::string mapName = msg.readString();
00308 const unsigned short x = msg.readInt16();
00309 const unsigned short y = msg.readInt16();
00310 const bool nearby = (engine->getCurrentMapName() == mapName);
00311
00312 logger->log("Changing map to %s (%d, %d)", mapName.c_str(), x, y);
00313
00314
00315 engine->changeMap(mapName);
00316
00317 current_npc = 0;
00318
00319 const Vector &playerPos = player_node->getPosition();
00320 float scrollOffsetX = 0.0f;
00321 float scrollOffsetY = 0.0f;
00322
00323
00324 if (!nearby
00325 || (abs(x - (int) playerPos.x) > MAP_TELEPORT_SCROLL_DISTANCE)
00326 || (abs(y - (int) playerPos.y) > MAP_TELEPORT_SCROLL_DISTANCE)) {
00327 scrollOffsetX = x - (int) playerPos.x;
00328 scrollOffsetY = y - (int) playerPos.y;
00329 }
00330
00331 player_node->setAction(Being::STAND);
00332 player_node->setPosition(x, y);
00333 player_node->setDestination(x, y);
00334
00335 logger->log("Adjust scrolling by %d,%d", (int) scrollOffsetX,
00336 (int) scrollOffsetY);
00337 viewport->scrollBy(scrollOffsetX, scrollOffsetY);
00338 }
00339
00340 void PlayerHandler::attack(Being *being)
00341 {
00342
00343 }
00344
00345 void PlayerHandler::emote(int emoteId)
00346 {
00347
00348 }
00349
00350 void PlayerHandler::increaseStat(LocalPlayer::Attribute attr)
00351 {
00352
00353 }
00354
00355 void PlayerHandler::decreaseStat(LocalPlayer::Attribute attr)
00356 {
00357
00358 }
00359
00360 void PlayerHandler::pickUp(FloorItem *floorItem)
00361 {
00362 int id = floorItem->getId();
00363 Net::GameServer::Player::pickUp(id >> 16, id & 0xFFFF);
00364 }
00365
00366 void PlayerHandler::setDirection(char direction)
00367 {
00368 MessageOut msg(PGMSG_DIRECTION_CHANGE);
00369 msg.writeInt8(direction);
00370 Net::GameServer::connection->send(msg);
00371 }
00372
00373 void PlayerHandler::setDestination(int x, int y, int )
00374 {
00375 MessageOut msg(PGMSG_WALK);
00376 msg.writeInt16(x);
00377 msg.writeInt16(y);
00378 Net::GameServer::connection->send(msg);
00379
00380
00381 effectManager->trigger(15, x, y);
00382 }
00383
00384 void PlayerHandler::changeAction(Being::Action action)
00385 {
00386 if (action == Being::SIT)
00387 player_node->setAction(action);
00388
00389 MessageOut msg(PGMSG_ACTION_CHANGE);
00390 msg.writeInt8(action);
00391 Net::GameServer::connection->send(msg);
00392 }
00393
00394 void PlayerHandler::respawn()
00395 {
00396
00397 }
00398
00399 void PlayerHandler::ingorePlayer(const std::string &player, bool ignore)
00400 {
00401
00402 }
00403
00404 void PlayerHandler::ingoreAll(bool ignore)
00405 {
00406
00407 }
00408
00409 }