Scripting:LadeStation

Aus STNE-Wiki

(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
(LadeStation Script.)
 
Zeile 9: Zeile 9:
Faldrian
Faldrian
-
PS: Zum Schreiben von Code ist das Wiki total bescheuert, daher hier noch ersatzweise ein Link auf eine vernünftig formatierte Version: http://www.pastebin.org/85331
+
PS1: <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/de/">Den Code stelle ich unter der BY-NC-SA CC-Lizenz zur Verfügung.</a> Details stehen im Link.
 +
 
 +
PS2: Zum Schreiben von Code ist das Wiki total bescheuert, daher hier noch ersatzweise ein Link auf eine vernünftig formatierte Version: http://www.pastebin.org/85331
  #UseInterface Web, ShipPortal;
  #UseInterface Web, ShipPortal;

Aktuelle Version vom 7. Februar 2010, 10:49 Uhr

Ihr kennt vielleicht die LadeStationen, die es überall im Quandranten gibt / mal gab. Hier veröffentliche ich nun den Code dafür, auf dass jeder sich Code-Praxis hieran abgucken kann und den sinnvollen Einsatz der PrettyPrint-Library nachvollziehen kann. Außerdem könnt ihr hiermit den Service-Level massiv heben, wenn ihr als Spieler selber solche Dienste anbietet. :)

Damit es funktioniert, müssen zwei Daten-Dateien angelegt werden, was konkret benötigt wird, steht im Code. Falls jemand mehr Zeit hat als ich, darf hier gerne Dokumentation hinzugefügt werden, um die Installation und das Verständnis einfacher zu machen.

Viele Grüße, Faldrian

PS1: <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/de/">Den Code stelle ich unter der BY-NC-SA CC-Lizenz zur Verfügung.</a> Details stehen im Link.

PS2: Zum Schreiben von Code ist das Wiki total bescheuert, daher hier noch ersatzweise ein Link auf eine vernünftig formatierte Version: http://www.pastebin.org/85331

#UseInterface Web, ShipPortal;

/**
 * prettyPrint
 * Formatiert einen Text gemäß der in IGMs möglichen Funktionen
 * Gibt ein Objekt zurück, dass an das Response-Objekt gehangen werden kann.
 * Wichtig: hier wird nur valides XML-artiges zeug geparst!
 *          HTML-durcheinander-Verdreckungen werden mit Fehlermeldung beantwortet.
 */
Function prettyPrint(text As String) As CHtmlControl {
  Var stack As New CObjectList(); // Stack für die Verschachtelung
  Var tmpObj As CObject; // Damit diese blöde Engine damit klar kommt.
  Var element As New Stackelement(); // Oberste Ebene definieren, macht die Schleife einfacher
  Var textStart As Integer = 0;
  Var nextTagAuf As Integer = text.IndexOf("<"); // Such den ersten HTML-Tag
  Var nextTagZu As Integer = text.IndexOf(">"); // Auch gleich die Position, wo es zu geht
  nextTagAuf = Math.Min(nextTagAuf, nextTagZu); // Das Minimum der beiden ist -1, wenn etwas nicht gefunden wurde, sonst nextTagAuf
  Var tag As String;
  
  While(nextTagAuf > 0) {
    If(textStart < nextTagAuf) {
      // Erstmal ist da Text, hinzufügen
      element.e.Add(text.Substring(textStart, nextTagAuf - textStart));
    }
    
    // Den Tag isolieren
    tag = text.Substring(nextTagAuf + 1, nextTagZu - nextTagAuf - 1); // <dies hier>
    If(String.Compare(tag, 0, "/", 0, 1) = 0) { // Wenn das erste Zeichen innerhalb des Tags "/" ist --> Endtag
      // Wenn der Tag ein schließender Tag ist
      If(tag = element.tag) { // element.tag sieht schon gleich so aus: "/tag"
        tmpObj = stack.Item(stack.Count - 1);
        element = tmpObj;
        stack.RemoveAt(stack.Count - 1); // Letzten vom Stack poppen
      } Else {
        // Hier ist was kaputt im Quellcode
        element.e.Add("[Fehler: schließender Tag " + element.tag + " erwartet, " + tag + "gefunden. Abbruch.]");
        Exit While; // While verlassen
      }
    } Elseif(is_singleTag(tag)) {
      // Wenns ein BR oder dergl ist, ersetzen
      element.e.Add(replaceSingleTag(tag));
    } Else {
      // Ist scheinbar ein umschließender Tag, also verarbeiten
      tmpObj = element;
      stack.Add(tmpObj); // Alten aktuellsten Tag auf den Stack schieben
      element = replaceTag(tag, element); // Baut ein neues Stackelement mit element und endtag
    }
    
    // Lege die neuen Limits fest
    textStart = nextTagZu + 1;
    nextTagAuf = text.IndexOf("<", textStart);
    nextTagZu = text.IndexOf(">", textStart);
    nextTagAuf = Math.Min(nextTagAuf, nextTagZu); // Das Minimum der beiden ist -1, wenn etwas nicht gefunden wurde, sonst nextTagAuf
    
  }
  
  // Letzten Text hinzufügen
  If(textStart < text.Length) { // Wenn da noch Text ist
    element.e.Add(text.Substring(textStart, text.Length - textStart));
  }
  
  Return element.e; // oberste Ebene zurückgeben
}

/**
 * replaceTag
 * Bekommt einen Tag und entscheidet dann, was für Formatierungen usw. es daraus macht.
 * Gibt ein HTML-Objekt zurück, in das der Inhalt reingeschoben werden kann
 */
Function replaceTag(text As String, element As Stackelement) As Stackelement {
  text = text.ToLower();
  Var tagType As String = text;
  Var retHtmlPart As New CHtmlSpan();
  Var newHtmlPart As New CHtmlSpan(); // Neues Element, in dem weiterer Inhalt reinkommt.- Wird manchmal gebraucht
  element.e.Add(retHtmlPart);
  
  If(text.IndexOf(" ") > 0) { // Checken, ob der Tag Parameter hat
    tagType = text.Substring(0, text.IndexOf(" "));
    If(tagType = "font") {
      Var firstquote_index As Integer = text.IndexOf("color='");
      Var secondquote_index As Integer = text.IndexOf("'", firstquote_index + 7);
      If(firstquote_index > 0 AND secondquote_index > 0) {
        retHtmlPart.Style.Add('color', text.Substring(firstquote_index + 7, secondquote_index - firstquote_index - 7));
      } Else {
        retHtmlPart.Add("[Fehler: Konnte das Font-Tag nicht korrekt Parsen. Quotes checken?]");
      }
    } Else {
      // Unbekannter Tag, gib Fehlermeldung aber nerv nicht weiter.
      retHtmlPart.Add("[Fehler: unbekannter Tag - " + tagType + " - ignoriert.]");
    }
    
  } Else { // Keine Parameter, erstmal diese Tags implementieren
    If(tagType = "b") {
      retHtmlPart.Style.Add('font-weight', 'bold');
    } Elseif(tagType = "u") {
      retHtmlPart.Style.Add('font-decoration', 'underline');
    } Elseif(tagType = "i") {
      retHtmlPart.Style.Add('font-style', 'italic');
    } Elseif(tagType = "small") {
      retHtmlPart.Style.Add('font-size', 'smaller');
    } Elseif(tagType = "ul") { // Einen UL-Tag simulieren, indem das SPAN drumherum manipuliert wird.
      retHtmlPart.Style.Add('display', 'block');
      retHtmlPart.Style.Add('margin', '13px 39px');
      retHtmlPart.Add(newHtmlPart);
      retHtmlPart = newHtmlPart; // Hier überschreiben, damit das neue Inhaltselement auch zurückgegeben wird.+
    } Elseif(tagType = "li") { // Einen LI-Tag simulieren, indem das SPAN drumherum manipuliert wird.
      retHtmlPart.Style.Add('display', 'list-item');
      retHtmlPart.Style.Add('list-style-image', 'url(http://game.stne.net/t/1/s/li.gif)');
    } Else {
      // Unbekannter Tag, gib Fehlermeldung aber nerv nicht weiter.
      retHtmlPart.Add("[Fehler: unbekannter Tag - " + tagType + " - ignoriert.]");
    }
  }
  
  // Jetzt sollten auf dem retHtmlPart alle passenden Formatierungen usw. drauf sein. Gib mal zurück.
  Return New Stackelement(retHtmlPart, "/" + tagType);
}

/**
 * replaceSingleTag
 * Ersetzt Tags, die man nicht schließen muss direkt und gibt ein CHtmlControl zurück.
 */
Function replaceSingleTag(text As String) As CHtmlControl {
  text = text.ToLower();
  text = text.Replace("""", "'"); // Damit ich nur nach einer Sorte suchen muss
  Var retHtmlPart As New CHtmlSpan();
  
  If(text.StartsWith("img")) {
    Var firstquote_index As Integer = text.IndexOf("src='");
    Var secondquote_index As Integer = text.IndexOf("'", firstquote_index + 5);
    If(firstquote_index > 0 AND secondquote_index > 0) {
      Return New CHtmlImage(text.Substring(firstquote_index + 5, secondquote_index - firstquote_index - 5));
    } Else {
      retHtmlPart.Add("[Fehler: Konnte das IMG-Tag nicht korrekt Parsen. Quotes checken?]");
    }
  } Elseif(text = "br") {
    Return New CHtmlBreak();
  } Else {
    retHtmlPart.Add("[Fehler: Unbekanntes Tag - " + text + " ]");
  }
  
  Return retHtmlPart;
}

/**
 * is_singleTag
 * Checkt, ob ein Tag mit einem als single-Tag bekannten Tag anfängt.
 */
Var singleTags[] As String = {"br", "img"}; // Enthält alle einfachen Tags, die keine Ebenen aufspannen
Function is_singleTag(text As String) As Boolean {
  Var walkstring As String;
  For(Each walkstring In singleTags) {
    If(String.Compare(walkstring, 0, text, 0, walkstring.Length) = 0) {
      Return true;
    }
  }
  Return false;
}

/* Ist eine komplexe Datenstruktur, damit mehr als ein Ding aufm Stack liegen kann */
Class Stackelement {
  Var e As CHtmlControl;
  Var tag As String;
  
  Function New() {
    This.e = New CHtmlControl();
    This.tag = "/none";
  }
  
  Function New(e As CHtmlControl, tag As String) {
    This.e = e;
    This.tag = tag;
  }
}
/** Ende PrettyPrint **/


Function println(text As String) {
  Response.Add(text);
  Response.Add(New CHtmlBreak());
}

// Checkt, ob ein String nur aus 0-9 besteht.
Function is_integer(text As String) As Boolean {
  Var stringindex As Integer = 0;
  For(stringindex = 0 To text.Length - 1) {
    If( not Char.IsNumber(text, stringindex)) {
      Return False;
    }
  }
  Return True;
}

// -- Konstanten
Var kostenProEnergie As Integer = 5;
Var maxGutscheinMenge As Integer = 1000;

// -- Initialisierung des DataNodes
// Var gutscheinspeicher As New CDataNodeStorage("ServicePortalReserve_Gutschein", true); <-- das braucht man nur um einen neuen Knoten zu erstellen.
Var speicher As CDataNodeStorage = CDataNodeStorage.LoadFromUser("ServicePortalReserve", 36705);
If( not speicher.Items.ContainsKey("logs")) { // Erster Aufruf?
  speicher.Items.Add("logs");
}
Var gutscheinspeicher As CDataNodeStorage = CDataNodeStorage.LoadFromUser("ServicePortalReserve_Gutschein", 36705);
If( not gutscheinspeicher.Items.ContainsKey("gutscheine")) { // Erster Aufruf?
  gutscheinspeicher.Items.Add("gutscheine");
}

/************************************
 ** DISPATCHER - Wohin gehts grad  **
 ************************************/
Var options As CStringHashTable = Request.Form;
If(options.ContainsKey("event")) {
  Var gotoevent As String = options.Item("event");
  If(gotoevent = "show_hauptseite") {
    event_show_hauptseite();
  } Elseif(gotoevent = "transfer_energy") {
    event_transfer_energy();
  } Elseif(gotoevent = "kaufe_gutschein") {
    event_kaufe_gutschein();
  } Elseif(gotoevent = "show_gutschein") {
    event_show_gutschein();
  } Elseif(gotoevent = "transfer_gutschein") {
    event_transfer_gutschein();
  } Elseif(gotoevent = "show_logs") {
    event_show_logs();
  } Else {
    // Wir programmieren gleich sauber mit Fehlermeldungen :)
    println("Hier muss ein Fehler vorliegen. Bitte Faldrian(36705) melden und das hier angeben:");
    println("Dispatcher - unbekanntes Ziel - view: '" & gotoevent & "'");
  }
} Else {
  // Einstiegsseite anzeigen
  event_show_hauptseite();
}


/***********************************************
 ** Controls - die Eventverarbeitenden Dinger **
 ***********************************************/

// Ergebnisklasse, die von Check-Funktionen zurückgegeben wird.
Class Checkresult {
  Var meldungen As CHtmlSpan;
  Var erfolg As Boolean;
  
  Function New() { // Konstruktor
    meldungen = New CHtmlSpan();
    erfolg = True;
  }
  
  Function Add(text As String) { // Fügt eine neue Bemerkung hinzu
    If(not erfolg) {
      meldungen.Add(New CHtmlBreak());
    }
    meldungen.Add(text);
    erfolg = False;
  }
}

Function event_transfer_energy() {
  /**
   * Event: Ein Aufladevorgang soll gestartet werden
   */
  Var menge As Integer = 0;
  
  // Basischeck erstmal machen, ob man waren Beamen kann
  Var checkergebnisse As Checkresult = check_before_transaction();
  
  // Sicherstellen, dass nur Zahlen im Eingabefeld sind
  If(not is_integer(options.Item("menge"))) {
    checkergebnisse.Add("Bitte geben sie in das Feld 'Menge' eine natürliche Zahl ein.");
  } Else {
    menge = Integer.Parse(options.Item("menge"));
  }
  
  // Sicherstellen, dass genug Energie für die Eingabe vorhanden ist - Es gibt keine Beamkosten wegen "angedockt".
  If(MyShip.Energie < menge) {
    checkergebnisse.Add("Es steht nicht genügend Energie zur Verfügung. Es ist nur " & MyShip.Energie & " Energie vorhanden.");
  }
  
  // Bunten Kasten erzeugen.
  Var meldungsbox As CHtmlSpan = generate_messagebox(checkergebnisse.erfolg);
  
  If(checkergebnisse.erfolg) {
    // Beamvorgang der Larne
    // Hierbei erstmal versuchen, die gewünschte menge herunterzubeamen, wenns nicht genug war, abrunden und den rest zurückbeamen.
    // dann soviel aufladen, wie bezahlt wurde.
    Var larneVorher As Double = MyShip.Larne;
    Var echte_menge As Integer = menge;
    MyShip.Aktion.TransferiereVonSchiff(GuestShip.ShipID, menge * kostenProEnergie, EBeamRessource.Larne);
    
    // Sicherstellen, dass genug Larne rübergekommen ist
    If(MyShip.Larne < larneVorher + menge * kostenProEnergie) {
      echte_menge = Math.Floor((MyShip.Larne - larneVorher) / kostenProEnergie); // angenommen 49 von 50 wurden gebeamt, gibt das 9 Ladungen Rest 4.
      
      // Rest zurückgeben
      MyShip.Aktion.TransferiereZuSchiff(GuestShip.ShipID, (MyShip.Larne - larneVorher) - echte_menge * kostenProEnergie, EBeamRessource.Larne);
      checkergebnisse.Add("Es wurde nur " & CStr(echte_menge * kostenProEnergie) & " Larne gefunden. Menge auf " & CStr(echte_menge) & " korrigiert.");
    }
    
    // Reservebatterie-Aufladung
    MyShip.Aktion.StationsReserveBatterieAufladen(GuestShip.ShipID, echte_menge);
    checkergebnisse.Add("Es wurde versucht die Reservebatterie Ihres Schiffs um " & CStr(echte_menge) & " aufzuladen.");
    checkergebnisse.Add("Die Aufladung hat Sie  " & CStr(echte_menge * kostenProEnergie) & " Larne gekostet.");
    
    // -- Absetzen des Logs im DataNode
    save_log(echte_menge, "");
  }
  
  // Fenster wieder anzeigen.
  meldungsbox.Add(checkergebnisse.meldungen); // hier erst den Inhalt rein, damit der restliche Kram schon drumherum ist.
  view_hauptseite(meldungsbox);
}

Function event_show_hauptseite() {
  /**
   * Event: Hauptseite soll angezeigt werden.
   */
  view_hauptseite(New CHtmlControl());
}

Function event_show_logs() {
  /**
   * Event: Die Logansicht soll angezeigt werden.
   */
  view_logs();
}

Function event_kaufe_gutschein() {
  /**
   * Event: Kaufe mit Larne einen Gutschein
   */
  Var menge As Integer = 0;
  
  // Basischeck erstmal machen, ob man waren Beamen kann
  Var checkergebnisse As Checkresult = check_before_transaction();
  
  // Sicherstellen, dass nur Zahlen im Eingabefeld sind
  If(not is_integer(options.Item("menge"))) {
    checkergebnisse.Add("Bitte geben sie in das Feld 'Menge' eine natürliche Zahl ein.");
  } Else {
    menge = Integer.Parse(options.Item("menge"));
  }
  
  // Bunten Kasten erzeugen.
  Var meldungsbox As CHtmlSpan = generate_messagebox(checkergebnisse.erfolg);
  
  If(checkergebnisse.erfolg) {
    // Begrenze die Gutscheinmenge - damit Leute nicht jetzt unbegrenzt für einen Preis kaufen und später einlösen, wenns teurer ist.
    If(menge > maxGutscheinMenge) {
      menge = maxGutscheinMenge;
      checkergebnisse.Add("Es können nur  " & CStr(maxGutscheinMenge) & " pro Gutschein gutgeschrieben werden. Menge angepasst.");
    }
    
    // Beamvorgang der Larne
    // Hierbei erstmal versuchen, die gewünschte menge herunterzubeamen, wenns nicht genug war, abrunden und den rest zurückbeamen.
    // dann soviel aufladen, wie bezahlt wurde.
    Var larneVorher As Double = MyShip.Larne;
    Var echte_menge As Integer = menge;
    MyShip.Aktion.TransferiereVonSchiff(GuestShip.ShipID, menge * kostenProEnergie, EBeamRessource.Larne);
    
    // Sicherstellen, dass genug Larne rübergekommen ist
    If(MyShip.Larne < larneVorher + menge * kostenProEnergie) {
      echte_menge = Math.Floor((MyShip.Larne - larneVorher) / kostenProEnergie); // angenommen 49 von 50 wurden gebeamt, gibt das 9 Ladungen Rest 4.
      
      // Rest zurückgeben
      MyShip.Aktion.TransferiereZuSchiff(GuestShip.ShipID, (MyShip.Larne - larneVorher) - echte_menge * kostenProEnergie, EBeamRessource.Larne);
      checkergebnisse.Add("Es wurde nur " & CStr(echte_menge * kostenProEnergie) & " Larne gefunden. Menge auf " & CStr(echte_menge) & " korrigiert.");
    }
    
    // Gutschein-Erstellung
    checkergebnisse.Add("Es wurden " & CStr(echte_menge * kostenProEnergie) & " Larne eingezogen.");
    Var uuid As String = erzeuge_Gutschein(echte_menge);
    checkergebnisse.Add("Ein Gutschein über " & Cstr(echte_menge) & " Reserveenergie ausgestellt:");
    checkergebnisse.Add("Code: " & uuid);
    checkergebnisse.Add("Speichern Sie den Code gut ab!");
    
    // -- Absetzen des Logs im DataNode
    save_log(echte_menge, "Gutschein erstellt: " & uuid);
  }
  
  // Fenster wieder anzeigen.
  meldungsbox.Add(checkergebnisse.meldungen); // hier erst den Inhalt rein, damit der restliche Kram schon drumherum ist.
  view_hauptseite(meldungsbox);
}

Function event_show_gutschein() {
  /**
   * Event: Ein Gutschein soll eingelöst werden und das verbleibende Guthaben wird angezeigt.
   * Falls der Gutschein nicht verfügbar ist oder kein Guthaben mehr aufweist, wird eine Fehlermeldung angezeigt und auf die Hauptseite weitergeleitet.
   */
  Var checkergebnisse As New Checkresult();
  Var meldungsbox As CHtmlSpan;
  If(gutscheinspeicher.Items.Item("gutscheine").Items.ContainsKey(options.Item("code"))) { // Checken, ob der Code überhaupt existiert.
    Var menge As Integer = Integer.Parse(gutscheinspeicher.Items.Item("gutscheine").Items.Item(options.Item("code")).Value);
    If(menge > 0) { // Ist noch Aufladung auf dem Gutschein vorhanden?
      view_gutschein(menge, options.Item("code"), New CHtmlControl());
    } Else {
      // Fehlermeldung erzeugen und Hauptseite anzeigen
      checkergebnisse.Add("Der Gutscheincode " & options.Item("code") & " hat kein Guthaben mehr.");
      meldungsbox = generate_messagebox(checkergebnisse.erfolg);
      meldungsbox.Add(checkergebnisse.meldungen); // hier erst den Inhalt rein, damit der restliche Kram schon drumherum ist.
      view_hauptseite(meldungsbox);
    }
  } Else {
    // Fehlermeldung erzeugen und Hauptseite anzeigen
    checkergebnisse.Add("Der Gutscheincode " & options.Item("code") & " existiert nicht.");
    meldungsbox = generate_messagebox(checkergebnisse.erfolg);
    meldungsbox.Add(checkergebnisse.meldungen); // hier erst den Inhalt rein, damit der restliche Kram schon drumherum ist.
    view_hauptseite(meldungsbox);
  }
}

Function event_transfer_gutschein() {
  /**
   * Löst einen Gutschein auch wirklich ein!
   */
  Var guthaben As Integer = Integer.Parse(gutscheinspeicher.Items.Item("gutscheine").Items.Item(options.Item("code")).Value);
  Var menge As Integer = 0;
  
  // Basischeck erstmal machen, ob man waren Beamen kann
  Var checkergebnisse As Checkresult = check_before_transaction();
  
  // Sicherstellen, dass nur Zahlen im Eingabefeld sind
  If(not is_integer(options.Item("menge"))) {
    checkergebnisse.Add("Bitte geben sie in das Feld 'Menge' eine natürliche Zahl ein.");
  } Else {
    menge = Integer.Parse(options.Item("menge"));
  }
  
  // Sicherstellen, dass genug Energie für die Eingabe vorhanden ist
  If(MyShip.Energie < menge) {
    checkergebnisse.Add("Es steht nicht genügend Energie zur Verfügung. Es ist nur " & MyShip.Energie & " Energie vorhanden.");
  }
  
  // Bunten Kasten erzeugen.
  Var meldungsbox As CHtmlSpan = generate_messagebox(checkergebnisse.erfolg);
  
  If(checkergebnisse.erfolg) {
    Var echte_menge As Integer = menge;
    If(menge > guthaben) {
      echte_menge = guthaben;
      checkergebnisse.Add("Es waren nur noch " & CStr(guthaben) & " Energieeinheiten gutgeschrieben. Lademenge auf " & CStr(guthaben) & " korrigiert.");
    }
    
    // Auflademenge abziehen
    guthaben = guthaben - echte_menge;
    gutscheinspeicher.Items.Item("gutscheine").Items.Item(options.Item("code")).Value = Cstr(guthaben);
    
    MyShip.Aktion.StationsReserveBatterieAufladen(GuestShip.ShipID, echte_menge);
    save_log(echte_menge, "Gutschein benutzt: " & options.Item("code")); // auch im Log abspeichern
    checkergebnisse.Add("Es wurde versucht die Reservebatterie Ihres Schiffs um " & CStr(echte_menge) & " aufzuladen.");
    checkergebnisse.Add("Es verbleibt eine Gutschrift von " & CStr(guthaben) & " auf ihrem Gutschein mit Code " & options.Item("code") & ".");
  }
  
  meldungsbox.Add(checkergebnisse.meldungen); // hier erst den Inhalt rein, damit der restliche Kram schon drumherum ist.
  view_gutschein(guthaben, options.Item("code"), meldungsbox);
}

Function check_before_transaction() As Checkresult {
  /**
   * Check: Stellt sicher, dass wir in der Lage sind, vom Zielschiff Larne zu beamen.
   */
  
  Var ergebnis As New Checkresult();
  
  // -- Sicherstellen, dass der Kunde angedockt ist
  If(GuestShip.AngedocktAnID <> MyShip.AngedocktAnID) {
    ergebnis.Add("Ihr Schiff muss an den VP angedockt sein.");
  }
  
  // -- Sicherstellen, man selbst angedockt ist
  If(MyShip.Angedockt = False) {
    // Versuchen, das Schiff anzudocken
    Var schiff As CShip;
    For(Each schiff In MyShip.SRS) {
      If(schiff.Definition.IstRaumstation) {
        MyShip.Aktion.AndockenAn(schiff.ShipID);
        Exit For;
      }
    }
    
    // Sind wir jetzt angedockt?
    If(MyShip.Angedockt = False) {
      ergebnis.Add("Das ServiceSchiff ist nicht angedockt - es tut uns leid. Bitte kontaktieren Sie den Besitzer.");
    }
  }
  
  // -- Sicherstellen, dass der Kunde auf Alarmstufe Grün ist
  If(GuestShip.Alarmstufe <> EAlarmStufe.Grün) {
    ergebnis.Add("Ihr Schiff muss auf Alarmstufe Grün sein - sonst kann nicht gebeamt werden.");
  }
  
  Return ergebnis;
}

Function erzeuge_Gutschein(menge As Integer) As String {
  /**
   * Erzeugt einen Gutschein und gibt den Code zurück.
   */
  Var zufall As New Random(Date.Now.DayOfYear * 86400 + Date.Now.Hour * 3600 + Date.Now.Minute * 60 + Date.Now.Second);
  Var chartabelle As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  Var i As Integer;
  Var ergebnis As String = "";
  For(i = 0 To 16) { // Jedes Zeichen 
    ergebnis = ergebnis & chartabelle.Substring(zufall.Next(26), 1);
  }
  
  // Abspeichern in einen DataNode
  gutscheinspeicher.Items.Item("gutscheine").Items.Add(ergebnis, menge);
  Return ergebnis;
}

Function save_log(menge As Integer, anmerkung As String) {
  /**
   * Speichert einen Vorgang in dem Datanode ab
   */
  If( not speicher.Items.ContainsKey('autoid')) { // Erster Aufruf?
    speicher.Items.AddInteger('autoid', 0);
  }
  Var autoid As Integer = speicher.Items.Item('autoid').asInteger;
  speicher.Items.Item('logs').Items.Add(Cstr(autoid));
  speicher.Items.Item('logs').Items.Item(Cstr(autoid)).Items.Add("position", MyShip.MapPosition.X & "|" & MyShip.MapPosition.Y);
  speicher.Items.Item('logs').Items.Item(Cstr(autoid)).Items.Add("spieler", GuestUser.UserID);
  speicher.Items.Item('logs').Items.Item(Cstr(autoid)).Items.Add("datum", Date.Now);
  speicher.Items.Item('logs').Items.Item(Cstr(autoid)).Items.Add("menge", menge);
  If(anmerkung.Length > 0) { // Nur, wenns auch gebraucht wird, wegen Platzsparen.
    speicher.Items.Item('logs').Items.Item(Cstr(autoid)).Items.Add("anmerkung", anmerkung);
  }
  speicher.Items.Item('autoid').asInteger = autoid + 1;
}


/************************************
 ** Views - die Seitengenerierung  **
 ************************************/
Function view_hauptseite(meldungen As CHtmlControl) {
  /**
   * Hauptseite, auf der die Benutzer ihre Aktionen durchführen können.
   * meldungen - Hier können Fehler oder Bestätigungen eingefügt werden.
   */
  Var table As New CTable();
  Response.Add(table);
  
  Var row As CTableRow;
  
  // -- 1. Block - Logo
  table.Add(part_header());
  
  // -- 2. Block - Aufladen - Gutschein
  row = table.AddRow(1);
  row.Cells.Item(0).Style.Add("padding", "3px");
  row.Cells.Item(0).Style.Add("text-align", "left");
  row.Cells.Item(0).Add(meldungen); // <-- Fehlermeldungen reinhauen
  
  // Reserveenergie laden
  row.Cells.Item(0).Add(prettyPrint(" <img src='http://a.imagehost.org/0475/reserve_aufladen.png'>
Hier können Sie die Reservebatterie Ihres Schiffes gegen Larne aufladen lassen.
Es stehen derzeit " & MyShip.Energie & " Energie zur Verfügung.
1 Einheit Reserveenergie kostet derzeit " & CStr(kostenProEnergie) & " Larne.
")); Var form As New CHtmlForm(New CScriptUrl()); form.Add(New CHtmlInput("transfer_energy", "event", EHtmlInputType.Hidden)); row.Cells.Item(0).Add(form); Var inputtabelle As New CTable(); form.Add(inputtabelle); Var inputtabelle_row As CTableRow = inputtabelle.AddRow(3); inputtabelle_row.Item(0).Add(prettyPrint(" Menge wählen: ")); inputtabelle_row.Item(0).Style.Add("border", "0px"); Var mengeFeld As New CHtmlTextBox("", "menge"); mengeFeld.Size = 5; inputtabelle_row.Item(1).Add(mengeFeld); inputtabelle_row.Item(1).Style.Add("border", "0px"); inputtabelle_row.Item(2).Add(New CHtmlSubmitButton("Reserve aufladen!", "submit")); inputtabelle_row.Item(2).Style.Add("border", "0px"); // Gutscheine kaufen row.Cells.Item(0).Add(prettyPrint("
<img src='http://a.imagehost.org/0052/gutscheine_kaufen_einloesen.png'>
Hier können Sie Gutscheine über bis zu " & CStr(maxGutscheinMenge) & " Reserveenergie kaufen oder vorhandene Gutscheine einlösen.
Beim Kauf werden die Larne direkt von Ihrem Schiff abgebucht und ein Gutscheincode erstellt,
den Sie speichern sollten.
")); form = New CHtmlForm(New CScriptUrl()); form.Add(New CHtmlInput("kaufe_gutschein", "event", EHtmlInputType.Hidden)); row.Cells.Item(0).Add(form); inputtabelle = New CTable(); form.Add(inputtabelle); inputtabelle_row = inputtabelle.AddRow(3); inputtabelle_row.Item(0).Add(prettyPrint(" Menge wählen: ")); inputtabelle_row.Item(0).Style.Add("border", "0px"); mengeFeld = New CHtmlTextBox("", "menge"); mengeFeld.Size = 5; inputtabelle_row.Item(1).Add(mengeFeld); inputtabelle_row.Item(1).Style.Add("border", "0px"); inputtabelle_row.Item(2).Add(New CHtmlSubmitButton("Gutschein kaufen!", "submit")); inputtabelle_row.Item(2).Style.Add("border", "0px"); // Gutscheine einlösen row.Cells.Item(0).Add(prettyPrint("
Um einen Gutschein einzulösen, einfach den Gutscheincode in das Feld eingeben,
dann wird das Guthaben angezeigt und der Gutschein kann benutzt werden.")); form = New CHtmlForm(New CScriptUrl()); form.Add(New CHtmlInput("show_gutschein", "event", EHtmlInputType.Hidden)); row.Cells.Item(0).Add(form); inputtabelle = New CTable(); form.Add(inputtabelle); inputtabelle_row = inputtabelle.AddRow(3); inputtabelle_row.Item(0).Add(prettyPrint(" Gutscheincode: ")); inputtabelle_row.Item(0).Style.Add("border", "0px"); mengeFeld = New CHtmlTextBox("", "code"); mengeFeld.Size = 16; inputtabelle_row.Item(1).Add(mengeFeld); inputtabelle_row.Item(1).Style.Add("border", "0px"); inputtabelle_row.Item(2).Add(New CHtmlSubmitButton("Gutschein einlösen!", "submit")); inputtabelle_row.Item(2).Style.Add("border", "0px"); // -- 3. Block - Hinweise table.Add(part_footer()); // Zeige den Link zu den aufgezeichneten Transfers, wenn ich es bin. If(GuestUser.UserID = MyShip.UserID) { Response.Add(New CHtmlBreak()); Var logform As New CHtmlForm(New CScriptUrl()); logform.Add(New CHtmlInput("show_logs", "event", EHtmlInputType.Hidden)); logform.Add(New CHtmlSubmitButton("Logs anzeigen", "submit")); Response.Add(logform); } } Function view_gutschein(menge As Integer, code As String, meldungen As CHtmlControl) { // HIER WEITERMACHEN /** * Gutscheinmenge anzeigen, Auswahl der Menge erlauben und so... */ Var table As New CTable(); Response.Add(table); Var row As CTableRow; // -- 1. Block - Logo table.Add(part_header()); // -- 2. Block - Gutschein-Informationen row = table.AddRow(1); row.Cells.Item(0).Style.Add("padding", "3px"); row.Cells.Item(0).Style.Add("text-align", "left"); row.Cells.Item(0).Add(meldungen); // <-- Fehlermeldungen reinhauen // Reserveenergie laden row.Cells.Item(0).Add(prettyPrint(" <img src='http://a.imagehost.org/0097/gutschein_einloesen.png'>
Auf dem Gutschein mit dem Code " & code & " sind noch " & menge & " Energieeinheiten gutgeschrieben.
Geben Sie hier die Menge ein, die Sie von dem Gutschein einlösen möchten.")); Var form As New CHtmlForm(New CScriptUrl()); form.Add(New CHtmlInput("transfer_gutschein", "event", EHtmlInputType.Hidden)); form.Add(New CHtmlInput(code, "code", EHtmlInputType.Hidden)); row.Cells.Item(0).Add(form); Var inputtabelle As New CTable(); form.Add(inputtabelle); Var inputtabelle_row As CTableRow = inputtabelle.AddRow(3); inputtabelle_row.Item(0).Add(prettyPrint(" Menge wählen: ")); inputtabelle_row.Item(0).Style.Add("border", "0px"); Var mengeFeld As New CHtmlTextBox("", "menge"); mengeFeld.Size = 5; inputtabelle_row.Item(1).Add(mengeFeld); inputtabelle_row.Item(1).Style.Add("border", "0px"); inputtabelle_row.Item(2).Add(New CHtmlSubmitButton("Reserve aufladen!", "submit")); inputtabelle_row.Item(2).Style.Add("border", "0px"); // Zurückknopf Response.Add(New CHtmlBreak()); Var form2 As New CHtmlForm(New CScriptUrl()); form2.Add(New CHtmlInput("show_hauptseite", "event", EHtmlInputType.Hidden)); form2.Add(New CHtmlSubmitButton("Zurück zur Hauptseite", "submit")); Response.Add(form2); } Function view_logs() { /** * Zeigt eine Tabelle mit allen bisherigen Aufladungen */ Var logs As CDataNodeList = speicher.Items.Item('logs').Items; Var table As New CTable(); Var row As CTableRow; row = table.AddRow(5); row.Cells.Item(0).Add("Ort"); row.Cells.Item(0).CssClass = "bb"; row.Cells.Item(1).Add("Spieler"); row.Cells.Item(1).CssClass = "bb"; row.Cells.Item(2).Add("Menge"); row.Cells.Item(2).CssClass = "bb"; row.Cells.Item(3).Add("Zeitpunkt"); row.Cells.Item(3).CssClass = "bb"; row.Cells.Item(4).Add("Anmerkung"); row.Cells.Item(4).CssClass = "bb"; Var i As Integer; Var log As CDataNode; Var benutzer As CUser; Var datum As Date; For(i = logs.Count - 1 To 0 Step - 1) { log = logs.Item(CStr(i)); benutzer = New CUser(log.Item("spieler").Value); datum = log.Item("datum").Value; row = table.AddRow(5); row.Cells.Item(0).Add(log.Item("position").Value); row.Cells.Item(1).Add(benutzer.GetHtmlNameAndID()); row.Cells.Item(2).Add(log.Item("menge").Value); row.Cells.Item(3).Add(datum.ToShortDateString() & " - " & datum.ToShortTimeString()); If(log.Items.ContainsKey("anmerkung")) { row.Cells.Item(4).Add(log.Item("anmerkung").Value); } Else { row.Cells.Item(4).Add("-"); } } Response.Add(table); Response.Add(New CHtmlBreak()); Var form As New CHtmlForm(New CScriptUrl()); form.Add(New CHtmlInput("show_hauptseite", "event", EHtmlInputType.Hidden)); form.Add(New CHtmlSubmitButton("Zurück zur Hauptseite", "submit")); Response.Add(form); } Function part_header() As CTableRow { /** * Generiert die oberste Tabellenzeile */ Var row As New CTableRow(1); row.Cells.Item(0).Style.Add("padding", "3px"); row.Cells.Item(0).Style.Add("text-align", "left"); Var centeredLogo As New CHtmlSpan(); centeredLogo.Style.Add("display", "block"); centeredLogo.Style.Add("text-align", "center"); centeredLogo.Add(New CHtmlImage("battery_logo_0.png")); row.Cells.Item(0).Add(centeredLogo); Return row; } Function part_footer() As CTableRow { /** * Generiert die Hinweise und Tipps. */ Var row As New CTableRow(1); row.Cells.Item(0).Style.Add("padding", "3px"); row.Cells.Item(0).Style.Add("text-align", "left");
row.Cells.Item(0).Add(prettyPrint(" Hinweise:
  • Es wird nicht überprüft, ob die Menge, die gewünscht wird, auch wirklich auf das Zielschiff passen wird.
    Dadurch kann es sein, dass zuviel Energie versucht wird aufzuladen.
    Es wird empfohlen, die Menge daher sorgfältig zu wählen, da sonst unnötige Kosten entstehen können.
  • Wenn die auf Ihrem Schiff vorhandenen Larne nicht für die gewünschte Aufladung ausreichen,
    wird die Reserve nur teilweise aufgeladen.
  • Es wird keinerlei Haftung für irgendwas, wodurch auch immer verursacht, übernommen.
  • Weiterhin besteht keinerlei Anspruch auf die Verfügbarkeit dieses Dienstes.
  • Sollte durch die Nutzung des Dienstes das Serviceschiff beschossen werden,
    hat der auslösende Kunde die Reparatur zu zahlen (4 Dura pro Hüllenpunkt).
Tipp:
  • Sollte nicht genug Energie bereitstehen, so können Sie selbst Energie zu diesem Schiff senden.
    Diese steht dann auch zur Aufladung bereit.
    Hauptenergie können Sie bei der Föderation gegen internes Ansehen bekommen.
  • Larne zum Bezahlen können am VP gegen Waren erworben werden.
"));
  Return row;
}

Function generate_messagebox(erfolg As Boolean) As CHtmlControl {
  /**
   * Generiert eine Notifikationsbox, wenn irgendeine Aktion stattgefunden hat.
   */
  Var meldungsbox As New CHtmlSpan();
  Var icon As CHtmlImage();
  meldungsbox.Style.Add("min-height", "29px");
  meldungsbox.Style.Add("font-weight", "bold");
  meldungsbox.Style.Add("padding", "6px");
  meldungsbox.Style.Add("margin", "7px");
  meldungsbox.Style.Add("background-color", "#000000");
  meldungsbox.Style.Add("display", "block");
  
  If(erfolg) {
    meldungsbox.Style.Add("color", "#00ff00");
    meldungsbox.Style.Add("border", "1px solid #1f5e1f");
    icon = New CHtmlImage("checkmark.png");
    icon.Style.Add("float", "right");
    meldungsbox.Add(icon);
  } Else {
    meldungsbox.Style.Add("color", "#ff0000");
    meldungsbox.Style.Add("border", "1px solid #903737");
    icon = New CHtmlImage("achtung.png");
    icon.Style.Add("float", "right");
    meldungsbox.Add(icon);
  }
  
  Return meldungsbox;
}
Persönliche Werkzeuge