[Gelöst] Forschung kostet Clunker

Gecko will das, wenn er Zeit hat, zwar schreiben, aber vllt können wir ihm ja arbeit abnehmen, oder es doch anders/einfacher lösen :slight_smile:

Ich möchte, dass das Erforschen eben nicht nur Zeit und energie benötigt, sondern auch Clunker kostet. Das soll je nach Forschung ein individueller Betrag sein, den ich dann halt zur Not in jedes Objekt reinschreibe, oder man nimmt den Wert des Objekts verrechnet mit irgendwas, da wird sich schon was finden.

Schreiben kann ich die Grundzüge dazu mittlerweile selbst, so habe ich schon etwas "fertig" wo dann eben nicht nur die Funktion "GetResearchTime" sondern eben auch "GetResearchCosts" überprüft wird, und dieser Betrag auch im Forschungsmenü angezeigt und abgezogen wird.

Das Problem ist nun nur noch dafür zu sorgen, dass Dinge nicht mehrfach bezahlt werden müssen, wenn man die Forschung zeitweise unterbricht. Gecko schlägt vor das ganze mit einem Arraysystem zu lösen, sodass eben für jede Forschung gespeichert wird, ob bereits bezahlt oder nicht.  Er meinte dass er dafür ungefähr 7 stunden brauchen würde.
(ich selbst komme mit arraysystemen immernoch nicht so gut klar, weshalb ich das noch nicht selbst machen kann)

Deswegen nun meine Frage: Geht das nicht auch irgendwie einfacher/schneller zu lösen?  Oder habt ihr einen anderen Vorschlag, wie man das Problem umgehen könnte?

Also ich hab für ein “Arraysystem” ungefähr eine halbe Stunde gebraucht (hab aber auch nur kurz mit zwei Spielern getestet). Ist nicht so schön, weil das mit der Zeit zumüllt, aber dafür recht simpel.

vielen dank =)

du hast es nur mit 2 spielern getestet, es sollte aber auch mit mehr funktionieren, richtig?
Was meinst du mit "zumüllt"? Inwiefern wirkt sich das auf das Spiel/die Forschung aus?

also könnte ich das einfach mal bei mir einsetzen und testen ob es funktioniert? Die erste Funktion dann z.b im Initialize vom Forschungsgebäude aufrufen? Oder könnte das bei mehreren Forschungsgebäuden zu Fehlern führen?

Die Funktion AddToResearchAcc() muss ich dann vermutlich im Forschungsgebäude ausführen lassen, sobald eine Forschung begonnen wird? Mit der ID des Objekts an dem nun geforscht wird und dem Besitzer der Forschungsgebäude. (…oder nehm ich den Clonk der forscht, damit man nicht auf kosten von anderen forschen kann… hmmm… ne ich glaub gebäude ist besser).

Und die Funktion HasResearch frage ich ab, bevor Geld abgezogen wird. (bzw. wäre vermutlich besser, zuerst zu gucken, ob bereits bezahlt. Wenn nicht dann AddTo… und bezahlen, und wenn doch schon bezahlt, nicht AddTo… und nicht bezahlen)

Mit 7 Stunden meint ich auch die komplette Implementation in das Forschungssystem. :wink:
So das quasi die Dinge, die man erforschen kann, folgende Funktion brauchen, um das Geld abzubuchen: GetResearchCosts(){ return Wert; }
Wobei es vermutlich eh schneller geht. Hab aber gerade nicht so den Plan wie das aufgebaut war…

achso :slight_smile:

ja ich brauch eig nur das arraysystem. Die Funktion GetResearchCosts() {return wert;} kann bzw. muss ich dann natürlich selbst bei jedem Objekt hinzufügen, allein schon, weil du mein Pack ja nicht hast :slight_smile: (wenn ich dich jetzt richtig verstanden habe und das der zeitaufwendigste Teil ist)

Wäre es nicht relativ einfach, dem Besitzer des aktuell forschenden Clonks für jede geforschte Sekunde oder so einen Clunker abzuziehen?

richtig, das wäre auch eine Möglichkeit, über die ich bereits nachgedacht habe, dennoch danke für die Idee :wink:
Aber dadurch würde der abgezogene Betrag dann sehr stark mit der Forschungszeit zusammenhängen und ich hätte da schon gern Variationsmöglichkeiten, sodass eine forschung z.b zwar schnell erforscht ist, aber viel kostet und umgekehrt.

>du hast es nur mit 2 spielern getestet, es sollte aber auch mit mehr funktionieren, richtig?


Ja. Würde mich zumindest wundern, wenn nicht.

>Was meinst du mit "zumüllt"?


Das Forschungskontoarray wird mit der Zeit immer größer, weil Sachen die schon erforscht sind, da drin bleiben. Und für rejoinende Spieler wird ein neues (leeres!) Forschungskonto angelegt.

>Inwiefern wirkt sich das auf das Spiel/die Forschung aus?


Gar nicht. Ist nur vom Stil der Datenhaltung her halt eher *quick and dirty*.

>Die erste Funktion dann z.b im Initialize vom Forschungsgebäude aufrufen?


Im Szenario Initialize wäre besser. Sonst setzt du mit jedem neuen Forschungsgebäude alle bezahlten Forschungen für alle Spieler zurück.

>Die Funktion AddToResearchAcc() muss ich dann vermutlich im Forschungsgebäude ausführen lassen, sobald eine Forschung begonnen wird?
>Wenn nicht dann AddTo... und bezahlen, und wenn doch schon bezahlt, nicht AddTo... und nicht bezahlen


Genau.

Könnte man lösen, indem man z.B. bei teuren Sachen das Geld in kleineren Abständen abzieht, als bei egünstigen.
Ich glaub vllt indem man die Zeit, die das erforschen in Frames benötigt, durch die Kosten teilt. Dann kommt eine Zahl x raus. und alle x Frames, muss man dem Spieler dann einen Clunker abziehen.

Probleme wären da Rundungsfehler, aber die dürften relativ gering sein, kA…

hmm … aber dann kommt noch das Problem hinzu, wenn jemand eine Forschung anfängt und hat 100Clunker. Dann verbrät er die 100Clunker bei der Forschung, sie ist aber noch nicht fertig (weil sie insg. vllt 120Clunker kostet) und dadurch wrid die Forschung dann abgebrochen, weil nicht mehr genug Geld da ist.

Also ne, ich bin eher dafür, dass es gleich zu beginn abgezogen wird und eben die Forschung garnicht erst anfängt, wenn man nicht genug Geld hat.

Alles klar, danke für deine Antworten :slight_smile:

Habe es jetzt mal eingebaut und es scheint auch zu funktionieren :slight_smile:

Leider hat sich ein anderes Problem eingeschlichen, was ich auch schon vor dem arraysystem hatte.  Und zwar passiert es nun, dass die Forschungszeit offensichtlich nciht mehr korrekt berechnet wird…  ICh hab noch nicht ganz rausgekriegt, welches muster dahinter steckt , aber zurzeit sieht es so aus, als würde es reichen eine Forschung normal durchzuziehen. Danach wird anscheinend der progress nicht mehr zurückgesetzt, denn jede weitere Forschung dauert plötzlich nur noch wenige sekunden.

Eigentlich ist das nicht möglich, da meine einzigen Änderungen am Originalskript if Befehle sind, welche sich lediglich um den Geldabzug kümmern und nicht mit progress oderso in Berührung kommen…

Hier mal die Funktionen die ich geändert habe. Alle anderen Funktionen sind unberührt und weiterhin wie im Originalskript, ich hebe meine Änderungen mal fett hervor:


local restime, kosten,kosten2; // Benötigte Gesamtzeit zum Forschen, kosten: die kostenanzeige im Menü, kosten2: die tatsächlichen kosten des nun zu erforschenden Objekts

protected func SelectResearchCategory(idImage, pClonk, dwCategory)
{
  // Auswahlmenü erzeugen
  CreateMenu(idImage, pClonk, this(), 0, "$TxtNothingelsetoresearc$");
  // Alle geladenen Baupläne überprüfen
  var i,idDef,iPlr=GetOwner(pClonk);
  while (idDef = GetDefinition(i++, dwCategory))
    // Passende Kategorie
    if (GetCategory(0, idDef) & C4D_Knowledge())
      // Dem Spieler noch nicht bekannt
      if (!GetPlrKnowledge(iPlr,idDef))
      {
        // Keine Forschungsgrundlage nötig oder Forschungsgrundlage vorhanden

kosten = DefinitionCall(idDef, "GetResearchCosts");

        var idBase = DefinitionCall(idDef,"GetResearchBase"), fHasBase, j;
        fHasBase = !idBase || GetPlrKnowledge(iPlr,idBase); j=1;
        // Erweiterte Forschungsgrundlagen
        while (idBase = DefinitionCall(idDef, Format("GetResearchBase%d", ++j)))
          if (!GetPlrKnowledge(iPlr,idBase)) fHasBase=0;
        // Ist schon durch etwas anderes erforschbar? (Zugbrücke rechts -> Zugbrücke links etc.)
        var link;
        if (link = DefinitionCall(idDef, "GetResearchLink"))
          if (GetName(0, link)) // Linkdefinition auch tatsächlich geladen?
            if(!GetPlrKnowledge(iPlr, link) ) // Linkdefinition noch nicht erforscht? (passiert durch SetPlrKnowledge-Aufrufe oder Szenariovorgaben)
              continue;
        // Menüeintrag hinzufügen
      // if (fHasBase) AddMenuItem("$TxtResearchs$", "SelectResearch", idDef, pClonk, 0, pClonk);

if (fHasBase) AddMenuItem(Format("%s (%d C.)erforschen",GetName(0,idDef),kosten),"SelectResearch",idDef, pClonk, 0, pClonk);

      }
  return(1); 
}

public func SelectResearch(def, clonk)
{
  kosten2 = DefinitionCall(target=def, "GetResearchCosts", this(), clonk);
if (!AccHasResearch(def, GetOwner())){
  if(GetWealth(GetOwner())< kosten2)
    return(Message("$NotEnoughMoney$",this()),Sound("Error"));
};


  // Anfangen
  AddCommand(clonk, "Call", this(), def, 0, 0, 0, "StartResearch", 10, 1);
  // Vorher ins Labor gehen
  if (Contained(clonk) != this())
  {
    AddCommand(clonk, "Wait", 0, 0, 0, 0, 40);
    AddCommand(clonk, "Enter", this());
  }
}
 
private func CancelResearch()
{
  if (GetChar(GetAction()) == GetChar("R")) SetAction("Idle");
  EnergyCheck(0);
}

protected func StartResearch(clonk, def)
{
  // Spieler hat diesen Bauplan schon
  if (GetPlrKnowledge(clonk->GetOwner(), def))
  {
    Message("$TxtAlreadyDeveloped$", this(), GetName(0, def));
    Sound("Error");
    return(0);
  }
  // Bisherige Forschung abbrechen
  CancelResearch();
  // nur, wenn ansonsten inaktiv oder schon am Forschen
  if (!ActIdle()) if (GetChar(GetAction()) != GetChar("R")) return(0);
  // Besitzer anpassen (der Besitzer des forschenden Clonks erhält den Bauplan)
  SetOwner(GetOwner(clonk));
  // Neues Forschungsziel: Fortschritt zurücksetzen
  if (def != target) progress = 0;
  // Forschungsziel und Gesamtzeit setzen
  restime = DefinitionCall(target=def, "GetResearchTime", this(), clonk);
  // Forschungsaktion starten

if (!AccHasResearch(def, GetOwner())){
  SetWealth(GetOwner(),GetWealth(GetOwner())- kosten2);
  Sound("Cash");
AddToResearchAcc(def, GetOwner());
};


  SetAction("Research");
  return (1);
}

Hm, ich seh’ den Fehler auch nicht auf Anhieb. Schau dir doch mal an, wie sich die lokalen Variablen verhalten (progress und so). Ggf. kannst du auch die Framerate runtersetzen, falls die Variablen zu schnell fluktuieren, um sie beobachten zu können.

habe den Fehler gefunden:
  kosten2 = DefinitionCall(target=def, “GetResearchCosts”, this(), clonk);

hier setze ich die beiden gleich, was dafür sorgt, dass progress nicht mehr zurückgesetzt wird…
Ich kann mich grad nicht mehr erinnern, warum ich das dort überhaupt geschrieben habe…
naja,  jetzt funktioniert es jedenfalls =) 
Vielen Dank für das Arraysystem :slight_smile:

@Gecko: Dann brauchst du das jetzt nicht mehr übernehmen, aber dennoch danke für deine Hilfe :slight_smile: Fehlt eigentlich nur noch das mit dem Sichtradius: https://clonkspot.org/forum/topic_show.pl?tid=326