using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NewestCOServer.Game
{
public class Companion
{
public uint MinAttack;
public uint MaxAttack;
public byte Level;
public uint SkillUses;//0 if just melee
public Location Loc;
public Character Owner;
public ushort CurHP;
public ushort MaxHP;
public uint Mesh;
public uint EntityID;
public string Name;
public byte Direction;
DateTime LastMovement = DateTime.Now;
DateTime LastAttack = DateTime.Now;
public PoisonType PoisonedInfo = null;
public Companion(Character Owner, uint Type)
{
this.Owner = Owner;
if (Database.CompanionInfos.Contains(Type))
{
CompanionInfo Cmp = (CompanionInfo)Database.CompanionInfos[Type];
MinAttack = Cmp.MinAttack;
MaxAttack = Cmp.MaxAttack;
Level = Cmp.Level;
SkillUses = Cmp.SkillUses;
CurHP = Cmp.HP;
MaxHP = Cmp.HP;
Mesh = Cmp.Mesh;
Name = Cmp.Name;
EntityID = (uint)Program.Rnd.Next(400000, 500000);
Direction = 0;
Loc = Owner.Loc;
World.H_Companions.Add(EntityID, this);
World.Spawn(this, false);
}
}
public void Dissappear()
{
if (World.H_Companions.Contains(EntityID))
{
World.H_Companions.Remove(EntityID);
if (Owner.MyCompanion == this)
Owner.MyCompanion = null;
World.Action(this, Packets.GeneralData(EntityID, 0, 0, 0, 135).Get);
}
}
public void Step()
{
if (DateTime.Now > LastMovement.AddMilliseconds(250))
{
LastMovement = DateTime.Now;
if (MyMath.PointDistance(Loc.X, Loc.Y, Owner.Loc.X, Owner.Loc.Y) <= 18)
{
if (Owner.AtkMem.Target != 0 && Owner.AtkMem.Target != Owner.EntityID && (MyMath.PointDistance(Loc.X, Loc.Y, Owner.Loc.X, Owner.Loc.Y) <= 8))
{
if (SkillUses != 0 && DateTime.Now > LastAttack.AddMilliseconds(1000))
{
LastAttack = DateTime.Now;
uint Damage = (uint)Program.Rnd.Next((int)MinAttack, (int)MaxAttack);
if (World.H_Chars.Contains(Owner.AtkMem.Target))
{
Character C = (Character)World.H_Chars[Owner.AtkMem.Target];
if (C.Alive && C.Loc.Map == Loc.Map && (MyMath.PointDistance(Loc.X, Loc.Y, C.Loc.X, C.Loc.Y) <= 10))
C.TakeAttack(this, Damage, AttackType.Magic);
}
else if (World.H_Mobs.Contains(Loc.Map) && ((Hashtable)World.H_Mobs[Loc.Map]).Contains(Owner.AtkMem.Target))
{
Mob M = (Mob)((Hashtable)World.H_Mobs[Loc.Map])[Owner.AtkMem.Target];
if (M.Alive && M.Loc.Map == Loc.Map && (MyMath.PointDistance(Loc.X, Loc.Y, M.Loc.X, M.Loc.Y) <= 10))
M.TakeAttack(this, Damage, AttackType.Magic);
}
}
}
else if (MyMath.PointDistance(Loc.X, Loc.Y, Owner.Loc.X, Owner.Loc.Y) >= 4)
{
GetDirection(Owner.Loc);
byte eDir = Direction;
bool Success = true;
while (!FreeToGo())
{
Direction = (byte)((Direction + 1) % 8);
if (Direction == eDir)
{
Success = false;
break;
}
Success = true;
}
if (!Success)
JumpToOwner();
else
{
Loc.Walk(Direction);
World.Action(this, Packets.Movement(EntityID, Direction).Get);
World.Spawn(this, true);
}
}
}
else
JumpToOwner();
}
}
void JumpToOwner()
{
Loc.X = (ushort)(Owner.Loc.X + Program.Rnd.Next(7) - Program.Rnd.Next(7));
Loc.Y = (ushort)(Owner.Loc.Y + Program.Rnd.Next(7) - Program.Rnd.Next(7));
World.Action(this, Packets.GeneralData(EntityID, Loc.X, Loc.Y, 0, 0, 137).Get);
World.Spawn(this, true);
}
void GetDirection(Location Target)
{
byte ToDir = (byte)(7 - (Math.Floor(MyMath.PointDirecton(Loc.X, Loc.Y, Target.X, Target.Y) / 45 % 8)) - 1 % 8);
Direction = (byte)((int)ToDir % 8);
}
bool FreeToGo()
{
Location eLoc = Loc;
eLoc.Walk(Direction);
if (!DMaps.H_DMaps.Contains(Loc.Map))
return true;
if (((DMap)DMaps.H_DMaps[Loc.Map]).GetCell(eLoc.X, eLoc.Y).NoAccess)
return false;
return true;
}
}
}
|