void GroupObjectImplementation::removeMember(CreatureObject* member) {
	bool wasLeader = getLeader() == member;

	if (hasSquadLeader()) {
		if (wasLeader)
			removeGroupModifiers();
		else
			removeGroupModifiers(member);
	}

	for (int i = 0; i < groupMembers.size(); i++) {
		CreatureObject* scno = groupMembers.get(i).get().get();

		if (scno == member) {
			GroupObjectDeltaMessage6* grp = new GroupObjectDeltaMessage6(_this.getReferenceUnsafeStaticCast());
			grp->startUpdate(1);
			groupMembers.remove(i, grp);
			grp->close();

			broadcastMessage(grp);
		}
	}

	if (member->isPlayerCreature()) {
		// Remove member's pets
		RemovePetsFromGroupTask* task = new RemovePetsFromGroupTask(member, _this.getReferenceUnsafeStaticCast());
		task->execute();

		//Close any open Group SUIs.
		ManagedReference<PlayerObject*> ghost = member->getPlayerObject();
		if (ghost != NULL) {
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_RULE);
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_CHANGED);
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_PICK_LOOTER);

			ghost->removeWaypointBySpecialType(WaypointObject::SPECIALTYPE_NEARESTMISSIONFORGROUP);
		}

		//Reset Master Looter if needed.
		if (getMasterLooterID() == member->getObjectID()) {
			ManagedReference<CreatureObject*> groupLeader = getLeader();
			GroupManager::instance()->changeMasterLooter(_this.getReferenceUnsafeStaticCast(), groupLeader, false);
		}

		if (wasLeader && hasSquadLeader()) {
			addGroupModifiers();
		}

		Zone* zone = member->getZone();

		if (zone != NULL) {
			scheduleUpdateNearestMissionForGroup(zone->getPlanetCRC());
		}
	}

	updatePvPStatusNearCreature(member);

	calcGroupLevel();
}
void GroupObjectImplementation::removeMember(SceneObject* member) {
	ManagedReference<SceneObject*> obj = member;

	for (int i = 0; i < groupMembers.size(); i++) {
		SceneObject* scno = groupMembers.get(i).get().get();

		if (scno == member) {
			GroupObjectDeltaMessage6* grp = new GroupObjectDeltaMessage6(_this.get());
			grp->startUpdate(1);
			groupMembers.remove(i, grp);
			grp->close();

			broadcastMessage(grp);
		}
	}

	if (member->isPlayerCreature()) {
		// Remove member's pets
		CreatureObject* playerCreature = cast<CreatureObject*>(member);
		RemovePetsFromGroupTask* task = new RemovePetsFromGroupTask(playerCreature, _this.get());
		task->execute();

		//Close any open Group SUIs.
		ManagedReference<PlayerObject*> ghost = playerCreature->getPlayerObject();
		if (ghost != NULL) {
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_RULE);
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_CHANGED);
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_PICK_LOOTER);
		}

		//Reset Master Looter if needed.
		if (getMasterLooterID() == playerCreature->getObjectID()) {
			ManagedReference<CreatureObject*> groupLeader = (getLeader()).castTo<CreatureObject*>();
			GroupManager::instance()->changeMasterLooter(_this.get(), groupLeader, false);
		}

		if (hasSquadLeader()) {
			removeGroupModifiers(playerCreature);
		}

		if (playerCreature->getPlayerObject() != NULL) {
			PlayerObject* ghost = playerCreature->getPlayerObject();
			ghost->removeWaypointBySpecialType(WaypointObject::SPECIALTYPE_NEARESTMISSIONFORGROUP);
		}
		scheduleUpdateNearestMissionForGroup(playerCreature->getPlanetCRC());
	}

	calcGroupLevel();
}
	void GroupManager::sendMasterLooterList(GroupObject* group, CreatureObject* leader) {
		//Pre: Leader and group are locked
		//Post: Leader and group are locked

		if (group == NULL || leader == NULL)
			return;

		ManagedReference<PlayerObject*> ghost = leader->getPlayerObject();
		if (ghost == NULL)
			return;

		//Close SUI box if already open.
		ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_PICK_LOOTER);

		//Create Master Looter selection list box.
		ManagedReference<SuiListBox*> sui = new SuiListBox(leader, SuiWindowType::GROUP_LOOT_PICK_LOOTER);
		sui->setPromptTitle("@group:master_looter_sui_title"); //"Select Master Looter"
		sui->setPromptText("@group:choose_master_looter"); //"Choose a Master Looter from the list of available players:"
		sui->setCancelButton(true, "@ui:cancel");
		sui->setOkButton(true, "@ui:ok");
		sui->setCallback(new GroupLootPickLooterSuiCallback(leader->getZoneServer()));

		for (int i = 0; i < group->getGroupSize(); ++i) {
			ManagedReference<CreatureObject*> member = (group->getGroupMember(i)).castTo<CreatureObject*>();
				if (member == NULL || !member->isPlayerCreature())
					continue;

			sui->addMenuItem(member->getFirstName(), member->getObjectID());
		}

		//Send list box to the group leader.
		ghost->addSuiBox(sui);
		leader->sendMessage(sui->generateMessage());
	}
void GroupManager::disbandGroup(ManagedReference<GroupObject*> group, CreatureObject* player) {
	//Pre: player locked
	//Post: player locked
	player->unlock();

	try {
		group->wlock();
		//The following should never happen, as a check is made in
		//ObjectControlMessage.cpp and removes the player from the group
		//if he's not the leader. Remove?
		//After Fix 13 feb 2009 - Bankler
		if (group->getLeader() != player) {
			player->sendSystemMessage("@group:must_be_leader");
			group->unlock();
			player->wlock();
			return;
		}

		for (int i = 0; i < group->getGroupSize(); i++) {
			Reference<CreatureObject*> play = ( group->getGroupMember(i)).castTo<CreatureObject*>();

			if (play->isPlayerCreature()) {
				play->sendSystemMessage("@group:disbanded"); //"The group has been disbanded."

				//Close any open Group SUIs.
				ManagedReference<PlayerObject*> ghost = play->getPlayerObject();
				if (ghost != NULL) {
					ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_RULE);
					ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_CHANGED);
					ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_PICK_LOOTER);
				}
			}
		}

		group->disband();

		group->unlock();
	} catch (...) {
		group->unlock();

		player->wlock();

		throw;
	}

	player->wlock();
}
void PlantObjectImplementation::sendResourceSUI(CreatureObject* player, int type) {
	ManagedReference<PlayerObject*> ghost = player->getPlayerObject();

	if (ghost == NULL)
		return;

	ManagedReference<SuiListBox*> suiBox = new SuiListBox(player, SuiWindowType::GROWABLE_PLANT, SuiListBox::HANDLETWOBUTTON);
	suiBox->setCallback(new GrowablePlantSuiCallback(player->getZoneServer()));
	suiBox->setPromptTitle("@plant_grow:select_resource_sub");
	suiBox->setPromptText("@plant_grow:select_resource_body");
	suiBox->setOkButton(true, "@ok");
	suiBox->setCancelButton(true, "@cancel");
	suiBox->setUsingObject(_this.getReferenceUnsafeStaticCast());
	suiBox->setForceCloseDistance(32.f);

	ManagedReference<SceneObject*> inventory = player->getSlottedObject("inventory");
	ManagedReference<SceneObject*> sceneObject = NULL;

	for (int i=0; i< inventory->getContainerObjectsSize(); i++) {
		sceneObject = inventory->getContainerObject(i);

		if (sceneObject == NULL)
			continue;

		if (sceneObject->isResourceContainer()) {
			ManagedReference<ResourceContainer*> rcno = cast<ResourceContainer*>( sceneObject.get());

			if (rcno == NULL)
				continue;

			ManagedReference<ResourceSpawn*> spawn = rcno->getSpawnObject();

			if (spawn == NULL)
				continue;

			if ((type == 1 && spawn->isType("organic")) || (type == 2 && spawn->isType("water"))) {
				suiBox->addMenuItem(spawn->getName(), sceneObject->getObjectID());
			}
		}
	}

	if (suiBox->getMenuSize() > 0) {
		ghost->closeSuiWindowType(SuiWindowType::GROWABLE_PLANT);
		ghost->addSuiBox(suiBox);
		player->sendMessage(suiBox->generateMessage());
	} else {
		if (type == 1)
			player->sendSystemMessage("@plant_grow:no_nutrients"); // You don't have any nutrients.
		else
			player->sendSystemMessage("@plant_grow:no_water"); // You don't have any water.
	}
}
void StructureManager::reportStructureStatus(CreatureObject* creature,
		StructureObject* structure) {
	ManagedReference<PlayerObject*> ghost = creature->getPlayerObject();

	if (ghost == NULL)
		return;

	//Close the window if it is already open.
	ghost->closeSuiWindowType(SuiWindowType::STRUCTURE_STATUS);

	ManagedReference<SuiListBox*> status = new SuiListBox(creature,
			SuiWindowType::STRUCTURE_STATUS);
	status->setPromptTitle("@player_structure:structure_status_t"); //Structure Status
	status->setPromptText(
			"@player_structure:structure_name_prompt "
					+ structure->getDisplayedName()); //Structure Name:
	status->setUsingObject(structure);
	status->setOkButton(true, "@refresh");
	status->setCancelButton(true, "@cancel");
	status->setCallback(new StructureStatusSuiCallback(server));

	ManagedReference<SceneObject*> ownerObject = server->getObject(
			structure->getOwnerObjectID());

	if (ownerObject != NULL && ownerObject->isCreatureObject()) {
		CreatureObject* owner = cast<CreatureObject*>(ownerObject.get());
		status->addMenuItem(
				"@player_structure:owner_prompt " + owner->getFirstName());
	}

	uint64 declaredOidResidence = ghost->getDeclaredResidence();

	ManagedReference<BuildingObject*> declaredResidence =
			server->getObject(declaredOidResidence).castTo<BuildingObject*>();

	if (declaredResidence == structure) {
		status->addMenuItem("@player_structure:declared_residency"); //You have declared your residency here.
	}

	if (structure->isPrivateStructure() && !structure->isCivicStructure()) {
		status->addMenuItem("@player_structure:structure_private"); //This structure is private
	} else {
		status->addMenuItem("@player_structure:structure_public"); //This structure is public
	}

	status->addMenuItem(
			"@player_structure:condition_prompt "
					+ String::valueOf(structure->getDecayPercentage()) + "%");

	if (!structure->isCivicStructure()) {

		// property tax
		float propertytax = 0.f;
		if(!structure->isCivicStructure() && structure->getCityRegion() != NULL){
			ManagedReference<CityRegion*> city = structure->getCityRegion().get();
			if(city != NULL){
				propertytax = city->getPropertyTax()/ 100.f * structure->getMaintenanceRate();
				status->addMenuItem(
							"@city/city:property_tax_prompt : "
									+ String::valueOf(ceil(propertytax))
									+  " cr/hr");
			}
		}

		// maintenance
		float secsRemainingMaint = 0.f;
		if( structure->getSurplusMaintenance() > 0 ){
			float totalrate = (float)structure->getMaintenanceRate() + propertytax;
			secsRemainingMaint = ((float)structure->getSurplusMaintenance() / totalrate)*3600;
		}

		status->addMenuItem(
			"@player_structure:maintenance_pool_prompt "
					+ String::valueOf( (int) floor( (float) structure->getSurplusMaintenance()))
					+ " "
					+ getTimeString( (uint32)secsRemainingMaint ) );

		status->addMenuItem(
			"@player_structure:maintenance_rate_prompt "
					+ String::valueOf(structure->getMaintenanceRate())
					+ " cr/hr");

		status->addMenuItem(
			"@player_structure:maintenance_mods_prompt "
					+ structure->getMaintenanceMods());
	}


	if (structure->isInstallationObject() && !structure->isGeneratorObject() && !structure->isCivicStructure()) {
		InstallationObject* installation = cast<InstallationObject*>(structure);

		float secsRemainingPower = 0.f;
		if( installation->getSurplusPower() > 0 ){
			secsRemainingPower = ((float)installation->getSurplusPower() / (float)installation->getBasePowerRate())*3600;
		}

		status->addMenuItem(
				"@player_structure:power_reserve_prompt "
						+ String::valueOf( (int) installation->getSurplusPower())
						+ " "
						+ getTimeString( (uint32)secsRemainingPower ) );

		status->addMenuItem(
				"@player_structure:power_consumption_prompt "
						+ String::valueOf(
								(int) installation->getBasePowerRate())
						+ " @player_structure:units_per_hour");
	}

	if (structure->isBuildingObject()) {
		BuildingObject* building = cast<BuildingObject*>(structure);

		status->addMenuItem(
				"@player_structure:items_in_building_prompt "
						+ String::valueOf(
								building->getCurrentNumberOfPlayerItems())); //Number of Items in Building:
	}

	ghost->addSuiBox(status);
	creature->sendMessage(status->generateMessage());
}
	void GroupManager::changeLootRule(GroupObject* group, int newRule) {
		//Pre: group is locked
		//Post: group is locked
		if (group == NULL)
			return;

		if (group->getLootRule() == newRule) //Don't change to the same rule.
			return;

		//This ensures that the loot rule abbreviations are next to the Leader's name.
		if (newRule != MASTERLOOTER || group->getMasterLooterID() == 0)
			group->setMasterLooterID(group->getLeader()->getObjectID());

		String promptText;

		switch (newRule) {
		case FREEFORALL:
			promptText = "@group:selected_free4all";
			break;
		case MASTERLOOTER:
			promptText = "@group:selected_master";
			notifyMasterLooter(group);
			break;
		case LOTTERY:
			promptText = "@group:selected_lotto";
			break;
		case RANDOM:
			promptText = "@group:selected_random";
			break;
		default:
			return; //Invalid Loot Rule Selected. Stop.
		}

		group->setLootRule(newRule);
		group->updateLootRules(); //Send update packet to all members.

		//Notify group members of the new rule with an SUI box.
		for (int i = 0; i < group->getGroupSize(); ++i) {
			ManagedReference<CreatureObject*> member = (group->getGroupMember(i)).castTo<CreatureObject*>();

			if (member == NULL || !member->isPlayerCreature() || member == group->getLeader())
				continue;

			ManagedReference<PlayerObject*> ghost = member->getPlayerObject();
			if (ghost == NULL)
				continue;

			//Close SUI box if already open.
			ghost->closeSuiWindowType(SuiWindowType::GROUP_LOOT_CHANGED);

			ManagedReference<SuiMessageBox*> sui = new SuiMessageBox(member, SuiWindowType::GROUP_LOOT_CHANGED);
			sui->setPromptTitle("@group:loot_changed"); //"Loot Type Changed."
			sui->setPromptText(promptText);
			sui->setCancelButton(true, "@group:ok");
			sui->setOkButton(true, "@group:leave_group");
			sui->setCallback(new GroupLootChangedSuiCallback(member->getZoneServer()));

			ghost->addSuiBox(sui);
			member->sendMessage(sui->generateMessage());
		}
}