void CityRegionImplementation::notifyExit(SceneObject* object) {
	//pre: no 2 different city regions should ever overlap, only 2 Regions of the same city region
	if (object->isTangibleObject()) {
		TangibleObject* tano = cast<TangibleObject*>(object);

		ManagedReference<Region*> activeRegion = tano->getActiveRegion().castTo<Region*>();

		if (activeRegion != NULL) {
			ManagedReference<CityRegion*> city = activeRegion->getCityRegion();

			object->setCityRegion(city);

			if (city == _this.getReferenceUnsafeStaticCast()) // if its the same city we wait till the object exits the last region
				return;
		} else {
			object->setCityRegion(NULL);
		}
	} else {
		object->setCityRegion(NULL);
	}


	if (object->isBazaarTerminal() || object->isVendor()) {
		if (object->isBazaarTerminal())
			bazaars.drop(object->getObjectID());

		AuctionTerminalDataComponent* terminalData = NULL;
		DataObjectComponentReference* data = object->getDataObjectComponent();
		if(data != NULL && data->get() != NULL && data->get()->isAuctionTerminalData())
			terminalData = cast<AuctionTerminalDataComponent*>(data->get());

		if(terminalData != NULL)
			terminalData->updateUID();
	}

	if (object->isPlayerCreature())
		currentPlayers.decrement();

	if (isClientRegion())
		return;

	if (object->isCreatureObject()) {

		CreatureObject* creature = cast<CreatureObject*>(object);

		StringIdChatParameter params("city/city", "city_leave_city"); //You have left %TO.
		params.setTO(getRegionName());

		creature->sendSystemMessage(params);

		removeSpecializationModifiers(creature);
	}

	if (object->isStructureObject()) {
		float x = object->getWorldPositionX();
		float y = object->getWorldPositionY();

		StructureObject* structure = cast<StructureObject*>(object);

		Locker slocker(&structureListMutex);

		if (structure->isBuildingObject()) {

			BuildingObject* building = cast<BuildingObject*>(object);
			uint64 ownerID = structure->getOwnerObjectID();

			ZoneServer* zoneServer = building->getZoneServer();

			if (zoneServer != NULL) {
				ManagedReference<CreatureObject*> owner = zoneServer->getObject(ownerID).castTo<CreatureObject*>();

				if(owner != NULL && owner->isPlayerCreature() && building->isResidence() && isCitizen(ownerID)) {
					CityManager* cityManager = zoneServer->getCityManager();
					cityManager->unregisterCitizen(_this.getReferenceUnsafeStaticCast(), owner);
				}
			}
		}

		completeStructureList.drop(structure->getObjectID());

		if (structure->isCivicStructure()) {
			removeStructure(structure);
		} else if (structure->isCommercialStructure()) {
			removeCommercialStructure(structure);
		}
	}

	if (object->isDecoration() && object->getParent().get() == NULL) {
		removeDecoration(object);
	}
}
void METKSurfaceDistance3D::handleObjMgrNotification() {
    ML_TRACE_IN("METKSurfaceDistance3D::handleObjMgrNotification()");
    omEventContainer myEventList = getEventContainer();

    //Durchiterieren der EventList
    omEventContainer::const_iterator iter;
    for ( iter = myEventList.begin(); iter!=myEventList.end(); iter++)
    {
        ObjMgrEvent myEvent = (*iter);

        //Status has changed
        if (myEvent.infoID == INF_SURFACEDIST || myEvent.infoID == INF_VISIBLE || myEvent.infoID == INF_IVPOINTER) {
            const omObjectContainer* oc = getObjContainer();
            if (oc) {
                const omObject &obj = (*oc)[myEvent.objectID];
                if (obj.isValid()) {
                    const bool visible = obj[LAY_APPEARANCE][INF_VISIBLE];
                    bool sdValid = obj.hasAttribute(LAY_APPEARANCE, INF_SURFACEDIST);
                    bool pValid = obj.hasAttribute(LAY_FILES, INF_IVPOINTER);

                    if (pValid && sdValid) {
                        const bool surfDist = obj[LAY_APPEARANCE][INF_SURFACEDIST];
                        const int pointer = obj[LAY_FILES][INF_IVPOINTER].get_MLint32();
                        if (pointer) {
                            if (visible && surfDist) {
                                addStructure((SoNode*) pointer);
                            } else {
                                removeStructure((SoNode*) pointer);
                            }
                        }
                    }
                }
            }
        }
        else if (myEvent.infoID == INF_CASELOADED) {
            const omObjectContainer* oc = getObjContainer();
            if (oc) {
                const omObject &obj = (*oc)[myEvent.objectID];
                if (obj.isValid()) {
                    const std::string status = obj[LAY_GLOBALEVENTS][INF_CASELOADED];
                    if (status == MSG_LOADED) {
                        // scan all objects for already visible surface distances
                        for (omObjectContainer::const_iterator iter = oc->begin(); iter != oc->end(); iter++) {
                            if (iter->second.isValid() && iter->second.exists(LAY_APPEARANCE)) {
                                const bool visible = iter->second[LAY_APPEARANCE][INF_VISIBLE];

                                bool pValid = iter->second.hasAttribute(LAY_FILES, INF_IVPOINTER);
                                bool sdValid = iter->second.hasAttribute(LAY_APPEARANCE, INF_SURFACEDIST);
                                if (pValid && sdValid) {
                                    const bool surfDist = iter->second[LAY_APPEARANCE][INF_SURFACEDIST];
                                    const int pointer   = iter->second[LAY_FILES][INF_IVPOINTER].get_MLint32();
                                    if (visible && surfDist && pointer) {
                                        addStructure((SoNode*) iter->second[LAY_FILES][INF_IVPOINTER].get_MLint32());
                                    }
                                }
                            }
                        }
                    }
                    else if (status == MSG_CLEANUP) {
                        T_ColorShapeIterator iter;
                        if (_inImageBox) {
                            delete _inImageBox;
                            _inImageBox = 0;
                        }
                        for (iter = _colorShapeVec.begin(); iter != _colorShapeVec.end(); iter++) {
                            (*iter)->unref();
                            if (_outGroup->findChild(*iter) != -1) {
                                _outGroup->removeChild(*iter);
                            }
                            _colorShapeVec.erase(iter);
                            iter--;
                        }
                        if (_memSlice) {
                            MLFree(_memSlice);
                            _memSlice = 0;
                        }
                    }
                }
            }
        }
    }
    clearEventContainer();
}