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 11 of 11
  1. Visit Homepage View Forum Posts #1 Reply With Quote
    Exodus Sektenspinner's Avatar
    Join Date
    Jul 2004
    Location
    Karlsruhe
    Posts
    7,827
     
    Sektenspinner is offline

    [Tipp] Funktionspointer

    EDIT: Fertige Schleifen-Implementierung ist verfügbar.

    Der User Korianous (er spricht Englisch, daher hier zweisprachige Antwort) fragte mich gerade, ob man nicht Funktionspointer in Daedalus nutzen könne. In der Tat ist das sogar relativ einfach möglich, sofern nur selten Funktionsaufrufe stattfinden (sagen wir, nicht mehr als 10 in der Sekunde) und nur Referenzen auf Funktionen ohne Parameter gefordert sind.

    Folgender Code ist als Vorbereitung notwendig:

    The user Korianous asked me, whether it was possible to use function pointers in Daedalus. This should indeed not be too hard, if only few calls are needed per second (lets lay, not more than 10) and if references to functions without parameters suffice.

    The following code is necessary as a setup:

    Code:
    //#################################################################
    //
    //  FUNCTION POINTER SETUP
    //
    //#################################################################
    
    PROTOTYPE FUNCTION (C_NPC) {
    	Mdl_SetVisual (self, "Meatbug.mds");
    };
    
    func void Call (var int funcPtr) {
    	Wld_InsertNpc (funcPtr, "TOT");
    };
    Danach können auf einfache weise Funktion deklariert werden, auf die hinterher referenziert werden kann.
    Das geschieht durch Ableiten des Prototyps FUNCTION. Hier zwei Funktionen, die HelloWorld bzw. FooBar ausgeben.

    After this, functions, that are to be referenced later on, can be declared quite simply by deriving from the prototype FUNCTION. Here are two functions that print "HelloWorld" and "FooBar" respectively.

    Code:
    INSTANCE MyFunc1 (FUNCTION) {
    	Print ("HelloWorld!");
    };
    
    INSTANCE MyFunc2 (FUNCTION) {
    	Print ("FooBar");
    };
    Ein Funktionspointer wird nun einfach als Integer deklariert. Ihm können direkt Funktionen zugewiesen werden, wenn diese wie oben gezeigt deklariert wurden.
    Die Prozedur Call kann genutzt werden um die im Funktionspointer enthaltene Funktion aufzurufen.

    A function pointer is declared as if it was an integer. It can be assigned different functions directly.
    The procedure call can be used to call the function that is currently stored in the function pointer.


    Code:
    var int MyFunctionPointer;
    
    func void SomeTestFunction() {
    	//Initialize MyFunctionPointer with some value
    	if (Hlp_Random (2)) {
    		MyFunctionPointer = MyFunc1;
    	} else {
    		MyFunctionPointer = MyFunc2;
    	};
    	
    	//Call the function that is currently referenced in MyFunctionPointer:
    	Call (MyFunctionPointer);
    };
    Anwendungen fallen mir leider gerade keine griffigen und sinnvollen ein. Vielleicht ein EventManager, den man elegant anweist, nach einer bestimmten Verzögerung oder mit einer bestimmten Frequenz Funktionen aufzurufen, die man an ihn übergibt.

    Ein zusätzliches Problem ist auch, dass der Inhalt des globalen self während einem Aufruf einer so deklarierten Funktion verändert wird.
    Ohne die Zerstörung von self und mit weniger Performance Problemen kommt man vermutlich aus, wenn man statt mit Wld_InsertNpc mit Npc_ExchangeRoutine arbeitet (jedes mal nur eine Routine neu startet statt einen Npc neu einzufügen). In diesem Fall haben aber die Funktionen alle seltsame Namen (Präfix Rtn_ Suffix irgendeine Zahl).

    Sofar, no really usefull application occured to me, however. Perhaps an EventManager that automatically calls various functions (that can be specified by parameters) in specific intervals or after specific delays.

    An additional problem not mentioned above is, that the content of "self" is changed when calling a function of the type above.
    I should be possible to avoid this (for example by changing Routines instead of inserting Npcs all the time). However, functions would be forced to have weird names (prefix "Rtn_" and some number as suffix).
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts
    Last edited by Sektenspinner; 07.02.2010 at 14:47.

  2. View Forum Posts #2 Reply With Quote
    Dea
    Join Date
    Jul 2007
    Posts
    10,308
     
    Lehona is offline
    Das ganze basiert also einfach auf der Erstellung eines NPCs, in dessen Script anstatt diversen Werten Befehle angegeben sind?
    Wenn ja ist das ziemlich genial^^

  3. View Forum Posts #3 Reply With Quote
    General Korianous's Avatar
    Join Date
    Jun 2008
    Location
    USA
    Posts
    3,080
     
    Korianous is offline
    Gut Arbeit! Deine weg ist besser, glaube ich.
    Ach Fry, Ich hab dich mehr als der Monde, die Sterne...das...fail.
    Last edited by Korianous; 08.10.2009 at 02:43. Reason: thanks lehona ;).

  4. View Forum Posts #4 Reply With Quote
    Dea
    Join Date
    Jul 2007
    Posts
    10,308
     
    Lehona is offline
    Quote Originally Posted by Korianous View Post
    Gut Arbeit! Deine modus ist besser, Ich glaube .
    Just speak english here
    We're all abled to understand you, if you speak english, but translated with sth. like the google-translator it's... horrible.

  5. View Forum Posts #5 Reply With Quote
    General Korianous's Avatar
    Join Date
    Jun 2008
    Location
    USA
    Posts
    3,080
     
    Korianous is offline
    Quote Originally Posted by Lehona View Post
    Just speak english here
    We're all abled to understand you, if you speak english, but translated with sth. like the google-translator it's... horrible.
    Didn't use google translate, my German is just really bad . I can understand it, but can't write properly, I'm literally learning it just through reading these forums.

    In case I wasn't intelligible, here's what I had intended to say:
    Good work! Your method is better, I believe.
    Ach Fry, Ich hab dich mehr als der Monde, die Sterne...das...fail.

  6. View Forum Posts #6 Reply With Quote
    Dea
    Join Date
    Jul 2007
    Posts
    10,308
     
    Lehona is offline
    Quote Originally Posted by Korianous View Post
    Didn't use google translate, my German is just really bad . I can understand it, but can't write properly, I'm literally learning it just through reading these forums.
    Oh, sorry for that then^^

    Your vocabs are right, but the grammar is wrong. That made me think you used a translator. And learning German by readin' the forum... Bad idea, dude. Getting some lessons would be much better 'coz German is really difficult to learn.

    Edit: Yeah, I understand it, and method may be "modus" in German... but it's not really right here. I'd say "Weg" (male) or "Art" (female).
    And the last two words have to be swapped^^

  7. View Forum Posts #7 Reply With Quote
    Deus Oparilames's Avatar
    Join Date
    May 2004
    Location
    ex contrariis
    Posts
    10,958
     
    Oparilames is offline
    An interessting experiment.
    But I can't believe that anyone needs such pointer often.
    Have aynone here a example to show me what a such pointer may do better than other "normaly" methods?

    I want to excuse me - you all can read that my english isn't very complex. I think it's a simple and bad english...
    Oparilames nachdem er seinen Gesellenbrief erhalten hat:
    »Das war's mit dir, du Mistvieh!«

  8. Visit Homepage View Forum Posts #8 Reply With Quote
    Exodus Sektenspinner's Avatar
    Join Date
    Jul 2004
    Location
    Karlsruhe
    Posts
    7,827
     
    Sektenspinner is offline
    I tried the Npc_ExchangeRoutine approach, and I think this is the better way to implement the feature, simply because it is probably by far less costly (has a better performance) than the way posted above (inserting npcs takes more time than just changing the routine). The self problem remains however, but can be avoided by simply introducing a callSlf that is initialized appropriatly and can be used instead of self.

    Now the following is the setup:
    Code:
    //--------------------------------------
    // variant 2
    //--------------------------------------
    
    //a helper npc that will be created once (and only once!) for each world.
    INSTANCE CallHelper(C_Npc)			
    {
    	name = "Call-Helper";
    	
    	id = 0; //different IDs would require different naming conventions for the functions that are to be referenced.
    	
    	flags = 2; //He may not die.
    	attribute	[ATR_HITPOINTS_MAX]	=	1;
    	attribute	[ATR_HITPOINTS]		=	1;
    	
    	Mdl_SetVisual (self, "Meatbug.mds"); //if missing, Gothic crashes when destroying the object.
    };
    
    //The functions that are called by this system should use "callSlf" instead of "self" (because "self" is initialized with the Call-Helper, who is of no interest)
    var C_NPC callSlf;
    
    //Calls the function "Rtn_<name>_0" and backups the current "self" in "callSlf"
    func void CallByString (var string name) {
    	var C_NPC callHelperNpc;
    	callHelperNpc = Hlp_GetNpc (CallHelper);
    	callSlf = Hlp_GetNpc (self);
    	
    	if (!Hlp_IsValidNpc (callHelperNpc)) {
    		Print ("ERROR: No CallHelper available!");
    	} else {
    		Npc_ExchangeRoutine (CallHelper, name);
    	};
    };
    Code:
    func void STARTUP_GLOBAL()
    {
    	[...]
    	
    	//every world needs a CallHelper
    	Wld_InsertNpc (CallHelper, "TOT");
    };
    Now, a function that needs to be referenced must be of the following form: Rtn_<Name>_0 where <name> can be choosen freely.

    In order to call this function <name> must be given to the function CallByString.

    Example: We can now introduce simple for-loops in Gothic (with severe limitations and weird notation however).

    Code:
    var int i; //the variable of which is ALLWAYS iterated
    func void for (var int start, var int stop, var string name) {
    	if (start <= stop) {
    		i = start;
    		CallByString (name);
    		for (start+1, stop, name);
    	};
    };
    We can use this for loop for example like this:
    Code:
    func void Rtn_Print_0() {
    	Print (IntToString (i));
    };
    
    func void foo() {
    	for (23, 42, "PRINT");
    };
    Calling foo will print the numbers from 23 to 42.
    I am pretty sure that there are better implementations of for, especially some that are less susceptible for stack overflows and allow the nesting of loops.
    I guess that implementations of while loops and C-like for loops are possible as well.

    Quote Originally Posted by Oparilames
    Have aynone here a example to show me what a such pointer may do better than other "normaly" methods?
    I think the for-loops are quite a good example. I do not know any other approach capable of doing this.
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts
    Last edited by Sektenspinner; 08.10.2009 at 02:39.

  9. View Forum Posts #9 Reply With Quote
    Dea
    Join Date
    Jul 2007
    Posts
    10,308
     
    Lehona is offline
    Yeah, for-loops are quite useful for me, 'cause i can now just remove this damn Arrays of you, who are a very bad solution for my problem.

    Thank you once more, Sektenspinner!

  10. View Forum Posts #10 Reply With Quote
    Dea
    Join Date
    Jul 2007
    Posts
    10,308
     
    Lehona is offline
    Code:
    func void CallByString (var string name) {
    	var C_NPC callHelperNpc;
    	callHelperNpc = Hlp_GetNpc (CallHelper);
    	callSlf = Hlp_GetNpc (self);
    	
    	if (!Hlp_IsValidNpc (callHelperNpc)) {
    		Print ("ERROR: No CallHelper available!");
    	} else {
    		Npc_ExchangeRoutine (CallHelper, name);
    	};
    };
    Shouldn't it be
    Code:
    Npc_ExchangeRoutine (callHelperNpc, name);
    Npc_ExChangeRoutine() requires a C_NPC variable (says the externals.d)...

  11. Visit Homepage View Forum Posts #11 Reply With Quote
    Exodus Sektenspinner's Avatar
    Join Date
    Jul 2004
    Location
    Karlsruhe
    Posts
    7,827
     
    Sektenspinner is offline
    That should not make a difference in this case since their is exactly one CallHelper in the world. But your right, it's better style to wright CallHelperNpc there.
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts

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