Browse Source

1.15 - Rewrote follow system, new features added, see documentation for usage.

master
Thorny 4 years ago
parent
commit
ed2ab118af
  1. 5
      .gitignore
  2. 31
      release/docs/MultiSend.txt
  3. BIN
      release/plugins/MultiSend.dll
  4. 168
      src/MultiSend/Commands.cpp
  5. 71
      src/MultiSend/Follow.cpp
  6. 100
      src/MultiSend/Groups.cpp
  7. 122
      src/MultiSend/IO.cpp
  8. 59
      src/MultiSend/Main.cpp
  9. 47
      src/MultiSend/MultiSend.h
  10. 24
      src/MultiSend/MultiSend.vcxproj
  11. 16
      src/MultiSend/MultiSend.vcxproj.filters
  12. 30
      src/MultiSend/Structs.h
  13. 84
      src/MultiSend/Thread.cpp
  14. 25
      src/MultiSend/packets.cpp
  15. 87
      src/MultiSend/text_sanitizing.cpp

5
.gitignore vendored

@ -1,3 +1,2 @@ @@ -1,3 +1,2 @@
*.vs/*
*ipch/*
*src*Release/*
src/.vs/
src/MultiSend/Release/

31
release/docs/MultiSend.txt

@ -1,13 +1,32 @@ @@ -1,13 +1,32 @@
Multisend is a replacement for servo. No synchronization is needed, just load and go.
Commands are as follows(all can be prefixed with /ms or /multisend):
Commands to send input to other instances on the same PC:
/ms send [command] - Sends the command to all characters with MultiSend loaded.
/ms sendto CharName [command] - Sends the command to a specific character, if they have MultiSend loaded.
/ms sendgroup GroupName [command] - Sends the command to all characters listed in a group. Groups can be defined in Ashita/Config/MultiSend.xml. See XML Structure file for example.
/ms followme on/off - Enables or disables followme. When followme is enabled, any characters with follow enabled will follow the player who last activated followme.
/ms follow on/off - Enables or disables follow. Any character with follow enabled with follow the player who last activated followme.
/ms ignoreself on/off - When enabled, any command that would effect the local character is not executed by the local character.
/ms debug on/off - When enabled, all received commands are printed to log and any character with followme updated will spam log with position updates. For debug purposes, obviously.
/ms sendgroup GroupName [command] - Sends the command to all characters listed in a group. Groups can be defined in Ashita/Config/MultiSend.xml. See XML Structure file for example.\
/ms sendothers [command] - Sends a command to all characters except for the current character.
/ms sendparty - Sends a command to all characters in the current character's immediate party. This includes the current character unless ignoreself is turned on.
/ms sendally - Sends a command to all characters in the current character's immediate alliance. This includes the current character unless ignoreself is turned on.
These have hardcoded aliases as well:
/mss = /ms send
/mst = /ms sendto
/mso = /ms sendothers
/msp = /ms sendparty
/msa = /ms sendally
/msg = /ms sendgroup
Configuration:
/ms followmax # - Sets a max range(in yalms). If follow target is more than this many yalms away, but in same zone, follow won't move.
-I recommend setting between 30 and 100 to prevent following from trying to use portals.
-Default is 5000, which will be the same behavior as before this setting was added.
/ms followme on/off - Enables or disables followme. When followme is enabled, any characters with follow enabled will follow the player who last activated followme. Default: OFF.
/ms follow on/off - Enables or disables follow. Any character with follow enabled with follow the player who last activated followme. Default: ON
/ms attemptzone on/off - Enables or disables attempted zoning. When enabled, if the leader zones, the other characters will continue running in the direction they were last running to follow suit. Default: OFF
NOTE: If you are using a home point, survival guide, etc, it will be detected as long as you stand still throughout the process and nobody will run off.
CONT: If you move after first acting upon the object or sending an uberwarp command, chars may run off.
/ms ignoreself on/off - When enabled, any command that would effect the local character is not executed by the local character. Default: OFF
/ms debug on/off - When enabled, all received commands are printed to log and any character with followme updated will spam log with position updates. For debug purposes, obviously. Default: OFF
/ms reload - Will reload groups xml.
/ms help - Print an ingame reference.

BIN
release/plugins/MultiSend.dll

Binary file not shown.

168
src/MultiSend/Commands.cpp

@ -21,9 +21,8 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -21,9 +21,8 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
if ((_stricmp(arg.c_str(), "send") == 0)
|| (_stricmp(arg.c_str(), "/mss") == 0))
{
if (strlen(com) < 2) return true;
SendCommand(0xFFFF0000, com + 1);
SendCommand(multisend_type::all, 0, com + 1);
return true;
}
@ -40,25 +39,49 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -40,25 +39,49 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
arg = SubValues(arg);
Claim(&(MMF_Pointer->Name.ProcessID), 0);
Claim(&(p_MMF->Name.ProcessID), 0);
for (int x = 0; x < 100; x++)
{
if (MMF_Pointer->Name.Names[x].Active)
if (p_MMF->Name.Names[x].Active)
{
if (_stricmp((const char*)&(MMF_Pointer->Name.Names[x].Name), arg.c_str()) == 0)
if (_stricmp((const char*)&(p_MMF->Name.Names[x].Name), arg.c_str()) == 0)
{
SendCommand(MMF_Pointer->Name.Names[x].Process, com + 1);
InterlockedExchange(&(MMF_Pointer->Name.ProcessID), 0);
SendCommand(multisend_type::single, p_MMF->Name.Names[x].Process, com + 1);
InterlockedExchange(&(p_MMF->Name.ProcessID), 0);
return true;
}
}
}
InterlockedExchange(&(MMF_Pointer->Name.ProcessID), 0);
InterlockedExchange(&(p_MMF->Name.ProcessID), 0);
m_AshitaCore->GetChatManager()->Write("MultiSend: Character not found.");
return true;
}
else if ((_stricmp(arg.c_str(), "sendothers") == 0)
|| (_stricmp(arg.c_str(), "/mso") == 0))
{
if (strlen(com) < 2) return true;
SendCommand(multisend_type::others, ::GetCurrentProcessId(), com + 1);
return true;
}
else if ((_stricmp(arg.c_str(), "sendparty") == 0)
|| (_stricmp(arg.c_str(), "/msp") == 0))
{
if (strlen(com) < 2) return true;
SendCommand(multisend_type::party, m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(0), com + 1);
return true;
}
else if ((_stricmp(arg.c_str(), "sendally") == 0)
|| (_stricmp(arg.c_str(), "/msa") == 0))
{
if (strlen(com) < 2) return true;
SendCommand(multisend_type::alliance, m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(0), com + 1);
return true;
}
else if ((_stricmp(arg.c_str(), "sendgroup") == 0)
|| (_stricmp(arg.c_str(), "/msg") == 0))
{
@ -70,11 +93,11 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -70,11 +93,11 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
com++;
com += GetArg(com, &arg);
for (std::map<uint16_t, string>::iterator it = m_Group.Map.begin(); it != m_Group.Map.end(); it++)
for (std::map<uint16_t, string>::iterator it = s_group.Map.begin(); it != s_group.Map.end(); it++)
{
if (_stricmp((*it).second.c_str(), arg.c_str()) == 0)
{
SendCommand(0x8FFF0000 + (*it).first, com + 1);
SendCommand(multisend_type::group, (*it).first, com + 1);
return true;
}
}
@ -89,43 +112,76 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -89,43 +112,76 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
com++;
com += GetArg(com, &arg);
if (_stricmp(arg.c_str(), "on") == 0)
bool toggle = !(p_MMF->Follow.target_process_id == GetCurrentProcessId());
if (_stricmp(arg.c_str(), "on") == 0) toggle = true;
else if (_stricmp(arg.c_str(), "off") == 0) toggle = false;
if (toggle)
{
InterlockedExchange(&(MMF_Pointer->Follow.FollowID), GetCurrentProcessId());
if (!Zoning)
InterlockedExchange(&(p_MMF->Follow.target_process_id), GetCurrentProcessId());
uint16_t zone = m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0);
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
if ((zone != 0) && (myindex != 0))
{
Following = false;
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
uint32_t mPosX = (uint32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex) * 100);
uint32_t mPosZ = (uint32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex) * 100);
MMF_Pointer->Follow.PosX = mPosX;
MMF_Pointer->Follow.PosZ = mPosZ;
MMF_Pointer->Follow.Follow = 1;
p_MMF->Follow.zone = zone;
p_MMF->Follow.position_x = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex);
p_MMF->Follow.position_z = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex);
p_MMF->Follow.idle_count = 0;
}
else
{
Following = false;
MMF_Pointer->Follow.Follow = 3;
p_MMF->Follow.zone = 0;
}
m_AshitaCore->GetChatManager()->Write("MultiSend: Followme enabled.");
}
else
{
p_MMF->Follow.zone = 0;
InterlockedExchange(&(p_MMF->Follow.target_process_id), 0);
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Followme is currently %s.", (p_MMF->Follow.target_process_id == GetCurrentProcessId()) ? "enabled" : "disabled");
return true;
}
else if (_stricmp(arg.c_str(), "followmax") == 0)
{
if (strlen(com) < 2) return true;
com++;
com += GetArg(com, &arg);
float dist = atof(arg.c_str());
if (dist < 1.0f) dist = 1.0f;
else if (dist > 5000.0f) dist = 5000.0f;
c_maxdist = dist;
m_AshitaCore->GetChatManager()->Writef("MultiSend: Maximum follow distance is currently %f.", c_maxdist);
return true;
}
else if (_stricmp(arg.c_str(), "follow") == 0)
{
if (strlen(com) < 2) return true;
com++;
com += GetArg(com, &arg);
if (_stricmp(arg.c_str(), "on") == 0)
{
c_follow = true;
}
else if (_stricmp(arg.c_str(), "off") == 0)
{
InterlockedExchange(&(MMF_Pointer->Follow.FollowID), 0);
MMF_Pointer->Follow.Follow = 0;
m_AshitaCore->GetChatManager()->Write("MultiSend: Followme disabled.");
c_follow = false;
}
else
{
m_AshitaCore->GetChatManager()->Writef("MultiSend: Followme is currently %s.", (MMF_Pointer->Follow.FollowID == GetCurrentProcessId()) ? "enabled" : "disabled");
c_follow = !c_follow;
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Follow is currently %s.", c_follow ? "enabled" : "disabled");
return true;
}
else if (_stricmp(arg.c_str(), "follow") == 0)
else if (_stricmp(arg.c_str(), "attemptzone") == 0)
{
if (strlen(com) < 2) return true;
com++;
@ -133,21 +189,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -133,21 +189,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
if (_stricmp(arg.c_str(), "on") == 0)
{
FollowEnabled = true;
m_AshitaCore->GetChatManager()->Write("MultiSend: Follow enabled. Note that if someone is not currently using followme, no movement will occur.");
c_attemptzone = true;
}
else if (_stricmp(arg.c_str(), "off") == 0)
{
FollowEnabled = false;
m_AshitaCore->GetChatManager()->Write("MultiSend: Follow disabled.");
c_attemptzone = false;
}
else
{
m_AshitaCore->GetChatManager()->Writef("MultiSend: Follow is currently %s.", FollowEnabled ? "enabled" : "disabled");
c_attemptzone = !c_attemptzone;
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Attempted zoning currently %s.", c_attemptzone ? "enabled" : "disabled");
return true;
}
@ -159,20 +212,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -159,20 +212,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
if (_stricmp(arg.c_str(), "on") == 0)
{
IgnoreSelf = true;
m_AshitaCore->GetChatManager()->Write("MultiSend: Now ignoring self-published commands.");
c_ignoreself = true;
}
else if (_stricmp(arg.c_str(), "off") == 0)
{
IgnoreSelf = false;
m_AshitaCore->GetChatManager()->Write("MultiSend: Now accepting self-published commands.");
c_ignoreself = false;
}
else
{
m_AshitaCore->GetChatManager()->Writef("MultiSend: Ignore self is currently %s.", IgnoreSelf ? "enabled" : "disabled");
c_ignoreself = !c_ignoreself;
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Ignore self is currently %s.", c_ignoreself ? "enabled" : "disabled");
return true;
}
@ -184,21 +235,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -184,21 +235,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
if (_stricmp(arg.c_str(), "on") == 0)
{
_Debug = true;
m_AshitaCore->GetChatManager()->Write("MultiSend: Debug prints enabled.");
c_debug = true;
}
else if (_stricmp(arg.c_str(), "off") == 0)
{
_Debug = false;
m_AshitaCore->GetChatManager()->Write("MultiSend: Debug prints disabled.");
c_debug = false;
}
else
{
m_AshitaCore->GetChatManager()->Writef("MultiSend: Debug prints currently %s.", _Debug ? "enabled" : "disabled");
c_debug = !c_debug;
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Debug prints currently %s.", c_debug ? "enabled" : "disabled");
return true;
}
@ -210,21 +258,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -210,21 +258,18 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
if (_stricmp(arg.c_str(), "on") == 0)
{
_SafeMode = true;
m_AshitaCore->GetChatManager()->Write("MultiSend: Safe mode enabled.");
c_safemode = true;
}
else if (_stricmp(arg.c_str(), "off") == 0)
{
_SafeMode = false;
m_AshitaCore->GetChatManager()->Write("MultiSend: Safe mode disabled.");
c_safemode = false;
}
else
{
m_AshitaCore->GetChatManager()->Writef("MultiSend: Safe mode currently %s.", _SafeMode ? "enabled" : "disabled");
c_safemode = !c_safemode;
}
m_AshitaCore->GetChatManager()->Writef("MultiSend: Safe mode currently %s.", c_safemode ? "enabled" : "disabled");
return true;
}
@ -244,6 +289,7 @@ bool MultiSend::HandleCommand(const char* command, int32_t type) @@ -244,6 +289,7 @@ bool MultiSend::HandleCommand(const char* command, int32_t type)
m_AshitaCore->GetChatManager()->Write("/ms followme on/off - When enabled, all characters with follow enabled will follow this character. Only one character can have this active at a time, if you activate it on a second the first will deactivate automatically.");
m_AshitaCore->GetChatManager()->Write("/ms reload - Reloads group file without reloading MultiSend.");
m_AshitaCore->GetChatManager()->Write("/ms ignoreself on/off - When enabled, send and sendgroup commands sent by this character will not execute on this character.");
m_AshitaCore->GetChatManager()->Write("/ms attemptzone on/off - When enabled, multisend will continue running in the direction you were running when follow leader zones.");
m_AshitaCore->GetChatManager()->Write("/ms debug on/off - When enabled, debug prints will be visible.");
m_AshitaCore->GetChatManager()->Write("/ms safemode on/off - When enabled, '/echo' will be inserted for commands missing the leading '/' to prevent chatlog spam.");
return true;

71
src/MultiSend/Follow.cpp

@ -13,31 +13,72 @@ bool MultiSend::Direct3DInitialize(IDirect3DDevice8* lpDevice) @@ -13,31 +13,72 @@ bool MultiSend::Direct3DInitialize(IDirect3DDevice8* lpDevice)
*/
void MultiSend::Direct3DPreRender(void)
{
if (FollowEnabled)
if (c_follow)
{
if (Following)
if (p_MMF->Follow.target_process_id == ::GetCurrentProcessId()) return;
if (p_MMF->Follow.target_process_id == 0)
{
if (s_last_run_state)
{
p_Follow->Autorun = 0;
s_last_run_state = false;
}
}
else if (p_MMF->Follow.zone == m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0))
{
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
float MyX = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex);
float MyZ = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex);
double Distance = sqrt(pow(PositionX - MyX, 2) + pow(PositionZ - MyZ, 2));
float my_pos_x = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex);
float my_pos_z = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex);
s_vector_x = p_MMF->Follow.position_x - my_pos_x;
s_vector_z = p_MMF->Follow.position_z - my_pos_z;
double distance = sqrt(pow(s_vector_x, 2) + pow(s_vector_z, 2));
if (Distance > 0.4f)
if ((distance > 0.4f) && (distance < c_maxdist))
{
StructPointer->DirX = PositionX - MyX;
StructPointer->DirY = 0;
StructPointer->DirZ = PositionZ - MyZ;
StructPointer->Autorun = 1;
p_Follow->FollowID = 0;
p_Follow->FollowIndex = 0;
p_Follow->DirX = s_vector_x;
p_Follow->DirY = 0;
p_Follow->DirZ = s_vector_z;
p_Follow->Autorun = 1;
s_last_run_state = true;
}
else
else if (s_last_run_state)
{
StructPointer->Autorun = 0;
p_Follow->Autorun = 0;
s_last_run_state = false;
}
}
else if (StopFollow)
else if (p_MMF->Follow.zone == 0)
{
StructPointer->Autorun = 0;
StopFollow = false;
if ((c_attemptzone)
&& (p_MMF->Follow.lastzone == m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0))
&& (p_MMF->Follow.idle_count < 5000))
{
p_Follow->FollowID = 0;
p_Follow->FollowIndex = 0;
p_Follow->DirX = s_vector_x;
p_Follow->DirY = 0;
p_Follow->DirZ = s_vector_z;
p_Follow->Autorun = 1;
s_last_run_state = true;
}
else if (s_last_run_state)
{
p_Follow->Autorun = 0;
s_last_run_state = false;
}
}
else if (s_last_run_state)
{
p_Follow->Autorun = 0;
s_last_run_state = false;
}
}
else if (s_last_run_state)
{
p_Follow->Autorun = 0;
s_last_run_state = false;
}
}

100
src/MultiSend/Groups.cpp

@ -3,24 +3,64 @@ @@ -3,24 +3,64 @@
#include <iostream>
using namespace rapidxml;
bool MultiSend::MatchID(uint32_t ID)
bool MultiSend::CheckMatch(MMF_ICommand_Single command)
{
if ((ID & 0xFFFF0000) == 0xFFFF0000)
if ((c_ignoreself) && (::GetCurrentProcessId() == command.sender_process_id)) return false;
if (command.type == multisend_type::all)
{
return true;
}
if ((ID & 0x8FFF0000) == 0x8FFF0000)
else if (command.type == multisend_type::others)
{
return (::GetCurrentProcessId() != command.param);
}
else if (command.type == multisend_type::group)
{
if (std::find(c_groups.begin(), c_groups.end(), command.param) != c_groups.end())
{
return true;
}
return false;
}
else if (command.type == multisend_type::party)
{
for (int x = 0; x < 6; x++)
{
if ((m_AshitaCore->GetDataManager()->GetParty()->GetMemberActive(x))
&& (m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(x) == command.param))
{
return true;
}
}
return false;
}
else if (command.type == multisend_type::alliance)
{
for (int x = 0; x < 18; x++)
{
if ((m_AshitaCore->GetDataManager()->GetParty()->GetMemberActive(x))
&& (m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(x) == command.param))
{
return true;
}
}
return false;
}
else if (command.type == multisend_type::single)
{
return (::GetCurrentProcessId() == command.param);
}
else
{
uint16_t GroupID = (ID & 0x0000FFFF);
return (std::find(Groups.begin(), Groups.end(), GroupID) != Groups.end());
return false;
}
return (::GetCurrentProcessId() == ID);
}
void MultiSend::LoadGroups()
{
m_Group.Map.clear();
Groups.clear();
s_group.Map.clear();
c_groups.clear();
string Path = m_AshitaCore->GetAshitaInstallPathA();
Path += "config\\MultiSend.xml";
@ -30,37 +70,37 @@ void MultiSend::LoadGroups() @@ -30,37 +70,37 @@ void MultiSend::LoadGroups()
Reader.seekg(0, ios::end);
uint32_t Size = (uint32_t)Reader.tellg();
m_Group.rawdata = new char[Size + 1];
s_group.rawdata = new char[Size + 1];
Reader.seekg(0, ios::beg);
Reader.read(m_Group.rawdata, Size);
Reader.read(s_group.rawdata, Size);
Reader.close();
m_Group.rawdata[Size] = '\0';
s_group.rawdata[Size] = '\0';
try
{
m_Group.doc.parse<0>(m_Group.rawdata);
s_group.doc.parse<0>(s_group.rawdata);
m_AshitaCore->GetChatManager()->Write("MultiSend: Groups loaded.");
m_Group.Loaded = true;
s_group.Loaded = true;
}
catch (...)
{
m_AshitaCore->GetChatManager()->Write("MultiSend: Groups failed to parse.");
m_Group.doc.clear();
m_Group.Loaded = false;
delete m_Group.rawdata;
s_group.doc.clear();
s_group.Loaded = false;
delete s_group.rawdata;
}
}
else
{
if (m_Group.Loaded)
if (s_group.Loaded)
{
m_Group.doc.clear();
delete m_Group.rawdata;
m_Group.Loaded = false;
s_group.doc.clear();
delete s_group.rawdata;
s_group.Loaded = false;
}
m_AshitaCore->GetChatManager()->Write("MultiSend: No groups file found.");
}
if (m_Group.Loaded)
if (s_group.Loaded)
{
ReadXML();
MatchGroups();
@ -69,9 +109,9 @@ void MultiSend::LoadGroups() @@ -69,9 +109,9 @@ void MultiSend::LoadGroups()
void MultiSend::ReadXML()
{
m_Group.Map.clear();
s_group.Map.clear();
xml_node<> *Node = m_Group.doc.first_node();
xml_node<> *Node = s_group.doc.first_node();
if (_stricmp(Node->name(), "multisend") == 0) Node = Node->first_node();
while (Node)
{
@ -83,7 +123,7 @@ void MultiSend::ReadXML() @@ -83,7 +123,7 @@ void MultiSend::ReadXML()
xml_attribute<> *Attr2 = Node->first_attribute("name");
if (Attr2)
{
m_Group.Map.insert(std::make_pair((uint16_t)atoi(Attr->value()), std::string(Attr2->value())));
s_group.Map.insert(std::make_pair((uint16_t)atoi(Attr->value()), std::string(Attr2->value())));
}
}
}
@ -93,11 +133,11 @@ void MultiSend::ReadXML() @@ -93,11 +133,11 @@ void MultiSend::ReadXML()
void MultiSend::MatchGroups()
{
Groups.clear();
if (CurrentName.length() < 3) return;
if (!m_Group.Loaded) return;
c_groups.clear();
if (s_name.length() < 3) return;
if (!s_group.Loaded) return;
xml_node<> *Node = m_Group.doc.first_node();
xml_node<> *Node = s_group.doc.first_node();
if (_stricmp(Node->name(), "multisend") == 0) Node = Node->first_node();
while (Node)
{
@ -112,9 +152,9 @@ void MultiSend::MatchGroups() @@ -112,9 +152,9 @@ void MultiSend::MatchGroups()
uint16_t Index = (uint16_t)atoi(Attr->value());
for (xml_node<> *SubNode = Node->first_node("char"); SubNode != NULL; SubNode = SubNode->next_sibling("char"))
{
if (_stricmp(CurrentName.c_str(), SubNode->value()) == 0)
if (_stricmp(s_name.c_str(), SubNode->value()) == 0)
{
Groups.push_back(Index);
c_groups.push_back(Index);
break;
}
}

122
src/MultiSend/IO.cpp

@ -2,137 +2,115 @@ @@ -2,137 +2,115 @@
bool MultiSend::ReadCommand()
{
if (MMF_Pointer->Command.Command[Position].Active)
if (p_MMF->Command.Command[s_position].active)
{
if (MatchID(MMF_Pointer->Command.Command[Position].Targets))
if (CheckMatch(p_MMF->Command.Command[s_position]))
{
if ((!IgnoreSelf)
|| (GetCurrentProcessId() != MMF_Pointer->Command.Command[Position].SendProcess))
const char* text = new char[248];
memcpy((void*)text, &(p_MMF->Command.Command[s_position].command), 248);
if (c_debug)
{
const char* text = new char[248];
memset((void*)text, 0, 248);
memcpy((void*)text, &(MMF_Pointer->Command.Command[Position].Command), 248);
if (_Debug)
{
m_AshitaCore->GetChatManager()->Writef("Sending command: %s", text);
}
if (m_AshitaCore->GetPluginManager()->GetPlugin("Shorthand"))
{
m_AshitaCore->GetChatManager()->QueueCommand(text, -1);
}
else
{
m_AshitaCore->GetChatManager()->QueueCommand(text, 0);
}
delete text;
m_AshitaCore->GetChatManager()->Writef("Sending command: %s", text);
}
if (m_AshitaCore->GetPluginManager()->GetPlugin("Shorthand"))
{
m_AshitaCore->GetChatManager()->QueueCommand(text, -1);
}
else
{
m_AshitaCore->GetChatManager()->QueueCommand(text, 0);
}
delete text;
}
Position++;
if (Position == 100) Position = 0;
s_position++;
if (s_position == 100) s_position = 0;
return true;
}
return false;
}
void MultiSend::SetFollow(bool Active)
{
if (Active)
{
Following = false;
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
uint32_t mPosX = (uint32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex) * 100);
uint32_t mPosZ = (uint32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex) * 100);
MMF_Pointer->Follow.PosX = mPosX;
MMF_Pointer->Follow.PosZ = mPosZ;
MMF_Pointer->Follow.Follow = 1;
}
else
{
MMF_Pointer->Follow.Follow = 0;
}
}
void MultiSend::SendCommand(uint32_t ID, const char* Command)
void MultiSend::SendCommand(multisend_type type, uint32_t param, const char* Command)
{
char* Text = new char[248];
memset((void*)Text, 0, 248);
memcpy(Text, Command, strlen(Command));
if (_SafeMode)
if (c_safemode)
SanitizeCommand(Text);
SubValues(Text);
Claim(&(MMF_Pointer->Command.ProcessID), 0);
Claim(&(p_MMF->Command.ProcessID), 0);
int NextPosition = MMF_Pointer->Command.Position + 1;
int NextPosition = p_MMF->Command.Position + 1;
if (NextPosition == 100) NextPosition = 0;
MMF_Pointer->Command.Command[NextPosition].Active = false;
p_MMF->Command.Command[NextPosition].active = false;
memset(&(MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].Command), 0, 248);
memset(&(p_MMF->Command.Command[p_MMF->Command.Position].command), 0, 248);
if (strlen(Text) > 247)
{
memcpy(&(MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].Command), Text, 247);
memcpy(&(p_MMF->Command.Command[p_MMF->Command.Position].command), Text, 247);
}
else
{
memcpy(&(MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].Command), Text, strlen(Text));
memcpy(&(p_MMF->Command.Command[p_MMF->Command.Position].command), Text, strlen(Text));
}
if (_Debug)
if (c_debug)
{
m_AshitaCore->GetChatManager()->Writef("Publishing position %d : %s", MMF_Pointer->Command.Position, Text);
m_AshitaCore->GetChatManager()->Writef("Publishing position %d : %s", p_MMF->Command.Position, Text);
}
MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].SendProcess = GetCurrentProcessId();
MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].Targets = ID;
MMF_Pointer->Command.Command[MMF_Pointer->Command.Position].Active = true;
MMF_Pointer->Command.Position = NextPosition;
InterlockedExchange(&(MMF_Pointer->Command.ProcessID), 0);
p_MMF->Command.Command[p_MMF->Command.Position].sender_process_id = GetCurrentProcessId();
p_MMF->Command.Command[p_MMF->Command.Position].type = type;
p_MMF->Command.Command[p_MMF->Command.Position].param = param;
p_MMF->Command.Command[p_MMF->Command.Position].active = true;
p_MMF->Command.Position = NextPosition;
InterlockedExchange(&(p_MMF->Command.ProcessID), 0);
delete Text;
}
void MultiSend::UpdateName(std::string Name)
{
Claim(&(MMF_Pointer->Name.ProcessID), 0xFFFF0000);
Claim(&(p_MMF->Name.ProcessID), 0xFFFF0000);
bool Written = false;
for (int x = 0; x < 100; x++)
{
if (!MMF_Pointer->Name.Names[x].Active)
if (!p_MMF->Name.Names[x].Active)
{
if (!Written)
{
memcpy(&(MMF_Pointer->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
MMF_Pointer->Name.Names[x].Process = GetCurrentProcessId();
MMF_Pointer->Name.Names[x].Active = 1;
memcpy(&(p_MMF->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
p_MMF->Name.Names[x].Process = GetCurrentProcessId();
p_MMF->Name.Names[x].Active = 1;
Written = true;
}
continue;
}
else if (MMF_Pointer->Name.Names[x].Process == GetCurrentProcessId())
else if (p_MMF->Name.Names[x].Process == GetCurrentProcessId())
{
memset(&(MMF_Pointer->Name.Names[x]), 0, sizeof(MMF_Name_Single));
memset(&(p_MMF->Name.Names[x]), 0, sizeof(MMF_Name_Single));
if (!Written)
{
memcpy(&(MMF_Pointer->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
MMF_Pointer->Name.Names[x].Process = GetCurrentProcessId();
MMF_Pointer->Name.Names[x].Active = 1;
memcpy(&(p_MMF->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
p_MMF->Name.Names[x].Process = GetCurrentProcessId();
p_MMF->Name.Names[x].Active = 1;
Written = true;
}
}
else if (strcmp((const char*)&(MMF_Pointer->Name.Names[x].Name), Name.c_str()) == 0)
else if (strcmp((const char*)&(p_MMF->Name.Names[x].Name), Name.c_str()) == 0)
{
memset(&(MMF_Pointer->Name.Names[x]), 0, sizeof(MMF_Name_Single));
memset(&(p_MMF->Name.Names[x]), 0, sizeof(MMF_Name_Single));
if (!Written)
{
memcpy(&(MMF_Pointer->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
MMF_Pointer->Name.Names[x].Process = GetCurrentProcessId();
MMF_Pointer->Name.Names[x].Active = 1;
memcpy(&(p_MMF->Name.Names[x].Name), Name.c_str(), strlen(Name.c_str()) + 1);
p_MMF->Name.Names[x].Process = GetCurrentProcessId();
p_MMF->Name.Names[x].Active = 1;
Written = true;
}
}
}
CurrentName = Name;
s_name = Name;
MatchGroups();
InterlockedExchange(&(MMF_Pointer->Name.ProcessID), 0);
InterlockedExchange(&(p_MMF->Name.ProcessID), 0);
}
void MultiSend::Claim(uint32_t* Target, uint32_t Mod)

59
src/MultiSend/Main.cpp

@ -27,27 +27,16 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) @@ -27,27 +27,16 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
LoadGroups();
DWORD Pointer = NULL;
MODULEINFO mod = { 0 };
if (!::GetModuleInformation(::GetCurrentProcess(), ::GetModuleHandle("FFXiMain.dll"), &mod, sizeof(MODULEINFO)))
return false;
Pointers* p = (Pointers*)m_AshitaCore->GetPluginManager()->GetPlugin("Pointers");
if (p)
{
Pointer = p->RegisterPointer("movement", "8BCFE8????FFFF8B0D????????E8????????8BE885ED750CB9", 0, 0);
}
else
{
MODULEINFO mod = { 0 };
if (!::GetModuleInformation(::GetCurrentProcess(), ::GetModuleHandle("FFXiMain.dll"), &mod, sizeof(MODULEINFO)))
return false;
Pointer = Ashita::Memory::FindPattern((uintptr_t)mod.lpBaseOfDll, (uintptr_t)mod.SizeOfImage,
"8BCFE8????FFFF8B0D????????E8????????8BE885ED750CB9",
0, 0);
}
Pointer = Ashita::Memory::FindPattern((uintptr_t)mod.lpBaseOfDll, (uintptr_t)mod.SizeOfImage,
"8BCFE8????FFFF8B0D????????E8????????8BE885ED750CB9",
0, 0);
if (Pointer == NULL) return false;
Pointer += 25;
StructPointer = (sFollow*)(*((DWORD*)Pointer));
p_Follow = (sFollow*)(*((DWORD*)Pointer));
//create a handle to the MMF, size matches the struct we're using for it
HANDLE hMapFile = CreateFileMapping(
@ -56,7 +45,7 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) @@ -56,7 +45,7 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
PAGE_READWRITE,
0, // maximum object size (high-order DWORD)
sizeof(MMF_Global), // maximum object size (low-order DWORD)
"FFXI_MultiSend");
"FFXI_MultiSend_1_15");
bool made = (GetLastError() == 0);
@ -66,12 +55,12 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) @@ -66,12 +55,12 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
}
MMF_Pointer = (MMF_Global*)MapViewOfFile(hMapFile, // handle to map object
p_MMF = (MMF_Global*)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
sizeof(MMF_Global));
if (MMF_Pointer == NULL)
if (p_MMF == NULL)
{
CloseHandle(hMapFile);
throw exception("Could not map MMF.");
@ -79,25 +68,25 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) @@ -79,25 +68,25 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
if (made)
{
memset(MMF_Pointer, 0, sizeof(MMF_Global));
memset(p_MMF, 0, sizeof(MMF_Global));
}
Position = MMF_Pointer->Command.Position;
FollowEnabled = true;
ZoneExtra = false;
IgnoreSelf = false;
CurrentName = "";
s_last_run_state = false;
s_position = p_MMF->Command.Position;
s_name = "";
if (m_AshitaCore->GetDataManager()->GetParty()->GetMemberActive(0))
{
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
UpdateName(std::string(m_AshitaCore->GetDataManager()->GetEntity()->GetName(myindex)));
}
_Debug = false;
//SafeMode enabled by Default (to avoid accidental chatlog spam):
//Allows for prepend of "/echo " to commands that are missing a leading "/".
_SafeMode = false;
//Default settings.
c_follow = true;
c_ignoreself = false;
c_attemptzone = false;
c_debug = false;
c_safemode = false;
c_maxdist = 5000.0f;
this->Start();
@ -107,9 +96,9 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) @@ -107,9 +96,9 @@ bool MultiSend::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
void MultiSend::Release(void)
{
this->Stop();
if (MMF_Pointer)
if (p_MMF)
{
UnmapViewOfFile((LPCVOID)MMF_Pointer);
UnmapViewOfFile((LPCVOID)p_MMF);
}
if (hMapFile)
{
@ -130,7 +119,7 @@ __declspec(dllexport) void __stdcall CreatePluginInfo(plugininfo_t* lpBuffer) @@ -130,7 +119,7 @@ __declspec(dllexport) void __stdcall CreatePluginInfo(plugininfo_t* lpBuffer)
strcpy_s(g_PluginInfo->Author, sizeof(g_PluginInfo->Author), "Thorny");
g_PluginInfo->InterfaceVersion = ASHITA_INTERFACE_VERSION;
g_PluginInfo->PluginVersion = 1.05f;
g_PluginInfo->PluginVersion = 1.15f;
g_PluginInfo->Priority = 0;
}

47
src/MultiSend/MultiSend.h

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#endif
#define SAFE_DELETE(p) if(p) { delete p; p = NULL; }
#include "C:\Ashita 3\Plugins\ADK\Ashita.h"
#include "C:\Program Files (x86)\Ashita 3\Plugins\ADK\Ashita.h"
#include "Structs.h"
#include "..\..\..\pluginheaders\Utilities.h"
#include "..\..\..\pluginheaders\Pointers.h"
@ -50,28 +50,28 @@ class MultiSend : IPlugin, Ashita::Threading::AS_Thread @@ -50,28 +50,28 @@ class MultiSend : IPlugin, Ashita::Threading::AS_Thread
ILogManager* m_LogManager;
DWORD m_PluginId;
IDirect3DDevice8* m_Direct3DDevice;
sFollow* StructPointer;
GroupData m_Group;
//References
HANDLE hMapFile;
MMF_Global* MMF_Pointer;
uint32_t Position;
volatile bool ZoneExtra;
volatile bool Following;
volatile float PositionX;
volatile float PositionZ;
std::list<uint16_t> Groups;
std::string CurrentName;
uint32_t Zoning; //0 = not zoning, 1 = waiting to zone, 2 = zoned and waiting to finish
volatile bool FollowEnabled;
volatile bool StopFollow;
volatile bool IgnoreSelf;
volatile bool _Debug;
volatile bool _SafeMode;
sFollow* p_Follow;
MMF_Global* p_MMF;
//State tracking
GroupData s_group;
std::string s_name;
uint32_t s_position;
bool s_last_run_state;
float s_vector_x;
float s_vector_z;
//Configuration
std::list<uint16_t> c_groups;
float c_maxdist;
volatile bool c_follow;
volatile bool c_attemptzone;
volatile bool c_ignoreself;
volatile bool c_debug;
volatile bool c_safemode;
public:
MultiSend(void);
@ -89,10 +89,9 @@ public: @@ -89,10 +89,9 @@ public:
bool HandleCommand(const char* command, int32_t type);
uint32_t ThreadEntry(void) override;
bool MatchID(uint32_t ID);
bool CheckMatch(MMF_ICommand_Single command);
bool ReadCommand();
void SetFollow(bool Active);
void SendCommand(uint32_t ID, const char* Command);
void SendCommand(multisend_type type, uint32_t param, const char* Command);
void SanitizeCommand(char* Input);
std::string SubValues(std::string Input);
void SubValues(char* Input);

24
src/MultiSend/MultiSend.vcxproj

@ -21,31 +21,32 @@ @@ -21,31 +21,32 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{3C74E1A4-E44B-4523-85DC-9A94AC2D6457}</ProjectGuid>
<RootNamespace>MultiSend</RootNamespace>
<WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -68,7 +69,7 @@ @@ -68,7 +69,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>..\..\bin\</OutDir>
<OutDir>..\..\..\bin\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>..\..\bin\</OutDir>
@ -110,7 +111,8 @@ @@ -110,7 +111,8 @@
<ModuleDefinitionFile>Exports.def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>copy "..\..\bin\MultiSend.dll" "C:\Ashita 3\plugins\MultiSend.dll"</Command>
<Command>copy "..\..\..\bin\MultiSend.dll" "C:\Program Files (x86)\Ashita 3\plugins\MultiSend.dll"
copy "..\..\..\bin\MultiSend.dll" "..\..\release\plugins\MultiSend.dll"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -140,12 +142,12 @@ @@ -140,12 +142,12 @@
<ItemGroup>
<ClCompile Include="Commands.cpp" />
<ClCompile Include="Follow.cpp" />
<ClCompile Include="Groups.cpp" />
<ClCompile Include="groups.cpp" />
<ClCompile Include="IO.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="Name.cpp" />
<ClCompile Include="Substitute.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="packets.cpp" />
<ClCompile Include="text_sanitizing.cpp" />
<ClCompile Include="thread.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="Exports.def" />

16
src/MultiSend/MultiSend.vcxproj.filters

@ -23,28 +23,28 @@ @@ -23,28 +23,28 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp">
<ClCompile Include="IO.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Thread.cpp">
<ClCompile Include="Commands.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IO.cpp">
<ClCompile Include="Follow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Groups.cpp">
<ClCompile Include="packets.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Name.cpp">
<ClCompile Include="text_sanitizing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Commands.cpp">
<ClCompile Include="thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Follow.cpp">
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Substitute.cpp">
<ClCompile Include="groups.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

30
src/MultiSend/Structs.h

@ -3,6 +3,16 @@ @@ -3,6 +3,16 @@
#include <stdint.h>
enum multisend_type
{
all, //Param irrelevant
others, //Param = sender's process ID
alliance, //Param = sender's server id
party, //Param = sender's server id
group, //Param = group id
single //Param = process id of target
};
struct MMF_Name_Single
{
uint32_t Process;
@ -18,10 +28,11 @@ struct MMF_Name @@ -18,10 +28,11 @@ struct MMF_Name
struct MMF_ICommand_Single
{
uint8_t Active;
uint32_t Targets;
uint32_t SendProcess;
uint8_t Command[248];
uint8_t active;
multisend_type type;
uint32_t param;
uint32_t sender_process_id;
uint8_t command[248];
};
struct MMF_ICommand
@ -33,11 +44,12 @@ struct MMF_ICommand @@ -33,11 +44,12 @@ struct MMF_ICommand
struct MMF_IFollow
{
uint16_t Zone;
uint32_t FollowID;
uint32_t Follow;
int32_t PosX;
int32_t PosZ;
uint32_t target_process_id;
uint16_t lastzone;
uint16_t zone;
float position_x;
float position_z;
uint32_t idle_count;
};
struct MMF_Global

84
src/MultiSend/Thread.cpp

@ -4,76 +4,38 @@ uint32_t MultiSend::ThreadEntry(void) @@ -4,76 +4,38 @@ uint32_t MultiSend::ThreadEntry(void)
{
while (!this->IsTerminated())
{
if (m_AshitaCore->GetDataManager()->GetParty()->GetMemberActive(0))
if (p_MMF->Follow.target_process_id == GetCurrentProcessId())
{
if (Zoning == 2) Zoning = 0;
}
else if (Zoning == 1)
{
Zoning = 2;
}
if (MMF_Pointer->Follow.Follow)
{
if (((MMF_Global*)MMF_Pointer)->Follow.FollowID == GetCurrentProcessId())
uint16_t zone = m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0);
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
uint32_t renderflags = m_AshitaCore->GetDataManager()->GetEntity()->GetRenderFlags0(myindex);
bool isrendered = (((renderflags & 0x200) != 0) && ((renderflags & 0x4000) == 0));
float my_pos_x = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex);
float my_pos_z = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex);
if ((zone == 0) || (myindex == 0) || (!isrendered))
{
if (!Zoning)
{
Following = false;
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
int32_t mPosX = (int32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex) * 100);
int32_t mPosZ = (int32_t)floor(m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex) * 100);
MMF_Pointer->Follow.PosX = mPosX;
MMF_Pointer->Follow.PosZ = mPosZ;
MMF_Pointer->Follow.Follow = 1;
MMF_Pointer->Follow.Zone = m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0);
}
else
if (p_MMF->Follow.zone != 0)
{
Following = false;
MMF_Pointer->Follow.Follow = 2;
p_MMF->Follow.lastzone = p_MMF->Follow.zone;
}
p_MMF->Follow.zone = 0;
}
else if (MMF_Pointer->Follow.Follow != 3)
else
{
if (m_AshitaCore->GetDataManager()->GetParty()->GetMemberActive(0))
if (p_MMF->Follow.zone == 0)
{
if (MMF_Pointer->Follow.Follow == 2)
{
if (!ZoneExtra)
{
Following = false;
uint16_t myindex = m_AshitaCore->GetDataManager()->GetParty()->GetMemberTargetIndex(0);
float MyX = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalX(myindex);
float MyZ = m_AshitaCore->GetDataManager()->GetEntity()->GetLocalZ(myindex);
PositionX = (float)MMF_Pointer->Follow.PosX / 100.0f;
PositionZ = (float)MMF_Pointer->Follow.PosZ / 100.0f;
float Scale = 1.0f + (8.0f / sqrt(pow(PositionX - MyX, 2) + pow(PositionZ - MyZ, 2)));
PositionX = (PositionX * Scale) + MyX;
PositionZ = (PositionZ * Scale) + MyZ;
ZoneExtra = true;
Following = true;
}
}
else
{
ZoneExtra = false;
PositionX = (float)MMF_Pointer->Follow.PosX / 100.0f;
PositionZ = (float)MMF_Pointer->Follow.PosZ / 100.0f;
Following = true;
}
p_MMF->Follow.idle_count = 0;
}
else if ((my_pos_x != p_MMF->Follow.position_x) || (my_pos_z != p_MMF->Follow.position_z))
{
p_MMF->Follow.idle_count = 0;
}
else p_MMF->Follow.idle_count++;
p_MMF->Follow.zone = zone;
p_MMF->Follow.position_x = my_pos_x;
p_MMF->Follow.position_z = my_pos_z;
}
else
{
if (Following) StopFollow = true;
Following = false;
}
}
else
{
if (Following) StopFollow = true;
Following = false;
}
while (ReadCommand()) {}

25
src/MultiSend/packets.cpp

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
#include "MultiSend.h"
bool MultiSend::HandleIncomingPacket(uint16_t id, uint32_t size, void* data, void* modified, bool blocked)
{
if (id == 0x00A)
{
if (strcmp(s_name.c_str(), (const char*)data + 0x84))
{
UpdateName(std::string((const char*)data + 0x84));
}
}
if ((id == 0x32) || (id == 0x34))
{
if (p_MMF->Follow.target_process_id == ::GetCurrentProcessId())
{
if (p_MMF->Follow.idle_count < 5000)
{
p_MMF->Follow.idle_count = 5000;
}
}
}
return false;
}

87
src/MultiSend/text_sanitizing.cpp

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
#include "MultiSend.h"
std::string MultiSend::SubValues(std::string Input)
{
std::string Working = Input;
size_t find = Working.find("[me]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(0)));
}
find = Working.find("[p0]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(0)));
}
find = Working.find("[p1]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(1)));
}
find = Working.find("[p2]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(2)));
}
find = Working.find("[p3]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(3)));
}
find = Working.find("[p4]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(4)));
}
find = Working.find("[p5]");
if (find != string::npos)
{
Working.replace(find, 4, std::to_string(m_AshitaCore->GetDataManager()->GetParty()->GetMemberServerId(5)));
}
find = Working.find("[t]");
if (find != string::npos)
{
unsigned int TargetIndex = m_AshitaCore->GetDataManager()->GetTarget()->GetTargetIndex();
if (m_AshitaCore->GetDataManager()->GetTarget()->GetSubTargetActive())
{
TargetIndex = m_AshitaCore->GetDataManager()->GetTarget()->GetSubTargetIndex();
}
Working.replace(find, 3, std::to_string(m_AshitaCore->GetDataManager()->GetEntity()->GetServerId(TargetIndex)));
}
return Working;
}
void MultiSend::SubValues(char* Input)
{
std::string Working = SubValues(std::string(Input));
const char* base = Working.c_str();
memset(Input, 0, 248);
memcpy(Input, base, strlen(base));
}
void MultiSend::SanitizeCommand(char* Input)
{
if (Input[0] != '/')
{
if (c_debug)
m_AshitaCore->GetChatManager()->Write("Detected command without leading '/'. Prepending '/echo'...");
char* prepend = "/echo ";
size_t plen = strlen(prepend);
memmove(Input + plen, Input, strlen(Input) + 1);
memcpy(Input, prepend, strlen(prepend));
}
else
{
if (c_debug)
m_AshitaCore->GetChatManager()->Write("No Sanitization Needed.");
}
}
Loading…
Cancel
Save