Exemplo n.º 1
0
bool SkillManager::awardSkill(const String& skillName, CreatureObject* creature, bool notifyClient, bool awardRequiredSkills, bool noXpRequired) {
	Skill* skill = skillMap.get(skillName.hashCode());

	if (skill == NULL)
		return false;

	Locker locker(creature);

	//Check for required skills.
	Vector<String>* requiredSkills = skill->getSkillsRequired();
	for (int i = 0; i < requiredSkills->size(); ++i) {
		String requiredSkillName = requiredSkills->get(i);
		Skill* requiredSkill = skillMap.get(requiredSkillName.hashCode());

		if (requiredSkill == NULL)
			continue;

		if (awardRequiredSkills)
			awardSkill(requiredSkillName, creature, notifyClient, awardRequiredSkills, noXpRequired);

		if (!creature->hasSkill(requiredSkillName))
			return false;
	}

	if (!canLearnSkill(skillName, creature, noXpRequired)) {
		return false;
	}

	//If they already have the skill, then return true.
	if (creature->hasSkill(skill->getSkillName()))
		return true;

	ManagedReference<PlayerObject*> ghost = creature->getPlayerObject();

	if (ghost != NULL) {
		//Withdraw skill points.
		ghost->addSkillPoints(-skill->getSkillPointsRequired());

		//Witdraw experience.
		if (!noXpRequired) {
			ghost->addExperience(skill->getXpType(), -skill->getXpCost(), true);
		}

		creature->addSkill(skill, notifyClient);

		//Add skill modifiers
		VectorMap<String, int>* skillModifiers = skill->getSkillModifiers();

		for (int i = 0; i < skillModifiers->size(); ++i) {
			VectorMapEntry<String, int>* entry = &skillModifiers->elementAt(i);
			creature->addSkillMod(SkillModManager::SKILLBOX, entry->getKey(), entry->getValue(), notifyClient);

		}

		//Add abilities
		Vector<String>* abilityNames = skill->getAbilities();
		addAbilities(ghost, *abilityNames, notifyClient);
		if (skill->isGodOnly()) {
			for (int i = 0; i < abilityNames->size(); ++i) {
				String ability = abilityNames->get(i);
				StringIdChatParameter params;
				params.setTU(ability);
				params.setStringId("ui", "skill_command_acquired_prose");

				creature->sendSystemMessage(params);
			}
		}

		//Add draft schematic groups
		Vector<String>* schematicsGranted = skill->getSchematicsGranted();
		SchematicMap::instance()->addSchematics(ghost, *schematicsGranted, notifyClient);

		//Update maximum experience.
		updateXpLimits(ghost);


		// Update Force Power Max.
		ghost->setForcePowerMax(creature->getSkillMod("jedi_force_power_max"), true);

		if (skillName.contains("master")) {
			ManagedReference<PlayerManager*> playerManager = creature->getZoneServer()->getPlayerManager();
			if (playerManager != NULL) {
				const Badge* badge = BadgeList::instance()->get(skillName);

				if (badge == NULL && skillName == "crafting_shipwright_master") {
					badge = BadgeList::instance()->get("crafting_shipwright");
				}

				if (badge != NULL) {
					playerManager->awardBadge(ghost, badge);
				}
			}
		}

		SkillList* list = creature->getSkillList();

		int totalSkillPointsWasted = 250;

		for (int i = 0; i < list->size(); ++i) {
			Skill* skill = list->get(i);

			totalSkillPointsWasted -= skill->getSkillPointsRequired();
		}

		if (ghost->getSkillPoints() != totalSkillPointsWasted) {
			creature->error("skill points mismatch calculated: " + String::valueOf(totalSkillPointsWasted) + " found: " + String::valueOf(ghost->getSkillPoints()));
			ghost->setSkillPoints(totalSkillPointsWasted);
		}

		ManagedReference<PlayerManager*> playerManager = creature->getZoneServer()->getPlayerManager();
		if (playerManager != NULL) {
			creature->setLevel(playerManager->calculatePlayerLevel(creature));
		}
	}

	/// Update client with new values for things like Terrain Negotiation
	CreatureObjectDeltaMessage4* msg4 = new CreatureObjectDeltaMessage4(creature);
	msg4->updateAccelerationMultiplierBase();
	msg4->updateAccelerationMultiplierMod();
	msg4->updateSpeedMultiplierBase();
	msg4->updateSpeedMultiplierMod();
	msg4->updateRunSpeed();
	msg4->updateTerrainNegotiation();
	msg4->close();
	creature->sendMessage(msg4);

	SkillModManager::instance()->verifySkillBoxSkillMods(creature);

	return true;
}
Exemplo n.º 2
0
std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills() const
{
	std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible
	if (!skillsInfo.wisdomCounter)
	{
		if (cb->isAllowed(2, SecondarySkill::WISDOM) && !getSecSkillLevel(SecondarySkill::WISDOM))
			obligatorySkills.push_back(SecondarySkill::WISDOM);
	}
	if (!skillsInfo.magicSchoolCounter)
	{
		std::vector<SecondarySkill> ss =
		{
			SecondarySkill::FIRE_MAGIC, SecondarySkill::AIR_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC
		};

		std::shuffle(ss.begin(), ss.end(), skillsInfo.rand.getStdGenerator());

		for (auto skill : ss)
		{
			if (cb->isAllowed(2, skill) && !getSecSkillLevel(skill)) //only schools hero doesn't know yet
			{
				obligatorySkills.push_back(skill);
				break; //only one
			}
		}
	}

	std::vector<SecondarySkill> skills;
	//picking sec. skills for choice
	std::set<SecondarySkill> basicAndAdv, expert, none;
	for(int i=0;i<GameConstants::SKILL_QUANTITY;i++)
		if (cb->isAllowed(2,i))
			none.insert(SecondarySkill(i));

	for(auto & elem : secSkills)
	{
		if(elem.second < SecSkillLevel::EXPERT)
			basicAndAdv.insert(elem.first);
		else
			expert.insert(elem.first);
		none.erase(elem.first);
	}
	for (auto s : obligatorySkills) //don't duplicate them
	{
		none.erase (s);
		basicAndAdv.erase (s);
		expert.erase (s);
	}

	//first offered skill:
	// 1) give obligatory skill
	// 2) give any other new skill
	// 3) upgrade existing
	if (canLearnSkill() && obligatorySkills.size() > 0)
	{
		skills.push_back (obligatorySkills[0]);
	}
	else if(none.size() && canLearnSkill()) //hero have free skill slot
	{
		skills.push_back(type->heroClass->chooseSecSkill(none, skillsInfo.rand)); //new skill
		none.erase(skills.back());
	}
	else if(!basicAndAdv.empty())
	{
		skills.push_back(type->heroClass->chooseSecSkill(basicAndAdv, skillsInfo.rand)); //upgrade existing
		basicAndAdv.erase(skills.back());
	}

	//second offered skill:
	//1) upgrade existing
	//2) give obligatory skill
	//3) give any other new skill
	if(!basicAndAdv.empty())
	{
		SecondarySkill s = type->heroClass->chooseSecSkill(basicAndAdv, skillsInfo.rand);//upgrade existing
		skills.push_back(s);
		basicAndAdv.erase(s);
	}
	else if (canLearnSkill() && obligatorySkills.size() > 1)
	{
		skills.push_back (obligatorySkills[1]);
	}
	else if(none.size() && canLearnSkill())
	{
		skills.push_back(type->heroClass->chooseSecSkill(none, skillsInfo.rand)); //give new skill
		none.erase(skills.back());
	}

	if (skills.size() == 2) // Fix for #1868 to avoid changing logic (possibly causing bugs in process)
		std::swap(skills[0], skills[1]);
	return skills;
}