Эх сурвалжийг харах

quest rewards will now be given

Kolja Strohm 9 сар өмнө
parent
commit
4ff579a149

+ 0 - 44
FactoryCraft/Quest.cpp

@@ -387,17 +387,6 @@ bool Quest::isActive(QuestParty* zParty)
     return active;
 }
 
-void Quest::giveReward(
-    int choice, Entity* zTargetEntity, QuestStorage* zStorage)
-{
-    if (!zStorage->isQuestFinished() || zStorage->isQuestRewarded())
-    {
-        return;
-    }
-    zStorage->setQuestRewarded(1);
-    rewards.z(choice)->giveReward(zTargetEntity);
-}
-
 const Framework::Text& Quest::getQuestId() const
 {
     return questId;
@@ -577,26 +566,6 @@ bool QuestCollection::isVisible(QuestParty* zParty, QuestManager* zManager)
     return visible;
 }
 
-void QuestCollection::giveReward(Framework::Text questId,
-    int choice,
-    Entity* zTargetEntity,
-    QuestParty* zParty)
-{
-    QuestStorage* zStorage = zParty->zQuestStorage(questId);
-    if (zStorage->isQuestRewarded() || !zStorage->isQuestFinished())
-    {
-        return;
-    }
-    for (Quest* quest : quests)
-    {
-        if (quest->getQuestId() == questId)
-        {
-            quest->giveReward(choice, zTargetEntity, zStorage);
-            return;
-        }
-    }
-}
-
 void QuestCollection::addQuest(Quest* zQuest)
 {
     quests.add(zQuest);
@@ -836,19 +805,6 @@ void QuestManager::processEvent(QuestEvent* event)
     event->release();
 }
 
-void QuestManager::giveReward(
-    Framework::Text questId, int choice, Entity* zTargetEntity)
-{
-    QuestParty* party = zParty(zTargetEntity->getId());
-    if (party)
-    {
-        for (QuestCollection* questCollection : questCollections)
-        {
-            questCollection->giveReward(questId, choice, zTargetEntity, party);
-        }
-    }
-}
-
 void QuestManager::setQuestVisible(
     bool visible, Framework::Text questId, QuestParty* zParty)
 {

+ 0 - 6
FactoryCraft/Quest.h

@@ -130,7 +130,6 @@ public:
     void processEvent(QuestEvent* zEvent, QuestStorage* zStorage);
     bool isVisible(QuestParty* zParty, QuestManager* zManager);
     bool isActive(QuestParty* zParty);
-    void giveReward(int choice, Entity* zTargetEntity, QuestStorage* zStorage);
     const Framework::Text& getQuestId() const;
     void setVisible(bool visible, QuestParty* zParty, QuestManager* zManager);
 
@@ -160,10 +159,6 @@ public:
 
     void processEvent(QuestEvent* zEvent, QuestParty* zParty);
     bool isVisible(QuestParty* zParty, QuestManager* zManager);
-    void giveReward(Framework::Text questId,
-        int choice,
-        Entity* zTargetEntity,
-        QuestParty* zParty);
     void addQuest(Quest* zQuest);
 
     const Framework::Text& getName() const;
@@ -201,7 +196,6 @@ public:
     void saveQuests();
 
     void processEvent(QuestEvent* event);
-    void giveReward(Framework::Text questId, int choice, Entity* zTargetEntity);
     void setQuestVisible(
         bool visible, Framework::Text questId, QuestParty* zParty);
 

+ 31 - 10
FactoryCraft/QuestDialog.cpp

@@ -167,17 +167,38 @@ void QuestDialog::api(
                     if (zStorage->isQuestFinished()
                         && !zStorage->isQuestRewarded())
                     {
-                        auto questView = uiml->selectChildsByAttribute(
-                                                 "id", "questDetailView")
-                                             .getFirstElement();
-                        questView->removeAllChilds();
-
-                        // TODO: give rewards
+                        Framework::XML::Element* rewardContainer
+                            = (Framework::RCPointer<Framework::XML::Element>)
+                                  uiml->selectChildren()
+                                      .selectAllElements()
+                                      .whereAttributeEquals(
+                                          "id", "quest_rewards")
+                                      .getFirstElement();
+                        bool valid = 1;
+                        for (auto reward : quest->rewards)
+                        {
+                            valid &= reward->validateSettings(
+                                rewardContainer, zStorage);
+                        }
+                        if (valid)
+                        {
+                            zStorage->setQuestRewarded(1);
+                            for (auto reward : quest->rewards)
+                            {
+                                reward->giveReward(rewardContainer,
+                                    zStorage,
+                                    Game::INSTANCE->zEntity(getPlayerId()));
+                            }
+                            auto questView = uiml->selectChildsByAttribute(
+                                                     "id", "questDetailView")
+                                                 .getFirstElement();
+                            questView->removeAllChilds();
+                            showQuestDetails(quest,
+                                zStorage,
+                                (Framework::RCPointer<Framework::XML::Element>)
+                                    questView);
+                        }
 
-                        showQuestDetails(quest,
-                            zStorage,
-                            (Framework::RCPointer<Framework::XML::Element>)
-                                questView);
                         break;
                     }
                 }

+ 24 - 1
FactoryCraft/QuestReward.cpp

@@ -4,6 +4,7 @@
 
 #include "Entity.h"
 #include "Game.h"
+#include "Player.h"
 
 QuestReward::QuestReward(Framework::Text rewardId)
     : ReferenceCounter(),
@@ -87,8 +88,17 @@ QuestRewardGiveItems::QuestRewardGiveItems(Framework::Text rewardId)
     : QuestReward(rewardId)
 {}
 
-void QuestRewardGiveItems::giveReward(Entity* zTargetEntity)
+void QuestRewardGiveItems::giveReward(Framework::XML::Element* zParent,
+    QuestStorage* zStorage,
+    Entity* zTargetEntity)
 {
+    Player *p = dynamic_cast<Player*>(zTargetEntity);
+    if (p)
+    {
+        zStorage->putValue(
+            (Framework::Text("reward_") += rewardId) += "_given_to",
+            new Framework::JSON::JSONString(p->getName()));
+    }
     for (ItemStackInfo* info : items)
     {
         ItemStack* stack = new ItemStack(
@@ -132,12 +142,25 @@ void QuestRewardGiveItems::addRewardUIML(Framework::XML::Element* zParent,
             new Framework::XML::Element(info->zItem()->getTooltipUIML()));
         auto text = new Framework::XML::Element(
             "<text margin-left=\"10\" width=\"auto\" height=\"auto\"/>");
+        text->setAttribute(
+            "id", (Framework::Text("reward_") += rewardId) += "_item_description");
         text->setText((Framework::Text(info->getCount()) += " ")
                       += info->zItem()->getName());
         text->setAttribute("align-left", stack->getAttributeValue("id"));
         text->setAttribute("align-y", stack->getAttributeValue("id"));
         container->addChild(stack);
         container->addChild(text);
+        if (zStorage->containsKey( (Framework::Text("reward_") += rewardId) += "_given_to"))
+		{
+			auto givenTo = new Framework::XML::Element(
+				"<text width=\"auto\" height=\"auto\" margin-top=\"10\" text-color=\"0xFF00FF00\"/>");
+            auto name = zStorage->zValue(
+				(Framework::Text("reward_") += rewardId) += "_given_to")->asString();
+            givenTo->setText((Framework::Text("Given to: ") += name->getString()));
+            givenTo->setAttribute("align-top", text->getAttributeValue("id"));
+            givenTo->setAttribute("align-x", text->getAttributeValue("id"));
+            container->addChild(givenTo);
+		}
     }
     zParent->addChild(container);
 }

+ 7 - 2
FactoryCraft/QuestReward.h

@@ -14,7 +14,10 @@ protected:
 public:
     QuestReward(Framework::Text rewardId);
 
-    virtual void giveReward(Entity* zTargetEntity) = 0;
+    virtual void giveReward(Framework::XML::Element* zParent,
+        QuestStorage* zStorage,
+        Entity* zTargetEntity)
+        = 0;
     virtual void addRewardUIML(
         Framework::XML::Element* zParent, QuestStorage* zStorage, Framework::Text onClickPrefix)
         = 0;
@@ -58,7 +61,9 @@ private:
 public:
     QuestRewardGiveItems(Framework::Text rewardId);
 
-    void giveReward(Entity* zTargetEntity) override;
+    void giveReward(Framework::XML::Element* zParent,
+        QuestStorage* zStorage,
+        Entity* zTargetEntity) override;
     void addRewardUIML(Framework::XML::Element* zParent,
         QuestStorage* zStorage,
         Framework::Text onClickPrefix) override;

+ 10 - 2
FactoryCraft/UIController.cpp

@@ -47,13 +47,17 @@ void UIController::api(Framework::StreamReader* zRequest,
     case 1: // close dialog
         {
             int entityId = zSource->getId();
-            for (auto dialog = activeDialogs.begin(); dialog; dialog++)
+            for (auto dialog = activeDialogs.begin(); dialog;)
             {
                 if (dialog->getId().istGleich(id)
                     && dialog->getPlayerId() == entityId)
                 {
                     dialog.remove();
                 }
+				else
+				{
+					dialog++;
+				}
             }
             break;
         }
@@ -63,11 +67,15 @@ void UIController::api(Framework::StreamReader* zRequest,
 
 void UIController::removePlayerDialogs(int playerId)
 {
-    for (auto dialog = activeDialogs.begin(); dialog; dialog++)
+    for (auto dialog = activeDialogs.begin(); dialog;)
     {
         if (dialog->getPlayerId() == playerId)
         {
             dialog.remove();
         }
+        else
+        {
+            dialog++;
+        }
     }
 }

+ 216 - 0
enc_temp_folder/9b5d8d394bbd57f419062a24c115732/QuestReward.cpp

@@ -0,0 +1,216 @@
+#include "QuestReward.h"
+
+#include <Fenster.h>
+
+#include "Entity.h"
+#include "Game.h"
+#include "Player.h"
+
+QuestReward::QuestReward(Framework::Text rewardId)
+    : ReferenceCounter(),
+      rewardId(rewardId)
+{}
+
+bool QuestReward::validateSettings(
+    Framework::XML::Element* zParent, QuestStorage* zStorage)
+{
+    return true;
+}
+
+void QuestReward::api(Framework::StreamReader* message,
+    Framework::XML::Element* zParent,
+    QuestStorage* zStorage)
+{}
+
+const Framework::Text& QuestReward::getRewardId() const
+{
+    return rewardId;
+}
+
+ItemStackInfo::ItemStackInfo(Item* item, int count)
+    : ReferenceCounter(),
+      item(item),
+      count(count)
+{}
+
+ItemStackInfo::~ItemStackInfo()
+{
+    item->release();
+}
+
+Item* ItemStackInfo::zItem() const
+{
+    return item;
+}
+
+int ItemStackInfo::getCount() const
+{
+    return count;
+}
+
+ItemStackInfoType::ItemStackInfoType()
+    : TypeFactory<ItemStackInfo>()
+{}
+
+ItemStackInfo* ItemStackInfoType::fromJson(
+    Framework::JSON::JSONValue* zJson) const
+{
+    return new ItemStackInfo(Game::INSTANCE->zTypeRegistry()->fromJson<Item>(
+                                 zJson->asObject()->zValue("item")),
+        (int)zJson->asObject()->zValue("count")->asNumber()->getNumber());
+}
+
+Framework::JSON::JSONValue* ItemStackInfoType::toJson(
+    ItemStackInfo* zObject) const
+{
+    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
+    result->addValue(
+        "item", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zItem()));
+    result->addValue(
+        "count", new Framework::JSON::JSONNumber((double)zObject->getCount()));
+    return result;
+}
+
+Framework::JSON::Validator::JSONValidator*
+ItemStackInfoType::getValidator() const
+{
+    return Framework::JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredAttribute(
+            "item", Game::INSTANCE->zTypeRegistry()->getValidator<Item>())
+        ->withRequiredNumber("count")
+        ->withDefault(1.0)
+        ->whichIsGreaterOrEqual(1.0)
+        ->finishNumber()
+        ->finishObject();
+}
+
+QuestRewardGiveItems::QuestRewardGiveItems(Framework::Text rewardId)
+    : QuestReward(rewardId)
+{}
+
+void QuestRewardGiveItems::giveReward(Framework::XML::Element* zParent,
+    QuestStorage* zStorage,
+    Entity* zTargetEntity)
+{
+    Player *p = dynamic_cast<Player*>(zTargetEntity);
+    if (p)
+    {
+        zStorage->putValue(
+            (Framework::Text("reward_") += rewardId) += "_given_to",
+            new Framework::JSON::JSONString(p->getName()));
+    }
+    for (ItemStackInfo* info : items)
+    {
+        ItemStack* stack = new ItemStack(
+            dynamic_cast<Item*>(info->zItem()->getThis()), info->getCount());
+        zTargetEntity->unsaveAddItem(stack, Direction::NO_DIRECTION, 0);
+        if (stack->getSize() > 0)
+        {
+            Game::INSTANCE->spawnItem(zTargetEntity->getLocation(),
+                zTargetEntity->getDimensionId(),
+                stack);
+        }
+        else
+        {
+            stack->release();
+        }
+    }
+}
+
+void QuestRewardGiveItems::addRewardUIML(Framework::XML::Element* zParent,
+    QuestStorage* zStorage,
+    Framework::Text onClickPrefix)
+{
+    Framework::XML::Element* container
+        = new Framework::XML::Element("<frame width=\"100%\" height=\"auto\" "
+                                      "display=\"column\" gap=\"10\"/>");
+    container->setAttribute("style",
+        Framework::Text() += (Framework::Fenster::Style::Sichtbar
+                              | Framework::Fenster::Style::Erlaubt));
+    container->setAttribute("id", Framework::Text("reward_") += rewardId);
+    container->addChild(new Framework::XML::Element(
+        "<text width=\"auto\" height=\"auto\">Item Reward:</text>"));
+    for (ItemStackInfo* info : items)
+    {
+        auto stack = new Framework::XML::Element(
+            "<itemStack width=\"50\" height=\"50\"/>");
+        stack->setAttribute(
+            "id", (Framework::Text("reward_") += rewardId) += "_item_stack");
+        stack->setAttribute("count", info->getCount());
+        stack->setAttribute("type", info->zItem()->getTypeId());
+        stack->addChild(
+            new Framework::XML::Element(info->zItem()->getTooltipUIML()));
+        auto text = new Framework::XML::Element(
+            "<text margin-left=\"10\" width=\"auto\" height=\"auto\"/>");
+        text->setText((Framework::Text(info->getCount()) += " ")
+                      += info->zItem()->getName());
+        text->setAttribute("align-left", stack->getAttributeValue("id"));
+        text->setAttribute("align-y", stack->getAttributeValue("id"));
+        container->addChild(stack);
+        container->addChild(text);
+        if (zStorage->containsKey( (Framework::Text("reward_") += rewardId) += "_given_to"))
+		{
+			auto givenTo = new Framework::XML::Element(
+				"<text width=\"auto\" height=\"auto\"/>");
+            auto name = zStorage->zValue(
+				(Framework::Text("reward_") += rewardId) += "_given_to")->asString();
+            givenTo->setText((Framework::Text("Given to: ") += name->getString()));
+            givenTo->setAttribute("align-top", text->getAttributeValue("id"));
+            givenTo->setAttribute("align-x", text->getAttributeValue("id"));
+            container->addChild(givenTo);
+		}
+    }
+    zParent->addChild(container);
+}
+
+QuestRewardGiveItemsType::QuestRewardGiveItemsType()
+    : SubTypeFactory<QuestReward, QuestRewardGiveItems>()
+{}
+
+QuestRewardGiveItems* QuestRewardGiveItemsType::fromJson(
+    Framework::JSON::JSONObject* zJson) const
+{
+    QuestRewardGiveItems* result = new QuestRewardGiveItems(
+        zJson->zValue("rewardId")->asString()->getString());
+    Framework::JSON::JSONArray* itemsJson = zJson->zValue("items")->asArray();
+    for (Framework::JSON::JSONValue* itemJson : *itemsJson)
+    {
+        result->items.add(
+            Game::INSTANCE->zTypeRegistry()->fromJson<ItemStackInfo>(itemJson));
+    }
+    return result;
+}
+
+Framework::JSON::JSONObject* QuestRewardGiveItemsType::toJson(
+    QuestRewardGiveItems* zObject) const
+{
+    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
+    result->addValue(
+        "rewardId", new Framework::JSON::JSONString(zObject->getRewardId()));
+    Framework::JSON::JSONArray* itemsJson = new Framework::JSON::JSONArray();
+    for (ItemStackInfo* item : zObject->items)
+    {
+        itemsJson->addValue(Game::INSTANCE->zTypeRegistry()->toJson(item));
+    }
+    result->addValue("items", itemsJson);
+    return result;
+}
+
+Framework::JSON::Validator::JSONValidator*
+QuestRewardGiveItemsType::getValidator(
+    Framework::JSON::Validator::ObjectValidationBuilder<
+        Framework::JSON::Validator::JSONValidator>* builder) const
+{
+    return builder->withRequiredString("rewardId")
+        ->finishString()
+        ->withRequiredArray("items")
+        ->addAcceptedTypeInArray(
+            Game::INSTANCE->zTypeRegistry()->getValidator<ItemStackInfo>())
+        ->finishArray()
+        ->finishObject();
+}
+
+Framework::Text QuestRewardGiveItemsType::getTypeToken() const
+{
+    return "give_items";
+}

+ 218 - 0
enc_temp_folder/f12bb5e05c148783c3dcfcb42ea2394/QuestReward.cpp

@@ -0,0 +1,218 @@
+#include "QuestReward.h"
+
+#include <Fenster.h>
+
+#include "Entity.h"
+#include "Game.h"
+#include "Player.h"
+
+QuestReward::QuestReward(Framework::Text rewardId)
+    : ReferenceCounter(),
+      rewardId(rewardId)
+{}
+
+bool QuestReward::validateSettings(
+    Framework::XML::Element* zParent, QuestStorage* zStorage)
+{
+    return true;
+}
+
+void QuestReward::api(Framework::StreamReader* message,
+    Framework::XML::Element* zParent,
+    QuestStorage* zStorage)
+{}
+
+const Framework::Text& QuestReward::getRewardId() const
+{
+    return rewardId;
+}
+
+ItemStackInfo::ItemStackInfo(Item* item, int count)
+    : ReferenceCounter(),
+      item(item),
+      count(count)
+{}
+
+ItemStackInfo::~ItemStackInfo()
+{
+    item->release();
+}
+
+Item* ItemStackInfo::zItem() const
+{
+    return item;
+}
+
+int ItemStackInfo::getCount() const
+{
+    return count;
+}
+
+ItemStackInfoType::ItemStackInfoType()
+    : TypeFactory<ItemStackInfo>()
+{}
+
+ItemStackInfo* ItemStackInfoType::fromJson(
+    Framework::JSON::JSONValue* zJson) const
+{
+    return new ItemStackInfo(Game::INSTANCE->zTypeRegistry()->fromJson<Item>(
+                                 zJson->asObject()->zValue("item")),
+        (int)zJson->asObject()->zValue("count")->asNumber()->getNumber());
+}
+
+Framework::JSON::JSONValue* ItemStackInfoType::toJson(
+    ItemStackInfo* zObject) const
+{
+    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
+    result->addValue(
+        "item", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zItem()));
+    result->addValue(
+        "count", new Framework::JSON::JSONNumber((double)zObject->getCount()));
+    return result;
+}
+
+Framework::JSON::Validator::JSONValidator*
+ItemStackInfoType::getValidator() const
+{
+    return Framework::JSON::Validator::JSONValidator::buildForObject()
+        ->withRequiredAttribute(
+            "item", Game::INSTANCE->zTypeRegistry()->getValidator<Item>())
+        ->withRequiredNumber("count")
+        ->withDefault(1.0)
+        ->whichIsGreaterOrEqual(1.0)
+        ->finishNumber()
+        ->finishObject();
+}
+
+QuestRewardGiveItems::QuestRewardGiveItems(Framework::Text rewardId)
+    : QuestReward(rewardId)
+{}
+
+void QuestRewardGiveItems::giveReward(Framework::XML::Element* zParent,
+    QuestStorage* zStorage,
+    Entity* zTargetEntity)
+{
+    Player *p = dynamic_cast<Player*>(zTargetEntity);
+    if (p)
+    {
+        zStorage->putValue(
+            (Framework::Text("reward_") += rewardId) += "_given_to",
+            new Framework::JSON::JSONString(p->getName()));
+    }
+    for (ItemStackInfo* info : items)
+    {
+        ItemStack* stack = new ItemStack(
+            dynamic_cast<Item*>(info->zItem()->getThis()), info->getCount());
+        zTargetEntity->unsaveAddItem(stack, Direction::NO_DIRECTION, 0);
+        if (stack->getSize() > 0)
+        {
+            Game::INSTANCE->spawnItem(zTargetEntity->getLocation(),
+                zTargetEntity->getDimensionId(),
+                stack);
+        }
+        else
+        {
+            stack->release();
+        }
+    }
+}
+
+void QuestRewardGiveItems::addRewardUIML(Framework::XML::Element* zParent,
+    QuestStorage* zStorage,
+    Framework::Text onClickPrefix)
+{
+    Framework::XML::Element* container
+        = new Framework::XML::Element("<frame width=\"100%\" height=\"auto\" "
+                                      "display=\"column\" gap=\"10\"/>");
+    container->setAttribute("style",
+        Framework::Text() += (Framework::Fenster::Style::Sichtbar
+                              | Framework::Fenster::Style::Erlaubt));
+    container->setAttribute("id", Framework::Text("reward_") += rewardId);
+    container->addChild(new Framework::XML::Element(
+        "<text width=\"auto\" height=\"auto\">Item Reward:</text>"));
+    for (ItemStackInfo* info : items)
+    {
+        auto stack = new Framework::XML::Element(
+            "<itemStack width=\"50\" height=\"50\"/>");
+        stack->setAttribute(
+            "id", (Framework::Text("reward_") += rewardId) += "_item_stack");
+        stack->setAttribute("count", info->getCount());
+        stack->setAttribute("type", info->zItem()->getTypeId());
+        stack->addChild(
+            new Framework::XML::Element(info->zItem()->getTooltipUIML()));
+        auto text = new Framework::XML::Element(
+            "<text margin-left=\"10\" width=\"auto\" height=\"auto\"/>");
+        text->setAttribute(
+            "id", (Framework::Text("reward_") += rewardId) += "_item_description");
+        text->setText((Framework::Text(info->getCount()) += " ")
+                      += info->zItem()->getName());
+        text->setAttribute("align-left", stack->getAttributeValue("id"));
+        text->setAttribute("align-y", stack->getAttributeValue("id"));
+        container->addChild(stack);
+        container->addChild(text);
+        if (zStorage->containsKey( (Framework::Text("reward_") += rewardId) += "_given_to"))
+		{
+			auto givenTo = new Framework::XML::Element(
+				"<text width=\"auto\" height=\"auto\"/>");
+            auto name = zStorage->zValue(
+				(Framework::Text("reward_") += rewardId) += "_given_to")->asString();
+            givenTo->setText((Framework::Text("Given to: ") += name->getString()));
+            givenTo->setAttribute("align-top", text->getAttributeValue("id"));
+            givenTo->setAttribute("align-x", text->getAttributeValue("id"));
+            container->addChild(givenTo);
+		}
+    }
+    zParent->addChild(container);
+}
+
+QuestRewardGiveItemsType::QuestRewardGiveItemsType()
+    : SubTypeFactory<QuestReward, QuestRewardGiveItems>()
+{}
+
+QuestRewardGiveItems* QuestRewardGiveItemsType::fromJson(
+    Framework::JSON::JSONObject* zJson) const
+{
+    QuestRewardGiveItems* result = new QuestRewardGiveItems(
+        zJson->zValue("rewardId")->asString()->getString());
+    Framework::JSON::JSONArray* itemsJson = zJson->zValue("items")->asArray();
+    for (Framework::JSON::JSONValue* itemJson : *itemsJson)
+    {
+        result->items.add(
+            Game::INSTANCE->zTypeRegistry()->fromJson<ItemStackInfo>(itemJson));
+    }
+    return result;
+}
+
+Framework::JSON::JSONObject* QuestRewardGiveItemsType::toJson(
+    QuestRewardGiveItems* zObject) const
+{
+    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
+    result->addValue(
+        "rewardId", new Framework::JSON::JSONString(zObject->getRewardId()));
+    Framework::JSON::JSONArray* itemsJson = new Framework::JSON::JSONArray();
+    for (ItemStackInfo* item : zObject->items)
+    {
+        itemsJson->addValue(Game::INSTANCE->zTypeRegistry()->toJson(item));
+    }
+    result->addValue("items", itemsJson);
+    return result;
+}
+
+Framework::JSON::Validator::JSONValidator*
+QuestRewardGiveItemsType::getValidator(
+    Framework::JSON::Validator::ObjectValidationBuilder<
+        Framework::JSON::Validator::JSONValidator>* builder) const
+{
+    return builder->withRequiredString("rewardId")
+        ->finishString()
+        ->withRequiredArray("items")
+        ->addAcceptedTypeInArray(
+            Game::INSTANCE->zTypeRegistry()->getValidator<ItemStackInfo>())
+        ->finishArray()
+        ->finishObject();
+}
+
+Framework::Text QuestRewardGiveItemsType::getTypeToken() const
+{
+    return "give_items";
+}