cssdm_utils.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Wed Oct 01 11:50:24 2014 -0400 (2014-10-01)
changeset 193 277c856152b0
parent 139 df5cbb604269
permissions -rw-r--r--
Update linix CS:GO gamedata
[email protected]
     1
/**
[email protected]
     2
 * vim: set ts=4 :
[email protected]
     3
 * ===============================================================
[email protected]
     4
 * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. 
[email protected]
     5
 * By David "BAILOPAN" Anderson
[email protected]
     6
 * All rights reserved.
[email protected]
     7
 * ===============================================================
[email protected]
     8
 *
[email protected]
     9
 * This program is free software; you can redistribute it and/or modify
[email protected]
    10
 * it under the terms of the GNU General Public License as published by
[email protected]
    11
 * the Free Software Foundation; either version 2 of the License, or (at
[email protected]
    12
 * your option) any later version.
[email protected]
    13
 * 
[email protected]
    14
 * This program is distributed in the hope that it will be useful, but
[email protected]
    15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
[email protected]
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
[email protected]
    17
 * General Public License for more details.
[email protected]
    18
 * 
[email protected]
    19
 * You should have received a copy of the GNU General Public License
[email protected]
    20
 * along with this program; see the file COPYING; if not, write to the
[email protected]
    21
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
[email protected]
    22
 * MA 02110-1301 USA
[email protected]
    23
 * 
[email protected]
    24
 * Version: $Id$
[email protected]
    25
 */
[email protected]
    26
[email protected]
    27
#include "cssdm_headers.h"
[email protected]
    28
#include "cssdm_players.h"
[email protected]
    29
#include "cssdm_utils.h"
[email protected]
    30
#include "cssdm_includesdk.h"
[email protected]
    31
#include <sh_list.h>
[email protected]
    32
#include <sh_memory.h>
[email protected]
    33
[email protected]
    34
using namespace SourceHook;
[email protected]
    35
[email protected]
    36
List<ICallWrapper *> g_CallWrappers;
[email protected]
    37
ICallWrapper *g_pRoundRespawn = NULL;
[email protected]
    38
ICallWrapper *g_pWeaponGetSlot = NULL;
[email protected]
    39
ICallWrapper *g_pDropWeapon = NULL;
[email protected]
    40
ICallWrapper *g_pRemoveAllItems = NULL;
[email protected]
    41
ICallWrapper *g_pGiveAmmo = NULL;
[email protected]
    42
int g_RagdollOffset = 0;
[email protected]
    43
int g_LifeStateOffset = 0;
[email protected]
    44
int g_DefuserOffset = 0;
[email protected]
    45
[email protected]
    46
void DM_ProtectMemory(void *addr, int length, int prot);
[email protected]
    47
[email protected]
    48
CBaseEntity *DM_GetBaseEntity(int index)
[email protected]
    49
{
[email protected]
    50
	edict_t *pEdict = gamehelpers->EdictOfIndex(index);
[email protected]
    51
	if (!pEdict || pEdict->IsFree())
[email protected]
    52
	{
[email protected]
    53
		return NULL;
[email protected]
    54
	}
[email protected]
    55
	IServerUnknown *pUnknown = pEdict->GetUnknown();
[email protected]
    56
	if (!pUnknown)
[email protected]
    57
	{
[email protected]
    58
		return NULL;
[email protected]
    59
	}
[email protected]
    60
	return pUnknown->GetBaseEntity();
[email protected]
    61
}
[email protected]
    62
[email protected]
    63
CBaseEntity *DM_GetAndClearRagdoll(CBaseEntity *pEntity, int &serial)
[email protected]
    64
{
[email protected]
    65
	if (!g_RagdollOffset)
[email protected]
    66
	{
[email protected]
    67
		return NULL;
[email protected]
    68
	}
[email protected]
    69
[email protected]
    70
	unsigned char *ptr = (unsigned char *)pEntity + g_RagdollOffset;
[email protected]
    71
	CBaseHandle &ph = *(CBaseHandle *)ptr;
[email protected]
    72
[email protected]
    73
	if (!ph.IsValid())
[email protected]
    74
	{
[email protected]
    75
		return NULL;
[email protected]
    76
	}
[email protected]
    77
[email protected]
    78
	int index = ph.GetEntryIndex();
[email protected]
    79
	serial = ph.GetSerialNumber();
[email protected]
    80
[email protected]
    81
	if (!index)
[email protected]
    82
	{
[email protected]
    83
		return NULL;
[email protected]
    84
	}
[email protected]
    85
[email protected]
    86
	CBaseEntity *pRagdoll = DM_GetBaseEntity(index);
[email protected]
    87
[email protected]
    88
	ph.Set(NULL);
[email protected]
    89
[email protected]
    90
	return pRagdoll;
[email protected]
    91
}
[email protected]
    92
[email protected]
    93
void DM_RespawnPlayer(int client)
[email protected]
    94
{
[email protected]
    95
	dm_player_t *player = DM_GetPlayer(client);
[email protected]
    96
	if (!player || !player->pEntity)
[email protected]
    97
	{
[email protected]
    98
		return;
[email protected]
    99
	}
[email protected]
   100
[email protected]
   101
	if (player->respawn_timer)
[email protected]
   102
	{
[email protected]
   103
		timersys->KillTimer(player->respawn_timer);
[email protected]
   104
		player->respawn_timer = NULL;
[email protected]
   105
	}
[email protected]
   106
[email protected]
   107
	CBaseEntity *pEntity = player->pEntity;
[email protected]
   108
	g_pRoundRespawn->Execute(&pEntity, NULL);
[email protected]
   109
}
[email protected]
   110
[email protected]
   111
class variant_t
[email protected]
   112
{
[email protected]
   113
public:
[email protected]
   114
	union
[email protected]
   115
	{
[email protected]
   116
		bool bVal;
[email protected]
   117
		string_t iszVal;
[email protected]
   118
		int iVal;
[email protected]
   119
		float flVal;
[email protected]
   120
		float vecVal[3];
[email protected]
   121
		color32 rgbaVal;
[email protected]
   122
	};
[email protected]
   123
	CBaseHandle eVal; // this can't be in the union because it has a constructor.
[email protected]
   124
	fieldtype_t fieldType;
[email protected]
   125
};
[email protected]
   126
[email protected]
   127
struct inputdata_t
[email protected]
   128
{
[email protected]
   129
	CBaseEntity *pActivator;		// The entity that initially caused this chain of output events.
[email protected]
   130
	CBaseEntity *pCaller;			// The entity that fired this particular output.
[email protected]
   131
	variant_t value;				// The data parameter for this output.
[email protected]
   132
	int nOutputID;					// The unique ID of the output that was fired.
[email protected]
   133
};
[email protected]
   134
[email protected]
   135
void DM_RemoveEntity(CBaseEntity *pEntity)
[email protected]
   136
{
[email protected]
   137
	datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
[email protected]
   138
[email protected]
   139
	if(!pMap)
[email protected]
   140
		return;
[email protected]
   141
[email protected]
   142
	typedescription_t *pDesc = gamehelpers->FindInDataMap(pMap, "InputKill");
[email protected]
   143
[email protected]
   144
	if(!pDesc)
[email protected]
   145
		return;
[email protected]
   146
[email protected]
   147
	inputdata_t data;
[email protected]
   148
	(pEntity->*pDesc->inputFunc)(data);
[email protected]
   149
}
[email protected]
   150
[email protected]
   151
bool DM_IsPlayerAlive(int client)
[email protected]
   152
{
[email protected]
   153
	dm_player_t *player = DM_GetPlayer(client);
[email protected]
   154
	if (!player || !player->pEntity || !g_LifeStateOffset)
[email protected]
   155
	{
[email protected]
   156
		return false;
[email protected]
   157
	}
[email protected]
   158
[email protected]
   159
	if (!g_LifeStateOffset)
[email protected]
   160
	{
[email protected]
   161
		return player->pInfo->IsDead() ? false : true;
[email protected]
   162
	}
[email protected]
   163
[email protected]
   164
	unsigned char *ptr = (unsigned char *)(player->pEntity) + g_LifeStateOffset;
[email protected]
   165
	return (*(char *)ptr == LIFE_ALIVE);
[email protected]
   166
}
[email protected]
   167
[email protected]
   168
bool DM_CheckSerial(edict_t *pEdict, int serial)
[email protected]
   169
{
[email protected]
   170
	int new_serial = (serial & ((1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1));
[email protected]
   171
	return (pEdict->m_NetworkSerialNumber == new_serial);
[email protected]
   172
}
[email protected]
   173
[email protected]
   174
CBaseEntity *DM_GetWeaponFromSlot(CBaseEntity *pEntity, int slot)
[email protected]
   175
{
[email protected]
   176
	unsigned char vstk[sizeof(CBaseEntity *) + sizeof(int)];
[email protected]
   177
	*(CBaseEntity **)(&vstk[0]) = pEntity;
[email protected]
   178
	*(int *)(&vstk[sizeof(CBaseEntity *)]) = slot;
[email protected]
   179
[email protected]
   180
	CBaseEntity *pWeapon = NULL;
[email protected]
   181
[email protected]
   182
	g_pWeaponGetSlot->Execute(vstk, &pWeapon);
[email protected]
   183
[email protected]
   184
	return pWeapon;
[email protected]
   185
}
[email protected]
   186
[email protected]
   187
void DM_DropWeapon(CBaseEntity *pEntity, CBaseEntity *pWeapon)
[email protected]
   188
{
[email protected]
   189
	unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool) * 2];
[email protected]
   190
	unsigned char *vptr = vstk;
[email protected]
   191
[email protected]
   192
	*(CBaseEntity **)vptr = pEntity;
[email protected]
   193
	vptr += sizeof(CBaseEntity *);
[email protected]
   194
	*(CBaseEntity **)vptr = pWeapon;
[email protected]
   195
	vptr += sizeof(CBaseEntity *);
[email protected]
   196
	*(bool *)vptr = true;
[email protected]
   197
	vptr += sizeof(bool);
[email protected]
   198
	*(bool *)vptr = false;
[email protected]
   199
	//vptr += sizeof(bool);
[email protected]
   200
[email protected]
   201
	g_pDropWeapon->Execute(vstk, NULL);
[email protected]
   202
}
[email protected]
   203
[email protected]
   204
void DM_RemoveAllItems(CBaseEntity *pEntity, bool removeSuit)
[email protected]
   205
{
[email protected]
   206
	unsigned char vstk[sizeof(CBaseEntity *) + sizeof(bool)];
[email protected]
   207
	unsigned char *vptr = vstk;
[email protected]
   208
[email protected]
   209
	*(CBaseEntity **)vptr = pEntity;
[email protected]
   210
	vptr += sizeof(CBaseEntity *);
[email protected]
   211
	*(bool *)vptr = removeSuit;
[email protected]
   212
	//vptr += sizeof(bool);
[email protected]
   213
[email protected]
   214
	g_pRemoveAllItems->Execute(vstk, NULL);
[email protected]
   215
}
[email protected]
   216
[email protected]
   217
void DM_SetDefuseKit(CBaseEntity *pEntity, bool defuseKit)
[email protected]
   218
{
[email protected]
   219
	if (!g_DefuserOffset)
[email protected]
   220
	{
[email protected]
   221
		return;
[email protected]
   222
	}
[email protected]
   223
[email protected]
   224
	*(bool *)((unsigned char *)pEntity + g_DefuserOffset) = defuseKit;
[email protected]
   225
}
[email protected]
   226
[email protected]
   227
int DM_GiveAmmo(CBaseEntity *pEntity, int type, int count, bool noSound)
[email protected]
   228
{
[email protected]
   229
	unsigned char vstk[sizeof(CBaseEntity *) + sizeof(int)*2 + sizeof(bool)];
[email protected]
   230
	unsigned char *vptr = vstk;
[email protected]
   231
[email protected]
   232
	*(CBaseEntity **)vptr = pEntity;
[email protected]
   233
	vptr += sizeof(CBaseEntity *);
[email protected]
   234
	*(int *)vptr = count;
[email protected]
   235
	vptr += sizeof(int);
[email protected]
   236
	*(int *)vptr = type;
[email protected]
   237
	vptr += sizeof(int);
[email protected]
   238
	*(bool *)vptr = noSound;
[email protected]
   239
	//vptr += sizeof(bool);
[email protected]
   240
[email protected]
   241
	int ret;
[email protected]
   242
	g_pGiveAmmo->Execute(vstk, &ret);
[email protected]
   243
[email protected]
   244
	return ret;
[email protected]
   245
}
[email protected]
   246
[email protected]
   247
size_t DM_StringToBytes(const char *str, unsigned char buffer[], size_t maxlength)
[email protected]
   248
{
[email protected]
   249
	size_t real_bytes = 0;
[email protected]
   250
	size_t length = strlen(str);
[email protected]
   251
[email protected]
   252
	for (size_t i=0; i<length; i++)
[email protected]
   253
	{
[email protected]
   254
		if (real_bytes >= maxlength)
[email protected]
   255
		{
[email protected]
   256
			break;
[email protected]
   257
		}
[email protected]
   258
		buffer[real_bytes++] = (unsigned char)str[i];
[email protected]
   259
		if (str[i] == '\\'
[email protected]
   260
			&& str[i+1] == 'x')
[email protected]
   261
		{
[email protected]
   262
			if (i + 3 >= length)
[email protected]
   263
			{
[email protected]
   264
				continue;
[email protected]
   265
			}
[email protected]
   266
			/* Get the hex part */
[email protected]
   267
			char s_byte[3];
[email protected]
   268
			int r_byte;
[email protected]
   269
			s_byte[0] = str[i+2];
[email protected]
   270
			s_byte[1] = str[i+3];
[email protected]
   271
			s_byte[2] = '\n';
[email protected]
   272
			/* Read it as an integer */
[email protected]
   273
			sscanf(s_byte, "%x", &r_byte);
[email protected]
   274
			/* Save the value */
[email protected]
   275
			buffer[real_bytes-1] = (unsigned char)r_byte;
[email protected]
   276
			/* Adjust index */
[email protected]
   277
			i += 3;
[email protected]
   278
		}
[email protected]
   279
	}
[email protected]
   280
[email protected]
   281
	return real_bytes;
[email protected]
   282
}
[email protected]
   283
[email protected]
   284
void DM_ApplyPatch(void *address, int offset, const dmpatch_t *patch, dmpatch_t *restore)
[email protected]
   285
{
[email protected]
   286
	unsigned char *addr = (unsigned char *)address + offset;
[email protected]
   287
[email protected]
   288
	SourceHook::SetMemAccess(addr, 20, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
[email protected]
   289
[email protected]
   290
	if (restore)
[email protected]
   291
	{
[email protected]
   292
		for (size_t i=0; i<patch->bytes; i++)
[email protected]
   293
		{
[email protected]
   294
			restore->patch[i] = addr[i];
[email protected]
   295
		}
[email protected]
   296
		restore->bytes = patch->bytes;
[email protected]
   297
	}
[email protected]
   298
[email protected]
   299
	for (size_t i=0; i<patch->bytes; i++)
[email protected]
   300
	{
[email protected]
   301
		addr[i] = patch->patch[i];
[email protected]
   302
	}
[email protected]
   303
}
[email protected]
   304
[email protected]
   305
void DM_SetMemPatchable(void *address, size_t size)
[email protected]
   306
{
[email protected]
   307
	SourceHook::SetMemAccess(address, (int)size, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
[email protected]
   308
}
[email protected]
   309
[email protected]
   310
#define GET_PROPERTY(cls, name, var) \
[email protected]
   311
	if ( (prop = gamehelpers->FindInSendTable(cls, name)) == NULL ) { \
[email protected]
   312
		snprintf(error, maxlength, "Could not find property: %s", name); \
[email protected]
   313
		return false; \
[email protected]
   314
	} \
[email protected]
   315
	var = prop->GetOffset();
[email protected]
   316
[email protected]
   317
bool InitializeUtils(char *error, size_t maxlength)
[email protected]
   318
{
[email protected]
   319
	void *addr;
[email protected]
   320
	int offset;
[email protected]
   321
	SourceMod::PassInfo pass[4];
[email protected]
   322
[email protected]
   323
	/** ROUNDRESPAWN */
[email protected]
   324
	g_pDmConf->GetMemSig("RoundRespawn", &addr);
[email protected]
   325
	g_pRoundRespawn = bintools->CreateCall(addr, CallConv_ThisCall, NULL, NULL, 0);
[email protected]
   326
	g_CallWrappers.push_back(g_pRoundRespawn);
[email protected]
   327
	
[email protected]
   328
	/** WEAPON_GETSLOT */
[email protected]
   329
	g_pDmConf->GetOffset("Weapon_GetSlot", &offset);
[email protected]
   330
	pass[0].flags = PASSFLAG_BYVAL;
[email protected]
   331
	pass[0].size = sizeof(int);
[email protected]
   332
	pass[0].type = PassType_Basic;
[email protected]
   333
	pass[1].flags = PASSFLAG_BYVAL;
[email protected]
   334
	pass[1].size = sizeof(CBaseEntity *);
[email protected]
   335
	pass[1].type = PassType_Basic;
[email protected]
   336
	g_pWeaponGetSlot = bintools->CreateVCall(offset, 0, 0, &pass[1], &pass[0], 1);
[email protected]
   337
	g_CallWrappers.push_back(g_pWeaponGetSlot);
[email protected]
   338
[email protected]
   339
	/** CSWEAPONDROP */
[email protected]
   340
	g_pDmConf->GetMemSig("CSWeaponDrop", &addr);
[email protected]
   341
	pass[0].flags = pass[1].flags = pass[2].flags  = PASSFLAG_BYVAL;
[email protected]
   342
	pass[0].type = pass[1].type = pass[2].type = PassType_Basic;
[email protected]
   343
	pass[0].size = sizeof(CBaseEntity *);
[email protected]
   344
	pass[1].size = pass[2].size = sizeof(bool);
[email protected]
   345
	g_pDropWeapon = bintools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 3);
[email protected]
   346
	g_CallWrappers.push_back(g_pDropWeapon);
[email protected]
   347
[email protected]
   348
	/** REMOVEALLITEMS */
[email protected]
   349
	g_pDmConf->GetOffset("RemoveAllItems", &offset);
[email protected]
   350
	pass[0].flags = PASSFLAG_BYVAL;
[email protected]
   351
	pass[0].size = sizeof(bool);
[email protected]
   352
	pass[0].type = PassType_Basic;
[email protected]
   353
	g_pRemoveAllItems = bintools->CreateVCall(offset, 0, 0, NULL, pass, 1);
[email protected]
   354
	g_CallWrappers.push_back(g_pRemoveAllItems);
[email protected]
   355
[email protected]
   356
	/** GIVEAMMO */
[email protected]
   357
	g_pDmConf->GetOffset("GiveAmmo", &offset);
[email protected]
   358
	pass[0].flags = pass[1].flags = pass[2].flags = pass[3].flags = PASSFLAG_BYVAL;
[email protected]
   359
	pass[0].size = pass[1].size = pass[2].size = sizeof(int);
[email protected]
   360
	pass[3].size = sizeof(bool);
[email protected]
   361
	pass[0].type = pass[1].type = pass[2].type = pass[3].type = PassType_Basic;
[email protected]
   362
	g_pGiveAmmo = bintools->CreateVCall(offset, 0, 0, &pass[3], pass, 3);
[email protected]
   363
	g_CallWrappers.push_back(g_pGiveAmmo);
[email protected]
   364
[email protected]
   365
	/** PROPERTIES */
[email protected]
   366
	sm_sendprop_info_t prop;
[email protected]
   367
	if(!gamehelpers->FindSendPropInfo("CCSPlayer", "m_hRagdoll", &prop))
[email protected]
   368
	{
[email protected]
   369
		snprintf(error, maxlength, "Failed to get prop info for m_hRagdoll");
[email protected]
   370
		return false;
[email protected]
   371
	}
[email protected]
   372
	g_RagdollOffset = prop.actual_offset;
[email protected]
   373
	if(!gamehelpers->FindSendPropInfo("CCSPlayer", "m_lifeState", &prop))
[email protected]
   374
	{
[email protected]
   375
		snprintf(error, maxlength, "Failed to get prop info for m_lifeState");
[email protected]
   376
		return false;
[email protected]
   377
	}
[email protected]
   378
	g_LifeStateOffset = prop.actual_offset;
[email protected]
   379
	if(!gamehelpers->FindSendPropInfo("CCSPlayer", "m_bHasDefuser", &prop))
[email protected]
   380
	{
[email protected]
   381
		snprintf(error, maxlength, "Failed to get prop info for m_bHasDefuser");
[email protected]
   382
		return false;
[email protected]
   383
	}
[email protected]
   384
	g_DefuserOffset = prop.actual_offset;
[email protected]
   385
[email protected]
   386
	return true;
[email protected]
   387
}
[email protected]
   388
[email protected]
   389
void ShutdownUtils()
[email protected]
   390
{
[email protected]
   391
	List<ICallWrapper *>::iterator iter;
[email protected]
   392
	for (iter = g_CallWrappers.begin();
[email protected]
   393
		 iter != g_CallWrappers.end();
[email protected]
   394
		 iter++)
[email protected]
   395
	{
[email protected]
   396
		(*iter)->Destroy();
[email protected]
   397
	}
[email protected]
   398
	g_CallWrappers.clear();
[email protected]
   399
}