diff --git a/regamedll/dlls/addons/point_command.cpp b/regamedll/dlls/addons/point_command.cpp
new file mode 100644
index 00000000..ed5279d0
--- /dev/null
+++ b/regamedll/dlls/addons/point_command.cpp
@@ -0,0 +1,90 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+*/
+
+#include "precompiled.h"
+
+void CPointBaseCommand::KeyValue(KeyValueData *pkvd)
+{
+ // add this field to the command list
+ if (m_uiCommandsCount < MAX_POINT_CMDS)
+ {
+ char command[128];
+ if (pkvd->szValue[0] != '\0' && Q_strcmp(pkvd->szValue, "-") != 0)
+ {
+ Q_snprintf(command, sizeof(command), "%s \"%s\"", pkvd->szKeyName, pkvd->szValue);
+ }
+ else
+ {
+ Q_strlcpy(command, pkvd->szKeyName);
+ }
+
+ m_iszCommands[m_uiCommandsCount++] = ALLOC_STRING(command);
+ pkvd->fHandled = TRUE;
+ return;
+ }
+
+ CPointEntity::KeyValue(pkvd);
+}
+
+LINK_ENTITY_TO_CLASS(point_clientcommand, CPointClientCommand, CCSPointClientCommand)
+
+void CPointClientCommand::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
+{
+ edict_t *pClient = nullptr;
+ if (gpGlobals->maxClients == 1)
+ {
+ pClient = INDEXENT(1);
+ }
+ else if (pActivator &&
+ pActivator->IsPlayer() &&
+ pActivator->IsNetClient() &&
+ !pActivator->IsDormant())
+ {
+ // In multiplayer, send it back to the activator
+ pClient = pActivator->edict();
+ }
+
+ if (pClient)
+ {
+ for (size_t cmd = 0; cmd < m_uiCommandsCount; cmd++) {
+ CLIENT_COMMAND(pClient, UTIL_VarArgs("%s\n", m_iszCommands[cmd].str()));
+ }
+ }
+}
+
+LINK_ENTITY_TO_CLASS(point_servercommand, CPointServerCommand, CCSPointServerCommand)
+
+void CPointServerCommand::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
+{
+ for (size_t cmd = 0; cmd < m_uiCommandsCount; cmd++) {
+ Execute(m_iszCommands[cmd]);
+ }
+}
+
+void CPointServerCommand::Execute(const char *command)
+{
+ if (!IS_DEDICATED_SERVER())
+ {
+ // potentially dangerous for untrusted maps
+ // so try to use it for passing through filtered svc_stufftext
+ CLIENT_COMMAND(INDEXENT(1), UTIL_VarArgs("%s\n", command));
+ return;
+ }
+
+ SERVER_COMMAND(UTIL_VarArgs("%s\n", command));
+}
diff --git a/regamedll/dlls/addons/point_command.h b/regamedll/dlls/addons/point_command.h
new file mode 100644
index 00000000..5690e19c
--- /dev/null
+++ b/regamedll/dlls/addons/point_command.h
@@ -0,0 +1,49 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+*/
+
+#pragma once
+
+const int MAX_POINT_CMDS = 16; // maximum number of commands a single point_[server/client]command entity may be assigned
+
+class CPointBaseCommand: public CPointEntity {
+public:
+ virtual void KeyValue(KeyValueData *pkvd);
+ virtual void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) = 0;
+
+protected:
+ size_t m_uiCommandsCount;
+ string_t m_iszCommands[MAX_POINT_CMDS];
+};
+
+// It issues commands to the client console
+class CPointClientCommand: public CPointBaseCommand {
+public:
+ virtual void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
+
+private:
+ void Execute(edict_t *pEdict, const char *command);
+};
+
+// It issues commands to the server console
+class CPointServerCommand: public CPointBaseCommand {
+public:
+ virtual void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
+
+private:
+ void Execute(const char *command);
+};
diff --git a/regamedll/extra/Toolkit/GameDefinitionFile/regamedll-cs.fgd b/regamedll/extra/Toolkit/GameDefinitionFile/regamedll-cs.fgd
index 1a2f80a0..e7c44158 100644
--- a/regamedll/extra/Toolkit/GameDefinitionFile/regamedll-cs.fgd
+++ b/regamedll/extra/Toolkit/GameDefinitionFile/regamedll-cs.fgd
@@ -3026,3 +3026,15 @@
sprite_scale(string) : "Sprite scale" : "1.0"
sprite_framerate(string) : "Sprite framerate" : "10"
]
+
+@BaseClass base(Targetname) = BaseCommand
+[
+]
+
+@PointClass base(BaseCommand) size(-8 -8 -8, 8 8 8) = point_servercommand : "It issues commands to the server console"
+[
+]
+
+@PointClass base(BaseCommand) size(-8 -8 -8, 8 8 8) = point_clientcommand : "It issues commands to the client console"
+[
+]
diff --git a/regamedll/msvc/ReGameDLL.vcxproj b/regamedll/msvc/ReGameDLL.vcxproj
index ed8f5289..350beed3 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj
+++ b/regamedll/msvc/ReGameDLL.vcxproj
@@ -24,6 +24,7 @@
+
@@ -602,6 +603,7 @@
+
diff --git a/regamedll/msvc/ReGameDLL.vcxproj.filters b/regamedll/msvc/ReGameDLL.vcxproj.filters
index 59396e9c..11d1fbea 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj.filters
+++ b/regamedll/msvc/ReGameDLL.vcxproj.filters
@@ -553,6 +553,9 @@
dlls\addons
+
+ dlls\addons
+
@@ -1047,6 +1050,9 @@
dlls\addons
+
+ dlls\addons
+
diff --git a/regamedll/public/regamedll/API/CSInterfaces.h b/regamedll/public/regamedll/API/CSInterfaces.h
index bf6c6c7b..98e9ea14 100644
--- a/regamedll/public/regamedll/API/CSInterfaces.h
+++ b/regamedll/public/regamedll/API/CSInterfaces.h
@@ -228,3 +228,6 @@ class CCSClientFog: public CCSEntity {};
class CCSTriggerSetOrigin: public CCSDelay {};
class CCSTriggerRandom: public CCSDelay {};
class CCSItemAirBox: public CCSArmoury {};
+class CCSPointBaseCommand: public CCSPointEntity {};
+class CCSPointClientCommand: public CCSPointBaseCommand {};
+class CCSPointServerCommand: public CCSPointBaseCommand {};
diff --git a/regamedll/regamedll/dlls.h b/regamedll/regamedll/dlls.h
index 60e0974d..2bef63d6 100644
--- a/regamedll/regamedll/dlls.h
+++ b/regamedll/regamedll/dlls.h
@@ -133,6 +133,7 @@ using FloatRef = float;
#include "addons/item_airbox.h"
#include "addons/trigger_setorigin.h"
#include "addons/trigger_random.h"
+#include "addons/point_command.h"
// Tutor
#include "tutor.h"