Add Archer Hero
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;
}
}
}
Previously, it was a painful thing to reduce endurance to 0 due to the archer's weapon. So it hasn't been tested The original post has been corrected fix bug:
private bool HasWeapon => Info.Equipment[(int)EquipmentSlot.Weapon] != null && Info.Equipment[(int)EquipmentSlot.Weapon].Info.Durability > 0;
public bool HasClassWeapon
{
get
{
var classweapon = Info.Equipment[(int)EquipmentSlot.Weapon];
return classweapon != null && classweapon.Info.RequiredClass == RequiredClass.Archer && classweapon.Info.Durability > 0;
}
}
replace with--------------->
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;
}
}
#956