View Single Post
Author Message
Olly
Senior Member
Join Date: Mar 2007
Location: UK
Old 05-27-2007 , 20:57   [USEFUL STOCKS] EntityTools
Reply With Quote #1

I have created a set of stocks for you to use in your plugins to play with Entities

You will need a copy of PimpinJuice's sigscan extension: http://forums.alliedmods.net/showthread.php?t=53893

All of the signatures have been taken from my big list: http://forums.alliedmods.net/showthread.php?t=55565 So check here if you want to do some more hacking

Ok...

If you are creating a plugin with these stocks, you will need to include the following:

Code:
#include <sourcemod>
#include <sigoffset>
#include <entity>
#include <clients>
And have the following globals:
Code:
new ScanCreateIndex, ScanTeleportIndex, ScanSpawnIndex, ScanSetModelIndex, ScanRemoveIndex;
new MyEntity;
InitEntitySigs
This stock will scan the memory for the required functions you need for these few stocks.
Code:
/**
 * Scans the memory for the required functions
 * MUST be called first!
 * @return                1 on success, 0 on error;
 */
stock InitEntitySigs()
{
    ScanCreateIndex = SignatureScanFind("CreateEntityByName", 
                    "\x56\x8b\x74\x24\x0c\x83\xfe\xff\x57\x8b\x7c\x24\x0c\x74\x25\x8b\x0d\x68\x69\x5f\x22\x8b\x01\x56\xff\x50\x54\x85\xc0\xa3\x9c\xfa\x5c\x22\x75\x10\x56\x57\x68\x08\x6d\x4e\x22\xff\x15\xfc\xb1\x48\x22\x83\xc4\x0c",
                    "xxxxxxxxxxxxx??xxxxxxxxx???xx???????xx???????????xxx",
                    52, 
                    "_Z18CreateEntityByNamePKci");
                    
    ScanSpawnIndex = SignatureScanFind("DispatchSpawn", 
                    "\x53\x55\x56\x8b\x74\x24\x10\x85\xf6\x57\x0f\x84\x3a\x01\x00\x00\x8b\x1d\xa4\x69\x5f\x22\x8b\x03\x8b\xcb\xff\x50\x60\x8b\x16\x8b\xce\xff\x52\x08\x8b\x0d\xa4\x69\x5f\x22\x8b\x28",
                    "xxxxxxxxxx????????????xxxxxxxxxxxxxxxxxxxxxx",
                    44, 
                    "_Z13DispatchSpawnP11CBaseEntity");
                    
    ScanTeleportIndex = SignatureScanFind("CBaseEntity::Teleport", 
                    "\x83\xEC\x18\x53\x56\x8B\xD9\x8B\x0D\x78\xB2\x46\x22\x33\xF6\x33\xC0\x3B\xCE\x7E\x21\x8B\x15\x6C\xB2\x46\x22\xEB\x03\x8D\x49\x00\x39\x1C\x82\x74\x09\x83\xC0\x01\x3B\xC1\x7C\xF4\xEB\x08\x3B\xC6\x0F\x8D\x17\x01\x00\x00\x55\x57\x8D\x44\x24\x10\x50\x51\xB9\x6C\xB2\x46\x22\x89\x5C\x24\x18\xE8\xB4\x88\xF9\xFF\x8D\x4C\x24\x14\x51\x53\x89\x44\x24\x18\x89\x74\x24\x1C\x89\x74\x24\x20\x89\x74\x24\x24\x89\x74\x24\x28\x89\x74\x24\x2C",
                    "xxxxxxx??????xxxxxx?????????????xxx?????xx????xx??????x?????xx?????xxxx?????????xxxxxxxxxxxxxxxxxxxxxxxxxx",
                    106, 
                    "_ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS");
                    
    ScanSetModelIndex = SignatureScanFind("CBaseEntity::SetModel", 
                    "\x56\x8b\x74\x24\x08\x57\x8b\xf9\x8b\x0d\x8c\x69\x5f\x22\x8b\x01\x56\xff\x50\x08\x8b\x0d\x8c\x69\x5f\x22\x8b\x11\x50\xff\x52\x04\x85\xc0\x74\x20\x8b\x0d\x8c\x69\x5f\x22\x8b\x11\x50\xff\xf2\x24\x83\xf8\x01",
                    "xxxxxxxx??????xxx?????????xxx???xx????????xxx??xxxx",
                     51, 
                    "_ZN11CBaseEntity8SetModelEPKc");
                    
    ScanRemoveIndex = SignatureScanFind("UTIL_Remove", 
                    "\x8b\x44\x24\x04\x85\xc0\x74\x0e\x05\x48\x01\x00\x00\x89\x44\x24\x04\xe9\x7a\xff\xff\xff\xc3",
                    "xxxxxx???????xxxx?????x",
                    23, 
                    "_Z11UTIL_RemoveP11CBaseEntity");
                    
    return !(ScanCreateIndex == -1 || ScanSpawnIndex == -1 || ScanTeleportIndex == -1 || ScanSetModelIndex == -1 || ScanRemoveIndex == -1);
}
CreateEntity
This stock will allow you to create a new entity. The class name that you need to specify is the 'type' of entity to create. For example: prop_ragdoll, hostage_entity. A list of these can be found from HAMMER in the SDK tools.
Code:
/**
 * Creates the entity from the given class name
 * @param    EntClass    The class of entity to create, eg: prop_ragdol, weapon_awp...
 * @return                the edict index.
 */
stock CreateEntity(String:EntClass[])
{
    for(new i = 64;i<4096;++i)
    {
        if(IsValidEntity(i))
            continue;
        else
        {
            return SignatureScan_HandleToIndex(
                SignatureScanCall_NoIndex(ScanCreateIndex,
                PARAM_CONST_CHAR_PTR, EntClass, 
                PARAM_INT, i));    
        }
    }
}
SpawnEntity
This stock will spawn the entity that you created earlier into the world at the desired location.
Code:
 /**
 * Spawns the entity
 * @param    entity            The entity ID.
 * @param    Vector:origin    the place the entity should spawn at.
 * @param    Vector:velocity    the velocity to move the entity.
 * @return     1 on success, 0 on error.
 */
stock SpawnEntity(entity, Float:origin[], angle, Float:velocity[])
{
    if (!IsValidEntity(entity) || 
            ScanSpawnIndex == -1 || 
            ScanTeleportIndex == -1)
        return 0;
    
    // Spawn it
    SignatureScanCall_NoIndex(ScanSpawnIndex,
                                PARAM_CBASEENTITY, 
                                entity);
    
    // Teleport the entity    
    SignatureScanCall(ScanTeleportIndex, 
                        entity, SIGTYPE_CBASEENTITY, 
                        PARAM_VECTOR, origin, 
                        PARAM_QANGLE, angle, 
                        PARAM_VECTOR, velocity);    
    return 1;
}
RemoveEntity
This stock will completely unload and remove an entity from the world
Code:
/**
 * Removes the entity from the world
 * @param     entity        The entity id to remove
 * @return     1 on success, 0 on error.
 */
stock RemoveEntity(entity)
{
    if (!IsValidEntity(entity) || 
            ScanRemoveIndex == -1)
        return 0;
    
    SignatureScanCall_NoIndex(ScanRemoveIndex,
                                PARAM_CBASEENTITY, 
                                entity);    
    return 1;
}
EntityModel
This stock will change the model of the current entity. Precaching is done inside this stock ;)
Code:
/**
 * Sets an entities model
 * @param     entity            The entity id to change
 * @param     String:model    The model to change it to
 * @return     1 on success, 0 on error.
 */
stock EntityModel(entity, String:model[])
{
    if (!IsValidEntity(entity) || 
            ScanSetModelIndex == -1)
         return 0;
    
    PrecacheModel(model, true);    
    SignatureScanCall(ScanSetModelIndex, entity, SIGTYPE_CBASEENTITY, 
                        PARAM_CONST_CHAR_PTR, model);    
     return 1;
}
-----------------------------------------------------------------------

Sample Plugin
This is a small sample plugin that i have made just to show you how all of this would look in a plugin
Code:
 #include <sourcemod>
#include <sigoffset>
#include <entity>
#include <clients>
#pragma semicolon 1
new ScanCreateIndex, ScanTeleportIndex, ScanSpawnIndex, ScanSetModelIndex, ScanRemoveIndex;
new MyEntity;

public OnPluginStart()
{
    RegConsoleCmd("dropdoll", DropRagDoll);
}

public Action:DropRagDoll(client, args)
{
    // Find our functions
    InitEntitySigs();            

// Create our ragdoll entity       
    MyEntity = CreateEntity("prop_ragdoll");
    new Float:vec[3];

    // Get our location
    GetClientAbsOrigin(client, vec);
    // Offset a little
    vec[0] += 5;
    vec[1] += 5;
    vec[2] += 5;
    // Give the ragdoll a model so we can see it
    EntityModel(MyEntity, "models/Alyx.mdl");

    // Spawn the entity at our location +5
    SpawnEntity(MyEntity, vec, -1, vec);
}

/**
 * Scans the memory for the required functions
 * MUST be called first!
 * @return                1 on success, 0 on error;
 */
stock InitEntitySigs()
{
    ScanCreateIndex = SignatureScanFind("CreateEntityByName", 
                    "\x56\x8b\x74\x24\x0c\x83\xfe\xff\x57\x8b\x7c\x24\x0c\x74\x25\x8b\x0d\x68\x69\x5f\x22\x8b\x01\x56\xff\x50\x54\x85\xc0\xa3\x9c\xfa\x5c\x22\x75\x10\x56\x57\x68\x08\x6d\x4e\x22\xff\x15\xfc\xb1\x48\x22\x83\xc4\x0c",
                    "xxxxxxxxxxxxx??xxxxxxxxx???xx???????xx???????????xxx",
                    52, 
                    "_Z18CreateEntityByNamePKci");
                    
    ScanSpawnIndex = SignatureScanFind("DispatchSpawn", 
                    "\x53\x55\x56\x8b\x74\x24\x10\x85\xf6\x57\x0f\x84\x3a\x01\x00\x00\x8b\x1d\xa4\x69\x5f\x22\x8b\x03\x8b\xcb\xff\x50\x60\x8b\x16\x8b\xce\xff\x52\x08\x8b\x0d\xa4\x69\x5f\x22\x8b\x28",
                    "xxxxxxxxxx????????????xxxxxxxxxxxxxxxxxxxxxx",
                    44, 
                    "_Z13DispatchSpawnP11CBaseEntity");
                    
    ScanTeleportIndex = SignatureScanFind("CBaseEntity::Teleport", 
                    "\x83\xEC\x18\x53\x56\x8B\xD9\x8B\x0D\x78\xB2\x46\x22\x33\xF6\x33\xC0\x3B\xCE\x7E\x21\x8B\x15\x6C\xB2\x46\x22\xEB\x03\x8D\x49\x00\x39\x1C\x82\x74\x09\x83\xC0\x01\x3B\xC1\x7C\xF4\xEB\x08\x3B\xC6\x0F\x8D\x17\x01\x00\x00\x55\x57\x8D\x44\x24\x10\x50\x51\xB9\x6C\xB2\x46\x22\x89\x5C\x24\x18\xE8\xB4\x88\xF9\xFF\x8D\x4C\x24\x14\x51\x53\x89\x44\x24\x18\x89\x74\x24\x1C\x89\x74\x24\x20\x89\x74\x24\x24\x89\x74\x24\x28\x89\x74\x24\x2C",
                    "xxxxxxx??????xxxxxx?????????????xxx?????xx????xx??????x?????xx?????xxxx?????????xxxxxxxxxxxxxxxxxxxxxxxxxx",
                    106, 
                    "_ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS");
                    
    ScanSetModelIndex = SignatureScanFind("CBaseEntity::SetModel", 
                    "\x56\x8b\x74\x24\x08\x57\x8b\xf9\x8b\x0d\x8c\x69\x5f\x22\x8b\x01\x56\xff\x50\x08\x8b\x0d\x8c\x69\x5f\x22\x8b\x11\x50\xff\x52\x04\x85\xc0\x74\x20\x8b\x0d\x8c\x69\x5f\x22\x8b\x11\x50\xff\xf2\x24\x83\xf8\x01",
                    "xxxxxxxx??????xxx?????????xxx???xx????????xxx??xxxx",
                     51, 
                    "_ZN11CBaseEntity8SetModelEPKc");
                    
    ScanRemoveIndex = SignatureScanFind("UTIL_Remove", 
                    "\x8b\x44\x24\x04\x85\xc0\x74\x0e\x05\x48\x01\x00\x00\x89\x44\x24\x04\xe9\x7a\xff\xff\xff\xc3",
                    "xxxxxx???????xxxx?????x",
                    23, 
                    "_Z11UTIL_RemoveP11CBaseEntity");
                    
    return !(ScanCreateIndex == -1 || ScanSpawnIndex == -1 || ScanTeleportIndex == -1 || ScanSetModelIndex == -1 || ScanRemoveIndex == -1);
}

/**
 * Creates the entity from the given class name
 * @param    EntClass    The class of entity to create, eg: prop_ragdol, weapon_awp...
 * @return                the edict index.
 */
stock CreateEntity(String:EntClass[])
{
    for(new i = 64;i<4096;++i)
    {
        if(IsValidEntity(i))
            continue;
        else
        {
            return SignatureScan_HandleToIndex(
                SignatureScanCall_NoIndex(ScanCreateIndex,
                PARAM_CONST_CHAR_PTR, EntClass, 
                PARAM_INT, i));    
        }
    }
}

/**
 * Spawns the entity
 * @param    entity            The entity ID.
 * @param    Vector:origin    the place the entity should spawn at.
 * @param    Vector:velocity    the velocity to move the entity.
 * @return     1 on success, 0 on error.
 */
stock SpawnEntity(entity, Float:origin[], angle, Float:velocity[])
{
    if (!IsValidEntity(entity) || 
            ScanSpawnIndex == -1 || 
            ScanTeleportIndex == -1)
        return 0;
    
    // Spawn it
    SignatureScanCall_NoIndex(ScanSpawnIndex,
                                PARAM_CBASEENTITY, 
                                entity);
    
    // Teleport the entity    
    SignatureScanCall(ScanTeleportIndex, 
                        entity, SIGTYPE_CBASEENTITY, 
                        PARAM_VECTOR, origin, 
                        PARAM_QANGLE, angle, 
                        PARAM_VECTOR, velocity);    
    return 1;
}

/**
 * Removes the entity from the world
 * @param     entity        The entity id to remove
 * @return     1 on success, 0 on error.
 */
stock RemoveEntity(entity)
{
    if (!IsValidEntity(entity) || 
            ScanRemoveIndex == -1)
        return 0;
    
    SignatureScanCall_NoIndex(ScanRemoveIndex,
                                PARAM_CBASEENTITY, 
                                entity);    
    return 1;
}

/**
 * Sets an entities model
 * @param     entity            The entity id to change
 * @param     String:model    The model to change it to
 * @return     1 on success, 0 on error.
 */
stock EntityModel(entity, String:model[])
{
    if (!IsValidEntity(entity) || 
            ScanSetModelIndex == -1)
         return 0;
    
    PrecacheModel(model);    
    SignatureScanCall(ScanSetModelIndex, entity, SIGTYPE_CBASEENTITY, 
                        PARAM_CONST_CHAR_PTR, model);    
     return 1;
}
// Yarrrr!
This is the result of this plugin:
[IMG]http://img513.**************/img513/6973/dedust0013rc6.jpg[/IMG]

Last edited by Olly; 05-29-2007 at 06:36. Reason: Yarrrr!
Olly is offline
Send a message via MSN to Olly