示例#1
0
        // This _function should prevent a mob from spamming
        // spellups on itself if it is already affected by the spell.
        // in the Spellup() _function, checks for Affect.AFFECT_WHATEVER
        // still need to be done. - Xangis
        static bool CheckSpellup( CharData ch, string name, int percent )
        {
            if (ch == null) return false;
            if (String.IsNullOrEmpty(name))
                return false;

            Spell spell = Spell.SpellList[name];
            if (spell == null)
            {
                return false;
            }

            // Keep mobs from casting spells they are affected by
            if( ch.HasAffect( Affect.AffectType.spell, spell ) )
                return false;

            if( ( ch.HasSpell( name ) )
                    && ( MUDMath.NumberPercent() < percent ) )
            {
                if (spell.ValidTargets != TargetType.singleCharacterDefensive &&
                        spell.ValidTargets != TargetType.self)
                    Log.Error( "CheckSpellup:  Mob casting spell {0} which is neither TargetType.self nor TargetType.defensive.", spell );

                SocketConnection.Act( "$n&n starts casting...", ch, null, null, SocketConnection.MessageTarget.room );
                ch.SetAffectBit( Affect.AFFECT_CASTING );
                CastData caster = new CastData();
                caster.Who = ch;
                caster.Eventdata = Event.CreateEvent(Event.EventType.spell_cast, spell.CastingTime, ch, ch, spell);
                Database.CastList.Add( caster );
                return true;
            }

            return false;
        }
示例#2
0
        /*
        * If a spell casting mob is hating someone, try to summon them.
        *
        * Xangis - Need to add code to also gate to the person if they can't be summoned
        */
        static void SummonIfHating( CharData ch )
        {
            string name = String.Empty;
            string buf = String.Empty;

            if( ch.Fighting || ch.Fearing || ch.Hating.Count == 0 || ch.InRoom.HasFlag( RoomTemplate.ROOM_SAFE ) )
                return;

            /* If summoner is busy hunting someone aleady, don't summon. */
            if( ch.Hunting )
                return;

            CharData victim = ch.GetRandomHateTarget( false );

            // Pretty stupid to summon someone who's in the same room.
            if( !victim || ch.InRoom == victim.InRoom )
                return;

            if( ( ch.HasSpell( "relocate" ) ))
            {
                if( !victim.IsNPC() )
                    buf += "relocate 0." + name;
                else
                    buf += "relocate " + name;
            }
            else if( ch.HasSpell( "summon" ) )
            {
                if( !victim.IsNPC() )
                    buf += "summon 0." + name;
                else
                    buf += "summon " + name;
            }
            else if ((ch.Level * 4 - 3) >= Spell.SpellList["spirit jump"].SpellCircle[(int)ch.CharacterClass.ClassNumber])
            {
                if( !victim.IsNPC() )
                    buf += "'spirit jump' 0." + name;
                else
                    buf += "'spirit jump' " + name;
            }

            CommandType.Interpret(ch, "cast " + buf);
            return;
        }
示例#3
0
        /// <summary>
        /// Check for use of Direct targeted spells (TargetType.singleCharacterOffensive)
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="spell"></param>
        /// <param name="percent"></param>
        /// <returns></returns>
        public static bool CheckOffensive( CharData ch, CharData victim, Spell spell, int percent )
        {
            if (ch == null) return false;
            string buf = String.Format("CheckOffensive: spell ({0})'{1}'", spell, spell.Name);
            Log.Trace( buf );

            if( spell == null )
                return false;

            if( ch.HasSpell(spell) && ( MUDMath.NumberPercent() < percent ) )
            {
                if (spell.ValidTargets != TargetType.singleCharacterOffensive &&
                        spell.ValidTargets != TargetType.none &&
                        spell.ValidTargets != TargetType.singleCharacterRanged)
                    Log.Error( "Check_spellup:  Mob casting spell {0} which is neither _targetType offensive nor ignore.a", spell );

                SocketConnection.Act( "$n&n  starts casting...", ch, null, null, SocketConnection.MessageTarget.room );
                ch.SetAffectBit( Affect.AFFECT_CASTING );
                CastData caster = new CastData();
                caster.Who = ch;
                caster.Eventdata = Event.CreateEvent(Event.EventType.spell_cast, spell.CastingTime, ch, victim, spell);
                Database.CastList.Add( caster );
                return true;
            }

            return false;
        }
示例#4
0
        /// <summary>
        /// This is called by Command.Memorize and Commandpray.  This was originally
        /// attached to each function, but it's silly to have two large blocks
        /// of the same code
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="argument"></param>
        /// <param name="pray"></param>
        public static void Memorize( CharData ch, string argument, bool pray )
        {
            string text;
            Dictionary<String, Int32> memmed = new Dictionary<String, Int32>();
            int[] circle = new int[ Limits.MAX_CIRCLE ];
            int[] circfree = new int[ Limits.MAX_CIRCLE ];

            // with an argument they want to start memorizing a new spell.
            if( !String.IsNullOrEmpty(argument) )
            {
                // Must be in the proper position
                if( ch.CurrentPosition != Position.resting )
                {
                    if( pray )
                        ch.SendText( "You can only pray for spells while resting.\r\n" );
                    else
                        ch.SendText( "You can memorize spells only when resting.\r\n" );
                    return;
                }

                // Find the spell they want
                Spell spell = StringLookup.SpellLookup( argument );
                if( spell == null )
                {
                    ch.SendText( "Never heard of that spell...\r\n" );
                    return;
                }

                // Check to see that they can memorize another spell
                // Immortals have no limits
                if( !ch.IsImmortal() )
                {
                    if( ( (PC)ch ).Hunger <= 0 || ( (PC)ch ).Thirst <= 0 )
                    {
                        ch.SendText( "You can't seem to concentrate on anything but your appetite.\r\n" );
                    }

                    if( !ch.HasSpell( argument ) )
                    {
                        ch.SendText( "That spell is beyond you.\r\n" );
                        return;
                    }

                    if (!pray && ((PC)ch).SpellAptitude[spell.Name] < 1)
                    {
                        ch.SendText( "You have not yet learned that spell.  Find a place to scribe it.\r\n" );
                        return;
                    }

                    int lvltotal = 0;
                    foreach( MemorizeData mem in ((PC)ch).Memorized )
                    {
                        if (mem.Circle == spell.SpellCircle[(int)ch.CharacterClass.ClassNumber])
                            lvltotal += 1;
                    }
                    int numMemmable = 0;
                    if (ch.CharacterClass.MemType == CharClass.MemorizationType.Lesser)
                    {
                        numMemmable = LesserMemchart[(ch.Level - 1), (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] - 1)];
                    }
                    else
                    {
                        numMemmable = Memchart[(ch.Level - 1), (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] - 1)];
                    }
                    if (lvltotal >= numMemmable )
                    {
                        if( pray )
                            ch.SendText( "You can pray for no more spells of that level.\r\n" );
                        else
                            ch.SendText( "You can memorize no more spells of that circle.\r\n" );
                        return;
                    }
                }

                // If we know what they want and they can have it, let's create it.
                MemorizeData memm = CreateMemorizeData( ch, spell );
                if( !memm )
                {
                    Log.Error( "Unable to create memorization (spell {0})", spell );
                    return;
                }

                // If they're not already memorizing, they are now.
                ch.SetActionBit(PC.PLAYER_MEMORIZING );

                if( pray )
                    text = String.Format( "You start praying for {0} which will take about {1} seconds.\r\n",
                              spell.Name, ( memm.Memtime / Event.TICK_PER_SECOND ) );
                else
                    text = String.Format( "You start memorizing {0} which will take about {1} seconds.\r\n",
                              spell.Name, ( memm.Memtime / Event.TICK_PER_SECOND ) );
                ch.SendText( text );

                return;
            }
            bool found = false;
            // If they didn't give us an argument, that means that they must
            // want to either see their spell list or continue memorizing
            // Either way we show their spell list.
            // make sure they have some mem data first...
            int count;
            if( ( (PC)ch ).Memorized.Count > 0 )
            {
                // Figure out what spells they have memorized
                foreach( MemorizeData mem in ((PC)ch).Memorized )
                {
                    if( mem.Memmed )
                    {
                        if (memmed.ContainsKey(mem.Name))
                        {
                            memmed[mem.Name] = memmed[mem.Name] + 1;
                        }
                        else
                        {
                            memmed[mem.Name] = 1;
                        }
                    }
                }

                // Show memorized spells
                if( pray )
                    ch.SendText( "You have prayed the following spells:\r\n" );
                else
                    ch.SendText( "You have memorized the following spells:\r\n" );
                int circleIndex;
                for( circleIndex = 12; circleIndex > 0; circleIndex-- )
                {
                    foreach (KeyValuePair<String, Spell> kvp in Spell.SpellList)
                    {
                        if (kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber] != circleIndex)
                            continue;
                        if( memmed.ContainsKey(kvp.Key) && memmed[ kvp.Key ] > 0 && kvp.Value.Name != null )
                        {
                            text = String.Format( "({0,2}{1} circle)  {2} - {3}\r\n",
                                                 kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber],
                                                 MUDString.NumberSuffix(kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber]),
                                                 memmed[ kvp.Key ],
                                                 kvp.Value.Name );
                            ch.SendText( text );
                        }
                    }
                } //end for(circle)

                // Figure out what spells they are working on
                if( pray )
                    ch.SendText( "You are praying for the following spells:\r\n" );
                else
                    ch.SendText( "You are memorizing the following spells:\r\n" );
                int totalMem = 0;
                // TODO: Make sure we cycle through this in the right order.
                // [ might need to do _memorized.Reverse() ]
                foreach( MemorizeData mem in ((PC)ch).Memorized )
                {
                    if( mem.Name == null )
                        break;
                    if( mem.Memmed )
                        continue;
                    found = true;
                    text = String.Format( "    {0} seconds:  ({1}{2}) {3}\r\n",
                                         ( ( totalMem + mem.Memtime ) / Event.TICK_PER_SECOND ),
                                         Spell.SpellList[mem.Name].SpellCircle[(int)ch.CharacterClass.ClassNumber],
                                         MUDString.NumberSuffix(Spell.SpellList[mem.Name].SpellCircle[(int)ch.CharacterClass.ClassNumber]),
                                         mem.Name );
                    ch.SendText( text );
                    totalMem += mem.Memtime;
                }
            }

            //
            // Tell them what they still have slots open for...
            for( count = 0; count < Limits.MAX_CIRCLE; ++count )
                circle[ count ] = 0;
            foreach( MemorizeData mem in ((PC)ch).Memorized )
            {
                circle[ ( mem.Circle - 1 ) ] += 1;
            }
            bool left = false;
            for( count = 0; count < Limits.MAX_CIRCLE; ++count )
            {
                int numMemmable = 0;
                if (ch.CharacterClass.MemType == CharClass.MemorizationType.Lesser)
                {
                    numMemmable = LesserMemchart[(ch.Level - 1), count];
                }
                else
                {
                    numMemmable = Memchart[(ch.Level - 1), count];
                }
                circfree[ count ] = numMemmable - circle[ count ];
                if( circfree[ count ] > 0 )
                    left = true;
            }
            if( !left )
            {
                if( pray )
                    ch.SendText( "\r\nYou can pray for no more spells.\r\n" );
                else
                    ch.SendText( "\r\nYou can memorize no more spells.\r\n" );
            }
            else
            {
                if( pray )
                    text = String.Format( "\r\nYou can pray for" );
                else
                    text = String.Format( "\r\nYou can memorize" );
                for( count = 0; count < Limits.MAX_CIRCLE; ++count )
                {
                    if( circfree[ count ] > 0 )
                    {
                        string buf2 = String.Format( " {0}x{1}{2}", circfree[ count ], ( count + 1 ), MUDString.NumberSuffix( count + 1 ) );
                        text += buf2;
                    }
                }
                text += " level spells.\r\n";
                ch.SendText( text );
            }

            // If they aren't memming and they should be, start 'em up.
            if( found && !ch.HasActionBit(PC.PLAYER_MEMORIZING )
                && ch.CurrentPosition == Position.resting )
            {
                ch.SetActionBit(PC.PLAYER_MEMORIZING );
                if( ( (PC)ch ).Hunger > 0
                    && ( (PC)ch ).Thirst > 0 )
                {
                    if( pray )
                        ch.SendText( "You continue your prayers.\r\n" );
                    else
                        ch.SendText( "You continue your studies.\r\n" );
                }
            }
            return;
        }
示例#5
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;
        }
示例#6
0
        /// <summary>
        /// Handles all spellcasting, whether it be willing, singing, or casting
        /// If they got here as a bard, they're using the SING command word,
        /// if they got here as a psionicist, they're using the WILL command word,
        /// and if they got here as anything else, they're using CAST.
        ///
        /// These are just cheesy details handled by CommandType.cs... we don't care.
        /// What we do care about is that we *know* it's safe to base all our
        /// messages/decisions on the character's class.
        ///
        /// This function is also *mob-safe*, meaning that mobs can cast spells
        /// too.  However, this is not the preferred method (as far as I can tell)
        ///
        /// Shaman totems are checked for in this function.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="argument"></param>
        public static void Cast( CharData ch, string argument )
        {
            // No casting while berzerked... Nor singing! Hah!
            if (ch.IsAffected(Affect.AFFECT_BERZERK))
            {
                ch.SendText( "Not while you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!\r\n" );
                return;
            }

            // No casting while thirsty... Nor singing! Hah!
            if (ch.IsAffected(Affect.AFFECT_THIRST) && ( ch.IsNPC() || ( (PC)ch ).Thirst < 10 ) )
            {
                ch.SendText( "&+BNo&+Ct w&+chi&+ble &+cyo&+Bu'&+cre &+Bso p&+carc&+Bhed&n!\r\n" );
                return;
            }

            String[] pieces = argument.Split( new Char[] {'\''}, StringSplitOptions.RemoveEmptyEntries);
            if (pieces.Length < 1)
            {
                ch.SendText("Spell names must always be in single quotes, such as:  cast 'magic missile' troll.\r\n");
                return;
            }
            if (pieces.Length > 1)
            {
                pieces[1] = pieces[1].Trim();
            }

            Spell spell;
            if (((spell = StringLookup.SpellLookup(pieces[0])) == null) || ((!ch.HasSpell(pieces[0])) && !ch.IsImmortal()))
            {
                ch.SendText( "You can't do that.\r\n" );
                return;
            }

            if( !CheckTotem( ch, spell ))
                return;

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

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

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

            if( !ch.InRoom.CheckCastable( ch, ch.IsClass( CharClass.Names.bard ), true) )
                return;

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

            int manaUsed = 0;
            // TODO: Rather than hard-code psionicist as a mana class, let that be set in the class files.
            if (ch.IsClass(CharClass.Names.psionicist))
            {
                manaUsed = Macros.ManaCost(ch, spell);
            }
            else if (ch.IsClass(CharClass.Names.bard))
            {
                manaUsed = spell.MinimumMana;
            }

            // Locate targets.
            if( ch.IsNPC() )
            {
                ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, "Magic.Cast: Attempting to find _targetType for " + ch.ShortDescription + "&n." );
            }

            if (pieces.Length > 1)
            {
                ProcessSpellTargets(ch, spell, pieces[1]);
            }
            else
            {
                ProcessSpellTargets(ch, spell, null);
            }
        }