bool InstallationObjectImplementation::updateMaintenance(Time& workingTime) {

	Time now;
	
	int currentTime = time(0);
	int lastTime = lastMaintenanceTime.getTime();

	int elapsedTime = currentTime - lastTime;
	int workTimePermitted = elapsedTime;

	float payAmount = ((float)elapsedTime / 3600.0f) * getMaintenanceRate();

	bool shutdownWork = false;


	if (payAmount > surplusMaintenance) {

		workTimePermitted = surplusMaintenance / getMaintenanceRate() * 3600;

		Time workTill(lastMaintenanceTime.getTime() + (int) workTimePermitted);
		workingTime = workTill;

		shutdownWork = true;
	}

	if (workTimePermitted > 0) {
		elapsedTime = workTimePermitted;
	}

	addMaintenance(-1.0f * payAmount);

	int basePowerRate = getBasePowerRate();

	if (isOperating() && basePowerRate != 0) {
		float energyAmount = (elapsedTime / 3600.0) * basePowerRate;

		if (energyAmount > surplusPower) {
			energyAmount = surplusPower;

			float workPowerPermitted = (surplusPower / basePowerRate) * 3600;

			if (workPowerPermitted < elapsedTime) {
				Time workTill(lastMaintenanceTime.getTime() + (int) workPowerPermitted);
				workingTime = workTill;
			}

			shutdownWork = true;
		}

		addPower(-1.0f * energyAmount);

	}

	lastMaintenanceTime.updateToCurrentTime();

	return shutdownWork;
}
void VendorDataComponent::runVendorUpdate() {
	ManagedReference<SceneObject*> strongParent = parent.get();

	if (strongParent == NULL || strongParent->getZoneServer() == NULL)
		return;

	ManagedReference<CreatureObject*> owner = strongParent->getZoneServer()->getObject(getOwnerId()).castTo<CreatureObject*>();
	ManagedReference<PlayerManager*> playerManager = strongParent->getZoneServer()->getPlayerManager();
	ManagedReference<TangibleObject*> vendor = cast<TangibleObject*>(strongParent.get());

	if (owner == NULL || !owner->isPlayerCreature() || playerManager == NULL || vendor == NULL) {
		return;
	}

	scheduleVendorCheckTask(VENDORCHECKINTERVAL);

	removeAllVendorBarks();

	int now = time(0);
	int last = lastSuccessfulUpdate.getTime();
	float hoursSinceLastUpdate = now - last;
	hoursSinceLastUpdate /= 3600.f;

	if (maintAmount > 0)
		inactiveTimer.updateToCurrentTime();

	/// parent salaries
	Locker vlocker(owner, vendor);
	maintAmount -= getMaintenanceRate() * hoursSinceLastUpdate;

	if (maintAmount < 0) {
		vendor->setConditionDamage(-maintAmount, true);
	} else {
		vendor->setConditionDamage(0, true);
		vendor->setMaxCondition(1000, true);
	}

	if (isEmpty()) {
		ManagedReference<ChatManager*> cman = strongParent->getZoneServer()->getChatManager();

		String sender = strongParent->getDisplayedName();
		UnicodeString subject("@auction:vendor_status_subject");

		if (!mail1Sent && time(0) - emptyTimer.getTime() > FIRSTWARNING) {
			StringIdChatParameter body("@auction:vendor_status_unaccessed");
			body.setTO(strongParent->getDisplayedName());
			if (cman != NULL)
				cman->sendMail(sender, subject, body, owner->getFirstName());
			mail1Sent = true;
		}

		else if (!mail2Sent && time(0) - emptyTimer.getTime() > SECONDWARNING) {
			StringIdChatParameter body("@auction:vendor_status_endangered");
			body.setTO(strongParent->getDisplayedName());
			if (cman != NULL)
				cman->sendMail(sender, subject, body, owner->getFirstName());
			mail2Sent = true;
		}

		else if (time(0) - emptyTimer.getTime() > EMPTYDELETE) {
			StringIdChatParameter body("@auction:vendor_status_deleted");
			if (cman != NULL)
				cman->sendMail(sender, subject, body, owner->getFirstName());
			VendorManager::instance()->destroyVendor(vendor);
			vendorCheckTask->cancel();
			return;
		}

	} else {
		mail1Sent = false;
		mail2Sent = false;
		emptyTimer.updateToCurrentTime();
	}

	if (isOnStrike()) {
		if (isRegistered())
			VendorManager::instance()->handleUnregisterVendor(owner, vendor);

		if (isVendorSearchEnabled())
			setVendorSearchEnabled(false);

		if (time(0) - inactiveTimer.getTime() > DELETEWARNING) {

			ManagedReference<ChatManager*> cman = strongParent->getZoneServer()->getChatManager();

			String sender = strongParent->getDisplayedName();
			UnicodeString subject("@auction:vendor_status_subject");

			StringIdChatParameter body("@auction:vendor_status_deleted");
			if (cman != NULL)
				cman->sendMail(sender, subject, body, owner->getFirstName());
			VendorManager::instance()->destroyVendor(vendor);
			vendorCheckTask->cancel();
		}

	} else {

		/// Award hourly XP
		assert(vendor->isLockedByCurrentThread());

		Locker locker(owner, vendor);
		playerManager->awardExperience(owner, "merchant", 150 * hoursSinceLastUpdate, false);

		playerManager->awardExperience(owner, "merchant", awardUsageXP * 50, false);

	}

	awardUsageXP = 0;
	lastSuccessfulUpdate.updateToCurrentTime();
}
void InstallationObjectImplementation::setOperating(bool value, bool notifyClient) {
	//updateInstallationWork();

	if (operating == value)
		return;

	if (value) {

		if(currentSpawn == NULL)
			return;

		spawnDensity = currentSpawn->getDensityAt(getZone()->getZoneName(), getPositionX(), getPositionY());

		if(spawnDensity < .10) {
			return;
		}

		if (basePowerRate != 0 && surplusPower <= 0) {
			StringIdChatParameter stringId("player_structure", "power_deposit_incomplete");
			ChatSystemMessage* msg = new ChatSystemMessage(stringId);

			broadcastToOperators(msg);
			return;
		}

		if (getMaintenanceRate() != 0 && surplusMaintenance <= 0) {
			StringIdChatParameter stringId("shared", "harvester_no_maint_4");
			ChatSystemMessage* msg = new ChatSystemMessage(stringId);

			broadcastToOperators(msg);
			return;
		}
	}

	Time timeToWorkTill;

	operating = value;
	extractionRemainder = 0;

	if (operating) {
		setOptionBit(OptionBitmask::ACTIVATED, false);

		lastStartTime.updateToCurrentTime();
	} else {
		clearOptionBit(OptionBitmask::ACTIVATED, false);

		lastStopTime.updateToCurrentTime();
	}

	InstallationObjectDeltaMessage3* delta = new InstallationObjectDeltaMessage3(_this.get());
	delta->updateOperating(value);
	delta->updateOptionsBitmask();
	delta->close();

	InstallationObjectDeltaMessage7* delta7 = new InstallationObjectDeltaMessage7(_this.get());
	delta7->updateOperating(value);
	delta7->close();

	Vector<BasePacket*> messages;
	messages.add(delta);
	messages.add(delta7);

	broadcastMessages(&messages, true);

	if (value) {
		resourceHopperTimestamp.updateToCurrentTime();
	}

	InstallationObjectDeltaMessage7* inso7 = new InstallationObjectDeltaMessage7( _this.get());
	inso7->updateExtractionRate(getActualRate());
	inso7->close();

	broadcastToOperators(inso7);
}