using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Otter; using _1869_Remake; namespace _1869_Remake.Entities { public class Schiff : Entity { //Eventuell eine Auflistung machen von den Verschiedenen Schiffstypen hier und andere Entitäten davon objekte erstellen lassen //Hinweis: Wenn waren eingeladert/ausgelagert werden, die NICHT verderblich sind kann gefahrlos immer nur ein Objekt dieser Ware in der Ladeliste stehen bleiben. //Problematisch wird es bei Verderblichen Sachen -> Hier muss mit dem Verderblich kennzeichen der Ware gearbeitet werden damit bei Ankauf und Verkauf der Ware richtiges Handling stattfindet //-> Bei einkauf: Immer neue Objekte erstellen und Einkaufspreis ist abhängig von Verderbtheitsgrad //-> Bei Verkauf: Durchlauf der gesamten Ware und verkauf aller Exemplare dieser Ware; Verkaufspreis ist wie bei Einkaufspreis abhängig von Verderbtheitsgrad -> Alle Warenexemplare müssen mit ihrem jeweiligen Verderbtheitsmultiplikator verrechnet werden und als Angebotspreis angeboten werden. //-> Preisberechnung sollte immer vom Hafen aus erfolgen um Kosten/Wert zentral berechnen zu lassen //-> Schiffe sind wie eigene Filiale, die aber nicht Hafengebunden sind (und eventuell Kampfgefährt im Freibeuter modus) #region Schiffsbasis Vars // Name des Schiffs public string NAME; // Besitzer des Schiffs public Spieler COMMANDEUR; //Zustandseigenschaften des Schiffs // SCHIFFSTYP beschreibt die Art von Schiff -> Es gibt unterkategorien jedoch wird der hier eingetragene Wert größtenteils generalisiert public string SCHIFFSTYP; // Mögliche Baumaterialien // HOLZ // EISEN public string BAUMATERIAL; //Anzahl Kabinen für Passagiere public int KABINEN; //Größe des Lagerraums(in Tonnen) public int LADERAUM; // Bauzeit -> Wird von Werftklasse benötigt für ermittlung der benötigten Bauzeit public int LIEFERZEIT; // Wird bei errichten des Schiffes gesetzt und be jedem Jahr hochgezählt -> Schiffe mit hohem alter haben höhere Wahrscheinlichkeit kaputt zu gehen public int ALTER; // Maximal Mögliche Geschwindigkeit (Ohne Abzüge durch äußere Einflüsse) public int OPTIMALSPEED; //Altags-Schiffszustände public int ZUSTAND_GEFLUTET; public int ZUSTAND_VERMUSCHELT; public int ZUSTAND_TAKELAGE; public string angedocktAnHafen; public DateTime FERTIGSTELLUNGSDATUM; public bool inBau = false; public bool inBereitstellung = false; public bool inReparatur = false; #endregion #region Geldspezifischen Vars // Neuwert, den Werften für das Bauen des Schiffes oder für ein <1 Jahre altes Schiff verlangen werden public int NEUWERT; public int ANZAHLUNGSPREIS; // Tatsächliche Preis der zuletzt für dieses Schiff bezahlt wurde public int VERKAUFSWERT; // Kasse des Schiffs -> Hiervon wird Sold der Crew und geschäfte mit Häfen über das Schiff verrechnet public int SCHIFFSBUDGET; // Laufende Kosten durch Crew -> wenn Schiffsbudget nicht groß genug ist für nächste Reise wird crew streiken (Außnahme erste Reise nach Rekrutierung der Crew) public int BESATZUNGSKOSTEN; public int RESTBETRAGKAUFPREIS; public bool bezahlt = false; #endregion #region Ladungsspezifische Vars // Liste der geladenen Waren public List LADUNG = new List(); #endregion #region Mannschafts Vars // Indikator, ob eine Crew vorhanden ist public bool MANNSCHAFT_VORHANDEN; public bool MANNSCHAFT_UNTERWEGS; // Indikator, wie erfahren Crew ist -> Erfahrene Crew erhält weniger Malus auf Reise und nutzt das Schiff nicht so stark ab public int MANNSCHAFT_ERFAHRUNG; // Indikator, wie ausgelaugt Crew ist -> Wenn Fittness zu niedrig für nächste Reise, wird Crew streiken (Außnahme erste Reise nach Rektrutierung der Crew)) public int MANNSCHAFT_VITALITÄT; // Indikator für Befehlsgewalt des Captains -> Je nach Abstufung wird Schiff schneller befördert oder nicht (schneller = mehr VITALITÄTSVERLUST & mehr Abnutzung) public string KAPITÄNSORDER; // Maximale Besatzungsgröße public int MANNSCHAFT_MAXGRÖßE; #endregion //Standardkonstruktor public Schiff() { } //ParameterKontruktor public Schiff(string Name, string Typ, int Alter, Spieler Commandeur = null) { this.NAME = Name; this.ALTER = Alter; if(ALTER > 0) { //Wenn Alter gesetzt ist muss das theoretische Fertigstellungsdatum errechnet werden FERTIGSTELLUNGSDATUM = Globals.AktuellesDatum-new TimeSpan(ALTER*365,0,0,0); } if (Commandeur != null) this.COMMANDEUR = Commandeur; this.SCHIFFSTYP = Typ; setzeSchiffsTypParameter(SCHIFFSTYP); Globals.registriereEntität(this); } //Kopierkonstruktor public Schiff(Schiff KopierSchiff) { this.NAME = KopierSchiff.NAME; this.ALTER = KopierSchiff.ALTER; if(COMMANDEUR != null) this.COMMANDEUR = KopierSchiff.COMMANDEUR; this.angedocktAnHafen = KopierSchiff.angedocktAnHafen; this.SCHIFFSTYP = KopierSchiff.SCHIFFSTYP; this.setzeSchiffsTypParameter(SCHIFFSTYP); this.bezahlt = KopierSchiff.bezahlt; this.FERTIGSTELLUNGSDATUM = KopierSchiff.FERTIGSTELLUNGSDATUM; this.inBau = KopierSchiff.inBau; this.inReparatur = KopierSchiff.inReparatur; this.ZUSTAND_GEFLUTET = KopierSchiff.ZUSTAND_GEFLUTET; this.ZUSTAND_TAKELAGE = KopierSchiff.ZUSTAND_TAKELAGE; this.ZUSTAND_VERMUSCHELT = KopierSchiff.ZUSTAND_VERMUSCHELT; this.SCHIFFSBUDGET = KopierSchiff.SCHIFFSBUDGET; this.LADUNG = KopierSchiff.LADUNG; this.BESATZUNGSKOSTEN = KopierSchiff.BESATZUNGSKOSTEN; this.MANNSCHAFT_ERFAHRUNG = KopierSchiff.MANNSCHAFT_ERFAHRUNG; this.MANNSCHAFT_VITALITÄT = KopierSchiff.MANNSCHAFT_VITALITÄT; this.MANNSCHAFT_VORHANDEN = KopierSchiff.MANNSCHAFT_VORHANDEN; this.MANNSCHAFT_UNTERWEGS = KopierSchiff.MANNSCHAFT_UNTERWEGS; this.KAPITÄNSORDER = KopierSchiff.KAPITÄNSORDER; } public override void Update() { base.Update(); } //Verwaltungsmethoden für Budget public void erhöhenBudget(int Einnahmen) { SCHIFFSBUDGET += Einnahmen; } public void vermindernBudget(int Ausgaben) { SCHIFFSBUDGET -= Ausgaben; } public void initiereBau(DateTime FertigstellungAm) { //Funktion wird bei Bau des Schiffs aufgerufen um alles für den Bau festzusetzen bezahlt = false; inBau = true; FERTIGSTELLUNGSDATUM = FertigstellungAm; RESTBETRAGKAUFPREIS = NEUWERT - ANZAHLUNGSPREIS; } public void initiereBereitstellung(DateTime BereitstellungAm) { bezahlt = false; inBereitstellung = true; FERTIGSTELLUNGSDATUM = BereitstellungAm; } public void initiiereFertigstellung() { bezahlt = true; inBau = false; inBereitstellung = false; } public string schiffAbbezahlen(int GeldBetrag) { //Funktion wird aufgerufen um restbetrag zu tilgen (Aufrufendes Programm muss vorab abfangen, ob zu zahlender Betrag <= RESTBETRAGDESKAUFPREISES ist) RESTBETRAGKAUFPREIS -= GeldBetrag; if(RESTBETRAGKAUFPREIS > 0) { //Teilbetrag wurde getilgt return "ERFOLG"; } else { if (RESTBETRAGKAUFPREIS == 0) { //Schiff ist abbezahlt und bei erreichen des Datums wird schiff auf Spieler geschrieben bezahlt = true; return "ERFOLG_BEZAHLT"; } else { //Falls man versucht hat mehr als den Restbetrag zu bezahlen RESTBETRAGKAUFPREIS += GeldBetrag; return "FEHLER"; } } } public void setzeSchiffsTypParameter(string Typ) { //Hier werden alle Parameter des Schiffs gemäß seines Typs gesetzt switch (Typ) { case "SCHONER": KABINEN = 0; MANNSCHAFT_MAXGRÖßE = 12; LADERAUM = 300; LIEFERZEIT = 78; BAUMATERIAL = "HOLZ"; NEUWERT = 400000; ANZAHLUNGSPREIS = 100000; break; case "BARK": KABINEN = 0; MANNSCHAFT_MAXGRÖßE = 14; LADERAUM = 450; LIEFERZEIT = 88; BAUMATERIAL = "HOLZ"; NEUWERT = 600000; ANZAHLUNGSPREIS = 150000; break; case "HOLZDAMPFSCHIFF": KABINEN = 0; MANNSCHAFT_MAXGRÖßE = 12; LADERAUM = 399; LIEFERZEIT = 85; BAUMATERIAL = "HOLZ"; NEUWERT = 800000; ANZAHLUNGSPREIS = 200000; break; case "EISENDAMPFSCHIFF": KABINEN = 30; MANNSCHAFT_MAXGRÖßE = 19; LADERAUM = 699; LIEFERZEIT = 104; BAUMATERIAL = "EISEN"; NEUWERT = 1400000; ANZAHLUNGSPREIS = 350000; break; case "BRIGG": KABINEN = 0; MANNSCHAFT_MAXGRÖßE = 19; LADERAUM = 600; LIEFERZEIT = 97; BAUMATERIAL = "EISEN"; NEUWERT = 800000; ANZAHLUNGSPREIS = 200000; break; case "FREGATTE": KABINEN = 40; MANNSCHAFT_MAXGRÖßE = 25; LADERAUM = 999; LIEFERZEIT = 123; BAUMATERIAL = "EISEN"; NEUWERT = 1600000; ANZAHLUNGSPREIS = 400000; break; case "KLIPPER": KABINEN = 45; MANNSCHAFT_MAXGRÖßE = 27; LADERAUM = 1197; LIEFERZEIT = 135; BAUMATERIAL = "HOLZ"; NEUWERT = 1900000; ANZAHLUNGSPREIS = 475000; break; } } //Verwaltungsmethoden für Waren (Überladung, damit man die Verwaltung sowohl mit dem Namen der Ware als auch mit der Ware selbst erledigen kann... jedenfalls beim Auslagern) public void einlagernLadung(Ware neueWare) { // Einlagerung von Waren benötigt immer die effektiv erzeugte Ware Ware TempWare = new Ware(neueWare); //Überprüfen, ob dies hinzuzufügende Ware verderblich ist if (neueWare.istVerderblich()) { // Wenn ja, regulär hinzubuchen (verderbliche Ware verfolgt angepasste Logik) // To Do: Einlagerlogik für verderbliche Ware implementieren } else { // Wenn Nein neue Ware wird erstellt und der Ladung hinzugefügt oder bei existierender Ware hinzugebucht bool wareHinzugebucht = false; foreach (Ware item in LADUNG) { if (item.BEZEICHNUNG == neueWare.BEZEICHNUNG) { item.MENGE += neueWare.MENGE; wareHinzugebucht = true; break; } } if (!wareHinzugebucht) { LADUNG.Add(TempWare); } } } public void löscheLadung(string Ladung, int Menge) { // gegebenenfalls feature im Remake: Löschen der Ladung hat zeitaufwand(Eventuelle Dauer = 1 Tag in dem eventuell ausgeraubt werden kann) bool verderblich = false; // Vorabcheck ob Ware existiert und ob diese verderblich ist foreach (Ware item in LADUNG) { if (item.BEZEICHNUNG == Ladung) { verderblich = item.istVerderblich(); //Wenn Ware gefunden wurde müssen wir nicht mehr weiter durchsuchen break; } } if (verderblich) { // Sonderlogik bei verderblicher Ware // To Do: Implementieren / durchdenken!! } else { foreach (Ware item in LADUNG) { if (item.BEZEICHNUNG == Ladung) { // Angefragte Menge Reduzieren // Wenn nicht mehr genug ware vorhanden ist wird null ausgegeben if (item.MENGE - Menge < 0) { // Wenn auszulagernder Menge unter 0 ist ist ein fehler Passiert ergo nichts tun! } else { item.MENGE -= Menge; // Wenn wir mit der Auslagerung das Lager geleert haben wird es aus dem Bestand genommen if (item.MENGE == 0) LADUNG.Remove(item); } //Wenn Ware gefunden wurde müssen wir nicht mehr weiter durchsuchen break; } } } } private void sortiereVerderblichListe() { //Aufspalten in 2 Listen(Verderbliche/normale Waren) -> am Ende wieder zusammen setzen (normale Waren werden an verderblichen drangehängt [damit die zuerst gelesen werden] List TempListe = new List(); List VerderbListe = new List(); foreach (Ware item in LADUNG) { if (item.istVerderblich()) { if (VerderbListe.Count() == 0) { VerderbListe.Add(item); } else { //Wenn Liste nicht leer ist -> Vergleiche MHDs miteinander und vorne/hinten anstellen (immer nur check erstes und letztes element weil rest bereits sortiert wurde // schnelle sortiercodes gugen (ToDo) } } else { //Wenn Ware nicht verderblich -> keine besondere Sortierlogik TempListe.Add(item); } } } public void fahreInHafenEin(string HafenName) { angedocktAnHafen = HafenName; } public void fahreAusHafenHeraus() { if (angedocktAnHafen != "") angedocktAnHafen = ""; } public int verkaufsWertBestimmen() {//Funktion ist vorgesehen für interner Verkaufswert zu bestimmen // Wird erst eingebaut wenn schiffszustand(Reperaturen) implementiert sind und // die Berechnung des Verkaufswertes vom schiff übernommen wird statt vom aufrufer //Berechnung: (Neuwert/(Alter+1))*(100-Zustand des Schiffs in %) return 0; } public void besatzungBereitstellen() { MANNSCHAFT_UNTERWEGS = true; } public void besatzungEinstellen(string BesatzungsTyp) { int PreisProNase = 0; //Setzen der spezifischen Eigenschaften switch (BesatzungsTyp) { case "SPITZE": MANNSCHAFT_ERFAHRUNG = 100; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[0]; break; case "ERFAHREN": MANNSCHAFT_ERFAHRUNG = 90; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[1]; break; case "TÜCHTIG": MANNSCHAFT_ERFAHRUNG = 80; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[2]; break; case "ZUVERLÄSSIG": MANNSCHAFT_ERFAHRUNG = 70; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[3]; break; case "STANDARD": MANNSCHAFT_ERFAHRUNG = 60; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[4]; break; case "FÄHIG": MANNSCHAFT_ERFAHRUNG = 50; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[5]; break; case "BRAUCHBAR": MANNSCHAFT_ERFAHRUNG = 40; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[6]; break; case "BILLIG": MANNSCHAFT_ERFAHRUNG = 30; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[7]; break; case "GRÜNSCHNABEL": MANNSCHAFT_ERFAHRUNG = 20; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[8]; break; case "IDIOTEN": MANNSCHAFT_ERFAHRUNG = 10; PreisProNase = Globals.MannschaftskostenMin + Globals.ErfahrungsFaktor[9]; break; } //Setzen Mannschaftskosten this.BESATZUNGSKOSTEN = PreisProNase * MANNSCHAFT_MAXGRÖßE; //Setzen der allgemeinen Eigenschaften MANNSCHAFT_VORHANDEN = true; MANNSCHAFT_UNTERWEGS = false; MANNSCHAFT_VITALITÄT = 100; KAPITÄNSORDER = "MITTEL"; } } }