public bool OnCast(Character caster, string args) { ReferenceSpell.SendGenericCastMessage(caster, null, true); int bitcount = 0; //loop through all visible cells for (int ypos = -3; ypos <= 3; ypos += 1) { for (int xpos = -3; xpos <= 3; xpos += 1) { Cell cell = Cell.GetCell(caster.FacetID, caster.LandID, caster.MapID, caster.X + xpos, caster.Y + ypos, caster.Z); if (caster.CurrentCell.visCells[bitcount] && cell.IsSecretDoor) { if (cell.AreaEffects.ContainsKey(Effect.EffectTypes.Hide_Door)) { cell.AreaEffects[Effect.EffectTypes.Hide_Door].StopAreaEffect(); } else { Effect.EffectTypes effectType = Effect.EffectTypes.Find_Secret_Door; string soundFile = Sound.GetCommonSound(Sound.CommonSound.OpenDoor); if (cell.DisplayGraphic == Cell.GRAPHIC_MOUNTAIN || cell.CellGraphic == Cell.GRAPHIC_MOUNTAIN) { effectType = Effect.EffectTypes.Find_Secret_Rockwall; soundFile = Sound.GetCommonSound(Sound.CommonSound.SlidingRockDoor); } AreaEffect effect = new AreaEffect(effectType, Cell.GRAPHIC_EMPTY, 0, (Skills.GetSkillLevel(caster.magic) / 2) + 10, caster, cell); cell.EmitSound(soundFile); } } bitcount++; } } return(true); }
public bool OnCast(Character caster, string args) { try { string[] sArgs = args.Split(" ".ToCharArray()); Item iditem = caster.FindHeldItem(args); if (iditem == null) { if (caster.RightHand != null) { iditem = caster.RightHand; } else if (caster.LeftHand != null) { iditem = caster.LeftHand; } else { caster.WriteToDisplay("You must hold the item to identify in your hands."); return(false); } } var itmeffect = ""; var itmspell = ""; var itmspecial = ""; var itmalign = ""; var itmattuned = ""; ReferenceSpell.SendGenericCastMessage(caster, caster, true); #region Spell and Charges if (iditem.spell > 0) { var spell = GameSpell.GetSpell(iditem.spell); itmspell = " It contains the spell of " + spell.Name; if (iditem.charges == 0) { if (iditem.baseType == Globals.eItemBaseType.Scroll) { if (caster.IsSpellWarmingProfession && spell.IsClassSpell(caster.BaseProfession)) { itmspell += " that you may scribe into your spellbook."; } else { itmspell += " that can be scribed into a spellbook."; } } else { itmspell += ", but there are no charges remaining."; } } else if (iditem.charges > 100) { itmspell += " with unlimited charges."; } else if (iditem.charges > 1) { itmspell += " with " + iditem.charges + " charges remaining."; } else if (iditem.charges == 1) { itmspell += " with 1 charge remaining."; } else // -1 or less { itmspell += " with unlimited charges."; } } #endregion var sb = new System.Text.StringBuilder(100); // Figurine info. if (iditem.baseType == Globals.eItemBaseType.Figurine || iditem.figExp > 0) { sb.AppendFormat(" The {0}'s avatar has " + iditem.figExp + " experience.", iditem.name); } // Combat adds. if (iditem.combatAdds > 0) { sb.AppendFormat(" The combat adds are {0}.", iditem.combatAdds); } // Silver or mithril silver. if (iditem.silver) { string silver = "silver"; if (iditem.longDesc.ToLower().Contains("mithril") || iditem.armorType == Globals.eArmorType.Mithril) { silver = "mithril silver"; } sb.AppendFormat(" The {0} is " + silver + ".", iditem.name); } // Blue glow. if (iditem.blueglow) { sb.AppendFormat(" The {0} is emitting a faint blue glow.", iditem.name); } itmspecial = sb.ToString(); //item effects #region Enchantments if (iditem.effectType.Length > 0) { string[] itmEffectType = iditem.effectType.Split(" ".ToCharArray()); string[] itmEffectAmount = iditem.effectAmount.Split(" ".ToCharArray()); // GameSpell IDs for procs #region Enchantment Effects if (itmEffectType.Length == 1 && Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])) != "") { if (iditem.baseType == Globals.eItemBaseType.Bottle) { itmeffect = " Inside the bottle is a potion of " + Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])) + "."; } else { string effectName = Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])); if (effectName.ToLower() != Effect.GetEffectName(Effect.EffectTypes.None).ToLower() && effectName.ToLower() != Effect.GetEffectName(Effect.EffectTypes.Weapon_Proc)) { itmeffect = " The " + iditem.name + " contains the enchantment of " + Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])) + "."; } } } else { var itemEffectList = new ArrayList(); for (int a = 0; a < itmEffectType.Length; a++) { Effect.EffectTypes effectType = (Effect.EffectTypes)Convert.ToInt32(itmEffectType[a]); if (effectType != Effect.EffectTypes.None && effectType != Effect.EffectTypes.Weapon_Proc) { itemEffectList.Add(Effect.GetEffectName(effectType)); } } if (itemEffectList.Count > 0) { if (itemEffectList.Count > 1) { itmeffect = " The " + iditem.name + " contains the enchantments of"; for (int a = 0; a < itemEffectList.Count; a++) { if (a != itemEffectList.Count - 1) { itmeffect += " " + (string)itemEffectList[a] + ","; } else { itmeffect += " and " + (string)itemEffectList[a] + "."; } } } else if (itemEffectList.Count == 1) { string effectName = Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])); if (effectName.ToLower() != "none") { if (iditem.baseType == Globals.eItemBaseType.Bottle) { itmeffect = " Inside the bottle is a potion of " + Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])) + "."; } else { itmeffect = " The " + iditem.name + " contains the enchantment of " + Effect.GetEffectName((Effect.EffectTypes)Convert.ToInt32(itmEffectType[0])) + "."; } } } } } #endregion } #endregion // Identify spell currently doesn't display weapon procs. 2/10/2017 Eb #region Alignment //item alignment if (iditem.alignment != Globals.eAlignment.None) { string aligncolor = ""; switch (iditem.alignment) { case Globals.eAlignment.Lawful: aligncolor = "white"; break; case Globals.eAlignment.Neutral: aligncolor = "green"; break; case Globals.eAlignment.Chaotic: aligncolor = "purple"; break; case Globals.eAlignment.ChaoticEvil: case Globals.eAlignment.Evil: aligncolor = "red"; break; case Globals.eAlignment.Amoral: aligncolor = "yellow"; break; default: break; } itmalign = " The " + iditem.name + " briefly pulses with a " + aligncolor + " glow."; } #endregion #region Attuned //item attuned if (iditem.attunedID != 0) { if (iditem.attunedID > 0) { if (iditem.attunedID == caster.UniqueID) { itmattuned = " The " + iditem.name + " is soulbound to you."; } else { itmattuned = " The " + iditem.name + " is soulbound to " + PC.GetName(iditem.attunedID) + "."; } } else { itmattuned = " The " + iditem.name + " is soulbound to another being."; } } #endregion //iditem.identified[iditem.identified.Length - 1] = caster.playerID; caster.WriteToDisplay("You are looking at " + iditem.longDesc + "." + itmeffect + itmspell + itmspecial + itmalign + itmattuned); #region Venom if (iditem.venom > 0) { var desc = iditem.name; if (iditem.baseType == Globals.eItemBaseType.Bow) { if (iditem.name.Contains("crossbow") || iditem.longDesc.Contains("crossbow")) { desc = "nocked bolt"; } else { desc = "nocked arrow"; } } caster.WriteToDisplay("The " + desc + " drips with a caustic venom."); } #endregion return(true); } catch (Exception e) { Utils.LogException(e); return(false); } }
public bool OnCommand(Character chr, string args) { int num = 0; #region Handle bad arguments or heavy command weight // TODO: add support for "throw # item at <target>" and "throw # item at # target" if (args == null || args == "" || !args.Contains(" ")) { chr.WriteToDisplay( "Usage of throw: throw <item> <target/direction> | throw <left/right> <target/direction> | throw <item> at # <target>"); return(true); } if (chr.CommandWeight > 3) { chr.WriteToDisplay("Command weight limit exceeded. Throw command not processed."); return(true); } #endregion var sArgs = args.Split(" ".ToCharArray()); var rightHand = false; Item item = null; //var thrownAtTarget = false; if (args.Contains(" at ")) { args = args.Replace(" at ", " "); sArgs = args.Split(" ".ToCharArray()); //thrownAtTarget = true; } else { goto ThrowDirection; } // left hand match if (chr.LeftHand != null && (sArgs[0].ToLower() == "left" || chr.LeftHand.name.ToLower().StartsWith(sArgs[0].ToLower()))) { item = chr.LeftHand; } // right hand match else if (chr.RightHand != null && (sArgs[0].ToLower() == "right" || chr.RightHand.name.ToLower().StartsWith(sArgs[0].ToLower()))) { item = chr.RightHand; rightHand = true; } #region Find throwable item on belt // one hand is empty, check belt for items and use FIRST weapon that may be thrown from belt if (item == null && chr.GetFirstFreeHand() != (int)Globals.eWearOrientation.None) { foreach (string throwFromBelt in Item.ThrowFromBelt) { if (throwFromBelt.ToLower().StartsWith(sArgs[0].ToLower())) { item = chr.RemoveFromBelt(throwFromBelt); if (item != null) { switch (chr.GetFirstFreeHand()) { case (int)Globals.eWearOrientation.Right: chr.EquipRightHand(item); rightHand = true; break; case (int)Globals.eWearOrientation.Left: chr.EquipLeftHand(item); rightHand = false; break; default: break; } break; } } } } #endregion if (item == null) { chr.WriteToDisplay("You do not have a " + sArgs[0] + " to throw."); return(true); } #region Thrown item is attuned if (chr.IsPC && item.IsAttunedToOther(chr)) { chr.CurrentCell.Add(item); chr.WriteToDisplay("The " + item.name + " leaps from your hand!"); if (rightHand) { chr.UnequipRightHand(item); } else { chr.UnequipLeftHand(item); } return(true); } #endregion #region Thrown item is aligned if (!item.AlignmentCheck(chr)) { chr.CurrentCell.Add(item); chr.WriteToDisplay("The " + item.name + " singes your hand and falls to the ground!"); if (rightHand) { chr.RightHand = null; Combat.DoDamage(chr, chr, Rules.Dice.Next(1, 4), false); } else { chr.LeftHand = null; Combat.DoDamage(chr, chr, Rules.Dice.Next(1, 4), false); } return(true); } #endregion Character target = null; #region Throw an item at a target // throw <item> <target>, throw <item> # <target>, throw <item> <direction> // throw <item> at # <target> if (sArgs.Length == 3 && char.IsNumber(sArgs[1].ToCharArray()[0])) { num = Convert.ToInt32(sArgs[1]); target = GameSystems.Targeting.TargetAquisition.FindTargetInView(chr, sArgs[2].ToLower(), num); } else { target = GameSystems.Targeting.TargetAquisition.FindTargetInView(chr, sArgs[1].ToLower(), false, chr.IsImmortal); } Cell targetCell = null; var isFigurine = false; if (target != null) { chr.CommandType = CommandTasker.CommandType.Throw; #region Thrown item is a weapon if (item.itemType == Globals.eItemType.Weapon) { targetCell = target.CurrentCell; chr.EmitSound(Sound.GetCommonSound(Sound.CommonSound.ThrownWeapon)); Combat.DoCombat(chr, target, item); // Possible double attack if returning weapon. if (item != null && item.returning && target != null && !target.IsDead) { Combat.CheckDoubleAttack(chr, target, item); } if (chr.LeftHand != null && chr.LeftHand.returning && chr.LeftHand.itemType == Globals.eItemType.Weapon && target != null && !target.IsDead) { Combat.CheckDualWield(chr, target, chr.LeftHand); } /* The code below was added by mlt in order to give Carfel extra attacks. * A better way to do this is to add a numAttacks or similar attribute to the Character class. */ #region Carfel hard code //if (!chr.IsPC && chr.Name == "Carfel" && target != null && !target.IsDead) //{ // Combat.DoCombat(chr, target, item); // if (target != null && !target.IsDead) // { // Combat.DoCombat(chr, target, item); // } //} #endregion #region Weapon with "figurine" in special - eg: Ebonwood Staff (snake staff) if (item.special.Contains("figurine")) { if (item == chr.RightHand) { chr.UnequipRightHand(item); } else if (item == chr.LeftHand) { chr.UnequipLeftHand(item); } Rules.SpawnFigurine(item, targetCell, chr); } #endregion } #endregion #region else if Figurine thrown at a target else if (item.special.ToLower().Contains("figurine") || item.baseType == Globals.eItemBaseType.Figurine || item.itemID == Item.ID_EBONSNAKESTAFF) // if thrown item is figurine { isFigurine = true; // breakable chance if figurine is fragile if (item.fragile) { // 2d100 roll for fig break var figBreakRoll = Rules.RollD(2, 100); if (chr.IsLucky && Rules.RollD(1, 100) >= 10) { figBreakRoll++; } // two 1's are rolled, character is not lucky if (figBreakRoll == 2) { target.SendShout("something shatter into a hundred pieces."); target.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); //TODO implement NPCs throwing figurines Utils.Log(chr.GetLogString() + " broke a figurine. Item ID: " + item.GetLogString() + " FigExp: " + item.figExp.ToString(), Utils.LogType.ItemFigurineUse); } else { Rules.SpawnFigurine(item, target.CurrentCell, chr); } } else { Rules.SpawnFigurine(item, target.CurrentCell, chr); } } #endregion #region else if Bottle thrown at a target else if (item.baseType == Globals.eItemBaseType.Bottle || item is SoulGem) // what to do if the thrown item is a bottle { if (Combat.CheckFumble(chr, item)) { target = chr; chr.SendToAllInSight(chr.Name + " fumbles!"); chr.WriteToDisplay("You fumble!"); } if (item.effectType.Length > 0) { var effectTypes = item.effectType.Split(" ".ToCharArray()); var effectAmounts = item.effectAmount.Split(" ".ToCharArray()); var effectDurations = item.effectDuration.Split(" ".ToCharArray()); for (int a = 0; a < effectTypes.Length; a++) { var effectType = (Effect.EffectTypes)Convert.ToInt32(effectTypes[a]); if (effectType == Effect.EffectTypes.Nitro) { GameSpell.CastGenericAreaSpell(target.CurrentCell, "", Effect.EffectTypes.Nitro, Convert.ToInt32(effectAmounts[a]), ""); } else if (effectType == Effect.EffectTypes.Naphtha) { var cells = new ArrayList { target.CurrentCell }; var effect = new AreaEffect(Effect.EffectTypes.Fire, Cell.GRAPHIC_FIRE, Convert.ToInt32(effectAmounts[a]), Convert.ToInt32(effectDurations[a]), chr, cells); } } } if (item.baseType == Globals.eItemBaseType.Bottle) { target.SendShout("the sound of glass shattering."); } else { target.SendShout("the sound of something shattering."); } target.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); if (item == chr.LeftHand) { chr.UnequipLeftHand(item); } if (item == chr.RightHand) { chr.UnequipRightHand(item); } } #endregion else { #region all other thrown objects targetCell = target.CurrentCell; if (Rules.RollD(1, 2) == 1) { chr.WriteToDisplay("Your " + item.name + " bounces harmlessly off of " + target.GetNameForActionResult(true) + "."); } else { chr.WriteToDisplay("You miss!"); } target.WriteToDisplay(chr.GetNameForActionResult() + " misses you!"); if (targetCell != null && !targetCell.Items.Contains(item)) { if (!item.special.Contains("figurine")) { targetCell.Add(item); if (chr.RightHand == item) { chr.UnequipRightHand(item); } else if (chr.LeftHand == item) { chr.UnequipLeftHand(item); } } } #endregion } } else { if (num > 0) { chr.WriteToDisplay(GameSystems.Text.TextManager.NullTargetMessage(sArgs[1] + " " + sArgs[2])); } else { chr.WriteToDisplay(GameSystems.Text.TextManager.NullTargetMessage(sArgs[1])); } return(true); } // ** item may have been removed from hand if fumbled result in Rules.doCombat // if the attack caused fatal damage the item is removed in Combat.DND_Attack if (rightHand && chr.RightHand != null && !item.returning && targetCell != null && !targetCell.Items.Contains(item)) { if (!item.fragile && !isFigurine) { targetCell.Add(item); } chr.UnequipRightHand(item); } else if (!rightHand && chr.LeftHand != null && !item.returning && targetCell != null && !targetCell.Items.Contains(item)) { if (!item.fragile && !isFigurine) { targetCell.Add(item); } chr.UnequipLeftHand(item); } return(true); #endregion ThrowDirection: // left hand match if (chr.LeftHand != null && (sArgs[0].ToLower() == "left" || chr.LeftHand.name.ToLower().StartsWith(sArgs[0].ToLower()))) { item = chr.LeftHand; } // right hand match else if (chr.RightHand != null && (sArgs[0].ToLower() == "right" || chr.RightHand.name.ToLower().StartsWith(sArgs[0].ToLower()))) { item = chr.RightHand; rightHand = true; } if (item == null) { chr.WriteToDisplay("You do not have a " + sArgs[0] + " to throw."); return(true); } #region Throw an item in a direction // not throwing an item AT a target args = ""; for (int a = 1; a < sArgs.Length; a++) { args += sArgs[a] + " "; } Cell cell = Map.GetCellRelevantToCell(chr.CurrentCell, args.Substring(0, args.Length - 1), true); if (cell != chr.CurrentCell) { var pathTest = new PathTest(PathTest.RESERVED_NAME_THROWNOBJECT, chr.CurrentCell); if (!pathTest.SuccessfulPathTest(cell)) { cell = chr.CurrentCell; } pathTest.RemoveFromWorld(); } int totalHeight = 0; // used to record how fall an object falls if (cell != null && cell.DisplayGraphic == Cell.GRAPHIC_AIR) { Segue segue = null; int countLoop = 0; do { segue = Segue.GetDownSegue(Cell.GetCell(cell.FacetID, cell.LandID, cell.MapID, cell.X, cell.Y, cell.Z)); countLoop++; if (segue != null) { cell = Cell.GetCell(cell.FacetID, segue.LandID, segue.MapID, segue.X, segue.Y, segue.Z); totalHeight += segue.Height; } else { break; } } while (cell.CellGraphic == Cell.GRAPHIC_AIR && countLoop < 100); } if (item.effectType.Length > 0) { #region Thrown item causes an effect string[] effectTypes = item.effectType.Split(" ".ToCharArray()); string[] effectAmounts = item.effectAmount.Split(" ".ToCharArray()); string[] effectDurations = item.effectDuration.Split(" ".ToCharArray()); for (int a = 0; a < effectTypes.Length; a++) { Effect.EffectTypes effectType = (Effect.EffectTypes)Convert.ToInt32(effectTypes[a]); if (effectType == Effect.EffectTypes.Nitro) { GameSpell.CastGenericAreaSpell(cell, "", Effect.EffectTypes.Nitro, Convert.ToInt32(effectAmounts[a]), "concussion", chr); } else if (effectType == Effect.EffectTypes.Naphtha) { ArrayList cells = new ArrayList { cell }; AreaEffect effect = new AreaEffect(Effect.EffectTypes.Fire, Cell.GRAPHIC_FIRE, Convert.ToInt32(effectAmounts[a]), Convert.ToInt32(effectDurations[a]), chr, cells); } } if (item.baseType == Globals.eItemBaseType.Bottle) { if (cell.DisplayGraphic != Cell.GRAPHIC_WATER) { cell.SendShout("the sound of glass shattering."); cell.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); } else { cell.EmitSound(Sound.GetCommonSound(Sound.CommonSound.Splash)); } } else if (item.fragile) { int breakRoll = Rules.RollD(1, 100); // add experience level of figurine to roll if (item.baseType == Globals.eItemBaseType.Figurine) { breakRoll += Rules.GetExpLevel(item.figExp); // less chance for a lucky character to break a figurine if (chr.IsLucky && Rules.RollD(1, 100) >= 10) { breakRoll += 20; } } if (breakRoll > 25) { cell.Add(item); } else { cell.SendShout("something shatter into pieces."); cell.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); if (item.baseType == Globals.eItemBaseType.Figurine) { Utils.Log(chr.GetLogString() + " broke a figurine. Item ID: " + item.GetLogString() + " FigExp: " + item.figExp.ToString(), Utils.LogType.ItemFigurineUse); } } } else { cell.Add(item); } #endregion } else { #region if figurine or snake staff thrown direction if (item.baseType == Globals.eItemBaseType.Figurine || item.special.ToLower().IndexOf("snake") > -1) // if thrown item is figurine { // breakable chance if figurine is fragile if (item.fragile) { // 2d100 roll for fig break int figBreakRoll = Rules.RollD(2, 100); // still a small chance for the figurine to break if (chr.IsLucky && Rules.RollD(1, 100) >= 10) { figBreakRoll++; } // every 20 feet of height dropped increases the chance of a break if (totalHeight > 0) { figBreakRoll -= Convert.ToInt32(totalHeight / 20); } if (figBreakRoll <= 2) { cell.SendShout("something shatter into a hundred pieces."); cell.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); Utils.Log(chr.GetLogString() + " broke a figurine. Item ID: " + item.GetLogString() + " FigExp: " + item.figExp.ToString(), Utils.LogType.ItemFigurineUse); } else { Rules.SpawnFigurine(item, cell, chr); } } else { Rules.SpawnFigurine(item, cell, chr); } } #endregion #region else if fragile else if (item.fragile) { int breakRoll = Rules.RollD(1, 100); // increase chance to break with every 20 feet dropped if (totalHeight > 0) { breakRoll -= Convert.ToInt32(totalHeight / 20); } if (item is SoulGem) { breakRoll -= 100; } if (cell != null) { // 25% chance to break if (breakRoll > 25) { cell.Add(item); } else { cell.SendShout("something shatter into pieces."); cell.EmitSound(Sound.GetCommonSound(Sound.CommonSound.BreakingGlass)); } } } #endregion else if (cell != null) { cell.Add(item); } } if (rightHand) { chr.UnequipRightHand(item); } else { chr.UnequipLeftHand(item); } #endregion return(true); }