using System; using System.Collections.Generic; using MCGalaxy.Events.PlayerEvents; using MCGalaxy; using MCGalaxy.Commands; using MCGalaxy.Network; using MCGalaxy.SQL; using MCGalaxy.Tasks; using MCGalaxy.Blocks; using MCGalaxy.Maths; namespace Survival { public class Mobs : Plugin_Simple { public override string creator { get { return "faeempress"; } } public override string MCGalaxy_Version { get { return "1.9.2.3"; } } public override string name { get { return "Mobs"; } } private int MaxMobs=100; private int init=0; private string SurvivalMap="survival"; private int lvlwidth=0; private int lvllength=0; private int lvlheight=0; List mobs=new List(); string[] mobtypes={"chicken","human","pig","sheep","zombie","creeper","skeleton","spider"}; SchedulerTask task; public override void Load(bool startup) { Command.Register(new CmdSpawnMob(this)); OnJoinedLevelEvent.Register(OnJoinedLevel, Priority.Low); OnPlayerClickEvent.Register(HandleClick, Priority.Low); task = Server.MainScheduler.QueueRepeat(MobsCallback, null, TimeSpan.FromMilliseconds(100)); } public override void Unload(bool shutdown) { int i; for(i=0;i %H- Spawns a specified mob"); } } public class Mob { public byte ID = 0; public int hp = 10; private int _count; private int _attackCount; private Mobs _survivalMobs; public Position _pos; public Position pos { get { return _pos; } } protected Orientation _rot; private bool _canJump = false; protected bool _beenHurted = false; private int _refreshClientCount = 0; private int _swimCount = 0; public string _model = ""; protected string _curMap = ""; protected int _speedX = 0; protected int _speedY = 0; protected int _speedZ = 0; protected int _VelX = 0; protected int _VelY = 0; protected int _VelZ = 0; protected int _width = 32; protected int _height = 64; public void SurvivalMob(int X, int Y, int Z, string model, string map,byte sID,Mobs m) { ID = sID; _pos = new Position(X*32,Y*32,Z*32); _rot = new Orientation(); _model = model; _curMap = map; _speedX = 4; _survivalMobs=m; } public bool HitTestMap() { Level map = LevelInfo.FindExact(_curMap); int minX = _pos.X/32 - 2; int maxX = _pos.X/32 + 2; int minY = _pos.Y/32 - 2; int maxY = _pos.Y/32 + 2; int minZ = _pos.Z/32 - 2; int maxZ = _pos.Z/32 + 2; for (int i = minY; i <= maxY; i++) { for (int j = minX; j <= maxX; j++) { for (int k = minZ; k <= maxZ; k++){ if (!CollideType.IsSolid(map.CollideType((map.GetBlock((ushort)(j), (ushort)(i), (ushort)(k)))))) continue; bool touchX = _pos.X + _width > (j * 32) && _pos.X < ((j+1) * 32); bool touchY = (_pos.Y-32) + _height > (i * 32) && (_pos.Y-32) < ((i+1) * 32); bool touchZ = _pos.Z + _width > (k * 32) && _pos.Z < ((k+1) * 32); if (touchX && touchY && touchZ) return true; } } } return false; } public bool HitTestPlayer(Player p) { bool touchX = _pos.X + _width+16 > p.Pos.X + p.ModelBB.BlockMin.X && _pos.X-16 < p.Pos.X + p.ModelBB.BlockMax.X; bool touchY = _pos.Y + _height > p.Pos.Y + p.ModelBB.BlockMin.Y && _pos.Y < p.Pos.Y + p.ModelBB.BlockMax.Y; bool touchZ = _pos.Z + _width+16 > p.Pos.Z + p.ModelBB.BlockMin.Z && _pos.Z-16 < p.Pos.Z + p.ModelBB.BlockMax.Z; if (touchX && touchY && touchZ) return true; return false; } public void createClientEntity() { foreach (Player p in PlayerInfo.Online.Items) { if (p.level.name != _curMap) continue; p.Send(Packet.AddEntity(ID, "", _pos, _rot, true, true)); p.Send(Packet.ChangeModel(ID, _model, true)); } } public void deleteClientEntity(){ foreach (Player p in PlayerInfo.Online.Items) { if (p.level.name == _curMap) p.Send(Packet.RemoveEntity(ID)); } } public void HurtByPlayer(int damage, Player p) { //knockback int a = p.Pos.X - _pos.X; int b = p.Pos.Z - _pos.Z; int angle = (int)(Math.Atan2(b, a)); _VelX = -(int)(Math.Cos(angle) * 15); _VelZ = -(int)(Math.Sin(angle) * 15); _VelY = 11; //Damage Hurt(damage,p); _beenHurted = true; } private void Hurt(int damage, Player p) { hp -= damage; if (hp <= 0) { p.SetMoney(p.money + 5); p.Message("Gained 5 %b"+Server.Config.Currency); Remove(ID); return; } } public Player getClosestPlayerFrom(float x,float y,float z,string map) { float deltaX; float deltaY; float deltaZ; Player pl=null; float lastd=120000; foreach (Player p in PlayerInfo.Online.Items) { if (p.level.name == map) { deltaX=x-p.Pos.X; deltaY=y-p.Pos.Y; deltaZ=z-p.Pos.Z; float distance = (float) Math.Abs(Math.Sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ)); if(distance _width+_height) continue; if (HitTestPlayer(pl)) { pl.HandleDeath(Block.Stone, "@p %c"+"was killed by a "+_model, false,false); } } } } public int eUpdate() { _attackCount++; if (_attackCount > 10) { _attackCount = 0; Attack(); } Player p = getClosestPlayerFrom(_pos.X,_pos.Y,_pos.Z,_curMap); if (p != null) { int dist = calculDistance(p.Pos, _pos); /*if (dist > 4096) { Remove(ID); return 1; }*/ if (dist > 250) { _speedX = 0; _speedZ = 0; UpdatePosition(); return 0; } int a = p.Pos.X - _pos.X; int b = p.Pos.Z - _pos.Z; int angle = (int)(Math.Atan2(b, a)); _speedX = (int)(Math.Cos(angle) * 5); _speedZ = (int)(Math.Sin(angle) * 5); Vec3F32 dir = new Vec3F32(a, 0, b); dir = Vec3F32.Normalise(dir); DirUtils.GetYawPitch(dir, out _rot.RotY, out _rot.HeadX); } UpdatePosition(); return 0; } public int aUpdate() { Player p = getClosestPlayerFrom(_pos.X,_pos.Y,_pos.Z,_curMap); if (p != null) { int dist = calculDistance(p.Pos, _pos); /*if (dist > 2048) { Remove(ID); return 1; }*/ if (dist > 256 || !_beenHurted) { _count++; if (_count > 100) { _count = 0; Random rnd = new Random(); _speedX = rnd.Next(-2,3); _speedZ = rnd.Next(-2,3); } int a2 = _pos.X - _pos.X + _speedX; int b2 = _pos.Z - _pos.Z + _speedZ; Vec3F32 dir2 = new Vec3F32(a2, 0, b2); dir2 = Vec3F32.Normalise(dir2); DirUtils.GetYawPitch(dir2, out _rot.RotY, out _rot.HeadX); UpdatePosition(); return 0; } int a = _pos.X - p.Pos.X; int b = _pos.Z - p.Pos.Z; int angle = (int)(Math.Atan2(b, a)); _speedX = (int)(Math.Cos(angle) * 5); _speedZ = (int)(Math.Sin(angle) * 5); Vec3F32 dir = new Vec3F32(a, 0, b); dir = Vec3F32.Normalise(dir); DirUtils.GetYawPitch(dir, out _rot.RotY, out _rot.HeadX); } UpdatePosition(); return 0; } public virtual int Update() { if(_model=="pig" || _model=="sheep" || _model=="chicken") aUpdate(); else eUpdate(); UpdatePosition(); return 0; } public void Jump() { if (_canJump) { _canJump = false; _speedY = 9; } } public void UpdatePosition() { //Refresh every 30secs to prevent invisible mobs bug _refreshClientCount++; if (_refreshClientCount >= 1000) { _refreshClientCount = 0; createClientEntity(); } //Swiming Level map = LevelInfo.FindExact(_curMap); ushort block = map.GetBlock((ushort)_pos.BlockX, (ushort)_pos.BlockY, (ushort)_pos.BlockZ); byte collide = map.CollideType(block); Random rnd = new Random(); if (collide == CollideType.SwimThrough) { _swimCount++; if(_swimCount > 20) { _speedY=3; if (_swimCount > 60) { _swimCount = 0; } } else { _speedY=-1; } } _speedY--; if (_VelX > 0) _VelX--; if (_VelX < 0) _VelX++; if (_VelY > 0) _VelY--; if (_VelY < 0) _VelY++; if (_VelZ > 0) _VelZ--; if (_VelZ < 0) _VelZ++; int oldX = _pos.X; _pos.X += _speedX+_VelX; if (HitTestMap()) { _pos.X = oldX; Jump(); } int oldY = _pos.Y; _pos.Y += _speedY+_VelY; if (HitTestMap()) { if(_speedY < 0) { _canJump = true; } _speedY = 0; _pos.Y = oldY; } int oldZ = _pos.Z; _pos.Z += _speedZ+_VelZ; if (HitTestMap()) { _pos.Z = oldZ; Jump(); } foreach (Player p in PlayerInfo.Online.Items) { if (p.level.name != _curMap) continue; Position fakePos = new Position(_pos.X+16,_pos.Y+17,_pos.Z+16); p.Send(Packet.Teleport(ID, fakePos, _rot, true)); } } } }