Suprcode / Crystal

Legend of Mir 2 - Official Public Crystal Source
1.15k stars 690 forks source link

Add Archer Hero #826

Open angelk727 opened 1 year ago

angelk727 commented 1 year ago

1、"X:\mir2-master\Server\MirObjects\PlayerObject.cs"(13559,13): HeroObject hero = CurrentHero.Class switch

public void SummonHero() { HeroObject hero = CurrentHero.Class switch { MirClass.Warrior => new WarriorHero(CurrentHero, this), MirClass.Wizard => new WizardHero(CurrentHero, this), MirClass.Taoist => new TaoistHero(CurrentHero, this), MirClass.Assassin => new AssassinHero(CurrentHero, this), MirClass.Archer => new ArcherHero(CurrentHero, this), //<+++++++++++ Add _ => new HeroObject(CurrentHero, this) };

        hero.ActionTime = Envir.Time + 1000;
        hero.RefreshNameColour();

        if (!hero.Dead)
            SpawnHero(hero);

        Hero = hero;
        Info.HeroSpawned = true;
        Enqueue(new S.UpdateHeroSpawnState { State = hero.Dead ? HeroSpawnState.Dead : HeroSpawnState.Summoned });
    }

2、"X:\mir2-master\Server\MirObjects\Hero\ArcherHero.cs" <+++++++++++ Create a new ArcherHero.cs

ArcherHero.cs CODE:


using Server.MirDatabase; using Server.MirEnvir;

namespace Server.MirObjects { public class ArcherHero : HeroObject { public ArcherHero(CharacterInfo info, PlayerObject owner) : base(info, owner) { }

    private bool HasRangedSpell => Info.Magics.Select(x => x.Spell).Intersect(Globals.RangedSpells).Any();

    public bool HasWeapon => Info.Equipment[(int)EquipmentSlot.Weapon] != null && Info.Equipment[(int)EquipmentSlot.Weapon].CurrentDura > 0;

    public bool HasClassWeapon
    {
        get
        {
            var classweapon = Info.Equipment[(int)EquipmentSlot.Weapon];
            return classweapon != null && classweapon.Info.RequiredClass == RequiredClass.Archer && classweapon.CurrentDura > 0;
        }
    }

    private static Point GetRandomPointAround(int distance, Point center)
    {
        int randomDistance = new Random().Next(1, distance);
        double randomAngle = new Random().NextDouble() * 2 * Math.PI;
        int targetX = (int)(center.X + (1 + randomDistance) * Math.Cos(randomAngle));
        int targetY = (int)(center.Y + (1 + randomDistance) * Math.Sin(randomAngle));
        return new Point(targetX, targetY);
    }

    protected override bool InAttackRange()
    {
        if (Target.CurrentMap != CurrentMap) return false;

        if (HasRangedSpell)
            return TargetDistance <= ViewRange;

        return Target.CurrentLocation != CurrentLocation && Functions.InRange(CurrentLocation, Target.CurrentLocation, 1);
    }

    protected override void ProcessFriend()
    {
        if (!HasBuff(BuffType.Concentration))
        {
            UserMagic magic = GetMagic(Spell.Concentration);
            if (CanUseMagic(magic))
            {
                BeginMagic(magic.Spell, Direction, ObjectID, CurrentLocation);
                return;
            }
        }
    }

    protected override void ProcessAttack()
    {
        if (Target == null || Target.Dead) return;
        TargetDistance = Functions.MaxDistance(CurrentLocation, Target.CurrentLocation);
        Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);

        switch (Envir.Random.Next(4))
        {
            case 0:
                UserMagic magic = GetMagic(Spell.PoisonShot);
                if (CanUseMagic(magic))
                {
                    BeginMagic(magic.Spell, Direction, Target.ObjectID, Target.CurrentLocation);
                    return;
                }
                break;
            case 1:
                magic = GetMagic(Spell.CrippleShot);
                if (CanUseMagic(magic))
                {
                    BeginMagic(magic.Spell, Direction, Target.ObjectID, Target.CurrentLocation);
                    return;
                }
                break;
            case 2:
                magic = GetMagic(Spell.StraightShot);
                if (CanUseMagic(magic))
                {
                    BeginMagic(magic.Spell, Direction, Target.ObjectID, Target.CurrentLocation);
                    return;
                }
                break;
            case 3:
                magic = GetMagic(Spell.ElementalShot);
                if (CanUseMagic(magic))
                {
                    BeginMagic(magic.Spell, Direction, Target.ObjectID, Target.CurrentLocation);
                    return;
                }
                break;
        }
    }

    protected override void ProcessTarget()
    {

        if (HasClassWeapon && CanCast && NextMagicSpell != Spell.None)
        {
            Magic(NextMagicSpell, NextMagicDirection, NextMagicTargetID, NextMagicLocation);
            NextMagicSpell = Spell.None;
        }

        if (Target == null || !CanAttack) return;

        if ((!HasWeapon || (HasWeapon && !HasClassWeapon)))
        {
            if (TargetDistance >= 1 && InAttackRange())
            {
                Attack();

                if (Target.Dead)
                {
                    FindTarget();
                    return;
                }
            }
            else
            {
                MoveTo(Target.CurrentLocation);
                return;
            }
        }

        if (HasClassWeapon && TargetDistance < 2)
        {
            Point randomPoint = GetRandomPointAround(6, CurrentLocation);
            MoveTo(randomPoint);
        }

        if (Target != null && HasClassWeapon && !HasRangedSpell)
        {
            Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
            RangeAttack(Direction, Target.CurrentLocation, Target.ObjectID);

            if (Target.Dead)
            {
                FindTarget();
            }
            return;
        }

        AttackTime = Envir.Time + AttackSpeed;
        ActionTime = Envir.Time + 1200;
        RegenTime = Envir.Time + RegenDelay;
    }
}

}


meacher0 commented 4 months ago

956