[Gelöst] Objekt soll sich selbst löschen

/– Nebel erzeugen –/

#strict

protected func Initialize()
{
  // Eigene Position festlegen
  SetPosition();
  return(1);
}

/* Eventuell Nebel erzeugen */
private func DoNebel()
{
  if(ObjectCount2(Find_ID(NB9Z))>=5) {RemoveAll(NBL1);}
else {CreateObject(NB9Z);Log("Nebelerzeuger erzeugt Nebel");}
return(1);
}


Dieses Skript soll einfach nur bis zu 5 Nebelobjekte erstellen. Sobald es 5 oder mehr Nebelobjekte gibt, soll es sich selbst (NBL1) vernichten.
Aber offensichtlich klappt das so wie im Skript beschrieben nicht, denn der Nebelerzeuger NBL1 ist auch nachdem 5 Nebelobjekte erstellt worden sind da (keine Fehlermeldung).

Ich hab es auch schon versucht mit:
private func DoNebel()
{
  if(ObjectCount2(Find_ID(NB9Z))>=5) {Destruction();}
else {CreateObject(NB9Z);Log("Nebelerzeuger erzeugt Nebel");}
return(1);}

func Destruction()
{
RemoveAll(NBL1);
}


Aber sobald dann das zweite NBL1 Objekt ins Spiel kommt (durch eine andere Regel, eigentlich sollte es maximal 1 NBL1 geben können, da es sich ja selbst entfernen soll und auch im DefCore MAxUserSelect 1 ist), kommt ein:
ERROR: internal error: value stack overflow! by: Destruction()

Also wie kann sich das Objekt nach getaner Arbeit selbst vernichten?

Edit:
habe es grad nochmal mit :
func Destruction()
{
RemoveAll(NBL1);
return();
}

probiert, weil das bei der Anleitung von RemoveObject steht, dass man return() schreiben soll, wenn sich ein Objekt selbst löscht, aber es kommt trzd. noch dieselbe Fehlermeldung =/

Von wo wird denn DoNebel() aufgerufen? Wird das auch noch aufgerufen, wenn 5 Nebelobjekte vorhanden sind? An und für sich müsste die erste Version funktionieren, auch wenn sie unübersichtlich geschrieben ist:

> / Eventuell Nebel erzeugen /
> private func DoNebel()
> {
>   if(ObjectCount2(Find_ID(NB9Z))>=5) {RemoveAll(NBL1);}
> else {CreateObject(NB9Z);Log("Nebelerzeuger erzeugt Nebel");}
> return(1);
> }


Destruction(); ist ein Enginecall, d.h. die Funktion wird von der Engine unter bestimmten Bedingungen aufgerufen, daher ist es in der Regel eine schlechte Idee, den Aufruf manuell zu machen. Genauer gesagt wird Destruction() aufgerufen, wenn das Objekt zerstört (RemoveObject) wird. Deswegen ist folgendes auch eine besonders schlechte Idee:

> func Destruction()
> {
> RemoveAll(NBL1);
> return();
> }


Was passiert? Du rufst Destruction() auf, deine Destruction-Funktion zerstört sodann das Objekt (RemoveAll), weil das Objekt zerstört wird, wird Destruction von der Engine im Objekt aufgerufen, Destruction führt wieder RemoveAll aus, das Objekt wird "noch mal" zerstört, es wird wieder Destruction aufgerufen usw. Die Engine stürzt davon nur nicht ab, weil nach einer bestimmten Anzahl von Kreisläufen aus Destruction und RemoveAll automatisch unterbrochen wird, weil der Speicher voll ist (stack overflow).

okay, danke, dann weiß ich jetzt zumindest schonmal, wo der ERROR herkommt =)
Und ja, "DoNebel" wird durch einen Timercall aufgerufen. D.h. auch wenn schon 5 oder mehr Nebelobjekte da sein sollten, wird sie aufgerufen, nur soll sie sich dann ja eig selbst zerstören.

Das Nebelobjekt selbst hatte übrigens ebenfalls einen Selbstzertörer eingebaut (habe ich nicht selbst erstellt, habe den selbstzerstörer mittlerweile entfernt). Das hatte vorher für Probleme mit meiner Zählfunktion hier gesorgt, weil er die Nebelobjekte so nicht zählen konnte und dadurch unendlich Nebel auf dem Spielfeld landet.  Allerdings habe ich selbst noch eine Destruction() Funktion in das Nebelobjekt eingebaut, in dem dann "ClearParticels("Nebel") und ResetGamma aufgerufen werden.  Das funktioniert auch soweit, wenn ich den Nebel (über eine andere Regel) entferne, dann verschwindet sowohl das Umweltobjekt, als auch der Nebel selbst.
Wenn sich dich das Nebelobjekt aber selbst zerstört, verschwindet offensichtlich nur das Objekt (lässt sich nicht mehr zählen), aber die Nebel Partikel bleiben vorhanden.

So ähnlich verhält es sich glaube ich auch mit meinem Nebelerzeuger NBL1. Jedenfalls ist es so, obwohl er sich eigentlich selbst zerstören soll, produziert er sofort neuen Nebel, wenn ich die Nebelobjekte entferne (weil dann ja wieder weniger als 5 Nebel da ist), obowhl der Nebelerzeuger schon längt gelöscht sein sollte.

EDIT:
habe es jetzt anders gelöst. Habe insg. 4 Objekte, die den Nebelvorgang steuern (soviele, weil ich unterschiedliche Timer brauche und nicht wusste, dass man durch Effekte mehr Timer machen kann, muss mich dann denmächst mehr mit effekten beschäftigen). Jedenfalls entfernen die sich jetzt immer gegenseitig, wobei ein Objekt dauerhaft vorhanden ist, aber das muss es ohnehin.
Letzlich habe ich jetzt eine Regel, die folgendes macht:
Alle 10.000Frames wird mit einer Chance von 1 zu 2 zwischen 0 und 6 Nebelobjekte erzeugt. Diese Werden dann alle 1003Frames mit einer Chance von 1 zu 3 wieder entfernt. usw. usw. =)

noch eine Frage:

Ich sehe gerade, dass auch bei anderen Umweltobjekten (z.b. Armageddon) im Initialize steht, dass wenn bereits ein Objekt vorhanden ist, es sich selbst löschen soll. Ich hab erst jetzt kapiert, dass das offensichtlich dazu da ist, damit wenn mehrere der Objekte erstellt werden, sich nur eines um die "Initialize"-daten kümmert.

Nun will ich aber auch Armageddon wie den Nebel nutzen, sodass eben immer mal ein paar (damit es mehr Meteoriten werden) solcher Regeln erstellt werden. Wenn die sich aber bis auf 1 immer wieder selbst löschen, kann ich sie nicht zählen.
Also kann ich ohne Bedenken die Selbstzerstörung entfernen?welche Auswirkungen hat das? z.b jetzt bei Armageddon :

/– Armageddon –/

#strict

local iStrength;

protected func Initialize()
{
  // schon ein Steuerungsobjekt da?
  iStrength = 1;
  SetPosition(0,0);
  var obj = FindObject(GetID());
  if (!obj) return(1);
  // sich selbst dazuzählen
  obj->AddOne();
  RemoveObject();
}

public func AddOne()
{
  ++iStrength;
}

protected func DoMeteors()
{
  if ((Random(5)+5) >= iStrength) return(1);
  var obj = CreateObject(METO, Random(LandscapeWidth()), -20, -1);
  SetXDir(Random(51)-25+GetWind()/10, obj);
  SetYDir(Random(25), obj);
  SetRDir(Random(21)-10, obj);
}

Es macht nicht so arg viel Sinn, das zu löschen. Die Mengenkontrolle findet ja über die iStrength-Variable statt und es werden bereits mehr Meteoriten erzeugt, umso öfters die Regel erstellt wurde.

ja für armageddon scheint es egal zu sein, weil ja trzd. mehr Meteoriten erzeugt werden. Aber wenn ich eine eigene neue Regel erstellen will, die bis zu x mal Armageddonobjekte erzeugen soll, dann muss ich ja zählen, wie oft es bereits aktiviert ist. Aber ich kann es nicht zählen, solange hier RemoveObejct steht, weshalb ich es entfernen müsste.

Ist nur die Frage, ob ich dadurch was kaputtmache. Falls ja, müsste ich mir eine andere Methode überlegen, wie es nur bis zu einem Maximum Armageddon erzeugt wird… möglicherweise würde ich dann diese Zählvariable, die im Armageddon verwendet wird, global machen.

Warum soll eine andere Regel davon abhängen, wie oft die Meteoritenregel aktiviert wurde? Mach es doch dort einfach genauso und aktiviere die entsprechende Regel dann genauso oft?

Ansonsten kannst du die iStrength-Variable ja mit einer Funktion von außen erreichbar machen:

c4script<br/>public func GetStrength() {<br/>&#160; return iStrength;<br/>}<br/>

Dann musst du nur nach dem Objekt suchen und die Funktion aufrufen: FindObject(IDID)-&gt;GetStrength()