Multiprotocol 8.1-9.6 finally working

Still have many minor issues, tests are needed
No recompilation needed anymore
9.60 messages is not fully implemented
This commit is contained in:
Eduardo Bart
2012-07-26 06:12:20 -03:00
parent 98c279c10b
commit 36c029fc69
28 changed files with 575 additions and 511 deletions

View File

@@ -87,6 +87,7 @@ set(otclient_SOURCES ${otclient_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.h
# net
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.h
${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolgame.h

View File

@@ -255,21 +255,60 @@ namespace Otc
IconPz = 16384
};
enum SpeakType {
SpeakSay = 1,
SpeakWhisper,
SpeakYell,
SpeakBroadcast,
SpeakPrivate,
SpeakPrivateRed,
SpeakPrivatePlayerToNpc,
SpeakPrivateNpcToPlayer,
SpeakChannelYellow,
SpeakChannelWhite,
SpeakChannelRed,
SpeakChannelOrange,
SpeakMonsterSay,
SpeakMonsterYell
enum MessageMode {
MessageNone = 0,
MessageSay = 1,
MessageWhisper = 2,
MessageYell = 3,
MessagePrivateFrom = 4,
MessagePrivateTo = 5,
MessageChannelManagement = 6,
MessageChannel = 7,
MessageChannelHighlight = 8,
MessageSpell = 9,
MessageNpcFrom = 10,
MessageNpcTo = 11,
MessageGamemasterBroadcast = 12,
MessageGamemasterChannel = 13,
MessageGamemasterPrivateFrom = 14,
MessageGamemasterPrivateTo = 15,
MessageLogin = 16,
MessageWarning = 17,
MessageGame = 18,
MessageFailure = 19,
MessageLook = 20,
MessageDamageDealed = 21,
MessageDamageReceived = 22,
MessageHeal = 23,
MessageExp = 24,
MessageDamageOthers = 25,
MessageHealOthers = 26,
MessageExpOthers = 27,
MessageStatus = 28,
MessageLoot = 29,
MessageTradeNpc = 30,
MessageGuild = 31,
MessagePartyManagement = 32,
MessageParty = 33,
MessageBarkLow = 34,
MessageBarkLoud = 35,
MessageReport = 36,
MessageHotkeyUse = 37,
MessageTutorialHint = 38,
MessageThankyou = 39,
MessageMarket = 40,
MessageBeyondLast = 41,
// deprecated
MessageMonsterYell = 42,
MessageMonsterSay = 43,
MessageRed = 44,
MessageBlue = 45,
MessageRVRChannel = 46,
MessageRVRAnswer = 47,
MessageRVRContinue = 48,
LastMessage = 49,
MessageInvalid = 255,
};
enum GameFeature {

View File

@@ -57,15 +57,6 @@ Creature::Creature() : Thing()
m_footStep = 0;
}
/*
PainterShaderProgramPtr outfitProgram;
int HEAD_COLOR_UNIFORM = 10;
int BODY_COLOR_UNIFORM = 11;
int LEGS_COLOR_UNIFORM = 12;
int FEET_COLOR_UNIFORM = 13;
int MASK_TEXTURE_UNIFORM = 14;
*/
void Creature::draw(const Point& dest, float scaleFactor, bool animate)
{
Point animationOffset = animate ? m_walkOffset : Point(0,0);

View File

@@ -32,6 +32,7 @@
#include <framework/core/application.h>
#include "luavaluecasts.h"
#include "protocolgame.h"
#include "protocolcodes.h"
Game g_game;
@@ -151,22 +152,22 @@ void Game::processPing()
g_lua.callGlobalField("g_game", "onPing");
}
void Game::processTextMessage(const std::string& type, const std::string& message)
void Game::processTextMessage(Otc::MessageMode mode, const std::string& text)
{
g_lua.callGlobalField("g_game","onTextMessage", type, message);
g_lua.callGlobalField("g_game", "onTextMessage", mode, text);
}
void Game::processCreatureSpeak(const std::string& name, int level, Otc::SpeakType type, const std::string& message, int channelId, const Position& creaturePos)
void Game::processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos)
{
if(creaturePos.isValid() && (type == Otc::SpeakSay || type == Otc::SpeakWhisper || type == Otc::SpeakYell
|| type == Otc::SpeakMonsterSay || type == Otc::SpeakMonsterYell || type == Otc::SpeakPrivateNpcToPlayer))
if(pos.isValid() && (mode == Otc::MessageSay || mode == Otc::MessageWhisper || mode == Otc::MessageYell ||
mode == Otc::MessageMonsterSay || mode == Otc::MessageMonsterYell || mode == Otc::MessageNpcFrom))
{
StaticTextPtr staticText = StaticTextPtr(new StaticText);
staticText->addMessage(name, type, message);
g_map.addThing(staticText, creaturePos);
staticText->addMessage(name, mode, text);
g_map.addThing(staticText, pos);
}
g_lua.callGlobalField("g_game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos);
g_lua.callGlobalField("g_game", "onTalk", name, level, mode, text, channelId, pos);
}
void Game::processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items)
@@ -769,21 +770,21 @@ void Game::talk(const std::string& message)
{
if(!canPerformGameAction() || message.empty())
return;
talkChannel(Otc::SpeakSay, 0, message);
talkChannel(Otc::MessageSay, 0, message);
}
void Game::talkChannel(Otc::SpeakType speakType, int channelId, const std::string& message)
void Game::talkChannel(Otc::MessageMode mode, int channelId, const std::string& message)
{
if(!canPerformGameAction() || message.empty())
return;
m_protocolGame->sendTalk(speakType, channelId, "", message);
m_protocolGame->sendTalk(mode, channelId, "", message);
}
void Game::talkPrivate(Otc::SpeakType speakType, const std::string& receiver, const std::string& message)
void Game::talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message)
{
if(!canPerformGameAction() || receiver.empty() || message.empty())
return;
m_protocolGame->sendTalk(speakType, 0, receiver, message);
m_protocolGame->sendTalk(mode, 0, receiver, message);
}
void Game::openPrivateChannel(const std::string& receiver)
@@ -1145,6 +1146,8 @@ void Game::setClientVersion(int version)
m_protocolVersion = version;
Proto::buildMessageModesMap(version);
g_lua.callGlobalField("g_game", "onClientVersionChange", version);
}

View File

@@ -60,8 +60,8 @@ protected:
void processWalkCancel(Otc::Direction direction);
// message related
void processTextMessage(const std::string& type, const std::string& message); // deprecated
void processCreatureSpeak(const std::string& name, int level, Otc::SpeakType type, const std::string& message, int channelId, const Position& creaturePos);
void processTextMessage(Otc::MessageMode mode, const std::string& text);
void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
// container related
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items);
@@ -155,8 +155,8 @@ public:
// talk related
void talk(const std::string& message);
void talkChannel(Otc::SpeakType speakType, int channelId, const std::string& message);
void talkPrivate(Otc::SpeakType speakType, const std::string& receiver, const std::string& message);
void talkChannel(Otc::MessageMode mode, int channelId, const std::string& message);
void talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message);
// channel related
void openPrivateChannel(const std::string& receiver);

View File

@@ -618,7 +618,7 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
StaticTextPtr cStaticText = *it;
if(cStaticText->getPosition() == pos) {
// try to combine messages
if(cStaticText->addMessage(staticText->getName(), staticText->getMessageType(), staticText->getFirstMessage())) {
if(cStaticText->addMessage(staticText->getName(), staticText->getMessageMode(), staticText->getFirstMessage())) {
mustAdd = false;
break;
} else {

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "protocolcodes.h"
namespace Proto {
std::map<uint8, uint8> messageModesMap;
void buildMessageModesMap(int version) {
messageModesMap.clear();
if(version >= 900) {
for(int i=Otc::MessageNone;i<=Otc::MessageBeyondLast;++i)
messageModesMap[i] = i;
} else if(version >= 861) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcFrom] = 4;
messageModesMap[Otc::MessageNpcTo] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannelHighlight] = 7;
messageModesMap[Otc::MessageChannel] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelManagement] = 12;
messageModesMap[Otc::MessageMonsterSay] = 13;
messageModesMap[Otc::MessageMonsterYell] = 14;
messageModesMap[Otc::MessageWarning] = 15;
messageModesMap[Otc::MessageGame] = 16;
messageModesMap[Otc::MessageLogin] = 17;
messageModesMap[Otc::MessageStatus] = 18;
messageModesMap[Otc::MessageLook] = 19;
messageModesMap[Otc::MessageFailure] = 20;
messageModesMap[Otc::MessageBlue] = 21;
messageModesMap[Otc::MessageRed] = 22;
} else if(version >= 854) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcFrom] = 4;
messageModesMap[Otc::MessageNpcTo] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannel] = 7;
messageModesMap[Otc::MessageChannelManagement] = 8;
messageModesMap[Otc::MessageRVRChannel] = 9;
messageModesMap[Otc::MessageRVRAnswer] = 10;
messageModesMap[Otc::MessageRVRContinue] = 11;
messageModesMap[Otc::MessageGamemasterBroadcast] = 12;
messageModesMap[Otc::MessageGamemasterChannel] = 13;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 14;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 14;
messageModesMap[Otc::MessageChannelHighlight] = 15;
// 16, 17, 18 ??
messageModesMap[Otc::MessageRed] = 18;
messageModesMap[Otc::MessageMonsterSay] = 19;
messageModesMap[Otc::MessageMonsterYell] = 20;
messageModesMap[Otc::MessageWarning] = 21;
messageModesMap[Otc::MessageGame] = 22;
messageModesMap[Otc::MessageLogin] = 23;
messageModesMap[Otc::MessageStatus] = 24;
messageModesMap[Otc::MessageLook] = 25;
messageModesMap[Otc::MessageFailure] = 26;
messageModesMap[Otc::MessageBlue] = 27;
} else if(version >= 810) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessagePrivateFrom] = 4;
messageModesMap[Otc::MessagePrivateTo] = 4;
messageModesMap[Otc::MessageChannel] = 5;
messageModesMap[Otc::MessageRVRChannel] = 6;
messageModesMap[Otc::MessageRVRAnswer] = 7;
messageModesMap[Otc::MessageRVRContinue] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelHighlight] = 12;
// 13, 14, 15 ??
messageModesMap[Otc::MessageMonsterSay] = 16;
messageModesMap[Otc::MessageMonsterYell] = 17;
messageModesMap[Otc::MessageWarning] = 18;
messageModesMap[Otc::MessageGame] = 19;
messageModesMap[Otc::MessageLogin] = 20;
messageModesMap[Otc::MessageStatus] = 21;
messageModesMap[Otc::MessageLook] = 22;
messageModesMap[Otc::MessageFailure] = 23;
messageModesMap[Otc::MessageBlue] = 24;
messageModesMap[Otc::MessageRed] = 25;
}
}
Otc::MessageMode translateMessageModeFromServer(uint8 mode)
{
auto it = std::find_if(messageModesMap.begin(), messageModesMap.end(), [=] (const std::pair<uint8, uint8>& p) { return p.second == mode; });
if(it != messageModesMap.end())
return (Otc::MessageMode)it->first;
return Otc::MessageInvalid;
}
uint8 translateMessageModeToServer(Otc::MessageMode mode)
{
if(mode < 0 || mode >= Otc::LastMessage)
return Otc::MessageInvalid;
auto it = messageModesMap.find(mode);
if(it != messageModesMap.end())
return it->second;
return Otc::MessageInvalid;
}
}

View File

@@ -39,7 +39,8 @@ namespace Proto {
Creature = 99
};
enum GameServerOpcodes {
enum GameServerOpcodes : uint8
{
GameServerInitGame = 10,
GameServerGMActions = 11,
GameServerLoginError = 20,
@@ -139,7 +140,8 @@ namespace Proto {
GameServerShowModalDialog = 250 // 960
};
enum ClientOpcodes {
enum ClientOpcodes : uint8
{
ClientEnterAccount = 1,
ClientEnterGame = 10,
ClientLeaveGame = 20,
@@ -230,107 +232,6 @@ namespace Proto {
ClientAnswerModalDialog = 249 // 960
};
enum ServerSpeakType {
#if PROTOCOL>=910
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivateFrom, // new
ServerSpeakPrivateTo, // new
ServerSpeakChannelManagement, // new
ServerSpeakChannelYellow,
ServerSpeakChannelOrange,
ServerSpeakSpell, // new
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedFrom, // new
ServerSpeakPrivateRedTo, // new
// 16 - 33
ServerSpeakMonsterSay = 34,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakRVRChannel = 255,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakChannelRed2,
ServerSpeakChannelWhite
#elif PROTOCOL>=861
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakChannelWhite,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
ServerSpeakMonsterSay,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakRVRChannel = 255,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakChannelRed2
#elif PROTOCOL>=854
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakChannelWhite,
ServerSpeakRVRChannel,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
// 16
ServerSpeakChannelRed2 = 17,
// 18
ServerSpeakMonsterSay = 19,
ServerSpeakMonsterYell
#elif PROTOCOL>=810
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakRVRChannel,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
// 13
ServerSpeakChannelRed2 = 14,
// 15
ServerSpeakMonsterSay = 16,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakPrivatePlayerToNpc = 255,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakChannelWhite
#endif
};
enum CreatureType {
CreatureTypePlayer = 0,
CreatureTypeMonster,
@@ -346,50 +247,9 @@ namespace Proto {
NpcEndId = 0xffffffff
};
inline Otc::SpeakType translateSpeakTypeFromServer(int type) {
switch(type) {
case Proto::ServerSpeakSay: return Otc::SpeakSay;
case Proto::ServerSpeakWhisper: return Otc::SpeakWhisper;
case Proto::ServerSpeakYell: return Otc::SpeakYell;
case Proto::ServerSpeakMonsterSay: return Otc::SpeakMonsterSay;
case Proto::ServerSpeakMonsterYell: return Otc::SpeakMonsterYell;
case Proto::ServerSpeakPrivateNpcToPlayer: return Otc::SpeakPrivateNpcToPlayer;
case Proto::ServerSpeakChannelYellow: return Otc::SpeakChannelYellow;
case Proto::ServerSpeakChannelWhite: return Otc::SpeakChannelWhite;
case Proto::ServerSpeakChannelRed: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelRed2: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelOrange: return Otc::SpeakChannelOrange;
case Proto::ServerSpeakPrivateTo: return Otc::SpeakPrivate;
case Proto::ServerSpeakPrivatePlayerToNpc: return Otc::SpeakPrivate;
case Proto::ServerSpeakBroadcast: return Otc::SpeakBroadcast;
case Proto::ServerSpeakPrivateRedTo: return Otc::SpeakPrivateRed;
default:
g_logger.error(stdext::format("unknown protocol speak type %d", type));
return Otc::SpeakSay;
}
}
inline Proto::ServerSpeakType translateSpeakTypeToServer(int type) {
switch(type) {
case Otc::SpeakSay: return Proto::ServerSpeakSay;
case Otc::SpeakWhisper: return Proto::ServerSpeakWhisper;
case Otc::SpeakYell: return Proto::ServerSpeakYell;
case Otc::SpeakBroadcast: return Proto::ServerSpeakBroadcast;
case Otc::SpeakPrivate: return Proto::ServerSpeakPrivateFrom;
case Otc::SpeakPrivateRed: return Proto::ServerSpeakPrivateRedFrom;
case Otc::SpeakPrivatePlayerToNpc: return Proto::ServerSpeakPrivatePlayerToNpc;
case Otc::SpeakPrivateNpcToPlayer: return Proto::ServerSpeakPrivateNpcToPlayer;
case Otc::SpeakChannelYellow: return Proto::ServerSpeakChannelYellow;
case Otc::SpeakChannelWhite: return Proto::ServerSpeakChannelWhite;
case Otc::SpeakChannelRed: return Proto::ServerSpeakChannelRed;
case Otc::SpeakChannelOrange: return Proto::ServerSpeakChannelOrange;
case Otc::SpeakMonsterSay: return Proto::ServerSpeakMonsterSay;
case Otc::SpeakMonsterYell: return Proto::ServerSpeakMonsterYell;
default:
g_logger.error(stdext::format("unknown protocol speak type desc %d", type));
return Proto::ServerSpeakSay;
}
}
void buildMessageModesMap(int version);
Otc::MessageMode translateMessageModeFromServer(uint8 mode);
uint8 translateMessageModeToServer(Otc::MessageMode mode);
}
#endif

View File

@@ -72,7 +72,7 @@ public:
void sendEditText(uint id, const std::string& text);
void sendEditList(uint id, int doorId, const std::string& text);
void sendLook(const Position& position, int thingId, int stackpos);
void sendTalk(Otc::SpeakType speakType, int channelId, const std::string& receiver, const std::string& message);
void sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message);
void sendRequestChannels();
void sendJoinChannel(int channelId);
void sendLeaveChannel(int channelId);
@@ -169,7 +169,7 @@ private:
void parseSpellCooldown(const InputMessagePtr& msg);
void parseSpellGroupCooldown(const InputMessagePtr& msg);
void parseMultiUseCooldown(const InputMessagePtr& msg);
void parseCreatureSpeak(const InputMessagePtr& msg);
void parseTalk(const InputMessagePtr& msg);
void parseChannelList(const InputMessagePtr& msg);
void parseOpenChannel(const InputMessagePtr& msg);
void parseOpenPrivateChannel(const InputMessagePtr& msg);

View File

@@ -211,7 +211,7 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
parsePlayerCancelAttack(msg);
break;
case Proto::GameServerTalk:
parseCreatureSpeak(msg);
parseTalk(msg);
break;
case Proto::GameServerChannels:
parseChannelList(msg);
@@ -469,7 +469,6 @@ void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg)
Position pos = thing->getPosition();
int stackpos = thing->getStackpos();
assert(thing->getStackPriority() == newThing->getStackPriority());
if(!g_map.removeThing(thing)) {
g_logger.traceError("unable to remove thing");
@@ -938,51 +937,49 @@ void ProtocolGame::parseMultiUseCooldown(const InputMessagePtr& msg)
msg->getU32(); // cooldown
}
void ProtocolGame::parseCreatureSpeak(const InputMessagePtr& msg)
void ProtocolGame::parseTalk(const InputMessagePtr& msg)
{
msg->getU32(); // channel statement guid
std::string name = msg->getString();
int level = msg->getU16();
int speakType = msg->getU8();
Otc::MessageMode mode = Proto::translateMessageModeFromServer(msg->getU8());
int channelId = 0;
Position creaturePos;
Position pos;
switch(speakType) {
case Proto::ServerSpeakSay:
case Proto::ServerSpeakWhisper:
case Proto::ServerSpeakYell:
case Proto::ServerSpeakMonsterSay:
case Proto::ServerSpeakMonsterYell:
case Proto::ServerSpeakPrivateNpcToPlayer:
creaturePos = getPosition(msg);
switch(mode) {
case Otc::MessageSay:
case Otc::MessageWhisper:
case Otc::MessageYell:
case Otc::MessageMonsterSay:
case Otc::MessageMonsterYell:
case Otc::MessageNpcFrom:
case Otc::MessageBarkLow:
case Otc::MessageBarkLoud:
case Otc::MessageSpell:
pos = getPosition(msg);
break;
case Proto::ServerSpeakChannelYellow:
case Proto::ServerSpeakChannelWhite:
case Proto::ServerSpeakChannelRed:
case Proto::ServerSpeakChannelRed2:
case Proto::ServerSpeakChannelOrange:
case Otc::MessageChannel:
case Otc::MessageChannelManagement:
case Otc::MessageChannelHighlight:
case Otc::MessageGamemasterChannel:
channelId = msg->getU16();
break;
case Proto::ServerSpeakPrivateFrom:
case Proto::ServerSpeakPrivatePlayerToNpc:
case Proto::ServerSpeakBroadcast:
case Proto::ServerSpeakPrivateRedFrom:
case Otc::MessagePrivateFrom:
case Otc::MessageGamemasterBroadcast:
case Otc::MessageGamemasterPrivateFrom:
break;
case Proto::ServerSpeakRVRChannel:
case Otc::MessageRVRChannel:
msg->getU32();
break;
//case Proto::ServerSpeakChannelManagement:
//case Proto::ServerSpeakSpell:
default:
stdext::throw_exception(stdext::format("unknown speak type %d", speakType));
stdext::throw_exception(stdext::format("unknown message mode %d", mode));
break;
}
std::string message = msg->getString();
Otc::SpeakType type = Proto::translateSpeakTypeFromServer(speakType);
std::string text = msg->getString();
g_game.processCreatureSpeak(name, level, type, message, channelId, creaturePos);
g_game.processTalk(name, level, mode, text, channelId, pos);
}
void ProtocolGame::parseChannelList(const InputMessagePtr& msg)
@@ -1066,9 +1063,58 @@ void ProtocolGame::parseRuleViolationLock(const InputMessagePtr& msg)
void ProtocolGame::parseTextMessage(const InputMessagePtr& msg)
{
msg->getU8(); // type
msg->getString(); // message
// this is now handled by game_textmessage module
int code = msg->getU8();
Otc::MessageMode mode = Proto::translateMessageModeFromServer(code);
std::string text;
switch(mode) {
case Otc::MessageChannelManagement: {
int channel = msg->getU16();
text = msg->getString();
break;
}
case Otc::MessageDamageDealed:
case Otc::MessageDamageReceived:
case Otc::MessageDamageOthers: {
Position pos = getPosition(msg);
uint value = msg->getU32();
int color = msg->getU8();
msg->getU32(); // ??
msg->getU8(); // ??
text = msg->getString();
AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText);
animatedText->setColor(color);
animatedText->setText(stdext::to_string(value));
g_map.addThing(animatedText, pos);
break;
}
case Otc::MessageHeal:
case Otc::MessageExp:
case Otc::MessageHealOthers:
case Otc::MessageExpOthers: {
Position pos = getPosition(msg);
uint value = msg->getU32();
int color = msg->getU8();
msg->getU32(); // ??
msg->getU8(); // ??
text = msg->getString();
AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText);
animatedText->setColor(color);
animatedText->setText(stdext::to_string(value));
g_map.addThing(animatedText, pos);
break;
}
case Otc::MessageInvalid:
stdext::throw_exception(stdext::format("unknown message mode %d", mode));
break;
default:
text = msg->getString();
break;
}
g_game.processTextMessage(mode, text);
}
void ProtocolGame::parseCancelWalk(const InputMessagePtr& msg)

View File

@@ -435,26 +435,33 @@ void ProtocolGame::sendLook(const Position& position, int thingId, int stackpos)
send(msg);
}
void ProtocolGame::sendTalk(Otc::SpeakType speakType, int channelId, const std::string& receiver, const std::string& message)
void ProtocolGame::sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message)
{
if(message.length() > 255 || message.length() <= 0)
if(message.empty())
return;
int serverSpeakType = Proto::translateSpeakTypeToServer(speakType);
if(message.length() > 255) {
g_logger.traceError("message too large");
return;
}
OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientTalk);
msg->addU8(serverSpeakType);
msg->addU8(Proto::translateMessageModeToServer(mode));
switch(serverSpeakType) {
case Proto::ServerSpeakPrivateFrom:
case Proto::ServerSpeakPrivateRedFrom:
switch(mode) {
case Otc::MessagePrivateTo:
case Otc::MessageGamemasterPrivateTo:
msg->addString(receiver);
break;
case Proto::ServerSpeakChannelYellow:
case Proto::ServerSpeakChannelRed:
case Otc::MessageChannel:
case Otc::MessageChannelHighlight:
case Otc::MessageChannelManagement:
case Otc::MessageGamemasterChannel:
msg->addU16(channelId);
break;
default:
break;
}
msg->addString(message);

View File

@@ -47,16 +47,16 @@ void StaticText::drawText(const Point& dest, const Rect& parentRect)
//}
}
bool StaticText::addMessage(const std::string& name, Otc::SpeakType type, const std::string& message)
bool StaticText::addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text)
{
//TODO: this could be moved to lua
// first message
if(m_messages.size() == 0) {
m_name = name;
m_messageType = type;
m_mode = mode;
}
// check if we can really own the message
else if(m_name != name || m_messageType != type) {
else if(m_name != name || m_mode != mode) {
return false;
}
// too many messages
@@ -66,7 +66,7 @@ bool StaticText::addMessage(const std::string& name, Otc::SpeakType type, const
m_updateEvent = nullptr;
}
m_messages.push_back(message);
m_messages.push_back(text);
compose();
if(!m_updateEvent)
@@ -105,26 +105,26 @@ void StaticText::compose()
//TODO: this could be moved to lua
std::string text;
if(m_messageType == Otc::SpeakSay) {
if(m_mode == Otc::MessageSay) {
text += m_name;
text += " says:\n";
m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakWhisper) {
} else if(m_mode == Otc::MessageWhisper) {
text += m_name;
text += " whispers:\n";
m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakYell) {
} else if(m_mode == Otc::MessageYell) {
text += m_name;
text += " yells:\n";
m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakMonsterSay || m_messageType == Otc::SpeakMonsterYell) {
} else if(m_mode == Otc::MessageMonsterSay || m_mode == Otc::MessageMonsterYell) {
m_color = Color(254, 101, 0);
} else if(m_messageType == Otc::SpeakPrivateNpcToPlayer) {
} else if(m_mode == Otc::MessageNpcFrom) {
text += m_name;
text += " says:\n";
m_color = Color(95, 247, 247);
} else {
g_logger.warning(stdext::format("Unknown speak type: %d", m_messageType));
g_logger.warning(stdext::format("Unknown speak type: %d", m_mode));
}
for(uint i = 0; i < m_messages.size(); ++i) {

View File

@@ -36,12 +36,12 @@ public:
void drawText(const Point& dest, const Rect& parentRect);
std::string getName() { return m_name; }
Otc::SpeakType getMessageType() { return m_messageType; }
Otc::MessageMode getMessageMode() { return m_mode; }
std::string getFirstMessage() { return m_messages[0]; }
bool isYell() { return m_messageType == Otc::SpeakYell || m_messageType == Otc::SpeakMonsterYell; }
bool isYell() { return m_mode == Otc::MessageYell || m_mode == Otc::MessageMonsterYell; }
bool addMessage(const std::string& name, Otc::SpeakType type, const std::string& message);
bool addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text);
StaticTextPtr asStaticText() { return std::static_pointer_cast<StaticText>(shared_from_this()); }
bool isStaticText() { return true; }
@@ -54,7 +54,7 @@ private:
Boolean<false> m_yell;
std::deque<std::string> m_messages;
std::string m_name;
Otc::SpeakType m_messageType;
Otc::MessageMode m_mode;
Color m_color;
CachedText m_cachedText;
ScheduledEventPtr m_updateEvent;

View File

@@ -192,6 +192,17 @@ ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos)
if(m_things.size() > MAX_THINGS)
removeThing(m_things[MAX_THINGS]);
/*
// check stack priorities
// this code exists to find stackpos bugs faster
int lastPriority = 0;
for(const ThingPtr& thing : m_things) {
int priority = thing->getStackPriority();
assert(lastPriority <= priority);
lastPriority = priority;
}
*/
update();
return oldObject;
}
@@ -510,13 +521,4 @@ void Tile::update()
if(c != 0)
m_minimapColorByte = c;
}
// check stack priorities
// this code exists to find stackpos bugs faster
int lastPriority = 0;
for(const ThingPtr& thing : m_things) {
int priority = thing->getStackPriority();
assert(lastPriority <= priority);
lastPriority = priority;
}
}