Пример #1
0
std::vector<std::string> InfoManager::GetLoadingAnnouncments() {
	STRINGLIST l = g_ClusterManager.GetList(LISTPREFIX_LOADING_ANNOUNCMENTS);
	STRINGLIST s;
	if(l.size() == 0) {
		s.push_back(StringUtil::Format(ReplaceBrandingPatterns("Welcome to ${GameName} - ${Edition}. You can set your own <b>Loading Announcements</b> by creating and adding multiple elements to the list <b>'%s'</b> in the Redis database."), LISTPREFIX_LOADING_ANNOUNCMENTS.c_str()));
	}
	else {
		for(auto it = l.begin(); it != l.end(); ++it) {
			s.push_back(ReplaceBrandingPatterns(*it));
		}
	}
	return s;

}
Пример #2
0
void IGFManager :: GetCategory(int id, MULTISTRING &output)
{
	IGFCategory *category = GetPagedCategoryPtr(id);
	if(category == NULL)
		return;

	STRINGLIST header;

	header.push_back(ConvertInteger(id));
	header.push_back(category->mTitle);
	output.push_back(header);

	EnumCategoryList(id, output);
	EnumThreadList(id, output);
}
Пример #3
0
void AINutPlayer::PlaySound(const char *name) {
	STRINGLIST sub;
	Util::Split(name, "|", sub);
	while (sub.size() < 2) {
		sub.push_back("");
	}
	attachedCreature->SendPlaySound(sub[0].c_str(), sub[1].c_str());
}
Пример #4
0
void IGFManager :: EnumCategoryList(int parentID, MULTISTRING &output)
{
	STRINGLIST entry;
	CATEGORYPAGE::iterator it;
	IGFCategoryPage::CATEGORYENTRY::iterator eit;
	for(it = mCategoryPages.begin(); it != mCategoryPages.end(); ++it)
	{
		for(eit = it->second.mEntries.begin(); eit != it->second.mEntries.end(); ++eit)
		{
			if(eit->second.mParentCategory == parentID)
			{
				entry.push_back(ConvertInteger(TYPE_CATEGORY));
				entry.push_back(ConvertInteger(eit->second.mID));
				entry.push_back(ConvertInteger(eit->second.mLocked));
				entry.push_back(ConvertInteger(0)); //Stickied.  Categories don't have this.
				entry.push_back(eit->second.mTitle);
				entry.push_back(ConvertInteger(eit->second.mThreadList.size()));
				entry.push_back(ConvertInteger(GetTimeOffset(eit->second.mLastUpdateTime)));

				output.push_back(entry);
				entry.clear();
			}
		}
	}
}
Пример #5
0
// Tokenize a string using whitespace as separators, but including string quotations.
void TokenizeByWhitespace(const std::string &input, STRINGLIST &output)
{
	std::string str = input;
	output.clear();
	size_t len = str.size();
	int first = -1;
	int last = -1;
	bool quote = false;
	bool terminate = false;
	for(size_t i = 0; i < len; i++)
	{
		switch(input[i])
		{
		case '"':
			terminate = true;  //Treat opening quote as a block start
			quote = !quote;
			break;

		case ' ':
		case '\t':
		case '\n':
		case '\r':
			if(quote == false)
				terminate = true;
			break;
		default:
			if(first == -1)
				first = i;
			last = i;
		}
		if(terminate == true)
		{
			if(first >= 0 && last >= 0)
			{
				std::string t = str.substr(first, last - first + 1);
				output.push_back(str.substr(first, last - first + 1));
				first = -1;
				last = -1;
			}
			terminate = false;
		}
	}
	if(first != -1 && first < (int)len)
		output.push_back(str.substr(first, len - first + 1));
}
Пример #6
0
void IGFManager :: OpenCategory(int type, int id, MULTISTRING &output)
{
	//Expand an object.  If it's a category, enumerate a list of subcategories.
	if(type == TYPE_CATEGORY)
	{
		IGFCategory *category = GetPagedCategoryPtr(id);
		if(category != NULL)
		{
			STRINGLIST header;
			header.push_back(ConvertInteger(id));
			header.push_back(category->mTitle);

			output.push_back(header);

			int searchID = category->mID;
			EnumCategoryList(searchID, output);
			EnumThreadList(searchID, output);
		}
	}
}
Пример #7
0
void IGFManager :: EnumThreadList(int parentID, MULTISTRING &output)
{
	IGFCategory* category = GetPagedCategoryPtr(parentID);
	if(category == NULL)
		return;

	//Pregenerate a list of threads
	std::vector<IGFThread*> results;
	for(size_t i = 0; i < category->mThreadList.size(); i++)
	{
		IGFThread* thread = GetPagedThreadPtr(category->mThreadList[i]);
		if(thread != NULL)
			results.push_back(thread);
	}

	if(category->mFlags.hasFlag(IGFFlags::FLAG_SORTALPHABETICAL))
		std::sort(results.begin(), results.end(), ThreadSortAlphabetical);

	STRINGLIST entry;
	for(size_t i = 0; i < results.size(); i++)
	{
		IGFThread* thread = results[i];
		entry.push_back(ConvertInteger(TYPE_THREAD));
		entry.push_back(ConvertInteger(thread->mID));
		entry.push_back(ConvertInteger(thread->mLocked));
		entry.push_back(ConvertInteger(thread->mStickied));
		entry.push_back(thread->mTitle);
		entry.push_back(ConvertInteger(thread->mPostList.size()));
		entry.push_back(ConvertInteger(GetTimeOffset(thread->mLastUpdateTime)));

		output.push_back(entry);
		entry.clear();
	}
}
Пример #8
0
int QuestActionContainer :: ExecuteSingleCommand(SimulatorThread *caller, ExtendedQuestAction &e)
{
	CreatureInstance *cInst = caller->creatureInst;
	switch(e.opCode)
	{
	case COMMAND_NONE: return 0;
	case CONDITION_HEROISM:
		{
			int value = cInst->css.heroism;
			if(Compare(value, e.param[0], e.param[1]) == true)
				return 0;
			caller->SendInfoMessage("You don't meet the heroism requirement.", INFOMSG_ERROR);
			return -1;
		}
		break;
	case CONDITION_HAS_ITEM:
		{
			int itemID = e.param[0];
			int itemCount = e.param[1];
			int count = caller->pld.charPtr->inventory.GetItemCount(INV_CONTAINER, itemID);
			if(count >= itemCount)
				return 0;
			caller->SendInfoMessage("You don't have the required items in your backpack inventory.", INFOMSG_ERROR);
			return -1;
		}
		break;
	case CONDITION_HAS_QUEST:
		{
			int questID = e.param[0];
			if(caller->pld.charPtr->questJournal.activeQuests.HasQuestID(questID) > -1)
				return 0;
			return -1;
		}
		break;
	case CONDITION_BELOW_LEVEL:
		{
			int maxLevel = e.param[0];
			if(caller->pld.charPtr->cdef.css.level < maxLevel)
				return 0;
			caller->SendInfoMessage("You are too high a level to accept this quest.", INFOMSG_ERROR);
			return -1;
		}
		break;
	case CONDITION_TRANSFORMED:
		{
			int creatureDefID = e.param[0];
			if(cInst->IsTransformed() && cInst->transformCreatureId == creatureDefID)
				return 0;
			CreatureDefinition *def = CreatureDef.GetPointerByCDef(creatureDefID);
			char buffer[128];
			Util::SafeFormat(buffer, sizeof(buffer), "You must be transformed into %s to continue with this quest.", def->css.display_name);
			caller->SendInfoMessage(buffer, INFOMSG_INFO);
			return -1;

		}
	case CONDITION_UNTRANSFORMED:
		{
			if(!cInst->IsTransformed())
				return 0;
			CreatureDefinition *def = CreatureDef.GetPointerByCDef(cInst->transformCreatureId);
			char buffer[128];
			Util::SafeFormat(buffer, sizeof(buffer), "You cannot be transformed into %s to continue with this quest.", def->css.display_name);
			caller->SendInfoMessage(buffer, INFOMSG_INFO);
			return -1;
		}
		break;
	case ACTION_CHANGE_HEROISM:
		cInst->css.heroism += e.param[0];
		cInst->OnHeroismChange();
		break;
	case ACTION_REMOVE_ITEM:
		{
			int itemID = e.param[0];
			int itemCount = e.param[1];
			char buffer[2048];
			int len = caller->pld.charPtr->inventory.RemoveItemsAndUpdate(INV_CONTAINER, itemID, itemCount, buffer);
			if(len > 0)
				caller->AttemptSend(buffer, len);
		}
		break;
	case ACTION_SEND_TEXT:
		caller->SendInfoMessage(e.paramStr.c_str(), INFOMSG_INFO);
		break;
	case ACTION_PLAY_SOUND:
		{
			STRINGLIST sub;
			Util::Split(e.paramStr, "|", sub);
			while(sub.size() < 2)
			{
				sub.push_back("");
			}
			caller->SendPlaySound(sub[0].c_str(), sub[1].c_str());
		}
		break;
	case ACTION_BROADCAST:
		{
			char buffer[128];
			Util::SafeFormat(buffer, sizeof(buffer), e.paramStr.c_str(), cInst->css.display_name);
			g_SimulatorManager.BroadcastMessage(buffer);
		}
		break;
	case ACTION_JOIN_GUILD:
		{
			int guildDefID = e.param[0];
			GuildDefinition *gDef = g_GuildManager.GetGuildDefinition(guildDefID);
			if(gDef == NULL)
				caller->SendInfoMessage("Hrmph. This guild does not exist, please report a bug!", INFOMSG_INFO);
			else {
				caller->SendInfoMessage("Joining guild ..", INFOMSG_INFO);
				caller->JoinGuild(gDef, 0);
				char buffer[64];
				Util::SafeFormat(buffer, sizeof(buffer), "You have joined %s", gDef->defName.c_str());
				caller->SendInfoMessage(buffer, INFOMSG_INFO);
			}
		}
		break;
	case ACTION_TRANSFORM:
		{
			int creatureDefID = e.param[0];
			g_Logs.data->debug("Transform: %v", creatureDefID);
			cInst->CAF_Transform(creatureDefID, 0, -1);
		}
		break;
	case ACTION_UNTRANSFORM:
		{
			g_Logs.data->debug("Untransform");
			cInst->CAF_Untransform();
		}
		break;
	default:
		return -1;
	}
	return 0;
}
Пример #9
0
void IGFManager :: OpenThread(int threadID, int startPost, int requestedCount, MULTISTRING &output)
{
	IGFThread *thread = GetPagedThreadPtr(threadID);
	if(thread == NULL)
		return;

	startPost = Util::ClipInt(startPost, 0, thread->mPostList.size() - 1);

	STRINGLIST row;

	//We retrieve the time offset since the first session since the client uses
	//4 byte integers which theoretically may not be large enough to hold the time data.
	unsigned long timeOffset = g_PlatformTime.getAbsoluteMinutes();

	//Prepare the header
	row.push_back(ConvertInteger(threadID));  //[0]
	row.push_back(thread->mTitle);   //[1]
	row.push_back(ConvertInteger(startPost));  //[2]
	row.push_back(ConvertInteger(thread->mPostList.size()));  //[3]
	row.push_back(ConvertInteger(timeOffset - thread->mLastUpdateTime));  //[4]
	output.push_back(row);
	row.clear();

	//Append the post data.
	int count = 0;
	for(size_t i = startPost; i < thread->mPostList.size(); i++)
	{
		IGFPost *post = GetPagedPostPtr(thread->mPostList[i]);
		if(post == NULL)
		{
			g_Logs.data->error("OpenThread: unable to find post: %v", thread->mPostList[i]);
			continue;
		}

		row.push_back(ConvertInteger(post->mID));  //[0]
		row.push_back(post->mCreatorName.c_str());  //[1]
		row.push_back(post->mCreationTime.c_str());  //[2]
		row.push_back(ConvertInteger(timeOffset - post->mPostedTime)); //[3]
		row.push_back(post->mBodyText.c_str());  //[4]
		row.push_back(ConvertInteger(post->mEditCount)); //[5]
		row.push_back(ConvertInteger(timeOffset - post->mLastUpdateTime)); //[6]

		output.push_back(row);
		row.clear();

		if(++count >= requestedCount)
			break;
	}
}
Пример #10
0
void AIScriptPlayer :: RunImplementationCommands(int opcode)
{
	ScriptCore::OpData *in = &def->instr[curInst];
	switch(opcode)
	{
	case OP_USE:
		if(attachedCreature->ab[0].bPending == false)
		{
			//DEBUG OUTPUT
			if(g_Config.DebugLogAIScriptUse == true)
			{
				const Ability2::AbilityEntry2* abptr = g_AbilityManager.GetAbilityPtrByID(in->param1);
				g_Logs.script->debug("Using: %v", abptr->GetRowAsCString(Ability2::ABROW::NAME));
			}
			//END DEBUG OUTPUT

			int r = attachedCreature->CallAbilityEvent(in->param1, EventType::onRequest);
			if(r != 0)
			{
				//Notify the creature we failed, may need a distance check.
				//The script should wait and retry soon.
				attachedCreature->AICheckAbilityFailure(r);
				nextFire = g_ServerTime + USE_FAIL_DELAY;


				if(g_Config.DebugLogAIScriptUse == true)
				{
					const Ability2::AbilityEntry2* abptr = g_AbilityManager.GetAbilityPtrByID(in->param1);
					g_Logs.script->debug("Using: %v   Failed: %v", abptr->GetRowAsCString(Ability2::ABROW::NAME), g_AbilityManager.GetAbilityErrorCode(r));
				}

				if(attachedCreature->AIAbilityFailureAllowRetry(r) == true)
				{
					advance = 0;  //Don't advance the instruction so that we can retry this command.
				}
			}
		}
		else
		{
			advance = 0;
			nextFire = g_ServerTime + USE_FAIL_DELAY;
		}
		break;
	case OP_GETWILL:
		SetVar(def->instr[curInst].param1, attachedCreature->css.will);
		break;
	case OP_GETWILLCHARGE:
		SetVar(def->instr[curInst].param1, attachedCreature->css.will_charges);
		break;
	case OP_GETMIGHT:
		SetVar(def->instr[curInst].param1, attachedCreature->css.might);
		break;
	case OP_GETMIGHTCHARGE:
		SetVar(def->instr[curInst].param1, attachedCreature->css.might_charges);
		break;
	case OP_HASTARGET:
		SetVar(def->instr[curInst].param1, (attachedCreature->CurrentTarget.targ != NULL) ? 1 : 0);
		break;
	case OP_GETLEVEL:
		SetVar(def->instr[curInst].param1, attachedCreature->css.level);
		break;
	case OP_DEBUGPRINT:
		g_Logs.script->debug("[DEBUGPRINT] (%v) %v", def->scriptName, def->stringList[def->instr[curInst].param1].c_str());
		break;
	case OP_GETCOOLDOWN:
		{
			const char *cooldownName = GetStringTableEntry(def->instr[curInst].param1);
			int cooldownID = g_AbilityManager.ResolveCooldownCategoryID(cooldownName);
			int result = (attachedCreature->HasCooldown(cooldownID) == true) ? 1 : 0;
			SetVar(in->param2, result);
		}
		break;
	case OP_ISBUSY:
		{
			int result = (attachedCreature->AICheckIfAbilityBusy() == true) ? 1 : 0;
			SetVar(in->param1, result);
		}
		break;
	case OP_COUNTENEMYNEAR:
		{
			float x = (float)attachedCreature->CurrentX;
			float z = (float)attachedCreature->CurrentZ;
			SetVar(in->param2, attachedCreature->AICountEnemyNear(in->param1, x, z));
		}
		break;
	case OP_COUNTENEMYAT:
		{
			float x = (float)attachedCreature->CurrentX;
			float z = (float)attachedCreature->CurrentZ;
			if(attachedCreature->CurrentTarget.targ != NULL)
			{
				x = (float)attachedCreature->CurrentTarget.targ->CurrentX;
				z = (float)attachedCreature->CurrentTarget.targ->CurrentZ;
			}
			SetVar(in->param2, attachedCreature->AICountEnemyNear(in->param1, x, z));
		}
		break;
	case OP_HEALTHPERCENT:
		SetVar(in->param1, static_cast<int>(attachedCreature->GetHealthRatio() * 100.0F));
		break;
	case OP_TARGETHEALTHPERCENT:
		{
			int health = 0;
			if(attachedCreature->CurrentTarget.targ != NULL)
				health = static_cast<int>(attachedCreature->CurrentTarget.targ->GetHealthRatio() * 100.0F);
			SetVar(in->param1, health);
		}
		break;
	case OP_SETELAPSEDTIME:
		SetVar(in->param1, static_cast<int>(g_PlatformTime.getElapsedMilliseconds()));
		break;
	case OP_TIMEOFFSET:
		{
			unsigned long offset = g_PlatformTime.getElapsedMilliseconds() - static_cast<unsigned long>(GetVarValue(in->param1));
			SetVar(in->param2, static_cast<int>(offset));
		}
		break;
	case OP_VISUALEFFECT:
		attachedCreature->SendEffect(GetStringTableEntry(in->param1), 0);
		break;
	case OP_VISUALEFFECTT:
		{
		int targID = 0;
		if(attachedCreature->CurrentTarget.targ != NULL)
			targID = attachedCreature->CurrentTarget.targ->CreatureID;
		attachedCreature->SendEffect(GetStringTableEntry(in->param1), targID);
		}
		break;
	case OP_SAY:
		attachedCreature->SendSay(GetStringTableEntry(in->param1));
		break;
	case OP_INSTANCECALL:
		attachedCreature->actInst->ScriptCall(GetStringTableEntry(in->param1));
		break;
	case OP_GETIDLEMOB:
		{
			int creatureDefID = in->param1;
			int creatureID = attachedCreature->AIGetIdleMob(creatureDefID);
			SetVar(in->param2, creatureID);
		}
		break;
	case OP_GETTARGET:
		{
			int creatureID = 0;
			if(attachedCreature->CurrentTarget.targ != NULL)
				creatureID = attachedCreature->CurrentTarget.targ->CreatureID;
			SetVar(in->param1, creatureID);
		}
		break;
	case OP_GETSELF:
		SetVar(in->param1, attachedCreature->CreatureID);
		break;
	case OP_SETOTHERTARGET:
		{
			int creatureID = GetVarValue(in->param1);
			int creatureIDTarg = GetVarValue(in->param2);
			attachedCreature->AIOtherSetTarget(creatureID, creatureIDTarg);
		}
		break;
	case OP_AISCRIPTCALL:
		{
			int creatureID = GetVarValue(in->param1);
			attachedCreature->AIOtherCallLabel(creatureID, GetStringTableEntry(in->param2));
		}
		break;
	case OP_ISTARGETENEMY:
		{
			int result = (attachedCreature->AIIsTargetEnemy() == true) ? 1 : 0;
			SetVar(in->param1, result);
		}
		break;
	case OP_ISTARGETFRIENDLY:
		{
			int result = (attachedCreature->AIIsTargetFriend() == true) ? 1 : 0;
			SetVar(in->param1, result);
		}
		break;
	case OP_SETSPEED:
		attachedCreature->Speed = in->param1;
		break;
	case OP_GETTARGETCDEF:
		{
			int targCDef = 0;
			if(attachedCreature->CurrentTarget.targ != NULL)
				targCDef = attachedCreature->CurrentTarget.targ->CreatureDefID;
			SetVar(in->param1, targCDef);
		}
		break;
	case OP_GETPROPERTY:
		{
			const char *propName = GetStringTableEntry(in->param1);
			SetVar(in->param2, static_cast<int>(attachedCreature->AIGetProperty(propName, false)));
		}
		break;
	case OP_GETTARGETPROPERTY:
		{
			const char *propName = GetStringTableEntry(in->param1);
			SetVar(in->param2, static_cast<int>(attachedCreature->AIGetProperty(propName, true)));
		}
		break;
	case OP_DISPELTARGETPROPERTY:
		{
			const char *propName = GetStringTableEntry(in->param1);
			int sign = in->param2;
			attachedCreature->AIDispelTargetProperty(propName, sign);
		}
		break;
	case OP_RANDOMIZE:
		SetVar(in->param2, randint(1, in->param1));
		break;
	case OP_FINDCDEF:
		{
			int creatureID = 0;
			CreatureInstance *targ = attachedCreature->actInst->GetNPCInstanceByCDefID(in->param1);
			if(targ != NULL)
				creatureID = targ->CreatureID;
			SetVar(in->param2, creatureID);
		}
		break;
	case OP_PLAYSOUND:
		{
			STRINGLIST sub;
			Util::Split(GetStringTableEntry(in->param1), "|", sub);
			while(sub.size() < 2)
			{
				sub.push_back("");
			}
			attachedCreature->SendPlaySound(sub[0].c_str(), sub[1].c_str());
		}
		break;
	case OP_GETBUFFTIER:
		SetVar(in->param2, attachedCreature->AIGetBuffTier(in->param1, false));
		break;
	case OP_GETTARGETBUFFTIER:
		SetVar(in->param2, attachedCreature->AIGetBuffTier(in->param1, true));
		break;
	case OP_TARGETINRANGE:
		SetVar(in->param2, (attachedCreature->InRange_Target((float)in->param1) == true) ? 1 : 0);
		break;
	case OP_GETTARGETRANGE:
		SetVar(in->param1, attachedCreature->AIGetTargetRange());
		break;
	case OP_SETGTAE:
		attachedCreature->AISetGTAE();
		break;
	case OP_GETSPEED:
		{
			int result = 0;
			int creatureID = GetVarValue(in->param1);
			CreatureInstance *targ = ResolveCreatureInstance(creatureID);
			if(targ != NULL)
			{
				result = targ->Speed;
			}
			SetVar(in->param2, result);
		}
		break;
	case OP_CIDISBUSY:
		{
			int result = 0;
			CreatureInstance *targ = ResolveCreatureInstance(GetVarValue(in->param1));
			if(targ != NULL)
			{
				result = (targ->AICheckIfAbilityBusy() == true) ? 1 : 0;
			}
			SetVar(in->param2, result);
		}
		break;
	default:
		g_Logs.script->error("Unidentified op type: %v", in->opCode);
		break;
	}
}
Пример #11
0
int TradeEssenceHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {

	/*  Query: trade.essence
	 Sent when an item is purchased from a chest using tokens or
	 essences, instead of gold.
	 Args : [0] = Creature Instance ID
	 [1] = Item proto of the player's selection.
	 */

	// [0] = Creature Instance ID
	// [1] = Item Proto that was selected ex: "item143548:0:0:0"
	if (query->argCount < 2)
		return 0;

	int CID = atoi(query->args[0].c_str());
	int CDef = sim->ResolveCreatureDef(CID);

	//Since the Essence Shop scanning functions modify the string while searching
	//for tokens, copy it to a buffer here.
	Util::SafeCopy(sim->Aux1, query->args[1].c_str(), sizeof(sim->Aux1));

	EssenceShopItem *iptr = NULL;
	EssenceShop *esptr =
			creatureInstance->actInst->essenceShopList.GetEssenceShopPtr(CDef, sim->Aux1,
					&iptr);
	if (esptr == NULL || iptr == NULL) {
		g_Logs.simulator->error(
				"[%d] Failed to process EssenceShop item [%s] for CreatureDef [%d]",
				sim->InternalID, sim->Aux1, CDef);
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Failed to determine item selection.");
	}

	InventoryManager &inv = pld->charPtr->inventory;
	int currentItemCount = inv.GetItemCount(INV_CONTAINER, esptr->EssenceID);
	if (currentItemCount < iptr->EssenceCost) {
		g_Logs.simulator->warn("[%v] Essence requirement for item %v: %v / %v",
				sim->InternalID, esptr->EssenceID, currentItemCount,
				iptr->EssenceCost);
		return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
				"You do not have enough essences.");
	}

	InventorySlot *newItem = pld->charPtr->inventory.AddItem_Ex(INV_CONTAINER,
			iptr->ItemID, 1);
	if (newItem == NULL) {
		pld->charPtr->pendingChanges++;
		int err = pld->charPtr->inventory.LastError;
		if (err == InventoryManager::ERROR_ITEM)
			return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
					"Server error: item does not exist.");
		else if (err == InventoryManager::ERROR_SPACE)
			return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
					"You do not have any free inventory space.");
		else if (err == InventoryManager::ERROR_LIMIT)
			return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
					"You already the maximum amount of these items.");
		else
			return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
					"Server error: undefined error.");
	}

	sim->ActivateActionAbilities(newItem);

	STRINGLIST result;
	result.push_back("OK");
	sprintf(sim->Aux3, "%d", iptr->EssenceCost);
	result.push_back(sim->Aux3);
	int wpos = PrepExt_QueryResponseStringList(sim->SendBuf, query->ID, result);
	wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, newItem);

	wpos += inv.RemoveItemsAndUpdate(INV_CONTAINER, esptr->EssenceID,
			iptr->EssenceCost, &sim->SendBuf[wpos]);
	pld->charPtr->pendingChanges++;
	return wpos;
}
Пример #12
0
void SceneryManager::SendPageRequest(const SceneryPageRequest& request, std::list<PacketManager::PACKET_PAIR>& outgoingPackets)
{
	TimeObject to("SceneryManager::SendPageRequest");

	STRINGLIST queryRows;
	Packet data;
	int wpos = 0;
	char idBuf[32];

	GetThread("SceneryManager::HandlePageRequests[page]");

	SceneryPage *page = GetOrCreatePage(request.zone, request.x, request.y);

	if(page == NULL)
	{
		g_Log.AddMessageFormat("[ERROR] SendPageRequest retrieved NULL page");
		
		wpos = PrepExt_QueryResponseNull(prepBuf, request.queryID);
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));

		ReleaseThread();
		return;
	}

	SceneryPage::SCENERY_IT it;
	for(it = page->mSceneryList.begin(); it != page->mSceneryList.end(); ++it)
	{
		//Build the list of scenery ID strings to form the response to the scenery.list query.
		//No need to save row data unless the query is required.
		if(request.skipQuery == false)
		{
			sprintf(idBuf, "%d", it->second.ID);
			queryRows.push_back(idBuf);
		}
		
		wpos += PrepExt_UpdateScenery(&prepBuf[wpos], &it->second);
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Assign(prepBuf, wpos);
			outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
			wpos = 0;
		}
	}
	if(wpos > 0)
	{
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
	}

	//Done accessing the scenery data itself, no need to hold the thread any longer.
	//All the remaining stuff is using a resident list of query IDs to form into a response
	//packet.
	ReleaseThread();

	//Now build the query response if the client has requested it.
	if(request.skipQuery == true)
		return;

	//Reset the packet buffer and data.
	wpos = 0;
	data.Clear();

	//Get the size of the response
	int sizeReq = 6;  //Query ID (4 bytes) + row count (2 bytes)
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		sizeReq++;  //1 string per row
		sizeReq += PutStringReq(queryRows[s].c_str());
	}

	wpos += PutByte(&prepBuf[wpos], 1);         //_handleQueryResultMsg
	wpos += PutShort(&prepBuf[wpos], sizeReq);  //Message size

	wpos += PutInteger(&prepBuf[wpos], request.queryID);
	wpos += PutShort(&prepBuf[wpos], queryRows.size());
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		wpos += PutByte(&prepBuf[wpos], 1);
		wpos += PutStringUTF(&prepBuf[wpos], queryRows[s].c_str());
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Append(prepBuf, wpos);
			wpos = 0;
		}
	}
	if(wpos > 0)
		data.Append(prepBuf, wpos);

	outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
}