// Logs every action/behavior/component allocation or deallocation // Used to track memory leaks // 1 - Enable memory debug, 0 - Disable memory debug ext_actions_debug_memory "0"
Commands
PHP Code:
ext_actions_dump - Dumps every nextbot actions to console.
Guide Samples
Action Handlers
You can hook action handler by setting it's callback function (or unhook with INVALID_FUNCTION)
PHP Code:
action.OnUpdate = OnUpdate;
Simple example, if you need to hook "Update" handler of every "whatever" action
PHP Code:
/* * OnActionCreated notifies whenever entity got a new action but without actual transition yet. * That means action is constructed by the corresponding constructor and still hasn't been updated or * started yet. */ public void OnActionCreated(BehaviorAction action, int actor, const char[] name) { if (strcmp(name, "whatever") = 0) { action.Update = OnWhateverUpdate; } }
public Action OnWhateverUpdate(BehaviorAction action, int actor, float interval, ActionResult) { // unhook it action.Update = INVALID_FUNCTION; return Plugin_Continue; }
You can store any data in action with and without identity
Data stored without identity is shared between plugins and persists until action is deleted
Data stored with identity is NOT shared between plugins (multiple plugins can use same keys) and persists until plugin who owns the data is unloaded
Usually you want to store data without identity, the latter is for specific use cases where you want to store handles or something important that has to be accessible even if action is destroyed
Example:
PHP Code:
public void OnActionCreated(BehaviorAction action, int actor, const char[] name) { // to store with identity add "Identity" after Data // action.SetUserDataIdentity("my_int", 2); // action.SetUserDataIdentityVector("my_vector", { -89.0, 125.0, -5324.0 });
action.SetUserData("my_int", 2); action.SetUserData("my_float", 2.25); action.SetUserDataVector("my_vector", { -89.0, 125.0, -5324.0 }); action.SetUserDataString("my_string", "Test test test test"); }
public void OnActionDestroyed(BehaviorAction action, int actor, const char[] name) { int ivalue, fvalue; float vector[3]; char buffer[64];
If you want to create internal game actions then you need to create SDKCall then call it on allocated memory.
Even if this approach works, I still think there should be a way to hide SDKCall and memory allocation into gamedata.
So there is ActionConstructor
PHP Code:
ActionConstructor g_SampleActionConstructor;
public void OnPluginStart() { GameData data = new GameData("");
"params" { "target" { /* * basic - plain generic data * float - floating point data * object - raw struct/class/array? */ "type" "basic"
/* * byval - pass by val * byref - pass by ref * dtor - object has destructor * ctor - object has constructor * assignop - object has assignment operator * unalign - object contains unaligned fields */ "flags" "byval"
// You can specify encoder to transform arbitary data to valve params (eg. entity index -> CBaseEntity) /* * entity - entity index to CBaseEntity * vector - raw array to Vector struct */ "encoder" "entity" } } } } } }
Action Component
All actions are eventually stored in the behavior and behavior is stored in IIntention component.
You can create your own IIntention component called "ActionComponent"
The created component works exactly the same as the other components but you can also delete it at any time
If the plugin is unloaded all its components will be deleted automatically
PHP Code:
#include <actions>
public void OnPluginStart() { HookEvent("player_spawn", player_spawn); }
public Action Suspendable_Update(BehaviorAction action, int actor, float interval, ActionResult result) { action.Update = INVALID_FUNCTION;
int approach_target; if (ActionsManager.GetActionUserData(action, "approach_target", approach_target)) { if ((approach_target = EntRefToEntIndex(approach_target)) <= 0) return Plugin_Continue;
public Action SurvivorApproach_Update(BehaviorAction action, int actor, float interval, ActionResult result) { float origin[3], goal[3]; GetClientAbsOrigin(actor, origin);
if (!ActionsManager.GetActionUserDataVector(action, "survivor_approach_goal", goal)) { int target = EntRefToEntIndex(action.GetUserData("survivor_approach_target"));