Home » BIT COMPOSER GAMES » JA:BiA Modding » Live Character Editor
Live Character Editor[message #315091] Sat, 02 February 2013 19:55 Go to next message
Reconsider

 
Messages:7
Registered:January 2013
Hello

I am working on a character editor with which you can edit characters while playing.
http://i.imgur.com/lB4oLrJ.jpg
http://i.imgur.com/OO66RKg.jpg
http://i.imgur.com/z8iD7tZ.jpg

I would like some input on what to add, if anyone got some offsets/classes/structs to help me out, that would be good too Smile

Here's the classes I've reversed sofar, in format for C++ and C#:
C++
class CList;
class CListEntry;
class CObject;
class CInventory;
class CInventorySlot;
class CGame;
class CObjectList;

class CList
{
public:
	CList* next; //0x0000 
	CList* prev; //0x0004 
	CListEntry* entry; //0x0008 
char _0x000C[12];

};//Size=0x0018

class CListEntry
{
public:
char _0x0000[52];
	CObject* merc; //0x0034 

};//Size=0x0038

class CObject
{
public:
char _0x0000[92];
	__int32 faction; //0x005C 
char _0x0060[4];
	__int32 melee_performed; //0x0064 
	__int32 grenades_thrown; //0x0068 
char _0x006C[16];
	__int32 rockets_fired; //0x007C 
	__int32 bullets_fired; //0x0080 
	__int32 bullets_hit; //0x0084 
	__int32 bullets_hit_normal; //0x0088 
	__int32 bullets_hit_critical; //0x008C 
	__int32 enemies_killed; //0x0090 
	__int32 total_damage_dealt; //0x0094 
char _0x0098[8];
	__int32 total_damage_taken; //0x00A0 
	__int32 times_bleeding; //0x00A4 
	__int32 times_wounded; //0x00A8 
	__int32 times_rescued_from_dying; //0x00AC 
	__int32 times_died; //0x00B0 
	__int32 successful_healing_checks; //0x00B4 
	__int32 unsuccessful_healing_checks; //0x00B8 
	__int32 total_amount_health_restored; //0x00BC 
	__int32 successful_repair_checks; //0x00C0 
	__int32 unsuccessful_repair_checks; //0x00C4 
	__int32 total_amount_durability_restored; //0x00C8 
	__int32 successful_mines_disarmed; //0x00CC 
	__int32 unsuccessful_mines_disarmed; //0x00D0 
	__int32 successful_mines_planted; //0x00D4 
	__int32 unsuccessful_mines_planted; //0x00D8 
	__int32 successful_explosives_planted; //0x00DC 
	__int32 unsuccessful_explosives_planted; //0x00E0 
	__int32 successful_locks_picked; //0x00E4 
	__int32 unsuccessful_locks_picked; //0x00E8 
	__int32 successful_doors_forced; //0x00EC 
	__int32 unsuccessful_doors_forced; //0x00F0 
	__int32 total_days_in_service; //0x00F4 
char _0x00F8[32];
	__int32 level; //0x0118 
	__int32 experience; //0x011C 
	__int32 training_points; //0x0120 
	__int32 agility_add; //0x0124 
	__int32 dexterity_add; //0x0128 
	__int32 strength_add; //0x012C 
	__int32 intelligence_add; //0x0130 
	__int32 perception_add; //0x0134 
	__int32 medical_add; //0x0138 
	__int32 explosives_add; //0x013C 
	__int32 marksmanship_add; //0x0140 
	__int32 stealth_add; //0x0144 
	__int32 mechanical_add; //0x0148 
char _0x014C[40];
	CInventory N00C3679F; //0x0174 
char _0x0264[16];
	char name[16]; //0x0274 
	__int32 name_length; //0x0284 
char _0x0288[4];
	__int32 faction2; //0x028C 
	__int32 state; //0x0290 13 dead, 27 dying, 29 dead
	float health; //0x0294 
	float stamina; //0x0298 
	__int32 agility; //0x029C 
	__int32 dexterity; //0x02A0 
	__int32 strength; //0x02A4 
	__int32 intelligence; //0x02A8 
	__int32 perception; //0x02AC 
	__int32 medical; //0x02B0 
	__int32 explosives; //0x02B4 
	__int32 marksmanship; //0x02B8 
	__int32 stealth; //0x02BC 
	__int32 mechanical; //0x02C0 
	float health_cap; //0x02C4 
	float stamina_cap; //0x02C8 
	__int32 agility_penalty; //0x02CC 
	__int32 dexterity_penalty; //0x02D0 
	__int32 strength_penalty; //0x02D4 
	__int32 intelligence_penalty; //0x02D8 
	__int32 perception_penalty; //0x02DC 
	__int32 bleed_rate; //0x02E0 
char _0x02E4[164];

};//Size=0x0388

class CInventory
{
public:
char _0x0000[16];
	CInventorySlot N00C4CF9D; //0x0010 INVENTORY_EQUIPPED_WEAPON
	CInventorySlot N00C7108C; //0x0018 INVENTORY_EQUIPPED_OFFHAND
	CInventorySlot N00C74D4E; //0x0020 INVENTORY_EQUIPPED_HEAD
	CInventorySlot N00C7721D; //0x0028 INVENTORY_EQUIPPED_FACE
	CInventorySlot N00C778D1; //0x0030 INVENTORY_EQUIPPED_TORSO
	CInventorySlot N00C886AA; //0x0038 INVENTORY_EQUIPPED_VEST
	CInventorySlot N00C886BA; //0x0040 INVENTORY_EQUIPPED_SHOES
	CInventorySlot N00C886CA; //0x0048 INVENTORY_EQUIPPED_LEGS
	CInventorySlot N00C886DA; //0x0050 INVENTORY_EQUIPPED_AMMO
	CInventorySlot N00C886EA; //0x0058 INVENTORY_EQUIPPED_ATTACHMENT
	CInventorySlot N00C886FA; //0x0060 INVENTORY_WEAPON_1
	CInventorySlot N00C8870A; //0x0068 INVENTORY_WEAPON_2
	CInventorySlot N00C8871A; //0x0070 INVENTORY_WEAPON_3
	CInventorySlot N00C8872A; //0x0078 INVENTORY_1_1
	CInventorySlot N00C8873A; //0x0080 INVENTORY_1_2
	CInventorySlot N00C8874A; //0x0088 INVENTORY_1_3
	CInventorySlot N00C8875A; //0x0090 INVENTORY_1_4
	CInventorySlot N00C8876A; //0x0098 INVENTORY_1_5
	CInventorySlot N00C8877A; //0x00A0 INVENTORY_2_1
	CInventorySlot N00C8878A; //0x00A8 INVENTORY_2_2
	CInventorySlot N00C8879A; //0x00B0 INVENTORY_2_3
	CInventorySlot N00C937FC; //0x00B8 INVENTORY_2_4
	CInventorySlot N00C93B47; //0x00C0 INVENTORY_2_5
	CInventorySlot N00C93B57; //0x00C8 INVENTORY_3_1
	CInventorySlot N00C93B67; //0x00D0 INVENTORY_3_2
	CInventorySlot N00C93B77; //0x00D8 INVENTORY_3_3
	CInventorySlot N00C93B87; //0x00E0 INVENTORY_3_4
	CInventorySlot N00C93B97; //0x00E8 INVENTORY_3_5

};//Size=0x00F0

class CInventorySlot
{
public:
	WORD id; //0x0000 
	WORD amount; //0x0002 
	WORD durability; //0x0004 
	WORD uses; //0x0006 

};//Size=0x0008

class CGame
{
public:
char _0x0000[188];
	CObjectList* objectList; //0x00BC 
char _0x00C0[896];

};//Size=0x0440

class CObjectList
{
public:
	CObjectList* next; //0x0000 
	CObjectList* prev; //0x0004 
	CObject* object; //0x0008 
char _0x000C[4];

};//Size=0x0010

C#
using System;
using System.Runtime.InteropServices;

namespace JABIAeditor
{
    class Engine
    {
        private static byte[] nameBuffer = new byte[16];
        public static unsafe string GetName(Engine.Object obj)
        {
            for (int i = 0; i < 16; i++)
            {
                if (i > obj.name_length)
                {
                    nameBuffer[i] = 0;
                }
                else
                {
                    nameBuffer[i] = obj.name[i];
                }
            }

            return System.Text.Encoding.Default.GetString(nameBuffer, 0, 16);
        }

        public static unsafe byte[] SetName(ref Engine.Object obj, string name)
        {
            char[] str = name.ToCharArray();
            fixed (byte* ptr = obj.name)
            {
                for (int i = 0; i < 16; i++)
                {
                    if (i == str.Length)
                    {
                        ptr[i] = 0;
                        break;
                    }
                    else
                    {
                        ptr[i] = (byte)str[i];
                    }
                }
            }

            return nameBuffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct InventorySlot
        {
            public UInt16 id;
            public UInt16 amount;
            public UInt16 durability;
            public UInt16 uses;
        }

        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct Inventory
        {
            private fixed byte _0000[16];
            public InventorySlot equipped_weapon;
            public InventorySlot equipped_offhand;
            public InventorySlot equipped_head;
            public InventorySlot equipped_face;
            public InventorySlot equipped_torso;
            public InventorySlot equipped_vest;
            public InventorySlot equipped_feet;
            public InventorySlot equipped_legs;
            public InventorySlot equipped_ammo;
            public InventorySlot equipped_attachment;
            public InventorySlot inventory_weapon1;
            public InventorySlot inventory_weapon2;
            public InventorySlot inventory_weapon3;
            public InventorySlot inventory_1_1;
            public InventorySlot inventory_1_2;
            public InventorySlot inventory_1_3;
            public InventorySlot inventory_1_4;
            public InventorySlot inventory_1_5;
            public InventorySlot inventory_2_1;
            public InventorySlot inventory_2_2;
            public InventorySlot inventory_2_3;
            public InventorySlot inventory_2_4;
            public InventorySlot inventory_2_5;
            public InventorySlot inventory_3_1;
            public InventorySlot inventory_3_2;
            public InventorySlot inventory_3_3;
            public InventorySlot inventory_3_4;
            public InventorySlot inventory_3_5;
        }

        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct Object
        {
            public fixed byte _0000[92];
            public int faction;
            public fixed byte _0060[4];
            public int melee_performed;
            public int grenades_thrown;
            public fixed byte _006C[16];
            public int rockets_fired;
            public int bullets_fired;
            public int bullets_hit;
            public int bullets_hit_normal;
            public int bullets_hit_critical;
            public int enemies_killed;
            public int total_damage_dealt;
            public fixed byte _0098[8];
            public int total_damage_taken;
            public int times_bleeding;
            public int times_wounded;
            public int times_rescued_from_dying;
            public int times_died;
            public int successful_healing_checks;
            public int unsuccessful_healing_checks;
            public int total_amount_health_restored;
            public int successful_repair_checks;
            public int unsuccessful_repair_checks;
            public int total_amount_durability_restored;
            public int successful_mines_disarmed;
            public int unsuccessful_mines_disarmed;
            public int successful_mines_planted;
            public int unsuccessful_mines_planted;
            public int successful_explosives_planted;
            public int unsuccessful_explosives_planted;
            public int successful_locks_picked;
            public int unsuccessful_locks_picked;
            public int successful_doors_forced;
            public int unsuccessful_doors_forced;
            public int total_days_in_service;
            public fixed byte _00F8[32];
            public int level;
            public int experience;
            public int training_points;
            public int agility_add;
            public int dexterity_add;
            public int strength_add;
            public int intelligence_add;
            public int perception_add;
            public int medical_add;
            public int explosives_add;
            public int marksmanship_add;
            public int stealth_add;
            public int mechanical_add;
            public fixed byte _014C[40];
            public Inventory inventory;
            public fixed byte _0264[16];
            public fixed byte name[16];
            public int name_length;
            public fixed byte _0288[4];
            public int faction2;
            public uint state;
            public float health;
            public float stamina;
            public int agility;
            public int dexterity;
            public int strength;
            public int intelligence;
            public int perception;
            public int medical;
            public int explosives;
            public int marksmanship;
            public int stealth;
            public int mechanical;
            public float health_cap;
            public float stamina_cap;
            public int agility_penalty;
            public int dexterity_penalty;
            public int strength_penalty;
            public int intelligence_penalty;
            public int perception_penalty;
            public int bleed_rate;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ObjectList
        {
            public UIntPtr next; // ObjectList* next;
            public UIntPtr prev; // ObjectList* prev;
            public UIntPtr ptr; // Object* ptr;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct Game
        {
            [FieldOffset(0xBC)]
            public UIntPtr objList; // ObjectList* objectList;
        }

        public enum InventorySlots
        {
            None = -1,
            Equipped_Weapon,
            Equipped_Offhand,
            Equipped_Head,
            Equipped_Face,
            Equipped_Torso,
            Equipped_Vest,
            Equipped_Feet,
            Equipped_Legs,
            Equipped_Ammo,
            Equipped_Attachment,
            Weapon_1,
            Weapon_2,
            Weapon_3,
            Slot_1_1,
            Slot_1_2,
            Slot_1_3,
            Slot_1_4,
            Slot_1_5,
            Slot_2_1,
            Slot_2_2,
            Slot_2_3,
            Slot_2_4,
            Slot_2_5,
            Slot_3_1,
            Slot_3_2,
            Slot_3_3,
            Slot_3_4,
            Slot_3_5
        };

        public enum Factions
        {
            HumanPlayer,
            HumanMilitia,
            Deidranna,
            Hillbillies,
            KillTarget,
            VillagePeople
        };
    }
}


Thanks to sbobovyc opensource project I got a few things too.

You can find CGame* like so:
/* this function runs through all players until the end
eax is CGame
+BC is start of list
GameJABiA.exe+108E30 - 55             - push ebp
GameJABiA.exe+108E31 - 8B EC          - mov ebp,esp
GameJABiA.exe+108E33 - 83 E4 F8       - and esp,F8
GameJABiA.exe+108E36 - 51             - push ecx
GameJABiA.exe+108E37 - 8B 45 08       - mov eax,[ebp+08]
GameJABiA.exe+108E3A - 8B 88 BC000000 - mov ecx,[eax+000000BC]
GameJABiA.exe+108E40 - 53             - push ebx
GameJABiA.exe+108E41 - 8B 19          - mov ebx,[ecx]
GameJABiA.exe+108E43 - 56             - push esi
GameJABiA.exe+108E44 - 57             - push edi
GameJABiA.exe+108E45 - 8B B8 A8000000  - mov edi,[eax+000000A8]
GameJABiA.exe+108E4B - EB 03          - jmp GameJABiA.exe+108E50
GameJABiA.exe+108E4D - 8D 49 00       - lea ecx,[ecx-00]
GameJABiA.exe+108E50 - 8B B0 BC000000 - mov esi,[eax+000000BC]
GameJABiA.exe+108E56 - 8B 80 A8000000 - mov eax,[eax+000000A8]
GameJABiA.exe+108E5C - 85 FF          - test edi,edi
GameJABiA.exe+108E5E - 74 04          - je GameJABiA.exe+108E64
GameJABiA.exe+108E60 - 3B F8          - cmp edi,eax
*/

I didn't look for a static ptr yet, but should..
Re: Live Character Editor[message #315093] Sat, 02 February 2013 20:04 Go to previous messageGo to next message
Sam Hotte

 
Messages:2023
Registered:March 2009
Location: Middle of Germany
Recons
I would like some input on what to add,

If that worked also for militia (and even enemy, too), one could give them some sort of uniform, distinguishable look ...
Re: Live Character Editor[message #315097] Sat, 02 February 2013 20:47 Go to previous messageGo to next message
Reconsider

 
Messages:7
Registered:January 2013
Sam_Hotte

If that worked also for militia (and even enemy, too), one could give them some sort of uniform, distinguishable look ...
Hello

It works Smile

See this image and read below:
http://i.imgur.com/xGVSCQE.jpg

I have changed the appearance of Militia member "Xavier Jimenez", he previously had a black bandana and the gas-mask t-shirt, now he has a white bandana and red Hawaii shirt. The changes are persistent.

Only issue is that if you are inside the same map as that character you need to leave (to the map screen) and back inside again, then it updates.

There is a function that is called when closing the inventory-screen that updates the character. I will try to find it and see if I can do something with it. Smile
Re: Live Character Editor[message #315099] Sat, 02 February 2013 21:06 Go to previous message
Sam Hotte

 
Messages:2023
Registered:March 2009
Location: Middle of Germany
:bluecool:
Previous Topic: Gateway to the Modifications
Next Topic: Blender import and export tools
Goto Forum:
  


Current Time: Tue Jun 19 07:44:48 EEST 2018

Total time taken to generate the page: 0.01151 seconds