#include "InventoryView.h" #include #include #include "DragController.h" #include "Game.h" #include "Globals.h" #include "UIMLToolTip.h" using namespace Framework; InventoryElement::InventoryElement() : UIMLElement() {} //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig ist bool InventoryElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("inventory"); } //! erstellt eine neue Zeichnung zu einem gegebenen xml Element Framework::Zeichnung* InventoryElement::parseElement( Framework::XML::Element& element, Framework::UIMLContainer& generalFactory) { Text targetValue = element.getAttributeValue("target"); Vec3 blockPos(0, 0, 0); Framework::Either> target((int)targetValue); if (targetValue.hat(',')) { Text* first = targetValue.getTeilText(0, targetValue.positionVon(",", 0) + 1); Text* second = targetValue.getTeilText(targetValue.positionVon(",", 0) + 1, targetValue.positionVon(",", 1)); Text* third = targetValue.getTeilText(targetValue.positionVon(",", 1) + 1, targetValue.positionVon(",", 2)); Text* forth = targetValue.getTeilText(targetValue.positionVon(",", 2) + 1); target = Framework::Either>(Framework::VecN( {(int)*first, (int)*second, (int)*third, (int)*forth})); first->release(); second->release(); third->release(); forth->release(); } return new InventoryView(element.getAttributeValue("id"), target, (int)element.getAttributeValue("rowSize"), element.getAttributeValue("slotNameFilter")); } bool InventoryElement::updateElement(Framework::XML::Element& element, Framework::Zeichnung& z, Framework::UIMLContainer& generalFactory) { return false; } //! wendet die layout parameter zu einer Zeichnung an void InventoryElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); } void SlotInfo::render( int x, int y, Framework::Bild& rObj, bool selected, bool lightBackground) { const Text* filter = dynamic_cast((Menu*)menuRegister->get("game"))->zFilterText(); TextRenderer tr; tr.setSchriftZ( dynamic_cast(uiFactory.initParam.schrift->getThis())); tr.setSchriftSize(12); bool filterMatch = filter->getLength() > 0 && this->name.hat(filter->getText()); rObj.fillRegion( x, y, 52, 52, selected || filterMatch ? 0xFFFFFFFF : 0xFF52525E); rObj.fillRegion(x + 1, y + 1, 50, 50, lightBackground ? 0xFF42424E : filter->getLength() == 0 ? 0xFF222222 : (filterMatch ? 0xFF222222 : 0xFF000000)); if (itemCount > 0) { rObj.alphaBild(x + 1, y + 1, 50, 50, *zItem); if (hp < maxHp) { rObj.fillRegion(x + 1, y + 47, 50, 2, 0xFF000000); rObj.fillRegion( x + 1, y + 47, (int)((hp / maxHp) * 50), 2, 0xFFFFFF00); } if (durability < maxDurability) { rObj.fillRegion(x + 1, y + 49, 50, 2, 0xFF000000); rObj.fillRegion(x + 1, y + 49, (int)((durability / maxDurability) * 50), 2, 0xFF00FF00); } const char* units[] = {"", "K", "M", "G", "T", "P"}; int i = 0; int tmpCount = itemCount; for (; i < 6 && tmpCount > 1024; i++) tmpCount = tmpCount / 1024; Text count = tmpCount; count += units[i]; tr.renderText(x + 45 - tr.getTextBreite(count), y + 45 - tr.getTextHeight(count), count, rObj, 0xFFFFFFFF); } } InventoryView::InventoryView( Text id, Either> target, int rowSize, Text slotNameFilter) : ZeichnungHintergrund(), rowSize(rowSize), target(target), slotNameFilter(slotNameFilter), id(id), slots(0), dragStartId(-1), dragStopId(-1), currentTooltipSlot(-1), requestetTooltipSlot(-1) { setStyle(ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Erlaubt); char* msg = new char[id.getLength() + slotNameFilter.getLength() + 3]; msg[0] = 0; msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); msg[2 + id.getLength()] = (char)slotNameFilter.getLength(); memcpy(msg + 3 + id.getLength(), slotNameFilter.getText(), slotNameFilter.getLength()); World::INSTANCE->zClient()->inventoryAPIRequest( target, msg, id.getLength() + slotNameFilter.getLength() + 3); delete[] msg; setNeedToolTipEvent([this](Zeichnung* z, Punkt p) { int slot = getSlotByLocalPos(p); if (currentTooltipSlot != slot && currentTooltipSlot != -1) { std::cout << "closing tooltip\n"; this->setToolTipZ(0); currentTooltipSlot = -1; } if (requestetTooltipSlot != slot && slot != -1) { if (World::INSTANCE) { std::cout << "requesting tooltip for slot " << slot << "\n"; requestetTooltipSlot = slot; char* msg = new char[this->id.getLength() + 6]; msg[0] = 2; // request inventory tooltip msg[1] = (char)this->id.getLength(); memcpy(msg + 2, this->id.getText(), this->id.getLength()); *(int*)(msg + 2 + this->id.getLength()) = slot; World::INSTANCE->zClient()->inventoryAPIRequest( this->target, msg, this->id.getLength() + 6); return 1; } } return 0; }); } InventoryView::~InventoryView() { DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); if (controller->getCurrentDragContainer() == this) controller->stopDrag(); if (slots) slots->release(); char* msg = new char[id.getLength() + 2]; msg[0] = 1; msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); World::INSTANCE->zClient()->inventoryAPIRequest( target, msg, id.getLength() + 2); delete[] msg; } int InventoryView::getSlotByLocalPos(Punkt pos) { int x = 0; int y = 0; int rowCount = 0; int slot = 0; dragStopId = -1; if (slots) { for (const SlotInfo& info : *slots) { if (pos.x >= x && pos.x < x + 50 && pos.y >= y && pos.y < y + 50) return info.id; x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } slot++; } } return -1; } void InventoryView::api(char* message) { switch (message[0]) { case 0: // send inventory content { Array* slots = new Array(); int count = *(int*)(++message); for (int i = 0; i < count; i++) { SlotInfo info; info.id = *(int*)(message += 4); info.itemCount = *(int*)(message += 4); if (info.itemCount > 0) { info.hp = *(float*)(message += 4); info.maxHp = *(float*)(message += 4); info.durability = *(float*)(message += 4); info.maxDurability = *(float*)(message += 4); info.zItem = zItemType(*(int*)(message += 4))->zIcon(); char len = *(message += 4); char* name = new char[len + 1]; memcpy(name, message += 1, len); name[len] = 0; info.name = name; delete[] name; message += len - 4; } slots->add(info); } window->zBildschirm()->postAction([this, slots]() { if (this->slots) this->slots->release(); this->slots = slots; }); break; } case 1: // set count of items { if (!slots) return; int id = *(int*)(message + 1); int count = *(int*)(message + 5); for (int i = 0; i < slots->getEintragAnzahl(); i++) { if (slots->get(i).id == id) { SlotInfo info = slots->get(i); info.itemCount = count; if (info.itemCount == 0) { info.name = ""; DragController* controller = ((Game*)(Menu*)menuRegister->get("game")) ->zInventoryDragController(); if (controller && controller->getCurrentDragContainer() == this && controller->getCurrentDaragElement() == info.id) { controller->stopDrag(); } } slots->set(info, i); break; } } break; } case 2: // add new stack { if (!slots) return; int id = *(int*)(message + 1); for (int i = 0; i < slots->getEintragAnzahl(); i++) { if (slots->get(i).id == id) { SlotInfo info = slots->get(i); info.itemCount = *(int*)(message + 5); info.hp = *(float*)(message + 9); info.maxHp = *(float*)(message + 13); info.durability = *(float*)(message + 17); info.maxDurability = *(float*)(message + 21); info.zItem = zItemType(*(int*)(message + 25))->zIcon(); char len = *(message + 29); char* name = new char[len + 1]; memcpy(name, message + 30, len); name[len] = 0; info.name = name; delete[] name; slots->set(info, i); break; } } break; } case 3: // receive tooltip uiml { int slotId = *(int*)(message + 1); if (slotId == requestetTooltipSlot) { std::cout << "tooltip loaded for slot " << slotId << "\n"; short len = *(short*)(message + 5); if (len > 0) { char* uiml = new char[len + 1]; memcpy(uiml, message + 7, len); uiml[len] = 0; UIMLToolTip* tip = new UIMLToolTip(); tip->setUIML(uiml); tip->setWarten(0); tip->setPosition(mausPos.x, mausPos.y + 15); setToolTipZ(tip); delete[] uiml; currentTooltipSlot = slotId; requestetTooltipSlot = -1; } else toolTipRequested = 0; } } } } bool InventoryView::tick(double tickVal) { return ZeichnungHintergrund::tick(tickVal); } void InventoryView::render(Bild& rObj) { ZeichnungHintergrund::render(rObj); if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return; if (slots) { int x = 0; int y = 0; int rowCount = 0; for (SlotInfo info : *slots) { info.render( x, y, rObj, dragStartId == info.id, dragStopId == info.id); x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } } } rObj.releaseDrawOptions(); } void InventoryView::doMausEreignis(MausEreignis& me, bool userRet) { mausPos.x = me.originalX; mausPos.y = me.originalY; if (!slots) return; if (me.id == ME_Bewegung) { if (getSlotByLocalPos(Punkt(me.mx, me.my)) != currentTooltipSlot) { if (currentTooltipSlot != -1) { std::cout << "closing tooltip\n"; setToolTipZ(0); } else toolTipRequested = 0; currentTooltipSlot = -1; } } DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); int x = 0; int y = 0; int rowCount = 0; int slot = 0; dragStopId = -1; for (SlotInfo info : *slots) { if (me.mx >= x && me.mx < x + 50 && me.my >= y && me.my < y + 50) { if (me.id == ME_RLinks) { if (!controller->getCurrentDragContainer() && info.itemCount > 0) { controller->beginDrag(this, info.id, info.zItem, [this]() { dragStartId = -1; }); dragStartId = info.id; } else if (controller->getCurrentDragContainer()) { // request to transfer items from source to target slot Framework::Either> source = controller->getCurrentDragContainer() ->getInventoryTarget(); int len = 2 + (source.isA() ? 4 : 16) + 5 + (target.isA() ? 4 : 16) + 4; char* msg = new char[len]; int index = 0; msg[index++] = 6; msg[index++] = (char)source.isA(); if (source.isA()) { *(int*)(msg + index) = source.getA(); index += 4; } else { *(int*)(msg + index) = source.getB()[0]; *(int*)(msg + index + 4) = source.getB()[1]; *(int*)(msg + index + 8) = source.getB()[2]; *(int*)(msg + index + 12) = source.getB()[3]; index += 16; } *(int*)(msg + index) = controller->getCurrentDaragElement(); index += 4; msg[index++] = target.isA(); if (target.isA()) { *(int*)(msg + index) = target.getA(); index += 4; } else { *(int*)(msg + index) = target.getB()[0]; *(int*)(msg + index + 4) = target.getB()[1]; *(int*)(msg + index + 8) = target.getB()[2]; *(int*)(msg + index + 12) = target.getB()[3]; index += 16; } *(int*)(msg + index) = info.id; World::INSTANCE->zClient()->sendPlayerAction(msg, len); delete[] msg; } } else { if (controller->getCurrentDragContainer() && (controller->getCurrentDragContainer() != this || controller->getCurrentDaragElement() != info.id)) { dragStopId = info.id; } } break; } x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } slot++; } ZeichnungHintergrund::doMausEreignis(me, userRet); } Framework::Either> InventoryView::getInventoryTarget() const { return target; }