Browse Source

ein paar grundlegende definitionen hinzugefügt

Kolja Strohm 4 years ago
parent
commit
7034cf4396

+ 0 - 0
StickmanWorldOnline/Aufzeichnung.h


+ 36 - 0
StickmanWorldOnline/DLLStart.cpp

@@ -0,0 +1,36 @@
+#include "SpielKlasse.h"
+#include "SpielStatistik.h"
+#include "HistorieStatistik.h"
+#include "../../../../Klient/Include/AufzeichnungV.h"
+#include "Editor.h"
+//#include "..\Aufzeichnung\Aufzeichnung.h"
+
+extern "C"
+{ // Dll Einstiegs Funktionen
+	__declspec( dllexport ) SpielV *getSpielKlasse()
+	{
+		return new SpielKlasse();
+	}
+
+	__declspec( dllexport ) SpielStatistikV *GetStatistikKlasse()
+	{
+		return new SpielStatistik();
+	}
+
+	__declspec( dllexport ) AccountHistorieStatistikV *GetAccountHistorieStatistik()
+	{
+		return 0;
+		//return new HistorieStatistik();
+	}
+
+	__declspec( dllexport ) AufzeichnungV *GetAufzeichnung()
+	{
+		return 0;
+		//return new Aufzeichnung();
+	}
+
+	__declspec( dllexport ) EditorV *getEditor()
+	{
+		return new Editor::AsteroidsEditor();
+	}
+}

+ 19 - 0
StickmanWorldOnline/Dialog.h

@@ -0,0 +1,19 @@
+#pragma once
+
+#include <Fenster.h>
+#include <Schrift.h>
+
+using namespace Framework;
+
+class Dialog : public Fenster
+{
+protected:
+    bool verlassen;
+
+public:
+    // Konstruktor
+    //  zS: Die zu verwendende Schrift
+    Dialog( TextRenderer *zS );
+    // Gibt zurück ob das Fenster verlassen wurde
+    bool hatVerlassen() const;
+};

+ 68 - 0
StickmanWorldOnline/Editor.h

@@ -0,0 +1,68 @@
+#ifndef Editor_H
+#define Editor_H
+
+#include "../../../../Klient/Include/EditorV.h"
+#include "Interface.h"
+#include "EditorKlient.h"
+#include "Dialog.h"
+#include "EditorKarte.h"
+#include <Kamera2D.h>
+
+namespace Editor
+{
+    class AsteroidsEditor : public EditorV
+    {
+    private:
+        enum Status
+        {
+            START,
+            SITZUNG_FRAGE,
+            INITIALIZED,
+            WARTEND,
+            EXIT
+        };
+        Status status;
+        Schrift *schrift;
+        EditorKlient *klient;
+        Animation2D *laden;
+        Interface *i;
+        Array< Dialog* > *dialogs;
+        Critical c;
+        Punkt windowSize;
+        SpielerTeamStruktur *sts;
+        KarteDaten *daten;
+        Kamera2D *kamera;
+        Kamera2D *minimap;
+        Punkt maus;
+        EditorObject *moveObj;
+        EditorObject *rotObj;
+        unsigned char alpha;
+        bool rend;
+        int ref;
+
+        void ladeKarte();
+
+    public:
+        // Konstruktor
+        AsteroidsEditor();
+        // Destruktor
+        ~AsteroidsEditor();
+        // nicht constant
+        void addDialog( Dialog *d );
+        void setSchrift( Schrift *schrift ) override;
+        void setKlient( KSGClient::EditorServerClient *ekv ) override;
+        void setLadeAnimation( Animation2D *la ) override;
+        void setSichtbar() override;
+        void doPublicMausEreignis( MausEreignis &me ) override;
+        void doTastaturEreignis( TastaturEreignis &te ) override;
+        bool tick( double z ) override;
+        void render( Bild &zRObj ) override;
+        // constant
+        bool hatVerlassen( bool jetzt ) const override;
+        // Reference Counting
+        EditorV *getThis() override;
+        EditorV *release() override;
+    };
+}
+
+#endif

+ 195 - 0
StickmanWorldOnline/EditorKarte.h

@@ -0,0 +1,195 @@
+#pragma once
+
+#include "EditorKlient.h"
+#include <Punkt.h>
+#include <Critical.h>
+#include <functional>
+#include <Welt2D.h>
+#include <Model2D.h>
+#include <GSLDateiV.h>
+
+namespace Editor
+{
+    struct ResourceDaten
+    {
+        int id;
+        Text path;
+    };
+
+    struct SpielerDaten //: public Model
+    {
+        int id;
+        Punkt pos;
+        double rot;
+        double beschleunigung;
+        int maxStabilität;
+        int maxEnergie;
+        double reparatur;
+        double akkuLeistung;
+        int laserIntensität;
+        int laserEffizienz;
+        int laserTempo;
+        double wendigkeit;
+        double antriebEffizienz;
+        double energieSchild;
+        double energieSchildEffizienz;
+        int netzwerk;
+        int skillPunkte;
+        int m2d;
+        int bild;
+
+        SpielerDaten();
+        SpielerDaten( const SpielerDaten &daten );
+    };
+
+    struct TeamDaten// : public Model
+    {
+        int id;
+        int maxPunkte;
+        double beschleunigung;
+        int maxStabilität;
+        int maxEnergie;
+        double reparatur;
+        double akkuLeistung;
+        int laserIntensität;
+        int laserEffizienz;
+        int laserTempo;
+        double wendigkeit;
+        double antriebEffizienz;
+        double energieSchild;
+        double energieSchildEffizienz;
+        int punkte;
+
+        TeamDaten();
+        TeamDaten( const TeamDaten &daten );
+    };
+
+    struct ObjektDaten //: public Model
+    {
+        Punkt pos;
+        float rot;
+        float scale;
+        int id;
+        int m2d;
+        int bild;
+        int style;
+        int maxStabilität;
+        int maxEnergie;
+        int energieRadius;
+        double reparatur;
+        double akkuLeistung;
+        char team;
+
+        ObjektDaten();
+        ObjektDaten( const ObjektDaten &daten );
+    };
+
+    class EditorObject : public Model2DObject
+    {
+    public:
+        enum ObjektTyp
+        {
+            SPIELER,
+            OBJEKT
+        };
+
+    private:
+        ObjektTyp typ;
+        int id;
+
+    public:
+        EditorObject( ObjektTyp typ, int id );
+        virtual ~EditorObject();
+        virtual void update() = 0;
+        bool isObjekt( ObjektTyp typ, int id );
+    };
+
+    class EdSpieler : public EditorObject
+    {
+    private:
+        SpielerDaten *mdl;
+
+    public:
+        EdSpieler( SpielerDaten *model );
+        ~EdSpieler();
+        void update();
+    };
+
+    class EdObjekt : public EditorObject
+    {
+    private:
+        ObjektDaten *mdl;
+
+    public:
+        EdObjekt( ObjektDaten *model );
+        ~EdObjekt();
+        void update();
+    };
+
+    class UpdateObserver //: public View
+    {
+    private:
+        std::function< void() > f;
+
+    public:
+        UpdateObserver( std::function< void() > f );
+        //void update( Model *m ) override;
+    };
+
+    typedef GSL::GSLDateiV *( *GetGSLDatei )( );
+
+    class KarteDaten : public Thread
+    {
+    private:
+        EditorKlient *client;
+        SpielerTeamStruktur *sts;
+        Array< SpielerDaten * > spieler;
+        Array< TeamDaten * > teams;
+        Array< ObjektDaten * > objekte;
+        Array< ResourceDaten * > resources;
+        Text error;
+        Array< std::function< void() > > aktionen;
+        Critical cs;
+        Welt2D *welt;
+       // RCArray< View > views;
+        Punkt size;
+        GetGSLDatei getGSLDatei;
+        bool exit;
+
+        void loadSpielResourcePathsFromFolder( const char *folderPath, RCArray< Text > *zPaths );
+
+    public:
+        KarteDaten( EditorKlient *client, SpielerTeamStruktur *sts );
+        ~KarteDaten();
+        void addObjekt( ObjektDaten &daten, std::function< void( int ) > callBack );
+        void removeObjekt( int index );
+        void thread() override;
+        ResourceDaten *getResource( int index );
+        ObjektDaten *getObjekt( int index );
+        SpielerDaten *getSpieler( int index );
+        TeamDaten *getTeam( int index );
+        const char *getTeamName( int index );
+        int getSpielerIndexById( int id );
+        int getSpielerAnzahl() const;
+        int getTeamIndexById( int id );
+        int getTeamAnzahl() const;
+        int getObjektIndexById( int id );
+        int getObjektAnzahl() const;
+        int getResourceIndexById( int id );
+        int getResourceAnzahl();
+        bool hasError() const;
+        char *getError() const;
+        bool hasAktions() const;
+        Welt2D *getWelt() const;
+        Welt2D *zWelt() const;
+        void getResourceIdFromPath( const char *path, std::function< void( int ) > callBack );
+        bool doesResourceExist( const char *path );
+        Model2DData *loadModelFromRessource( int id );
+        Bild *loadBildFromRessource( int id );
+        Model2DData *loadModelFromPath( const char *path );
+        Bild *loadBildFromPath( const char *path );
+        void loadUnusedResourcePaths( std::function< void( RCArray< Text > * ) > callBack );
+        // löscht das objekt wenn es nicht mehr gebraucht wird und beendet den Thread
+        Thread *release() override;
+    };
+}

+ 69 - 0
StickmanWorldOnline/EditorKlient.h

@@ -0,0 +1,69 @@
+#pragma once
+
+#include <KSGNetwork.h>
+#include <Punkt.h>
+#include <Critical.h>
+
+namespace Editor
+{
+    struct ResourceDaten;
+    struct TeamDaten;
+    struct SpielerDaten;
+    struct ObjektDaten;
+
+    class SpielerTeamStruktur : public SpielerTeamStrukturV
+    {
+    public:
+        SpielerTeamStruktur();
+        ~SpielerTeamStruktur();
+        SpielerTeamStrukturV *getThis() override;
+        SpielerTeamStrukturV *release() override;
+    };
+
+    class EditorKlient
+    {
+    private:
+        KSGClient::EditorServerClient *klient;
+        Text error;
+        int ref;
+        Critical cs;
+
+        void loadMapResourcePathsFromFolder( const char *folderPath, RCArray< Text > *zPaths );
+
+    public:
+        // Konstruktor
+        //  k: Der zu verwendende Klient
+        EditorKlient( KSGClient::EditorServerClient *k );
+        // Destruktor
+        ~EditorKlient();
+        // Initialisiert den Server
+        //  return: 1, falls erfolgreich
+        //          2, falls bereits eine Sitzung existiert
+        //          0, sonnst
+        int init();
+        // Verwirft die vorhandene Sitzung und erstellt eine neue
+        bool sitzungVerwerfen();
+        // Speichert Sitzung und beendet Editor
+        bool sitzungBeenden();
+        // Lädt die Spieler Team Struktur
+        bool getSpielerTeamStruktur( SpielerTeamStrukturV *zSts );
+        bool loadMapSize( Punkt &size );
+        bool saveTeam( const TeamDaten *team );
+        bool saveSpieler( const SpielerDaten *spieler );
+        bool saveObjekt( const ObjektDaten *objekt );
+        bool deleteObjekt( int id );
+        bool loadResources( Array< ResourceDaten * > &resources );
+        int addResource( const char *path );
+        bool loadSpieler( Array< SpielerDaten* > &spieler );
+        bool loadTeams( Array< TeamDaten* > &teams );
+        bool loadObjekte( Array< ObjektDaten* > &Objekte );
+        Bild *loadBild( const char *templatePath );
+        Model2DData *loadModel( const char *templatePath );
+        RCArray< Text > *getAllMapResourcePaths();
+        // Gibt den Letzten Fehler zurück
+        char *getLastError() const;
+        // Reference Counting
+        EditorKlient *getThis();
+        EditorKlient *release();
+    };
+}

+ 47 - 0
StickmanWorldOnline/HistorieStatistik.h

@@ -0,0 +1,47 @@
+#ifndef HistorieStatistik_H
+#define HistorieStatistik_H
+
+#include <AccountHistorieStatistikV.h>
+#include "SpielStatistikDaten.h"
+#include "StatistikTabelle.h"
+
+class HistorieStatistik : public AccountHistorieStatistikV
+{
+private:
+	Schrift *schrift;
+	Bildschirm *screen;
+	Array< SSDSpieler* > *gss;
+	Array< SSDTeam* > *gts;
+	StatistikTabelle *tabelle;
+	Knopf *fertig;
+	bool geladen;
+	bool geschlossen;
+	unsigned char alpha;
+	bool sichtbar;
+	double tickVal;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	HistorieStatistik();
+	// Destruktor
+	~HistorieStatistik();
+	// nicht constant
+	virtual void setSchrift( Schrift *schrift );
+	virtual void setBildschirm( Bildschirm *zScreen );
+	virtual void ladeDaten( int spielId );
+	virtual void setSichtbar( bool sichtbar );
+	virtual void doPublicMausEreignis( MausEreignis &me );
+	virtual void doTastaturEreignis( TastaturEreignis &te );
+	virtual bool tick( double tickVal );
+	virtual void render( Bild &zRObj );
+	// constant
+	virtual bool istNochSichtbar() const;
+	virtual bool wurdeGeschlossen() const;
+	// Reference Counting
+	virtual AccountHistorieStatistikV *getThis();
+	virtual AccountHistorieStatistikV *release();
+};
+
+#endif

+ 216 - 0
StickmanWorldOnline/Initialisierung.cpp

@@ -0,0 +1,216 @@
+#include "Initialisierung.h"
+#include <ToolTip.h>
+#include <Bildschirm.h>
+#include <MausEreignis.h>
+
+Knopf *initKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *titel )
+{
+	Knopf *ret = new Knopf();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( titel )
+		ret->setText( titel );
+	return ret;
+}
+
+KontrollKnopf *initKontrollKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *txt )
+{
+	KontrollKnopf *ret = new KontrollKnopf();
+	ret->addStyle( style );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( txt )
+	{
+		ret->setText( txt );
+		ret->setSText( txt );
+	}
+	ret->setSFarbe( 0xFFFFFFFF );
+	ret->setSSize( 12 );
+	if( ret->hatStyle( TextFeld::Style::Buffered ) )
+	{
+		ret->setAlphaFeldFarbe( 0x5500FF00 );
+		ret->setAlphaFeldStrength( -5 );
+	}
+	if( ret->hatStyle( TextFeld::Style::Rahmen ) )
+	{
+		ret->setRahmenBreite( 1 );
+		ret->setRahmenFarbe( 0xFF00FF00 );
+	}
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	ret->loadData( "data/bilder/system.ltdb" );
+    ret->setMausEreignis( _ret1ME );
+	return ret;
+}
+
+Fenster *initFenster( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *titel )
+{
+	Fenster *ret = new Fenster();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ret->hatStyle( Fenster::Style::Rahmen ) )
+	{
+		ret->setRBreite( 1 );
+		ret->setRFarbe( 0xFFFFFFFF );
+	}
+	if( ret->hatStyle( Fenster::Style::Titel ) )
+	{
+		if( titel )
+			ret->setTitel( titel );
+		if( zSchrift )
+			ret->setTSchriftZ( zSchrift->getThis() );
+		ret->setTSFarbe( 0xFFFFFFFF );
+		ret->zTTextFeld()->setSize( 0, 20 );
+		ret->zTTextFeld()->addStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center | TextFeld::Style::Rahmen );
+		ret->setTRFarbe( 0xFF00FF00 );
+		ret->setTRBreite( 1 );
+		if( ret->hatStyle( Fenster::Style::TitelBuffered ) )
+		{
+			ret->setTAfFarbe( 0x1000FF00 );
+			ret->setTAfStrength( -15 );
+		}
+	}
+	return ret;
+}
+
+TextFeld *initTextFeld( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *txt )
+{
+	TextFeld *ret = new TextFeld();
+	ret->setStyle( style );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( txt )
+		ret->setText( txt );
+	ret->setSchriftFarbe( 0xFFFFFFFF );
+	ret->setSchriftSize( 12 );
+	if( ret->hatStyle( TextFeld::Style::Buffered ) )
+	{
+		ret->setAlphaFeldFarbe( 0x5500FF00 );
+		ret->setAlphaFeldStrength( -5 );
+	}
+	if( ret->hatStyle( TextFeld::Style::Rahmen ) )
+	{
+		ret->setRahmenBreite( 1 );
+		ret->setRahmenFarbe( 0xFF00FF00 );
+	}
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	return ret;
+}
+
+BildZ *initBildZ( int x, int y, int br, int hö, int style, Bild *b )
+{
+	BildZ *ret = new BildZ();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( b )
+		ret->setBildZ( b );
+	if( ( style | BildZ::Style::Rahmen ) == style )
+	{
+		ret->setRahmenBreite( 1 );
+		ret->setRahmenFarbe( 0xFFFFFFFF );
+	}
+	return ret;
+}
+
+AuswahlBox *initAuswahlBox( int x, int y, int br, int hö, Schrift *zSchrift, __int64 style, std::initializer_list< const char * > values )
+{
+	AuswahlBox *ret = new AuswahlBox();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ( style | AuswahlBox::Style::Hintergrund ) == style )
+		ret->setHintergrundFarbe( 0xFF000000 );
+	if( ( style | AuswahlBox::Style::Erlaubt ) == style )
+		ret->setMausEreignis( _ret1ME );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( ( style | AuswahlBox::Style::Rahmen ) == style )
+	{
+		ret->setRahmenBreite( 1 );
+		ret->setRahmenFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | AuswahlBox::Style::MaxHeight ) == style )
+		ret->setMaxAuskappHeight( 100 );
+	if( ( style | AuswahlBox::Style::MausRahmen ) == style )
+	{
+		ret->setMausRahmenBreite( 1 );
+		ret->setMausRahmenFarbe( 0xFF005500 );
+	}
+	if( ( style | AuswahlBox::Style::MausBuffer ) == style )
+	{
+		ret->setMausAlphaFeldFarbe( 0x00008700 );
+		ret->setMausAlphaFeldStrength( -8 );
+	}
+	if( ( style | AuswahlBox::Style::AuswahlRahmen ) == style )
+	{
+		ret->setAuswRahmenBreite( 1 );
+		ret->setAuswRahmenFarbe( 0xFF00FF00 );
+	}
+	if( ( style | AuswahlBox::Style::AuswahlBuffer ) == style )
+	{
+		ret->setAuswAlphaFeldFarbe( 0x0000FF00 );
+		ret->setAuswAlphaFeldStrength( -8 );
+	}
+	for( auto i = values.begin(); i != values.end(); i++ )
+	{
+		ret->addEintrag( *i );
+	}
+	return ret;
+}
+
+ObjTabelle *initObjTabelle( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< OBJTabelleSpalteIni > spalten, int überschriftHöhe )
+{
+	ObjTabelle *ret = new ObjTabelle();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ( style | ObjTabelle::Style::Erlaubt ) == style )
+		ret->setMausEreignis( _ret1ME );
+	if( ( style | ObjTabelle::Style::Rahmen ) == style )
+	{
+		ret->setRahmenBreite( 1 );
+		ret->setRahmenFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | ObjTabelle::Style::Raster ) == style )
+	{
+		ret->setRasterBreite( 1 );
+		ret->setRasterFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | ObjTabelle::Style::VScroll ) == style )
+		ret->setVertikalKlickScroll( 5 );
+	if( ( style | ObjTabelle::Style::HScroll ) == style )
+		ret->setHorizontalKlickScroll( 5 );
+	for( auto i = spalten.begin(); i != spalten.end(); i++ )
+	{
+		ret->addSpalte( i->name );
+		ret->setSpaltenBreite( i->name, i->breite );
+		if( ( style | ObjTabelle::Style::SpaltenBreiteMin ) == style )
+			ret->setMinSpaltenBreite( i->name, i->minBreite );
+		if( ( style | ObjTabelle::Style::SpaltenBreiteMax ) == style )
+			ret->setMaxSpaltenBreite( i->name, i->maxBreite );
+		if( überschriftHöhe )
+		{
+			if( ret->getZeilenNummer( "Überschrift" ) < 0 )
+			{
+				ret->addZeile( 0, "Überschrift" );
+				ret->setZeilenHeight( 0, 20 );
+			}
+			ret->setZeichnungZ( i->name, "Überschrift", initTextFeld( 0, 0, i->breite, 20, zSchrift, TextFeld::Style::Text, i->name ) );
+		}
+	}
+	return ret;
+}
+
+void initToolTip( Zeichnung *obj, const char *txt, Schrift *zSchrift, Bildschirm *zBs )
+{
+	obj->setToolTipText( txt, zBs, zSchrift );
+	obj->zToolTip()->addStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen | TextFeld::Style::Hintergrund | TextFeld::Style::HAlpha | TextFeld::Style::Mehrzeilig );
+	obj->zToolTip()->setHintergrundFarbe( 0xA0000000 );
+	obj->zToolTip()->setRahmenFarbe( 0xFFFFFFFF );
+}

+ 32 - 0
StickmanWorldOnline/Initialisierung.h

@@ -0,0 +1,32 @@
+#ifndef Initialisierung_H
+#define Initialisierung_H
+
+#include <Knopf.h>
+#include <Fenster.h>
+#include <TextFeld.h>
+#include <Schrift.h>
+#include <Bild.h>
+#include <AuswahlBox.h>
+#include <Tabelle.h>
+#include <initializer_list>
+
+using namespace Framework;
+
+struct OBJTabelleSpalteIni
+{
+    const char *name;
+	int breite;
+	int minBreite;
+	int maxBreite;
+};
+
+Knopf *initKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *titel );
+KontrollKnopf *initKontrollKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *txt );
+Fenster *initFenster( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *titel );
+TextFeld *initTextFeld( int x, int y, int br, int hö, Schrift *zSchrift, int style, const char *txt );
+BildZ *initBildZ( int x, int y, int br, int hö, int style, Bild *b );
+AuswahlBox *initAuswahlBox( int x, int y, int br, int hö, Schrift *zSchrift, __int64 style, std::initializer_list< const char * > values );
+ObjTabelle *initObjTabelle( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< OBJTabelleSpalteIni > spalten, int überschriftHöhe );
+void initToolTip( Zeichnung *obj, const char *txt, Schrift *zSchrift, Bildschirm *zBs );
+
+#endif

+ 50 - 0
StickmanWorldOnline/Interface.h

@@ -0,0 +1,50 @@
+#pragma once
+
+#include <Fenster.h>
+#include <Knopf.h>
+#include "RightTools.h"
+#include "EditorKarte.h"
+
+using namespace Framework;
+
+namespace Editor
+{
+    class Interface : public ZeichnungHintergrund
+    {
+    private:
+        Knopf * beenden;
+        RightTools *right;
+        KarteDaten *daten;
+        Schrift *schrift;
+        bool verlassen;
+        int ref;
+
+    public:
+        // Konstruktor
+        //  zS: Ein Zeiger auf die zu verwendende Schrift
+        Interface( Schrift *zS, Punkt maxSize );
+        // Destruktor
+        ~Interface();
+        void setDaten( KarteDaten *daten );
+        // Verarbeitet eine Mausnachricht
+        //  me: Die Nachricht die verarbeitet werden soll
+        void doPublicMausEreignis( MausEreignis &me ) override;
+        // Verarbeitet eine Tastaturnachricht
+        //  te: Die Nachricht die verarbeitet werden soll
+        void doTastaturEreignis( TastaturEreignis &te ) override;
+        bool tick( double time ) override;
+        // Zeichnet das Interface nach uRObj
+        //  zRObj: Das Bild in das gezeichnet werden soll
+        void render( Bild &zRObj ) override;
+        // Setzt das Interface in den Initialisierungszustand zurück
+        void reset();
+        // Gibt zurück, ob der Benutzer den Editor verlassen möchte
+        bool hatVerlassen() const;
+        // erhöht den Reference Counter
+        //  return: this
+        Interface *getThis();
+        // verringert den Reference Counter und löscht das Objekt wenn es nicht mehr gebraucht wird.
+        //  return: 0
+        Interface *release();
+    };
+}

+ 40 - 0
StickmanWorldOnline/RightTools.h

@@ -0,0 +1,40 @@
+#pragma once
+
+#include <AuswahlBox.h>
+#include "EditorKlient.h"
+
+using namespace Framework;
+
+class RightTool : public Zeichnung
+{
+private:
+    int ref;
+
+public:
+    RightTool();
+    virtual ~RightTool();
+    virtual void renderDialogs( Bild &rObj );
+    RightTool *getThis();
+    RightTool *release();
+};
+
+class RightTools : public ZeichnungHintergrund
+{
+private:
+    AuswahlBox *toolAuswahl;
+    RCArray< RightTool > *tools;
+    Punkt maxSize;
+    int ref;
+
+public:
+    RightTools( Schrift *zSchrift, Punkt maxSize );
+    ~RightTools();
+    void addTool( RightTool *tool, char *name );
+    void doPublicMausEreignis( MausEreignis &me ) override;
+    void doTastaturEreignis( TastaturEreignis &te ) override;
+    bool tick( double tickVal ) override;
+    void render( Bild &rObj ) override;
+    void selectTool( int index );
+    RightTools *getThis();
+    RightTools *release();
+};

+ 98 - 0
StickmanWorldOnline/SpielKlasse.h

@@ -0,0 +1,98 @@
+#ifndef SpielKlasse_H
+#define SpielKlasse_H
+
+#include "SpielV.h"
+#include "Spieler\Spieler.h"
+#include "Karte\Karte.h"
+#include "Chat\Chat.h"
+#include "Ende\Ende.h"
+#include "Bestenliste\Bestenliste.h"
+#include "..\Netzwerk\STKNachricht.h"
+#include "Schuss\Laser.h"
+#include <Bildschirm.h>
+#include "Objekt/SpielObjekt.h"
+#include <Kamera2D.h>
+#include "Asteroid/Asteroid.h"
+#include "Asteroid/Pixel.h"
+
+class SpielKlasse : public SpielV
+{
+private:
+    struct SaveData
+    {
+        int spielZeit;
+    };
+
+	RCArray< STKNachricht > *stkn;
+	int stkna;
+	Bestenliste *bestenliste;
+	Schrift *schrift;
+    KSGClient::InformationServerClient *infoKlient;
+    KSGClient::SpielServerClient *spielKlient;
+	RCArray< Spieler > *spieler;
+    RCArray< Asteroid > *asteroids;
+	RCArray< Team > *teams;
+	RCArray< SpielObjekt > *objekte;
+    RCArray< Laser > *schüsse;
+	Bildschirm *screen;
+	Karte *map;
+	Kamera2D *kam;
+    Kamera2D *minimap;
+    Welt2D *welt;
+	SpielChat *chat;                                                                                                   
+	Ende *end;
+	SpielerGUI *shipGUI;
+    Datei csv;
+    RCArray< DeadPlayer > *deads;
+    RCArray< Model2DData > *asteroidModels;
+    RCArray< Textur2D > *asteroidTextures;
+    RCArray< Pixel > *pixel;
+    Bild *speedBoost;
+    Bild *shieldBoost;
+	bool rendern;
+	int spielZeit;
+	double rZeit;
+	int spielerAnzahl;
+	int karteId;
+	int ladenProzent;
+	int spielerNummer;
+	char *tasten;
+	bool spielPause;
+    SaveData last;
+    bool setKam;
+	int ref;
+
+	bool istAmLeben() const;
+    void goBackInTime( int zeit );
+    void goToPresence( int zeit );
+    void load();
+    void save();
+    void tick();
+
+public:
+	// Konstruktor
+	SpielKlasse();
+	// Destruktor
+	~SpielKlasse();
+	// nicht constant
+	void lock();
+	void unlock();
+	void setSchrift( Schrift *schrift ) override; // call 4
+	void setBildschirm( Bildschirm *zScreen ) override; // call 3
+	void nachricht( int län, char *bytes ) override;
+	void setKlients( KSGClient::InformationServerClient *infoKlient, KSGClient::SpielServerClient *spielKlient ) override; // call 2
+	void setKarteId( int karteId ) override; // call 1
+	void ladeDaten() override; // call 5
+	void doPublicMausEreignis( MausEreignis &me ) override;
+	void doTastaturEreignis( TastaturEreignis &te ) override;
+	void stknVerarbeitung();
+	bool tick( double zeit ) override;
+	void render( Bild &zRObj ) override;
+	// constant
+	int läuft() const override;
+	// Reference Counting
+	SpielV *getThis() override;
+	SpielV *release() override;
+};
+
+#endif

+ 63 - 0
StickmanWorldOnline/SpielStatistik.h

@@ -0,0 +1,63 @@
+#ifndef SpielStatistik_H
+#define SpielStatistik_H
+
+#include <SpielStatistikV.h>
+#include "SpielStatistikDaten.h"
+#include "StatistikChat.h"
+#include "StatistikTabelle.h"
+
+class SpielStatistik : public SpielStatistikV
+{
+private:
+	void( *addNachrichtF )( void *, Text *, Text *, Text *, Text * );
+	void( *addChatF )( void *, int );
+	void( *addFreundF )( void *, int );
+	void( *accountAnsehenF )( void *, int );
+	bool( *istFreundF )( void *, int );
+	void *nachrichtParam;
+	BilderV *bilder;
+	Schrift *schrift;
+	Bildschirm *screen;
+    KSGClient::InformationServerClient *infoc;
+    KSGClient::SpielServerClient *spielc;
+	CRITICAL_SECTION cs;
+	Array< SSDSpieler* > *gss;
+	Array< SSDTeam* > *gts;
+	StatistikChat *chat;
+	StatistikTabelle *tabelle;
+	int accountId;
+	bool rend;
+	int status;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielStatistik();
+	// Destruktor
+	~SpielStatistik();
+	// nicht constant
+	void lock();
+	void unlock();
+	virtual void bereit();
+	virtual void setBilder( BilderV *b );
+	virtual void setAccountId( int id );
+	virtual void setRückrufFunktionen( void( *addNachrichtF )( void *, Text *, Text *, Text *, Text * ),
+															   void( *addChatF )( void *, int ), void( *addFreundF )( void *, int ),
+															   void( *accountAnsehenF )( void *, int ), bool( *istFreundF )( void *, int ), void *nachrichtParam );
+	virtual void setSchrift( Schrift *schrift );
+	virtual void setBildschirm( Bildschirm *zScreen );
+	virtual void setKlients( KSGClient::InformationServerClient *infoc, KSGClient::SpielServerClient *spielc );
+	virtual void nachricht( int län, char *bytes );
+	virtual void doPublicMausEreignis( MausEreignis &me );
+	virtual void doTastaturEreignis( TastaturEreignis &te );
+	virtual bool tick( double zeit );
+	virtual void render( Bild &zRObj );
+	virtual void verlassen();
+	// constant
+	virtual int getStatus() const; // 0 = laden, 1 = läuft, 2 = fortsetzen
+	// Reference Counting
+	virtual SpielStatistikV *getThis();
+	virtual SpielStatistikV *release();
+};
+
+#endif

+ 45 - 0
StickmanWorldOnline/SpielStatistikDaten.h

@@ -0,0 +1,45 @@
+#ifndef SpielStatistikDaten_H
+#define SpielStatistikDaten_H
+
+#include <Text.h>
+#include <Bild.h>
+#include <Array.h>
+
+using namespace Framework;
+
+struct SSDSpieler
+{
+	int spielerNummer;
+	Text spielerName;
+	Text teamName;
+	int spielerFarbe;
+	int teamFarbe;
+	int schadenBekommen;
+	int schadenGemacht;
+	int treibstoffVerbraucht;
+	int schüsse;
+	int treffer;
+	int punkte;
+	int kills;
+	int tode;
+	int zeitAmLeben;
+	int zeitTod;
+};
+
+struct SSDTeam
+{
+	int teamNummer;
+	Text teamName;
+	int teamFarbe;
+	int schadenBekommen;
+	int schadenGemacht;
+	int treibstoffVerbraucht;
+	int schüsse;
+	int treffer;
+	int punkte;
+	int kills;
+	int tode;
+	bool gewonnen;
+};
+
+#endif

+ 482 - 0
StickmanWorldOnline/StatistikChat.cpp

@@ -0,0 +1,482 @@
+#include "StatistikChat.h"
+#include <Punkt.h>
+#include <DateiSystem.h>
+#include <MausEreignis.h>
+#include <AlphaFeld.h>
+#include <Scroll.h>
+#include <Rahmen.h>
+#include <TastaturEreignis.h>
+#include "Initialisierung.h"
+
+// Inhalt der ChatListeSpieler Klasse aus StatistikChat.h
+// Konstruktor
+ChatListeSpieler::ChatListeSpieler( int accountId, int eigeneId, Schrift *zSchrift, BilderV *bilder, KSGClient::InformationServerClient *zInfoc,
+									bool istFreund, void( *addChatF )( void*, int ), void( *addFreundF )( void*, int ),
+									void( *accountAnsehenF )( void *, int ), void *param )
+									: addChatF( addChatF ),
+									addFreundF( addFreundF ),
+									accountAnsehenF( accountAnsehenF ),
+									nachrichtParam( param ),
+									accountId( accountId ),
+									bg( new AlphaFeld() ),
+									name( initTextFeld( 0, 0, 133, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Rahmen | TextFeld::Style::VCenter, "" ) ),
+									accountAnsehen( initKnopf( 133, 0, 20, 20, 0, 0, "" ) ),
+									nachrichtSenden( initKnopf( 153, 0, 20, 20, 0, 0, "" ) ),
+									freundesanfrageSenden( initKnopf( 173, 0, 20, 20, 0, 0, "" ) ),
+									pos( 0, 0 ),
+									gr( 133, 20 ),
+									online( 1 ),
+									minKnopfX( 113 - ( ( ( accountId != eigeneId ) + !istFreund ) * 20 ) ),
+									knopfX( 133 ),
+									mausIn( 0 ),
+									tickVal( 0 ),
+									rend( 0 ),
+									ref( 1 )
+{
+	Bild *ansehenBild = bilder->get( "data/client/bilder/chat.ltdb/ansehen.png" );
+	Bild *nachrichtBild = bilder->get( "data/client/bilder/chat.ltdb/nachricht.png" );
+	Bild *einladungBild = bilder->get( "data/client/bilder/chat.ltdb/neuerfreund.png" );
+	bg->setSize( gr );
+	bg->setFarbe( 0x0000FF00 );
+	bg->setStrength( -4 );
+	name->setText( zInfoc->getSpielerName( accountId ) );
+	accountAnsehen->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	accountAnsehen->setHintergrundBildZ( ansehenBild );
+	nachrichtSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	nachrichtSenden->setHintergrundBildZ( nachrichtBild );
+	freundesanfrageSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	freundesanfrageSenden->setHintergrundBildZ( einladungBild );
+}
+
+// Destruktor
+ChatListeSpieler::~ChatListeSpieler()
+{
+	bg->release();
+	name->release();
+	accountAnsehen->release();
+	nachrichtSenden->release();
+	freundesanfrageSenden->release();
+}
+
+// nicht constant
+void ChatListeSpieler::setOffline()
+{
+	online = 0;
+}
+
+void ChatListeSpieler::setPosition( int y )
+{
+	if( pos.y != y )
+		rend = 1;
+	pos.y = y;
+}
+
+void ChatListeSpieler::doPublicMausEreignis( MausEreignis &me )
+{
+	int mx = me.mx;
+	int my = me.my;
+	me.mx -= pos.x;
+	me.my -= pos.y;
+	if( me.mx > 0 && me.mx < gr.x && me.my > 0 && me.my < gr.y )
+		mausIn = 1;
+	else
+		mausIn = 0;
+	me.mx += 133 - knopfX;
+	bool vera = me.verarbeitet;
+	accountAnsehen->doPublicMausEreignis( me );
+	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
+	nachrichtSenden->doPublicMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
+	freundesanfrageSenden->doPublicMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 3 : aktion;
+	me.mx -= 133 - knopfX;
+	if( me.id == ME_RLinks && mausIn )
+	{
+		switch( aktion )
+		{
+		case 1:
+			accountAnsehenF( nachrichtParam, accountId );
+			break;
+		case 2:
+			addChatF( nachrichtParam, accountId );
+			break;
+		case 3:
+			addFreundF( nachrichtParam, accountId );
+			break;
+		}
+	}
+	me.mx = mx;
+	me.my = my;
+}
+
+bool ChatListeSpieler::tick( double tickVal )
+{
+	rend |= name->tick( tickVal );
+	rend |= accountAnsehen->tick( tickVal );
+	rend |= nachrichtSenden->tick( tickVal );
+	rend |= freundesanfrageSenden->tick( tickVal );
+	this->tickVal += tickVal * 60;
+	int val = ( int )this->tickVal;
+	if( val )
+	{
+		this->tickVal -= val;
+		if( mausIn && knopfX != minKnopfX )
+		{
+			if( knopfX - val < minKnopfX )
+				knopfX = minKnopfX;
+			else
+				knopfX -= val;
+			rend = 1;
+		}
+		if( !mausIn && knopfX != gr.x )
+		{
+			if( knopfX + val > gr.x )
+				knopfX = gr.x;
+			else
+				knopfX += val;
+			rend = 1;
+		}
+		if( !online && bg->getFarbe() != 0x00FF0000 )
+		{
+			int g = ( bg->getFarbe() >> 8 ) & 0xFF;
+			if( g - val < 0 )
+				bg->setFarbe( 0x00FF0000 );
+			else
+			{
+				bg->setFarbe( ( ( ( g - val ) << 8 ) & 0xFF00 ) | ( bg->getFarbe() & 0xFFFF00FF ) );
+				bg->setFarbe( ( ( ( 255 - ( g - val ) ) << 16 ) & 0xFF0000 ) | ( bg->getFarbe() & 0xFF00FFFF ) );
+			}
+			rend = 1;
+		}
+	}
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void ChatListeSpieler::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( pos, gr ) )
+		return;
+	bg->render( zRObj );
+	name->render( zRObj );
+	zRObj.addScrollOffset( 133 - knopfX, 0 );
+	accountAnsehen->render( zRObj );
+	nachrichtSenden->render( zRObj );
+	freundesanfrageSenden->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int ChatListeSpieler::getAccountId() const
+{
+	return accountId;
+}
+
+// Reference Counting
+ChatListeSpieler *ChatListeSpieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+ChatListeSpieler *ChatListeSpieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der ChatListe Klasse aus StatistikChat.h
+// Konstruktor
+ChatListe::ChatListe( int eigeneId, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
+					  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+					  void( *accountAnsehen )( void *, int ), void *param )
+					  : addChat( addChat ),
+					  addFreund( addFreund ),
+					  accountAnsehen( accountAnsehen ),
+					  nachrichtParam( nachrichtParam ),
+					  eigeneId( eigeneId ),
+					  spieler( new RCArray< ChatListeSpieler >() ),
+					  vScroll( new VScrollBar() ),
+					  pos( 620, 295 ),
+					  gr( 150, 150 ),
+					  infoc( infoc ),
+					  schrift( schrift ),
+					  bilder( bilder ),
+					  ram( new LRahmen() ),
+					  rend( 0 ),
+					  ref( 1 )
+{
+	vScroll->setKlickScroll( 10 );
+	vScroll->update( 0, 148 );
+	ram->setFarbe( 0xFFFFFFFF );
+	ram->setSize( 150, 150 );
+}
+
+// Destruktor
+ChatListe::~ChatListe()
+{
+	spieler->release();
+	vScroll->release();
+	infoc->release();
+	schrift->release();
+	ram->release();
+}
+
+// nicht constant
+void ChatListe::addSpieler( int accountId, bool istFreund )
+{
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
+			return;
+	}
+	ChatListeSpieler *s = new ChatListeSpieler( accountId, eigeneId, schrift, bilder, infoc, istFreund, addChat, addFreund, accountAnsehen, nachrichtParam );
+	s->setPosition( anz * 20 );
+	spieler->add( s );
+	rend = 1;
+}
+
+void ChatListe::setOffline( int accountId )
+{
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
+		{
+			spieler->z( i )->setOffline();
+			return;
+		}
+	}
+}
+
+void ChatListe::doPublicMausEreignis( MausEreignis &me )
+{
+	int mx = me.mx;
+	int my = me.my;
+	me.mx -= pos.x;
+	me.my -= pos.y - vScroll->getScroll();
+	vScroll->doMausMessage( 134, 1, 15, 148, me );
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			spieler->z( i )->doPublicMausEreignis( me );
+	}
+	me.mx = mx;
+	me.my = my;
+}
+
+bool ChatListe::tick( double tickVal )
+{
+	rend |= vScroll->getRend();
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			rend |= spieler->z( i )->tick( tickVal );
+	}
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void ChatListe::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( pos, gr ) )
+		return;
+	int anz = spieler->getEintragAnzahl();
+	zRObj.addScrollOffset( 0, vScroll->getScroll() );
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			spieler->z( i )->render( zRObj );
+	}
+	zRObj.addScrollOffset( 0, -vScroll->getScroll() );
+	vScroll->render( 134, 1, 15, 148, zRObj );
+	ram->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+
+// Reference Counting
+ChatListe *ChatListe::getThis()
+{
+	ref++;
+	return this;
+}
+
+ChatListe *ChatListe::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der StatistikChat Klasse aus StatistikChat.h
+// Konstruktor
+StatistikChat::StatistikChat( int eigeneId, KSGClient::SpielServerClient *spielc, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
+							  void( *addNachricht )( void *, Text *, Text *, Text *, Text * ),
+							  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+							  void( *accountAnsehen )( void *, int ), void *param )
+							  : addNachricht( addNachricht ),
+							  nachrichtParam( nachrichtParam ),
+							  spielc( spielc ),
+							  infoc( infoc ),
+							  verlauf( initTextFeld( 10, 295, 600, 150, schrift, TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen | TextFeld::Style::VScroll | TextFeld::Style::Mehrzeilig, "" ) ),
+							  nachricht( initTextFeld( 10, 450, 575, 20, schrift, TextFeld::Style::TextFeld, "" ) ),
+							  senden( initKnopf( 590, 450, 20, 20, 0, 0, "" ) ),
+							  verlassen( initKnopf( 630, 450, 130, 20, schrift, Knopf::Style::Sichtbar, "Verlassen" ) ),
+							  spielerListe( new ChatListe( eigeneId, infoc->getThis(), schrift, bilder, addChat, addFreund, accountAnsehen, nachrichtParam ) ),
+							  beenden( 0 ),
+							  ref( 1 )
+{
+	Bild *sendenBild = bilder->get( "data/client/bilder/chat.ltdb/senden.png" );
+	senden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	senden->setHintergrundBildZ( sendenBild );
+}
+
+// Destruktor
+StatistikChat::~StatistikChat()
+{
+	spielc->release();
+	infoc->release();
+	verlauf->release();
+	nachricht->release();
+	senden->release();
+	verlassen->release();
+	spielerListe->release();
+}
+
+// nicht constant
+void StatistikChat::addSpieler( int accountId, bool istFreund )
+{
+	spielerListe->addSpieler( accountId, istFreund );
+}
+
+void StatistikChat::spielerOffline( int accountId )
+{
+	spielerListe->setOffline( accountId );
+}
+
+void StatistikChat::addChatNachricht( int vonAccount, char *nachricht )
+{
+	Text *txt = vonAccount ? infoc->getSpielerName( vonAccount ) : 0;
+	if( !txt )
+		txt = new Text();
+	else
+		*txt += ": ";
+	*txt += nachricht;
+	*txt += "\n";
+	verlauf->zTextRenderer()->textFormatieren( txt, verlauf->getBreite() - 15 );
+	verlauf->zText()->append( txt );
+	verlauf->updateVScroll();
+}
+
+void StatistikChat::doPublicMausEreignis( MausEreignis &me )
+{
+	verlauf->doPublicMausEreignis( me );
+	nachricht->doPublicMausEreignis( me );
+	spielerListe->doPublicMausEreignis( me );
+	bool vera = me.verarbeitet;
+	senden->doPublicMausEreignis( me );
+	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
+	verlassen->doPublicMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
+	if( me.id == ME_RLinks )
+	{
+		if( aktion == 1 )
+		{
+			if( nachricht->zText()->getLength() )
+			{
+				short län = 1 + nachricht->zText()->getLength();
+				char *bytes = new char[ län ];
+				bytes[ 0 ] = 1;
+				for( int i = 0; i < län - 1; i++ )
+					bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
+				if( !spielc->statistikNachricht( län, bytes ) )
+					addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0 );
+				else
+				{
+					nachricht->setAuswahl( 0, 0 );
+					nachricht->setText( "" );
+				}
+				delete[] bytes;
+			}
+		}
+		if( aktion == 2 )
+			beenden = 1;
+	}
+}
+
+void StatistikChat::doTastaturEreignis( TastaturEreignis &te )
+{
+	bool vera = te.verarbeitet;
+	nachricht->doTastaturEreignis( te );
+	if( !vera && te.verarbeitet && te.id == TE_Release && te.taste == T_Enter )
+	{
+		if( nachricht->zText()->getLength() )
+		{
+			short län = 1 + nachricht->zText()->getLength();
+			char *bytes = new char[ län ];
+			bytes[ 0 ] = 1;
+			for( int i = 0; i < län - 1; i++ )
+				bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
+			if( !spielc->statistikNachricht( län, bytes ) )
+				addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0 );
+			else
+			{
+				nachricht->setAuswahl( 0, 0 );
+				nachricht->setText( "" );
+			}
+			delete[] bytes;
+		}
+	}
+}
+
+bool StatistikChat::tick( double tickVal )
+{
+	bool rend = verlauf->tick( tickVal );
+	rend |= nachricht->tick( tickVal );
+	rend |= senden->tick( tickVal );
+	rend |= verlassen->tick( tickVal );
+	rend |= spielerListe->tick( tickVal );
+	return rend;
+}
+
+void StatistikChat::render( Bild &zRObj )
+{
+	verlauf->render( zRObj );
+	nachricht->render( zRObj );
+	senden->render( zRObj );
+	verlassen->render( zRObj );
+	spielerListe->render( zRObj );
+}
+
+// constant
+bool StatistikChat::hatVerlassen()
+{
+	return beenden;
+}
+
+// Reference Counting
+StatistikChat *StatistikChat::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikChat *StatistikChat::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 132 - 0
StickmanWorldOnline/StatistikChat.h

@@ -0,0 +1,132 @@
+#ifndef StatistikChat_H
+#define StatistikChat_H
+
+#include <Fenster.h>
+#include <Knopf.h>
+#include <KSGNetwork.h>
+#include <BilderV.h>
+#include <Rahmen.h>
+
+using namespace Framework;
+
+class ChatListeSpieler
+{
+private:
+	void( *addChatF )( void *, int );
+	void( *addFreundF )( void *, int );
+	void( *accountAnsehenF )( void *, int );
+	void *nachrichtParam;
+	int accountId;
+	AlphaFeld *bg;
+	TextFeld *name;
+	Knopf *accountAnsehen;
+	Knopf *nachrichtSenden;
+	Knopf *freundesanfrageSenden;
+	Punkt pos;
+	Punkt gr;
+	bool online;
+	int minKnopfX;
+	int knopfX;
+	bool mausIn;
+	double tickVal;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	ChatListeSpieler( int accountId, int eigeneId, Schrift *zSchrift, BilderV *bilder, KSGClient::InformationServerClient *zInfoc,
+											  bool istFreund, void( *addChatF )( void*, int ), void( *addFreundF )( void*, int ),
+											  void( *accountAnsehenF )( void *, int ), void *param );
+	// Destruktor
+	~ChatListeSpieler();
+	// nicht constant
+	void setOffline();
+	void setPosition( int y );
+	void doPublicMausEreignis( MausEreignis &me );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+	int getAccountId() const;
+	// Reference Counting
+	ChatListeSpieler *getThis();
+	ChatListeSpieler *release();
+};
+
+class ChatListe
+{
+private:
+	void( *addChat )( void *, int );
+	void( *addFreund )( void *, int );
+	void( *accountAnsehen )( void *, int );
+	void *nachrichtParam;
+	int eigeneId;
+	RCArray< ChatListeSpieler > *spieler;
+	VScrollBar *vScroll;
+	Punkt pos;
+	Punkt gr;
+    KSGClient::InformationServerClient *infoc;
+	Schrift *schrift;
+	BilderV *bilder;
+	LRahmen *ram;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	ChatListe( int eigeneId, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
+									   void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+									   void( *accountAnsehen )( void *, int ), void *param );
+	// Destruktor
+	~ChatListe();
+	// nicht constant
+	void addSpieler( int accountId, bool istFreund );
+	void setOffline( int accountId );
+	void doPublicMausEreignis( MausEreignis &me );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+
+	// Reference Counting
+	ChatListe *getThis();
+	ChatListe *release();
+};
+
+class StatistikChat
+{
+private:
+	void( *addNachricht )( void *, Text *, Text *, Text *, Text * );
+	void *nachrichtParam;
+    KSGClient::SpielServerClient *spielc;
+    KSGClient::InformationServerClient *infoc;
+	TextFeld *verlauf;
+	TextFeld *nachricht;
+	Knopf *senden;
+	Knopf *verlassen;
+	ChatListe *spielerListe;
+	bool beenden;
+	int ref;
+
+public:
+	// Konstruktor
+	StatistikChat( int eigeneId, KSGClient::SpielServerClient *spielc, KSGClient::InformationServerClient *infoc, Schrift *schrift, BilderV *bilder,
+										   void( *addNachricht )( void *, Text *, Text *, Text *, Text * ),
+										   void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+										   void( *accountAnsehen )( void *, int ), void *param );
+	// Destruktor
+	~StatistikChat();
+	// nicht constant
+	void addSpieler( int accountId, bool istFreund );
+	void spielerOffline( int accountId );
+	void addChatNachricht( int vonAccount, char *nachricht );
+	void doPublicMausEreignis( MausEreignis &me );
+	void doTastaturEreignis( TastaturEreignis &te );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+	bool hatVerlassen();
+	// Reference Counting
+	StatistikChat *getThis();
+	StatistikChat *release();
+};
+
+#endif

+ 422 - 0
StickmanWorldOnline/StatistikTabelle.cpp

@@ -0,0 +1,422 @@
+#include "StatistikTabelle.h"
+#include "Initialisierung.h"
+
+#define ABSTYLE     AuswahlBox::Style::Sichtbar | AuswahlBox::Style::Erlaubt | AuswahlBox::Style::Rahmen | AuswahlBox::Style::AuswahlBuffer | AuswahlBox::Style::MausBuffer | AuswahlBox::Style::MaxHeight | AuswahlBox::Style::Hintergrund | AuswahlBox::Style::VScroll
+#define OTSTYLE     ObjTabelle::Style::Sichtbar | ObjTabelle::Style::Erlaubt | ObjTabelle::Style::Rahmen | ObjTabelle::Style::Raster | ObjTabelle::Style::scroll | ObjTabelle::Style::SpaltenBreiteMax | ObjTabelle::Style::SpaltenBreiteMin | ObjTabelle::Style::SpaltenBreiteChangeable | ObjTabelle::Style::SpaltenBeweglich
+
+// Inhalt der StatistikTabelle Klasse aus StatistikTabelle.h
+// Konstruktor
+StatistikTabelle::StatistikTabelle( Array< SSDSpieler* > *ssdgs, Array< SSDTeam* > *ssdgt,
+									Schrift *zSchrift, Bildschirm *zScreen, bool historie )
+									: schrift( zSchrift->getThis() ),
+									ssdgs( ssdgs ),
+									ssdgt( ssdgt ),
+									stAuswahl( initAuswahlBox( 10, 10, 120, 20, zSchrift, ABSTYLE, { "Spieler", "Teams" } ) ),
+									sortAuswahlGS( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Spielername", "Teamname",
+									"Spielerfarbe", "Teamfarbe", "Schaden bekommen", "Schaden gemacht", "Treibstoff verbraucht",
+									"Präzision", "Punkte", "Kills", "Tode", "Zeit am Leben", "Zeit tod" } ) ),
+									sortAuswahlGT( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Teamname", "Teamfarbe",
+									"Schaden bekommen", "Schaden gemacht", "Treibstoff verbraucht", "Präzision", "Punkte", "Kills", "Tode" } ) ),
+									sortRichtungGS( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } ) ),
+									sortRichtungGT( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } ) ),
+									gesamtSpieler( initObjTabelle( 10, 40, 760, 245, zSchrift, OTSTYLE, { { "Spielername", 120, 20, 200 },
+									{ "Teamname", 120, 20, 120 }, { "Spielerfarbe", 100, 20, 100 }, { "Teamfarbe", 100, 20, 100 },
+									{ "Schaden bekommen", 130, 20, 130 }, { "Schaden gemacht", 130, 20, 130 },
+									{ "Treibstoff verbraucht", 140, 20, 140 }, { "Präzision", 60, 20, 60 }, { "Punkte", 50, 20, 50 },
+									{ "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 }, { "Zeit Am Leben", 120, 20, 120 },
+									{ "Zeit tod", 60, 20, 60 } }, 20 ) ),
+									gesamtTeam( initObjTabelle( 10, 40, 760, 245, zSchrift, OTSTYLE, { { "Teamname", 120, 20, 120 },
+									{ "Teamfarbe", 100, 20, 100 }, { "Schaden bekommen", 130, 20, 130 }, { "Schaden gemacht", 130, 20, 130 },
+									{ "Treibstoff verbraucht", 140, 20, 140 }, { "Präzision", 60, 20, 60 }, { "Punkte", 50, 20, 50 },
+									{ "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 } }, 20 ) ),
+									teamS( 0 ),
+									rend( 0 ),
+									ref( 1 )
+{
+	tabelleFüllen( gesamtSpieler );
+	tabelleFüllen( gesamtTeam );
+	if( historie )
+	{
+		sortRichtungGS->setSize( 110, 20 );
+		sortRichtungGT->setSize( 110, 20 );
+		gesamtSpieler->setSize( 760, 380 );
+		gesamtTeam->setSize( 760, 380 );
+	}
+}
+
+// Destruktor
+StatistikTabelle::~StatistikTabelle()
+{
+	schrift->release();
+	ssdgs->release();
+	ssdgt->release();
+	stAuswahl->release();
+	sortAuswahlGS->release();
+	sortAuswahlGT->release();
+	sortRichtungGS->release();
+	sortRichtungGT->release();
+	gesamtSpieler->release();
+	gesamtTeam->release();
+}
+
+// privat
+void StatistikTabelle::tabelleLehren( ObjTabelle *zT, bool überschrift )
+{
+	int zAnz = zT->getZeilenAnzahl();
+	for( int i = !überschrift; i < zAnz; i++ )
+		zT->removeZeile( !überschrift );
+}
+
+void StatistikTabelle::tabelleFüllen( ObjTabelle *zT )
+{
+	if( zT == gesamtSpieler )
+	{
+		if( !sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() ) )
+			return;
+		if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
+			return;
+		Array< int > reihenfolge;
+		bool aufsteigend = sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() )->istGleich( "Aufwärts" );
+		int anz = ssdgs->getEintragAnzahl();
+		bool *fertig = new bool[ anz ];
+		ZeroMemory( fertig, anz );
+		bool spielername = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielername" );
+		bool teamname = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamname" );
+		bool spielerfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielerfarbe" );
+		bool teamfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamfarbe" );
+		bool schadenBekommen = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Schaden bekommen" );
+		bool schadenGemacht = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Schaden gemacht" );
+		bool treibstoffVerbraucht = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Treibstoff verbraucht" );
+		bool präzision = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Präzision" );
+		bool punkte = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Punkte" );
+		bool kills = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Kills" );
+		bool tode = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Tode" );
+		bool zeitamleben = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Zeit am Leben" );
+		bool zeittod = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Zeit tod" );
+		for( int i = 0; i < anz; i++ )
+		{
+			Text minMaxT;
+			int minMax;
+			int pos = -1;
+			for( int j = 0; j < anz; j++ )
+			{
+				if( !ssdgs->hat( j ) || fertig[ j ] )
+					continue;
+				if( spielername && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->spielerName > minMaxT ) ) )
+				{ // Sortiert nach Spieler Name
+					minMaxT = ssdgs->get( j )->spielerName.getText();
+					pos = j;
+				}
+				if( teamname && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->teamName > minMaxT ) ) )
+				{ // Sortiert nach Team Name
+					minMaxT = ssdgs->get( j )->teamName.getText();
+					pos = j;
+				}
+				if( spielerfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->spielerFarbe > minMax ) ) )
+				{ // Sortiert nach Spieler Farbe
+					minMax = ssdgs->get( j )->spielerFarbe;
+					pos = j;
+				}
+				if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->teamFarbe > minMax ) ) )
+				{ // Sortiert nach Team Farbe
+					minMax = ssdgs->get( j )->teamFarbe;
+					pos = j;
+				}
+				if( schadenBekommen && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->schadenBekommen < minMax ) || ( !aufsteigend && ssdgs->get( j )->schadenBekommen > minMax ) ) )
+				{ // Sortiert nach Schaden bekommen
+					minMax = ssdgs->get( j )->schadenBekommen;
+					pos = j;
+				}
+				if( schadenGemacht && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->schadenGemacht < minMax ) || ( !aufsteigend && ssdgs->get( j )->schadenGemacht > minMax ) ) )
+				{ // Sortiert nach Schaden gemacht
+					minMax = ssdgs->get( j )->schadenGemacht;
+					pos = j;
+				}
+				if( treibstoffVerbraucht && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->treibstoffVerbraucht < minMax ) || ( !aufsteigend && ssdgs->get( j )->treibstoffVerbraucht > minMax ) ) )
+				{ // Sortiert nach Treibstoff verbraucht
+					minMax = ssdgs->get( j )->treibstoffVerbraucht;
+					pos = j;
+				}
+				if( präzision && ( pos < 0 || ( aufsteigend && ( ssdgs->get( j )->treffer ? (int)( 100 / ( (double)ssdgs->get( j )->schüsse / ssdgs->get( j )->treffer ) ) : 0 ) < minMax ) || ( !aufsteigend && ( 100 / ( ssdgs->get( j )->schüsse / ssdgs->get( j )->treffer ) ) > minMax ) ) )
+				{ // Sortiert nach Treibstoff verbraucht
+					minMax = (int)( 100 / ( (double)ssdgs->get( j )->schüsse / ssdgs->get( j )->treffer ) );
+					pos = j;
+				}
+				if( punkte && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgs->get( j )->punkte > minMax ) ) )
+				{ // Sortiert nach Punkten
+					minMax = ssdgs->get( j )->punkte;
+					pos = j;
+				}
+				if( kills && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->kills < minMax ) || ( !aufsteigend && ssdgs->get( j )->kills > minMax ) ) )
+				{ // Sortiert nach Kills
+					minMax = ssdgs->get( j )->kills;
+					pos = j;
+				}
+				if( tode && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->tode < minMax ) || ( !aufsteigend && ssdgs->get( j )->tode > minMax ) ) )
+				{ // Sortiert nach Toden
+					minMax = ssdgs->get( j )->tode;
+					pos = j;
+				}
+				if( zeitamleben && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->zeitAmLeben < minMax ) || ( !aufsteigend && ssdgs->get( j )->zeitAmLeben > minMax ) ) )
+				{ // Sortiert nach Zeit Am Leben
+					minMax = ssdgs->get( j )->zeitAmLeben;
+					pos = j;
+				}
+				if( zeittod && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->zeitTod < minMax ) || ( !aufsteigend && ssdgs->get( j )->zeitTod > minMax ) ) )
+				{ // Sortiert nach Zeit Tod
+					minMax = ssdgs->get( j )->zeitTod;
+					pos = j;
+				}
+			}
+			if( pos >= 0 )
+			{
+				reihenfolge.add( pos );
+				fertig[ pos ] = 1;
+			}
+			else
+				break;
+		}
+		delete[] fertig;
+		anz = reihenfolge.getEintragAnzahl();
+		for( int j = 0; j < anz; j++ )
+		{
+			int i = reihenfolge.get( j );
+			zT->addZeile( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
+			int zNum = zT->getZeilenNummer( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Spielername" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->spielerName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->teamName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Spielerfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Spielerfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->spielerFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->teamFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden bekommen" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->schadenBekommen ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden gemacht" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->schadenGemacht ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Treibstoff verbraucht" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->treibstoffVerbraucht ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Präzision" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ( ssdgs->get( i )->schüsse ? ( 100 * ssdgs->get( i )->treffer / ssdgs->get( i )->schüsse ) : 0 ) ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->punkte ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->kills ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->tode ) );
+			Text zeitAmLeben;
+			zeitAmLeben += ssdgs->get( i )->zeitAmLeben / 60;
+			zeitAmLeben += ":";
+			zeitAmLeben += ssdgs->get( i )->zeitAmLeben % 60;
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Zeit Am Leben" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, zeitAmLeben ) );
+			Text zeitTod;
+			zeitTod += ssdgs->get( i )->zeitTod / 60;
+			zeitTod += ":";
+			zeitTod += ssdgs->get( i )->zeitTod % 60;
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Zeit tod" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, zeitTod ) );
+		}
+		return;
+	}
+	if( zT == gesamtTeam )
+	{
+		if( !sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() ) )
+			return;
+		if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
+			return;
+		Array< int > reihenfolge;
+		bool aufsteigend = sortRichtungGT->zEintragText( sortRichtungGT->getAuswahl() )->istGleich( "Aufwärts" );
+		int anz = ssdgt->getEintragAnzahl();
+		bool *fertig = new bool[ anz ];
+		ZeroMemory( fertig, anz );
+		bool teamname = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamname" );
+		bool teamfarbe = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamfarbe" );
+		bool schadenBekommen = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Schaden bekommen" );
+		bool schadenGemacht = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Schaden gemacht" );
+		bool treibstoffVerbraucht = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Treibstoff verbraucht" );
+		bool präzision = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Präzision" );
+		bool punkte = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Punkte" );
+		bool kills = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Kills" );
+		bool tode = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Tode" );
+		for( int i = 0; i < anz; i++ )
+		{
+			Text minMaxT;
+			int minMax;
+			int pos = -1;
+			for( int j = 0; j < anz; j++ )
+			{
+				if( !ssdgt->hat( j ) || fertig[ j ] )
+					continue;
+				if( teamname && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgt->get( j )->teamName > minMaxT ) ) )
+				{ // Sortiert nach Team Name
+					minMaxT = ssdgt->get( j )->teamName.getText();
+					pos = j;
+				}
+				if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgt->get( j )->teamFarbe > minMax ) ) )
+				{ // Sortiert nach Team Farbe
+					minMax = ssdgt->get( j )->teamFarbe;
+					pos = j;
+				}
+				if( schadenBekommen && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->schadenBekommen < minMax ) || ( !aufsteigend && ssdgt->get( j )->schadenBekommen > minMax ) ) )
+				{ // Sortiert nach Schaden bekommen
+					minMax = ssdgt->get( j )->schadenBekommen;
+					pos = j;
+				}
+				if( schadenGemacht && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->schadenGemacht < minMax ) || ( !aufsteigend && ssdgt->get( j )->schadenGemacht > minMax ) ) )
+				{ // Sortiert nach Schaden gemacht
+					minMax = ssdgt->get( j )->schadenGemacht;
+					pos = j;
+				}
+				if( treibstoffVerbraucht && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->treibstoffVerbraucht < minMax ) || ( !aufsteigend && ssdgt->get( j )->treibstoffVerbraucht > minMax ) ) )
+				{ // Sortiert nach Linienlängen
+					minMax = ssdgt->get( j )->treibstoffVerbraucht;
+					pos = j;
+				}
+				if( präzision && ( pos < 0 || ( aufsteigend && ( ssdgt->get( j )->treffer ? (int)( 100 / ( (double)ssdgt->get( j )->schüsse / ssdgt->get( j )->treffer ) ) : 0 ) < minMax ) || ( !aufsteigend && ( 100 / ( ssdgt->get( j )->schüsse / ssdgt->get( j )->treffer ) ) > minMax ) ) )
+				{ // Sortiert nach Präzision
+					minMax = (int)( 100 / ( (double)ssdgt->get( j )->schüsse / ssdgt->get( j )->treffer ) );
+					pos = j;
+				}
+				if( punkte && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgt->get( j )->punkte > minMax ) ) )
+				{ // Sortiert nach Punkten
+					minMax = ssdgt->get( j )->punkte;
+					pos = j;
+				}
+				if( kills && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->kills < minMax ) || ( !aufsteigend && ssdgt->get( j )->kills > minMax ) ) )
+				{ // Sortiert nach Kills
+					minMax = ssdgt->get( j )->kills;
+					pos = j;
+				}
+				if( tode && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->tode < minMax ) || ( !aufsteigend && ssdgt->get( j )->tode > minMax ) ) )
+				{ // Sortiert nach Toden
+					minMax = ssdgt->get( j )->tode;
+					pos = j;
+				}
+			}
+			if( pos >= 0 )
+			{
+				reihenfolge.add( pos );
+				fertig[ pos ] = 1;
+			}
+			else
+				break;
+		}
+		delete[] fertig;
+		anz = reihenfolge.getEintragAnzahl();
+		for( int j = 0; j < anz; j++ )
+		{
+			int i = reihenfolge.get( j );
+			zT->addZeile( Text( "Team " ) += ssdgt->get( i )->teamNummer );
+			int zNum = zT->getZeilenNummer( Text( "Team " ) += ssdgt->get( i )->teamNummer );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgt->get( i )->teamName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgt->get( i )->teamFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden bekommen" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->schadenBekommen ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden gemacht" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->schadenGemacht ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Treibstoff verbraucht" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->treibstoffVerbraucht ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Präzision" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ( ssdgt->get( j )->treffer ? ( 100 / ( ssdgt->get( j )->schüsse / ssdgt->get( j )->treffer ) ) : 0 ) ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->punkte ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->kills ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->tode ) );
+		}
+		return;
+	}
+}
+
+// nicht constant
+void StatistikTabelle::doPublicMausEreignis( MausEreignis &me )
+{
+	// Auswahl Boxen
+	int ausw = stAuswahl->getAuswahl();
+	stAuswahl->doPublicMausEreignis( me );
+	if( ausw != stAuswahl->getAuswahl() )
+	{
+		teamS = stAuswahl->zEintragText( stAuswahl->getAuswahl() )->istGleich( "Teams" );
+		stAuswahl->einklappen();
+	}
+	if( teamS )
+	{ // Team Statistik
+		int ausw = sortAuswahlGT->getAuswahl();
+		sortAuswahlGT->doPublicMausEreignis( me );
+		if( ausw != sortAuswahlGT->getAuswahl() )
+		{ // Sortierungs Spalte ändert sich
+			tabelleLehren( gesamtTeam, 0 );
+			tabelleFüllen( gesamtTeam );
+			sortAuswahlGT->einklappen();
+		}
+		ausw = sortRichtungGT->getAuswahl();
+		sortRichtungGT->doPublicMausEreignis( me );
+		if( ausw != sortRichtungGT->getAuswahl() )
+		{ // Sortierungs Richtung ändert sich
+			tabelleLehren( gesamtTeam, 0 );
+			tabelleFüllen( gesamtTeam );
+			sortRichtungGT->einklappen();
+		}
+		gesamtTeam->doPublicMausEreignis( me );
+	}
+	else
+	{ // Spieler Statistik
+		int ausw = sortAuswahlGS->getAuswahl();
+		sortAuswahlGS->doPublicMausEreignis( me );
+		if( ausw != sortAuswahlGS->getAuswahl() )
+		{ // Sortierungs Spalte ändert sich
+			tabelleLehren( gesamtSpieler, 0 );
+			tabelleFüllen( gesamtSpieler );
+			sortAuswahlGS->einklappen();
+		}
+		ausw = sortRichtungGS->getAuswahl();
+		sortRichtungGS->doPublicMausEreignis( me );
+		if( ausw != sortRichtungGS->getAuswahl() )
+		{ // Sortierungs Richtung ändert sich
+			tabelleLehren( gesamtSpieler, 0 );
+			tabelleFüllen( gesamtSpieler );
+			sortRichtungGS->einklappen();
+		}
+		gesamtSpieler->doPublicMausEreignis( me );
+	}
+}
+
+bool StatistikTabelle::tick( double tickVal )
+{
+	if( teamS )
+	{ // Team Statistik
+		rend |= gesamtTeam->tick( tickVal );
+		rend |= sortAuswahlGT->tick( tickVal );
+		rend |= sortRichtungGT->tick( tickVal );
+	}
+	else
+	{ // Spieler Statistik
+		rend |= gesamtSpieler->tick( tickVal );
+		rend |= sortAuswahlGS->tick( tickVal );
+		rend |= sortRichtungGS->tick( tickVal );
+	}
+	// Auswahl Boxen
+	rend |= stAuswahl->tick( tickVal );
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void StatistikTabelle::render( Bild &zRObj )
+{
+	if( teamS )
+	{ // Team Statistik
+		gesamtTeam->render( zRObj );
+		sortAuswahlGT->render( zRObj );
+		sortRichtungGT->render( zRObj );
+	}
+	else
+	{ // Spieler Statistik
+		gesamtSpieler->render( zRObj );
+		sortAuswahlGS->render( zRObj );
+		sortRichtungGS->render( zRObj );
+	}
+	// Auswahl Boxen
+	stAuswahl->render( zRObj );
+}
+
+// Reference Counting
+StatistikTabelle *StatistikTabelle::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikTabelle *StatistikTabelle::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 44 - 0
StickmanWorldOnline/StatistikTabelle.h

@@ -0,0 +1,44 @@
+#ifndef StatistikTabelle_H
+#define StatistikTabelle_H
+
+#include <Tabelle.h>
+#include <AuswahlBox.h>
+#include "SpielStatistikDaten.h"
+
+using namespace Framework;
+
+class StatistikTabelle
+{
+private:
+	Schrift *schrift;
+	Array< SSDSpieler* > *ssdgs;
+	Array< SSDTeam* > *ssdgt;
+	AuswahlBox *stAuswahl;
+	AuswahlBox *sortAuswahlGS;
+	AuswahlBox *sortAuswahlGT;
+	AuswahlBox *sortRichtungGS;
+	AuswahlBox *sortRichtungGT;
+	ObjTabelle *gesamtSpieler;
+	ObjTabelle *gesamtTeam;
+	bool teamS;
+	bool rend;
+	int ref;
+	// privat
+	void tabelleLehren( ObjTabelle *zT, bool überschrift );
+	void tabelleFüllen( ObjTabelle *zT );
+
+public:
+	// Konstruktor
+	StatistikTabelle( Array< SSDSpieler* > *ssdgs, Array< SSDTeam* > *ssdgt, Schrift *zSchrift, Bildschirm *zScreen, bool historie = 0 );
+	// Destruktor
+	~StatistikTabelle();
+	// nicht constant
+	void doPublicMausEreignis( MausEreignis &me );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// Reference Counting
+	StatistikTabelle *getThis();
+	StatistikTabelle *release();
+};
+
+#endif

+ 22 - 12
StickmanWorldOnline/StickmanWorldOnline.vcxproj

@@ -18,6 +18,28 @@
       <Platform>x64</Platform>
     </ProjectConfiguration>
   </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="DLLStart.cpp" />
+    <ClCompile Include="Initialisierung.cpp" />
+    <ClCompile Include="StatistikChat.cpp" />
+    <ClCompile Include="StatistikTabelle.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Aufzeichnung.h" />
+    <ClInclude Include="Dialog.h" />
+    <ClInclude Include="Editor.h" />
+    <ClInclude Include="EditorKarte.h" />
+    <ClInclude Include="EditorKlient.h" />
+    <ClInclude Include="HistorieStatistik.h" />
+    <ClInclude Include="Initialisierung.h" />
+    <ClInclude Include="Interface.h" />
+    <ClInclude Include="RightTools.h" />
+    <ClInclude Include="SpielKlasse.h" />
+    <ClInclude Include="SpielStatistik.h" />
+    <ClInclude Include="SpielStatistikDaten.h" />
+    <ClInclude Include="StatistikChat.h" />
+    <ClInclude Include="StatistikTabelle.h" />
+  </ItemGroup>
   <PropertyGroup Label="Globals">
     <VCProjectVersion>15.0</VCProjectVersion>
     <ProjectGuid>{1bd07113-b8c1-4634-bcab-4aa7196b3fe1}</ProjectGuid>
@@ -142,18 +164,6 @@
       <Outputs>kopieren;%(Outputs)</Outputs>
     </CustomBuildStep>
   </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="Initialisierung\Initialisierung.cpp" />
-    <ClCompile Include="Start\DllStart.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="Aufzeichnung\Aufzeichnung.h" />
-    <ClInclude Include="Editor\Editor.h" />
-    <ClInclude Include="HistorieStatistik\HistorieStatistik.h" />
-    <ClInclude Include="Initialisierung\Initialisierung.h" />
-    <ClInclude Include="SpielStatistik\SpielStatistik.h" />
-    <ClInclude Include="Spiel\SpielKlasse.h" />
-  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 55 - 13
StickmanWorldOnline/StickmanWorldOnline.vcxproj.filters

@@ -13,33 +13,75 @@
       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
     </Filter>
+    <Filter Include="Headerdateien\Editor">
+      <UniqueIdentifier>{11e31a9e-2489-407d-a303-c83976d905d1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Headerdateien\Aufzeichnung">
+      <UniqueIdentifier>{26bdcc05-4e4c-4404-a042-011efeee9e28}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Headerdateien\Spiel">
+      <UniqueIdentifier>{cfc385f8-b6a4-49ce-90e7-39d76346152c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Headerdateien\Statistik">
+      <UniqueIdentifier>{31c87e6a-c17a-4812-8869-8a9838337660}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="Start\DllStart.cpp">
+    <ClCompile Include="DLLStart.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Initialisierung.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
-    <ClCompile Include="Initialisierung\Initialisierung.cpp">
+    <ClCompile Include="StatistikChat.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="StatistikTabelle.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="Initialisierung\Initialisierung.h">
+    <ClInclude Include="Initialisierung.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
-    <ClInclude Include="Spiel\SpielKlasse.h">
-      <Filter>Headerdateien</Filter>
+    <ClInclude Include="Aufzeichnung.h">
+      <Filter>Headerdateien\Aufzeichnung</Filter>
     </ClInclude>
-    <ClInclude Include="SpielStatistik\SpielStatistik.h">
-      <Filter>Headerdateien</Filter>
+    <ClInclude Include="Dialog.h">
+      <Filter>Headerdateien\Editor</Filter>
     </ClInclude>
-    <ClInclude Include="Aufzeichnung\Aufzeichnung.h">
-      <Filter>Headerdateien</Filter>
+    <ClInclude Include="Editor.h">
+      <Filter>Headerdateien\Editor</Filter>
     </ClInclude>
-    <ClInclude Include="HistorieStatistik\HistorieStatistik.h">
-      <Filter>Headerdateien</Filter>
+    <ClInclude Include="EditorKarte.h">
+      <Filter>Headerdateien\Editor</Filter>
     </ClInclude>
-    <ClInclude Include="Editor\Editor.h">
-      <Filter>Headerdateien</Filter>
+    <ClInclude Include="EditorKlient.h">
+      <Filter>Headerdateien\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="HistorieStatistik.h">
+      <Filter>Headerdateien\Statistik</Filter>
+    </ClInclude>
+    <ClInclude Include="Interface.h">
+      <Filter>Headerdateien\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="RightTools.h">
+      <Filter>Headerdateien\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielKlasse.h">
+      <Filter>Headerdateien\Spiel</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik.h">
+      <Filter>Headerdateien\Statistik</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistikDaten.h">
+      <Filter>Headerdateien\Statistik</Filter>
+    </ClInclude>
+    <ClInclude Include="StatistikChat.h">
+      <Filter>Headerdateien\Statistik</Filter>
+    </ClInclude>
+    <ClInclude Include="StatistikTabelle.h">
+      <Filter>Headerdateien\Statistik</Filter>
     </ClInclude>
   </ItemGroup>
 </Project>

+ 21 - 0
build.bat

@@ -0,0 +1,21 @@
+:DebugWin64
+SET RETURN=DebugWin64
+SET NEXT=ReleaseWin64
+"%InstallDir%\%MSBuildExe%" "StickmanWorldOnline.sln" /p:configuration=debug /p:platform=x64
+if errorlevel 1 GOTO Error
+:ReleaseWin64
+SET RETURN=ReleaseWin64
+SET NEXT=ReleaseWin32
+"%InstallDir%\%MSBuildExe%" "StickmanWorldOnline.sln" /p:configuration=release /p:platform=x64
+if errorlevel 1 GOTO Error
+:ReleaseWin32
+SET RETURN=ReleaseWin32
+SET NEXT=END
+"%InstallDir%\%MSBuildExe%" "StickmanWorldOnline.sln" /p:configuration=release /p:platform=win32
+if errorlevel 1 GOTO Error
+GOTO End
+:Error
+SET /p redo=Nochmal versuchen?(j/n):
+IF /I '%redo%' equ 'j' GOTO %RETURN%
+GOTO %NEXT%
+:End