/** * Ashita - Copyright (c) 2014 - 2016 atom0s [atom0s@live.com] * * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to * Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. * * By using Ashita, you agree to the above license and its terms. * * Attribution - You must give appropriate credit, provide a link to the license and indicate if changes were * made. You must do so in any reasonable manner, but not in any way that suggests the licensor * endorses you or your use. * * Non-Commercial - You may not use the material (Ashita) for commercial purposes. * * No-Derivatives - If you remix, transform, or build upon the material (Ashita), you may not distribute the * modified material. You are, however, allowed to submit the modified works back to the original * Ashita project in attempt to have it added to the original project. * * You may not apply legal terms or technological measures that legally restrict others * from doing anything the license permits. * * No warranties are given. */ #include "Repeat.h" /** * Constructor and Deconstructor */ Repeat::Repeat(void) : m_AshitaCore(nullptr) , m_LogManager(nullptr) , m_PluginId(0) , m_Direct3DDevice(nullptr) { } Repeat::~Repeat(void) { } /** * Returns the plugins information structure. * * @returns {plugininfo_t} The plugin information structure of the plugin. */ plugininfo_t Repeat::GetPluginInfo(void) { return *g_PluginInfo; } /** * Invoked when the plugin is loaded, allowing it to prepare for usage. * * @param {IAshitaCore*} core - The Ashita core object to interact with the various Ashita managers. * @param {ILogManager*} log - The log manager used to interact with the current log file. * @param {uint32_t} id - The plugins id, or its module base, that identifies it other than its name. * @returns {bool} True on success, false otherwise. (If false, the plugin will not be loaded.) * * @notes * * Plugins must return true here or they will be considered invalid and unload immediately. * Returning false means that the plugin failed to initialize and should not be used. */ bool Repeat::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) { // Store the variables for later usage.. this->m_AshitaCore = core; this->m_LogManager = log; this->m_PluginId = id; this->_userdelayinms = 0; this->_jitter = 0; this->doJitter = false; this->_debug = false; this->command = ""; this->Start(); return true; } /** * Invoked when the plugin is being unloaded, allowing it to cleanup its resources. * * @notes * * Plugins should use this function to cleanup non-Direct3D related objects. * - Delete created font objects. * - Delete created Gui objects. * - Internal memory allocations. */ void Repeat::Release(void) { this->Stop(); } /** * Invoked when a command is being processed by the game client. * * Note: * Please note, this handles all things done via the game in terms of commands * and chat. All / commands as well as normal chat you type, macros, etc. will * be processed through here. You should only use this to handle / commands. * * If you wish to handle other bits of outgoing text before the client sees it, * then use the HandleOutgoingText callback instead. * * @param {const char*} command - The raw command string being processed. * @param {uint32_t} type - The type of the command being processed. (See Ashita::CommandInputType enumeration.) * @returns {bool} True if handled and should be blocked, false otherwise. * * @notes * * Plugins can handle and block input from being sent to the game in this function. Returning * true will block the current command from happening at all within the client. Plugins should * only return true when the command passed to this function is being handled by the plugin. */ bool Repeat::HandleCommand(const char* given_command, int32_t type) { //UNREFERENCED_PARAMETER(type); std::string arg; const char* com = given_command + GetArg(given_command, &arg); if ((_strnicmp(given_command, "/rp", 3)) && (_stricmp(arg.c_str(), "/repeat")) && (_stricmp(arg.c_str(), "/repeater"))) { return false; } if (strlen(com) < 2) return true; if ((_stricmp(arg.c_str(), "/rp") == 0) || (_stricmp(arg.c_str(), "/repeat") == 0) || (_stricmp(arg.c_str(), "/repeater") == 0)) { com++; com += GetArg(com, &arg); } /* m_AshitaCore->GetChatManager()->Write("Repeater Command Listing: /repeater or /rp are both valid:"); m_AshitaCore->GetChatManager()->Write("/rp [set|unset] [command] - Set or Unset command to be repeated"); m_AshitaCore->GetChatManager()->Write("/rp [cycle] - Number of milliseconds to wait before repeating."); m_AshitaCore->GetChatManager()->Write("/rp [jitter] [on|off] - Toggle or turn on/off small differences in cycle time."); m_AshitaCore->GetChatManager()->Write("/rp [start|stop] - Starts or Stops repeating of previously set command"); m_AshitaCore->GetChatManager()->Write("/rp debug on/off - When enabled, debug prints will be visible."); */ if (_stricmp(arg.c_str(), "set") == 0) { if (strlen(com) < 2) return true; command = com + 1; m_AshitaCore->GetChatManager()->Writef("Setting command to: %s", command.c_str()); return true; } else if (_stricmp(arg.c_str(), "unset") == 0) { command = ""; this->m_AshitaCore->GetChatManager()->Write("Clearing command."); return true; } else if (_stricmp(arg.c_str(), "cycle") == 0) { if (strlen(com) < 2) return true; com++; com += GetArg(com, &arg); if (!IsNumber(arg.c_str())) return true; _userdelayinms = stoi(arg.c_str()); _userdelayinms = max(_userdelayinms, 1000); _userdelayinms = min(_userdelayinms, 3600000); if (doJitter) this->m_AshitaCore->GetChatManager()->Writef("Commands will be executed every %i milliseconds with random jitter!", _userdelayinms); else this->m_AshitaCore->GetChatManager()->Writef("Commands will be executed every %i milliseconds!", _userdelayinms); return true; } else if (_stricmp(arg.c_str(), "jitter") == 0) { if (strlen(com) < 2) return true; com++; com += GetArg(com, &arg); _maxjitter = stoi(arg.c_str()); _maxjitter = max(_maxjitter, 0); _maxjitter = min(_maxjitter, 3600000); if (_maxjitter > 0) { doJitter = true; this->m_AshitaCore->GetChatManager()->Writef("Random jitter betweem 0 and %ims will be added to cycle time.", _maxjitter); } else { doJitter = false; this->m_AshitaCore->GetChatManager()->Writef("Jitter disabled.", _maxjitter); } return true; } else if (_stricmp(arg.c_str(), "start") == 0) { if (command != "") { _tickcount = 0; this->m_AshitaCore->GetChatManager()->Write("Starting command!"); _ispluginrunning = true; } else { _ispluginrunning = false; this->m_AshitaCore->GetChatManager()->Write("Please specify a command to be repeated."); } return true; } else if (_stricmp(arg.c_str(), "stop") == 0) { _ispluginrunning = false; this->m_AshitaCore->GetChatManager()->Write("Cycle terminated!"); return true; } else if (_stricmp(arg.c_str(), "debug") == 0) { _debug = !(_debug); this->m_AshitaCore->GetChatManager()->Writef("Repeat debug set to: %s", _debug ? "True" : "False" ); return true; } else { PrintHelp(); return true; } // Return false here to allow unhandled commands to continue to be processed. return false; } void Repeat::PrintHelp() { this->m_AshitaCore->GetChatManager()->Write("Repeat Command Listing: /rp, /repeat or /repeater are all valid:"); this->m_AshitaCore->GetChatManager()->Write("/rp [set|unset] [command] - Set or Unset command to be repeated."); this->m_AshitaCore->GetChatManager()->Write("/rp [cycle] - Number of milliseconds to wait before repeating."); this->m_AshitaCore->GetChatManager()->Write("/rp [jitter] - Specify max. random addition to cycle time. Default: 0"); this->m_AshitaCore->GetChatManager()->Write("/rp [start|stop] - Starts or Stops repeating of previously set command"); this->m_AshitaCore->GetChatManager()->Write("/rp debug - Toggles debug prints messages."); this->m_AshitaCore->GetChatManager()->Write("Note: Cycle duration must be within 1s and 3600s (1000ms to 3600000ms)."); this->m_AshitaCore->GetChatManager()->Write("Note: Jitter duration must be within 0s and 3600s (1ms to 3600000ms; 0 = disabled)."); } uint32_t Repeat::ThreadEntry(void) { while (!this->IsTerminated()) { if (_ispluginrunning) { _tickcount = max(0, _tickcount - 1); if (_tickcount == 0) { if (_debug) this->m_AshitaCore->GetChatManager()->Writef("Command being executed is: %s", command.c_str()); this->m_AshitaCore->GetChatManager()->QueueCommand(command.c_str(), -1); if (doJitter) { _jitter = (rand() % _maxjitter); if (_debug) { this->m_AshitaCore->GetChatManager()->Writef("cycle time: %ims jitter: %ims", _userdelayinms, _jitter); } _tickcount = _userdelayinms + _jitter; } else { _tickcount = _userdelayinms; } } } ::Sleep(1); } return 0; } bool Repeat::IsNumber(const char* Input) { bool Decimal = false; for (unsigned int X = 0; X < strlen(Input); X++) { if (Input[X] == '-') { if (X != 0) return false; } else if (Input[X] == '.') { if (Decimal) return false; Decimal = true; } else if (!isdigit(Input[X])) return false; } return true; } uint32_t Repeat::GetArg(const char* text, std::string* buffer) { std::string working(text); if (working[0] == '"') { size_t second = working.substr(1).find_first_of('"'); if (second != string::npos) { *buffer = working.substr(1, second); return second + 1; } } size_t space = working.find_first_of(' '); if (space != string::npos) { *buffer = working.substr(0, space); return space; } *buffer = string(text); return strlen(text); } /** * Invoked when incoming text being sent to the chat log is being processed. * * @param {int16_t} mode - The mode of the message being added to the chatlog. * @param {const char*} message - The raw message being added to the chat log. * @param {int16_t*} modifiedMode - The modified mode, if any, that has been altered by other plugins/addons. * @param {char*} modifiedMessage - The modified message, if any, that has been altered by other plugins/addons. * @param {bool} blocked - Flag if this message has been blocked already by another plugin. (Once blocked, other plugins cannot restore it.) * @returns {bool} True if handled and should be blocked, false otherwise. * * @notes * * Plugins can block the incoming text line by returning true in this function. * Plugins can override the incoming text mode by setting the value of modifiedMode. * Plugins can override the incoming text by writing a new message to the modifiedMessage buffer. * Plugins can check if other plugins have blocked the current message by checking of the blocked param is true. */ bool Repeat::HandleIncomingText(int16_t mode, const char* message, int16_t* modifiedMode, char* modifiedMessage, bool blocked) { UNREFERENCED_PARAMETER(mode); UNREFERENCED_PARAMETER(message); UNREFERENCED_PARAMETER(modifiedMode); UNREFERENCED_PARAMETER(modifiedMessage); UNREFERENCED_PARAMETER(blocked); return false; } /** * Invoked when outgoing text has not been handled by other plugins/addons. * Invoked after HandleCommand if nothing else processed the data. * * @param {int16_t} mode - The type of the text that is being sent. (See Ashita::CommandInputType enumeration.) * @param {const char*} message - The raw message being sent. * @param {int16_t*} modifiedMode - The modified mode, if any, that has been altered by other plugins/addons. * @param {char*} modifiedMessage - The modified message, if any, that has been altered by other plugins/addons. * @param {bool} blocked - Flag if this message has been blocked already by another plugin. (Once blocked, other plugins cannot restore it.) * @returns {bool} True if handled and should be blocked, false otherwise. * * @notes * * Plugins can block the outgoing text line by returning true in this function. * Plugins can override the outgoing text mode by setting the value of modifiedMode. * Plugins can override the outgoing text by writing a new message to the modifiedMessage buffer. * Plugins can check if other plugins have blocked the current message by checking of the blocked param is true. * * Plugins can use this event as a last-ditch effort to handle outgoing text being sent from the client. * This event can be used for overriding things like custom token parsing for things such as: * %player_name% to be parsed out and replaced with the actual player name. */ bool Repeat::HandleOutgoingText(int32_t type, const char* message, int32_t* modifiedType, char* modifiedMessage, bool blocked) { UNREFERENCED_PARAMETER(type); UNREFERENCED_PARAMETER(message); UNREFERENCED_PARAMETER(modifiedType); UNREFERENCED_PARAMETER(modifiedMessage); UNREFERENCED_PARAMETER(blocked); return false; } /** * Invoked when an incoming packet is being handled. * * @param {uint16_t} id - The id of the packet. * @param {uint32_t} size - The size of the packet data. * @param {void*} data - The raw data of the packet. * @param {void*} modified - The modified data, if any, that has been altered by other plugins/addons. * @param {bool} blocked - Flag if this message has been blocked already by another plugin. (Once blocked, other plugins cannot restore it.) * @returns {bool} True if handled and should be blocked, false otherwise. * * @notes * * Plugins can block the packet by returning true in this function. * Plugins can alter the data of the packet by editing the modified data parameter. * Plugins can check if other plugins have blocked the current packet by checking if the blocked param is true. * * Please note; altering packets incorrectly or altering the flow of packets incorrectly can have adverse affects * and possibly lead to players being banned. Edit with caution! */ bool Repeat::HandleIncomingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked) { UNREFERENCED_PARAMETER(id); UNREFERENCED_PARAMETER(size); UNREFERENCED_PARAMETER(data); UNREFERENCED_PARAMETER(modified); UNREFERENCED_PARAMETER(blocked); return false; } /** * Invoked when an outgoing packet is being handled. * * @param {uint16_t} id - The id of the packet. * @param {uint32_t} size - The size of the packet data. * @param {void*} data - The raw data of the packet. * @param {void*} modified - The modified data, if any, that has been altered by other plugins/addons. * @param {bool} blocked - Flag if this message has been blocked already by another plugin. (Once blocked, other plugins cannot restore it.) * @returns {bool} True if handled and should be blocked, false otherwise. * * @notes * * Plugins can block the packet by returning true in this function. * Plugins can alter the data of the packet by editing the modified data parameter. * Plugins can check if other plugins have blocked the current packet by checking if the blocked param is true. * * Please note; altering packets incorrectly or altering the flow of packets incorrectly can have adverse affects * and possibly lead to players being banned. Edit with caution! */ bool Repeat::HandleOutgoingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked) { UNREFERENCED_PARAMETER(id); UNREFERENCED_PARAMETER(size); UNREFERENCED_PARAMETER(data); UNREFERENCED_PARAMETER(modified); UNREFERENCED_PARAMETER(blocked); return false; } /** * Invoked when the plugin is being initialized for Direct3D rendering. * * Note: * Plugins must return true with this function in order to have the other Direct3D * functions invoked. Returning false is ideal here if you do not need to use the * Direct3D functions within your plugin. This can help with overall performance. * * @param {IDirect3DDevice8*} device - The Direct3D device pointer currently being used by the game. * @return {bool} True if the plugin should handle the other Direct3D messages, false otherwise. */ bool Repeat::Direct3DInitialize(IDirect3DDevice8* device) { // Store the device for later usage.. this->m_Direct3DDevice = device; /** * Returning true here for the sake of the example plugin! If you do not need * to make use of any of the Direct3D calls, it is recommended to return false * here to save on performance! */ return true; } /** * Invoked when the plugin is being unloaded and is able to cleanup its Direct3D related resources. * * @notes * * Plugins should use this function to cleanup Direct3D related objects. * - Index Buffers, Vertex Buffers * - Textures */ void Repeat::Direct3DRelease(void) { } /** * Invoked when the Direct3D device is beginning to render. (BeginScene) * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called after BeginScene is called. */ void Repeat::Direct3DPreRender(void) { } /** * Invoked when the Direct3D device is ending its rendering. (EndScene) * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before EndScene is called. */ void Repeat::Direct3DRender(void) { } /** * Invoked when the Direct3D device is presenting the scene. (Present) * * @param {RECT*} pSourceRect - The source rect being rendered into. * @param {RECT*} pDestRect - The destination rect being rendered from. * @param {HWND} hDestWindowOverride - The window handle, if any, to override the rendering into. * @param {RGNDATA*} pDirtyRegion - The dirty region data. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before Present is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DPresent(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion) { UNREFERENCED_PARAMETER(pSourceRect); UNREFERENCED_PARAMETER(pDestRect); UNREFERENCED_PARAMETER(hDestWindowOverride); UNREFERENCED_PARAMETER(pDirtyRegion); return false; } /** * Invoked when the Direct3D device is drawing a primitive to the scene. (DrawPrimitive) * * @param {D3DPRIMITIVETYPE} PrimitiveType - The type of primitive being rendered. * @param {UINT} StartVertex - Index of the first vertex to load. * @param {UINT} PrimitiveCount - Number of primitives to render. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before DrawPrimitive is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DDrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { UNREFERENCED_PARAMETER(PrimitiveType); UNREFERENCED_PARAMETER(StartVertex); UNREFERENCED_PARAMETER(PrimitiveType); return false; } /** * Invoked when the Direct3D device is drawing a primitive to the scene. (DrawIndexedPrimitive) * * @param {D3DPRIMITIVETYPE} PrimitiveType - The type of primitive being rendered. * @param {UINT} minIndex - Minimum vertex index for vertices used during this call. * @param {UINT} numVertices - Number of vertices used during this call * @param {UINT} startIndex - Index of the first index to use when accesssing the vertex buffer. * @param {UINT} primCount - Number of primitives to render. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before DrawIndexedPrimitive is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DDrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) { UNREFERENCED_PARAMETER(PrimitiveType); UNREFERENCED_PARAMETER(minIndex); UNREFERENCED_PARAMETER(NumVertices); UNREFERENCED_PARAMETER(startIndex); UNREFERENCED_PARAMETER(primCount); return false; } /** * Invoked when the Direct3D device is drawing a primitive to the scene. (DrawPrimitiveUP) * * @param {D3DPRIMITIVETYPE} PrimitiveType - The type of primitive being rendered. * @param {UINT} PrimitiveCount - Number of primitives to render. * @param {void*} pVertexStreamZeroData - User memory pointer to the vertex data. * @param {UINT} VertexStreamZeroStride - The number of bytes of data for each vertex. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before DrawPrimitiveUP is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DDrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { UNREFERENCED_PARAMETER(PrimitiveType); UNREFERENCED_PARAMETER(PrimitiveCount); UNREFERENCED_PARAMETER(pVertexStreamZeroData); UNREFERENCED_PARAMETER(VertexStreamZeroStride); return false; } /** * Invoked when the Direct3D device is drawing a primitive to the scene. (DrawIndexedPrimitiveUP) * * @param {D3DPRIMITIVETYPE} PrimitiveType - The type of primitive being rendered. * @param {UINT} MinVertexIndex - Minimum vertex index. * @param {UINT} NumVertexIndices - Number of vertices used during this call. * @param {UINT} PrimitiveCount - Number of primitives to render. * @param {void*} pIndexData - User memory pointer to the index data. * @param {D3DFORMAT} IndexDataFormat - The format of the index data. * @param {void*} pVertexStreamZeroData - User memory pointer to the vertex data. * @param {UINT} VertexStreamZeroStride - The number of bytes of data for each vertex. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before DrawIndexedPrimitiveUP is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DDrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { UNREFERENCED_PARAMETER(PrimitiveType); UNREFERENCED_PARAMETER(MinVertexIndex); UNREFERENCED_PARAMETER(NumVertexIndices); UNREFERENCED_PARAMETER(PrimitiveCount); UNREFERENCED_PARAMETER(pIndexData); UNREFERENCED_PARAMETER(IndexDataFormat); UNREFERENCED_PARAMETER(pVertexStreamZeroData); UNREFERENCED_PARAMETER(VertexStreamZeroStride); return false; } /** * Invoked when the Direct3D device is setting a render state. (SetRenderState) * * @param {D3DRENDERSTATETYPE} state - The render state to alter. * @param {DWORD} value - The new value for the render state. * @returns {bool} True if the call should be blocked, false otherwise. * * @notes * * This will only be called if you returned true inside of Direct3DInitialize! * This function is called before SetRenderState is called. * * Plugins can block the call from happening by returning true. */ bool Repeat::Direct3DSetRenderState(D3DRENDERSTATETYPE State, DWORD Value) { UNREFERENCED_PARAMETER(State); UNREFERENCED_PARAMETER(Value); return false; } /** * Returns the interface version this plugin was compiled with. * * @returns {double} The Ashita interface version. */ __declspec(dllexport) double __stdcall GetInterfaceVersion(void) { return ASHITA_INTERFACE_VERSION; } /** * Creates and populates the plugins information structure. * * @returns {double} The Ashita interface version. */ __declspec(dllexport) void __stdcall CreatePluginInfo(plugininfo_t* info) { // Store the pointer from Ashita.. g_PluginInfo = info; // Populate the structure with our plugins information.. strcpy_s(info->Author, sizeof(info->Author), "Felgar"); strcpy_s(info->Name, sizeof(info->Name), "Repeat"); info->InterfaceVersion = ASHITA_INTERFACE_VERSION; info->PluginVersion = 3.0f; info->Priority = 0; } /** * Creates an instance of the plugins main class. * * @returns {IPlugin*} The plugin base class instance created by this plugin. */ __declspec(dllexport) IPlugin* __stdcall CreatePlugin(void) { return (IPlugin*)new Repeat; }