/// <inheritdoc /> public void ChangeJob(IPlayerEntity player, DefineJob.Job newJob) { if (!_gameResources.Jobs.TryGetValue(newJob, out JobData jobData)) { throw new KeyNotFoundException($"Cannot find job '{newJob}'."); } IEnumerable <SkillInfo> jobSkills = _skillSystem.GetSkillsByJob(newJob); var skillTree = new List <SkillInfo>(); foreach (SkillInfo skill in jobSkills) { SkillInfo playerSkill = player.SkillTree.GetSkill(skill.SkillId); if (playerSkill != null) { skillTree.Add(playerSkill); } else { skillTree.Add(new SkillInfo(skill.SkillId, player.PlayerData.Id, skill.Data)); } } player.PlayerData.JobData = jobData; player.SkillTree.Skills = skillTree.ToList(); _playerPacketFactory.SendPlayerJobUpdate(player); _specialEffectPacketFactory.SendSpecialEffect(player, DefineSpecialEffects.XI_GEN_LEVEL_UP01, false); }
/// <inheritdoc /> public void StartSpecialEffect(IWorldEntity entity, DefineSpecialEffects specialEffect, bool noFollowSfx) { _specialEffectPacketFactory.SendSpecialEffect(entity, specialEffect, noFollowSfx); }
/// <inheritdoc /> public void UpdateSkills(IPlayerEntity player, IReadOnlyDictionary <int, int> skillsToUpdate) { int requiredSkillPoints = 0; foreach (KeyValuePair <int, int> skill in skillsToUpdate) { int skillId = skill.Key; int skillLevel = skill.Value; SkillInfo playerSkill = player.SkillTree.GetSkill(skillId); if (playerSkill == null) { _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot find skill with id '{skillId}' for player '{player}'."); return; } if (playerSkill.Level == skillLevel) { // Skill hasn't change continue; } if (player.Object.Level < playerSkill.Data.RequiredLevel) { _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Player need to be level '{playerSkill.Data.RequiredLevel}' to learn this skill."); return; } if (!CheckRequiredSkill(playerSkill.Data.RequiredSkillId1, playerSkill.Data.RequiredSkillLevel1, skillsToUpdate)) { SkillData requiredSkill1 = _gameResources.Skills[playerSkill.Data.RequiredSkillId1]; _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Skill '{requiredSkill1.Name}' must be at least Lv.{requiredSkill1.RequiredSkillLevel1}"); return; } if (!CheckRequiredSkill(playerSkill.Data.RequiredSkillId2, playerSkill.Data.RequiredSkillLevel2, skillsToUpdate)) { SkillData requiredSkill2 = _gameResources.Skills[playerSkill.Data.RequiredSkillId2]; _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Skill '{requiredSkill2.Name}' must be at least Lv.{requiredSkill2.RequiredSkillLevel1}"); return; } if (skillLevel < 0 || skillLevel < playerSkill.Level || skillLevel > playerSkill.Data.MaxLevel) { _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. The skill level is out of bounds."); return; } if (!SkillPointUsage.TryGetValue(playerSkill.Data.JobType, out int requiredSkillPointAmount)) { _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Cannot find required skill point for job type '{playerSkill.Data.JobType}'."); return; } requiredSkillPoints += (skillLevel - playerSkill.Level) * requiredSkillPointAmount; } if (player.Statistics.SkillPoints < requiredSkillPoints) { _logger.LogError($"Cannot update skills for player '{player}'. Not enough skill points."); _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR); return; } player.Statistics.SkillPoints -= (ushort)requiredSkillPoints; foreach (KeyValuePair <int, int> skill in skillsToUpdate) { int skillId = skill.Key; int skillLevel = skill.Value; player.SkillTree.SetSkillLevel(skillId, skillLevel); } _specialEffectPacketFactory.SendSpecialEffect(player, DefineSpecialEffects.XI_SYS_EXCHAN01, false); _skillPacketFactory.SendSkillTreeUpdate(player); }