HISP/HorseIsleServer/LibHISP/Game/Npc.cs
2022-07-25 19:17:30 +12:00

339 lines
11 KiB
C#

using HISP.Player;
using HISP.Server;
using System.Collections.Generic;
namespace HISP.Game
{
public class Npc
{
public struct NpcReply
{
public int Id;
public string ReplyText;
public int GotoChatpoint;
public int RequiresQuestIdCompleted;
public int RequiresQuestIdNotCompleted;
}
public struct NpcChat
{
public int Id;
public string ChatText;
public int ActivateQuestId;
public NpcReply[] Replies;
}
public class NpcEntry
{
public NpcEntry(int npcId, int posX, int posY, bool npcMoves, int udlrStartX=0, int udlrStartY=0)
{
id = npcId;
x = posX;
y = posY;
Moves = npcMoves;
UDLRStartX = udlrStartX;
UDLRStartY = udlrStartY;
if(Moves)
{
if(Database.HasNpcPos(id))
{
udlrScriptPos = Database.GetNpcUdlrPointer(npcId);
x = Database.GetNpcPosX(npcId);
y = Database.GetNpcPosY(npcId);
}
else
{
if(udlrStartX != 0 && udlrStartY != 0)
{
x = udlrStartX;
y = udlrStartY;
}
udlrScriptPos = 0;
Database.AddNpcPos(npcId, x, Y, udlrScriptPos);
}
}
}
private int id;
public string Name;
public string AdminDescription;
public string ShortDescription;
public string LongDescription;
public bool Moves;
private int x;
private int y;
public int Id
{
get
{
return id;
}
}
public int X
{
get
{
return x;
}
set
{
Database.SetNpcX(id, value);
x = value;
}
}
public int Y
{
get
{
return y;
}
set
{
Database.SetNpcY(id, value);
y = value;
}
}
public string StayOn;
public int RequiresQuestIdCompleted;
public int RequiresQuestIdNotCompleted;
public string UDLRScript;
public int UDLRStartX;
public int UDLRStartY;
public bool AdminOnly;
public bool LibarySearchable;
public int IconId;
private int udlrScriptPos = 0;
public int UdlrScriptPos
{
get
{
return udlrScriptPos;
}
set
{
Database.SetNpcUdlrPointer(Id, value);
udlrScriptPos = value;
}
}
private bool canNpcBeHere(int x, int y)
{
// Horses cannot be in towns.
if (World.InTown(x, y))
return false;
if (World.InSpecialTile(x, y))
return false;
// Check Tile Type
int TileID = Map.GetTileId(x, y, false);
string TileType = Map.TerrainTiles[TileID - 1].Type;
if (TileType != this.StayOn)
return false;
if (Map.CheckPassable(x, y)) // Can the player stand over here?
return true;
return false;
}
public void RandomWander()
{
if(Moves)
{
if(UDLRStartX == 0 && UDLRStartY == 0) // not scripted.
{
if (GameServer.GetUsersAt(this.X, this.Y, true, true).Length > 0)
return;
int tries = 0;
while(true)
{
int direction = GameServer.RandomNumberGenerator.Next(0, 4);
int tryX = this.X;
int tryY = this.Y;
switch (direction)
{
case 0:
tryX += 1;
break;
case 1:
tryX -= 1;
break;
case 2:
tryY += 1;
break;
case 3:
tryY -= 1;
break;
}
if (canNpcBeHere(tryX, tryY))
{
X = tryX;
Y = tryY;
break;
}
tries++;
if (tries > 100) // yo stuck lol
{
Logger.ErrorPrint("NPC: " + this.Name + " is probably stuck (cant move after 100 tries)");
break;
}
}
}
else // Is Scripted.
{
if (GameServer.GetUsersAt(this.X, this.Y, true, true).Length > 0)
return;
if (UdlrScriptPos >= UDLRScript.Length)
{
X = UDLRStartX;
Y = UDLRStartY;
UdlrScriptPos = 0;
}
switch (UDLRScript.ToLower()[UdlrScriptPos])
{
case 'u':
Logger.DebugPrint(this.Name + " Moved up: was " + X + ", " + Y + " now: " + X + ", " + (Y + 1).ToString());
Y--;
break;
case 'd':
Logger.DebugPrint(this.Name + " Moved down: was " + X + ", " + Y + " now: " + X + ", " + (Y - 1).ToString());
Y++;
break;
case 'l':
Logger.DebugPrint(this.Name + " Moved left: was " + X + ", " + Y + " now: " + (X - 1).ToString() + ", " + Y );
X--;
break;
case 'r':
Logger.DebugPrint(this.Name + " Moved right: was " + X + ", " + Y + " now: " + (X + 1).ToString() + ", " + Y);
X++;
break;
}
UdlrScriptPos++;
}
}
}
public NpcChat[] Chatpoints;
}
private static List<NpcEntry> npcList = new List<NpcEntry>();
public static void AddNpc(NpcEntry npc)
{
npcList.Add(npc);
}
public static NpcEntry[] NpcList
{
get
{
return npcList.ToArray();
}
}
public static NpcReply GetNpcReply(NpcEntry npc, int id)
{
foreach (NpcChat chatpoint in npc.Chatpoints)
{
foreach (NpcReply reply in chatpoint.Replies)
{
if (reply.Id == id)
return reply;
}
}
throw new KeyNotFoundException("Npc reply with " + id + " not found!");
}
public static NpcReply GetNpcReply(NpcChat chatpoint, int id)
{
foreach(NpcReply reply in chatpoint.Replies)
{
if (reply.Id == id)
return reply;
}
throw new KeyNotFoundException("Npc reply with " + id + " not found!");
}
public static NpcChat GetNpcChatpoint(NpcEntry npc, int chatpointId)
{
foreach(Npc.NpcChat chatpoint in npc.Chatpoints)
{
if(chatpoint.Id == chatpointId)
{
return chatpoint;
}
}
return npc.Chatpoints[0];
}
public static int GetDefaultChatpoint(User user, NpcEntry npc)
{
if (Database.HasNpcStartpointSet(user.Id, npc.Id))
return Database.GetNpcStartPoint(user.Id, npc.Id);
else
return 0;
}
public static void SetDefaultChatpoint(User user, NpcEntry npc, int chatpointId)
{
if (Database.HasNpcStartpointSet(user.Id, npc.Id))
Database.SetNpcStartPoint(user.Id, npc.Id, chatpointId);
else
Database.AddNpcStartPoint(user.Id, npc.Id, chatpointId);
}
public static bool NpcExists(int id)
{
try
{
GetNpcById(id);
return true;
}
catch (KeyNotFoundException)
{
return false;
}
}
public static NpcEntry GetNpcById(int id)
{
foreach(NpcEntry npc in NpcList)
{
if (npc.Id == id)
return npc;
}
throw new KeyNotFoundException("Npc id: " + id + " not found!");
}
public static void WanderNpcs()
{
Logger.DebugPrint("Making NPC's randomly wander.");
foreach(NpcEntry npc in NpcList)
{
npc.RandomWander();
}
}
public static NpcEntry[] GetNpcByXAndY(int x, int y)
{
List<NpcEntry> npcs = new List<NpcEntry>();
foreach(NpcEntry npc in NpcList)
{
if (npc.X == x && npc.Y == y)
npcs.Add(npc);
}
return npcs.ToArray();
}
}
}