Posts by TechPro

Information: The EMERGENCY community board is completely free and is financed by advertisement. Please deactivate adblocker if you use this site. Thank you!

    Freue mich schon auf deine Bordell-Manager 2022 Mod 8)8):thumbup:
    Melde dich gerne nochmal, wenn du Sounds benötigst. Ich kenne hier im Forum jemanden, der professionelles Sounddesign auf höchster Qualität kann.

    Da Eltern für die Mediennutzung ihrer Kinder selbst verantwortlich sind, finde ich nicht, dass man sich für Mods keine eigene FSK12 oä auferlegen muss.

    Gibt es denn vielleicht die Möglichkeit den Zwischenspeicher von EM 4 irgendwo zu löschen ??

    Ja, das kommt dann aber einem Schließen der Em4.exe gleich. Also eigentlich Nein.



    Sonst der Post, den Drummer verlinkt hat.

    Macht euch von Angelus' Beitrag von September 2013 frei. Der ist bis auf eine einzige der getroffenen Annahmen falsch!
    Vor allem ist aber auch seine Schlussfolgerung, dass "?ERROR: Could not allocate memory for model vertex data" bedeutet, dass das logfile zu groß ist, falsch. Wäre dem so, könnte diese Zeile überhaupt nicht geloggt werden.


    Zu große Logs scheinen mir nicht die Hauptursache zu sein.

    Sie sind hier nicht nur nicht die Hauptursache, sondern definitiv nicht die Ursache.


    Es wäre doch nur der Zwischenspeicher, kein Hauptspeicher oder so.

    Jede Applikation muss die von ihr genutzten Daten, vor allem aber auch selbst in den RAM geladen werden. Daher ist es gänzlich unsinnig, den von Em4 in Anspruch genommenen Zwischenspeicher ... "freizugeben".



    Nochmal für alle zum Mitschreiben:
    Em4 ist verdammt alt und dass es ein Limit des nutzbaren Arbeitsspeichers, gleichzeitig aber auch eine Obergrenze für die geladenen Objekte je Map gibt, wurde im Forum mehr als einmal festgehalten.
    Akzeptiert es und arbeitet darum herum, oder nutzt einfach ... ein aktuelleres Spiel.

    Da es hier ja leider keinen Dislike-Button gibt: hier wird mal wieder über etwas diskutiert, zu dem es nichts zu sagen gibt, außer persönliche Befindlichkeiten.



    ich persönlich kann sie nicht nachvollziehen und hätte anders gehandelt.

    Richtig. Du hast sogar bereits anders gehandelt: Du hast erst gar keine Mod angefangen. :)


    jedem Entwickler muss bewusst sein ( auch wenn es noch so zeitintensiv ist) - jeder Spieler " tickt "anders und daher sollte man das berücksichtigen , bevor man solche Entscheidungen trifft

    Was willst du hier zum Ausdruck bringen ?Dass jemand ,der in seiner Freizeit Bilder aus einem Computerspiel hochlädt ,dir etwas schuldig ist ?


    Und nur um das nochmal klar zu machen: Ich halte von Privat-Mods, bei denen nur etwas gezeigt wird auch nichts - wer das für sich machen will, kann es meinetwegen auch im stillen Kämmerlein machen. Aber so ist diese Welt nunmal: Solange die Nutzungsbedingungen eingehalten werden, ist das okay.




    PS: wenn ihr euch alle mal am Modding versuchen wollt, könnt ihr godra bestimmt ein paar nette Stücke für den Adventskalender zukommen lassen. Da haben wir ja schließlich am Ende alle was davon. ;)

    Aber der Konstruktor nimmt keine Parameter an


    Das ist tatsächlich in der qsf::ai::MoveAction der Fall, nicht aber in der em5::MoveAction, oder irre ich?


    Ja, du hast Recht: die em5::MoveAction Klasse hat keinen Konstruktor, der Parameter erwartet.
    Bin da bei den Files durcheinander gekommen.


    Damit wären wir aber wieder an dem Punkt, wo es keinen Sinn macht, eine eigene ACTION_ID festzulegen, da die tatsächlich verwendete immer em5::MoveAction sein wird.
    Da ich nicht weiß, wie die action id vom Spiel verwendet wird, kann ich aber nicht bewerten, ob es dann sinnvoller ist, von em5::MoveAction, oder von qsf::ai::MoveAction zu erben. Code wirst du wahrscheinlich in beiden Fällen in größerem Umfang kopieren.

    wenn ich keine neue ACTION_ID für meiner Klasse deklariere, dann kann ich eigentlich in meinem MoveCommand-Befehl nur die em5:Moveaction pushen, stimmt es?

    ja, genau.
    Ich habe jetzt nochmal geschaut, wie der Mechanismus mit ACTION_ID genau funktioniert - denn so wie in meinem letzten Post analysiert macht es softwaretechnisch keinen Sinn. Das em5 System ist ja darauf ausgelegt, auch vorab unbekannte Klassen verwenden zu können.
    In qsf::ai::Action (davon erben alle Actions) ist für den Konstruktor ein Parameter uint32 actionTypeId deklariert. Das ist der erwähnte Hash. Das bedeutet, dass irgendwo der Inhalt von ACTION_ID an diesen Konstruktor übergeben wird.
    Wenn man dann in den Header von em5::MoveAction schaut, sieht man in Zeile 62 einen protected Konstruktor mit dem Hinweis, dass dieser von Subklassen verwendet werden soll.
    Das heißt für dich: Du rufst den em5::MoveAction Konstruktor in deinem eigenen auf und packst dort deine eigene ActionId rein. Dein Konstruktor würde dann so aussehen:

    C: Konstruktor neue MoveAction
    NewMoveAction::NewMoveAction() : em5::MoveAction(ACTION_ID)
    {
      // Nothing here
    }


    Hier nochmal die Nachfrage und der Hinweis: nutzt du namespaces? Programmierst du im em5 namespace?
    Letzteres solltest du keinesfalls tun!
    Leg' dir einen eigenen namespace an - der Name ist quasi egal, sollte aber einzigartig sein. Möglich ist zum Beispiel "bud".
    Und dann nutze bitte kein using namespace ...
    Das mag angenehm erscheinen, senkt aber die Code-Qualität, denn wie man an qsf::ai::MoveAction und em5::MoveAction sieht, wird es damit zunehmend schwieriger zu identifizieren, welche Klasse gemeint ist. Wenn du mehrere namespaces mit using direkt in den Kontext importierst kann es auch zu Konflikten kommen.
    Kurzum: bei < 100 LOC und mit std erscheint es wie eine gute Idee, ist es aber nicht.


    Waypoint bekommst du über die includes von em5::MoveAction -> qsf::ai::MoveAction -> qsf::ai::Path -> qsf::ai::Waypoint
    Schau' erstmal, was passiert wenn du die Änderung einbaust und melde dich dann nochmal.
    Was auch helfen würde, wäre mehr Code zu sehen. In C++ gibt es oft die exotischsten Fehlermeldungen, die nicht immer direkt auf die Ursache schließen lassen. Hier z.B. fällt mir jetzt spontan nichts ein.

    Die action ID scheint für jede Action einzigartig zu sein. Sie ist static const im scope der jeweiligen Action-Klasse umgesetzt.
    Siehe auch hier unter "Static Public Attributes": https://emergency.kn-solutions…sem5_1_1_move_action.html


    In Zeile 82 aus der originalen MoveAction siehst du auch, wie diese Konstante definiert werden kann:
    const qsf::NamedIdentifier MoveAction::ACTION_ID = "em5::MoveAction";
    Der Wert setzt sich quasi aus dem Namen (also em5::MoveAction) und einem Hash zusammen.


    Wichtig: Wenn du von MoveAction erbst, musst du in deinem Code mit der action id der MoveAction eigentlich nichts mehr machen. Denn: die action id ist ja bereits const in em5::MoveAction deklariert und soll für sie einzigartig sein (und bleiben).
    Du kannst jetzt entweder ACTION_ID nicht nochmal deklarieren, dann müsstest du in deiner abgeleiteten Klasse dieselbe action id wie em5::MoveAction haben und wegen public inheritance und declaration auch drauf zugreifen können.
    Oder: du deklarierst und definierst einfach nochmal eine ACTION_ID für deine Subklasse. Da würdest du dann analog zu Z.82 die action id anhand deines Klassennamens festlegen.



    Aber Achtung: Wenn du dann ein Objekt deiner abgeleiteten Klasse als em5::MoveAction pointer übergibst, oder verwendest, kann dort die action id von em5::MoveAction auftauchen. Es macht also wahrscheinlich eher wenig Sinn, eine neue Action Id zu deklarieren, wenn die am Ende eh nur in deiner eigenen Klasse ausgelesen werden kann.


    Im Beispiel ist die action id der BaseClass 1 und die der SubClass 6.
    Im Konstruktor wird jeweils die aktuell gültige action id ausgegeben.



    Code
    BaseClass constructor 1
    BaseClass constructor 1
    SubClass constructor 6
    1
    6
    1

    Ich mag euch natürlich nicht vorschreiben, wo ihr zu kommunizieren habt, aber wenn Fragen und Probleme hier transparent im Forum geklärt werden (gerne auch in mehreren verschiedenen eigenen Threads), dann haben hier alle was davon.
    Insofern mag ich dich, lieber @Zheerd, dazu ermuntern gerne die Fragen hier zu posten, oder eigene Themen dafür aufzumachen, falls das jeweils thematisch nicht zusammengehört. :)

    Nur, um jetzt ein Missverständnis zu vermeiden (- mag wie ne Dullifrage klingen) : 32 Bit Integer im Sinne von 32 Einsen und Nullen - also 0000 0000 0000 0000 0000 0000 0000 0000 und nicht, dass der einen Maximalwert von 32 (00000 bis 11111) annehmen kann, right?
    Wenn es nämlich 32 Einser und Nuller sein dürfen, dann kann ich mir da ja alle meine Flags reinpacken, die ich will. Ich muss immer nur erst auslesen, was schon gemacht wurde, ggf. addieren/subtrahieren und neu setzen. (Dann bräuchte ich für den Patienten wahrscheinlich nur 8-12 Bit, um das vollständige Equipment und seine "Zustände" zu definieren.) Kann man den Wert binär auslesen oder geht das über die API hinaus?

    Richtig, ein 32 Bit Integer besteht aus 32 Bits, die jeweils logisch eins, oder null sein können. Erst die Interpretation dieser Bits macht den Speicherbereich zu einem Integer, Float, Boolean, etc.
    Das machen wir uns zu Nutze und nehmen einen Integer her, um darin 32 einzelne Wahrheitswerte unterzubringen.




    Addieren und Subtrahieren würde ich nicht machen. Durch bitwise operations und Masken kann man das sehr angenehm lösen.
    Du legst also zum Beispiel fest, dass das least significant bit (LSB) ein Flag für die Intubation ist. Das eins höherwertige sei dann z.B. ob der Patient ein Schmerzmittel bekommen hat, oder nicht (Achtung: nicht die Dosis, sondern nur ob, oder ob nicht. Es handelt sich ja nur um ein Flag!) und das wiederum eins höherwertige sei dann etwa ob eine Infusion gelegt wurde, oder nicht.
    Im Beispiel würdest du mit einem bitwise or (|) das Flag setzen, mit einem bitwise and (&) und entsprechender Maske auslesen und mit einer negierten Maske zurücksetzen. Die Maske erzeugt man mithilfe des left shift operators (<<). Der verschiebt dir einfach nur die Einsen und Nullen im Speicher.
    Im Beispiel beschränke ich mich auf die untersten vier Bits (von rechts nach links steigen die in ihrer Wertigkeit).
    Ich verwende hier die Notation für binäre Konstanten ("0b" als Prefix). Hängt vom Compiler ab, ob man das auch tatsächlich im Code nutzen kann. In Em4 würde ich es eher nicht erwarten.

    Soo, jetzt kann man das jeweils ein bisschen unübersichtlich finden. Abhilfe schaffen dann oft enums und Makros. Dann muss man z.B. nur noch BITWISE_SET(ac.UserData, ENUM_INTUBATION) schreiben. Aber auch hier wieder: inwieweit das von Em4 unterstützt wird weiß ich nicht.
    Du kannst wie bei anderen Operatoren auch die bitwise operators abkürzen, also z.B. ac.UserData |= 1<<2 anstatt ac.UserData = ac.UserData | (1<<2) schreiben.


    Alle Unklarheiten beseitigt?

    Hallo Lauri, schön, dass du es ins Forum geschafft hast.
    Der Export mit Blender funktioniert prinzipiell so: Blender -> .mesh.xml -> .mesh
    D.h. dein mesh wird erst in einer xml-Datei exportiert und in einem zweiten Schritte von einem speziellen Tool binär abgespeichert.
    Die CommandLineTools gibt es mittlerweile in Ogre nicht mehr so richtig (Ogre ist die Open Source Engine, auf der die Em5-Engine basiert).
    Ich konnte den Link hier finden, lass das dann einfach mal durch virustotal laufen, dann sollte es passen: https://deac-fra.dl.sourceforg…ommandLineTools_1.7.2.zip


    Ich hoffe das hilft dir weiter.
    Du kannst mit dem Wissen gerne nochmal selbst herumprobieren. Ich schaue ob ich heute Abend, oder morgen Zeit finde mir das mit den aktuellen Plugins genauer anzuschauen und melde mich dann nochmal.

    Dann müsste ich aber vermutlich allen Zivilpersonen und dem gesamten Einsatzpersonal diese Childs zuweisen, oder?

    Auftritt @noBlubb und sein .e4p Parser :D


    Ich glaube wir reden insgesamt gerade ein bisschen aneinander vorbei.
    Ich dachte, es ginge dir vorallem darum, den Personen einen Zustand zu verpassen und den über die Laufzeit des Skripts hinaus zu erhalten.
    Denkbar ist da also der userData member, den jedes GameObject hat. Das ist aber "nur" ein 32 bit int. Hast also 32 flags zur Verfügung. Könnte ausreichen - wirklich problematisch wird's aber, wenn du noch andere Skripte einsetzt, die ebenfalls auf die userData setzen. Die Skripte wären dann ja inkompatibel und du hast nichts gewonnen.
    Danach bin ich dann auf Childs gekommen. Von denen könntest du beliebig viele einer Person zuweisen - also mehr als 32 flags pro Person produzieren. Der Zustand des flags würde sich dann direkt aus der Aktivierung eines Childs ableiten. (Diese Childs würde ich unsichtbar machen, ich rede also nicht von einem EKG, einer Trage, oder so, sondern wirklich nur von der logischen Information, die die Existenz dieses Childs impliziert)
    Dritte Alternative scheint der Weg zu sein, den du bereits mit Dummy-Commands gewählt hast. Der Vorteil scheint da zu sein, dass du diese den Objekten dynamisch hinzufügen kannst. Das geht bei den Childs anscheinend nicht, deswegen sind die wohl eher ne Sackgasse. Ich hatte gehofft, dass man durch SetChildEnabled("", true) auch ein komplett neues Child einer Person zuweisen kann. Scheint aber ja nicht zu gehen.

    Bin leider noch nicht ganz am Start, was in C++ geht und was eben nicht.

    Der von dir gezeigte Schnipsel dürfte irgendein C# Voodoo sein. In C++ habe ich das noch nie gesehen.


    Zu den Flags: man kann in em4 keine header includen, d.h. du brauchst dir eigentlich auch keinen enum oder so zurechtbasteln. Bzw. könntest du das zwar, musst das dann aber überall, wo du es auslesen willst, wieder in der Skriptdatei neu deklarieren. Für ne einmalige Sache ist das kein Problem - wenn du das aber nachträglich ändern willst, wird das zur Hölle.


    Kann man in Em4 Personen Childs geben? Ne Person ist ja ein GameObject und dann könntest du da standardmäßig deine verschiedenen Zustände als children hinterlegen und dann je nach Auftreten beim Verletzten aktivieren und während des Heilungsprozesses wieder deaktivieren.
    Aus dem SDK von der GameObject-Klasse:

    Bisher habe ich es in EM4 mit Dummy-Befehlen gelöst

    Komme nicht ganz mit - please elaborate.


    Sowas wie "bool RTW1.hasMedumat = true;" oder "bool patient.needsNA = false;", sodass beim Aufruf eines Scripts dieser Wert wieder geändert werden kann? Bzw. wie kann ich den Objektverweis hier herstellen? Sodass es immer in Relation zum verwendeten Fahrzeug/Patient/... steht und ich nicht tausend Abfragen à la "if(Caller.HasName("RTW1") RTW1.hasMedumat = false;" stellen muss). Kann man hier über die ID arbeiten?

    Hast du dazu ein bisschen Kontext?
    Welchen Typ hat RTW1, woher kommt hasMedumat und was machst du im Folgenden mit dieser Information?
    Scheint so, als würdest du im Gesamtkonstrukt einen Zustandsautomaten bauen wollen (?) aber sicher bin ich mir da nicht.


    Objekte, die in einem Script erstellst, werden entsprechend ihres scopes wieder vom stack genommen. Die musst du dann also beim nächsten Scriptdurchlauf wieder neu erstellen und initialisieren.
    Du kannst Em4 mit Referenzen austricksen und deinen eigenen Speicherbereich vollkleistern, aber das würde ich dir eher nicht empfehlen: Modding-Entdeckung - jetzt noch?! || Erweiterte UserData


    apropos Wetter: Bin eigentlich gerade mit strahlendem Sonnenschein ganz zufrieden. Wehe du änderst das! :D



    Edit:
    die Konstruktion bool obj.member = value; dürfte nicht vom C++ Standard abgedeckt sein. Ich denke, dass das ein Bug im Scriptinterpreter von Em4 ist.
    Effektiv dürftest du damit einen Boolean anlegen, der zwar "obj.member" heißt, aber tatsächlich eben nicht dem Objekt "obj" einen neuen member "member" hinzufügt und dadurch das Objekt weiterhin unverändert bleibt. Würde auch erklären, warum du zwar erwartest, dass dieses Objekt auch beim nächsten Skriptaufruf noch den member hat, der aber dann auf einmal "verschwunden" ist. Es gab ihn schlicht nie.



    Edit 2:
    Für kleine Datenmengen (flags) kannst du die userData eines jeden Objektes hernehmen. Muss dann aber natürlich insgesamt mit allen anderen Skripten kompatibel sein, sonst funkt dir ein anderes Skript rein und der Inhalt ist nicht mehr zu gebrauchen.

    Zu 1.) Hier musste ich an EActionExecuteCommand denken. Würde aber dann eigentlich genauso funktionieren, wie du es geschrieben hast. Man lässt das Script sich quasi selbst nochmal aufrufen und nutzt die Actionlist mit den erwähnten EActionWait, um das in einem bestimmten Intervall zu tun.


    Zu 2.) Sowas wird mWn über Missionsscripte gesteuert. Wie das exakt umgesetzt ist weiß ich aber nicht, da ich das noch nie gemacht habe. Die meisten größeren Mods sind eigentlich mit Missionsscript umgesetzt.


    Zu 3.) Du meinst quasi eine Steuerung der Geschehnisse in der Spielwelt? Ganz grundsätzlich ist sowas über eine while Schleife gelöst. Das ist dann die sogenannte gameloop. Musst halt natürlich sicherstellen, dass du dir deinen Prozessor nicht durch unnötig häufige Berechnungen auslastest und andere Prozesse regelmäßig verdrängst. (e.g. einfach sicherstellen, dass du die Schleife nicht zu oft durchläufst) Inwieweit das bei em4 missionsscripts relevant ist, kann ich nicht genau sagen. Ist aber bei Performanceproblemen der erste Punkt, den du überprüfen könntest.


    Zu dem Wetter: das liest sich so, als könnte man zwar den Zustand des Wetter-Systems ändern, nicht aber einen übergeordneten Zustand, aus dem sich unter anderem der Zustand des Wetter-Systems ableitet.