[ create a new paste ] login | about

Link: http://codepad.org/NztZ1Shx    [ raw code | fork ]

C++, pasted on Aug 7:
/* $Id: Players.cpp 184 2010-01-10 05:58:12Z sausage $
 * EOSERV is released under the zlib license.
 * See LICENSE.txt for more info.
 */

#include "handlers.h"

#include "eodata.hpp"
#include "map.hpp"
#include "npc.hpp"

CLIENT_F_FUNC(Quest)
{
	PacketBuilder reply;

	switch (action)
	{
		case PACKET_USE: // Player clicked on a quest NPC
		{
			if (this->state < EOClient::Playing) return false;

			short id = reader.GetShort();
			short quests_index = reader.GetShort();

			UTIL_PTR_VECTOR_FOREACH(this->player->character->map->npcs, NPC, npc)
			{
				if (npc->index == id && npc->Data()->type == ENF::Quest)
				{
				    this->player->character->npc = *npc;
				    this->player->character->npc_type = ENF::Quest;

				    PtrVector<Quest> quests;
				    Quest *quests_start = this->server->world->GetQuest(quests_index == 0 ? npc->Data()->type_index : quests_index);
				    if (quests_start->exists)
				    {
				        quests.push_back(quests_start);

				        Character_Quest *character_quest = this->player->character->GetQuest(quests_start->id);
				        if (!character_quest)
				        {
				            character_quest = new Character_Quest();
				            character_quest->id = quests_start->id;
				            character_quest->state = "begin";
				            this->player->character->quests.push_back(character_quest);
				        }
				    }

				    State *state = 0;
				    Quest *temp_quest = 0;
                    std::list<std::string> npc_text;
                    std::map<int, std::string> npc_input;
				    UTIL_PTR_LIST_FOREACH(this->player->character->quests, Character_Quest, quest)
				    {
				        temp_quest = this->server->world->GetQuest(quest->id);
				        if (!temp_quest->exists) continue;

				        state = temp_quest->GetState(quest->state);
				        if (!state) continue;

				        bool found = false;
				        UTIL_PTR_VECTOR_FOREACH(state->actions, Action, action)
				        {
                            if (action->name.compare("addnpctext") == 0 && ((int)(*action->args[0])) == npc->Data()->type_index)
                            {
                                if (quests.size() == 0)
                                {
                                    npc_text.push_back(static_cast<std::string>((*action->args[1])));
                                    if (!found)
                                        found = true;
                                }
                                else if (quests[0]->id == quest->id)
                                {
                                    npc_text.push_back(static_cast<std::string>((*action->args[1])));
                                }
                                else
                                {
                                    if (!found)
                                        found = true;
                                }
                            }
                            else if (action->name.compare("addnpcinput") == 0 && ((int)(*action->args[0])) == npc->Data()->type_index)
                            {
                                if (quests.size() == 0)
                                {
                                    npc_input.insert(std::pair<int, std::string>(static_cast<int>((*action->args[1])), static_cast<std::string>((*action->args[2]))));
                                    if (!found)
                                        found = true;
                                }
                                else if (quests[0]->id == quest->id)
                                {
                                    npc_input.insert(std::pair<int, std::string>(static_cast<int>((*action->args[1])), static_cast<std::string>((*action->args[2]))));
                                }
                                else
                                {
                                    if (!found)
                                        found = true;
                                }
                            }
                            else if (action->name.compare("addnpcchat") == 0 && ((int)(*action->args[0])) == npc->Data()->type_index)
                            {
                                if ((quests.size() == 0 || quests[0]->id == quest->id) && util::rand(0, 100) < 20) /* 20 percent chance */
                                {
                                    npc->ShowDialog(static_cast<std::string>((*action->args[1])));
                                }
                            }
				        }

				        if (found)
				        {
				            quests.push_back(temp_quest);
				        }
				    }

				    if (quests.size() == 0) return false;

                    reply.SetID(PACKET_QUEST, PACKET_DIALOG);
                    reply.AddChar(quests.size());
                    reply.AddShort(npc->Data()->type_index);
                    reply.AddShort(quests[0]->id); //Quest_ID
                    reply.AddInt(0); // Session token
                    reply.AddByte(255);
                    UTIL_PTR_VECTOR_FOREACH(quests, Quest, npc_quests)
                    {
                        reply.AddShort(npc_quests->id);
                        reply.AddBreakString(npc_quests->name);
                    }
                    bool has_dialog = !npc_text.empty() || !npc_input.empty();
                    while (!npc_text.empty())
                    {
                        reply.AddShort(1);
                        reply.AddBreakString(npc_text.front());
                        npc_text.pop_front();
                    }
                    for (std::map<int, std::string>::iterator it = npc_input.begin(); it != npc_input.end(); ++it)
                    {
                        reply.AddShort(2);
                        reply.AddShort((*it).first);
                        reply.AddBreakString((*it).second);
                    }

                    if (has_dialog)
                        CLIENT_SEND(reply);
				}
			}
		}
		break;

        case PACKET_ACCEPT: // User clicking a link, or accepting quest
		{
			if (this->state < EOClient::PlayingModal) return false;

			reader.GetInt(); // Session token
			short id = reader.GetShort();
			short npc_quest_index = reader.GetShort();
			unsigned char input_type = reader.GetChar();
			unsigned char input = reader.GetChar();
			if (!this->player->character->npc || this->player->character->npc_type != ENF::Quest ||
                this->player->character->npc->Data()->type_index != npc_quest_index)
            {
                return false;
            }

            Character_Quest *character_quest = this->player->character->GetQuest(id);
            State *state = 0;
            if (character_quest) state = this->server->world->GetQuest(id)->GetState(character_quest->state);
            else state = this->server->world->GetQuest(id)->GetState("begin");

			UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
			{
			    if ((rule->name.compare("inputnpc") == 0 && (int)(*rule->args[0]) == input) ||
                    (rule->name.compare("talkedtonpc") == 0 && (int)(*rule->args[0]) == npc_quest_index) ||
                    (rule->name.compare("gotitems") == 0 && this->player->character->HasItem((int)(*rule->args[0])) >= (int)(*rule->args[1])) ||
                    (rule->name.compare("lostitems") == 0 && this->player->character->HasItem((int)(*rule->args[0])) < (int)(*rule->args[1])))
			    {
                    if (!character_quest)
                    {
                        character_quest = new Character_Quest();
                        character_quest->id = id;
                        this->player->character->quests.push_back(character_quest);
                    }

                    character_quest->state = rule->goto_state;
                    if (this->player->character->PerformQuestActions(character_quest->id))
                    {
                        util::quadchar index = PacketProcessor::ENumber(this->player->character->npc->index);
                        PacketBuilder builder(PACKET_QUEST, PACKET_USE);
                        builder.AddShort(this->player->character->npc->index);
                        builder.AddShort(npc_quest_index == id ? 0 : id);
                        PacketReader reader(builder.Get().substr(4)); // Skip the id and length
                        this->player->client->queue.AddAction(PACKET_QUEST, PACKET_USE, reader, 0.0);
                    }
                    break;
			    }
			}
		}
		break;

		case PACKET_LIST: // User requests his own quest history
		{
		    if (this->state < EOClient::PlayingModal) return false;

		    unsigned char book_type = reader.GetChar();

		    reply.SetID(PACKET_QUEST, PACKET_LIST);
		    reply.AddChar(book_type);
		    reply.AddShort(this->player->character->quests.size());

		    if (this->player->character->quests.size() == 0)
		    {
		        CLIENT_SEND(reply);
		        return true;
		    }

		    Quest *temp_quest = 0;
		    State *state = 0;
		    UTIL_PTR_LIST_FOREACH(this->player->character->quests, Character_Quest, quest)
		    {
		        temp_quest = this->server->world->GetQuest(quest->id);
		        if (!temp_quest->exists) continue;

                state = temp_quest->GetState(quest->state);
                if (!state) continue;

                bool completed = false;
                UTIL_PTR_VECTOR_FOREACH(state->actions, Action, action)
                {
                    if (action->name.compare("end") == 0)
                    {
                        completed = true;
                        break;
                    }
                }

                if (!completed && book_type == 1) // Progress
                {
                    reply.AddBreakString(temp_quest->name);
                    reply.AddBreakString(state->description);
                    UTIL_PTR_VECTOR_FOREACH(state->rules, Rule, rule)
                    {
                        if (rule->name.compare("gotitems") == 0 || rule->name.compare("lostitems") == 0)
                        {
                            short item = ((int)(*rule->args[0]));
                            int amount = ((int)(*rule->args[1]));

                            reply.AddShort(BOOK_ICON_ITEM);
                            reply.AddShort(this->player->character->HasItem(item));
                            reply.AddShort(amount);
                        }
                        else if (rule->name.compare("inputnpc") == 0 || rule->name.compare("talkedtonpc") == 0)
                        {
                            reply.AddShort(BOOK_ICON_TALK);
                            reply.AddShort(0);
                            reply.AddShort(0);
                        }
                        else if (rule->name.compare("killednpcs") == 0 || rule->name.compare("killedplayers") == 0)
                        {
                            int amount = ((int)(*rule->args[1]));

                            reply.AddShort(BOOK_ICON_KILL);
                            reply.AddShort(quest->killed);
                            reply.AddShort(amount);
                        }
                        else if (rule->name.compare("entercoord") == 0 || rule->name.compare("leavecoord") == 0 ||
                            rule->name.compare("entermap") == 0 || rule->name.compare("leavemap") == 0)
                        {
                            reply.AddShort(BOOK_ICON_STEP);
                            reply.AddShort(0);
                            reply.AddShort(1);
                        }
                        break;
                    }
                    reply.AddByte(255);
                }
                else if (completed && book_type == 2) // History
                {
                    reply.AddBreakString(temp_quest->name);
                    reply.AddByte(255);
                }
		    }
		    CLIENT_SEND(reply);
		}
		break;

		default:
			return false;
	}

	return true;
}


Create a new paste based on this one


Comments: