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 5 von 5
  1. Beiträge anzeigen #1 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    270
     
    F a w k e s ist offline

    G1 AI_StartState - hardcoded ZS states for Player?

    Hello folks, (NicoDE!)
    I've been trying to 'import' ZS_WhirlWind from G2A to G1 - I have everything setup - and everything works ok when I am using this on NPC. However I cannot use AI_StartState (self, ZS_WhirlWind, 1, ""); on hero.
    When I change name ZS_WhirlWind to ZS_MagicSleep (and disable original one) I can run this function on hero !
    I was searching for anything that would give me a hint on what is different with ZS_MagicSleep and found out that this state function is mentioned directly in Gothic.exe along with others: ZS_MAGICFEAR, ZS_MAGICSLEEP, ZS_PYRO, ZS_ZAPPED, ZS_SHORTZAPPED, ZS_MAGICFREEZE, ZS_ASSESSSTOPMAGIC, ZS_ASSESSMAGIC.
    So I experimented now and changed name of state ZS_WhirlWind to ZS_MagicFear (not used in G1) and again I can run this on hero !
    This tells me that states names are restricted and most likely hardcoded - and I can use only these mentioned above on hero.
    Is there any way to change this - can I somehow avoid this restriction of ZS_ states when using them with hero instance?

  2. Beiträge anzeigen #2 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist offline
    As you already found out, the allowed states for the player are hard-coded.

    G1
    Code:
    const int NPC_PLAYER_STATES_ENABLED_MAX = 8;
    
    const zSTRING strPlayerStatesEnabled[NPC_PLAYER_STATES_ENABLED_MAX] = {
    	"ZS_ASSESSMAGIC",
    	"ZS_ASSESSSTOPMAGIC",
    	"ZS_MAGICFREEZE",
    	"ZS_SHORTZAPPED",
    	"ZS_ZAPPED",
    	"ZS_PYRO",
    	"ZS_MAGICSLEEP",
    	"ZS_MAGICFEAR"
    };
    
    static
    int playerStatesEnabled[NPC_PLAYER_STATES_ENABLED_MAX] = {
    	-1,  // [0] checked in oCNpc_States constructor to initialize all others
    	-1,
    	-1,
    	-1,
    	-1,
    	-1
    //	0
    //	0
    };
    G2A
    Code:
    const int NPC_PLAYER_STATES_ENABLED_MAX = 9;
    
    const zSTRING strPlayerStatesEnabled[NPC_PLAYER_STATES_ENABLED_MAX] = {
    	"ZS_ASSESSMAGIC",
    	"ZS_ASSESSSTOPMAGIC",
    	"ZS_MAGICFREEZE",
    	"ZS_WHIRLWIND",
    	"ZS_SHORTZAPPED",
    	"ZS_ZAPPED",
    	"ZS_PYRO",
    	"ZS_MAGICSLEEP"
    //	NULL
    };
    
    static int playerStatesEnabled[NPC_PLAYER_STATES_ENABLED_MAX] = {
    	-1,  // [0] checked in oCNpc_States constructor to initialize all others
    	-1,
    	-1,
    	-1,
    	-1,
    	-1
    //	0
    //	0
    //	0
    };
    So you might change/hack the symbol indices in the playerStatesEnabled array at runtime. Extending the list would require more effort...
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  3. Beiträge anzeigen #3 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    270
     
    F a w k e s ist offline
    You don't have any of those addresses which should be manipulated handy, do you?

  4. Beiträge anzeigen #4 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist offline
    Addresses from http://bendlins.de/nico/gothic/misc/dbg/1.08k_mod/
    Code:
    .data:0085081C ; int playerStatesEnabled[8]
    .data:0085081C playerStatesEnabled dd 6 dup(-1), 2 dup(0)
    .data:0085081C                                         ; DATA XREF: oCNpc_States::oCNpc_States(void):loc_006C49FFr
    .data:0085081C                                         ; oCNpc_States::oCNpc_States(void)+257o
    .data:0085081C                                         ; oCNpc_States::CanPlayerUseAIState(void)+36o
    .data:0085081C                                         ; oCNpc_States::DoAIState(void)+2A3o
    .data:0085083C `string'        db 'ZS_MAGICFEAR',0     ; DATA XREF: strPlayerStatesEnabled__init+69o
    .data:0085083C                                         ; oCNpc_States::CanPlayerUseAIState(void)+47o
    .data:0085083C                                         ; oCNpc_States::DoAIState(void)+2B3o
    .data:00850849                 align 4
    .data:0085084C `string'        db 'ZS_MAGICSLEEP',0    ; DATA XREF: strPlayerStatesEnabled__init+5Ao
    .data:0085085A                 align 4
    .data:0085085C `string'        db 'ZS_PYRO',0          ; DATA XREF: strPlayerStatesEnabled__init+4Bo
    .data:00850864 `string'        db 'ZS_ZAPPED',0        ; DATA XREF: strPlayerStatesEnabled__init+3Co
    .data:0085086E                 align 4
    .data:00850870 `string'        db 'ZS_SHORTZAPPED',0   ; DATA XREF: strPlayerStatesEnabled__init+2Do
    .data:0085087F                 align 4
    .data:00850880 `string'        db 'ZS_MAGICFREEZE',0   ; DATA XREF: strPlayerStatesEnabled__init+1Eo
    .data:0085088F                 align 4
    .data:00850890 `string'        db 'ZS_ASSESSSTOPMAGIC',0
    .data:00850890                                         ; DATA XREF: strPlayerStatesEnabled__init+Fo
    .data:008508A3                 align 4
    .data:008508A4 `string'        db 'ZS_ASSESSMAGIC',0   ; DATA XREF: strPlayerStatesEnabled__inito
    .data:008508B3                 align 4
    Code:
    .data:008DC0E0 ; zSTRING strPlayerStatesEnabled[8]
    .data:008DC0E0 strPlayerStatesEnabled zSTRING 8 dup(<?>)
    .data:008DC0E0                                         ; DATA XREF: strPlayerStatesEnabled__init+5o
    .data:008DC0E0                                         ; strPlayerStatesEnabled__exit+9o
    .data:008DC0E0                                         ; oCNpc_States::oCNpc_States(void)+25Co
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (08.02.2019 um 08:52 Uhr)

  5. Beiträge anzeigen #5 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    270
     
    F a w k e s ist offline

    G1 control player zs_states

    Thank you NicoDe!
    I was unfortunatelly not able to use potential hidden in these addresses. However I found an alternative way:
    I have hooked _HOOK_NPC_STATES_DOAISTATE - and here I am checking npc.state_nextState_name,
    if (npc.state_nextState_name == "ZS_WHIRLWIND") I will repoint npc.state_nextState_index to ZS_ASSESSMAGIC.
    In ZS_ASSESSMAGIC I will call intended function, which is still stored in npc.state_nextState_name and will overwrite npc.state_nextState_loop & npc.state_nextState_end to match npc.state_nextState_name function.
    Code:
    //Cannibalized from Ikarus 1.2.1 oCNPC class definition:
    
    class oCNpc_States {
            var int        state_vfptr;                                // 0x0470
            var string     state_name;                                 // 0x0474 zSTRING
            var int        state_npc;                                  // 0x0488 oCNpc*
    //      TNpcAIState curState {
                var int    state_curState_index;                       // 0x048C int
                var int    state_curState_loop;                        // 0x0490 int
                var int    state_curState_end;                         // 0x0494 int
                var int    state_curState_timeBehaviour;               // 0x0498 int
                var int    state_curState_restTime;                    // 0x049C zREAL
                var int    state_curState_phase;                       // 0x04A0 int
                var int    state_curState_valid;                       // 0x04A4 zBOOL
                var string state_curState_name;                        // 0x04A8 zSTRING
                var int    state_curState_stateTime;                   // 0x04BC zREAL
                var int    state_curState_prgIndex;                    // 0x04C0 int
                var int    state_curState_isRtnState;                  // 0x04C4 zBOOL
    //      }
    //      TNpcAIState nextState {
                var int    state_nextState_index;                      // 0x04C8 int
                var int    state_nextState_loop;                       // 0x04CC int
                var int    state_nextState_end;                        // 0x04D0 int
                var int    state_nextState_timeBehaviour;              // 0x04D4 int
                var int    state_nextState_restTime;                   // 0x04D8 zREAL
                var int    state_nextState_phase;                      // 0x04DC int
                var int    state_nextState_valid;                      // 0x04E0 zBOOL
                var string state_nextState_name;                       // 0x04E4 zSTRING
                var int    state_nextState_stateTime;                  // 0x04F8 zREAL
                var int    state_nextState_prgIndex;                   // 0x04FC int
                var int    state_nextState_isRtnState;                 // 0x0500 zBOOL
    };
    
    /*
        ZS_ASSESSMAGIC is allowed state for player, but it is not defined in G1 -> we can reserve it for ourselves
        When this function will be called by _HOOK_NPC_STATES_DOAISTATE on player - it will
            call npc.state_nextState_name (intended function)
            overwrite npc.state_nextState_loop with npc.state_nextState_name_LOOP
            overwrite npc.state_nextState_end with npc.state_nextState_name_END
    */        
    FUNC VOID ZS_ASSESSMAGIC ()
    {
        var oCNPC npc;
        npc = Hlp_GetNPC (self);
        
        //Disable further calls
        npc.state_nextState_index = -1;
        
        //Call npc.state_nextState_name (ZS_WHIRLWIND or others, if specified in _HOOK_NPC_STATES_DOAISTATE)
        MEM_CallByString (npc.state_nextState_name);
        
        //Overwrite npc.state_nextState_loop with npc.state_nextState_name_LOOP
        var string fNameLoop;
        fNameLoop = ConcatStrings (npc.state_nextState_name, "_LOOP");
        npc.state_nextState_loop = MEM_FindParserSymbol (fNameLoop);
        
        //Overwrite npc.state_nextState_end with npc.state_nextState_name_END
        var string fNameEnd;
        fNameEnd = ConcatStrings (npc.state_nextState_name, "_END");
        npc.state_nextState_end = MEM_FindParserSymbol (fNameEnd);
    };
    
    FUNC INT ZS_ASSESSMAGIC_Loop ()    {};
    
    FUNC VOID ZS_ASSESSMAGIC_End ()    {};
    
    //006C5C60  .text     Debug data           ?DoAIState@oCNpc_States@@QAEHXZ
    const int oCNpc_States__DoAIState_G1 = 7101536;
    
    //0x0076D1A0 public: int __thiscall oCNpc_States::DoAIState(void)
    const int oCNpc_States__DoAIState_G2 = 7786912;
    FUNC VOID _HOOK_NPC_STATES_DOAISTATE ()
    {
        var oCNpc_States state;
        state = _^ (ECX);
    
        var oCNPC npc;
        npc = _^ (state.state_npc);
    
        if (NPC_IsPlayer (npc))
        {
            if (state.state_nextState_index != 0)
            && (state.state_nextState_index != -1)
            {
                //Here you can specify what states are allowed for player
                if (Hlp_StrCmp (state.state_nextState_name, "ZS_WHIRLWIND"))
                {
                    //Overwrite state_nextState_index - this will point to function ZS_ASSESSMAGIC
                    //npc.state_nextState_name will still contain string "ZS_WHIRLWIND")
                    npc.state_nextState_index = MEM_FindParserSymbol ("ZS_ASSESSMAGIC");
                };
            };
        };
    };
    Hook:
    Code:
    HookEngine (MEMINT_SwitchG1G2 (oCNpc_States__DoAIState_G1, oCNpc_States__DoAIState_G2), 6, "_HOOK_NPC_STATES_DOAISTATE");

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