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

 

Seite 4 von 10 « Erste 12345678 ... Letzte »
Ergebnis 61 bis 80 von 195
  1. Beiträge anzeigen #61 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.205
     
    Milky-Way ist offline
    Wäre es sinnvoll, ScriptBin ebenfalls zu GitHub zu transferieren, und bei der Gelegenheit die weiteren hier im Thema genannten und aktualisierten Skripte einzubauen?

  2. Beiträge anzeigen #62 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Milky-Way Beitrag anzeigen
    Wäre es sinnvoll, ScriptBin ebenfalls zu GitHub zu transferieren, und bei der Gelegenheit die weiteren hier im Thema genannten und aktualisierten Skripte einzubauen?
    Vielleicht sogar nicht als ein Repository, sondern angelegt als "Organisation" (das ist eine Kollektion von Repositories). Dann kann jedes Skript(-paket) in einem eigenen Repository bleiben und es ist einfacher sich ein bestimmtes Skript-Feature heraus zu picken (wenn man an all den anderen Skripten nicht interessiert ist). Die bisherige Struktur vom SkriptBin Repo kann schnell unübersichtlich werden und man kann teilweise nur schwer zuordnen welche Skripte oder Funktionen jetzt zu dem gewünschten Skript dazu gehören. Verlinken von einem Skript macht das auch einfacher. Auch das hinzufügen von neuen Skripten bedurfte bisher eher aufwändiges eingliedern in die Ordnerstruktur und in die SRC-Datei.
    Die "Gefahr" ist aber, dass es zu viele Repos werden.

    Das sind so meine Gedanken dazu.

  3. Beiträge anzeigen #63 Zitieren
    banned
    Registriert seit
    Jan 2009
    Ort
    Oberösterreich
    Beiträge
    2.393
     
    Moe ist offline
    Eine Frage: Wie rufe ich stopAllSounds beim Spiel Laden auf? Beim Spiel Start hab wird meine (lange) Gamestart.wav schon schön abgebrochen, aber beim Spiel Laden noch nicht.

  4. Beiträge anzeigen #64 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Naja wo rufst du es denn momentan auf? Generell ist die INIT_Global (Startup.d) die Funktion, die sowohl beim Start eines neuen Spiels als auch beim Laden eines Speicherstandes aufgerufen wird.

  5. Beiträge anzeigen #65 Zitieren
    banned
    Registriert seit
    Jan 2009
    Ort
    Oberösterreich
    Beiträge
    2.393
     
    Moe ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Naja wo rufst du es denn momentan auf? Generell ist die INIT_Global (Startup.d) die Funktion, die sowohl beim Start eines neuen Spiels als auch beim Laden eines Speicherstandes aufgerufen wird.
    Okay, danke. Ich hatte sie nicht in INIT_Global eingetragen. Jetzt funktioniert's.

  6. Beiträge anzeigen #66 Zitieren
    Apprentice Avatar von Rayzer
    Registriert seit
    Sep 2014
    Ort
    Poland
    Beiträge
    44
     
    Rayzer ist offline
    Few days ago I wrote a script that creates in inventory every existing in the game item. Maybe someone will make use of it
    Code:
    func void CreateAllItems(var c_npc slf) {
        var int i;
    
    
        repeat(i, MEM_Parser.symtab_table_numInArray);
            var zCPar_Symbol symb; symb = _^(MEM_ReadIntArray(MEM_Parser.symtab_table_array, i));
    
    
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) != zPAR_TYPE_INSTANCE || STR_IndexOf(symb.name, ".") > 0 || !symb.parent) {
    	    continue;
            };
    
    
            symb = _^(symb.parent);
    
    
            if (Hlp_StrCmp(symb.name, "C_ITEM")) {
                CreateInvItems(slf, i, 1);
            }
            else if (symb.parent && (symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_PROTOTYPE) {
                symb = _^(symb.parent);
    
    
                if (Hlp_StrCmp(symb.name, "C_ITEM")) {
                    CreateInvItems(slf, i, 1);
                };
            };
        end;
    };
    The game may freeze for a while because table of parser symbols is very huge.

  7. Beiträge anzeigen #67 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Nicely written code, thanks for sharing!

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

    G1 NPC VobList functions

    I will also add something I believe can be useful:
    NPCVobList.d – functions will showcase better control over what NPCs can 'detect' in specified range.
    Code:
    //Tested with G1 Ikarus 1.2.1
    //Maybe also compatible with G2A - I never tested :)
    
    
    /***
        NPC_CreateVobList (var int slfInstance, var int range)
        Pretty much same as NPC_PerceiveAll - however allows you to control range in which Vobs will be collected.
        When used all collected vobs will be available in slf.vobList_array.
    ***/
    FUNC VOID NPC_CreateVobList (var int slfInstance, var int range)
    {
        //006B7110  .text     Debug data           ?CreateVobList@oCNpc@@QAEXM@Z
        const int oCNpc__CreateVobList_G1 = 7041296;
    
    
        //0x0075DA40 public: void __thiscall oCNpc::CreateVobList(float)
        const int oCNpc__CreateVobList_G2 = 7723584;
        
        var C_NPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        CALL_IntParam (mkf (range));
        CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNpc__CreateVobList_G1, oCNpc__CreateVobList_G2));
    };
    
    
    /***
        NPC_ClearVobList (var int slfInstance)
        Clears slf.vobList_array - not sure if this useful - I never used it :)
    ***/
    FUNC VOID NPC_ClearVobList (var int slfInstance)
    {
        //006B6EB0  .text     Debug data           ?ClearVobList@oCNpc@@QAEXXZ
        const int oCNpc__ClearVobList_G1 = 7040688;
    
    
        //0x0075D7F0 public: void __thiscall oCNpc::ClearVobList(void)
        const int oCNpc__ClearVobList_G2 = 7722992;
        
        var C_NPC slf;
        slf = Hlp_GetNPC (slfInstance);
    
    
        CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNpc__ClearVobList_G1, oCNpc__ClearVobList_G2));
    };
    
    
    /***
        NPC_RemoveFromVobList (var int slfInstance, var int vobPtr)
        Removes specific vobPtr from slf.vobList_array
    ***/
    FUNC VOID NPC_RemoveFromVobList (var int slfInstance, var int vobPtr)
    {
        //006B7080  .text     Debug data           ?RemoveFromVobList@oCNpc@@QAEXPAVzCVob@@@Z
        const int oCNpc__RemoveFromVobList_G1 = 7041152;
    
    
        //0x0075D9B0 public: void __thiscall oCNpc::RemoveFromVobList(class zCVob *)
        const int oCNpc__RemoveFromVobList_G2 = 7723440;
        
        if (!vobPtr)    {    return;        };
        
        var C_NPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        var zCVob Vob;
        Vob = _^ (vobPtr);
        
        CALL_PtrParam (MEM_InstToPtr (Vob));
        CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNpc__RemoveFromVobList_G1, oCNpc__RemoveFromVobList_G2));
    };
    
    
    /***
        NPC_VobList_RemoveDeadNPC (var int slfInstance)
        Will remove dead NPC from slf.vobList_array.
    ***/
    FUNC VOID NPC_VobList_RemoveDeadNPC (var int slfInstance)
    {
        var oCNPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        var int i; i = 0;
        var int loop;
    
    
        MEM_InitLabels ();
        loop = MEM_StackPos.position;
    
    
        if (slf.vobList_numInArray > 0)
        {
            var int vobPtr; vobPtr = MEM_ReadIntArray (slf.vobList_array, i);
            
            if (Hlp_Is_oCNpc (vobPtr))
            {
                var C_NPC npc;
                npc = MEM_PtrToInst (vobPtr);
    
    
                if (NPC_IsDead (npc))
                {
                    //remove npc from vobList_array
                    NPC_RemoveFromVobList (slfInstance, vobPtr);
    
    
                    //restart loop
                    i = 0;
                    MEM_StackPos.position = loop;
                };
            };
            
            i += 1;
            if (i < slf.vobList_numInArray)    {
                MEM_StackPos.position = loop;
            };
        };
    };
    
    
    /***
        NPC_VobList_RemovePlayer (var int slfInstance)
        Will remove player from slf.vobList_array.
    ***/
    FUNC VOID NPC_VobList_RemovePlayer (var int slfInstance)
    {
        var oCNPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        var int i; i = 0;
        var int loop;
    
    
        MEM_InitLabels ();
        loop = MEM_StackPos.position;
    
    
        if (slf.vobList_numInArray > 0)
        {
            var int vobPtr; vobPtr = MEM_ReadIntArray (slf.vobList_array, i);
            
            if (Hlp_Is_oCNpc (vobPtr))
            {
                var C_NPC npc;
                npc = MEM_PtrToInst (vobPtr);
    
    
                if (NPC_IsPlayer (npc))
                {
                    //remove npc from vobList_array
                    NPC_RemoveFromVobList (slfInstance, vobPtr);
    
    
                    //restart loop
                    i = 0;
                    MEM_StackPos.position = loop;
                };
            };
            
            i += 1;
            if (i < slf.vobList_numInArray) {
                MEM_StackPos.position = loop;
            };
        };
    };
    
    
    /***
        NPC_VobList_FindMobInter (var int slfInstance, var string scemeName)
        Function removes from slf.vobList_array everything that is not oCMobInter and does not have sceme equal to scemeName.
        
        //Example will detect VWHEEL object:
            var int ptr;
            
            NPC_CreateVobList (self, 800);
            ptr = NPC_VobList_FindMobInter (self, "VWHEEL");
    
    
        //Example will detect chest (CHESTBIG or CHESTMEDIUM or CHESTSMALL) object:
            var int ptr;
            
            NPC_CreateVobList (self, 800);
            ptr = NPC_VobList_FindMobInter (self, "CHESTBIG");
            
            if (ptr == 0) {
                NPC_CreateVobList (self, 800);
                ptr = NPC_VobList_FindMobInter (self, "CHESTMEDIUM");
            };
    
    
            if (ptr == 0) {
                NPC_CreateVobList (self, 800);
                ptr = NPC_VobList_FindMobInter (self, "CHESTSMALL");
            };
    ***/
    FUNC INT NPC_VobList_FindMobInter (var int slfInstance, var string scemeName)
    {
        var oCNPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        scemeName = STR_Upper (scemeName);
        
        var int i; i = 0;
        var int loop;
        var int vobPtr;
        var int flgRemove;
    
    
        MEM_InitLabels ();
        loop = MEM_StackPos.position;
    
    
        if (slf.vobList_numInArray > 0)
        {
            flgRemove = TRUE;
            vobPtr = MEM_ReadIntArray (slf.vobList_array, i);
            
            if (Hlp_Is_oCMobInter (vobPtr)) {
                var oCMobInter mob;
                mob = MEM_PtrToInst (vobPtr);
    
    
                if (Hlp_StrCmp (STR_Upper (mob.sceme), scemeName)) {
                    flgRemove = FALSE;
                };
            };
            
            if (flgRemove) {
                //remove npc from vobList_array
                NPC_RemoveFromVobList (slfInstance, vobPtr);
    
    
                //restart loop
                i = 0;
                MEM_StackPos.position = loop;
            };
            
            i += 1;
            if (i < slf.vobList_numInArray) {
                MEM_StackPos.position = loop;
            };
        };
    
    
        i = 0;
        loop = MEM_StackPos.position;
    
    
        if (slf.vobList_numInArray > 0)
        {
            vobPtr = MEM_ReadIntArray (slf.vobList_array, i);
            return vobPtr;
        };
        
        return 0;
    };
    
    
    /***
        NPC_FreeLineOfSight (var int slfInstance, var int vobPtr)
        Checks if NPC can see vobPtr. Used further below by function NPC_VobList_DetectObject.
    ***/
    FUNC INT NPC_FreeLineOfSight (var int slfInstance, var int vobPtr)
    {
        //0069DE50  .text     Debug data           ?FreeLineOfSight@oCNpc@@QAEHPAVzCVob@@@Z
        const int oCNpc__FreeLineOfSight_G1 = 6938192;
    
    
        //0x007418E0 public: int __thiscall oCNpc::FreeLineOfSight(class zCVob *)
        const int oCNpc__FreeLineOfSight_G2 = 7608544;
        
        if (!vobPtr)    {    return 0;    };
        
        var C_NPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        var zCVob Vob;
        Vob = _^ (vobPtr);
    
    
        CALL_PtrParam (MEM_InstToPtr (Vob));
        CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNpc__FreeLineOfSight_G1, oCNpc__FreeLineOfSight_G2));
        
        return CALL_RetValAsInt();
    };
    
    
    /***
        NPC_VobList_DetectObject (var int slfInstance, var int freeLOS, var int vtbl, var int objInstance)
        Allows you to detect specific objects. Returns object pointer.
        freeLOS: is object in Free Line of Sight? If TRUE - will return object pointer only if in Free Line of Sight, if FALSE - will return object regardless of whether it is in Free Line of sight or not.
        object vtbl: oCMobFire_vtbl, zCMover_vtbl, oCMob_vtbl, oCMobInter_vtbl, oCMobContainer_vtbl, oCMobDoor_vtbl, oCMobContainer_vtbl, oCNpc_vtbl, oCItem_vtbl, zCVobLight_vtbl
        objInstance: detection of specific instance. (use 0 if you don't want to detect instances)
        
        //Example will detect npc, Bloodfly, which is in Free Line of Sight    
            NPC_CreateVobList (self, 3000);
            if (NPC_VobList_DetectObject (self, TRUE, oCNpc_vtbl, Bloodfly)) {
                ...
            };
        
        //Example will detect item, ItMi_Plants_Swampherb_01, which is in Free Line of Sight
            NPC_CreateVobList (self, 1500);
            if (NPC_VobList_DetectObject (self, TRUE, oCItem_vtbl, ItMi_Plants_Swampherb_01)) {
                ...
            };
        
        //Example will detect chest, which is in Free Line of Sight
            var int ptr;
            
            NPC_CreateVobList (self, 1000);
            ptr = NPC_VobList_DetectObject (self, TRUE, oCMobContainer_vtbl, 0);
            
            if (ptr) {
                var oCMobLockable chestLock;
                chestLock = MEM_PtrToInst (ptr);
                
                //Is chest locked?
                if (chestLock.bitfield & oCMobLockable_bitfield_locked) {
                    var oCMobContainer chest;
                    chest = MEM_PtrToInst (ptr);
                    
                    PrintScreen (chest._oCMobLockable_pickLockStr, -1, _YPOS_MESSAGE_LOGENTRY, "font_old_10_white.tga", _TIME_MESSAGE_LOGENTRY);
                };
            };
    
    
        //Example will detect door, which is in Free Line of Sight
            var int ptr;
            
            NPC_CreateVobList (self, 1000);
            ptr = NPC_VobList_DetectObject (self, TRUE, oCMobDoor_vtbl, 0);
            
            if (ptr) {
                var oCMobLockable doorLock;
                doorLock = MEM_PtrToInst (ptr);
                
                //Is door locked?
                if (doorLock.bitfield & oCMobLockable_bitfield_locked) {
                    var oCMobDoor door;
                    door = MEM_PtrToInst (ptr);
    
    
                    PrintScreen (door._oCMobLockable_pickLockStr, -1, _YPOS_MESSAGE_LOGENTRY, "font_old_10_white.tga", _TIME_MESSAGE_LOGENTRY);
                };
            };
    ***/
    FUNC INT NPC_VobList_DetectObject (var int slfInstance, var int freeLOS, var int vtbl, var int objInstance)
    {
        var oCNPC slf;
        slf = Hlp_GetNPC (slfInstance);
        
        var int i; i = 0;
        var int loop;
        
        //flags
        var int fFreeLOS;
        var int fVtbl;
        var int fObjInstance;
    
    
        //loop through objects
        MEM_InitLabels ();
        loop = MEM_StackPos.position;
        
        fVtbl = FALSE;
        fFreeLOS = FALSE;
        fObjInstance = FALSE;
        
        if (!objInstance)    {    fObjInstance = TRUE;    };
        
        if (slf.vobList_numInArray > 0)
        {
            var int vobPtr; vobPtr = MEM_ReadIntArray (slf.vobList_array, i);
            var int vobVtbl; vobVtbl = MEM_ReadInt (vobPtr);
            
            //oCMobFire_vtbl
            if (vtbl == oCMobFire_vtbl) {
                if (vobVtbl == oCMobFire_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            //zCMover_vtbl
            if (vtbl == zCMover_vtbl) {
                if (vobVtbl == zCMover_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            //oCMob_vtbl
            if (vtbl == oCMob_vtbl) {
                //
                if (vobVtbl == oCMob_vtbl)
                || (vobVtbl == oCMobInter_vtbl)
                || (vobVtbl == oCMobContainer_vtbl)
                || (vobVtbl == oCMobDoor_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            //oCMobInter_vtbl
            if (vtbl == oCMobInter_vtbl) {
                //
                if (vobVtbl == oCMobInter_vtbl)
                || (vobVtbl == oCMobContainer_vtbl)
                || (vobVtbl == oCMobDoor_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            //oCMobLockable (does not exist in G1 Ikarus as a constant
            //if (vtbl == oCMobLockable_vtbl) {
            if (vtbl == oCMobContainer_vtbl) {
                //
                if (vobVtbl == oCMobContainer_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            if (vtbl == oCMobDoor_vtbl) {
                if (vobVtbl == oCMobDoor_vtbl) {
                    fVtbl = TRUE;
                };
            } else
            //oCNpc_vtbl
            if (vtbl == oCNpc_vtbl) {
                //
                if (vobVtbl == oCNpc_vtbl) {
                    //Check NPC instance if required
                    if (objInstance) {
                        var C_NPC npc;
                        npc = _^ (vobPtr);
                        
                        if (Hlp_GetInstanceID (npc) == objInstance) {
                            fObjInstance = TRUE;
                        };
                    };
                    
                    fVtbl = TRUE;
                };
            } else
            //oCItem_vtbl
            if (vtbl == oCItem_vtbl) {
                //
                if (vobVtbl == oCItem_vtbl) {
                    //Check item instance if required
                    if (objInstance) {
                        var C_Item itm;
                        itm = _^ (vobPtr);
                        
                        if (Hlp_GetInstanceID (itm) == objInstance) {
                            fObjInstance = TRUE;
                        };
                    };
                    
                    fVtbl = TRUE;
                };
            } else
            //zCVobLight_vtbl
            if (vtbl == zCVobLight_vtbl) {
                //
                if (vobVtbl == zCVobLight_vtbl) {
                    fVtbl = TRUE;
                };
            };
    
    
            //Free Line of Sight
            if (freeLOS) {
                if (NPC_FreeLineOfSight (slf, vobPtr)) {
                    fFreeLOS = TRUE;
                };
            } else {
                fFreeLOS = TRUE;
            };
    
    
            if (fVtbl) && (fFreeLOS) && (fObjInstance) {
                return vobPtr;
            };
            
            i += 1;
            if (i < slf.vobList_numInArray) {
                MEM_StackPos.position = loop;
            };
        };
        
        return 0;
    };

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

    G1 In-game object moving

    Hello folks,
    Today I want to demonstrate how powerful npc.vobList_array can actually be - even I did not fully realize it till today!
    I always wanted to move around in-game objects while playing the game, but was not really able to - as I was not able to detect what kind of object is in front of hero. (in case it would not be focus-able)
    I know you can use trace rays somehow, but that is just .. out of my league! But with NPC_CreateVobList I can detect all objects which are nearby hero, and then I can just check, whether hero can see an object or not.
    If he can see object, then it means object is in front of hero - and we can assume that he can move it around:

    [Video]

    Here is complete code in case you would like to try it yourself.

    Required:
    Ikarus 1.2.1
    Function NPC_CanSeeVob from:
    https://forum.worldofplayers.de/foru...1#post26055633
    Function SetVobToFloor from Scriptbin\InsertAnything:
    (@mud-freak thank you!)
    https://forum.worldofplayers.de/foru...1#post25712257
    Functions from Scriptbin\NPCVobList.d:
    https://forum.worldofplayers.de/foru...1#post26052199
    + Functions Vob_Move & moveVobInFront:
    (@Lehona thank you!)
    Code:
    const int zCVob__Move_G1 = 6217184; //0x5EDDE0
    const int zCVob__Move_G2 = 6402784; //0x61B2E0
    
    func void Vob_Move (var int ptr, var int x, var int y, var int z)
    {
        CALL_FloatParam (x);
        CALL_FloatParam (y);
        CALL_FloatParam (z);
        CALL__thiscall (ptr, MEMINT_SwitchG1G2 (zCVob__Move_G1, zCVob__Move_G2));
    };
    
    /***
        Function moveVobInFront move vob in front of NPC
    ***/
    func void moveVobInFront (var int slfInstance, var int vobPtr)
    {
        var zCVob slf; slf = Hlp_GetNPC (slfInstance);
        var zCVob vob; vob = _^ (vobPtr);
                
        // trafo kopieren
        MEM_CopyBytes(_@(slf) + 60, vobPtr + 60, 64);
    
        // Vob vor den Helden setzen
        var int delta; delta = mkf(150);
        Vob_Move (vobPtr, mulf (slf.trafoObjToWorld[10], delta), mulf (slf.trafoObjToWorld[6], delta), mulf (slf.trafoObjToWorld[2], delta));
    };
    I have hooked function oCGame__HandleEvent - within this function I am checking if player pressed '[' key to start/stop object moving mode, or key ']' to enable/disable floor aligning mode:
    Code:
    //Global variables
    var int vobTransportPtr;
    var int vobTransportMode;
        const int cvobTransportMode_Disabled    = 0;
        const int cvobTransportMode_Init    = 1;
        const int cvobTransportMode_Moving    = 2;
        const int cvobTransportMode_Done    = 3;
    
    var int vobTransportModeFloor;
    var int vobTransportCollBits;
    
    const int oCGame__HandleEvent_G1 = 6680288;    //0x65EEE0
    const int oCGame__HandleEvent_G2 = 7324016;    //0x6FC170
    
    FUNC VOID _HOOK_GAME_HANDLEEVENT ()
    {
        var int inputKey;
        inputKey = MEM_KeyState (KEY_LBRACKET);
        
        //Vob moving on/off
        if (inputKey == KEY_PRESSED) || (inputKey == KEY_HOLD)
        {
            if (vobTransportMode == cvobTransportMode_Disabled)
            {
                vobTransportMode = cvobTransportMode_Init;
            };
    
            if (vobTransportMode == cvobTransportMode_Moving)
            {
                vobTransportMode = cvobTransportMode_Done;
            };
        };
        
        //Vob surface align mode on/off
        inputKey = MEM_KeyState (KEY_RBRACKET);
        if (inputKey == KEY_PRESSED) || (inputKey == KEY_HOLD)
        {
            vobTransportModeFloor = !vobTransportModeFloor;
        };
    };
    
    //Hook this
    HookEngine (MEMINT_SwitchG1G2(oCGame__HandleEvent_G1, oCGame__HandleEvent_G2), 6, "_HOOK_GAME_HANDLEEVENT");
    And finally FrameHandler_VobTransport function - is the one responsible for object detection and moving (should be called every frame):
    Code:
    /***
        VobGetCollBits will return collision bitfield values
    ***/
    FUNC INT VobGetCollBits (var int vobPtr)
    {
        if (!vobPtr) { return; };
        var int collBits; collBits = (zCVob_bitfield0_collDetectionStatic + zCVob_bitfield0_collDetectionDynamic);
        var zCVob vob; vob = MEM_PtrToInst (vobPtr);
        return (vob.bitfield[0] & (collBits));
    };
    
    /***
        VobRemoveCollBits - will remove collisions based on input bitfield values in collBits
    ***/
    FUNC VOID VobRemoveCollBits (var int vobPtr, var int collBits)
    {
        if (!vobPtr) { return; };
        var zCVob vob; vob = MEM_PtrToInst (vobPtr);
        vob.bitfield[0] = vob.bitfield[0] & ~ (collBits);
    };
    
    /***
        VobRestoreCollBits - will apply collisions based on input bitfield values in collBits
    ***/
    FUNC VOID VobRestoreCollBits (var int vobPtr, var int collBits)
    {
        if (!vobPtr) { return; };
        var zCVob vob; vob = MEM_PtrToInst (vobPtr);
        vob.bitfield[0] = vob.bitfield[0] | (collBits);
    };
    
    /***
        Hlp_Is_zcVob - validates whether ptr object is zcVob
    ***/
    FUNC INT Hlp_Is_zcVob (var int ptr) {
        if (!ptr) { return 0; };
    
        var int vtbl;
        vtbl = MEM_ReadInt (ptr);
    
        return (vtbl == zCVob_vtbl);
    }; 
    
    /***
        Hlp_Is_oCMobLadder - validates whether ptr object is oCMobLadder
    ***/
    FUNC INT Hlp_Is_oCMobLadder (var int ptr) {
        if (!ptr) { return 0; };
    
        var int vtbl;
        vtbl = MEM_ReadInt (ptr);
    
        return (vtbl == oCMobLadder_vtbl);
    }; 
    
    /***    Why are these 2 above not in Ikarus by default :-O    ***/
    
    /***
        FrameHandler_VobTransport
        Call this function every frame, in your frame trigger function for example.
        Code within this function identifies object which should be moved around.
    ***/
    FUNC VOID FrameHandler_VobTransport ()
    {
        //Identification of object which should be moved around
        if (vobTransportMode == cvobTransportMode_Init)
        {
            //Safety-check
            if (Hlp_IsValidNPC (hero))
            {
                var oCNPC her;
                her = Hlp_GetNPC (hero);
                
                var zCVob vobHero;
                var zCVob vob;
                
                //Is there anything in hero's focus ?
                if (her.focus_vob)
                {
                    //Move around following objects
                    if (Hlp_Is_oCMob (her.focus_vob))
                    || (Hlp_Is_oCMobInter (her.focus_vob))
                    || (Hlp_Is_oCMobFire (her.focus_vob))
                    || (Hlp_Is_oCMobLockable (her.focus_vob))
    //                || (Hlp_Is_zCMover (her.focus_vob))
                    || (Hlp_Is_oCMobContainer (her.focus_vob))
                    || (Hlp_Is_oCMobDoor (her.focus_vob))
                    || (Hlp_Is_oCMobLadder (her.focus_vob))
                    {
                        //Get pointer of moved object - it's in our focus
                        vobTransportPtr = her.focus_vob;
    
                        //Backup collision bitfields
                        vobTransportCollBits = VobGetCollBits (vobTransportPtr);
                        
                        //Remove active collisions
                        VobRemoveCollBits (vobTransportPtr, vobTransportCollBits);
                        
                        //Change vobTransportMode
                        vobTransportMode = cvobTransportMode_Moving;
                    };
                } else
                
                //Detect vob, which cannot be in her.focus_vob (e.g. zcVobs)
                {
                    //Detect all nearby vobs
                    NPC_ClearVobList (hero);
                    NPC_CreateVobList (hero, 120);
    
                    //Loop through all nearby vobs
                    var int i; i = 0;
                    var int loop;
                    
                    var int vobPtr;
    
                    MEM_InitLabels ();
                    loop = MEM_StackPos.position;
                    
                    if (her.vobList_numInArray > 0)
                    {
                        vobPtr = MEM_ReadIntArray (her.vobList_array, i);
                        
                        //Is this object zcVob ?
                        if (Hlp_Is_zcVob (vobPtr))
                        {
                            //Is this vob in front of player - can player see it?
                            if (NPC_CanSeeVob (hero, vobPtr))
                            {
                                //Get pointer of moved object
                                vobTransportPtr = vobPtr;
                                
                                //Backup collision bitfields
                                vobTransportCollBits = VobGetCollBits (vobTransportPtr);
                                
                                //Remove active collisions
                                VobRemoveCollBits (vobTransportPtr, vobTransportCollBits);
                                
                                //Change vobTransportMode
                                vobTransportMode = cvobTransportMode_Moving;
                            };
                        };
                        
                        //If vobTransportMode was not changed ... continue in loop (or exit)
                        if (vobTransportMode == cvobTransportMode_Init)
                        {
                            i += 1;
                            if (i < her.vobList_numInArray) {
                                MEM_StackPos.position = loop;
                            };
                        };
                    };
                };
            };
            
            //If vobTransportMode was not changed ... then there was no object detected - disable vobTransportMode
            if (vobTransportMode == cvobTransportMode_Init)
            {
                vobTransportMode = cvobTransportMode_Disabled;
            };
        };
        
        //Moving mode
        if (vobTransportMode == cvobTransportMode_Moving)
        {
            //Move object in front of hero
            MoveVobInFront (hero, vobTransportPtr);
            
            //Align vob to floor
            if (vobTransportModeFloor == TRUE) {
                SetVobToFloor (vobTransportPtr);
            };
        };
        
        //Do we want to stop moving object around?
        if (vobTransportMode == cvobTransportMode_Done)
        {
            //Restore collision bitfields
            VobRestoreCollBits (vobTransportPtr, vobTransportCollBits);
            
            //Disable vobTransportMode
            vobTransportMode = cvobTransportMode_Disabled;
        };
    };
    Geändert von F a w k e s (11.03.2019 um 12:10 Uhr)

  10. Beiträge anzeigen #70 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Thanks for sharing. A couple of suggestions:
    • Why are you hooking oCGame::HandleEvent, but then use MEM_KeyState? HandleEvent already provides the pressed key. Using MEM_KeyState is unreliable, because if called with the same key at another place, KEY_PRESSED might never be detected. To add new key detection directly to oCGame::HandleEvent, see this post.
    • Zitat Zitat von F a w k e s Beitrag anzeigen
      /*** Why are these 2 above not in Ikarus by default :-O ***/
      Hlp_Is_oCMobLadder could be added. But Hlp_Is_zcVob - the way you have it - does something different from Ikarus. The Hlp_Is_* functions in Ikarus are designed to include all inherited classes. Your function explicitly checks for zCVob only. This is of course not "illegal" but the name of the function is misleading compared to the Ikarus functions.
    • Because of this inheritance checking, you will only need to check Hlp_Is_oCMob and Hlp_Is_zCMover. All other checks are redundant.
    • Are you sure you want to allow moving movers? This probably won't move their key frames causing it to "jump" around when triggered.
    • You are traversing the voblist, why the need to check if a respective vob is a zCVob?

  11. Beiträge anzeigen #71 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    270
     
    F a w k e s ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Thanks for sharing. A couple of suggestions:
    Why are you hooking oCGame::HandleEvent, but then use MEM_KeyState? HandleEvent already provides the pressed key. Using MEM_KeyState is unreliable, because if called with the same key at another place, KEY_PRESSED might never be detected. To add new key detection directly to oCGame::HandleEvent, see this post.
    I actually saw your post - and that's why I decided to hook this one specifically. In Gothic 1 however ESI does not return pressed key. I was printing on screen all registers - and seems like EAX is kind of returning pressed key (if you hold it long enough) - however if you just quickly tap a key - this was not working. Then I tested MEM_KeyState - and this worked reliably for both tapping and pressing-holding a key. Maybe it's because I was not directly hooking this specific address oCGame__HandleEvent_dfltCase - here I have no idea how to find this address in G1.
    Zitat Zitat von mud-freak Beitrag anzeigen
    Hlp_Is_oCMobLadder could be added. But Hlp_Is_zcVob - the way you have it - does something different from Ikarus. The Hlp_Is_* functions in Ikarus are designed to include all inherited classes. Your function explicitly checks for zCVob only. This is of course not "illegal" but the name of the function is misleading compared to the Ikarus functions.
    Ok, I see your point here - Hlp_Is_zcVob might be misleading then as all inherited classes belong to zCVob. What would be a better name then?
    Zitat Zitat von mud-freak Beitrag anzeigen
    Because of this inheritance checking, you will only need to check Hlp_Is_oCMob and Hlp_Is_zCMover. All other checks are redundant.
    Good point - thank you
    Zitat Zitat von mud-freak Beitrag anzeigen
    Are you sure you want to allow moving movers? This probably won't move their key frames causing it to "jump" around when triggered.
    Another good one! I actually do not want to move movers!
    Zitat Zitat von mud-freak Beitrag anzeigen
    You are traversing the voblist, why the need to check if a respective vob is a zCVob?
    Sooo this npc.vobList_array actually does not contain only zCVobs - when you call function NPC_CreateVobList (npc, range) - function collects all objects - NPCs, Items, Vobs, mobs - everything in specified range.
    If I would not be verifying that object in a list and in front of hero is zCVob only - I would be able to move unintentionally around mobs (which I don't want to, if I want to move mobs, I will have them in a focus), Items and even NPCs!
    [Video]
    Geändert von F a w k e s (11.03.2019 um 12:26 Uhr)

  12. Beiträge anzeigen #72 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von F a w k e s Beitrag anzeigen
    I actually saw your post - and that's why I decided to hook this one specifically. In Gothic 1 however ESI does not return pressed key. I was printing on screen all registers - and seems like EAX is kind of returning pressed key (if you hold it long enough) - however if you just quickly tap a key - this was not working. Then I tested MEM_KeyState - and this worked reliably for both tapping and pressing-holding a key. Maybe it's because I was not directly hooking this specific address oCGame__HandleEvent_dfltCase - here I have no idea how to find this address in G1.
    Yes, I forgot you are talking about Gothic 1. When I find the time, I will look up the respective address in Gothic 1. Essentially, this address is reached only when no other game key is pressed - the perfect address to "inject" new key strokes for a running game, without having to perform all the checks that are already passed.


    Zitat Zitat von F a w k e s Beitrag anzeigen
    Ok, I see your point here - Hlp_Is_zcVob might be misleading then as all inherited classes belong to zCVob. What would be a better name then?
    Because you are using this check explicitly and only once, I suppose you could just use the code inline.
    Code:
                        //Is this object zcVob ?
                        if (MEM_ReadInt(vobPtr) == zCVob_vtbl)
                        {

    Zitat Zitat von F a w k e s Beitrag anzeigen
    Sooo this npc.vobList_array actually does not contain only zCVobs - when you call function NPC_CreateVobList (npc, range) - function collects all objects - NPCs, Items, Vobs, mobs - everything in specified range.
    If I would not be verifying that object in a list and in front of hero is zCVob only - I would be able to move unintentionally around mobs (which I don't want to, if I want to move mobs, I will have them in a focus), Items and even NPCs!
    Right! Seems I already got confused by Hlp_Is_zcVob.


    You might also want to exclude doors (the player could just move locked doors to places that they are not supposed to reach yet) and ladders (the player could reach places that are not intended to be accessible - same problem as with the elevation and blink spell btw).
    You could simplify your condition to:
    Code:
                    if ((Hlp_Is_oCMob(her.focus_vob))
                    ||  (Hlp_Is_oCMobFire (her.focus_vob)))
                    && (!Hlp_Is_oCMobDoor(her.focus_vob))
                    && (!Hlp_Is_oCMobLadder (her.focus_vob))
                    {
    You should also keep in mind that oCMobInters might be in use by other NPCs at the moment. Furthermore, once you moved a particular oCMobInter (e.g. a bench) NPCs whose daily routine depends on it might not find it anymore.

  13. Beiträge anzeigen #73 Zitieren
    Serima Avatar von Fisk2033
    Registriert seit
    Dec 2010
    Ort
    Dresden
    Beiträge
    5.802
     
    Fisk2033 ist offline
    Thanks for sharing Fawkes!

  14. Beiträge anzeigen #74 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    I looked up the address within oCGame::HandleEvent. I made into a universally usable script for Gothic 1 and Gothic 2.

    One could argue now that this is not much different from a FrameFunction with MEM_KeyState. The difference is that this approach saves the extra work of checking if any menu is open, whether the player is in a dialog, whether the player may move, etc. Also this function is "event driven", meaning it is really only called when a key is pressed/held instead of every frame in vain. So it's arguably more performant.

    gameKeyEvents.d – Adding new key events to oCGame::HandleEvent.
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    /*
     * gameKeyEvents.d
     * Source: https://forum.worldofplayers.de/forum/threads/?p=26055992
     *
     * Handle key events from the player the way Gothic is doing it
     *
     * - Requires Ikarus, LeGo (HookEngine)
     * - Compatible with Gothic 1 and Gothic 2
     *
     * Instructions
     * - Initialize from Init_Global with
     *     Game_KeyEventInit();
     * - Add your key event detection in Game_KeyEvent
     */
    
    
    /*
     * Customizable function to handle key events (pressed is FALSE: key is held, pressed is TRUE: key press onset)
     * This function has to return TRUE if the given key was handled, and FALSE otherwise
     */
    func int Game_KeyEvent(var int key, var int pressed) {
        if (key == KEY_LBRACKET) && (pressed) {
            // Entertain me!
            return TRUE;
        };
        return FALSE;
    };
    
    
    /*
     * This function is called during the running game when a key is pressed/held that is not already handled by Gothic
     */
    func void Game_KeyEvent_() {
        if (Game_KeyEvent(ESI, MEM_ReadByte(MEMINT_KeyToggle_Offset + ESI))) {
            MEM_WriteByte(MEMINT_KeyToggle_Offset + ESI, 0); // Change toggle state only if key event was handled
        };
    };
    
    
    /*
     * Initialization function for custom key events
     */
    func void Game_KeyEventInit() {
        const int oCGame__HandleEvent_dfltCase_G1 = 6684404; //0x65FEF4
        const int oCGame__HandleEvent_dfltCase_G2 = 7328820; //0x6FD434
        HookEngineF(+MEMINT_SwitchG1G2(oCGame__HandleEvent_dfltCase_G1,
                                       oCGame__HandleEvent_dfltCase_G2), 6, Game_KeyEvent_);
    };
    Geändert von mud-freak (30.10.2020 um 10:26 Uhr) Grund: Fixed script

  15. Beiträge anzeigen #75 Zitieren
    Local Hero
    Registriert seit
    Feb 2017
    Beiträge
    270
     
    F a w k e s ist offline
    Thank you !! Works like a charm
    Why is there a + in front of MEMINT_Switch (works with & without it, so was wondering if this is just a typo)?
    Code:
    HookEngineF(+MEMINT_SwitchG1G2(oCGame__HandleEvent_dfltCase_G1,
                                       oCGame__HandleEvent_dfltCase_G2), 6, Game_KeyEvent_);

  16. Beiträge anzeigen #76 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.205
     
    Milky-Way ist offline
    Zitat Zitat von Rayzer Beitrag anzeigen
    Few days ago I wrote a script that creates in inventory every existing in the game item. Maybe someone will make use of it
    Code:
    func void CreateAllItems(var c_npc slf) {
        var int i;
    
    
        repeat(i, MEM_Parser.symtab_table_numInArray);
            var zCPar_Symbol symb; symb = _^(MEM_ReadIntArray(MEM_Parser.symtab_table_array, i));
    
    
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) != zPAR_TYPE_INSTANCE || STR_IndexOf(symb.name, ".") > 0 || !symb.parent) {
    	    continue;
            };
    
    
            symb = _^(symb.parent);
    
    
            if (Hlp_StrCmp(symb.name, "C_ITEM")) {
                CreateInvItems(slf, i, 1);
            }
            else if (symb.parent && (symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_PROTOTYPE) {
                symb = _^(symb.parent);
    
    
                if (Hlp_StrCmp(symb.name, "C_ITEM")) {
                    CreateInvItems(slf, i, 1);
                };
            };
        end;
    };
    The game may freeze for a while because table of parser symbols is very huge.
    What's the idea here that the variable i is the item to be created and not something using symb? Looking at the code, I would have thought that i is just an array index rather than the actual address of the object.

  17. Beiträge anzeigen #77 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von Milky-Way Beitrag anzeigen
    What's the idea here that the variable i is the item to be created and not something using symb? Looking at the code, I would have thought that i is just an array index rather than the actual address of the object.
    An instance, like you would normally pass to CreateInvItem, is internally just an id (integer). The script iterates over all possible ids and if they are C_ITEMs, it creates them via the External.

  18. Beiträge anzeigen #78 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von F a w k e s Beitrag anzeigen
    Thank you !! Works like a charm
    Why is there a + in front of MEMINT_Switch (works with & without it, so was wondering if this is just a typo)?
    You could say, it is used to make the parser resolve a variable (lvalue) into its actual value (rvalue) before pushing it. You can find it a lot in Ikarus. At some point I had similar(?) code that would only work like that. I cannot remember the exact circumstances but I've grown accustomed to using it, when using MEMINT_SwitchG1G2 inside HookEngineF. Thanks for letting me know that it works regardless. I must have remembered it wrong.

  19. Beiträge anzeigen #79 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    For a bug to occur without the '+', the following conditions are necessary:
    A function f that returns a variable directly, not a computation (return x; vs return x+1)
    And a caller has to use f in a way such that it is called twice before either return value is used in a computation. Essentially:

    Code:
    func int thingy(var int x) {
        return x;
    };
    
    func int bug() {
        // Prints 8, not 7
        print(IntToString(thingy(3)+thingy(4)));
    };
    Changing thingy to 'return +x;' instead fixes the bug.

  20. Beiträge anzeigen #80 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.205
     
    Milky-Way ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    An instance, like you would normally pass to CreateInvItem, is internally just an id (integer). The script iterates over all possible ids and if they are C_ITEMs, it creates them via the External.
    Thanks for the explanation, that's exactly what I needed

Seite 4 von 10 « Erste 12345678 ... Letzte »

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