<commit_before>/*
 * EntertainingSessionImplementation.cpp
 *
 *  Created on: 20/08/2010
 *      Author: victor
 */

#include "server/zone/objects/player/sessions/EntertainingSession.h"
#include "server/zone/managers/skill/SkillManager.h"
#include "server/zone/managers/skill/Performance.h"
#include "server/zone/managers/skill/PerformanceManager.h"
#include "server/zone/managers/player/PlayerManager.h"
#include "server/zone/objects/group/GroupObject.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/Races.h"
#include "server/zone/objects/player/events/EntertainingSessionTask.h"
#include "server/zone/objects/player/EntertainingObserver.h"
#include "server/zone/objects/creature/CreatureAttribute.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/tangible/Instrument.h"
#include "server/zone/packets/object/Flourish.h"
#include "server/zone/packets/creature/CreatureObjectDeltaMessage6.h"
#include "server/zone/objects/mission/MissionObject.h"
#include "server/zone/objects/mission/EntertainerMissionObjective.h"
#include "server/zone/objects/creature/buffs/PerformanceBuff.h"
#include "server/zone/objects/creature/buffs/PerformanceBuffType.h"

void EntertainingSessionImplementation::doEntertainerPatronEffects() {
	ManagedReference<CreatureObject*> creo = entertainer.get();

	if (creo == NULL)
		return;

	Locker locker(creo);
	//info("EntertainingSessionImplementation::doEntertainerPatronEffects() begin");

	//**DECLARATIONS**
	VectorMap<ManagedReference<CreatureObject*>, EntertainingData>* patrons = NULL;

	SkillManager* skillManager = creo->getZoneServer()->getSkillManager();

	PerformanceManager* performanceManager = skillManager->getPerformanceManager();
	Performance* performance = NULL;

	float enhancementSkill = 0.0f;
	float woundHealingSkill = 0.0f;
	float playerShockHealingSkill = 0.0f;
	float buildingShockHealingSkill = creo->getSkillMod("private_med_battle_fatigue");
	int campModtemp = 100;

	/*if (entertainer->isInCamp()) {
			campModtemp = getCampModifier();
		}*/

	if (performanceName == "")
		return;

	ManagedReference<Instrument*> instrument = getInstrument(creo);

	//**LOAD PATRONS, GET THE PERFORMANCE AND ENT'S HEALING SKILL.**
	if (dancing) {
		patrons = &watchers;
		performance = performanceManager->getDance(performanceName);
		enhancementSkill = (float) creo->getSkillMod("healing_dance_mind");
		woundHealingSkill = (float) creo->getSkillMod("healing_dance_wound");
		playerShockHealingSkill = (float) creo->getSkillMod("healing_dance_shock");
	} else if (playingMusic && instrument != NULL) {
		patrons = &listeners;
		performance = performanceManager->getSong(performanceName, instrument->getInstrumentType());
		enhancementSkill = (float) creo->getSkillMod("healing_music_mind");
		woundHealingSkill = (float) creo->getSkillMod("healing_music_wound");
		playerShockHealingSkill = (float) creo->getSkillMod("healing_music_shock");

	} else {
		cancelSession();
		return;
	}

	if (performance == NULL) {
		return;
	}

	//**DETERMINE WOUND HEAL AMOUNTS.**
	int woundHeal = ceil(performance->getHealMindWound() * (woundHealingSkill / 100.0f));
	int shockHeal = ceil(performance->getHealShockWound() * ((playerShockHealingSkill + buildingShockHealingSkill) / 100.0f));

	//**ENTERTAINER HEALS THEIR OWN MIND.**
	healWounds(creo, woundHeal*(flourishCount+1), shockHeal*(flourishCount+1));

	//**APPLY EFFECTS TO PATRONS.**
	if (patrons != NULL && patrons->size() > 0) {

		for (int i = 0; i < patrons->size(); ++i) {
			ManagedReference<CreatureObject*> patron = patrons->elementAt(i).getKey();

			try {
				//**VERIFY THE PATRON IS NOT ON THE DENY SERVICE LIST

				if (creo->isInRange(patron, 10.0f)) {
					healWounds(patron, woundHeal*(flourishCount+1), shockHeal*(flourishCount+1));
					increaseEntertainerBuff(patron);

				} else { //patron is not in range, force to stop listening
					ManagedReference<PlayerManager*> playerManager = patron->getZoneServer()->getPlayerManager();

					Locker locker(patron, entertainer.get());

					if (dancing) {
						if (playerManager != NULL)
							playerManager->stopWatch(patron, creo->getObjectID(), true, false, false, true);

						if (!patron->isListening())
							sendEntertainmentUpdate(patron, 0, "", true);

					} else if (playingMusic) {
						if (playerManager != NULL)
							playerManager->stopListen(patron, creo->getObjectID(), true, false, false, true);

						if (!patron->isWatching())
							sendEntertainmentUpdate(patron, 0, "", true);
					}
				}

			} catch (Exception& e) {
				error("Unreported exception caught in EntertainingSessionImplementation::doEntertainerPatronEffects()");
			}
		}
	} //else
	//System::out << "There are no patrons.\n";


	info("EntertainingSessionImplementation::doEntertainerPatronEffects() end");
}

bool EntertainingSessionImplementation::isInEntertainingBuilding(CreatureObject* creature) {
	ManagedReference<SceneObject*> root = creature->getRootParent();

	if (root != NULL) {
		uint32 gameObjectType = root->getGameObjectType();

		switch (gameObjectType) {
		case SceneObjectType::RECREATIONBUILDING:
		case SceneObjectType::HOTELBUILDING:
		case SceneObjectType::THEATERBUILDING:
			return true;
		}
	}

	return false;
}

void EntertainingSessionImplementation::healWounds(CreatureObject* creature, float woundHeal, float shockHeal) {
	float amountHealed = 0;

	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker clocker(creature, entertainer);

	if(!canGiveEntertainBuff())
		return;

	if(isInDenyServiceList(creature))
		return;

	if(shockHeal > 0 && creature->getShockWounds() > 0 && canHealBattleFatigue()) {
		creature->addShockWounds(-shockHeal, true, false);
		amountHealed += shockHeal;
	}
	if(woundHeal > 0 && (creature->getWounds(CreatureAttribute::MIND) > 0
			|| creature->getWounds(CreatureAttribute::FOCUS) > 0
			|| creature->getWounds(CreatureAttribute::WILLPOWER) > 0)) {
		creature->healWound(entertainer, CreatureAttribute::MIND, woundHeal, true, false);
		creature->healWound(entertainer, CreatureAttribute::FOCUS, woundHeal, true, false);
		creature->healWound(entertainer, CreatureAttribute::WILLPOWER, woundHeal, true, false);

		amountHealed += woundHeal;
	}

	clocker.release();

	if(entertainer->getGroup() != NULL)
		addHealingXpGroup(amountHealed);
	else
		addHealingXp(amountHealed);

}

void EntertainingSessionImplementation::addHealingXpGroup(int xp) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	ManagedReference<GroupObject*> group = entertainer->getGroup();
	int groupSize = group->getGroupSize();
	ManagedReference<PlayerManager*> playerManager = entertainer->getZoneServer()->getPlayerManager();

	for(int i = 0; i < groupSize; ++i) {
		ManagedReference<CreatureObject*> groupMember = group->getGroupMember(i)->isPlayerCreature() ? group->getGroupMember(i).castTo<CreatureObject*>() : NULL;

		if (groupMember != NULL) {
			Locker clocker(groupMember, entertainer);

			if (groupMember->isEntertaining() && groupMember->isInRange(entertainer, 40.0f)
					&& groupMember->hasSkill("social_entertainer_novice")) {
				String healxptype("entertainer_healing");

				if (playerManager != NULL)
					playerManager->awardExperience(groupMember, healxptype, xp, true);

			}
		}

	}
}

void EntertainingSessionImplementation::activateAction() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	if (entertainer == NULL)
		return;

	Locker locker(entertainer);

	if (!isDancing() && !isPlayingMusic()) {
		return; // don't tick action if they aren't doing anything
	}

	doEntertainerPatronEffects();
	awardEntertainerExperience();
	doPerformanceAction();


	startTickTask();

	entertainer->info("EntertainerEvent completed.");
}

void EntertainingSessionImplementation::startTickTask() {
	if (tickTask == NULL) {
		tickTask = new EntertainingSessionTask(_this.get());
	}

	if (!tickTask->isScheduled()) {
		tickTask->schedule(10000);
	}
}

void EntertainingSessionImplementation::doPerformanceAction() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	if (entertainer == NULL)
		return;

	Locker locker(entertainer);

	Performance* performance = NULL;

	PerformanceManager* performanceManager = SkillManager::instance()->getPerformanceManager();
	ManagedReference<Instrument*> instrument = getInstrument(entertainer);

	if (isDancing())
		performance = performanceManager->getDance(performanceName);
	else if (isPlayingMusic() && instrument)
		performance = performanceManager->getSong(performanceName, instrument->getInstrumentType());
	else {
		cancelSession();
		return;
	}

	if (performance == NULL) { // shouldn't happen
		StringBuffer msg;
		msg << "Performance was null.  Please report to www.swgemu.com/bugs ! Name: " << performanceName << " and Type: " << dec << instrument->getInstrumentType();

		entertainer->sendSystemMessage(msg.toString());
		return;
	}

	int actionDrain = performance->getActionPointsPerLoop();

	//Adjust cost based upon player's quickness
	actionDrain = entertainer->calculateCostAdjustment(CreatureAttribute::QUICKNESS, actionDrain);

	if (entertainer->getHAM(CreatureAttribute::ACTION) <= actionDrain) {
		if (isDancing()) {
			stopDancing();
			entertainer->sendSystemMessage("@performance:dance_too_tired");
		}

		if (isPlayingMusic()) {
			stopPlayingMusic();
			entertainer->sendSystemMessage("@performance:music_too_tired");
		}
	} else {
		entertainer->inflictDamage(entertainer, CreatureAttribute::ACTION, actionDrain, false, true);
	}
}

Instrument* EntertainingSessionImplementation::getInstrument(CreatureObject* creature) {
	//all equipable instruments are in hold_r

	if (targetInstrument) {
		ManagedReference<SceneObject*> target = creature->getZoneServer()->getObject(creature->getTargetID());

		if (target == NULL)
			return NULL;

		Instrument* instrument = dynamic_cast<Instrument*>(target.get());

		if (externalInstrument != NULL && externalInstrument != instrument)
			return NULL;
		else
			return instrument;
	} else {
		SceneObject* object = creature->getSlottedObject("hold_r");

		return dynamic_cast<Instrument*>(object);
	}
}

void EntertainingSessionImplementation::stopPlayingMusic() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	if (!playingMusic)
		return;

	playingMusic = false;
	entertainer->sendSystemMessage("@performance:music_stop_self");

	sendEntertainingUpdate(entertainer, 0.8025000095f, entertainer->getPerformanceAnimation(), 0, 0);

	performanceName = "";
	entertainer->setListenToID(0);

	if (entertainer->getPosture() == CreaturePosture::SKILLANIMATING)
		entertainer->setPosture(CreaturePosture::UPRIGHT);

	if (externalInstrument != NULL && externalInstrument->isBeingUsed())
		externalInstrument->setBeingUsed(false);

	externalInstrument = NULL;

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

	while (listeners.size() > 0) {
		ManagedReference<CreatureObject*> listener = listeners.elementAt(0).getKey();

		Locker clocker(listener, entertainer);

		playerManager->stopListen(listener, entertainer->getObjectID(), true, true, false);

		if (!listener->isWatching())
			sendEntertainmentUpdate(listener, 0, "", true);

		listeners.drop(listener);
	}

	if (tickTask != NULL && tickTask->isScheduled())
		tickTask->cancel();

	targetInstrument = false;
	updateEntertainerMissionStatus(false, MissionObject::MUSICIAN);

	entertainer->notifyObservers(ObserverEventType::STOPENTERTAIN, entertainer);

	entertainer->dropObserver(ObserverEventType::POSTURECHANGED, observer);

	ManagedReference<GroupObject*> group = entertainer->getGroup();

	if (group != NULL) {
		bool otherPlaying = group->isOtherMemberPlayingMusic(entertainer);

		if (!otherPlaying) {
			Locker locker(group);

			group->setBandSong("");
		}
	}

	if (!dancing && !playingMusic) {
		ManagedReference<PlayerObject*> entPlayer = entertainer->getPlayerObject();
		if (entPlayer != NULL && entPlayer->getPerformanceBuffTarget() != 0)
			entPlayer->setPerformanceBuffTarget(0);

		entertainer->dropActiveSession(SessionFacadeType::ENTERTAINING);
	}
}

void EntertainingSessionImplementation::startDancing(const String& dance, const String& animation) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	sendEntertainingUpdate(entertainer, /*0x3C4CCCCD*/0.0125, animation, 0x07339FF8, 0xDD);
	performanceName = dance;
	dancing = true;

	entertainer->sendSystemMessage("@performance:dance_start_self");

	updateEntertainerMissionStatus(true, MissionObject::DANCER);

	entertainer->notifyObservers(ObserverEventType::STARTENTERTAIN, entertainer);

	startEntertaining();
}

void EntertainingSessionImplementation::startPlayingMusic(const String& song, const String& instrumentAnimation, int instrid) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	ManagedReference<GroupObject*> group = entertainer->getGroup();

	if (group != NULL) {
		if (group->getBandSong() != song)

			Locker locker(group);

			group->setBandSong(song);
	}
<commit_msg>[Fixed] stability issue<commit_after>/*
 * EntertainingSessionImplementation.cpp
 *
 *  Created on: 20/08/2010
 *      Author: victor
 */

#include "server/zone/objects/player/sessions/EntertainingSession.h"
#include "server/zone/managers/skill/SkillManager.h"
#include "server/zone/managers/skill/Performance.h"
#include "server/zone/managers/skill/PerformanceManager.h"
#include "server/zone/managers/player/PlayerManager.h"
#include "server/zone/objects/group/GroupObject.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/Races.h"
#include "server/zone/objects/player/events/EntertainingSessionTask.h"
#include "server/zone/objects/player/EntertainingObserver.h"
#include "server/zone/objects/creature/CreatureAttribute.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/tangible/Instrument.h"
#include "server/zone/packets/object/Flourish.h"
#include "server/zone/packets/creature/CreatureObjectDeltaMessage6.h"
#include "server/zone/objects/mission/MissionObject.h"
#include "server/zone/objects/mission/EntertainerMissionObjective.h"
#include "server/zone/objects/creature/buffs/PerformanceBuff.h"
#include "server/zone/objects/creature/buffs/PerformanceBuffType.h"

void EntertainingSessionImplementation::doEntertainerPatronEffects() {
	ManagedReference<CreatureObject*> creo = entertainer.get();

	if (creo == NULL)
		return;

	Locker locker(creo);
	//info("EntertainingSessionImplementation::doEntertainerPatronEffects() begin");

	//**DECLARATIONS**
	VectorMap<ManagedReference<CreatureObject*>, EntertainingData>* patrons = NULL;

	SkillManager* skillManager = creo->getZoneServer()->getSkillManager();

	PerformanceManager* performanceManager = skillManager->getPerformanceManager();
	Performance* performance = NULL;

	float enhancementSkill = 0.0f;
	float woundHealingSkill = 0.0f;
	float playerShockHealingSkill = 0.0f;
	float buildingShockHealingSkill = creo->getSkillMod("private_med_battle_fatigue");
	int campModtemp = 100;

	/*if (entertainer->isInCamp()) {
			campModtemp = getCampModifier();
		}*/

	if (performanceName == "")
		return;

	ManagedReference<Instrument*> instrument = getInstrument(creo);

	//**LOAD PATRONS, GET THE PERFORMANCE AND ENT'S HEALING SKILL.**
	if (dancing) {
		patrons = &watchers;
		performance = performanceManager->getDance(performanceName);
		enhancementSkill = (float) creo->getSkillMod("healing_dance_mind");
		woundHealingSkill = (float) creo->getSkillMod("healing_dance_wound");
		playerShockHealingSkill = (float) creo->getSkillMod("healing_dance_shock");
	} else if (playingMusic && instrument != NULL) {
		patrons = &listeners;
		performance = performanceManager->getSong(performanceName, instrument->getInstrumentType());
		enhancementSkill = (float) creo->getSkillMod("healing_music_mind");
		woundHealingSkill = (float) creo->getSkillMod("healing_music_wound");
		playerShockHealingSkill = (float) creo->getSkillMod("healing_music_shock");

	} else {
		cancelSession();
		return;
	}

	if (performance == NULL) {
		return;
	}

	//**DETERMINE WOUND HEAL AMOUNTS.**
	int woundHeal = ceil(performance->getHealMindWound() * (woundHealingSkill / 100.0f));
	int shockHeal = ceil(performance->getHealShockWound() * ((playerShockHealingSkill + buildingShockHealingSkill) / 100.0f));

	//**ENTERTAINER HEALS THEIR OWN MIND.**
	healWounds(creo, woundHeal*(flourishCount+1), shockHeal*(flourishCount+1));

	//**APPLY EFFECTS TO PATRONS.**
	if (patrons != NULL && patrons->size() > 0) {

		for (int i = 0; i < patrons->size(); ++i) {
			ManagedReference<CreatureObject*> patron = patrons->elementAt(i).getKey();

			try {
				//**VERIFY THE PATRON IS NOT ON THE DENY SERVICE LIST

				if (creo->isInRange(patron, 10.0f)) {
					healWounds(patron, woundHeal*(flourishCount+1), shockHeal*(flourishCount+1));
					increaseEntertainerBuff(patron);

				} else { //patron is not in range, force to stop listening
					ManagedReference<PlayerManager*> playerManager = patron->getZoneServer()->getPlayerManager();

					Locker locker(patron, entertainer.get());

					if (dancing) {
						if (playerManager != NULL)
							playerManager->stopWatch(patron, creo->getObjectID(), true, false, false, true);

						if (!patron->isListening())
							sendEntertainmentUpdate(patron, 0, "", true);

					} else if (playingMusic) {
						if (playerManager != NULL)
							playerManager->stopListen(patron, creo->getObjectID(), true, false, false, true);

						if (!patron->isWatching())
							sendEntertainmentUpdate(patron, 0, "", true);
					}
				}

			} catch (Exception& e) {
				error("Unreported exception caught in EntertainingSessionImplementation::doEntertainerPatronEffects()");
			}
		}
	} //else
	//System::out << "There are no patrons.\n";


	info("EntertainingSessionImplementation::doEntertainerPatronEffects() end");
}

bool EntertainingSessionImplementation::isInEntertainingBuilding(CreatureObject* creature) {
	ManagedReference<SceneObject*> root = creature->getRootParent();

	if (root != NULL) {
		uint32 gameObjectType = root->getGameObjectType();

		switch (gameObjectType) {
		case SceneObjectType::RECREATIONBUILDING:
		case SceneObjectType::HOTELBUILDING:
		case SceneObjectType::THEATERBUILDING:
			return true;
		}
	}

	return false;
}

void EntertainingSessionImplementation::healWounds(CreatureObject* creature, float woundHeal, float shockHeal) {
	float amountHealed = 0;

	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker clocker(creature, entertainer);

	if(!canGiveEntertainBuff())
		return;

	if(isInDenyServiceList(creature))
		return;

	if(shockHeal > 0 && creature->getShockWounds() > 0 && canHealBattleFatigue()) {
		creature->addShockWounds(-shockHeal, true, false);
		amountHealed += shockHeal;
	}
	if(woundHeal > 0 && (creature->getWounds(CreatureAttribute::MIND) > 0
			|| creature->getWounds(CreatureAttribute::FOCUS) > 0
			|| creature->getWounds(CreatureAttribute::WILLPOWER) > 0)) {
		creature->healWound(entertainer, CreatureAttribute::MIND, woundHeal, true, false);
		creature->healWound(entertainer, CreatureAttribute::FOCUS, woundHeal, true, false);
		creature->healWound(entertainer, CreatureAttribute::WILLPOWER, woundHeal, true, false);

		amountHealed += woundHeal;
	}

	clocker.release();

	if(entertainer->getGroup() != NULL)
		addHealingXpGroup(amountHealed);
	else
		addHealingXp(amountHealed);

}

void EntertainingSessionImplementation::addHealingXpGroup(int xp) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	ManagedReference<GroupObject*> group = entertainer->getGroup();
	int groupSize = group->getGroupSize();
	ManagedReference<PlayerManager*> playerManager = entertainer->getZoneServer()->getPlayerManager();

	for(int i = 0; i < groupSize; ++i) {
		ManagedReference<CreatureObject*> groupMember = group->getGroupMember(i)->isPlayerCreature() ? group->getGroupMember(i).castTo<CreatureObject*>() : NULL;

		if (groupMember != NULL) {
			Locker clocker(groupMember, entertainer);

			if (groupMember->isEntertaining() && groupMember->isInRange(entertainer, 40.0f)
					&& groupMember->hasSkill("social_entertainer_novice")) {
				String healxptype("entertainer_healing");

				if (playerManager != NULL)
					playerManager->awardExperience(groupMember, healxptype, xp, true);

			}
		}

	}
}

void EntertainingSessionImplementation::activateAction() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	if (entertainer == NULL)
		return;

	Locker locker(entertainer);

	if (!isDancing() && !isPlayingMusic()) {
		return; // don't tick action if they aren't doing anything
	}

	doEntertainerPatronEffects();
	awardEntertainerExperience();
	doPerformanceAction();


	startTickTask();

	entertainer->info("EntertainerEvent completed.");
}

void EntertainingSessionImplementation::startTickTask() {
	if (tickTask == NULL) {
		tickTask = new EntertainingSessionTask(_this.get());
	}

	if (!tickTask->isScheduled()) {
		tickTask->schedule(10000);
	}
}

void EntertainingSessionImplementation::doPerformanceAction() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	if (entertainer == NULL)
		return;

	Locker locker(entertainer);

	Performance* performance = NULL;

	PerformanceManager* performanceManager = SkillManager::instance()->getPerformanceManager();
	ManagedReference<Instrument*> instrument = getInstrument(entertainer);

	if (isDancing())
		performance = performanceManager->getDance(performanceName);
	else if (isPlayingMusic() && instrument)
		performance = performanceManager->getSong(performanceName, instrument->getInstrumentType());
	else {
		cancelSession();
		return;
	}

	if (performance == NULL) { // shouldn't happen
		StringBuffer msg;
		msg << "Performance was null.  Please report to www.swgemu.com/bugs ! Name: " << performanceName << " and Type: " << dec << instrument->getInstrumentType();

		entertainer->sendSystemMessage(msg.toString());
		return;
	}

	int actionDrain = performance->getActionPointsPerLoop();

	//Adjust cost based upon player's quickness
	actionDrain = entertainer->calculateCostAdjustment(CreatureAttribute::QUICKNESS, actionDrain);

	if (entertainer->getHAM(CreatureAttribute::ACTION) <= actionDrain) {
		if (isDancing()) {
			stopDancing();
			entertainer->sendSystemMessage("@performance:dance_too_tired");
		}

		if (isPlayingMusic()) {
			stopPlayingMusic();
			entertainer->sendSystemMessage("@performance:music_too_tired");
		}
	} else {
		entertainer->inflictDamage(entertainer, CreatureAttribute::ACTION, actionDrain, false, true);
	}
}

Instrument* EntertainingSessionImplementation::getInstrument(CreatureObject* creature) {
	//all equipable instruments are in hold_r

	if (targetInstrument) {
		ManagedReference<SceneObject*> target = creature->getZoneServer()->getObject(creature->getTargetID());

		if (target == NULL)
			return NULL;

		Instrument* instrument = dynamic_cast<Instrument*>(target.get());

		if (externalInstrument != NULL && externalInstrument != instrument)
			return NULL;
		else
			return instrument;
	} else {
		SceneObject* object = creature->getSlottedObject("hold_r");

		return dynamic_cast<Instrument*>(object);
	}
}

void EntertainingSessionImplementation::stopPlayingMusic() {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	if (!playingMusic)
		return;

	playingMusic = false;
	entertainer->sendSystemMessage("@performance:music_stop_self");

	sendEntertainingUpdate(entertainer, 0.8025000095f, entertainer->getPerformanceAnimation(), 0, 0);

	performanceName = "";
	entertainer->setListenToID(0);

	if (entertainer->getPosture() == CreaturePosture::SKILLANIMATING)
		entertainer->setPosture(CreaturePosture::UPRIGHT);

	if (externalInstrument != NULL && externalInstrument->isBeingUsed())
		externalInstrument->setBeingUsed(false);

	externalInstrument = NULL;

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

	while (listeners.size() > 0) {
		ManagedReference<CreatureObject*> listener = listeners.elementAt(0).getKey();

		Locker clocker(listener, entertainer);

		playerManager->stopListen(listener, entertainer->getObjectID(), true, true, false);

		if (!listener->isWatching())
			sendEntertainmentUpdate(listener, 0, "", true);

		listeners.drop(listener);
	}

	if (tickTask != NULL && tickTask->isScheduled())
		tickTask->cancel();

	targetInstrument = false;
	updateEntertainerMissionStatus(false, MissionObject::MUSICIAN);

	entertainer->notifyObservers(ObserverEventType::STOPENTERTAIN, entertainer);

	entertainer->dropObserver(ObserverEventType::POSTURECHANGED, observer);

	ManagedReference<GroupObject*> group = entertainer->getGroup();

	if (group != NULL) {
		bool otherPlaying = group->isOtherMemberPlayingMusic(entertainer);

		if (!otherPlaying) {
			Locker locker(group);

			group->setBandSong("");
		}
	}

	if (!dancing && !playingMusic) {
		ManagedReference<PlayerObject*> entPlayer = entertainer->getPlayerObject();
		if (entPlayer != NULL && entPlayer->getPerformanceBuffTarget() != 0)
			entPlayer->setPerformanceBuffTarget(0);

		entertainer->dropActiveSession(SessionFacadeType::ENTERTAINING);
	}
}

void EntertainingSessionImplementation::startDancing(const String& dance, const String& animation) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	sendEntertainingUpdate(entertainer, /*0x3C4CCCCD*/0.0125, animation, 0x07339FF8, 0xDD);
	performanceName = dance;
	dancing = true;

	entertainer->sendSystemMessage("@performance:dance_start_self");

	updateEntertainerMissionStatus(true, MissionObject::DANCER);

	entertainer->notifyObservers(ObserverEventType::STARTENTERTAIN, entertainer);

	startEntertaining();
}

void EntertainingSessionImplementation::startPlayingMusic(const String& song, const String& instrumentAnimation, int instrid) {
	ManagedReference<CreatureObject*> entertainer = this->entertainer.get();

	Locker locker(entertainer);

	ManagedReference<GroupObject*> group = entertainer->getGroup();

	if (group != NULL) {
		if (group->getBandSong() != song)

			Locker clocker(group, entertainer);

			group->setBandSong(song);
	}

{'fraction_non_alphanumeric': 0.13322492815005293, 'fraction_numerical': 0.0068068370896989866, 'mean_word_length': 6.139578833693305, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 281, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '21786', 'n_tokens_mistral': 9218, 'n_tokens_neox': 8243, 'n_words': 1431}