/// <summary> /// Song of weakness. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongWeakling(CharData ch, Spell spell, int level, Target target) { Affect af = new Affect(); foreach (CharData victim in ch.InRoom.People) { if (victim.IsAffected(Affect.AFFECT_STRENGTH_REDUCED) || Magic.SpellSavingThrow(level, victim, AttackType.DamageType.black_magic)) { continue; } af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 7; af.AddModifier(Affect.Apply.strength, -(level / 2)); af.SetBitvector(Affect.AFFECT_STRENGTH_REDUCED); if (level > 25) { af.AddModifier(Affect.Apply.damroll, 0 - (level / 7)); } victim.AddAffect(af); SocketConnection.Act("$n&n looks weaker.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You feel weaker.\r\n"); } return(true); }
/// <summary> /// Song of idiocy. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongIdiocy(CharData ch, Spell spell, int level, Target target) { Affect af = new Affect(); foreach (CharData victim in ch.InRoom.People) { if (victim.IsAffected(Affect.AFFECT_FEEBLEMIND) || Magic.SpellSavingThrow(level, victim, AttackType.DamageType.black_magic)) { ch.SendText("You failed!\r\n"); continue; } af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 9; af.AddModifier(Affect.Apply.intelligence, 0 - (level + 15)); af.SetBitvector(Affect.AFFECT_FEEBLEMIND); victim.AddAffect(af); SocketConnection.Act("A dumb look crosses $n&n's face and $e starts to drool.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You feel _REALLY_ dumb.\r\n"); } return(true); }
/// <summary> /// Song of warding, protective. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongWarding(CharData ch, Spell spell, int level, Target target) { Affect af = new Affect(); foreach (CharData victim in ch.InRoom.People) { af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 7; af.AddModifier(Affect.Apply.save_spell, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_paralysis, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_petrification, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_poison, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_breath, 0 - ((level / 5) + 1)); af.SetBitvector(Affect.AFFECT_NONE); victim.AddAffect(af); } return(true); }
/// <summary> /// Generic spell processing function. Handles basic spells based on values set in the spell file. /// </summary> /// <param name="ch"></param> /// <param name="level"></param> /// <param name="target"></param> public void GenericSpellFunction(CharData ch, int level, Target target) { switch (ValidTargets) { case TargetType.singleCharacterOffensive: { CharData opponent = (CharData)target; if (level > LevelCap) { level = LevelCap; } int damage = MUDMath.Dice(level, DamageDicePerLevel) + BaseDamage; bool saved = Magic.SpellSavingThrow(level, opponent, DamageInflicted); bool affects = true; if (saved) { switch (SavingThrowEffect) { case SavingThrowResult.negates: damage = 0; affects = false; ch.SendText("Nothing happens.\r\n"); return; case SavingThrowResult.halfDamage: damage /= 2; affects = true; break; case SavingThrowResult.halfDamageNoAffects: damage /= 2; affects = true; break; case SavingThrowResult.fullDamageNoAffects: affects = false; break; case SavingThrowResult.none: affects = true; break; } } if (damage > 0) { Combat.InflictSpellDamage(ch, opponent, damage, this, DamageInflicted); } if (affects) { // Apply "negates" to character. for (int n = 0; n < Negates.Length; n++) { opponent.RemoveAffect(new Bitvector(n, Negates[n])); } Affect af = new Affect(); af.Level = ch.Level; af.BitVectors = Provides; af.Value = Name; af.Type = Affect.AffectType.spell; for (int p = 0; p < Provides.Length; p++) { if (Provides[p] != 0) { if (!ch.IsAffected(new Bitvector(p, Provides[p]))) { opponent.AddAffect(af); if (!String.IsNullOrEmpty(MessageCompleted)) { SocketConnection.Act(MessageCompleted, ch, null, null, SocketConnection.MessageTarget.character); } else { ch.SendText("Ok.\r\n"); } if (!String.IsNullOrEmpty(MessageCompletedToTarget)) { SocketConnection.Act(MessageCompletedToTarget, ch, opponent, null, SocketConnection.MessageTarget.victim); } if (!String.IsNullOrEmpty(MessageCompletedToRoom)) { SocketConnection.Act(this.MessageCompletedToRoom, ch, opponent, null, SocketConnection.MessageTarget.room); } } else { switch (StackingType) { case StackType.addDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addDuration stacking types are not yet supported."); case StackType.addModifier: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifier stacking types are not yet supported."); case StackType.addModifierAddDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifierAddDuration stacking types are not yet supported."); case StackType.addModifierMaxDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifierMaxDuration stacking types are not yet supported."); case StackType.alwaysReplace: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell alwaysReplace stacking types are not yet supported."); case StackType.noRefresh: ch.SendText("Your spell has no effect.\r\n"); break; case StackType.replaceDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell replaceDuration stacking types are not yet supported."); case StackType.takeMaxDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxDuration stacking types are not yet supported."); case StackType.takeMaxModifier: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxModifier stacking types are not yet supported."); case StackType.takeMaxModifierAndDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxModifierAndDuration stacking types are not yet supported."); } } } } } return; } case TargetType.singleCharacterDefensive: case TargetType.self: { CharData victim; if (ValidTargets == TargetType.self) { victim = ch; } else { victim = (CharData)target; if (victim == null) { victim = ch; } } for (int n = 0; n < Negates.Length; n++) { victim.RemoveAffect(new Bitvector(n, Negates[n])); } Affect af = new Affect(); af.Level = ch.Level; af.BitVectors = Provides; af.Value = Name; af.Type = Affect.AffectType.spell; switch (this.Duration) { case SpellDurationType.oneHourPerlevel: af.Duration = level; break; case SpellDurationType.quarterHourPerLevel: af.Duration = level / 4; break; case SpellDurationType.halfHourPerLevel: af.Duration = level / 2; break; case SpellDurationType.oneDay: af.Duration = 24; break; case SpellDurationType.threeHoursPerLevel: af.Duration = level * 3; break; case SpellDurationType.twoHoursPerLevel: af.Duration = level * 2; break; case SpellDurationType.fourHoursPerLevel: af.Duration = level * 4; break; case SpellDurationType.oneHour: af.Duration = 1; break; case SpellDurationType.permanent: af.Duration = -1; break; case SpellDurationType.sixHours: af.Duration = 6; break; case SpellDurationType.threeHours: af.Duration = 3; break; case SpellDurationType.twoHours: af.Duration = 2; break; default: throw new NotSupportedException("Spells with duration type " + Duration + " are not implemented yet."); } foreach (AffectApplyType apply in Modifies) { af.AddModifier(apply.Location, apply.Amount); } for (int p = 0; p < Provides.Length; p++) { if (Provides[p] != 0) { if (!ch.IsAffected(new Bitvector(p, Provides[p]))) { victim.AddAffect(af); if (!String.IsNullOrEmpty(MessageCompleted)) { SocketConnection.Act(MessageCompleted, ch, null, null, SocketConnection.MessageTarget.character); } else { ch.SendText("Ok.\r\n"); } if (!String.IsNullOrEmpty(MessageCompletedToTarget)) { SocketConnection.Act(MessageCompletedToTarget, ch, victim, null, SocketConnection.MessageTarget.victim); } if (!String.IsNullOrEmpty(MessageCompletedToRoom)) { SocketConnection.Act(MessageCompletedToRoom, ch, victim, null, SocketConnection.MessageTarget.room); } } else { switch (StackingType) { case StackType.addDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addDuration stacking types are not yet supported."); case StackType.addModifier: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifier stacking types are not yet supported."); case StackType.addModifierAddDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifierAddDuration stacking types are not yet supported."); case StackType.addModifierMaxDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell addModifierMaxDuration stacking types are not yet supported."); case StackType.alwaysReplace: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell alwaysReplace stacking types are not yet supported."); case StackType.noRefresh: ch.SendText("Your spell has no effect.\r\n"); break; case StackType.replaceDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell replaceDuration stacking types are not yet supported."); case StackType.takeMaxDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxDuration stacking types are not yet supported."); case StackType.takeMaxModifier: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxModifier stacking types are not yet supported."); case StackType.takeMaxModifierAndDuration: ch.SendText("Your spell has no effect.\r\n"); throw new NotSupportedException("Spell takeMaxModifierAndDuration stacking types are not yet supported."); } } } } } break; case TargetType.multipleCharacterOffensive: { } break; case TargetType.objectCorpse: { } break; case TargetType.objectInInventory: { } break; case TargetType.objectInRoom: { } break; case TargetType.objectOrCharacter: { } break; case TargetType.ritual: { } break; case TargetType.singleCharacterRanged: { CharData opponent = (CharData)target; if (level > LevelCap) { level = LevelCap; } int damage = MUDMath.Dice(level, DamageDicePerLevel) + BaseDamage; bool saved = Magic.SpellSavingThrow(level, opponent, DamageInflicted); bool affects = true; if (saved) { switch (SavingThrowEffect) { case SavingThrowResult.negates: damage = 0; affects = false; break; case SavingThrowResult.halfDamage: damage /= 2; affects = true; break; case SavingThrowResult.halfDamageNoAffects: damage /= 2; affects = false; break; case SavingThrowResult.fullDamageNoAffects: affects = false; break; case SavingThrowResult.none: affects = true; break; } } if (damage > 0) { Combat.InflictSpellDamage(ch, opponent, damage, this, DamageInflicted); } if (affects) { // TODO: Apply "provides" to character. // TODO: Apply "negates" to character. } return; } case TargetType.singleCharacterWorld: { } break; case TargetType.trap: { } break; case TargetType.none: { Log.Error("Magic spell '" + Name + "' is flagged as TargetType.none. This should never happen. Fix it."); } break; } }