Exemplo n.º 1
0
BedItem* Tile::getBedItem() const
{
	if(!hasFlag(TILESTATE_BED))
		return NULL;

	if(ground && ground->getBed())
		return ground->getBed();

	if(const TileItemVector* items = getItemList())
	{
		for(ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it)
		{
			if((*it)->getBed())
				return (*it)->getBed();
		}
	}

	return NULL;
}
Exemplo n.º 2
0
Item* Tile::getUseItem() const
{
	const TileItemVector* items = getItemList();
	if (!items || items->size() == 0) {
		return ground;
	}

	for (Item* item : boost::adaptors::reverse(*items)) {
		if (Item::items[item->getID()].forceUse) {
			return item;
		}
	}

	Item* item = items->getTopDownItem();
	if (!item) {
		item = items->getTopTopItem();
	}
	return item;
}
Exemplo n.º 3
0
MagicField* Tile::getFieldItem() const
{
	if (!hasFlag(TILESTATE_MAGICFIELD)) {
		return nullptr;
	}

	if (ground && ground->getMagicField()) {
		return ground->getMagicField();
	}

	if (const TileItemVector* items = getItemList()) {
		for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) {
			if ((*it)->getMagicField()) {
				return (*it)->getMagicField();
			}
		}
	}
	return nullptr;
}
Exemplo n.º 4
0
TrashHolder* Tile::getTrashHolder() const
{
	if (!hasFlag(TILESTATE_TRASHHOLDER)) {
		return nullptr;
	}

	if (ground && ground->getTrashHolder()) {
		return ground->getTrashHolder();
	}

	if (const TileItemVector* items = getItemList()) {
		for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) {
			if ((*it)->getTrashHolder()) {
				return (*it)->getTrashHolder();
			}
		}
	}
	return nullptr;
}
Exemplo n.º 5
0
Item* Tile::getItemByTopOrder(uint32_t topOrder)
{
	//topOrder:
	//1: borders
	//2: ladders, signs, splashes
	//3: doors etc
	//4: creatures

	if(TileItemVector* items = getItemList()){
		ItemVector::reverse_iterator itEnd = ItemVector::reverse_iterator(items->getBeginTopItem());
		for(ItemVector::reverse_iterator it = ItemVector::reverse_iterator(items->getEndTopItem()); it != itEnd; ++it){
			if(Item::items[(*it)->getID()].alwaysOnTopOrder == (int32_t)topOrder){
				return (*it);
			}
		}
	}

	return NULL;
}
Exemplo n.º 6
0
Mailbox* Tile::getMailbox() const
{
	if (!hasFlag(TILESTATE_MAILBOX)) {
		return NULL;
	}

	if (ground && ground->getMailbox()) {
		return ground->getMailbox();
	}

	if (const TileItemVector* items = getItemList()) {
		for (ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) {
			if ((*it)->getMailbox()) {
				return (*it)->getMailbox();
			}
		}
	}

	return NULL;
}
Exemplo n.º 7
0
bool Tile::hasProperty(enum ITEMPROPERTY prop, bool checkSolidForItems /* =false */) const
{
	if (ground && ground->hasProperty(prop))
	{
		return true;
	}

	if (const TileItemVector* items = getItemList())
	{
		for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
		{
			if ((*it)->hasProperty(prop) || (prop == BLOCKSOLID && checkSolidForItems && (*it)->isSolidForItems()))
			{
				return true;
			}
		}
	}

	return false;
}
Exemplo n.º 8
0
bool Tile::hasProperty(Item* exclude, enum ITEMPROPERTY prop) const
{
	assert(exclude);

	if (ground && exclude != ground && ground->hasProperty(prop)) {
		return true;
	}

	if (const TileItemVector* items = getItemList()) {
		for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it) {
			Item* item = *it;

			if (item != exclude && item->hasProperty(prop)) {
				return true;
			}
		}
	}

	return false;
}
Exemplo n.º 9
0
Teleport* Tile::getTeleportItem() const
{
	if (!hasFlag(TILESTATE_TELEPORT))
	{
		return NULL;
	}

	if (const TileItemVector* items = getItemList())
	{
		for (ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it)
		{
			if ((*it)->getTeleport())
			{
				return (*it)->getTeleport();
			}
		}
	}

	return NULL;
}
Exemplo n.º 10
0
uint32_t Tile::__getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const
{
	uint32_t count = 0;

	if (ground && ground->getID() == itemId) {
		count += Item::countByType(ground, subType);
	}

	const TileItemVector* items = getItemList();

	if (items) {
		for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) {
			Item* item = (*it);

			if (item->getID() == itemId) {
				count += Item::countByType(item, subType);
			}
		}
	}

	return count;
}
Exemplo n.º 11
0
// define an incompatibility between parameters (if one is set, any of the others can be set)
bool ParameterManager::defineIncompatibility(const char *strParameters, bool bOneRequired) {

	Incompatibility incompatibility;

	// get the list of incompatible parameters
	incompatibility.vParameters = getItemList(strParameters);
	if ((incompatibility.vParameters == NULL) || (incompatibility.vParameters->size() < 2)) {
		return false;
	}

	// make sure all the parameters exist
	for(VString::iterator it = incompatibility.vParameters->begin() ; it != incompatibility.vParameters->end() ; ++it) {
		if (m_mParameter.find(*it) == m_mParameter.end()) {
			return false;
		}
	}
	
	incompatibility.bOneRequired = bOneRequired;
	m_vIncompatibility.push_back(incompatibility);

	return true;
}
Exemplo n.º 12
0
Thing* Tile::__getThing(uint32_t index) const
{
	if (ground) {
		if (index == 0) {
			return ground;
		}

		--index;
	}

	const TileItemVector* items = getItemList();

	if (items) {
		uint32_t topItemSize = items->getTopItemCount();

		if (index < topItemSize) {
			return items->at(items->downItemCount + index);
		}

		index -= topItemSize;
	}

	if (const CreatureVector* creatures = getCreatures()) {
		if (index < (uint32_t)creatures->size()) {
			return creatures->at(index);
		}

		index -= (uint32_t)creatures->size();
	}

	if (items) {
		if (index < items->getDownItemCount()) {
			return items->at(index);
		}
	}

	return NULL;
}
Exemplo n.º 13
0
int32_t Tile::getNewCreatureStackpos(const Player* player)
{
	int32_t n = -1;

	if (ground) {
		++n;
	}

	const TileItemVector* items = getItemList();

	if (items) {
		n += items->getTopItemCount();
	}

	if (const CreatureVector* creatures = getCreatures()) {
		for (CreatureVector::const_reverse_iterator cit = creatures->rbegin(); cit != creatures->rend(); ++cit) {
			if (!(*cit)->isInGhostMode() || player->isAccessPlayer()) {
				++n;
			}
		}
	}

	return n + 1;
}
Exemplo n.º 14
0
void Tile::__removeThing(Thing* thing, uint32_t count)
{
	Creature* creature = thing->getCreature();
	if(creature)
	{
		if(CreatureVector* creatures = getCreatures())
		{
			CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing);
			if(it == creatures->end())
			{
#ifdef __DEBUG_MOVESYS__
				std::clog << "[Failure - Tile::__removeThing] creature not found" << std::endl;
#endif
				return/* RET_NOTPOSSIBLE*/;
			}

			g_game.clearSpectatorCache();
			creatures->erase(it);
			--thingCount;
		}
#ifdef __DEBUG_MOVESYS__
		else
			std::clog << "[Failure - Tile::__removeThing] creature not found" << std::endl;
#endif

		return;
	}

	Item* item = thing->getItem();
	if(!item)
	{
#ifdef __DEBUG_MOVESYS__
		std::clog << "[Failure - Tile::__removeThing] item == NULL" << std::endl;
#endif
		return/* RET_NOTPOSSIBLE*/;
	}

	int32_t index = __getIndexOfThing(item);
	if(index == -1)
	{
#ifdef __DEBUG_MOVESYS__
		std::clog << "[Failure - Tile::__removeThing] index == -1" << std::endl;
#endif
		return/* RET_NOTPOSSIBLE*/;
	}

	if(item == ground)
	{
		const SpectatorVec& list = g_game.getSpectators(pos);
		std::vector<int32_t> oldStackposVector;

		Player* tmpPlayer = NULL;
		for(SpectatorVec::const_iterator it = list.begin(); it != list.end(); ++it)
		{
			if((tmpPlayer = (*it)->getPlayer()))
				oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, ground));
		}

#ifdef __GROUND_CACHE__
		std::map<Item*, int32_t>::iterator it = g_game.grounds.find(ground);
		bool erase = it == g_game.grounds.end();
		if(!erase)
		{
			it->second--;
			erase = it->second < 1;
			if(erase)
				g_game.grounds.erase(it);
		}

		if(erase)
		{
#endif
			ground->setParent(NULL);
			g_game.freeThing(ground);
#ifdef __GROUND_CACHE__
		}
#endif

		ground = NULL;
		--thingCount;

		onRemoveTileItem(list, oldStackposVector, item);
		return/* RET_NOERROR*/;
	}

	TileItemVector* items = getItemList();
	if(!items)
		return;

	if(item->isAlwaysOnTop())
	{
		ItemVector::iterator it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item);
		if(it != items->end())
		{
			const SpectatorVec& list = g_game.getSpectators(pos);
			std::vector<int32_t> oldStackposVector;

			Player* tmpPlayer = NULL;
			for(SpectatorVec::const_iterator iit = list.begin(); iit != list.end(); ++iit)
			{
				if((tmpPlayer = (*iit)->getPlayer()))
					oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, item));
			}

			item->setParent(NULL);
			items->erase(it);

			--thingCount;
			onRemoveTileItem(list, oldStackposVector, item);
			return/* RET_NOERROR*/;
		}
	}
	else
	{
		ItemVector::iterator it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item);
		if(it != items->end())
		{
			if(item->isStackable() && count != item->getItemCount())
			{
				uint8_t newCount = (uint8_t)std::max((int32_t)0, (int32_t)(item->getItemCount() - count));
				updateTileFlags(item, true);

				item->setItemCount(newCount);
				updateTileFlags(item, false);

				const ItemType& it = Item::items[item->getID()];
				onUpdateTileItem(item, it, item, it);
			}
			else
			{
				const SpectatorVec& list = g_game.getSpectators(pos);
				std::vector<int32_t> oldStackposVector;

				Player* tmpPlayer = NULL;
				for(SpectatorVec::const_iterator iit = list.begin(); iit != list.end(); ++iit)
				{
					if((tmpPlayer = (*iit)->getPlayer()))
						oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, item));
				}

				item->setParent(NULL);
				items->erase(it);

				--items->downItemCount;
				--thingCount;
				onRemoveTileItem(list, oldStackposVector, item);
			}

			return/* RET_NOERROR*/;
		}
	}
#ifdef __DEBUG_MOVESYS__

	std::clog << "[Failure - Tile::__removeThing] thing not found" << std::endl;
#endif
}
Exemplo n.º 15
0
void Tile::__addThing(int32_t index, Thing* thing)
{
	Creature* creature = thing->getCreature();

	if (creature)
	{
		g_game.clearSpectatorCache();
		creature->setParent(this);
		CreatureVector* creatures = makeCreatures();
		creatures->insert(creatures->begin(), creature);
		++thingCount;
	}
	else
	{
		Item* item = thing->getItem();

		if (!item)
		{
#ifdef __DEBUG__MOVESYS__
			std::cout << "Failure: [Tile::__addThing] item == NULL" << std::endl;
			DEBUG_REPORT
#endif
			return /*RET_NOTPOSSIBLE*/;
		}

		TileItemVector* items = getItemList();

		if (items && items->size() > 0xFFFF)
		{
			return /*RET_NOTPOSSIBLE*/;
		}

		item->setParent(this);

		if (item->isGroundTile())
		{
			if (!ground)
			{
				ground = item;
				++thingCount;
				onAddTileItem(item);
			}
			else
			{
				const ItemType& oldType = Item::items[ground->getID()];
				const ItemType& newType = Item::items[item->getID()];
				int32_t oldGroundIndex = __getIndexOfThing(ground);
				Item* oldGround = ground;
				ground->setParent(NULL);
				g_game.FreeThing(ground);
				ground = item;
				updateTileFlags(oldGround, true);
				updateTileFlags(item, false);
				onUpdateTileItem(oldGround, oldType, item, newType);
				postRemoveNotification(oldGround, NULL, oldGroundIndex, true);
			}
		}
		else if (item->isAlwaysOnTop())
		{
			if (item->isSplash())
			{
				//remove old splash if exists
				if (items)
				{
					for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
					{
						if ((*it)->isSplash())
						{
							int32_t oldSplashIndex = __getIndexOfThing(*it);
							Item* oldSplash = *it;
							__removeThing(oldSplash, 1);
							oldSplash->setParent(NULL);
							g_game.FreeThing(oldSplash);
							postRemoveNotification(oldSplash, NULL, oldSplashIndex, true);
							break;
						}
					}
				}
			}

			bool isInserted = false;

			if (items)
			{
				for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
				{
					//Note: this is different from internalAddThing
					if (Item::items[item->getID()].alwaysOnTopOrder <= Item::items[(*it)->getID()].alwaysOnTopOrder)
					{
						items->insert(it, item);
						++thingCount;
						isInserted = true;
						break;
					}
				}
			}
			else
			{
				items = makeItemList();
			}

			if (!isInserted)
			{
				items->push_back(item);
				++thingCount;
			}

			onAddTileItem(item);
		}
		else
		{
			if (item->isMagicField())
			{
				//remove old field item if exists
				if (items)
				{
					MagicField* oldField = NULL;

					for (ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it)
					{
						if ((oldField = (*it)->getMagicField()))
						{
							if (oldField->isReplaceable())
							{
								int32_t oldFieldIndex = __getIndexOfThing(*it);
								__removeThing(oldField, 1);
								oldField->setParent(NULL);
								g_game.FreeThing(oldField);
								postRemoveNotification(oldField, NULL, oldFieldIndex, true);
								break;
							}
							else
							{
								//This magic field cannot be replaced.
								item->setParent(NULL);
								g_game.FreeThing(item);
								return;
							}
						}
					}
				}
			}

			items = makeItemList();
			items->insert(items->getBeginDownItem(), item);
			++items->downItemCount;
			++thingCount;
			onAddTileItem(item);
		}
	}
Exemplo n.º 16
0
BTSpecialOperation *BTEditor::editSpecialOperation(BTDisplay &d, BTSpecialOperation *special)
{
 BTDisplay::selectItem cmds[BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS];
 for (int i = 0; i < BT_CONDITIONALCOMMANDS; ++i)
 {
  cmds[i].name = std::string("if ") + conditionalCommands[i];
  cmds[i].value = i;
 }
 for (int i = 0; i < BT_SPECIALCOMMANDS; ++i)
 {
  cmds[i + BT_CONDITIONALCOMMANDS].name = specialCommands[i];
  cmds[i + BT_CONDITIONALCOMMANDS].value = i + BT_CONDITIONALCOMMANDS;
 }
 std::sort(cmds, cmds + BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS);
 int start(0);
 int current(0);
 {
  BTSpecialConditional *specialCond = dynamic_cast<BTSpecialConditional*>(special);
  if (NULL != specialCond)
  {
   for (int i = 0; i < BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS; i++)
   {
    if (cmds[i].value == specialCond->getType())
    {
     current = i;
     break;
    }
   }
  }
  BTSpecialCommand *specialCom = dynamic_cast<BTSpecialCommand*>(special);
  if (NULL != specialCom)
  {
   for (int i = 0; i < BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS; i++)
   {
    if (cmds[i].value == specialCom->getType() + BT_CONDITIONALCOMMANDS)
    {
     current = i;
     break;
    }
   }
  }
 }
 int original = current;
 d.addSelection(cmds, BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS, start, current);
 int key = d.process();
 d.clearText();
 if (key == 27)
  return NULL;
 std::string text;
 int number[3] = {0, 0, 0};
 int count = 0;
 const char *cmd = NULL;
 if (cmds[current].value < BT_CONDITIONALCOMMANDS)
 {
  cmd = conditionalCommands[cmds[current].value];
  if (original == current)
  {
   BTSpecialConditional *specialCond = dynamic_cast<BTSpecialConditional*>(special);
   if (NULL != specialCond)
   {
    for (int i = 0; i < specialCond->getArgumentCount(); i++)
    {
     number[i] = specialCond->getNumber(i);
    }
    text = specialCond->getText();
   }
  }
 }
 else
 {
  cmd = specialCommands[cmds[current].value - BT_CONDITIONALCOMMANDS];
  if (original == current)
  {
   BTSpecialCommand *specialCom = dynamic_cast<BTSpecialCommand*>(special);
   if (NULL != specialCom)
   {
    for (int i = 0; i < 3; i++)
    {
     number[i] = specialCom->getNumber(i);
    }
    text = specialCom->getText();
   }
  }
 }
 const char *dollarSign;
 std::string newMap;
 int facingDir = -1;
 while (dollarSign = strchr(cmd, '$'))
 {
  switch (dollarSign[1])
  {
   case 'S':
   {
    int len = levelMap->getNumOfSpecials();
    BTDisplay::selectItem list[len];
    for (int i = 0; i < len; ++i)
    {
     list[i].name = levelMap->getSpecial(i)->getName();
    }
    int specialStart(0);
    d.addSelection(list, len, specialStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'I':
   {
    BTFactory<BTItem> &itemList = getItemList();
    BTDisplay::selectItem items[itemList.size()];
    for (size_t i = 0; i < itemList.size(); ++i)
     items[i].name = itemList[i].getName();
    int itemStart(0);
    d.addSelection(items, itemList.size(), itemStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'A':
   case 'M':
   {
    BTFactory<BTMonster> &monsterList = getMonsterList();
    BTDisplay::selectItem monsters[monsterList.size()];
    for (size_t i = 0; i < monsterList.size(); ++i)
     monsters[i].name = monsterList[i].getName();
    int monsterStart(0);
    d.addSelection(monsters, monsterList.size(), monsterStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'X':
   {
    BTFactory<BTSpell, BTSpell1> &spellList = getSpellList();
    BTDisplay::selectItem spells[spellList.size()];
    for (size_t i = 0; i < spellList.size(); ++i)
     spells[i].name = spellList[i].getName();
    int spellStart(0);
    d.addSelection(spells, spellList.size(), spellStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'L':
   {
    if ((newMap.empty()) || (0 != PHYSFS_exists(newMap.c_str())))
    {
     int origX = xPos;
     int origY = yPos;
     int origFacing = facing;
     bool toggle = false;
     if ((!newMap.empty()) && (newMap != levelMap->getFilename()))
     {
      toggleMap();
      loadMap(newMap.c_str());
      toggle = true;
     }
     BTDisplayConfig *oldConfig = d.getConfig();
     BTDisplayConfig config;
     XMLSerializer parser;
     config.serialize(&parser);
     parser.parse(BTDisplay::applyDisplayDir("data/mapedit.xml").c_str(), true);
     d.setConfig(&config);
     xPos = number[count] % levelMap->getXSize(); yPos = levelMap->getYSize() - 1 - (number[count + 1] % levelMap->getYSize()); facing = number[count + 2];
     p3dConfig = d.setWallGraphics(levelMap->getType());
     unsigned char key = ' ';
     while (key != '\r')
     {
      if (levelMap->getSquare(yPos, xPos).getSpecial() > -1)
       d.drawLabel("main", levelMap->getSpecial(levelMap->getSquare(yPos, xPos).getSpecial())->getName());
      else
       d.drawLabel("main", "");
      d.drawView();
      key = d.readChar();
      switch (key)
      {
       case BTKEY_UP:
        if (yPos > 0)
         yPos--;
        else
         yPos = getYSize() - 1;
        break;
       case BTKEY_LEFT:
        if (xPos > 0)
         xPos--;
        else
         xPos = getXSize() - 1;
        break;
       case BTKEY_DOWN:
        if (yPos < getYSize() - 1)
         yPos++;
        else
         yPos = 0;
        break;
       case BTKEY_RIGHT:
        if (xPos < getXSize() - 1)
         xPos++;
        else
         xPos = 0;
        break;
       case BTKEY_PGDN:
        if (facing < 3)
         facing++;
        else
         facing = 0;
        break;
       case BTKEY_END:
        if (facing > 0)
         facing--;
        else
         facing = 3;
        break;
       default:
        break;
      }
     }
     number[count++] = xPos;
     number[count++] = levelMap->getYSize() - 1 - yPos;
     facingDir = facing;
     d.clearText();
     d.setConfig(oldConfig);
     if (toggle)
     {
      toggleMap();
      p3dConfig = d.setWallGraphics(levelMap->getType());
     }
     xPos = origX;
     yPos = origY;
     facing = origFacing;
     break;
    }
    // Fall through to $O processing if map file does not exist.
   }
   case 'O':
   {
    std::string val;
    if (number[count] != 0)
    {
     char convert[30];
     sprintf(convert, "%d", number[count]);
     val = convert;
    }
    d.addReadString("X>", 100, val);
    key = d.process();
    d.clearText();
    if (27 == key)
     return NULL;
    number[count++] = atol(val.c_str());
    val = "";
    if (number[count] != 0)
    {
     char convert[30];
     sprintf(convert, "%d", number[count]);
     val = convert;
    }
    d.addReadString("Y>", 100, val);
    key = d.process();
    d.clearText();
    if (27 == key)
     return NULL;
    number[count++] = atol(val.c_str());
    break;
   }
   case 'T':
   {
    BTDisplay::selectItem damage[BT_MONSTEREXTRADAMAGE];
    for (int i = 0; i < BT_MONSTEREXTRADAMAGE; ++i)
     damage[i].name = extraDamage[i];
    int damageStart(0);
    d.addSelection(damage, BT_MONSTEREXTRADAMAGE, damageStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'C':
   {
    BTJobList &jobList = getJobList();
    BTDisplay::selectItem jobs[jobList.size()];
    for (size_t i = 0; i < jobList.size(); ++i)
     jobs[i].name = jobList[i]->name;
    int jobStart(0);
    d.addSelection(jobs, jobList.size(), jobStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'R':
   {
    BTRaceList &raceList = getRaceList();
    BTDisplay::selectItem races[raceList.size()];
    for (size_t i = 0; i < raceList.size(); ++i)
     races[i].name = raceList[i]->name;
    int raceStart(0);
    d.addSelection(races, raceList.size(), raceStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'D':
   {
    if (facingDir != -1)
    {
     number[count++] = facingDir;
    }
    else
    {
     BTDisplay::selectItem dir[BT_DIRECTIONS];
     for (int i = 0; i < BT_DIRECTIONS; ++i)
      dir[i].name = directions[i];
     int dirStart(0);
     d.addSelection(dir, BT_DIRECTIONS, dirStart, number[count]);
     int key = d.process();
     d.clearText();
     if (key == 27)
      return NULL;
     count++;
    }
    break;
   }
   case '#':
   case 'G':
   case 'F':
   case '!':
   case 'J':
   {
    std::string val;
    if (number[count] != 0)
    {
     char convert[30];
     sprintf(convert, "%d", number[count]);
     val = convert;
    }
    d.addReadString("Number>", 100, val);
    key = d.process();
    d.clearText();
    if (27 == key)
     return NULL;
    number[count++] = atol(val.c_str());
    break;
   }
   case 'P':
   {
    BTDisplayConfig *oldConfig = d.getConfig();
    BTDisplayConfig config;
    XMLSerializer parser;
    config.serialize(&parser);
    parser.parse(BTDisplay::applyDisplayDir("data/pictureselect.xml").c_str(), true);
    d.setConfig(&config);
    d.clearText();
    d.addText("Select Image");
    int val(number[count]);
    d.addSelectImage(val);
    key = d.process();
    d.clearText();
    d.clearImage();
    d.setConfig(oldConfig);
    if (27 == key)
     return NULL;
    number[count++] = val;
    break;
   }
   case 'E':
   {
    BTDisplay::selectItem effects[BT_SPELLTYPES_FULL];
    for (int i = 0; i < BT_SPELLTYPES_FULL; ++i)
     effects[i].name = spellTypes[i];
    int effectStart(0);
    d.addSelection(effects, BT_SPELLTYPES_FULL, effectStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case 'N':
   {
    char **files = PHYSFS_enumerateFiles("");
    char **i;
    int count(1);

    for (i = files; *i != NULL; i++)
    {
     if (checkSkipFiles(*i))
      continue;
     int len = strlen(*i);
     if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0))
     {
      char tmp[len + 1];
      strcpy(tmp, (*i));
      strcpy(tmp + len - 3, "xml");
      if (0 == PHYSFS_exists(tmp))
      {
       count++;
      }
     }
     else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0))
     {
      count++;
     }
    }
    BTDisplay::selectItem *list = new BTDisplay::selectItem[count];
    int current = 0;
    for (i = files; *i != NULL; i++)
    {
     if (checkSkipFiles(*i))
      continue;
     int len = strlen(*i);
     if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0))
     {
      char tmp[len + 1];
      strcpy(tmp, (*i));
      strcpy(tmp + len - 3, "xml");
      if (0 == PHYSFS_exists(tmp))
      {
       list[current].name = *i;
       current++;
      }
     }
     else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0))
     {
      list[current].name = *i;
      current++;
     }
    }
    list[current].name = "<New Map>";
    PHYSFS_freeList(files);
    int start(0);
    int select(0);
    d.clearElements();
    d.addSelection(list, count, start, select);
    unsigned int key = d.process();
    d.clearText();
    if (27 == key)
     return NULL;
    else if (count - 1 != select)
     text = list[select].name;
    else
    {
     d.addReadString(">", 100, text);
     key = d.process();
     d.clearText();
     if (27 == key)
      return NULL;
    }
    newMap = text;
    break;
   }
   case 'K':
   {
    BTSkillList &skillList = getSkillList();
    BTDisplay::selectItem items[skillList.size()];
    for (size_t i = 0; i < skillList.size(); ++i)
     items[i].name = skillList[i]->name;
    int itemStart(0);
    d.addSelection(items, skillList.size(), itemStart, number[count]);
    int key = d.process();
    d.clearText();
    if (key == 27)
     return NULL;
    count++;
    break;
   }
   case '$':
   default:
    d.addReadString(">", 100, text);
    key = d.process();
    d.clearText();
    if (27 == key)
     return NULL;
    break;
  }
  cmd = dollarSign + 2;
 }
 if (cmds[current].value < BT_CONDITIONALCOMMANDS)
 {
  BTSpecialConditional *opNew = new BTSpecialConditional(cmds[current].value, text.c_str());
  for (int i = 0; i < count; ++i)
   opNew->addNumber(number[i]);
  BTSpecialConditional *opOld = dynamic_cast<BTSpecialConditional*>(special);
  if (opOld)
  {
   opNew->getThenClause()->moveFrom(opOld->getThenClause());
   opNew->getElseClause()->moveFrom(opOld->getElseClause());
  }
  return opNew;
 }
 else
 {
  BTSpecialCommand *opNew = new BTSpecialCommand(cmds[current].value - BT_CONDITIONALCOMMANDS);
  opNew->setText(text);
  for (int i = 0; i < count; ++i)
   opNew->setNumber(i, number[i]);
  return opNew;
 }
}
Exemplo n.º 17
0
void BTEditor::edit(BTDisplay &d)
{
 char **files = PHYSFS_enumerateFiles("");
 char **i;
 int count(4);

 d.setPsuedo3DConfig(&getPsuedo3DConfigList());
 d.setWallGraphics(0);
 for (i = files; *i != NULL; i++)
 {
  if (checkSkipFiles(*i))
   continue;
  int len = strlen(*i);
  if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0))
  {
   char tmp[len + 1];
   strcpy(tmp, (*i));
   strcpy(tmp + len - 3, "xml");
   if (0 == PHYSFS_exists(tmp))
   {
    count++;
   }
  }
  else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0))
  {
   count++;
  }
 }
 BTDisplay::selectItem *list = new BTDisplay::selectItem[count];
 list[0].name = module->item;
 list[1].name = module->spell;
 list[2].name = module->monster;
 int current = 3;
 for (i = files; *i != NULL; i++)
 {
  if (checkSkipFiles(*i))
   continue;
  int len = strlen(*i);
  if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0))
  {
   char tmp[len + 1];
   strcpy(tmp, (*i));
   strcpy(tmp + len - 3, "xml");
   if (0 == PHYSFS_exists(tmp))
   {
    list[current].name = *i;
    current++;
   }
  }
  else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0))
  {
   list[current].name = *i;
   current++;
  }
 }
 list[current].name = "<New Map>";
 PHYSFS_freeList(files);
 int start(0);
 int select(0);
 d.clearElements();
 d.addSelection(list, count, start, select);
 unsigned int key = d.process();
 d.clearText();
 if (key == 13)
 {
  if (list[select].name == module->monster)
  {
   BTFactory<BTMonster> &monsterList = getMonsterList();
   BTMonsterListCompare compare;
   BTMonsterEditor monsterEditor;
   int monster = 0;
   while (-1 != (monster = monsterEditor.editFactoryList<BTMonster>(d, monsterList, compare, "<New Monster>")))
   {
    ObjectSerializer serial;
    monsterList[monster].serialize(&serial);
    monsterEditor.edit(d, serial);
   }
   monsterList.save(module->monster);
  }
  else if (list[select].name == module->spell)
  {
   BTFactory<BTSpell, BTSpell1> &spellList = getSpellList();
   BTSpellListCompare compare;
   int spell = 0;
   BTSpellEditor spellEditor;
   while (-1 != (spell = spellEditor.editFactoryList<BTSpell, BTSpell1>(d, spellList, compare, "<New Spell>")))
   {
    ObjectSerializer serial;
    spellList[spell].serialize(&serial);
    spellEditor.edit(d, serial);
   }
   spellList.save(module->spell);
  }
  else if (list[select].name == module->item)
  {
   BTFactory<BTItem> &itemList = getItemList();
   BTItemListCompare compare;
   int item = 0;
   BTItemEditor itemEditor;
   while (-1 != (item = itemEditor.editFactoryList<BTItem>(d, itemList, compare, "<New Item>")))
   {
    ObjectSerializer serial;
    itemList[item].serialize(&serial);
    itemEditor.edit(d, serial);
   }
   itemList.save(module->item);
  }
  else if (count - 1 == select)
  {
   d.clearText();
   d.drawText("Filename:");
   std::string name = d.readString("", 60, "");
   d.clearText();
   editMap(d, name.c_str());
  }
  else
   editMap(d, list[select].name.c_str());
 }
 d.setPsuedo3DConfig(NULL);
}
Exemplo n.º 18
0
void	LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index )
{
	S32 cur_index = getHighlightedItemInx();
	if (cur_index != target_index)
	{
		bool is_mouse_over_name_cell = false;

		S32 mouse_x, mouse_y;
		LLUI::getMousePositionLocal(this, &mouse_x, &mouse_y);

		S32 column_index = getColumnIndexFromOffset(mouse_x);
		LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y);
		if (hit_item && column_index == mNameColumnIndex)
		{
			// Get the name cell which is currently under the mouse pointer.
			LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
			if (hit_cell)
			{
				is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y);
			}
		}

		// If the tool tip is visible and the mouse is over the currently highlighted item's name cell,
		// we should not reset the highlighted item index i.e. set mHighlightedItem = -1
		// and should not increase the width of the text inside the cell because it may
		// overlap the tool tip icon.
		if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell)
			return;

		if(0 <= cur_index && cur_index < (S32)getItemList().size())
		{
			LLScrollListItem* item = getItemList()[cur_index];
			if (item)
			{
				LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
				if (cell)
					cell->setTextWidth(cell->getTextWidth() + info_icon_size);
			}
			else
			{
				llwarns << "highlighted name list item is NULL" << llendl;
			}
		}
		if(target_index != -1)
		{
			LLScrollListItem* item = getItemList()[target_index];
			LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
			if (item)
			{
				if (cell)
					cell->setTextWidth(cell->getTextWidth() - info_icon_size);
			}
			else
			{
				llwarns << "target name item is NULL" << llendl;
			}
		}
	}

	LLScrollListCtrl::mouseOverHighlightNthItem(target_index);
}
Exemplo n.º 19
0
		++thingCount;
		return;
	}

	Item* item = thing->getItem();
	if(!item)
	{
#ifdef __DEBUG_MOVESYS__
		std::cout << "[Failure - Tile::__addThing] item == NULL" << std::endl;
		DEBUG_REPORT
#endif
		return/* RET_NOTPOSSIBLE*/;
	}

	TileItemVector* items = getItemList();
	if(items && items->size() >= 0xFFFF)
		return/* RET_NOTPOSSIBLE*/;

	if(g_config.getBool(ConfigManager::STORE_TRASH) && !hasFlag(TILESTATE_TRASHED))
	{
		g_game.addTrash(pos);
		setFlag(TILESTATE_TRASHED);
	}

	item->setParent(this);
	if(item->isGroundTile())
	{
		if(ground)
		{
			const ItemType& oldType = Item::items[ground->getID()];
Exemplo n.º 20
0
void Tile::replaceThing(uint32_t index, Thing* thing)
{
	int32_t pos = index;

	Item* item = thing->getItem();
	if (item == nullptr) {
		return /*RETURNVALUE_NOTPOSSIBLE*/;
	}

	Item* oldItem = nullptr;
	bool isInserted = false;

	if (ground) {
		if (pos == 0) {
			oldItem = ground;
			ground = item;
			isInserted = true;
		}

		--pos;
	}

	TileItemVector* items = getItemList();
	if (items && !isInserted) {
		int32_t topItemSize = getTopItemCount();
		if (pos < topItemSize) {
			ItemVector::iterator it = items->getBeginTopItem();
			it += pos;

			oldItem = (*it);
			it = items->erase(it);
			items->insert(it, item);
			isInserted = true;
		}

		pos -= topItemSize;
	}

	CreatureVector* creatures = getCreatures();
	if (creatures) {
		if (!isInserted && pos < static_cast<int32_t>(creatures->size())) {
			return /*RETURNVALUE_NOTPOSSIBLE*/;
		}

		pos -= static_cast<uint32_t>(creatures->size());
	}

	if (items && !isInserted) {
		int32_t downItemSize = getDownItemCount();
		if (pos < downItemSize) {
			ItemVector::iterator it = items->getBeginDownItem() + pos;
			oldItem = *it;
			it = items->erase(it);
			items->insert(it, item);
			isInserted = true;
		}
	}

	if (isInserted) {
		item->setParent(this);

		resetTileFlags(oldItem);
		setTileFlags(item);
		const ItemType& oldType = Item::items[oldItem->getID()];
		const ItemType& newType = Item::items[item->getID()];
		onUpdateTileItem(oldItem, oldType, item, newType);

		oldItem->setParent(nullptr);
		return /*RETURNVALUE_NOERROR*/;
	}
}
Exemplo n.º 21
0
ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags, Creature*) const
{
	if (const Creature* creature = thing.getCreature()) {
		if (hasBitSet(FLAG_NOLIMIT, flags)) {
			return RETURNVALUE_NOERROR;
		}

		if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

		if (ground == nullptr) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

		if (const Monster* monster = creature->getMonster()) {
			if (hasFlag(TILESTATE_PROTECTIONZONE | TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) {
				return RETURNVALUE_NOTPOSSIBLE;
			}

			const CreatureVector* creatures = getCreatures();
			if (monster->canPushCreatures() && !monster->isSummon()) {
				if (creatures) {
					for (Creature* tileCreature : *creatures) {
						if (tileCreature->getPlayer() && tileCreature->getPlayer()->isInGhostMode()) {
							continue;
						}

						const Monster* creatureMonster = tileCreature->getMonster();
						if (!creatureMonster || !tileCreature->isPushable() ||
						        (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) {
							return RETURNVALUE_NOTPOSSIBLE;
						}
					}
				}
			} else if (creatures && !creatures->empty()) {
				for (const Creature* tileCreature : *creatures) {
					if (!tileCreature->isInGhostMode()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}
				}
			}

			if (hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID)) {
				return RETURNVALUE_NOTPOSSIBLE;
			}

			if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH)) {
				return RETURNVALUE_NOTPOSSIBLE;
			}

			if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH))) {
				if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))) {
					return RETURNVALUE_NOTPOSSIBLE;
				}
			}

			MagicField* field = getFieldItem();
			if (field && !field->isBlocking()) {
				CombatType_t combatType = field->getCombatType();

				//There is 3 options for a monster to enter a magic field
				//1) Monster is immune
				if (!monster->isImmune(combatType)) {
					//1) Monster is "strong" enough to handle the damage
					//2) Monster is already afflicated by this type of condition
					if (hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags)) {
						if (!(monster->canPushItems() || monster->hasCondition(Combat::DamageToConditionType(combatType)))) {
							return RETURNVALUE_NOTPOSSIBLE;
						}
					} else {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}

			return RETURNVALUE_NOERROR;
		}

		const CreatureVector* creatures = getCreatures();
		if (const Player* player = creature->getPlayer()) {
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags) && !player->isAccessPlayer()) {
				for (const Creature* tileCreature : *creatures) {
					if (!player->canWalkthrough(tileCreature)) {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}

			if (player->getParent() == nullptr && hasFlag(TILESTATE_NOLOGOUT)) {
				//player is trying to login to a "no logout" tile
				return RETURNVALUE_NOTPOSSIBLE;
			}

			const Tile* playerTile = player->getTile();
			if (playerTile && player->isPzLocked()) {
				if (!playerTile->hasFlag(TILESTATE_PVPZONE)) {
					//player is trying to enter a pvp zone while being pz-locked
					if (hasFlag(TILESTATE_PVPZONE)) {
						return RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE;
					}
				} else if (!hasFlag(TILESTATE_PVPZONE)) {
					// player is trying to leave a pvp zone while being pz-locked
					return RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE;
				}

				if ((!playerTile->hasFlag(TILESTATE_NOPVPZONE) && hasFlag(TILESTATE_NOPVPZONE)) ||
					(!playerTile->hasFlag(TILESTATE_PROTECTIONZONE) && hasFlag(TILESTATE_PROTECTIONZONE))) {
					// player is trying to enter a non-pvp/protection zone while being pz-locked
					return RETURNVALUE_PLAYERISPZLOCKED;
				}
			}
		} else if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (const Creature* tileCreature : *creatures) {
				if (!tileCreature->isInGhostMode()) {
					return RETURNVALUE_NOTENOUGHROOM;
				}
			}
		}

		if (!hasBitSet(FLAG_IGNOREBLOCKITEM, flags)) {
			//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
			if (hasFlag(TILESTATE_BLOCKSOLID)) {
				return RETURNVALUE_NOTENOUGHROOM;
			}
		} else {
			//FLAG_IGNOREBLOCKITEM is set
			if (ground) {
				const ItemType& iiType = Item::items[ground->getID()];
				if (iiType.blockSolid && (!iiType.moveable || ground->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) {
					return RETURNVALUE_NOTPOSSIBLE;
				}
			}

			if (const auto items = getItemList()) {
				for (const Item* item : *items) {
					const ItemType& iiType = Item::items[item->getID()];
					if (iiType.blockSolid && (!iiType.moveable || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}
		}
	} else if (const Item* item = thing.getItem()) {
		const TileItemVector* items = getItemList();
		if (items && items->size() >= 0xFFFF) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

		if (hasBitSet(FLAG_NOLIMIT, flags)) {
			return RETURNVALUE_NOERROR;
		}

		bool itemIsHangable = item->isHangable();
		if (ground == nullptr && !itemIsHangable) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

		const CreatureVector* creatures = getCreatures();
		if (creatures && !creatures->empty() && item->isBlocking() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (const Creature* tileCreature : *creatures) {
				if (!tileCreature->isInGhostMode()) {
					return RETURNVALUE_NOTENOUGHROOM;
				}
			}
		}

		if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) {
			if (items) {
				for (const Item* tileItem : *items) {
					if (tileItem->isHangable()) {
						return RETURNVALUE_NEEDEXCHANGE;
					}
				}
			}
		} else {
			if (ground) {
				const ItemType& iiType = Item::items[ground->getID()];
				if (iiType.blockSolid) {
					if (!iiType.allowPickupable || item->isMagicField() || item->isBlocking()) {
						if (!item->isPickupable()) {
							return RETURNVALUE_NOTENOUGHROOM;
						}

						if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
							return RETURNVALUE_NOTENOUGHROOM;
						}
					}
				}
			}

			if (items) {
				for (const Item* tileItem : *items) {
					const ItemType& iiType = Item::items[tileItem->getID()];
					if (!iiType.blockSolid) {
						continue;
					}

					if (iiType.allowPickupable && !item->isMagicField() && !item->isBlocking()) {
						continue;
					}

					if (!item->isPickupable()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}

					if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}
				}
			}
		}
	}
	return RETURNVALUE_NOERROR;
}
Exemplo n.º 22
0
void Tile::__removeThing(Thing* thing, uint32_t count)
{
	Creature* creature = thing->getCreature();

	if (creature) {
		CreatureVector* creatures = getCreatures();

		if (creatures) {
			CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing);

			if (it != creatures->end()) {
				g_game.clearSpectatorCache();
				creatures->erase(it);
			}
		}

		return;
	}

	Item* item = thing->getItem();

	if (item) {
		int32_t index = __getIndexOfThing(item);

		if (index == -1) {
			return;
		}

		if (item == ground) {
			const SpectatorVec& list = g_game.getSpectators(getPosition());

			std::vector<uint32_t> oldStackPosVector;

			for (SpectatorVec::const_iterator it = list.begin(), end = list.end(); it != end; ++it) {
				if (Player* tmpPlayer = (*it)->getPlayer()) {
					oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, ground));
				}
			}

			ground->setParent(NULL);
			ground = NULL;
			onRemoveTileItem(list, oldStackPosVector, item);
			return;
		}

		if (item->isAlwaysOnTop()) {
			TileItemVector* items = getItemList();

			if (items) {
				for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) {
					if (*it == item) {
						const SpectatorVec& list = g_game.getSpectators(getPosition());

						std::vector<uint32_t> oldStackPosVector;

						for (SpectatorVec::const_iterator iit = list.begin(), iend = list.end(); iit != iend; ++iit) {
							if (Player* tmpPlayer = (*iit)->getPlayer()) {
								oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, *it));
							}
						}

						(*it)->setParent(NULL);
						items->erase(it);
						onRemoveTileItem(list, oldStackPosVector, item);
						return;
					}
				}
			}
		} else {
			TileItemVector* items = getItemList();

			if (items) {
				for (ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it) {
					if (*it == item) {
						if (item->isStackable() && count != item->getItemCount()) {
							uint8_t newCount = (uint8_t)std::max<int32_t>(0, (int32_t)(item->getItemCount() - count));

							updateTileFlags(item, true);
							item->setItemCount(newCount);
							updateTileFlags(item, false);

							const ItemType& it = Item::items[item->getID()];
							onUpdateTileItem(item, it, item, it);
						} else {
							const SpectatorVec& list = g_game.getSpectators(getPosition());

							std::vector<uint32_t> oldStackPosVector;

							for (SpectatorVec::const_iterator iit = list.begin(), iend = list.end(); iit != iend; ++iit) {
								if (Player* tmpPlayer = (*iit)->getPlayer()) {
									oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, *it));
								}
							}

							(*it)->setParent(NULL);
							items->erase(it);
							--items->downItemCount;
							onRemoveTileItem(list, oldStackPosVector, item);
						}

						return;
					}
				}
			}
		}
	}
}
Exemplo n.º 23
0
void Tile::__replaceThing(uint32_t index, Thing* thing)
{
	int32_t pos = index;

	Item* item = thing->getItem();

	if (item == NULL) {
		return /*RET_NOTPOSSIBLE*/;
	}

	Item* oldItem = NULL;
	bool isInserted = false;

	if (ground) {
		if (pos == 0) {
			oldItem = ground;
			ground = item;
			isInserted = true;
		}

		--pos;
	}

	TileItemVector* items = getItemList();

	if (items && !isInserted) {
		int32_t topItemSize = getTopItemCount();

		if (pos < topItemSize) {
			ItemVector::iterator it = items->getBeginTopItem();
			it += pos;

			oldItem = (*it);
			it = items->erase(it);
			items->insert(it, item);
			isInserted = true;
		}

		pos -= topItemSize;
	}

	CreatureVector* creatures = getCreatures();

	if (creatures) {
		if (!isInserted && pos < (int32_t)creatures->size()) {
			return /*RET_NOTPOSSIBLE*/;
		}

		pos -= (uint32_t)creatures->size();
	}

	if (items && !isInserted) {
		int32_t downItemSize = getDownItemCount();

		if (pos < downItemSize) {
			ItemVector::iterator it = items->begin();
			it += pos;
			pos = 0;

			oldItem = (*it);
			it = items->erase(it);
			items->insert(it, item);
			isInserted = true;
		}
	}

	if (isInserted) {
		item->setParent(this);

		updateTileFlags(oldItem, true);
		updateTileFlags(item, false);
		const ItemType& oldType = Item::items[oldItem->getID()];
		const ItemType& newType = Item::items[item->getID()];
		onUpdateTileItem(oldItem, oldType, item, newType);

		oldItem->setParent(NULL);
		return /*RET_NOERROR*/;
	}
}
Exemplo n.º 24
0
void Tile::__addThing(Creature* actor, int32_t, Thing* thing)
{
	if(Creature* creature = thing->getCreature())
	{
		g_game.clearSpectatorCache();
		creature->setParent(this);

		CreatureVector* creatures = makeCreatures();
		creatures->insert(creatures->begin(), creature);

		++thingCount;
		return;
	}

	Item* item = thing->getItem();
	if(!item)
	{
#ifdef __DEBUG_MOVESYS__
		std::clog << "[Failure - Tile::__addThing] item == NULL" << std::endl;
#endif
		return/* RET_NOTPOSSIBLE*/;
	}

	TileItemVector* items = getItemList();
	if(items && items->size() >= 0xFFFF)
		return/* RET_NOTPOSSIBLE*/;

	if(g_config.getBool(ConfigManager::STORE_TRASH) && !hasFlag(TILESTATE_TRASHED))
	{
		g_game.addTrash(pos);
		setFlag(TILESTATE_TRASHED);
	}

	item->setParent(this);
	if(item->isGroundTile())
	{
		if(ground)
		{
			int32_t oldGroundIndex = __getIndexOfThing(ground);
			Item* oldGround = ground;

			updateTileFlags(oldGround, true);
			updateTileFlags(item, false);
			ground = item;

#ifdef __GROUND_CACHE__
			std::map<Item*, int32_t>::iterator it = g_game.grounds.find(oldGround);
			bool erase = it == g_game.grounds.end();
			if(!erase)
			{
				it->second--;
				erase = it->second < 1;
				if(erase)
					g_game.grounds.erase(it);
			}

			if(erase)
			{
#endif
				oldGround->setParent(NULL);
				g_game.freeThing(oldGround);
#ifdef __GROUND_CACHE__
			}
#endif

			postRemoveNotification(actor, oldGround, NULL, oldGroundIndex, true);
			onUpdateTile();
		}
		else
		{
			ground = item;
			++thingCount;
			onAddTileItem(item);
		}
	}
	else if(item->isAlwaysOnTop())
	{
		if(item->isSplash())
		{
			//remove old splash if exists
			if(items)
			{
				for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
				{
					if(!(*it)->isSplash())
						continue;

					int32_t oldSplashIndex = __getIndexOfThing(*it);
					Item* oldSplash = *it;

					__removeThing(oldSplash, 1);
					oldSplash->setParent(NULL);
					g_game.freeThing(oldSplash);

					postRemoveNotification(actor, oldSplash, NULL, oldSplashIndex, true);
					break;
				}
			}
		}

		bool isInserted = false;
		if(items)
		{
			for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
			{
				//Note: this is different from internalAddThing
				if(Item::items[item->getID()].alwaysOnTopOrder > Item::items[(*it)->getID()].alwaysOnTopOrder)
					continue;

				items->insert(it, item);
				++thingCount;

				isInserted = true;
				break;
			}
		}
		else
			items = makeItemList();

		if(!isInserted)
		{
			items->push_back(item);
			++thingCount;
		}

		onAddTileItem(item);
	}
	else
	{
		if(item->isMagicField())
		{
			//remove old field item if exists
			if(items)
			{
				MagicField* oldField = NULL;
				for(ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it)
				{
					if(!(oldField = (*it)->getMagicField()))
						continue;

					if(oldField->isReplacable())
					{
						int32_t oldFieldIndex = __getIndexOfThing(*it);
						__removeThing(oldField, 1);

						oldField->setParent(NULL);
						g_game.freeThing(oldField);

						postRemoveNotification(actor, oldField, NULL, oldFieldIndex, true);
						break;
					}

					//This magic field cannot be replaced.
					item->setParent(NULL);
					g_game.freeThing(item);
					return;
				}
			}
		}

		if(item->getID() == ITEM_WATERBALL_SPLASH && !hasFlag(TILESTATE_TRASHHOLDER))
			item->setID(ITEM_WATERBALL);

		items = makeItemList();
		items->insert(items->getBeginDownItem(), item);

		++items->downItemCount;
		++thingCount;
		onAddTileItem(item);
	}
}
Exemplo n.º 25
0
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
                             uint32_t flags) const
{
	const CreatureVector* creatures = getCreatures();
	const TileItemVector* items = getItemList();

	if (const Creature* creature = thing->getCreature())
	{
		if (hasBitSet(FLAG_NOLIMIT, flags))
		{
			return RET_NOERROR;
		}

		if (hasBitSet(FLAG_PATHFINDING, flags))
		{
			if (floorChange() || positionChange())
			{
				return RET_NOTPOSSIBLE;
			}
		}

		if (!ground)
		{
			return RET_NOTPOSSIBLE;
		}

		if (const Monster* monster = creature->getMonster())
		{
			if (hasFlag(TILESTATE_PROTECTIONZONE))
			{
				return RET_NOTPOSSIBLE;
			}

			if (floorChange() || positionChange())
			{
				return RET_NOTPOSSIBLE;
			}

			if (monster->canPushCreatures() && !monster->isSummon())
			{
				if (creatures)
				{
					Creature* creature;

					for (uint32_t i = 0; i < creatures->size(); ++i)
					{
						creature = creatures->at(i);

						if (monster->canWalkthrough(creature))
						{
							continue;
						}

						if (!creature->getMonster() ||
						        !creature->isPushable() ||
						        (creature->getMonster()->isPlayerSummon()))
						{
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
			else if (creatures && !creatures->empty())
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!monster->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM;
					}
				}
			}

			if (hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))
			{
				return RET_NOTPOSSIBLE;
			}

			if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH))
			{
				return RET_NOTPOSSIBLE;
			}

			if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH)))
			{
				if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags)))
				{
					return RET_NOTPOSSIBLE;
				}
			}

			MagicField* field = getFieldItem();

			if (field && !field->isBlocking(monster))
			{
				CombatType_t combatType = field->getCombatType();

				//There are 3 options for a monster to enter a magic field
				//1) Monster is immune
				if (!monster->isImmune(combatType))
				{
					//2) Monster is "strong" enough to handle the damage and was attacked
					//3) Monster is already afflicated by this type of condition
					if (hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags))
					{
						if (!monster->hasCondition(Combat::DamageToConditionType(combatType), false))
						{
							if (!monster->canPushItems() || !monster->hadRecentBattle())
							{
								return RET_NOTPOSSIBLE;
							}
						}
					}
					else
					{
						return RET_NOTPOSSIBLE;
					}
				}
			}
		}
		else if (const Player* player = creature->getPlayer())
		{
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!player->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM; //RET_NOTPOSSIBLE
					}
				}
			}

			if (!player->getParent() && hasFlag(TILESTATE_NOLOGOUT))
			{
				//player is trying to login to a "no logout" tile
				return RET_NOTPOSSIBLE;
			}

			if (player->getTile())
			{
				if (player->isPzLocked() && !player->getTile()->hasFlag(TILESTATE_PVPZONE) && hasFlag(TILESTATE_PVPZONE))
				{
					//player is trying to enter a pvp zone while being pz-locked
					return RET_PLAYERISPZLOCKEDENTERPVPZONE;
				}

				if (player->isPzLocked() && player->getTile()->hasFlag(TILESTATE_PVPZONE) && !hasFlag(TILESTATE_PVPZONE))
				{
					//player is trying to leave a pvp zone while being pz-locked
					return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;
				}
			}

			if (hasFlag(TILESTATE_NOPVPZONE) && player->isPzLocked())
			{
				return RET_PLAYERISPZLOCKED;
			}

			if (hasFlag(TILESTATE_PROTECTIONZONE) && player->isPzLocked())
			{
				return RET_PLAYERISPZLOCKED;
			}
		}
		else
		{
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!creature->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM;
					}
				}
			}
		}

		if (items)
		{
			MagicField* field = getFieldItem();

			if (field && field->isBlocking(creature))
			{
				return RET_NOTPOSSIBLE;
			}

			if (!hasBitSet(FLAG_IGNOREBLOCKITEM, flags))
			{
				//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
				if (hasFlag(TILESTATE_BLOCKSOLID))
				{
					return RET_NOTENOUGHROOM;
				}
			}
			else
			{
				//FLAG_IGNOREBLOCKITEM is set
				if (ground)
				{
					const ItemType& iiType = Item::items[ground->getID()];

					if (ground->isBlocking(creature) && (!iiType.moveable || ground->getUniqueId() != 0))
					{
						return RET_NOTPOSSIBLE;
					}
				}

				if (const TileItemVector* items = getItemList())
				{
					Item* iitem;

					for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
					{
						iitem = (*it);
						const ItemType& iiType = Item::items[iitem->getID()];

						if (iitem->isBlocking(creature) && (!iiType.moveable || iitem->getUniqueId() != 0))
						{
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
		}
	}
	else if (const Item* item = thing->getItem())
	{
#ifdef __DEBUG__

		if (!thing->getParent() && !hasBitSet(FLAG_NOLIMIT, flags))
		{
			std::cout << "Notice: Tile::__queryAdd() - thing->getParent() == NULL" << std::endl;
		}

#endif

		if (items)
		{
			int64_t c = g_config.getNumber(ConfigManager::MAX_STACK_SIZE);
			//acceptable stack sizes should be higher than 100 and <= than 65535
			uint16_t max_stack_size = uint16_t(std::max(std::min(c, int64_t(0xFFFF)), int64_t(100)));

			if (items->size() >= max_stack_size)
			{
				return RET_NOTPOSSIBLE;
			}
		}

		if (hasBitSet(FLAG_NOLIMIT, flags))
		{
			return RET_NOERROR;
		}

		bool itemIsHangable = item->isHangable();

		if (!ground && !itemIsHangable)
		{
			return RET_NOTPOSSIBLE;
		}

		if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if ((!(*cit)->getPlayer() || !(*cit)->getPlayer()->hasSomeInvisibilityFlag()) && item->isBlocking(*cit))
				{
					return RET_NOTENOUGHROOM;
				}
			}
		}

		const uint32_t itemLimit = g_config.getNumber(hasFlag(TILESTATE_PROTECTIONZONE) ? ConfigManager::PROTECTION_TILE_LIMIT : ConfigManager::TILE_LIMIT);

		if (itemLimit && getThingCount() > itemLimit)
		{
			return RET_TILEISFULL;
		}

		bool hasHangable = false;
		bool supportHangable = false;

		if (items)
		{
			Thing* iithing = NULL;

			for (uint32_t i = 0; i < getThingCount(); ++i)
			{
				iithing = __getThing(i);

				if (const Item* iitem = iithing->getItem())
				{
					const ItemType& iiType = Item::items[iitem->getID()];

					if (iiType.isHangable)
					{
						hasHangable = true;
					}

					if (iiType.isHorizontal || iiType.isVertical)
					{
						supportHangable = true;
					}

					if (itemIsHangable && (iiType.isHorizontal || iiType.isVertical))
					{
						//
					}
					else if (iiType.blockSolid || iiType.isSolidForItems())
					{
						if (item->isPickupable())
						{
							if (iiType.allowPickupable)
							{
								continue;
							}

							if (!iiType.hasHeight || iiType.pickupable || iiType.isBed())
							{
								return RET_NOTENOUGHROOM;
							}
						}
						else
						{
							return RET_NOTENOUGHROOM;
						}
					}
				}
			}
		}

		if (itemIsHangable && hasHangable && supportHangable)
		{
			return RET_NEEDEXCHANGE;
		}
	}

	return RET_NOERROR;
}
Exemplo n.º 26
0
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
                             uint32_t flags, Creature* actor/* = NULL*/) const
{
	const CreatureVector* creatures = getCreatures();
	const TileItemVector* items = getItemList();

	if (const Creature* creature = thing->getCreature()) {
		if (hasBitSet(FLAG_NOLIMIT, flags)) {
			return RET_NOERROR;
		}

		if (hasBitSet(FLAG_PATHFINDING, flags)) {
			if (floorChange() || positionChange()) {
				return RET_NOTPOSSIBLE;
			}
		}

		if (ground == NULL) {
			return RET_NOTPOSSIBLE;
		}

		if (const Monster* monster = creature->getMonster()) {
			if (hasFlag(TILESTATE_PROTECTIONZONE)) {
				return RET_NOTPOSSIBLE;
			}

			if (floorChange() || positionChange()) {
				return RET_NOTPOSSIBLE;
			}

			if (monster->canPushCreatures() && !monster->isSummon()) {
				if (creatures) {
					Creature* creature;

					for (uint32_t i = 0; i < creatures->size(); ++i) {
						creature = creatures->at(i);

						if (creature->getPlayer() && creature->getPlayer()->isInGhostMode()) {
							continue;
						}

						const Monster* creatureMonster = creature->getMonster();

						if (!creatureMonster || !creature->isPushable() ||
						        (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) {
							return RET_NOTPOSSIBLE;
						}
					}
				}
			} else if (creatures && !creatures->empty()) {
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit) {
					if (!(*cit)->isInGhostMode()) {
						return RET_NOTENOUGHROOM;
					}
				}
			}

			if (hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID)) {
				return RET_NOTPOSSIBLE;
			}

			if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH)) {
				return RET_NOTPOSSIBLE;
			}

			if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH))) {
				if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))) {
					return RET_NOTPOSSIBLE;
				}
			}

			MagicField* field = getFieldItem();

			if (field && !field->isBlocking()) {
				CombatType_t combatType = field->getCombatType();

				//There is 3 options for a monster to enter a magic field
				//1) Monster is immune
				if (!monster->isImmune(combatType)) {
					//1) Monster is "strong" enough to handle the damage
					//2) Monster is already afflicated by this type of condition
					if (hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags)) {
						if (!(monster->canPushItems() || monster->hasCondition(Combat::DamageToConditionType(combatType)))) {
							return RET_NOTPOSSIBLE;
						}
					} else {
						return RET_NOTPOSSIBLE;
					}
				}
			}

			return RET_NOERROR;
		} else if (const Player* player = creature->getPlayer()) {
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags) && !player->isAccessPlayer()) {
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit) {
					if (!player->canWalkthrough(*cit)) {
						return RET_NOTPOSSIBLE;
					}
				}
			}

			if (player->getParent() == NULL && hasFlag(TILESTATE_NOLOGOUT)) {
				//player is trying to login to a "no logout" tile
				return RET_NOTPOSSIBLE;
			}

			if (player->getTile() && player->isPzLocked()) {
				if (!player->getTile()->hasFlag(TILESTATE_PVPZONE)) {
					//player is trying to enter a pvp zone while being pz-locked
					if (hasFlag(TILESTATE_PVPZONE)) {
						return RET_PLAYERISPZLOCKEDENTERPVPZONE;
					}
				} else if (!hasFlag(TILESTATE_PVPZONE)) { //player is trying to leave a pvp zone while being pz-locked
					return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;
				}

			}

			if ((hasFlag(TILESTATE_NOPVPZONE) || hasFlag(TILESTATE_PROTECTIONZONE)) && player->isPzLocked()) {
				return RET_PLAYERISPZLOCKED;
			}
		} else if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit) {
				if (!(*cit)->isInGhostMode()) {
					return RET_NOTENOUGHROOM;
				}
			}
		}

		if (items) {
			if (!hasBitSet(FLAG_IGNOREBLOCKITEM, flags)) {
				//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
				if (hasFlag(TILESTATE_BLOCKSOLID)) {
					return RET_NOTENOUGHROOM;
				}
			} else {
				//FLAG_IGNOREBLOCKITEM is set
				if (ground) {
					const ItemType& iiType = Item::items[ground->getID()];

					if (iiType.blockSolid && (!iiType.moveable || ground->getUniqueId() != 0)) {
						return RET_NOTPOSSIBLE;
					}
				}

				if (const TileItemVector* items = getItemList()) {
					Item* iitem;

					for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it) {
						iitem = (*it);
						const ItemType& iiType = Item::items[iitem->getID()];

						if (iiType.blockSolid && (!iiType.moveable || iitem->getUniqueId() != 0)) {
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
		}
	} else if (const Item* item = thing->getItem()) {
		if (items && items->size() >= 0xFFFF) {
			return RET_NOTPOSSIBLE;
		}

		if (hasBitSet(FLAG_NOLIMIT, flags)) {
			return RET_NOERROR;
		}

		bool itemIsHangable = item->isHangable();
		if (ground == NULL && !itemIsHangable) {
			return RET_NOTPOSSIBLE;
		}

		if (creatures && !creatures->empty() && item->isBlocking() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit) {
				if (!(*cit)->isInGhostMode()) {
					return RET_NOTENOUGHROOM;
				}
			}
		}

		if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) {
			if (items) {
				for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) {
					if ((*it)->isHangable()) {
						return RET_NEEDEXCHANGE;
					}
				}
			}
		} else {
			if (ground) {
				const ItemType& iiType = Item::items[ground->getID()];
				if (iiType.blockSolid) {
					if (!iiType.allowPickupable || item->isMagicField() || item->isBlocking()) {
						if (!item->isPickupable()) {
							return RET_NOTENOUGHROOM;
						}

						if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
							return RET_NOTENOUGHROOM;
						}
					}
				}
			}

			if (items) {
				for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) {
					const ItemType& iiType = Item::items[(*it)->getID()];
					if (!iiType.blockSolid) {
						continue;
					}

					if (iiType.allowPickupable && !item->isMagicField() && !item->isBlocking()) {
						continue;
					}

					if (!item->isPickupable()) {
						return RET_NOTENOUGHROOM;
					}

					if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
						return RET_NOTENOUGHROOM;
					}
				}
			}
		}
	}
	return RET_NOERROR;
}
Exemplo n.º 27
0
void Tile::addThing(int32_t, Thing* thing)
{
	Creature* creature = thing->getCreature();
	if (creature) {
		g_game.map.clearSpectatorCache();
		creature->setParent(this);
		CreatureVector* creatures = makeCreatures();
		creatures->insert(creatures->begin(), creature);
	} else {
		Item* item = thing->getItem();
		if (item == nullptr) {
			return /*RETURNVALUE_NOTPOSSIBLE*/;
		}

		TileItemVector* items = getItemList();
		if (items && items->size() >= 0xFFFF) {
			return /*RETURNVALUE_NOTPOSSIBLE*/;
		}

		item->setParent(this);

		const ItemType& itemType = Item::items[item->getID()];
		if (itemType.isGroundTile()) {
			if (ground == nullptr) {
				ground = item;
				onAddTileItem(item);
			} else {
				const ItemType& oldType = Item::items[ground->getID()];

				Item* oldGround = ground;
				ground->setParent(nullptr);
				g_game.ReleaseItem(ground);
				ground = item;
				resetTileFlags(oldGround);
				setTileFlags(item);
				onUpdateTileItem(oldGround, oldType, item, itemType);
				postRemoveNotification(oldGround, nullptr, 0);
			}
		} else if (itemType.alwaysOnTop) {
			if (itemType.isSplash() && items) {
				//remove old splash if exists
				for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) {
					Item* oldSplash = *it;
					if (!Item::items[oldSplash->getID()].isSplash()) {
						continue;
					}

					removeThing(oldSplash, 1);
					oldSplash->setParent(nullptr);
					g_game.ReleaseItem(oldSplash);
					postRemoveNotification(oldSplash, nullptr, 0);
					break;
				}
			}

			bool isInserted = false;

			if (items) {
				for (ItemVector::iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) {
					//Note: this is different from internalAddThing
					if (itemType.alwaysOnTopOrder <= Item::items[(*it)->getID()].alwaysOnTopOrder) {
						items->insert(it, item);
						isInserted = true;
						break;
					}
				}
			} else {
				items = makeItemList();
			}

			if (!isInserted) {
				items->push_back(item);
			}

			onAddTileItem(item);
		} else {
			if (itemType.isMagicField()) {
				//remove old field item if exists
				if (items) {
					for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) {
						MagicField* oldField = (*it)->getMagicField();
						if (oldField) {
							if (oldField->isReplaceable()) {
								removeThing(oldField, 1);

								oldField->setParent(nullptr);
								g_game.ReleaseItem(oldField);
								postRemoveNotification(oldField, nullptr, 0);
								break;
							} else {
								//This magic field cannot be replaced.
								item->setParent(nullptr);
								g_game.ReleaseItem(item);
								return;
							}
						}
					}
				}
			}

			items = makeItemList();
			items->insert(items->getBeginDownItem(), item);
			items->addDownItemCount(1);
			onAddTileItem(item);
		}
	}
}
Exemplo n.º 28
0
int main()
{
    //Create two lists
    LinkedListP list1 = newList();
    LinkedListP list2 = newList();
    char name[10] = "Diana";

    // Insert three items and print the list
    insertItemList( list1, "Alice" );
    printf("\n\nCurrent item contains  (Alice) %s\n", getItemList(list1));
    insertItemList( list1, "Bob" );
    printf("Current item contains  (Bob)   %s\n", getItemList(list1));
    insertItemList( list1, "Carl" );
    printf("Current item containsj (Carl) %s\n", getItemList(list1));
    displayListForward(list1);
    displayListBackward(list1);
    
    printf("\n\nCurrent item contains  (Carl)  %s\n", getItemList(list1));
    printf("Moving to NEXT item\n");
    nextItemList( list1 );
    printf("Current item contains  (Bob)   %s\n", getItemList( list1 ));

    //Try moving to previous - no change
    printf("moving to PREVIOUS item \n");
    previousItemList( list1 );
    printf("Current item contains  (Carl)  %s\n", getItemList( list1 ));

    //Add three more names into list1
    printf("\n\nAdding three items Don, Eric, Diana\n");
    addItemList( list1, "Don" );
    addItemList( list1, "Eric" );
    addItemList( list1, name );

    //Use the utility function below to display list1 forward
    displayListForward(list1);

    //Change Diana's name
    //Notice that the node is NOT modified
    printf("\nSetting DIANA to DONNY\n");
    strcpy(name, "Donny");
    displayListForward(list1);

    //Insert two more people into list1
    printf("\n\nInserting EARL and FRAN at front of list 10 :\n");
    firstItemList(list1);
    insertItemList( list1, "Earl" );
    insertItemList( list1, "Fran" );
    displayListForward(list1);

    if(isEmptyList(list1)) printf("\n\nList 1 is empty\n");
    else printf("\n\nList 1 is not empty\n");
    if(isEmptyList(list2)) printf("List 2 is empty\n");
    else printf("List 2 is not empty\n");

    //Take three people from list1 and insert into list2
    printf("\n\nRemove 3 from front of list 1 add to list 2\n");
    firstItemList(list1);
    addItemList(list2, removeItemList(list1));
    addItemList(list2, removeItemList(list1));
    addItemList(list2, removeItemList(list1));

    //Use the utility function below to display both lists forward
    printf("\nList 1 Forward\n");
    displayListForward(list1);
    printf("List 1 Forward\n");
    displayListBackward(list1);
    printf("\nList 2 Forward\n");
    displayListForward(list2);
    printf("List 2 Backward\n");
    displayListBackward(list2);

    //Free both lists
    list1 = freeList(list1);
    list2 = freeList(list2);
    if(list1 == NULL) printf("\n\nList 1 is NULL\n");
    else printf("\n\nList 1 is not NULL\n");
    if(list2 == NULL) printf("List 2 is NULL\n");
    else printf("List 2 is not NULL\n");

   return 0;
}
Exemplo n.º 29
0
void Tile::removeThing(Thing* thing, uint32_t count)
{
	Creature* creature = thing->getCreature();
	if (creature) {
		CreatureVector* creatures = getCreatures();
		if (creatures) {
			CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing);
			if (it != creatures->end()) {
				g_game.map.clearSpectatorCache();
				creatures->erase(it);
			}
		}
		return;
	}

	Item* item = thing->getItem();
	if (!item) {
		return;
	}

	int32_t index = getThingIndex(item);
	if (index == -1) {
		return;
	}

	if (item == ground) {
		ground->setParent(nullptr);
		ground = nullptr;

		SpectatorVec list;
		g_game.map.getSpectators(list, getPosition(), true);
		onRemoveTileItem(list, std::vector<int32_t>(list.size(), 0), item);
		return;
	}

	TileItemVector* items = getItemList();
	if (!items) {
		return;
	}

	const ItemType& itemType = Item::items[item->getID()];
	if (itemType.alwaysOnTop) {
		auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item);
		if (it == items->getEndTopItem()) {
			return;
		}

		std::vector<int32_t> oldStackPosVector;

		SpectatorVec list;
		g_game.map.getSpectators(list, getPosition(), true);
		for (Creature* spectator : list) {
			if (Player* tmpPlayer = spectator->getPlayer()) {
				oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item));
			}
		}

		item->setParent(nullptr);
		items->erase(it);
		onRemoveTileItem(list, oldStackPosVector, item);
	} else {
		auto it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item);
		if (it == items->getEndDownItem()) {
			return;
		}

		if (itemType.stackable && count != item->getItemCount()) {
			uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, static_cast<int32_t>(item->getItemCount() - count)));
			item->setItemCount(newCount);
			onUpdateTileItem(item, itemType, item, itemType);
		} else {
			std::vector<int32_t> oldStackPosVector;

			SpectatorVec list;
			g_game.map.getSpectators(list, getPosition(), true);
			for (Creature* spectator : list) {
				if (Player* tmpPlayer = spectator->getPlayer()) {
					oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item));
				}
			}

			item->setParent(nullptr);
			items->erase(it);
			items->addDownItemCount(-1);
			onRemoveTileItem(list, oldStackPosVector, item);
		}
	}
}
Exemplo n.º 30
0
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
	uint32_t flags) const
{
	const CreatureVector* creatures = getCreatures();
	const TileItemVector* items = getItemList();
	if(const Creature* creature = thing->getCreature())
	{
        if(ground)
	{
	 if(const Monster* monster = creature->getMonster())
				{
					const ItemType& iType = Item::items[ground->getID()];
					if(ground->getID() == 11756)
						return RET_NOTPOSSIBLE;
					if(ground->getID() == 4821)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4822)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4823)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4824)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4825)
						return RET_NOTPOSSIBLE;                	
				}
    }      
             
		if(hasBitSet(FLAG_NOLIMIT, flags))
			return RET_NOERROR;

		if(hasBitSet(FLAG_PATHFINDING, flags))
		{
			if(floorChange() || positionChange())
				return RET_NOTPOSSIBLE;
		}

		if(!ground)
			return RET_NOTPOSSIBLE;

		if(const Monster* monster = creature->getMonster())
		{
			if((hasFlag(TILESTATE_PROTECTIONZONE)) && monster->isSummon())
				return RET_NOERROR;

			if(floorChange() || positionChange())
				return RET_NOTPOSSIBLE;

			if(monster->canPushCreatures() && !monster->isSummon())
			{
				if(creatures)
				{
					Creature* tmp = NULL;
					for(uint32_t i = 0; i < creatures->size(); ++i)
					{
						tmp = creatures->at(i);
						if(creature->canWalkthrough(tmp))
							continue;

						if(!tmp->getMonster() || !tmp->isPushable() ||
							(tmp->getMonster()->isSummon() &&
							tmp->getMonster()->isPlayerSummon()))
							return RET_NOTPOSSIBLE;
					}
				}
			}
			else if(creatures && !creatures->empty())
			{
				for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if(!creature->canWalkthrough(*cit))
						return RET_NOTENOUGHROOM;
				}
			}

			if(hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))
				return RET_NOTPOSSIBLE;

			if(hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH))
				return RET_NOTPOSSIBLE;

			if((hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH)))
				&& (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))))
				return RET_NOTPOSSIBLE;

			MagicField* field = getFieldItem();
			if(field && !field->isBlocking(monster))
			{
				CombatType_t combatType = field->getCombatType();
				//There is 3 options for a monster to enter a magic field
				//1) Monster is immune
				if(!monster->isImmune(combatType))
				{
					//1) Monster is "strong" enough to handle the damage
					//2) Monster is already afflicated by this type of condition
					if(!hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags))
						return RET_NOTPOSSIBLE;

					if(!monster->canPushItems() && !monster->hasCondition(
						Combat::DamageToConditionType(combatType), false))
						return RET_NOTPOSSIBLE;
				}
			}

			return RET_NOERROR;
		}
		else if(const Player* player = creature->getPlayer())
		{
			if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if(!creature->canWalkthrough(*cit))
						return RET_NOTENOUGHROOM; //RET_NOTPOSSIBLE
				}
			}

			if(!player->getParent() && hasFlag(TILESTATE_NOLOGOUT)) //player is trying to login to a "no logout" tile
				return RET_NOTPOSSIBLE;

			if(player->isPzLocked() && !player->getTile()->hasFlag(TILESTATE_PVPZONE) && hasFlag(TILESTATE_PVPZONE)) //player is trying to enter a pvp zone while being pz-locked
				return RET_PLAYERISPZLOCKEDENTERPVPZONE;

			if(player->isPzLocked() && player->getTile()->hasFlag(TILESTATE_PVPZONE) && !hasFlag(TILESTATE_PVPZONE)) //player is trying to leave a pvp zone while being pz-locked
				return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;

			if(hasFlag(TILESTATE_NOPVPZONE) && player->isPzLocked())
				return RET_PLAYERISPZLOCKED;

			if(hasFlag(TILESTATE_PROTECTIONZONE) && player->isPzLocked())
				return RET_PLAYERISPZLOCKED;
		}
		else if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if(!creature->canWalkthrough(*cit))
					return RET_NOTENOUGHROOM;
			}
		}

		if(items)
		{
			MagicField* field = getFieldItem();
			if(field && field->isBlocking(creature))
				return RET_NOTPOSSIBLE;

			if(!hasBitSet(FLAG_IGNOREBLOCKITEM, flags))
			{
				//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
				if(hasFlag(TILESTATE_BLOCKSOLID))
					return RET_NOTENOUGHROOM;
			}
			else
			{
				//FLAG_IGNOREBLOCKITEM is set
				if(ground)
				{
					const ItemType& iType = Item::items[ground->getID()];
					if(ground->isBlocking(creature) && (!iType.moveable || (ground->isLoadedFromMap() &&
						(ground->getUniqueId() || (ground->getActionId()
						&& ground->getContainer())))))
						return RET_NOTPOSSIBLE;
				}

				if(const TileItemVector* items = getItemList())
				{
					Item* iItem = NULL;
					for(ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
					{
						iItem = (*it);
						const ItemType& iType = Item::items[iItem->getID()];
						if(iItem->isBlocking(creature) && (!iType.moveable || (iItem->isLoadedFromMap() &&
							(iItem->getUniqueId() || (iItem->getActionId()
							&& iItem->getContainer())))))
							return RET_NOTPOSSIBLE;
					}
				}
			}
		}
	}
	else if(const Item* item = thing->getItem())
	{
#ifdef __DEBUG__
		if(thing->getParent() == NULL && !hasBitSet(FLAG_NOLIMIT, flags))
			std::cout << "[Notice - Tile::__queryAdd] thing->getParent() == NULL" << std::endl;

#endif
		if(items && items->size() >= 0xFFFF)
			return RET_NOTPOSSIBLE;

		if(hasBitSet(FLAG_NOLIMIT, flags))
			return RET_NOERROR;

		bool itemIsHangable = item->isHangable();
		if(!ground && !itemIsHangable)
			return RET_NOTPOSSIBLE;

		if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if(!(*cit)->isGhost() && item->isBlocking(*cit))
					return RET_NOTENOUGHROOM;
			}
		}

		if(hasFlag(TILESTATE_PROTECTIONZONE))
		{
			const uint32_t itemLimit = g_config.getNumber(ConfigManager::ITEMLIMIT_PROTECTIONZONE);
			if(itemLimit && getThingCount() > itemLimit)
				return RET_TILEISFULL;
		}

		bool hasHangable = false, supportHangable = false;
		if(items)
		{
			Thing* iThing = NULL;
			for(uint32_t i = 0; i < getThingCount(); ++i)
			{
				iThing = __getThing(i);
				if(const Item* iItem = iThing->getItem())
				{
					const ItemType& iType = Item::items[iItem->getID()];
					if(iType.isHangable)
						hasHangable = true;

					if(iType.isHorizontal || iType.isVertical)
						supportHangable = true;

					if(itemIsHangable && (iType.isHorizontal || iType.isVertical))
						continue;
					else if(iType.blockSolid)
					{
						if(!item->isPickupable())
							return RET_NOTENOUGHROOM;

						if(iType.allowPickupable)
							continue;

						if(!iType.hasHeight || iType.pickupable || iType.isBed())
							return RET_NOTENOUGHROOM;
					}
				}
			}
		}

		if(itemIsHangable && hasHangable && supportHangable)
			return RET_NEEDEXCHANGE;
	}

	return RET_NOERROR;
}