CEventAction hook

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

CEventAction hook

Postby velocity » Fri Nov 30, 2018 9:08 am

I'm trying to get more information about the entities in CS:GO. A way to do that is to access the CEventAction:__operator_delete function, but IIRC is too small to get a signature. Instead, it's possible to use g_pEntityListPool directly because that is what the operator delete function use internally.
A small side-note: I know you guys are busy, but Ayuto the hint you gave for CollisionHook was perfect, so same as a here a hint would be more than fine!

How to do that can be found here in C++ https://github.com/SlidyBat/sm-ext-o...nsion.cpp#L106 :

Syntax: Select all

class CEventAction
{
public:
CEventAction(const char *ActionData = NULL) { m_iIDStamp = 0; };

string_t m_iTarget; // name of the entity(s) to cause the action in
string_t m_iTargetInput; // the name of the action to fire
string_t m_iParameter; // parameter to send, 0 if none
float m_flDelay; // the number of seconds to wait before firing the action
int m_nTimesToFire; // The number of times to fire this event, or EVENT_FIRE_ALWAYS.

int m_iIDStamp; // unique identifier stamp

static int s_iNextIDStamp;

CEventAction *m_pNext;

// allocates memory from engine.MPool/g_EntityListPool
#if SOURCE_ENGINE == SE_CSGO
static void *operator new(size_t stAllocateBlock)
{
#ifdef PLATFORM_WINDOWS
return g_EntityListPool_Alloc();
#else
return g_EntityListPool_Alloc( g_pEntityListPool );
#endif
}
static void *operator new(size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine)
{
#ifdef PLATFORM_WINDOWS
return g_EntityListPool_Alloc();
#else
return g_EntityListPool_Alloc( g_pEntityListPool );
#endif
}
static void operator delete(void *pMem)
{
g_pEntityListPool->Free(pMem);
}
static void operator delete( void *pMem , int nBlockUse, const char *pFileName, int nLine )
{
operator delete(pMem);
}
#endif

DECLARE_SIMPLE_DATADESC();

};


My question is how can this be done in SourcePython? Here are all the signatures for linux:

Code: Select all

      
       "g_EntityListPool"
         {
            "signature" "CBaseEntity_ConnectOutputToScript"
            "read" "216"
            "read" "12"
         }
         "CBaseEntity_ConnectOutputToScript"
         {
            "library"   "server"
            "linux"      "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\x8B\x45\x10\x8B\x5D\x0C"
         }
         "CUtlMemoryPool_Alloc"
         {
            "library"   "server"
            "linux"      "\x55\x31\xC0\x89\xE5\x53\x83\xEC\x14\x8B\x5D\x08\x8B\x55\x0C\x39\x13"
         }
         


I appreciate all the help I can get!
User avatar
L'In20Cible
Project Leader
Posts: 1105
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: CEventAction hook

Postby L'In20Cible » Sat Dec 01, 2018 5:54 am

velocity wrote:I'm trying to get more information about the entities in CS:GO. A way to do that is to access the CEventAction:__operator_delete function, but IIRC is too small to get a signature.

How would hooking/calling the deleter of a registered output action gives you information? :eek:
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Sat Dec 01, 2018 2:00 pm

From the CEventAction function you can get the addoutput of an entity, you can see here, what information you can get:

Image

This is the coresponding variables:

Syntax: Select all

CEventAction(const char *ActionData = NULL) { m_iIDStamp = 0; };

string_t m_iTarget; // name of the entity(s) to cause the action in
string_t m_iTargetInput; // the name of the action to fire
string_t m_iParameter; // parameter to send, 0 if none
float m_flDelay; // the number of seconds to wait before firing the action
int m_nTimesToFire; // The number of times to fire this event, or EVENT_FIRE_ALWAYS.
User avatar
L'In20Cible
Project Leader
Posts: 1105
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: CEventAction hook

Postby L'In20Cible » Sat Dec 01, 2018 3:29 pm

Yes, but you don't need to sigscan the deleter of this class to access it. You need to restructure the class, grab an object pointer and read it without deleting it.
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Sat Dec 01, 2018 4:14 pm

I'm not sure how to do that, that's why I'm posting. :confused:
User avatar
L'In20Cible
Project Leader
Posts: 1105
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: CEventAction hook

Postby L'In20Cible » Sat Dec 01, 2018 7:19 pm

It's raw and hard-coded but here is a working example:

Syntax: Select all

from entities.datamaps import Variant
from memory import NULL, get_size
from players.entity import Player

# Get a Player instance
pl = Player(1)

# Add some outputs for testing
pl.call_input('AddOutput', 'OnIgnite !self,IgniteLifeTime,5,2,10')
pl.call_input('AddOutput', 'OnIgnite !activator,Something,,1,50')

# Get the first action in the chained map of actions
action = (pl.pointer + pl.datamap.find(
'OnIgnite').offset).get_pointer(get_size(Variant))

# Loop until we hit the end of the chain
while action != NULL:
print('--------------------------------')

# Read and print the data of the current action
print('m_iTarget:', action.get_string_pointer())
print('m_iTargetInput:', action.get_string_pointer(4))
print('m_iParameter:', action.get_string_pointer(8))
print('m_flDelay:', action.get_float(12))
print('m_nTimesToFire:', action.get_int(16))
print('m_iIDStamp:', action.get_int(20))

# Move to the next action
action = action.get_pointer(24) # m_pNext

"""
Expected result:
--------------------------------
m_iTarget: !activator
m_iTargetInput: Something
m_iParameter: None
m_flDelay: 1.0
m_nTimesToFire: 50
m_iIDStamp: 9
--------------------------------
m_iTarget: !self
m_iTargetInput: IgniteLifeTime
m_iParameter: 5
m_flDelay: 2.0
m_nTimesToFire: 10
m_iIDStamp: 8
"""


PS: Moved your thread to the support section, since you are not requesting a pre-made plugin.

EDIT: With this commit, you should be able to simply use the following for the same results:

Syntax: Select all

from entities import BaseEntityOutput, EventAction
from memory import make_object
from players.entity import Player

# Get a Player instance
pl = Player(1)

# Add some outputs for testing
pl.call_input('AddOutput', 'OnIgnite !self,IgniteLifeTime,5,2,10')
pl.call_input('AddOutput', 'OnIgnite !activator,Something,,1,50')

# Get the output instance of OnIgnite
output = make_object(BaseEntityOutput,
pl.pointer + pl.datamap.find('OnIgnite').offset)

# Get the first action in the chained map of actions
action = make_object(EventAction, output.event_action)

# Loop until we hit the end of the chain
while action:
print('--------------------------------')

# Read and print the data of the current action
print('m_iTarget:', action.target)
print('m_iTargetInput:', action.target_input)
print('m_iParameter:', action.parameter)
print('m_flDelay:', action.delay)
print('m_nTimesToFire:', action.times_to_fire)
print('m_iIDStamp:', action.id_stamp)

# Move to the next action
action = action.next # m_pNext

"""
Expected result:
--------------------------------
m_iTarget: !activator
m_iTargetInput: Something
m_iParameter: None
m_flDelay: 1.0
m_nTimesToFire: 50
m_iIDStamp: 9
--------------------------------
m_iTarget: !self
m_iTargetInput: IgniteLifeTime
m_iParameter: 5
m_flDelay: 2.0
m_nTimesToFire: 10
m_iIDStamp: 8
"""
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Sun Dec 02, 2018 5:03 am

Wow, that looks great, I can't wait to test it. Thanks! Do I just use sp update?
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Sun Dec 02, 2018 4:52 pm

I did "sp update"

but I get import error:

Syntax: Select all

File "../addons/source-python/plugins/trikzcafe/region_phase.py", line 18, in <module>

from entities import BaseEntityOutput, EventAction


EDIT:
ImportError: cannot import name 'BaseEntityOutput



I also tried your old code, it gives me following error, from a make_object(Entity, stack_data[3]):

Syntax: Select all

File "../addons/source-python/plugins/trikzcafe/region_phase.py", line 250, in pre_accept_input

'OnTrigger').offset).get_pointer(get_size(Variant))



AttributeError: 'NoneType' object has no attribute 'offset'
User avatar
L'In20Cible
Project Leader
Posts: 1105
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: CEventAction hook

Postby L'In20Cible » Sun Dec 02, 2018 6:43 pm

velocity wrote:I did "sp update"

but I get import error:

Syntax: Select all

File "../addons/source-python/plugins/trikzcafe/region_phase.py", line 18, in <module>

from entities import BaseEntityOutput, EventAction


EDIT:
ImportError: cannot import name 'BaseEntityOutput

Due to the recent buildbot changes, builds can be delayed as they now relies on Ayuto's local setup. You can however always build yourself for your game/platform: http://wiki.sourcepython.com/contributing/building.html

velocity wrote:I also tried your old code, it gives me following error, from a make_object(Entity, stack_data[3]):

Syntax: Select all

File "../addons/source-python/plugins/trikzcafe/region_phase.py", line 250, in pre_accept_input

'OnTrigger').offset).get_pointer(get_size(Variant))



AttributeError: 'NoneType' object has no attribute 'offset'

That means DataMap.find returned None because OnTrigger was not a valid output for that entity. Add your own sanity checks:

Syntax: Select all

descriptor = entity.datamap.find(output_name)
if descriptor is None:
return
action = make_object(BaseEntityOutput, entity.pointer + descriptor.offset)
...

I will see to make the use easier by adding some qol methods or something.

EDIT: With this commit you will be able to simply do:

Syntax: Select all

for action in entity.get_output(output_name).events_actions:
...
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Tue Dec 04, 2018 4:34 pm

If you want I am available to host the buildbot?

I tried building the repository I get the following error (I did install the required dependecies):


root@Ubuntu-1804-bionic-64-minimal ~/sourcepython/Source.Python/src # ./Build.sh csgo
Already on 'csgo'
Your branch is up to date with 'origin/csgo'.
Already up to date.
-- Configuring done
-- Generating done
-- Build files have been written to: /root/sourcepython/Source.Python/src/Builds/Linux/csgo
Scanning dependencies of target core
[ 1%] Building CXX object CMakeFiles/core.dir/core/patches/csgo/patches.cpp.o
Using built-in specs.
COLLECT_GCC=/usr/bin/c++
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bu gs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program- prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default -libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system- zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multil ib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=re lease --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
COLLECT_GCC_OPTIONS='-D' 'BOOST_PYTHON_MAX_ARITY=32' '-D' 'BOOST_PYTHON_NO_LIB' '-D' 'BOOST_PYTHON_SOURCE' '-D' 'BOOST_PYTHON_STATIC_LIB' '-D' 'ENGINE_BRANCH_CSGO' '-D' 'ENGINE_CSGO' '-D' 'GAME_DLL=1' '-D' 'SOURCE_ENGINE=csgo' '-D' 'SOURCE_ENGINE_BRANCH=csgo' '-D' 'USE_PROT OBUF' '-D' 'core_EXPORTS' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo/ common' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo/common/protobuf-2.5.0/src' '-I' '/root/sourcepython/Source.Python/src/hl2s dk/csgo/game/shared' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo/game/server' '-I' '/root/sourcepython/Source.Python/src/hl2sd k/csgo/public' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo/public/tier0' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csg o/public/tier1' '-I' '/root/sourcepython/Source.Python/src/hl2sdk/csgo/public/engine/protobuf' '-I' '/root/sourcepython/Source.Python/src /thirdparty/dyncall/include' '-I' '/root/sourcepython/Source.Python/src/thirdparty/boost' '-I' '/root/sourcepython/Source.Python/src/thir dparty/AsmJit/include' '-I' '/root/sourcepython/Source.Python/src/thirdparty/DynamicHooks/include' '-I' '/root/sourcepython/Source.Python /src/core' '-I' '/root/sourcepython/Source.Python/src/thirdparty/python_linux/include' '-D' '_LINUX' '-D' 'POSIX' '-D' 'LINUX' '-D' 'GNUC ' '-D' 'COMPILER_GCC' '-D' 'stricmp=strcasecmp' '-D' '_stricmp=strcasecmp' '-D' '_strnicmp=strncasecmp' '-D' 'strnicmp=strncasecmp' '-D' '_snprintf=snprintf' '-D' '_vsnprintf=vsnprintf' '-D' '_alloca=alloca' '-D' 'strcmpi=strcasecmp' '-Wall' '-Wno-uninitialized' '-Wno-switc h' '-Wno-unused' '-Wno-non-virtual-dtor' '-Wno-overloaded-virtual' '-Wno-conversion-null' '-Wno-write-strings' '-Wno-invalid-offsetof' '- Wno-reorder' '-mfpmath=sse' '-msse' '-m32' '-fno-strict-aliasing' '-std=c++11' '-fno-threadsafe-statics' '-v' '-fvisibility=hidden' '-D' '_NDEBUG' '-O3' '-D' 'NDEBUG' '-fPIC' '-o' 'CMakeFiles/core.dir/core/patches/csgo/patches.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' ' -march=i686'
/usr/lib/gcc/x86_64-linux-gnu/7/cc1plus -quiet -v -I /root/sourcepython/Source.Python/src/hl2sdk/csgo -I /root/sourcepython/Source.Pytho n/src/hl2sdk/csgo/common -I /root/sourcepython/Source.Python/src/hl2sdk/csgo/common/protobuf-2.5.0/src -I /root/sourcepython/Source.Pytho n/src/hl2sdk/csgo/game/shared -I /root/sourcepython/Source.Python/src/hl2sdk/csgo/game/server -I /root/sourcepython/Source.Python/src/hl2 sdk/csgo/public -I /root/sourcepython/Source.Python/src/hl2sdk/csgo/public/tier0 -I /root/sourcepython/Source.Python/src/hl2sdk/csgo/publ ic/tier1 -I /root/sourcepython/Source.Python/src/hl2sdk/csgo/public/engine/protobuf -I /root/sourcepython/Source.Python/src/thirdparty/dy ncall/include -I /root/sourcepython/Source.Python/src/thirdparty/boost -I /root/sourcepython/Source.Python/src/thirdparty/AsmJit/include -I /root/sourcepython/Source.Python/src/thirdparty/DynamicHooks/include -I /root/sourcepython/Source.Python/src/core -I /root/sourcepytho n/Source.Python/src/thirdparty/python_linux/include -imultilib 32 -imultiarch i386-linux-gnu -D_GNU_SOURCE -D BOOST_PYTHON_MAX_ARITY=32 - D BOOST_PYTHON_NO_LIB -D BOOST_PYTHON_SOURCE -D BOOST_PYTHON_STATIC_LIB -D ENGINE_BRANCH_CSGO -D ENGINE_CSGO -D GAME_DLL=1 -D SOURCE_ENGI NE=csgo -D SOURCE_ENGINE_BRANCH=csgo -D USE_PROTOBUF -D core_EXPORTS -D _LINUX -D POSIX -D LINUX -D GNUC -D COMPILER_GCC -D stricmp=strca secmp -D _stricmp=strcasecmp -D _strnicmp=strncasecmp -D strnicmp=strncasecmp -D _snprintf=snprintf -D _vsnprintf=vsnprintf -D _alloca=al loca -D strcmpi=strcasecmp -D _NDEBUG -D NDEBUG /root/sourcepython/Source.Python/src/core/patches/csgo/patches.cpp -quiet -dumpbase patch es.cpp -mfpmath=sse -msse -m32 -mtune=generic -march=i686 -auxbase-strip CMakeFiles/core.dir/core/patches/csgo/patches.cpp.o -O3 -Wall -W no-uninitialized -Wno-switch -Wno-unused -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-conversion-null -Wno-write-strings -Wno-inval id-offsetof -Wno-reorder -std=c++11 -version -fno-strict-aliasing -fno-threadsafe-statics -fvisibility=hidden -fPIC -fstack-protector-str ong -Wformat-security -o /tmp/cc0nA9Qv.s
GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu)
compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../include/x86_64-linux-gnu/c++/7/32"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../include/i386-linux-gnu/c++/7"
ignoring nonexistent directory "/usr/local/include/i386-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i386-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
/root/sourcepython/Source.Python/src/hl2sdk/csgo
/root/sourcepython/Source.Python/src/hl2sdk/csgo/common
/root/sourcepython/Source.Python/src/hl2sdk/csgo/common/protobuf-2.5.0/src
/root/sourcepython/Source.Python/src/hl2sdk/csgo/game/shared
/root/sourcepython/Source.Python/src/hl2sdk/csgo/game/server
/root/sourcepython/Source.Python/src/hl2sdk/csgo/public
/root/sourcepython/Source.Python/src/hl2sdk/csgo/public/tier0
/root/sourcepython/Source.Python/src/hl2sdk/csgo/public/tier1
/root/sourcepython/Source.Python/src/hl2sdk/csgo/public/engine/protobuf
/root/sourcepython/Source.Python/src/thirdparty/dyncall/include
/root/sourcepython/Source.Python/src/thirdparty/boost
/root/sourcepython/Source.Python/src/thirdparty/AsmJit/include
/root/sourcepython/Source.Python/src/thirdparty/DynamicHooks/include
/root/sourcepython/Source.Python/src/core
/root/sourcepython/Source.Python/src/thirdparty/python_linux/include
/usr/include/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include
End of search list.
GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu)
compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 1bfae38ae5df64de6196cbd8c3b07d86
In file included from /usr/include/c++/7/math.h:36:0,
from /root/sourcepython/Source.Python/src/hl2sdk/csgo/public/mathlib/vector.h:16,
from /root/sourcepython/Source.Python/src/hl2sdk/csgo/public/datamap.h:15,
from /root/sourcepython/Source.Python/src/core/utilities/baseentity.h:32,
from /root/sourcepython/Source.Python/src/core/patches/csgo/patches.cpp:27:
/usr/include/c++/7/cmath:41:10: fatal error: bits/c++config.h: No such file or directory
#include <bits/c++config.h>
^~~~~~~~~~~~~~~~~~
compilation terminated.
CMakeFiles/core.dir/build.make:62: recipe for target 'CMakeFiles/core.dir/core/patches/csgo/patches.cpp.o' failed
make[2]: *** [CMakeFiles/core.dir/core/patches/csgo/patches.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/core.dir/all' failed
make[1]: *** [CMakeFiles/core.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
./Build.sh: 152: ./Build.sh: Bad substitution
User avatar
Ayuto
Project Leader
Posts: 1911
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: CEventAction hook

Postby Ayuto » Tue Dec 04, 2018 6:37 pm

I guess there are missing 32 bit libraries on your system. GCC 7 might also cause problems. Try 4.8 -- that's also what our buildbot uses:
http://wiki.sourcepython.com/contributi ... html#linux

However, I will be back home tomorrow. Then I will create a new release.
User avatar
velocity
Senior Member
Posts: 153
Joined: Sat May 10, 2014 6:17 pm

Re: CEventAction hook

Postby velocity » Thu Dec 06, 2018 1:49 am

I have updated to the latest release and I'm now available to use the code, but it appears that I get a ValueError even tho I know (the trigger_multiple) has an OnTrigger output (Checked with hammer).

Syntax: Select all

@EntityPreHook(EntityCondition.is_player, "accept_input")
def pre_accept_input(stack_data):
trigger= make_object(Entity, stack_data[3])
for action in trigger.get_output("OnTrigger").event_actions:
SayText2(str(action)).send()

ValueError: Failed to retrieve offset of 'OnTrigger'


Also, with buttons it appears that the parameter is an empty string? Perhaps that just means it doesn't have one.

Syntax: Select all

m_iTarget: door2_template

m_iTargetInput: ForceSpawn

m_iParameter:

m_flDelay: 30.0

m_nTimesToFire: -1

m_iIDStamp: 210
User avatar
L'In20Cible
Project Leader
Posts: 1105
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: CEventAction hook

Postby L'In20Cible » Thu Dec 06, 2018 2:26 am

velocity wrote:I have updated to the latest release and I'm now available to use the code, but it appears that I get a ValueError even tho I know (the trigger_multiple) has an OnTrigger output (Checked with hammer).

Syntax: Select all

@EntityPreHook(EntityCondition.is_player, "accept_input")
def pre_accept_input(stack_data):
trigger= make_object(Entity, stack_data[3])
for action in trigger.get_output("OnTrigger").event_actions:
SayText2(str(action)).send()

ValueError: Failed to retrieve offset of 'OnTrigger'


Well, that's normal. You never validate your "trigger" to ensure it is indeed a "trigger_multiple" so it can be any entity type that shares the same method (for example, if your hook is registered on CBaseEntity::AcceptInput, then it will fires for every classes that inherits from that class and is not providing their own implementation in their dispatch table). This also applies to the caller/activator; they can be any entity. Just filter by classname adding your own sanity checks as stated above:

Syntax: Select all

@EntityPreHook(EntityCondition.is_player, "accept_input")
def pre_accept_input(stack_data):
trigger= make_object(Entity, stack_data[3])
if trigger.classname != 'trigger_multiple':
return # Not a trigger; exit the call.
for action in trigger.get_output("OnTrigger").event_actions:
SayText2(str(action)).send()

ValueError: Failed to retrieve offset of 'OnTrigger'
You should also test for "is None", because an output can be fired without any activator/caller and your code will raise if you attempt to make a BaseEntity object from an invalid pointer.

velocity wrote:Also, with buttons it appears that the parameter is an empty string? Perhaps that just means it doesn't have one.

Syntax: Select all

m_iTarget: door2_template

m_iTargetInput: ForceSpawn

m_iParameter:

m_flDelay: 30.0

m_nTimesToFire: -1

m_iIDStamp: 210
Correct, it appears the ForceSpawn input doesn't take any parameter to be executed. Although, this is up to the one that register the output to pass the appropriate values so this is not enough to guarantee that the input itself doesn't take any parameters over the mapper, etc. forgot to pass it in.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 27 guests