Portal-Zone Gothic-Zone Gothic II-Zone Gothic 3-Zone Gothic 4-Zone Modifikationen-Zone Download-Zone Foren-Zone RPG-Zone Almanach-Zone Spirit of Gothic

 

Ergebnis 1 bis 8 von 8
  1. Beiträge anzeigen #1 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    290
     
    F a w k e s ist offline

    G1 - how to pickpocket Orcs?

    Hello folks,
    Hoping someone has here experience with this - I assume pickpocketing is restricted to humans only in G1 (GIL_SEPERATOR_HUM) in some engine functions. I would like to remove that restriction, since I want to be able to use pickpocketing with Orcs
    However with my limited knowledge I am not sure how to do this. I guess this will require LeGo and hook/override of an engine functions.
    Can anyone advice how to enable pickpocketing for orcs?

  2. Beiträge anzeigen #2 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.327
     
    mud-freak ist offline
    Zitat Zitat von F a w k e s Beitrag anzeigen
    Hello folks,
    Hoping someone has here experience with this - I assume pickpocketing is restricted to humans only in G1 (GIL_SEPERATOR_HUM) in some engine functions. I would like to remove that restriction, since I want to be able to use pickpocketing with Orcs
    However with my limited knowledge I am not sure how to do this. I guess this will require LeGo and hook/override of an engine functions.
    Can anyone advice how to enable pickpocketing for orcs?
    If you are eager to figure it out yourself, here are some pointers:
    You can check this script to get a better idea of how pickpocketing is implemented. This script reinstates it in Gothic 2 on engine-level, the same way it is implemented in Gothic 1. For a rough idea, it might point you in the right direction regarding what engine functions to look at.
    From what I remember the check for the victim being human (among other things), should either be in oCAIHuman::StandActions just before the call to oCNpc::OpenSteal or in oCNpc::OpenSteal itself.

    If this info doesn't help you, I (or someone else) might be willing to give you an exact address.


    PS: The script that I linked is overly long, but the core is actually quite simple. It's only the function "PP_Enable" that is important, the rest is sugar.

  3. Beiträge anzeigen #3 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    290
     
    F a w k e s ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    ... If this info doesn't help you, I (or someone else) might be willing to give you an exact address.
    Hello mud-freak !
    How willing would you be to give me whole solution ?
    I assume this will require more (from your script I guess some machine code like entries) than just a simple MEM_WriteInt I am used to - I am afraid I would fail spectacularly here

  4. Beiträge anzeigen #4 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.327
     
    mud-freak ist offline
    Zitat Zitat von F a w k e s Beitrag anzeigen
    Hello mud-freak !
    How willing would you be to give me whole solution ?
    I assume this will require more (from your script I guess some machine code like entries) than just a simple MEM_WriteInt I am used to - I am afraid I would fail spectacularly here
    In the beginning of oCNpc::OpenSteal(void) (0x6BB350) you find - very tidily - the conditions on which the victims is valid. One of which is something like
    Code:
    if (stealnpc->GetTrueGuild() == GIL_SEPERATOR_ORC /*0x25 = 37*/)
    This is
    Code:
    .text:006BB3AD 8B 0D 28 BC 8D 00             mov     ecx, oCNpc * stealnpc
    .text:006BB3B3 E8 08 2C FD FF                call    oCNpc::GetTrueGuild(void)
    .text:006BB3B8 83 F8 25                      cmp     eax, 25h
    .text:006BB3BB 0F 84 88 04 00 00             jz      loc_006BB849
    You could do all kinds of things to disable/skip this condition. The most simple might be to change the guild ID at 0x6BB3BA to one that does not exist, like 255 (0xFF):
    Code:
    const int once = 0;
    if (!once) {
        const int oCNpc__OpenSteal_guildId = 7058362; //0x6BB3BA
        MemoryProtectionOverride(oCNpc__OpenSteal_guildId, 1);
        MEM_WriteByte(oCNpc__OpenSteal_guildId, 255); // Guild that does not exist
        once = 1;
    };
    Maybe that works. Code for Gothic 1 and untested.



    PS: From what I can guess, when getting caught, the perception will trigger ZS_CatchThief - also for orcs, as their perception is set like humans with ObservingPerception. So you should add a special case for orcs in that function to avoid weird bugs.
    Geändert von mud-freak (23.04.2020 um 14:30 Uhr)

  5. Beiträge anzeigen #5 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    290
     
    F a w k e s ist offline
    Hello mud-freak,
    Thank you for your time!
    I did some testing - writing value 255 does not allow me to pickpocket Orcs unfortunatelly.
    Code:
        const int oCNpc__OpenSteal_guildId = 7058362; //0x6BB3BA
        MemoryProtectionOverride(oCNpc__OpenSteal_guildId, 1);
        MEM_WriteByte(oCNpc__OpenSteal_guildId, 255); // Guild that does not exist
    Writing value 1 (GIL_EBR) however prevents me from pickpocketing Ore Barons.
    Code:
        const int oCNpc__OpenSteal_guildId = 7058362; //0x6BB3BA
        MemoryProtectionOverride(oCNpc__OpenSteal_guildId, 1);
        MEM_WriteByte(oCNpc__OpenSteal_guildId, 1); // GIL_EBR
    I also hooked oCNpc__OpenSteal just to see if function is called - hook prints out 'oCNpc__OpenSteal' and I am getting prints for both scenarios when I am attempting to pickpocket Humans & Orcs.

    Which suggests me that there is one more condition somewhere ruling out Orcs. Would you mind to check further what it might be ?

  6. Beiträge anzeigen #6 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.327
     
    mud-freak ist offline
    Zitat Zitat von F a w k e s Beitrag anzeigen
    Hello mud-freak,
    Thank you for your time!
    I did some testing - writing value 255 does not allow me to pickpocket Orcs unfortunatelly.
    Code:
        const int oCNpc__OpenSteal_guildId = 7058362; //0x6BB3BA
        MemoryProtectionOverride(oCNpc__OpenSteal_guildId, 1);
        MEM_WriteByte(oCNpc__OpenSteal_guildId, 255); // Guild that does not exist
    Writing value 1 (GIL_EBR) however prevents me from pickpocketing Ore Barons.
    Code:
        const int oCNpc__OpenSteal_guildId = 7058362; //0x6BB3BA
        MemoryProtectionOverride(oCNpc__OpenSteal_guildId, 1);
        MEM_WriteByte(oCNpc__OpenSteal_guildId, 1); // GIL_EBR
    I also hooked oCNpc__OpenSteal just to see if function is called - hook prints out 'oCNpc__OpenSteal' and I am getting prints for both scenarios when I am attempting to pickpocket Humans & Orcs.

    Which suggests me that there is one more condition somewhere ruling out Orcs. Would you mind to check further what it might be ?
    Nice debugging! I would have looked outside of OpenSteal assuming another condition prevents to even enter the function, but your hint about the print in the hook made it easy to find my mistake.

    One of the conditions in the beginning of OpenSteal that I mentioned, is stealnpc->IsMonster(). Since there is the additional check for orcs afterwards, I thought orcs do not count as monsters. But they are already excluded with this condition (it's essentially checking (stealnpc.bitfield[2] & oCNpc_bitfield2_guildTrue) <= GIL_SEPERATOR_HUM), so they never reach the condition for orcs. I guess I can rewrite these conditions to something like:
    Code:
    a = stealnpc->GetTrueGuild(); // (stealnpc.bitfield[2] & oCNpc_bitfield2_guildTrue)
    if ((a <= GIL_SEPERATOR_HUM /*0x10 = 16*/)
    ||  (a == GIL_SEPERATOR_ORC /*0x25 = 37*/))
    This could either be done by rewriting the bytes directly, or hooking it and handling the conditions in Daedalus (allowing more freedom in general). Not sure when I find the time, but I can have a look.

  7. Beiträge anzeigen #7 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.327
     
    mud-freak ist offline
    I decided to write a hook for deadalus. I haven't tested this code, there is a good chance there are some mistakes in there.

    Code:
    /*
     * Customize this function to define the conditions for eligible pickpocketing victims
     */
    func int Npc_OpenStealConditions(var int stealnpc) {
        var oCNpc vict; vict = _^(stealnpc);
        var int trueGuild; trueGuild = vict.bitfield[2] & oCNpc_bitfield2_guildTrue;
        return (trueGuild <= GIL_SEPERATOR_HUM) || (trueGuild == GIL_SEPERATOR_ORC);
    };
    
    
    // ...
    
    
    /*
     * One-time initialization
     */
    func void Npc_OpenStealConditions_Init() {
        const int once = 0;
        if (!once) {
            // The once-construct is really important here, because the hook must not be overwritten a second time
            const int oCNpc__OpenSteal_conditions = 7058333; //0x6BB39D
            const int bytes[8] = {-1869574000, -1869574000, -1869574000, -1869574000,  // 0x90909090 nop; nop; nop; nop
                                  -1869574000, -1869574000, -1869574000,       49285}; // 0xC085     test eax, eax
            MemoryProtectionOverride(oCNpc__OpenSteal_conditions, 30);
            MEM_CopyBytes(_@(bytes), oCNpc__OpenSteal_conditions, 30);
            HookEngineF(oCNpc__OpenSteal_conditions, 5, Npc_OpenStealConditions_);
            once = 1;
        };
    }; func void Npc_OpenStealConditions_() {
        EAX = Npc_OpenStealConditions(ECX);
    };
    Geändert von mud-freak (23.04.2020 um 21:21 Uhr)

  8. Beiträge anzeigen #8 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    290
     
    F a w k e s ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    ... hooking it and handling the conditions in Daedalus (allowing more freedom in general).
    I love freedom !
    Zitat Zitat von mud-freak Beitrag anzeigen
    I decided to write a hook for deadalus. I haven't tested this code, there is a good chance there are some mistakes in there.
    I had to use bitwise right shift on trueguild + change operator to include all orc guilds (>=GIL_SEPERATOR_ORC) and now I am able to pickpocket them. Thank you very much ! You are a lifesaver.
    Code:
    /*
     * Customize this function to define the conditions for eligible pickpocketing victims
    */
    func int Npc_OpenStealConditions(var int stealnpc) {
        var oCNpc vict; vict = _^(stealnpc);
        //const int oCNPC_bitfield2_guildTrue = ((1 << 8) - 1) << 16;
        var int trueGuild; trueGuild = (vict.bitfield[2] & oCNpc_bitfield2_guildTrue)>>16;
        return (trueGuild <= GIL_SEPERATOR_HUM) || (trueGuild >= GIL_SEPERATOR_ORC);
    };

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
Impressum | Link Us | intern
World of Gothic © by World of Gothic Team
Gothic, Gothic 2 & Gothic 3 are © by Piranha Bytes & Egmont Interactive & JoWooD Productions AG, all rights reserved worldwide