Exemplo n.º 1
0
Arquivo: brush.cpp Projeto: CkyLua/rme
void DoorBrush::draw(BaseMap* map, Tile* tile, void* parameter) {
	for(ItemVector::iterator item_iter = tile->items.begin();
			item_iter != tile->items.end();)
	{
		Item* item = *item_iter;
		if(item->isWall() == false) {
			++item_iter;
			continue;
		}
		WallBrush* wb = item->getWallBrush();
		if(!wb) {
			++item_iter;
			continue;
		}

		BorderType wall_alignment = item->getWallAlignment();

		uint16_t discarded_id = 0; // The id of a discarded match
		bool close_match = false;
		bool perfect_match = false;

		bool open = false;
		if(parameter) {
			open = *reinterpret_cast<bool*>(parameter);
		}

		if(item->isBrushDoor()) {
			open = item->isOpen();
		}

		WallBrush* test_brush = wb;
		do {
			for(std::vector<WallBrush::DoorType>::iterator iter = test_brush->door_items[wall_alignment].begin();
					iter != test_brush->door_items[wall_alignment].end();
					++iter)
			{
				WallBrush::DoorType& dt = *iter;
				if(dt.type == doortype) {
					ASSERT(dt.id);
					ItemType& it = item_db[dt.id];
					ASSERT(it.id != 0);

					if(it.isOpen == open) {
						item = transformItem(item, dt.id, tile);
						perfect_match = true;
						break;
					} else if(close_match == false) {
						discarded_id = dt.id;
						close_match = true;
					}
					if(!close_match && discarded_id == 0) {
						discarded_id = dt.id;
					}
				}
			}
			test_brush = test_brush->redirect_to;
			if(perfect_match) {
				break;
			}
		} while(test_brush != wb && test_brush != nullptr);

		// If we've found no perfect match, use a close-to perfect
		if(perfect_match == false && discarded_id) {
			item = transformItem(item, discarded_id, tile);
		}

		if(settings.getInteger(Config::AUTO_ASSIGN_DOORID) && tile->isHouseTile()) {
			Map* mmap = dynamic_cast<Map*>(map);
			Door* door = dynamic_cast<Door*>(item);
			if(mmap && door) {
				House* house = mmap->houses.getHouse(tile->getHouseID());
				ASSERT(house);
				Map* real_map = dynamic_cast<Map*>(map);
				if(real_map) {
					door->setDoorID(house->getEmptyDoorID());
				}
			}
		}

		// We need to consider decorations!
		while(true) {
			// Vector has been modified, before we can use the iterator again we need to find the wall item again
			item_iter = tile->items.begin();
			while(true) {
				if(item_iter == tile->items.end()) {
					return;
				}
				if(*item_iter == item) {
					++item_iter;
					if(item_iter == tile->items.end()) {
						return;
					}
					break;
				}
				++item_iter;
			}
			// Now it points to the correct item!

			item = *item_iter;
			if(item->isWall()) {
				if(WallDecorationBrush* wdb = dynamic_cast<WallDecorationBrush*>(item->getWallBrush())) {
					// We got a decoration!
					for(std::vector<WallBrush::DoorType>::iterator iter = wdb->door_items[wall_alignment].begin();
							iter != wdb->door_items[wall_alignment].end();
							++iter)
					{
						WallBrush::DoorType& dt = *iter;
						if(dt.type == doortype) {
							ASSERT(dt.id);
							ItemType& it = item_db[dt.id];
							ASSERT(it.id != 0);

							if(it.isOpen == open) {
								item = transformItem(item, dt.id, tile);
								perfect_match = true;
								break;
							} else if(close_match == false) {
								discarded_id = dt.id;
								close_match = true;
							}
							if(!close_match && discarded_id == 0) {
								discarded_id = dt.id;
							}
						}
					}
					// If we've found no perfect match, use a close-to perfect
					if(perfect_match == false && discarded_id) {
						item = transformItem(item, discarded_id, tile);
					}
					continue;
				}
			}
			break;
		}
		// If we get this far in the loop we should return
		return;
	}
}