basic protocol 910 support

This commit is contained in:
Eduardo Bart 2012-05-11 22:44:13 -03:00
parent cc261931be
commit abbd15b1c2
5 changed files with 352 additions and 210 deletions

View File

@ -17,6 +17,8 @@ Icons[2048] = { tooltip = tr('You are cursed'), path = '/game_healthbar/icons/cu
Icons[4096] = { tooltip = tr('You are strengthened'), path = '/game_healthbar/icons/strengthened.png', id = 'condition_strengthened' } Icons[4096] = { tooltip = tr('You are strengthened'), path = '/game_healthbar/icons/strengthened.png', id = 'condition_strengthened' }
Icons[8192] = { tooltip = tr('You may not logout or enter a protection zone'), path = '/game_healthbar/icons/protection_zone_block.png', id = 'condition_protection_zone_block' } Icons[8192] = { tooltip = tr('You may not logout or enter a protection zone'), path = '/game_healthbar/icons/protection_zone_block.png', id = 'condition_protection_zone_block' }
Icons[16384] = { tooltip = tr('You are within a protection zone'), path = '/game_healthbar/icons/protection_zone.png', id = 'condition_protection_zone' } Icons[16384] = { tooltip = tr('You are within a protection zone'), path = '/game_healthbar/icons/protection_zone.png', id = 'condition_protection_zone' }
Icons[32768] = { tooltip = tr('You are bleeding'), path = '/game_healthbar/icons/bleeding.png', id = 'condition_bleeding' }
Icons[65536] = { tooltip = tr('You are hungry'), path = '/game_healthbar/icons/hungry.png', id = 'condition_hungry' }
-- private variables -- private variables
local healthBarWindow local healthBarWindow

View File

@ -30,7 +30,8 @@
PROTOCOL != 860 && \ PROTOCOL != 860 && \
PROTOCOL != 861 && \ PROTOCOL != 861 && \
PROTOCOL != 862 && \ PROTOCOL != 862 && \
PROTOCOL != 870 PROTOCOL != 870 && \
PROTOCOL != 910
#error "the supplied protocol version is not supported" #error "the supplied protocol version is not supported"
#endif #endif
@ -53,9 +54,10 @@ namespace Proto {
constexpr int PicSignature = 0x4E119CBF; constexpr int PicSignature = 0x4E119CBF;
enum OsTypes { enum OsTypes {
OsWindows = 1, OsLinux = 1,
OsLinux = 2, OsWindows = 2,
OsMac = 3 OsFlash = 3,
OsMac = 4
}; };
#ifdef OSTYPE #ifdef OSTYPE
@ -132,8 +134,8 @@ namespace Proto {
GameServerPlayerSkills = 161, GameServerPlayerSkills = 161,
GameServerPlayerState = 162, GameServerPlayerState = 162,
GameServerClearTarget = 163, GameServerClearTarget = 163,
GameServerSpellDelay = 164, GameServerSpellDelay = 164, // 870
GameServerSpellGroupDelay = 165, GameServerSpellGroupDelay = 165, // 870
GameServerTalk = 170, GameServerTalk = 170,
GameServerChannels = 171, GameServerChannels = 171,
GameServerOpenChannel = 172, GameServerOpenChannel = 172,
@ -158,8 +160,8 @@ namespace Proto {
GameServerQuestLog = 240, GameServerQuestLog = 240,
GameServerQuestLine = 241, GameServerQuestLine = 241,
GameServerChannelEvent = 243, GameServerChannelEvent = 243,
GameServerObjectInfo = 244, GameServerObjectInfo = 244, // 910
GameServerPlayerInventory = 245, GameServerPlayerInventory = 245, // 910
GameServerExtendedOpcode = 254 // otclient only GameServerExtendedOpcode = 254 // otclient only
}; };
@ -182,7 +184,7 @@ namespace Proto {
ClientTurnEast = 112, ClientTurnEast = 112,
ClientTurnSouth = 113, ClientTurnSouth = 113,
ClientTurnWest = 114, ClientTurnWest = 114,
//ClientEquipObject = 119, ClientEquipObject = 119, // 910
ClientMove = 120, ClientMove = 120,
ClientInspectNpcTrade = 121, ClientInspectNpcTrade = 121,
ClientBuyItem = 122, ClientBuyItem = 122,
@ -232,19 +234,46 @@ namespace Proto {
ClientDebugReport = 232, ClientDebugReport = 232,
ClientRequestQuestLog = 240, ClientRequestQuestLog = 240,
ClientRequestQuestLine = 241, ClientRequestQuestLine = 241,
//ClientRuleViolationReport = 242, ClientRuleViolationReport = 242, // 910
//ClientGetObjectInfo = 243 ClientGetObjectInfo = 243, // 910
ClientExtendedOpcode = 254 // otclient only ClientExtendedOpcode = 254 // otclient only
}; };
enum ServerSpeakType { enum ServerSpeakType {
#if PROTOCOL>=861 #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, ServerSpeakSay = 1,
ServerSpeakWhisper, ServerSpeakWhisper,
ServerSpeakYell, ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc, ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer, ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivate, ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow, ServerSpeakChannelYellow,
ServerSpeakChannelWhite, ServerSpeakChannelWhite,
ServerSpeakBroadcast, ServerSpeakBroadcast,
@ -265,7 +294,8 @@ namespace Proto {
ServerSpeakYell, ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc, ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer, ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivate, ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow, ServerSpeakChannelYellow,
ServerSpeakChannelWhite, ServerSpeakChannelWhite,
ServerSpeakRVRChannel, ServerSpeakRVRChannel,
@ -273,7 +303,8 @@ namespace Proto {
ServerSpeakRVRContinue, ServerSpeakRVRContinue,
ServerSpeakBroadcast, ServerSpeakBroadcast,
ServerSpeakChannelRed, ServerSpeakChannelRed,
ServerSpeakPrivateRed, ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange, ServerSpeakChannelOrange,
// 16 ?? // 16 ??
ServerSpeakChannelRed2 = 17, ServerSpeakChannelRed2 = 17,
@ -284,14 +315,16 @@ namespace Proto {
ServerSpeakSay = 1, ServerSpeakSay = 1,
ServerSpeakWhisper, ServerSpeakWhisper,
ServerSpeakYell, ServerSpeakYell,
ServerSpeakPrivate, ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow, ServerSpeakChannelYellow,
ServerSpeakRVRChannel, ServerSpeakRVRChannel,
ServerSpeakRVRAnswer, ServerSpeakRVRAnswer,
ServerSpeakRVRContinue, ServerSpeakRVRContinue,
ServerSpeakBroadcast, ServerSpeakBroadcast,
ServerSpeakChannelRed, ServerSpeakChannelRed,
ServerSpeakPrivateRed, ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange, ServerSpeakChannelOrange,
// 13 ?? // 13 ??
ServerSpeakChannelRed2 = 14, ServerSpeakChannelRed2 = 14,
@ -307,7 +340,39 @@ namespace Proto {
}; };
enum MessageTypes { enum MessageTypes {
#if PROTOCOL>=861 #if PROTOCOL>=910
// 1-3 ??
MessageConsoleBlue = 4, // old
// 5-11 ??
MessageConsoleRed = 12, // old
// 13-15 ??
MessageStatusDefault = 16, // old
MessageWarning, // old
MessageEventAdvance, // old
MessageStatusSmall, // old
MessageInfoDescription, // old
MessageDamageDealt, // new
MessageDamageReceived, // new
MessageHealed, // new
MessageExperience, // new
MessageDamageOthers, // new
MessageHealedOthers, // new
MessageExperienceOthers, // new
MessageEventDefault, // old
MessageLoot, // new
MessageTradeNpc, // unused
MessageChannelGuild, // new
MessagePartyManagment, // unused
MessageParty, // unused
MessageEventOrange, // old
MessageConsoleOrange, // old
MessageReport, // unused
MessageHotkeyUse, // unused
MessageTutorialHint, // unused
// unsupported
MessageConsoleOrange2 = 255
#elif PROTOCOL>=861
MessageConsoleOrange = 13, MessageConsoleOrange = 13,
MessageConsoleOrange2, MessageConsoleOrange2,
MessageWarning, MessageWarning,
@ -345,6 +410,12 @@ namespace Proto {
#endif #endif
}; };
enum CreatureType {
CreatureTypePlayer = 0,
CreatureTypeMonster,
CreatureTypeNpc
};
enum CreaturesIdRange { enum CreaturesIdRange {
PlayerStartId = 0x10000000, PlayerStartId = 0x10000000,
PlayerEndId = 0x40000000, PlayerEndId = 0x40000000,
@ -367,10 +438,10 @@ namespace Proto {
case Proto::ServerSpeakChannelRed: return Otc::SpeakChannelRed; case Proto::ServerSpeakChannelRed: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelRed2: return Otc::SpeakChannelRed; case Proto::ServerSpeakChannelRed2: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelOrange: return Otc::SpeakChannelOrange; case Proto::ServerSpeakChannelOrange: return Otc::SpeakChannelOrange;
case Proto::ServerSpeakPrivate: return Otc::SpeakPrivate; case Proto::ServerSpeakPrivateTo: return Otc::SpeakPrivate;
case Proto::ServerSpeakPrivatePlayerToNpc: return Otc::SpeakPrivate; case Proto::ServerSpeakPrivatePlayerToNpc: return Otc::SpeakPrivate;
case Proto::ServerSpeakBroadcast: return Otc::SpeakBroadcast; case Proto::ServerSpeakBroadcast: return Otc::SpeakBroadcast;
case Proto::ServerSpeakPrivateRed: return Otc::SpeakPrivateRed; case Proto::ServerSpeakPrivateRedTo: return Otc::SpeakPrivateRed;
default: default:
logError("unknown protocol speak type ", type); logError("unknown protocol speak type ", type);
return Otc::SpeakSay; return Otc::SpeakSay;
@ -383,8 +454,8 @@ namespace Proto {
case Otc::SpeakWhisper: return Proto::ServerSpeakWhisper; case Otc::SpeakWhisper: return Proto::ServerSpeakWhisper;
case Otc::SpeakYell: return Proto::ServerSpeakYell; case Otc::SpeakYell: return Proto::ServerSpeakYell;
case Otc::SpeakBroadcast: return Proto::ServerSpeakBroadcast; case Otc::SpeakBroadcast: return Proto::ServerSpeakBroadcast;
case Otc::SpeakPrivate: return Proto::ServerSpeakPrivate; case Otc::SpeakPrivate: return Proto::ServerSpeakPrivateFrom;
case Otc::SpeakPrivateRed: return Proto::ServerSpeakPrivateRed; case Otc::SpeakPrivateRed: return Proto::ServerSpeakPrivateRedFrom;
case Otc::SpeakPrivatePlayerToNpc: return Proto::ServerSpeakPrivatePlayerToNpc; case Otc::SpeakPrivatePlayerToNpc: return Proto::ServerSpeakPrivatePlayerToNpc;
case Otc::SpeakPrivateNpcToPlayer: return Proto::ServerSpeakPrivateNpcToPlayer; case Otc::SpeakPrivateNpcToPlayer: return Proto::ServerSpeakPrivateNpcToPlayer;
case Otc::SpeakChannelYellow: return Proto::ServerSpeakChannelYellow; case Otc::SpeakChannelYellow: return Proto::ServerSpeakChannelYellow;

View File

@ -181,6 +181,9 @@ private:
void parseAutomapFlag(InputMessage& msg); void parseAutomapFlag(InputMessage& msg);
void parseQuestLog(InputMessage& msg); void parseQuestLog(InputMessage& msg);
void parseQuestLine(InputMessage& msg); void parseQuestLine(InputMessage& msg);
void parseChannelEvent(InputMessage& msg);
void parseObjectInfo(InputMessage& msg);
void parsePlayerInventory(InputMessage& msg);
void parseExtendedOpcode(InputMessage& msg); void parseExtendedOpcode(InputMessage& msg);
void setMapDescription(InputMessage& msg, int x, int y, int z, int width, int height); void setMapDescription(InputMessage& msg, int x, int y, int z, int width, int height);

View File

@ -41,6 +41,7 @@ void ProtocolGame::parseMessage(InputMessage& msg)
try { try {
while(!msg.eof()) { while(!msg.eof()) {
opcode = msg.getU8(); opcode = msg.getU8();
//dump << opcode;
if(m_firstPacket) { if(m_firstPacket) {
if(opcode != Proto::GameServerInitGame) if(opcode != Proto::GameServerInitGame)
@ -67,7 +68,6 @@ void ProtocolGame::parseMessage(InputMessage& msg)
case Proto::GameServerPing: case Proto::GameServerPing:
parsePing(msg); parsePing(msg);
break; break;
//case Proto::GameServerChallange:
case Proto::GameServerDeath: case Proto::GameServerDeath:
parseDeath(msg); parseDeath(msg);
break; break;
@ -155,7 +155,6 @@ void ProtocolGame::parseMessage(InputMessage& msg)
case Proto::GameServerMarkCreature: case Proto::GameServerMarkCreature:
parseCreatureMark(msg); parseCreatureMark(msg);
break; break;
//case Proto::GameServerTrappers
case Proto::GameServerCreatureHealth: case Proto::GameServerCreatureHealth:
parseCreatureHealth(msg); parseCreatureHealth(msg);
break; break;
@ -195,14 +194,6 @@ void ProtocolGame::parseMessage(InputMessage& msg)
case Proto::GameServerClearTarget: case Proto::GameServerClearTarget:
parsePlayerCancelAttack(msg); parsePlayerCancelAttack(msg);
break; break;
#if PROTOCOL>=870
case Proto::GameServerSpellDelay:
parseSpellDelay(msg);
break;
case Proto::GameServerSpellGroupDelay:
parseSpellGroupDelay(msg);
break;
#endif
case Proto::GameServerTalk: case Proto::GameServerTalk:
parseCreatureSpeak(msg); parseCreatureSpeak(msg);
break; break;
@ -239,7 +230,6 @@ void ProtocolGame::parseMessage(InputMessage& msg)
case Proto::GameServerCancelWalk: case Proto::GameServerCancelWalk:
parseCancelWalk(msg); parseCancelWalk(msg);
break; break;
//case Proto::GameServerWait:
case Proto::GameServerFloorChangeUp: case Proto::GameServerFloorChangeUp:
parseFloorChangeUp(msg); parseFloorChangeUp(msg);
break; break;
@ -270,12 +260,33 @@ void ProtocolGame::parseMessage(InputMessage& msg)
case Proto::GameServerQuestLine: case Proto::GameServerQuestLine:
parseQuestLine(msg); parseQuestLine(msg);
break; break;
//case Proto::GameServerChannelEvent: #if PROTOCOL>=870
//case Proto::GameServerObjectInfo: case Proto::GameServerSpellDelay: // 870 only
//case Proto::GameServerPlayerInventory: parseSpellDelay(msg);
case Proto::GameServerExtendedOpcode: // additional opcode used by otclient break;
case Proto::GameServerSpellGroupDelay: // 870 only
parseSpellGroupDelay(msg);
break;
#endif
#if PROTOCOL>=910
case Proto::GameServerChannelEvent: // 910 only
parseChannelEvent(msg);
break;
case Proto::GameServerObjectInfo: // 910 only
parseObjectInfo(msg);
break;
case Proto::GameServerPlayerInventory: // 910 only
parsePlayerInventory(msg);
break;
#endif
// additional opcode used by otclient only
case Proto::GameServerExtendedOpcode:
parseExtendedOpcode(msg); parseExtendedOpcode(msg);
break; break;
// not handled yet
//case Proto::GameServerChallange:
//case Proto::GameServerTrappers
//case Proto::GameServerWait:
default: default:
Fw::throwException("unknown opcode"); Fw::throwException("unknown opcode");
break; break;
@ -520,6 +531,12 @@ void ProtocolGame::parseRemoveInventoryItem(InputMessage& msg)
void ProtocolGame::parseOpenNpcTrade(InputMessage& msg) void ProtocolGame::parseOpenNpcTrade(InputMessage& msg)
{ {
std::vector<std::tuple<ItemPtr, std::string, int, int, int>> items; std::vector<std::tuple<ItemPtr, std::string, int, int, int>> items;
std::string npcName;
#if PROTOCOL>=910
npcName = msg.getString();
#endif
int listCount = msg.getU8(); int listCount = msg.getU8();
for(int i = 0; i < listCount; ++i) { for(int i = 0; i < listCount; ++i) {
uint16 itemId = msg.getU16(); uint16 itemId = msg.getU16();
@ -600,12 +617,7 @@ void ProtocolGame::parseWorldLight(InputMessage& msg)
void ProtocolGame::parseMagicEffect(InputMessage& msg) void ProtocolGame::parseMagicEffect(InputMessage& msg)
{ {
Position pos = parsePosition(msg); Position pos = parsePosition(msg);
#if PROTOCOL>=854
// newer tibia decreased the max effects number, why???
int effectId = msg.getU8(); int effectId = msg.getU8();
#else
int effectId = msg.getU16();
#endif
EffectPtr effect = EffectPtr(new Effect()); EffectPtr effect = EffectPtr(new Effect());
effect->setId(effectId); effect->setId(effectId);
@ -777,6 +789,9 @@ void ProtocolGame::parsePlayerStats(InputMessage& msg)
#else #else
double freeCapacity = msg.getU16() / 100.0; double freeCapacity = msg.getU16() / 100.0;
#endif #endif
#if PROTOCOL>=910
msg.getU32(); // total capacity
#endif
#if PROTOCOL>=870 #if PROTOCOL>=870
double experience = msg.getU64(); double experience = msg.getU64();
#else #else
@ -787,6 +802,9 @@ void ProtocolGame::parsePlayerStats(InputMessage& msg)
double mana = msg.getU16(); double mana = msg.getU16();
double maxMana = msg.getU16(); double maxMana = msg.getU16();
double magicLevel = msg.getU8(); double magicLevel = msg.getU8();
#if PROTOCOL>=910
msg.getU8(); // base magic level
#endif
double magicLevelPercent = msg.getU8(); double magicLevelPercent = msg.getU8();
double soul = msg.getU8(); double soul = msg.getU8();
double stamina = msg.getU16(); double stamina = msg.getU16();
@ -799,17 +817,22 @@ void ProtocolGame::parsePlayerStats(InputMessage& msg)
m_localPlayer->setMagicLevel(magicLevel, magicLevelPercent); m_localPlayer->setMagicLevel(magicLevel, magicLevelPercent);
m_localPlayer->setStamina(stamina); m_localPlayer->setStamina(stamina);
m_localPlayer->setSoul(soul); m_localPlayer->setSoul(soul);
#if PROTOCOL>=910
int speed = msg.getU16();
msg.getU16(); // regeneration time
m_localPlayer->setSpeed(speed);
#endif
} }
void ProtocolGame::parsePlayerSkills(InputMessage& msg) void ProtocolGame::parsePlayerSkills(InputMessage& msg)
{ {
if(!m_localPlayer) {
logTraceError("there is no local player");
return;
}
for(int skill = 0; skill < Otc::LastSkill; skill++) { for(int skill = 0; skill < Otc::LastSkill; skill++) {
int level = msg.getU8(); int level = msg.getU8();
#if PROTOCOL>=910
msg.getU8(); // base
#endif
int levelPercent = msg.getU8(); int levelPercent = msg.getU8();
m_localPlayer->setSkill((Otc::Skill)skill, level, levelPercent); m_localPlayer->setSkill((Otc::Skill)skill, level, levelPercent);
@ -818,13 +841,8 @@ void ProtocolGame::parsePlayerSkills(InputMessage& msg)
void ProtocolGame::parsePlayerState(InputMessage& msg) void ProtocolGame::parsePlayerState(InputMessage& msg)
{ {
if(!m_localPlayer) {
logTraceError("there is no local player");
return;
}
int states = msg.getU16(); int states = msg.getU16();
m_localPlayer->setStates((Otc::PlayerStates)states); m_localPlayer->setStates(states);
} }
void ProtocolGame::parsePlayerCancelAttack(InputMessage& msg) void ProtocolGame::parsePlayerCancelAttack(InputMessage& msg)
@ -852,7 +870,7 @@ void ProtocolGame::parseSpellGroupDelay(InputMessage& msg)
void ProtocolGame::parseCreatureSpeak(InputMessage& msg) void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
{ {
msg.getU32(); // unknown msg.getU32(); // channel statement guid
std::string name = msg.getString(); std::string name = msg.getString();
int level = msg.getU16(); int level = msg.getU16();
@ -876,16 +894,18 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
case Proto::ServerSpeakChannelOrange: case Proto::ServerSpeakChannelOrange:
channelId = msg.getU16(); channelId = msg.getU16();
break; break;
case Proto::ServerSpeakPrivate: case Proto::ServerSpeakPrivateFrom:
case Proto::ServerSpeakPrivatePlayerToNpc: case Proto::ServerSpeakPrivatePlayerToNpc:
case Proto::ServerSpeakBroadcast: case Proto::ServerSpeakBroadcast:
case Proto::ServerSpeakPrivateRed: case Proto::ServerSpeakPrivateRedFrom:
break; break;
case Proto::ServerSpeakRVRChannel: case Proto::ServerSpeakRVRChannel:
msg.getU32(); msg.getU32();
break; break;
//case Proto::ServerSpeakChannelManagement:
//case Proto::ServerSpeakSpell:
default: default:
logTraceError("unknown speak type ", speakType); Fw::throwException("unknown speak type ", speakType);
break; break;
} }
@ -1106,6 +1126,23 @@ void ProtocolGame::parseQuestLine(InputMessage& msg)
g_game.processQuestLine(questId, questMissions); g_game.processQuestLine(questId, questMissions);
} }
void ProtocolGame::parseChannelEvent(InputMessage& msg)
{
msg.getU16(); // channel id
msg.getString(); // player name
msg.getU8(); // event type
}
void ProtocolGame::parseObjectInfo(InputMessage& msg)
{
//TODO
}
void ProtocolGame::parsePlayerInventory(InputMessage& msg)
{
//TODO
}
void ProtocolGame::parseExtendedOpcode(InputMessage& msg) void ProtocolGame::parseExtendedOpcode(InputMessage& msg)
{ {
int opcode = msg.getU8(); int opcode = msg.getU8();
@ -1162,11 +1199,16 @@ void ProtocolGame::setFloorDescription(InputMessage& msg, int32 x, int32 y, int3
void ProtocolGame::setTileDescription(InputMessage& msg, Position position) void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
{ {
#if PROTOCOL>=910
msg.getU16(); // environment effect
#endif
int stackPos = 0; int stackPos = 0;
while(true) { while(true) {
int inspectItemId = msg.getU16(true); int inspectItemId = msg.getU16(true);
if(inspectItemId >= 0xFF00) if(inspectItemId >= 0xFF00) {
return; return;
}
else { else {
if(stackPos >= 10) if(stackPos >= 10)
logTraceError("too many things, stackpos=", stackPos, " pos=", position); logTraceError("too many things, stackpos=", stackPos, " pos=", position);
@ -1222,9 +1264,8 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg)
ThingPtr thing; ThingPtr thing;
int thingId = msg.getU16(); int thingId = msg.getU16();
if(thingId == 0) { if(thingId == 0)
Fw::throwException("[ProtocolGame::internalGetThing] thingId == 0"); Fw::throwException("thingId == 0");
}
if(thingId == 0x0061 || thingId == 0x0062) { // add new creature if(thingId == 0x0061 || thingId == 0x0062) { // add new creature
CreaturePtr creature; CreaturePtr creature;
@ -1240,6 +1281,18 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg)
} else if(thingId == 0x0061) { //creature is not known } else if(thingId == 0x0061) { //creature is not known
uint removeId = msg.getU32(); uint removeId = msg.getU32();
uint id = msg.getU32(); uint id = msg.getU32();
int creatureType;
#if PROTOCOL>=910
creatureType = msg.getU8();
#else
if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId)
creatureType = Proto::CreatureTypePlayer;
else if(id >= Proto::MonsterStartId && id < Proto::MonsterEndId)
creatureType = Proto::CreatureTypeMonster;
else
creatureType = Proto::CreatureTypeNpc;
#endif
std::string name = msg.getString(); std::string name = msg.getString();
if(name.length() > 0) // every creature name must start with a capital letter if(name.length() > 0) // every creature name must start with a capital letter
@ -1249,14 +1302,14 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg)
if(id == m_localPlayer->getId()) if(id == m_localPlayer->getId())
creature = m_localPlayer; creature = m_localPlayer;
else if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId) else if(creatureType == Proto::CreatureTypePlayer)
creature = PlayerPtr(new Player); creature = PlayerPtr(new Player);
else if(id >= Proto::MonsterStartId && id < Proto::MonsterEndId) else if(creatureType == Proto::CreatureTypeMonster)
creature = MonsterPtr(new Monster); creature = MonsterPtr(new Monster);
else if(id >= Proto::NpcStartId && id < Proto::NpcEndId) else if(creatureType == Proto::CreatureTypeNpc)
creature = NpcPtr(new Npc); creature = NpcPtr(new Npc);
else else
logTraceError("creature id is invalid"); logTraceError("creature type is invalid");
if(creature) { if(creature) {
creature->setId(id); creature->setId(id);
@ -1321,9 +1374,20 @@ ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, int id)
id = msg.getU16(); id = msg.getU16();
ItemPtr item = Item::create(id); ItemPtr item = Item::create(id);
if(item->getId() == 0)
Fw::throwException("unable to create item with invalid id");
if(item->isStackable() || item->isFluidContainer() || item->isFluid()) if(item->isStackable() || item->isFluidContainer() || item->isFluid())
item->setCountOrSubType(msg.getU8()); item->setCountOrSubType(msg.getU8());
#if PROTOCOL>=910
if(item->getAnimationPhases() > 1) {
// 0xfe => random phase
// 0xff => async?
msg.getU8();
}
#endif
return item; return item;
} }

View File

@ -406,8 +406,8 @@ void ProtocolGame::sendTalk(Otc::SpeakType speakType, int channelId, const std::
msg.addU8(serverSpeakType); msg.addU8(serverSpeakType);
switch(serverSpeakType) { switch(serverSpeakType) {
case Proto::ServerSpeakPrivate: case Proto::ServerSpeakPrivateFrom:
case Proto::ServerSpeakPrivateRed: case Proto::ServerSpeakPrivateRedFrom:
msg.addString(receiver); msg.addString(receiver);
break; break;
case Proto::ServerSpeakChannelYellow: case Proto::ServerSpeakChannelYellow:
@ -530,7 +530,9 @@ void ProtocolGame::sendShareExperience(bool active, int unknown)
OutputMessage msg; OutputMessage msg;
msg.addU8(Proto::ClientShareExperience); msg.addU8(Proto::ClientShareExperience);
msg.addU8(active ? 0x01 : 0x00); msg.addU8(active ? 0x01 : 0x00);
#if PROTOCOL<910
msg.addU8(unknown); msg.addU8(unknown);
#endif
send(msg); send(msg);
} }