private string GetSpellName(uint spellId) { SpellTable spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey(spellId)) { return(null); } return(spellTable.Spells[spellId].Name); }
public static void Initialize() { nextPlayerGuid = CharacterTable.getNextGuid(); nextPlayerGuid++; nextItemGuid = InventoryItemTable.getNextGuid(); nextItemGuid++; nextGuildId = GuildTable.getNextGuid(); nextGuildId++; nextMountId = MountTable.getNextGuid(); nextMountId++; nextSpeakingId = SpeakingTable.getNextGuid(); nextSpeakingId++; SpellTable.Load(); ExpFloorTable.Load(); MonsterTable.Load(); ItemTemplateTable.Load(); ItemTemplateTable.LoadItemActions(); ItemSetTable.Load(); DropTable.Load(); TitleTable.Load(); IObjectTemplateTable.Load(); AreaTable.Load(); AreaSubTable.Load(); MapTable.Load(); MapTable.LoadActions(); CellActionTable.Load(); MobGroupFixTable.Load(); BreedTable.Load(); NpcTemplateTable.Load(); NpcTemplateTable.LoadPlaces(); NpcQuestionTable.Load(); NpcReplyTable.Load(); ShopNpcTable.Initialize(); GuildTable.Load(); CharactersGuildTable.Load(); TaxCollectorTable.Load(); PrismeTable.Load(); BidHouseTable.Load(); BidHouseTable.LoadItems(); MountParkTable.Load(); StaticMountTable.Load(); MountTable.Load();//TODO Dynamic load of Character mount ZaapTable.Load(); ZaapiTable.Load(); var Timer = new System.Timers.Timer(1000 * 60 * 25); Timer.Elapsed += delegate(object sender, ElapsedEventArgs e) { Save(); }; Timer.Start(); }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> private void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } // 0.1秒毎に判定する if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var combatants = FFXIVPlugin.Instance.GetPartyList(); if (combatants == null || combatants.Count < 1) { return; } // 関係者が全員死んでる? if (combatants.Count == combatants.Count(x => x.CurrentHP <= 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.lastWipeOutDateTime).TotalSeconds >= 15.0) { // インスタンススペルを消去する SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); this.lastWipeOutDateTime = DateTime.Now; // wipeoutログを発生させる LogParser.RaiseLog(DateTime.Now, ConstantKeywords.Wipeout); ActInvoker.Invoke(() => { // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActGlobals.oFormActMain.ActCommands("end"); } }); } } }
//MY Code begins execution here public static void begin(Form1 form) { dbForm = form; party = new Party(); npcs = new List <NPC>(); magicItems = new List <MagicItem>(); monsters = new Dictionary <String, Monster>(); //Load data from files Load.load(); dbForm.updateInformation(); SpellTable.initializeSpellTable(); MagicItemTable.initializeMagicItemTables(); TreasureTable.initializeTreasureTables(); }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> private void ResetCountAtRestart() { // FFXIV以外での使用ならば何もしない if (Settings.Default.UseOtherThanFFXIV) { return; } // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } var combatants = FFXIVPlugin.Instance.GetPartyList(); if (combatants == null || combatants.Count < 1) { return; } // 関係者が全員死んでる? if (combatants.Count == combatants.Count(x => x.CurrentHP <= 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.lastWipeOutDateTime).TotalSeconds >= 15.0) { SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => { ActGlobals.oFormActMain.ActCommands("end"); }); } this.lastWipeOutDateTime = DateTime.Now; } } }
public void Wipeout( bool isRaiseWipeoutLog = true) { // リセットするのは10秒に1回にする // 暗転中もずっとリセットし続けてしまうので var now = DateTime.Now; if ((now - this.lastWipeOutDateTime).TotalSeconds >= 10.0) { this.lastWipeOutDateTime = now; Task.Run(() => { if (Settings.Default.WipeoutNotifyToACT) { CommonSounds.Instance.PlayWipeout(); } // ChatログをFlushする ParsedLogWorker.Instance.Flush(true); Thread.Sleep(TimeSpan.FromSeconds(1)); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => ActGlobals.oFormActMain.EndCombat(true)); } // トリガーをリセットする SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる if (isRaiseWipeoutLog) { Task.Run(() => { Thread.Sleep(200); LogParser.RaiseLog(now, WipeoutKeywords.Wipeout); }); } }); } }
private void PreloadSpell(string tableName, SpellType type) { SpellTable spellTable = this.GetSpellTable(tableName); if (spellTable == null) { object[] messageArgs = new object[] { tableName }; Error.AddDevFatal("SpellCache.PreloadSpell() - Preloaded nonexistent SpellTable {0}", messageArgs); } else { SpellTableEntry entry = spellTable.FindEntry(type); if (entry == null) { object[] objArray2 = new object[] { tableName, type }; Error.AddDevFatal("SpellCache.PreloadSpell() - SpellTable {0} has no spell of type {1}", objArray2); } else if (entry.m_Spell == null) { string name = FileUtils.GameAssetPathToName(entry.m_SpellPrefabName); GameObject obj2 = AssetLoader.Get().LoadActor(name, true, true); if (obj2 == null) { object[] objArray3 = new object[] { name }; Error.AddDevFatal("SpellCache.PreloadSpell() - {0} does not contain a spell component: ", objArray3); } else { Spell component = obj2.GetComponent <Spell>(); if (component == null) { object[] objArray4 = new object[] { name }; Error.AddDevFatal("SpellCache.PreloadSpell() - {0} does not contain a spell component: ", objArray4); } else { spellTable.SetSpell(type, component); } } } } }
public string GetTitle(CharacterTitle title) { var titleEnums = DatManager.PortalDat.ReadFromDat <EnumMapper>(EnumMapper_CharacterTitle_FileID); if (!titleEnums.IdToStringMap.TryGetValue((uint)title, out var titleEnum)) { return(null); } var hash = SpellTable.ComputeHash(titleEnum); var entry = DatManager.LanguageDat.CharacterTitles.StringTableData.FirstOrDefault(i => i.Id == hash); if (entry == null) { return(null); } return(entry.Strings.FirstOrDefault()); }
public static void loadRandomTables() { Dictionary <String, NameTable> nameTables = new Dictionary <string, NameTable>(); nameTables.Add("humanNames", new NameTable("human")); nameTables.Add("elvenNames", new NameTable("elven")); nameTables.Add("dwarvenNames", new NameTable("dwarven")); nameTables.Add("halflingNames", new NameTable("halfling")); nameTables.Add("gnomishNames", new NameTable("gnomish")); nameTables.Add("gnollNames", new NameTable("gnoll")); MagicItemTable magicItemTable = new MagicItemTable(); magicItemTable.initializeMagicItemTables(); SpellTable spellTable = new SpellTable(); spellTable.initializeSpellTable(); HttpRuntime.Cache.Insert("names", nameTables, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); HttpRuntime.Cache.Insert("items", magicItemTable, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); HttpRuntime.Cache.Insert("spells", spellTable, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); }
private SpellTable LoadSpellTable(string tableName) { GameObject obj2 = AssetLoader.Get().LoadActor(tableName, false, false); if (obj2 == null) { object[] messageArgs = new object[] { base.name }; Error.AddDevFatal("SpellCache.LoadSpellTable() - {0} failed to load", messageArgs); return(null); } SpellTable component = obj2.GetComponent <SpellTable>(); if (component == null) { object[] objArray2 = new object[] { base.name }; Error.AddDevFatal("SpellCache.LoadSpellTable() - {0} has no SpellTable component", objArray2); return(null); } component.transform.parent = base.transform; this.m_spellTableCache.Add(tableName, component); return(component); }
/// <summary> /// Method used for the scaling, windup motion, and spell gestures for spell casts /// </summary> protected static float SpellAttributes(string account, uint spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture) { float scale; SpellComponentsTable comps = DatManager.PortalDat.SpellComponentsTable; SpellTable spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey(spellId)) { windUpMotion = MotionCommand.Invalid; spellGesture = MotionCommand.Invalid; castingDelay = 0.0f; return(-1.0f); } SpellBase spell = spellTable.Spells[spellId]; ////Determine scale of the spell effects and windup animation SpellLevel spellLevel = CalculateSpellLevel(spell.Power); if (account == null) { switch (spellLevel) { case SpellLevel.One: scale = 0.1f; break; case SpellLevel.Two: scale = 0.2f; break; case SpellLevel.Three: scale = 0.4f; break; case SpellLevel.Four: scale = 0.5f; break; case SpellLevel.Five: scale = 0.6f; break; case SpellLevel.Six: scale = 1.0f; break; default: scale = 1.0f; break; } spellGesture = MotionCommand.Magic; windUpMotion = 0; castingDelay = 0.0f; return(scale); } switch (spellLevel) { case SpellLevel.One: scale = 0.1f; castingDelay = 1.3f; windUpMotion = MotionCommand.MagicPowerUp01; break; case SpellLevel.Two: scale = 0.2f; castingDelay = 1.4f; windUpMotion = MotionCommand.MagicPowerUp02; break; case SpellLevel.Three: scale = 0.4f; castingDelay = 1.5f; windUpMotion = MotionCommand.MagicPowerUp03; break; case SpellLevel.Four: scale = 0.5f; castingDelay = 1.7f; windUpMotion = MotionCommand.MagicPowerUp04; break; case SpellLevel.Five: scale = 0.6f; castingDelay = 1.9f; windUpMotion = MotionCommand.MagicPowerUp05; break; case SpellLevel.Six: scale = 1.0f; castingDelay = 2.0f; windUpMotion = MotionCommand.MagicPowerUp06; break; default: scale = 1.0f; castingDelay = 2.0f; windUpMotion = MotionCommand.MagicPowerUp07Purple; break; } var formula = SpellTable.GetSpellFormula(spellTable, spellId, account); spellGesture = (MotionCommand)comps.SpellComponents[formula[formula.Count - 1]].Gesture; return(scale); }
//Randomly gets a magic item from the appropriate Item Table, and assigns spells to any scrolls public MagicItem getItem(String letter) { MagicItem item; if (letter == "A") { item = magicItemTableA.ElementAt(random.Next(magicItemTableA.Length)); } else if (letter == "B") { item = magicItemTableB.ElementAt(random.Next(magicItemTableB.Length)); } else if (letter == "C") { item = magicItemTableC.ElementAt(random.Next(magicItemTableC.Length)); } else if (letter == "D") { item = magicItemTableD.ElementAt(random.Next(magicItemTableD.Length)); } else if (letter == "E") { item = magicItemTableE.ElementAt(random.Next(magicItemTableE.Length)); } else if (letter == "F") { item = magicItemTableF.ElementAt(random.Next(magicItemTableF.Length)); } else if (letter == "G") { item = magicItemTableG.ElementAt(random.Next(magicItemTableG.Length)); } else if (letter == "H") { item = magicItemTableH.ElementAt(random.Next(magicItemTableH.Length)); } else if (letter == "I") { item = magicItemTableI.ElementAt(random.Next(magicItemTableI.Length)); } else { item = new MagicItem(); item.Name = "ERROR"; item.Rarity = "ERROR"; item.Value = 0; item.MaximumValue = 0; item.MinimumValue = 0; } //Make a copy of the item so any changes dont mess with the table MagicItem itemCopy = new MagicItem(); itemCopy.Name = item.Name; itemCopy.Rarity = item.Rarity; itemCopy.Value = item.Value; itemCopy.MaximumValue = item.MaximumValue; itemCopy.MinimumValue = item.MinimumValue; //If grabbed item is a scroll, determine its level then acquire a random spell of that level and append the spell name to the item if (itemCopy.Name.Contains("scroll")) { int level = 0; //Check for #, which will be the spell lvl foreach (Char c in itemCopy.Name) { if (Int32.TryParse(Char.ToString(c), out int spellLvl)) { level = spellLvl; } } if (HttpRuntime.Cache.Get("spells") == null) { CacheLoader.loadRandomTables(); } SpellTable spellsTable = (SpellTable)HttpRuntime.Cache.Get("spells"); //Grab a random spell of the appropriate level and add to name itemCopy.Name += $" of {spellsTable.getRandomSpell(level)}"; } return(itemCopy); }
public Scroll(AceObject aceObject) : base(aceObject) { SpellTable table = SpellTable.ReadFromDat(); Use = $"Inscribed spell: {table.Spells[SpellId].Name}\n"; Use += $"{table.Spells[SpellId].Desc}"; LongDesc = "Use this item to attempt to learn its spell."; Power = table.Spells[SpellId].Power; School = table.Spells[SpellId].School; Burden = 30; switch (Power) { case spellLevel1: Value = 1; break; case spellLevel2: Value = 5; break; case spellLevel3: Value = 20; break; case spellLevel4: Value = 100; break; case spellLevel5: Value = 200; break; case spellLevel6: Value = 1000; break; case spellLevel7: Value = 2000; break; case spellLevel8: Value = 60000; break; } ScrollPropertiesInt = PropertiesInt.Where(x => x.PropertyId == (uint)PropertyInt.Value || x.PropertyId == (uint)PropertyInt.EncumbranceVal).ToList(); if (ScrollPropertiesString == null) { ScrollPropertiesString = new List <AceObjectPropertiesString>(); } if (ScrollPropertiesSpellId == null) { ScrollPropertiesSpellId = new List <AceObjectPropertiesSpell>(); } var useString = new AceObjectPropertiesString(); useString.AceObjectId = Guid.Full; useString.PropertyId = (ushort)PropertyString.Use; useString.PropertyValue = Use; ScrollPropertiesString.Add(useString); var longDescString = new AceObjectPropertiesString(); longDescString.AceObjectId = Guid.Full; longDescString.PropertyId = (ushort)PropertyString.LongDesc; longDescString.PropertyValue = LongDesc; ScrollPropertiesString.Add(longDescString); var propSpell = new AceObjectPropertiesSpell(); propSpell.AceObjectId = Guid.Full; propSpell.SpellId = SpellId; ScrollPropertiesSpellId.Add(propSpell); }
/// <summary> /// Method used for handling player untargeted spell casts /// </summary> public void CreatePlayerSpell(uint spellId) { if (IsBusy == true) { Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YoureTooBusy)); return; } else { IsBusy = true; } SpellTable spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey(spellId)) { Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.MagicInvalidSpellType)); IsBusy = false; return; } SpellBase spell = spellTable.Spells[spellId]; Database.Models.World.Spell spellStatMod = DatabaseManager.World.GetCachedSpell(spellId); if (spellStatMod == null) { Session.Network.EnqueueSend(new GameMessageSystemChat($"{spell.Name} spell not implemented, yet!", ChatMessageType.System)); Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.MagicInvalidSpellType)); IsBusy = false; return; } // Grab player's skill level in the spell's Magic School var magicSkill = GetCreatureSkill(spell.School); float scale = SpellAttributes(Session.Account, spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture); var formula = SpellTable.GetSpellFormula(spellTable, spellId, Session.Account); bool spellCastSuccess = false || ((Physics.Common.Random.RollDice(0.0f, 1.0f) > (1.0f - SkillCheck.GetMagicSkillChance((int)magicSkill.Current, (int)spell.Power))) && (magicSkill.Current >= (int)spell.Power - 50) && (magicSkill.Current > 0)); // Calculating mana usage #region if (spellCastSuccess == true) { CreatureSkill mc = GetCreatureSkill(Skill.ManaConversion); double z = mc.Current; double baseManaPercent = 1; if (z > spell.Power) { baseManaPercent = spell.Power / z; } double preCost; uint manaUsed; if ((int)Math.Floor(baseManaPercent) == 1) { preCost = spell.BaseMana; manaUsed = (uint)preCost; } else { preCost = spell.BaseMana * baseManaPercent; if (preCost < 1) { preCost = 1; } manaUsed = (uint)Physics.Common.Random.RollDice(1, (int)preCost); } if (spell.MetaSpellType == SpellType.Transfer) { uint vitalChange, casterVitalChange; vitalChange = (uint)(GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source) * spellStatMod.Proportion); if (spellStatMod.TransferCap != 0) { if (vitalChange > spellStatMod.TransferCap) { vitalChange = (uint)spellStatMod.TransferCap; } } casterVitalChange = (uint)(vitalChange * (1.0f - spellStatMod.LossPercent)); vitalChange = (uint)(casterVitalChange / (1.0f - spellStatMod.LossPercent)); if (spellStatMod.Source == (int)PropertyAttribute2nd.Mana && (vitalChange + 10 + manaUsed) > Mana.Current) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => { Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YouDontHaveEnoughManaToCast)); IsBusy = false; }); resourceCheckChain.EnqueueChain(); return; } if ((vitalChange + 10) > GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source)) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => IsBusy = false); resourceCheckChain.EnqueueChain(); return; } } else if (manaUsed > Mana.Current) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => { Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YouDontHaveEnoughManaToCast)); IsBusy = false; }); resourceCheckChain.EnqueueChain(); return; } else { UpdateVital(Mana, Mana.Current - manaUsed); } } #endregion ActionChain spellChain = new ActionChain(); uint fastCast = (spell.Bitfield >> 14) & 0x1u; if (fastCast != 1) { spellChain.AddAction(this, () => { var motionWindUp = new UniversalMotion(MotionStance.Spellcasting); motionWindUp.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionWindUp.MovementData.ForwardCommand = (uint)windUpMotion; motionWindUp.MovementData.ForwardSpeed = 2; DoMotion(motionWindUp); }); } spellChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageCreatureMessage(SpellComponentsTable.GetSpellWords(DatManager.PortalDat.SpellComponentsTable, formula), Name, Guid.Full, ChatMessageType.Magic)); }); spellChain.AddAction(this, () => { var motionCastSpell = new UniversalMotion(MotionStance.Spellcasting); motionCastSpell.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionCastSpell.MovementData.ForwardCommand = (uint)spellGesture; motionCastSpell.MovementData.ForwardSpeed = 2; DoMotion(motionCastSpell); }); if (fastCast == 1) { spellChain.AddDelaySeconds(castingDelay * 0.26f); } else { spellChain.AddDelaySeconds(castingDelay); } if (spellCastSuccess == false) { spellChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f))); } else { // TODO - Successful spell casting code goes here for untargeted spells to replace line below Session.Network.EnqueueSend(new GameMessageSystemChat("Targeted SpellID " + spellId + " not yet implemented!", ChatMessageType.System)); } spellChain.AddAction(this, () => { var motionReturnToCastStance = new UniversalMotion(MotionStance.Spellcasting); motionReturnToCastStance.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionReturnToCastStance.MovementData.ForwardCommand = (uint)MotionCommand.Invalid; DoMotion(motionReturnToCastStance); }); spellChain.AddDelaySeconds(1.0f); spellChain.AddAction(this, () => { Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.None)); IsBusy = false; }); spellChain.EnqueueChain(); return; }
/// <summary> /// Method used for handling items casting spells on the player equiping the item /// </summary> /// <param name="guidItem"></param> /// <param name="spellId"></param> public void CreateItemSpell(ObjectGuid guidItem, uint spellId) { Player player = CurrentLandblock.GetObject(Guid) as Player; WorldObject item = player.GetWieldedItem(guidItem); if (item == null) { item = player.GetInventoryItem(guidItem); if (item == null) { return; } if (item.WeenieType != WeenieType.Gem) { return; } } CreatureSkill arcaneLore = player.GetCreatureSkill(Skill.ArcaneLore); CreatureSkill meleeDefense = player.GetCreatureSkill(Skill.MeleeDefense); CreatureSkill missileDefense = player.GetCreatureSkill(Skill.MissileDefense); CreatureSkill magicDefense = player.GetCreatureSkill(Skill.MagicDefense); if (arcaneLore.Current >= item.ItemDifficulty || item.ItemDifficulty == null) { if (item.AppraisalItemSkill != 0 || item.AppraisalItemSkill != null) { switch (item.AppraisalItemSkill) { case 6: if (meleeDefense.Current < item.ItemSkillLevelLimit) { return; } break; case 7: if (missileDefense.Current < item.ItemSkillLevelLimit) { return; } break; case 8: if (magicDefense.Current < item.ItemSkillLevelLimit) { return; } break; } } SpellTable spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey(spellId)) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicInvalidSpellType)); return; } SpellBase spell = spellTable.Spells[spellId]; Database.Models.World.Spell spellStatMod = DatabaseManager.World.GetCachedSpell(spellId); if (spellStatMod == null) { player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{spell.Name} spell not implemented, yet!", ChatMessageType.System)); return; } float scale = SpellAttributes(player.Session.Account, spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture); string message; switch (spell.School) { case MagicSchool.CreatureEnchantment: if (IsSpellHarmful(spell)) { break; } CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(player.Guid, (PlayScript)spell.TargetEffect, scale)); message = CreatureMagic(player, spell, spellStatMod, item.Name); if (message != "") { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } break; case MagicSchool.LifeMagic: if (spell.MetaSpellType != SpellType.LifeProjectile) { if (IsSpellHarmful(spell)) { break; } } CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(player.Guid, (PlayScript)spell.TargetEffect, scale)); LifeMagic(player, spell, spellStatMod, out message, item.Name); if (message != null) { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } break; case MagicSchool.ItemEnchantment: CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(item.Guid, (PlayScript)spell.TargetEffect, scale)); message = ItemMagic(item, spell, spellStatMod, item.Name); if (message != "") { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } break; default: break; } } }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> public void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var player = CombatantsManager.Instance.Player; var party = CombatantsManager.Instance.GetPartyList(); if (party == null || party.Count() < 1) { if (player == null || player.ID == 0) { return; } party = new[] { player }; } // 異常なデータ? if (party.Count() > 1) { var first = party.First(); if (party.Count() == party.Count(x => x.CurrentHP == first.CurrentHP && x.MaxHP == first.MaxHP)) { return; } if (!party.Any(x => x.IsPlayer)) { return; } } if (player != null) { switch (player.JobInfo.Role) { case Roles.Crafter: case Roles.Gatherer: return; } } // 関係者が全員死んでる? if (party.Count() == party.Count(x => x.CurrentHP <= 0 && x.MaxHP > 0)) { // リセットするのは10秒に1回にする // 暗転中もずっとリセットし続けてしまうので var now = DateTime.Now; if ((now - this.lastWipeOutDateTime).TotalSeconds >= 10.0) { this.lastWipeOutDateTime = now; Task.Run(() => { Thread.Sleep(TimeSpan.FromSeconds(1)); // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActInvoker.Invoke(() => ActGlobals.oFormActMain.EndCombat(true)); CommonSounds.Instance.PlayWipeout(); } // トリガーをリセットする SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる Task.Run(() => { Thread.Sleep(200); LogParser.RaiseLog(now, ConstantKeywords.Wipeout); }); }); } } }
/// <summary> /// Method used for handling player targeted spell casts /// </summary> public void CreatePlayerSpell(ObjectGuid guidTarget, uint spellId) { Player player = CurrentLandblock.GetObject(Guid) as Player; WorldObject target = CurrentLandblock.GetObject(guidTarget); TargetCategory targetCategory = TargetCategory.WorldObject; if (target == null) { target = GetWieldedItem(guidTarget); targetCategory = TargetCategory.Wielded; } if (target == null) { target = GetInventoryItem(guidTarget); targetCategory = TargetCategory.Inventory; } if (target == null) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.TargetNotAcquired)); targetCategory = TargetCategory.UnDef; return; } SpellTable spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey(spellId)) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicInvalidSpellType)); return; } SpellBase spell = spellTable.Spells[spellId]; if (IsInvalidTarget(spell, target)) { player.Session.Network.EnqueueSend(new GameEventCommunicationTransientString(player.Session, $"{spell.Name} cannot be cast on {target.Name}.")); player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.None)); return; } Database.Models.World.Spell spellStatMod = DatabaseManager.World.GetCachedSpell(spellId); if (spellStatMod == null) { player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{spell.Name} spell not implemented, yet!", ChatMessageType.System)); player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicInvalidSpellType)); return; } if (player.IsBusy == true) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YoureTooBusy)); return; } else { player.IsBusy = true; } uint targetEffect = spell.TargetEffect; // Grab player's skill level in the spell's Magic School var magicSkill = player.GetCreatureSkill(spell.School).Current; if (targetCategory == TargetCategory.WorldObject) { if (guidTarget != Guid) { float distanceTo = Location.Distance2D(target.Location); if (distanceTo > spell.BaseRangeConstant + magicSkill * spell.BaseRangeMod) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicTargetOutOfRange), new GameMessageSystemChat($"{target.Name} is out of range!", ChatMessageType.Magic)); player.IsBusy = false; return; } } } // Ensure that a harmful spell isn't being cast on a player target that doesn't have the same PK status if (target.WeenieClassId == 1 && player.PlayerKillerStatus != ACE.Entity.Enum.PlayerKillerStatus.NPK) { bool isSpellHarmful = IsSpellHarmful(spell); if (player.PlayerKillerStatus != target.PlayerKillerStatus && isSpellHarmful) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.InvalidPkStatus)); player.IsBusy = false; return; } } float scale = SpellAttributes(player.Session.Account, spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture); var formula = SpellTable.GetSpellFormula(spellTable, spellId, player.Session.Account); bool spellCastSuccess = false || ((Physics.Common.Random.RollDice(0.0f, 1.0f) > (1.0f - SkillCheck.GetMagicSkillChance((int)magicSkill, (int)spell.Power))) && (magicSkill >= (int)spell.Power - 50) && (magicSkill > 0)); // Calculating mana usage #region CreatureSkill mc = player.GetCreatureSkill(Skill.ManaConversion); double z = mc.Current; double baseManaPercent = 1; if (z > spell.Power) { baseManaPercent = spell.Power / z; } double preCost; uint manaUsed; if ((int)Math.Floor(baseManaPercent) == 1) { preCost = spell.BaseMana; manaUsed = (uint)preCost; } else { preCost = spell.BaseMana * baseManaPercent; if (preCost < 1) { preCost = 1; } manaUsed = (uint)Physics.Common.Random.RollDice(1, (int)preCost); } if (spell.MetaSpellType == SpellType.Transfer) { uint vitalChange, casterVitalChange; vitalChange = (uint)(player.GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source) * spellStatMod.Proportion); if (spellStatMod.TransferCap != 0) { if (vitalChange > spellStatMod.TransferCap) { vitalChange = (uint)spellStatMod.TransferCap; } } casterVitalChange = (uint)(vitalChange * (1.0f - spellStatMod.LossPercent)); vitalChange = (uint)(casterVitalChange / (1.0f - spellStatMod.LossPercent)); if (spellStatMod.Source == (int)PropertyAttribute2nd.Mana && (vitalChange + 10 + manaUsed) > player.Mana.Current) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YouDontHaveEnoughManaToCast)); player.IsBusy = false; }); resourceCheckChain.EnqueueChain(); return; } else if ((vitalChange + 10) > player.GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source)) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => player.IsBusy = false); resourceCheckChain.EnqueueChain(); return; } } else if (manaUsed > player.Mana.Current) { ActionChain resourceCheckChain = new ActionChain(); resourceCheckChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)); }); resourceCheckChain.AddDelaySeconds(2.0f); resourceCheckChain.AddAction(this, () => { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YouDontHaveEnoughManaToCast)); player.IsBusy = false; }); resourceCheckChain.EnqueueChain(); return; } else { player.UpdateVital(player.Mana, player.Mana.Current - manaUsed); } #endregion ActionChain spellChain = new ActionChain(); uint fastCast = (spell.Bitfield >> 14) & 0x1u; if (fastCast != 1) { spellChain.AddAction(this, () => { var motionWindUp = new UniversalMotion(MotionStance.Spellcasting); motionWindUp.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionWindUp.MovementData.ForwardCommand = (uint)windUpMotion; motionWindUp.MovementData.ForwardSpeed = 2; DoMotion(motionWindUp); }); } spellChain.AddAction(this, () => { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageCreatureMessage(SpellComponentsTable.GetSpellWords(DatManager.PortalDat.SpellComponentsTable, formula), Name, Guid.Full, ChatMessageType.Magic)); }); spellChain.AddAction(this, () => { var motionCastSpell = new UniversalMotion(MotionStance.Spellcasting); motionCastSpell.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionCastSpell.MovementData.ForwardCommand = (uint)spellGesture; motionCastSpell.MovementData.ForwardSpeed = 2; DoMotion(motionCastSpell); }); if (fastCast == 1) { spellChain.AddDelaySeconds(castingDelay * 0.26f); } else { spellChain.AddDelaySeconds(castingDelay); } if (spellCastSuccess == false) { spellChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f))); } else { spellChain.AddAction(this, () => { bool targetDeath; string message; switch (spell.School) { case MagicSchool.WarMagic: WarMagic(target, spell, spellStatMod); break; case MagicSchool.VoidMagic: VoidMagic(target, spell, spellStatMod); break; case MagicSchool.CreatureEnchantment: if (IsSpellHarmful(spell)) { // Retrieve player's skill level in the Magic School var playerMagicSkill = player.GetCreatureSkill(spell.School).Current; // Retrieve target's Magic Defense Skill Creature creature = (Creature)target; var targetMagicDefenseSkill = creature.GetCreatureSkill(Skill.MagicDefense).Current; if (MagicDefenseCheck(playerMagicSkill, targetMagicDefenseSkill)) { CurrentLandblock.EnqueueBroadcastSound(player, Sound.ResistSpell); player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{creature.Name} resists {spell.Name}", ChatMessageType.Magic)); break; } } CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale)); message = CreatureMagic(target, spell, spellStatMod); if (message != "") { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } break; case MagicSchool.LifeMagic: if (spell.MetaSpellType != SpellType.LifeProjectile) { if (IsSpellHarmful(spell)) { // Retrieve player's skill level in the Magic School var playerMagicSkill = player.GetCreatureSkill(spell.School).Current; // Retrieve target's Magic Defense Skill Creature creature = (Creature)target; var targetMagicDefenseSkill = creature.GetCreatureSkill(Skill.MagicDefense).Current; if (MagicDefenseCheck(playerMagicSkill, targetMagicDefenseSkill)) { CurrentLandblock.EnqueueBroadcastSound(player, Sound.ResistSpell); player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{creature.Name} resists {spell.Name}", ChatMessageType.Magic)); break; } } } CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale)); targetDeath = LifeMagic(target, spell, spellStatMod, out message); if (message != null) { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } if (targetDeath == true) { Creature creatureTarget = (Creature)target; creatureTarget.Die(); Strings.DeathMessages.TryGetValue(DamageType.Base, out var messages); player.Session.Network.EnqueueSend(new GameMessageSystemChat(string.Format(messages[0], target.Name), ChatMessageType.Broadcast)); player.EarnXP((long)target.XpOverride); } break; case MagicSchool.ItemEnchantment: if (guidTarget == Guid) { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, (PlayScript)spell.CasterEffect, scale)); } else { CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale)); } message = ItemMagic(target, spell, spellStatMod); if (message != "") { player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic)); } break; default: break; } }); } spellChain.AddAction(this, () => { var motionReturnToCastStance = new UniversalMotion(MotionStance.Spellcasting); motionReturnToCastStance.MovementData.CurrentStyle = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF); motionReturnToCastStance.MovementData.ForwardCommand = (uint)MotionCommand.Invalid; DoMotion(motionReturnToCastStance); }); spellChain.AddDelaySeconds(1.0f); spellChain.AddAction(this, () => { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.None)); player.IsBusy = false; }); spellChain.EnqueueChain(); return; }
/// <summary> /// リスタートのときスペルのカウントをリセットする /// </summary> public void ResetCountAtRestart() { // 無効? if (!Settings.Default.ResetOnWipeOut) { return; } if ((DateTime.Now - this.lastWipeOutDetectDateTime).TotalSeconds <= 0.1) { return; } this.lastWipeOutDetectDateTime = DateTime.Now; var party = default(IEnumerable <Combatant>); party = FFXIVPlugin.Instance.GetPartyList(); if (party == null || party.Count() < 1) { return; } // 異常なデータ? if (party.Count() > 1) { var first = party.First(); if (party.Count() == party.Count(x => x.CurrentHP == first.CurrentHP && x.MaxHP == first.MaxHP)) { return; } if (!party.Any(x => x.IsPlayer)) { return; } if (party.Any(x => x.IsNPC())) { return; } } var player = FFXIVPlugin.Instance.GetPlayer(); if (player != null) { switch (player.AsJob().Role) { case Roles.Crafter: case Roles.Gatherer: return; } } // 関係者が全員死んでる? if (party.Count() == party.Count(x => x.CurrentHP <= 0 && x.MaxHP > 0)) { // リセットするのは15秒に1回にする // 暗転中もずっとリセットし続けてしまうので if ((DateTime.Now - this.lastWipeOutDateTime).TotalSeconds >= 15.0) { this.lastWipeOutDateTime = DateTime.Now; // インスタンススペルを消去する SpellTable.ResetCount(); TickerTable.Instance.ResetCount(); // wipeoutログを発生させる LogParser.RaiseLog(DateTime.Now, ConstantKeywords.Wipeout); ActInvoker.Invoke(() => { // ACT本体に戦闘終了を通知する if (Settings.Default.WipeoutNotifyToACT) { ActGlobals.oFormActMain.ActCommands("end"); } }); } } }