// public override bool WhisperReceive(GameLiving source, string text) // string tmpStr = player.Client.Account.Characters[player.Client.ActiveCharIndex].SerializedSpecs; // { // if (!base.WhisperReceive(source, text) || !(source is GamePlayer)) // return false; // GamePlayer player = source as GamePlayer; // } // return false; public override bool Interact(GamePlayer player) { string tmpStr = player.Client.Account.Characters[player.Client.ActiveCharIndex].SerializedSpecs.Replace(@";", ",").Replace(@"|", ","); string[] values = {}; foreach (string spec in tmpStr.SplitCSV()) { values = spec.Split(','); } if (values.Length >= 2) { for (var i = 0; i < values.Length; i++) { Specialization tempSpec = SkillBase.GetSpecialization(values[i]); i++; if (tempSpec != null) { if (tempSpec.AllowSave) { int level; level = player.Level; if (player.HasSpecialization(tempSpec.KeyName)) { player.GetSpecializationByName(tempSpec.KeyName).Level = level; } else { tempSpec.Level = level; player.AddSpecialization(tempSpec); } } player.Out.SendUpdatePoints(); player.Out.SendUpdatePlayerSkills(); player.SaveIntoDatabase(); player.UpdatePlayerStatus(); SayTo(player, "Updated spec levels."); } } } return(false); }
/// <summary> /// Add all spell-lines and other things that are new when this skill is trained /// </summary> /// <param name="player">player to modify</param> /// <param name="skill">The skill that is trained</param> public override void OnSkillTrained(GamePlayer player, Specialization skill) { base.OnSkillTrained(player, skill); // BD subpet spells can be scaled with the BD's spec as a cap, so when a BD // trains, we have to re-scale spells for subpets from that spec. if (DOL.GS.ServerProperties.Properties.PET_SCALE_SPELL_MAX_LEVEL > 0 && DOL.GS.ServerProperties.Properties.PET_CAP_BD_MINION_SPELL_SCALING_BY_SPEC && player.ControlledBrain != null && player.ControlledBrain.Body is GamePet pet) { foreach (ABrain subBrain in pet.ControlledNpcList) { if (subBrain != null && subBrain.Body is BDSubPet subPet && subPet.PetSpecLine == skill.KeyName) { subPet.SortSpells(); } } } }
public override bool WhisperReceive(GameLiving source, string text) { if (!base.WhisperReceive(source, text) || !(source is GamePlayer)) { return(false); } GamePlayer player = source as GamePlayer; if (text.Length > 1) { Specialization tempSpec = SkillBase.GetSpecialization(text); player.Out.SendCustomDialog("CAUTION: All spec removals final. Do you want to remove " + tempSpec.KeyName + "?", new CustomDialogResponse(PlayerResponse)); SELECTED_SPEC = tempSpec.KeyName; } return(false); }
public void TrainSpecLine(GamePlayer player, string line, int points) { if (player == null) { return; } if (!(player.TargetObject is GameTrainer)) { player.Out.SendMessage("You must have your trainer targetted to be trained in a specialization line.", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if ((points <= 0) || (points >= 51)) { player.Out.SendMessage("An Error occurred, there was an invalid amount to train: " + points + " points is not valid!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } int target = points; Specialization spec = player.GetSpecializationByName(line); if (spec == null) { player.Out.SendMessage("An Error occurred, there was an invalid line name: " + line + ".", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } int current = spec.Level; if (current >= player.Level) { player.Out.SendMessage("You can't train in " + line + " again this level.", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (points <= current) { player.Out.SendMessage("You have already trained this amount in " + line + ".", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } target = target - current; ushort skillspecialtypoints = 0; int speclevel = 0; bool changed = false; for (int i = 0; i < target; i++) { if (spec.Level + speclevel >= player.Level) { player.Out.SendMessage("You can't train in " + line + " again this level!", eChatType.CT_System, eChatLoc.CL_SystemWindow); break; } if ((player.SkillSpecialtyPoints + player.GetAutoTrainPoints(spec, 3)) - skillspecialtypoints >= (spec.Level + speclevel) + 1) { changed = true; skillspecialtypoints += (ushort)((spec.Level + speclevel) + 1); if (spec.Level + speclevel < player.Level / 4 && player.GetAutoTrainPoints(spec, 4) != 0) { skillspecialtypoints -= (ushort)((spec.Level + speclevel) + 1); } speclevel++; } else { player.Out.SendMessage("That specialization costs " + (spec.Level + 1) + " specialization points!", eChatType.CT_System, eChatLoc.CL_SystemWindow); player.Out.SendMessage("You don't have that many specialization points left for this level.", eChatType.CT_System, eChatLoc.CL_SystemWindow); break; } } if (changed) { if (player.SkillSpecialtyPoints >= skillspecialtypoints) { spec.Level += speclevel; } player.OnSkillTrained(spec); player.Out.SendUpdatePoints(); player.Out.SendTrainerWindow(); player.Out.SendMessage("You now have " + points + " points in the " + line + " line!", eChatType.CT_System, eChatLoc.CL_PopupWindow); } return; }
public static int LoadSpecializations() { m_syncLockUpdates.EnterWriteLock(); try { IList<DBSpecialization> specs = GameServer.Database.SelectAllObjects<DBSpecialization>(); int count = 0; if (specs != null) { // Clear Spec Cache m_specsByName.Clear(); // Clear SpecXAbility Cache (Ability Career) m_specsAbilities.Clear(); // Clear SpecXSpellLine Cache (Spell Career) m_specsSpellLines.Clear(); // Clear Style Cache (Style Career) m_specsStyles.Clear(); // Clear Style ID Cache (Utils...) m_styleIndex.Clear(); // Clear Style X Spell Cache (Style Procs...) m_stylesProcs.Clear(); foreach (DBSpecialization spec in specs) { StringBuilder str = new StringBuilder("Specialization "); str.AppendFormat("{0} - ", spec.KeyName); Specialization gameSpec = null; if (Util.IsEmpty(spec.Implementation, true) == false) { gameSpec = GetNewSpecializationInstance(spec.KeyName, spec.Implementation, spec.Name, spec.Icon, spec.SpecializationID); } else { gameSpec = new Specialization(spec.KeyName, spec.Name, spec.Icon, spec.SpecializationID); } if (log.IsDebugEnabled) log.DebugFormat("Specialization {0} successfuly instanciated from {1} (expected {2})", spec.KeyName, gameSpec.GetType().FullName, spec.Implementation); Tuple<Type, string, ushort, int> entry = new Tuple<Type, string, ushort, int>(gameSpec.GetType(), spec.Name, spec.Icon, spec.SpecializationID); // Now we have an instanciated Specialization, Cache their properties in Skillbase to prevent using too much memory // As most skill objects are duplicated for every game object use... // Load SpecXAbility count = 0; if (spec.AbilityConstraints != null) { if (!m_specsAbilities.ContainsKey(spec.KeyName)) m_specsAbilities.Add(spec.KeyName, new List<Tuple<string, byte, int, int>>()); foreach (DBSpecXAbility specx in spec.AbilityConstraints) { try { m_specsAbilities[spec.KeyName].Add(new Tuple<string, byte, int, int>(m_abilityIndex[specx.AbilityKey].KeyName, (byte)specx.SpecLevel, specx.AbilityLevel, specx.ClassId)); count++; } catch (Exception e) { if (log.IsWarnEnabled) log.WarnFormat("Specialization : {0} while adding Spec X Ability {1}, from Spec {2}({3}), Level {4}", e.Message, specx.AbilityKey, specx.Spec, specx.SpecLevel, specx.AbilityLevel); } } // sort them according to required levels m_specsAbilities[spec.KeyName].Sort((i, j) => i.Item2.CompareTo(j.Item2)); } str.AppendFormat("{0} Ability Constraint, ", count); // Load SpecXSpellLine count = 0; if (spec.SpellLines != null) { foreach (DBSpellLine line in spec.SpellLines) { if (!m_specsSpellLines.ContainsKey(spec.KeyName)) m_specsSpellLines.Add(spec.KeyName, new List<Tuple<SpellLine, int>>()); try { m_specsSpellLines[spec.KeyName].Add(new Tuple<SpellLine, int>(m_spellLineIndex[line.KeyName], line.ClassIDHint)); count++; } catch (Exception e) { if (log.IsWarnEnabled) log.WarnFormat("Specialization : {0} while adding Spec X SpellLine {1} from Spec {2}, ClassID {3}", e.Message, line.KeyName, line.Spec, line.ClassIDHint); } } } str.AppendFormat("{0} Spell Line, ", count); // Load DBStyle count = 0; if (spec.Styles != null) { foreach (DBStyle specStyle in spec.Styles) { // Update Style Career if (!m_specsStyles.ContainsKey(spec.KeyName)) { m_specsStyles.Add(spec.KeyName, new Dictionary<int, List<Tuple<Style, byte>>>()); } if (!m_specsStyles[spec.KeyName].ContainsKey(specStyle.ClassId)) { m_specsStyles[spec.KeyName].Add(specStyle.ClassId, new List<Tuple<Style, byte>>()); } Style newStyle = new Style(specStyle); m_specsStyles[spec.KeyName][specStyle.ClassId].Add(new Tuple<Style, byte>(newStyle, (byte)specStyle.SpecLevelRequirement)); // Update Style Index. KeyValuePair<int, int> styleKey = new KeyValuePair<int, int>(newStyle.ID, specStyle.ClassId); if (!m_styleIndex.ContainsKey(styleKey)) { m_styleIndex.Add(styleKey, newStyle); count++; } else { if (log.IsWarnEnabled) log.WarnFormat("Specialization {0} - Duplicate Style Key, StyleID {1} : ClassID {2}, Ignored...", spec.KeyName, newStyle.ID, specStyle.ClassId); } // load Procs if (specStyle.AttachedProcs != null) { foreach (DBStyleXSpell styleProc in specStyle.AttachedProcs) { if (m_spellIndex.ContainsKey(styleProc.SpellID)) { if (!m_stylesProcs.ContainsKey(specStyle.ID)) { m_stylesProcs.Add(specStyle.ID, new Dictionary<int, Tuple<Spell, int>>()); } if (!m_stylesProcs[specStyle.ID].ContainsKey(styleProc.ClassID)) m_stylesProcs[specStyle.ID].Add(styleProc.ClassID, new Tuple<Spell, int>(m_spellIndex[styleProc.SpellID], styleProc.Chance)); } } } } } // We've added all the styles to their respective lists. Now lets go through and sort them by their level foreach (string keyname in m_specsStyles.Keys) { foreach (int classid in m_specsStyles[keyname].Keys) m_specsStyles[keyname][classid].Sort((i, j) => i.Item2.CompareTo(j.Item2)); } str.AppendFormat("{0} Styles", count); if (log.IsDebugEnabled) log.Debug(str.ToString()); // Add spec to global Spec Index Cache if (!m_specsByName.ContainsKey(spec.KeyName)) { m_specsByName.Add(spec.KeyName, entry); } else { if (log.IsWarnEnabled) log.WarnFormat("Specialization {0} is duplicated ignoring...", spec.KeyName); } } specs = null; } if (log.IsInfoEnabled) log.InfoFormat("Total specializations loaded: {0}", m_specsByName.Count); } finally { m_syncLockUpdates.ExitWriteLock(); } return m_specsByName.Count; }
private static Specialization GetNewSpecializationInstance(string keyname, string type, string name, ushort icon, int id) { Specialization gameSpec = null; // Try instanciating Specialization foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { try { gameSpec = (Specialization)asm.CreateInstance( typeName: type, // string including namespace of the type ignoreCase: true, bindingAttr: BindingFlags.Default, binder: null, args: new object[] { keyname, name, icon, id }, culture: null, activationAttributes: null); // instanciation worked if (gameSpec != null) { break; } } catch { } } if (gameSpec == null) { // Something Went Wrong when instanciating gameSpec = new Specialization(keyname, name, icon, id); if (log.IsErrorEnabled) log.ErrorFormat("Could not Instanciate Specialization {0} from {1} reverting to default Specialization...", keyname, type); } return gameSpec; }
/// <summary> /// Register or Overwrite a spec in Cache /// </summary> /// <param name="spec"></param> public static void RegisterSpec(Specialization spec) { m_syncLockUpdates.EnterWriteLock(); try { Tuple<Type, string, ushort, int> entry = new Tuple<Type, string, ushort, int>(spec.GetType(), spec.Name, spec.Icon, spec.ID); if (m_specsByName.ContainsKey(spec.KeyName)) m_specsByName[spec.KeyName] = entry; else m_specsByName.Add(spec.KeyName, entry); } finally { m_syncLockUpdates.ExitWriteLock(); } }
/// <summary> /// Add a new style to a specialization. If the specialization does not exist it will be created. /// After adding all styles call SortStyles to sort the list by level /// </summary> /// <param name="style"></param> public static void AddScriptedStyle(Specialization spec, DBStyle style) { m_syncLockUpdates.EnterWriteLock(); try { if (!m_specsStyles.ContainsKey(spec.KeyName)) m_specsStyles.Add(spec.KeyName, new Dictionary<int, List<Tuple<Style, byte>>>()); if (!m_specsStyles[spec.KeyName].ContainsKey(style.ClassId)) m_specsStyles[spec.KeyName].Add(style.ClassId, new List<Tuple<Style, byte>>()); Style st = new Style(style); m_specsStyles[spec.KeyName][style.ClassId].Add(new Tuple<Style, byte>(st, (byte)style.SpecLevelRequirement)); KeyValuePair<int, int> styleKey = new KeyValuePair<int, int>(st.ID, style.ClassId); if (!m_styleIndex.ContainsKey(styleKey)) m_styleIndex.Add(styleKey, st); if (!m_specsByName.ContainsKey(spec.KeyName)) RegisterSpec(spec); } finally { m_syncLockUpdates.ExitWriteLock(); } }
/// <summary> /// Add all spell-lines and other things that are new when this skill is trained /// FIXME : this should be in database. /// </summary> /// <param name="player"></param> /// <param name="skill"></param> public override void OnSkillTrained(GamePlayer player, Specialization skill) { base.OnSkillTrained(player, skill); switch (skill.KeyName) { case Specs.RecurveBow: if (ServerProperties.Properties.ALLOW_OLD_ARCHERY == true) { if (skill.Level < 3) { // do nothing } else if (skill.Level < 6) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 1)); } else if (skill.Level < 9) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 2)); } else if (skill.Level < 12) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 3)); } else if (skill.Level < 15) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 4)); } else if (skill.Level < 18) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 5)); } else if (skill.Level < 21) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 6)); } else if (skill.Level < 24) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 7)); } else if (skill.Level < 27) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 8)); } else if (skill.Level >= 27) { player.AddAbility(SkillBase.GetAbility(Abilities.Critical_Shot, 9)); } if (skill.Level >= 45) { player.AddAbility(SkillBase.GetAbility(Abilities.RapidFire, 2)); } else if (skill.Level >= 35) { player.AddAbility(SkillBase.GetAbility(Abilities.RapidFire, 1)); } if (skill.Level >= 45) { player.AddAbility(SkillBase.GetAbility(Abilities.SureShot)); } if (skill.Level >= 50) { player.AddAbility(SkillBase.GetAbility(Abilities.PenetratingArrow, 3)); } else if (skill.Level >= 40) { player.AddAbility(SkillBase.GetAbility(Abilities.PenetratingArrow, 2)); } else if (skill.Level >= 30) { player.AddAbility(SkillBase.GetAbility(Abilities.PenetratingArrow, 1)); } } break; } }
/// <summary> /// Check and add this spec to m_specsByName /// </summary> /// <param name="spec"></param> public static void RegisterSpec(Specialization spec) { if (m_specsByName.ContainsKey(spec.KeyName)) m_specsByName[spec.KeyName] = spec; else m_specsByName.Add(spec.KeyName, spec); }
/// <summary> /// Add a new style to a specialization. If the specialization does not exist it will be created. /// After adding all styles call SortStyles to sort the list by level /// </summary> /// <param name="style"></param> public static void AddScriptedStyle(Specialization spec, DBStyle style) { string hashKey = string.Format("{0}|{1}", style.SpecKeyName, style.ClassId); List<Style> styleList; if (!m_styleLists.TryGetValue(hashKey, out styleList)) { styleList = new List<Style>(); m_styleLists.Add(hashKey, styleList); } Style st = new Style(style); //(procs) Add procs to the style, 0 is used for normal style if (m_styleSpells.ContainsKey(st.ID)) { // now we add every proc to the style (even if ClassID != 0) foreach (byte classID in Enum.GetValues(typeof(eCharacterClass))) { if (m_styleSpells[st.ID].ContainsKey(classID)) { foreach (DBStyleXSpell styleSpells in m_styleSpells[st.ID][classID]) st.Procs.Add(styleSpells); } } } styleList.Add(st); KeyValuePair<int, int> styleKey = new KeyValuePair<int, int>(st.ID, style.ClassId); if (!m_stylesByIDClass.ContainsKey(styleKey)) m_stylesByIDClass.Add(styleKey, st); if (!m_specsByName.ContainsKey(spec.KeyName)) RegisterSpec(spec); }
/// <summary> /// Add all spell-lines and other things that are new when this skill is trained /// </summary> /// <param name="player">player to modify</param> /// <param name="skill">The skill that is trained</param> public virtual void OnSkillTrained(GamePlayer player, Specialization skill) { }
/// <summary> /// Add all spell-lines and other things that are new when this skill is trained /// </summary> /// <param name="player"></param> /// <param name="skill"></param> public override void OnSkillTrained(GamePlayer player, Specialization skill) { base.OnSkillTrained(player, skill); switch(skill.KeyName) { case Specs.Stealth: if(skill.Level >= 5) player.AddAbility(SkillBase.GetAbility(Abilities.Distraction)); if (skill.Level >= 8) player.AddAbility(SkillBase.GetAbility(Abilities.DangerSense)); if (skill.Level >= 10) player.AddAbility(SkillBase.GetAbility(Abilities.SafeFall, 1)); if(skill.Level >= 16) player.AddAbility(SkillBase.GetAbility(Abilities.DetectHidden)); if (skill.Level >= 20) player.AddAbility(SkillBase.GetAbility(Abilities.SafeFall, 2)); if (skill.Level >= 25) player.AddAbility(SkillBase.GetAbility(Abilities.Climbing)); if (skill.Level >= 30) player.AddAbility(SkillBase.GetAbility(Abilities.SafeFall, 3)); if (skill.Level >= 40) player.AddAbility(SkillBase.GetAbility(Abilities.SafeFall, 4)); if (skill.Level >= 50) player.AddAbility(SkillBase.GetAbility(Abilities.SafeFall, 5)); break; } }