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 2 von 10 « Erste 1234569 ... Letzte »
Ergebnis 21 bis 40 von 195
  1. Beiträge anzeigen #21 Zitieren
    Waldläufer Avatar von Siemekk
    Registriert seit
    May 2016
    Beiträge
    121
     
    Siemekk ist offline
    About buff's - i "rewrited" buff's package from LeGo, to similary AST.
    Code:
    const int BUFF_NORMAL     = 0;
    const int BUFF_BAD         = 1;
    const int BUFF_GOOD     = 2;
    
    
    const int Buff_TextureSize = 64;
    class CBuff
    {
        var int Type;    
        var int ID;    
        
        var int EndTime;
        var int OldTime;    
        
        var int pSelf;        // oCNpc*
        
        var int OnApply;
        var int OnTick;    
        var int OnRemove;
        
        var int delay;        // 
        var int Cycles;
    
    
    };
    
    
    
    
    var int m_arrBuffs;     //zCArray<CBuff*>
    var int Current_Buff;    //CBuff*
    
    
    func int SAVE_GetFuncID(var func f) 
    {
            var int i; i = MEM_GetUseInstance();
            var int res; res = MEM_GetFuncID(f);
            MEM_SetUseInstance(i);
            return res;
    };
    
    
    func void GetBuffsByNpc(var int Array_Ptr, var c_npc slf)
    {
        var int InstID; InstID = Hlp_GetInstanceID(slf);
        if(!Array_Ptr || !m_arrBuffs)
        {
            return;
        };
        
        var int size; size = MEM_ArraySize(m_arrBuffs);
        if(size)
        {
            var int i; i = 0;
            repeat(i, size);
                var int ptr; ptr = MEM_ArrayRead(m_arrBuffs, i);    
                if(Hlp_IsValidHandle(ptr))
                {
                    var CBuff bf; bf = get(ptr);
                    if(bf.pSelf == InstID)
                    {
                        MEM_ArrayInsert(Array_Ptr, ptr);
                    };
                };
            end;
        };
    };
    
    
    func int Npc_HasBuff(var c_npc slf, var int ID)
    {    
        var int arr; arr = MEM_ArrayCreate();
        GetBuffsByNpc(arr, slf);
        
        if(arr)
        {
            var int size; size = MEM_ArraySize(arr);
            if(size)
            {
                var int i; i = 0;
                repeat(i, size);
                
                    var int ptr; ptr = MEM_ArrayRead(arr, i);
                    if(Hlp_IsValidHandle(ptr))
                    {
                        var CBuff bf; bf = get(ptr);
                        if(bf.ID == ID)
                        {
                            MEM_ArrayFree(arr);
                            return true;
                        };
                    };
                end;
            };
        };
        MEM_ArrayFree(arr);
        return false;
    };
    
    
    func void Buff_Apply(var c_npc slf, var int _bf)    //Operator new
    {
        var int InstID;     InstID    = Hlp_GetInstanceID(slf);
            
        var int ptr;         ptr     = new(_bf);
        var CBuff buff;     buff     = get(ptr);
        
        buff.pSelf         = InstID;
        buff.EndTime    = Timer();
        buff.OldTime     = Timer();
        
        if(!m_arrBuffs)
        {
            m_arrBuffs = MEM_ArrayCreate();
        };
        
        if(!m_arrBuffs)
        {
            return;
        };
        
        MEM_ArrayInsert(m_arrBuffs, ptr);
        
        
        //OnApply
        if(buff.OnApply > 0)
        {
            var c_npc n; n = Hlp_GetNpc(InstID);
            MEM_PushInstParam(n);
            MEM_CallByID(buff.OnApply);
        };
    };
    
    
    func void Buff_ApplyUnique(var c_npc slf, var int _bf)
    {
        var int hlp;         hlp = new(_bf);
        var CBuff b;         b = get(hlp);
        if(!Npc_HasBuff(slf, b.ID))
        {
            Buff_Apply(slf, _bf);
        };
    };
    
    
    func void Buff_Delete(var int ptr)
    {
        if(m_arrBuffs)
        {
            var CBuff b; b = get(ptr);
            if(b.OnRemove > 0)
            {
                var c_npc slf; slf = Hlp_GetNpc(b.pSelf);
                MEM_PushInstParam(slf);
                MEM_CallByID(b.OnRemove);
            };
            MEM_ArrayRemoveValue(m_arrBuffs, ptr);
            if(MEM_ArraySize(m_arrBuffs) <= 0)
            {
                MEM_ArrayClear(m_arrBuffs);
                m_arrBuffs = 0;
            };
        };
    };
    
    
    func void Buff_End()
    {
        Buff_Delete(Current_Buff);
    };
    
    
    func void Buff_CallFunc(var int ptr)
    {    
        var CBuff b; b = get(ptr);
        if(b.OnTick > 0)
        {
            var c_npc slf; slf = Hlp_GetNpc(b.pSelf);
            MEM_PushInstParam(slf);
            MEM_CallByID(b.OnTick);
        };
    };
    
    
    func void Buff_Do(var int nr)
    {        
        if(!m_arrBuffs)
        {
            return;
        };
        
        var int ptr; ptr = MEM_ArrayRead(m_arrBuffs, nr);    
        if(!Hlp_IsValidHandle(ptr))
        {
            return;
        };
            
        var int bPause;
        var int NowTime;
        var CBuff buff;
        
        bPause             = MEM_GAME.singleStep;    //BOOL
        Current_Buff     = ptr;
        NowTime            = Timer();
        buff            = get(ptr);
        
        if(!bPause)
        {
            if(NowTime >= buff.EndTime)
            {
                buff.EndTime += buff.delay;
                Buff_CallFunc(ptr);
                if(buff.Cycles != -1)
                {
                    buff.Cycles -= 1;
                    if(buff.Cycles  < 1 )
                    {
                        Buff_Delete(ptr);
                        return;
                    };
                };    
            };
        }
        else
        {
            buff.EndTime += Timer() - buff.OldTime;
        };
        buff.OldTime = NowTime;
    };
    
    
    func void Buffs_Attach()
    {
        if(m_arrBuffs)
        {
            if(MEM_ArraySize(m_arrBuffs))
            {
                var int i; i = 0;
                var int pos; pos = MEM_StackPos.position;
                if(i < MEM_ArraySize(m_arrBuffs))    //for(int i = 0; i < m_arrBuffs.GetSize(); i++);
                {
                    Buff_Do(i);
                    i += 1;
                    MEM_StackPos.position = pos;
                };            
            };
        };    
    };
    
    
    func void Buff_RemoveByType(var c_npc slf, var int type)
    {
        var int arr; arr = MEM_ArrayCreate();
        GetBuffsByNpc(arr, slf);
        
        if(arr)
        {
            var int size; size = MEM_ArraySize(arr);
            if(size)
            {
                var int i; i = 0;
                repeat(i, size);
                    var int ptr; ptr = MEM_ArrayRead(arr, i);
                    if(Hlp_IsValidHandle(ptr))
                    {
                        var CBuff b; b = get(ptr);
                        if(type == b.Type)
                        {
                            Buff_Delete(ptr);
                        };
                    };
                end;
            };
        };
        
        MEM_ArrayFree(arr);
    };
    
    
    func void Buff_RemoveByID(var c_npc slf, var int id)
    {
        var int arr; arr = MEM_ArrayCreate();
        GetBuffsByNpc(arr, slf);
        
        if(arr)
        {
            var int size; size = MEM_ArraySize(arr);
            if(size)
            {
                var int i; i = 0;
                repeat(i, size);
                    var int ptr; ptr = MEM_ArrayRead(arr, i);
                    if(Hlp_IsValidHandle(ptr))
                    {
                        var CBuff b; b = get(ptr);
                        if(id == b.ID)
                        {
                            Buff_Delete(ptr);
                        };
                    };
                end;
            };
        };    
        MEM_ArrayFree(arr);
    };
    
    
    func void Buff_SetCycles(var c_npc slf, var int ID, var int cycles)
    {
        var int arr; arr = MEM_ArrayCreate();
        GetBuffsByNpc(arr, slf);
        
        if(arr)
        {
            var int size; size = MEM_ArraySize(arr);
            if(size)
            {
                var int i; i = 0;
                repeat(i, size);
                    var int ptr; ptr = MEM_ArrayRead(arr, i);
                    if(Hlp_IsValidHandle(ptr))
                    {
                        var CBuff b; b = get(ptr);
                        if(id == b.ID)
                        {
                            b.cycles = cycles;
                        };
                    };
                end;
            };
        };    
        MEM_ArrayFree(arr);
    };
    
    
    func int Buff_CreateView(var int x, var int y, var string texture)
    {
        var int ptr; ptr = View_CreateCenter(x, y, 
        Print_ToVirtual(Buff_TextureSize, PS_X), 
        Print_ToVirtual(Buff_TextureSize, PS_Y));
        View_SetTexture(ptr, texture);
        View_Open(ptr);
        return ptr;
    };
    Example:
    Code:
    const int ID_DeadlyPoison = 1;
    INSTANCE DeadlyPoison(CBuff)
    {
        Type     	= BUFF_BAD;    
        ID         	= ID_DeadlyPoison;    
    
    
    
    
        OnApply    	= SAVE_GetFuncID(Poison_Apply);
        OnTick    	= SAVE_GetFuncID(Poison_Tick);    
        OnRemove    = SAVE_GetFuncID(Poison_Remove);
        
         delay    	= 500;    //500 * 20 = 10000 = 10s
         cycles    	= 20;
    };
    
    func void Poison_Apply(var c_npc slf)
    {
        PrintS(slf.name);
        PrintS("Poison Apply");
    };
    
    func void Poison_Tick(var c_npc slf)
    {
        Npc_ChangeAttribute(slf, ATR_HITPOINTS, -5);
        if(Npc_IsDead(slf))
        {
            Buff_End();
        };
    };
    
    
    func void Poison_End(var c_npc slf)
    {
        PrintS("End");
    };
    Functions in this "Package":
    Code:
    Buff_Apply            (c_npc slf, buff instance);
    Buff_ApplyUnique    (c_npc slf, buff instance);        
    Npc_HasBuff            (c_npc slf, int Buff_ID);
    Buff_RemoveByType    (c_npc slf, int Buff_type(BAD|NORMAL|GOOD));
    Buff_RemoveByID        (c_npc slf, int Buff_ID);
    Buff_SetCycles        (c_npc slf, int Buff_ID, int cycles);
    Buff_End(); //End current buff - Use in Buff Tick function!
    To fully work, we must add in Init_Global(); FF_ApplyOnce(Buffs_Attach); after init lego.

  2. Beiträge anzeigen #22 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Zitat Zitat von Rayzer Beitrag anzeigen
    Cinemascope was wrote by OrcWarriorPL many years ago. I just ordered it, because script was practically illegible. Bottom part of script (strange formula) is for moving choice box bellow black bar when resolution is set at 1024x768 or lower. It's not necessary, because hardly anyone plays at these resolutions yet :P I think it may be written simplier, but I'm lazy xD
    That looks a lot better! I still have to ask... what's he computing with the %1 in the formula at the bottom? I had asked the last time this script showed up but no one was able to answer me

    Zitat Zitat von Rayzer Beitrag anzeigen
    Btw. Some time ago I wrote script of temporary regeneration for my personal use, as alternative of Buffs. You can set delay and ticks. Usage is very easy. Just call fuction RE_CastEffects per frame. Example:
    Code:
    RE_AddEffect (self, ATR_HITPOINTS, 120, 8, 1000);
    Code:
    Code:
    class RegenerationEffect
    {
        var int instance;
        var int attribute;
        var int value;
        var int cycles;
        var int cycles_current;
        var int delay;
        var int time;
    };
    
    
    instance RegenerationEffect@ (RegenerationEffect);
    
    
    func void RE_AddEffect (var c_npc slf, var int attribute, var int value, var int cycles, var int delayMS)
    {
        var int hndl; hndl = new (RegenerationEffect@);
        var RegenerationEffect effect; effect = get (hndl);
        effect.instance = Hlp_GetInstanceID (slf);
        effect.attribute = attribute;
        effect.value = value;
        effect.cycles = cycles;
        effect.cycles_current = cycles;
        effect.delay = delayMS;
        effect.time = MEM_Timer.totalTime;
    };
    
    
    func void RE_CastEffect (var int hndl)
    {
        var RegenerationEffect effect; effect = get (hndl);
        
        if (MEM_Timer.totalTime - effect.time < effect.delay || MEM_Game.singleStep == true)
        {
        return;
        };
        
        if (effect.cycles_current > 0)
        {
        var c_npc slf; slf = Hlp_GetNpc (effect.instance);    
        var int value; value = roundf (divf (mkf (effect.value), mkf (effect.cycles)));
        effect.cycles_current -= 1;
        effect.time = MEM_Timer.totalTime;
        
            if (effect.cycles_current == 0 && effect.value - (value*effect.cycles) > 0)
            {
            value += effect.value - (value*effect.cycles);
            };
    
    
            if (slf.attribute[ATR_HITPOINTS] > 0)
            {
            Npc_ChangeAttribute (slf, effect.attribute, value);
            };
        };
        
        if (effect.cycles_current == 0 || slf.attribute[ATR_HITPOINTS] == 0)
        {
        delete (hndl);
        };
    };
    
    
    func void RE_CastEffects ()
    {
        foreachHndl (RegenerationEffect@, RE_CastEffect);
    };
    The script looks good but I don't think there's any use for it given that LeGo implements its own buffs - I think it's only marginally more work to implement a regen effect using them.
    I think your script may have problems when such an effect is applied to monsters (e.g. more than one NPC of the given instance). I think the only and thus best way to save NPCs is Npc_GetID()/Npc_FindByID().

    @Siemekk: I don't mind you rewriting stuff (although I have to ask why: It looks like you're still using LeGo functions in there anyway?), but I really see nothing to gain here. Why publish a script that is almost a literal copy?

  3. Beiträge anzeigen #23 Zitieren
    Waldläufer Avatar von Siemekk
    Registriert seit
    May 2016
    Beiträge
    121
     
    Siemekk ist offline
    I don't know how's look's buffs in LeGo - last time when i used this package i had crash in buff_apply. So i rewrited system - my script save all values to array. It's working, but if buff's from LeGo work, for others this script is no sense.

  4. Beiträge anzeigen #24 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Zitat Zitat von Siemekk Beitrag anzeigen
    I don't know how's look's buffs in LeGo - last time when i used this package i had crash in buff_apply. So i rewrited system - my script save all values to array. It's working, but if buff's from LeGo work, for others this script is no sense.
    Oh, that is understandable! For future reference: If you find crashes (or other bugs) when using LeGo, make a small post in the LeGo thread! I'd love to fix them.

  5. Beiträge anzeigen #25 Zitieren
    Apprentice Avatar von Rayzer
    Registriert seit
    Sep 2014
    Ort
    Poland
    Beiträge
    44
     
    Rayzer ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    That looks a lot better! I still have to ask... what's he computing with the %1 in the formula at the bottom? I had asked the last time this script showed up but no one was able to answer me
    I don't know. This is also strange to me. This question should be addressed to OrcWarrior, but it's hard to get in touch with him. Here is original script: https://github.com/orcwarrior/Czas_Z...nctions.d#L192
    Be careful. Eyes can hurt from reading this xD

    Zitat Zitat von Lehona Beitrag anzeigen
    The script looks good but I don't think there's any use for it given that LeGo implements its own buffs - I think it's only marginally more work to implement a regen effect using them.
    I think your script may have problems when such an effect is applied to monsters (e.g. more than one NPC of the given instance). I think the only and thus best way to save NPCs is Npc_GetID()/Npc_FindByID().
    Thanks. I think this will help. I did not think about monsters, because I wrote this script for food and potions.

  6. Homepage besuchen Beiträge anzeigen #26 Zitieren
    Clockwork Origins Avatar von Bonne6
    Registriert seit
    Jun 2004
    Ort
    Erlangen
    Beiträge
    11.826
     
    Bonne6 ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Name:
    Wld_StopEffect_Ext
    Voraussetzungen:
    Ikarus 1.2
    Kompatibilität:
    Gothic 1 und Gothic 2
    Beschreibung:
    Schon immer hat mich an Wld_PlayEffect genervt, dass man Effekte nicht verlässlich stoppen kann. Wld_StopEffect beendet nur den erst gefundenen Effekt mit dem Namen, was häufig dazu geführt hat, dass Effekte in der Welt hängen geblieben sind. Ausserdem gibt es in Gothic 1 gar kein Wld_StopEffect, wodurch man gestartete Effekte gar nicht erst beenden konnte.
    Ich möchte hier Wld_StopEffect_Ext vorstellen. Ein Skript, mit dem man genau bestimmen kann welcher Effekt beendet werden soll (und ob nur einer oder alle übereinstimmenden). Das ganze kompatibel mit Gothic 2 und Gothic 1. Die Funktion tut haargenau das, was Wld_StopEffect in der Engine tut, nur mit erweiterter Funktionalität.
    Genauer:
    Es gibt drei zusätzliche Funktionsparamenter und einen Rückgabewert:
    func int Wld_StopEffect_Ext(string effect, int origin, int target, int stopAll)
    Parameter zwei und drei sind Ursprungsobjekt und Zielobjekt (so wie man das von Wld_PlayEffect kennt). Übergeben wird jeweils eine Instanz. So kann mal sowohl NPCs und Items, als auch jegliche andere Instanz übergeben, die von der Klasse zCVob erbt. Diese Parameter können auch null sein, wenn sie nicht festgelegt werden sollen.
    Der vierte Parameter lässt entscheiden, ob nur der erst gefundene Effekt gestoppt werden soll (0), so wie bei Wld_StopEffect, oder alle Effekte gestoppt werden sollen, die mit den Voraussetzungen übereinstimmen (1).
    Der Rückgabewert gibt an, wie viele Effekte gestoppt wurden. Null bedeutet, dass entweder keine passenden Effekte gefunden wurden, oder die Argumente fehlerhaft waren. Mit diesem Rückgabewert hat man aus der Skripten nun auch mehr Kontrolle über was geschieht.
    Beispiel:
    Code:
    var C_NPC Diego; Diego = Hlp_GetNpc(PC_ThiefOW);
    Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, Diego, 2, 150, DAM_FIRE, TRUE);
    Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, hero,  2, 150, DAM_FIRE, TRUE);
    
    Wld_StopEffect_Ext("SPELLFX_SLEEPER_FIREBALL", 0, Diego, 0); // Stops exactly and only the first effect
    Code:
    // Wld_StopEffect for Gothic 1
    func void Wld_StopEffect(var string effect) {
        Wld_StopEffect_Ext(effect, 0, 0, 0);
    };


    Spoiler:(zum lesen bitte Text markieren)

    Aufgrund der vielen Speicheradressen für sowohl Gothic 1, als auch Gothic 2, wirkt das Skript enorm lang, ist aber eigentlich ziemlich kurz und simpel.

    Ich habe das Skript schon in die Form der übrigen Skripte aus dem ScriptBin gebracht (Kopfzeile im Skript), kann also direkt so übernommen werden.

    Code:
    // Extended functionality for Wld_StopEffect()
    // See https://forum.worldofplayers.de/forum/threads/1495001-Scriptsammlung-ScriptBin?p=25548652&viewfull=1#post25548652
    // Made by mud-freak (@szapp) 2017-08-05 (modified 2017-08-09)
    //
    // Compatible with Gothic 1 and Gothic 2
    // Requirements: Ikarus 1.2
    
    
    /*
     * Check the inheritance of a zCObject against a zCClassDef. Emulating zCObject::CheckInheritance() at 0x476E30 in G2.
     * This function is used in Wld_StopEffect_Ext().
     */
    func int objCheckInheritance(var int objPtr, var int classDef) {
        if (!objPtr) || (!classDef) {
            return 0;
        };
    
        const int zCClassDef_baseClassDef_offset = 60;  //0x003C
    
        // Iterate over base classes
        var int curClassDef; curClassDef = MEM_GetClassDef(objPtr);
        while((curClassDef) && (curClassDef != classDef));
            curClassDef = MEM_ReadInt(curClassDef+zCClassDef_baseClassDef_offset);
        end;
    
        return (curClassDef == classDef);
    };
    
    
    /*
     * Emulate the Gothic 2 external function Wld_StopEffect(), with additional settings: Usually it is not clear which
     * effect will be stopped, leading to effects getting "stuck". Here, Wld_StopEffect is extended with additional checks
     * for origin and/or target vob and whether to stop all matching FX or only the first one found (like in Wld_StopEffect)
     * The function returns the number of stopped effects, or zero if none was found or an error occurred.
     * Compatible with Gothic 1 and Gothic 2. This means there is finally the possibility to stop effects in Gothic 1!
     *
     * Examples:
     *  var C_NPC Diego; Diego = Hlp_GetNpc(PC_ThiefOW);
     *  Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, Diego, 2, 150, DAM_FIRE, TRUE);
     *  Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, hero,  2, 150, DAM_FIRE, TRUE);
     *  Wld_StopEffect_Ext("SPELLFX_SLEEPER_FIREBALL", 0, Diego, 0); // Stops only the first effect
     *
     *  Calling Wld_StopEffect("EFFECT_1") corresponds to Wld_StopEffect_Ext("EFFECT_1", 0, 0, 0).
     *
     * Big parts if this function are taken from Wld_StopEffect. Gothic 2: sub_006E32B0() 0x6E32B0
     */
    func int Wld_StopEffect_Ext(var string effectName, var int originInst, var int targetInst, var int all) {
        // Gothic 1 addresses and offsets
        const int zCVob__classDef_G1                =  9269976; //0x8D72D8
        const int zCWorld__SearchVobListByClass_G1  =  6249792; //0x5F5D40
        const int oCVisualFX__classDef_G1           =  8822272; //0x869E00
        const int oCVisualFX__Stop_G1               =  4766512; //0x48BB30
        const int oCVisualFX_originVob_offset_G1    =     1112; //0x0458
        const int oCVisualFX_targetVob_offset_G1    =     1120; //0x0460
        const int oCVisualFX_instanceName_offset_G1 =     1140; //0x0474
    
        // Gothic 2 addresses and offsets
        const int zCVob__classDef_G2                = 10106072; //0x9A34D8
        const int zCWorld__SearchVobListByClass_G2  =  6439504; //0x624250
        const int oCVisualFX__classDef_G2           =  9234008; //0x8CE658
        const int oCVisualFX__Stop_G2               =  4799456; //0x493BE0
        const int oCVisualFX_originVob_offset_G2    =     1192; //0x04A8
        const int oCVisualFX_targetVob_offset_G2    =     1200; //0x04B0
        const int oCVisualFX_instanceName_offset_G2 =     1220; //0x04C4
    
        var int zCVob__classDef;
        var int zCWorld__SearchVobListByClass;
        var int oCVisualFX__classDef;
        var int oCVisualFX__Stop;
        var int oCVisualFX_originVob_offset;
        var int oCVisualFX_targetVob_offset;
        var int oCVisualFX_instanceName_offset;
        zCVob__classDef                = MEMINT_SwitchG1G2(zCVob__classDef_G1,
                                                           zCVob__classDef_G2);
        zCWorld__SearchVobListByClass  = MEMINT_SwitchG1G2(zCWorld__SearchVobListByClass_G1,
                                                           zCWorld__SearchVobListByClass_G2);
        oCVisualFX__classDef           = MEMINT_SwitchG1G2(oCVisualFX__classDef_G1,
                                                           oCVisualFX__classDef_G2);
        oCVisualFX__Stop               = MEMINT_SwitchG1G2(oCVisualFX__Stop_G1,
                                                           oCVisualFX__Stop_G2);
        oCVisualFX_originVob_offset    = MEMINT_SwitchG1G2(oCVisualFX_originVob_offset_G1,
                                                           oCVisualFX_originVob_offset_G2);
        oCVisualFX_targetVob_offset    = MEMINT_SwitchG1G2(oCVisualFX_targetVob_offset_G1,
                                                           oCVisualFX_targetVob_offset_G2);
        oCVisualFX_instanceName_offset = MEMINT_SwitchG1G2(oCVisualFX_instanceName_offset_G1,
                                                           oCVisualFX_instanceName_offset_G2);
    
        var int worldPtr; worldPtr = _at(MEM_World);
        if (!worldPtr) {
            return 0;
        };
    
        // Create array from all oCVisualFX vobs
        var int vobArrayPtr; vobArrayPtr = MEM_ArrayCreate();
        var zCArray vobArray; vobArray = _hat(vobArrayPtr);
        const int call = 0; var int zero;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_at(zero));                 // Vob tree (0 == globalVobTree)
            CALL_PtrParam(_at(vobArrayPtr));          // Array to store found vobs in
            CALL_PtrParam(_at(oCVisualFX__classDef)); // Class definition
            CALL__thiscall(_at(worldPtr), zCWorld__SearchVobListByClass);
            call = CALL_End();
        };
    
        if (!vobArray.numInArray) {
            MEM_ArrayFree(vobArrayPtr);
            return 0;
        };
    
        effectName = STR_Upper(effectName);
    
        var zCPar_Symbol symb;
    
        // Validate origin vob instance
        if (originInst) {
            // Get pointer from instance symbol
            if (originInst > 0) && (originInst < MEM_Parser.symtab_table_numInArray) {
                symb = _hat(MEM_ReadIntArray(contentSymbolTableAddress, originInst));
                originInst = symb.offset;
            } else {
                originInst = 0;
            };
    
            if (!objCheckInheritance(originInst, zCVob__classDef)) {
                MEM_Warn("Wld_StopEffect_Ext: Origin is not a valid vob");
                return 0;
            };
        };
    
        // Validate target vob instance
        if (targetInst) {
            // Get pointer from instance symbol
            if (targetInst > 0) && (targetInst < MEM_Parser.symtab_table_numInArray) {
                symb = _hat(MEM_ReadIntArray(contentSymbolTableAddress, targetInst));
                targetInst = symb.offset;
            } else {
                targetInst = 0;
            };
    
            if (!objCheckInheritance(targetInst, zCVob__classDef)) {
                MEM_Warn("Wld_StopEffect_Ext: Target is not a valid vob");
                return 0;
            };
        };
    
        // Search all vobs for the matching name
        var int stopped; stopped = 0; // Number of FX stopped
        repeat(i, vobArray.numInArray); var int i;
            var int vobPtr; vobPtr = MEM_ArrayRead(vobArrayPtr, i);
            if (!vobPtr) {
                continue;
            };
    
            // Search for FX with matching name
            if (!Hlp_StrCmp(effectName, "")) {
                var string effectInst; effectInst = MEM_ReadString(vobPtr+oCVisualFX_instanceName_offset);
                if (!Hlp_StrCmp(effectInst, effectName)) {
                    continue;
                };
            };
    
            // Search for a specific origin vob
            if (originInst) {
                var int originVob; originVob = MEM_ReadInt(vobPtr+oCVisualFX_originVob_offset);
                if (originVob != originInst) {
                    continue;
                };
            };
    
            // Search for a specific target vob
            if (targetInst) {
                var int targetVob; targetVob = MEM_ReadInt(vobPtr+oCVisualFX_targetVob_offset);
                if (targetVob != targetInst) {
                    continue;
                };
            };
    
            // Stop the oCVisualFX
            const int call2 = 0; const int one = 1;
            if (CALL_Begin(call2)) {
                CALL_PtrParam(_at(one));
                CALL__thiscall(_at(vobPtr), oCVisualFX__Stop);
                call2 = CALL_End();
            };
            stopped += 1;
    
            if (!all) {
                break;
            };
        end;
        MEM_ArrayFree(vobArrayPtr);
    
        return stopped;
    };




    Was haltet ihr eigentlich davon, diesen Thread mal anzupinnen?
    Was hat es mit dem _at auf sich? Das wird bei mir nicht gefunden und ich weiß auch nicht, wo es herkommen müsste.

  7. Beiträge anzeigen #27 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    _at() und _hat() sind _@() beziehungsweise _^(). Ich nehme an, da ist irgendwas beim schön formatieren kaputt gegangen? Vielleicht mag mud-freak auch einfach die Symbole nicht, ich hab gehört die Schweizer benutzen ein anderes Tastaturlayout als das deutsche.

    Die Datei war im ScriptBin nicht in die zugehörige .src eingetragen, daher ist mir das nicht aufgefallen. Aktualisierte .src und Wld_StopEffect.d (die sich parsen lässt) sind jetzt auf dem SVN.

  8. Homepage besuchen Beiträge anzeigen #28 Zitieren
    Clockwork Origins Avatar von Bonne6
    Registriert seit
    Jun 2004
    Ort
    Erlangen
    Beiträge
    11.826
     
    Bonne6 ist offline
    Danke, Leona, werd's morgen dann gleich testen.

  9. Beiträge anzeigen #29 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.243
     
    Milky-Way ist gerade online
    Zitat Zitat von mud-freak Beitrag anzeigen
    Name:
    Wld_StopEffect_Ext
    Voraussetzungen:
    Ikarus 1.2
    Kompatibilität:
    Gothic 1 und Gothic 2
    Beschreibung:
    Schon immer hat mich an Wld_PlayEffect genervt, dass man Effekte nicht verlässlich stoppen kann. Wld_StopEffect beendet nur den erst gefundenen Effekt mit dem Namen, was häufig dazu geführt hat, dass Effekte in der Welt hängen geblieben sind. Ausserdem gibt es in Gothic 1 gar kein Wld_StopEffect, wodurch man gestartete Effekte gar nicht erst beenden konnte.
    Ich möchte hier Wld_StopEffect_Ext vorstellen. Ein Skript, mit dem man genau bestimmen kann welcher Effekt beendet werden soll (und ob nur einer oder alle übereinstimmenden). Das ganze kompatibel mit Gothic 2 und Gothic 1. Die Funktion tut haargenau das, was Wld_StopEffect in der Engine tut, nur mit erweiterter Funktionalität.
    Genauer:
    Es gibt drei zusätzliche Funktionsparamenter und einen Rückgabewert:
    func int Wld_StopEffect_Ext(string effect, int origin, int target, int stopAll)
    Parameter zwei und drei sind Ursprungsobjekt und Zielobjekt (so wie man das von Wld_PlayEffect kennt). Übergeben wird jeweils eine Instanz. So kann mal sowohl NPCs und Items, als auch jegliche andere Instanz übergeben, die von der Klasse zCVob erbt. Diese Parameter können auch null sein, wenn sie nicht festgelegt werden sollen.
    Der vierte Parameter lässt entscheiden, ob nur der erst gefundene Effekt gestoppt werden soll (0), so wie bei Wld_StopEffect, oder alle Effekte gestoppt werden sollen, die mit den Voraussetzungen übereinstimmen (1).
    Der Rückgabewert gibt an, wie viele Effekte gestoppt wurden. Null bedeutet, dass entweder keine passenden Effekte gefunden wurden, oder die Argumente fehlerhaft waren. Mit diesem Rückgabewert hat man aus der Skripten nun auch mehr Kontrolle über was geschieht.
    Beispiel:
    Code:
    var C_NPC Diego; Diego = Hlp_GetNpc(PC_ThiefOW);
    Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, Diego, 2, 150, DAM_FIRE, TRUE);
    Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, hero,  2, 150, DAM_FIRE, TRUE);
    
    Wld_StopEffect_Ext("SPELLFX_SLEEPER_FIREBALL", 0, Diego, 0); // Stops exactly and only the first effect
    Code:
    // Wld_StopEffect for Gothic 1
    func void Wld_StopEffect(var string effect) {
        Wld_StopEffect_Ext(effect, 0, 0, 0);
    };


    Spoiler:(zum lesen bitte Text markieren)

    Aufgrund der vielen Speicheradressen für sowohl Gothic 1, als auch Gothic 2, wirkt das Skript enorm lang, ist aber eigentlich ziemlich kurz und simpel.

    Ich habe das Skript schon in die Form der übrigen Skripte aus dem ScriptBin gebracht (Kopfzeile im Skript), kann also direkt so übernommen werden.

    Code:
    // Extended functionality for Wld_StopEffect()
    // See https://forum.worldofplayers.de/forum/threads/1495001-Scriptsammlung-ScriptBin?p=25548652&viewfull=1#post25548652
    // Made by mud-freak (@szapp) 2017-08-05 (modified 2017-08-09)
    //
    // Compatible with Gothic 1 and Gothic 2
    // Requirements: Ikarus 1.2
    
    
    /*
     * Check the inheritance of a zCObject against a zCClassDef. Emulating zCObject::CheckInheritance() at 0x476E30 in G2.
     * This function is used in Wld_StopEffect_Ext().
     */
    func int objCheckInheritance(var int objPtr, var int classDef) {
        if (!objPtr) || (!classDef) {
            return 0;
        };
    
        const int zCClassDef_baseClassDef_offset = 60;  //0x003C
    
        // Iterate over base classes
        var int curClassDef; curClassDef = MEM_GetClassDef(objPtr);
        while((curClassDef) && (curClassDef != classDef));
            curClassDef = MEM_ReadInt(curClassDef+zCClassDef_baseClassDef_offset);
        end;
    
        return (curClassDef == classDef);
    };
    
    
    /*
     * Emulate the Gothic 2 external function Wld_StopEffect(), with additional settings: Usually it is not clear which
     * effect will be stopped, leading to effects getting "stuck". Here, Wld_StopEffect is extended with additional checks
     * for origin and/or target vob and whether to stop all matching FX or only the first one found (like in Wld_StopEffect)
     * The function returns the number of stopped effects, or zero if none was found or an error occurred.
     * Compatible with Gothic 1 and Gothic 2. This means there is finally the possibility to stop effects in Gothic 1!
     *
     * Examples:
     *  var C_NPC Diego; Diego = Hlp_GetNpc(PC_ThiefOW);
     *  Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, Diego, 2, 150, DAM_FIRE, TRUE);
     *  Wld_PlayEffect("SPELLFX_SLEEPER_FIREBALL", self, hero,  2, 150, DAM_FIRE, TRUE);
     *  Wld_StopEffect_Ext("SPELLFX_SLEEPER_FIREBALL", 0, Diego, 0); // Stops only the first effect
     *
     *  Calling Wld_StopEffect("EFFECT_1") corresponds to Wld_StopEffect_Ext("EFFECT_1", 0, 0, 0).
     *
     * Big parts if this function are taken from Wld_StopEffect. Gothic 2: sub_006E32B0() 0x6E32B0
     */
    func int Wld_StopEffect_Ext(var string effectName, var int originInst, var int targetInst, var int all) {
        // Gothic 1 addresses and offsets
        const int zCVob__classDef_G1                =  9269976; //0x8D72D8
        const int zCWorld__SearchVobListByClass_G1  =  6249792; //0x5F5D40
        const int oCVisualFX__classDef_G1           =  8822272; //0x869E00
        const int oCVisualFX__Stop_G1               =  4766512; //0x48BB30
        const int oCVisualFX_originVob_offset_G1    =     1112; //0x0458
        const int oCVisualFX_targetVob_offset_G1    =     1120; //0x0460
        const int oCVisualFX_instanceName_offset_G1 =     1140; //0x0474
    
        // Gothic 2 addresses and offsets
        const int zCVob__classDef_G2                = 10106072; //0x9A34D8
        const int zCWorld__SearchVobListByClass_G2  =  6439504; //0x624250
        const int oCVisualFX__classDef_G2           =  9234008; //0x8CE658
        const int oCVisualFX__Stop_G2               =  4799456; //0x493BE0
        const int oCVisualFX_originVob_offset_G2    =     1192; //0x04A8
        const int oCVisualFX_targetVob_offset_G2    =     1200; //0x04B0
        const int oCVisualFX_instanceName_offset_G2 =     1220; //0x04C4
    
        var int zCVob__classDef;
        var int zCWorld__SearchVobListByClass;
        var int oCVisualFX__classDef;
        var int oCVisualFX__Stop;
        var int oCVisualFX_originVob_offset;
        var int oCVisualFX_targetVob_offset;
        var int oCVisualFX_instanceName_offset;
        zCVob__classDef                = MEMINT_SwitchG1G2(zCVob__classDef_G1,
                                                           zCVob__classDef_G2);
        zCWorld__SearchVobListByClass  = MEMINT_SwitchG1G2(zCWorld__SearchVobListByClass_G1,
                                                           zCWorld__SearchVobListByClass_G2);
        oCVisualFX__classDef           = MEMINT_SwitchG1G2(oCVisualFX__classDef_G1,
                                                           oCVisualFX__classDef_G2);
        oCVisualFX__Stop               = MEMINT_SwitchG1G2(oCVisualFX__Stop_G1,
                                                           oCVisualFX__Stop_G2);
        oCVisualFX_originVob_offset    = MEMINT_SwitchG1G2(oCVisualFX_originVob_offset_G1,
                                                           oCVisualFX_originVob_offset_G2);
        oCVisualFX_targetVob_offset    = MEMINT_SwitchG1G2(oCVisualFX_targetVob_offset_G1,
                                                           oCVisualFX_targetVob_offset_G2);
        oCVisualFX_instanceName_offset = MEMINT_SwitchG1G2(oCVisualFX_instanceName_offset_G1,
                                                           oCVisualFX_instanceName_offset_G2);
    
        var int worldPtr; worldPtr = _@(MEM_World);
        if (!worldPtr) {
            return 0;
        };
    
        // Create array from all oCVisualFX vobs
        var int vobArrayPtr; vobArrayPtr = MEM_ArrayCreate();
        var zCArray vobArray; vobArray = _^(vobArrayPtr);
        const int call = 0; var int zero;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(zero));                 // Vob tree (0 == globalVobTree)
            CALL_PtrParam(_@(vobArrayPtr));          // Array to store found vobs in
            CALL_PtrParam(_@(oCVisualFX__classDef)); // Class definition
            CALL__thiscall(_@(worldPtr), zCWorld__SearchVobListByClass);
            call = CALL_End();
        };
    
        if (!vobArray.numInArray) {
            MEM_ArrayFree(vobArrayPtr);
            return 0;
        };
    
        effectName = STR_Upper(effectName);
    
        var zCPar_Symbol symb;
    
        // Validate origin vob instance
        if (originInst) {
            // Get pointer from instance symbol
            if (originInst > 0) && (originInst < MEM_Parser.symtab_table_numInArray) {
                symb = _^(MEM_ReadIntArray(contentSymbolTableAddress, originInst));
                originInst = symb.offset;
            } else {
                originInst = 0;
            };
    
            if (!objCheckInheritance(originInst, zCVob__classDef)) {
                MEM_Warn("Wld_StopEffect_Ext: Origin is not a valid vob");
                return 0;
            };
        };
    
        // Validate target vob instance
        if (targetInst) {
            // Get pointer from instance symbol
            if (targetInst > 0) && (targetInst < MEM_Parser.symtab_table_numInArray) {
                symb = _^(MEM_ReadIntArray(contentSymbolTableAddress, targetInst));
                targetInst = symb.offset;
            } else {
                targetInst = 0;
            };
    
            if (!objCheckInheritance(targetInst, zCVob__classDef)) {
                MEM_Warn("Wld_StopEffect_Ext: Target is not a valid vob");
                return 0;
            };
        };
    
        // Search all vobs for the matching name
        var int stopped; stopped = 0; // Number of FX stopped
        repeat(i, vobArray.numInArray); var int i;
            var int vobPtr; vobPtr = MEM_ArrayRead(vobArrayPtr, i);
            if (!vobPtr) {
                continue;
            };
    
            // Search for FX with matching name
            if (!Hlp_StrCmp(effectName, "")) {
                var string effectInst; effectInst = MEM_ReadString(vobPtr+oCVisualFX_instanceName_offset);
                if (!Hlp_StrCmp(effectInst, effectName)) {
                    continue;
                };
            };
    
            // Search for a specific origin vob
            if (originInst) {
                var int originVob; originVob = MEM_ReadInt(vobPtr+oCVisualFX_originVob_offset);
                if (originVob != originInst) {
                    continue;
                };
            };
    
            // Search for a specific target vob
            if (targetInst) {
                var int targetVob; targetVob = MEM_ReadInt(vobPtr+oCVisualFX_targetVob_offset);
                if (targetVob != targetInst) {
                    continue;
                };
            };
    
            // Stop the oCVisualFX
            const int call2 = 0; const int one = 1;
            if (CALL_Begin(call2)) {
                CALL_PtrParam(_@(one));
                CALL__thiscall(_@(vobPtr), oCVisualFX__Stop);
                call2 = CALL_End();
            };
            stopped += 1;
    
            if (!all) {
                break;
            };
        end;
        MEM_ArrayFree(vobArrayPtr);
    
        return stopped;
    };
    Im ScriptBin fehlt die Funktion objCheckInheritance, bzw. ist sie nicht in dieser Datei zu finden. Die Funktion sollte aber mindestens unter den Voraussetzungen genannt und verlinkt werden.

  10. Beiträge anzeigen #30 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
    Im ScriptBin fehlt die Funktion objCheckInheritance, bzw. ist sie nicht in dieser Datei zu finden. Die Funktion sollte aber mindestens unter den Voraussetzungen genannt und verlinkt werden.
    Doch die ist dabei. Lehona hat sie nur von dem Skript abgetrennt und separat in der Datei /Ikarus_Scripts/Misc.d aufgenommen.

  11. Beiträge anzeigen #31 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.243
     
    Milky-Way ist gerade online
    Zitat Zitat von mud-freak Beitrag anzeigen
    Doch die ist dabei. Lehona hat sie nur von dem Skript abgetrennt und separat in der Datei /Ikarus_Scripts/Misc.d aufgenommen.
    Ja, dann wäre es schön, wenn das im Kopf der Datei vermerkt oder verlinkt wäre. Ich könnte mir vorstellen, dass der ein oder andere so wie ich nicht alle Skripte nimmt, sondern sich die raussucht, die er /sie braucht

  12. Beiträge anzeigen #32 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
    Ja, dann wäre es schön, wenn das im Kopf der Datei vermerkt oder verlinkt wäre. Ich könnte mir vorstellen, dass der ein oder andere so wie ich nicht alle Skripte nimmt, sondern sich die raussucht, die er /sie braucht
    Gut, dem muss ich zustimmen. Das fänd ich auch gut.

    Wo ich gerade mal hier bin: Mir ist aufgefallen, dass das InsertAnything-Skript fehlerhaft ist. Unter gewissen Umständen gehen Vobs nach Speichern und Laden verloren. Ausserdem ist es eher suboptimal implementiert. Beheben lässt sich das ganz einfach, aber das Skript ist einfach so unleserlich formatiert (80 Zeichen Zeilenlänge und kaum Leerzeilen), dass ich da gar keine Lust drauf habe.
    Ich werde mir das heute vielleicht mal anschauen und es bei der Gelegenheit auch mal für Gothic 1 kompatibel machen.

  13. Beiträge anzeigen #33 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Ich habe das Skript jetzt komplett geändert. Die Funktionen haben jetzt nicht mehr so viele Parameter und sind übersichtlicher (stattdessen kann man bei Bedarf weitere Funktionen nach dem Einfügen aufrufen, um bspw. eine Truhe zu füllen, oder eine Tür zu verschliessen).
    Die Funktionen sind jetzt auch performanter (falls das eine Rolle spielt) und das ganze ist so aufgesetzt, dass man nun Objekte jeder beliebigen Art einfügen kann, die von zCVob erben. Für die meist genutzten habe ich aber Wrapper-Funktionen erstellt, um die Anzahl der Argumente klein und es übersichtlich zu halten.

    Alles sollte jetzt auch unter Gothic 1 laufen, habe ich aber nicht mehr explizit alles durchgetestet.

    Und hier ein kleines, nettes Beispiel:
    Code:
    const float pos[3] = { 9458.563477, 589.735718, -4732.891602 }; // World coordinates (use [ALT]+[P] in MARVIN-mode)
    
    var int chestPtr;
    chestPtr = InsertMobContainerPos("myNewChest", "CHESTBIG_OCCHESTLARGE.MDS", _@f(pos), 0);
    
    SetMobName(chestPtr,       "MOBNAME_CHEST");                    // Set focus name
    LockMobLockable(chestPtr,  "ItKe_Key_01", "LRLR", TRUE);        // A key and/or lock picking string can be set
    FillMobContainer(chestPtr, "ItMi_Gold:23,ItKe_Key_01:1 ");      // Whoops, dropped the key inside!
    

    Und hier ein Beispiel, wie man Objekte jeglicher (von zCVob erbenden) Klasse einfügen kann. Das obere Beispiel kann man auch so schreiben. Man muss nur die Klassenbezeichnung wissen, hier "oCMobContainer".
    Code:
    chestPtr = InsertObjectPos("oCMobContainer", "myNewChest", "CHESTBIG_OCCHESTLARGE.MDS", _@f(pos), 0, 0);

    Hier das Skript. Kann dann bei Gelegenheit im Scriptbin aktualisiert werden.
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    /*
     * insertAnything.d
     * Source: https://forum.worldofplayers.de/forum/threads/?p=25712257
     *
     * Create and insert any kind of object inheriting from the zCVob class in real time.
     *
     *
     * The core function behind this is
     *
     *    func int InsertObject(string class, string objName, string visual, int trafoPtr, int parentVobPtr)
     *
     * However, for the most common object classes there are specific functions with simpler signature for inserting at
     *  - way points                                                           (functions with "WP" postfix)
     *  - exact coordinates with optionally specifying the direction           (functions with "Pos" postfix)
     *  - aligned at a full trafo-matrix                                       (functions without postfix)
     *
     * Additionally, the objects may be inserted as child vobs of other vobs.  (functions with "AsChild" postfix)
     * Objects inheriting from the oCMob class can then be further adjusted with additional functions listed below.
     *
     *    [A] = {Vob,Mob,MobInter,MobLockable,MobContainer,MobDoor,MobFire}
     *
     *    func int  Insert[A]WP         (string objName, string visual, string waypoint)
     *    func int  Insert[A]Pos        (string objName, string visual, int posPtr, int dirPtr)
     *    func int  Insert[A]           (string objName, string visual, int trafoPtr)
     *
     *    func int  Insert[A]AsChildWP  (string objName, string visual, string waypoint,        int parentVobPtr)
     *    func int  Insert[A]AsChildPos (string objName, string visual, int posPtr, int dirPtr, int parentVobPtr)
     *    func int  Insert[A]AsChild    (string objName, string visual, int trafoPtr,           int parentVobPtr)
     *
     *
     *    [B] = {Trigger,TriggerScript,TriggerChangeLevel}
     *
     *    func int  Insert[B]Pos        (string objName, int posPtr, int dirPtr)
     *    func int  Insert[B]           (string objName, int trafoPtr)
     *
     *    func int  InsertMoverPos      (string objName, string visual, int posPtr, int dirPtr)
     *    func int  InsertMover         (string objName, string visual, int trafoPtr)
     *
     *    func int  InsertItemWP        (string scriptInst, int amount, string waypoint)
     *    func int  InsertItemPos       (string scriptInst, int amount, int posPtr, int dirPtr)
     *    func int  InsertItem          (string scriptInst, int amount, int trafoPtr)
     *
     *    func void InsertPileOfVobs    (string objName, string visual, int trafoPtr, int amount, int cm2, int rotate)
     *    func void InsertPileOfItems   (string scriptInst,             int trafoPtr, int amount, int cm2, int rotate)
     *
     *
     *  Additional functions (not all functions are mentioned here)
     *
     *    func void SetVobToFloor       (int vobPtr)
     *    func void SetWPToFloor        (int wpPtr)
     *
     *
     *  Further mob setter-functions
     *
     *    func int  SetMobName          (int mobPtr, string symbolicFocusName)
     *    func void SetMobOwner         (int mobPtr, string owner, string ownerGuild)
     *    func void SetMobMisc          (int mobPtr, string triggerTarget, string useWithItem, string onStateFuncName)
     *    func void LockMobLockable     (int mobPtr, string keyInstance, string pickLockStr, int isLocked)
     *    func void FillMobContainer    (int mobPtr, string contents)
     *
     *
     *  Example
     *
     *   // Inserting a locked chest with specific contents
     *
     *   const float pos[3] = { 9458.563477, 589.735718, -4732.891602 }; // World coordinates (use [ALT]+[P] in MARVIN-mode)
     *
     *   var int chestPtr;
     *   chestPtr = InsertMobContainerPos("myNewChest", "CHESTBIG_OCCHESTLARGE.MDS", _@f(pos), 0);
     *
     *   SetMobName(chestPtr,       "MOBNAME_CHEST");                    // Set focus name
     *   LockMobLockable(chestPtr,  "ItKe_Key_01", "LRLR", TRUE);        // A key and/or lock picking string can be set
     *   FillMobContainer(chestPtr, "ItMi_Gold:23,ItKe_Key_01:1 ");      // Whoops, dropped the key inside!
     *
     */
    
    
    /*
     * Creates an "empty" trafo-matrix
     */
    func void NewTrafo(var int trafoPtr) {
        const int zMAT4__s_identity_G1 = 8845416; //0x86F868
        const int zMAT4__s_identity_G2 = 9258472; //0x8D45E8
        const int sizeof_zMAT4         = 64; // Same for G1 and G2
    
        MEM_CopyBytes(MEMINT_SwitchG1G2(zMAT4__s_identity_G1, zMAT4__s_identity_G2), trafoPtr, sizeof_zMAT4);
    };
    
    
    /*
     * Rotate trafo-matrix around its up-vector (change front-facing direction)
     */
    func void RotateTrafoY(var int trafoPtr, var int degrees) {
        const int zMAT4__PostRotateY_G1 = 5274256; //0x507A90
        const int zMAT4__PostRotateY_G2 = 5339008; //0x517780
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_FloatParam(_@(degrees));
            CALL__thiscall(_@(trafoPtr), MEMINT_SwitchG1G2(zMAT4__PostRotateY_G1, zMAT4__PostRotateY_G2));
            call = CALL_End();
        };
    };
    
    
    /*
     * Store the positional information of a trafo-matrix into a vector
     */
    func void TrfToPos(var int trafoPtr, var int posPtr) {
        MEM_WriteIntArray(posPtr, 0, MEM_ReadIntArray(trafoPtr,  3));
        MEM_WriteIntArray(posPtr, 1, MEM_ReadIntArray(trafoPtr,  7));
        MEM_WriteIntArray(posPtr, 2, MEM_ReadIntArray(trafoPtr, 11));
    };
    
    
    /*
     * Store positional and/or directional information into a trafo-matrix
     */
    func void PosDirToTrf(var int posPtr, var int dirPtr, var int trafoPtr) {
        const int zMAT4__MakeOrthonormal_G1 = 5273152; //0x507640
        const int zMAT4__MakeOrthonormal_G2 = 5337904; //0x517330
    
        if (posPtr) {
            MEM_WriteIntArray(trafoPtr,  3, MEM_ReadIntArray(posPtr, 0));
            MEM_WriteIntArray(trafoPtr,  7, MEM_ReadIntArray(posPtr, 1));
            MEM_WriteIntArray(trafoPtr, 11, MEM_ReadIntArray(posPtr, 2));
        };
    
        if (dirPtr) {
            MEM_WriteIntArray(trafoPtr,  2, MEM_ReadIntArray(dirPtr, 0));
            MEM_WriteIntArray(trafoPtr,  6, MEM_ReadIntArray(dirPtr, 1));
            MEM_WriteIntArray(trafoPtr, 10, MEM_ReadIntArray(dirPtr, 2));
    
            const int call = 0;
            if (CALL_Begin(call)) {
                CALL__thiscall(_@(trafoPtr), MEMINT_SwitchG1G2(zMAT4__MakeOrthonormal_G1, zMAT4__MakeOrthonormal_G2));
                call = CALL_End();
            };
        };
    };
    
    
    /*
     * Get ground level (y-coordinate) from a position
     */
    func int GetGroundLvlPos(var int posPtr) {
        const float dir[3] = { 0.0, -2000.0, 0.0 }; // Check for ground up to 2000 cm below (Gothic does 1000 cm)
    
        const int zCWorld__TraceRayNearestHit_G1 = 6243008; //0x5F42C0
        const int zCWorld__TraceRayNearestHit_G2 = 6429568; //0x621B80
    
        const int flags = 33; // 0x21 (zTRACERAY_VOB_IGNORE_NO_CD_DYN | zTRACERAY_STAT_POLY)
        const int ignoreList = 0;
        var int worldPtr; worldPtr = MEM_Game._zCSession_world;
        var int dirPtr; dirPtr = _@f(dir);
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_IntParam(_@(flags));
            CALL_PtrParam(_@(ignoreList));
            CALL_PtrParam(_@(dirPtr));
    
            CALL__fastcall(_@(worldPtr), _@(posPtr), MEMINT_SwitchG1G2(zCWorld__TraceRayNearestHit_G1,
                                                                       zCWorld__TraceRayNearestHit_G2));
            call = CALL_End();
        };
    
        // Check for intersection and return y-position
        if (CALL_RetValAsInt()) && ((MEM_World.foundPoly) || (MEM_World.foundVob)) {
            return MEM_World.foundIntersection[1];
        } else {
            return subf(MEM_ReadInt(posPtr+4), mkf(2000));
        };
    };
    
    
    /*
     * Get ground level (y-coordinate) from a trafo-matrix
     */
    func int GetGroundLvl(var int trfPtr) {
        var int pos[3];
        TrfToPos(trfPtr, _@(pos));
        return GetGroundLvlPos(_@(pos));
    };
    
    
    /*
     * Search a way point by its name
     */
    func int SearchWaypointByName(var string waypoint) {
        const int zCWayNet__GetWaypoint_G1 = 7366448; //0x706730
        const int zCWayNet__GetWaypoint_G2 = 8061744; //0x7B0330
    
        var int waynetPtr; waynetPtr = MEM_World.wayNet;
        var int wpNamePtr; wpNamePtr = _@s(waypoint);
    
        const int call = 0;
        if (Call_Begin(call)) {
            CALL__fastcall(_@(waynetPtr), _@(wpNamePtr), MEMINT_SwitchG1G2(zCWayNet__GetWaypoint_G1,
                                                                           zCWayNet__GetWaypoint_G2));
            call = CALL_End();
        };
        return CALL_RetValAsPtr();
    };
    
    
    /*
     * Get trafo-matrix from way point
     */
    func void GetTrafoFromWP(var string wpName, var int trafoPtr) {
        var int wpPtr; wpPtr = SearchWaypointByName(wpName);
        if (!wpPtr) {
            MEM_Warn("Way point not found!");
            return;
        };
    
        var zCWaypoint wp; wp = _^(wpPtr);
        PosDirToTrf(_@(wp.pos), _@(wp.dir), trafoPtr);
    };
    
    
    /*
     * Set way point to correct height above ground level
     */
    func void SetWPToFloor(var int wpPtr) {
        const int zCWaypoint__CorrectHeight_G1 = 7365792; //0x7064A0
        const int zCWaypoint__CorrectHeight_G2 = 8061088; //0x7B00A0
    
        var int worldPtr; worldPtr = MEM_Game._zCSession_world;
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(worldPtr));
    
            CALL__thiscall(_@(wpPtr), MEMINT_SwitchG1G2(zCWaypoint__CorrectHeight_G1, zCWaypoint__CorrectHeight_G2));
            call = CALL_End();
        };
    };
    
    
    /*
     * Align a vob to a trafo-matrix
     */
    func void AlignVobAt(var int vobPtr, var int trfPtr) {
        if (!vobPtr) || (!trfPtr) {
            return;
        };
    
        const int zCVob__SetTrafoObjToWorld_G1 = 6219616; //0x5EE760
        const int zCVob__SetTrafoObjToWorld_G2 = 6405248; //0x61BC80
    
        // Lift collision
        var zCVob vob; vob = _^(vobPtr);
        var int bits; bits = vob.bitfield[0];
        vob.bitfield[0] = vob.bitfield[0] & ~zCVob_bitfield0_collDetectionStatic & ~zCVob_bitfield0_collDetectionDynamic;
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(trfPtr));
            CALL__thiscall(_@(vobPtr), MEMINT_SwitchG1G2(zCVob__SetTrafoObjToWorld_G1, zCVob__SetTrafoObjToWorld_G2));
            call = CALL_End();
        };
    
        // Restore bits
        vob.bitfield[0] = bits;
    };
    
    
    /*
     * Set vob to align at ground level
     */
    func void SetVobToFloor(var int vobPtr) {
        if (!vobPtr) {
            return;
        };
    
        // Correct height
        var zCVob vob; vob = _^(vobPtr);
        var int half; half = subf(vob.trafoObjToWorld[7], vob.bbox3D_mins[1]);
        vob.trafoObjToWorld[7] = GetGroundLvl(_@(vob.trafoObjToWorld));
        vob.trafoObjToWorld[7] = addf(vob.trafoObjToWorld[7], half);
        vob.trafoObjToWorld[7] = subf(vob.trafoObjToWorld[7], castToIntf(0.5));
    
        // Update position
        AlignVobAt(vobPtr, _@(vob.trafoObjToWorld));
    };
    
    
    /*
     * Set a visual of a given vob by string
     */
    func void VobSetVisual(var int vobPtr, var String visual) {
        const int zCVob__SetVisual_G1 = 6123424; //0x5D6FA0
        const int zCVob__SetVisual_G2 = 6301312; //0x602680
    
        if (!vobPtr) {
            return;
        };
    
        var int strPtr; strPtr = _@s(visual);
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(strPtr));
            CALL__thiscall(_@(vobPtr), MEMINT_SwitchG1G2(zCVob__SetVisual_G1, zCVob__SetVisual_G2));
            call = CALL_End();
        };
    };
    
    
    /*
     * Retrieve class definition address by string
     */
    func int GetClassDefByString(var string classDefName) {
        const int zCClassDef__GetClassDef_G1 = 5809264; //0x58A470
        const int zCClassDef__GetClassDef_G2 = 5939168; //0x5A9FE0
    
        var int classDefNamePtr; classDefNamePtr = _@s(classDefName);
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(classDefNamePtr));
            CALL__cdecl(MEMINT_SwitchG1G2(zCClassDef__GetClassDef_G1, zCClassDef__GetClassDef_G2));
            call = CALL_End();
        };
        return CALL_RetValAsPtr();
    };
    
    
    /*
     * Create a new instance by class definition
     */
    func int CreateNewInstance(var int classDefAddr) {
        const int zCClassDef__createNewInstance_offset = 64; //0x40 Same for G1 and G2
    
        // This is a non-recyclable call, because of varying function address
        CALL__cdecl(MEM_ReadInt(classDefAddr+zCClassDef__createNewInstance_offset));
        return CALL_RetValAsPtr();
    };
    
    
    /*
     * Create new instance by class definition name
     */
    func int CreateNewInstanceByString(var string classDefName) {
        var int classDefAddr; classDefAddr = GetClassDefByString(classDefName);
        if (!classDefAddr) {
            MEM_Warn("ClassDef not found");
            return 0;
        };
    
        return CreateNewInstance(classDefAddr);
    };
    
    
    /*
     * Create and insert object
     */
    func int InsertObject(var string class, var string objName, var string visual, var int trfPtr, var int parentPtr) {
        var int vobPtr; vobPtr = CreateNewInstanceByString(class);
        if (!vobPtr) {
            return 0;
        };
    
        VobSetVisual(vobPtr, visual);
        MEM_RenameVob(vobPtr, objName);
    
        // Adjust bits
        var zCVob vob; vob = _^(vobPtr);
        vob.bitfield[0] = vob.bitfield[0] & (-67108865); //0xFBFFFFFF
        vob.bitfield[0] = vob.bitfield[0] & ~zCVob_bitfield0_collDetectionStatic & ~zCVob_bitfield0_collDetectionDynamic;
    
        // Set positional and rotational information
        AlignVobAt(vobPtr, trfPtr);
    
        // Get parent vob tree
        var int vobTreePtr;
        if (parentPtr) {
            var zCVob parent; parent = _^(parentPtr);
            vobTreePtr = parent.globalVobTreeNode;
        } else {
            vobTreePtr = _@(MEM_Vobtree); // Global vob tree
        };
    
        // Insert into world
        const int oCWorld__AddVobAsChild_G1 = 7171232; //0x6D6CA0
        const int oCWorld__AddVobAsChild_G2 = 7863856; //0x77FE30
    
        var int worldPtr; worldPtr = MEM_Game._zCSession_world;
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(vobTreePtr));
            CALL_PtrParam(_@(vobPtr));
    
            CALL_PutRetValTo(0);
    
            CALL__thiscall(_@(worldPtr), MEMINT_SwitchG1G2(oCWorld__AddVobAsChild_G1, oCWorld__AddVobAsChild_G2));
            call = CALL_End();
        };
    
        // Set bits
        vob.bitfield[0] = vob.bitfield[0] | zCVob_bitfield0_collDetectionStatic | zCVob_bitfield0_collDetectionDynamic;
        vob.bitfield[2] = vob.bitfield[2] & ~zCVob_bitfield2_sleepingMode; // vob.SetSleeping(1);
    
        // Decrease reference counter... why is that necessary?
        vob._zCObject_refCtr -= 1;
        if (vob._zCObject_refCtr <= 0) {
            const int _scalar_deleting_destructor_offset = 12; // Same for G1 and G2
            CALL_IntParam(1);
            CALL__thiscall(vobPtr, MEM_ReadInt(vob._vtbl+_scalar_deleting_destructor_offset));
        };
    
        return vobPtr;
    };
    func int InsertObjectPos(var string class, var string nm, var string vis, var int pos, var int dir, var int par) {
        var int trafo[16]; NewTrafo(_@(trafo));
        PosDirToTrf(pos, dir, _@(trafo));
        return InsertObject(class, nm, vis, _@(trafo), par);
    };
    func int InsertObjectWP(var string class, var string nm, var string vis, var string wpName, var int par) {
        var int wpPtr; wpPtr = SearchWaypointByName(wpName);
        if (!wpPtr) {
            MEM_Warn(ConcatStrings("Way point not found: ", wpName));
            return 0;
        };
        var zCWaypoint wp; wp = _^(wpPtr);
        return InsertObjectPos(class, nm, vis, _@(wp.pos), _@(wp.dir), par);
    };
    
    
    /*
     * zCVob/oCVob functions:
     *
     * InsertVobWP        (string objName, string visual, string waypoint)
     * InsertVobPos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertVob          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertVobAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertVobAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertVobAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertVobAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("zCVob", nm, vis, trf, par);
    };
    func int InsertVobAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("zCVob", nm, vis, pos, dir, par);
    };
    func int InsertVobAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("zCVob", nm, vis, wp, par);
    };
    func int InsertVob(var string nm, var string vis, var int trf) {
        return InsertObject("zCVob", nm, vis, trf, 0);
    };
    func int InsertVobPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("zCVob", nm, vis, pos, dir, 0);
    };
    func int InsertVobWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("zCVob", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMob functions:
     *
     * InsertMobWP        (string objName, string visual, string waypoint)
     * InsertMobPos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMob          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMOB", nm, vis, trf, par);
    };
    func int InsertMobAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMOB", nm, vis, pos, dir, par);
    };
    func int InsertMobAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMOB", nm, vis, wp, par);
    };
    func int InsertMob(var string nm, var string vis, var int trf) {
        return InsertObject("oCMOB", nm, vis, trf, 0);
    };
    func int InsertMobPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMOB", nm, vis, pos, dir, 0);
    };
    func int InsertMobWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMOB", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMobInter functions:
     *
     * InsertMobInterWP        (string objName, string visual, string waypoint)
     * InsertMobInterPos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMobInter          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobInterAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobInterAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobInterAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobInterAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMobInter", nm, vis, trf, par);
    };
    func int InsertMobInterAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMobInter", nm, vis, pos, dir, par);
    };
    func int InsertMobInterAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMobInter", nm, vis, wp, par);
    };
    func int InsertMobInter(var string nm, var string vis, var int trf) {
        return InsertObject("oCMobInter", nm, vis, trf, 0);
    };
    func int InsertMobInterPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMobInter", nm, vis, pos, dir, 0);
    };
    func int InsertMobInterWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMobInter", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMobLockable functions:
     *
     * InsertMobLockableWP        (string objName, string visual, string waypoint)
     * InsertMobLockablePos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMobLockable          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobLockableAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobLockableAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobLockableAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobLockableAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMobLockable", nm, vis, trf, par);
    };
    func int InsertMobLockableAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMobLockable", nm, vis, pos, dir, par);
    };
    func int InsertMobLockableAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMobLockable", nm, vis, wp, par);
    };
    func int InsertMobLockable(var string nm, var string vis, var int trf) {
        return InsertObject("oCMobLockable", nm, vis, trf, 0);
    };
    func int InsertMobLockablePos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMobLockable", nm, vis, pos, dir, 0);
    };
    func int InsertMobLockableWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMobLockable", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMobContainer functions:
     *
     * InsertMobContainerWP        (string objName, string visual, string waypoint)
     * InsertMobContainerPos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMobContainer          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobContainerAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobContainerAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobContainerAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobContainerAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMobContainer", nm, vis, trf, par);
    };
    func int InsertMobContainerAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMobContainer", nm, vis, pos, dir, par);
    };
    func int InsertMobContainerAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMobContainer", nm, vis, wp, par);
    };
    func int InsertMobContainer(var string nm, var string vis, var int trf) {
        return InsertObject("oCMobContainer", nm, vis, trf, 0);
    };
    func int InsertMobContainerPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMobContainer", nm, vis, pos, dir, 0);
    };
    func int InsertMobContainerWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMobContainer", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMobDoor functions:
     *
     * InsertMobDoorWP        (string objName, string visual, string waypoint)
     * InsertMobDoorPos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMobDoor          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobDoorAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobDoorAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobDoorAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobDoorAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMobDoor", nm, vis, trf, par);
    };
    func int InsertMobDoorAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMobDoor", nm, vis, pos, dir, par);
    };
    func int InsertMobDoorAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMobDoor", nm, vis, wp, par);
    };
    func int InsertMobDoor(var string nm, var string vis, var int trf) {
        return InsertObject("oCMobDoor", nm, vis, trf, 0);
    };
    func int InsertMobDoorPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMobDoor", nm, vis, pos, dir, 0);
    };
    func int InsertMobDoorWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMobDoor", nm, vis, wp, 0);
    };
    
    
    /*
     * oCMobFire functions:
     *
     * InsertMobFireWP        (string objName, string visual, string waypoint)
     * InsertMobFirePos       (string objName, string visual, int[3] *pos, int[3] *dir)
     * InsertMobFire          (string objName, string visual, int[16] *trafoMat)
     *
     * InsertMobFireAsChildWP (string objName, string visual, string waypoint,          int *parentVob)
     * InsertMobFireAsChildPos(string objName, string visual, int[3] *pos, int[3] *dir, int *parentVob)
     * InsertMobFireAsChild   (string objName, string visual, int[16] *trafoMat,        int *parentVob)
     */
    func int InsertMobFireAsChild(var string nm, var string vis, var int trf, var int par) {
        return InsertObject("oCMobFire", nm, vis, trf, par);
    };
    func int InsertMobFireAsChildPos(var string nm, var string vis, var int pos, var int dir, var int par) {
        return InsertObjectPos("oCMobFire", nm, vis, pos, dir, par);
    };
    func int InsertMobFireAsChildWP(var string nm, var string vis, var string wp, var int par) {
        return InsertObjectWP("oCMobFire", nm, vis, wp, par);
    };
    func int InsertMobFire(var string nm, var string vis, var int trf) {
        return InsertObject("oCMobFire", nm, vis, trf, 0);
    };
    func int InsertMobFirePos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("oCMobFire", nm, vis, pos, dir, 0);
    };
    func int InsertMobFireWP(var string nm, var string vis, var string wp) {
        return InsertObjectWP("oCMobFire", nm, vis, wp, 0);
    };
    
    
    /*
     * "Abstract" vob functions:
     *
     * InsertTriggerPos           (string objName,                int[3] *pos, int[3] *dir)
     * InsertTriggerScriptPos     (string objName,                int[3] *pos, int[3] *dir)
     * InsertTriggerChangeLevelPos(string objName,                int[3] *pos, int[3] *dir)
     * InsertMoverPos             (string objName, string visual, int[3] *pos, int[3] *dir)
     *
     * InsertTrigger              (string objName,                int[16] *trafoMat)
     * InsertTriggerScript        (string objName,                int[16] *trafoMat)
     * InsertTriggerChangeLevel   (string objName,                int[16] *trafoMat)
     * InsertMover                (string objName, string visual, int[16] *trafoMat)
     */
    func int InsertTrigger(var string nm, var int trf) {
        return InsertObject("zCTrigger", nm, "", trf, 0);
    };
    func int InsertTriggerPos(var string nm, var int pos, var int dir) {
        return InsertObjectPos("zCTrigger", nm, "", pos, dir, 0);
    };
    func int InsertTriggerScript(var string nm, var int trf) {
        return InsertObject("oCTriggerScript", nm, "", trf, 0);
    };
    func int InsertTriggerScriptPos(var string nm, var int pos, var int dir) {
        return InsertObjectPos("oCTriggerScript", nm, "", pos, dir, 0);
    };
    func int InsertTriggerChangeLevel(var string nm, var int trf) {
        return InsertObject("oCTriggerChangeLevel", nm, "", trf, 0);
    };
    func int InsertTriggerChangeLevelPos(var string nm, var int pos, var int dir) {
        return InsertObjectPos("oCTriggerChangeLevel", nm, "", pos, dir, 0);
    };
    func int InsertMover(var string nm, var string vis, var int trf) {
        return InsertObject("zCMover", nm, vis, trf, 0);
    };
    func int InsertMoverPos(var string nm, var string vis, var int pos, var int dir) {
        return InsertObjectPos("zCMover", nm, vis, pos, dir, 0);
    };
    
    
    /*
     * oCItem functions:
     *
     * InsertItemWP (string itemInstance, int amount, string waypoint)
     * InsertItemPos(string itemInstance, int amount, int* pos, int* dir)
     * InsertItem   (string itemInstance, int amount, int* trafoMat)
     */
    func int InsertItemWP(var string itmInst, var int amount, var string wp) {
        var int symbIdx; symbIdx = MEM_GetSymbolIndex(itmInst);
        Wld_InsertItem(symbIdx, wp);
    
        var zCTree newTreeNode; newTreeNode = _^(MEM_World.globalVobTree_firstChild);
        var int itmPtr; itmPtr = newTreeNode.data;
    
        if (!Hlp_Is_oCItem(itmPtr)) {
            // Item effect is spawned last
            newTreeNode = _^ (newTreeNode.next);
            itmPtr = newTreeNode.data;
            if (!Hlp_Is_oCItem(itmPtr)) {
                MEM_Warn(ConcatStrings("Could not insert item: ", itmInst));
                return 0;
            };
        };
    
        var oCItem itm; itm = _^(itmPtr);
        if (itm.instanz != symbIdx) {
            MEM_Warn(ConcatStrings("Could not insert item: ", itmInst));
            return 0;
        };
    
        itm.amount = amount;
    
        return itmPtr;
    };
    func int InsertItem(var string itmInst, var int amount, var int trf) {
        var int itmPtr; itmPtr = InsertItemWP(itmInst, amount, MEM_FARFARAWAY);
    
        AlignVobAt(itmPtr, trf);
    
        return itmPtr;
    };
    func int InsertItemPos(var string itmInst, var int amount, var int pos, var int dir) {
        var int trafo[16];
        NewTrafo(_@(trafo));
        PosDirToTrf(pos, dir, _@(trafo));
    
        var int itmPtr; itmPtr = InsertItem(itmInst, amount, _@(trafo));
        SetVobToFloor(itmPtr);
    
        return itmPtr;
    };
    
    
    /*
     * PileOf functions:
     *
     * InsertPileOf     (string class, string objName, string visual, int[16]* trafoMat, int amount, int cm2, int rotate)
     * InsertPileOfVobs (              string objName, string visual, int[16]* trafoMat, int amount, int cm2, int rotate)
     * InsertPileOfItems(              string itmInst,                int[16]* trafoMat, int amount, int cm2, int rotate)
     */
    func void InsertPileOf(var string cl, var string nm, var string vis, var int trf, var int am, var int cm, var int rot) {
        const int sizeof_zMAT4 = 64; // Same for G1 and G2
    
        repeat(i, am); var int i;
            // Get new trafo from the original
            var int trafo[16];
            MEM_CopyBytes(trf, _@(trafo), sizeof_zMAT4);
    
            // Increase height for better piling (will be "dropped")
            trafo[ 7] = addf(trafo[ 7], mkf(200));
    
            // Shift position (will be distributed over a square not a circle)
            trafo[ 3] = addf(trafo[ 3], mkf(Hlp_Random(cm*2)-cm));
            trafo[11] = addf(trafo[11], mkf(Hlp_Random(cm*2)-cm));
    
            // Rotate
            if (rot) {
                RotateTrafoY(_@(trafo), mkf(Hlp_Random(360)));
            };
    
            // Create vob or item
            var int vobPtr;
            if (Hlp_StrCmp(cl, "oCItem")) {
                vobPtr = InsertItem(nm, 1, _@(trafo));
            } else {
                var string name; name = ConcatStrings(nm, IntToString(i+1));
                vobPtr = InsertObject(cl, name, vis, _@(trafo), 0);
            };
            SetVobToFloor(vobPtr);
        end;
    };
    func void InsertPileOfVobs(var string nm, var string vis, var int trf, var int am, var int cm, var int rot) {
        InsertPileOf("zCVob", nm, vis, trf, am, cm, rot);
    };
    func void InsertPileOfItems(var string itmInst, var int trf, var int am, var int cm, var int rot) {
        InsertPileOf("oCItem", itmInst, "", trf, am, cm, rot);
    };
    
    
    
    /*
     * Post-insert functions
     */
    
    
    /*
     * Set the focus name of a mob (see Text.d)
     */
    func int SetMobName(var int mobPtr, var string symbolicFocusName) {
        if (Hlp_Is_oCMob(mobPtr)) {
            var oCMob mob; mob = _^(mobPtr);
            mob.name           = symbolicFocusName;
            mob.focusNameIndex = MEM_GetSymbolIndex(symbolicFocusName);
        };
        return mobPtr;
    };
    
    
    /*
     * Set mob owner. Thanks to Bisasam!
     */
    func void SetMobOwner(var int mobPtr, var string owner, var string ownerGuild) {
        if (!Hlp_Is_oCMob(mobPtr)) {
            MEM_Warn("Not a oCMob!");
            return;
        };
    
        var oCMob mob; mob = _^(mobPtr);
        mob.ownerStr       = owner;
        mob.ownerGuildStr  = ownerGuild;
    };
    
    
    /*
     * Set some miscellaneous properties of mobs
     */
    func void SetMobMisc(var int mobPtr, var string triggerTarget, var string useWithItem, var string onStateFuncName) {
        if (!Hlp_Is_oCMobInter(mobPtr)) {
            MEM_Warn("Not a oCMobInter!");
            return;
        };
    
        var oCMobInter mob; mob = _^(mobPtr);
        mob.triggerTarget   = triggerTarget;
        mob.useWithItem     = useWithItem;
        mob.onStateFuncName = onStateFuncName;
    };
    
    
    /*
     * Lock a oCMobLockable
     */
    func void LockMobLockable(var int mobPtr, var string keyInstance, var string pickLockStr, var int locked) {
        if (!Hlp_Is_oCMobLockable(mobPtr)) {
            MEM_Warn("Not a oCMobLocable!");
            return;
        };
    
        var oCMobLockable mob; mob = _^(mobPtr);
        mob.keyInstance = keyInstance;
        mob.pickLockStr = pickLockStr;
    
        if (locked) {
            mob.bitfield = mob.bitfield | oCMobLockable_bitfield_locked;
        };
    };
    
    
    /*
     * Create contents of oCMobContainers by string
     */
    func void FillMobContainer(var int mobPtr, var string contents) {
        if (!Hlp_Is_oCMobContainer(mobPtr)) {
            MEM_Warn("Not a oCMobContainer!");
            return;
        };
    
        const int oCMobContainer__CreateContents_G1 = 6832208; //0x684050
        const int oCMobContainer__CreateContents_G2 = 7496080; //0x726190
    
        var int contentsPtr; contentsPtr = _@s(contents);
    
        const int call = 0;
        if (CALL_Begin(call)) {
            CALL_PtrParam(_@(contentsPtr));
            CALL__thiscall(_@(mobPtr), MEMINT_SwitchG1G2(oCMobContainer__CreateContents_G1,
                                                         oCMobContainer__CreateContents_G2));
            call = CALL_End();
        };
    };
    Geändert von mud-freak (24.11.2021 um 09:33 Uhr)

  14. Beiträge anzeigen #34 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Hier ist noch ein Tipp zur Benutzung. Ich habe ein kleines Skript geschrieben, das die Trafo-Matrix vom Helden, dem Fokusvob oder einem Vob nach Name formatiert auf dem zSpy ausgibt. Das ganz sehr nützlich sein, um schnell an vernünftige Koordinaten um Einfügen von Vobs heranzukommen.

    Spoiler:(zum lesen bitte Text markieren)
    Code:
    /*
     * Print the current trafo-matrix to zSpy
     */
    
    
    /*
     * Send readable trafo of vob to zSpy
     */
    func void printTrafo(var int vobPtr) {
        if (!vobPtr) {
            return;
        };
    
        var zCVob vob; vob = _^(vobPtr);
        MEM_Info(ConcatStrings("Print trafo of ", vob._zCObject_objectname));
    
        var int s; s = SB_New();
        repeat(i, 4); var int i;
            SB("    ");
            repeat(j, 4); var int j;
                SBf(MEM_ReadStatArr(_@(vob.trafoObjToWorld), j+i*4));
                if (j+i*4 != 15) {
                    SB(", ");
                };
            end;
            MEM_Info(SB_ToString());
            SB_Clear();
        end;
        SB_Destroy();
    };
    
    
    /*
     * Console command for hero trafo
     */
    func string CC_PrintTrafoHero(var string _) {
        printTrafo(_@(hero));
        return "Trafo sent to zSpy";
    };
    func void CC_PrintTrafoHeroInit() {
        CC_Register(CC_PrintTrafoHero, "print trafo hero", "Send the trafo coordinates of the hero to the zSpy");
    };
    
    
    /*
     * Console command for focus trafo
     */
    func string CC_PrintTrafoFocus(var string _) {
        var oCNpc her; her = Hlp_GetNpc(hero);
        printTrafo(her.focus_vob);
        return "Trafo sent to zSpy";
    };
    func void CC_PrintTrafoFocusInit() {
        CC_Register(CC_PrintTrafoFocus, "print trafo focus", "Send the trafo coordinates of the focus vob to the zSpy");
    };
    
    
    /*
     * Console command for trafo by vob name
     */
    func string CC_PrintTrafoVobByName(var string vobname) {
        var int vobPtr; vobPtr = MEM_SearchVobByName(vobName);
        if (!vobPtr) {
            return "Vob not found";
        };
    
        printTrafo(vobPtr);
        return "Trafo sent to zSpy";
    };
    func void CC_PrintTrafoVobByNameInit() {
        CC_Register(CC_PrintTrafoVobByName, "print trafo vob ", "Send the trafo coordinates by vob name to the zSpy");
    };


    Initialisieren der Konsolenbefehle in der der Init_Global mit:
    Code:
    CC_PrintTrafoHeroInit();
    CC_PrintTrafoFocusInit();
    CC_PrintTrafoVobByNameInit();


    Aufrufen der Funktionen von der Konsole jeweils mit:
    Code:
    print trafo hero
    print trafo focus
    print trafo vob



    Man kann eine solche Trafo-Matrix dann einfach kopieren und ganz leicht so erstellen und an Insert-Funktionen "weitergeben":
    Code:
    const float trafo[16] = {
        -0.225040, 0.000001, -0.974349,  9456.563477,
        -0.000001, 1.000000,  0.000002,   589.735718,
         0.974349, 0.000000, -0.225040, -4588.891602,
         0.000000, 0.000000,  0.000000,     1.000000
    };
    
    var int ptr;
    ptr = InsertVob("LMS_ENTRANCE_DOOR_02", "DOOR_WOODEN.MDS", _@f(trafo));
    Geändert von mud-freak (15.02.2019 um 13:23 Uhr)

  15. Beiträge anzeigen #35 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Mir ist aufgefallen, dass das InsertAnything-Skript fehlerhaft ist. Unter gewissen Umständen gehen Vobs nach Speichern und Laden verloren.
    Kannst du ausführen was für Umstände das sind?

    Beim Wechsel zum neuen Skript verliert man leider einige der nützlichen Hilfsfunktionen die im alten Skript drin sind, im Scriptbin einfach ersetzten ist daher eventuell nicht ideal.

  16. Beiträge anzeigen #36 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Cryp18Struct Beitrag anzeigen
    Kannst du ausführen was für Umstände das sind?
    Nicht genau. Bei mir kam es bei Verwendung dazu, dass Vobs, die ich mit InsertVobAt eingefügt hatte, nach dem Spielladen mit Fehlermeldungen nicht mehr da waren. Ich vermute stark, dass es mit der Allokation von deren Speicher zusammenhing.
    Das war seitens des Skripts übernommen und wird im neuen Skript jetzt von Gothic selbst verwaltet.

    Zitat Zitat von Cryp18Struct Beitrag anzeigen
    Beim Wechsel zum neuen Skript verliert man leider einige der nützlichen Hilfsfunktionen die im alten Skript drin sind, im Scriptbin einfach ersetzten ist daher eventuell nicht ideal.
    Rückwärtskompatibilität habe ich aufgegeben, nachdem ich bemerkt habe, dass mehrere der Funktionen fehlerhaft waren (z.B. LevelVec) und ich wollte die Anzahl der Funktionsparameter verringern, sodass ich irgendwann mehr oder weniger von null gestartet bin, wodurch einige Funktionen einfach nicht mehr notwendig waren.
    Gibt es bestimmte Funktionen die du vermisst? Sicher kann ich die dort wieder irgendwie einbauen.

  17. Beiträge anzeigen #37 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Gibt es bestimmte Funktionen die du vermisst? Sicher kann ich die dort wieder irgendwie einbauen.
    Unter der Annahme das es keine Probleme gibt(und mir sind keine aufgefallen):
    RemoveoCVobSafe/RemovezCVobSafe sind sehr praktisch. Sollte jeder haben. Und passt auch thematisch: wenn man dynamisch Objekte erzeugt kommt es bestimmt auch vor das man sie löschen möchte.

    GetGroundAtTrf/GetGroundAtPos
    AlignWPToFloor
    GetTrafoFromWP

    Hier bin ich mir jetzt nicht sicher ob das Teil des Pakets war oder ob ich das da nur reinkopiert hatte:
    PileOfVobs/PileOfItems

  18. Beiträge anzeigen #38 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Cryp18Struct Beitrag anzeigen
    Unter der Annahme das es keine Probleme gibt(und mir sind keine aufgefallen):
    RemoveoCVobSafe/RemovezCVobSafe sind sehr praktisch. Sollte jeder haben. Und passt auch thematisch: wenn man dynamisch Objekte erzeugt kommt es bestimmt auch vor das man sie löschen möchte.
    Vobs löschen ging schon die ganze Zeit mit den "Basis"-Skripten von Ikarus. Dort gibt es eine Funktion MEM_DeleteVob. Das wusste ich zu dem Zeitpunkt nicht und hatte sie selbst noch einmal erstellt.

    Die anderen Funktionen, die du erwähnt hast, kann ich wieder (etwas verbessert) aufnehmen. Das schaue ich mir dann in den nächsten Tagen an. Die PileOf*-Funktionen waren eine Spielerei, die im Grunde nur x Items/Vobs mit zufälligem Radius y um eine Position z einfügen. Kann ich aber auch wieder mit reinnehmen.

  19. Beiträge anzeigen #39 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Ich habe das Skript oben (u.a.) mit folgenden Funktionen ergänzt.

    Code:
    func int  GetGroundLvlPos(int posPtr)
    func int  GetGroundLvl   (int trafoPtr)
    
    func void GetTrafoFromWP(string waypoint, int trafoPtr)
    func void SetWPToFloor  (int wpPtr)
    
    func int  InsertItem(string scriptInst, int amount, int trafoPtr)
    
    func void InsertPileOf     (string class, string objName, string visual, int trafoPtr, int amount, int cm2, int rotate)
    func void InsertPileOfVobs (              string objName, string visual, int trafoPtr, int amount, int cm2, int rotate)
    func void InsertPileOfItems(              string scriptInst,             int trafoPtr, int amount, int cm2, int rotate)

    EDIT: Ich habe die Funktion SetVobToFloor verschönert; Vobs schliessen jetzt tatsächlich am Boden an und schweben nicht mehr 4cm darüber.
    Geändert von mud-freak (22.01.2018 um 17:40 Uhr)

  20. Beiträge anzeigen #40 Zitieren
    Knight
    Registriert seit
    Aug 2009
    Ort
    Hessen
    Beiträge
    1.487
     
    Cryp18Struct ist offline
    Danke mud-freak.
    Wäre ja auch Schade wenn die Funktionen einfach verschwinden.

    Was RemoveoCVobSafe angeht: da hat man per Parameter die Möglichkeit alle Kinder gleich mit zu löschen im Gegensatz zu MEM_DeleteVob.

Seite 2 von 10 « Erste 1234569 ... 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