Esempio n. 1
0
/**
 * \brief Creates a pickable item with the specified subtype.
 *
 * This method acts like a constructor, except that it can return nullptr in several cases:
 * - the treasure is saved and the player already has it,
 * or:
 * - the treasure is empty,
 * or:
 * - the item cannot be obtained by the hero yet,
 * or:
 * - the animation of the item is missing in sprite 'entities/items'.
 *
 * \param game the current game
 * \param name Name identifying the entity on the map or an empty string.
 * \param layer layer of the pickable item to create on the map
 * \param x x coordinate of the pickable item to create
 * \param y y coordinate of the pickable item to create
 * \param treasure the treasure to give
 * \param falling_height to make the item fall when it appears
 * \param force_persistent true to make the item stay forever
 * (otherwise, the properties of the item
 * decide if it disappears after some time)
 * \return the pickable item created, or nullptr
 */
std::shared_ptr<Pickable> Pickable::create(
    Game& /* game */,
    const std::string& name,
    Layer layer,
    int x,
    int y,
    Treasure treasure,
    FallingHeight falling_height,
    bool force_persistent
) {
  treasure.ensure_obtainable();

  // Don't create anything if there is no treasure to give.
  if (treasure.is_found() || treasure.is_empty()) {
    return nullptr;
  }

  std::shared_ptr<Pickable> pickable = std::make_shared<Pickable>(
      name, layer, x, y, treasure
  );

  // Set the item properties.
  pickable->falling_height = falling_height;
  pickable->will_disappear = !force_persistent && treasure.get_item().get_can_disappear();

  // Initialize the pickable item.
  if (!pickable->initialize_sprites()) {
    return nullptr;  // No valid sprite: don't create the pickable.
  }
  pickable->initialize_movement();

  return pickable;
}
Esempio n. 2
0
/**
 * \brief Creates a new chest with the specified treasure.
 * \param name Name identifying this chest.
 * \param layer Layer of the chest to create on the map.
 * \param xy Coordinates of the chest to create.
 * \param sprite_name Name of the animation set of the
 * sprite to create for the chest. It must have animations "open" and "closed".
 * \param treasure The treasure in the chest.
 */
Chest::Chest(
    const std::string& name,
    Layer layer,
    const Point& xy,
    const std::string& sprite_name,
    const Treasure& treasure):

  Detector(COLLISION_FACING, name, layer, xy, Size(16, 16)),
  treasure(treasure),
  open(treasure.is_found()),
  treasure_given(open),
  treasure_date(0),
  opening_method(OpeningMethod::BY_INTERACTION),
  opening_condition_consumed(false) {

  // Create the sprite.
  Sprite& sprite = *create_sprite(sprite_name);
  std::string animation = is_open() ? "open" : "closed";
  sprite.set_current_animation(animation);

  set_origin(get_width() / 2, get_height() - 3);

  // TODO set this as the default drawn_in_y_order for MapEntity
  set_drawn_in_y_order(sprite.get_max_size().height > get_height());
}
Esempio n. 3
0
/**
 * \brief Creates a new shop treasure with the specified treasure and price.
 * \param game the current game
 * \param name the name identifying this entity
 * \param layer layer of the entity to create
 * \param x x coordinate of the entity to create
 * \param y y coordinate of the entity to create
 * \param treasure the treasure that the hero can buy
 * \param price the treasure's price in rupees
 * \param dialog_id id of the dialog describing the item when the player watches it
 * \return the shop treasure created, or nullptr if it is already bought or if it
 * is not obtainable.
 */
std::shared_ptr<ShopTreasure> ShopTreasure::create(
    Game& /* game */,
    const std::string& name,
    Layer layer,
    int x,
    int y,
    const Treasure& treasure,
    int price,
    const std::string& dialog_id
) {
  // See if the item is not already bought and is obtainable.
  if (treasure.is_found() || !treasure.is_obtainable()) {
    return nullptr;
  }

  return std::make_shared<ShopTreasure>(
      name, layer, x, y, treasure, price, dialog_id
  );
}
Esempio n. 4
0
/**
 * \brief Constructor.
 * \param hero The hero controlled by this state.
 * \param treasure The treasure to give to the hero. It must be obtainable.
 * \param callback_ref Lua ref to a function to call when the
 * treasure's dialog finishes (possibly LUA_REFNIL).
 */
Hero::TreasureState::TreasureState(
    Hero& hero,
    const Treasure& treasure,
    int callback_ref):

  State(hero, "treasure"),
  treasure(treasure),
  callback_ref(callback_ref) {

  treasure.check_obtainable();
}
Esempio n. 5
0
/**
 * @brief Creates a new chest with the specified treasure.
 * @param name name identifying this chest
 * @param layer layer of the chest to create on the map
 * @param x x coordinate of the chest to create
 * @param y y coordinate of the chest to create
 * @param big_chest true to make a big chest, false to make a normal chest
 * @param treasure the treasure in the chest (will be deleted automatically)
 */
Chest::Chest(const std::string &name, Layer layer, int x, int y,
	     bool big_chest, const Treasure &treasure):

  Detector(COLLISION_FACING_POINT, name, layer, x, y, 16, 16),
  treasure(treasure),
  big_chest(big_chest),
  open(treasure.is_found()),
  treasure_given(open),
  treasure_date(0) {

  initialize_sprite();
}
Esempio n. 6
0
/**
 * \brief Constructor.
 * \param hero The hero controlled by this state.
 * \param treasure The treasure to give to the hero. It must be obtainable.
 * \param callback_ref Lua ref to a function to call when the
 * treasure's dialog finishes (possibly an empty ref).
 */
Hero::TreasureState::TreasureState(
    Hero& hero,
    const Treasure& treasure,
    const ScopedLuaRef& callback_ref
):

  BaseState(hero, "treasure"),
  treasure(treasure),
  callback_ref(callback_ref) {

  treasure.check_obtainable();
}
Esempio n. 7
0
/**
 * @brief Creates a new chest with the specified treasure.
 * @param name Name identifying this chest.
 * @param layer Layer of the chest to create on the map.
 * @param x X coordinate of the chest to create.
 * @param y Y coordinate of the chest to create.
 * @param sprite_name Name of the animation set of the
 * sprite to create for the chest. It must have animations "open" and "closed".
 * @param treasure The treasure in the chest.
 */
Chest::Chest(
    const std::string& name,
    Layer layer,
    int x,
    int y,
    const std::string& sprite_name,
    const Treasure& treasure):

  Detector(COLLISION_FACING_POINT, name, layer, x, y, 16, 16),
  treasure(treasure),
  open(treasure.is_found()),
  treasure_given(open),
  treasure_date(0) {

  // Create the sprite.
  Sprite& sprite = create_sprite(sprite_name);
  std::string animation = is_open() ? "open" : "closed";
  sprite.set_current_animation(animation);

  set_origin(get_width() / 2, get_height() - 3);
}
int main()
{


    //ascii table
    /*
    ASCII is a character encoding scheme. Remember, everything in a computer is
    stored is 0 or 1 and from that, we get a number. From the number, we need a
    way of displaying letters and symbols and numerical strings. ASCII enables
    this to happen. We can use the char data type to interpret numbers as
    characters. Since the underlying value is still a number, any numerical
    changes we make to the value will just generate a new char when we display
    it.
    */
    string strTest = "test string";
    //get the first character of the strTest
    char c = strTest[0];
    //display as a character
    cout<<c<<endl;
    //modify it
    c+=5;
    //display again
    //display its integer value by casting as an integer
    cout<<(int)c<<endl;
    cout<<c<<endl;
    //we can do this for all characters in the string
    for(int x = 0; x < strTest.length(); x++){
        c = strTest[x];
        cout<<"ascii char: "<<c<<endl;
        cout<<"numeric value: "<<(int)c<<endl;
    }
    char ascii;
    int numeric;
    /*An interactive example, ask for a character and give it's numerical
    value. Could also ask for a number and give it's ascii value.*/
    while(ascii != 'q'){
        cout << "Give character: ";
        cin >> ascii;
        cout << "Its ascii value is: " << (int) ascii << endl;
    }

    while((char)numeric != 'q'){
        cout << "Give a number to convert to ascii: ";
        cin >> numeric;
        cout << "The ascii value of " << numeric << " is " << (char) numeric<<endl;
    }

    /*
    Create a pointer. Allocate the memory needed for an integer using
    new int. Once allocated, the pointer stores an address and the value
    at that address can be obtained by de-referencing the pointer.
    */
    int *ptrX = NULL; //good practice to initialize pointers to null
    ptrX = new int;
    cout<<ptrX<<endl;
    *ptrX = 10;
    cout<<*ptrX<<endl;

    /*
    We previously did pointers by creating two variables and the pointer
    pointed to the address of the other variable.
    */
    int intB = 5;
    int *ptrB = &intB;
    cout<<*ptrB<<endl;

    //Also works for doubles
    double *ptrD = NULL;
    ptrD = new double;

    //create an array the same way
    int *ptrArray = new int[5];
    for(int x = 0; x < 5; x++)
        cout<<ptrArray[x]<<endl;
    /*
    Memory has been allocated here. Each int is 4 bytes. When we create a
    pointer that points to an existing variable, the variable is destroyed
    when it goes out of scope. For example, in a function, a local variable
    declared in the function is destroyed when the function is done executing.

    When memory is allocated dynamically, it has to be destroyed with delete
    */
    delete ptrX;
    delete ptrD;
    delete []ptrArray;

    /*
    What happens when memory isn't freed. Over time, the longer the program
    runs, memory is allocated, allocated, allocated. The program will
    generally start to slow down. When memory is allocated and not freed, it's called
    a memory leak.
    */
    /*
    Any variable type can be created dynamically, including objects.
    Create a treasure class.
    */
    Treasure *treasure = new Treasure();
    //or, an array of treasures
    Treasure *treasures = new Treasure[2];
    //accessing methods is a bit different.
    /*
    Accessing members of a pointer to a class, use the -> notation instead
    of the . notation.
    */
    cout<<treasure->getX()<<endl;
    /*
    When you create objects dynamically, they need to be destroyed with a
    destructor. The constructor serves the opposite purpose as the constructor.
    If the constructor is where the object is born, the destructor is the
    end of the object's life.
    */
    delete treasure;
    delete []treasures;
    return 0;
}
void CGLotterySelectHandler::execute (CGLotterySelect* pPacket , Player* pPlayer)
	 throw(Error)
{
	__BEGIN_TRY __BEGIN_DEBUG_EX
		
#ifdef __GAME_SERVER__

	GamePlayer* pGP = dynamic_cast<GamePlayer*>(pPlayer);
	Assert(pGP != NULL);

	Creature* pCreature = pGP->getCreature();
	Assert(pCreature != NULL);
		
	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature);
	Assert(pPC != NULL);

	filelog("EventQuest.log", "CGLotterySelectHandler : got [%d:%d:%d] from %s", pPacket->getType(), pPacket->getGiftID(), pPacket->getQuestLevel(),
			pPC->getName().c_str());

	switch (pPacket->getType() )
	{
		case TYPE_SELECT_LOTTERY:
			{
				// 인벤에서 퀘스트 아이템 삭제
				QuestID_t qID;
				EventQuestAdvance::Status status = pPC->getQuestManager()->getEventQuestAdvanceManager()->getStatus(pPacket->getQuestLevel());
				int ownerQuestLevel = pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel();
				if (
					(ownerQuestLevel > pPacket->getQuestLevel() && status == EventQuestAdvance::EVENT_QUEST_ADVANCED ) ||	
					(pPacket->getQuestLevel() == 4 &&  ownerQuestLevel== -1 ) ||
					pPC->getQuestManager()->successEventQuest(pPacket->getQuestLevel(), qID ) )
				{
					pPC->getQuestManager()->getEventQuestAdvanceManager()->rewarded(pPacket->getQuestLevel());
					pPC->getQuestManager()->getEventQuestAdvanceManager()->save();
					pPC->getQuestManager()->questRewarded(qID);
					pPC->sendCurrentQuestInfo();

					list<Item*> iList;
					pPC->getInventory()->clearQuestItem(iList);

					list<Item*>::iterator itr = iList.begin();
					list<Item*>::iterator endItr = iList.end();

					for (; itr != endItr ; ++itr )
					{
						GCDeleteInventoryItem gcDII;
						gcDII.setObjectID((*itr)->getObjectID());
						pPC->getPlayer()->sendPacket(&gcDII);
						(*itr)->destroy();
						SAFE_DELETE(*itr);
					}

					iList.clear();
				}
				else
				{
					filelog("EventBug.txt", "CGLotterySelectHandler : 복권 선택이 날라왔는데 완료한 퀘스트가 없다. -_-; %s[%d:%d]",
							pPC->getName().c_str(), pPacket->getQuestLevel(), pPacket->getGiftID());

					return;
				}

				GCNoticeEvent gcNE;
				gcNE.setCode(NOTICE_EVENT_RESULT_LOTTERY);
				if (bWinPrize(pPacket->getGiftID(), pPacket->getQuestLevel() ) ) 
				{
					// PlayerCreature 에 정보를 저장한다
					pPC->setLotto(true);
					pPC->setLottoRewardID(pPacket->getGiftID());
					pPC->setLottoQuestLevel(pPacket->getQuestLevel());
					gcNE.setParameter((uint)1);
				}
				else
				{
					// PlayerCreature 에 정보를 저장한다
					pPC->setLotto(false);
					pPC->setLottoRewardID(pPacket->getGiftID());
					pPC->setLottoQuestLevel(pPacket->getQuestLevel());
					gcNE.setParameter((uint)0);
				}
				pGP->sendPacket(&gcNE);

				filelog("EventQuest.log", "CGLotterySelectHandler : %d to %s", gcNE.getParameter(), pPC->getName().c_str());
			}
			break;
		case TYPE_FINISH_SCRATCH:
			{
				// 당첨된 경우 디비에 저장
				if (pPC->isLotto() )
				{
					// 다시 false 로 만들어줘야함.
					// 아님 담번 퀘스트에서 무조건 당첨으로 처리되니 ;;
					pPC->setLotto(false);

					Statement* pStmt = NULL;

					BEGIN_DB
					{
						pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement();

						pStmt->executeQuery("INSERT INTO EventQuestRewardRecord (PlayerID, RewardID, Time, RealPlayerID) VALUES ('%s', %d, now(), '%s' )",
								pCreature->getName().c_str(),
								pPC->getLottoRewardID(),
								pPC->getPlayer()->getID().c_str());

						SAFE_DELETE(pStmt);
					}
					END_DB(pStmt)

					// 이쪽 서버에 브로드 캐스트 하고 (allworld 는 해당 서버는 처리 안함)
					GCNotifyWin gcNW;
					gcNW.setGiftID(pPC->getLottoRewardID());
					gcNW.setName(pCreature->getName());

					g_pZoneGroupManager->broadcast(&gcNW);

					// 전 월드에 브로드캐스트해준다 
					char sCommand[200];
					string worldName = g_pGameWorldInfoManager->getGameWorldInfo(g_pConfig->getPropertyInt("WorldID" ))->getName();
					sprintf(sCommand, "*allworld *command NotifyWin %s(%s) %lu", pCreature->getName().c_str(), worldName.c_str(), pPC->getLottoRewardID());
					CGSayHandler::opworld(NULL, sCommand, 0, false);

				}
				else
				{
					// 아니면 그냥 퀘스트 아이템만 인벤에 넣어주면 되는듯
					Item::ItemClass iClass;
					ItemType_t iType;
					list<OptionType_t> oList;
					bool isTimeLimit = false;
					bool isLairItem = false;
					bool isUnique = false;
					MonsterType_t masterType;

					switch(pPC->getLottoQuestLevel() )
//					switch(pPC->getQuestManager()->getEventQuestAdvanceManager()->getQuestLevel() )
					{
						case 0:
							{
								static const string options1[] =
								{
									"STR+2",
									"DEX+2",
									"INT+2",
									"ASPD+2",
									"HP+2"
								};

								static const string options2[] =
								{
									"STR+3",
									"DEX+3",
									"INT+3",
									"ASPD+3",
									"HP+3"
								};
								if (pPC->isSlayer() )
								{
									Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
									QuestGrade_t qGrade = pSlayer->getTotalAttr(ATTR_BASIC);

									iClass = Item::ITEM_CLASS_RING;

									if (qGrade < 131 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (qGrade < 211 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (qGrade < 271 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (qGrade < 300 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isVampire() )
								{
									Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
									Level_t level = pVampire->getLevel();

									iClass = Item::ITEM_CLASS_VAMPIRE_RING;

									if (level < 31 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isOusters() )
								{
									Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
									Level_t level = pOusters->getLevel();

									iClass = Item::ITEM_CLASS_OUSTERS_RING;

									if (level < 31 )
									{
										iType = 1;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 2;
										makeOptionList(options1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 3;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 4;
										makeOptionList(options2[ rand()%5 ], oList);
									}
									else
									{
										iType = 5;
										makeOptionList(options2[ rand()%5 ], oList);
									}
								}
							}
							break;
						case 1:
							{
								static const string oSlayer1[] =
								{
									"DAM+2",
									"VIS+3",
									"MP+2",
									"LUCK+1",
									"HP+2"
								};
								static const string oSlayer2[] =
								{
									"DAM+3",
									"VIS+3",
									"MP+3",
									"LUCK+2",
									"HP+3"
								};
								static const string oVampire1[] =
								{
									"DAM+2",
									"VIS+3",
									"ASPD+2",
									"LUCK+1",
									"HP+2"
								};
								static const string oVampire2[] =
								{
									"DAM+3",
									"VIS+3",
									"ASPD+3",
									"LUCK+2",
									"HP+3"
								};
								if (pPC->isSlayer() )
								{
									Slayer* pSlayer = dynamic_cast<Slayer*>(pPC);
									QuestGrade_t qGrade = pSlayer->getTotalAttr(ATTR_BASIC);

									iClass = Item::ITEM_CLASS_RING;

									if (qGrade < 131 )
									{
										iType = 2;
										makeOptionList(oSlayer1[ rand()%5 ], oList);
									}
									else if (qGrade < 211 )
									{
										iType = 3;
										makeOptionList(oSlayer1[ rand()%5 ], oList);
									}
									else if (qGrade < 271 )
									{
										iType = 4;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
									else if (qGrade < 300 )
									{
										iType = 5;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oSlayer2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isVampire() )
								{
									Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
									Level_t level = pVampire->getLevel();

									iClass = Item::ITEM_CLASS_VAMPIRE_RING;
									
									if (level < 31 )
									{
										iType = 2;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 3;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 4;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 5;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
								}
								else if (pPC->isOusters() )
								{
									Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
									Level_t level = pOusters->getLevel();

									iClass = Item::ITEM_CLASS_OUSTERS_RING;
									
									if (level < 31 )
									{
										iType = 2;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 51 )
									{
										iType = 3;
										makeOptionList(oVampire1[ rand()%5 ], oList);
									}
									else if (level < 71 )
									{
										iType = 4;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else if (level < 91 )
									{
										iType = 5;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
									else
									{
										iType = 6;
										makeOptionList(oVampire2[ rand()%5 ], oList);
									}
								}
							}
							break;
						case 2:
							{
								isLairItem = true;
								masterType = 432;
							}
							break;
						case 3:
							{
								isLairItem = true;
								masterType = 433;
							}
							break;
						case 4:
							{
								isTimeLimit = true;
								if (pPC->isSlayer() )
								{
									isUnique = true;
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_COAT,
										Item::ITEM_CLASS_TROUSER,
										Item::ITEM_CLASS_GLOVE,
										Item::ITEM_CLASS_HELM,
										Item::ITEM_CLASS_SHOES,
//										Item::ITEM_CLASS_BELT,
										Item::ITEM_CLASS_NECKLACE,
										Item::ITEM_CLASS_BRACELET
									};
									static const ItemType_t iTypes[] =
									{
										16,
										16,
										8,
										9,
										7,
//										4,
										10,
										10
									};

									int index = rand() % 7;
									iClass = iClasses[index];
									iType = iTypes[index];
								}
								else if (pPC->isVampire() )
								{
									isUnique = true;
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_VAMPIRE_COAT,
										Item::ITEM_CLASS_VAMPIRE_WEAPON,
										Item::ITEM_CLASS_VAMPIRE_RING,
										Item::ITEM_CLASS_VAMPIRE_NECKLACE,
										Item::ITEM_CLASS_VAMPIRE_BRACELET,
										Item::ITEM_CLASS_VAMPIRE_AMULET,
										Item::ITEM_CLASS_VAMPIRE_EARRING
									};
									static const ItemType_t iTypes[] =
									{
										12,
										15,
										10,
										10,
										9,
										10,
										10
									};
									int index = rand() % 7;
									iClass = iClasses[index];
									iType = iTypes[index];
								}
								else if (pPC->isOusters() )
								{
									static const Item::ItemClass iClasses[] =
									{
										Item::ITEM_CLASS_OUSTERS_COAT,
										Item::ITEM_CLASS_OUSTERS_CIRCLET,
										Item::ITEM_CLASS_OUSTERS_ARMSBAND,
										Item::ITEM_CLASS_OUSTERS_BOOTS,
										Item::ITEM_CLASS_OUSTERS_PENDENT,
										Item::ITEM_CLASS_OUSTERS_RING
									};
									static const ItemType_t iTypes[] =
									{
										7,
										9,
										9,
										7,
										9,
										9
									};
									static const string options[] =
									{
										"DAM+3",
										"ASPD+3",
										"LUCK+2",
										"HP+9",
										"STR+3",
										"DEX+3",
										"INT+3",
										"ATTR+2",
										"RES+3",
										"MP+4"
									};
									int index = rand() % 6;
									iClass = iClasses[index];
									iType = iTypes[index];

									int option1 = rand()%10;
									int option2 = rand()%10;

									while (option1 == option2 ) option2 = rand()%10;

									makeOptionList(options[ option1 ] + "," + options[ option2 ], oList);
								}
							}
							break;
						default:
							break;
					}

					Item* pItem;

					if (isLairItem )
					{
						const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(masterType);
						TreasureList *pTreasureList = NULL;

						if (pPC->isSlayer())
							pTreasureList = pMonsterInfo->getSlayerTreasureList();
						else if (pPC->isVampire() )
							pTreasureList = pMonsterInfo->getVampireTreasureList();
						else if (pPC->isOusters() )
							pTreasureList = pMonsterInfo->getOustersTreasureList();

						const list<Treasure*>& treasures = pTreasureList->getTreasures();

						list<Treasure*>::const_iterator itr = treasures.begin();

						ITEM_TEMPLATE it;

						for(; itr != treasures.end(); itr++)
						{
							Treasure* pTreasure = (*itr);

							it.ItemClass = Item::ITEM_CLASS_MAX;
							it.ItemType = 0;

							it.NextOptionRatio = 0;

							//cout << "TradeLairItem: BonusRatio = " << it.NextOptionRatio << endl;

							if (pTreasure->getRandomItem(&it) )
							{
								pItem = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType);
								Assert(pItem != NULL);
							}
						}

					}
					else
					{
						pItem = g_pItemFactoryManager->createItem(iClass, iType, oList);
					}

					GenderRestriction gender = GENDER_BOTH;
					switch(pPC->getSex() )
					{
						case MALE:
							gender = GENDER_MALE;
							break;
						case FEMALE:
							gender = GENDER_FEMALE;
							break;
						default:
							break;
					}

					setItemGender(pItem, gender);

					_TPOINT tp;

					if (pItem != NULL && pPC->getInventory()->addItem(pItem, tp ) )
					{
						pPC->getZone()->registerObject(pItem);
						pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, tp.x, tp.y);

						if (isTimeLimit )
						{
							pPC->addTimeLimitItem(pItem, 604800);
							pPC->sendTimeLimitItemInfo();
						}

						GCCreateItem gcCreateItem;
						makeGCCreateItem(&gcCreateItem, pItem, tp.x, tp.y);
						pPC->getPlayer()->sendPacket(&gcCreateItem);

						remainTraceLog(pItem, "GOD", pCreature->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
					}
					else
					{
						if (isUnique )
							pItem->setUnique();

						if (isTimeLimit )
							pItem->setTimeLimitItem();

						pPC->setQuestItem(pItem);

						remainTraceLog(pItem, "GOD", pCreature->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
					}

				}

				if (pPC->getLottoQuestLevel() == 4 )
				{
					pPC->getQuestManager()->cancelQuest();
					GCNoticeEvent gcNE;
					gcNE.setCode(NOTICE_EVENT_START_QUEST_ENDING);
					pPC->getPlayer()->sendPacket(&gcNE);
				}
			}
Esempio n. 10
0
////////////////////////////////////////////////////////////////////////////////
// 액션을 실행한다.
////////////////////////////////////////////////////////////////////////////////
void ActionTradeLairItem::execute(Creature * pCreature1 , Creature * pCreature2) 
	throw(Error)
{
	__BEGIN_TRY

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

	if (m_Type <= 5 )
	{
		SYSTEM_RETURN_IF_NOT(SYSTEM_MASTER_LAIR);
	}

	PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2);
	Assert(pPC != NULL);

	Player* pPlayer = pPC->getPlayer();
	Assert(pPlayer != NULL);

	GCNPCResponse okpkt;
	pPlayer->sendPacket(&okpkt);
	StringStream message;

	/*

	GCSystemMessage gcSystemMessage;
	gcSystemMessage.setMessage("아직 지원되지 않는 기능입니다");
	pPlayer->sendPacket(&gcSystemMessage);
	*/


	//cout << "ActionTradeLairItem" << ":" << m_Type;

	Inventory* pInventory = pPC->getInventory();

	// 먼저 아이템을 가지고 있는가를 체크한다.
	Item* pMasterItem = NULL;
	MonsterType_t MonsterType = 0;

	Item* pItem1 = NULL;
	bool bUpgrade = false;
	
	// 옵션에 따라서 다른 아이템을 검사해야 한다.
	// 코난 : 팬던트/ 비쥬만 체크한다.
	// 브리콜라카스: 테페즈 펜던트/비쥬만 체크해야 한다
	// 카임 : 바토리 팬던트/비쥬만 체크해야 한다.

	if (m_Type == 0) // 코난, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0);
		MonsterType = BATORI_TYPE;

		if (pMasterItem == NULL )
		{
			pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2);
			MonsterType = TEPEZ_TYPE;
			if (pMasterItem == NULL )
			{
				pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
				MonsterType = GDR_TYPE;
				bUpgrade = true;
			}
		}
	}
	else if (m_Type == 1) // 코난, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1);
		MonsterType = BATORI_TYPE;

		if (pMasterItem == NULL)
		{
			pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3);
			MonsterType = TEPEZ_TYPE;
			if (pMasterItem == NULL )
			{
				pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
				MonsterType = GDR_TYPE;
				bUpgrade = true;
			}
		}
	}
	else if (m_Type == 2) // 브리콜라카스, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
		MonsterType = TEPEZ_TYPE;
	}
	else if (m_Type == 3) // 브리콜라카스, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
		MonsterType = TEPEZ_TYPE;
	}
	else if (m_Type == 4) // 카임, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 5) // 카임, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1);
//		if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 10) // 질드레, 비쥬
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8);
		bUpgrade = true;
		MonsterType = GDR_TYPE;
	}
	else if (m_Type == 11) // 질드레, 팬던트
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9);
		bUpgrade = true;
		MonsterType = GDR_TYPE;
	}
	else if (m_Type == 6) // 젬스톤이지롱~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 4);
		MonsterType = BATORI_TYPE;
	}
	else if (m_Type == 7) // 보름달~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 5);
		ItemMineInfo* pItemMineInfo;

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

			Attr_t totalAttr = pSlayer->getTotalAttr(ATTR_BASIC);

			if (totalAttr <= 130 )	// 하드코딩 ㅜ.ㅠ
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(0);
			else if (totalAttr <= 210 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(1);
			else if (totalAttr <= 270 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(2);
			else if (totalAttr <= 300 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(3);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(4);
		}
		else if (pPC->isVampire() )
		{
			Vampire* pVampire = dynamic_cast<Vampire*>(pPC);
			Assert(pVampire != NULL);

			Level_t level = pVampire->getLevel();

			if (level <= 20 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(5);
			else if (level <= 40 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(6);
			else if (level <= 60 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(7);
			else if (level <= 90 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(8);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(9);
		}
		else if (pPC->isOusters() )
		{
			Ousters* pOusters = dynamic_cast<Ousters*>(pPC);
			Assert(pOusters != NULL);

			Level_t level = pOusters->getLevel();

			if (level <= 20 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(10);
			else if (level <= 40 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(11);
			else if (level <= 60 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(12);
			else if (level <= 90 )
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(13);
			else
				pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(14);
		}
		else Assert(false);

		pItem1 = pItemMineInfo->getItem();
		setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE);
	}
	else if (m_Type == 8) // 그믐달~
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 6);

		if (pPC->isSlayer() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(15, 32);
		}
		else if (pPC->isVampire() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(33, 45);
		}
		else if (pPC->isOusters() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(46, 61);
		}

		setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE);
	}
	else if (m_Type == 9) // 빨간색 복주머니
	{
		pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 7);

		if (pPC->isSlayer() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(62, 81);
		}
		else if (pPC->isVampire() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(82, 96);
		}
		else if (pPC->isOusters() )
		{
			pItem1 = g_pItemMineInfoManager->getRandomItem(97, 112);
		}
	}
	else
	{
		// 거래를 위한 NPC의 Property가 잘못되었다. 이런 경우에는
		// 운영팀으로 문의를 하면 바로 처리를 할 수 있다.
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NPC_ERROR ));
		pPlayer->sendPacket(&gcSystemMessage);

		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&response);
		return;
	}
	
	if (pMasterItem == NULL)
	{
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_LAIR_ITEM ));
		pPlayer->sendPacket(&gcSystemMessage);

		GCNPCResponse response;
		response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
		pPlayer->sendPacket(&response);

		return;
	}

	Zone* pZone = pPC->getZone();

//	if (MonsterType != 0 ) // 루팅표를 참조해서 아이템을 만들어오는 경우
	if (pItem1 == NULL )
	{
		QuestItemInfo* pItemInfo = dynamic_cast<QuestItemInfo*>(g_pQuestItemInfoManager->getItemInfo(pMasterItem->getItemType() ));
		Assert(pItemInfo!=NULL);

		///////////////////////////////////////////////////////////////////////////////
		// 가장 난감한 부분
		//   아이템을 랜덤하게 선택해야 한다.
		//   일단은 기본 아이템 하나로 한다.
		//////////////////////////////////////////////////////////////////////////////
		const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(MonsterType);
		TreasureList *pTreasureList = NULL;

		// 종족에 따라서 주는 아이템도 달라야 한다.
		if (pCreature2->isSlayer())
			pTreasureList = pMonsterInfo->getSlayerTreasureList();
		else if (pCreature2->isVampire())
			pTreasureList = pMonsterInfo->getVampireTreasureList();
		else if (pCreature2->isOusters())
			pTreasureList = pMonsterInfo->getOustersTreasureList();

		const list<Treasure*>& treasures = pTreasureList->getTreasures();

		list<Treasure*>::const_iterator itr = treasures.begin();

		ITEM_TEMPLATE it;

		for(; itr != treasures.end(); itr++)
		{
			Treasure* pTreasure = (*itr);

			it.ItemClass = Item::ITEM_CLASS_MAX;
			it.ItemType = 0;

			// QuestItem 마다 다른.. 옵션이 2개 붙을 확률
			it.NextOptionRatio = pItemInfo->getBonusRatio();

			//cout << "TradeLairItem: BonusRatio = " << it.NextOptionRatio << endl;

			if (pTreasure->getRandomItem(&it) )
			{
/*				if (bUpgrade && isPossibleUpgradeItemType(it.ItemClass ) )
				{
					it.ItemType = getUpgradeItemType(it.ItemClass, it.ItemType, 1);
				}
*/
				pItem1 = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType);
				Assert(pItem1 != NULL);
			}
		}

		if (pItem1 == NULL)
		{
			StringStream msg;
			msg << "ActionTradeLairItem: "
				<< (int)it.ItemClass << ", "
				<< (int)it.ItemType << ", "
				<< (int)it.bCreateOption << ", "
				<< getOptionTypeToString(it.OptionType);

			filelog("tradeLairItemBUG.txt", "%s", msg.toString().c_str());

			GCSystemMessage gcSystemMessage;
			gcSystemMessage.setMessage(g_pStringPool->getString(STRID_ITEM_CREATE_ERROR ));
			pPlayer->sendPacket(&gcSystemMessage);

			GCNPCResponse response;
			response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
			pPlayer->sendPacket(&response);

			return;
		}
	}

	TPOINT pt;

	pItem1->setGrade(min(7,ItemGradeManager::Instance().getRandomBeadGrade()));
	pZone->registerObject(pItem1);

	// 만약 inventory에 공간이 있다면, 넣는다. 
	if(pInventory->addItem(pItem1, pt))
	{
		pItem1->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y);

		GCCreateItem gcCreateItem;
/*		gcCreateItem.setObjectID(pItem1->getObjectID());
		gcCreateItem.setItemClass(pItem1->getItemClass());
		gcCreateItem.setItemType(pItem1->getItemType());
		gcCreateItem.setOptionType(pItem1->getOptionTypeList());
		gcCreateItem.setDurability(pItem1->getDurability());
		gcCreateItem.setItemNum(pItem1->getNum());
		gcCreateItem.setInvenX(pt.x);
		gcCreateItem.setInvenY(pt.y);
		gcCreateItem.setGrade(pItem1->getGrade());*/

		makeGCCreateItem(&gcCreateItem, pItem1, pt.x, pt.y);

		pPlayer->sendPacket(&gcCreateItem);

		// ItemTraceLog 를 남긴다
		if (pItem1 != NULL && pItem1->isTraceItem() )
		{
			remainTraceLog(pItem1, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC);
		}

		// 기존의 아이템을 없앤다
		GCDeleteInventoryItem gcDeleteInventoryItem;
		gcDeleteInventoryItem.setObjectID(pMasterItem->getObjectID());
		pPlayer->sendPacket(&gcDeleteInventoryItem);

		// 서버에서 없애준다.
		pInventory->deleteItem(pMasterItem->getObjectID());	// 좌표로 바꿔주면 좋을건데..
		// ItemTraceLog 를 남긴다
		if (pMasterItem != NULL && pMasterItem->isTraceItem() )
		{
			remainTraceLog(pMasterItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC);
		}
		pMasterItem->destroy();
		SAFE_DELETE(pMasterItem);

		// 사용자에게 성공 메시지 출력
//		StringStream message;
//		message << "성공적으로 교환되었습니다";
		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TRADE_SUCCESS ));
		pPlayer->sendPacket(&gcSystemMessage);
	}
	else
	{
//		StringStream buf;
//		buf << "인벤토리에 공간이 부족합니다";

		GCSystemMessage gcSystemMessage;
		gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NOT_ENOUGH_INVENTORY_SPACE ));
		pPlayer->sendPacket(&gcSystemMessage);
	}

	GCNPCResponse response;
	response.setCode(NPC_RESPONSE_QUIT_DIALOGUE);
	pPlayer->sendPacket(&response);

	__END_CATCH
}