예제 #1
0
        /// <summary>
        /// Inflict damage from a single hit.  This could use some cleanup since it's way too unwieldy at more than 600 lines.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="dam"></param>
        /// <param name="skill"></param>
        /// <param name="weapon"></param>
        /// <param name="damType"></param>
        /// <returns></returns>
        public static bool InflictDamage(CharData ch, CharData victim, int dam, string skill, ObjTemplate.WearLocation weapon, AttackType.DamageType damType)
        {
            if (ch == null || victim == null)
            {
                return false;
            }

            Object obj;
            bool critical = false;

            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                return true;
            }

            /*
            * Stop up any residual loopholes.
            */
            if( ( dam > 1276 ) && ch.Level < Limits.LEVEL_AVATAR )
            {
                string text;

                if (ch.IsNPC() && ch.Socket)
                {
                    text = String.Format("Damage: {0} from {1} by {2}: > 1276 points with {3} damage type!",
                              dam, ch.Name, ch.Socket.Original.Name, skill);
                }
                else
                {
                    text = String.Format("Damage: {0} from {1}: > 1276 points with {2} damage type!",
                              dam, ch.IsNPC() ? ch.ShortDescription : ch.Name, skill);
                }
                Log.Error( text, 0 );
                dam = 1276;
            }

            // Remove memorization and meditation bits - Xangis
            victim.BreakMeditate();
            victim.BreakMemorization();
            if (victim.IsAffected( Affect.AFFECT_MINOR_PARA))
            {
                SocketConnection.Act( "$n&n disrupts the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                SocketConnection.Act( "You disrupt the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+YYou can move again.&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                victim.RemoveAffect( Affect.AFFECT_MINOR_PARA );
            }

            bool immune = false;
            if( victim != ch )
            {
                /*
                * Certain attacks are forbidden.
                * Most other attacks are returned.
                */
                victim = CheckGuarding( ch, victim );
                if( IsSafe( ch, victim ) )
                    return false;
                // is_safe could wipe out victim, as it calls procs if a boss
                // check and see that victim is still valid
                if( victim == null )
                    return true;
                Crime.CheckAttemptedMurder( ch, victim );
                if( victim.CurrentPosition > Position.stunned )
                {
                    if( !victim.Fighting )
                        SetFighting( victim, ch );
                    // Can't have prone people automatically stand
                    if( victim.CurrentPosition == Position.standing )
                        victim.CurrentPosition = Position.fighting;

                    if( !ch.Fighting )
                        SetFighting( ch, victim );

                    /*
                    * If NPC victim is following, ch might attack victim's master.
                    * No charm check here because charm would be dispelled from
                    * tanking mobile when combat ensues thus ensuring PC charmer is
                    * not harmed.
                    * Check for IsSameGroup wont work as following mobile is not
                    * always grouped with PC charmer
                    *
                    * Added a check for whether ch has switch skill.  If not,
                    * much lower chancing of retargetting
                    */
                    if( ch.IsNPC()
                            && victim.IsNPC()
                            && victim.Master
                            && victim.Master.InRoom == ch.InRoom
                            && MUDMath.NumberBits( 2 ) == 0 )
                    {
                        StartGrudge( ch, victim.Master, false );
                    }
                }

                /*
                * More charm stuff.
                */
                if( victim.Master == ch )
                {
                    StopFighting( victim, true );
                }

                ch.BreakInvisibility();

                /*
                * Hunting stuff...
                */
                if( dam != 0 && victim.IsNPC() )
                {
                    /* StartGrudge is combined StartHating and StartHunting */
                    StartGrudge( victim, ch, false );
                }

                /*
                * Damage modifiers.
                */

                // Critical hits for double damage
                // Average of 5% for those that have average luck
                // Gnomes could concievably have 10%
                if( MUDMath.NumberPercent() < ( 2 + ( ch.GetCurrLuck() / 18 ) ) && dam > 0 )
                {
                    ch.SendText( "&+WYou score a CRITICAL HIT!&n\r\n" );
                    dam *= 2;
                    critical = true;
                }

                if( victim.IsAffected( Affect.AFFECT_SANCTUARY ) )
                    dam /= 2;

                if( victim.IsAffected( Affect.AFFECT_PROTECT_EVIL ) && ch.IsEvil() )
                    dam -= dam / 8;
                else if( victim.IsAffected( Affect.AFFECT_PROTECT_GOOD ) && ch.IsGood() )
                    dam -= dam / 8;

                // Check stoneskin.  People not affected by a stoneskin affect
                // cannot lose their stoneskin for any reason.  This should mean
                // that mobs will keep their stoneskin and players should always
                // have a chance to lose it, since no player should ever be
                // setbit stoneskin.
                //
                // The bool value of found is used so that we can have them
                // take full damage when their stoneskin shatters, but get the
                // damage reduction if they are either a mob or their stoneskin
                // wears off that round.
                //
                /* Yeah, yeah.. so maybe backstabs shouldn't be aff'd. */
                // Actually they should be affected, but they should have a much
                // higher chance of getting through (say 30-70%).
                //
                // Critical hits will now go through stoneskin
                // automatically
                if (!critical && victim.IsAffected( Affect.AFFECT_STONESKIN) &&
                        ( skill != "backstab" || MUDMath.NumberPercent() < ( 25 + ch.Level ) ) )
                {
                    bool found = false;
                    for (int i = (victim.Affected.Count - 1); i >= 0; i--)
                    {
                        if( victim.Affected[i].HasBitvector( Affect.AFFECT_STONESKIN ) )
                        {
                            // Small chance of shattering the stoneskin on a good hit.
                            // Reduced chance by about 20%
                            if( dam >= 25 && MUDMath.NumberPercent() <= ( dam / 12 ) )
                            {
                                victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" );
                                SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                                SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character );
                                victim.RemoveAffect(victim.Affected[i]);
                                found = true;
                            }
                            else if( dam > 0 ) // Added check for actual damage
                            {
                                for( int j = 0; j < victim.Affected[i].Modifiers.Count; j++ )
                                {
                                    victim.Affected[i].Modifiers[j].Amount--;
                                    if (victim.Affected[i].Modifiers[j].Amount < 1)
                                    {
                                        victim.RemoveAffect(victim.Affected[i]);
                                        victim.SendText("&+LYou feel your skin soften and return to normal.&n\r\n");
                                    }
                                    dam /= 15;
                                    found = true;
                                }
                            }
                        }
                    }
                    // This means they're Affect.AFFECT_STONESKIN as an innate/permenant.
                    // We will still allow it to shatter, but it will refresh itself
                    // upon a mob update.  Because of this, we make it easier to shatter.
                    // No damage reduction when it shatters.
                    if( !found )
                    {
                        if( dam >= 8 && MUDMath.NumberPercent() <= ( dam / 8 ) )
                        {
                            victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" );
                            SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                            SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character );
                            victim.RemoveAffect( Affect.AFFECT_STONESKIN );
                        }
                        else
                        {
                            dam = dam / 15 != 0 ? dam / 15 : 1;
                        }
                    }

                }

                if( dam < 0 )
                    dam = 0;

                /*
                * Check for disarm, trip, parry, dodge and shield block.
                */
                if (skill != "barehanded fighting" || skill == "kick")
                {
                    // Trip and disarm removed because those should be handled
                    // by each individual mob's special function.
                    if( ch.IsNPC()
                            && ch.HasInnate( Race.RACE_WEAPON_WIELD )
                            && MUDMath.NumberPercent() < Math.Min( 25, Math.Max( 10, ch.Level ) )
                            && !victim.IsNPC() )
                        UseMagicalItem( ch );
                }
            }

            switch( victim.CheckRIS( damType ) )
            {
                case Race.ResistanceType.resistant:
                    dam -= dam / 3;
                    break;
                case Race.ResistanceType.immune:
                    immune = true;
                    dam = 0;
                    break;
                case Race.ResistanceType.susceptible:
                    dam += dam / 2;
                    break;
                case Race.ResistanceType.vulnerable:
                    dam *= 2;
                    break;
                default:
                    break;
            }

            if( ( damType == AttackType.DamageType.wind || damType == AttackType.DamageType.gas || damType == AttackType.DamageType.asphyxiation )
                    && victim.IsAffected(Affect.AFFECT_DENY_AIR))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+CYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_DENY_FIRE))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+rYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.earth || damType == AttackType.DamageType.crushing )
                    && victim.IsAffected( Affect.AFFECT_DENY_EARTH))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+yYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.water || damType == AttackType.DamageType.acid || damType == AttackType.DamageType.drowning )
                    && victim.IsAffected( Affect.AFFECT_DENY_WATER))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+bYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }

            // Check for protection spells that give 25% damage reduction - Xangis
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_PROTECT_FIRE))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.cold && victim.IsAffected( Affect.AFFECT_PROTECT_COLD))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.acid && victim.IsAffected( Affect.AFFECT_PROTECT_ACID))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.gas && victim.IsAffected( Affect.AFFECT_PROTECT_GAS))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.electricity && victim.IsAffected( Affect.AFFECT_PROTECT_LIGHTNING))
                dam = ( dam * 3 ) / 4;

            // Barkskin protects from 8% of slash and 12% of pierce damage.
            if (victim.IsAffected( Affect.AFFECT_BARKSKIN))
            {
                if (skill == "1h slashing" || skill == "2h slashing")
                    dam = dam * 11 / 12;
                else if (skill == "1h piercing" || skill == "2h piercing")
                    dam = dam * 7 / 8;
            }

            // Check for vampiric touch for anti-paladins and vampires
            if( weapon == ObjTemplate.WearLocation.hand_one || weapon == ObjTemplate.WearLocation.hand_two || weapon == ObjTemplate.WearLocation.hand_three || weapon == ObjTemplate.WearLocation.hand_four )
            {
                if( ( ( ch.IsClass(CharClass.Names.antipaladin) || ch.GetRace() == Race.RACE_VAMPIRE )
                        && skill == "barehanded fighting" && !Object.GetEquipmentOnCharacter(ch, weapon)) || (ch.IsAffected( Affect.AFFECT_VAMP_TOUCH)
                             && ( !( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) || obj.HasAffect( Affect.AFFECT_VAMP_TOUCH ) ) ) )
                {
                    ch.Hitpoints += dam / 3;
                    if( ch.Hitpoints > ( ch.GetMaxHit() + 50 + ch.Level * 5 ) )
                    {
                        ch.Hitpoints = ch.GetMaxHit() + 50 + ch.Level * 5;
                    }
                }
            }

            /* PC to PC damage quartered.
            *  NPC to PC damage divided by 3.
            */
            if( dam > 0 && !victim.IsNPC() && victim != ch )
            {
                if( !ch.IsNPC() )
                    dam /= 4;
                else
                    dam /= 3;
            }

            /*
            * Just a check for anything that is excessive damage
            * Send a log message, keeping the imms on their toes
            * Changed this from 300 to 250 'cause hitters get more than one
            *  attack/round and w/haste that's 1000 possible in the time one fist
            *  goes off.  That's more than the fist might do and it has to be
            *  memmed.
            */
            if (dam > 250 && skill != "backstab" )
            {
                string buf4;
                if (!string.IsNullOrEmpty(skill))
                {
                    buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, skill = {3}({4}).",
                              ch.Name, victim.Name, dam, Skill.SkillList[skill].DamageText, skill);
                }
                else
                {
                    buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, unknown damage type.",
                              ch.Name, victim.Name, dam);
                }
                Log.Trace( buf4 );
            }

            /*
            * We moved DamageMessage out of the victim != ch if above
            * so self damage would show.  Other valid type_undefined
            * damage is ok to avoid like mortally wounded damage
            */
            if (!String.IsNullOrEmpty(skill))
            {
                SendDamageMessage(ch, victim, dam, skill, weapon, immune);
            }

            victim.Hitpoints -= dam;

            /* Check for HOLY_SACRFICE and BATTLE_ECSTASY */
            if( dam > 0 && victim != ch )
            {
                CharData groupChar;
                if (victim.IsAffected( Affect.AFFECT_HOLY_SACRIFICE) && victim.GroupLeader)
                {
                    for( groupChar = victim.GroupLeader; groupChar; groupChar = groupChar.NextInGroup )
                    {
                        if( groupChar == victim || groupChar.InRoom != ch.InRoom )
                            continue;
                        groupChar.Hitpoints += dam / 5;
                        if (groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5)
                        {
                            groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5;
                        }
                    } //end for loop
                } //end if holy sac
                if( ch.GroupLeader != null )
                {
                    for( groupChar = ch.GroupLeader; groupChar != null; groupChar = groupChar.NextInGroup )
                    {
                        if( groupChar == victim || groupChar.InRoom != ch.InRoom )
                            continue;
                        if( groupChar.IsAffected( Affect.AFFECT_BATTLE_ECSTASY ) )
                        {
                            groupChar.Hitpoints += dam / 20;
                            if( groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5 )
                                groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5;
                        } // end if battle ecstasy
                    } //end for loop
                } //end if grouped
            } //end if

            // Make sure if they got an instant kill roll that the victim dies.
            if (skill == "instant kill")
            {
                if( victim.GetRace() != Race.RACE_DEVIL
                        && victim.GetRace() != Race.RACE_DEMON
                        && victim.GetRace() != Race.RACE_GOD )
                    victim.Hitpoints = -20;
            }

            /* Added damage exp! */
            // chance added because people level faster and faster as they get higher level...
            // to be worked out when exp is redone.
            // you can now only get damage exp on mobs that con easy or better
            // and there's only a 25% chance per hit of you evern being eligible for damage exp.
            if( MUDMath.NumberPercent() < 25 && victim.Level >= ( ch.Level - 3 ) )
                ch.GainExperience( Math.Max( 1, dam / 20 ) );

            if( !victim.IsNPC()
                    && victim.Level >= Limits.LEVEL_AVATAR
                    && victim.Hitpoints < 1 )
                victim.Hitpoints = 1;

            /*
            * Magic shields that retaliate
            *
            * Apparently two people with the same sort of shield do not
            * take damage from each other
            */
            if( ( dam > 1 ) && victim != ch )
            {
                if( victim.IsAffected( Affect.AFFECT_FIRESHIELD )
                        && !ch.IsAffected( Affect.AFFECT_FIRESHIELD ) )
                    InflictSpellDamage( victim, ch, dam / 2, "fireshield", AttackType.DamageType.fire );

                if (victim.IsAffected( Affect.AFFECT_COLDSHIELD)
                        && !ch.IsAffected(Affect.AFFECT_COLDSHIELD))
                    InflictSpellDamage( victim, ch, dam / 2, "coldshield", AttackType.DamageType.cold );

                if (victim.IsAffected(Affect.AFFECT_SHOCK_SHIELD)
                        && !ch.IsAffected(Affect.AFFECT_SHOCK_SHIELD))
                    InflictSpellDamage( victim, ch, dam / 2, "shockshield", AttackType.DamageType.electricity );

                /* Soulshield is a complex one.  If the attacker and victim are of
                * opposite alignment, the shield retaliates with 1/2 damage just like
                * any other shield.  If the victim is neutral and the attacker is
                * not, the shield retaliates with 1/4 damage.  If the victim is good
                * or evil and the attacker is neutral, the shield retaliates with
                * 1/8 damage.  If the attacker and victim are of same alignment,
                * the shield does nothing.
                */
                if (victim.IsAffected(Affect.AFFECT_SOULSHIELD)
                        && !ch.IsAffected(Affect.AFFECT_SOULSHIELD))
                {
                    if( victim.IsEvil() && ch.IsGood() )
                        InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsGood() && ch.IsEvil() )
                        InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsNeutral() && ( ch.IsEvil() || ch.IsGood() ) )
                        InflictSpellDamage(victim, ch, dam / 4, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsGood() && ch.IsNeutral() )
                        InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsEvil() && ch.IsNeutral() )
                        InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm);
                }
            }

            if (victim.IsAffected( Affect.AFFECT_BERZERK ) && victim.CurrentPosition <= Position.stunned )
                victim.RemoveAffect(Affect.AFFECT_BERZERK);

            if (dam > 0 && skill != "barehanded fighting"
                    && IsWieldingPoisoned( ch, weapon )
                    && !Magic.SpellSavingThrow( ch.Level, victim, AttackType.DamageType.poison ) )
            {
                InflictPoison( "poison_weapon", ch.Level, IsWieldingPoisoned( ch, weapon ), ch, victim );
                SocketConnection.Act( "$n&n suffers from the &+Gpoison&n inflicted upon $m.", victim, null, null, SocketConnection.MessageTarget.room, true );
                Object.StripAffect( Object.GetEquipmentOnCharacter( ch, weapon ), Affect.AffectType.skill, "poison weapon" );
            }

            victim.UpdatePosition();

            switch( victim.CurrentPosition )
            {
                case Position.mortally_wounded:
                    victim.SendText(
                        "&+LYou are &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n\r\n" );
                    SocketConnection.Act( "$n&+L is &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.incapacitated:
                    victim.SendText(
                        "&+LYou are incapacitated and will &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n\r\n" );
                    SocketConnection.Act( "$n&+L is incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.stunned:
                    victim.SendText( "&+LYou are stunned, but will probably recover.&n\r\n" );
                    SocketConnection.Act( "$n&+L is stunned, but will probably recover.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                case Position.dead:
                    if( victim == ch )
                    {
                        victim.SendText( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L!&n\r\n\r\n" );
                    }
                    else
                    {
                        string buf = String.Format( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L by&n {0}&+L!&n\r\n\r\n",
                                                    ch.ShowNameTo( victim, false ) );
                        victim.SendText( buf );
                    }
                    /* Added this to stop a bug. */
                    Combat.StopFighting( victim, true );
                    SocketConnection.Act( "$n&+L is &n&+rdead&+L!&n", victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                default:
                    if( dam > victim.GetMaxHit() / 5 )
                        victim.SendText( "That really did &+RHURT&n!\r\n" );
                    if( victim.Hitpoints < victim.GetMaxHit() / 10 )
                        victim.SendText( "You sure are &n&+rBL&+RE&n&+rE&+RDI&n&+rN&+RG&n!\r\n" );
                    break;
            }

            // Check for weapon procs
            if( ( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) && Position.dead != victim.CurrentPosition )
            {
                if( obj.SpecFun.Count > 0 )
                    obj.CheckSpecialFunction(true);
            }

            /*
            * Sleep spells and extremely wounded folks.
            */
            if( !victim.IsAwake() )      /* lets make NPC's not slaughter PC's */
            {
                if( victim.Fighting
                        && victim.Fighting.Hunting
                        && victim.Fighting.Hunting.Who == victim )
                    StopHunting( victim.Fighting );
                if( victim.Fighting
                        && !victim.IsNPC()
                        && ch.IsNPC() )
                    StopFighting( victim, true );
                else
                    StopFighting( victim, false );
            }

            /*
            * Payoff for killing things.
            */
            if( victim.CurrentPosition == Position.dead )
            {
                // Done in attempt to squelch the combat continuation bug
                StopFighting( victim, true );

                if( !victim.HasActionBit(MobTemplate.ACT_NOEXP ) || !victim.IsNPC() )
                    GroupExperienceGain( ch, victim );

                if( ch.IsNPC() )
                {
                    if( ch.Hunting )
                    {
                        if( ch.Hunting.Who == victim )
                            StopHunting( ch );
                    }
                    if( ch.IsHating(victim) )
                    {
                        ch.StopHating( victim );
                    }
                }

                if( !victim.IsNPC() )
                {
                    if( ch.IsNPC() )
                    {
                        ( (PC)victim ).MobDeaths++;
                        if( victim.IsGuild() )
                        {
                            ( (PC)victim ).GuildMembership.MonsterDeaths++;
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );

                    }
                    else
                    {
                        ( (PC)ch ).PlayerKills++;
                        ( (PC)victim ).PlayerDeaths++;

                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );

                        if( ch.IsGuild()
                                && victim.IsGuild()
                                && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership )
                        {
                            ( (PC)ch ).GuildMembership.PlayerKills++;
                            ( (PC)victim ).GuildMembership.PlayerDeaths++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                    }

                    string logBuf = String.Format( "{0}&n killed by {1}&n at {2}",
                              victim.Name, ( ch.IsNPC() ? ch.ShortDescription : ch.Name ),
                              victim.InRoom.IndexNumber );
                    Log.Trace( logBuf );
                    ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, logBuf );

                    /*
                    * Dying penalty:
                    *
                    * At level 1 you lose 12.5% of a level.
                    * At level 50 you lose 25% of a level.
                    */
                    // Made it so people level 5 and under lose no exp from death.
                    if( ch.Level > 5 )
                        victim.GainExperience( ( 0 - ( ( ( 50 + victim.Level ) * ExperienceTable.Table[ victim.Level ].LevelExperience ) / 400 ) ) );
                    if( victim.Level < 2 && victim.ExperiencePoints < 1 )
                        victim.ExperiencePoints = 1;

                }
                else
                {
                    if( !ch.IsNPC() )
                    {
                        ( (PC)ch ).MobKills++;
                        if( ch.IsGuild() )
                        {
                            ( (PC)ch ).GuildMembership.MonsterKills++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                        }
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );
                    }
                }
                KillingBlow( ch, victim );

                return true;
            }

            if( victim == ch )
            {
                return false;
            }

            /*
            * Wimp out?
            */
            if( victim.IsNPC() && dam > 0 )
            {
                if( ( victim.HasActionBit(MobTemplate.ACT_WIMPY ) && MUDMath.NumberBits( 1 ) == 0
                        && victim.Hitpoints < victim.GetMaxHit() / 5 )
                        || (victim.IsAffected( Affect.AFFECT_CHARM) && victim.Master
                             && victim.Master.InRoom != victim.InRoom ) )
                {
                    StartFearing( victim, ch );
                    StopHunting( victim );
                    CommandType.Interpret(victim, "flee");
                }
            }

            if( !victim.IsNPC() && victim.Hitpoints > 0 && victim.Hitpoints <= victim.Wimpy )
            {
                CommandType.Interpret(victim, "flee");
            }

            return false;
        }
예제 #2
0
        /// <summary>
        /// Search the local area for food.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Forage(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int indexNumber;
            Object obj = null;
            int[] flist = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 };

            if (!ch.InRoom)
            {
                ch.SendText("There's no foraging to be done here.\r\n");
                return;
            }

            if (ch.FlightLevel != 0)
            {
                ch.SendText("Right, you're going to find something way up here.\r\n");
                return;
            }
            int chance = 10 + (ch.GetCurrLuck() / 20);
            if (ch.IsClass(CharClass.Names.ranger) || ch.IsClass(CharClass.Names.hunter) || ch.IsImmortal())
                chance = 75;
            if (chance < MUDMath.NumberPercent())
            {
                ch.SendText("You don't find anything at all.\r\n");
                ch.Wait += 10;
                return;
            }
            ch.Wait += 15;
            TerrainType sector = ch.InRoom.TerrainType;
            // TODO: FIXME: Don't use hard-coded item numbers!
            switch (sector)
            {
                default:
                    ch.SendText("Nothing edible could be growing here.\r\n");
                    return;
                case TerrainType.field:
                    flist[0] = 80;
                    flist[1] = 84;
                    flist[2] = 86;
                    flist[6] = 91;
                    flist[7] = 80;
                    break;
                case TerrainType.hills:
                    flist[0] = 82748;
                    flist[1] = 86;
                    flist[2] = 92;
                    flist[6] = 94;
                    break;
                case TerrainType.underground_wild:
                    flist[0] = 3352;
                    flist[5] = 3352;
                    flist[6] = 7711;
                    flist[1] = 85;
                    flist[2] = 88;
                    flist[7] = 82;
                    flist[8] = 83;
                    break;
                case TerrainType.swamp:
                    flist[0] = 3352;
                    flist[1] = 88;
                    flist[5] = 94;
                    flist[6] = 83;
                    flist[7] = 89;
                    break;
                case TerrainType.forest:
                    flist[0] = 2057;
                    flist[1] = 81651;
                    flist[2] = 90;
                    flist[3] = 93;
                    flist[4] = 92;
                    flist[5] = 90;
                    flist[6] = 87;
                    flist[7] = 84;
                    break;
            } //end switch
            if (ch.IsClass(CharClass.Names.ranger) || ch.IsClass(CharClass.Names.hunter))
                indexNumber = flist[MUDMath.NumberRange(0, 9)];
            else
                indexNumber = flist[MUDMath.NumberRange(0, 4)];
            if (indexNumber == 0)
            {
                ch.SendText("You find nothing edible.\r\n");
                return;
            }
            string buf = String.Format("Forage: {0} found index number {1} in room {2}.", ch.Name, indexNumber, ch.InRoom.IndexNumber);
            ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, buf);
            /*
            if (fvnum == StaticObjects.OBJECT_NUMBER_SPRING) {
            //don't allow endless springs
            for ( obj = ch.in_room.contents; obj; obj = obj.next_content ) {
            if (obj.pIndexData.vnum == fvnum) {
            Descriptor._actFlags("You notice the $p&n.", ch, obj, null, Descriptor.MessageTarget.character);
            return;
            }
            }
            }
            */
            ObjTemplate objTemplate = Database.GetObjTemplate(indexNumber);
            // Foraging found an object that doesn't exist -- log an error and fail gracefully.
            if (objTemplate == null)
            {
                Log.Error("Forage: invalid object index number " + indexNumber + " in terrain type " + sector + ".");
                ch.SendText("The area appears to have been picked clean.\r\n");
                return;
            }
            obj = Database.CreateObject(objTemplate, 1);
            obj.AddToRoom(ch.InRoom);
            obj.FlyLevel = 0;
            if (indexNumber == StaticObjects.OBJECT_NUMBER_SPRING) // give spring a timer;
            {
                obj.Timer = 10 + MUDMath.NumberRange(1, 20);
            }
            SocketConnection.Act("You find $p&n.", ch, obj, null, SocketConnection.MessageTarget.character);
            SocketConnection.Act("$n&n forages around and finds $p&n.", ch, obj, null, SocketConnection.MessageTarget.room);
            return;
        }
예제 #3
0
        /// <summary>
        /// Guard someone - try to prevent them from becoming the target of attacks.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Guard(CharData ch, string[] str)
        {
            if( ch == null ) return;
            CharData worldChar;

            if (ch.IsNPC())
                return;

            if (!ch.HasSkill("guard"))
            {
                ch.SendText("Guard!? You can't even protect yourself!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                if (!((PC)ch).Guarding)
                {
                    ch.SendText("Guard who?\r\n");
                    return;
                }
                if (!((PC)ch).Guarding)
                {
                    string buf = "You are guarding " + (((PC)ch).Guarding.IsNPC() ?
                                 ((PC)ch).Guarding.ShortDescription : ((PC)ch).Guarding.Name) + ".\r\n";
                    ch.SendText(buf);
                    return;
                }
            }

            if (!MUDString.StringsNotEqual(str[0], "who"))
            {
                if (!((PC)ch).Guarding)
                {
                    ch.SendText("You are not guarding anyone.\r\n");
                }
                else
                {
                    SocketConnection.Act("You are guarding $N&n.", ch, null, ((PC)ch).Guarding, SocketConnection.MessageTarget.character);
                }
                foreach (CharData it in Database.CharList)
                {
                    worldChar = it;
                    if (worldChar.IsNPC())
                    {
                        continue;
                    }
                    if (((PC)worldChar).Guarding && ((PC)worldChar).Guarding == ch)
                    {
                        SocketConnection.Act("$N&n is guarding you.", ch, null, worldChar, SocketConnection.MessageTarget.character);
                    }
                }
                return;
            }

            CharData victim = ch.GetCharRoom(str[0]);
            if (!victim)
            {
                ch.SendText("You don't see them here.\r\n");
                return;
            }

            if (victim == ch)
            {
                ch.SendText("You no longer guard anyone.\r\n");
                ((PC)ch).Guarding = null;
                return;
            }

            if (ch.IsClass(CharClass.Names.paladin) && victim.IsEvil())
            {
                ch.SendText("Their blackened soul is hardly worth the effort.\r\n");
                return;
            }

            if (((PC)ch).Guarding)
            {
                SocketConnection.Act("$N&n stops guarding you.", ((PC)ch).Guarding, null, ch, SocketConnection.MessageTarget.character);
                SocketConnection.Act("You stop guarding $N&n.", ch, null, ((PC)ch).Guarding, SocketConnection.MessageTarget.character);
            }

            ((PC)ch).Guarding = victim;
            SocketConnection.Act("You now guard $N&n.", ch, null, victim, SocketConnection.MessageTarget.character);
            SocketConnection.Act("$n&n is now guarding you.", ch, null, victim, SocketConnection.MessageTarget.victim);
            return;
        }
예제 #4
0
        /// <summary>
        /// Train: For monks or mystics, lets them learn skills and traditions.  For everyone
        /// else it tells them they practice by using their skills.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Train(CharData ch, string[] str)
        {
            if( ch == null ) return;
            int count, teacherTradition = 0;
            string buf;
            Object icon = null;
            CharData teacher = null;
            int skillLevel;

            if (!ch.IsClass(CharClass.Names.monk) && !ch.IsClass(CharClass.Names.mystic))
            {
                // Send them to the error message.
                Practice(ch, str);
                return;
            }
            if (ch.IsNPC())
            {
                return;
            }
            //find a teacher
            foreach (CharData iteacher in ch.InRoom.People)
            {
                if (iteacher.CharacterClass == ch.CharacterClass && iteacher.HasActionBit(MobTemplate.ACT_TEACHER))
                {
                    teacher = iteacher;
                    break;
                }
            }
            // find an icon
            foreach (Object iconobj in ch.InRoom.Contents)
            {
                if (iconobj.ItemType == ObjTemplate.ObjectType.tradition_icon)
                {
                    icon = iconobj;
                    break;
                }
            }
            // if not in room, check on the teacher
            if (!icon && teacher)
            {
                foreach (Object iconobj in teacher.Carrying)
                {
                    if (iconobj.ItemType == ObjTemplate.ObjectType.tradition_icon)
                    {
                        icon = iconobj;
                        break;
                    }
                }
            }
            if (icon && teacher)
            {
                teacherTradition = icon.Values[0];
            }
            int tradition = ((PC)ch).Tradition;

            if (str.Length == 0)
            {
                if (tradition == 0 && teacherTradition == 0)
                {
                    // tell em how to train
                    ch.SendText("One trains their skills by first training a tradition.\r\n");
                    return;
                }
                string buf1;
                if (tradition != teacherTradition && teacherTradition <= TraditionData.Table.Length
                    && teacherTradition != 0)
                {
                    // they can train a new tradition here
                    if (tradition == 0)
                    {
                        buf1 = String.Format("To train the {0} tradition, type 'train tradition'.\r\n", TraditionData.Names[teacherTradition]);
                    }
                    else
                    {
                        buf1 = String.Format("It will cost you {0} points to train tradition in the {1}.\r\n", ch.Level, TraditionData.Names[teacherTradition]);
                    }
                    ch.SendText(buf1);
                    return;
                }
                //show  existing monk skills

                buf1 = "&+WTradition:&n ";
                if (tradition != 0)
                {
                    buf = String.Format("&+B{0}&n\r\n", TraditionData.Names[tradition]);
                }
                else
                {
                    buf = String.Format("none\r\n");
                }
                buf1 += buf;
                buf1 += "\r\n&+WYou can train the following:&n\r\n\r\n";
                buf1 += "      Skill                  Level                  Cost\r\n";
                for (count = 0; count < TraditionData.Table.Length; ++count)
                {
                    if (TraditionData.Table[count].Tradition != tradition)
                        continue;
                    string sn = (TraditionData.Table[count].TraditionName);
                    skillLevel = (((PC)ch).SkillAptitude[sn] + 1) / 20;
                    if (skillLevel < 5 && TraditionData.Table[count].Cost[skillLevel] >= 0)
                    {
                        buf = String.Format("    &n&+c{0}  &+Y{1}&n  &+r{2}&n\r\n",
                        MUDString.PadStr(Skill.SkillList[sn].Name, 25),
                        MUDString.PadStr(StringConversion.SkillString(((PC)ch).SkillAptitude[sn]), 25),
                        TraditionData.Table[count].Cost[skillLevel]);
                    }
                    else
                    {
                        buf = String.Format("    &n&+c{0}  &+Y{1}&n\r\n",
                        MUDString.PadStr(Skill.SkillList[sn].Name, 25),
                        StringConversion.SkillString(((PC)ch).SkillAptitude[sn]));
                    }
                    buf1 += buf;
                } // end for
                buf1 += "\r\n";
                ch.SendText(buf1);
                return;
            }
            if (!MUDString.StringsNotEqual(str[0], "tradition"))
            {
                if (str.Length < 2 || MUDString.StringsNotEqual(str[1], "confirm"))
                {
                    ch.SendText("To train monk traditions, type 'train tradition confirm'\r\n");
                    return;
                }
                if (!teacher)
                {
                    ch.SendText("You see no teacher here.\r\n");
                    return;
                }
                if (teacherTradition == 0)
                {
                    ch.SendText("This teacher needs to be in a monastery to teach.\r\n");
                    return;
                }
                if (teacherTradition >= TraditionData.Table.Length)
                {
                    ch.SendText("It seems you have found an order so secretive that even we\r\n");
                    ch.SendText("don't know what they do!\r\n");
                    return;
                }
                if (((PC)ch).Tradition > 0 && ((PC)ch).SkillPoints < ch.Level)
                {
                    ch.SendText("You do not have enough skill points to change traditions.\r\n");
                    return;
                }
                if (((PC)ch).Tradition > 0)
                {
                    ((PC)ch).SkillPoints -= ch.Level;
                }
                ((PC)ch).Tradition = teacherTradition;
                buf = "You are now an initiate of the " + TraditionData.Names[teacherTradition] + "\r\n";
                ch.SendText(buf);
                return;
            }
            // Now we process arg string again and train the skills.
            MonkSkill skill = StringLookup.MonkSkillLookup(str[0]);
            if (skill == null )
            {
                ch.SendText("You can't train that skill here.\r\n");
                return;
            }
            if (!teacher)
            {
                ch.SendText("You see no teacher here.\r\n");
                return;
            }
            for (count = 0; count < TraditionData.Table.Length; ++count)
            {
                if (skill.Name != (TraditionData.Table[count].TraditionName))
                    continue;
                if (TraditionData.Table[count].Tradition != ((PC)ch).Tradition)
                    continue;
                skillLevel = (((PC)ch).MonkAptitude[skill.Name] + 1) / 20;
                if (skillLevel >= 5)
                {
                    ch.SendText("You have already mastered that skill.\r\n");
                    return;
                }
                if (TraditionData.Table[count].Cost[skillLevel] < 0)
                {
                    ch.SendText("You cannot train that skill any higher in this tradition.\r\n");
                    return;
                }
                if (TraditionData.Table[count].Cost[skillLevel] > ((PC)ch).SkillPoints)
                {
                    ch.SendText("You lack the experience to train this skill further.\r\n");
                    return;
                }
                // Train the skill
                ((PC)ch).SkillAptitude[skill.Name] += 20;
                ((PC)ch).SkillPoints -= TraditionData.Table[count].Cost[skillLevel];
                while (TraditionData.Table[count].Cost[skillLevel + 1] == 0 && skillLevel < 4)
                {
                    // bump em up to the next level free of charge
                    ((PC)ch).SkillAptitude[skill.Name] += 20;
                    skillLevel++;
                }
                buf = String.Format("&+cYou advance in {0}.&n\r\n", skill.Name);
                ch.SendText(buf);
                return;
            }
        }
예제 #5
0
        /// <summary>
        /// Command to cast a spell.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Cast(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if ((ch.IsClass(CharClass.Names.psionicist) || ch.IsClass(CharClass.Names.enslaver)) && !ch.IsImmortal())
            {
                ch.SendText("Psionicists use the WILL command to invoke their powers.\r\n");
                return;
            }

            if (ch.IsClass(CharClass.Names.bard) && !ch.IsImmortal())
            {
                ch.SendText("Bards use the SING or PLAY commands to invoke their powers.\r\n");
                return;
            }

            if (ch.Riding && ch.InRoom == ch.Riding.InRoom)
            {
                ch.SendText("You cannot cast while mounted!\r\n");
                return;
            }

            if (ch.IsAffected( Affect.AFFECT_MINOR_PARA) ||
                    ch.IsAffected( Affect.AFFECT_HOLD))
            {
                ch.SendText("You can't cast when you're paralyzed!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("Cast what spell where?\r\n");
                return;
            }

            Magic.Cast(ch, String.Join(" ", str));
        }
예제 #6
0
        /// <summary>
        /// Shows the list of songs available to the player, if any.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Songs(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string buf = String.Empty;
            int level;

            if (ch.IsNPC() || ch.IsClass(CharClass.Names.bard))
            {
                ch.SendText("&nYou do not need any stinking songs!\r\n");
                return;
            }

            buf += "&n&+rALL songs available for your class.&n\r\n";
            buf += "&+RLv      Song&n\r\n";

            for (level = 1; level < 56; level++)
            {
                bool pSong = true;

                foreach (KeyValuePair<String, Song> kvp in Database.SongList)
                {
                    if (kvp.Value.SongCircle[(int)ch.CharacterClass.ClassNumber] != level)
                        continue;

                    if (pSong)
                    {
                        buf += "&+Y" + MUDString.PadInt(level, 2) + "&+y:&n";
                        pSong = false;
                    }
                    else
                    {
                        buf += "   ";
                    }
                    buf += "     ";
                    buf += "&n&+c" + MUDString.PadStr(kvp.Key, 21) + "  &+Y" + ((PC)ch).SongAptitude[kvp.Key] +
                        "&n (" + StringConversion.SpellSchoolString(kvp.Value.PerformanceType) + ")";
                    buf += "\r\n";
                }

            }

            ch.SendText(buf);
            return;
        }
예제 #7
0
        /// <summary>
        /// Cant language for thieves only.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Cant(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string buf;

            if (str.Length == 0)
            {
                ch.SendText("Cant what?\r\n");
                return;
            }

            if (!ch.IsClass(CharClass.Names.thief) && !ch.IsImmortal())
            {
                ch.SendText("You speak gibberish.\r\n");
                buf = String.Format("$n says, '{0}'\r\n", NounType.RandomSentence());
                SocketConnection.Act(buf, ch, null, null, SocketConnection.MessageTarget.room);
                return;
            }

            string text = String.Join(" ", str);

            // We don't want to let them know they're drunk.
            SocketConnection.Act("You cant '&n$T&n'", ch, null, text, SocketConnection.MessageTarget.character);

            text = DrunkSpeech.MakeDrunk(text, ch);
            string random = NounType.RandomSentence();

            foreach (CharData roomChar in ch.InRoom.People)
            {
                if (roomChar == ch || roomChar.IsNPC())
                    continue;

                if (roomChar.IsImmortal() || roomChar.IsClass(CharClass.Names.thief))
                {
                    buf = String.Format("{0} cants '&n$T&n'", ch.ShowNameTo(roomChar, true));
                }
                else
                {
                    buf = String.Format("{0} says, '{1}'\r\n", ch.ShowNameTo(roomChar, true), random);
                }

                SocketConnection.Act(buf, roomChar, null, SocketConnection.TranslateText(text, ch, roomChar), SocketConnection.MessageTarget.character);
            }

            return;
        }
예제 #8
0
        /// <summary>
        /// Checks whether spells can be cast in this room.
        /// </summary>
        /// <param name="ch">The caster</param>
        /// <param name="song">Is this a bard song?</param>
        /// <param name="start">true if just starting to cast, false if finishing up the spell.</param>
        /// <returns>true if the caster is able to cast spells here.</returns> 
        public bool CheckCastable( CharData ch, bool song, bool start )
        {
            if( !ch.IsClass( CharClass.Names.psionicist ) )
            {
                if( HasFlag( ROOM_SILENT ) )
                {
                    ch.SendText( "Your voice makes no sound in this room!\r\n" );
                    return false;
                }

                if( !song && HasFlag( ROOM_NO_MAGIC ) )
                {
                    // Extra message and a wait state if this happens when they start casting.
                    if( start )
                    {
                        ch.SendText( "You start casting..." );
                        ch.WaitState( 6 );
                    }
                    ch.SendText( "After a brief gathering of energy, your spell fizzles!\r\n" );
                    return false;
                }
            }
            else if( HasFlag( ROOM_NO_PSIONICS ) )
            {
                ch.SendText( "Something here prevents you from focusing your will.\r\n" );
                ch.WaitState( 2 );
                return false;
            }
            // No reason they can't cast.
            return true;
        }
예제 #9
0
 /// <summary>
 /// Checks whether a spell cast by the player is swallowed by one of the starshell types.
 /// </summary>
 /// <param name="ch">The caster</param>
 /// <returns>true if the spell was eaten.</returns>
 public bool CheckStarshell(CharData ch)
 {
     if( !ch.IsClass( CharClass.Names.bard ) )
     {
         if( ch.InRoom.HasFlag( ROOM_EARTHEN_STARSHELL ) )
         {
             ch.SendText( "You start casting...\r\n" );
             ch.SendText( "&+lThe &+yearth&n &+lcomes up &+yand engulfs &+lyour spell.\r\n" );
             Combat.InflictSpellDamage( ch, ch, 1, "earthen starshell", AttackType.DamageType.fire );
             ch.WaitState( 6 );
             return true;
         }
         if( ch.InRoom.HasFlag( ROOM_AIRY_STARSHELL ) )
         {
             ch.SendText( "You start casting...\r\n" );
             ch.SendText( "&+CAir swir&n&+cls a&+Cnd absorbs y&n&+cour spell.&n\r\n" );
             ch.WaitState( 6 );
             if( ch.CurrentPosition > Position.reclining && MUDMath.NumberPercent() + 50 > ch.GetCurrAgi() )
             {
                 ch.CurrentPosition = Position.reclining;
                 ch.WaitState( 6 );
                 ch.SendText( "You are knocked over!\r\n" );
             }
             return true;
         }
         if( ch.InRoom.HasFlag( ROOM_WATERY_STARSHELL ) )
         {
             ch.SendText( "You start casting...\r\n" );
             ch.SendText( "&+bWater b&+Bursts up a&n&+bnd absor&+Bbs your spell.&n\r\n" );
             ch.WaitState( 6 );
             ch.CurrentMoves -= 20;
             ch.SendText( "You feel tired!\r\n" );
             return true;
         }
         if( ch.InRoom.HasFlag( ROOM_FIERY_STARSHELL ) )
         {
             ch.SendText( "You start casting...\r\n" );
             ch.SendText( "&+RFire&n&+r engu&+Rlfs y&n&+rour s&+Rpell.&n\r\n" );
             Combat.InflictSpellDamage( ch, ch, 1, "fiery starshell", AttackType.DamageType.fire );
             ch.WaitState( 6 );
             return true;
         }
     }
     return false;
 }
예제 #10
0
        public static bool CheckAggressive( CharData ch, CharData victim )
        {
            if( ch == null )
            {
                Log.Error( "CheckAggressive: called with null ch.", 0 );
                return false;
            }
            if( victim == null )
            {
                Log.Error( "CheckAggressive: called with null victim.", 0 );
                return false;
            }

            if (!victim.IsAggressive(ch))
            {
                return false;
            }
            if( !ch.IsNPC() && ( (PC)ch ).AggressiveLevel >= 1 && ( (PC)ch ).AggressiveLevel < ch.Hitpoints && ch.CurrentPosition == Position.standing
                    && !ch.IsAffected( Affect.AFFECT_CASTING ) )
            {
                ch.SendText( "You charge aggressively at your foe!\r\n" );
                if (ch.IsClass(CharClass.Names.thief) || ch.IsClass(CharClass.Names.assassin)
                        || ch.IsClass(CharClass.Names.bard) || ch.IsClass(CharClass.Names.mercenary))
                {
                    Backstab(ch, victim);
                    SetFighting(victim, ch);
                }
                else
                {
                    CombatRound(ch, victim, String.Empty);
                }
                return true;
            }
            return false;
        }
예제 #11
0
        /// <summary>
        /// Do one round of attacks for one character.
        /// Note: This is a round, not a single attack!
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="skill"></param>
        /// <returns></returns>
        public static bool CombatRound(CharData ch, CharData victim, string skill)
        {
            Object wield;
            int chance = 0;

            if( ch == null )
            {
                return false;
            }

            if( victim == null )
            {
                return false;
            }

            /* No casting/being para'd and hitting at the same time. */
            if( ( ch.IsAffected( Affect.AFFECT_CASTING ) ) || ch.IsAffected( Affect.AFFECT_MINOR_PARA )
                    || ch.IsAffected(Affect.AFFECT_HOLD))
            {
                return false;
            }

            /* I don't know how a dead person can hit someone/be hit. */
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( victim, true );
                return true;
            }

            /*
            * Set the fighting fields now.
            */
            if( victim.CurrentPosition > Position.stunned )
            {
                if( !victim.Fighting )
                    SetFighting( victim, ch );
                // Can't have bashed/prone people just automatically be standing.
                if( victim.CurrentPosition == Position.standing )
                    victim.CurrentPosition = Position.fighting;
            }

            // HORRIBLE HORRIBLE! We've got index numbers hard-coded.  TODO: FIXME: BUG: Get rid of this!
            if( ch.IsNPC() && ch.MobileTemplate != null && ( ch.MobileTemplate.IndexNumber == 9316 ||
                   ch.MobileTemplate.IndexNumber == 9748 ) && MUDMath.NumberPercent() < 20 )
            {
                CheckShout( ch, victim );
            }
            ch.BreakInvisibility();

            // Everyone gets at least one swing/breath in battle.
            // This handles breathing, roaring, etc.
            if (!CheckRaceSpecial(ch, victim, skill))
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);

            // Thrikreen primary hand extra attack, only thri extra attack that is
            // given to non-warriors in addition to warriors
            if( ch.GetRace() == Race.RACE_THRIKREEN && MUDMath.NumberPercent() < ch.Level )
            {
                if( ch.IsClass(CharClass.Names.warrior) )
                {
                    switch( MUDMath.NumberRange( 1, 4 ) )
                    {
                        case 1:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                            break;
                        case 2:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two);
                            break;
                        case 3:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three);
                            break;
                        case 4:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four);
                            break;
                    }
                }
                else
                {
                    SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                    if( MUDMath.NumberPercent() < ch.Level / 2 )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                    }
                }
            }

            // Don't hurt a corpse.
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( ch, false );
                {
                    return true;
                }
            }

            // For NPCs we assume they have max skill value for their level.
            // When checking combat skills we only prDescriptor.actice them on a successful
            // check in order to make them go up slower.  If they go up too slow
            // we can always practice them before they check.

            chance = ch.GetAttackChance(2);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "second attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for Thri-Kreen arm #3
            if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    if( ch.IsNPC() )
                    {
                        if( !ch.HasSkill( "second attack" ))
                        {
                            chance = ch.Level / 5;  // Up to 10% chance of third arm for psis and
                        }
                        // other miscellaneous thris
                        else
                        {
                            chance = ((ch.Level - Skill.SkillList["second attack"].ClassAvailability[(int)ch.CharacterClass.ClassNumber]) * 2 + 25);
                        }
                    }
                    else
                    {
                        if (((PC)ch).SkillAptitude.ContainsKey("second attack"))
                        {
                            chance = ((PC)ch).SkillAptitude["second attack"];
                        }
                        else
                        {
                            chance = 0;
                        }
                    }

                    if( chance > 95 )
                        chance = 95;

                    if( MUDMath.NumberPercent() < chance )
                    {
                        ch.PracticeSkill( "second attack" );
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three);
                        if( ch.Fighting != victim )
                        {
                            return false;
                        }
                    }
                }
            }

            chance = ch.GetAttackChance(3);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "third attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            chance = ch.GetAttackChance(4);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "fourth attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for dual wield.  May want to allow a second swing when dual wielding.
            // We'll wait and see what combat looks like before we decide - Xangis
            wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two );
            if( wield )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    ch.PracticeSkill( "dual wield" );
                    if (ch.IsNPC())
                    {
                        chance = ch.Level;
                    }
                    else
                    {
                        if (((PC)ch).SkillAptitude.ContainsKey("dual wield"))
                        {
                            chance = ((PC)ch).SkillAptitude["dual wield"] * 2 / 3;
                        }
                        else
                        {
                            chance = 0;
                        }
                    }
                    chance += ch.IsClass(CharClass.Names.ranger) ? 10 : 0;
                    if( MUDMath.NumberPercent() < chance )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two);
                    }
                }
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for fourth arm on thrikreen
            if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    ch.PracticeSkill( "dual wield" );
                    chance = ch.IsNPC() ? ( ch.Level * 3 / 2 + 20 ) : ( (PC)ch ).SkillAptitude[ "dual wield" ];
                    if( chance > 95 )
                    {
                        chance = 95;
                    }
                    if( MUDMath.NumberPercent() < chance )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four);
                    }
                }
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Don't hurt a corpse.
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( ch, false );
                return true;
            }

            return false;
        }
예제 #12
0
        /// <summary>
        /// Processes a blur-type attack.  Returns true if the victim died.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool BlurAttack( CharData ch, CharData victim )
        {
            if (ch == null) return false;

            int numAttacks;
            int count;

            if( ch.IsAffected( Affect.AFFECT_CASTING ) )
            {
                return false;
            }

            if( ch.IsAffected( Affect.AFFECT_BLUR ) && MUDMath.NumberPercent() < 25 )
            {
                SocketConnection.Act( "$n&n moves with a BLUR of speed!", ch, null, null, SocketConnection.MessageTarget.room );
                SocketConnection.Act( "You move with a BLUR of speed!", ch, null, null, SocketConnection.MessageTarget.character );
                for( count = 0, numAttacks = 4; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                {
                    SingleAttack( ch, victim, String.Empty, ObjTemplate.WearLocation.hand_one );
                }
            }
            else
            {
                Object wield;

                if( MUDMath.NumberPercent() > 10 )
                    return false;
                if( ch.IsClass(CharClass.Names.hunter) || ch.IsClass(CharClass.Names.ranger ))
                    numAttacks = 2;
                else if( ch.GetRace() == Race.RACE_OGRE || ch.GetRace() == Race.RACE_CENTAUR )
                    numAttacks = 4;
                else
                    numAttacks = 9;
                if( MUDMath.NumberPercent() < ch.GetCurrLuck() )
                    numAttacks++;
                if( MUDMath.NumberPercent() < victim.GetCurrLuck() )
                    numAttacks--;

                /* 9716 is the index number for the dagger of the wind. */
                // HORRIBLE HORRIBLE TODO: FIXME: BUG: Never hard-code item index numbers.
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_one);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_two);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_three);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_four);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
            }
            return false;
        }
예제 #13
0
        /// <summary>
        /// The backstab function was cloned from Command.Backstab for use by mobile AI code.
        /// the difference is that a mob that wants to backstab already knows their
        /// victim, so no need for the argument stuff
        ///
        /// Modified by to allow auto-stab for backstabbers with aggr_level set.  Called
        /// from Commandbackstab()
        /// 
        /// Added ability to stab if piercer is secondary. Useful for mercs.
        ///
        /// Reduced damage for bards and mercs.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool Backstab(CharData ch, CharData victim)
        {
            Object obj;
            Object obj2;
            int chance = 0;
            int stabChance;

            // Can't stab if lacking the skill

            if (!ch.HasSkill("backstab"))
            {
                ch.SendText("Leave backstabbing to the assassins!\r\n");
                return false;
            }

            if (victim == null)
            {
                ch.SendText("Pick a target!\r\n");
                return false;
            }

            // Can't stab if blind
            if (ch.IsBlind())
                return false;

            // Can't stab on horseback
            if (ch.Riding)
            {
                ch.SendText("You can't get close enough while mounted.\r\n");
                return false;
            }

            // Can't stab yourself
            if (victim == ch)
                return false;

            victim = CheckGuarding(ch, victim);

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

            /* Check size of ch vs. victim. */
            if (victim.CurrentPosition > Position.sleeping)
            {
                /* If ch is more than 2 sizes smaller it's too small. */
                if ((ch.CurrentSize - 2) > victim.CurrentSize && victim.CurrentPosition >= Position.stunned
                        && !(ch.IsNPC() && ch.MobileTemplate.IndexNumber == 10165))
                {
                    ch.SendText("Such tiny beings evade your skills.\r\n");
                    return false;
                }
                /* Ch 2 or more sizes larger than victim => bad! */
                if ((ch.CurrentSize + 2) < victim.CurrentSize && victim.CurrentPosition >= Position.stunned)
                {
                    ch.SendText("It is rather ineffective to stab someone in the calf.\r\n");
                    return false;
                }
            }

            ObjTemplate.WearLocation hand = 0;
            if ((obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one)) && obj.ItemType == ObjTemplate.ObjectType.weapon
                    && (AttackType.Table[obj.Values[3]].SkillName) == "1h piercing")
                hand = ObjTemplate.WearLocation.hand_one;
            if (hand == 0 && (obj2 = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two))
                    && obj2.ItemType == ObjTemplate.ObjectType.weapon && (AttackType.Table[obj2.Values[3]].SkillName) == "1h piercing")
                hand = ObjTemplate.WearLocation.hand_two;
            if (hand == 0)
            {
                ch.SendText("You need to wield a piercing weapon.\r\n");
                return false;
            }

            if (!ch.IsNPC())
                ch.PracticeSkill("backstab");

            Crime.CheckAttemptedMurder(ch, victim);

            ch.WaitState(Skill.SkillList["backstab"].Delay);
            if (ch.IsNPC())
            {
                stabChance = 2 * ch.Level;
            }
            else
            {
                stabChance = ((PC)ch).SkillAptitude["backstab"];
            }
            if (Math.Abs(ch.CurrentSize - victim.CurrentSize) == 2)
                stabChance -= 10;
            switch (victim.CurrentPosition)
            {
                default:
                    break;
                case Position.mortally_wounded:
                case Position.incapacitated:
                case Position.unconscious:
                    stabChance += 80;
                    break;
                case Position.stunned:
                case Position.sleeping:
                    stabChance += 40;
                    break;
                case Position.reclining:
                    stabChance += 20;
                    break;
                case Position.resting:
                case Position.sitting:
                    stabChance += 10;
                    break;
            } //end switch
            // Half as likely to succeed on those that are aware
            if (victim.IsAffected(Affect.AFFECT_AWARE) || victim.IsAffected( Affect.AFFECT_SKL_AWARE))
            {
                chance /= 2;
            }
            string lbuf = String.Format("Command.Backstab: {0} is attempting with a {1}%% chance.", ch.Name, stabChance);
            ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf);
            if (MUDMath.NumberPercent() < stabChance)
            {
                /* First hit on backstab.  Check for instant kill. - Xangis */
                if (ch.HasSkill("instant kill"))
                {
                    if (!ch.IsNPC())
                        chance = ((PC)ch).SkillAptitude["instant kill"];
                    else
                        chance = (ch.Level * 3) / 2 + 20;

                    // People over level 50 get a bonus, equates to about 1-2%
                    if (ch.Level > 50)
                        chance += 25;

                    chance += (ch.Level - victim.Level);

                    // Immortals will get a bonus too
                    if (ch.IsImmortal())
                        chance *= 4;

                    // Half as likely to succeed on those that are aware
                    if (victim.IsAffected(Affect.AFFECT_AWARE) || victim.IsAffected(Affect.AFFECT_SKL_AWARE))
                    {
                        chance /= 2;
                    }

                    if (MUDMath.NumberRange(1, 20000) < chance)
                    {
                        if (!ch.IsNPC())
                            ch.PracticeSkill("instant kill");
                        {
                            lbuf = String.Format("backstab: {0} hit an instakill on {1} with a {2} chance in hundredths of a percent.",
                                      ch.Name, victim.Name, (chance / 30));
                            ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf);
                            Log.Trace(lbuf);
                            ch.WaitState(15);
                            SingleAttack(ch, victim, "instant kill", hand);
                            return true;
                        }
                    }
                }

                SingleAttack(ch, victim, "backstab", hand);
                /* No double stabs when the first stab kills'm. */
                if (victim.CurrentPosition == Position.dead)
                    return true;

                /* Case of thieves/assassins doing a double backstab. */
                obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two);
                /* Stop 2nd-hand non-pierce backstabs. */
                if (!ch.IsNPC() && (obj != null) && (hand != ObjTemplate.WearLocation.hand_two)
                        && obj.ItemType == ObjTemplate.ObjectType.weapon
                        && (AttackType.Table[obj.Values[3]].SkillName) == "1h piercing")
                {
                    /* Thieves get 1/2 chance at double, assassins get 2/3. */
                    // Xangis - removed double stab for thieves 6-9-00
                    if ((ch.IsClass(CharClass.Names.assassin)) && (MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["backstab"] * 2 / 3))
                    {
                        lbuf = String.Format("backstab: {0} hit a double backstab.", ch.Name);
                        ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf);
                        SingleAttack(ch, victim, "backstab", ObjTemplate.WearLocation.hand_two);
                    }
                }
            }
            else    /* Send a "you miss your backstab" messge & engage. */
            {
                InflictDamage(ch, victim, 0, "backstab", ObjTemplate.WearLocation.hand_one, AttackType.DamageType.pierce);
            }
            return true;
        }
예제 #14
0
        /// <summary>
        /// Hit one guy once.
        ///
        /// Hitroll is now done on a 200-sided die rather than a 20-sided die
        /// This allows for more dynamic modifiers to hitroll.
        /// i.e. a couple extra points of strength and whatnot _may_ make the
        /// difference between a hit and a miss rather than incrementing something
        /// every 10-20 points of an ability we can modify it every 1-2 points.
        /// </summary>
        /// <param name="ch">attacker</param>
        /// <param name="victim">person being attacked</param>
        /// <param name="skill">damage type being used (skill)</param>
        /// <param name="weapon">wear location of weapon (usually primary or secondary hand)</param>
        /// <returns>true if victim is killed, otherwise false</returns>
        public static bool SingleAttack(CharData ch, CharData victim, string skill, ObjTemplate.WearLocation weapon)
        {
            string text;
            int dam;
            int chance;

            /*
            * Can't beat a dead char!
            * Guard against weird room-leavings.
            */
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                text = String.Format("SingleAttack: ch {0} fighting dead victim {1}.", ch.Name, victim.Name );
                Log.Error( text, 0 );
                ch.Fighting = null;
                if( ch.CurrentPosition == Position.fighting )
                    ch.CurrentPosition = Position.standing;
                return true;
            }
            if( ch.InRoom != victim.InRoom )
            {
                text = String.Format("SingleAttack: ch {0} not with victim {1}.", ch.Name, victim.Name );
                Log.Error( text, 0 );
                ch.Fighting = null;
                if( ch.CurrentPosition == Position.fighting )
                    ch.CurrentPosition = Position.standing;
                return false;
            }

            /* No casting/being para'd and hitting at the same time. */
            if ((ch.IsAffected(Affect.AFFECT_CASTING)) || ch.IsAffected(Affect.AFFECT_MINOR_PARA)
                    || ch.IsAffected(Affect.AFFECT_HOLD))
            {
                return false;
            }

            // Inertial barrier will prevent some attacks.  At the following levels a person
            // affected by inertial barrier will be able to avoid this percentage of attacks:
            // 1 = 7%  5 = 10%  10 = 13%  20 = 20%  30 = 27%  40 = 33%  50 = 39%  51 = 40%
            if (victim.IsAffected(Affect.AFFECT_INERTIAL_BARRIER) && MUDMath.NumberPercent() > (victim.Level * 2 / 3 + 7))
                return false;

            // Keep in mind that CheckRiposte returns a boolean.
            if (skill != "kick" && skill != "backstab" && skill != "circle" && CheckRiposte( ch, victim ) )
            {
                SingleAttack( victim, ch, String.Empty, ObjTemplate.WearLocation.hand_one );
                return false;
            }
            if (CheckParry(ch, victim) && skill != "backstab" && skill != "circle")
                return false;
            if (CheckShieldBlock(ch, victim) && skill != "backstab" && skill != "circle")
                return false;
            if (CheckDodge(ch, victim) && skill != "backstab" && skill != "circle")
                return false;

            /*
            * Figure out the type of damage message if we don't have an associated attack skill.
            */
            Object wield = Object.GetEquipmentOnCharacter( ch, weapon );
            if (String.IsNullOrEmpty(skill))
            {
                skill = "barehanded fighting";
                if( wield && wield.ItemType == ObjTemplate.ObjectType.weapon )
                    skill = AttackType.Table[wield.Values[3]].SkillName;
            }

            /*
            * Weapon proficiencies.
            */
            string weaponGsn = "barehanded fighting";
            AttackType.DamageType damType = AttackType.DamageType.bludgeon;
            if( wield && wield.ItemType == ObjTemplate.ObjectType.weapon )
            {
                if( wield.Values[ 3 ] >= 0 && wield.Values[ 3 ] < AttackType.Table.Length )
                {
                    weaponGsn = (AttackType.Table[wield.Values[3]].SkillName);
                    damType = AttackType.Table[ wield.Values[ 3 ] ].DamageInflicted;
                }
                else
                {
                    text = String.Format( "SingleAttack: bad weapon damage type {0} caused by {1} ({2}).",
                              skill, wield.Name, wield.ObjIndexData ?
                              wield.ObjIndexData.IndexNumber : -1 );
                    Log.Error( text, 0 );
                    wield.Values[ 3 ] = 0;
                }
            }

            /*
            * Calculate to-hit-armor-class-0 versus armor.
            */
            int hitroll00 = ch.CharacterClass.HitrollLevel0;
            int hitroll40 = ch.CharacterClass.HitrollLevel40;

            /* Weapon-specific hitroll and damroll */

            int hitroll = MUDMath.Interpolate( ch.Level, hitroll00, hitroll40 )
                          - ( ch.GetHitroll( weapon ) * 3 );
            int victimAC = Math.Max( -100, victim.GetAC() );

            // Added blindfighting skill - Xangis
            if( !CharData.CanSee( ch, victim ) )
            {
                if( ch.CheckSkill( "blindfighting" ) )
                {
                    victimAC -= 5;
                }
                else
                {
                    victimAC -= 40;
                }
            }

            /* Weapon proficiencies *
            *
            * The twohanded version of a weapon proficiency *MUST* follow the onehanded
            * version in the definitions.  This is stupid.
            */
            if( wield && wield.ItemType == ObjTemplate.ObjectType.weapon )
            {
                if( !wield.HasFlag( ObjTemplate.ITEM_TWOHANDED ) )
                {
                    if( ch.CheckSkill( weaponGsn ))
                    {
                        victimAC += 20;
                        ch.PracticeSkill( weaponGsn );
                    }
                }
                else
                {
                    // This is not going to work.
                    if (ch.CheckSkill(weaponGsn+1))
                    {
                        victimAC += 20;
                        ch.PracticeSkill(weaponGsn);
                    }
                }
            }
            else if( ch.CheckSkill("barehanded fighting"))
            {
                victimAC += 20;
            }

            /*
            * The moment of excitement!
            */
            int diceroll = MUDMath.NumberRange( 0, 199 );

            // Give them a small bonus if they can make a successful luck check.
            if( MUDMath.NumberPercent() <= ch.GetCurrLuck() )
                diceroll += 5;

            /* Made really lucky chars get saved by the godz. */
            if( diceroll == 0 || ( diceroll <= 196 && diceroll < hitroll - victimAC )
                     || ( MUDMath.NumberPercent() < victim.GetCurrLuck() / 40 ) )
            {
                /* Miss. */
                return InflictDamage(ch, victim, 0, skill, weapon, damType);
            }

            /*
            * Hit.
            * Calc damage.
            *
            * NPCs are more badass barehanded than players.  If they weren't
            * the game would be too damned easy since mobs almost never have
            * weapons.
            *
            * Increased mob damage by about 1/6
            * It was previously level/2 to level*3/2 (25-75 at 50, average 50)
            * It is now level*3/5 to level*10/6      (30-87 at 50, average 59)
            *
            * Added the + ch.level - 1 'cause mobs still not hittin' hard enough
            */
            if( ch.IsNPC() )
            {
                dam = MUDMath.NumberRange( ( ch.Level * 3 / 5 ), ( ch.Level * 14 / 8 ) )
                      + ( ch.Level - 1 );
                if (wield)
                {
                    dam += MUDMath.Dice(wield.Values[1], wield.Values[2]);
                }
                else if (ch.CheckSkill("unarmed damage"))
                {
                    dam += MUDMath.NumberRange(1, (ch.GetSkillChance("unarmed damage") / 12));
                }
            }
            else
            {
                if (wield)
                {
                    dam = MUDMath.Dice(wield.Values[1], wield.Values[2]);
                }
                else
                {
                    if (!ch.IsClass(CharClass.Names.monk))
                    {
                        dam = MUDMath.NumberRange(1, (2 + (int)ch.CurrentSize / 3));
                        if (ch.CheckSkill("unarmed damage"))
                        {
                            dam += MUDMath.NumberRange(1, (ch.GetSkillChance("unarmed damage") / 12));
                        }
                    }
                    else
                    {
                        int min;
                        // monk barehanded damage - Xangis
                        ch.PracticeSkill("unarmed damage");
                        chance = ch.GetSkillChance("unarmed damage");
                        if (chance < 13)
                        {
                            min = 1;
                        }
                        else
                        {
                            min = chance / 13;
                        }
                        // at max skill for barehanded and unarmed, a monk will get
                        // a damage of 7-38, an average of 22.5 damage per hit before
                        // modifiers.  This is slightly better than a 6d6 weapon (average of 21 dmg)
                        // this is slightly worse than a 6d7 weapon (average of 24 dmg)
                        dam = MUDMath.NumberRange(min, ((chance / 3) + min));
                    }
                }
                if( ( wield && dam > 1000 ) && ch.Level < Limits.LEVEL_AVATAR )
                {
                    text = String.Format( "SingleAttack damage range > 1000 from {0} to {1}",
                              wield.Values[ 1 ], wield.Values[ 2 ] );
                    Log.Error( text, 0 );
                }
            }

            /*
            * Played a character with an armor class of 126 (awful agility).
            * Wasn't getting pounded much at all.  Added a damage bonus applied
            * when the target's ac is worse than 100.
            *
            * This also means that someone who makes their weapon proficiency
            * check against someone with an ac of 81 or higher will also get a
            * damage bonus of 1% per ac point.
            *
            * This applies to mobs too, so if a mob has a terrible AC it will
            * get whacked harder.  I call this the "soft as a pudding" code.
            *
            * This would also make AC debuffs stronger if they can make ac worse
            * than 100.
            */
            if( victimAC > 100 )
            {
                dam += ( (victimAC - 100) * dam) / 100;
            }

            /*
            * Bonuses.
            */
            dam += ch.GetDamroll( weapon );

            /* Weapon proficiencies, players only */
            /* Up to 50% increase based on weapon skill */
            if (wield && !ch.IsNPC())
            {
                dam += dam * ch.GetSkillChance(weaponGsn) / 180;
            }

            /* Up to 33% for offense skill */
            /* This means someone that has mastered a weapon and offense
            automatically does double damage in combat */
            chance = ch.GetSkillChance("offense");
            dam += dam * chance / 270;

            /* Bad idea to get caught napping in a fight */
            if( !victim.IsAwake() )
                dam *= 2;

            /* Backstab: 2 + one per 9 levels, 7x damage at 50 */
            if (skill == "backstab")
            {
                // Cap was previously too low.  It has been raised because a merc that was previously
                // stabbing for 180 now stabs for 64.  Assassins will still be able to stab for
                // 175 and mercs for 116 with this revised cap.  Keep in mind that a sorc can easily
                // fist for 250.
                int cap = 100 + 12 * ch.Level;
                if( ch.IsClass(CharClass.Names.mercenary) || ch.IsClass(CharClass.Names.bard ))
                    cap = cap * 2 / 3;
                dam *= ( 2 + ( ch.Level / 9 ) );
                /* damage cap applied here */
                dam = Math.Min( dam, cap );
            }
            else if (skill == "circle")              /* 150% to 200% at lev. 50 */
                dam += dam / 2 + ( dam * ch.Level ) / 100;

            if( dam <= 0 )
                dam = 1;

            return InflictDamage(ch, victim, dam, skill, weapon, damType);
        }
예제 #15
0
        /// <summary>
        /// Shows a character's score screen.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Score(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string text = String.Empty;

            if (ch == null)
            {
                Log.Error("Command.Score(): null ch.", 0);
                return;
            }

            Affect prev;

            text += "&+WName: &+G" + ch.Name + "&n" + (ch.IsNPC() ? String.Empty : ((PC)ch).Title) + "\r\n";
            text += "&+WRace:&n " + MUDString.PadStr(Race.RaceList[ch.GetRace()].ColorName, 16);
            text += "&+WClass:&n " + MUDString.PadStr(ch.CharacterClass.WholistName, 32) + "&n\r\n";
            text += "&+WLevel: " + MUDString.PadInt(ch.Level, 5) + "     Played: " + (ch.TimePlayed.Hours) + " hours       &+WSex: ";
            text += System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(ch.GetSexString()) + "\r\n";
            if (ch.Fighting == null)
            {
                text += "&+WExperience: &+B" + StringConversion.ExperienceString(ch) + "&n\r\n\r\n";
            }
            text += "&+WCurrent/Max Health: [&n&+g" + MUDString.PadInt(ch.Hitpoints, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.GetMaxHit(), 5);
            text += "&+W]     Coins:     Carried     In Bank\r\n";
            text += "&+WCurrent/Max Moves:  [&n&+g" + MUDString.PadInt(ch.CurrentMoves, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.MaxMoves, 5);
            text += "&+W]     &+WPlatinum      " + MUDString.PadInt(ch.GetPlatinum(), 5) + "        ";
            text += (ch.IsNPC() ? 0 : ((PC)ch).Bank.Platinum) + "\r\n";
            text += "Current/Max Mana:   [&n&+g" + MUDString.PadInt(ch.CurrentMana, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.MaxMana, 5);
            text += "&+W]     &+YGold          " + MUDString.PadInt(ch.GetGold(), 5) + "        " + (ch.IsNPC() ? 0 : ((PC)ch).Bank.Gold) + "\r\n";
            text += "                                        &n&+wSilver        " + MUDString.PadInt(ch.GetSilver(), 5) + "        ";
            text += (ch.IsNPC() ? 0 : ((PC)ch).Bank.Silver) + "\r\n";
            text += "&+WFrags: &+W" + MUDString.PadInt((ch.IsNPC() ? 0 : ((PC)ch).Frags), 3) + "&n                               &n&+yCopper        ";
            text += MUDString.PadInt(ch.GetCopper(), 5) + "        " + (ch.IsNPC() ? 0 : ((PC)ch).Bank.Copper) + "\r\n";
            if (!ch.IsNPC())
            {
                text += "&+WTotal Deaths: &+W" + MUDString.PadInt(((PC)ch).MobDeaths + ((PC)ch).PlayerDeaths, 5) + "&n     &+WMobs Killed: &+W";
                text += MUDString.PadInt(((PC)ch).MobKills, 5) + "&n\r\n&+WPlayers Killed: &+W" + MUDString.PadInt(((PC)ch).PlayerKills, 5);
                text += "&n   &+WPlayer Deaths: &+W" + MUDString.PadInt(((PC)ch).PlayerDeaths, 5) + "&n\r\n";
            }

            if (!ch.IsNPC())
            {
                int divisor = ((PC)ch).Created.Quantity;
                if (divisor == 0)
                    divisor = 1;
                text += String.Format("&+WItems Created: &n{0}    &+WTotal Value: &n{1}  &+WBest: &n{2}  &+WAvg: &n{3}\r\n",
                    MUDString.PadInt(((PC)ch).Created.Quantity, 5),
                    MUDString.PadInt(((PC)ch).Created.TotalCost, 5),
                    MUDString.PadInt(((PC)ch).Created.MaxCost, 5),
                    MUDString.PadInt((((PC)ch).Created.TotalCost / divisor), 5));
                divisor = ((PC)ch).Destroyed.Quantity;
                if (divisor == 0)
                    divisor = 1;
                text += String.Format("&+WItems Destroyed: &n{0}  &+WTotal Value: &n{1}  &+WBest: &n{2}  &+WAvg: &n{3}\r\n",
                    MUDString.PadInt(((PC)ch).Destroyed.Quantity, 5),
                    MUDString.PadInt(((PC)ch).Destroyed.TotalCost, 5),
                    MUDString.PadInt(((PC)ch).Destroyed.MaxCost, 5),
                    MUDString.PadInt((((PC)ch).Destroyed.TotalCost / divisor), 5));
            }

            if (!ch.IsNPC())
            {
                text += "&+WTotal Score: &+W" + ((PC)ch).Score + "&n\r\n";
            }

            if (ch.IsClass(CharClass.Names.monk) || ch.IsClass(CharClass.Names.mystic))
            {
                text += "&+WTradition: &+B" + TraditionData.Names[((PC)ch).Tradition] + "&n\r\n";
                text += "&+WTraining Points: &+B" + (ch.IsNPC() ? 0 : ((PC)ch).SkillPoints) + "&n\r\n";
            }

            if (ch.Followers != null && ch.Followers.Count > 0)
            {
                text += "&+BFollowers:&n\r\n";
                foreach (CharData follower in ch.Followers)
                {
                    if (follower == null)
                    {
                        continue;
                    }
                    text += follower.ShowNameTo(ch, true) + " &n\r\n";
                }
                text += "\r\n";
            }
            if (ch.IsAffected( Affect.AFFECT_POISON))
            {
                text += "&+GYou are poisoned.&n\r\n";
            }

            if ((ch.IsAffected( Affect.AFFECT_DETECT_MAGIC) || ch.IsImmortal())
                    && MUDString.StringsNotEqual(BitvectorFlagType.AffectString(ch.AffectedBy, true), "none"))
            {
                text += "&+BEnchantments: &+W" + BitvectorFlagType.AffectString(ch.AffectedBy, true) + "&n\r\n\r\n";
            }

            if (ch.Affected != null)
            {
                bool printed = false;
                prev = null;
                foreach (Affect affect in ch.Affected)
                {
                    if (!printed)
                    {
                        text += "&+BActive Spells:&+W\r\n";
                        printed = true;
                    }

                    /* Show only new affects to mortals. */
                    if (prev != null && prev.Value == affect.Value
                            && prev.Type == affect.Type && !ch.IsImmortal())
                    {
                        prev = affect;
                        continue;
                    }
                    prev = affect;

                    if (affect.Type == Affect.AffectType.skill && !String.IsNullOrEmpty(affect.Value) && ch.IsImmortal())
                    {
                        text += MUDString.CapitalizeANSIString( Skill.SkillList[affect.Value].Name );
                    }
                    else if (affect.Type == Affect.AffectType.skill && !String.IsNullOrEmpty(affect.Value))
                    {
                        continue;
                    }
                    else if (affect.Type == Affect.AffectType.spell && !String.IsNullOrEmpty(affect.Value))
                    {
                        text += MUDString.CapitalizeANSIString(Spell.SpellList[affect.Value].Name);
                    }
                    else if (affect.Type == Affect.AffectType.song && !String.IsNullOrEmpty(affect.Value))
                    {
                        text += MUDString.CapitalizeANSIString(affect.Value);
                    }
                    else
                    {
                        text += "Something";
                    }

                    if (ch.IsImmortal())
                    {
                        foreach (AffectApplyType apply in affect.Modifiers)
                        {
                            text += " modifies " + StringConversion.AffectApplyString(apply.Location) + " by " + apply.Amount;
                        }
                        text += " for " + affect.Duration + " hours with bits " + affect.AffectString(false) + ".\r\n";
                    }
                    else
                    {
                        if (affect.Duration == 0 && ch.IsAffected( Affect.AFFECT_DETECT_MAGIC))
                        {
                            text += " (fading rapidly)\r\n";
                        }
                        else if (affect.Duration == 1 && ch.IsAffected( Affect.AFFECT_DETECT_MAGIC))
                        {
                            text += " (fading)\r\n";
                        }
                        else
                        {
                            text += "\r\n";
                        }
                    }
                }
            }
            text += "&n";
            ch.SendText(text);
            return;
        }
예제 #16
0
        /// <summary>
        /// Code to check if someone just fragged. 
        /// Will also have to add to race, class, and guild frag tables in
        /// addition to the master frag table.  This does not update any
        /// lists yet and instead only updates the totals.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        public static void CheckForFrag( CharData ch, CharData victim )
        {
            // NPC's don't participate in fragging, can't frag yourself,
            // have to be within 10 levels, no same side frags, no frags
            // from races not participating in racewars, have to be level
            // 20 to frag, and have to be a valid class.

            // Check to see if kill qualifies for a frag.

            if( ch.IsNPC() )
                return;
            if( victim.IsNPC() )
                return;
            if( ch == victim )
                return;
            if( ch.GetRacewarSide() == Race.RacewarSide.neutral )
                return;
            if( !ch.IsRacewar( victim ) )
                return;
            if( ch.IsImmortal() )
                return;
            if( victim.IsImmortal() )
                return;
            if( victim.Level < 20 )
                return;
            if( ch.Level < 20 )
                return;
            if( ( ch.Level - 10 ) > victim.Level )
                return;
            if (ch.IsClass(CharClass.Names.none) || victim.IsClass(CharClass.Names.none))
                return;
            if( victim.GetOrigRace() > Limits.MAX_PC_RACE )
                return;

            // Give frag to ch.
            ( (PC)ch ).Frags++;

            // Protect against polymorphed character race frags.
            if( ch.GetOrigRace() < Limits.MAX_PC_RACE )
            {
                _fraglist._totalFragsByRaceAndClass[ch.GetOrigRace()][ (int)ch.CharacterClass.ClassNumber]++;
                _fraglist._totalFragsBySide[ (int)ch.GetRacewarSide() ]++;
            }

            if( ( (PC)ch ).GuildMembership != null )
                ( (PC)ch ).GuildMembership.Frags++;

            // Take frag from victim.
            ( (PC)victim ).Frags--;

            // Protect against polymorphed character race frags
            if( victim.GetOrigRace() < Limits.MAX_PC_RACE )
            {
                _fraglist._totalFragsByRaceAndClass[victim.GetOrigRace()][ (int)victim.CharacterClass.ClassNumber]--;
                _fraglist._totalFragsBySide[ (int)victim.GetRacewarSide() ]--;
            }

            if (((PC)victim).GuildMembership != null)
            {
                ((PC)victim).GuildMembership.Frags--;
            }

            ch.SendText( "&+WYou gain a frag!&n\r\n" );
            victim.SendText( "&+WYou lose a frag!&n\r\n" );

            string text = ch.Name + " has fragged " + victim.Name + " in room " + ch.InRoom.IndexNumber + ".";
            ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, text );
            Log.Trace( text );

            // Check to see if either person goes up or down on their particular lists.
            if( ( (PC)ch ).Frags > 0 )
            {
                SortFraglist( ch, _fraglist._topFrags );
                SortFraglist( ch, _fraglist._topRaceFrags[ ch.GetOrigRace() ] );
                SortFraglist(ch, _fraglist._topClassFrags[(int)ch.CharacterClass.ClassNumber]);
            }
            else if( ( (PC)ch ).Frags < 0 )
            {
                SortFraglist( ch, _fraglist._bottomFrags );
                SortFraglist( ch, _fraglist._bottomRaceFrags[ ch.GetOrigRace() ] );
                SortFraglist(ch, _fraglist._bottomClassFrags[(int)ch.CharacterClass.ClassNumber]);
            }

            if( ( (PC)victim ).Frags > 0 )
            {
                SortFraglist( victim, _fraglist._topFrags );
                SortFraglist( victim, _fraglist._topRaceFrags[ victim.GetOrigRace() ] );
                SortFraglist(victim, _fraglist._topClassFrags[(int)victim.CharacterClass.ClassNumber]);
            }
            else if( ( (PC)victim ).Frags < 0 )
            {
                SortFraglist( victim, _fraglist._bottomFrags );
                SortFraglist( victim, _fraglist._bottomRaceFrags[ victim.GetOrigRace() ] );
                SortFraglist(victim, _fraglist._bottomClassFrags[(int)victim.CharacterClass.ClassNumber]);
            }

            _fraglist.Save();

            return;
        }
예제 #17
0
        /// <summary>
        /// Sing -- using a bard song without an instrument.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Sing(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (!ch.IsClass(CharClass.Names.bard) && !ch.IsImmortal())
            {
                ch.SendText("You don't know how to sing.\r\n");
                return;
            }

            if (ch.IsAffected(Affect.AFFECT_MINOR_PARA) ||
                    ch.IsAffected(Affect.AFFECT_HOLD))
            {
                ch.SendText("You can't Sing when you're paralyzed!\r\n");
                return;
            }

            if (ch.HasActionBit(Affect.AFFECT_MUTE))
            {
                ch.SendText("You have no voice!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                if (ch.IsAffected(Affect.AFFECT_SINGING))
                {
                    ch.RemoveAffect(Affect.AFFECT_SINGING);
                    ch.SendText("You stop singing.\r\n");
                }
                else
                {
                    ch.SendText("Sing what?\r\n");
                }
                return;
            }

            Magic.Cast(ch, String.Join(" ", str));
        }
예제 #18
0
        /// <summary>
        /// Innate command.  Shows and activates innate abilitiies.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Innate(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string text;
            Affect af = new Affect();

            // Use innates here
            if (str.Length > 0 && !String.IsNullOrEmpty(str[0]))
            {
                if (!MUDString.IsPrefixOf(str[0], "strength"))
                {
                    if (ch.HasInnate(Race.RACE_STRENGTH))
                    {
                        if (ch.IsAffected(Affect.AFFECT_STRENGTH_INCREASED))
                        {
                            ch.SendText("You are already affected by strength.");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.strength))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "strength";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.AddModifier(Affect.Apply.strength, MUDMath.Dice(2, 4) + 15);
                        af.SetBitvector(Affect.AFFECT_STRENGTH_INCREASED);
                        ch.AddAffect(af);
                        ch.SendText("You feel stronger.\r\n");
                        ch.AddInnateTimer(InnateTimerData.Type.strength, 24);

                        ch.WaitState(14);

                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "levitate"))
                {
                    if (ch.HasInnate(Race.RACE_LEVITATE))
                    {
                        if (ch.IsAffected( Affect.AFFECT_LEVITATE))
                        {
                            ch.SendText("You are already levitating.");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.levitate))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "levitation";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.SetBitvector(Affect.AFFECT_LEVITATE);
                        ch.AddAffect(af);
                        ch.SendText("Your feet rise off the ground.\r\n");
                        ch.AddInnateTimer(InnateTimerData.Type.levitate, 24);

                        ch.WaitState(6);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "faerie"))
                {
                    if (ch.HasInnate(Race.RACE_FAERIE_FIRE))
                    {
                        CharData victim = ch.GetCharRoom(str[0]);

                        if (victim == null)
                            ch.SendText("You do not see them here.");
                        else
                        {
                            Spell spl = Spell.SpellList["faerie fire"];
                            if (spl != null)
                            {
                                spl.Invoke(ch, ch.Level, victim);
                            }
                        }
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "invisibility"))
                {
                    if (ch.HasInnate(Race.RACE_INVIS))
                    {
                        if (ch.IsAffected( Affect.AFFECT_INVISIBLE))
                        {
                            ch.SendText("You are already invisible!\r\n");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.invisibility))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "invisibility";
                        af.Duration = MUDMath.Dice(2, 8) + 4;
                        af.SetBitvector(Affect.AFFECT_INVISIBLE);

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

                        ch.AddAffect(af);
                        ch.AddInnateTimer(InnateTimerData.Type.invisibility, 24);

                        ch.WaitState(24);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "enlarge"))
                {
                    if (ch.HasInnate(Race.RACE_ENLARGE))
                    {
                        if (ch.IsAffected(Affect.AFFECT_ENLARGED))
                        {
                            ch.SendText("You are already enlarged.\r\n");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.enlarge))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "enlarge";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.AddModifier(Affect.Apply.size, 1);
                        af.SetBitvector(Affect.AFFECT_NONE);
                        ch.AddAffect(af);

                        ch.SendText("&nYou grow to almost twice your normal size!\r\n");
                        SocketConnection.Act("$n&n grows to almost twice $s normal size!&n", ch, null, null, SocketConnection.MessageTarget.room);
                        ch.AddInnateTimer(InnateTimerData.Type.enlarge, 24);

                        ch.WaitState(10);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "shift"))
                {
                    if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "astral"))
                    {
                        if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL))
                        {
                            if (ch.HasInnateTimer(InnateTimerData.Type.shift_astral))
                            {
                                ch.SendText("You need to rest a bit first.\r\n");
                                return;
                            }
                            Spell spell = StringLookup.SpellLookup("plane shift");
                            if (!spell)
                            {
                                ch.SendText("Something seems to be blocking your ability to shift.");
                                Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file.");
                                return;
                            }
                            spell.Invoke(ch, ch.Level, new Target(str[1]));
                            ch.AddInnateTimer(InnateTimerData.Type.shift_astral, 8);

                            ch.WaitState(10);
                        }
                        else
                        {
                            ch.SendText("You don't know how to do that.\r\n");
                            return;
                        }
                    }
                    else if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "prime"))
                    {
                        if (ch.HasInnate(Race.RACE_SHIFT_PRIME))
                        {
                            if (ch.HasInnateTimer(InnateTimerData.Type.shift_prime))
                            {
                                ch.SendText("You need to rest a bit first.\r\n");
                                return;
                            }
                            Spell spell = StringLookup.SpellLookup("plane shift");
                            if (!spell)
                            {
                                ch.SendText("Something seems to be blocking your ability to shift.");
                                Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file.");
                                return;
                            }
                            spell.Invoke(ch, ch.Level, new Target(str[1]));
                            ch.AddInnateTimer(InnateTimerData.Type.shift_prime, 8);

                            ch.WaitState(10);
                        }
                        else
                        {
                            ch.SendText("You don't know how to do that.\r\n");
                            return;
                        }
                    }
                }
                else
                {
                    ch.SendText("That's not implemented yet. :(\r\n");
                }
                return;
            }

            text = String.Format("&+BInnate abilities available to your race and class:&n\r\n");

            if (ch.HasInnate(Race.RACE_BODYSLAM))
                text += "&n  bodyslam\r\n";
            if (ch.HasInnate(Race.RACE_CHARGE))
                text += "&n  charge\r\n";
            if (ch.HasInnate(Race.RACE_FLY))
                text += "&n  fly\r\n";
            if (ch.HasInnate(Race.RACE_PASSDOOR))
                text += "&n  pass door\r\n";
            if (ch.HasInnate(Race.RACE_SWIM))
                text += "&n  swim\r\n";
            if (ch.HasInnate(Race.RACE_WATERBREATH))
                text += "&n  water breathing\r\n";
            if (ch.HasInnate(Race.RACE_INFRAVISION))
                text += "&n  infravision\r\n";
            if (ch.HasInnate(Race.RACE_ULTRAVISION))
                text += "&n  ultravision\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_ALIGN)
                    || ch.IsClass(CharClass.Names.antipaladin)
                    || ch.IsClass(CharClass.Names.paladin))
                text += "&n  detect align\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_INVIS))
                text += "&n  detect invis\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_HIDDEN))
                text += "&n  detect hidden\r\n";
            if (ch.HasInnate(Race.RACE_MUTE))
                text += "&n  mute\r\n";
            if (ch.HasInnate(Race.RACE_DOORBASH))
                text += "&n  doorbash\r\n";
            if (ch.HasInnate(Race.RACE_SHRUG))
                text += "&n  shrug\r\n";
            if (ch.HasInnate(Race.RACE_ODSNEAK))
                text += "&n  outdoor sneak\r\n";
            if (ch.HasInnate(Race.RACE_UDSNEAK))
                text += "&n  underdark sneak\r\n";
            if (ch.HasInnate(Race.RACE_STRENGTH))
                text += "&n  strength\r\n";
            if (ch.HasInnate(Race.RACE_FAERIE_FIRE))
                text += "&n  faerie fire\r\n";
            //    if( ch.HasInnate( Race.RACE_STEAL ))
            //      buf += "&n  steal\r\n" );
            if (ch.HasInnate(Race.RACE_ENLARGE))
                text += "&n  enlarge\r\n";
            if (ch.HasInnate(Race.RACE_INVIS))
                text += "&n  invisibility\r\n";
            //    if( ch.HasInnate( Race.RACE_SUMMON_HOARDE ))
            //      buf += "&n  summon hoarde\r\n" );
            if (ch.HasInnate(Race.RACE_SHIFT_PRIME))
                text += "&n  shift prime\r\n";
            if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL))
                text += "&n  shift astral\r\n";
            if (ch.HasInnate(Race.RACE_LEVITATE))
                text += "&n  levitate\r\n";
            if (ch.HasInnate(Race.RACE_BITE))
                text += "&n  bite\r\n";

            ch.SendText(text);

            return;
        }
예제 #19
0
        /// <summary>
        /// Stance: Change combat fighting stance for martial artists.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Stance(CharData ch, string[] str)
        {
            if( ch == null ) return;

            MonkSkill stance = null;
            string buf;

            if ((!ch.IsClass(CharClass.Names.monk) && !ch.IsClass(CharClass.Names.mystic)) || ch.IsNPC())
            {
                ch.SendText("You don't know how to do anything fancier than just stand there.\r\n");
                return;
            }

            if (str.Length == 0)
            {
                buf = String.Format("Available stances:  none");

                if (((PC)ch).MonkAptitude["Bear Stance"] != 0)
                    buf += ", bear";
                if (((PC)ch).MonkAptitude["Cat Stance"] != 0)
                    buf += ", cat";
                if (((PC)ch).MonkAptitude["Cobra Stance"] != 0)
                    buf += ", cobra";
                if (((PC)ch).MonkAptitude["Crane Stance"] != 0)
                    buf += ", crane";
                if (((PC)ch).MonkAptitude["Dragon Stance"] != 0)
                    buf += ", dragon";
                if (((PC)ch).MonkAptitude["Dragonfly Stance"] != 0)
                    buf += ", dragonfly";
                if (((PC)ch).MonkAptitude["Hawk Stance"] != 0)
                    buf += ", hawk";
                if (((PC)ch).MonkAptitude["Leopard Stance"] != 0)
                    buf += ", leopard";
                if (((PC)ch).MonkAptitude["Mantis Stance"] != 0)
                    buf += ", mantis";
                if (((PC)ch).MonkAptitude["Monkey Stance"] != 0)
                    buf += ", monkey";
                if (((PC)ch).MonkAptitude["Snake Stance"] != 0)
                    buf += ", snake";
                if (((PC)ch).MonkAptitude["Tiger Stance"] != 0)
                    buf += ", tiger";

                buf += "\r\n";

                ch.SendText(buf);
                return;
            }

            if ("none".StartsWith(str[0]))
            {
                ((PC)ch).Stance = String.Empty;
                SocketConnection.Act("You break out of your fighting stance and return to a relaxed position.", ch, null, null, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n leaves $s fighting stance.", ch, null, null, SocketConnection.MessageTarget.room);
                return;
            }

            if ("bear".StartsWith(str[0]))
                stance = Database.MonkSkillList["Bear Stance"];
            else if ("cat".StartsWith(str[0]))
                stance = Database.MonkSkillList["Cat Stance"];
            else if ("cobra".StartsWith(str[0]))
                stance = Database.MonkSkillList["Cobra Stance"];
            else if ("crane".StartsWith(str[0]))
                stance = Database.MonkSkillList["Crane Stance"];
            else if ("dragon".StartsWith(str[0]))
                stance = Database.MonkSkillList["Dragon Stance"];
            else if ("dragonfly".StartsWith(str[0]))
                stance = Database.MonkSkillList["Bear Stance"];
            else if ("hawk".StartsWith(str[0]))
                stance = Database.MonkSkillList["Hawk Stance"];
            else if ("leopard".StartsWith(str[0]))
                stance = Database.MonkSkillList["Leopard Stance"];
            else if ("mantis".StartsWith(str[0]))
                stance = Database.MonkSkillList["Mantis Stance"];
            else if ("monkey".StartsWith(str[0]))
                stance = Database.MonkSkillList["Monkey Stance"];
            else if ("snake".StartsWith(str[0]))
                stance = Database.MonkSkillList["Snake Stance"];
            else if ("tiger".StartsWith(str[0]))
                stance = Database.MonkSkillList["Tiger Stance"];

            if (((PC)ch).MonkAptitude[stance.Name] == 0)
            {
                buf = String.Format("You try to shift into a {0} stance and realize you have no idea what you are doing.", StringConversion.StanceString(stance.Name));
                SocketConnection.Act(buf, ch, null, null, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n contorts $s body strangely, nearly tying $mself into a knot.  With a frustrated look, $e returns to a standing position.", ch, null, null, SocketConnection.MessageTarget.room);
                ((PC)ch).Stance = String.Empty;
                return;
            }

            ((PC)ch).Stance = stance.Name;

            buf = String.Format("You shift your body into a {0} stance.", StringConversion.StanceString(stance.Name));
            SocketConnection.Act(buf, ch, null, null, SocketConnection.MessageTarget.character);
            buf = String.Format("$n&n changes $s stance, looking much like a {0}", StringConversion.StanceString(stance.Name));
            SocketConnection.Act(buf, ch, null, null, SocketConnection.MessageTarget.room);

            return;
        }
예제 #20
0
        /// <summary>
        /// Paladin "lay hands" healing command.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void LayHands(CharData ch, string[] str)
        {
            if( ch == null ) return;
            Affect af = new Affect();

            if (ch.Level <= Limits.LEVEL_AVATAR && !ch.IsClass(CharClass.Names.paladin))
            {
                ch.SendText("&nYou aren't holy enough to do that!\r\n");
                return;
            }

            if (ch.IsAffected(Affect.AFFECT_LAYHANDS_TIMER))
            {
                ch.SendText("&nIt is too soon to accomplish that!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("&nLayhands on whom?\r\n");
                return;
            }

            CharData victim = ch.GetCharRoom(str[0]);
            if (!victim)
            {
                ch.SendText("&nThey're not here.\r\n");
                return;
            }

            if (victim != ch && ch.Fighting)
            {
                ch.SendText("&nYou can only layhands on yourself while fighting.\r\n");
                return;
            }

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

            if (ch != victim)
            {
                SocketConnection.Act("You lay your hands upon $N.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n lays $s hands upon you.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n lays $s hands upon $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
            }
            else
            {
                ch.SendText("&nYou layhands upon yourself.\r\n");
                SocketConnection.Act("$n&n lays hands upon $mself&n.", ch, null, null, SocketConnection.MessageTarget.room);
            }
            victim.SendText("&+WYou feel a warm glow!&n\r\n");
            if (ch.Level >= Limits.LEVEL_AVATAR)
                return;
            af.Value = "layhands timer";
            af.Type = Affect.AffectType.skill;
            af.Duration = 24;
            af.SetBitvector(Affect.AFFECT_LAYHANDS_TIMER);
            ch.AddAffect(af);
        }
예제 #21
0
        /// <summary>
        /// Sets and gets player configuration options.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="argument"></param>
        public static void Toggle(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (ch.IsNPC())
                return;

            if (str.Length == 0)
            {
                ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n");
                ch.SendText("&+L|&n&+m  Option&+L    |&n&+r Description&n                                                &+L|&n\r\n");
                ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n");
                ch.SendText(ch.HasActionBit(PC.PLAYER_AUTOWRAP)
                               ? "&+L[&+WX&+L]&n Autowrap &+L|&n &+cThe MUD automatically wraps long lines of text.            &+L|&n\r\n"
                               : "&+L[ ]&n Autowrap &+L|&n &+cThe MUD does not automatically wrap long text.             &+L|&n\r\n"
                               );
                ch.SendText(ch.HasActionBit(PC.PLAYER_BLANK)
                               ? "&+L[&+WX&+L]&n Blank    &+L|&n &+cYou have a blank line before your prompt.                  &+L|&n\r\n"
                               : "&+L[ ]&n Blank    &+L|&n &+cYou have no blank line before your prompt.                 &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_BRIEF)
                               ? "&+L[&+WX&+L]&n Brief    &+L|&n &+cYou see brief descriptions.                                &+L|&n\r\n"
                               : "&+L[ ]&n Brief    &+L|&n &+cYou see long descriptions.                                 &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_CAST_TICK)
                               ? "&+L[&+WX&+L]&n Casttick &+L|&n &+cYou see your casting ticks.                                &+L|&n\r\n"
                               : "&+L[ ]&n Casttick &+L|&n &+cFor spam's sake, no casting ticks!                         &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_COMBINE)
                               ? "&+L[&+WX&+L]&n Combine  &+L|&n &+cYou see object lists in combined format.                   &+L|&n\r\n"
                               : "&+L[ ]&n Combine  &+L|&n &+cYou see object lists in single format.                     &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_COLOR)
                               ? "&+L[&+WX&+L]&n Color    &+L|&n &+cYou see ANSI colors.                                       &+L|&n\r\n"
                               : "&+L[ ]&n Color    &+L|&n &+cYou don't see ANSI colors.                                 &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_COLOR_CON)
                               ? "&+L[&+WX&+L]&n Colorcon &+L|&n &+cYou see ANSI colors in consider messages.                  &+L|&n\r\n"
                               : "&+L[ ]&n Colorcon &+L|&n &+cYou don't see ANSI colors in consider messages.            &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_MSP)
                               ? "&+L[&+WX&+L]&n MSP      &+L|&n &+cMUD Sound Protocol (MSP) support is on.                    &+L|&n\r\n"
                               : "&+L[ ]&n MSP      &+L|&n &+cMUD Sound Protocol (MSP) support is off.                   &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_PAGER)
                               ? "&+L[&+WX&+L]&n Pager    &+L|&n &+cText is shown in separate pages.                           &+L|&n\r\n"
                               : "&+L[ ]&n Pager    &+L|&n &+cText is shown all-at-once with no paging.                  &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_PROMPT)
                               ? "&+L[&+WX&+L]&n Prompt   &+L|&n &+cYou have a prompt.                                         &+L|&n\r\n"
                               : "&+L[ ]&n Prompt   &+L|&n &+cYou don't have a prompt.                                   &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_SHOUT)
                               ? "&+L[&+WX&+L]&n Shout    &+L|&n &+cYou can hear shouts.                                       &+L|&n\r\n"
                               : "&+L[ ]&n Shout    &+L|&n &+cYou cover your ears when someone is yelling.               &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_TELNET_GA)
                               ? "&+L[&+WX&+L]&n TelnetGA &+L|&n &+cYou receive a telnet go-ahead sequence.                    &+L|&n\r\n"
                               : "&+L[ ]&n TelnetGA &+L|&n &+cYou don't receive a telnet GA sequence.                    &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_TELL)
                               ? "&+L[&+WX&+L]&n Tell     &+L|&n &+cYou can hear tells.                                        &+L|&n\r\n"
                               : "&+L[ ]&n Tell     &+L|&n &+cYou are ignoring tells.                                    &+L|&n\r\n"
                                );
                ch.SendText(ch.HasActionBit(PC.PLAYER_VICIOUS)
                               ? "&+L[&+WX&+L]&n Vicious  &+L|&n &+cYou are vicious and will kill mortally wounded foes.       &+L|&n\r\n"
                               : "&+L[ ]&n Vicious  &+L|&n &+cYou aren't vicious and will spare a mortally wounded foe.  &+L|&n\r\n");
                ch.SendText(ch.HasActionBit(PC.PLAYER_MAP)
                               ? "&+L[&+WX&+L]&n Map      &+L|&n &+cYou see the maps.                                          &+L|&n\r\n"
                               : "&+L[ ]&n Map      &+L|&n &+cYou do not see maps.                                       &+L|&n\r\n");

                if (ch.HasActionBit(PC.PLAYER_SILENCE))
                {
                    ch.SendText( "&+L[&+WX&+L]&n Silence  &+L|&n &+cYou are silenced.                                       &+L|&n\r\n");
                }

                ch.SendText(!ch.HasActionBit(PC.PLAYER_NO_EMOTE)
                              ? "&n"
                              : "&+L[ ]&n emote    | &+cYou can't emote.                                                 &+L|&n\r\n");

                ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n");
                string termStr = "&+L|&n &+cYour terminal type is " + ch.Socket.Terminal + " and MCCP is " +
                    ch.Socket.MCCPEnabled + ".";
                while (termStr.Length < 82)
                    termStr += " ";
                termStr += "&+L|&n\r\n";
                ch.SendText(termStr);
                ch.SendText("&+L+-------------------------------------------------------------------------+&n\r\n");
            }
            else
            {
                string word;
                Bitvector bit;
                int fSet;

                if (str[0][0] == '-')
                {
                    fSet = 0;
                    word = str[0].Substring(1);
                }
                else if (str[0][0] == '+')
                {
                    fSet = 1;
                    word = str[0].Substring(1);
                }
                else
                {
                    fSet = 2;
                    word = str[0];
                }

                if (("blank".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_BLANK;
                else if (("autowrap".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_AUTOWRAP;
                else if (("brief".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_BRIEF;
                else if (("casttick".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_CAST_TICK;
                else if (("combine".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_COMBINE;
                else if (("color".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                {
                    if (ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        ch.SendText("You cannot turn color off when using the enhanced client.\r\n");
                        return;
                    }
                    bit = PC.PLAYER_COLOR;
                }
                else if (("colorcon".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_COLOR_CON;
                else if (("msp".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_MSP;
                else if (("pager".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_PAGER;
                else if (("shout".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_SHOUT;
                else if (("prompt".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_PROMPT;
                else if (("telnetga".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_TELNET_GA;
                else if (("tell".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_TELL;
                else if (("vicious".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_VICIOUS;
                else if (("map".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_MAP;
                else if (("vicious".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_VICIOUS;
                else if (("compact".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)))
                    bit = PC.PLAYER_BLANK;
                else if (word.Contains("wimpy"))
                {
                    CommandType.Interpret(ch, "wimpy " + word.Substring((word.IndexOf("wimpy") + 5)));
                    return;
                }
                else if ("mccp".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))
                {
                    ch.Socket.MCCPEnabled = !ch.Socket.MCCPEnabled;
                    if (ch.Socket.MCCPEnabled)
                    {
                        ch.SendText("MCCP is now enabled.");
                    }
                    else
                    {
                        ch.SendText("MCCP is now disabled.");
                    }
                    return;
                }
                else
                {
                    ch.SendText("&nConfig which option?\r\n");
                    return;
                }

                if (ch.IsClass(CharClass.Names.paladin) && bit == PC.PLAYER_VICIOUS)
                {
                    ch.SendText("Paladins may not toggle vicious.\r\n");
                    /* Just to make sure they don't have it toggled on. */
                    ch.RemoveActionBit(bit);
                    return;
                }

                if (fSet == 1)
                {
                    if (bit != PC.PLAYER_NONE)
                    {
                        ch.SetActionBit(bit);
                    }
                    ch.SendText( (String.Format("&n{0} is now ON.\r\n", word.ToUpper())));
                }
                else if (fSet == 0)
                {
                    if (bit != PC.PLAYER_NONE)
                    {
                        ch.RemoveActionBit(bit);
                    }
                    ch.SendText((String.Format("&n{0} is now OFF.\r\n", word.ToUpper())));
                }
                else if (fSet == 2)
                {
                    if (bit != PC.PLAYER_NONE)
                    {
                        ch.ToggleActionBit(bit);
                    }
                    if (ch.HasActionBit(bit))
                        ch.SendText((String.Format("&n{0} is now ON.\r\n", word.ToUpper())));
                    else
                        ch.SendText((String.Format("&n{0} is now OFF.\r\n", word.ToUpper())));
                }
            }

            return;
        }
예제 #22
0
        /// <summary>
        /// Looks at an object, mobile, or room.
        /// </summary>
        /// <param name="ch">The acting character.</param>
        /// <param name="str">Command arguments.</param>
        public static void LookCommand(CharData ch, string[] str)
        {
            if( ch == null ) return;

            // Build argument list, stripping articles.
            bool inside = false;
            List<String> args = new List<string>(str);
            for (int i = (args.Count - 1); i >= 0; i-- )
            {
                if (args[i].Equals("in", StringComparison.CurrentCultureIgnoreCase) || args[i].Equals("i", StringComparison.CurrentCultureIgnoreCase))
                {
                    args.RemoveAt(i);
                    inside = true;
                }
                else if (args[i].Equals("at", StringComparison.CurrentCultureIgnoreCase))
                {
                    args.RemoveAt(i);
                }
            }

            // If it's a mob that isn't switched, bail.
            if (ch.Socket == null)
                return;

            if (ch.CurrentPosition < Position.sleeping)
            {
                ch.SendText("&nYou can't see anything but &+Ystars&n!  See how pretty!\r\n");
                return;
            }

            if (ch.CurrentPosition == Position.sleeping)
            {
                ch.SendText("&nYou can't see anything, you're &+Lsleeping&n!  Zzz.\r\n");
                return;
            }

            if (ch.IsBlind())
                return;

            // Look panel for ships.
            if ( args.Count > 0 && args[0].Equals("panel", StringComparison.CurrentCultureIgnoreCase))
            {
                CommandType.Interpret(ch, "Lookpanel");
                return;
            }
            // Look out for ships.
            if (args.Count > 0 && args[0].Equals("out", StringComparison.CurrentCultureIgnoreCase))
            {
                CommandType.Interpret(ch, "Lookout");
                return;
            }

            Object obj;
            Exit exit;
            string pdesc;
            int number = 0;
            string output = String.Empty;

            // 'look' or 'look auto' or 'look room'
            if (args.Count == 0 || args[0].Equals( "auto", StringComparison.CurrentCultureIgnoreCase) ||
                args[0].Equals("room", StringComparison.CurrentCultureIgnoreCase))
            {
                if (ch.InRoom == null)
                {
                    ch.SendText("You are not in a room.  You are just floating in empty space.  This should never happen.  You should <petition> someone for help.\r\n");
                    Log.Error("Character executing Commandlook command from null room: " + ch.Name);
                    return;
                }
                if (ch.FlightLevel > 0)
                {
                    switch (ch.FlightLevel)
                    {
                        case CharData.FlyLevel.low:
                            ch.SendText("Hovering above ");
                            break;
                        case CharData.FlyLevel.medium:
                            ch.SendText("Flying above ");
                            break;
                        case CharData.FlyLevel.high:
                            ch.SendText("Flying high above ");
                            break;
                    }
                }
                if (!ch.HasActionBit(PC.PLAYER_GODMODE) && ch.InRoom.IsDark()
                        && !ch.HasInnate(Race.RACE_ULTRAVISION)
                        && !ch.IsAffected( Affect.AFFECT_ULTRAVISION))
                {
                    ch.SendText("&+lSomewhere\r\n");
                }
                else if (!ch.HasActionBit(PC.PLAYER_GODMODE))
                {
                    String roomOpen = String.Empty;
                    String roomClose = String.Empty;
                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        roomOpen = "<zone>" + ch.InRoom.Area.Name + "</zone><roomTitle>";
                        roomClose = "</roomTitle>";
                    }
                    else
                    {
                        roomClose = "&n\r\n";
                    }
                    // Added support for both manual and automatic descriptions on the worldmap.
                    if (!ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP) || ch.InRoom.Title.Length > 1)
                    {
                        output += roomOpen + ch.InRoom.Title + roomClose;
                    }
                    else
                    {
                        output += roomOpen + "No room title." + roomClose;
                    }
                }
                else
                {
                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        ch.SendText("<zone>" + ch.InRoom.Area.Name + "</zone>");
                    }
                    Look.ShowRoomInfo(ch, ch.InRoom);
                }

                if (!ch.IsNPC() && !ch.HasActionBit(PC.PLAYER_GODMODE) && ch.InRoom.IsDark()
                    && !ch.HasInnate(Race.RACE_ULTRAVISION) && !ch.IsAffected( Affect.AFFECT_ULTRAVISION))
                {
                    ch.SendText("&+LIt is pitch black...&n \r\n");
                    Look.ShowCharacterToCharacter(ch.InRoom.People, ch);
                    return;
                }

                if (!ch.IsNPC() && (args.Count > 0 && (args[0].Equals("room", StringComparison.CurrentCultureIgnoreCase) ||
                    args[0].Equals("auto", StringComparison.CurrentCultureIgnoreCase))))
                {
                    String roomDescOpen = String.Empty;
                    String roomDescClose = String.Empty;
                    String mapSpace = String.Empty;

                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        roomDescOpen = "<roomDescription>";
                        roomDescClose = "</roomDescription>";
                    }
                    else
                    {
                        roomDescClose = "&n\r\n";
                        mapSpace = "    ";
                    }
                    if( !ch.HasActionBit(PC.PLAYER_BRIEF) && !ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP))
                    {
                        // Added support for both manual and automatic descriptions on the worldmap.
                        if (ch.InRoom.Description.Length > 0)
                        {
                            output += roomDescOpen + "    " + (ch.InRoom.Description.Trim()) + roomDescClose;
                        }
                        //else if (ch._inRoom.WorldmapTerrainType < Database.SystemData.MapInfo.Length)
                        //    output += roomDescOpen + mapSpace + Database.SystemData.MapInfo[ch._inRoom.WorldmapTerrainType].RoomDescription + roomDescClose;
                        else
                        {
                            output += roomDescOpen + "    No room description." + roomDescClose;
                        }
                    }
                }
                if (!String.IsNullOrEmpty(output))
                {
                    ch.SendText(output);
                }

                if (ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP))
                {
                    if (ch.HasActionBit(PC.PLAYER_MAP))
                    {
                        Command.Worldmap(ch, null);
                    }
                    else if (!ch.IsNPC() && ch.Socket.Terminal != SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        ch.SendText("\r\n");
                    }
                }

                if (ch.InRoom.HasFlag(RoomTemplate.ROOM_SILENT))
                {
                    ch.SendText("&nIt seems preternaturally quiet.\r\n");
                }

                CommandType.Interpret(ch, "exits auto");

                Look.ShowRoomAffects(ch, ch.InRoom);

                Look.ShowListToCharacter(ch.InRoom.Contents, ch, false, false);
                Look.ShowCharacterToCharacter(ch.InRoom.People, ch);
                return;
            }

            // 'look direction'
            int door = -1;
            if (args.Count > 0)
            {
                if ("north".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 0;
                else if ("east".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 1;
                else if ("south".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 2;
                else if ("west".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 3;
                else if ("up".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 4;
                else if ("down".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 5;
                else if ("northwest".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 6;
                else if ("southwest".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 7;
                else if ("northeast".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 8;
                else if ("southeast".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 9;
                else if ("nw".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 6;
                else if ("sw".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 7;
                else if ("ne".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 8;
                else if ("se".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 9;
            }
            if (door != -1)
            {
                // If no exit data, then return.
                exit = ch.InRoom.ExitData[door];
                if (!exit)
                {
                    ch.SendText("There's nothing to see in that direction.\r\n");
                    return;
                }

                if (exit.HasFlag(Exit.ExitFlag.walled))
                {
                    ch.SendText("There's a wall in the way.\r\n");
                    return;
                }

                // Check for farsee
                if ((ch.IsAffected( Affect.AFFECT_FARSEE) || ch.HasActionBit(PC.PLAYER_GODMODE))
                        && !exit.HasFlag(Exit.ExitFlag.closed))
                {
                    if (exit.TargetRoom)
                    {
                        Room room = ch.InRoom;
                        ch.RemoveFromRoom();
                        ch.AddToRoom(Room.GetRoom(exit.IndexNumber));
                        CommandType.Interpret(ch, "look");
                        ch.RemoveFromRoom();
                        ch.AddToRoom(room);
                        return;
                    }
                    ch.SendText("Nothing special there.\r\n");
                }

                if (exit.Description.Length != 0)
                {
                    ch.SendText(exit.Description);
                }
                else
                {
                    ch.SendText("Nothing special there.\r\n");
                }

                if (exit.Keyword.Length != 0)
                {
                    if (exit.HasFlag(Exit.ExitFlag.bashed))
                        SocketConnection.Act("The $d has been bashed from its &n&+whinges&n.",
                             ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.closed))
                        SocketConnection.Act("The $d is closed.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.secret))
                        SocketConnection.Act("The $d is secret.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.blocked))
                        SocketConnection.Act("The $d is blocked.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                }
                else
                {
                    if (exit.HasFlag(Exit.ExitFlag.bashed))
                    {
                        SocketConnection.Act("The door has been bashed from its &n&+whinges&n.",
                             ch, null, null, SocketConnection.MessageTarget.character);
                    }
                    else if (exit.HasFlag(Exit.ExitFlag.closed))
                        SocketConnection.Act("The door is closed.", ch, null, null, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.is_door))
                        SocketConnection.Act("The door is open.", ch, null, null, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.secret))
                        SocketConnection.Act("The door is secret.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.blocked))
                        SocketConnection.Act("The $d is blocked.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                }
                // If exit found, don't keep looking.
                return;
            }

            // Look inside something ('look in').
            if (inside)
            {
                // 'look in'
                if (args.Count < 1)
                {
                    ch.SendText("Look in what?\r\n");
                    return;
                }

                obj = ch.GetObjHere(args[0]);
                if (!obj)
                {
                    ch.SendText("You do not see that here.\r\n");
                    return;
                }

                switch (obj.ItemType)
                {
                    default:
                        ch.SendText("That is not a container.\r\n");
                        break;

                    case ObjTemplate.ObjectType.drink_container:
                        if (obj.Values[1] == -1)
                        {
                            ch.SendText("It is full.\r\n");
                            break;
                        }

                        if (obj.Values[1] <= 0)
                        {
                            ch.SendText("It is empty.\r\n");
                            break;
                        }

                        output += "It's ";
                        if (obj.Values[1] < obj.Values[0] / 4)
                            output += "less than half";
                        else if (obj.Values[1] < (3 * obj.Values[0] / 4))
                            output += "about half";
                        else if (obj.Values[1] < obj.Values[0])
                            output += "more than half";
                        else
                            output += "completely";
                        output += " full of a " + Liquid.Table[obj.Values[2]].Color + "liquid.\r\n";

                        ch.SendText(output);
                        break;

                    case ObjTemplate.ObjectType.quiver:
                    case ObjTemplate.ObjectType.container:
                    case ObjTemplate.ObjectType.npc_corpse:
                    case ObjTemplate.ObjectType.pc_corpse:
                        if (Macros.IsSet(obj.Values[1], ObjTemplate.CONTAINER_CLOSED.Vector))
                        {
                            ch.SendText("It is closed.\r\n");
                            break;
                        }

                        SocketConnection.Act("$p&n contains:", ch, obj, null, SocketConnection.MessageTarget.character, true);
                        Look.ShowListToCharacter(obj.Contains, ch, true, true);
                        break;
                    case ObjTemplate.ObjectType.portal:
                        SocketConnection.Act("A $p&n leads to:", ch, obj, null, SocketConnection.MessageTarget.character);
                        output += Room.GetRoom(obj.Values[0]).Title + "\r\n";
                        output += Room.GetRoom(obj.Values[0]).Description;
                        output += "\r\n";
                        ch.SendText(output);
                        break;
                }
                return;
            }

            // Look at another char.
            if (args.Count > 0)
            {
                CharData victim = ch.GetCharRoom(args[0]);
                if (victim != null)
                {
                    Look.ShowCharacterToCharacterFull(victim, ch);
                    return;
                }
            }

            // Look at an object.
            if (args.Count > 0)
            {
                // Check inventory.
                obj = ch.GetObjCarrying(args[0]);
                // If not in inventory, check eq.
                if (obj == null)
                    obj = ch.GetObjWear(args[0]);
                // If not on character, check room.
                if (obj == null)
                    obj = Object.GetObjFromList(ch.InRoom.Contents, ch, args[0]);
                // If object found, show it to the char.
                if (obj != null)
                {
                    pdesc = (Database.GetExtraDescription(args[0], obj.ExtraDescription));
                    if (pdesc.Length != 0)
                    {
                        ch.SendText(pdesc);
                    }
                    else if ((pdesc = (Database.GetExtraDescription(args[0], obj.ObjIndexData.ExtraDescriptions))).Length > 0)
                    {
                        ch.SendText(pdesc);
                    }
                    else if (obj.FullDescription.Length > 0)
                    {
                        ch.SendText(obj.FullDescription);
                        ch.SendText("\r\n");
                    }
                    if (obj.HasAffect(Affect.AffectType.skill, "poison weapon"))
                    {
                        if (ch.IsClass(CharClass.Names.thief) || ch.IsClass(CharClass.Names.assassin)
                                || MUDMath.NumberPercent() < ch.GetCurrInt() / 2)
                            ch.SendText("It has a &+Gsickly &+Lcolored&n hue.\r\n");
                    }
                    return;
                }
            }

            // Look at an object in the room
            if (args.Count > 0)
            {
                int count = 0;
                foreach (Object iobj in ch.InRoom.Contents)
                {
                    if (CharData.CanSeeObj(ch, iobj))
                    {
                        pdesc = (Database.GetExtraDescription(args[0], iobj.ExtraDescription));
                        if (pdesc.Length != 0)
                        {
                            if (++count == number)
                            {
                                ch.SendText(pdesc);
                                return;
                            }
                            continue;
                        }
                        pdesc = (Database.GetExtraDescription(args[0], iobj.ObjIndexData.ExtraDescriptions));
                        if (pdesc.Length != 0)
                        {
                            if (++count == number)
                            {
                                ch.SendText(pdesc);
                                return;
                            }
                            continue;
                        }
                        if (MUDString.NameContainedIn(args[0], iobj.Name))
                        {
                            if (++count == number)
                            {
                                ch.SendText(iobj.FullDescription);
                                ch.SendText("\r\n");
                                return;
                            }
                            continue;
                        }
                    }
                }
            }

            // Check for room extra descriptions
            if (args.Count > 0)
            {
                pdesc = (Database.GetExtraDescription(args[0], ch.InRoom.ExtraDescriptions));
                if (!String.IsNullOrEmpty(pdesc))
                {
                    ch.SendText(pdesc);
                    return;
                }
            }

            ch.SendText("You do not see that here.\r\n");
            return;
        }
예제 #23
0
        /// <summary>
        /// Psionics should be instantaneous and exempt from the casting stuff, and suffer
        /// lag after their power goes off.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Will(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (!ch.IsClass(CharClass.Names.psionicist) && !ch.IsClass(CharClass.Names.enslaver) && !ch.IsImmortal())
            {
                ch.SendText("Your mind is much too puny for you to focus your will.\r\n");
                return;
            }

            if (ch.IsClass(CharClass.Names.bard) && !ch.IsImmortal())
            {
                ch.SendText("Bards use the SING or PLAY commands to invoke their powers.\r\n");
                return;
            }

            if (ch.Riding && ch.Riding.InRoom == ch.InRoom)
            {
                ch.SendText("It's too hard to concentrate! Dismount.\r\n");
                return;
            }

            // Psis should be able to will stuff when paralyzed, thus no check for para.

            if (str.Length == 0)
            {
                ch.SendText("Will which what where?\r\n");
                return;
            }

            Magic.Cast(ch, String.Join(" ", str));
        }
예제 #24
0
        /// <summary>
        /// Defines how a player's prompt is displayed.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Prompt(CharData ch, string[] str)
        {
            string buf = String.Empty;

            /* Unswitched NPC's get kicked out */
            if (ch.Socket == null)
                return;

            /* Will always have a pc ch after this */
            ch = (ch.Socket.Original != null ? ch.Socket.Original : ch.Socket.Character);

            if (str.Length == 0)
            {
                if (ch.HasActionBit(PC.PLAYER_PROMPT))
                {
                    buf = "-prompt";
                }
                else
                {
                    buf = "+prompt";
                }
                CommandType.Interpret(ch, "toggle " + buf);
                return;
            }

            if (str[0].Equals("raw", StringComparison.CurrentCultureIgnoreCase))
                buf += "&n&+g<%h&n&+g/%H&n&+ghp %mm %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%D&n %B&+g>&n ";
            else if (str[0].Equals("dark", StringComparison.CurrentCultureIgnoreCase))
                buf += "&+L<&n&+m%h&+L/&n&+m%H&+Lhp &n&+m%v&+L/&n&+m%V&+Lmv>\r\n&+L<&n%T&n %E&+L>&n ";
            else if (str[0].Equals("meter", StringComparison.CurrentCultureIgnoreCase))
                if (ch.IsClass(CharClass.Names.psionicist) || ch.IsClass(CharClass.Names.bard))
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp %mm/%MM %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%d&n %b&+g>&n ";
                else
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%d&n %b&+g>&n ";
            else if (str[0].Equals("chains", StringComparison.CurrentCultureIgnoreCase))
                buf += "&+L<&n&+m%h&+L/&n&+m%H&+Lhp &n&+m%v&+L/&n&+m%V&+Lmv>\r\n&+L<&n%t&n %e&+L>&n ";
            else if (str[0].Equals("status", StringComparison.CurrentCultureIgnoreCase))
                buf += "&n&+g<%l&+g:%h&n&+g/%H&n&+ghp %mm %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%D&n %B&+g>&n ";
            else if (str[0].Equals("all", StringComparison.CurrentCultureIgnoreCase))
                if (ch.IsClass(CharClass.Names.psionicist) || ch.IsClass(CharClass.Names.bard))
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp %m/%Mm %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%D&n %B&+g>&n ";
                else
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp %v&n&+g/%V&n&+gmv>\r\n&n&+g<&n%D&n %B&+g>&n ";
            else if (str[0].Equals("fancy", StringComparison.CurrentCultureIgnoreCase))
                if (ch.IsClass(CharClass.Names.psionicist) || ch.IsClass(CharClass.Names.bard))
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp %m/%Mm &+g%v&n&+g/%V&n&+gmv %a>\r\n&n%n&+g< &n%l&n &n%d&n %b&+g>&n ";
                else
                    buf += "&n&+g<%h&n&+g/%H&n&+ghp &+g%v&n&+g/%V&n&+gmv %a>\r\n&n%n&+g< &n%l&n &n%d&n %b&+g>&n";
            else
            {
                string text = String.Join(" ", str);
                if (text.Length > 70)
                    text = text.Substring(0, 70);
                buf = text;
            }

            ((PC)ch).Prompt = buf;
            ch.SendText("&nOk.\r\n");
            return;
        }
예제 #25
0
        /// <summary>
        /// Ingest a liquid.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Drink(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Object obj = null;

            if (ch.IsBlind())
            {
                return;
            }

            if (ch.Fighting || ch.CurrentPosition == Position.fighting)
            {
                ch.SendText("You can't drink while you're fighting!\r\n");
                return;
            }

            if (str.Length == 0 && ch.InRoom != null)
            {
                foreach (Object iobj in ch.InRoom.Contents)
                {
                    if (iobj.ItemType == ObjTemplate.ObjectType.drink_container)
                    {
                        obj = iobj;
                        break;
                    }
                }

                if (!obj)
                {
                    ch.SendText("Drink what?\r\n");
                    return;
                }
            }
            else
            {
                if (!(obj = ch.GetObjHere(str[0])))
                {
                    ch.SendText("You can't find it.\r\n");
                    return;
                }
            }

            // Allow bards to get twice as drunk as other classes - Xangis
            if (!ch.IsNPC() && !ch.IsImmortal()
                    && ((PC)ch).Drunk > 15 && ch.IsClass(CharClass.Names.bard)
                    && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk)
            {
                ch.SendText("You fail to reach your mouth.  *Hic*\r\n");
                return;
            }
            if (!ch.IsNPC() && !ch.IsImmortal()
                && ((PC)ch).Drunk > 25 && ch.IsClass(CharClass.Names.bard)
                && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk)
            {
                ch.SendText("You fail to reach your mouth.  *Hic*\r\n");
                return;

            }

            switch (obj.ItemType)
            {
                default:
                    ch.SendText("You can't drink from that.\r\n");
                    break;

                case ObjTemplate.ObjectType.drink_container:
                    // -1 Means a container never goes empty.
                    if (obj.Values[1] <= 0 && obj.Values[1] != -1)
                    {
                        ch.SendText("It is already &+Lempty&n.\r\n");
                        return;
                    }

                    /* No drinking if you're full */
                    if ((!ch.IsImmortal()) && (
                                (!ch.IsNPC() && ((PC)ch).Thirst > 40) ||
                                (!ch.IsNPC() && ((PC)ch).Hunger > 50)))
                    {
                        ch.SendText("You couldn't possibly drink any more.\r\n");
                        return;
                    }

                    int liquid;
                    if ((liquid = obj.Values[2]) >= Liquid.Table.Length)
                    {
                        Log.Error("Drink: bad liquid number {0}.", liquid);
                        liquid = obj.Values[2] = 0;
                    }

                    SocketConnection.Act("You drink $T from $p&n.",
                         ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n drinks $T from $p&n.",
                         ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.room);

                    int amount = MUDMath.NumberRange(3, 10);
                    if (obj.Values[0] != -1)
                    {
                        amount = Math.Min(amount, obj.Values[1]);
                    }

                    ch.AdjustDrunk(amount * Liquid.Table[liquid].DrunkValue);

                    if (!ch.IsUndead())
                    {
                        ch.AdjustHunger(amount * Liquid.Table[liquid].HungerValue);
                        if (ch.IsAffected(Affect.AFFECT_THIRST))
                        {
                            ch.AdjustThirst((amount * Liquid.Table[liquid].ThirstValue) / 12);
                            ch.SendText("That doesn't taste as &+bwet&n as it used to.\r\n");
                        }
                        else
                        {
                            ch.AdjustThirst(amount * Liquid.Table[liquid].ThirstValue);
                        }
                    }
                    else
                    {
                        /* If blood */
                        if (Liquid.Table[liquid].Name == "blood")
                        {
                            ch.AdjustHunger(amount * 2);
                            ch.AdjustThirst(amount);
                        }
                    }

                    if (!ch.IsNPC() && ((PC)ch).Drunk > 10)
                    {
                        ch.SendText("You feel &n&+gdrunk&n.\r\n");
                    }
                    if (!ch.IsNPC() && ((PC)ch).Hunger > 20)
                    {
                        ch.SendText("You are &n&+yfull&n.\r\n");
                    }
                    if (!ch.IsNPC() && ((PC)ch).Thirst > 20)
                    {
                        ch.SendText("You do not feel &n&+cth&+Ci&n&+cr&+Cst&n&+cy&n.\r\n");
                    }

                    if (obj.Values[3] != 0 && !CharData.CheckImmune(ch, Race.DamageType.poison))
                    {
                        /* The shit was poisoned ! */
                        Affect af = new Affect();

                        ch.SendText("You choke and gag.\r\n");
                        SocketConnection.Act("$n chokes and gags.", ch, null, null, SocketConnection.MessageTarget.room);
                        af.Type = Affect.AffectType.spell;
                        af.Value = "poison";
                        af.Duration = 3 * amount;
                        af.AddModifier(Affect.Apply.strength, -(obj.Level / 7 + 1));
                        af.SetBitvector(Affect.AFFECT_POISON);
                        ch.CombineAffect(af);
                    }

                    /* HOLY_WATER and UNHOLY_WATER effects */
                    if ((ch.IsGood() && obj.Values[2] == 27) ||
                            (ch.IsEvil() && obj.Values[2] == 28))
                    {
                        int heal = MUDMath.Dice(1, 8);
                        if (ch.Hitpoints < ch.GetMaxHit())
                        {
                            ch.Hitpoints = Math.Min(ch.Hitpoints + heal, ch.GetMaxHit());
                            ch.UpdatePosition();
                            ch.SendText("You feel a little better!\r\n");
                        }
                    }
                    if ((ch.IsEvil() && obj.Values[2] == 27) ||
                            (ch.IsGood() && obj.Values[2] == 28))
                    {
                        int harm = MUDMath.Dice(1, 10);
                        ch.Hitpoints = Math.Max(ch.Hitpoints - harm, -10);
                        ch.SendText("You choke and feel as if you'd swallowed boiling oil!\r\n");
                        ch.UpdatePosition();
                    }
                    /* End (UN)HOLY_WATER effects */

                    // -1 Means a container never goes empty.
                    if (obj.Values[1] != -1)
                    {
                        obj.Values[1] -= amount;
                        if (obj.Values[1] <= 0)
                        {
                            ch.SendText("The container is now &+Lempty&n.\r\n");
                            obj.Values[1] = 0;
                        }
                    }
                    break;
            }

            return;
        }
예제 #26
0
        /// <summary>
        /// Bodyslam an opponent.  Can only be used to initiate combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Bodyslam(CharData ch, string[] str)
        {
            if( ch == null ) return;

            CharData victim;

            /* Check player's level and class, mobs can use this skill */
            if (!ch.HasInnate(Race.RACE_BODYSLAM))
            {
                ch.SendText("You don't feel massive enough to manhandle that.\r\n");
                return;
            }

            if (ch.IsBlind())
            {
                return;
            }
            if (ch.Riding)
            {
                ch.SendText("You can't do that while mounted.\r\n");
                return;
            }

            if (str.Length != 0)
            {
                if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("They aren't here.\r\n");
                    return;
                }
            }
            else
            {
                ch.SendText("Bodyslam who?\r\n");
                return;
            }

            // Added size restrictions -- Xangis
            if (victim.CurrentSize > ch.CurrentSize)
            {
                if (ch.HasInnate(Race.RACE_SLAM_LARGER))
                {
                    // allowing centaurs to slam one size up if it's an ogre
                    if (victim.CurrentSize > (ch.CurrentSize + 1))
                    {
                        ch.SendText("You can't bodyslam something that much bigger than you.\r\n");
                        return;
                    }
                }
                else
                {
                    ch.SendText("You can't bodyslam something bigger than you.\r\n");
                    return;
                }
            }

            if ((ch.CurrentSize > victim.CurrentSize) && ((ch.CurrentSize - victim.CurrentSize) > 3))
            {
                ch.SendText("They're too small to slam.\r\n");
                return;
            }

            /* Bodyslam self?  Ok! */
            if (ch == victim)
            {
                ch.SendText("You slam yourself to the ground!\r\n");
                SocketConnection.Act("$n&n throws $mself to the ground in a fit of clumsiness.",
                     ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.WaitState((Skill.SkillList["bodyslam"].Delay / 2));
                ch.CurrentPosition = Position.reclining;
                Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 6), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                return;
            }

            ch.WaitState(Skill.SkillList["bodyslam"].Delay);
            ch.PracticeSkill("bodyslam");

            int chance = (ch.Level * 3) / 2 + 15;
            chance += ch.GetCurrAgi() - victim.GetCurrAgi();
            chance -= (victim.Level - ch.Level);

            switch (victim.CurrentPosition)
            {
                case Position.dead:
                    return;
                case Position.mortally_wounded:
                    chance += 15;
                    break;
                case Position.incapacitated:
                    chance += 10;
                    break;
                case Position.unconscious:
                    chance += 5;
                    break;
                case Position.stunned:
                    chance += 3;
                    break;
                case Position.sleeping:
                    chance += 2;
                    break;
                case Position.reclining:
                    chance -= 45;
                    break;
                case Position.resting:
                    chance -= 30;
                    break;
                case Position.sitting:
                    chance -= 20;
                    break;
                case Position.kneeling:
                    chance -= 15;
                    break;
                case Position.fighting:
                case Position.standing:
                default:
                    break;
            }

            // Small penalty for the small buggers -- Xangis
            if (victim.CurrentSize < (ch.CurrentSize - 1))
            {
                chance -= 15;
            }

            if (chance > 90)
            {
                chance = 90;
            }

            // Shaman bodyslam penalty.
            if (ch.IsClass(CharClass.Names.shaman) || ch.IsClass(CharClass.Names.druid))
            {
                chance = (chance * 2) / 3;
            }

            if (victim.IsAffected(Affect.AFFECT_AWARE))
            {
                chance -= 15;
            }
            else if (victim.IsAffected( Affect.AFFECT_SKL_AWARE))
            {
                if (ch.HasSkill("springleap"))
                {
                    if (ch.IsNPC())
                    {
                        if (MUDMath.NumberPercent() < ((ch.Level * 3) / 2 + 15))
                        {
                            chance -= 15;
                        }
                    }
                    else if (MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["awareness"])
                    {
                        ch.PracticeSkill("awareness");
                        chance -= 15;
                    }
                    else
                    {
                        ch.PracticeSkill("awareness");
                    }
                }
            }

            if (!ch.Fighting)
            {
                Combat.SetFighting(ch, victim);
            }
            if (victim.Fighting == null)
            {
                Combat.SetFighting(victim, ch);
            }

            if (ch.IsNPC() || MUDMath.NumberPercent() < chance)
            {
                if (victim.IsAffected( Affect.AFFECT_SINGING))
                {
                    victim.RemoveAffect(Affect.AFFECT_SINGING);
                    SocketConnection.Act("$n&n suddenly loses track of the key $e was singing in.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("You get the wind knocked out of you!\r\n");
                }
                if (victim.IsAffected( Affect.AFFECT_CASTING))
                {
                    victim.RemoveAffect(Affect.AFFECT_CASTING);
                    SocketConnection.Act("$n&n's thoughts of casting are scattered about as $e is slammed into the ground.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("Your brain slamming against your skull disrupts your concentration.\r\n");
                }
                // Moved damage to bottom because it would crash when a person died, because
                // it still tried to access them as a valid character.  Also added tumble check for
                // thieves.
                if (!Combat.CheckTumble(victim))
                {
                    victim.WaitState(Skill.SkillList["bodyslam"].Delay);
                    victim.CurrentPosition = Position.reclining;
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
                else
                {
                    if (!Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon))
                    {
                        ch.SendText("You roll with the blow, finally landing on your feet.\r\n");
                        SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", ch, null, null, SocketConnection.MessageTarget.room);
                    }
                }
            }
            else
            {
                ch.Hitpoints -= MUDMath.NumberRange(1, 5);
                SocketConnection.Act("As $N&n avoids your slam, you smack headfirst into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n throws $mself to the &n&+yground&n in a fit of clumsiness.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n misses a bodyslam on $N&n and slams $s head into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.CurrentPosition = Position.reclining;
            }

            return;
        }
예제 #27
0
        /// <summary>
        /// Bandage someone's wounds.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Bandage(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (ch.IsNPC() || !ch.HasSkill("bandage"))
            {
                ch.SendText("You don't know how to bandage!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("Bandage whom?\r\n");
                return;
            }

            CharData victim = ch.GetCharRoom(str[0]);
            if (victim == null)
            {
                ch.SendText("They're not here.\r\n");
                return;
            }

            if (victim.Hitpoints > 0)
            {
                ch.SendText("They do not need your help.\r\n");
                return;
            }

            int chance = ((PC)ch).SkillAptitude["bandage"];

            if (ch.IsClass(CharClass.Names.cleric))
                chance += 4;
            else if (ch.IsClass(CharClass.Names.antipaladin))
                chance -= 4;

            /* Don't allow someone doing more than 1 pt. of damage with bandage. */
            int change = (Math.Max(chance - MUDMath.NumberPercent(), -1) / 20) + 1;

            // Bandage is rarely used, make it likely to increase
            ch.PracticeSkill("bandage");
            ch.PracticeSkill("bandage");
            ch.PracticeSkill("bandage");

            ch.WaitState(Skill.SkillList["bandage"].Delay);

            if (change < 0)
            {
                ch.SendText("You just made the problem worse!\r\n");
                SocketConnection.Act("$n&n tries bandage you but your condition only worsens.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n tries bandage $N&n but $S condition only worsens.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
            }
            else if (change > 0)
            {
                ch.SendText("You manage to fix them up a _bitvector.\r\n");
                SocketConnection.Act("$n&n bandages you.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n bandages $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
            }
            else
            {
                ch.SendText("Your bandaging attempt had no effect.\r\n");
                SocketConnection.Act("$n&n tries to bandage you but the wounds are too great.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n tries to bandage $N&n but is unable to have any effect.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
            }

            victim.Hitpoints += change;

            victim.UpdatePosition();

            return;
        }
예제 #28
0
        /// <summary>
        /// Command to set your level of aggressiveness.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Aggressive(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string arg1 = String.Empty;

            if (ch.IsNPC())
                return;
            if (ch.IsClass(CharClass.Names.paladin))
            {
                ch.SendText("Your beliefs prevent you from acting in such a manner.\r\n");
                return;
            }

            if (arg1.Length > 0)
            {
                if (MUDString.NameContainedIn("off", arg1) || MUDString.NameContainedIn("none", arg1))
                {
                    ((PC)ch).AggressiveLevel = -1;
                }
                else
                {
                    int aggr;
                    Int32.TryParse(arg1, out aggr);
                    if (aggr < -1 || aggr > ch.GetMaxHit())
                    {
                        ch.SendText("Value out of range.\r\n");
                        return;
                    }
                    ((PC)ch).AggressiveLevel = aggr;
                }
            }
            string buf;
            if (((PC)ch).AggressiveLevel == -1)
            {
                buf = "You are not aggressive.\r\n";
            }
            else
            {
                buf = "You are aggressive to creatures if hit points above " + ((PC)ch).AggressiveLevel + ".\r\n";
            }
            ch.SendText(buf);
            return;
        }
예제 #29
0
        /// <summary>
        /// Bash. Usable to initiate combat and during combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Bash(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int chance;

            /* Check player's level and class, mobs can use this skill */
            if ((!ch.HasSkill("bash")))
            {
                ch.SendText("You'd better leave that to those with more skills.\r\n");
                return;
            }

            if (ch.IsBlind() && !ch.Fighting)
            {
                return;
            }

            /* Verify a target. */
            CharData victim = ch.Fighting;
            if (str.Length != 0)
            {
                victim = ch.GetCharRoom(str[0]);
                if (!victim || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("They aren't anywhere to be found.\r\n");
                    return;
                }
            }
            else
            {
                if (!victim || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("You aren't fighting anyone.\r\n");
                    return;
                }
            }

            /* Bash self? Ok! */
            // Toned down the damage cuz you can't really bash yourself
            // like you could with someone else.
            if (victim == ch)
            {
                ch.SendText("You throw yourself to the ground!\r\n");
                SocketConnection.Act("$N&n knocks $mself to the ground.", ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.CurrentPosition = Position.kneeling;
                ch.WaitState((Skill.SkillList["bash"].Delay * 8) / 10);
                Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 3), "bash", ObjTemplate.WearLocation.none,
                        AttackType.DamageType.bludgeon);
                return;
            }

            /* Check size of ch vs. victim. */
            /* If ch is too small. */
            if (ch.CurrentSize < victim.CurrentSize)
            {
                SocketConnection.Act("$N&n is too big for you to bash!", ch, null, victim, SocketConnection.MessageTarget.character);
                return;
            }
            /* Ch 2 or more sizes larger than victim => bad! */
            if (ch.CurrentSize - 2 > victim.CurrentSize)
            {
                SocketConnection.Act("You nearly topple over as you try to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n nearly topples over as $e attempts to bash you.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n nearly topples over as $e attempts to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.WaitState((Skill.SkillList["bash"].Delay));
                ch.CurrentPosition = Position.kneeling;
                if (victim.Fighting == null)
                {
                    Combat.SetFighting(victim, ch);
                }
                return;
            }

            /* Lag to basher from bash. Pets get more lag because pets are cheesy */
            if (!ch.IsNPC())
            {
                ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["bash"].Delay));
            }
            else
            {
                ch.WaitState((Skill.SkillList["bash"].Delay * 6 / 5));
            }

            /* Base chance to bash, followed by chance modifications. */
            if (ch.IsNPC())
            {
                chance = (ch.Level * 3) / 2 + 15;
            }
            else
            {
                chance = ((PC)ch).SkillAptitude["bash"] - 5;
            }

            if (victim.CurrentPosition < Position.fighting)
            {
                chance /= 5; //used to be 0
            }
            else
            {
                chance += ch.GetCurrAgi() - victim.GetCurrAgi();
            }

            if (chance > 95)
            {
                chance = 95;
            }

            Object obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one);
            if (!obj)
            {            /* No primary item. */
                if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two)))
                {          /* No items in hand. */
                    if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin))
                    {
                        if (!ch.IsClass(CharClass.Names.warrior))
                        {
                            chance -= 25;
                        }
                        else
                        {
                            chance -= 20;
                        }
                        ch.SendText("You lower your shoulder and attempt to bash without a shield...\r\n");
                    }
                    else
                    {
                        chance -= 3; // Hidden penalty for not having a shield
                    }
                }
                else if (obj.ItemType != ObjTemplate.ObjectType.shield)
                {          /* Secondary item isn't a shield, no primary. */
                    if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin))
                    {
                        if (!ch.IsClass(CharClass.Names.warrior))
                        {
                            chance -= 25;
                        }
                        else
                        {
                            chance -= 20;
                        }
                        ch.SendText("Bashing without a shield is tough, but you try anyway...\r\n");
                    }
                    else
                    {
                        chance -= 5; // Small hidden penalty for not having a shield
                    }
                }          /* Secondary item is a shield, no primary. */
                else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))
                {
                    chance += 3; // Small hidden bonus for having a shield
                }
            }
            else if (obj.ItemType != ObjTemplate.ObjectType.shield)
            {            /* Primary item isn't a shield. */
                if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two)))
                {          /* No secondary. */
                    if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin))
                    {
                        if (!ch.IsClass(CharClass.Names.warrior))
                        {
                            chance -= 25;
                        }
                        else
                        {
                            chance -= 20;
                        }
                        ch.SendText("Without a shield, bashing is a wistful thought, but you try anyway...\r\n");
                    }
                    else
                    {
                        chance -= 5; // Hidden penalty for not having a shield
                    }
                }
                else if (obj.ItemType != ObjTemplate.ObjectType.shield)
                {          /* Secondary item is not a shield. */
                    if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin))
                    {
                        if (!ch.IsClass(CharClass.Names.warrior))
                        {
                            chance -= 25;
                        }
                        else
                        {
                            chance -= 20;
                        }
                        ch.SendText("Without a shield, your shoulder bash is but wishful thinking...\r\n");
                    }
                    else
                    {
                        chance -= 5; // Hidden penalty for not having a shield
                    }
                }
                else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))
                {          /* Secondary is a shield. */
                    chance += 3; // Small hidden bonus for having a shield
                }
                else if (ch.IsClass(CharClass.Names.ranger))
                {
                    chance -= 8;
                }
                else if (ch.IsClass(CharClass.Names.warrior))
                {
                    chance -= 5;
                }
            }

            // Centaurs are awful damned hard to bash -- Xangis
            if (victim.GetRace() == Race.RACE_CENTAUR)
            {
                chance -= 25;
            }

            // damned high penalty for bashing blind
            if (ch.IsAffected(Affect.AFFECT_BLIND) && !victim.IsAffected(Affect.AFFECT_BLIND))
            {
                chance /= 10;
            }
            if (ch.IsAffected(Affect.AFFECT_BLIND) && victim.IsAffected(Affect.AFFECT_BLIND))
            {
                chance /= 4;
            }

            ch.PracticeSkill("bash");

            /* Start a fight if not already in one. */
            if (ch != victim)
            {
                if (!ch.Fighting)
                {
                    Combat.SetFighting(ch, victim);
                }
                if (!victim.Fighting)
                {
                    Combat.SetFighting(victim, ch);
                }
            }

            string lbuf = "Bash: " + ch.Name + " bashing " + victim.Name + " with " + chance + " chance.";
            ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf);

            /* Do the bash, deal the damage. */
            if (MUDMath.NumberPercent() < chance)
            {
                /* Hit the bash. */
                if (victim.IsAffected(Affect.AFFECT_SINGING))
                {
                    victim.RemoveAffect(Affect.AFFECT_SINGING);
                    SocketConnection.Act("$n&n chokes on a note and falls silent as $e slams into the ground!", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("You abort your singing!\r\n");
                }
                if (victim.IsAffected(Affect.AFFECT_CASTING))
                {
                    victim.RemoveAffect(Affect.AFFECT_CASTING);
                    SocketConnection.Act("$n&n's eyes roll back in $s head and $e forgets all about $s spell.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("Being knocked over so forcefully makes it hard to cast.\r\n");
                }
                if (!Combat.CheckTumble(victim))
                {
                    victim.WaitState(((Skill.SkillList["bash"].Delay * 5) / 6));
                    if (victim.CurrentPosition > Position.kneeling)
                    {
                        victim.CurrentPosition = Position.kneeling;
                    }
                    victim.SendText("You are knocked to the ground!\r\n");
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
                else
                {
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                    victim.SendText("You roll with the blow, finally landing on your feet.\r\n");
                    SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", victim, null, null, SocketConnection.MessageTarget.room);
                }
            }
            else
            { /* Miss the bash. */
                SocketConnection.Act("As $N&n avoids your bash, you topple to the &n&+yground&n with a loud crash.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n crashes to the &n&+yground&n as you sidestep $s bash.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n misses $s bash at $N&n and is driven to the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.CurrentPosition = Position.kneeling;
            }

            return;
        }
예제 #30
0
        /// <summary>
        /// Per-tick mana recovery.
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static int ManaGain( CharData ch )
        {
            int gain;
            int percent = 0;

            if( ch == null )
            {
                Log.Error( "ManaGain(): null ch", 0 );
                return 0;
            }

            if( ch.IsNPC() )
            {
                gain = 4 + ch.Level / 10;
            }
            else
            {
                /* at 17 gain == base 5, at 34 gain == base 6, at 51 gain == base 7 */
                gain = 4 + ch.Level / 17;
                percent = 100;

                switch( ch.CurrentPosition )
                {
                    case Position.sleeping:
                        percent += 100;
                        break;
                    case Position.resting:
                        percent += 50;
                        if (ch.HasActionBit(PC.PLAYER_MEDITATING))
                        {
                            percent += 50;
                            int number = MUDMath.NumberPercent();
                            if( number < ( (PC)ch ).SkillAptitude[ "meditate" ] )
                                percent += 150;
                            ch.PracticeSkill( "meditate" );
                        }
                        break;
                }

                if( ( (PC)ch ).Hunger == 0 )
                {
                    percent -= 50;
                }
                if( ( (PC)ch ).Thirst == 0 )
                {
                    percent -= 50;
                }

            }

            if( percent < 0 )
                percent = 0;

            gain = ( gain * percent ) / 100;
            if (!ch.IsClass(CharClass.Names.bard))
                gain = ( gain * ch.GetCurrPow() ) / 100;
            else
                gain = ( gain * ch.GetCurrCha() ) / 100;

            return Math.Min( gain, ch.MaxMana - ch.CurrentMana );
        }