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

 

Ergebnis 1 bis 6 von 6
  1. Beiträge anzeigen #1 Zitieren
    Lehrling Avatar von LOGX
    Registriert seit
    Sep 2012
    Beiträge
    27
     
    LOGX ist offline

    [LeGo] Zufallsgenerierte NPCs

    Hallo zusammen,

    Ich benutze LeGo 2.5 für Gothic 1, um bei Spielstart meiner Mod NPCs per Zufallsgenerator zu erstellen. Die NPC-Instanzen sind dabei ganz normal in Skriptdateien definiert. Anstelle fixer Werte für Aussehen, Attribute und Items werden aber Funktionen aufgerufen, welche diese Sachen zufällig setzen.
    Das Spiel startet normal und alle NPCs werden ordentlich erstellt. Auch wenn ich die NPCs per Konsole einfüge, werden die Funktionen korrekt aufgerufen und jeweils neue Werte ausgewürfelt.
    Mein Problem ist das Speichern und Laden des Spielstands. Solange das Spiel läuft, kann ich problemlos Speichern und Laden. Nach einem Spielneustart stürzt der Ladevorgang aber immer mit folgender Access Violation ab:

    Code:
    ======================================= UNHANDLED EXCEPTION OCCURED ======================================================
    ======================================= CRASH INFOS: =====================================================================
    GOTHIC 1.08k_mod, Parser Version: 50
    User:  og,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    Startup Options:-game:nyx.ini -zreparse -zlog:5,s -vdfs:physicalfirst
    =============================================== CALLSTACK : ==============================================================
    0023:006E8808 (0x000002BA 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+520 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1369+12 byte(s)
    0023:006E91A4 (0x000002BA 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x000003F8 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x0000078F 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x000009E1 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x00000A8F 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x0000126F 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x0000258D 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x0000930F 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x0000CC30 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x00011312 0x008DCE50 0x00000000 0x008DCE08) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x00072B25 0x008DCE08 0x154C05F8 0x000033AF) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E91A4 (0x00072B4B 0x1BD9EAA8 0x1BD9E780 0x0068CB31) GothicMod.exe, zCParser::DoStack()+2980 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1415
    0023:006E9C37 (0x0007513B 0x1BD9E780 0x007DDF34 0x144A64D8) GothicMod.exe, zCParser::CreateInstance()+87 byte(s), D:\dev\gothic\current_work\ZenGin\_Ulf\zParser.cpp, line 1583+12 byte(s)
    0023:0068CB31 (0x000033AF 0x00000001 0x00004F73 0x144A64D8) GothicMod.exe, oCNpc::InitByScript()+753 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oNPC.cpp, line 1566
    0023:006A3284 (0x144A64D8 0x144A64D8 0x007D06E8 0x00000019) GothicMod.exe, oCNpc::Unarchive()+164 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oNPC.cpp, line 9002
    0023:00516188 (0x00000000 0x144A64D8 0x007D06E8 0x00000000) GothicMod.exe, zCArchiverGeneric::ReadObject()+1992 byte(s), D:\dev\gothic\current_work\ZenGin\_Dieter\zArchiverGeneric.cpp, line 1274
    0023:006D681B (0x0000002D 0x144CD020 0x144A64D8 0x00000001) GothicMod.exe, oCWorld::Unarchive()+283 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oWorld.cpp, line 390
    0023:00516188 (0x144CD020 0x005F8B22 0x00000001 0x0126F7E4) GothicMod.exe, zCArchiverGeneric::ReadObject()+1992 byte(s), D:\dev\gothic\current_work\ZenGin\_Dieter\zArchiverGeneric.cpp, line 1274
    0023:005161BE (0x00000001 0x0126F7E4 0x144CD020 0x00000000) GothicMod.exe, zCArchiverGeneric::ReadObject()+14 byte(s), D:\dev\gothic\current_work\ZenGin\_Dieter\zArchiverGeneric.cpp, line 1282
    0023:005F8B22 (0x00000001 0x00000001 0x14547AA8 0x00000000) GothicMod.exe, zCWorld::LoadWorld()+290 byte(s), D:\dev\gothic\current_work\ZenGin\_Dieter\zWorld.cpp, line 2343
    0023:006D6C4D (0x0126F7E0 0x00000001 0x0126FA20 0x14547AA8) GothicMod.exe, oCWorld::LoadWorld()+669 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oWorld.cpp, line 447+13 byte(s)
    0023:0063FA4D (0x0126FA44 0x007D06E8 0x150F8CF0 0x14547AA8) GothicMod.exe, oCGame::LoadWorldDyn()+589 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oGame.cpp, line 2972
    0023:0063E814 (0xFFFFFFFF 0x0126FA1C 0x0126FCB4 0x0A1EF6A0) GothicMod.exe, oCGame::LoadWorld()+740 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oGame.cpp, line 2715
    0023:0063C6BB (0xFFFFFFFF 0x00000001 0x0082C4E6 0x0126FCB4) GothicMod.exe, oCGame::LoadSavegame()+1051 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\oGame.cpp, line 2113
    0023:00428D09 (0x00000001 0x0126FC38 0x00000000 0x0126FCB4) GothicMod.exe, CGameManager::Read_Savegame()+441 byte(s), D:\dev\gothic\current_work\Gothic\_Bert\oGameManager.cpp, line 1449
    0023:0042844F (0x00000000 0x0077A8D8 0x014F36F8 0x0126FEC4) GothicMod.exe, CGameManager::Menu()+2655 byte(s), D:\dev\gothic\current_work\Gothic\_Bert\oGameManager.cpp, line 1355
    0023:00424EBE (0x007D1078 0x7615DC7C 0x00030854 0x14547AA8) GothicMod.exe, CGameManager::Run()+974 byte(s), D:\dev\gothic\current_work\Gothic\_Bert\oGameManager.cpp, line 683
    0023:006D867B (0x00323000 0x0000002C 0x00000003 0x00000001) GothicMod.exe, MainProg()+75 byte(s), D:\dev\gothic\current_work\Gothic\_Ulf\Phoenix.cpp, line 115
    0023:004F4326 (0x00400000 0x00000000 0x014F36F8 0x00000001) GothicMod.exe, HandledWinMain()+966 byte(s), D:\dev\gothic\current_work\ZenGin\_Carsten\zWin32.cpp, line 772
    0023:004F3E90 (0x00400000 0x00000000 0x014F36F8 0x00000001) GothicMod.exe, WinMain()+128 byte(s), D:\dev\gothic\current_work\ZenGin\_Carsten\zWin32.cpp, line 684+21 byte(s)
    0023:0077A9B8 (0xA4458DD0 0xE815FF50 0xE8007D01 0x000072DE) GothicMod.exe, WinMainCRTStartup()+224 byte(s)
    0023:7589FFFF (0x00000000 0x00000000 0x00000000 0x00000000) OLEAUT32.dll, VarSub()+73391 byte(s)
    Ich vermute, dass beim Speichern irgendeine Information verloren geht, die beim Wiederherstellen der NPCs benötigt, aber nicht gefunden wird.
    Ein Beispiel für ein NPC-Skript ist hier:
    Code:
    instance MIL_2103_Burgtorwache (Npc_Default)
    {
     //------------- random generic NPC creation -------------
     D_SetGenericMilitia(self,
      2103,
      NAME_Militia,
      NPC_TIER_VETERAN,
      NPC_OCC_MELEE);
      
     //------------- daily routine -------------
     daily_routine = Rtn_Start_2103;
    };
    
    func void Rtn_Start_2103()
    {
     TA_GuardPassage(06,00,21,00,"OCC_GATE_LEFT_GUARD");
     TA_GuardPassage(21,00,06,00,"OCC_GATE_LEFT_GUARD");
    };
    Und meine verwendeten Funktionen (nicht alle, aber die meisten) sind hier zu finden:
    Code:
    //-------- generic NPC tiers --------
    const int NPC_TIER_TRAINEE  = 1;
    const int NPC_TIER_VETERAN  = 2;
    
    //-------- generic NPC occupations --------
    const int NPC_OCC_MELEE  = 1;
    const int NPC_OCC_RANGED  = 2;
    const int NPC_OCC_GUARD  = 3;
    
    //-------- generic NPC head textures --------
    func int _D_Npc_Headtex_C1_All_MIL()
    {
     var int texList; texList = List_Create(6);
     List_Add(texList, 8);
     List_Add(texList, 12);
     List_Add(texList, 13);
     List_Add(texList, 16);
     List_Add(texList, 17);
     List_Add(texList, 18);
     List_Add(texList, 35);
     List_Add(texList, 36);
     List_Add(texList, 46);
     List_Add(texList, 47);
     List_Add(texList, 48);
     List_Add(texList, 49);
     List_Add(texList, 50);
     List_Add(texList, 51);
     List_Add(texList, 52);
     List_Add(texList, 54);
     List_Add(texList, 55);
     List_Add(texList, 56);
     List_Add(texList, 57);
     return texList;
    };
    func int _D_Npc_Headtex_C3_All_MIL()
    {
     var int texList; texList = List_Create(1);
     List_Add(texList, 2);
     List_Add(texList, 4);
     List_Add(texList, 5);
     List_Add(texList, 10);
     return texList;
    };
    
    //-------- generic NPC voice assignments --------
    func int _D_Npc_Voice_MIL_Trainee()
    {
     var int voiceList; voiceList = List_Create(3);
     List_Add(voiceList, 6);
     List_Add(voiceList, 7);
     return voiceList;
    };
    func int _D_Npc_Voice_MIL_Veteran()
    {
     var int voiceList; voiceList = List_Create(7);
     List_Add(voiceList, 8);
     return voiceList;
    };
    
    //-------- generic NPC abilities --------
    const int NPC_LVL_MIL_TRAINEE_BASE  = 8;
    const int NPC_LVL_MIL_TRAINEE_RANGE = 9;
    const int NPC_LVL_MIL_VETERAN_BASE  = 20;
    const int NPC_LVL_MIL_VETERAN_RANGE = 4;
    
    
    //-------- generic militia presets --------
    /*
    body mesh: "hum_body_Naked0"
    body tex:
     - C0: 0
     - C1: 0
     - C2: 0
     - C3: 0
    skin color: 0 - 3
    head MMS:
     - bald
     - fighter
     - std_pony
    head tex:
     - C0: 2b! | 3b! | 5 | 9 | 11 | 12b! | 13b! | 
       16 | 18b! | 20
     - C1: 0 | 1 | 2 | 3 | 5 | 6 | 7 | 8 | 12 | 
       13 | 14b! | 15b! | 16 | 17 | 18 | 
       19 | 35 | 36 | 46 | 47 | 48 | 49 | 
       50 | 51 | 52 | 53b! | 54 | 55 | 56 | 
       57 | 58 | 94 | 97b! | 98 | 101b! | 
       106 | 107 | 112
     - C2: 10 | 12 | 
     - C3: 1 | 2 | 4 | 5 | 10 
    teeth tex: 0 - 2
    level: TRAINEE
    - lvl: 8 - 16
    - voices: 3 (depressive) | 6 (brawler) | 7 (aggressive)
    - armor: mil_armor_l
    - fatness: 0 - 1
    level: VETERAN
    - voices: 7 (aggressive) | 8 (elite)
    - lvl: 20 - 23
    - armor: mil_armor_m
    - fatness: 0 - 2
    occupation: MELEE
    - equip: NPC_EQUIP_MIL_LIGHT | NPC_EQUIP_MIL_HEAVY
    occupation: RANGED
    - equip: NPC_EQUIP_MIL_RANGED
    occupation: GUARD
    - equip: NPC_EQUIP_MIL_GUARD 
    */
    func void D_SetGenericMilitia(
     var C_NPC npc,
     var int npc_id, 
     var string npc_name,
     var int NPC_TIER,
     var int NPC_OCC)
    { 
     //-------- random selector --------
     var int rnd_select;
     
     //-------- primary data --------
     D_SetNpcPrimary(npc, 
      npc_id,     // ID
      npc_name,    // name
      NPCTYPE_AMBIENT,   // npctype
      GIL_MIL,     // guild
      AIV_RNK_MIL,    // rank within guild
      0,       // flags
      false);     // aiv_important 
      
     //-------- abilities --------
     var int level;
     if NPC_TIER == NPC_TIER_TRAINEE
      { level = NPC_LVL_MIL_TRAINEE_BASE + Hlp_Random(NPC_LVL_MIL_TRAINEE_RANGE); }
     else if NPC_TIER == NPC_TIER_VETERAN
      { level = NPC_LVL_MIL_VETERAN_BASE + Hlp_Random(NPC_LVL_MIL_VETERAN_RANGE); }
     else
      { level = 10; };
     
     D_SetNpcAbilities(npc, 
      level,     // level
      NPC_ARCH_SOLDIER);  // npc_archetype  
     
     //-------- appearance --------
     var int voice;
     var int voiceList;
     if NPC_TIER == NPC_TIER_TRAINEE
     {
      voiceList = _D_Npc_Voice_MIL_Trainee();
      rnd_select = Hlp_Random(List_Length(voiceList));
      voice = List_Get(voiceList, rnd_select);
      List_Destroy(voiceList);
     }
     else if NPC_TIER == NPC_TIER_VETERAN
     {
      voiceList = _D_Npc_Voice_MIL_Veteran();
      rnd_select = Hlp_Random(List_Length(voiceList));
      voice = List_Get(voiceList, rnd_select);
      List_Destroy(voiceList);
     }
     else { voice = 7; };
     
     var int skin_color;
     rnd_select = Hlp_Random(100);
     if rnd_select < 70 { skin_color = 1; }
     else { skin_color = 3; };
     
     var int head_tex;
     var int texList;
     if skin_color == 1 { 
      texList = _D_Npc_Headtex_C1_All_MIL();
      rnd_select = Hlp_Random(List_Length(texList)); 
      head_tex = List_Get(texList, rnd_select);
      List_Destroy(texList);
     }
     else { 
      texList = _D_Npc_Headtex_C3_All_MIL();
      rnd_select = Hlp_Random(List_Length(texList)); 
      head_tex = List_Get(texList, rnd_select);
      List_Destroy(texList);
     };
     
     var string head_mms;
     rnd_select = Hlp_Random(100);
     if rnd_select < 60 { head_mms = "Hum_Head_Fighter"; }
     else { head_mms = "Hum_Head_Bald"; };
     
     var int teeth_tex;
     teeth_tex = Hlp_Random(2); // TODO: als Konstante?
     
     var int armor;
     if NPC_TIER == NPC_TIER_TRAINEE { armor = GRD_ARMOR_L; } // TODO: mit korrekter Rüstung ersetzen!
     else if NPC_TIER == NPC_TIER_VETERAN { armor = MIL_ARMOR_M; }
     else { armor = GRD_ARMOR_L; }; // TODO: mit korrekter Rüstung ersetzen!
     
     var float fatness; // TODO: als Konstante?
     // if NPC_TIER == NPC_TIER_TRAINEE { fatness = Hlp_Random(2); }
     // else if NPC_TIER == NPC_TIER_VETERAN { fatness = Hlp_Random(3); }
     // else { fatness = 0.0; };
     fatness = 0.0;
     
     D_SetNpcAppearance(npc, 
      voice,     // voice
      "humans.mds",    // visual
      "hum_body_Naked0",   // body mesh
      0,       // body tex
      skin_color,   // skin color
      head_mms,     // head MMS
      head_tex,    // head tex
      teeth_tex,   // teeth tex
      armor,     // armor
      "humans_militia.mds", // overlay MDS
      fatness);    // model fatness
     
     
     //-------- equipment --------
     var int equip_preset;
     if NPC_OCC == NPC_OCC_MELEE
     {
      if NPC_TIER == NPC_TIER_TRAINEE { equip_preset = NPC_EQUIP_MIL_LIGHT; }
      else if NPC_TIER == NPC_TIER_VETERAN { equip_preset = NPC_EQUIP_MIL_HEAVY; }
      else { equip_preset = NPC_EQUIP_MIL_LIGHT; };
     }
     else if NPC_OCC == NPC_OCC_RANGED
     {
      equip_preset = NPC_EQUIP_MIL_RANGED;
     }
     else if NPC_OCC == NPC_OCC_GUARD
     {
      equip_preset = NPC_EQUIP_MIL_GUARD;
     }
     else
     {
      equip_preset = NPC_EQUIP_MIL_LIGHT;
     };
     
     D_EquipNpc(npc,
      equip_preset);   // equipment preset
      
      
     //-------- inventory --------
     D_GiveNpcFactionInventory(npc, 
      NPC_INV_MIL);   // inventory preset 
     
    };
    Ich initialisiere LeGo mittels LeGo_Init(LeGo_All); in der Funktion FUNC VOID INIT_WORLD() in der Startup.d
    Kann mir jemand bei diesem Problem weiterhelfen? Oder vielleicht einen Tipp geben, wie man auf einfachere Weise einen Zufallsgenerator für NPCs erstellen kann?

    Vielen Dank schon mal!
    logx

  2. Beiträge anzeigen #2 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Da grätscht dir die interne Architektur von Gothic leider mitten in deine Pläne. Wenn Gothic einen Spielstand lädt werden NPCs (und Items) aus dem Spielstand geladen (soweit alles offensichtlich). Um Speicherplatz zu sparen werden aber nur die wichtigsten Sachen überhaupt im Spielstand gespeichert - beim Rest ging man davon aus, dass er sich während der Laufzeit sowieso nicht ändert. D.h. um NPCs/Items zu laden wird effektiv ein neuer NPC erstellt, mit der Instanz-Funktion initialisiert und dann werden ein paar wenige Werte aus dem Spielstand geladen (so Kram wie Attribute, Erfahrung, ... nehme ich an). Das passiert alles bevor irgendeine eigentliche Scriptfunktion (z.B. INIT_World(), INIT_Global(), ...) ausgeführt wird. Dementsprechend ist LeGo zu diesem Zeitpunkt noch nicht initialisiert und es geht kaputt.

    Du kannst die Variable _LeGo_Init überprüfen, um herauszufinden, ob LeGo bereits initialisiert wurde. Genau genommen ist es eine Konstante, aber das sind Details


    Wenn ich mir deinen Code so anschaue sieht es allerdings so aus, als ob du LeGo gar nicht brauchen würdest (Ikarus reicht um dynamisch auf statische Gothic-Arrays zugreifen zu können). Im Gegensatz zu LeGo kann man Ikarus immer und überall einfach initialisieren, wenn man es braucht.


    Allerdings (und das ist ein recht großes allerdings) funktioniert das sowieso nicht so, wie du möchtest (nehme ich an). Selbst wenn LeGo funktionieren würde zu dem Zeitpunkt würden deine NPCs bei jedem Laden neu ausgewürfelt, oder?

  3. Beiträge anzeigen #3 Zitieren
    Lehrling Avatar von LOGX
    Registriert seit
    Sep 2012
    Beiträge
    27
     
    LOGX ist offline
    Vielen Dank für die Antwort, Lehona! So etwas in der Art habe ich mir schon gedacht, als ich die Funktion oCNpc::InitByScript() im Stacktrace gesehen habe.
    Ich habe deinen Vorschlag mit Ikarus noch nicht ausprobiert. Könntest du dazu noch etwas mehr erzählen? Wie initialisiere ich Ikarus denn genau? Im LeGo-Wiki (http://lego.worldofplayers.de/) habe ich dazu leider nichts gefunden.
    Dennoch würde ich die NPCs gerne nur einmal beim Spielstart auswürfeln und nicht bei jedem Neuladen. Mit Attributen und Items funktioniert das auch ganz gut (das wird ja auch, wie du gesagt hast, mit gespeichert). Nur die Visuals (Texturen, Meshes, evtl. auch Stimmen) machen Probleme. PermMem (http://lego.worldofplayers.de/?PermMem) habe ich mir noch nicht genau angesehen. Könnte man damit evtl. die fehlenden Sachen persistieren? Doch selbst wenn man die zufälligen Visuals mit speichert, müsste man dann immer noch beim Laden oCNpc::InitByScript() mit einer eigenen Routine ersetzen, oder? Doch das würde wahrscheinlich einigen Aufwand nach sich ziehen, wenn es überhaupt realisierbar ist.
    Könnte man das Ganze evtl. mit einem eleganten Workaround lösen? Hat das überhaupt schonmal jemand in einer Mod gemacht?Wenn nicht wird es wohl doch auf statische Templates hinauslaufen.

  4. Beiträge anzeigen #4 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Zitat Zitat von LOGX Beitrag anzeigen
    Vielen Dank für die Antwort, Lehona! So etwas in der Art habe ich mir schon gedacht, als ich die Funktion oCNpc::InitByScript() im Stacktrace gesehen habe.
    Ich habe deinen Vorschlag mit Ikarus noch nicht ausprobiert. Könntest du dazu noch etwas mehr erzählen? Wie initialisiere ich Ikarus denn genau? Im LeGo-Wiki (http://lego.worldofplayers.de/) habe ich dazu leider nichts gefunden.
    Dennoch würde ich die NPCs gerne nur einmal beim Spielstart auswürfeln und nicht bei jedem Neuladen. Mit Attributen und Items funktioniert das auch ganz gut (das wird ja auch, wie du gesagt hast, mit gespeichert). Nur die Visuals (Texturen, Meshes, evtl. auch Stimmen) machen Probleme. PermMem (http://lego.worldofplayers.de/?PermMem) habe ich mir noch nicht genau angesehen. Könnte man damit evtl. die fehlenden Sachen persistieren? Doch selbst wenn man die zufälligen Visuals mit speichert, müsste man dann immer noch beim Laden oCNpc::InitByScript() mit einer eigenen Routine ersetzen, oder? Doch das würde wahrscheinlich einigen Aufwand nach sich ziehen, wenn es überhaupt realisierbar ist.
    Könnte man das Ganze evtl. mit einem eleganten Workaround lösen? Hat das überhaupt schonmal jemand in einer Mod gemacht?Wenn nicht wird es wohl doch auf statische Templates hinauslaufen.
    Ikarus initialisierst du einfach mit MEM_InitAll(). Ich spreche davon nur, weil du LeGo anscheinend nur für die Listen verwendest, die aber ja statisch sind - du könntest auch einfach ganz normale Daedalus-Arrays benutzen (const int MIL_faces[3] = { 1, 2, 3}; ). Mittels Ikarus kannst du dann einen dynamischen Index verwenden (d.h. zufällig etwas daraus auswählen).

    Auf die schnelle wüsste ich nicht, dass es das schon gibt. Um da eine Lösung zu finden müsste man auf jeden Fall einige Sachen testen... Vermutlich wirst du das Aussehen der NPCs erst kurz nach dem Laden ändern können? Keine Ahnung, wie man das am besten löst.
    Geändert von Lehona (02.12.2017 um 21:12 Uhr)

  5. Beiträge anzeigen #5 Zitieren
    Lehrling Avatar von LOGX
    Registriert seit
    Sep 2012
    Beiträge
    27
     
    LOGX ist offline
    Danke für die Antwort. In Anbetracht des Aufwands werde ich es wohl doch über statische Templates lösen. Aber die Sache mit dem dynamischen Index für statische Arrays gefällt mir. So wollte ich das ursprünglich auch machen, aber der Parser hat meine zufälligen Index-Nummern immer bemängelt. Kannst du mir noch ein kurzes Code-Snippet geben, wie das mit Ikarus aussehen würde? Das könnte ich auch an anderer Stelle noch sehr gut gebrauchen.

  6. Beiträge anzeigen #6 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Die Funktionen aus Ikarus dazu sind:

    Code:
    void MEM_WriteStatArr (var int array, var int offset, var int value)
    int MEM_ReadStatArr (var int array, var int offset)
    
    // z.B.
    var int myArray[4];
    MEM_WriteStatArr(myArray, Hlp_GetRandom(4), 0);

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