[Gelöst] Flagge prüfung ob bereits Flagge vorhanden?

Wo findet diese Prüfung statt?
Durch das star Empire Pack gibt es nun auch sogenannte "Uplinks", welche sozusagen die neue verbesserte Flagge sind. Diese haben einen Timercall "CheckBuilding", der sie dann eben aufs Gebäude setzt. Dort konnte ich auch brereits die Bedingung hinzufügen, dass sie sich nicht aufstellen, wenn bereits eine Flagge auf dem Gebäude ist.

Aber ich weiß nicht, wie die Flagge das ganze regelt. Ich würde halt gerne einstellen, dass die Flagge nur auf Gebäude geht, wenn dort eben noch kein Uplink ist.

(danke für die antworten im "etwas für jeden Spieler machen, der x erfüllt hat " Thread. Damit beschäftige ich mich dann die Tage :slight_smile: habe mal wieder 100 verschiedene Baustellen gleichzeitig offen :D   Habe gerade ein Abschließsystem über Schlüssel und Sensoren fertig angepasst und dem Uplinksystem die Möglichkeit zur Freigabe für alle NichtFeinde gegeben )

Soweit ich das sehe, pollt die Engine intern einfach nach Flaggen im Inventar bzw. in der Umgebung mit passendem Action-Target. Das kannst du im Source-Code unter engine/src/C4Object.cpp in C4Object::ExecBase nachlesen (der fettgedruckte Teil sollte für dich relevant sein, weil du damit nach Flaggen auf der Basis suchen kannst):

  C4Object *flag;;

  // New base assignment by flag (no old base removal)
  if (!Tick10)
    if (Def->CanBeBase) if (!ValidPlr(Base))
      if (flag=Contents.Find(C4ID_Flag))
        if (ValidPlr(flag->Owner) && (flag->Owner!=Base))
          {
          // Attach new flag
          flag->Exit();
          flag->SetActionByName("FlyBase",this);
          // Assign new base
          Base=flag->Owner;
          Contents.CloseMenus();
          StartSoundEffect("Trumpet",false,100,this);
          SetOwner(flag->Owner);
          }   

  // Base execution
  if (!Tick35)
    if (ValidPlr(Base))
      {
      // Auto sell contents
      if (Game.C4S.Game.Realism.BaseFunctionality & BASEFUNC_AutoSellContents) AutoSellContents();
      // Lost flag?
      if (!Game.FindObject(C4ID_Flag,0,0,0,0,OCF_All,"FlyBase",this))
        {
        Base=NO_OWNER;
        Contents.CloseMenus();
        }
      }

Danke dir! =)

Wo finde ich den Source Code? Also wie komme ich nach "engine/src…" ?

Okay, so ähnlich macht es der Uplink auch.   Beim Uplink kann ich das ja aber ganz leicht im Skript ändern.
Wie ändere ich das nun bei der flagge? ein appendto mit Überladung welcher Funktion?

Du kannst das nicht überladen, da das so in der Engine implementiert ist. Im dem Fall absolut unnötig - der C++ Code sieht ja schon fast wie C4Script aus. Das ist vermutlich ein Relikt aus Clonk 4, wo C4Script noch nicht so viele Möglichkeiten hatte.

Du kannst entweder keine Flaggen erlauben und ein eigenes Flaggen-Objekt mit anderer ID machen oder von den betroffenen Gebäuden das IsBase aus der DefCore entfernen.

hm… das ist ja echt dämlich, dass man alles beliebig skripten kann, aber an sowas kommt man nicht ran :smiley:

Ja gut… dann bleibt wohl nur die Flagge mit anderer ID zu kopieren und ihr dieselben Eigenschaften wie dem Uplink zu geben…
hm… allerdings musste beim Uplink ja wirklich alles selbst geschrieben werden, also z.b auch, dass Clonks geheilt und das feuer gelöscht wird, wenn sie brennen… Das sieht zwar soweit ganz okay aus, aber ist nicht ganz so gut, wie es bei der Flagge der Fall ist…
Zudem wäre es ein großer Aufwand, dann auch noch überall zu schauen, wo ich die ID der Flagee verwende und das zu ändern =/

Das eigentliche Problem ist ja nur, dass, sobald man den Uplink erforscht hat, die Flaggen überflüssig sind. Und da so ein Ding immerhin 100Clunker wert ist, würde vermutlich jeder dann einfach die Flagge verkaufen wollen. Nur geht das halt nicht, weil sie sich immer wieder aufs Gebäude setzt :D  Man könnte ein Verkaufsgebäude machen, welches nicht als basis nutzbar ist… hmm…  oder habt ihr noch Ideen, wie man die letzte Flagge dann verkaufen kann? :smiley:

>Wo finde ich den Source Code? Also wie komme ich nach "engine/src..." ?


Da. Einfach entpacken, dann siehst du die Ordnerstruktur.

>oder habt ihr noch Ideen, wie man die letzte Flagge dann verkaufen kann? :D


Ich würde eine Dummy-Flagge mit gleichem Geldwert wie die normale Flagge (aber halt mit einer anderen ID, damit die Engine sie nicht findet) benutzen. Dann kannst du in der normalen Flagge Entrance so erweitern, dass die Flagge die ID wechselt (ChangeDef), wenn sie in ein Gebäude mit Uplink gelegt wird (Bonuspunkte, wenn die Dummy-Flagge die ID wieder zurückwechselt, wenn sie den Container verlässt (Departure)).

das klingt gut, danke dir, werde ich ausprobieren :slight_smile:

weiß einer zufällig, wie ich von einer Flagge die Kaufmenüfunktion aufrufen kann?

Im Uplinkobjekt ist zum Kaufen von Objekten ein eigenes Skript geschrieben, wo dann eben eine Liste von allen kaufbaren objekten erstellt wird usw. 
Das Problem dabei ist, dass das Kaufen via Uplink extrem laggt. Nach jedem einzelnen gekauften Objekt bleibt das spiel eine halbe sekunde stehen, was beim Kauf von mehreren Objekten sehr stört.

Da das beim Kauf via Flagge nicht passiert, war mein Gedanke jetzt, dass beim "up" drücken im Haus mit Uplink, dann einfach das Kaufmenü der Flagge aufgerufen wird. Nur weiß ich ja nicht, wie die Funktion in der Flagge heißt… Oder wie könnte ich das lösen?

Steht das evtl im cr_source? Sind so viele Dateien und eine Suche nach Flag bzw. buy liefert viele Ergebnisse… habe ein paar durchgeguckt, aber bisher nichts finden können.

Das sieht ziemlich engineintern aus (C4ObjectMenu.cpp:144-355). Hast du mal mit dem Profiler geschaut, was genau so langsam an dem Kaufmenü vom Uplink ist? Ansonsten kannst du auch selber versuchen mit GetHomebaseMaterial ein Kaufmenü zu schreiben.

Der Skript Profiler sagt:
03180ms  UPLB::BuyMenu
03127ms  Direct exec
03113ms  UPLB::BuyWare


wobei die besagten 2 Funktionen so aussehen:

private func BuyMenu(selection)
{
  // kein caller?
  if (!caller) return(0);
  // Menü mit allen kaufbaren Objekten
  CreateMenu(GetID(building), caller, 0,2, "Es gibt nichts zu kaufen", 0,0,1);
  // alle Homebasematerials durchgehen
  var i, ID;
  while (ID = GetHomebaseMaterial(GetOwner(),0,i,C4D_All()))
  {
    AddMenuItem("Kauf: %s", "BuyWare", ID, caller, GetHomebaseMaterial(GetOwner(),ID), i);
    ++i;
  }
  // Menüeintrag setzen, falls einer angegeben ist
  SelectMenuItem(selection, caller);
}

private func BuyWare(ID, selection)
{
  // genug finanzielle Rücklagen?
  if (GetWealth(GetOwner()) < GetValue(0,ID))
  {
    PlayerMessage(GetOwner(), "Nicht genug Geld!", building);
    Sound("Error");
    return(BuyMenu(selection));
  }
  // Ware auch noch da?
  if (!GetHomebaseMaterial(GetOwner(),ID))
  {
    Sound("Error");
    return(BuyMenu(selection));
  }
  // Ware erzeugen
  var ware = CreateContents(ID, building);
  DoHomebaseMaterial(GetOwner(), ID, -1);
  // frische Clonks müssen noch zur Crew hinzugefügt werden
  if (GetOCF(ware) & OCF_CrewMember())
    MakeCrewMember(ware, GetOwner());
  // erst noch bezahlen
  DoWealth(GetOwner(), -GetValue(0,ID));
  Sound("Cash");
  // und fertig
  return(BuyMenu(selection));
}


Die Verzögerungen treten erst auf, wenn ein Objekt gekauft wird. Das erstmalige Aufrufen des Kaufmenüs ist nicht langsam.
Wobei es auch von der Anzahl der kaufbaren Objekte abzuhängen scheint. Wenn die Auswahl klein ist, hakt es nur wenig.  Aber mit der Flagge klappt auch bei großer auswahl alles einwandfrei, weshalb ich es gern über die Flagge lösen würde… aktuell habe ich deswegen sogar das Kaufmenü vom Uplink insofern deaktiviert, dass man dort nur eine Flagge kaufen kann. Wenn man mehr kaufen will, muss man dann die Flagge verwenden.

Hast du in C4ObjectMenu.cpp oder sonst wo, irgendeinen Befehl gesehen den ich nutzen kann? Ich hoffe halt, dass da z.b sowas wie hier im uplink steht, also eine Funktion mit einem Namen, die das ganze Kaufverhalten regelt und die ich dann einfach aus dem uplink heraus aufrufe und dadurch das Flaggenkaufmenü geöffnet wird.

Was der Profiler danach sagt - falls das nicht das komplette Log ist - wäre interessant.
Ich hätte angenommen, die Auflistung verursacht den Lag, und sehe in BuyWare keinen klassischen "Frameschlucker". Das ist komisch.

hab nur den Teil kopiert, weil danach glaub ich nur noch andere Objekte gelistet sind… Ich starte den Skriptprofiler, kaufe 10-20 dinge und stoppe ihn wieder. Gibts noch eine andere Vorgehensweise?   Die komplette Liste sieht zb so aus:

-> StartScriptProfiler()
= true
Profiler statistics:

08160ms  Direct exec
08152ms  UPLB::BuyWare
08126ms  UPLB::BuyMenu
00579ms  TS9Z::FogofWar
00564ms  _Z2A::CheckPollution
00285ms  global IsNight
00230ms  _Z2A::Waste
00213ms  global ForestChange
00138ms  global IsDay
00107ms  _Z2A::FilterAir
00107ms  R_EG::Regen
00092ms  global PathFree
00042ms  global PathFree
00040ms  CLNK::FxInventarCheckTimer
00034ms  global FadeGraphics
00032ms  global Find_ID
00028ms  global SetGraphics
00023ms  global FxShowWeaponTimer
00017ms  GRA1::IsBulletGrasTarget
00015ms  UPLB::Heal
00013ms  TIME::Timing
00013ms  global Find_Action
00012ms  TIME::RestoreColors
00010ms  STRS::Dusk
00010ms  global FxgraphFadeStart
00010ms  HZCK::UpdateCharge
00010ms  1HUD::Timer
00010ms  TIME::TimingTwo
00007ms  global Find_Func
00006ms  global RandomX
00006ms  EGLN::Twinkle
00006ms  TIME::UpdateGraphics
00005ms  TIME::RestoreMatColors
00004ms  global VerticesStuck
00004ms  _ETG::Check
00003ms  GOAL::CheckTime
00003ms  WRBO::Check
00003ms  BEAR::Activity
00003ms  TIME::Dawn
00003ms  SSUN::CheckLight
00003ms  TRE3::IsTree
00003ms  TRE3::IsDeadTree
00003ms  GOAL::EnoughGoals
00003ms  BEAR::DoJump
00002ms  OWL1::Owl
00002ms  TIME::RestoreSkyColors
00002ms  TRE4::IsDeadTree
00002ms  CHMU::Entrance
00002ms  CHMU::Pack
00002ms  _CHF::IsWaste
00002ms  TRE2::IsDeadTree
00002ms  _GVC::GmVal
00002ms  BMAN::Check
00001ms  global Find_Exclude
00001ms  global Find_OCF
00001ms  global Find_Category
00001ms  global GetGraphics
00001ms  FARP::JoinPack
00001ms  FARP::CalcValue
00001ms  LGFL::Init
00001ms  BEAR::Walking
00001ms  FARP::Entrance
00001ms  CHMU::JoinPack
00001ms  TRE2::IsTree
00001ms  ATO2::IsWaste
00001ms  GRA1::Seed
00001ms  D12M::Check
00001ms  global FxgraphFadeTimer
00001ms  _CHF::PackCount

-> StopScriptProfiler()
= true

Mh, vielleicht irre ich mich auch, aber:

> CreateMenu(GetID(building), caller, 0,2, "Es gibt nichts zu kaufen", 0,0,1);


Das Menü ist durch die 1 ein permanentes Menü, oder? (D.h. es geht nicht zu, wenn du einen Eintrag auswählst)

>   return(BuyMenu(selection));


… und trotzdem erzeugst du das Menü neu, sobald ein Eintrag ausgewählt wurde? Versuch mal einfach testweise das Menü nicht-permanent zu machen. Also einfach die 1 oben zu einer 0 machen.

Das Auflisten der Objekte sorgt definitiv für den Lag - leider gibt es da keine wirkliche Möglichkeit, um die Funktion zu optimieren und gleichzeitig aktuellste Informationen zu gewährleisten.

Als eine Art Ansatz für einen Workaround der mir einfällt, wäre das ganze mit Hilfe der Commands zu regeln: SetCommand(pClonk, "Buy", pBase) sorgt dafür, dass das Engineseitige Kaufmenü geöffnet wird. Leider versucht der Clonk, beim Versuch etwas zu kaufen, zur Basis hinzugehen. Wenn man an der Stelle den Command abfangen könnte und die Informationen herausholen könnte, könnte man das so relativ einfach umsetzen. Mit ControlCommand war es mir jedoch nicht möglich, diese Buy-Commands abzufangen, weshalb mir im Moment nicht weiter einfallen könnte, wie man das lösen möchte.
Die andere Alternative wäre, die Anzahl der Objekte die aufgelistet werden zu limitieren und bspw. auf ein Seitensystem zurückzugreifen. (Wobei das bei sehr vielen Objekten ziemlich unangenehm sein kann.)

gute Idee, hat aber leider nichts verändert =/
habe aber grad festgestellt, dass der Lag auch auftritt, wenn ich nichts kaufe, sondern das Menü über die "graben" Taste schließe.

Danke für die Mühe eine Lösung zu finden :slight_smile:

Hmm… da es schon wirklich viele Objekte sind, ist das Kaufmenü allgemein sehr überfüllt, weshalb eine Untergliederung in Kategorien garnicht mal schlecht wäre…
Es gibt im Uplink noch ein anderes Kaufsystem, welches Trades zwischen den Spielern abwickelt. Dort existiert bereits so ein Kategoriesystem, welches ich schon mit den meisten meiner Objekte aufgefüllt habe. Man muss leider jede einzelne Objekt ID  in  ein Array eintragen, aber für die meisten Dinge habe ich das bereits erledigt.

D.h sollten wir keine Lösung finden, werde ich wohl das Kategoriesystem übernehmen :slight_smile:

Flagge nur aufs Gebaeude, wenn kein Uplink da ist: Einfach eine unsichtbare Flagge dort erzeugen, so dass die Engine denkt, es waere schon eine Basis? Oder eben wie schon empfohlen eine eigene ID nehmen und den Flaggenkram selber scripten.

Kaufmenue aufrufen per Script geht ganz einfach per Command "Buy" ohne ID-Parameter (Analog "Sell" fuers Verkaufen). Das oeffnet dann das Menue.

Vielen vielen Dank!! :slight_smile:
Dadurch sind tatsächlich gleich beide Probleme gelöst :slight_smile:

Sobald der Uplink sich auf das Gebäude setzt (macht er nur, wenn noch keine Flagge drauf), dann erstellt er eine unsichtbare Flagge, welche sich ebenfalls aufs Gebäude setzt. Dennoch werden bei den unterschiedlichen Befehlen an den Clonk nur die Uplinkfunktionen aufgerufen und nicht die der Flagge (da hab ich wohl einfach nur glück, dass es richtig rum überladen wird?).   Nun führt der "up" Befehl im Gebäude zu  SetCommand(caller,"Buy",building); (was nur klappt, wenn eine Flagge auf dem Gebäude ist) und ruft das Flaggenkaufmenü auf :) 
Sobald das Gebäude weg ist, oder der Uplink runtergenommen wird, entfernt sich auch die unsichtbare Flagge.

Klappt also alles wunderbar, der Kauf lagged nicht mehr, alle anderen Dinge des Uplinks funktionieren und in die Basis gelegte Flaggen setzen sich nicht oben aufs Gebäude, weil die unsichtbare Flagge bereits da ist :slight_smile: