Ejemplo n.º 1
0
int LuaCreatureObject::isCombatDroidPet(lua_State* L) {
    bool retVal = false;
    if (realObject->isDroidObject() && realObject->isPet()) {
        DroidObject* d = cast<DroidObject*>(realObject);
        retVal = d->isCombatDroid();
    }
    lua_pushboolean(L, retVal);
    return 1;
}
Ejemplo n.º 2
0
void StructureManager::promptMaintenanceDroid(StructureObject* structure, CreatureObject* creature) {
	ManagedReference<PlayerObject*> ghost = creature->getPlayerObject();

	if (ghost == NULL)
		return;

	Vector<DroidObject*> droids;
	ManagedReference<SceneObject*> datapad = creature->getSlottedObject("datapad");
	if(datapad == NULL) {
		return;
	}
	for (int i = 0; i < datapad->getContainerObjectsSize(); ++i) {
		ManagedReference<SceneObject*> object = datapad->getContainerObject(i);

		if (object != NULL && object->isPetControlDevice()) {
			PetControlDevice* device = cast<PetControlDevice*>( object.get());

			if (device->getPetType() == PetManager::DROIDPET) {
				DroidObject* pet = cast<DroidObject*>(device->getControlledObject());
				if (pet->isMaintenanceDroid()) {
					droids.add(pet);
				}
			}
		}
	}
	if (droids.size() == 0) {
		creature->sendSystemMessage("@player_structure:no_droids");
		return;
	}

	ManagedReference<SuiListBox*> box = new SuiListBox(creature,SuiWindowType::STRUCTURE_ASSIGN_DROID);
	box->setCallback(new StructureAssignDroidSuiCallback(creature->getZoneServer()));

	box->setPromptText("@sui:assign_droid_prompt");
	box->setPromptTitle("@sui:assign_droid_title"); // Configure Effects
	box->setOkButton(true, "@ok");

	// Check if player has a droid called with a maintenance module installed
	for (int i = 0; i < droids.size(); ++i) {
		DroidObject* droidObject = droids.elementAt(i);
		box->addMenuItem(droidObject->getDisplayedName(),droidObject->getObjectID());
	}
	box->setUsingObject(structure);
	ghost->addSuiBox(box);
	creature->sendMessage(box->generateMessage());

}
void DroidArmorModuleDataComponent::initialize(CreatureObject* creature) {
	// Change droid resist and armor stat

	DroidObject* droid = cast<DroidObject*>(creature);
	if( droid == NULL )
		return;

	int level = armorModule;
	unsigned int armor = 0;
	float resist = -1;

	// Capped at 6
	if( level > 6 )
		level = 6;

	// Set armor type
	if( level == 0 ){
		armor = 0; // NO ARMOR
	}
	else if( level <= 3 ){
		armor = 1; // LIGHT ARMOR
	}
	else if( level <= 6 ){
		armor = 2; // MEDIUM ARMOR
	}

	// Set damage resistance
	if( level == 1 || level == 4 ){
		resist = 15;
	}
	else if( level == 2 || level == 5 ){
		resist = 25;
	}
	else if( level == 3 || level == 6 ){
		resist = 40;
	}

	droid->setArmor( armor );
	droid->setResists( resist );

}
void PetControlDeviceImplementation::spawnObject(CreatureObject* player) {
	ZoneServer* zoneServer = getZoneServer();

	ManagedReference<TangibleObject*> controlledObject = this->controlledObject.get();

	if (controlledObject == NULL)
		return;

	assert(controlledObject->isLockedByCurrentThread());

	if (!isASubChildOf(player))
		return;

	ManagedReference<TradeSession*> tradeContainer = player->getActiveSession(SessionFacadeType::TRADE).castTo<TradeSession*>();

	if (tradeContainer != NULL) {
		server->getZoneServer()->getPlayerManager()->handleAbortTradeMessage(player);
	}

	controlledObject->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
	ManagedReference<CreatureObject*> creature = NULL;

	if (controlledObject->isCreatureObject()) {
		creature = cast<CreatureObject*>(controlledObject.get());
		creature->setCreatureLink(player);
		creature->setControlDevice(_this.getReferenceUnsafeStaticCast());
		creature->setFaction(player->getFaction());
		creature->setObjectMenuComponent("PetMenuComponent");

		if (player->getPvpStatusBitmask() & CreatureFlag::PLAYER)
			creature->setPvpStatusBitmask(player->getPvpStatusBitmask() - CreatureFlag::PLAYER, true);
		else
			creature->setPvpStatusBitmask(player->getPvpStatusBitmask(), true);

		if (trainedAsMount && (creature->getOptionsBitmask() ^ 0x1000)) {
			creature->setOptionBit(0x1000);
		}
	}

	Zone* zone = player->getZone();

	if (zone == NULL)
		return;

	ManagedReference<CellObject*> parent = player->getParent().get().castTo<CellObject*>();

	if (parent != NULL)
		parent->transferObject(controlledObject, -1, true);
	else
		zone->transferObject(controlledObject, -1, true);

	updateStatus(1);

	if (petControlObserver != NULL)
		player->dropObserver(ObserverEventType::STARTCOMBAT, petControlObserver);

	AiAgent* pet = cast<AiAgent*>(creature.get());

	if (pet == NULL)
		return;

	ManagedReference<PlayerObject*> ghost = player->getPlayerObject();
	ghost->addToActivePets(pet);

	bool isDroid = false;
	if (pet->isDroidObject()) {
		DroidObject* droid = cast<DroidObject*>(pet);
		isDroid = true;
		if( droid == NULL )
			return;

		// Sanity check that there aren't outstanding power/skill mod tasks
		droid->removePendingTask( "droid_power" );
		droid->removePendingTask( "droid_skill_mod" );
		droid->initDroidModules();
		droid->onCall();
		droid->loadSkillMods(player);
		// Submit new power task
		Reference<Task*> droidPowerTask = new DroidPowerTask( droid );
		droid->addPendingTask("droid_power", droidPowerTask, 120000); // 2 min
		// Submit new skill mod task
		Reference<Task*> droidSkillModTask = new DroidSkillModTask( droid, player );
		droid->addPendingTask("droid_skill_mod", droidSkillModTask, 3000); // 3 sec
	}

	pet->setHomeLocation(player->getPositionX(), player->getPositionZ(), player->getPositionY(), parent);
	pet->setNextStepPosition(player->getPositionX(), player->getPositionZ(), player->getPositionY(), parent);
	pet->clearPatrolPoints();
	if (petType == PetManager::CREATUREPET) {
		pet->setCreatureBitmask(CreatureFlag::PET);
	}
	if (petType == PetManager::DROIDPET) {
		pet->setCreatureBitmask(CreatureFlag::DROID_PET);
	}
	if (petType == PetManager::FACTIONPET) {
		pet->setCreatureBitmask(CreatureFlag::FACTION_PET);
		/** dont know if npc faction pets trained via converse instead of radial
		if (pet->isNonPlayerCreatureObject() && pet->getDiet() != CreatureFlag::NONE) // show converse to npcs that eat food i.e. not atst
			pet->setOptionBit(OptionBitmask::CONVERSE,true);
		**/
	}
	pet->activateLoad("");
	pet->activateRecovery();
	// Not training any commands
	trainingCommand = 0;
	clearPatrolPoints();
}
int DroidCustomKitObjectMenuComponent::handleObjectMenuSelect(SceneObject* sceneObject, CreatureObject* player, byte selectedID) {

	if (player == NULL)
		return 0;

	if (!sceneObject->isASubChildOf(player))
		return 0;

	if (selectedID != 20)
		return TangibleObjectMenuComponent::handleObjectMenuSelect(sceneObject, player, selectedID);

	if(!sceneObject->isTangibleObject())
		return 0;

	ManagedReference<TangibleObject*> kitTano = cast<TangibleObject*>(sceneObject);
	if(kitTano == NULL)
		return 0;

	uint64 targetID = player->getTargetID();
	ZoneServer* server = player->getZoneServer();
	if (server == NULL)
		return 0;

	ManagedReference<TangibleObject*> target = server->getObject(targetID, true).castTo<TangibleObject*>();
	if (target == NULL || !target->isDroidObject()) {
		player->sendSystemMessage("You can only use this tool to customize droids");
		return 0;
	}
	//permission check
	CreatureObject* droid = cast<CreatureObject*>(target.get());
	uint64 ownerID = droid->getCreatureLinkID();
	if ( ownerID != player->getObjectID()){
		bool hasConsent = false;

		ManagedReference<CreatureObject*> targetOwner = server->getObject(ownerID, true).castTo<CreatureObject*>();
		if (targetOwner != NULL)
		{
			Locker crossLock(targetOwner, player);
			ManagedReference<PlayerObject*> ghostOwner = targetOwner->getPlayerObject();
			for (int i = 0; i < ghostOwner->getConsentListSize(); ++i) {
				String entryName = ghostOwner->getConsentName(i);
				if (!entryName.isEmpty()){
					if (entryName == player->getFirstName().toLowerCase()){
						hasConsent = true;
					}
				}
			}
		}
		if (!hasConsent){
			player->sendSystemMessage("You require consent to customize another player's droid");
			return 0;
		}
	}
	//end permission check

	Locker clocker(droid, player);

	String appearanceFilename = target->getObjectTemplate()->getAppearanceFilename();
	VectorMap<String, Reference<CustomizationVariable*> > variables;
	AssetCustomizationManagerTemplate::instance()->getCustomizationVariables(appearanceFilename.hashCode(), variables, false);
	int numPalette = 0;
	for(int i = 0; i< variables.size(); ++i)
	{
		String varkey = variables.elementAt(i).getKey();
		if (varkey.contains("color"))
		{
			++numPalette;
		}
	}

	if (numPalette == 0) {
		player->sendSystemMessage("No customization options available on this droid"); // protocol droids
		return 0;
	}

	DroidObject* painted = cast<DroidObject*>(droid);
	if (painted != NULL){
		painted->refreshPaint();
	}

	ManagedReference<SuiListBox*> frameTrimSelector = new SuiListBox(player, SuiWindowType::CUSTOMIZE_KIT);
	frameTrimSelector->setUsingObject(player);
	frameTrimSelector->setCallback(new CustomDroidSuiCallback(server, numPalette, kitTano));
	frameTrimSelector->setUsingObject(target);
	frameTrimSelector->setPromptTitle("Customize");
	frameTrimSelector->setPromptText("Please select the customization action you would like to take");

	frameTrimSelector->addMenuItem("Color Frame");

	if (numPalette > 1 ) {
		frameTrimSelector->addMenuItem("Color Trim");
	}

	if (numPalette > 2 ) {
		frameTrimSelector->addMenuItem("Color Extra Trim");
	}

	frameTrimSelector->setCancelButton(true, "");
	frameTrimSelector->setOkButton(true, "@ok");

	ManagedReference<PlayerObject*> ghost = player->getPlayerObject();
	ghost->addSuiBox(frameTrimSelector);
	player->sendMessage(frameTrimSelector->generateMessage());

	return 0;
}
void PetManagerImplementation::handleChat(CreatureObject* speaker, AiAgent* pet, const String& message){
	if( speaker == NULL || pet == NULL )
		return;

	if( message.isEmpty() )
		return;

	if (pet->isDead() || pet->isIncapacitated())
		return;

	ManagedReference<PetControlDevice*> pcd = pet->getControlDevice().get().castTo<PetControlDevice*>();

	if( pcd == NULL )
		return;

	// Handle command training
	if( pcd->getTrainingCommand() > 0 ){
		bool ownerChat = handleCommandTraining( speaker, pet, message );
		if (ownerChat) {
			Locker locker(pcd);
			pcd->setTrainingCommand(0); // no longer training
		}

		return;
	}

	ManagedWeakReference< CreatureObject*> linkedCreature = pet->getLinkedCreature();
	if( linkedCreature == NULL )
		return;

	// Check if speaker has permission to command pet
	if( linkedCreature != speaker && !pcd->isFriend(speaker->getObjectID()))
		return;

	ManagedWeakReference<SceneObject*> speakerParent = speaker->getRootParent();
	ManagedWeakReference<SceneObject*> petParent = pet->getRootParent();

	// If speaker is mounted, pet must be outdoors
	if( speaker->isRidingMount() && petParent != NULL )
		return;

	// If speaker is unmounted, pet and speaker must both be outdoors or inside same building
	if( !speaker->isRidingMount() && speakerParent != petParent )
		return;

	// Handle trained command
	if( isTrainedCommand( pcd, STAY, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petstay"), "");
	}
	else if( isTrainedCommand( pcd, FOLLOW, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petfollow"), "", true);
	}
	else if( isTrainedCommand( pcd, STORE, message ) ){
		enqueueOwnerOnlyPetCommand(speaker, pet, STRING_HASHCODE("petstore"), "");
	}
	else if( isTrainedCommand( pcd, ATTACK, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petattack"), "");
	}
	else if( isTrainedCommand( pcd, GUARD, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petguard"), "", true);
	}
	else if( isTrainedCommand( pcd, FRIEND, message ) ){
		enqueueOwnerOnlyPetCommand(speaker, pet, STRING_HASHCODE("petfriend"), "");
	}
	else if( isTrainedCommand( pcd, FOLLOWOTHER, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petfollow"), "");
	}
	else if( isTrainedCommand( pcd, TRICK1, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("pettrick"), "1", true);
	}
	else if( isTrainedCommand( pcd, TRICK2, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("pettrick"), "2", true);
	}
	else if( isTrainedCommand( pcd, PATROL, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petpatrol"), "");
	}
	else if( isTrainedCommand( pcd, GETPATROLPOINT, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petgetpatrolpoint"), "", true);
	}
	else if( isTrainedCommand( pcd, CLEARPATROLPOINTS, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petclearpatrolpoints"), "", true);
	}
	else if( isTrainedCommand( pcd, FORMATION1, message ) ){
		speaker->sendSystemMessage("FORMATION2 pet command is not yet implemented.");
	}
	else if( isTrainedCommand( pcd, FORMATION2, message ) ){
		speaker->sendSystemMessage("FORMATION2 pet command is not yet implemented.");
	}
	else if( isTrainedCommand( pcd, SPECIAL_ATTACK1, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petspecialattack"), "1");
	}
	else if( isTrainedCommand( pcd, SPECIAL_ATTACK2, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petspecialattack"), "2");
	}
	else if( isTrainedCommand( pcd, RANGED_ATTACK, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petrangedattack"), "", true);
	}
	else if( isTrainedCommand( pcd, GROUP, message ) ){
		enqueueOwnerOnlyPetCommand(speaker, pet, STRING_HASHCODE("petgroup"), "");
	}
	else if( isTrainedCommand( pcd, RECHARGEOTHER, message ) ){
		enqueuePetCommand(speaker, pet, STRING_HASHCODE("petrechargeother"), "");
	}
	else if( isTrainedCommand( pcd, TRANSFER, message ) ){
		enqueueOwnerOnlyPetCommand(speaker, pet, STRING_HASHCODE("pettransfer"), "");
	}

	// Hand off to droid modules for handling
	if( pcd->getPetType() == PetManager::DROIDPET ){

		DroidObject* droidObject = cast<DroidObject*>(pet);
		if( droidObject != NULL ){
			droidObject->handleChat(speaker, message);
		}

	}

}
void PetControlDeviceImplementation::spawnObject(CreatureObject* player) {
	ZoneServer* zoneServer = getZoneServer();

	ManagedReference<TangibleObject*> controlledObject = this->controlledObject.get();

	if (controlledObject == NULL)
		return;

	if (!isASubChildOf(player))
		return;

	ManagedReference<TradeSession*> tradeContainer = player->getActiveSession(SessionFacadeType::TRADE).castTo<TradeSession*>();

	if (tradeContainer != NULL) {
		server->getZoneServer()->getPlayerManager()->handleAbortTradeMessage(player);
	}

	controlledObject->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
	ManagedReference<CreatureObject*> creature = NULL;

	if (controlledObject->isCreatureObject()) {
		creature = cast<CreatureObject*>(controlledObject.get());
		creature->setCreatureLink(player);
		creature->setControlDevice(_this.get());
		creature->setFaction(player->getFaction());
		creature->setObjectMenuComponent("PetMenuComponent");

		if (player->getPvpStatusBitmask() & CreatureFlag::PLAYER)
			creature->setPvpStatusBitmask(player->getPvpStatusBitmask() - CreatureFlag::PLAYER, true);
		else
			creature->setPvpStatusBitmask(player->getPvpStatusBitmask(), true);
	}

	Zone* zone = player->getZone();

	if (zone == NULL)
		return;

	ManagedReference<SceneObject*> parent = player->getParent();

	if (parent != NULL && parent->isCellObject())
		parent->transferObject(controlledObject, -1, true);
	else
		zone->transferObject(controlledObject, -1, true);

	updateStatus(1);

	if (petControlObserver != NULL)
		player->dropObserver(ObserverEventType::STARTCOMBAT, petControlObserver);

	AiAgent* pet = cast<AiAgent*>(creature.get());

	if (pet == NULL)
		return;

	ManagedReference<PlayerObject*> ghost = player->getPlayerObject();
	ghost->addToActivePets(pet);

	if (pet->isDroidObject()) {
		DroidObject* droid = cast<DroidObject*>(pet);

		if( droid == NULL )
			return;

		// Sanity check that there isn't another power task outstanding
		droid->removePendingTask( "droid_power" );

		// Submit new power task
		Reference<Task*> droidPowerTask = new DroidPowerTask( droid );
		droid->addPendingTask("droid_power", droidPowerTask, 120000); // 2 min

		if( droid->hasPower() ){
			// TODO Temporarily set to autofollow player
			droid->setFollowObject(player);
		}
		else{
			droid->handleLowPower();
		}

	} else {
		pet->setFollowObject(player);
	}

	// Not training any commands
	trainingCommand = 0;


}
ConversationScreen* PetTrainingScreenHandler::handleScreen(CreatureObject* conversingPlayer, CreatureObject* conversingNPC, int selectedOption, ConversationScreen* conversationScreen) {

	ManagedReference<PetControlDevice*> controller = conversingNPC->getControlDevice().get().castTo<PetControlDevice*>();
	if (controller == NULL) {
		return NULL;
	}

	if (conversationScreen->getScreenID() == "convoscreenpetinfo") {
		if(conversingNPC->isDroidObject()) {
			// we can technically just re-add the 4 options from base hireling
			DroidObject* droid = cast<DroidObject*>(conversingNPC);
			if (droid->getModule("repair_module") != NULL) {
				conversationScreen->addOption("@hireling/hireling:menu_repair_other","pet_repair_command");
			}
		}
	}

	Locker locker(controller);

	if (conversationScreen->getScreenID() == "pet_repair_command") {
		controller->setTrainingCommand(PetManager::REPAIR);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_formation_1_command") {
		controller->setTrainingCommand(PetManager::FORMATION1);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_formation_2_command") {
		controller->setTrainingCommand(PetManager::FORMATION2);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_attack_command") {
		controller->setTrainingCommand(PetManager::ATTACK);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_guard_command") {
		controller->setTrainingCommand(PetManager::GUARD);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_friend_command") {
		controller->setTrainingCommand(PetManager::FRIEND);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_transfer_command") {
		controller->setTrainingCommand(PetManager::TRANSFER);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_clear_patrol_points_command") {
		controller->setTrainingCommand(PetManager::CLEARPATROLPOINTS);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_get_patrol_point_command") {
		controller->setTrainingCommand(PetManager::GETPATROLPOINT);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_patrol_command") {
		controller->setTrainingCommand(PetManager::PATROL);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_stay_command") {
		controller->setTrainingCommand(PetManager::STAY);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_follow_command") {
		controller->setTrainingCommand(PetManager::FOLLOW);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_follow_other_command") {
		controller->setTrainingCommand(PetManager::FOLLOWOTHER);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_group_command") {
		controller->setTrainingCommand(PetManager::GROUP);
		return NULL;
	}
	if (conversationScreen->getScreenID() == "pet_release_command") {
		controller->setTrainingCommand(PetManager::STORE);
		return NULL;
	}

	locker.release();

	if (conversationScreen->getScreenID() == "pet_leave_group_command") {
		GroupObject* g = conversingNPC->getGroup();
		if (g != NULL) {
			g->removeMember(conversingNPC);
		}
		return NULL;
	}


	return conversationScreen;
}
void CreatureManagerImplementation::droidHarvest(Creature* creature, CreatureObject* droid, int selectedID, int harvestBonus) {
	// droid and creature are locked coming in.
	ManagedReference<CreatureObject*> owner = droid->getLinkedCreature();
	if (owner == NULL) {
		return;
	}
	Locker pLock(owner);
	Zone* zone = creature->getZone();

	if (zone == NULL || !creature->isCreature()) {
		return;
	}

	// this will perform a range check on the corpse to the droid
	if (!creature->canDroidHarvestMe(owner,droid)) {
		owner->sendSystemMessage("@pet/droid_modules:cannot_access_corpse");
		return;
	}

	ManagedReference<ResourceManager*> resourceManager = zone->getZoneServer()->getResourceManager();
	String restype = "";
	float quantity = 0;

	if (selectedID == 234) {
		restype = creature->getMeatType();
		quantity = creature->getMeatMax();
	} else if (selectedID == 235) {
		restype = creature->getHideType();
		quantity = creature->getHideMax();
	} else if (selectedID == 236) {
		restype = creature->getBoneType();
		quantity = creature->getBoneMax();
	}
	if(quantity == 0 || restype.isEmpty()) {
		owner->sendSystemMessage("Tried to harvest something this creature didn't have, please report this error");
		return;
	}
	int ownerSkill = owner->getSkillMod("creature_harvesting");
	int quantityExtracted = int(quantity * float(ownerSkill / 100.0f));
	// add in droid bonus
	quantityExtracted = MAX(quantityExtracted, 3);
	ManagedReference<ResourceSpawn*> resourceSpawn = resourceManager->getCurrentSpawn(restype, droid->getZone()->getZoneName());

	if (resourceSpawn == NULL) {
		owner->sendSystemMessage("Error: Server cannot locate a current spawn of " + restype);
		return;
	}

	float density = resourceSpawn->getDensityAt(droid->getZone()->getZoneName(), droid->getPositionX(), droid->getPositionY());

	String creatureHealth = "";

	if (density > 0.80f) {
		quantityExtracted = int(quantityExtracted * 1.25f);
		creatureHealth = "creature_quality_fat";
	} else if (density > 0.60f) {
		quantityExtracted = int(quantityExtracted * 1.00f);
		creatureHealth = "creature_quality_medium";
	} else if (density > 0.40f) {
		quantityExtracted = int(quantityExtracted * 0.75f);
		creatureHealth = "creature_quality_scrawny";
	} else {
		quantityExtracted = int(quantityExtracted * 0.50f);
		creatureHealth = "creature_quality_skinny";
	}

	float modifier = 1;
	int baseAmount = quantityExtracted;
	if (owner->isGrouped()) {
		modifier = owner->getGroup()->getGroupHarvestModifier(owner);

		quantityExtracted = (int)(quantityExtracted * modifier);
		if (owner->getGroup()->getGroupSize() > 2 ) {
			quantityExtracted -= quantityExtracted * 0.3; // 30% reduction
		}
	}

	if (creature->getParent().get() != NULL)
		quantityExtracted = 1;
	int droidBonus = DroidMechanics::determineDroidSkillBonus(ownerSkill,harvestBonus,quantityExtracted);

	quantityExtracted += droidBonus;
	// add to droid inventory if there is space available, otherwise to player
	DroidObject* pet = cast<DroidObject*>(droid);
	if (pet == NULL) {
		error("Incoming droid harvest call didnt include a droid!");
		return;
	}

	if (pet->hasStorage()) {
		bool didit = resourceManager->harvestResourceToPlayer(droid, resourceSpawn, quantityExtracted);
		if (!didit) {
			resourceManager->harvestResourceToPlayer(owner, resourceSpawn, quantityExtracted);
		}
	} else {
		resourceManager->harvestResourceToPlayer(owner, resourceSpawn, quantityExtracted);
	}

	/// Send System Messages
	StringIdChatParameter harvestMessage("skl_use", creatureHealth);

	harvestMessage.setDI(quantityExtracted);
	harvestMessage.setTU(resourceSpawn->getFinalClass());

	owner->sendSystemMessage(harvestMessage);

	/// Send bonus message
	if (modifier == 1.2f)
		owner->sendSystemMessage("@skl_use:group_harvest_bonus");
	else if (modifier == 1.3f)
		owner->sendSystemMessage("@skl_use:group_harvest_bonus_ranger");
	else if (modifier == 1.4f)
		owner->sendSystemMessage("@skl_use:group_harvest_bonus_masterranger");

	/// Send group spam
	if (owner->isGrouped()) {
		StringIdChatParameter bonusMessage("group", "notify_harvest_corpse");

		bonusMessage.setTU(droid->getDisplayedName());
		bonusMessage.setDI(quantityExtracted);
		bonusMessage.setTO(resourceSpawn->getFinalClass());
		bonusMessage.setTT(creature->getObjectNameStringIdFile(), creature->getObjectNameStringIdName());

		ChatSystemMessage* sysMessage = new ChatSystemMessage(bonusMessage);
		owner->getGroup()->broadcastMessage(owner, sysMessage, false);
	}

	ManagedReference<PlayerManager*> playerManager = zoneServer->getPlayerManager();

	int xp = creature->getLevel() * 5 + 19;

	if(playerManager != NULL)
		playerManager->awardExperience(owner, "scout", xp, true);

	creature->addAlreadyHarvested(owner);

	if (!creature->hasLoot() && creature->getBankCredits() < 1 && creature->getCashCredits() < 1 && !playerManager->canGroupMemberHarvestCorpse(owner, creature)) {
		Reference<DespawnCreatureTask*> despawn = creature->getPendingTask("despawn").castTo<DespawnCreatureTask*>();

		if (despawn != NULL) {
			despawn->cancel();

			despawn->reschedule(1000);
		}
	}


}