ffxivapp / sharlayan Goto Github PK
View Code? Open in Web Editor NEWVisit us on Discord! https://discord.gg/aCzSANp
Home Page: https://xivapp.com
License: MIT License
Visit us on Discord! https://discord.gg/aCzSANp
Home Page: https://xivapp.com
License: MIT License
Hi there,
I am trying to work out a way to collect the emnity data of the party, based on the current target, and sort it according to the emnity value. I can do this using the code below, however I have noticed two things which is currently making this process useless.
The first is the .ID value of the emnity struct doesn't seem to relate in anyway to PC or NPC ID's.. I can see that each player or npc is getting a unique ID from the returned emnity methods, but these ID's are different to their Actor ID's so I have no way of making comparisons - in particular if my character has top emnity, etc.
The second, which I found trying to remedy the first, is the .Name value of the emnity struct returns random data to my debugging console. Mostly in the form of ??? and ���, which means I cannot use this either as a comparison point.
The basic rundown of the code I'm using is:
var TargetInfo = Reader.GetTargetInfo().TargetEntity.CurrentTarget;
var TargetEmnityInfo = Reader.GetTargetInfo().TargetEntity.EnmityEntries;
var PlayerInfo = Reader.GetActors().PCEntities.FirstOrDefault().Value.CurrentUser;;
if (TargetInfo.IsClaimed)
{
//Collect Emnity Data
var TargetEmnity = TargetEmnityInfo.Count;
var _emnitytable = new List<KeyValuePair<uint, uint>>();
//Create a list of emnity data <ID, Emnity>
for (int i = 0; i < TargetEmnityInfo.Count; i++)
{
_emnitytable.Add(new KeyValuePair<uint, uint>(TargetEmnityInfo[i].ID, TargetEmnityInfo[i].Enmity));
}
//Sort emnity by highest holder
_emnitytable.OrderBy(kvp => kvp.Value);
//Get your index in the list
var PersonalID = PlayerInfo.ID;
int EmnityPosition = _emnitytable.FindIndex(a => a.Key == PersonalID);
//Debug compare the values of the highest holder emnity ID to my character ID
//Returns different IDs.
Console.WriteLine(PersonalID + "->" + _emnitytable.First().Key);
}
Any help on how I can someone relate the emnity ID to Actor IDs would be greatly appreciated. :)
Built a quick app to test inventory and getting some very odd results:
gamelist.Items.Clear();
gamelist.Items.Add("Getting inventory items ...");
PlayerInfoReadResult player = Reader.GetPlayerInfo();
gamelist.Items.Add("Reading the inventory for: " + player.PlayerEntity.Name);
InventoryReadResult inventory = Reader.GetInventoryItems();
int inventoryCount = 1;
foreach(InventoryEntity items in inventory.InventoryEntities)
{
foreach(ItemInfo item in items.Items)
{
if (item.Amount == 0)
{
continue;
}
string itemEntry = $"- Slot: {item.Slot} -- x{item.Amount} {item.ID}";
gamelist.Items.Add(itemEntry);
}
}
Some of these entries make no sense, eg: Slot: 1 -- x23 1253500709
, I know that isn't an item ID so no idea what it is. Some of the amounts are off too. nearly all the items/values in that list are incorrect or make no sense. Not even shards
The only correct one is slot 0 the very first one :D
Have the memory values shifted again with the latest patch for DX9?
I found a wrong key name in https://xivapp.com/api/zones.
French, German and Japanese is shuffled.
For example, "Limsa Lominsa Upper Decks",
Wrong:
"128": {
"Name": {
"Chinese": "Limsa Lominsa Upper Decks",
"Korean": "Limsa Lominsa Upper Decks",
"English": "Limsa Lominsa Upper Decks",
"French": "リムサ・ロミンサ:上甲板層",
"German": "Limsa Lominsa - Le Tillac",
"Japanese": "Obere Decks"
},
"IsDungeonInstance": false
},
Correct:
"128": {
"Name": {
"Chinese": "Limsa Lominsa Upper Decks",
"Korean": "Limsa Lominsa Upper Decks",
"English": "Limsa Lominsa Upper Decks",
"Japanese": "リムサ・ロミンサ:上甲板層",
"French": "Limsa Lominsa - Le Tillac",
"German": "Obere Decks"
},
"IsDungeonInstance": false
},
mousover target info seems to be not working from:
Reader.GetTargetInfo().TargetInfo.MouseOverTarget (always null)
Could you please check?
It would be useful to be able to query the contents of the crafting logs, including which items are marked as having been completed already.
These enums does not currently exist for bag ids InventoryBagId.FreeCompanyPage4, InventoryBagId.FreeCompanyPage5
Below are those numbers respectively with 4 being the first one
https://github.com/FFXIVAPP/sharlayan/blob/main/Sharlayan/Core/Enums/Inventory.cs#L105-L106
Mobs throughout the game have different icons to their nameplates indicating whether they are hostile and attack on sight or whether they are neutral until attacked. These icons can be seen here:
So far I was only able to determine whether my target is a NPC / PC / Monster / EObj (market boards, placards, etc.) but not its hostility. I guess that this is a property that hasn't been scanned and made available in the code yet. It would actually suffice to know whether the target is passive or aggresive - the rank doesn't actually matter. Do you think you might add this as well?
And slightly offtopic: since I finally got the library to work for my private project I guess I'll stumble upon few more things every now and then I'd like to see added like the check for the hostility. Do you want me to continue creating issues for them?
Since @EmperorArthur started an issue in the main repository for 64bit offsets which are outdated I thought we can have that collection of information in the Memory repository where everyone can share his results.
The following lists and tables are non-exhaustive and there are many things that either have to be verified or found in the first place. For example I wasn't able to find units for all mob difficulty icons in the game.
I'd be glad if you happen to have something to improve this overview.
In my newest gist you will find a Cheat Engine list of addresses and a Lua script included in the ct file which is separately available as well. When you run CE and open the ct file it will automatically attach to the game and calculate the addresses which are written to the memory records so you don't have to find base addresses at all.
Here are my current offsets for the ActorEntity
target struct (with some redundant annotations about the values):
Name = 0x30, -- Text[68]
Id = 0x74, -- Int32
NpcId1 = 0x7C, -- Int32
NpcId2 = 0x80, -- Int32
OwnerId = 0x84, -- Int32
--[[ 0 Unknown, 1 PC, 2 Monster, 3 NPC, 5 Aetheryte, 6 Gathering, 7 EObj, 9 Minion ]]--
Type = 0x8C, -- Int8
--[[ Probably bitfield - 0 Unknown, 1 Own, 2 True, 4 False ]]--
TargetType = 0x8D, -- Int8
--[[ 0x8F could be some server-side altitude difference - lagging ]]--
--[[ 0x90 is distance in rounded yalms as well but it is lagging - maybe server-side value? ]]--
--[[ 0x91 could be some *local* altitude difference ]]--
--[[ 0x92 *local* distance in rounded yalms since it is not lagging at all ]]--
Distance = 0x92, -- Int8
X = 0xB0, -- float
Z = 0xB4, -- float
Y = 0xB8, -- float
--[[ Rotation around own axis (-pi, pi) ]]--
Heading = 0xC0, -- float
HitBoxRadius = 0xD0, -- float
--[[ 0x801AFFFF for FATE targets (Monster and NPCs!) - Check for Type = Monster]]--
FateFlag = 0xF4, -- Int32
--[[ 0 Unknown, 1 Idle, 2 Dead, 3 Sitting, 4 Mounted, 5 Crafting, 6 Gathering, 7 Melding,
8 SMachine (what is this?!) ]]--
ActionStatusId = 0x1A0, -- Int8
IconId = 0x1B0, -- Int8
--[[
Certain enemies are part of factions - thus NPCs can be aggressive but still friendly.
Guards and NPCs during FATEs do happen to behave like that.
0 Allied, 4 Monsters, 6 Ixali, 7 Amalj'aa, 8 Kobold
]]--
FactionId = 0x1B1, -- Int8
--[[ Probably bitfield - 0 Unknown, 1 Claimed, 2 Idle, 5 Crafting, 6 UnknownUnSheathed,
7 UnknownSheathed, 97 Unknown (something in the middle of gathering) ]]--
StatusId = 0x1B2, -- Int8
ClaimedById = 0x1B8, -- Int32
TargetId = 0x1C0, -- Int32
JobId = 0x1440, -- Int8
Level = 0x1441, -- Int8
--[[ 1 Maelstrom, 2 Order of the Twin Adder, 3 Immortal Flames ]]--
GrandCompany = 0x1442, -- Int8
GrandCompanyRank = 0x1443, -- Int8
TitleId = 0x1446, -- Int16
CurrentHp = 0x1448, -- Int32
MaxHp = 0x144C, -- Int32
CurrentMp = 0x1450, -- Int32
MaxMp = 0x1454, -- Int32
CurrentTp = 0x1458, -- Int16
CurrentGp = 0x145A, -- Int16
MaxGp = 0x145C, -- Int16
CurrentCp = 0x145E, -- Int16
MaxCp = 0x1460, -- Int16
--[[
val & 0x1
- boolean value indicating whether entity is aggressive
val & 0x2
- boolean value indicating whether entity is currently in combat
val & 0x4
- boolean value indicating entities battle stance (weapon shethed)
val & 0x80
- boolean value indicating whether entity is currently casting
]]--
CombatFlags = 0x15CA, -- Int8 (bitfield!)
--[[ See below for more detailed information ]]--
DifficultyRank = 0x179D, -- Int8
IsCasting1 = 0x19D0, -- Int8
IsCasting2 = 0x19D1, -- Int8
CastingId = 0x19D4, -- UInt8!!
CastingTargetId = 0x19E0, -- Int32
CastingProgress = 0x1A04, -- float
CastingTime = 0x1A08 -- float
These icons appear next to a players name in the party list and/or above their heads next to their name, and describe what the player's status or what they are seeking. The IconId
obtained at 0x1B0
is different to the ones from the API. Either the API is highly outdated or 64 bit has almost completely different ids. I wasn't able to get all the icons yet since I couldn't create an alliance, find someone with particular quests or FATEs as well as some duty realated stuff. Here is my non-exhaustive list for the time being:
Id | Description | Id | Description | |
---|---|---|---|---|
5 | Disconnecting | 27 | Mentor | |
11 | Idle Cam | 28 | PvE Mentor | |
13 | Busy | 29 | Trade Mentor | |
15 | Playing Triple Triad | 30 | PvP Mentor | |
16 | Cutscene | 31 | Returning Player | |
18 | Away From Keyboard | 32 | Sprout | |
21 | Looking to Meld Materia | 36 | Party Leader | |
22 | RP | 37 | Party Member | |
23 | Looking for Party (Green) | 38 | Cross World Party Leader | |
25 | Duty Finder Queue | 39 | Cross World Party Member | |
26 | Recruiting via Party Finder | 43 | In Duty |
Certains entities are associated with factions. Aggressiveness and hostility are not the same which is why factions must be used to determine either of those. NPC guards can be aggressive but they are not hostile towards your character. There is a enmity table for each faction to deduce hostility but this is just too deep into the memory. The factions I encountered thus far are the following:
Id | Description |
---|---|
0 | Allied NPCs and PCs |
4 | Monsters in general |
6 | Ixali |
7 | Amalj'aa |
8 | Kobold |
At 0x15CA
you will encounter a byte which indicates certain actions and behaviors of an entity. Thus far I only noticed four interesting bits:
Bit | Mask | Description |
---|---|---|
1 | 0x1 |
Indicates whether the entity is aggressive |
2 | 0x2 |
Indicates whether the entity is currently in combat |
3 | 0x4 |
Indicates the battle stance, i.e. whether the weapon is sheathed |
8 | 0x80 |
Indicates whether the entity is currently casting |
At 0x179D
there is a byte that describes (together with the first bit of the Combat Flags) which icons is displayed above an enemy. Here is a table with the values I found thus far:
Level | Icon | Value | Affected Units |
---|---|---|---|
1 | 0 |
Generic Hostile Units and newly spawned Adds during Boss Encounters | |
2 | 3 |
Dungeon Trash | |
3 | ?? | ?? | |
4 | 1 |
Elite Marks | |
5 | 6 |
Minor Boss | |
6 | 2 |
Major Boss |
Status effects start at 0x1850
and are 12 bytes long with the following structure:
Offset | Type | Name |
---|---|---|
0x00 |
Int16 |
Id |
0x02 |
Int8 |
Stacks |
0x03 |
Int8 |
??? |
0x04 |
float |
Duration |
0x08 |
Int32 |
CasterId |
It seems that only 30 status effect fit in there as seen in the attached picture. Enemies which are not PCs seem to have more, however Ravahn mentioned once they are not actually stored in the momory but communicated using network packages. I'll be trying to track the status effects on some S ranks and big FATE mobs with many people to find it out.
I am not entirely sure but I do think that the entire struct is 0x2730
bytes long for 64bit. Here is a ToDo list as well to keep track on what is still missing to recreate a compatible structure with your ActorEntity
class without my custom additions and findings.
Right at ffxiv_dx11.exe+0x16BE8C0
there is a 4 byte pointer that points to the camera structure. It contains a lot of different variables, but the most notable ones are the following:
Offset | Type | Description |
---|---|---|
+0x110 |
Int8 |
Boolean value indicating whether free camera mode (not first person mode) is enabled. |
+0x118 |
float |
Distance of the camera. Value between 1.5 and 20 in steps of 0.25. |
+0x134 |
float |
Azimuth of the camera. Can confirm that zero is north and facing south. |
+0x138 |
float |
Elevation of the camera. Above the ground it is negative and caps at -pi/2 + epsilon. Below the ground it caps exactly at +pi/4. |
+0x1A0 |
float |
X value of world coordinates of the camera. |
+0x1A4 |
float |
Z value of world coordinates of the camera. |
+0x1A8 |
float |
Y value of world coordinates of the camera. |
+0x1B0 |
float |
X value of world coordinates of the focused object. |
+0x1B4 |
float |
Z value of world coordinates of the focused object. |
+0x1B8 |
float |
Y value of world coordinates of the focused object. |
The current map id (not to confuse with the zone id!) can be found directly at ffxiv_dx11.exe+0x186F940
as a Int32
value. However, some maps dont have this value, e.g. "The Topmast Subdivision" in "Mist". However there is another unique value right at ffxiv_dx11.exe+0x186F93C
describing that map.
At This wasn't the correct byte yet...ffxiv_dx11.exe+0x1870C60
you will find an Int8
which has the value 1 if the player is currently in-game; otherwise, 0 when the main menu or character selection are active.
I have been experimenting with your library lately but unfortunately you haven't updated the signatures for 64bit yet so I have tried accessing the data from the 32bit version of the game hence I have tried accesing something really basic with this piece of code:
var processes = Process.GetProcessesByName("ffxiv");
if(processes.Length > 0) {
var process = processes[0];
var processModel = new ProcessModel
{
Process = process,
IsWin64 = false
};
MemoryHandler.Instance.SetProcess(processModel);
var readResult = Reader.GetPlayerInfo().PlayerEntity;
Console.WriteLine("Name: " + readResult.Name);
}
Unfortunately the code returns an empty string but the GetPlayerInfo()
returns a result object with default values of 0 everywhere and does not trigger an error. I was wondering what might be the issue accessing the data - any suggestions?
Furthermore, do you know when you will be able to update offsets and signatures? I guess you have those already running in the Aetherflow framework which you're working on as well if I am not mistaken?
Seems memory module has broken, either some data has been moved or offsets have changed. MapID for sure is broken!
Will look into others.
I found that NewNPC always contains Marketboard and Summoning Bell.
This problem always occurs when the character is near the market.
Code:
ActorReadResult readResult = Reader.GetActors();
foreach (var id in readResult.NewNPC)
{
string strNPC = "NPC => ID: " + id + ", Name: " + readResult.NPCEntities[id].Name;
Console.WriteLine(strNPC);
}
Result:
NPC => ID: 2000402, Name: マーケットボード
NPC => ID: 2000401, Name: 呼び鈴
NPC => ID: 2000402, Name: マーケットボード
Remarks:
"Marketbord" is "マーケットボード" in Japanese.
"Summoning Bell" is "呼び鈴" in Japanese.
@cybaersam Adding you here because you were working on a fix in the radar.
https://github.com/Icehunter/ffxivapp-memory/blob/master/FFXIVAPP.Memory/Reader.Actor.cs#L81
That is where I start looking at whether something was in the list previously or not; and determine which ones are new.
The main application fires the OnNewEntities events only 1 time; and sends a concurrentDictionary by ref. I think if radar was to listen to removed/added events it could handle that?
https://github.com/Minoost/ffxivapp-memory/issues/1
Chatlog, PlayerInfo does not work w/ Korean 2.45 due to lack of PLAYERINFO and CHATLOG signatures.
https://github.com/Icehunter/ffxivapp/blob/4adf758eebfc2feef6e23d4000a4181d09a12ce4/FFXIVAPP.Client/Memory/PlayerInfoWorker.cs#L182
https://github.com/Icehunter/ffxivapp/blob/4adf758eebfc2feef6e23d4000a4181d09a12ce4/FFXIVAPP.Client/Memory/ChatLogWorker.cs#L176
Still have a no idea about "how can I port this thing" so I'd just leave it here
Hi there,
I was wondering if it would be possible to add a way to check if FFXIVApp is receiving data from the game? At the moment we achieve this by performing a null reference check as follows:
var PlayerInfo = Reader.GetActors()?.PCEntities?.FirstOrDefault().Value?.CurrentUser;
if (PlayerInfo != null)
However this feels really clunky to use and can cause some interesting behaviour, especially when moving between zones or instances in games.
We have worked around these issues for the time being however I thought it might be nice if a simple bool to check whether FFXIVApp.Memory is actively attached and receiving data from the game could be implemented, therefore avoiding the above issues.
Almost all is well, just the X,Y,Z and Heading moved abit, found the new offsets and it works again.
In structures-global-latest.json
In "ActorItem" :
"Heading": 192
"X": 176
"Y": 184
"Z": 180
In Core\Enums\Actor.cs:
To enum Job : byte added:
RPR = 0x27,
SGE = 0x28,
which adds reaper and sage
Hi there,
I'm trying to initiate this DLL in my project, however whenever i try to attach to FFXIV (using the example in your readme), i get an null value exception error. I have attached a screenshot of the debugger for reference.
public bool InitiateMemory()
{
bool _initiated = false;
Process[] processes9 = Process.GetProcessesByName("ffxiv");
Process[] processes11 = Process.GetProcessesByName("ffxiv_dx11");
// DX9
if (processes9.Length > 0)
{
// supported: English, Chinese, Japanese, French, German, Korean
string gameLanguage = "English";
Process process = processes9[0];
ProcessModel processModel = new ProcessModel
{
Process = process
};
MemoryHandler.Instance.SetProcess(processModel, gameLanguage);
_initiated = true;
}
// DX11
else if (processes11.Length > 0)
{
// supported: English, Chinese, Japanese, French, German, Korean
string gameLanguage = "English";
Process process = processes11[0];
ProcessModel processModel = new ProcessModel
{
Process = process,
IsWin64 = true
};
MemoryHandler.Instance.SetProcess(processModel, gameLanguage);
_initiated = true;
}
return _initiated;
}
Any help would be appreciated.
Patch 6.1 changed a few addresses im guessing regarding CurrentPlayerInfo, though Inventory and Chat retrieval appear unaffected.
A few player properties now return null. HP, GP, Heading, MapZone, etc.
Sorry for all the bug reports/questions..
I've noticed I can't get a read on the PlayerEntity model. I'm trying to access the "Name" variable but also the other variables in the model seem to be incorrect also.
var name = Reader.GetPlayerInfo().PlayerEntity.Name;
//returns random string data.
Are the memory offsets incorrect or is this model depreciated now? I'm trying to use it to compare against the ConcurrentDictionary of ActorEntity to find the active player on the game.
Herro,
Hopefully someone can help.
Trying to get the ModelID returns 0 for all enemies, from the ActorEntity
I can output this:
String text = String.Format("[NPC] {0} {1} - Level: {2} HP: {3} - X: {4} Y: {5} Z: {6} Map: {7}",
entity.ModelID.toString(),
entity.Name,
entity.Level.ToString(),
entity.HPMax.ToString(),
position.X.ToString(),
position.Y.ToString(),
position.Z.ToString(),
entity.MapIndex.ToString()
);
I get all data, but ModelID is 0, either it's returning false or I'm using uint
completely wrong XD
Back when this was memory module I could get the current players position via:
ActorReadResult readResult = Reader.GetActors();
ActorEntity player = readResult.PCEntities.First().Value;
player.X
player.Y
player.MapId
// etc
But First()
is no longer "you", it can be any random person. My assumption is that this is because the memory now deletes all previously recorded entities, so whenever you call readResult
it's already deleted some... Maybe...
Since PlayerInfo
doesn't provde anything, what is best way to get the position of your own character?
Basically the title. There's bytes for the levels and EXP of all the jobs except the new ones added by stormblood.
In my experience,
"ActorEntity": {
...
"TargetID": 472,
...
}
is not perfect.
I found a better one. Try it.
"ActorEntity": {
...
"TargetID": 5648,
...
}
In addition, need to change the type of TargetID from int
to uint
.
Describe the bug
Setting JSONCacheDirectory on a directory that does not exists causes reader to fail silently
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Successful saving of json data in said directory with creation of directory if not existing
Additional context
C# has an inbuilt method for directory creation in DirectoryInfo.Exists
and DirectoryInfo.Create()
Current way of solving this is to just manually check if the directory is created before even initializing the memory reader but this function should be implemented into the library as a safety since some people can get stuck if they try to modify this without realizing this issue exists.
Updated pointer path for ZONEINFO
"PointerPath": [
18515832
]
Don't remember how to submit to the API!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.