コード例 #1
0
ファイル: ActionRandomSay.cpp プロジェクト: hillwah/darkeden
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionRandomSay::execute (Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY
	__BEGIN_DEBUG

	Assert(pCreature1 != NULL);
	Assert(pCreature2 == NULL);
	Assert(pCreature1->isNPC());

	// RandomSay는 아래에서 보다시피, 임의의 범위(Start와 End) 안의 
	// 스크립트 중 랜덤을 돌려 하나를 클라이언트에게 보내는 식이다.
	// 그러므로 Start와 End 사이에 존재하지 않는 스크립트가 있으면 곤란하다.
	// 스크립트 테이블을 만들 때, RandomSay에 사용하는 것은 
	// 데이터가 반드시 연속적으로 존재하게 만들어야 한다.
	NPC*          pNPC     = dynamic_cast<NPC*>(pCreature1);
	ScriptID_t    scriptID = m_StartScriptID + random() % (m_EndScriptID - m_StartScriptID + 1);
	const Script* pScript  = g_pPublicScriptManager->getScript(scriptID);

	GCNPCSay gcNPCSay;
	gcNPCSay.setObjectID(pNPC->getObjectID());
	gcNPCSay.setScriptID(pScript->getScriptID());
	gcNPCSay.setSubjectID(0);

	Zone * pZone = pNPC->getZone();
	Assert(pZone != NULL);
	pZone->broadcastPacket(pNPC->getX() , pNPC->getY() , &gcNPCSay);

	__END_DEBUG
	__END_CATCH
}
コード例 #2
0
//////////////////////////////////////////////////////////////////////////////
// 
// 일반 아이템을 처리한다.
//
//////////////////////////////////////////////////////////////////////////////
void CGShopRequestSellHandler::executeNormal (CGShopRequestSell* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	ObjectID_t      NPCID        = pPacket->getObjectID();
	ObjectID_t      ITEMOID      = pPacket->getItemObjectID();
	GamePlayer*     pGamePlayer  = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*       pCreature    = pGamePlayer->getCreature();
	PlayerCreature* pPC          = dynamic_cast<PlayerCreature*>(pCreature);
	BYTE            index        = 0;
	bool            bSpecialItem = false;

	Zone* pZone = pPC->getZone();
	if (pZone == NULL) return sendFailPacket(pPacket, pPlayer);

	Creature* pNPCBase = NULL;
	/*
	try 
	{ 
		pNPCBase = pZone->getCreature(NPCID); 
	}
	catch (NoSuchElementException & nsee) 
	{ 
		pNPCBase = NULL; 
	}
	*/

	// NoSuch제거. by sigi. 2002.5.2
	pNPCBase = pZone->getCreature(NPCID); 

	if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer);

	NPC* pNPC = dynamic_cast<NPC*>(pNPCBase);
	
	// 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사
	Inventory* pInventory  = pPC->getInventory();
	//Gold_t     playerMoney = pPC->getGold(); 
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);
	ItemNum_t  itemNumber  = pItem->getNum();
	Price_t    itemPrice   = g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * itemNumber;

	// 플레이어의 인벤토리에 아이템을 제거한다.
	pInventory->deleteItem(ITEMOID);
	pItem->whenPCLost(pPC);

	if (!pItem->destroy()) {
		filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str());

		throw DisconnectException("아이템 지울려는데 DB에 없다.");
	}

	// 만약 벨트라면 안에 있는 포션을 삭제해준다.
	// DB에서 지우는 것은 Belt::destroy()를 부르는 것만으로 포션까지 삭제된다.
	if (pItem->getItemClass() == Item::ITEM_CLASS_BELT) {
		Inventory* pBeltInventory = dynamic_cast<Belt*>(pItem)->getInventory();
		for (int y=0; y<pBeltInventory->getHeight(); y++) {
			for (int x=0; x<pBeltInventory->getWidth(); x++) {
				Item* pBeltItem = pBeltInventory->getItem(x, y);
				if (pBeltItem != NULL) {
					pBeltInventory->deleteItem(x, y);
					SAFE_DELETE(pBeltItem);
				}
			}
		}
	}

	// Skull 일 경우 Variable Manager 에서 머리값 배수 값으로 가격을 새로 계산한다
	if (pItem->getItemClass() == Item::ITEM_CLASS_SKULL)
		itemPrice = itemPrice * (g_pVariableManager->getHeadPriceBonus() / 100);

	// ItemTrace Log 를 남겨야 한다면 남긴다
	if (pItem != NULL && pItem->isTraceItem() )
		remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL);

	// 플레이어에게 물건값을 지불한다.
	// pPC->setGoldEx(playerMoney+itemPrice);
	// by sigi. 2002.9.4
	pPC->increaseGoldEx(itemPrice);

	// 플레이어가 물건 팔 때 처리할 것들을 처리한다.
	pPC->sellItem(pItem);

	if (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 4)
		addOlympicStat(pPC, 4, (uint)(itemNumber));

	bool bClearDefaultOptionTypes = false;
	if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_ITEM && pItem->getItemType() >= 32 && pItem->getItemType() <= 36)
		bClearDefaultOptionTypes = true;

	// NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다.
	// 운영자 명령어로 만든 아이템은 바로 없앤다.
	// 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림.
	// 퀘스트 아이템은 보관하지 않고 버린다.
	if (pNPC->getShopType()==SHOPTYPE_NORMAL &&
		pItem->getCreateType()!=Item::CREATE_TYPE_CREATE &&
		!pItem->getOptionTypeList().empty() &&
		!pItem->isTimeLimitItem()) {
		bSpecialItem = true;
		index        = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL);

		if (index < SHOP_RACK_INDEX_MAX) {
			// 아이템을 추가한다.
			pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItem);

			// 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다.
			pNPC->increaseShopVersion(SHOP_RACK_SPECIAL);

			////////////////////////////////////////////////////////////////////////////
			// 근처의 플레이어들에게는 GCShopBought를...
			////////////////////////////////////////////////////////////////////////////

			int         CenterX       = pNPC->getX();
			int         CenterY       = pNPC->getY();
			Creature*   pNearCreature = NULL;
			Player*     pNearPlayer   = NULL;

			GCShopBought boughtpkt;
			boughtpkt.setObjectID(NPCID);
			if (!pItem->getOptionTypeList().empty()) {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
				boughtpkt.setShopType(SHOP_RACK_SPECIAL);
			} else {
				boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
				boughtpkt.setShopType(SHOP_RACK_NORMAL);
			}
			boughtpkt.setShopIndex(index);
			boughtpkt.setItemObjectID(ITEMOID);
			boughtpkt.setItemClass(pItem->getItemClass());
			boughtpkt.setItemType(pItem->getItemType());
			boughtpkt.setOptionType(pItem->getOptionTypeList());
			boughtpkt.setDurability(pItem->getDurability());
			boughtpkt.setSilver(pItem->getSilver());
			boughtpkt.setGrade(pItem->getGrade());
			boughtpkt.setEnchantLevel(pItem->getEnchantLevel());

			//pZone->broadcastPacket(pNPC->getX(), pNPC->getY(), &boughtpkt, pPC);

			try
			{
				for (int zx=CenterX-5; zx<=CenterX+5; zx++)
				{
					for (int zy=CenterY-5; zy<=CenterY+5; zy++)
					{
						// 바운드를 넘어가지 않는가를 체크
						if (!isValidZoneCoord(pZone, zx, zy)) continue;

						Tile & tile = pZone->getTile(zx, zy);

						// 걸어다니는 크리쳐를 검색	
						if (tile.hasCreature(Creature::MOVE_MODE_WALKING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_WALKING);
							if (pNearCreature == NULL) continue;

							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;
							
							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}
						// 날아다니는 크리쳐를 검색
						if (tile.hasCreature(Creature::MOVE_MODE_FLYING))
						{
							pNearCreature = tile.getCreature(Creature::MOVE_MODE_FLYING);
							if (pNearCreature == NULL) continue;
							
							// 방금 물건을 판 플레이어라면 생략
							if (pNearCreature->getObjectID() == pPC->getObjectID()) continue;

							// 만약 플레이어라면 패킷을 보내준다.
							if (pNearCreature->isPC())
							{
								pNearPlayer = pNearCreature->getPlayer();
								if (pNearPlayer == NULL) continue;
								pNearPlayer->sendPacket(&boughtpkt);
							}
						}

					} // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
				} // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)
			}
			catch (Throwable & t)
			{
				filelog("shopbug_packet.log", "%s", t.toString().c_str());
			}

		} // if (index < SHOP_RACK_INDEX_MAX)
		else
		{
			SAFE_DELETE(pItem);
		}
	} // if (pItem->getOptionType() != 0)
	else
	{
		bSpecialItem = false;
		SAFE_DELETE(pItem);
	}

	// 물건을 산 플레이어에게 GCShopSellOK를...보낸다.
	GCShopSellOK okpkt;
	okpkt.setObjectID(NPCID);
	if (bSpecialItem) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
	else              okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
	okpkt.setItemObjectID(ITEMOID);
	//okpkt.setPrice(playerMoney+itemPrice);
	// playerMoney + itemPrice 가 MAX_MONEY를 넘어갈 수 있다.
	// 2003.1.8 by bezz
	okpkt.setPrice(pPC->getGold());
	pPlayer->sendPacket(&okpkt);
	
	if (bClearDefaultOptionTypes )
	{
		pPC->clearDefaultOptionTypes();
		pPC->initAllStatAndSend();

		if (pPC->isSlayer() )
		{
			Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
			Assert(pSlayer != NULL);

			pSlayer->sendRealWearingInfo();
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
			Assert(pVampire != NULL);

			pVampire->sendRealWearingInfo();
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
			Assert(pOusters != NULL);

			pOusters->sendRealWearingInfo();
		}
	}

#endif

	__END_DEBUG_EX __END_CATCH
}
コード例 #3
0
//////////////////////////////////////////////////////////////////////////////
//
// 모터 사이클을 처리한다.
//
//////////////////////////////////////////////////////////////////////////////
void CGShopRequestSellHandler::executeMotorcycle (CGShopRequestSell* pPacket , Player* pPlayer)
	 throw(ProtocolException , Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX

#ifdef __GAME_SERVER__

	// 패킷 정보를 뽑아낸다.
	ObjectID_t      NPCID       = pPacket->getObjectID();
	ObjectID_t      ITEMOID     = pPacket->getItemObjectID();
	GamePlayer*     pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer);
	Creature*       pCreature   = pGamePlayer->getCreature();
	PlayerCreature* pPC         = dynamic_cast<PlayerCreature*>(pCreature);

	Zone* pZone = pPC->getZone();
	if (pZone == NULL) return sendFailPacket(pPacket, pPlayer);

	Creature* pNPCBase = NULL;
	/*
	try 
	{ 
		pNPCBase = pZone->getCreature(NPCID); 
	} 
	catch (NoSuchElementException & nsee) 
	{ 
		pNPCBase = NULL; 
	}
	*/

	// NoSuch제거. by sigi. 2002.5.2
	pNPCBase = pZone->getCreature(NPCID); 

	if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer);

	NPC*        pNPC    = dynamic_cast<NPC*>(pNPCBase);
	int         CenterX = pNPC->getX();
	int         CenterY = pNPC->getY();
	
	// 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사
	Inventory* pInventory  = pPC->getInventory();
	Gold_t     playerMoney = pPC->getGold();
	Item*      pItem       = pInventory->getItemWithObjectID(ITEMOID);
	if (pItem == NULL) return sendFailPacket(pPacket, pPlayer);

	// 주위 일정 범위를 검색해서, 모터 사이클이 있는지 확인한다.
	try
	{
		for (int zx=CenterX-5; zx<=CenterX+5; zx++)
		{
			for (int zy=CenterY-5; zy<=CenterY+5; zy++)
			{
				// 바운드를 넘어가지 않는가를 체크
				if (!isValidZoneCoord(pZone, zx, zy)) continue;

				Tile & tile = pZone->getTile(zx, zy);
				if (tile.hasItem())
				{
					Item* pItemOnTile = tile.getItem();
					if (pItemOnTile == NULL) continue;

					// 만일 아이템이 타일 위에 있을 경우, 모터 사이클인지 확인한다.
					if (pItemOnTile->getItemClass() == Item::ITEM_CLASS_MOTORCYCLE)
					{
						DWORD    targetID     = dynamic_cast<Key*>(pItem)->getTarget();
						ItemID_t motorcycleID = pItemOnTile->getItemID();

						if (targetID == motorcycleID)
						{
							// 모터사이클을 DB에서 삭제한다.
							pItemOnTile->destroy();

							// 플레이어의 인벤토리에서 열쇠를 제거한다.
							pInventory->deleteItem(ITEMOID);
							pItem->destroy();
							SAFE_DELETE(pItem);
							
							// 열쇠 값이 아니라, 오토바이 값을 줘야 한다.
							Price_t itemPrice = g_pPriceManager->getPrice(pItemOnTile, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC);

							// 플레이어의 돈을 늘린다.
							//pPC->setGoldEx(playerMoney+itemPrice);
							// by sigi. 2002.9.4
							pPC->increaseGoldEx(itemPrice);

							// 물건을 판 플레이어에게 GCShopSellOK를...보낸다.
							GCShopSellOK okpkt;
							okpkt.setObjectID(NPCID);
							if (!pItemOnTile->getOptionTypeList().empty()) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL));
							else                                   okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL));
							okpkt.setItemObjectID(ITEMOID);
							okpkt.setPrice(playerMoney+itemPrice);
							pPlayer->sendPacket(&okpkt);

							// 뻑킹 센터에서 박스를 삭제해 준다.
							if (g_pParkingCenter->hasMotorcycleBox(motorcycleID)) 
								g_pParkingCenter->deleteMotorcycleBox(motorcycleID);

							// NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다.
							// 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림.
							//if (pItemOnTile->getOptionType() != 0)
							//{
							//	index = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL);
							//	if (index < SHOP_RACK_INDEX_MAX)
							//	{
							//		pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItemOnTile);
							//		// 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다.
							//		pNPC->increaseShopVersion(SHOP_RACK_SPECIAL);
							//	}
							//}
							//else
							//{
							//	SAFE_DELETE(pItemOnTile);
							//}

							// 모터 사이클을 찾았으므로, 할 일이 끝났다. 
							return;
						}
					}
				}
			} // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++)
		} // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++)
	}
	catch (Throwable & t)
	{
		filelog("shopbug_packet.log", "%s", t.toString().c_str());
	}

	// FOR 루프를 다 돌고, 이까지 왔다는 것은 근처에 오토바이가 없다는 말이당...
	// 그러므로 모터 사이클 팔기가 실패했다는 것을 알린다.
	GCShopSellFail failpkt;
	failpkt.setObjectID(NPCID);
	pPlayer->sendPacket(&failpkt);
	
#endif

	__END_DEBUG_EX __END_CATCH
}
コード例 #4
0
ファイル: Player.cpp プロジェクト: TheZoq2/Silverheart
void Player::activation()
{
	float lowestDist = 90;
	bool partFound = false;
	Part* closestPart = NULL;
	int closestPartID;
	float partDist = lowestDist + 1;

	//Looping thru all of the parts
	for(int i = 0; i < world->getPartAmount(); i++)
	{
		if(world->getPartUsable(i) == 1) //Making sure we are only looking at parts that can actually be used
		{
			float partX = world->getPartX(i);
			float partY = world->getPartY(i);

			float distX = partX - x;
			float distY = partY - y;
			float dist = agk::Sqrt(distX * distX + distY * distY);

			int useRange = 90;
			if(dist < useRange) //Checking if the part is within reach
			{
				partFound = true;
				
				if(dist < lowestDist) //CHecking if this is the closest part found
				{
					lowestDist = dist; //Changing the lowest distance
					partDist = dist;

					closestPart = world->getPartFromID(i); //Changing the lowest part we have found
					closestPartID = i;
				}
			}
		}
	}

	bool npcFound = false;
	NPC* closestNPC = NULL;
	float npcDist = lowestDist + 1;
	
	//Looping thru all the NPCs (Using the)
	for(unsigned int i = 0; i < defaultNPCGroup->getNPCAmount(); i++)
	{
		NPC* npc = defaultNPCGroup->getNPC(i);

		if(npc != NULL)
		{
			float npcX = npc->getX();
			float npcY = npc->getY();

			float distX = npcX - x;
			float distY = npcY - y;
			float dist = agk::Sqrt(distX * distX + distY * distY);

			if(dist < lowestDist)
			{
				npcFound = true;

				lowestDist = dist;
				npcDist = dist;

				closestNPC = npc;
			}
		}
	}

	if((partFound == true && closestPart != NULL) || (npcFound == true && closestNPC != NULL))
	{
		if(partDist < npcDist)
		{
			//Positioning the activation text
			agk::SetTextVisible(activateText, 1);
			agk::SetTextPosition(activateText, agk::WorldToScreenX( closestPart->getX() ), agk::WorldToScreenY( closestPart->getY() ));

			//Changing the text to the use text of the part
			std::string fText;
			fText = i_activateName;
			fText.append(") ");
			fText.append(closestPart->getUseMsg());

			agk::SetTextString(activateText, fText.data());

			//Adding the background
			agk::SetSpritePosition(activateSprite, agk::WorldToScreenX(closestPart->getX()) -5.0f, agk::WorldToScreenY(closestPart->getY()) - 2.5f);
			agk::SetSpriteVisible(activateSprite, 1);
			agk::SetSpriteScale(activateSprite, agk::GetTextTotalWidth(activateText) + 10, agk::GetTextTotalHeight(activateText) + 5);

			//Checking if the part is activated
			if(Input::activate() == true)
			{
				//Getting the script of the item
				std::string actScript;
				actScript = ("scripts/");
				actScript.append(closestPart->getActScript());

				//Saving the part that was activated last for use with labels in lua
				world->setLastActive(closestPartID);

				//Checking if this is a lua script or an old script
				if(actScript.find(".lua") != -1)
				{
					LuaHandler::runScript(actScript);
				}
				else
				{
					//Starting the script
					Script::run(actScript.data(), closestPart, world, this);
				}
			}
		}
		else
		{
			//Positioning the activation text
			agk::SetTextVisible(activateText, 1);
			agk::SetTextPosition(activateText, agk::WorldToScreenX( closestNPC->getX() ), agk::WorldToScreenY( closestNPC->getY() ));

			//Changing the text to the use text of the part
			std::string fText;
			fText = i_activateName;
			fText.append(") ");
			fText.append("talk");

			agk::SetTextString(activateText, fText.data());

			//Adding the background
			agk::SetSpritePosition(activateSprite, agk::WorldToScreenX(closestNPC->getX()) -5.0f, agk::WorldToScreenY(closestNPC->getY()) - 2.5f);
			agk::SetSpriteVisible(activateSprite, 1);
			agk::SetSpriteScale(activateSprite, agk::GetTextTotalWidth(activateText) + 10, agk::GetTextTotalHeight(activateText) + 5);

			//Checking if the part is activated
			if(Input::activate() == true)
			{
				closestNPC->startConversation();
			}
		}
	}
	else //No parts where found, hide the text
	{
		agk::SetTextVisible(activateText, 0);
		agk::SetSpriteVisible(activateSprite, 0);
	}
}