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

 

Results 1 to 9 of 9
  1. View Forum Posts #1 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline

    Compiled ZenGin Script Format

    Gibt es irgendwo öffentliche Dokumentationen, Beschreibungen oder Informationen zum Binärformat der Skripte und/oder der binären Skriptdaten aus Spielständen?
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  2. View Forum Posts #2 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    Aus den fehlenden Antworten schließe ich mal ein "Nein".

    Anbei eine erste Beschreibung des Binärformats.
    Fehler meinerseits sind nicht ausgeschlossen. Die Beschreibung der gespeicherten globalen Int-Variablen ohne Flags (const, ...) eines Spielstandes (SaveDat.sav) fehlt, da diese Datei einiges mehr enthält und die verschiedenen Archivtypen (ASCII, BinarySafe, ...) dokumentiert werden müssten.

    Fragen bitte in diesem Thread.
    Attached Files
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Last edited by NicoDE; 09.06.2009 at 13:55.

  3. View Forum Posts #3 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    Hier eine Liste der PCode-OpCodes, die in der ZenGin implementiert sind:
    Code:
    namespace Daedalus
    {
      enum Token : byte
      {
        Token_Addition                 = 0,   // PushInt(PopValue() + PopValue())
        Token_Subtraction              = 1,   // PushInt(PopValue() - PopValue())
        Token_Multiplication           = 2,   // PushInt(PopValue() * PopValue())
        Token_Division                 = 3,   // PushInt(PopValue() / PopValue())
        Token_Modulus                  = 4,   // PushInt(PopValue() % PopValue())
        Token_BitwiseInclusiveOR       = 5,   // PushInt(PopValue() | PopValue())
        Token_BitwiseAND               = 6,   // PushInt(PopValue() & PopValue())
        Token_LessThan                 = 7,   // PushInt(PopValue() < PopValue())
        Token_GreaterThan              = 8,   // PushInt(PopValue() > PopValue())
        Token_Assignment               = 9,   // *PopVar() = PopValue()
        Token_LogicalOR                = 11,  // PushInt(PopValue() || PopValue())
        Token_LogicalAND               = 12,  // PushInt(PopValue() && PopValue())
        Token_LeftShift                = 13,  // PushInt(PopValue() << PopValue())
        Token_RightShift               = 14,  // PushInt(PopValue() >> PopValue())
        Token_LessThanOrEqualTo        = 15,  // PushInt(PopValue() <= PopValue())
        Token_Equality                 = 16,  // PushInt(PopValue() == PopValue())
        Token_Inequality               = 17,  // PushInt(PopValue() != PopValue())
        Token_GreaterThanOrEqualTo     = 18,  // PushInt(PopValue() >= PopValue())
        Token_AdditionAssignment       = 19,  // *PopVar() += PopValue()
        Token_SubtractionAssignment    = 20,  // *PopVar() -= PopValue()
        Token_MultiplicationAssignment = 21,  // *PopVar() *= PopValue()
        Token_DivisionAssignment       = 22,  // *PopVar() /= PopValue()
        Token_UnaryPlus                = 30,  // PushInt(+PopValue())
        Token_UnaryMinus               = 31,  // PushInt(-PopValue())
        Token_LogicalNot               = 32,  // PushInt(!PopValue())
        Token_OnesComplement           = 33,  // PushInt(~PopValue())
        Token_Return                   = 60,  // return
        Token_Call                     = 61,  // call OpInt()
        Token_CallExternal             = 62,  // Sym(OpInt()).Addr()()
        Token_PushInt                  = 64,  // PushInt(OpInt())
        Token_PushVar                  = 65,  // PushVar(&Sym(OpInt()).Data[0])
      //Token_PushString               = 66,
        Token_PushInstance             = 67,  // Push(OpInt())
        Token_StringAssignment         = 70,  // *(string*)PopVar() = PopString()
        Token_StringListAssignment     = 71,  // *(string**)PopVar() = PopString()
        Token_FuncAssignment           = 72,  // *PopVar() = PopValue()
        Token_FloatAssignment          = 73,  // *(float*)PopVar() = (float)PopValue()
        Token_InstanceAssignment       = 74,  // Sym(Pop()).SetAddr(Sym(Pop()).Addr)
        Token_Jump                     = 75,  // goto OpInt()
        Token_JumpIf                   = 76,  // x = OpInt(); if(0 == PopValue()) goto x
        Token_SetInstance              = 80,  // g_CurrentInstance = Sym(OpInt())
        Token_PushArrayVar             = 245  // PushVar(&Sym(OpInt()).Data[OpByte()])
      };
    };
    Die entsprechenden Operationen sehen so aus:
    Code:
    byte OpByte()
    {
      return CodeStack.PopByte();
    }
    
    int OpInt()
    {
      return CodeStack.PopInt();
    }
    
    int Pop()
    {
      return DataStack.PopInt();
    }
    
    string* PopString()
    {
      switch(Pop())
      {
      default:
        return (string*)Pop();
      }
    }
    
    int PopValue()
    {
      switch(Pop())
      {
      case Token_PushInt:
        return Pop();
      case Token_PushVar:
        return *(int*)Pop();
      default:
        return(0);
      }
    }
    
    int* PopVar()
    {
      switch(Pop())
      {
      case Token_PushVar:
        return (int*)Pop();
      default:
        Pop();
        return(0);
      }
    }
    
    void Push(int x)
    {
      DataStack.PushInt(x);
    }
    
    void PushInt(int x)
    {
      Push(x);
      Push(Token_PushInt);
    }
    
    void PushVar(int* x)
    {
      Push((int)x);
      Push(Token_PushVar);
    }
    
    symbol* Sym(int x)
    {
      return SymbolTable[x];
    }

    --- Achtung (1) ---

    Externals die einen string zurückgeben, schreiben das Ergebnis in eine lokale statische Variable. Wenn man solch eine Funktion mehrmals in einem Ausdruck verwendet, dann wird das Ergebnis der vorherigen Aufrufe überschrieben.
    Beispiel: ConcatStrings(IntToString(1), IntToString(2)) = "22"

    func string Externals:
    • ConcatStrings
    • FloatToString
    • IntToString
    • NPC_GetDetectedMob
    • NPC_GetNearestWP
    • NPC_GetNextWP


    --- Achtung (2) ---

    Externals die eine instance zurückgeben, schreiben das Ergebnis in ein globales Symbol (ÿINSTANCE_HELP).

    ---

    Auf dem Daten-Stack befinden sich normalerweise Wert/Typ-Paare (Token_PushInt, 42). Dies gilt nicht für instance-Werte (dort fehlt der Typ).

    PopValue() ist mit Vorsicht zu betrachten, da der Stack (abhängig von dessen Inhalt) anders hinterlassen werden kann. So könnte man Token_PushInt, 0-Parameter "optimieren" (bzw. für Verwirrung sorgen), indem man als Typ etwas anderes als Token_PushInt/Token_PushVar auf den Stack legt (mit Token_PushInstance) und den Wert weglässt.
    Attached Files
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Last edited by NicoDE; 11.07.2017 at 20:13.

  4. View Forum Posts #4 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    Eine Liste der Funktionen, die durch die Engine bzw. das Spiel aufgerufen werden (können - es tauchen dort Dinge auf, die in Gothic nicht verwendet werden oder so nicht im Spiel vorkommen):
    Code:
    CGameManager::HandleEvent
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Hotkey_Lame_Potion")
    }
    CGameManager::HandleEvent
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Hotkey_Lame_Heal")
    }
    oCGame::CallScriptInit
    {
      CallFunc("Init_Global")
      CallFunc("Init_" + WorldName)
    }
    oCGame::CallScriptStartup
    {
      CallFunc("Startup_Global")
      CallFunc("Startup_" + WorldName)
    }
    oCGame::HandleEvent
    {
      MapInstance = <int>CallFunc("Player_Hotkey_Screen_Map")
    }
    oCInfo::Info
    {
      SELF = <oCNpc>Respondent
      OTHER = <oCNpc>Questioner
      CallFunc(Information)
    }
    oCInfo::InfoConditions
    {
      SELF = <oCNpc>Respondent
      OTHER = <oCNpc>Questioner
      Fulfilled = <int>CallFunc(Condition)
    }
    oCInformationManager::OnChoice
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(Function)
    }
    oCItemReactModule::StartReaction
    {
       Exchange = <int>CallFunc(Reaction)
    }
    oCMag_Book::Spell_Cast
    {
      SELF = <oCNpc>SpellCaster
      OTHER = <oCNpc>SpellTarget
      CallFunc("Spell_Cast_" + SpellName, SpellLevel)
    }
    oCMission::Failure
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(FailureFunction)
    }
    oCMission::FailureConditions
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      Fulfilled = <int>CallFunc(FailureCondition)
    }
    oCMission::Obsolete
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(ObsoleteFunction)
    }
    oCMission::ObsoleteConditions
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      Fulfilled = <int>CallFunc(ObsoleteCondition)
    }
    oCMission::Offer
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(OfferFunction)
    }
    oCMission::OfferConditions
    {	
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      Fulfilled = <int>CallFunc(OfferCondition)
    }
    oCMission::Running
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(RunningFunction)
    }
    oCMission::Success
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      CallFunc(SuccessFunction)
    }
    oCMission::SuccessConditions
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Player
      Fulfilled = <int>CallFunc(SuccessCondition)
    }
    oCMob::OnAction
    {
      TARGET = <oCNpc>Player
      OBJECT = <oCMob>this
      CallFunc(OnAction, ActionCounter)
    }
    oCMob::OnSpotted
    {
      CallFunc(OnSpotted, SpottedCounter)
    }
    oCMobInter::CallOnStateFunc
    {
      SELF = <oCNpc>Npc
      ITEM = <oCItem>InteractItem
      CallFunc(OnStateFunc + "_S" + State)
    }
    oCMobInter::CanInteractWith
    {
      SELF = <oCNpc>Npc
      CanUse = <int>CallFunc(ConditionFunc)
    }
    oCMobInter::CanInteractWith
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Another_Is_Using")
    }
    oCMobInter::CanInteractWith
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Missing_Item")
    }
    oCMobInter::SearchFreePosition
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Too_Far_Away")
    }
    oCMobInter::SearchFreePosition
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Wrong_Side")
    }
    oCMobLockable::CanOpen
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Missing_Key")
    }
    oCMobLockable::CanOpen
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Missing_Key_Or_Lockpick")
    }
    oCMobLockable::CanOpen
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Missing_Lockpick")
    }
    oCMobLockable::CanOpen
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Mob_Never_Open")
    }
    oCMobLockable::Interact
    {
      SELF = <oCMobLockable>this
      CallFunc("G_Picklock", Success, Lockpick)
    }
    oCMobLockable::Unlock
    {
      CallFunc("G_NoKey")
    }
    oCMobLockable::Unlock
    {
      SELF = <oCMobLockable>this
      CallFunc("G_Picklock", Success, LockpickOrOpened)
    }
    oCNewsManager::CreateNews
    {
      SELF =  = <oCNpc>Witness
      OTHER  = <oCNpc>Offender
      VICTIM = <oCNpc>Victim
      SpreadType = <int>CallFunc("C_CanNewsBeSpread")
    }
    oCNewsManager::SpreadNews
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Offender
      VICTIM = <oCNpc>Victim
      CallFunc("B_SpreadAndMemorize", NewsId, TRUE)
    }
    oCNpc::AddItemEffects
    {
      SELF = <oCNpc>this
      CallFunc(Item.OnEquip)
    }
    oCNpc::CanUse
    {
      SELF = <oCNpc>this
      ITEM = <oCItem>Item
      CallFunc("G_CannotCast", IsPlayer, ItemMagicCircle, MagicCircle)
    }
    oCNpc::CanUse
    {
      SELF = <oCNpc>this
      ITEM = <oCItem>Item
      CallFunc("G_CannotUse", IsPlayer, ItemConditionAttribute, ItemConditionValue)
    }
    oCNpc::EV_UseItemToState
    {
      SELF = <oCNpc>this
      ITEM = <oCItem>InteractItem
      CallFunc(InteractItem.OnState[InteractItem.CurrentState])
    }
    oCNpc::EV_WaitForQuestion
    {
      SELF = <oCNpc>this
      CallFunc("B_NpcBye")
    }
    oCNpc::Enable
    {
      SELF = <oCNpc>this
      CallFunc("B_RefreshAtInsert")
    }
    oCNpc::InitStatics
    {
      CallFunc("InitPerceptions")
    }
    oCNpc::OnDamage
    {
      CallFunc("Player_Victim_Is_Immortal")
    }
    oCNpc::OnDamage_Condition
    {
      SELF = <oCNpc>this
      OTHER = <oCNpc>Attacker
      UnconsciousnessAllowed = <int>CallFunc("C_DropUnconscious")
    }
    oCNpc::OnMessage
    {
      SELF = <oCNpc>this
      CallFunc("B_SetCutscenePerceptions")
    }
    oCNpc::OpenDeadNpc
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Plunder_Is_Empty")
    }
    oCNpc::OpenSteal
    {
      SELF = <oCNpc>this
      OTHER = <oCNpc>Victim
      CanSteal = <int>CallFunc("G_CanSteal")
    }
    oCNpc::RefreshNpc
    {
      SELF = <oCNpc>this
      CallFunc("B_RefreshArmor")
    }
    oCNpc::RemoveItemEffects
    {
      SELF = <oCNpc>this
      CallFunc(Item.OnUnequip)
    }
    oCNpc::SetCurrentAnswer
    {
      SELF = <oCNpc>this
      OTHER = <oCNpc>other
      CallFunc(Function)
    }
    oCNpc_States::DoAIState
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Other
      VICTIM = <oCNpc>Victim
      ITEM = <oCItem>Item
      CallFunc(StateFunction)
    }
    oCNpc_States::DoAIState
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Other
      VICTIM = <oCNpc>Victim
      ITEM = <oCItem>Item
      End = <int>CallFunc(StateFunction + '_LOOP')
    }
    oCNpc_States::DoAIState
    {
      SELF = <oCNpc>Npc
      OTHER = <oCNpc>Other
      VICTIM = <oCNpc>Victim
      ITEM = <oCItem>Item
      CallFunc(StateFunction + '_END')
    }
    oCNpc_States::InitRoutine
    {
      SELF = <oCNpc>Npc
      CallFunc(Npc.DailyRoutine)
    }
    oCNpc_States::StartAIState
    {
      SELF = <oCNpc>Npc
      CallFunc(AiState)
    }
    oCSpell::CallScriptInvestedMana
    {
      SELF = <oCNpc>SpellCaster
      OTHER = <oCNpc>SpellTarget
      SpellStatus = <int>CallFunc("Spell_ProcessMana", ManaInvested)
    }
    oCSpell::SetReleaseStatus
    {
      SELF = <oCNpc>SpellCaster
      OTHER = <oCNpc>SpellTarget
      SpellStatus = <int>CallFunc("Spell_ProcessMana_Release", ManaInvested)
    }
    oCTriggerScript::TriggerTarget
    {
      SELF = <oCNpc>Originator
      OTHER = NULL
      ITEM = NULL
      CallFunc(ScriptFunc)
    }
    oCViewDialogTrade::OnTransferRight
    {
      SELF = <oCNpc>Player
      OTHER = <oCNpc>Player
      CallFunc("Player_Trade_Not_Enough_Gold")
    }
    oCVisualFX::ProcessCollision
    {
      SELF = <oCNpc>Target
      OTHER = <oCNpc>Origin
      CollideFlags = <int>CallFunc("C_CanNpcCollideWithSpell", SpellType)
    }
    zCCSCutsceneContext::Stop
    {
      SELF = <oCNpc>MainRole
      OTHER = NULL
      VICTIM = NULL
      CallFunc(ScriptFuncOnStop, Name)
    }
    zCMenu::HandleAction
    {
      Leave = <int>CallFunc(MenuItem.OnEventAction[x])
    }
    zCMenu::HandleSelAction
    {
      Leave = <int>CallFunc(MenuItem.OnEventAction[x])
    }
    zCMenuItem::HandleEvent
    {
      Exit = <int>CallFunc(OnEventAction[MENU_EVENT_INIT])
    }
    zCMenuItemChoice::InsertInWin
    {
      CallFunc(OnEventAction[MENU_EVENT_INIT])
    }
    Wann und unter welchen Bedingungen die Funktionen aufgerufen werden ist teilweise schwer zu beantworten (und würde den Rahmen des Threads sprengen). Detailfragen können (wenn möglich) hier im Thread geklärt werden.

    ps: Alle Informationen beziehen sich auf Version 2.6.
    Attached Files
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Last edited by NicoDE; 07.07.2009 at 13:58.

  5. View Forum Posts #5 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    Hier eine Liste der Skriptklassen (Beschreibung eines zusammenhängenden Speicherbereichs eines Objekts zur Laufzeit in der Engine, auf den in den Skripten zugegriffen werden kann), deren Größen und/oder Offsets in der Engine überprüft werden:
    • sizeof(Camera.CCamSys)
    • sizeof(Gothic.C_Info)
    • offset(Gothic.C_Item)
    • sizeof(Gothic.C_Item)
    • sizeof(Gothic.C_ItemReact)
    • sizeof(Gothic.C_Mob)
    • offset(Gothic.C_Npc)
    • sizeof(Gothic.C_Npc)
    • sizeof(Music.C_MusicJingle)
    • sizeof(Music.C_MusicSys_Cfg)
    • sizeof(Music.C_MusicTheme)
    • sizeof(ParticleFX.C_ParticleFX)
    • sizeof(SFX.C_SFX)
    • sizeof(SFX.C_SndSys_Cfg)
    • sizeof(VisualFX.CFX_Base)
    • sizeof(VisualFX.C_ParticleFxEmitKey)

    Im Gegensatz zu C_Item und C_Npc initialisiert die Engine den Klassenoffset für C_Mob (wäre wie bei den anderen beiden sizeof(oCVob)...) nicht nach dem Laden/Parsen der Gothic.dat. Dadurch ist die Nutzbarkeit von C_Mob (wenn sie in den Skripten vorhanden wäre) mehr als fragwürdig.
    Attached Files
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  6. View Forum Posts #6 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline

    Beware of the NULL

    Neben den Schlüsselwörtern SELF (innerhalb der Funktion einer Instanz) und NOFUNC (es wird Symbolindex -1 für einen FUNC-Parameter übergeben), gibt es noch NULL (es wird Symbolindex 0 für einen Objektreferenz-Parameter übergeben). Aber dies ist mit Vorsicht zu genießen. Wie oben schon erwähnt, ist das Symbol mit dem Index 0 ÿINSTANCE_HELP und wird für den Rückgabewert von Externals verwendet, die eine Objektreferenz zurückgeben. Bei Externals funktioniert NULL wie erwartet, weil das Symbol mit dem Index 0 nicht als Parameter akzeptiert wird (die Objektreferenz wird nicht aus dem Symbol gelesen und der Standardwert für ungültige Symbole ist ein Nullzeiger). Diverse Folgefehler dieses Verhaltens von Externals können nicht auftreten, weil der Parser es nicht erlaubt, den Rückgabewert einer Funktion direkt als Parameter für eine Objektreferenz zu verwenden. Allerdings muss man bei eigenen Funktionen aufpassen, da dort der Symbolindex 0 durchaus gültig ist:
    Code:
    func int NullTest_GetNpcId(var C_NPC Character)
    {
    	// push_inst       NullTest_GetNpcId.Character
    	// assign_inst
    	// push_inst       NullTest_GetNpcId.Character
    	// call_external   Hlp_GetInstanceID
    	// return
    	return Hlp_GetInstanceID(Character);
    	// return
    };
    
    func void NullTest()
    {
    	var int HeroId;
    	var C_NPC HeroInst;
    	var int NullId;
    	var C_NPC NullInst;
    	var int Book;
    
    	// push_inst       hero
    	// call_external   Hlp_GetInstanceID
    	// push_var        NullTest.HeroId
    	// assign
    	HeroId = Hlp_GetInstanceID(hero);
    
    	// push_var        NullTest.HeroId
    	// call_external   Hlp_GetNpc  // result in symbol 0 (ÿINSTANCE_HELP)
    	// push_inst       NullTest.HeroInst
    	// assign_inst
    	HeroInst = Hlp_GetNpc(HeroId);  
    
    	/* NullId = Hlp_GetInstanceID(Hlp_GetNpc(HeroId));  // does not compile */
    	/* NullId = NullTest_GetNpcId(Hlp_GetNpc(HeroId));  // does not compile */
    	/* NullId = Hlp_GetInstanceID(NULL);  // externals do not read symbol 0 */
    
    	// push_inst       ÿINSTANCE_HELP
    	// call            NullTest_GetNpcId
    	// push_var        NullTest.NullId
    	// assign
    	NullId = NullTest_GetNpcId(NULL);  // does not what a reader would expect :)
    	// Attention: NullId could be the symbol index of an item (Npc_GetEquippedXxx)
    
    	NullInst = Hlp_GetNpc(NullId);
    	Book = Doc_Create();
    	Doc_SetPages(Book, 2);
    	Doc_SetPage(Book, 0, "BOOK_MAGE_L.TGA", FALSE);
    	Doc_SetMargins(Book, 0, 275, 20, 30, 20, TRUE);
    	Doc_SetPage(Book, 1, "BOOK_MAGE_R.TGA", FALSE);
    	Doc_SetMargins(Book, 1, 30, 20, 275, 20, TRUE);
    	Doc_SetFont(Book, -1, "FONT_15_BOOK.TGA");
    	Doc_PrintLine(Book, 0, "Hello, HERO");
    	Doc_PrintLine(Book, 1, "Hello, NULL");
    	Doc_SetFont(Book, -1, "FONT_10_BOOK.TGA");
    	Doc_PrintLine(Book, 0, ConcatStrings("id = ", IntToString(HeroId)));
    	Doc_PrintLine(Book, 1, ConcatStrings("id = ", IntToString(NullId)));
    	Doc_PrintLine(Book, 0, ConcatStrings("name = ", HeroInst.Name));
    	Doc_PrintLine(Book, 1, ConcatStrings("name = ", NullInst.Name));
    	Doc_Show(Book);
    };
    
    instance ANullTest(C_Item)
    {
    	name        = "NullTest";
    	mainflag    = ITEM_KAT_DOCS;
    	flags       = ITEM_MISSION;
    	value       = 42;
    	visual      = "ItWr_Book_02_05.3ds";
    	material    = MAT_LEATHER;
    	scemeName   = "MAP";
    	on_state[0] = NullTest;
    };
    [Bild: attachment.php?s=bcea87567881f9c1222fb7fd95ddc2c2&attachmentid=45504&d=1491567366&thumb=1]
    Kurz: NULL sollte, wenn überhaupt, nur bei Externals verwendet werden.
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  7. View Forum Posts #7 Reply With Quote
    Ehrengarde Neconspictor's Avatar
    Join Date
    Jan 2009
    Posts
    2,742
     
    Neconspictor is offline
    Interessant, ich wusste gar nicht, dass es NULL in Daedalus gibt. Eine Frage hätte ich allerdings. Macht es überhaupt irgendwo Sinn, Null bei Externals zu verwenden? Ich bin da gerade ein wenig unkreativ

  8. View Forum Posts #8 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    Quote Originally Posted by Neconspictor View Post
    Macht es überhaupt irgendwo Sinn, Null bei Externals zu verwenden?
    Nein, in den meisten Fällen sollten/müssen die Objektreferenzen gültig sein.
    Lediglich Npc_SendPassivePerc/Npc_HasNews/Npc_MemoryEntry[Guild] lassen sich für Spezialfälle missbrauchen (wenn VICTIM und/oder OTHER ungültig sein können/sollen).
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  9. View Forum Posts #9 Reply With Quote
    research NicoDE's Avatar
    Join Date
    Dec 2004
    Posts
    7,405
     
    NicoDE is offline
    AI_ContinueRoutine(npc) macht im Endeffekt nichts anderes als AI_StandUpQuick(npc), AI_StopLookAt(npc), AI_StopPointAt(npc), AI_RemoveWeapon(npc) und AI_StartState(npc, 0, FALSE, ""). Wobei der spezielle Wert 0 für die Zustandsfunktion bedeutet: verwende den, der aktuellen Weltzeit entsprechenden, Eintrag des Tagesablaufs. Allerdings ist es nicht möglich, Integer-Literale, FUNC-Variablen oder FUNC-Klassenfelder zu verwenden. Die einizige "Konstante" ist NOFUNC (die entspricht aber -1). Allerdings erlaubt der Parser die Verwendung von Instanzen/Prototypen als FUNC-Parameter (es wird der Symbolindex übergeben). Und das Symbol mit dem Index 0 ist ÿINSTANCE_HELP

    Code:
    func void AI_StartRoutineState(var C_NPC npc, var int end, var string wp)
    {
    	// AI_StartState has a special value of 0 for the second parameter
    	// to start the current daily routine entry. But the script parser
    	// does not allow to pass integer constants as FUNC parameters and
    	// at run-time an error is raised if a FUNC variable or FUNC class
    	// member is used as parameter. However, the script parser accepts
    	// instances/prototypes as FUNC parameter (symbol index is pushed)
    	// and the special ÿINSTANCE_HELP symbol has always the index 0...
    	AI_StartState(npc, ÿINSTANCE_HELP, end, wp);
    };
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
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