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 9 von 9
  1. Beiträge anzeigen #1 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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. Beiträge anzeigen #2 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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.
    Angehängte Dateien
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (09.06.2009 um 11:55 Uhr)

  3. Beiträge anzeigen #3 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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.
    Angehängte Dateien
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (11.07.2017 um 18:13 Uhr)

  4. Beiträge anzeigen #4 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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.
    Angehängte Dateien
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (07.07.2009 um 11:58 Uhr)

  5. Beiträge anzeigen #5 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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.
    Angehängte Dateien
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  6. Beiträge anzeigen #6 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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=971c829f066e9c9b990dd4ba54a9fa13&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. Beiträge anzeigen #7 Zitieren
    Knight Commander Avatar von Neconspictor
    Registriert seit
    Jan 2009
    Beiträge
    2.749
     
    Neconspictor ist 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. Beiträge anzeigen #8 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist offline
    Zitat Zitat von Neconspictor Beitrag anzeigen
    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. Beiträge anzeigen #9 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist 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

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