예제 #1
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
 /// <summary>
 /// Song of chaos.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="spell"></param>
 /// <param name="level"></param>
 /// <param name="target"></param>
 /// <returns></returns>
 public static bool SongChaos( CharData ch, Spell spell, int level, Target target )
 {
     foreach( CharData victim in ch.InRoom.People )
     {
     }
     return true;
 }
예제 #2
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
 /// <summary>
 /// Song of calming.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="spell"></param>
 /// <param name="level"></param>
 /// <param name="target"></param>
 /// <returns></returns>
 public static bool SongCalming( CharData ch, Spell spell, int level, Target target )
 {
     foreach( CharData victim in ch.InRoom.People )
     {
         Combat.StopFighting( victim, false );
         victim.WaitState( 2 );
     }
     return true;
 }
예제 #3
0
파일: Event.cs 프로젝트: ramseur/ModernMUD
        private object _var; // A miscellaneous variable

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Parameterized constructor.
        /// </summary>
        /// <param name="itype"></param>
        /// <param name="itime"></param>
        /// <param name="varg1"></param>
        /// <param name="varg2"></param>
        /// <param name="var"></param>
        public Event( EventType itype, int itime, Target varg1, Target varg2, object var )
        {
            ++_numEvents;

            _type = itype;
            _time = itime;
            _arg1 = varg1;
            _arg2 = varg2;
            _var = var;
        }
예제 #4
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of armor.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongArmor( CharData ch, Spell spell, int level, Target target )
        {
            ch.SendText( "You Sing a song of protection.\r\n" );

            foreach( CharData victim in ch.InRoom.People )
            {
                if (victim.IsAffected( Affect.AFFECT_ARMOR))
                    continue;

                Affect af = new Affect( Affect.AffectType.song, spell.Name, 4, Affect.Apply.ac, ( 0 - ( 10 + ( level / 5 ) ) ), Affect.AFFECT_ARMOR );
                victim.CombineAffect( af );

                victim.SendText( "You feel someone protecting you.\r\n" );
            }

            return true;
        }
예제 #5
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of heroism.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongHeroism( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                Affect af = new Affect(Affect.AffectType.song, spell.Name, (level / 8), Affect.Apply.hitroll, (level / 6 + 1), Affect.AFFECT_NONE);
                victim.AddAffect(af);
                af = new Affect(Affect.AffectType.song, spell.Name, (level / 8), Affect.Apply.damroll, (level / 11 + 1), Affect.AFFECT_NONE);
                victim.AddAffect(af);

                SocketConnection.Act( "$n&n looks more courageous.", victim, null, null, SocketConnection.MessageTarget.room );
                victim.SendText( "You feel righteous.\r\n" );
            }
            return true;
        }
예제 #6
0
        /// <summary>
        /// When a spell event terminates, we need something to happen.
        /// 
        /// By this point we should have terminated the spell/song event data
        /// and should only need the info about the character and the spell
        /// and the argument(s).
        /// 
        /// Passing of the correct function parameters should be handled by the
        /// event system.
        /// </summary>
        /// <param name="ch">The caster</param>
        /// <param name="spell">The spell number</param>
        /// <param name="target">The _targetType</param>
        public static void FinishSpell( CharData ch, Spell spell, Target target )
        {
            Object obj;
            int chance = 0;
            bool found = false;

            string lbuf = String.Format("Magic.FinishSpell: {0} by {1}", spell.Name, ch.Name);
            Log.Trace( lbuf );

            for( int i = Database.CastList.Count - 1; i >= 0; i--)
            {
                if (Database.CastList[i].Who && Database.CastList[i].Who == ch)
                {
                    Database.CastList.RemoveAt( i );
                }
            }

            // If they're not casting at the end of the song or spell
            // they certainly can't finish it.
            if( ch.IsAffected( Affect.AFFECT_CASTING ) )
                ch.RemoveAffect( Affect.AFFECT_CASTING );
            else
            {
                return;
            }

            if( !ch.CheckConcentration(spell) )
                return;

            if( ( ch.IsAffected( Affect.AFFECT_MUTE ) || ch.HasInnate( Race.RACE_MUTE ) )
                    && !ch.IsClass( CharClass.Names.psionicist ) )
            {
                ch.SendText( "Your lips move but no sound comes out.\r\n" );
                return;
            }

            // Make sure the room is still castable.
            if( !ch.InRoom.CheckCastable( ch, false, false ) )
                return;

            if( ch.InRoom.CheckStarshell( ch ) )
                return;

            MemorizeData memorized = null;
            if (!ch.IsNPC() && !ch.IsImmortal() && !ch.IsClass(CharClass.Names.psionicist))
            {
                foreach( MemorizeData mem in ((PC)ch).Memorized )
                {
                    if( !mem.Memmed )
                        continue;
                    if( mem.Name == spell.Name )
                    {
                        found = true;
                        memorized = mem;
                        break;
                    }
                }

                if (!found && !ch.IsNPC() && !ch.IsClass(CharClass.Names.psionicist))
                {
                    ch.SendText( "You do not have that spell memorized!\r\n" );
                    if( spell.ValidTargets == TargetType.objectOrCharacter )
                        target = null;
                    else if( spell.ValidTargets == TargetType.none )
                        target = null;
                    return;
                }
            }

            if( ch.IsAffected( Affect.AFFECT_FEEBLEMIND ) )
            {
                ch.SendText( "You are just too stupid to cast that spell!\r\n" );
                SocketConnection.Act( "$n&n screws up $s face in concentration.", ch, null, null, SocketConnection.MessageTarget.room );
                SocketConnection.Act( "$n&n tries really, really hard to complete a spell, but fails.", ch, null, null, SocketConnection.MessageTarget.room );
                return;
            }

            // Locate targets.
            CharData victim = null;
            switch( spell.ValidTargets )
            {
                default:
                    Log.Trace( "FinishSpell: bad TargetType for spell {1}.", spell );
                    return;
                case TargetType.objectOrCharacter:
                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    break;
                case TargetType.none:
                    break;
                case TargetType.trap:
                    ch.SendText( "You cannot cast a trap!\r\n" );
                    return;
                case TargetType.singleCharacterOffensive:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        //allow casting if in combat and no _targetType specified
                        if( !( ch.Fighting && victim == ch.Fighting ) )
                        {
                            ch.SendText( "You cannot see to cast that spell.\r\n" );
                            return;
                        }
                    }
                    if( !victim )
                    {
                        ch.SendText( "They aren't here.\r\n" );
                        return;
                    }
                    if( !victim.InRoom || victim.InRoom != ch.InRoom )
                    {
                        ch.SendText( "They are not here.\r\n" );
                        return;
                    }
                    if( Combat.IsSafe( ch, victim ) )
                        return;
                    // Command.is_safe could wipe out victim, as it calls procs if a boss
                    // check and see that victim is still valid
                    if( !victim )
                        return;

                    Crime.CheckAttemptedMurder( ch, victim );

                    /* Check for globes.  This will stop any spells of type TargetType.singleCharacterOffensive
                    * but area effect spells with type TargetType.none will get through, since we
                    * don't know whether they will be offensive or not.  The only thing we can
                    * really do is add this same thing in the Command.SpellDamage function to prevent
                    * those from getting through.  However, we must treat cases of things like
                    * an area effect sleep spell as a special case within the SpellWhatever
                    * function in Spells.cs.  However, by the nature of the spell, anything
                    * that is not either offensive and not direct damage, it should get through
                    * just so that these spells have some weaknesses for the strategic to get
                    * around.
                    */
                    /*
                    *  TODO: Find out why this globe code was commented out and either uncomment or delete.
                    if( CharData.IsAffected( victim, Affect.AFFECT_MAJOR_GLOBE ) && Spell.Table[spell].spell_circle[ch.cclass] <= 6 )
                    {
                    Descriptor._actFlags( "&+RThe globe around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_GREATER_SPIRIT_WARD ) && Spell.Table[spell].spell_circle[ch.cclass] <= 5 )
                    {
                    Descriptor._actFlags( "&+WThe aura around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_MINOR_GLOBE ) && Spell.Table[spell].spell_circle[ch.cclass] <= 4 )
                    {
                    Descriptor._actFlags( "&+RThe globe around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_SPIRIT_WARD ) && Spell.Table[spell].spell_circle[ch.cclass] <= 3 )
                    {
                    Descriptor._actFlags( "&+WThe aura around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    */
                    break;
                case TargetType.singleCharacterWorld:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) && victim != ch )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    break;
                case TargetType.singleCharacterDefensive:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) && victim != ch )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !victim || victim.InRoom != ch.InRoom )
                    {
                        ch.SendText( "They aren't here.\r\n" );
                        return;
                    }
                    break;
                case TargetType.self:
                    break;
                case TargetType.objectInInventory:
                    obj = (Object)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !obj || obj.CarriedBy != ch )
                    {
                        ch.SendText( "You are not carrying that.\r\n" );
                        return;
                    }
                    break;
                case TargetType.objectInRoom:
                    obj = (Object)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !obj || ( obj.CarriedBy != ch && obj.InRoom != ch.InRoom ) )
                    {
                        ch.SendText( "You do not see that here.\r\n" );
                        return;
                    }
                    break;
                case TargetType.objectCorpse:
                    break;
                case TargetType.singleCharacterRanged:
                    victim = (CharData)target;
                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !victim
                            || victim.FlightLevel != ch.FlightLevel
                            || !CharData.CanSee( ch, victim ) )
                    {
                        ch.SendText( "Your prey has disappeared.\r\n" );
                        return;
                    }
                    //check that _targetType is still within the spell range
                    if( ch.InRoom == victim.InRoom )
                    {
                        break;
                    }
                    bool targetInRange = false;
                    int dir;
                    for( dir = 0; dir < Limits.MAX_DIRECTION; dir++ )
                    {
                        if( !ch.InRoom.ExitData[ dir ]
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.secret )
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.closed )
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.blocked )
                                || ch.InRoom.ExitData[dir].HasFlag(Exit.ExitFlag.walled))
                            continue;
                        if( ch.InRoom.ExitData[ dir ].TargetRoom == victim.InRoom )
                        {
                            targetInRange = true;
                            break;
                        }
                        // for fireball we check two rooms away
                        if( ch.InRoom.ExitData[ dir ].TargetRoom &&
                                ch.InRoom.ExitData[ dir ].TargetRoom.ExitData[ dir ]
                                && ch.InRoom.ExitData[ dir ].TargetRoom.ExitData[ dir ].TargetRoom == victim.InRoom )
                        {
                            targetInRange = true;
                            break;
                        }
                    }
                    if( !targetInRange )
                    {
                        ch.SendText( "They are no longer in range!\r\n" );
                        return;
                    }
                    break;
                }

            // No wait state - we already made them wait.
            ch.PracticeSpell( spell );

            if (ch.IsNPC())
            {
                chance = 85;
            }
            else if (ch.HasSpell(spell.Name))
            {
                chance = ((PC)ch).SpellAptitude[spell.Name];
            }

            if( !ch.IsImmortal() && ( MUDMath.NumberPercent() > chance ) )
            {
                ch.SendText( "You lost your concentration.\r\n" );
                SocketConnection.Act( "&+r$n&n&+r stops chanting abruptly.&n", ch, null, null, SocketConnection.MessageTarget.room );
            }
            else
            {
                // TODO: Figure out whether this should be re-enabled.
                //if( song )
                //{
                //    ch.SendText( "You complete a verse of the song...\r\n" );
                //    ch.GainExperience( 1 );
                //    SaySong( ch, spell );
                //}
                //else
                {
                    if (!ch.IsClass(CharClass.Names.psionicist))
                    {
                        ch.SendText( "You complete your spell...\r\n" );
                        if( MUDString.StringsNotEqual( spell.Name, "ventriloquate" ) )
                            SaySpell( ch, spell );
                    }
                    ch.GainExperience( 1 );
                }
                if( !ch.IsNPC() )
                {
                    string buf = String.Format( "Spell ({0}) being cast by {1}", spell.Name, ch.Name );
                    Log.Trace( buf );
                }

                int level = Macros.Range(1, ch.Level, Limits.LEVEL_HERO);
                spell.Invoke(ch, level, target);

                if( memorized && !ch.IsNPC() && !ch.IsImmortal() )
                {
                    memorized.Memmed = false;
                    memorized.Memtime = memorized.FullMemtime;
                }
            }

            if( ( spell.ValidTargets == TargetType.singleCharacterOffensive
                    || spell.ValidTargets == TargetType.singleCharacterRanged )
                    && victim && victim.Master != ch && victim != ch && victim.IsAwake() )
            {
                if( ch.InRoom == victim.InRoom )
                {
                    if( !victim.Fighting && CharData.CanSee( victim, ch ) )
                        victim.AttackCharacter( ch );
                }
                else
                {
                    // Range spell presumably, since different rooms
                    Combat.StartGrudge( victim, ch, true );
                    foreach( CharData roomChar in ch.InRoom.People )
                    {
                        if( roomChar == victim )
                            continue;
                        if( roomChar.FlightLevel != ch.FlightLevel )
                            continue;
                        //protectors will be aggro'd
                        if (roomChar.HasActionBit(MobTemplate.ACT_PROTECTOR) && (roomChar.GetRace() == victim.GetRace()))
                        {
                            Combat.StartGrudge( roomChar, ch, true );
                        }
                        // all aggro mobs will hunt down caster
                        if (roomChar.HasActionBit(MobTemplate.ACT_AGGRESSIVE))
                        {
                            Combat.StartGrudge(roomChar, ch, true);
                        }
                    }
                }
            }
            return;
        }
예제 #7
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <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;
        }
예제 #8
0
 /// <summary>
 /// TODO: Put Bard song code here.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="song"></param>
 /// <param name="target"></param>
 public static void SongVerse(CharData ch, Song song, Target target)
 {
 }
예제 #9
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of sleep.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongSleep( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if (victim.IsAffected(Affect.AFFECT_SLEEP)
                        || Magic.SpellSavingThrow( level, victim, AttackType.DamageType.charm )
                        || victim.GetRace() == Race.RACE_VAMPIRE
                        || ch.IsSameGroup( victim ) )
                {
                    continue;
                }

                Affect af = new Affect(Affect.AffectType.song, spell.Name, level / 8, Affect.Apply.none, 0, Affect.AFFECT_SLEEP);
                victim.CombineAffect(af);

                if( victim.IsAwake() )
                {
                    victim.SendText( "You feel very sleepy... zzzzz.\r\n" );
                    if (ch.Fighting || victim.CurrentPosition == Position.fighting)
                    {
                        Combat.StopFighting(victim, false);
                    }
                    CommandType.Interpret( victim, "sleep" );
                }

            }

            return true;
        }
예제 #10
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of quagmire (move drain).
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongQuagmire( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if( victim.CurrentMoves < 0 )
                    continue;

                victim.CurrentMoves -= MUDMath.Dice( 2, ( level / 2 ) ) + 5;

                if( victim.CurrentMoves < 0 )
                    victim.CurrentMoves = 0;

                victim.SendText( "Your feet feel mired to the ground.\r\n" );
            }
            return true;
        }
예제 #11
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of nightmares.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongNightmares( CharData ch, Spell spell, int level, Target target )
        {
            Affect af = new Affect();

            foreach( CharData victim in ch.InRoom.People )
            {
                if (victim.IsAffected(Affect.AFFECT_FEAR) || Magic.SpellSavingThrow(level, victim,
                        AttackType.DamageType.black_magic ) )
                {
                    ch.SendText( "You have failed.\r\n" );
                    ch.SendText( "You resist the urge to panic.\r\n" );
                    continue;
                }

                af.Type = Affect.AffectType.song;
                af.Value = spell.Name;
                af.Duration = 1 + ( level / 7 );
                af.SetBitvector( Affect.AFFECT_FEAR );
                victim.AddAffect(af);

                SocketConnection.Act( "$N&n is scared!", ch, null, victim, SocketConnection.MessageTarget.character );
                victim.SendText( "You are scared!\r\n" );
                SocketConnection.Act( "$N&n is scared!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );

                CommandType.Interpret( victim, "flee" );
                if( victim.IsNPC() )
                    Combat.StartFearing( victim, ch );
            }
            return true;
        }
예제 #12
0
 /// <summary>
 /// Forwards to Act with default argument of false. We don't use a default argument version that
 /// takes 5 or 6 parameters because the spell compiler doesn't like default arguments.
 /// </summary>
 /// <param name="format"></param>
 /// <param name="ch"></param>
 /// <param name="arg1"></param>
 /// <param name="arg2"></param>
 /// <param name="type"></param>
 public static void Act(string format, CharData ch, Target arg1, Target arg2, MessageTarget type)
 {
     Act(format, ch, arg1, arg2, type, false);
 }
예제 #13
0
파일: Spell.cs 프로젝트: ramseur/ModernMUD
        /// <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;
            }
        }
예제 #14
0
파일: Spell.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Creating a portal.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <param name="indexNumber"></param>
        public static void MakePortal(CharData ch, Spell spell, int level, Target target, int indexNumber)
        {
            Room location;
            CharData victim = (CharData)target;
            Room original = ch.InRoom;

            if (ch.IsNPC())
                return;
            if (!victim)
            {
                ch.SendText("Who exactly is your target?\r\n");
                return;
            }
            if (victim.IsNPC() && !ch.IsImmortal())
                return;

            if (!Magic.HasSpellConsent(ch, victim))
            {
                return;
            }

            if (victim == ch || ch.InRoom == victim.InRoom)
            {
                ch.SendText("Seems like a waste of time.\r\n");
                return;
            }

            if (!(location = victim.InRoom)
                    || victim.InRoom.HasFlag(RoomTemplate.ROOM_SAFE)
                    || victim.InRoom.HasFlag(RoomTemplate.ROOM_PRIVATE)
                    || victim.InRoom.HasFlag(RoomTemplate.ROOM_SOLITARY))
            {
                ch.SendText("You can't seem to get a fix their location.\r\n");
                return;
            }
            if (!victim.IsNPC() && (ch.IsRacewar(victim)) && !ch.IsImmortal())
            {
                ch.SendText("Don't you wish it was that easy!\r\n");
                return;
            }

            Object portal = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0);

            if (victim.InRoom.HasFlag(RoomTemplate.ROOM_NO_GATE)
                    || ch.InRoom.HasFlag(RoomTemplate.ROOM_NO_GATE))
            {
                SocketConnection.Act("$p opens for a brief instant and then collapses.&n", ch, portal, null, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$p opens for a brief instant and then collapses.&n", ch, portal, null, SocketConnection.MessageTarget.room);
                SocketConnection.Act("$p opens for a brief instant and then collapses.&n", victim, portal, null, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$p opens for a brief instant and then collapses.&n", victim, portal, null, SocketConnection.MessageTarget.room);
                portal.RemoveFromWorld();
                return;
            }

            portal.Timer = level / 15;
            portal.Values[2] = level / 7;
            portal.Values[0] = location.IndexNumber;

            portal.AddToRoom(original);

            portal = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0);
            portal.Timer = level / 15;
            portal.Values[2] = level / 7;
            portal.Values[0] = original.IndexNumber;

            portal.AddToRoom(location);

            switch (indexNumber)
            {
                case StaticObjects.OBJECT_NUMBER_PORTAL:
                    SocketConnection.Act("$p&+Y rises up from the ground.&n", ch, portal, null, SocketConnection.MessageTarget.room);
                    SocketConnection.Act("$p&+Y rises up before you.&n", ch, portal, null, SocketConnection.MessageTarget.character);

                    if (location.People.Count > 0)
                    {
                        SocketConnection.Act("$p&+Y rises up from the ground.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.room);
                        SocketConnection.Act("$p&+Y rises up from the ground.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.character);
                    }
                    break;
                case StaticObjects.OBJECT_NUMBER_MOONWELL:
                    SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", ch, portal, null, SocketConnection.MessageTarget.room);
                    SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", ch, portal, null, SocketConnection.MessageTarget.character);

                    if (location.People.Count > 0)
                    {
                        SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.room);
                        SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.character);
                    }
                    break;
                case StaticObjects.OBJECT_NUMBER_WORMHOLE:
                    SocketConnection.Act("$p&+L appears from a warping of space and time.&n", ch, portal, null, SocketConnection.MessageTarget.room);
                    SocketConnection.Act("$p&+L appears from a warping of space and time.&n", ch, portal, null, SocketConnection.MessageTarget.character);

                    if (location.People.Count > 0)
                    {
                        SocketConnection.Act("$p&+L appears from a warping of space and time.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.room);
                        SocketConnection.Act("$p&+L appears from a warping of space and time.&n", location.People[0], portal, null,
                             SocketConnection.MessageTarget.character);
                    }
                    break;
            }

            ch.WaitState(8);

            return;
        }
예제 #15
0
파일: Spell.cs 프로젝트: ramseur/ModernMUD
 /// <summary>
 /// Invokes a spell by calling either that spell's compiled code or the generic spell processing
 /// function, whichever is appropriate.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="level"></param>
 /// <param name="target"></param>
 public void Invoke(CharData ch, int level, Target target)
 {
     if (CompiledCode == null)
     {
         GenericSpellFunction(ch, level, target);
     }
     else
     {
         object o = CompiledCode.CreateInstance("ModernMUD.SpellScript");
         Type type = o.GetType();
         MethodInfo[] methods = type.GetMethods();
         try
         {
             type.InvokeMember("Execute", BindingFlags.Default|BindingFlags.InvokeMethod, null, o, new object[] { ch, this, level, target });
         }
         catch (Exception ex)
         {
             Log.Error("Error executing spell code for " + Name + ":" + ex.ToString());
         }
     }
 }
예제 #16
0
        public void ImprintSpell(Spell spell, int level, Target target)
        {
            int[] sucessRate = new[]
            {
                80, 30, 25, 10
            };

            string text;
            Object obj = (Object)target;
            int freeSlots;
            int i;

            if (spell == null)
            {
                SendText("That is not a spell.\r\n");
                return;
            }

            for (freeSlots = i = 1; i < 5; i++)
                if (obj.Values[i] != -1)
                    freeSlots++;

            if (freeSlots > 4)
            {
                SocketConnection.Act("$p&n cannot contain any more spells.", this, obj, null, SocketConnection.MessageTarget.character);
                return;
            }

            int mana = 4 * Macros.ManaCost(this, spell);

            if (!IsNPC() && CurrentMana < mana)
            {
                SendText("You don't have enough mana.\r\n");
                return;
            }

            if (MUDMath.NumberPercent() > ((PC)this).SpellAptitude[spell.Name]
                    && (Level <= (spell.SpellCircle[(int)this.CharacterClass.ClassNumber] * 4 + 1)))
            {
                SendText("You lost your concentration.\r\n");
                SocketConnection.Act("&+r$n&n&+r stops chanting abruptly.&n", this, null, null, SocketConnection.MessageTarget.room);
                CurrentMana -= mana / 2;
                return;
            }

            CurrentMana -= mana;
            // TODO: FIXME: BUG: Can't cram a string into a integer value inside an object.
            // This is a problem because it makes it impossible for objects to contain spells.
            //obj._values[free_slots] = spell;

            if (MUDMath.NumberPercent() > sucessRate[freeSlots - 1])
            {
                text = String.Format("The magic enchantment has failed: the {0} vanishes.\r\n",
                          StringConversion.ItemTypeString(obj));
                SendText(text);
                obj.RemoveFromWorld();
                ;
                return;
            }

            obj.ShortDescription = String.Empty;
            text = String.Format("a {0} of ", StringConversion.ItemTypeString(obj));
            for (i = 1; i <= freeSlots; i++)
            {
                if (obj.Values[i] != -1)
                {
                    text += SpellNumberToTextMap.GetSpellNameFromNumber(obj.Values[i]);
                    if (i != freeSlots)
                    {
                        text += ", ";
                    }
                    else
                    {
                        text += String.Empty;
                    }
                }
            }
            obj.ShortDescription = text;

            text = String.Format("{0} {1}", obj.Name, StringConversion.ItemTypeString(obj));
            obj.Name = text;

            text = String.Format("You have imbued a new spell to the {0}.\r\n",
                      StringConversion.ItemTypeString(obj));
            SendText(text);

            return;
        }
예제 #17
0
파일: Object.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Utility function to create a wall.  Called by create wall spells.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <param name="indexNumber"></param>
        /// <returns></returns>
        public static Object MakeWall(CharData ch, Spell spell, int level, Target target, int indexNumber)
        {
            if (ch == null || spell == null) return null;

            Object wall2;
            Exit exit;
            string targetName = (string)target;
            // If we were really smooth we would just create another _targetType called
            // tar_exit
            if (String.IsNullOrEmpty(targetName))
            {
                ch.SendText("Specify a direction in which to cast the spell!\r\n");
                return null;
            }

            Exit.Direction door = Movement.FindExit(ch, targetName);

            if (door == Exit.Direction.invalid)
            {
                ch.SendText("You failed!\r\n");
                return null;
            }

            // The exit of the same direction should be flagged Exit.ExitFlags.walled
            if (!(exit = ch.InRoom.GetExit(door)))
            {
                ch.SendText("You failed!\r\n");
                return null;
            }

            if (exit.HasFlag(Exit.ExitFlag.walled))
            {
                ch.SendText("There's already a wall there!\r\n");
                return null;
            }

            if (exit.HasFlag(Exit.ExitFlag.is_door))
            {
                return null;
            }

            ObjTemplate wallTemplate = Database.GetObjTemplate(indexNumber);
            if (!wallTemplate)
            {
                string output = String.Format("MakeWall: null wall pointer from Database.GetObjTemplate( {0} ).", indexNumber);
                ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, output);
                Log.Error(output, 0);
                ch.SendText("Uh oh, no template found for that wall.\r\n");
                return null;
            }

            Object wall = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0);
            if (!wall)
            {
                Log.Error("MakeWall: null wall pointer from Database.CreateObject", 0);
                ch.SendText("Whoops, failed to create wall.  Report this as a bug.\r\n");
                return null;
            }

            // Value[0] should be the direction that is blocked by the wall.
            wall.Values[0] = (int)door;
            // Set the wall's level
            wall.Values[2] = level;

            string text = String.Format("{0} {1} exit.&n", wall.FullDescription, door.ToString());
            wall.FullDescription = text;

            exit.AddFlag(Exit.ExitFlag.walled);
            if (indexNumber == StaticObjects.OBJECT_NUMBER_WALL_ILLUSION)
            {
                exit.AddFlag(Exit.ExitFlag.illusion);
            }

            wall.Timer = ch.Level / 3;
            wall.Level = ch.Level;
            wall.AddToRoom(ch.InRoom);

            // Create the wall on the other side
            if (exit.TargetRoom)
            {
                if (exit.TargetRoom.ExitData[(int)Exit.ReverseDirection(door)])
                {
                    //we actually have a matching exit
                    wall2 = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0);

                    // Value[0] should be the direction that is blocked by the wall.
                    wall2.Values[0] = (int)Exit.ReverseDirection(door);
                    // Set the wall's level
                    wall2.Values[2] = level;

                    text = String.Format("{0} {1} exit.&n", wall2.FullDescription, Exit.ReverseDirection(door).ToString());
                    wall2.FullDescription = text;

                    if (exit.TargetRoom.ExitData[(int)Exit.ReverseDirection(door)])
                    {
                        exit.TargetRoom.ExitData[(int)Exit.ReverseDirection(door)].AddFlag(Exit.ExitFlag.walled);
                    }

                    wall2.Timer = ch.Level / 2;
                    wall2.Level = ch.Level;
                    wall2.AddToRoom(Room.GetRoom(exit.IndexNumber));
                    if (Room.GetRoom(exit.IndexNumber).People.Count > 0)
                    {
                        text = String.Format("$p&n appears to the {0}.", Exit.ReverseDirection(door).ToString());
                        SocketConnection.Act(text, Room.GetRoom(exit.IndexNumber).People[0], wall2, null, SocketConnection.MessageTarget.all);
                    }
                } //end if matching exit
            }

            return wall;
        }
예제 #18
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <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;
        }
예제 #19
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of invisibility.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongInvisibility( CharData ch, Spell spell, int level, Target target )
        {
            int total = 0;

            int max = level / 8;

            foreach( CharData victim in ch.InRoom.People )
            {
                if( !victim.IsSameGroup( ch ) || victim.IsAffected( Affect.AFFECT_INVISIBLE ) )
                    continue;

                if( total >= max )
                    return true;

                victim.SendText( "You slowly fade out of existence.\r\n" );
                SocketConnection.Act( "$n&n slowly fades out of existence.", victim, null, null, SocketConnection.MessageTarget.room );

                Affect af = new Affect(Affect.AffectType.song, spell.Name, (level / 6), Affect.Apply.none, 0, Affect.AFFECT_INVISIBLE);
                victim.AddAffect(af);
                total++;
            }
            foreach( Object obj in ch.InRoom.Contents )
            {
                if( obj.HasFlag( ObjTemplate.ITEM_INVIS ) )
                    continue;

                if( total >= max )
                    return true;

                SocketConnection.Act( "&+L$p&+L fades away.", ch, obj, null, SocketConnection.MessageTarget.room );
                SocketConnection.Act( "&+L$p&+L fades away.", ch, obj, null, SocketConnection.MessageTarget.character );
                obj.AddFlag( ObjTemplate.ITEM_INVIS );
                total++;
            }
            return true;
        }
예제 #20
0
        /// <summary>
        /// The primary output interface for formatted output.
        /// </summary>
        /// <param name="format">Format string for output.</param>
        /// <param name="actor">The actor (or TargetType, depending on format string).</param>
        /// <param name="arg1">Argument Target, use varies based on format string.</param>
        /// <param name="arg2">Argument Target, use varies based on format string</param>
        /// <param name="type">Target of Act statement.</param>
        /// <param name="capitalize">If capitalize is set, the first word of the phrase will be capitalized (after variable substitution).</param>
        public static void Act( string format, CharData actor, Target arg1, Target arg2, MessageTarget type, bool capitalize )
        {
            Object obj1 = (Object)arg1;
            Object obj2 = (Object)arg2;
            CharData victimChar = (CharData)arg2;
            string[] himHer = new[] { "it", "him", "her" };
            string[] hisHer = new[] { "its", "his", "her" };
            string str;
            // Discard null and zero-length messages.
            if( format.Length == 0 )
            {
                return;
            }

            if( actor == null )
            {
                Log.Error( "Act: null actor!", 0 );
                return;
            }

            // To prevent crashes
            if( !actor.InRoom )
            {
                Log.Error( "Act: Actor CharData (" + actor.Name + ") is not in a room!" );
                return;
            }

            List<CharData> to = actor.InRoom.People;
            if( type == MessageTarget.victim || type == MessageTarget.room_vict )
            {
                if( !victimChar )
                {
                    Log.Error( "Act: null victim with Descriptor.MessageTarget.victim.", 0 );
                    Log.Error(String.Format("Bad act string: {0}", format));
                    return;
                }
                to = victimChar.InRoom.People;
            }

            string outputBuffer;

            foreach (CharData roomChar in to)
            {
                if( !roomChar.Socket && roomChar.IsNPC() || !roomChar.IsAwake() )
                    continue;
                if( type == MessageTarget.room_vict && victimChar.FlightLevel != roomChar.FlightLevel )
                    continue;
                if( ( type == MessageTarget.room_vict || type == MessageTarget.room || type == MessageTarget.everyone_but_victim ) && actor.FlightLevel != roomChar.FlightLevel )
                    continue;
                if( type == MessageTarget.room_vict && ( roomChar == actor || roomChar == victimChar ) )
                    continue;
                if( type == MessageTarget.character && roomChar != actor )
                    continue;
                if( type == MessageTarget.victim && ( roomChar != victimChar || roomChar == actor ) )
                    continue;
                if( type == MessageTarget.room && roomChar == actor )
                    continue;
                if( type == MessageTarget.everyone_but_victim && ( roomChar == victimChar ) )
                    continue;
                if( type == MessageTarget.room_above && ( roomChar.FlightLevel <= actor.FlightLevel ) )
                    continue;
                if( type == MessageTarget.room_below && ( roomChar.FlightLevel >= actor.FlightLevel ) )
                    continue;

                str = format;

                if (str.Contains("$t"))
                    str = str.Replace("$t", (String)arg1);
                if (str.Contains("$T"))
                    str = str.Replace("$T", (String)arg2);
                if (str.Contains("$n") && actor != null)
                    str = str.Replace("$n", actor.ShowNameTo(roomChar, false));
                if (str.Contains("$N") && victimChar != null)
                    str = str.Replace("$N", victimChar.ShowNameTo(roomChar, false));
                if (str.Contains("$e") && actor != null)
                    str = str.Replace("$e", actor.GetSexPronoun());
                if (str.Contains("$E") && victimChar != null)
                    str = str.Replace("$E", victimChar.GetSexPronoun());
                if (str.Contains("$m") && actor != null)
                    str = str.Replace("$m", himHer[Macros.Range(0, (int)actor.Gender, 2)]);
                if (str.Contains("$M") && victimChar != null)
                    str = str.Replace("$M", himHer[Macros.Range(0, (int)victimChar.Gender, 2)]);
                if (str.Contains("$s") && actor != null)
                    str = str.Replace("$s", hisHer[Macros.Range(0, (int)actor.Gender, 2)]);
                if (str.Contains("$S") && victimChar != null)
                    str = str.Replace("$S", hisHer[Macros.Range(0, (int)victimChar.Gender, 2)]);
                if (str.Contains("$p") && obj1 != null)
                    str = str.Replace("$p", CharData.CanSeeObj(roomChar, obj1) ? obj1.ShortDescription : "something");
                if (str.Contains("$P") && obj1 != null)
                    str = str.Replace("$P", CharData.CanSeeObj(roomChar, obj2) ? obj2.ShortDescription : "something");
                if (str.Contains("$d"))
                {
                    if (((string)arg2).Length == 0)
                    {
                        str = str.Replace("$d", "door");
                    }
                    else
                    {
                        str = str.Replace("$d", (string)arg2);
                    }
                }

                str += "\r\n";

                ColorConvert( out outputBuffer, str, roomChar );

                if (capitalize)
                {
                    outputBuffer = MUDString.CapitalizeANSIString(outputBuffer);
                }

                if (roomChar.Socket)
                {
                    roomChar.Socket.WriteToBuffer(outputBuffer);
                }
            }
            return;
        }
예제 #21
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of obscrurement.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongObscurement( CharData ch, Spell spell, int level, Target target )
        {
            Affect af = new Affect();

            foreach( CharData victim in ch.InRoom.People )
            {
                if( victim.IsAffected( Affect.AFFECT_MINOR_INVIS ) || victim.IsAffected( Affect.AFFECT_INVISIBLE ) )
                    return true;

                SocketConnection.Act( "$n&n fades out of existence.", ch, null, null, SocketConnection.MessageTarget.room );
                ch.SendText( "You vanish.\r\n" );

                af.Type = Affect.AffectType.song;
                af.Value = spell.Name;
                af.Duration = level / 6;
                af.SetBitvector( Affect.AFFECT_MINOR_INVIS );
                victim.AddAffect(af);
            }
            return true;
        }
예제 #22
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of cowardice.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongCowardice( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if( !victim.IsSameGroup( ch ) )
                {
                    Affect af = new Affect(Affect.AffectType.song, spell.Name, (level / 6 + 1), Affect.Apply.hitroll, (0 - (level / 3)), Affect.AFFECT_COWARDLY);
                    victim.AddAffect(af);

                    SocketConnection.Act( "$n&n looks unsure of $mself.", victim, null, null, SocketConnection.MessageTarget.room );
                    victim.SendText( "You feel less confident about your battle skills.\r\n" );
                }
            }
            return true;
        }
예제 #23
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
 /// <summary>
 /// Song of revelation.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="spell"></param>
 /// <param name="level"></param>
 /// <param name="target"></param>
 /// <returns></returns>
 public static bool SongRevelation( CharData ch, Spell spell, int level, Target target )
 {
     foreach( CharData victim in ch.InRoom.People )
     {
         victim.AffectStrip( Affect.AffectType.skill, "shadow form");
         victim.RemoveAffect(Affect.AFFECT_HIDE);
         victim.RemoveAffect(Affect.AFFECT_INVISIBLE);
         SocketConnection.Act( "$n&n is revealed!", victim, null, null, SocketConnection.MessageTarget.room );
         victim.SendText( "You are revealed!\r\n" );
     }
     return true;
 }
예제 #24
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of feasting.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongFeasting( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if( victim.IsNPC() )
                    continue;

                int amount = level / 7 + 1;

                if( ( (PC)victim ).Hunger < 48 )
                    ( (PC)victim ).Hunger += amount;
                if( ( (PC)victim ).Thirst < 48 )
                    ( (PC)victim ).Thirst += amount;

                victim.SendText( "You stomach feels fuller.\r\n" );
            }
            return true;
        }
예제 #25
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of slowness.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongSlowness( CharData ch, Spell spell, int level, Target target )
        {
            Affect af = new Affect();

            foreach( CharData victim in ch.InRoom.People )
            {
                if( Magic.SpellSavingThrow( level, victim, AttackType.DamageType.magic_other ) )
                {
                    ch.SendText( "You failed!\r\n" );
                    continue;
                }

                // Removes haste, takes two castings to make a hasted person slowed
                if (victim.IsAffected( Affect.AFFECT_HASTE))
                {
                    victim.RemoveAffect(Affect.AFFECT_HASTE);
                    victim.SendText( "You slow to your normal speed.\r\n" );
                    continue;
                }

                if (victim.IsAffected(Affect.AFFECT_SLOWNESS))
                    continue;

                af.Type = Affect.AffectType.song;
                af.Value = spell.Name;
                af.Duration = 6;
                af.SetBitvector( Affect.AFFECT_SLOWNESS );
                victim.AddAffect(af);

                SocketConnection.Act( "&+R$n&+R moves much more slowly.&n", victim, null, null, SocketConnection.MessageTarget.room );
                victim.SendText( "&+RYou feel yourself slowing down.&n\r\n" );
            }
            return true;
        }
예제 #26
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of flight.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongFlight( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if (victim.IsAffected(Affect.AFFECT_FLYING))
                    return true;

                Affect af = new Affect(Affect.AffectType.song, spell.Name, (level / 6), Affect.Apply.none, 0, Affect.AFFECT_FLYING);
                victim.AddAffect(af);

                victim.SendText( "&+WYour feet rise off the ground.&n\r\n" );
                SocketConnection.Act( "$n&n rises off the ground.", victim, null, null, SocketConnection.MessageTarget.room );
            }
            return true;
        }
예제 #27
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <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;
        }
예제 #28
0
        /// <summary>
        /// Casts a spell using a magical object.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="victim"></param>
        /// <param name="obj"></param>
        public static void ObjectCastSpell( CharData ch, Spell spell, int level, CharData victim, Object obj )
        {
            Target target;

            if( spell == null || obj == null )
            {
                return;
            }

            switch( spell.ValidTargets )
            {
                default:
                    Log.Error( "ObjectCastSpell: bad TargetType for spell {0}.", spell.Name );
                    return;

                case TargetType.none:
                    target = null;
                    break;

                case TargetType.trap:
                    return;

                case TargetType.singleCharacterOffensive:
                    if( !victim )
                        victim = ch.Fighting;
                    if( !victim )
                    {
                        ch.SendText( "You can't do that.\r\n" );
                        return;
                    }

                    if( Combat.IsSafe( ch, victim ) )
                        return;
                    // Combat.IsSafe could wipe out victim, as it calls procs if a boss
                    // check and see that victim is still valid
                    if(  !victim )
                        return;

                    Crime.CheckAttemptedMurder( ch, victim );

                    target = new Target( victim );
                    break;

                case TargetType.singleCharacterDefensive:
                    if( !victim )
                        victim = ch;
                    target = new Target( victim );
                    break;

                case TargetType.self:
                    target = new Target( ch );
                    break;

                case TargetType.objectInInventory:
                    if( !obj )
                    {
                        ch.SendText( "You can't do that.\r\n" );
                        return;
                    }
                    target = new Target( obj );
                    break;

                case TargetType.objectInRoom:
                    if( !obj )
                    {
                        ch.SendText( "You can't do that.\r\n" );
                        return;
                    }
                    target = new Target( obj );
                    break;

                case TargetType.objectCorpse:
                    target = new Target( obj );
                    break;
            }

            spell.Invoke(ch, level, target);

            if( spell.ValidTargets == TargetType.singleCharacterOffensive
                    && victim.Master != ch && ch != victim )
            {
                foreach( CharData roomChar in ch.InRoom.People )
                {
                    if( victim == roomChar && !victim.Fighting )
                    {
                        victim.AttackCharacter( ch );
                        break;
                    }
                }
            }

            return;
        }
예제 #29
0
파일: Songs.cs 프로젝트: ramseur/ModernMUD
        /// <summary>
        /// Song of healing.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="level"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SongHealing( CharData ch, Spell spell, int level, Target target )
        {
            foreach( CharData victim in ch.InRoom.People )
            {
                if( !ch.IsSameGroup( victim ) )
                    continue;

                int heal = MUDMath.Dice( 4, ( level / 3 ) ) + 1;

                if( victim.Hitpoints < victim.GetMaxHit() )
                    victim.Hitpoints = Math.Min( victim.Hitpoints + heal, victim.GetMaxHit() );
                victim.UpdatePosition();

                victim.SendText( "&+WYour wounds begin to heal.&n\r\n" );
            }
            return true;
        }
예제 #30
0
        /// <summary>
        /// Called by the cast function to process a spell's targets and react accordingly.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="spell"></param>
        /// <param name="argument"></param>
        private static void ProcessSpellTargets(CharData ch, Spell spell, string argument)
        {
            Object obj = null;
            Target target = null;
            CharData victim = null;

            if (!ch.IsClass(CharClass.Names.bard))
                switch (spell.ValidTargets)
                {
                    default:
                        Log.Error("Magic.Cast: bad target type for spell {0}.  Type is: {1}", spell.Name, spell.ValidTargets.ToString());
                        return;
                    case TargetType.none:
                        target = new Target(argument);
                        break;
                    case TargetType.singleCharacterWorld:
                        victim = ch.GetCharWorld(argument);
                        if (victim == null)
                        {
                            ch.SendText("Cast the spell on whom?\r\n");
                            return;
                        }
                        target = new Target(victim);
                        break;
                    case TargetType.trap:
                        ch.SendText("You cannot cast a trap!\r\n");
                        return;
                    case TargetType.singleCharacterOffensive:
                        if (String.IsNullOrEmpty(argument))
                        {
                            victim = ch.Fighting;
                            if (victim == null)
                            {
                                if (ch.IsClass(CharClass.Names.psionicist))
                                    ch.SendText("Will the spell upon whom?\r\n");
                                else
                                    ch.SendText("Cast the spell upon whom?\r\n");
                                return;
                            }
                        }
                        else
                        {
                            victim = ch.GetCharRoom(argument);
                            if (!victim)
                            {
                                ch.SendText("They aren't here.\r\n");
                                return;
                            }
                        }

                        if (ch.IsAffected( Affect.AFFECT_CHARM) && ch.Master == victim)
                        {
                            ch.SendText("You can't do that to your master!.\r\n");
                            return;
                        }

                        if (Combat.IsSafe(ch, victim))
                            return;
                        // Combat.IsSafe could wipe out victim, as it calls procs if a boss
                        // check and see that victim is still valid
                        if (!victim)
                            return;

                        Crime.CheckAttemptedMurder(ch, victim);
                        target = new Target(victim);
                        ch.BreakInvisibility();
                        break;

                    case TargetType.singleCharacterDefensive:
                        if (String.IsNullOrEmpty(argument))
                        {
                            victim = ch;
                        }
                        else
                        {
                            victim = ch.GetCharRoom(argument);
                            if (victim == null)
                            {
                                ch.SendText("They aren't here.\r\n");
                                return;
                            }
                        }

                        target = new Target(victim);
                        break;

                    case TargetType.self:
                        if (!String.IsNullOrEmpty(argument) && !MUDString.NameContainedIn(argument, ch.Name) &&
                                "me".Equals(argument, StringComparison.CurrentCultureIgnoreCase) &&
                                "self".Equals(argument, StringComparison.CurrentCultureIgnoreCase))
                        {
                            ch.SendText("You cannot cast this spell on another.\r\n");
                            return;
                        }

                        target = new Target(ch);
                        break;

                    case TargetType.objectInInventory:
                        if (String.IsNullOrEmpty(argument))
                        {
                            ch.SendText("What item should the spell be cast upon?\r\n");
                            return;
                        }

                        obj = ch.GetObjCarrying(argument);
                        if (obj == null)
                        {
                            ch.SendText("You are not carrying that.\r\n");
                            return;
                        }

                        target = new Target(obj);
                        break;

                    case TargetType.objectInRoom:
                        if (String.IsNullOrEmpty(argument))
                        {
                            ch.SendText("What should the spell be cast upon?\r\n");
                            return;
                        }

                        obj = ch.GetObjHere(argument);
                        if (obj == null)
                        {
                            ch.SendText("You do not see that here.\r\n");
                            return;
                        }

                        target = new Target(obj);
                        break;

                    case TargetType.objectCorpse:
                        target = new Target(argument);
                        break;
                    case TargetType.objectOrCharacter:
                        if (String.IsNullOrEmpty(argument))
                        {
                            if (ch.Fighting != null)
                                victim = ch.Fighting;
                            else
                            {
                                ch.SendText("Cast upon what?\r\n");
                                return;
                            }
                        }
                        else if (!(victim = ch.GetCharRoom(argument)))
                        {
                            obj = ch.GetObjHere(argument);
                        }

                        if (victim != null)
                        {
                            target = new Target(victim);
                        }
                        else if (obj != null)
                        {
                            target = new Target(obj);
                        }
                        else
                        {
                            ch.SendText("You do not see that here.\r\n");
                            return;
                        }

                        break;
                    case TargetType.singleCharacterRanged:
                        if (String.IsNullOrEmpty(argument))
                        {
                            victim = ch.Fighting;
                            if (victim == null)
                            {
                                ch.SendText("Cast the spell on whom?\r\n");
                                return;
                            }
                        }
                        else
                        {
                            victim = ch.GetCharRoom(argument);
                            if (!victim)
                            {
                                ch.SendText("They aren't here.\r\n");
                                return;
                            }
                            // Ranged combat.
                            //
                            // TODO: FIXME: The next line does not successfully get the required argument.
                            //int dir = Movement.FindExit(ch, arg3);
                            //if (ch._level >= Limits.LEVEL_IMMORTAL)
                            //{
                            //    buf = String.Format("Looking for {0} to the {1}.\r\n", arg2, arg3);
                            //    ch.SendText(buf);
                            //}
                            //if (ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.walled)
                            //        || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.blocked)
                            //        || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.secret)
                            //        || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.closed)
                            //        || !ch._inRoom._exitData[dir]._targetRoom
                            //        || ch._inRoom._area != ch._inRoom._exitData[dir]._targetRoom._area)
                            //{
                            //    ch.SendText("You see nothing in that direction.\r\n");
                            //    return;
                            //}
                            //room2 = Movement.FindRoom(ch, arg3);
                            //if (room2 == null)
                            //{
                            //    ch.SendText("You see nothing in that direction.\r\n");
                            //    return;
                            //}
                            //victim = CharData.GetCharAtRoom(room2, ch, arg2);
                            //if (victim == null)
                            //{
                            //    Room room3;
                            //    if (room2._exitData[dir] && ((room3 = Room.GetRoom(room2._exitData[dir]._vnum))) &&
                            //        spell == Spell.SpellList["fireball"])
                            //    {
                            //        victim = CharData.GetCharAtRoom(room3, ch, arg2);
                            //    }
                            //}
                            //if (victim == null)
                            //{
                            //    ch.SendText("They aren't here.\r\n");
                            //    return;
                            //}
                            //} //end else
                        } //end else
                        if (ch.IsAffected(Affect.AFFECT_CHARM) && ch.Master == victim)
                        {
                            ch.SendText("You can't do that to your master!.\r\n");
                            return;
                        }

                        if (Combat.IsSafe(ch, victim))
                            return;
                        // Combat.IsSafe could wipe out victim, as it calls procs if a boss
                        // check and see that victim is still valid
                        if (!victim)
                            return;

                        Crime.CheckAttemptedMurder(ch, victim);

                        target = new Target(victim);
                        ch.BreakInvisibility();
                        break;
                }

            int beats = 0;  // For quick chant
            if (!ch.IsClass(CharClass.Names.bard) && !ch.IsClass(CharClass.Names.psionicist))
            {
                ch.SendText( "You begin casting...\r\n" );
                if( "ventriloquate".Equals(spell.Name, StringComparison.CurrentCultureIgnoreCase ))
                {
                    if( spell.ValidTargets == TargetType.singleCharacterOffensive
                            || spell.ValidTargets == TargetType.singleCharacterRanged )
                        SocketConnection.Act( "$n&n begins casting an offensive spell...", ch, null, null, SocketConnection.MessageTarget.room );
                    else
                        SocketConnection.Act( "$n&n begins casting...", ch, null, null, SocketConnection.MessageTarget.room );
                }
                beats = spell.CastingTime;
            }
            else if (ch.IsClass(CharClass.Names.bard))
            {
                ch.SendText( "You begin singing...\r\n" );
                SocketConnection.Act( "$n&n starts singing...", ch, null, null, SocketConnection.MessageTarget.room );
                beats = 0;
            }

            if (!ch.IsClass(CharClass.Names.psionicist) && !ch.IsClass(CharClass.Names.bard))
            {
                // Characters with int of 110 have normal memtimes.
                // int of 100 worsens casting times by 10%
                // with an int of 55 casting times are doubled.
                // This may seem a bit harsh, but keep in mind any
                // casters are very likely to have an int above 100, as it
                // is their prime requisite.  120 is the max int for Grey Elves
                // to start.
                if (ch.IsClass(CharClass.Names.cleric) || ch.IsClass(CharClass.Names.druid)
                        || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))
                {
                    beats = ( beats * 110 ) / ch.GetCurrWis();
                }
                else if (ch.IsClass( CharClass.Names.shaman))
                {
                    beats = ( beats * 330 ) / ( ch.GetCurrInt() + ( ch.GetCurrWis() * 2 ) );
                }
                else
                {
                    beats = ( beats * 110 ) / ch.GetCurrInt();
                }

                if( ch.CheckSkill("quick chant", PracticeType.only_on_success) )
                {
                    beats = beats / 2;
                }

                /*
                * A check for impossibly long cast times...came about from a player
                * trying to cast when feebleminded.  100 casting time is arbitrary.
                */
                if( beats > 100 )
                {
                    ch.SendText( "Forget it!  In your present state you haven't a dream of success.\r\n" );
                    return;
                }
                ch.WaitState( beats );

                if( CheckHypnoticPattern( ch ) )
                {
                    return;
                }

                CastData caster = new CastData();
                caster.Who = ch;
                caster.Eventdata = Event.CreateEvent( Event.EventType.spell_cast, beats, ch, target, spell );
                Database.CastList.Add( caster );
                ch.SetAffectBit( Affect.AFFECT_CASTING );
            }
            else if (ch.IsClass( CharClass.Names.psionicist))
            {
                ch.WaitState( beats );

                if( CheckHypnoticPattern( ch ) )
                {
                    return;
                }

                ch.PracticeSpell( spell );

                int mana = 0;
                if( !ch.IsImmortal() && !ch.IsNPC()
                        && ch.Level < ( spell.SpellCircle[ (int)ch.CharacterClass.ClassNumber ] * 4 + 1 )
                        && MUDMath.NumberPercent() > ((PC)ch).SpellAptitude[spell.Name])
                {
                    ch.SendText( "You lost your concentration.\r\n" );
                    SocketConnection.Act( "&+r$n&n&+r's face flushes white for a moment.&n", ch, null, null, SocketConnection.MessageTarget.room );
                    ch.CurrentMana -= mana / 2;
                }
                else
                {
                    ch.CurrentMana -= mana;
                    string buf = String.Format( "Spell {0} ({1}) being willed by {2}", spell,
                                                spell.Name, ch.Name );
                    Log.Trace( buf );
                    ch.SetAffectBit( Affect.AFFECT_CASTING );
                    FinishSpell( ch, spell, target );
                }
                if( ch.CurrentPosition > Position.sleeping && ch.CurrentMana < 0 )
                {
                    ch.WaitState( 2 * Event.TICK_PER_SECOND );
                    ch.SendText( "&+WThat last spe&+wll w&+Las a _bitvector&+l much...&n\r\n" );
                    ch.CurrentPosition = Position.standing;
                    ch.Fighting = null;
                    SocketConnection.Act( "$n&n collapses from exhaustion&n.",
                         ch, null, null, SocketConnection.MessageTarget.room );
                    ch.CurrentPosition = Position.sleeping;
                }

                if( spell.ValidTargets == TargetType.singleCharacterOffensive
                        && victim && victim.Master != ch && victim != ch && victim.IsAwake() )
                {
                    foreach( CharData roomChar in ch.InRoom.People )
                    {
                        if( victim == roomChar && !victim.Fighting )
                        {
                            victim.AttackCharacter( ch );
                            break;
                        }
                    }
                }
            }
            else if( ch.IsClass(CharClass.Names.bard ))
            {
                ch.WaitState( 0 );

                // Create an event to handle the spell
                CastData caster = new CastData();
                caster.Who = ch;
                caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG, ch, target, spell );
                caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 2, ch, target, spell);
                caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 3, ch, target, spell);
                caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 4, ch, target, spell);
                caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 5, ch, target, spell);
                Database.CastList.Add( caster );
                ch.SetAffectBit( Affect.AFFECT_SINGING );
            }
            return;
        }