mirror of
https://github.com/MilkBarModding/MilkBarLauncher.git
synced 2025-06-17 04:31:00 +00:00
288 lines
9.0 KiB
C++
288 lines
9.0 KiB
C++
#pragma once
|
|
#include "CharacterEquipment.h"
|
|
#include "Memory.h"
|
|
|
|
namespace DataTypes
|
|
{
|
|
class EquipmentAccess
|
|
{
|
|
public:
|
|
bool Changed = false;
|
|
bool SetupFailed = false;
|
|
CharacterEquipment* LastKnown = new CharacterEquipment();
|
|
std::string lastBase = "Jugador1ModelNameLongForASpecificReasonHead";
|
|
|
|
bool Compare(CharacterEquipment newEquipment)
|
|
{
|
|
Mutex.lock();
|
|
|
|
if (LastKnown->WType != newEquipment.WType)
|
|
{
|
|
Changed = true;
|
|
LastKnown->WType = newEquipment.WType;
|
|
}
|
|
if (LastKnown->Sword != newEquipment.Sword)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Sword = newEquipment.Sword;
|
|
}
|
|
if (LastKnown->Shield != newEquipment.Shield)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Shield = newEquipment.Shield;
|
|
}
|
|
if (LastKnown->Bow != newEquipment.Bow)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Bow = newEquipment.Bow;
|
|
}
|
|
if (LastKnown->Head != newEquipment.Head)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Head = newEquipment.Head;
|
|
}
|
|
if (LastKnown->Upper != newEquipment.Upper)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Upper = newEquipment.Upper;
|
|
}
|
|
if (LastKnown->Lower != newEquipment.Lower)
|
|
{
|
|
Changed = true;
|
|
LastKnown->Lower = newEquipment.Lower;
|
|
}
|
|
|
|
Mutex.unlock();
|
|
|
|
return Changed;
|
|
}
|
|
|
|
void SetWeapons(uint64_t baseAddr)
|
|
{
|
|
std::string RIGHT_DEFAULT = "RightHandWeaponLongName";
|
|
std::string LEFT_DEFAULT = "LeftHandWeaponLongName";
|
|
|
|
FindWeaponAddr(baseAddr);
|
|
|
|
uint64_t OldAddress = ArmorAddrs.Face;
|
|
|
|
FindArmorAddr(baseAddr);
|
|
|
|
std::string RightHandWeapon = "Weapon_Null_";
|
|
std::string LeftHandWeapon = "Weapon_Shield_";
|
|
|
|
switch (LastKnown->WType)
|
|
{
|
|
case 1:
|
|
RightHandWeapon.replace(RightHandWeapon.find("Null"), 4, "Sword");
|
|
break;
|
|
case 2:
|
|
RightHandWeapon.replace(RightHandWeapon.find("Null"), 4, "Lsword");
|
|
break;
|
|
case 3:
|
|
RightHandWeapon.replace(RightHandWeapon.find("Null"), 4, "Spear");
|
|
break;
|
|
}
|
|
|
|
Mutex.lock();
|
|
|
|
Memory::write_string(WeaponAddrs.Right, RightHandWeapon + NumToStr(LastKnown->Sword), RIGHT_DEFAULT.size() + 8, __FUNCTION__);
|
|
Memory::write_string(WeaponAddrs.Left, LeftHandWeapon + NumToStr(LastKnown->Shield), LEFT_DEFAULT.size() + 8, __FUNCTION__);
|
|
|
|
if (OldAddress == ArmorAddrs.Face)
|
|
Changed = false;
|
|
|
|
Mutex.unlock();
|
|
}
|
|
|
|
void SetArmor()
|
|
{
|
|
std::string BASE_FOLDER = "Jugador1ModelNameLongForASpecificReason";
|
|
std::string BASE_DEFAULT = "Jugador1ModelNameLongForASpecificReasonHead";
|
|
std::string CHEST_DEFAULT = "Jugador1ModelNameLongForASpecificReasonChest";
|
|
std::string UPPER_DEFAULT = "Jugador1ModelNameLongForASpecificReasonHelmet";
|
|
std::string LOWER_DEFAULT = "Jugador1ModelNameLongForASpecificReasonLower";
|
|
std::string HEAD_DEFAULT = "Jugador1ModelNameLongForASpecificReasonUpper";
|
|
|
|
std::string UPPER_DEFAULT_ARMOR = "MP_Armor_Default_Upper";
|
|
std::string LOWER_DEFAULT_ARMOR = "MP_Armor_Default_Lower";
|
|
std::string HEAD_DEFAULT_ARMOR = "MP_Armor_Default_Head";
|
|
|
|
std::string BaseToWrite = BASE_DEFAULT;
|
|
std::string UpperToWrite = LastKnown->Upper == 0 ? UPPER_DEFAULT_ARMOR : "MP_Armor_" + NumToStr(LastKnown->Upper) + "_Upper";
|
|
std::string LowerToWrite = LastKnown->Lower == 0 ? LOWER_DEFAULT_ARMOR : "MP_Armor_" + NumToStr(LastKnown->Lower) + "_Lower";
|
|
std::string HeadToWrite = LastKnown->Head == 0 ? HEAD_DEFAULT_ARMOR : "MP_Armor_" + NumToStr(LastKnown->Head) + "_Head";
|
|
std::string ChestToWrite = CHEST_DEFAULT;
|
|
|
|
if (UpperToWrite != "" && UpperToWrite != UPPER_DEFAULT_ARMOR)
|
|
ChestToWrite = "EmptyModel";
|
|
|
|
if (HeadToWrite == "MP_Armor_180_Head" || HeadToWrite == "MP_Armor_160_Head" || HeadToWrite == "MP_Armor_171_Head")
|
|
BaseToWrite = "EmptyModel";
|
|
|
|
if(ArmorAddrs.Face != 0)
|
|
{
|
|
try {
|
|
std::string HeadStr = Memory::read_string(ArmorAddrs.Face, BASE_DEFAULT.size() + 2, __FUNCTION__);
|
|
if (HeadStr != lastBase && HeadStr != "EmptyModel")
|
|
{
|
|
ArmorAddrs.Face = 0;
|
|
Logging::LoggerService::LogInformation("Failed to set up armor. Trying again...", __FUNCTION__);
|
|
this->SetupFailed = true;
|
|
return;
|
|
}
|
|
|
|
Memory::write_string(ArmorAddrs.Folder, BASE_FOLDER, BASE_FOLDER.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Face, BaseToWrite, BASE_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Chest, ChestToWrite, CHEST_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Head, HeadToWrite, HEAD_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Lower, LowerToWrite, LOWER_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Upper, UpperToWrite, UPPER_DEFAULT.size() + 2, __FUNCTION__);
|
|
|
|
lastBase = BaseToWrite;
|
|
|
|
this->SetupFailed = false;
|
|
Logging::LoggerService::LogInformation("Armor setup.", __FUNCTION__);
|
|
}
|
|
catch (...)
|
|
{
|
|
this->SetupFailed = true;
|
|
Logging::LoggerService::LogInformation("Failed to setup armor.", __FUNCTION__);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Logging::LoggerService::LogInformation("Couldn't find armor address.", __FUNCTION__);
|
|
this->SetupFailed = true;
|
|
}
|
|
}
|
|
|
|
void SetModel(std::string model)
|
|
{
|
|
//model = "Npc_Zora_Prince:Npc_Zora_Prince";
|
|
std::stringstream stream(model);
|
|
std::string segment;
|
|
std::vector<std::string> splitModel;
|
|
|
|
while (std::getline(stream, segment, ':'))
|
|
{
|
|
splitModel.push_back(segment);
|
|
}
|
|
|
|
std::string BASE_FOLDER = "Jugador1ModelNameLongForASpecificReason";
|
|
std::string BASE_DEFAULT = "Jugador1ModelNameLongForASpecificReasonHead";
|
|
std::string CHEST_DEFAULT = "Jugador1ModelNameLongForASpecificReasonChest";
|
|
std::string UPPER_DEFAULT = "Jugador1ModelNameLongForASpecificReasonHelmet";
|
|
std::string LOWER_DEFAULT = "Jugador1ModelNameLongForASpecificReasonLower";
|
|
std::string HEAD_DEFAULT = "Jugador1ModelNameLongForASpecificReasonUpper";
|
|
|
|
if (ArmorAddrs.Face != 0)
|
|
{
|
|
try {
|
|
Memory::write_string(ArmorAddrs.Folder, splitModel[0], BASE_FOLDER.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Face, splitModel[1], BASE_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Chest, splitModel[1], CHEST_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Head, splitModel[1], HEAD_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Lower, splitModel[1], LOWER_DEFAULT.size() + 2, __FUNCTION__);
|
|
Memory::write_string(ArmorAddrs.Upper, splitModel[1], UPPER_DEFAULT.size() + 2, __FUNCTION__);
|
|
|
|
lastBase = splitModel[1];
|
|
|
|
this->SetupFailed = false;
|
|
Logging::LoggerService::LogInformation("Model setup.", __FUNCTION__);
|
|
}
|
|
catch (...)
|
|
{
|
|
Logging::LoggerService::LogInformation("Failed to setup model.", __FUNCTION__);
|
|
this->SetupFailed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Logging::LoggerService::LogInformation("Could not find model address. Trying again...", __FUNCTION__);
|
|
this->SetupFailed = true;
|
|
}
|
|
}
|
|
|
|
std::string NumToStr(int number)
|
|
{
|
|
std::string result = std::to_string(number);
|
|
|
|
int numberOfZeros = 3 - result.size();
|
|
|
|
for (int i = 0; i < numberOfZeros; i++)
|
|
result = "0" + result;
|
|
|
|
return result;
|
|
}
|
|
|
|
void FindWeaponAddr(uint64_t baseAddr)
|
|
{
|
|
uint64_t addr = Memory::ReadPointers(baseAddr, { 0x39C, 0x78, 0x244 }, false);
|
|
|
|
bool Found = false;
|
|
int iterator = 0;
|
|
|
|
while (!Found)
|
|
{
|
|
uint64_t temp = Memory::read_bigEndian4BytesOffset(addr + (iterator * 0x4), __FUNCTION__);
|
|
|
|
if (int(3518303375) == Memory::read_bigEndian4BytesOffset(temp + 0x10, __FUNCTION__))
|
|
{
|
|
Found = true;
|
|
addr = Memory::read_bigEndian4BytesOffset(temp + 0x4, __FUNCTION__);
|
|
this->WeaponAddrs.Right = Memory::read_bigEndian4BytesOffset(addr + 0x1C, __FUNCTION__) + Memory::getBaseAddress();
|
|
this->WeaponAddrs.Left = Memory::read_bigEndian4BytesOffset(addr + 0xA0, __FUNCTION__) + Memory::getBaseAddress();
|
|
}
|
|
|
|
iterator++;
|
|
}
|
|
}
|
|
|
|
void FindArmorAddr(uint64_t baseAddr)
|
|
{
|
|
|
|
if (baseAddr == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint64_t addr = Memory::ReadPointers(baseAddr, { 0x39C, 0x6C });
|
|
|
|
this->ArmorAddrs.Folder = Memory::ReadPointers(addr, { 0x48C, 0x1C }, true) + 0xC;
|
|
|
|
addr = Memory::ReadPointers(addr, { 0x4B0, 0x38 });
|
|
this->ArmorAddrs.Face = Memory::ReadPointers(addr, { 0x0, 0xC }, true);
|
|
addr = Memory::read_bigEndian4BytesOffset(addr + 0x10, __FUNCTION__);
|
|
this->ArmorAddrs.Chest = Memory::ReadPointers(addr, { 0x0, 0xC }, true);
|
|
addr = Memory::read_bigEndian4BytesOffset(addr + 0x10, __FUNCTION__);
|
|
this->ArmorAddrs.Head = Memory::ReadPointers(addr, { 0x0, 0xC }, true);
|
|
addr = Memory::read_bigEndian4BytesOffset(addr + 0x10, __FUNCTION__);
|
|
this->ArmorAddrs.Lower = Memory::ReadPointers(addr, { 0x0, 0xC }, true);
|
|
addr = Memory::read_bigEndian4BytesOffset(addr + 0x10, __FUNCTION__);
|
|
this->ArmorAddrs.Upper = Memory::ReadPointers(addr, { 0x0, 0xC }, true);
|
|
|
|
this->Changed = true;
|
|
}
|
|
|
|
private:
|
|
std::shared_mutex Mutex;
|
|
|
|
struct WeaponAddr
|
|
{
|
|
uint64_t Left = 0;
|
|
uint64_t Right = 0;
|
|
} WeaponAddrs;
|
|
|
|
struct ArmorAddr
|
|
{
|
|
uint64_t Folder = 0;
|
|
uint64_t Face = 0;
|
|
uint64_t Chest = 0;
|
|
uint64_t Head = 0;
|
|
uint64_t Upper = 0;
|
|
uint64_t Lower = 0;
|
|
} ArmorAddrs;
|
|
|
|
};
|
|
} |