[Gelöst] "AddLight" abändern, weil sonst Gebäude

Hi,
die Gebäude aus CognitionAlliance bzw. Space Launch haben ja so eine coole Lichtfunktion, welche ich nun auch schon für andere Objekte übernommen habe, um für mehr Licht zu sorgen.
Die Funktionen im Skript dafür sind ziemlich einfach, zusätzlich kann man halt noch selbst in einer weiteren Funktion bestimmen, wann das Licht ausgelöst werden soll:

private func TurnLightOn()
{
  var iColor;
  iColor = RGBa(235,150,10,50);
  mlight = AddLight(1000, iColor, this());
  return(1);
}

private func TurnLightOff()
{
  if (mlight) RemoveObject(mlight);
  return(1);
}


Erstmal die Frage:
Ist dieser "AddLight" Befehl ein fester befehl in der Engine? Ich vermute mal ja, weil im Skript dieser Befehl nirgends definiert ist und es auch keine Verweise zu anderen Skripten gibt.

Nun ist aber das Problem, dass dieses Licht offensichtlich als Gebäude gewertet wird. Da ich aber Funktionen wie "reparieren" und Gebäude abreißen" verwende, wird auch das Licht als mögliches Ziel ausgegeben. Das ist natürlich quatsch und muss ich irgendwie abstellen.

Eigentlich dachte ich mir, ich ändere beim Licht entweder, dass es kein Gebäude mehr ist, oder ich füge eine Eigenschaft hinzu, die ich dann beim reparieren/abreißen ausschließe.
Aber bei dem Befehl "AddLight" wüsste ich nicht, wie ich rausfinde, welche Eigenschaften daraus folgen und ob/wie ich das ändern kann.

>Ist dieser "AddLight" Befehl ein fester befehl in der Engine? Ich vermute mal ja, weil im Skript dieser Befehl nirgends definiert ist und es auch keine Verweise zu anderen Skripten gibt.


Ich glaube, der kommt aus dem Hazardpack.

PS: Es gibt die Funktion "LocateFunc" um rauszufinden, wo eine andere Funktion definiert wird. Kannst ja mal im Spiel LocateFunc("AddLight") eintippen und gucken was rauskommt.

okay, guter Hinweis, danke :slight_smile:

wo tippe ich das denn ein? In ein Script und dann ein Testspiel starten, oder wie mache ich das?
Wenn wir schon bei Suchfunktion sind, gibt es eine Möglichkeit eine ID zu finden? Also z.b wenn ich über ein script stolpere, welches z.b. "DSFK" verwendet, wie finde ich dieses Objekt dann möglichst effektiv?

Wenn du im Entwickler-Modus startest (Kommandozeilenargument /console), dann ist direkt im Hauptfenster ein Eingabefeld.

Zum ID suchen kannst du bei entpackten Paketen eine einfache Textinhaltsuche auf DefCore.txt-Dateien machen (z.B. mit grep).

Du kannst in der Commandozeile der Engine (… wenn du aus dem Entwicklermodus startest) jeden Script eingeben.
Also das Fenster, wo man auch den Pinsel zum Kartenzeichnen hat. Dieses Texteingabefeld im unteren Bereich.

Man kann sich relativ schnell eine Funktion schreiben, zum Testen.

func TestForID(id tid){

var pIDTest = CreateObject(tid,0,0,-1);

if(pIDTest){
   RemoveObject(pIDTest);
   return true;
} else {
   return false;
}
}


Aber vermutlich entsteht schon bei CreateObject ein Fehler, falls die ID nicht existent ist. Von daher sollte auch einfach CreateObject() reichen. :smiley:

EDIT:
Ach so, es wird natürlich keine Auskunft über den Ort geben, hab ich irgendwie überlesen… Aber du weißt dann wenigstens, ob das Object in den Vorgaben vorhanden ist…

Wie Luchs meinte: Einfach irgendein Szenario im Entwicklermodus starten.

Du bekommst den Namen zu einer ID per GetName, also zB GetName(0, DSFK). Den Rest musst du raten :slight_smile:

Danke für den Hinweis mit dem entpackten Dateien, das ist natürlich eine gute idee. Nur leider funktioniert das entpacken großer Objektpakete selten. Es dauert einige Minuten und danach funktionieren viele Dinge nicht mehr (weil fehlerhaft entpackt) -.-  zum Glück sichere ich die Dateien immer, bevor ich das entpacken versuche, sodass ich es rückgängig machen kann.  Das heißt entpacken kann ich nur kleinere Pakete fehlerfrei, aber auch das mache ich wenn möglich immer wieder rückgängig, um fehler zu vermeiden.

Was meint ihr mit "entwickler Modus" ?  Soweit ich sehe gibt es doch nur das Spiel und den Editor. Ist der Editor nicht automatisch im Entwicklermodus?
Beim Editor ist unten ein Eingabefeld. Soll ich da was reinschreiben? Wenn ich "LocateFunc("AddLight")" reinschreibe und Enter drücke, wird automatisch die Clonk.exe vorgeschoben und das Spiel startet, also ist das wohl nicht das richtige feld?

Danke auch an Gecko für die Funktion, ich brauch aber halt den Ort selbst. wenn eine ID fehlt, dann merke ich das meistens auch im Testspiel selbst, wenn die entsprechene Fehlermeldung kommt.

EDIT: achso, also ein Spiel aus dem Editor aus starten und dann in diesem Engine Fenster die Funnktion LocateFunc("AddLight") eingeben. mache ich jetzt mal, und editere dann hier.
Edit2: hab den Ort nun gefunden, Space Empire.c4d\Hazard.c4d\Effects.c4d\Light.c4d\Script.c:98     dann schau ich dort mal rein :slight_smile: danke.

So…

im Skript vom Lichtobjekt mit der ID LIGH steht unter anderem:
global func AddLight(int iSize, int iColor, object pTarget) {
  if(!pTarget)
    if(!(pTarget = this()))
      return();
 
  return(CreateLight(LIGH, iSize, iColor, pTarget));
}


die Category in der Defcore vom Objekt LIGH , ist “C4D_Foreground|C4D_MouseIgnore|C4D_Vehicle”.

So, die Funktionsweise von “abreißen” ist in einem Clonk appendto so gergelt:

/* Gebäude-Abriss */

public func ContextDestruction()
{
  [Abreißen|Image=SYF1|Condition=BackAnything]
  var obj = BackAnything();
  if (!obj) return(1);
  CreateMenu(SYF1);
  AddMenuItem("%s abreißen",“DoDestruction”,GetID(obj),0,0,obj);
  AddMenuItem(“Zurück”,“NoDestruction”,SYCC);
}

private func BackBuilding()
{
  var obj;
  while (obj = FindObjectOwner(0,GetOwner(), -1,+9,0,0, OCF_Exclusive(), 0,0,obj))
//    if (GetCategory(obj) & C4D_Structure())
//      if (GetCon(obj) >= 100)
        if (!FindObject(DSTR,0,0,0,0,0,“Destruct”,obj))
          return(obj);
  return(0);
}

private func BackConstruct()
{
  var obj;
  while (obj = FindObjectOwner(0,GetOwner(), -20,+8,40,5, OCF_Construct(), 0,0,obj))
//   if (GetCategory(obj) & C4D_Structure())
      if (!FindObject(DSTR,0,0,0,0,0,“Destruct”,obj))
        return(obj);
  obj = 0;
  while (obj = FindObjectOwner(0,GetOwner(), -1,+9,0,0, OCF_Construct(), 0,0,obj))
//    if (GetCategory(obj) & C4D_Structure())
      if (!FindObject(DSTR,0,0,0,0,0,“Destruct”,obj))
        return(obj);
  return(0);
}

private func BackAnything()
{
  var obj = BackBuilding();
  if (obj) return(obj);
  return(BackConstruct());
}

private func DoDestruction(par0, target)
{
  CreateObject(DSTR)->DoDestruction(target);
}

private func NoDestruction() {}


genauer ist das dann unter SpaceEmpire bzw. StarEmpire /Genereal/Structures/Destruction geregelt, aber das ist hierfür unwichtig.

In dem oben genannten Skript wird recht lang beschrieben, was abgerissen werden kann.
Ich kenn mich wie ihr wisst noch nicht so gut aus, habe aber das Gefühl, dass man das besser lösen kann.  Das Problem ist nämlich, dass hier definiert wird, dass nur Dinge die im DefCore “Exclusive” stehen haben, abgerissen werden können.  Das ist aber nicht gut, weil dann Dinge wie ein Amboss und ähnliche kleine Objekte nicht abgerissen werden können.  Deswegen habe ich den Eintrag “OCF_Exclusive()”  durch “(GetCategory(obj) & C4D_Structure())” erstetzt.  Danach können auch der Amboss und CO abgerissen werden. Nur dummerweise sorgt dies auch dafür, dass Lichter abgerissen werden können, was ich nicht ganz verstehe, da das “LIGH” Objekt kein Gebäude ist…

Also woran liegt es und/oder wie könnte man das Skript fürs abreißen abändern, sodass alle Gebäude abgerissen werden können, aber nicht die Lichter… Ich hatte an einen Befehl gedacht, der prüft, ob in der defCore “Construction=1” steht, aber sowas gibt es leider nicht =/  http://crdocs.clonkspot.org/de/sdk/definition/ocf.html
Alternativ könnte ich natürlich auch irgendwie das Licht verändern, wenn ihr da Ideen zu habt… aber ich will da natürlich auch nichts kaputtmachen =/

>Ich hatte an einen Befehl gedacht, der prüft, ob in der defCore "Construction=1" steht, aber sowas gibt es leider nicht =/


Doch: http://crdocs.clonkspot.org/de/sdk/script/fn/GetDefCoreVal.html

>Nur leider funktioniert das entpacken großer Objektpakete selten. Es dauert einige Minuten und danach funktionieren viele Dinge nicht mehr (weil fehlerhaft entpackt) -.-


Huh. Du könntest vielleicht mal versuchen, direkt mit c4group zu entpacken. Also über die Kommandozeile `c4group foo.c4d -x`

danke, das kannte ich noch nicht, werde ich morgen mal testen, ob ich das damit schaffe. Falls nicht melde ich mich nochmal :slight_smile:

die Seiten der Entwickler Dokumentation sind ziemlich unübersichtlich und ich hab das Gefühl, dass man sich nur von Begriff zu Begriff hangeln kann…
ich meine, wenn ich etwas noch nicht kenne, wie jetzt z.b den Befehl zu "GetDefcoreVal" oder auch die von mir zuvor geposteten "Object Character Flags", wie finde ich sowas dann vernünftig? Ich speicher mir schon für alles wichtige Lesezeichen ab… hatte aber z.b für die "Object Character Flags" noch eine richtige Liste gefunden gehabt, die ich nun nicht mehr wiederfinde =/

ich finde “Funktionen nach Kategorie” hier eigentlich ganz ok.

> auch die von mir zuvor geposteten "Object Character Flags", wie finde ich sowas dann vernünftig?


Irgendwie muss die Doku sortiert sein. Alle Funktionen findest du am besten "nach Kategorie" (in "Script"), alles was nicht Funktion ist (also z.B. OCF, das sind nur benannte Konstanten), ist möglichst nach Logik einsortiert: OCF betrifft Objekte (Object Character Flag), daher Objektdefinitionen aufklappen. OCF ergeben sich auf DefCore und dem Spielstatus, darum DefCore aufklappen. Und da sind OCF eingeordnet. Ansonsten ist diese Inhaltsübersicht auch nicht so riesig verschachtelt, als dass man nicht alles mal durchklicken könnte. Mit Doppelklick kannst du alles auf einmal aufklappen.

okay, danke an dich und Pyrit.

ist ein bisschen unglücklich gemacht, dass man nicht auf die schrift von "Funktionen nach Kategorie" klicken kann, um es zu öffnen. So habe ich es tatsächlich übersehen, weil ich dachte es funktioniert nicht.

Das ist, weil die Überschriften in einigen Fällen auch eigene Übersichtsseiten haben.

so ich komm nicht weiter =/
ist das hier denn richtig? :
GetDefCoreVal("Construction", "DefCore");

ich wollte prüfen, ob das der richtige Wert ist, also ob 0 oder 1 dabei rauskommt, wenn die Funktion in der es steht aufgerufen wird, aber selbst das hab ich nicht hinbekommen =( (habe es in die Funktion Backbuilding eingetragen)
Wollte es mit "Log()" machen. Aber ich wieß nicht, was ich da dann eintragen muss.
Habe es dann mit

var con;
con = GetDefCoreVal("Construction", "DefCore");
Log(con);


probiert, aber das spuckt nichts aus. Dann dachte ich mir, vllt ist ja iwas falsch und es gibt keinen Wert, deshalb wollte ich dann den Variablen Wert mit dem Wort "test" zusammen als Lognachricht haben, aber keeeeine ahnug, wie das geht, ständig gab es nur syntaxfehler…  Wenn ich Log("con") schreibe, dann gibt er mir das Wort "con" aus, aber ich will ja den Wert der Variablen haben.

Ach und ich würde es dann eigentlich wie folgt schreiben:
private func BackBuilding()
{
  var obj;
  while (obj = FindObjectOwner(0,GetOwner(), -1,+9,0,0, OCF_Exclusive(), 0,0,obj))
//    if (GetCategory(obj) & C4D_Structure())
//      if (GetCon(obj) >= 100)
       if (!GetDefCoreVal("Construction", "DefCore") = 0)
        if (!FindObject(DSTR,0,0,0,0,0,"Destruct",obj))
          return(obj);
  return(0);
}

Aber das wirft aktuell noch einen Fehler aus, iwas mit der linken Seite des Gleichheitszeichen, dass ein & erwartet würde, aber keine ahnung warum.
Ich möchte, dass er letzlich weitermacht und das obj im return angibt, wenn der Wert von Construction im DefCore nicht Null ist. (wenn garkein Construction drin steht, ist er automatisch Null, oder produziert das einen Fehler?)

       if (GetDefCoreVal("Construction", "DefCore",GetID(obj)) != 0)
So müsste es sein. Nur " = " würde den Wert auf 0 setzen.
Das Ausrufezeichen für "Nicht" kann direkt vor das Gleichheitszeichnen, Sprich: "Ist Nicht". :slight_smile:
Und bei GetDefCoreVal hat der dritte Parameter gefehlt. Quasi die Referenz, bei welchem Objekt die Werte abgefragt werden sollen…

Um mit der Log Funktion Variablen auszugeben, musst du es wie mit dem Format Befehl angeben, also z.b.:
                  
                       
var con = GetDefCoreVal(“Width”, “DefCore”,WOOD);
Log("%v", con);

Super danke, das funktioniert =)

Ich sehe gerade die "Reparieren" Funktion, funktioniert auch für Fahrzeuge, was ja auch sinnvoll ist.  Dummerweise wird das Licht wohl auch als Objekt Fahrzeug gesehen (im gegensatz zu der Gebäude Definition steht "C4D_Vehicle" sogar im DefCore von dem Lichtobjekt, aber keine Ahnung, wie wichtig das ist und ob man es entfernen könnte…).  Also brauche ich nun etwas, dass bei allen Fahrzeugen vorhanden ist.  Bin gerade mal die DefCore verschiedener Fahrzeuge durchgegangen. Es gibt den Eintrag "VehicleControl", dessen Wert halt 0, 1 oder 2 sein kann. 

Leider hat z.b eine Lore den Wert Null (bzw. der Eintrag ist nicht vorhanden). würde es schaden, wenn ich einfach bei jedem Fahrzeug, wo dieser Eintrag nicht vorhanden ist, den Wert auf 1 setze?

Oder gibt es noch was anderes, was alle Fahrzeuge gemeinsam haben, abgesehen von der Objektdefintion Vehicle?

Edit:
Falls es da keine vernünftige Lösung gibt, könnte ich auch versuchen Eigenschaften die nur das Licht hat auszuschließen. Aber versuchen wir es erstmal so, weil glaube ich ab und zu sogar verbrannte/tote Bäume als Ziel vom reparieren angezeigt werden.

dankesehr =)