Quiz etkinliği

  • Konuyu açan Konuyu açan pasha37
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 7
  • Gösterim Gösterim 481

pasha37

Premium Üye
Premium Üye
Geliştirici
MT Üye
Mesaj
219
Çözümler
6
Beğeni
564
Puan
819
Ticaret Puanı
0
Eskiden IRC'de Kaos soru-cevap botu isminde bir etkinlik botu vardı, onu metin2'ye uyarladım. OX gibi mini bir event olarak düşünebilirsiniz, her soru birden fazla cevap destekler ve her cevap için katılımcılar + puan kazanır ve en çok puana ulaşanda belirlediğiniz ödülü alır.



Aşağıdaki diff patch dosyasındaki değişiklikleri yaparak ekleyebilirsiniz.

Diff:
Genişlet Daralt Kopyala
From 4d2d1a51d48e4e9ca2fcf66e5829dbef727fac45 Mon Sep 17 00:00:00 2001
From: mq1n <[email protected]>
Date: Thu, 17 Jul 2025 20:45:52 +0300
Subject: [PATCH] quiz

---
 client/pack/root/colorinfo.py                 |   1 +
 client/pack/root/uichat.py                    | 111 +++-
 .../Srcs/Client/UserInterface/Packet.h        |   1 +
 .../Srcs/Client/UserInterface/PythonChat.cpp  |   1 +
 .../Client/UserInterface/PythonChatModule.cpp |   1 +
 .../PythonNetworkStreamPhaseGame.cpp          |   1 +
 s3ll_server/Srcs/Server/common/length.h       |   1 +
 s3ll_server/Srcs/Server/game/src/QuizShow.cpp | 622 ++++++++++++++++++
 s3ll_server/Srcs/Server/game/src/QuizShow.h   |  80 +++
 s3ll_server/Srcs/Server/game/src/char.cpp     |   3 +
 s3ll_server/Srcs/Server/game/src/cmd.cpp      |   8 +
 .../Srcs/Server/game/src/cmd_general.cpp      |  11 +
 s3ll_server/Srcs/Server/game/src/cmd_gm.cpp   |   9 +
 s3ll_server/Srcs/Server/game/src/game.vcxproj |   2 +
 .../Srcs/Server/game/src/game.vcxproj.filters |   6 +
 .../Srcs/Server/game/src/input_main.cpp       |  18 +
 s3ll_server/Srcs/Server/game/src/main.cpp     |   2 +
 .../srv1/share/locale/germany/quizshow.lua    |  57 ++
 18 files changed, 924 insertions(+), 11 deletions(-)
 create mode 100644 s3ll_server/Srcs/Server/game/src/QuizShow.cpp
 create mode 100644 s3ll_server/Srcs/Server/game/src/QuizShow.h
 create mode 100644 s3ll_svfiles/main/srv1/share/locale/germany/quizshow.lua

diff --git a/client/pack/root/colorinfo.py b/client/pack/root/colorinfo.py
index 5898eace..56a0f1ec 100644
--- a/client/pack/root/colorinfo.py
+++ b/client/pack/root/colorinfo.py
@@ -3,6 +3,7 @@ CHAT_RGB_INFO = (255, 200, 200) #1
 CHAT_RGB_NOTICE = (255, 230, 186) #2
 CHAT_RGB_PARTY = (0, 255, 228) #3
 CHAT_RGB_GUILD = (253, 255, 124) #4
+CHAT_RGB_QUIZ = (255, 255, 255) #5
 CHAT_RGB_COMMAND = (167, 255, 212) #5
 CHAT_RGB_SHOUT = (167, 255, 212) #6
 CHAT_RGB_WHISPER = (74, 225, 74) #7
diff --git a/client/pack/root/uichat.py b/client/pack/root/uichat.py
index e2a3980b..00a8347e 100644
--- a/client/pack/root/uichat.py
+++ b/client/pack/root/uichat.py
@@ -112,10 +112,13 @@ class ChatModeButton(ui.Window):
 ## ChatLine
 class ChatLine(ui.EditLine):
 
-    CHAT_MODE_NAME = {    chat.CHAT_TYPE_TALKING : localeInfo.CHAT_NORMAL,
-                        chat.CHAT_TYPE_PARTY : localeInfo.CHAT_PARTY,
-                        chat.CHAT_TYPE_GUILD : localeInfo.CHAT_GUILD,
-                        chat.CHAT_TYPE_SHOUT : localeInfo.CHAT_SHOUT, }
+    CHAT_MODE_NAME = {
+        chat.CHAT_TYPE_TALKING : localeInfo.CHAT_NORMAL,
+        chat.CHAT_TYPE_PARTY : localeInfo.CHAT_PARTY,
+        chat.CHAT_TYPE_GUILD : localeInfo.CHAT_GUILD,
+        chat.CHAT_TYPE_SHOUT : localeInfo.CHAT_SHOUT,
+        chat.CHAT_TYPE_QUIZ : localeInfo.CHAT_QUIZ,
+    }
 
     def __init__(self):
         ui.EditLine.__init__(self)
@@ -138,6 +141,14 @@ class ChatLine(ui.EditLine):
         self.lastSentencePos = 0
 
     def SetChatMode(self, mode):
+        # Handle quiz mode transitions
+        if self.chatMode != chat.CHAT_TYPE_QUIZ and mode == chat.CHAT_TYPE_QUIZ:
+            # Entering quiz mode
+            net.SendChatPacket("/enter_quiz_spec", chat.CHAT_TYPE_TALKING)
+        elif self.chatMode == chat.CHAT_TYPE_QUIZ and mode != chat.CHAT_TYPE_QUIZ:
+            # Leaving quiz mode
+            net.SendChatPacket("/leave_quiz_spec", chat.CHAT_TYPE_TALKING)
+      
         self.chatMode = mode
 
     def GetChatMode(self):
@@ -150,6 +161,11 @@ class ChatLine(ui.EditLine):
             self.SetEndPosition()
 
         elif chat.CHAT_TYPE_PARTY == self.GetChatMode():
+            self.SetChatMode(chat.CHAT_TYPE_QUIZ)
+            self.SetText("&")
+            self.SetEndPosition()
+  
+        elif chat.CHAT_TYPE_QUIZ == self.GetChatMode():
             self.SetChatMode(chat.CHAT_TYPE_GUILD)
             self.SetText("%")
             self.SetEndPosition()
@@ -199,6 +215,9 @@ class ChatLine(ui.EditLine):
         elif chat.CHAT_TYPE_GUILD == self.GetChatMode():
             self.SetText("%")
             self.SetEndPosition()
+        elif chat.CHAT_TYPE_QUIZ == self.GetChatMode():
+            self.SetText("&")
+            self.SetEndPosition()
         elif chat.CHAT_TYPE_SHOUT == self.GetChatMode():
             self.SetText("!")
             self.SetEndPosition()
@@ -248,6 +267,20 @@ class ChatLine(ui.EditLine):
 
         self.lastShoutTime = app.GetTime()
 
+    def __SendQuizChatPacket(self, text):
+
+        if 1 == len(text):
+            self.RunCloseEvent()
+            return
+
+        # if not net.IsQuizEnabled():
+        #     chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.CHAT_QUIZ_NOT_ENABLED)
+        #     self.__ResetChat()
+        #     return
+
+        self.__SendChatPacket(text[1:], chat.CHAT_TYPE_QUIZ)
+        self.__ResetChat()
+
     def __SendTalkingChatPacket(self, text):
         self.__SendChatPacket(text, chat.CHAT_TYPE_TALKING)
         self.__ResetChat()
@@ -274,6 +307,9 @@ class ChatLine(ui.EditLine):
             elif '%' == text[0]:
                 self.overTextLine.SetText("%")
                 self.overTextLine.Show()
+            elif '&' == text[0]:
+                self.overTextLine.SetText("&")
+                self.overTextLine.Show()
             elif '!' == text[0]:
                 self.overTextLine.SetText("!")
                 self.overTextLine.Show()
@@ -346,6 +382,8 @@ class ChatLine(ui.EditLine):
                 self.__SendGuildChatPacket(text)
             elif '!' == text[0]:
                 self.__SendShoutChatPacket(text)
+            elif '&' == text[0]:
+                self.__SendQuizChatPacket(text)
             else:
                 self.__SendTalkingChatPacket(text)
         else:
@@ -624,6 +662,7 @@ class ChatWindow(ui.Window):
             chat.CHAT_TYPE_NOTICE : colorInfo.CHAT_RGB_NOTICE,
             chat.CHAT_TYPE_PARTY : colorInfo.CHAT_RGB_PARTY,
             chat.CHAT_TYPE_GUILD : colorInfo.CHAT_RGB_GUILD,
+            chat.CHAT_TYPE_QUIZ : colorInfo.CHAT_RGB_QUIZ,
             chat.CHAT_TYPE_COMMAND : colorInfo.CHAT_RGB_COMMAND,
             chat.CHAT_TYPE_SHOUT : colorInfo.CHAT_RGB_SHOUT,
             chat.CHAT_TYPE_WHISPER : colorInfo.CHAT_RGB_WHISPER,
@@ -840,13 +879,24 @@ class ChatWindow(ui.Window):
 class ChatLogWindow(ui.Window):
 
     BLOCK_WIDTH = 32
-    CHAT_MODE_NAME = [ localeInfo.CHAT_NORMAL, localeInfo.CHAT_PARTY, localeInfo.CHAT_GUILD, localeInfo.CHAT_SHOUT, localeInfo.CHAT_INFORMATION, localeInfo.CHAT_NOTICE, ]
-    CHAT_MODE_INDEX = [ chat.CHAT_TYPE_TALKING,
-                        chat.CHAT_TYPE_PARTY,
-                        chat.CHAT_TYPE_GUILD,
-                        chat.CHAT_TYPE_SHOUT,
-                        chat.CHAT_TYPE_INFO,
-                        chat.CHAT_TYPE_NOTICE, ]
+    CHAT_MODE_NAME = [
+        localeInfo.CHAT_NORMAL,
+        localeInfo.CHAT_PARTY,
+        localeInfo.CHAT_GUILD,
+        localeInfo.CHAT_SHOUT,
+        localeInfo.CHAT_INFORMATION,
+        localeInfo.CHAT_NOTICE,
+        localeInfo.CHAT_QUIZ,
+    ]
+    CHAT_MODE_INDEX = [
+        chat.CHAT_TYPE_TALKING,
+        chat.CHAT_TYPE_PARTY,
+        chat.CHAT_TYPE_GUILD,
+        chat.CHAT_TYPE_SHOUT,
+        chat.CHAT_TYPE_INFO,
+        chat.CHAT_TYPE_NOTICE,
+        chat.CHAT_TYPE_QUIZ,
+    ]
 
     if app.ENABLE_DICE_SYSTEM:
         CHAT_MODE_NAME.append(localeInfo.CHAT_DICE_INFO)
@@ -1026,14 +1076,32 @@ class ChatLogWindow(ui.Window):
         if self.allChatMode:
             return
 
+        # Check if quiz mode was active before switching to all chat mode
+        quiz_was_active = False
+        quiz_button_index = None
+        for i, chat_mode in enumerate(self.CHAT_MODE_INDEX):
+            if chat_mode == chat.CHAT_TYPE_QUIZ:
+                quiz_button_index = i
+                break
+      
+        if quiz_button_index is not None and quiz_button_index < len(self.modeButtonList):
+            quiz_button = self.modeButtonList[quiz_button_index]
+            quiz_was_active = quiz_button.IsDown()
+
         self.allChatMode = True
 
         for i in self.CHAT_MODE_INDEX:
             chat.EnableChatMode(self.chatID, i)
         for btn in self.modeButtonList:
             btn.SetUp()
+      
+        # If quiz mode was active, send leave command when switching to all chat mode
+        if quiz_was_active:
+            net.SendChatPacket("/leave_quiz_spec", chat.CHAT_TYPE_TALKING)
 
     def ToggleChatMode(self, mode):
+        was_all_chat_mode = self.allChatMode
+      
         if self.allChatMode:
             self.allChatMode = False
             for i in self.CHAT_MODE_INDEX:
@@ -1043,6 +1111,27 @@ class ChatLogWindow(ui.Window):
 
         else:
             chat.ToggleChatMode(self.chatID, mode)
+      
+        # Handle quiz mode transitions for ChatLogWindow based on button state
+        if mode == chat.CHAT_TYPE_QUIZ:
+            # Find the quiz button (index 6 in CHAT_MODE_INDEX)
+            quiz_button_index = None
+            for i, chat_mode in enumerate(self.CHAT_MODE_INDEX):
+                if chat_mode == chat.CHAT_TYPE_QUIZ:
+                    quiz_button_index = i
+                    break
+          
+            if quiz_button_index is not None and quiz_button_index < len(self.modeButtonList):
+                quiz_button = self.modeButtonList[quiz_button_index]
+                if quiz_button.IsDown():
+                    # Button is pressed down - entering quiz mode
+                    net.SendChatPacket("/enter_quiz_spec", chat.CHAT_TYPE_TALKING)
+                elif was_all_chat_mode:
+                    # Coming from all chat mode and quiz button is now active - entering quiz mode
+                    net.SendChatPacket("/enter_quiz_spec", chat.CHAT_TYPE_TALKING)
+                else:
+                    # Button is up - leaving quiz mode
+                    net.SendChatPacket("/leave_quiz_spec", chat.CHAT_TYPE_TALKING)
 
     def SetSize(self, width, height):
         self.imgCenter.SetRenderingRect(0.0, 0.0, float((width - self.BLOCK_WIDTH*2) - self.BLOCK_WIDTH) / self.BLOCK_WIDTH, 0.0)
diff --git a/s3ll_client/Srcs/Client/UserInterface/Packet.h b/s3ll_client/Srcs/Client/UserInterface/Packet.h
index a1b2e37a..b8a1cce1 100644
--- a/s3ll_client/Srcs/Client/UserInterface/Packet.h
+++ b/s3ll_client/Srcs/Client/UserInterface/Packet.h
@@ -1365,6 +1365,7 @@ enum EChatType
     CHAT_TYPE_NOTICE,
     CHAT_TYPE_PARTY,
     CHAT_TYPE_GUILD,
+    CHAT_TYPE_QUIZ,
     CHAT_TYPE_COMMAND,
     CHAT_TYPE_SHOUT,
     CHAT_TYPE_WHISPER,
diff --git a/s3ll_client/Srcs/Client/UserInterface/PythonChat.cpp b/s3ll_client/Srcs/Client/UserInterface/PythonChat.cpp
index 4ee94a91..be862145 100644
--- a/s3ll_client/Srcs/Client/UserInterface/PythonChat.cpp
+++ b/s3ll_client/Srcs/Client/UserInterface/PythonChat.cpp
@@ -633,6 +633,7 @@ void CPythonChat::__Initialize()
     m_akD3DXClrChat[CHAT_TYPE_NOTICE]        = D3DXCOLOR(1.0f, 0.902f, 0.730f, 1.0f);
     m_akD3DXClrChat[CHAT_TYPE_PARTY]        = D3DXCOLOR(0.542f, 1.0f, 0.949f, 1.0f);
     m_akD3DXClrChat[CHAT_TYPE_GUILD]        = D3DXCOLOR(0.906f, 0.847f, 1.0f, 1.0f);
+    m_akD3DXClrChat[CHAT_TYPE_QUIZ]            = D3DXCOLOR(0.658f, 1.0f, 0.835f, 1.0f);
     m_akD3DXClrChat[CHAT_TYPE_COMMAND]        = D3DXCOLOR(0.658f, 1.0f, 0.835f, 1.0f);
     m_akD3DXClrChat[CHAT_TYPE_SHOUT]        = D3DXCOLOR(0.658f, 1.0f, 0.835f, 1.0f);
     m_akD3DXClrChat[CHAT_TYPE_WHISPER]        = D3DXCOLOR(0xff4AE14A);
diff --git a/s3ll_client/Srcs/Client/UserInterface/PythonChatModule.cpp b/s3ll_client/Srcs/Client/UserInterface/PythonChatModule.cpp
index 1dd99350..cd8cc8a0 100644
--- a/s3ll_client/Srcs/Client/UserInterface/PythonChatModule.cpp
+++ b/s3ll_client/Srcs/Client/UserInterface/PythonChatModule.cpp
@@ -503,6 +503,7 @@ void initChat()
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_NOTICE",        CHAT_TYPE_NOTICE);
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_PARTY",        CHAT_TYPE_PARTY);
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_GUILD",        CHAT_TYPE_GUILD);
+    PyModule_AddIntConstant(poModule, "CHAT_TYPE_QUIZ",            CHAT_TYPE_QUIZ);
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_COMMAND",        CHAT_TYPE_COMMAND);
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_SHOUT",        CHAT_TYPE_SHOUT);
     PyModule_AddIntConstant(poModule, "CHAT_TYPE_WHISPER",        CHAT_TYPE_WHISPER);
diff --git a/s3ll_client/Srcs/Client/UserInterface/PythonNetworkStreamPhaseGame.cpp b/s3ll_client/Srcs/Client/UserInterface/PythonNetworkStreamPhaseGame.cpp
index 35398bf0..12439847 100644
--- a/s3ll_client/Srcs/Client/UserInterface/PythonNetworkStreamPhaseGame.cpp
+++ b/s3ll_client/Srcs/Client/UserInterface/PythonNetworkStreamPhaseGame.cpp
@@ -1404,6 +1404,7 @@ bool CPythonNetworkStream::RecvChatPacket()
         case CHAT_TYPE_TALKING:
         case CHAT_TYPE_PARTY:
         case CHAT_TYPE_GUILD:
+        case CHAT_TYPE_QUIZ:
         case CHAT_TYPE_SHOUT:
         case CHAT_TYPE_WHISPER:
             {
diff --git a/s3ll_server/Srcs/Server/common/length.h b/s3ll_server/Srcs/Server/common/length.h
index 8d5b3852..ff25a2cf 100644
--- a/s3ll_server/Srcs/Server/common/length.h
+++ b/s3ll_server/Srcs/Server/common/length.h
@@ -309,6 +309,7 @@ enum EChatType
     CHAT_TYPE_NOTICE,
     CHAT_TYPE_PARTY,
     CHAT_TYPE_GUILD,
+    CHAT_TYPE_QUIZ,
     CHAT_TYPE_COMMAND,
     CHAT_TYPE_SHOUT,
     CHAT_TYPE_WHISPER,
diff --git a/s3ll_server/Srcs/Server/game/src/QuizShow.cpp b/s3ll_server/Srcs/Server/game/src/QuizShow.cpp
new file mode 100644
index 00000000..20959427
--- /dev/null
+++ b/s3ll_server/Srcs/Server/game/src/QuizShow.cpp
@@ -0,0 +1,622 @@
+#include "stdafx.h"
+#include "QuizShow.h"
+#include "char.h"
+#include "char_manager.h"
+#include "desc_manager.h"
+#include "questmanager.h"
+#include "log.h"
+#include "lua_incl.h"
+#include "locale_service.h"
+#include "event.h"
+#include "config.h"
+#include "item_manager.h"
+#include <boost/algorithm/string.hpp>
+#include <boost/regex.hpp>
+#include <random>
+#include <filesystem>
+#include <fmt/format.h>
+
+EVENTINFO(quiz_show_event_info)
+{
+};
+EVENTFUNC(quiz_show_event_func)
+{
+    if (!event || !event->info)
+        return 0;
+
+    auto& manager = CQuizShowManager::instance();
+  
+    // Let the manager handle the event tick
+    manager.ProcessEvent();
+  
+    // Continue the event if quiz is still running
+    return manager.IsRunning() ? PASSES_PER_SEC(1) : 0;
+}
+
+CQuizShowManager::CQuizShowManager()
+{
+    m_isRunning = false;
+    m_currentQuestionIndex = -1;
+    m_event = nullptr;
+    m_state = QUIZ_IDLE;
+    m_stateTimer = 0;
+    m_lastNoticeTime = 0;
+}
+CQuizShowManager::~CQuizShowManager()
+{
+    Clear();
+}
+
+void CQuizShowManager::Clear()
+{
+    m_questions.clear();
+    m_rewards.clear();
+    m_map_scores.clear();
+    m_found_answers.clear();
+    m_watchers.clear();
+
+    m_isRunning = false;
+    m_currentQuestionIndex = -1;
+    m_state = QUIZ_IDLE;
+    m_stateTimer = 0;
+    m_lastNoticeTime = 0;
+    m_event = nullptr;
+}
+
+void CQuizShowManager::StartEvent()
+{
+    if (m_isRunning)
+        return;
+
+    Clear();
+    m_isRunning = true;
+    LoadQuestions("quizshow.lua");
+
+    if (m_questions.empty())
+    {
+        BroadcastNotice("Quiz show questions file not found.");
+        EndEvent();
+        return;
+    }
+
+    std::random_device rd;
+    std::mt19937 g(rd());
+    std::shuffle(m_questions.begin(), m_questions.end(), g);
+  
+    BroadcastNotice("The quiz show has started! Please send your answers in the format '&answer'.");
+  
+    // Initialize state for first question
+    m_currentQuestionIndex = -1;
+    m_state = QUIZ_PREPARING;
+    m_stateTimer = 0;
+    m_lastNoticeTime = 0;
+  
+    // Start the single continuous event
+    auto info = AllocEventInfo<quiz_show_event_info>();
+    m_event = event_create(quiz_show_event_func, info, PASSES_PER_SEC(1));
+}
+
+void CQuizShowManager::EndEvent()
+{
+    if (!m_isRunning)
+        return;
+
+    if (m_event)
+    {
+        event_cancel(&m_event);
+        m_event = nullptr;
+    }
+
+    GiveRewardToWinner();
+    ShowScores();
+    BroadcastNotice("The quiz show has ended. Thank you for participating!");
+    Clear();
+}
+
+void CQuizShowManager::ClearEvent()
+{
+    if (m_event)
+    {
+        event_cancel(&m_event);
+    }
+    m_event = nullptr;
+}
+
+void CQuizShowManager::LoadQuestions(const std::string& filename)
+{
+    lua_State* L = quest::CQuestManager::instance().GetLuaState();
+    if (!L)
+    {
+        sys_err("Lua state is not initialized.");
+        return;
+    }
+
+    char script[256];
+    std::snprintf(script, sizeof(script), "%s/%s", LocaleService_GetBasePath().c_str(), filename.c_str());
+    if (!std::filesystem::exists(script))
+    {
+        sys_err("Quiz show script file not found: %s", script);
+        return;
+    }
+
+    if (lua_dofile(L, script))
+    {
+        sys_err("Cannot dofile quizshow script: %s", script);
+        return;
+    }
+
+    // Load questions
+    lua_getglobal(L, "quiz_questions");
+    if (lua_isnil(L, -1))
+    {
+        sys_err("quiz_questions table not found in %s", filename.c_str());
+        lua_pop(L, 1);
+        return;
+    }
+
+    if (lua_istable(L, -1))
+    {
+        const size_t tableSize = static_cast<size_t>(luaL_getn(L, -1));
+        for (int i = 1; i <= tableSize; ++i)
+        {
+            lua_rawgeti(L, -1, i);
+            if (lua_istable(L, -1))
+            {
+                TQuizQuestion q;
+
+                lua_pushstring(L, "q");
+                lua_gettable(L, -2);
+                if (lua_isstring(L, -1)) {
+                    q.question = lua_tostring(L, -1);
+                }
+                lua_pop(L, 1);
+
+                lua_pushstring(L, "a");
+                lua_gettable(L, -2);
+                if (lua_istable(L, -1)) {
+                    int answers_size = luaL_getn(L, -1);
+                    for (int j = 1; j <= answers_size; ++j) {
+                        lua_rawgeti(L, -1, j);
+                        if (lua_isstring(L, -1)) {
+                            q.answers.push_back(lua_tostring(L, -1));
+                        }
+                        lua_pop(L, 1);
+                    }
+                }
+                lua_pop(L, 1);
+
+                m_questions.push_back(q);
+            }
+            lua_pop(L, 1);
+        }
+    }
+    lua_pop(L, 1);
+
+    // Load rewards
+    LoadRewards();
+}
+
+void CQuizShowManager::LoadRewards()
+{
+    lua_State* L = quest::CQuestManager::instance().GetLuaState();
+    if (!L)
+    {
+        sys_err("Lua state is not initialized.");
+        return;
+    }
+
+    lua_getglobal(L, "quiz_rewards");
+    if (lua_isnil(L, -1))
+    {
+        sys_log(0, "quiz_rewards table not found, no rewards will be given");
+        lua_pop(L, 1);
+        return;
+    }
+
+    if (lua_istable(L, -1))
+    {
+        const size_t tableSize = static_cast<size_t>(luaL_getn(L, -1));
+        for (int i = 1; i <= tableSize; ++i)
+        {
+            lua_rawgeti(L, -1, i);
+            if (lua_istable(L, -1))
+            {
+                TQuizReward reward;
+
+                lua_pushstring(L, "vnum");
+                lua_gettable(L, -2);
+                if (lua_isnumber(L, -1)) {
+                    reward.vnum = static_cast<uint32_t>(lua_tonumber(L, -1));
+                }
+                lua_pop(L, 1);
+
+                lua_pushstring(L, "count");
+                lua_gettable(L, -2);
+                if (lua_isnumber(L, -1)) {
+                    reward.count = static_cast<uint32_t>(lua_tonumber(L, -1));
+                } else {
+                    reward.count = 1;
+                }
+                lua_pop(L, 1);
+
+                lua_pushstring(L, "name");
+                lua_gettable(L, -2);
+                if (lua_isstring(L, -1)) {
+                    reward.name = lua_tostring(L, -1);
+                }
+                lua_pop(L, 1);
+
+                if (reward.vnum > 0) {
+                    m_rewards.push_back(reward);
+                }
+            }
+            lua_pop(L, 1);
+        }
+    }
+    lua_pop(L, 1);
+
+    if (!m_rewards.empty())
+    {
+        std::string reward_msg = "Quiz show rewards: ";
+
+        for (size_t i = 0; i < m_rewards.size(); ++i)
+        {
+            if (i > 0)
+                reward_msg += ", ";
+
+            if (!m_rewards[i].name.empty())
+            {
+                reward_msg += fmt::format("{}x {}", m_rewards[i].count, m_rewards[i].name);
+            }
+            else
+            {
+                reward_msg += fmt::format("{}x Item#{}", m_rewards[i].count, m_rewards[i].vnum);
+            }
+        }
+
+        BroadcastNotice(reward_msg.c_str());
+    }
+}
+
+void CQuizShowManager::ProcessEvent()
+{
+    if (!m_isRunning)
+        return;
+
+    m_stateTimer++;
+
+    switch (m_state)
+    {
+        case QUIZ_PREPARING:
+        {
+            // Wait 3 seconds before first question
+            if (m_stateTimer >= 3)
+            {
+                SendQuestion();
+            }
+            break;
+        }
+      
+        case QUIZ_ASKING:
+        {
+            // Send periodic reminders about remaining time
+            int remaining = 30 - m_stateTimer;
+            if (remaining > 0 && (remaining == 20 || remaining == 10 || remaining == 5))
+            {
+                if (m_lastNoticeTime != remaining)
+                {
+                    BroadcastNotice(fmt::format("Time remaining: {} seconds", remaining).c_str());
+                    m_lastNoticeTime = remaining;
+                }
+            }
+          
+            // Check if all answers found
+            if (m_found_answers.size() == m_questions[m_currentQuestionIndex].answers.size())
+            {
+                // All answers found - transition to reveal immediately but wait for timer
+                if (m_state != QUIZ_REVEAL)
+                {
+                    m_state = QUIZ_REVEAL;
+                    BroadcastNotice("All answers have been found!");
+                    ShowScores();
+                    BroadcastNotice("Next question will be asked in 15 seconds. Please prepare your answers!");
+                    m_stateTimer = 0; // Reset timer for reveal phase
+                }
+            }
+            // Time's up
+            else if (m_stateTimer >= 30)
+            {
+                EndRound();
+            }
+            break;
+        }
+      
+        case QUIZ_REVEAL:
+        {
+            // Send countdown notices for next question
+            int remaining = 15 - m_stateTimer;
+            if (remaining > 0 && (remaining == 10 || remaining == 5))
+            {
+                if (m_lastNoticeTime != remaining)
+                {
+                    BroadcastNotice(fmt::format("Next question in {} seconds", remaining).c_str());
+                    m_lastNoticeTime = remaining;
+                }
+            }
+          
+            // Time to send next question
+            if (m_stateTimer >= 15)
+            {
+                SendQuestion();
+            }
+            break;
+        }
+      
+        default:
+            break;
+    }
+}
+
+void CQuizShowManager::SendQuestion()
+{
+    if (!m_isRunning || m_questions.empty())
+    {
+        EndEvent();
+        return;
+    }
+
+    m_currentQuestionIndex++;
+    m_found_answers.clear();
+
+    if (m_currentQuestionIndex >= m_questions.size())
+    {
+        EndEvent();
+        return;
+    }
+
+    const auto& q = m_questions[m_currentQuestionIndex];
+    BroadcastNotice(fmt::format("Question #{0}: {1} ({2} answers)", m_currentQuestionIndex + 1, q.question, q.answers.size()).c_str());
+
+    m_state = QUIZ_ASKING;
+    m_stateTimer = 0;
+    m_lastNoticeTime = 0;
+}
+
+void CQuizShowManager::EndRound()
+{
+    m_state = QUIZ_REVEAL;
+
+    std::string reveal_msg = "Time's up! ";
+    int unfound_count = 0;
+  
+    for (const auto& answer : m_questions[m_currentQuestionIndex].answers)
+    {
+        if (m_found_answers.find(NormalizeAnswer(answer)) == m_found_answers.end())
+        {
+            unfound_count++;
+        }
+    }
+
+    if (unfound_count == 0)
+        reveal_msg = "All answers have been found!";
+    else
+        reveal_msg += fmt::format("Unfound answers: {} out of {}", unfound_count, m_questions[m_currentQuestionIndex].answers.size());
+
+    BroadcastNotice(reveal_msg.c_str());
+    ShowScores();
+    BroadcastNotice("Next question will be asked in 15 seconds. Please prepare your answers!");
+  
+    // Reset timer for reveal phase - the single event will handle the transition
+    m_stateTimer = 0;
+    m_lastNoticeTime = 0;
+}
+
+
+void CQuizShowManager::HandleAnswer(LPCHARACTER ch, const std::string& answer)
+{
+    if (!m_isRunning || m_state != QUIZ_ASKING)
+        return;
+
+    std::string normalized_answer = NormalizeAnswer(answer);
+
+    for (const auto& correct_answer : m_questions[m_currentQuestionIndex].answers)
+    {
+        if (normalized_answer == NormalizeAnswer(correct_answer))
+        {
+            if (m_found_answers.find(normalized_answer) == m_found_answers.end())
+            {
+                m_found_answers.insert(normalized_answer);
+                m_map_scores[ch->GetPlayerID()]++;
+                BroadcastNotice(fmt::format("{0} has correctly answered '{1}'! (+1 point)", ch->GetName(), correct_answer).c_str());
+            }
+            else
+            {
+                ch->ChatPacket(CHAT_TYPE_INFO, "That answer has already been found.");
+            }
+            return;
+        }
+    }
+}
+
+std::string CQuizShowManager::NormalizeAnswer(const std::string& str)
+{
+    std::string temp = str;
+    boost::algorithm::to_lower(temp);
+    boost::regex re("[^a-z0-9]");
+    return boost::regex_replace(temp, re, "");
+}
+
+void CQuizShowManager::HandleCommand(LPCHARACTER ch, const std::string& command)
+{
+    if (!ch->IsGM())
+        return;
+
+    std::vector<std::string> tokens;
+    boost::split(tokens, command, boost::is_any_of(" "));
+
+    if (tokens.empty())
+        return;
+
+    if (tokens[0] == "start")
+    {
+        StartEvent();
+    }
+    else if (tokens[0] == "end")
+    {
+        EndEvent();
+    }
+    else if (tokens[0] == "scores")
+    {
+        ShowScores(ch);
+    }
+}
+
+void CQuizShowManager::ShowScores(LPCHARACTER ch)
+{
+    std::string score_message = "--- Quiz Show Scores ---";
+
+    if (m_map_scores.empty())
+    {
+        score_message += "\nNo players have scored yet.";
+    }
+    else
+    {
+        std::vector<std::pair<uint32_t, int>> sorted_scores(m_map_scores.begin(), m_map_scores.end());
+        std::sort(sorted_scores.begin(), sorted_scores.end(), [](const auto& a, const auto& b) {
+            return a.second > b.second;
+        });
+
+        int displayed_count = 0;
+        for (const auto& score_pair : sorted_scores)
+        {
+            if (displayed_count >= 10)
+                break;
+              
+            LPCHARACTER player = CHARACTER_MANAGER::instance().FindByPID(score_pair.first);
+            if (player)
+            {
+                score_message += fmt::format("\n{0}: {1} points", player->GetName(), score_pair.second);
+                displayed_count++;
+            }
+        }
+      
+        if (sorted_scores.size() > 10)
+        {
+            score_message += fmt::format("\n... and {} more players", sorted_scores.size() - 10);
+        }
+    }
+  
+    if (ch)
+        ch->ChatPacket(CHAT_TYPE_INFO, score_message.c_str());
+    else
+        BroadcastNotice(score_message.c_str());
+}
+
+void CQuizShowManager::GiveRewardToWinner()
+{
+    if (m_rewards.empty() || m_map_scores.empty())
+        return;
+
+    uint32_t winner_pid = 0;
+    int max_score = 0;
+
+    for (const auto& score_pair : m_map_scores)
+    {
+        if (score_pair.second > max_score)
+        {
+            max_score = score_pair.second;
+            winner_pid = score_pair.first;
+        }
+    }
+
+    if (winner_pid != 0)
+    {
+        LPCHARACTER winner = CHARACTER_MANAGER::instance().FindByPID(winner_pid);
+        if (winner)
+        {
+            // Give all rewards to the winner
+            for (const auto& reward : m_rewards)
+            {
+                if (reward.vnum > 2)
+                {
+                    winner->AutoGiveItem(reward.vnum, reward.count);
+                }
+                else if (reward.vnum == 2) // Special case for EXP
+                {
+                    winner->PointChange(POINT_EXP, reward.count, true);
+                }
+                else if (reward.vnum == 1) // Special case for yang
+                {
+                    winner->PointChange(POINT_GOLD, reward.count, true);
+                }
+                else
+                {
+                    sys_err("CQuizShowManager::GiveRewardToWinner : Invalid reward vnum %u", reward.vnum);
+                }
+            }
+
+            const auto buffer = fmt::format("The winner is {0} with {1} points! Congratulations!", winner->GetName(), max_score);
+            BroadcastNotice(buffer.c_str(), true);
+        }
+        else
+        {
+            sys_err("CQuizShowManager::GiveRewardToWinner : Winner character not found (PID: %u)", winner_pid);
+        }
+    }
+}
+
+// Watcher functionality implementation
+void CQuizShowManager::AddWatcher(uint32_t pid)
+{
+    if (!pid)
+        return;
+
+    if (IsWatcher(pid))
+        return;
+      
+    m_watchers.insert(pid);
+
+    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pid);
+    if (ch)
+        ch->ChatPacket(CHAT_TYPE_INFO, "You are now watching the quiz show. You will see all answers submitted by players.");
+}
+
+void CQuizShowManager::RemoveWatcher(uint32_t pid)
+{
+    if (!pid)
+        return;
+      
+    auto it = m_watchers.find(pid);
+    if (it != m_watchers.end())
+    {
+        m_watchers.erase(it);
+
+        LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pid);
+        if (ch)
+            ch->ChatPacket(CHAT_TYPE_INFO, "You are no longer watching the quiz show.");
+    }
+}
+
+void CQuizShowManager::BroadcastToWatchers(const std::string& message)
+{
+    // Remove disconnected watchers
+    auto it = m_watchers.begin();
+    while (it != m_watchers.end())
+    {
+        LPCHARACTER watcher = CHARACTER_MANAGER::instance().FindByPID(*it);
+        if (!watcher || !watcher->GetDesc())
+        {
+            it = m_watchers.erase(it);
+        }
+        else
+        {
+            watcher->ChatPacket(CHAT_TYPE_QUIZ, message.c_str());
+            ++it;
+        }
+    }
+}
+
+bool CQuizShowManager::IsWatcher(uint32_t pid) const
+{
+    return pid && m_watchers.find(pid) != m_watchers.end();
+}
\ No newline at end of file
diff --git a/s3ll_server/Srcs/Server/game/src/QuizShow.h b/s3ll_server/Srcs/Server/game/src/QuizShow.h
new file mode 100644
index 00000000..89d7c20f
--- /dev/null
+++ b/s3ll_server/Srcs/Server/game/src/QuizShow.h
@@ -0,0 +1,80 @@
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <unordered_set>
+
+class CHARACTER;
+
+struct TQuizQuestion
+{
+    std::string question;
+    std::vector<std::string> answers;
+};
+
+struct TQuizReward
+{
+    uint32_t vnum;
+    uint32_t count;
+    std::string name;
+};
+
+enum EQuizState
+{
+    QUIZ_IDLE,
+    QUIZ_PREPARING,
+    QUIZ_ASKING,
+    QUIZ_REVEAL,
+};
+
+class CQuizShowManager : public singleton<CQuizShowManager>
+{
+public:
+    CQuizShowManager();
+    virtual ~CQuizShowManager();
+
+    void StartEvent();
+    void EndEvent();
+    bool IsRunning() const { return m_isRunning; }
+
+    void LoadQuestions(const std::string& filename);
+    void SendQuestion();
+    void EndRound();
+
+    void HandleAnswer(LPCHARACTER ch, const std::string& answer);
+    void HandleCommand(LPCHARACTER ch, const std::string& command);
+
+    void ShowScores(LPCHARACTER ch = nullptr);
+    void ClearEvent();
+    EQuizState GetState() const { return m_state; }
+    void ProcessEvent();
+  
+    // Watcher functionality
+    void AddWatcher(uint32_t pid);
+    void RemoveWatcher(uint32_t pid);
+    void BroadcastToWatchers(const std::string& message);
+    bool IsWatcher(uint32_t pid) const;
+  
+protected:
+    void Clear();
+    std::string NormalizeAnswer(const std::string& str);
+    void GiveRewardToWinner();
+    void LoadRewards();
+
+private:
+    bool m_isRunning;
+    EQuizState m_state;
+    std::vector<TQuizQuestion> m_questions;
+    std::vector<TQuizReward> m_rewards;
+    int m_currentQuestionIndex;
+    LPEVENT m_event;
+
+    std::unordered_map<uint32_t, int> m_map_scores;
+    std::unordered_set<std::string> m_found_answers;
+    std::unordered_set<uint32_t> m_watchers;
+  
+    // Timer management for single event system
+    int m_stateTimer;
+    int m_lastNoticeTime;
+};
\ No newline at end of file
diff --git a/s3ll_server/Srcs/Server/game/src/char.cpp b/s3ll_server/Srcs/Server/game/src/char.cpp
index 7fa25519..39ec7e2b 100644
--- a/s3ll_server/Srcs/Server/game/src/char.cpp
+++ b/s3ll_server/Srcs/Server/game/src/char.cpp
@@ -28,6 +28,7 @@
 #include "party.h"
 #include "start_position.h"
 #include "questmanager.h"
+#include "QuizShow.h"
 #include "log.h"
 #include "p2p.h"
 #include "guild.h"
@@ -1476,6 +1477,8 @@ void CHARACTER::Disconnect(const char * c_pszReason)
         GetParty()->UpdateOfflineState(GetPlayerID());
     }
 
+    CQuizShowManager::instance().RemoveWatcher(GetPlayerID());
+
     marriage::CManager::instance().Logout(this);
 
     // P2P Logout
diff --git a/s3ll_server/Srcs/Server/game/src/cmd.cpp b/s3ll_server/Srcs/Server/game/src/cmd.cpp
index e710e12a..186ac1ef 100644
--- a/s3ll_server/Srcs/Server/game/src/cmd.cpp
+++ b/s3ll_server/Srcs/Server/game/src/cmd.cpp
@@ -59,6 +59,10 @@ ACMD(do_refine_pick);
 
 ACMD(do_refine_tool);
 
+ACMD(do_quiz_manage);
+ACMD(do_enter_quiz_spec);
+ACMD(do_leave_quiz_spec);
+
 ACMD(do_fishing_simul);
 ACMD(do_console);
 ACMD(do_restart);
@@ -387,6 +391,10 @@ struct command_info cmd_info[] =
 
     { "refine_tool",    do_refine_tool,        0,            POS_DEAD,    GM_IMPLEMENTOR    },
 
+    { "quiz_manage",    do_quiz_manage,        0,            POS_DEAD,    GM_IMPLEMENTOR    },
+    { "enter_quiz_spec", do_enter_quiz_spec, 0,            POS_DEAD,    GM_PLAYER    },
+    { "leave_quiz_spec", do_leave_quiz_spec, 0,            POS_DEAD,    GM_PLAYER    },
+  
     { "fish_simul",    do_fishing_simul,    0,            POS_DEAD,    GM_IMPLEMENTOR    },
     { "invisible",    do_invisibility,    0,            POS_DEAD,    GM_LOW_WIZARD    },
     { "qf",        do_qf,            0,            POS_DEAD,    GM_IMPLEMENTOR    },
diff --git a/s3ll_server/Srcs/Server/game/src/cmd_general.cpp b/s3ll_server/Srcs/Server/game/src/cmd_general.cpp
index 9e6fe1e5..46614246 100644
--- a/s3ll_server/Srcs/Server/game/src/cmd_general.cpp
+++ b/s3ll_server/Srcs/Server/game/src/cmd_general.cpp
@@ -17,6 +17,7 @@
 #include "pvp.h"
 #include "start_position.h"
 #include "party.h"
+#include "QuizShow.h"
 #include "guild_manager.h"
 #include "p2p.h"
 #include "dungeon.h"
@@ -2186,6 +2187,16 @@ ACMD(do_cube)
     }
 }
 
+ACMD(do_enter_quiz_spec)
+{
+    CQuizShowManager::instance().AddWatcher(ch->GetPlayerID());
+}
+
+ACMD(do_leave_quiz_spec)
+{
+    CQuizShowManager::instance().RemoveWatcher(ch->GetPlayerID());
+}
+
 ACMD(do_in_game_mall)
 {
     if (LC_IsEurope() == true)
diff --git a/s3ll_server/Srcs/Server/game/src/cmd_gm.cpp b/s3ll_server/Srcs/Server/game/src/cmd_gm.cpp
index db0fa67f..4e900be1 100644
--- a/s3ll_server/Srcs/Server/game/src/cmd_gm.cpp
+++ b/s3ll_server/Srcs/Server/game/src/cmd_gm.cpp
@@ -15,6 +15,7 @@
 #include "guild_manager.h"
 #include "p2p.h"
 #include "buffer_manager.h"
+#include "QuizShow.h"
 #include "fishing.h"
 #include "mining.h"
 #include "questmanager.h"
@@ -4709,6 +4710,14 @@ ACMD (do_use_item)
     }
 }
 
+ACMD(do_quiz_manage)
+{
+    char arg1[256];
+    one_argument(argument, arg1, sizeof(arg1));
+
+    CQuizShowManager::instance().HandleCommand(ch, arg1);
+}
+
 ACMD (do_clear_affect)
 {
     ch->ClearAffect(true);
diff --git a/s3ll_server/Srcs/Server/game/src/game.vcxproj b/s3ll_server/Srcs/Server/game/src/game.vcxproj
index a17be2d4..60c008dc 100644
--- a/s3ll_server/Srcs/Server/game/src/game.vcxproj
+++ b/s3ll_server/Srcs/Server/game/src/game.vcxproj
@@ -258,6 +258,7 @@
     <ClCompile Include="questmanager.cpp" />
     <ClCompile Include="questnpc.cpp" />
     <ClCompile Include="questpc.cpp" />
+    <ClCompile Include="QuizShow.cpp" />
     <ClCompile Include="refine.cpp" />
     <ClCompile Include="regen.cpp" />
     <ClCompile Include="safebox.cpp" />
@@ -383,6 +384,7 @@
     <ClInclude Include="questmanager.h" />
     <ClInclude Include="questnpc.h" />
     <ClInclude Include="questpc.h" />
+    <ClInclude Include="QuizShow.h" />
     <ClInclude Include="refine.h" />
     <ClInclude Include="regen.h" />
     <ClInclude Include="safebox.h" />
diff --git a/s3ll_server/Srcs/Server/game/src/game.vcxproj.filters b/s3ll_server/Srcs/Server/game/src/game.vcxproj.filters
index d31f5a72..b7cb67bc 100644
--- a/s3ll_server/Srcs/Server/game/src/game.vcxproj.filters
+++ b/s3ll_server/Srcs/Server/game/src/game.vcxproj.filters
@@ -472,6 +472,9 @@
     <ClCompile Include="JobManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="QuizShow.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="affect.h">
@@ -856,6 +859,9 @@
     <ClInclude Include="JobManager.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="QuizShow.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="any_function.inc">
diff --git a/s3ll_server/Srcs/Server/game/src/input_main.cpp b/s3ll_server/Srcs/Server/game/src/input_main.cpp
index 70d6b193..00e53702 100644
--- a/s3ll_server/Srcs/Server/game/src/input_main.cpp
+++ b/s3ll_server/Srcs/Server/game/src/input_main.cpp
@@ -21,6 +21,8 @@
 #include "questmanager.h"
 #include "profiler.h"
 #include "messenger_manager.h"
+#include "QuizShow.h"
+#include <fmt/format.h>
 #include "party.h"
 #include "p2p.h"
 #include "affect.h"
@@ -831,6 +833,22 @@ int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
                 }
             }
             break;
+          
+        case CHAT_TYPE_QUIZ:
+        {
+            if (!CQuizShowManager::instance().IsRunning())
+            {
+                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Quiz event is not running."));
+            }
+            else
+            {
+                // Broadcast answer to watchers before processing
+                std::string watcherMessage = fmt::format("{}: {}", ch->GetName(), buf);
+                CQuizShowManager::instance().BroadcastToWatchers(watcherMessage);
+              
+                CQuizShowManager::instance().HandleAnswer(ch, std::string(buf, buflen));
+            }
+        } break;
 
         case CHAT_TYPE_GUILD:
             {
diff --git a/s3ll_server/Srcs/Server/game/src/main.cpp b/s3ll_server/Srcs/Server/game/src/main.cpp
index d650d4a9..a167bf9f 100644
--- a/s3ll_server/Srcs/Server/game/src/main.cpp
+++ b/s3ll_server/Srcs/Server/game/src/main.cpp
@@ -30,6 +30,7 @@
 #include "refine.h"
 #include "banword.h"
 #include "priv_manager.h"
+#include "QuizShow.h"
 #include "war_map.h"
 #include "building.h"
 #include "login_sim.h"
@@ -387,6 +388,7 @@ int main(int argc, char **argv)
     CHorseNameManager horsename_manager;
 
     DESC_MANAGER    desc_manager;
+    CQuizShowManager quiz_show_manager;
 
     CTableBySkill SkillPowerByLevel;
     CPolymorphUtils polymorph_utils;
diff --git a/s3ll_svfiles/main/srv1/share/locale/germany/quizshow.lua b/s3ll_svfiles/main/srv1/share/locale/germany/quizshow.lua
new file mode 100644
index 00000000..98e02404
--- /dev/null
+++ b/s3ll_svfiles/main/srv1/share/locale/germany/quizshow.lua
@@ -0,0 +1,57 @@
+-- Quiz Show Configuration File
+-- This file contains questions and rewards for the quiz show system
+
+-- Questions table - each question has a question text (q) and array of answers (a)
+quiz_questions = {
+    {
+        q = "What is the capital of France?",
+        a = {"Paris"}
+    },
+    {
+        q = "What are the primary colors?",
+        a = {"Red", "Blue", "Yellow"}
+    },
+    {
+        q = "Name planets in our solar system",
+        a = {"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"}
+    },
+    {
+        q = "What are common web browsers?",
+        a = {"Chrome", "Firefox", "Safari", "Edge", "Opera"}
+    }
+}
+
+-- Rewards table - items given to the winner
+-- Each reward has: vnum (item ID), count (quantity), name (display name - optional)
+--
+-- HARDCODED SPECIAL IDs:
+-- vnum = 1: Direct Yang/Gold (count = amount of yang to give)
+-- vnum = 2: Direct Experience Points (count = amount of exp to give)
+-- All other vnums are regular item IDs from your item_proto
+quiz_rewards = {
+    {
+        vnum = 1,       -- HARDCODED: Direct Yang/Gold
+        count = 1000000,
+        name = "Yang"
+    },
+    {
+        vnum = 2,       -- HARDCODED: Direct Experience Points
+        count = 500000,
+        name = "Experience"
+    },
+    {
+        vnum = 50300,   -- Regular item: Skill Book
+        count = 10,
+        name = "Skill Book"
+    },
+    {
+        vnum = 70038,   -- Regular item: Bravery Cape
+        count = 1,
+        name = "Bravery Cape"
+    },
+    {
+        vnum = 50001,   -- Regular item: Lucky Book
+        count = 5,
+        name = "Lucky Book"
+    }
+}
\ No newline at end of file
--
2.47.1.windows.2

© 2006 - 2025 Paste2.org.
Follow paste2.org on Twitter

locale kısmı eksik kalmış, locale/../locale_game.txt dosyasına ekleyin:
Kod:
Genişlet Daralt Kopyala
CHAT_QUIZ    Etkinlik

Sublime text ya da benzeri modern bir IDE ile ya da online olarak ya da benzeri bir site ile daha düzgün görüntüleyebilirsiniz.

Event komutları:
/quiz_manage <start/end/scores>
 
En son bir moderatör tarafından düzenlenmiş:
Etkinlik sonunda pek çok oyuncunun muhtemel yüz ifadesi:
orig_828x6065fe8a5307aacab7adff584840c39a959c6b44817.webp



Eline sağlık :You_Rock_Emoticon:
 
epey iyi görünüyor eline sağlık
 
Eskiden IRC'de Kaos soru-cevap botu isminde bir etkinlik botu vardı, onu metin2'ye uyarladım. OX gibi mini bir event olarak düşünebilirsiniz, her soru birden fazla cevap destekler ve her cevap için katılımcılar + puan kazanır ve en çok puana ulaşanda belirlediğiniz ödülü alır.



Aşağıdaki diff patch dosyasındaki değişiklikleri yaparak ekleyebilirsiniz.


locale kısmı eksik kalmış, locale/../locale_game.txt dosyasına ekleyin:
Kod:
Genişlet Daralt Kopyala
CHAT_QUIZ    Etkinlik

Sublime text ya da benzeri modern bir IDE ile ya da online olarak ya da benzeri bir site ile daha düzgün görüntüleyebilirsiniz.

Event komutları:
/quiz_manage <start/end/scores>

Eline sağlık gelişime açık bir sistem . Bu arada şu oyun içi debug modu baya bir iş görecek hepimize :)
 
Alttaki kiro detayıda gözden kaçmadı Koray abi bizde erken erişim istiyoruz
 
Eskiden IRC'de Kaos soru-cevap botu isminde bir etkinlik botu vardı, onu metin2'ye uyarladım. OX gibi mini bir event olarak düşünebilirsiniz, her soru birden fazla cevap destekler ve her cevap için katılımcılar + puan kazanır ve en çok puana ulaşanda belirlediğiniz ödülü alır.



Aşağıdaki diff patch dosyasındaki değişiklikleri yaparak ekleyebilirsiniz.


locale kısmı eksik kalmış, locale/../locale_game.txt dosyasına ekleyin:
Kod:
Genişlet Daralt Kopyala
CHAT_QUIZ    Etkinlik

Sublime text ya da benzeri modern bir IDE ile ya da online olarak ya da benzeri bir site ile daha düzgün görüntüleyebilirsiniz.

Event komutları:
/quiz_manage <start/end/scores>

Diff patchi kendiniz elle mi oluşturuyorsunuz üstad o kadar profesyonel gözüküyor ki bir program çıktısı gibi

ek olarak protonmail fav <3
 
Son düzenleme:
Geri
Üst