extensions/cstrike/forwards.cpp
author Drifter <drifter01620@gmail.com>
Wed Jul 31 22:11:15 2013 -0400 (2013-07-31)
changeset 3965 86dedf4462d8
parent 3754 11c89c729fac
child 4011 5f9105e3a64d
permissions -rw-r--r--
Added CS_IsValidWeaponID native and validity checks to other natives (bug 5566, r=psychonic).
     1 #include "extension.h"
     2 #include "forwards.h"
     3 #include "util_cstrike.h"
     4 
     5 bool g_pTerminateRoundDetoured = false;
     6 bool g_pCSWeaponDropDetoured = false;
     7 bool g_pIgnoreTerminateDetour = false;
     8 bool g_pIgnoreCSWeaponDropDetour = false;
     9 bool g_PriceDetoured = false;
    10 bool g_HandleBuyDetoured = false;
    11 int lastclient = -1;
    12 
    13 IForward *g_pHandleBuyForward = NULL;
    14 IForward *g_pPriceForward = NULL;
    15 IForward *g_pTerminateRoundForward = NULL;
    16 IForward *g_pCSWeaponDropForward = NULL;
    17 CDetour *DHandleBuy = NULL;
    18 CDetour *DWeaponPrice = NULL;
    19 CDetour *DTerminateRound = NULL;
    20 CDetour *DCSWeaponDrop = NULL;
    21 
    22 int weaponNameOffset = -1;
    23 
    24 #if SOURCE_ENGINE == SE_CSGO
    25 DETOUR_DECL_MEMBER2(DetourHandleBuy, int, const char *, weapon, bool, bRebuy)
    26 #else
    27 DETOUR_DECL_MEMBER1(DetourHandleBuy, int, const char *, weapon)
    28 #endif
    29 {
    30 	int client = gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(this));
    31 
    32 	lastclient = client;
    33 
    34 	cell_t result = Pl_Continue;
    35 
    36 	g_pHandleBuyForward->PushCell(client);
    37 	g_pHandleBuyForward->PushString(weapon);
    38 	g_pHandleBuyForward->Execute(&result);
    39 
    40 	if (result != Pl_Continue)
    41 	{
    42 		lastclient = -1;
    43 		return 0;
    44 	}
    45 
    46 #if SOURCE_ENGINE == SE_CSGO
    47 	int defaultprice = -1;
    48 	if (g_iPriceOffset != -1 && g_PriceDetoured)
    49 	{
    50 		defaultprice = CallPriceForwardCSGO(client, weapon);
    51 	}
    52 
    53 	int val = DETOUR_MEMBER_CALL(DetourHandleBuy)(weapon, bRebuy);
    54 #else
    55 	int val = DETOUR_MEMBER_CALL(DetourHandleBuy)(weapon);
    56 #endif
    57 
    58 
    59 #if SOURCE_ENGINE == SE_CSGO
    60 	if (defaultprice != -1)
    61 		SetWeaponPrice(weapon, defaultprice);
    62 #endif
    63 
    64 	lastclient = -1;
    65 	return val;
    66 }
    67 
    68 #if SOURCE_ENGINE != SE_CSGO
    69 DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
    70 {
    71 	int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)();
    72 
    73 	if (lastclient == -1)
    74 		return price;
    75 
    76 	const char *weapon_name = reinterpret_cast<char *>(this+weaponNameOffset);
    77 
    78 	return CallPriceForward(lastclient, weapon_name, price);
    79 }
    80 #endif
    81 
    82 DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
    83 {
    84 	if (g_pIgnoreTerminateDetour)
    85 	{
    86 		g_pIgnoreTerminateDetour = false;
    87 		DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
    88 		return;
    89 	}
    90 	float orgdelay = delay;
    91 	int orgreason = reason;
    92 
    93 	cell_t result = Pl_Continue;
    94 
    95 	g_pTerminateRoundForward->PushFloatByRef(&delay);
    96 	g_pTerminateRoundForward->PushCellByRef(&reason);
    97 	g_pTerminateRoundForward->Execute(&result);
    98 
    99 	if (result >= Pl_Handled)
   100 		return;
   101 
   102 	if (result == Pl_Changed)
   103 		return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
   104 
   105 	return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason);
   106 }
   107 
   108 DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, something, bool, toss)
   109 {
   110 	if (g_pIgnoreCSWeaponDropDetour)
   111 	{
   112 		g_pIgnoreCSWeaponDropDetour = false;
   113 		DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, something, toss);
   114 		return;
   115 	}
   116 
   117 	int client = gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(this));
   118 	int weaponIndex = gamehelpers->EntityToBCompatRef(weapon);
   119 
   120 	cell_t result = Pl_Continue;
   121 	g_pCSWeaponDropForward->PushCell(client);
   122 	g_pCSWeaponDropForward->PushCell(weaponIndex);
   123 	g_pCSWeaponDropForward->Execute(&result);
   124 
   125 
   126 	if (result == Pl_Continue)
   127 		DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, something, toss);
   128 
   129 	return;
   130 }
   131 
   132 bool CreateWeaponPriceDetour()
   133 {
   134 	if (weaponNameOffset == -1)
   135 	{
   136 		if (!g_pGameConf->GetOffset("WeaponName", &weaponNameOffset))
   137 		{
   138 			smutils->LogError(myself, "Could not find WeaponName offset - Disabled OnGetWeaponPrice forward");
   139 			return false;
   140 		}
   141 	}
   142 
   143 #if SOURCE_ENGINE == SE_CSGO
   144 	if (g_iPriceOffset == -1)
   145 	{
   146 		if (!g_pGameConf->GetOffset("WeaponPrice", &g_iPriceOffset))
   147 		{
   148 			g_iPriceOffset = -1;
   149 			g_pSM->LogError(myself, "Failed to get WeaponPrice offset - Disabled OnGetWeaponPrice forward");
   150 			return false;
   151 		}
   152 	}
   153 	if (!CreateHandleBuyDetour())
   154 	{
   155 		g_pSM->LogError(myself, "HandleCommand_Buy_Internal failed to detour, disabled OnGetWeaponPrice forward.");
   156 		return false;
   157 	}
   158 	else
   159 	{
   160 		g_PriceDetoured = true;
   161 		return true;
   162 	}
   163 #else
   164 
   165 	DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, "GetWeaponPrice");
   166 
   167 	if (DWeaponPrice != NULL)
   168 	{
   169 		if (!CreateHandleBuyDetour())
   170 		{
   171 			g_pSM->LogError(myself, "GetWeaponPrice detour could not be initialized - HandleCommand_Buy_Internal failed to detour, disabled OnGetWeaponPrice forward.");
   172 			return false;
   173 		}
   174 		DWeaponPrice->EnableDetour();
   175 		g_PriceDetoured = true;
   176 		return true;
   177 	}
   178 
   179 	g_pSM->LogError(myself, "GetWeaponPrice detour could not be initialized - Disabled OnGetWeaponPrice forward.");
   180 
   181 	return false;
   182 #endif
   183 }
   184 
   185 bool CreateTerminateRoundDetour()
   186 {
   187 	DTerminateRound = DETOUR_CREATE_MEMBER(DetourTerminateRound, "TerminateRound");
   188 
   189 	if (DTerminateRound != NULL)
   190 	{
   191 		DTerminateRound->EnableDetour();
   192 		g_pTerminateRoundDetoured = true;
   193 		return true;
   194 	}
   195 	g_pSM->LogError(myself, "TerminateRound detour could not be initialized - Disabled OnTerminateRound forward");
   196 	return false;
   197 }
   198 
   199 bool CreateHandleBuyDetour()
   200 {
   201 	if (g_HandleBuyDetoured)
   202 		return true;
   203 
   204 	DHandleBuy = DETOUR_CREATE_MEMBER(DetourHandleBuy, "HandleCommand_Buy_Internal");
   205 
   206 	if (DHandleBuy != NULL)
   207 	{
   208 		DHandleBuy->EnableDetour();
   209 		g_HandleBuyDetoured = true;
   210 		return true;
   211 	}
   212 	g_pSM->LogError(myself, "HandleCommand_Buy_Internal detour could not be initialized - Disabled OnBuyCommand forward");
   213 	return false;
   214 }
   215 
   216 bool CreateCSWeaponDropDetour()
   217 {
   218 	DCSWeaponDrop = DETOUR_CREATE_MEMBER(DetourCSWeaponDrop, "CSWeaponDrop");
   219 
   220 	if (DCSWeaponDrop != NULL)
   221 	{
   222 		DCSWeaponDrop->EnableDetour();
   223 		g_pCSWeaponDropDetoured = true;
   224 		return true;
   225 	}
   226 
   227 	g_pSM->LogError(myself, "CSWeaponDrop detour could not be initialized - Disabled OnCSWeaponDrop forward");
   228 	return false;
   229 }
   230 
   231 void RemoveWeaponPriceDetour()	
   232 {
   233 #if SOURCE_ENGINE != SE_CSGO
   234 	if (DWeaponPrice != NULL)
   235 	{
   236 		DWeaponPrice->Destroy();
   237 		DWeaponPrice = NULL;
   238 	}
   239 	g_PriceDetoured = false;
   240 #endif
   241 }
   242 
   243 void RemoveHandleBuyDetour()	
   244 {
   245 	if (g_PriceDetoured)
   246 		return;
   247 
   248 	if (DHandleBuy != NULL)
   249 	{
   250 		DHandleBuy->Destroy();
   251 		DHandleBuy = NULL;
   252 	}
   253 	g_HandleBuyDetoured = false;
   254 }
   255 
   256 void RemoveTerminateRoundDetour()	
   257 {
   258 	if (DTerminateRound != NULL)
   259 	{
   260 		DTerminateRound->Destroy();
   261 		DTerminateRound = NULL;
   262 	}
   263 	g_pTerminateRoundDetoured = false;
   264 }
   265 
   266 void RemoveCSWeaponDropDetour()	
   267 {
   268 	if (DCSWeaponDrop != NULL)
   269 	{
   270 		DCSWeaponDrop->Destroy();
   271 		DCSWeaponDrop = NULL;
   272 	}
   273 	g_pCSWeaponDropDetoured = false;
   274 }
   275 
   276 #if SOURCE_ENGINE == SE_CSGO
   277 bool SetWeaponPrice(int weaponID, int price)
   278 {
   279 	void *info = GetWeaponInfo(weaponID);
   280 	if (!info)
   281 	{
   282 		return false;
   283 	}
   284 	*(int *)((intptr_t)info+g_iPriceOffset) = price;
   285 	return true;
   286 }
   287 
   288 bool SetWeaponPrice(const char *weapon, int price)
   289 {
   290 	const char *weaponalias = GetTranslatedWeaponAlias(weapon);
   291 	int weaponID = AliasToWeaponID(weaponalias);
   292 	if (weaponID <= 0)
   293 	{
   294 		return false;
   295 	}
   296 	void *info = GetWeaponInfo(weaponID);
   297 	if (!info)
   298 	{
   299 		return false;
   300 	}
   301 	*(int *)((intptr_t)info+g_iPriceOffset) = price;
   302 	return true;
   303 
   304 }
   305 
   306 int CallPriceForwardCSGO(int client, const char *weapon, int price)
   307 {
   308 	int changedprice = price;
   309 	cell_t result = Pl_Continue;
   310 
   311 	g_pPriceForward->PushCell(client);
   312 	g_pPriceForward->PushString(weapon);
   313 	g_pPriceForward->PushCellByRef(&changedprice);
   314 	g_pPriceForward->Execute(&result);
   315 	
   316 	if (result == Pl_Continue)
   317 		return price;
   318 
   319 	return changedprice;
   320 }
   321 
   322 int CallPriceForwardCSGO(int client, const char *weapon)
   323 {
   324 	const char *weaponalias = GetTranslatedWeaponAlias(weapon);
   325 	int weaponID = AliasToWeaponID(weaponalias);
   326 	if (weaponID <= 0)
   327 	{
   328 		return -1;
   329 	}
   330 	void *info = GetWeaponInfo(weaponID);
   331 	if (!info)
   332 	{
   333 		return -1;
   334 	}
   335 	const char *weapon_name = (const char *)((intptr_t)info + weaponNameOffset);
   336 	int price = *(int *)((intptr_t)info + g_iPriceOffset);
   337 	int changedprice = price;
   338 	cell_t result = Pl_Continue;
   339 
   340 	g_pPriceForward->PushCell(client);
   341 	g_pPriceForward->PushString(weapon_name);
   342 	g_pPriceForward->PushCellByRef(&changedprice);
   343 	g_pPriceForward->Execute(&result);
   344 		
   345 	if (result == Pl_Continue)
   346 		return -1;
   347 	if (SetWeaponPrice(weaponID, changedprice))
   348 		return price;
   349 	else
   350 		return -1;
   351 }
   352 #else
   353 
   354 int CallPriceForward(int client, const char *weapon_name, int price)
   355 {
   356 	int changedprice = price;
   357 
   358 	cell_t result = Pl_Continue;
   359 
   360 	g_pPriceForward->PushCell(client);
   361 	g_pPriceForward->PushString(weapon_name);
   362 	g_pPriceForward->PushCellByRef(&changedprice);
   363 	g_pPriceForward->Execute(&result);
   364 	
   365 	if (result == Pl_Continue)
   366 		return price;
   367 
   368 	return changedprice;
   369 }
   370 #endif