diff --git a/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs b/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs
new file mode 100644
index 000000000..9abf476bc
--- /dev/null
+++ b/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs
@@ -0,0 +1,42 @@
+// SampSharp
+// Copyright 2017 Tim Potze
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+using SampSharp.GameMode.World;
+using System;
+
+namespace SampSharp.GameMode.Events
+{
+ ///
+ /// Provides data for the NPC connection event.
+ ///
+ public class NPCConnectionEventArgs : EventArgs
+ {
+ ///
+ /// Initializes a new instance of the NPCConnectionEventArgs class.
+ ///
+ /// of the NPC.
+ public NPCConnectionEventArgs(BasePlayer npcBasePlayer)
+ {
+ NPCBasePlayer = npcBasePlayer;
+ }
+
+ // Not using Player here as we don't delete the object when
+ // the player fails to connect to the server.
+
+ ///
+ /// Gets the NPC's trying to connect.
+ ///
+ public BasePlayer NPCBasePlayer { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/SampSharp.GameMode/SAMP/Server.cs b/src/SampSharp.GameMode/SAMP/Server.cs
index c43726294..12f53166a 100644
--- a/src/SampSharp.GameMode/SAMP/Server.cs
+++ b/src/SampSharp.GameMode/SAMP/Server.cs
@@ -160,34 +160,24 @@ public static void SendRconCommand(string command)
}
///
- /// Connect an NPC to the server.
+ /// Connects an NPC to the server.
///
/// The name the NPC should connect as. Must follow the same rules as normal player names.
/// The NPC script name that is located in the npcmodes folder (without the .amx extension).
///
- /// An instance of based on the first available player slot. If no slots are available,
- /// null.
+ /// An instance of
///
- public static BasePlayer ConnectNPC(string name, string script)
+ public static NPC ConnectNPC(string name, string script)
{
- var id = -1;
- var max = MaxPlayers;
+ if (BasePlayer.FindByName(name) != null)
+ throw new Exception($"The name \"{name}\" is already used in game");
- for (var i = 0; i < max; i++)
- if (!ServerInternal.Instance.IsPlayerConnected(i))
- id = i;
-
- if (id == -1)
- return null;
-
- ServerInternal.Instance.ConnectNPC(name, script);
- var result = BasePlayer.FindOrCreate(id);
- result.IsNpcOverride = true;
- return result;
+ NPC npc = new NPC(name, script);
+ return npc;
}
///
- /// Set the world weather for all players.
+ /// Sets the world weather for all players.
///
/// The weather to set.
public static void SetWeather(int weatherid)
diff --git a/src/SampSharp.GameMode/World/BasePlayer.cs b/src/SampSharp.GameMode/World/BasePlayer.cs
index feaecb644..31132e90c 100644
--- a/src/SampSharp.GameMode/World/BasePlayer.cs
+++ b/src/SampSharp.GameMode/World/BasePlayer.cs
@@ -58,6 +58,26 @@ public partial class BasePlayer : IdentifiedPool, IWorldObject
/// Maximum length of the text in a chat bubble.
///
public const int MaxChatBubbleLength = 144;
+
+ ///
+ /// Finds a from the given
+ ///
+ /// The name of the BasePlayer to find
+ /// The found BasePlayer
+ public static BasePlayer FindByName(string name)
+ {
+ BasePlayer result = null;
+ for (int i = 0; i < Server.MaxPlayers; i++)
+ {
+ if (BasePlayer.Find(i) != null)
+ {
+ BasePlayer p = BasePlayer.Find(i);
+ if (p.Name.Equals(name))
+ result = p;
+ }
+ }
+ return result;
+ }
#region Constructors
diff --git a/src/SampSharp.GameMode/World/NPC.cs b/src/SampSharp.GameMode/World/NPC.cs
new file mode 100644
index 000000000..a17542798
--- /dev/null
+++ b/src/SampSharp.GameMode/World/NPC.cs
@@ -0,0 +1,75 @@
+// SampSharp
+// Copyright 2017 Tim Potze
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+using SampSharp.GameMode.Events;
+using System;
+using static SampSharp.GameMode.SAMP.Server;
+
+namespace SampSharp.GameMode.World
+{
+ ///
+ /// Represents a SA-MP NPC
+ ///
+ public class NPC
+ {
+ internal string Name { get; }
+
+ #region Constructors
+
+ ///
+ /// Initialize a new instance of the class.
+ ///
+ /// The name the NPC should connect as. Must follow the same rules as normal player names.
+ /// The NPC script name that is located in the npcmodes folder (without the .amx extension).
+ public NPC(string name, string script)
+ {
+ this.Name = name;
+ BaseMode.Instance.PlayerConnected += (p, e) => this.OnNPCConnect(p as BasePlayer);
+ ServerInternal.Instance.ConnectNPC(name, script);
+ }
+ #endregion
+
+ #region Callbacks
+
+ private void OnNPCConnect(BasePlayer p)
+ {
+ if(p.Name.Equals(Name) && p.IsNPC)
+ {
+ PlayerInstance = p;
+ Connected?.Invoke(this, new NPCConnectionEventArgs(p));
+ }
+
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// The of the NPC
+ ///
+ public BasePlayer PlayerInstance { get; set; }
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Occurs when the NPC instance has been connected
+ ///
+ public event EventHandler Connected;
+
+ #endregion
+ }
+}