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[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[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
local healthBarWindow

View File

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

View File

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

View File

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