예제 #1
0
        public static ReturnTypes SpringTheTrap(this CharacterInstance ch, ObjectInstance obj)
        {
            var level    = obj.Value.ToList()[2];
            var txt      = string.Empty;
            var trapType = TrapTypes.None;
            DescriptorAttribute attrib = null;

            try
            {
                trapType = EnumerationExtensions.GetEnum <TrapTypes>(obj.Value.ToList()[1]);
                attrib   = trapType.GetAttribute <DescriptorAttribute>();
                txt      = attrib.Messages.FirstOrDefault();
            }
            catch (ArgumentException)
            {
                txt = TrapTypeLookupDefault;
            }

            var dam = SmaugRandom.Between(obj.Value.ToList()[2], obj.Value.ToList()[2] * 2);

            comm.act(ATTypes.AT_HITME, $"You are {txt}!", ch, null, null, ToTypes.Character);
            comm.act(ATTypes.AT_ACTION, $"$n is {txt}.", ch, null, null, ToTypes.Room);

            --obj.Value.ToList()[0];
            if (obj.Value.ToList()[0] <= 0)
            {
                obj.Extract();
            }

            var returnCode = ReturnTypes.None;

            if (!string.IsNullOrEmpty(attrib?.Messages.ToList()[1]))
            {
                var skill = RepositoryManager.Instance.GetEntity <SkillData>(attrib.Messages.ToList()[1]);
                returnCode = ch.ObjectCastSpell((int)skill.ID, level, ch);
            }

            if (trapType == TrapTypes.Blade || trapType == TrapTypes.ElectricShock)
            {
                returnCode = ch.CauseDamageTo(ch, dam, Program.TYPE_UNDEFINED);
            }
            if ((trapType == TrapTypes.PoisonArrow ||
                 trapType == TrapTypes.PoisonDagger ||
                 trapType == TrapTypes.PoisonDart ||
                 trapType == TrapTypes.PoisonNeedle) &&
                returnCode == ReturnTypes.None)
            {
                returnCode = ch.CauseDamageTo(ch, dam, Program.TYPE_UNDEFINED);
            }

            return(returnCode);
        }
예제 #2
0
        private static ReturnTypes ConditionBloodthirsty(CharacterInstance ch, int conditionValue)
        {
            ReturnTypes retcode = ReturnTypes.None;

            if (ch.Level < LevelConstants.AvatarLevel)
            {
                color.set_char_color(ATTypes.AT_BLOOD, ch);
                DescriptorAttribute attrib = ConditionTypes.Bloodthirsty.GetAttribute <DescriptorAttribute>();

                color.send_to_char(attrib.Messages[conditionValue * 2], ch);
                if (conditionValue < 2)
                {
                    comm.act(ATTypes.AT_HUNGRY, attrib.Messages[(conditionValue * 2) + 1], ch, null, null, ToTypes.Room);
                    if (conditionValue == 0)
                    {
                        ch.WorsenMentalState(2);
                        retcode = ch.CauseDamageTo(ch, ch.MaximumHealth / 20, (int)SkillNumberTypes.Undefined);
                    }
                    else
                    {
                        ch.WorsenMentalState(1);
                    }
                }
            }

            return(retcode);
        }
예제 #3
0
        public static ReturnTypes spell_attack(int sn, int level, CharacterInstance ch, object vo)
        {
            var skill = RepositoryManager.Instance.SKILLS.Get(sn);
            var vch   = (CharacterInstance)vo;

            var saved = skill.CheckSave(level, ch, vch);

            if (CheckFunctions.CheckIfTrueCasting(
                    saved && Macros.SPELL_SAVE(skill) == (int)SpellSaveEffectTypes.Negate, skill, ch,
                    CastingFunctionType.Failed, vch))
            {
                return(ReturnTypes.SpellFailed);
            }

            var damage = GetBaseDamage(level, ch, skill);

            if (saved)
            {
                var spellSaveType =
                    EnumerationExtensions.GetEnum <SpellSaveEffectTypes>(Macros.SPELL_SAVE(skill));
                switch (spellSaveType)
                {
                case SpellSaveEffectTypes.ThreeQuartersDamage:
                    damage = GetThreeQuartersDamage(damage);
                    break;

                case SpellSaveEffectTypes.HalfDamage:
                    damage = GetHalfDamage(damage);
                    break;

                case SpellSaveEffectTypes.QuarterDamage:
                    damage = GetQuarterDamage(damage);
                    break;

                case SpellSaveEffectTypes.EighthDamage:
                    damage = GetEighthDamage(damage);
                    break;

                case SpellSaveEffectTypes.Absorb:
                    AbsorbDamage(ch, skill, vch, damage);
                    return(ReturnTypes.None);

                case SpellSaveEffectTypes.Reflect:
                    return(spell_attack(sn, level, vch, ch));
                }
            }

            var retcode = ch.CauseDamageTo(vch, damage, sn);

            if (retcode == ReturnTypes.None &&
                !ch.CharDied() && !vch.CharDied()
                &&
                (!vch.IsAffectedBy(sn) || skill.Flags.IsSet(SkillFlags.Accumulative) ||
                 skill.Flags.IsSet(SkillFlags.ReCastable)))
            {
                retcode = AffectCharacter.spell_affectchar(sn, level, ch, vch);
            }

            return(retcode);
        }
예제 #4
0
        private static ReturnTypes ConditionThirsty(CharacterInstance ch, int conditionValue)
        {
            ReturnTypes retcode = ReturnTypes.None;

            if (ch.Level < LevelConstants.AvatarLevel && ch.CurrentClass != ClassTypes.Vampire)
            {
                color.set_char_color(ATTypes.AT_THIRSTY, ch);
                DescriptorAttribute attrib = ConditionTypes.Thirsty.GetAttribute <DescriptorAttribute>();

                color.send_to_char(attrib.Messages[conditionValue * 2], ch);
                if (conditionValue < 2)
                {
                    comm.act(ATTypes.AT_THIRSTY, attrib.Messages[(conditionValue * 2) + 1], ch, null, null, ToTypes.Room);
                    if (conditionValue == 0)
                    {
                        ch.WorsenMentalState(ch.IsPKill() ? 1 : 2);
                        retcode = ch.CauseDamageTo(ch, 2, (int)SkillNumberTypes.Undefined);
                    }
                    else
                    {
                        ch.WorsenMentalState(1);
                    }
                }
            }

            return(retcode);
        }
예제 #5
0
        public static ReturnTypes spell_area_attack(int sn, int level, CharacterInstance ch, object vo)
        {
            var skill = RepositoryManager.Instance.SKILLS.Get(sn);

            if (CheckFunctions.CheckIfTrueCasting(ch.CurrentRoom.Flags.IsSet(RoomFlags.Safe), skill, ch))
            {
                return(ReturnTypes.SpellFailed);
            }

            if (string.IsNullOrEmpty(skill.HitCharacterMessage))
            {
                comm.act(ATTypes.AT_MAGIC, skill.HitCharacterMessage, ch, null, null, ToTypes.Character);
            }
            if (string.IsNullOrEmpty(skill.HitRoomMessage))
            {
                comm.act(ATTypes.AT_MAGIC, skill.HitRoomMessage, ch, null, null, ToTypes.Room);
            }

            foreach (var vch in ch.CurrentRoom.Persons
                     .Where(x => x.IsNpc() || !x.Act.IsSet((int)PlayerFlags.WizardInvisibility) ||
                            ((PlayerInstance)x).PlayerData.WizardInvisible < LevelConstants.ImmortalLevel)
                     .Where(x => x != ch)
                     .Where(x => !fight.is_safe(ch, x, false))
                     .Where(x => ch.IsNpc() || x.IsNpc() || ch.IsInArena() || (ch.IsPKill() && x.IsPKill())))
            {
                var saved = skill.CheckSave(level, ch, vch);
                if (saved &&
                    CheckFunctions.CheckIfTrueCasting(Macros.SPELL_SAVE(skill) == (int)SpellSaveEffectTypes.Negate,
                                                      skill, ch, CastingFunctionType.Failed, vch))
                {
                    continue;
                }

                var damage = GetBaseDamage(level, ch, skill);

                if (saved)
                {
                    damage = GetDamageIfSaved(sn, level, ch, skill, vch, damage);
                }

                var retcode = ch.CauseDamageTo(vch, damage, sn);
                if (retcode == ReturnTypes.None &&
                    !ch.CharDied() && !vch.CharDied()
                    &&
                    (!vch.IsAffectedBy(sn) || skill.Flags.IsSet(SkillFlags.Accumulative) ||
                     skill.Flags.IsSet(SkillFlags.ReCastable)))
                {
                    retcode = AffectCharacter.spell_affectchar(sn, level, ch, vch);
                }

                if (retcode == ReturnTypes.CharacterDied || ch.CharDied())
                {
                    break;
                }
            }
            return(ReturnTypes.None);
        }
예제 #6
0
        private static void Bash(CharacterInstance actor, SkillData skill, string arg)
        {
            comm.act(ATTypes.AT_SKILL, "WHAAAAM!!! You bash against the $d, but it doesn't budge.", actor, null, arg,
                     ToTypes.Character);
            comm.act(ATTypes.AT_SKILL, "WHAAAAM!!! $n bashes against the $d, but it holds strong.", actor, null, arg,
                     ToTypes.Room);

            var damage = actor.MaximumHealth / 20 + 10;

            actor.CauseDamageTo(actor, damage, (int)skill.ID);
            skill.LearnFromFailure(actor);
        }
예제 #7
0
        public static ReturnTypes spell_acetum_primus(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;

            var lvl    = 0.GetHighestOfTwoNumbers(level);
            var damage = (int)(1.3f * (2 * lvl * SmaugRandom.D4() + 7));

            if (victim.SavingThrows.CheckSaveVsSpellStaff(lvl, victim))
            {
                damage = 3 * damage / 4;
            }
            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #8
0
        public static ReturnTypes spell_acid_blast(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = vo.CastAs <CharacterInstance>();

            var damage = SmaugRandom.D6(level);

            if (victim.SavingThrows.CheckSaveVsSpellStaff(level, victim))
            {
                damage /= 2;
            }

            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #9
0
        public static ReturnTypes spell_sulfurous_spray(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;

            var lvl = 0.GetHighestOfTwoNumbers(level);

            lvl = 19.GetLowestOfTwoNumbers(lvl);
            var damage = (int)(1.3f * (2 * lvl * SmaugRandom.Roll(7, 1) + 11));

            if (victim.SavingThrows.CheckSaveVsSpellStaff(lvl, victim))
            {
                damage /= 4;
            }
            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #10
0
        private static void BashSomething(CharacterInstance actor, ExitData exit, SkillData skill, string arg)
        {
            if (CheckFunctions.CheckIfSet(actor, exit.Flags, ExitFlags.Closed, "Calm down. It is already open."))
            {
                return;
            }

            Macros.WAIT_STATE(actor, skill.Rounds);

            var keyword = exit.Flags.IsSet(ExitFlags.Secret) ? "wall" : exit.Keywords;

            var chance = !actor.IsNpc()
                ? Macros.LEARNED(actor, (int)skill.ID) / 2
                : 90;

            if (exit.Flags.IsSet(ExitFlags.Locked))
            {
                chance /= 3;
            }

            if (exit.Flags.IsSet(ExitFlags.BashProof) ||
                actor.CurrentMovement < 15 ||
                SmaugRandom.D100() >= chance + 4 * (actor.GetCurrentStrength() - 19))
            {
                Bash(actor, skill, arg);
                return;
            }

            BashExit(exit);

            comm.act(ATTypes.AT_SKILL, "Crash! You bashed open the $d!", actor, null, keyword, ToTypes.Character);
            comm.act(ATTypes.AT_SKILL, "$n bashes open the $d!", actor, null, keyword, ToTypes.Room);
            skill.LearnFromSuccess(actor);

            var reverseExit = exit.GetReverse();

            BashExit(reverseExit);

            var destination = exit.GetDestination(RepositoryManager.Instance);

            foreach (var ch in destination.Persons)
            {
                comm.act(ATTypes.AT_SKILL, "The $d crashes open!", ch, null, reverseExit.Keywords, ToTypes.Character);
            }

            actor.CauseDamageTo(actor, actor.CurrentHealth / 20, (int)skill.ID);
        }
예제 #11
0
        public static ReturnTypes spell_caustic_fount(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;

            var lvl = 0.GetHighestOfTwoNumbers(level);

            lvl = 42.GetLowestOfTwoNumbers(lvl);
            var damage = (int)(1.3f * (2 * lvl * SmaugRandom.D6() - 31));

            damage = 0.GetHighestOfTwoNumbers(damage);

            if (victim.SavingThrows.CheckSaveVsSpellStaff(lvl, victim))
            {
                damage = damage * 1 / 2;
            }
            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #12
0
        public static ReturnTypes spell_black_hand(int sn, int level, CharacterInstance ch, object vo)
        {
            var lvl = 0.GetHighestOfTwoNumbers(level);

            lvl = 5.GetLowestOfTwoNumbers(lvl);

            var dam = (int)(1.3f * (lvl * SmaugRandom.D6() + 3));

            var victim = (CharacterInstance)vo;

            if (victim.SavingThrows.CheckSaveVsSpellStaff(lvl, victim))
            {
                dam /= 4;
            }

            return(ch.CauseDamageTo(victim, dam, sn));
        }
예제 #13
0
        public static ReturnTypes spell_colour_spray(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;

            var modLevel = level.GetLowestOfTwoNumbers(DamageValues.Length * 2 / 2 - 1);

            modLevel = modLevel.GetHighestOfTwoNumbers(0);

            if (DamageValues.Length >= modLevel)
            {
                throw new InvalidDataException(
                          $"ModLevel {modLevel} is larger than the Damage Array size of {DamageValues.Length}");
            }

            var dam = SmaugRandom.Between(DamageValues[modLevel] / 2, DamageValues[modLevel] * 2);

            if (victim.SavingThrows.CheckSaveVsSpellStaff(modLevel, victim))
            {
                dam /= 2;
            }

            return(ch.CauseDamageTo(victim, dam, sn));
        }
예제 #14
0
        public static ReturnTypes spell_acid_breath(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;

            int chance;

            checked
            {
                chance = 2 * level;
            }

            if (ch.Chance(chance) && !victim.SavingThrows.CheckSaveVsBreath(level, victim))
            {
                foreach (var obj in victim.Carrying.Where(obj => SmaugRandom.Bits(2) == 0))
                {
                    switch (obj.ItemType)
                    {
                    case ItemTypes.Armor:
                        CheckDamageArmor(obj, victim);
                        break;

                    case ItemTypes.Container:
                        CheckDamageContainer(obj, victim);
                        break;
                    }
                }
            }

            var hpChange = 10.GetHighestOfTwoNumbers(ch.CurrentHealth);
            var damage   = SmaugRandom.Between(hpChange / 16 + 1, hpChange / 8);

            if (victim.SavingThrows.CheckSaveVsBreath(level, victim))
            {
                damage /= 2;
            }
            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #15
0
        public static ReturnTypes spell_dispel_evil(int sn, int level, CharacterInstance ch, object vo)
        {
            var victim = (CharacterInstance)vo;
            var skill  = RepositoryManager.Instance.GetEntity <SkillData>(sn);

            if (!ch.IsNpc() && ch.IsEvil())
            {
                victim = ch;
            }

            if (victim.IsGood())
            {
                comm.act(ATTypes.AT_MAGIC, "Thoric protects $N.", ch, null, victim, ToTypes.Room);
                return(ReturnTypes.SpellFailed);
            }

            if (victim.IsNeutral())
            {
                comm.act(ATTypes.AT_MAGIC, "$N does not seem to be affected.", ch, null, victim, ToTypes.Character);
                return(ReturnTypes.SpellFailed);
            }

            if (CheckFunctions.CheckIfTrueCasting(victim.IsImmune(ResistanceTypes.Magic), skill, ch,
                                                  CastingFunctionType.Immune, victim))
            {
                return(ReturnTypes.SpellFailed);
            }

            var damage = SmaugRandom.Roll(level, 4);

            if (victim.SavingThrows.CheckSaveVsSpellStaff(level, victim))
            {
                damage /= 2;
            }

            return(ch.CauseDamageTo(victim, damage, sn));
        }
예제 #16
0
        public static ReturnTypes ranged_got_target(CharacterInstance ch, CharacterInstance victim,
                                                    ObjectInstance weapon, ObjectInstance projectile, int dist, int dt, string stxt,
                                                    ATTypes color)
        {
            if (ch.CurrentRoom.Flags.IsSet(RoomFlags.Safe))
            {
                if (projectile != null)
                {
                    ch.PrintfColor("Your %s is blasted from existence by a godly presence.", projectile);
                    comm.act(color, "A godly presence smites $p!", ch, projectile, null, ToTypes.Room);
                    projectile.Extract();
                }
                else
                {
                    ch.Printf("Your %s is blasted from existence by a godly presence.", stxt);
                    comm.act(color, "A godly presence smites $t!", ch, stxt.AddArticle(ArticleAppendOptions.TheToFront), null, ToTypes.Room);
                }
                return(ReturnTypes.None);
            }

            var skill = RepositoryManager.Instance.GetEntity <SkillData>("MissileWeapons");

            if (victim.IsNpc() && victim.Act.IsSet((int)ActFlags.Sentinel) &&
                ch.CurrentRoom != victim.CurrentRoom)
            {
                if (projectile == null)
                {
                    return(ch.CauseDamageTo(victim, 0, dt));
                }
                skill.LearnFromFailure(ch);

                if (SmaugRandom.D100() < 50)
                {
                    projectile.Extract();
                }
                else
                {
                    if (projectile.InObject != null)
                    {
                        projectile.RemoveFrom(projectile.InObject);
                    }
                    if (projectile.CarriedBy != null)
                    {
                        projectile.RemoveFrom();
                    }
                    victim.CurrentRoom.AddTo(projectile);
                }
                return(ch.CauseDamageTo(victim, 0, dt));
            }

            if (SmaugRandom.D100() > 50 || (projectile != null && weapon != null &&
                                            ch.CanUseSkill(SmaugRandom.D100(), skill)))
            {
                return(projectile != null?fight.projectile_hit(ch, victim, weapon, projectile, dist) : Attack.spell_attack(dt, ch.Level, ch, victim));
            }

            skill.LearnFromFailure(ch);
            var returnCode = ch.CauseDamageTo(victim, 0, dt);

            if (projectile == null)
            {
                return(returnCode);
            }

            if (SmaugRandom.D100() < 50)
            {
                projectile.Extract();
            }
            else
            {
                if (projectile.InObject != null)
                {
                    projectile.RemoveFrom(projectile.InObject);
                }
                if (projectile.CarriedBy != null)
                {
                    projectile.RemoveFrom();
                }
                victim.CurrentRoom.AddTo(projectile);
            }

            return(returnCode);
        }
예제 #17
0
        public static ReturnTypes ObjectCastSpell(this CharacterInstance ch, int sn, int level,
                                                  CharacterInstance victim = null, ObjectInstance obj = null)
        {
            var skill = RepositoryManager.Instance.GetEntity <SkillData>(sn);

            if (skill?.SpellFunction == null)
            {
                return(ReturnTypes.Error);
            }

            if (ch.CurrentRoom.Flags.IsSet(RoomFlags.NoMagic) ||
                (ch.CurrentRoom.Flags.IsSet(RoomFlags.Safe) &&
                 skill.Target == TargetTypes.OffensiveCharacter))
            {
                ch.SetColor(ATTypes.AT_MAGIC);
                ch.SendTo("Nothing seems to happen...");
                return(ReturnTypes.None);
            }

            // Reduces the number of level 5 players using level 40 scrolls in battle
            var levelDiff = ch.Level - level;

            if ((skill.Target == TargetTypes.OffensiveCharacter || SmaugRandom.Bits(7) == 1) &&
                skill.Type != SkillTypes.Herb &&
                ch.Chance(95 + levelDiff))
            {
                switch (SmaugRandom.Bits(2))
                {
                case 0:
                case 2:
                    ch.FailedCast(skill, victim);
                    break;

                case 1:
                case 3:
                    comm.act(ATTypes.AT_MAGIC, "The $t spell backfires!", ch, skill.Name, victim, ToTypes.Character);
                    if (victim != null)
                    {
                        comm.act(ATTypes.AT_MAGIC, "$n's $t spell backfires!", ch, skill.Name, victim,
                                 ToTypes.Victim);
                    }
                    comm.act(ATTypes.AT_MAGIC, "$n's $t spell backfires!", ch, skill.Name, victim, ToTypes.Room);
                    return(ch.CauseDamageTo(ch, SmaugRandom.Between(1, level), Program.TYPE_UNDEFINED));
                }

                return(ReturnTypes.None);
            }

            object vo;

            switch (skill.Target)
            {
            default:
                LogManager.Instance.Bug("Bad target for sn {0}", sn);
                return(ReturnTypes.Error);

            case TargetTypes.Ignore:
                vo = null;
                if (victim != null)
                {
                    Cast.TargetName = victim.Name;
                }
                else if (obj != null)
                {
                    Cast.TargetName = obj.Name;
                }
                break;

            case TargetTypes.OffensiveCharacter:
                if (victim != ch)
                {
                    if (victim == null)
                    {
                        victim = ch.GetMyTarget();
                    }
                    if (CheckFunctions.CheckIfTrue(ch, victim == null || (!victim.IsNpc() && !victim.IsInArena()),
                                                   "You can't do that."))
                    {
                        return(ReturnTypes.None);
                    }
                }
                if (ch != victim && fight.is_safe(ch, victim, true))
                {
                    return(ReturnTypes.None);
                }
                vo = victim;
                break;

            case TargetTypes.DefensiveCharacter:
                if (victim == null)
                {
                    victim = ch;
                }
                vo = victim;
                if (CheckFunctions.CheckIfTrueCasting(
                        skill.Type != SkillTypes.Herb && victim.Immunity.IsSet(ResistanceTypes.Magic),
                        skill, ch, CastingFunctionType.Immune, victim))
                {
                    return(ReturnTypes.None);
                }
                break;

            case TargetTypes.Self:
                vo = ch;
                if (CheckFunctions.CheckIfTrueCasting(
                        skill.Type != SkillTypes.Herb && ch.Immunity.IsSet(ResistanceTypes.Magic),
                        skill, ch, CastingFunctionType.Immune, victim))
                {
                    return(ReturnTypes.None);
                }
                break;

            case TargetTypes.InventoryObject:
                if (CheckFunctions.CheckIfNullObject(ch, obj, "You can't do that!"))
                {
                    return(ReturnTypes.None);
                }

                vo = obj;
                break;
            }

            var start   = DateTime.Now;
            var retcode = skill.SpellFunction.Value.Invoke(sn, level, ch, vo);

            skill.UseHistory.Use(ch, DateTime.Now.Subtract(start));

            if (retcode == ReturnTypes.SpellFailed)
            {
                retcode = ReturnTypes.None;
            }

            if (retcode == ReturnTypes.CharacterDied || retcode == ReturnTypes.Error)
            {
                return(retcode);
            }

            if (ch.CharDied())
            {
                return(ReturnTypes.CharacterDied);
            }

            if (skill.Target == TargetTypes.OffensiveCharacter &&
                victim != ch &&
                !victim.CharDied())
            {
                foreach (
                    var vch in
                    ch.CurrentRoom.Persons.Where(
                        vch => victim == vch && vch.CurrentFighting == null && vch.Master != ch))
                {
                    retcode = fight.multi_hit(vch, ch, Program.TYPE_UNDEFINED);
                    break;
                }
            }

            return(retcode);
        }