[Gelöst] Reparatursymbol aus Erweiterungspack

Damit der "AddLight" Thread nicht zu unüberischtlich wird, mache ich für das neue Thema des Reparatursymbols einen neuen Thread auf. Ich verwende Wissen, welches mir im "AddLight" Thread mitgeteilt wurde :slight_smile:

Das Origianlscript sieht wie folgt aus, wobei "Warn" im ActMap" definiert und "TimerCall=Fading, Timer=5" im DefCore.

#strict

local iAlpha,iChange,pTarget,iMaxDamage,iYPos;

protected func Initialize()
{
  if(GetOwner() != NO_OWNER()) SetVisibility(VIS_Owner());
  SetAction("Warn");
  iChange= -20;
}

private func Fading()
{
  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) return(RemoveObject());
  if(WildcardMatch(GetName(pTarget),"Verbrannt*") ||
     WildcardMatch(GetName(pTarget),"Abgebrannt*") ||
     WildcardMatch(GetName(pTarget),"Burned*"))
      return(RemoveObject());
  SetPosition(GetX(pTarget),GetY(pTarget)+iYPos);
  var value= Min(GetDamage(pTarget),iMaxDamage)255/iMaxDamage;
  iAlpha= BoundBy(iAlpha+iChange,0,255);
  SetClrModulation(RGBa(255,255-value,255-value,iAlpha));
  if(iAlpha == 0) return(iChange= +20);
  if(iAlpha == 255) return(iChange= -20);
}

global func Damage(a,b,c,d,e,f,g,h,i)
{
  if(GetDefCoreVal("Construction","DefCore",GetID()))
   if(GetDamage())
    if(!GetEffect("IntRepairMarker",this()))
     if(!WildcardMatch(GetName(),"Verbrannt
"))
      if(!WildcardMatch(GetName(),"Abgebrannt*"))
       if(!WildcardMatch(GetName(),"Burned*"))
        if(GetName() ne "Fundament")
         if(GetName() ne "Basement")
          {
          var sign= CreateObject(REPA,0,0,GetOwner());
          LocalN("pTarget",sign)= this();
          LocalN("iMaxDamage",sign)= GetDefCoreVal("BlastIncinerate","DefCore",GetID());
          LocalN("iYPos",sign)= GetDefCoreVal("Offset","DefCore",GetID(),1)-20;
          AddEffect("IntRepairMarker",this(),1);
          sign-> Fading();
          }
  return(_inherited(a,b,c,d,e,f,g,h,i));
}


Ich denke wichtig für die Kriterien ist hier nur die Damage Funktion, wofür stehen diese buchstaben a,b,c,…usw?
Nun möchte ich, dass auch Fundamente und Fahrzeuge dieses Symbol bekommen, wenn sie beschädigt sind. Für Fundamente muss ich lediglich die "ne"Fundament" Befehle rausnehmen.  Für Fahrzeuge müsste ich meine "IsRepa" Funktion als Bedingung einfügen. normalerweise würde ich das über:
"if ( obj->~IsRepa())"
machen, aber hier wird kein obj als variable verwendet, weshalb es möglicherweise zu Problemen mit den restlichen Befehlen kommen könnte, wenn ich nun überall (wo genau?) obj einfüge…?!

Dann habe ich überlegt, ob ich einfach dieselbe Bedingungen nehme, wie im AddLight Thread dafür, dass etwas überhaupt repariert werden kann, also:
if(FindObject2(Find_Distance(90), Find_NoContainer(), Find_Or(Find_Func("GetDefCoreVal", "Construction", "DefCore"), Find_Func("IsRepa"), Find_Func("IsBasement")), Find_Or(Find_Owner(GetOwner()), Find_Owner(NO_OWNER)), Find_Func("GetDamage"))
anstelle von nur "if(GetDefCoreVal("Construction","DefCore",GetID()))".
Das klappt auch so weit fast. Über Gebäuden und Fundamenten erscheint das Symbol, aber nicht über Fahrzeugen. Welcher der Befehle in dieser Damage Funktion verhindern, dass es bei Fahrzeugen angewendet wird?

Ein weiteres Problem ist, dass dieses Symbol nur einmal pro Spiel angezeigt wird. Also das Objekt ist beschädigt und das Symbol wird angezeigt. Wenn ich es nun repariere verschwindet es, so weit so gut. Aber wenn ich es dann wieder beschädige, taucht das Symbol nicht mehr auf, das ist auch schon im Original so. Was muss hinzugefügt werden, damit das Symbol immer da ist, wenn ein Gebäude beschädigt ist, egal wie oft es schon repariert wurde?

>Ich denke wichtig für die Kriterien ist hier nur die Damage Funktion, wofür stehen diese buchstaben a,b,c,...usw?


Die stehen tatsächlich für gar nichts. Was hier passiert, ist dass eine globale (d.h. für alle Objekte gültige) Damage-Funktion definiert wird. Ganz unten wird mit einem Aufruf an `_inherited` evtl. eine gleichnamige Funktion aufgerufen, die von dieser Funktion überschrieben wurde. Das passiert typischwerweise, wenn man mit einem `#appendto` eine Funktion neu definiert, aber die alte Funktionalität immer noch benötigt. Funktionsparameter müssen dabei explizit durchgereicht werden. CR hat dafür auch eine Abkürzung, nämlich `_inherited(...)`, womit alle nicht genannten Parameter der Funktion durchgereicht werden.

>hier wird kein obj als variable verwendet


Hier wird implizit auf den aufrufenden Objekt `this` gearbeitet. Die meisten Funktionen, die irgendetwas mit Objekten anfangen, machen das standardmäßig mit `this`, wenn man kein anderes angibt.

>Welcher der Befehle in dieser Damage Funktion verhindern, dass es bei Fahrzeugen angewendet wird?


Ich glaube, Fahrzeuge haben kein `Construction` in ihrer DefCore.

>Was muss hinzugefügt werden, damit das Symbol immer da ist, wenn ein Gebäude beschädigt ist, egal wie oft es schon repariert wurde?


Das hängt vermutlich irgendwie mit der Implementierung von dem `IntRepairMarker`-Effekt zusammen. Vielleicht wird der nicht richtig entfernt oder so?

Vielen dank, dass du dich nun auch diesem Problem angenommen hast =)

Danke für die Erklärung :)

> Ich glaube, Fahrzeuge haben kein Construction in ihrer DefCore.


ja richtig, deswegen hab ich das ja bereits durch unsere Bedingungen ersetzt, siehe oben ;)  Und der Fehler, dass das appendto falsch ist, kann es nun eig nicht mehr sein, da das reparieren an sich ja nun einwandfrei funktioniert…  Aber vllt steckt ja noch ein anderer fehler drin… hm…

> Das hängt vermutlich irgendwie mit der Implementierung von dem IntRepairMarker-Effekt zusammen. Vielleicht wird der nicht richtig entfernt oder so?


jaa… das klingt logisch… Ich hab hier das komplette Script dieses Objekts "REPA" gepostet. Die Reparatur an sich, welche wir im anderen Thread behandelt haben, steht in einem appendto für Clonks. 
Es müsste also irgendwo einen Befehl geben, dass der IntRepairMarker-Effekt aufgehoben wird?  Nach der Reperatur wird das Zeichen ja entfernt. Also gibt es etwas, das bereits feststellt, dass das Objekt nicht mehr beschädigt ist und entfernt das Zeichen. Nun müsste es aber auch diesen IntRepairMarker-Effekt entfernen, richtig?
Steht die "entfernung des Zeichens" in dem oben geposteten Script?  Oder sollte ich dafür nochmal im Clonk appendto nach suchen?

Die Definition des Effekts, also die FxIntRepairMarker...-Funktionen, sind an der Stelle interessant. Guck dir die mal an bzw. poste sie hier.

dazu müsste man die Funtktion ersteinmal finden…

LocateFunc("IntRepairMarker")

Func IntRepairMarker not found
-> LocateFunc("IntRepairMarker")
= true


So klappt es schonmal nicht… aber das ist ja, wie ich in meinem "radioaktiv" Thread gelernt habe, ein Effekt. Die Funktion wird also vermutlich so aussehen:

Func FXIntRepairMarker     und dann noch Timer/Effect/Damage/Add…
ich probier für diese 4 begriffe nochmal eine Suche durch und schaue, ob ich sie finde und editiere dann hier.

Edit:
nein, auch folgendes findet die Funktion nicht:
LocateFunc("FxIntRepairMarkerDamage")

LocateFunc("FxIntRepairMarkerTimer")

LocateFunc("FxIntRepairMarkerEffect")

LocateFunc("FxIntRepairMarkerAdd")

LocateFunc geht nur mit globalen Funktionen, glaube ich.

Ich schätze die Funktion steht im selben Objekt wo auch der passende AddEffect-Aufruf dazu steht. Man muss bei AddEffect nämlich angeben, wo der Effekt definiert ist. Und wenn man nichts angibt, dann ist die Funktion entweder global oder im lokalen Objekt.

das “problem” ist halt, dass das hier im ersten Post gepostete Script das komplette Script dieses “REPA” Objekts ist. Dort steht der “AddEffekt” befehl drin, aber die Funktion dazu steht dort nirgends…

edit:
das Objekt begindet sich in diesem Pack: https://ccan.de/ unter “appends/Clonks”  (keine ahnung wie ccan links gehen… in die Suche “Erweiterungspack” eingeben)

Zu diesem Pack werde ich iwann auch noch ein paar fragen stellen, denn ein paar Dinge daraus funktionieren nicht, bzw. geben viele Fehler aus. Aber darum kümmere ich mich ganz zum schluss.

Es könnte natürlich auch sein, dass der Effekt nirgendwo definiert ist und nur mal eine gute Idee war. Das hätte dann den Effekt, dass er erstellt wird und dann nicht tut, außer weitere Reparierversuche zu stoppen. Versuche alternativ einfach mal, den AddEffect-Aufruf zu entfernen und schau, ob dann irgendwas dabei kaputt geht.

hab meinen vorherigen Post mal erweitert und dort den Link zum Pack gepostet. (Erweiterungspack)

Wenn ich den Befehl wegnehme, würde das doch dafür sorgen, dass das REparatursymbol unendlich oft über beschädigten Gebäuden gespawnt wird, oder nicht?
Traue mich gerade nicht es auszuprobieren, weil ich es gerade nicht brauchen kann, dass der Computer dadurch mal wieder abschmiert :D   aber vllt probiere ich es später, bevor ich den pc eh ausschalten will.

Ah, das könnte natürlich sein %)

Aber eigentlich wird Damage() ja nur einmal pro Schadensquelle aufgerufen, d.h. solange du nicht unendlich viele Flints draufwirfst, bist du eigentlich auf der sicheren Seite.

okay, es ist so wie du sagst.
Das heißt wenn ich 10 Flints draufschmeiße, dann ist das Symbol 10 mal da, übereinandergestapelt.
Normalerweise blinkt das Symbol langsam. Durch das stapeln blinkt es dann natürlich nicht mehr, aber es verschwindet wie gewünscht nach der Reperatur und taucht wieder auf, wenn das Gebäude wieder beschädigt wird.

Ich denke so könnte man es spielen…  schöner wäre es aber natürlich, wenn man es anders lösen würde.
Man kann doch eigentlich einfach einen Effekt passend dazu erstellen, der nichts macht, außer eben zu verhindern, dass ein zweites Symbol auftaucht. 
Nur müsste man diesen Effekt dann eben auch wieder entfernen, wenn das Symbol entfernt wird (weil es repariert wurde).

>Man kann doch eigentlich einfach einen Effekt passend dazu erstellen, der nichts macht, außer eben zu verhindern, dass ein zweites Symbol auftaucht.


Macht der IntRepairMarker-Effekt nicht genau das? :)

ja stimmt schon, aber ich dachte man muss vllt noch die Funktion dazu erstellen, um ihn wieder zu entfernen ^^  aber falls das nicht nötig ist, müssen wir den Effekt natürlich nicht erstellen.
Die hauptsache ist, dass wir ihn wieder entfernen, sobald das Gebäude repariert ist. Und da Luchs dazu bisher vermutlich noch keine Idee hatte, ohne die Funktion des Effects zu sehen, dachte ich, dass wir eine Funtkion daztu erstellen müssen :wink:

Effekte ohne Funktionen dafür haben eine lustige Eigenschaft:
Sie werden entfernt, wenn das erste mal die Fx*Timer Funktion aufgerufen werden würde.

In deinem Fall ist der Intervall-Parameter von AddEffect aber 0! Also wird die Timerfunktion nie aufgerufen und der Effekt nie von alleine entfernt.
Dann müsste man sich darum kümmern den Effekt selbst per RemoveEffect irgendwann zu entfernen.

okay, danke für die Erklärung.

> Dann müsste man sich darum kümmern den Effekt selbst per RemoveEffect irgendwann zu entfernen.


Genau das sag ich doch von anfang an :D =P
Die Frage ist nur wo man das einbauen kann. Am sinnvollsten wäre es, wenn wir rausfinden, wodurch das Zeichen über dem Gebäude wieder entfernt wird. Denn das geschieht ja nach der Reperatur. Direkt dort müsste man dann ebenfalls dien RemoveEffect Befehl hinschrieben.
Daher nun folgende Frage: steht in dem hier im ersten Post geposteten Skript, was mit diesem "sign" passiert? In der funktion Fading wird glaube ich beschrieben, wie sich die Farbe anpassen soll.
Wird es aber auch irgendwo entfernt? Oder wird es nur unsichtbar bei Reperatur gemacht? Habs grad mal getestet, es wird irgendwo im Skript entfernt, zumindest wird es nicht unsichtbar, weil es dann durch Schaden ja wieder sichtbar werden müsste und zusätzlich ein neues Symbol kommen, aber das tut es nicht.

>>Welcher der Befehle in dieser Damage Funktion verhindern, dass es bei Fahrzeugen angewendet wird?


>Ich glaube, Fahrzeuge haben kein Construction in ihrer DefCore.


Ich hab das Problem zufällig gerade gefunden. Weil z.b der Amboss auch kein Symbol erhält. Ich hab dem Amboss aber neuerdings ein Basement zugeteilt. Nun erscheint das Symbol. Nach etwas Tüftelei hab ich jetzt rausgefunden, dass das Symbol nur erscheint, wenn das Objekt im Skript die Damage() Funktion beinhaltet.
Ich schreibe  per appendto also nun einfach in alle Fahrzeuge:

protected func Damage()
{
inherited();
}


Dadurch erscheint das Symbol und es sollte keine weiteren Auswrikungen haben, richtig?

Mir ist im Script das "RemoveObject" aufgefallen. Das sorgt offensichtlich dafür, dass das Zeichen entfernt wird, z.b hier:

  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) return(RemoveObject());

Letzlich müsste man vermutlich einfach nur noch das RemoveEffect dort hinzufügen. Aber wie mache ich das hier?  Ich kann in die Klammern von return ja keine 2 Dinge reinschreiben, oder?  Und wenn ich return weglassen und einfach:

  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) {RemoveObject() && RemoveEffect()};

schreibe, dann fehlt ja das return, welches mit ausgeführt werden soll wenn die if Bedingung erfüllt ist…
kann ich denn schreiben:

  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) {RemoveObject() && RemoveEffect() && return(1)};

Ich probiere letzteres mal eben aus und editiere dann hier.

edit:
okay, hab vergessen, dass man hier kein && verwendet, dewegen jetzt:

  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) {RemoveObject() ; RemoveEffect() ; return(1)};

dennoch kommt die Fehlermeldung:ERROR: ';' expected, but found '}' (in Fading, C:[…]\Reparatur.c4d\Script.c:14:103)

edit2:
achso, nach dem letzten Befehl kommt auch noch ein ;  :

  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) {RemoveObject() ; RemoveEffect() ; return(1);};

edit3:
habe es jetzt noch zusätzlich mit dem effektnamen, also RemoveEffect("IntRepairMarker")  versucht, aber es wirkt nicht… der Effekt wird offensichtlich nicht entfernt, da das Symbol nach Reparatur und weiterer Beschädigung nicht wieder auftaucht…
aber das Symbol selbst verschwindet nach der Reparatur, woraus ich schließe, dass "remove Object" ausgeführt wird. Demnach muss Removeeffect eigentlich auch ausgeführt werden… hmm…

Edit 4:
habe nun noch ein wenig herumexperementiert.
Wenn dort steht:
  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) return(1);
oder auch
  if(!pTarget || !GetDamage(pTarget) || OnFire(pTarget)) return(RemoveEffect());

dann hat das zur Folge, dass das Symbol nach der Reperatur nicht entfernt wird. Soweit so gut. Aber wenn der Effekt entfernt wurde, müsste das eigentlich zur Folge haben, dass das Zeichen nach Reperatur und nochmaliger Beschädigung nun 2 mal vorhanden ist usw. 
Wichtig zu wissen ist vermutlich noch, dass das Symbol langsam blinkt (Sichtbarkeit wird langsam immer durchsichtiger und dann wieder sichtbarer). Wenn es repariert wurde, dann bleibt es in dem Durchsichtigkeitsstand stehen, wie es in der Sekunde der Reperatur der Fall war. 
Wenn ich es nun abermals beschädige, dann fängt es einfach ganz normal wieder an zu blinken. Es entsteht kein zweites Symbol.

Für mich ergibt das gerade recht wenig Sinn… einzig der Gedanke kam mir, dass das Zeichen (also das Objekt REPA) und der Effekt, eigentlich gekoppelt sein sollten. Das könnte der Grund sein, weshalb man den Effekt nicht mit RemoveEffect wegbekommt… aber mit REmoveOjvekt geht er ja leider auch nicht weg…
Oder hab ich einen Denkfehler?

Das kommt mir seltsam vor. In dem Fall solltest du aber lieber eine leere Funktion nur an die Objekte hängen, die betroffen sind.

Ohne inherited?  wird dadurch dann nicht die alte Damagefunktion (falls vorhanden) überschrieben wodurch Fehler entstehen können, weil dann nichts mehr gemacht wird, anstelle der ursprünglichen Dinge, die bei Damage passieren sollen?

>aber das Symbol selbst verschwindet nach der Reparatur, woraus ich schließe, dass "remove Object" ausgeführt wird. Demnach muss Removeeffect eigentlich auch ausgeführt werden... hmm..


`RemoveEffect` will auch wissen von welchem Objekt du den Effekt entfernen willst