Skip to content

Commit

Permalink
0.4.0-alpha
Browse files Browse the repository at this point in the history
- New major feature: Enemy tracking:
	* display name, HP, and MP of every hostile character in the current room,
	* text file for this one is `game_data/map/enemy_data.txt`,

- Add controller input tracking, with button holding timers (debug build only),
- Add current game mode tracking (debug build only). Currently recognized modes are:
	* Normal,
	* Battle,
	* Cut-scene,
	* Menu Screen,
	* Quick Menu,
	* First Person View,
	* Activate Panel,
	* Open Container,
	* Draw Weapon,
	* Use Locked Door,
	* End of Turn
- Update supported `BizHawk` version to `2.6.1`
  • Loading branch information
tomasz-rozanski committed Apr 7, 2021
1 parent 75fb2c3 commit eacc614
Show file tree
Hide file tree
Showing 15 changed files with 598 additions and 41 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,6 @@ sub.bat
# Misc
changes.md
TODO.md
.vimrc
ed.bat

5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ At this moment, you can track the following:
* Player stats (HP, MP, RISK, STR, INT, AGL, range, walking/running speed)
* Player status effects
* Player location (area name, room name)
* Enemy tracking (name, HP, MP)
* In-game timer (with 1 second precision)
* Kill List and Weapon Usage list
* Map and Chest completion (**real-time!**)
Expand All @@ -37,7 +38,7 @@ Currently, *VSTrack* can work with [ePSXe][epsxe-emulator] and [BizHawk][bizhawk
To use *VSTrack* you'll need:
* One of the supported emulators:
* **ePSXe** version *1.9.25* or *2.0.5*
* **BizHawk** version *2.4.2*
* **BizHawk** version *2.6.1*
* Copy of the game:
* **Vagrant Story** NTSC-US version *(SLUS-01040)* <sup>1</sup>

Expand All @@ -52,7 +53,7 @@ No installation is required. Just copy the executable into preffered folder, and

When you'll see the start menu, press key `1-3` to choose emulator version you're using to play the game, or `0` to exit. If your selection was correct, you should see some basic game information in the console window.

Alternatively, you can pass preferred emulator number as a command-line parameter, so if you want to use *VSTrack* with `BizHawk 2.4.2`, type:
Alternatively, you can pass preferred emulator number as a command-line parameter, so if you want to use *VSTrack* with `BizHawk 2.6.1`, type:
```bash
vstrack.exe 3
```
Expand Down
345 changes: 345 additions & 0 deletions includes/vst_actors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
#ifndef _VST_ACTORS_H
#define _VST_ACTORS_H

#define OFFSET_ACTOR_DATA_POINTERS 0x800F1928
#define OFFSET_ACTOR_DATA_FIRST_NODE 0x8011f9f0
#define MAX_ACTORS_NUMBER 15
#define ACTORS_NAMES_LIST_LENGTH 108

char *ActorsNamesList[ACTORS_NAMES_LIST_LENGTH] = { //
"Air Elemental", //
"Arch Dragon", //
"Ashley Riot", //
"Asura", //
"Bandit", //
"Basilisk", //
"Bat", //
"Bejart", //
"Blood Lizard", //
"Callo Merlose", //
"City Gaurd", //
"Crimson Blade", //
"Damascus Crab", //
"Damascus Golem", //
"Dao", //
"Dark Crusader", //
"Dark Dragon", //
"Dark Elemental", //
"Dark Skeleton", //
"Dark Eye", //
"Dead Crimson Blade", //
"Death", //
"Djinn", //
"Dragon", //
"Dragon Zombie", //
"Duane", //
"Duke Bardorba", //
"Dullahan", //
"Dummy", //
"Earth Dragon", //
"Earth Elemental", //
"Fire Elemental", //
"Flame Dragon", //
"Gargoyle", //
"Ghast", //
"Ghost", //
"Ghoul", //
"Giant Crab", //
"Goblin", //
"Goblin Leader", //
"Golem", //
"Goodwin", //
"Gremlin", //
"Grissom", //
"Guildenstern", //
"Harpy", //
"Hellhound", //
"Ichthious", //
"Ifrit", //
"Imp", //
"Iron Crab", //
"Iron Golem", //
"John Hardin", //
"Joshua Bardorba", //
"Kali", //
"Last Crusader", //
"Lich", //
"Lich Lord", //
"Lizardman", //
"Lord Joshua", //
"Mandel", //
"Marco Riot", //
"Marid", //
"Matrix Ashley", //
"Matrix Merlose", //
"Mimic", //
"Minotaur", //
"Minotaur Lord", //
"Minotaur Zombie", //
"Mullenkamp Soldier", // change 'ü' to 'u'?
"Mummy", //
"Neesa", //
"Nightmare", //
"Nightstalker", //
"Ogre", //
"Ogre Lord", //
"Ogre Zombie", //
"Orc", //
"Orc Leader", //
"Poison Slime", //
"Quicksilver", //
"Ravana", //
"Rosencrantz", //
"Sackheim", //
"Samantha", //
"Sarjik", //
"Shadow", //
"Shrieker", //
"Silver Wolf", //
"Skeleton", //
"Skeleton Knight", //
"Sky Dragon", //
"Slime", //
"Snow Dragon", //
"Stirge", //
"Sydney Losstarot", // probably not used in this form (look below)
"Sydney", //
"Tia Riot", //
"Tieger", //
"Water Elemental", //
"Wraith", //
"Wyvern", //
"Wyvern Knight", //
"Wyvern Queen", //
"Zombie", //
"Zombie Fighter", //
"Zombie Knight", //
"Zombie Mage"
};

void
ReadActorPointer(u32 *ActorPointer, usize ActorNumber)
{
usize BytesToRead = sizeof(u32);

ReadGameMemory(processID,
OFFSET_ACTOR_DATA_POINTERS + (ActorNumber * sizeof(u32)), BytesToRead,
ActorPointer);
}

void
ReadActorData(actor_data *ActorData, u32 ActorPointer)
{
usize BytesToRead = sizeof(actor_data);

ReadGameMemory(processID, (usize) ActorPointer, BytesToRead, ActorData);
}

void
ReadNextActorPointer(u32 *ActorPointerCur, u32 *ActorPointerNext)
{
actor_data ActorDataTemp;
ReadActorData(&ActorDataTemp, *ActorPointerCur);
*ActorPointerNext = ActorDataTemp.NextActorPtr;
}

BOOL
IsActorNameValid(char *ActorName)
{
for (int i = 0; i < ACTORS_NAMES_LIST_LENGTH; i++)
{

if (strcmp(ActorName, ActorsNamesList[i]) == 0)
{
return TRUE;
}
}
return FALSE;
}

void
PrintActorsDataOld()
{
sprintf(szBuffer, "\nACTIVE ACTORS:\n");
WriteToBackBuffer();

actor_data ActorData;
u32 ActorPointer = 0;
u32 ActiveActorMarker = 0;

// ReadActiveActorMarker(OFFSET_ACTIVE_ACTOR_MARKER, &ActiveActorMarker);
// sprintf(szBuffer, "ActiveActorMarker: 0x%x\n", ActiveActorMarker);
// WriteToBackBuffer();

for (int i = 2; i < MAX_ACTORS_NUMBER; i++)
{
ReadActorPointer(&ActorPointer, i);
if (ActorPointer)
{
ReadActorData(&ActorData, ActorPointer);

// u32 NameOffset = ActorPointer + (u32) offsetof(actor_data, Name);
ReadActorName(ActorData.NamePointer);

if (IsActorNameValid(ActorName))
{
u16 HPCur = ActorData.HPCur;
u16 HPMax = ActorData.HPMax;
u16 MPCur = ActorData.MPCur;
u16 MPMax = ActorData.MPMax;

if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 &&
MPMax == 100) // cutscene
{
return;
}

if (HPCur == 0)
{
continue;
}

sprintf(szBuffer, "%s -- ", ActorName);
WriteToBackBuffer();

sprintf(szBuffer, "HP %d/%d ", HPCur, HPMax);
WriteToBackBuffer();

if (MPMax > 0)
{
sprintf(szBuffer, "MP %d/%d ", MPCur, MPMax);
}

sprintf(szBuffer, "ADDR 0x%x ", ActorPointer);
WriteToBackBuffer();

sprintf(szBuffer, "\n");
WriteToBackBuffer();
}
}
}
}

void
PrintActorsData()
{
sprintf(szBuffer, "\nACTIVE ACTORS:\n");
WriteToBackBuffer();

actor_data ActorData;
u32 ActorPointerCur = OFFSET_ACTOR_DATA_POINTERS;
u32 ActorPointerNext = 0x000000;

// sprintf(szBuffer, "ADDR 0x%x\n", ActorPointerCur);
// WriteToBackBuffer();

ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext);
while (ActorPointerNext)
{
ReadActorData(&ActorData, ActorPointerNext);

ReadActorName(ActorData.NamePointer);

u16 HPCur = ActorData.HPCur;
u16 HPMax = ActorData.HPMax;
u16 MPCur = ActorData.MPCur;
u16 MPMax = ActorData.MPMax;

if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 &&
MPMax == 100) // cutscene
{
return;
}

sprintf(szBuffer, "0x%x -- ", ActorPointerNext);
WriteToBackBuffer();

sprintf(szBuffer, "%s -- ", ActorName);
WriteToBackBuffer();

if (HPCur == 0)
{
sprintf(szBuffer, "Dead ");
WriteToBackBuffer();
}
else
{
sprintf(szBuffer, "HP %d/%d ", HPCur, HPMax);
WriteToBackBuffer();

if (MPMax > 0)
{
sprintf(szBuffer, "MP %d/%d ", MPCur, MPMax);
WriteToBackBuffer();
}
}
sprintf(szBuffer, "\n");
WriteToBackBuffer();

ActorPointerCur = ActorPointerNext;
ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext);
}
}

void
WriteActorsData()
{
FILE *fpActorsData = fopen("game_data/map/enemy_data.txt", "w");

fprintf(fpActorsData, "Active Enemies\n");

actor_data ActorData;
// Use this one if you want to include player data:
// u32 ActorPointerCur = OFFSET_ACTOR_DATA_POINTERS;
u32 ActorPointerCur = OFFSET_ACTOR_DATA_FIRST_NODE;
u32 ActorPointerNext = 0x000000;

// sprintf(fpActorsData, "ADDR 0x%x\n", ActorPointerCur);
// WriteToBackBuffer();

ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext);
while (ActorPointerNext)
{
ReadActorData(&ActorData, ActorPointerNext);

ReadActorName(ActorData.NamePointer);

u16 HPCur = ActorData.HPCur;
u16 HPMax = ActorData.HPMax;
u16 MPCur = ActorData.MPCur;
u16 MPMax = ActorData.MPMax;

if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 &&
MPMax == 100) // cutscene
{
return;
}

// fprintf(fpActorsData, "0x%x -- ", ActorPointerNext);

fprintf(fpActorsData, "%s -- ", ActorName);

if (HPCur == 0)
{
fprintf(fpActorsData, "Dead ");
}
else
{
fprintf(fpActorsData, "HP %d/%d ", HPCur, HPMax);

if (MPMax > 0)
{
fprintf(fpActorsData, "MP %d/%d ", MPCur, MPMax);
}
}
fprintf(fpActorsData, "\n");

ActorPointerCur = ActorPointerNext;
ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext);
}

fclose(fpActorsData);
}

#endif

Loading

0 comments on commit eacc614

Please sign in to comment.