diff --git a/extensions/tf2/AMBuilder b/extensions/tf2/AMBuilder
index 40d1891ad..e68d3a549 100644
--- a/extensions/tf2/AMBuilder
+++ b/extensions/tf2/AMBuilder
@@ -17,6 +17,7 @@ binary.AddSourceFiles('extensions/tf2', [
'util.cpp',
'criticals.cpp',
'holiday.cpp',
+ 'teleporter.cpp',
'gameplayrules.cpp',
'conditions.cpp',
'CDetour/detours.cpp',
diff --git a/extensions/tf2/Makefile b/extensions/tf2/Makefile
index 80d80cf2f..3d4fc4585 100644
--- a/extensions/tf2/Makefile
+++ b/extensions/tf2/Makefile
@@ -19,7 +19,7 @@ PROJECT = game.tf2
USEMETA = true
OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp criticals.cpp \
- holiday.cpp gameplayrules.cpp conditions.cpp util.cpp CDetour/detours.cpp asm/asm.c
+ holiday.cpp gameplayrules.cpp conditions.cpp util.cpp teleporter.cpp CDetour/detours.cpp asm/asm.c
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
diff --git a/extensions/tf2/extension.cpp b/extensions/tf2/extension.cpp
index e38d9176d..3473d4aba 100644
--- a/extensions/tf2/extension.cpp
+++ b/extensions/tf2/extension.cpp
@@ -39,6 +39,7 @@
#include "holiday.h"
#include "conditions.h"
#include "gameplayrules.h"
+#include "teleporter.h"
#include "CDetour/detours.h"
/**
@@ -117,6 +118,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
g_removeCondForward = forwards->CreateForward("TF2_OnConditionRemoved", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
g_waitingPlayersStartForward = forwards->CreateForward("TF2_OnWaitingForPlayersStart", ET_Ignore, 0, NULL);
g_waitingPlayersEndForward = forwards->CreateForward("TF2_OnWaitingForPlayersEnd", ET_Ignore, 0, NULL);
+ g_teleportForward = forwards->CreateForward("TF2_OnPlayerTeleport", ET_Hook, 3, NULL, Param_Cell, Param_Cell, Param_CellByRef);
g_pCVar = icvar;
@@ -124,6 +126,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
m_IsHolidayDetourEnabled = false;
m_CondChecksEnabled = false;
m_RulesDetoursEnabled = false;
+ m_TeleportDetourEnabled = false;
return true;
}
@@ -173,6 +176,7 @@ void TF2Tools::SDK_OnUnload()
forwards->ReleaseForward(g_removeCondForward);
forwards->ReleaseForward(g_waitingPlayersStartForward);
forwards->ReleaseForward(g_waitingPlayersEndForward);
+ forwards->ReleaseForward(g_teleportForward);
}
void TF2Tools::SDK_OnAllLoaded()
@@ -338,6 +342,11 @@ void TF2Tools::OnPluginLoaded(IPlugin *plugin)
{
m_RulesDetoursEnabled = InitialiseRulesDetours();
}
+
+ if (!m_TeleportDetourEnabled && g_teleportForward->GetFunctionCount())
+ {
+ m_TeleportDetourEnabled = InitialiseTeleporterDetour();
+ }
}
void TF2Tools::OnPluginUnloaded(IPlugin *plugin)
@@ -368,6 +377,11 @@ void TF2Tools::OnPluginUnloaded(IPlugin *plugin)
m_RulesDetoursEnabled = false;
}
}
+ if (m_TeleportDetourEnabled && !g_teleportForward->GetFunctionCount())
+ {
+ RemoveTeleporterDetour();
+ m_TeleportDetourEnabled = false;
+ }
}
void TF2Tools::OnClientPutInServer(int client)
diff --git a/extensions/tf2/extension.h b/extensions/tf2/extension.h
index 711877336..4fefd35ba 100644
--- a/extensions/tf2/extension.h
+++ b/extensions/tf2/extension.h
@@ -121,6 +121,7 @@ private:
bool m_IsHolidayDetourEnabled;
bool m_CondChecksEnabled;
bool m_RulesDetoursEnabled;
+ bool m_TeleportDetourEnabled;
};
enum TFClassType
diff --git a/extensions/tf2/msvc10/tf2.vcxproj b/extensions/tf2/msvc10/tf2.vcxproj
index 40ca0dc4b..600742e13 100644
--- a/extensions/tf2/msvc10/tf2.vcxproj
+++ b/extensions/tf2/msvc10/tf2.vcxproj
@@ -114,6 +114,7 @@
+
@@ -126,6 +127,7 @@
+
diff --git a/extensions/tf2/msvc10/tf2.vcxproj.filters b/extensions/tf2/msvc10/tf2.vcxproj.filters
index b3c7ce85e..464dbac17 100644
--- a/extensions/tf2/msvc10/tf2.vcxproj.filters
+++ b/extensions/tf2/msvc10/tf2.vcxproj.filters
@@ -57,6 +57,9 @@
asm
+
+ Source Files
+
@@ -95,5 +98,8 @@
asm
+
+ Header Files
+
\ No newline at end of file
diff --git a/extensions/tf2/msvc9/tf2.vcproj b/extensions/tf2/msvc9/tf2.vcproj
index 6c723002b..636519332 100644
--- a/extensions/tf2/msvc9/tf2.vcproj
+++ b/extensions/tf2/msvc9/tf2.vcproj
@@ -215,6 +215,10 @@
RelativePath="..\RegNatives.cpp"
>
+
+
@@ -249,6 +253,10 @@
RelativePath="..\RegNatives.h"
>
+
+
diff --git a/extensions/tf2/teleporter.cpp b/extensions/tf2/teleporter.cpp
new file mode 100644
index 000000000..6a308a147
--- /dev/null
+++ b/extensions/tf2/teleporter.cpp
@@ -0,0 +1,96 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod Team Fortress 2 Extension
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * 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, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include "teleporter.h"
+
+CDetour *canPlayerTeleportDetour = NULL;
+
+IForward *g_teleportForward = NULL;
+
+class CTFPlayer;
+
+DETOUR_DECL_MEMBER1(CanPlayerBeTeleported, bool, CTFPlayer *, pPlayer)
+{
+ bool origCanTeleport = DETOUR_MEMBER_CALL(CanPlayerBeTeleported)(pPlayer);
+
+ cell_t teleporterCell = gamehelpers->EntityToBCompatRef((CBaseEntity *)this);
+ cell_t playerCell = gamehelpers->EntityToBCompatRef((CBaseEntity *)pPlayer);
+
+ if (!g_teleportForward)
+ {
+ g_pSM->LogMessage(myself, "Teleport forward is invalid");
+ return origCanTeleport;
+ }
+
+ cell_t returnValue = origCanTeleport ? 1 : 0;
+
+ g_teleportForward->PushCell(playerCell); // client
+ g_teleportForward->PushCell(teleporterCell); // teleporter
+ g_teleportForward->PushCellByRef(&returnValue); // return value
+
+ cell_t result = 0;
+
+ g_teleportForward->Execute(&result);
+
+ if (result > Pl_Continue)
+ {
+ // plugin wants to override the game (returned something other than Plugin_Continue)
+ return returnValue == 1;
+ }
+ else
+ {
+ return origCanTeleport; // let the game decide
+ }
+}
+
+bool InitialiseTeleporterDetour()
+{
+ canPlayerTeleportDetour = DETOUR_CREATE_MEMBER(CanPlayerBeTeleported, "CanPlayerTeleport");
+
+ if (canPlayerTeleportDetour != NULL)
+ {
+ canPlayerTeleportDetour->EnableDetour();
+ return true;
+ }
+
+ g_pSM->LogError(myself, "Teleport forward could not be initialized - Disabled hook");
+
+ return false;
+}
+
+void RemoveTeleporterDetour()
+{
+ if (canPlayerTeleportDetour != NULL)
+ {
+ canPlayerTeleportDetour->Destroy();
+ canPlayerTeleportDetour = NULL;
+ }
+}
diff --git a/extensions/tf2/teleporter.h b/extensions/tf2/teleporter.h
new file mode 100644
index 000000000..ae28037f1
--- /dev/null
+++ b/extensions/tf2/teleporter.h
@@ -0,0 +1,43 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod Team Fortress 2 Extension
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * 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, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#ifndef _INCLUDE_SOURCEMOD_TELEPORTER_H_
+#define _INCLUDE_SOURCEMOD_TELEPORTER_H_
+
+#include "extension.h"
+#include "CDetour/detours.h"
+
+bool InitialiseTeleporterDetour();
+void RemoveTeleporterDetour();
+
+extern IForward *g_teleportForward;
+
+#endif //_INCLUDE_SOURCEMOD_TELEPORTER_H_
diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt
index 1273d37da..d68d9b3f0 100644
--- a/gamedata/sm-tf2.games.txt
+++ b/gamedata/sm-tf2.games.txt
@@ -120,6 +120,13 @@
"linux" "@_Z21DuelMiniGame_IsInDuelP9CTFPlayer"
"mac" "@_Z21DuelMiniGame_IsInDuelP9CTFPlayer"
}
+ "CanPlayerTeleport"
+ {
+ "library" "server"
+ "windows" "\x55\x8b\xec\x53\x8b\x5d\x08\x85\xdb\x56\x8b\xf1\x74\x2A\x8b\xcb\xe8\x2A\x2A\x2A\x2A\x84\xc0"
+ "linux" "@_ZN17CObjectTeleporter21PlayerCanBeTeleportedEP9CTFPlayer"
+ "mac" "@_ZN17CObjectTeleporter21PlayerCanBeTeleportedEP9CTFPlayer"
+ }
}
"Offsets"
{
diff --git a/plugins/include/tf2.inc b/plugins/include/tf2.inc
index 6017c09e0..cc7d6baac 100644
--- a/plugins/include/tf2.inc
+++ b/plugins/include/tf2.inc
@@ -339,6 +339,19 @@ forward TF2_OnWaitingForPlayersStart();
*/
forward TF2_OnWaitingForPlayersEnd();
+/**
+ * Called when a player attempts to use a teleporter to decide if the player should be allowed to teleport.
+ * Return Plugin_Continue to let the original calculation or return a higher
+ * action to override the decision with the value of 'result'
+ *
+ * @param client Client index.
+ * @param teleporter Teleporter entity index.
+ * @param result Buffer param for the result of the decision.
+ * This is prepopulated with the game's original decision to let a player teleport.
+ * @return Plugin_Continue for original calculation, higher value to use 'result'.
+ */
+forward Action:TF2_OnPlayerTeleport(client, teleporter, &bool:result);
+
/**
* Do not edit below this line!
*/