Example #1
0
int TradeCurrencyHandler::protected_helper_query_trade_currency(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	if (query->argCount < 2)
		return QueryErrorMsg::GENERIC;

	//Ignore currency type for now, assume always copper.  Just get the amount.
	// Note: I found no evidence that the credit currency could actually be used
	// in trades.
	//args[0] is usually COPPER
	int amount = strtol(query->args[1].c_str(), NULL, 10);

	int selfID = creatureInstance->CreatureID;
	int tradeID = creatureInstance->activeLootID;
	ActiveInstance *actInst = creatureInstance->actInst;
	TradeTransaction *tradeData = actInst->tradesys.GetExistingTransaction(
			tradeID);
	if (tradeData == NULL)
		return QueryErrorMsg::TRADENOTFOUND;

	TradePlayerData *pData = tradeData->GetPlayerData(selfID);
	if (pData == NULL)
		return actInst->tradesys.CancelTransaction(selfID, tradeID, sim->SendBuf);

	CreatureInstance *cInst = pData->otherPlayerData->cInst;

	pData->SetCoin(amount);

	if (tradeData->player->otherPlayerData->tradeWindowOpen == true) {
		int wpos = PrepExt_TradeCurrencyOffer(sim->SendBuf, selfID, amount);
		SendToOneSimulator(sim->SendBuf, wpos, cInst->simulatorPtr);
	}
	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Example #2
0
int TradeOfferHandler::protected_helper_query_trade_offer(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	int selfID = creatureInstance->CreatureID;
	int tradeID = creatureInstance->activeLootID;
	ActiveInstance *actInst = creatureInstance->actInst;
	TradeTransaction *tradeData = actInst->tradesys.GetExistingTransaction(
			tradeID);
	if (tradeData == NULL)
		return QueryErrorMsg::TRADENOTFOUND;

	TradePlayerData *pData = tradeData->GetPlayerData(selfID);
	if (pData == NULL)
		return actInst->tradesys.CancelTransaction(selfID, tradeID, sim->SendBuf);

	CreatureInstance *cInst = pData->otherPlayerData->cInst;

	int wpos = 0;
	wpos += PutByte(&sim->SendBuf[wpos], 51);     //_handleTradeMsg
	wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
	wpos += PutInteger(&sim->SendBuf[wpos], creatureInstance->CreatureID);   //traderID
	wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::OFFER_MADE);    //eventType
	PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size

	SendToOneSimulator(sim->SendBuf, wpos, cInst->simulatorPtr);
	//actInst->LSendToOneSimulator(SendBuf, wpos, cInst->SimulatorIndex);

	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Example #3
0
int TradeManager :: CancelTransaction(int playerID, int tradeID, char *buffer)
{
	//Removes a transaction from the list.  Prepares and sends a close message
	//to the players involved.

	//The return value needs to be a generic error, so the calling function can
	//easily exit by do something like "return CancelTransaction()";

	TradeTransaction *tradeData = GetExistingTransaction(tradeID);
	if(tradeData == NULL)
		return -1;

	if(playerID == tradeData->player[1].selfPlayerID)
		playerID = tradeData->player[0].selfPlayerID;

	int wpos = 0;
	wpos += PutByte(&buffer[wpos], 51);     //_handleTradeMsg
	wpos += PutShort(&buffer[wpos], 0);    //Placeholder for size
	wpos += PutInteger(&buffer[wpos], playerID);   //traderID
	wpos += PutByte(&buffer[wpos], TradeEventTypes::REQUEST_CLOSED);     //eventType
	wpos += PutByte(&buffer[wpos], CloseReasons::CANCELED);     //eventType
	PutShort(&buffer[1], wpos - 3);       //Set message size

	//Send to both players.
	SendToOneSimulator(buffer, wpos, tradeData->player[0].cInst->simulatorPtr);
	SendToOneSimulator(buffer, wpos, tradeData->player[1].cInst->simulatorPtr);

	//tradeData->player[0].cInst->actInst->LSendToOneSimulator(buffer, wpos, tradeData->player[0].cInst->SimulatorIndex);
	//tradeData->player[1].cInst->actInst->LSendToOneSimulator(buffer, wpos, tradeData->player[1].cInst->SimulatorIndex);

	//Remove trade data
	tradeData->player[0].cInst->activeLootID = 0;
	tradeData->player[1].cInst->activeLootID = 0;

	//Remove this trade object entirely.
	RemoveTransaction(tradeID);
	return -1;
}
Example #4
0
int TradeItemsHandler::protected_helper_query_trade_items(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	int selfID = creatureInstance->CreatureID;
	int tradeID = creatureInstance->activeLootID;

	ActiveInstance *actInst = creatureInstance->actInst;
	TradeTransaction *tradeData = actInst->tradesys.GetExistingTransaction(
			tradeID);
	if (tradeData == NULL)
		return QueryErrorMsg::TRADENOTFOUND;

	TradePlayerData *pData = tradeData->GetPlayerData(selfID);
	if (pData == NULL)
		return actInst->tradesys.CancelTransaction(selfID, tradeID, sim->SendBuf);

	if (pData->otherPlayerData->tradeWindowOpen == false)
		return QueryErrorMsg::TRADENOTOPENED;

	InventorySlot item;
	pData->itemList.clear();
	for (unsigned int a = 0; a < query->argCount; a++) {
		unsigned long CCSID = strtol(query->args[a].c_str(), NULL, 16);
		InventorySlot *itemPtr = pld->charPtr->inventory.GetItemPtrByCCSID(
				CCSID);
		if (itemPtr == NULL)
			return QueryErrorMsg::INVALIDITEM;

		item.CopyFrom(*itemPtr, false);
		item.CCSID = CCSID;
		pData->itemList.push_back(item);
	}

	CreatureInstance *cInst = pData->otherPlayerData->cInst;
	int wpos = PrepExt_TradeItemOffer(sim->SendBuf, sim->Aux3, selfID, pData->itemList);

	SendToOneSimulator(sim->SendBuf, wpos, cInst->simulatorPtr);
	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Example #5
0
int TradeAcceptHandler::protected_helper_query_trade_accept(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	int selfID = creatureInstance->CreatureID;
	int tradeID = creatureInstance->activeLootID;
	ActiveInstance *actInst = creatureInstance->actInst;
	TradeTransaction *tradeData = actInst->tradesys.GetExistingTransaction(
			tradeID);
	if (tradeData == NULL)
		return QueryErrorMsg::TRADENOTFOUND;

	TradePlayerData *pData = tradeData->GetPlayerData(selfID);
	if (pData == NULL)
		return actInst->tradesys.CancelTransaction(selfID, tradeID, sim->SendBuf);

	CreatureInstance *cInst = pData->otherPlayerData->cInst;

	pData->SetAccepted(true);

	int wpos = 0;
	wpos += PutByte(&sim->SendBuf[wpos], 51);     //_handleTradeMsg
	wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
	wpos += PutInteger(&sim->SendBuf[wpos], creatureInstance->CreatureID);   //traderID
	wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::OFFER_ACCEPTED); //eventType
	PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
	SendToOneSimulator(sim->SendBuf, wpos, cInst->simulatorPtr);
	//actInst->LSendToOneSimulator(SendBuf, wpos, cInst->SimulatorIndex);

	CreatureInstance *origin = tradeData->player[0].cInst;
	CreatureInstance *target = tradeData->player[1].cInst;
	if (origin == NULL || target == NULL)
		return QueryErrorMsg::INVALIDOBJ;

	if (tradeData->MutualAccept() == true) {
		//Process the trade.
		int wpos = 0;

		//When counting slots, get the currently free slots.
		//Then add the number of items that would be traded (given away).
		//This allows a currently full inventory to potentially receive items
		//after the transaction is processed.

		int oslots = origin->charPtr->inventory.CountFreeSlots(INV_CONTAINER);
		oslots += tradeData->player[0].itemList.size();

		int tslots = target->charPtr->inventory.CountFreeSlots(INV_CONTAINER);
		tslots += tradeData->player[1].itemList.size();

		if (oslots < (int) tradeData->player[1].itemList.size()) {
			//Origin player does not have enough space to receive items.
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_SPACE); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Origin lacks space", sim->InternalID);
			goto exit;
		}
		if (tslots < (int) tradeData->player[0].itemList.size()) {
			//Target player does not have enough space to receive items.
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], target->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_SPACE); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Target lacks space", sim->InternalID);
			goto exit;
		}

		//Check that each player has the required currencies.
		if (tradeData->player[0].coin > origin->css.copper) {
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_FUNDS); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Origin lacks copper", sim->InternalID);
			goto exit;
		}
		if (tradeData->player[1].coin > target->css.copper) {
			wpos = 0;
			wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
			wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
			wpos += PutInteger(&sim->SendBuf[wpos], target->CreatureID);   //traderID
			wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
			wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::INSUFFICIENT_FUNDS); //eventType
			PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size
			SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
			SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
			//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
			//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
			g_Logs.simulator->debug("[%v] Target lacks copper", sim->InternalID);
			goto exit;
		}

		//Ready to trade.
		g_Logs.simulator->debug("[%v] Trade requirements passed", sim->InternalID);

		//Adjust and send coin transfer to both players.
		origin->css.copper -= tradeData->player[0].coin;
		target->css.copper -= tradeData->player[1].coin;

		origin->css.copper += tradeData->player[1].coin;
		target->css.copper += tradeData->player[0].coin;

		static const short statSend = STAT::COPPER;
		wpos = PrepExt_SendSpecificStats(sim->SendBuf, origin, &statSend, 1);
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);

		wpos = PrepExt_SendSpecificStats(sim->SendBuf, target, &statSend, 1);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);

		//Adjust and send items for first player.

		//Remove items from first player.
		wpos = 0;
		CharacterData *p1 = origin->charPtr;
		CharacterData *p2 = target->charPtr;
		g_Logs.simulator->debug("[%v] Trade betweeen [%v] and [%v]",
				sim->InternalID, p1->cdef.css.display_name, p2->cdef.css.display_name);
		for (size_t a = 0; a < tradeData->player[0].itemList.size(); a++) {
			unsigned long CCSID = tradeData->player[0].itemList[a].CCSID;
			InventorySlot *item = p1->inventory.GetItemPtrByCCSID(CCSID);
			if (item == NULL) {
				g_Logs.simulator->error(
						"[%v] Failed to remove item from first player.", sim->InternalID);
			} else {
				wpos += p1->inventory.RemoveItemUpdate(&sim->SendBuf[wpos], sim->Aux3,
						item);
				p1->inventory.RemItem(CCSID);
				p1->pendingChanges++;
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Removed %v items from first player.", sim->InternalID,
				tradeData->player[0].itemList.size());

		//Remove items from second player.
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[1].itemList.size(); a++) {
			unsigned long CCSID = tradeData->player[1].itemList[a].CCSID;
			InventorySlot *item = p2->inventory.GetItemPtrByCCSID(CCSID);
			if (item == NULL) {
				g_Logs.simulator->error(
						"[%v] Failed to remove item from first player.", sim->InternalID);
			} else {
				wpos += p2->inventory.RemoveItemUpdate(&sim->SendBuf[wpos], sim->Aux3,
						item);
				p2->inventory.RemItem(CCSID);
				p2->pendingChanges++;
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Removed %v items from second player.", sim->InternalID,
				tradeData->player[1].itemList.size());

		//Give items to first player
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[1].itemList.size(); a++) {
			int itemID = tradeData->player[1].itemList[a].IID;
			int count = tradeData->player[1].itemList[a].count + 1;
			InventorySlot *item = p1->inventory.AddItem_Ex(INV_CONTAINER,
					itemID, count);
			if (item == NULL)
				g_Logs.simulator->error("[%v] Failed to add item to first player.", sim->InternalID);
			else {
				p1->pendingChanges++;
				g_Logs.event->info("[TRADE] From %v to %v (%v)",
						tradeData->player[1].cInst->css.display_name,
						tradeData->player[0].cInst->css.display_name,
						item->IID);
				item->CopyWithoutCount(tradeData->player[1].itemList[a], false);
				sim->ActivateActionAbilities(item);
				wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, item);
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Gave %v items to first player.", sim->InternalID,
				tradeData->player[1].itemList.size());

		//Give items to second player
		wpos = 0;
		for (size_t a = 0; a < tradeData->player[0].itemList.size(); a++) {
			int itemID = tradeData->player[0].itemList[a].IID;
			int count = tradeData->player[0].itemList[a].count + 1;
			InventorySlot *item = p2->inventory.AddItem_Ex(INV_CONTAINER,
					itemID, count);
			if (item == NULL)
				g_Logs.simulator->error("[%v] Failed to add item to second player.", sim->InternalID);
			else {
				p2->pendingChanges++;
				g_Logs.event->info("[TRADE] From %v to %v (%v)",
						tradeData->player[0].cInst->css.display_name,
						tradeData->player[1].cInst->css.display_name,
						item->IID);
				item->CopyWithoutCount(tradeData->player[0].itemList[a], false);
				sim->ActivateActionAbilities(item);
				wpos += AddItemUpdate(&sim->SendBuf[wpos], sim->Aux3, item);
			}
		}
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);
		g_Logs.simulator->debug("[%v] Gave %v items to second player.", sim->InternalID,
				tradeData->player[0].itemList.size());

		//Send trade completion message.
		wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);    //Placeholder for size
		wpos += PutInteger(&sim->SendBuf[wpos], origin->CreatureID);     //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_CLOSED); //eventType
		wpos += PutByte(&sim->SendBuf[wpos], CloseReasons::COMPLETE);     //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);       //Set message size

		SendToOneSimulator(sim->SendBuf, wpos, origin->simulatorPtr);
		//origin->actInst->LSendToOneSimulator(SendBuf, wpos, origin->SimulatorIndex);

		PutInteger(&sim->SendBuf[3], target->CreatureID);     //traderID
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
		//target->actInst->LSendToOneSimulator(SendBuf, wpos, target->SimulatorIndex);

		//Clear trade IDs.
		origin->activeLootID = 0;
		target->activeLootID = 0;

		g_Logs.simulator->debug("[%v] Trade complete", sim->InternalID);
		actInst->tradesys.RemoveTransaction(tradeID);
	}

	//Yes, I'm using goto.
	//Yes, I know this whole thing is badly programmed.
	//Deal with it.

	exit: return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}
Example #6
0
int TradeStartHandler::protected_helper_query_trade_start(SimulatorThread *sim,
		CharacterServerData *pld, SimulatorQuery *query,
		CreatureInstance *creatureInstance) {
	// Note: query errors don't seem to do anything in the client.

	// Note: The trade starter has an argument for the target player.
	//       When the target player accepts, there is no argument to this
	//       query.

	int selfPlayerID = creatureInstance->CreatureID;
	int otherPlayerID = 0;
	if (query->argCount > 0)
		otherPlayerID = query->GetInteger(0);

	ActiveInstance *actInst = creatureInstance->actInst;
	if (actInst == NULL) {
		g_Logs.simulator->error(
				"[%v] trade.start active instance is NULL", sim->InternalID);
		return QueryErrorMsg::INVALIDOBJ;
	}

	CreatureInstance *target = NULL;
	if (otherPlayerID != 0) {
		//Make sure we're not busy.
		if (sim->CanMoveItems() == false)
			return QueryErrorMsg::SELFBUSYSKILL;

		//Make sure the other player exists
		target = actInst->GetPlayerByID(otherPlayerID);
		if (target == NULL)
			return QueryErrorMsg::INVALIDOBJ;

		//Make sure the other player isn't busy
		if (actInst->tradesys.GetExistingTradeForPlayer(otherPlayerID) != NULL)
			return QueryErrorMsg::TRADEBUSY;

		if (target->simulatorPtr->CanMoveItems() == false)
			return QueryErrorMsg::OTHERBUSYSKILL;
	}

	//It only takes one player to start the trade for both, so initialize a
	//transaction for both players.
	int CheckID = creatureInstance->activeLootID;
	if (CheckID == 0)
		CheckID = selfPlayerID;
	TradeTransaction *tradeData = actInst->tradesys.GetNewTransaction(CheckID);
	//tradeData->Clear();
	bool initiator = false;
	if (otherPlayerID != 0) {
		initiator = true;
		tradeData->SetPlayers(creatureInstance, target);
		creatureInstance->activeLootID = CheckID;
		target->activeLootID = CheckID;
		tradeData->init = true;
	} else {
		//This is the accepting player, so the target must be the origin.
		otherPlayerID = tradeData->player[0].selfPlayerID;
		target = tradeData->player[0].cInst;
	}

	if (target == NULL || otherPlayerID == 0)
		return QueryErrorMsg::INVALIDOBJ;

	tradeData->GetPlayerData(selfPlayerID)->tradeWindowOpen = true;

	if (initiator == true) {
		// Send trade request message to the other player.
		int wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);
		wpos += PutInteger(&sim->SendBuf[wpos], selfPlayerID);   //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST); //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
	} else {
		int wpos = 0;
		wpos += PutByte(&sim->SendBuf[wpos], 51);    //_handleTradeMsg
		wpos += PutShort(&sim->SendBuf[wpos], 0);
		wpos += PutInteger(&sim->SendBuf[wpos], selfPlayerID);   //traderID
		wpos += PutByte(&sim->SendBuf[wpos], TradeEventTypes::REQUEST_ACCEPTED); //eventType
		PutShort(&sim->SendBuf[1], wpos - 3);
		SendToOneSimulator(sim->SendBuf, wpos, target->simulatorPtr);
	}

	return PrepExt_QueryResponseString(sim->SendBuf, query->ID, "OK");
}