void ProtocolGame::parseCreatureHealth(InputMessage& msg) { uint id = msg.getU32(); int healthPercent = msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setHealthPercent(healthPercent); }
void ProtocolGame::parseCreatureSquare(InputMessage& msg) { uint id = msg.getU32(); int color = msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->addVolatileSquare(color); }
void ProtocolGame::parseCreatureShields(InputMessage& msg) { uint id = msg.getU32(); int shield = msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setShield(shield); }
void ProtocolGame::parseCreatureTurn(InputMessage& msg) { uint id = msg.getU32(); Otc::Direction direction = (Otc::Direction)msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->turn(direction); }
void ProtocolGame::parseCreatureSkulls(InputMessage& msg) { uint id = msg.getU32(); int skull = msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setSkull(skull); }
void ProtocolGame::parseCreatureSpeed(InputMessage& msg) { uint id = msg.getU32(); int speed = msg.getU16(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setSpeed(speed); }
void ProtocolGame::parseCreatureOutfit(InputMessage& msg) { uint id = msg.getU32(); Outfit outfit = internalGetOutfit(msg); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setOutfit(outfit); }
void ProtocolGame::parseCreatureLight(InputMessage& msg) { uint id = msg.getU32(); Light light; light.intensity = msg.getU8(); light.color = msg.getU8(); CreaturePtr creature = g_map.getCreatureById(id); if(creature) creature->setLight(light); }
bool Tile::isWalkable(bool ignoreCreatures) { if(!getGround()) return false; for(const ThingPtr& thing : m_things) { if(thing->isNotWalkable()) return false; if(!ignoreCreatures) { if(thing->isCreature()) { CreaturePtr creature = thing->static_self_cast<Creature>(); if(!creature->isPassable() && creature->canBeSeen()) return false; } } } return true; }
void Game::follow(const CreaturePtr& creature) { if(!canPerformGameAction() || creature == m_localPlayer || creature == m_followingCreature) return; if(creature && isAttacking()) cancelAttack(); setFollowingCreature(creature); m_protocolGame->sendFollow(creature ? creature->getId() : 0, ++m_seq); }
void Game::processOpenOutfitWindow(const Outfit& currentOufit, const std::vector<std::tuple<int, std::string, int> >& outfitList, const std::vector<std::tuple<int, std::string> >& mountList) { // create virtual creature outfit CreaturePtr virtualOutfitCreature = CreaturePtr(new Creature); virtualOutfitCreature->setDirection(Otc::South); Outfit outfit = currentOufit; outfit.setMount(0); virtualOutfitCreature->setOutfit(outfit); // creature virtual mount outfit CreaturePtr virtualMountCreature = nullptr; if(getFeature(Otc::GamePlayerMounts)) { virtualMountCreature = CreaturePtr(new Creature); virtualMountCreature->setDirection(Otc::South); if(currentOufit.getMount() > 0) { Outfit mountOutfit; mountOutfit.setId(currentOufit.getMount()); virtualMountCreature->setOutfit(mountOutfit); } } g_lua.callGlobalField("g_game", "onOpenOutfitWindow", virtualOutfitCreature, outfitList, virtualMountCreature, mountList); }
void ProtocolGame::parseOutfitWindow(InputMessage& msg) { Outfit outfit = internalGetOutfit(msg); typedef std::tuple<int, std::string, int> OutfitInfo; std::vector<OutfitInfo> outfitList; uint8 outfitCount = msg.getU8(); for(int i = 0; i < outfitCount; i++) { uint16 outfitId = msg.getU16(); std::string outfitName = msg.getString(); uint8 outfitAddons = msg.getU8(); outfitList.push_back(OutfitInfo(outfitId, outfitName, outfitAddons)); } CreaturePtr creature = CreaturePtr(new Creature); creature->setXPattern(2); creature->setOutfit(outfit); g_lua.callGlobalField("Game", "onOpenOutfitWindow", creature, outfitList); }
void Game::follow(CreaturePtr creature) { if(!canPerformGameAction() || creature == m_localPlayer) return; // cancel when following again if(creature && creature == m_followingCreature) creature = nullptr; if(creature && isAttacking()) cancelAttack(); setFollowingCreature(creature); m_localPlayer->stopAutoWalk(); if(m_protocolVersion >= 963) { if(creature) m_seq = creature->getId(); } else m_seq++; m_protocolGame->sendFollow(creature ? creature->getId() : 0, m_seq); }
void LocalPlayer::setFollowingCreature(const CreaturePtr& creature) { // clear current following creature if(m_followingCreature) { m_followingCreature->hideStaticSquare(); m_followingCreature = nullptr; } // set the new attacking creature if(creature) { creature->showStaticSquare(Fw::green); m_followingCreature = creature; } }
void Map::addCreature(const CreaturePtr& creature) { m_knownCreatures[creature->getId()] = creature; }
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView) { bool animate = drawFlags & Otc::DrawAnimations; /* Flags to be checked for. */ static const tileflags_t flags[] = { TILESTATE_HOUSE, TILESTATE_PROTECTIONZONE, TILESTATE_OPTIONALZONE, TILESTATE_HARDCOREZONE, TILESTATE_NOLOGOUT }; // first bottom items if(drawFlags & (Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawOnBottom)) { m_drawElevation = 0; for(const ThingPtr& thing : m_things) { if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) break; bool restore = false; if(g_map.showZones() && thing->isGround()) { for(unsigned int i = 0; i < sizeof(flags) / sizeof(tileflags_t); ++i) { tileflags_t flag = flags[i]; if(hasFlag(flag) && g_map.showZone(flag)) { g_painter->setOpacity(g_map.getZoneOpacity()); g_painter->setColor(g_map.getZoneColor(flag)); restore = true; break; } } } if((thing->isGround() && drawFlags & Otc::DrawGround) || (thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) || (thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) { thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); if(restore) { g_painter->resetOpacity(); g_painter->resetColor(); } } m_drawElevation += thing->getElevation(); if(m_drawElevation > Otc::MAX_ELEVATION) m_drawElevation = Otc::MAX_ELEVATION; } } int redrawPreviousTopW = 0; int redrawPreviousTopH = 0; if(drawFlags & Otc::DrawItems) { // now common items in reverse order for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const ThingPtr& thing = *it; if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature()) break; thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); if(thing->isLyingCorpse()) { redrawPreviousTopW = std::max(thing->getWidth(), redrawPreviousTopW); redrawPreviousTopH = std::max(thing->getHeight(), redrawPreviousTopH); } m_drawElevation += thing->getElevation(); if(m_drawElevation > Otc::MAX_ELEVATION) m_drawElevation = Otc::MAX_ELEVATION; } } // after we render 2x2 lying corpses, we must redraw previous creatures/ontop above them if(redrawPreviousTopH > 0 || redrawPreviousTopW > 0) { int topRedrawFlags = drawFlags & (Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawOnTop | Otc::DrawAnimations); if(topRedrawFlags) { for(int x=-redrawPreviousTopW;x<=0;++x) { for(int y=-redrawPreviousTopH;y<=0;++y) { if(x == 0 && y == 0) continue; const TilePtr& tile = g_map.getTile(m_position.translated(x,y)); if(tile) tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags); } } } } // creatures if(drawFlags & Otc::DrawCreatures) { if(animate) { for(const CreaturePtr& creature : m_walkingCreatures) { creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor, dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor), scaleFactor, animate, lightView); } } for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const ThingPtr& thing = *it; if(!thing->isCreature()) continue; CreaturePtr creature = thing->static_self_cast<Creature>(); if(creature && (!creature->isWalking() || !animate)) creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); } } // effects if(drawFlags & Otc::DrawEffects) for(const EffectPtr& effect : m_effects) effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); // top items if(drawFlags & Otc::DrawOnTop) for(const ThingPtr& thing : m_things) if(thing->isOnTop()) thing->draw(dest, scaleFactor, animate, lightView); // draw translucent light (for tiles beneath holes) if(hasTranslucentLight() && lightView) { Light light; light.intensity = 1; lightView->addLightSource(dest + Point(16,16) * scaleFactor, scaleFactor, light); } }
ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) { ThingPtr thing; int thingId = msg.getU16(); assert(thingId != 0); if(thingId == 0x0061 || thingId == 0x0062) { // add new creature CreaturePtr creature; if(thingId == 0x0062) { //creature is known uint id = msg.getU32(); CreaturePtr knownCreature = g_map.getCreatureById(id); if(knownCreature) creature = knownCreature; else logTraceError("server says creature is known, but its not on creatures list"); } else if(thingId == 0x0061) { //creature is not known uint removeId = msg.getU32(); uint id = msg.getU32(); std::string name = msg.getString(); if(name.length() > 0) // every creature name must start with a capital letter name[0] = toupper(name[0]); g_map.removeCreatureById(removeId); if(id == m_localPlayer->getId()) creature = m_localPlayer; else if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId) creature = PlayerPtr(new Player); else if(id >= Proto::MonsterStartId && id < Proto::MonsterEndId) creature = MonsterPtr(new Monster); else if(id >= Proto::NpcStartId && id < Proto::NpcEndId) creature = NpcPtr(new Npc); else logTraceError("creature id is invalid"); creature->setId(id); creature->setName(name); } uint8 healthPercent = msg.getU8(); Otc::Direction direction = (Otc::Direction)msg.getU8(); Outfit outfit = internalGetOutfit(msg); Light light; light.intensity = msg.getU8(); light.color = msg.getU8(); int speed = msg.getU16(); int skull = msg.getU8(); int shield = msg.getU8(); int emblem = -1; if(thingId == 0x0061) // emblem is sent only in packet type 0x61 emblem = msg.getU8(); bool passable = (msg.getU8() == 0); if(creature) { creature->setHealthPercent(healthPercent); creature->setDirection(direction); creature->setOutfit(outfit); creature->setLight(light); creature->setSpeed(speed); creature->setSkull(skull); creature->setShield(shield); if(emblem != -1) creature->setEmblem(emblem); creature->setPassable(passable); creature->setDirection(direction); if(creature == m_localPlayer) { m_localPlayer->setKnown(true); } } thing = creature; } else if(thingId == 0x0063) { // creature turn parseCreatureTurn(msg); } else // item thing = internalGetItem(msg, thingId); return thing; }
void Game::requestTrade(const ItemPtr& item, const CreaturePtr& creature) { if(!canPerformGameAction() || !item || !creature) return; m_protocolGame->sendRequestTrade(item->getPosition(), item->getId(), item->getStackpos(), creature->getId()); }
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *lightView) { bool animate = drawFlags & Otc::DrawAnimations; // Added for MapEditor purposes. // This check will and must evaluate to false if using // normal client, unless some flag error. // Save last color Color lastColor = g_painter->getColor(); if((m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE) g_painter->setColor(Color::blue); else if((m_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) g_painter->setColor(Color::green); // first bottom items if(drawFlags & (Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawOnBottom)) { m_drawElevation = 0; for(const ThingPtr& thing : m_things) { if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) break; if((thing->isGround() && drawFlags & Otc::DrawGround) || (thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) || (thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) { thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); } m_drawElevation += thing->getElevation(); if(m_drawElevation > Otc::MAX_ELEVATION) m_drawElevation = Otc::MAX_ELEVATION; } } int redrawPreviousTopW = 0; int redrawPreviousTopH = 0; if(drawFlags & Otc::DrawItems) { // now common items in reverse order for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const ThingPtr& thing = *it; if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->isCreature()) break; thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); if(thing->isLyingCorpse()) { redrawPreviousTopW = std::max(thing->getWidth(), redrawPreviousTopW); redrawPreviousTopH = std::max(thing->getHeight(), redrawPreviousTopH); } m_drawElevation += thing->getElevation(); if(m_drawElevation > Otc::MAX_ELEVATION) m_drawElevation = Otc::MAX_ELEVATION; } } // after we render 2x2 lying corpses, we must redraw previous creatures/ontop above them if(redrawPreviousTopH > 0 || redrawPreviousTopW > 0) { int topRedrawFlags = drawFlags & (Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawOnTop | Otc::DrawAnimations); if(topRedrawFlags) { for(int x=-redrawPreviousTopW;x<=0;++x) { for(int y=-redrawPreviousTopH;y<=0;++y) { if(x == 0 && y == 0) continue; const TilePtr& tile = g_map.getTile(m_position.translated(x,y)); if(tile) tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags); } } } } // creatures if(drawFlags & Otc::DrawCreatures) { if(animate) { for(const CreaturePtr& creature : m_walkingCreatures) { creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor, dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - m_drawElevation)*scaleFactor), scaleFactor, animate, lightView); } } for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { const ThingPtr& thing = *it; if(!thing->isCreature()) continue; CreaturePtr creature = thing->static_self_cast<Creature>(); if(creature && (!creature->isWalking() || !animate)) creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); } } // effects if(drawFlags & Otc::DrawEffects) { for(const EffectPtr& effect : m_effects){ effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView); } } // top items if(drawFlags & Otc::DrawOnTop) { for(const ThingPtr& thing : m_things) { if(thing->isOnTop()){ thing->draw(dest, scaleFactor, animate, lightView); } } } // draw translucent light (for tiles beneath holes) if(hasTranslucentLight() && lightView) { Light light; light.intensity = 1; lightView->addLightSource(dest + Point(16,16) * scaleFactor, scaleFactor, light); } // Restore color g_painter->setColor(lastColor); }