int TradeShopHandler::helper_trade_shop_sell(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance,
		const char *itemHex) {
	//Return the query response when selling stuff to an NPC shop.
	unsigned int CCSID = strtol(itemHex, NULL, 16);
	InventorySlot *item = pld->charPtr->inventory.GetItemPtrByCCSID(CCSID);
	if (item == NULL)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Item not found in inventory.");

	ItemDef *itemPtr = item->ResolveItemPtr();
	if (itemPtr == NULL)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Item does not exist in server database.");

	int wpos = 0;
	wpos += PrepExt_QueryResponseString(&sim->SendBuf[wpos], query->ID, "OK");

	int cost = itemPtr->mValue;
	cost *= item->GetStackCount();
	wpos += pld->charPtr->inventory.AddBuyBack(item, &sim->SendBuf[wpos]);
	wpos += RemoveItemUpdate(&sim->SendBuf[wpos], sim->Aux3, item);
	pld->charPtr->inventory.RemItem(CCSID);
	pld->charPtr->pendingChanges++;
	creatureInstance->AdjustCopper(cost);

	return wpos;
}
int TradeShopHandler::helper_trade_shop_buyback(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance,unsigned int CCSID) {
	InventorySlot *buybackItem = pld->charPtr->inventory.GetItemPtrByCCSID(
			CCSID);
	if (buybackItem == NULL)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Item not found in buyback list.");

	int freeslot = pld->charPtr->inventory.GetFreeSlot(INV_CONTAINER);
	if (freeslot == -1)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"No free inventory space.");

	ItemDef *itemPtr = buybackItem->ResolveItemPtr();
	if (itemPtr == NULL)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Item does not exist in database.");

	int cost = itemPtr->mValue * buybackItem->GetStackCount();
	if (creatureInstance->css.copper < cost)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID, "Not enough coin.");

	InventorySlot newItem;
	newItem.CopyFrom(*buybackItem, false);
	newItem.CCSID = pld->charPtr->inventory.GetCCSID(INV_CONTAINER, freeslot);

	int r = pld->charPtr->inventory.AddItem(INV_CONTAINER, newItem);
	if (r == -1)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Failed to create item.");
	pld->charPtr->pendingChanges++;

	int wpos = 0;
	wpos = RemoveItemUpdate(sim->SendBuf, sim->Aux3, buybackItem);
	wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, &newItem);
	wpos += PrepExt_QueryResponseString(&sim->SendBuf[wpos], query->ID, "OK");
	pld->charPtr->inventory.RemItem(buybackItem->CCSID);
	pld->charPtr->pendingChanges++;
	creatureInstance->AdjustCopper(-cost);
	return wpos;
}
int TradeAcceptHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	/*  Query: trade.accept
	 A player has accepted the trade offer.
	 Args : [none]
	 */
	int rval = protected_helper_query_trade_accept(sim, pld, query, creatureInstance);
	if (rval <= 0)
		rval = PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				sim->GetErrorString(rval));

	return rval;
}
int TradeCurrencyHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	/*  Query: trade.currency
	 Sent when the player offers a coin amount.
	 Args : [0] currency name, ex: "COPPER"
	 [1] amount offered
	 */
	int rval = protected_helper_query_trade_currency(sim, pld, query, creatureInstance);
	if (rval <= 0)
		rval = PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				sim->GetErrorString(rval));

	return rval;
}
int TradeStartHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {

	/*  Query: trade.start
	 Attempt to open a trade with another player.
	 Args : [0] = Creature ID of the player to trade with.
	 */
	int rval = protected_helper_query_trade_start(sim, pld, query,
			creatureInstance);
	if (rval <= 0) {
		rval = PrepExt_SendInfoMessage(sim->SendBuf,
				sim->GetErrorString(rval), INFOMSG_ERROR);
		rval += PrepExt_QueryResponseError(&sim->SendBuf[rval], query->ID,
				"");
	}

	return rval;
}
Beispiel #6
0
int PersonaCreateHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	/* Query: persona.create
	 Args : [variable] list of attributes
	 Notes: Attributes are customized by the player in the Character Creation
	 steps.
	 Return: Unknown.  Possibly an index for use in the client?
	 */
	g_AccountManager.cs.Enter("SimulatorThread::handle_query_persona_create");
	CharacterData newChar;
	int r = g_AccountManager.CreateCharacter(query->args, pld->accPtr, newChar);
	g_AccountManager.cs.Leave();
	if (r < AccountManager::CHARACTER_SUCCESS)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				g_AccountManager.GetCharacterErrorMessage(r));
	g_CharacterManager.SaveCharacter(newChar.cdef.CreatureDefID);

	sprintf(sim->Aux1, "%d", r + 1);
	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, sim->Aux1);
}
Beispiel #7
0
int PersonaDeleteHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	/* Query: persona.delete
	 Args : [0] index to remove
	 */
	if (query->argCount < 1)
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Invalid query");

	int index = query->GetInteger(0);
	if (index >= 0 && index <= pld->accPtr->MAX_CHARACTER_SLOTS) {
		int CDefID = pld->accPtr->CharacterSet[index];
		CharacterData *cd = g_CharacterManager.RequestCharacter(CDefID, true);
		if (cd->clan > 0) {
			Clans::Clan c = g_ClanManager.mClans[cd->clan];
			if (c.mId > 0) {
				Clans::ClanMember me = c.GetMember(CDefID);
				c.RemoveMember(me);
				if (c.mMembers.size() < 1) {
					g_Logs.event->info(
							"[CLAN] Disbanding clan %v because the last member left.",
							c.mName.c_str());
					g_ClanManager.RemoveClan(c);
				} else {
					if (me.mRank == Clans::Rank::LEADER) {
						Clans::ClanMember nextLeader = c.GetFirstMemberOfRank(
								Clans::Rank::OFFICER);
						if (nextLeader.mID == 0) {
							nextLeader = c.GetFirstMemberOfRank(
									Clans::Rank::MEMBER);
							if (nextLeader.mID == 0) {
								nextLeader = c.GetFirstMemberOfRank(
										Clans::Rank::INITIATE);
								if (nextLeader.mID == 0) {
									g_Logs.event->warn(
											"[CLAN] There is nobody to pass leadership of clan of %v to! Removing the clan",
											c.mName.c_str());
									g_ClanManager.RemoveClan(c);
									BroadcastClanDisbandment(c);
								}

							}
						}
						if (nextLeader.mID != 0) {
							nextLeader.mRank = Clans::Rank::LEADER;
							c.UpdateMember(nextLeader);
							BroadcastClanRankChange(cd->cdef.css.display_name,
									c, nextLeader);
							g_ClanManager.SaveClan(c);
						}
					} else {
						g_ClanManager.SaveClan(c);
					}
				}
			}
		}
	}

	g_AccountManager.DeleteCharacter(index, pld->accPtr);
	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
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;
}
int TradeShopHandler::handleQuery(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {

	/*  Query: trade.shop
	 Sent when an item is purchased from a shop.
	 Args : [0] = Creature ID of the NPC

	 If buying from shop:
	 [1] = Item proto of selection (ex: item143548:0:0:0);

	 If buying from buyback:
	 [1] = Hex string of item container/slot ID

	 If selling
	 [1] = String constant: "sell"
	 [2] = Hex string of item container/slot ID
	 */

	if (query->argCount < 2)
		return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");

	if (pld->zoneDef->mGrove == true)
		if (sim->CheckPermissionSimple(Perm_Account, Permission_Admin) == false)
			return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
					"You cannot use shops in a grove.");

	//if(HasQueryArgs(2) == false)
	//	return 0;

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

	if (query->args[1].compare("sell") == 0) {
		//if(HasQueryArgs(3) == false)
		//	return 0;
		if (query->argCount < 3)
			return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");

		//[2] = Hex String, pass it to the helper function
		return helper_trade_shop_sell(sim, pld, query, creatureInstance, query->args[2].c_str());
	}

	//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->itemShopList.GetEssenceShopPtr(
			CDef, sim->Aux1, &iptr);
	if (esptr == NULL || iptr == NULL) {
		//This might be a buyback item.
		unsigned int CCSID = strtol(sim->Aux1, NULL, 16);
		int r = helper_trade_shop_buyback(sim, pld, query, creatureInstance,CCSID);
		if (r > 0)
			return r;

		g_Logs.simulator->error(
				"[%d] Failed to process Shop item [%s] for CreatureDef [%d]",
				sim->InternalID, sim->Aux1, CDef);
		return PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Failed to determine item selection.");
	}

	ItemDef *itemPtr = g_ItemManager.GetPointerByID(iptr->ItemID);
	if (itemPtr == NULL)
		return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
				"Server error: item does not exist.");

	int cost = (int) (itemPtr->mValue * g_VendorMarkup);
	if (creatureInstance->css.copper < cost)
		return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
				"Not enough coin.");

	//Check to see if this was a gambled item, and modify its ID accordingly.
	int newItemID = 0;
	newItemID = g_ItemManager.RunPurchaseModifier(itemPtr->mID);

	//If the normal gamble options failed, it will return the same ID.  Check for new randomized gamble options instead.
	if (newItemID == itemPtr->mID) {
		VirtualItemSpawnParams viParam;
		if (g_ItemManager.CheckVirtualItemGamble(itemPtr,
				creatureInstance->css.level, &viParam, cost) == true) {
			//Coin amount may be modified.
			if (creatureInstance->css.copper < cost)
				return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
						"Not enough coin.");

			newItemID = g_ItemManager.RollVirtualItem(viParam);
		}
	}
	if (newItemID == 0)
		return PrepExt_QueryResponseString(sim->SendBuf, query->ID,
				"A purchase modifier has failed.");

	InventorySlot *newItem = pld->charPtr->inventory.AddItem_Ex(INV_CONTAINER,
			newItemID, 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.");
	} else {
		sim->ActivateActionAbilities(newItem);
	}

	int wpos = PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
	wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, newItem);
	creatureInstance->AdjustCopper(-cost);
	return wpos;
}
Beispiel #10
0
//
//GameQueryMessage
//
int GameQueryMessage::handleMessage(SimulatorThread *sim, CharacterServerData *pld,
		SimulatorQuery *query, CreatureInstance *creatureInstance) {

#ifdef DEBUG_TIME
	unsigned long startTime = g_PlatformTime.getMilliseconds();
#endif

	int PendingData = 0;
	query->Clear(); //Clear it here so that debug polls can fetch the most recent query.
	sim->ReadQueryFromMessage();

	//LogMessageL(MSG_SHOW, "[DEBUG] handle_game_query:%s (ID:%d)", query.name.c_str(), query.ID);

	// Debug
	/*
	 LogMessageL(MSG_SHOW, "Query: %d=%s", query.ID, query.name.c_str());
	 for(int i = 0; i < query.argCount; i++)
	 LogMessageL(MSG_SHOW, "  %d=%s", i, query.args[i].c_str());
	 */

	QueryHandler *qh = g_QueryManager.getQueryHandler(query->name);
	if (qh == NULL) {
		// See if the instance script will handle the command
		if (creatureInstance != NULL && creatureInstance->actInst != NULL
				&& creatureInstance->actInst->nutScriptPlayer != NULL) {
			std::vector<ScriptCore::ScriptParam> p;
			p.push_back(creatureInstance->CreatureID);
			p.insert(p.end(), query->args.begin(), query->args.end());
			Util::SafeFormat(sim->Aux1, sizeof(sim->Aux1), "on_command_%s",
					query->name.c_str());
			if (creatureInstance->actInst->nutScriptPlayer->RunFunction(
					sim->Aux1, p, true)) {
				return PrepExt_QueryResponseString(sim->SendBuf,
						query->ID, "OK.");
			}
		}

		g_Logs.simulator->warn("[%v] Unhandled query in game: %v",
				sim->InternalID, query->name.c_str());
		for (unsigned int i = 0; i < query->argCount; i++)
			g_Logs.simulator->warn("[%v]   [%v]=[%v]", sim->InternalID, i,
					query->args[i].c_str());

		PendingData = PrepExt_QueryResponseError(sim->SendBuf, query->ID,
				"Unknown query.");
	} else {
		PendingData = qh->handleQuery(sim, pld, query, creatureInstance);
	}


#ifdef DEBUG_TIME
	unsigned long passTime = g_PlatformTime.getMilliseconds() - startTime;
	if (passTime > 50) {
		g_Logs.simulator->debug(
				"[%v] TIME PASS handle_game_query() %v ms for query:%v (ID:%v)",
				sim->InternalID, passTime, query->name.c_str(), query->ID);
		for (unsigned int i = 0; i < query->argCount; i++)
			g_Logs.simulator->debug("[%v]   [%v]=%v", sim->InternalID, i,
					query->args[i].c_str());
	}

#ifdef DEBUG_PROFILER
	_DebugProfiler.AddQuery(query->name, passTime);
#endif

#endif
	return PendingData;
}