#include "SpielAuswahl.h"
#include <Datei.h>
#include <Text.h>
#include <Schrift.h>
#include <Rahmen.h>
#include <Punkt.h>
#include <DateiSystem.h>
#include "..\..\..\Global\Initialisierung.h"
#include <AlphaFeld.h>
#include <MausEreignis.h>
#include <KSGTDatei.h>
#include "..\..\..\Global\Variablen.h"

void SpielAuswahlKSGSAktion( void *p, RCArray< KSGSVariable > *parameter, KSGSVariable **retVal )
{
    if( !p )
        return;
    ( (SpielDaten*)p )->ksgsAktion( parameter, retVal );
}

// Inhalt der SpielDaten Klasse aus SpielAuswahl.h
// Konstruktor
SpielDaten::SpielDaten( Schrift *zSchrift, const char *name, int id )
    : Thread()
{
    beenden = 0;
    this->name = new Text( name );
    hintergrund = 0;
    aAnimation = 0;
    beschreibung = 0;
    ksgs = 0;
    rahmen = new LRahmen();
    rahmen->setFarbe( 0xFFFFFFFF );
    rahmen->setRamenBreite( 1 );
    tickVal = 0;
    animation = 0;
    ausgewählt = 0;
    pos = Punkt( 0, 500 );
    gr = Punkt( 200, 100 );
    schrift = zSchrift->getThis();
    spielId = id;
    aktion = 1;
    geladen = 0;
    erlaubt = 0;
    auswahl = new AlphaFeld();
    auswahl->setFarbe( 0x0000FF00 );
    auswahl->setStärke( 8 );
    auswahl->setGröße( 200, 100 );
    ladenBild = 0;
    rend = 0;
    ref = 1;
    alpha = 0;
    tAlpha = 0;
    start();
}

// Destruktor
SpielDaten::~SpielDaten()
{
    beenden = 1;
    if( run )
        this->warteAufThread( 5000 );
    if( run )
        ende();
    if( schrift )
        schrift->release();
    name->release();
    if( hintergrund )
        hintergrund->release();
    if( aAnimation )
        aAnimation->release();
    if( beschreibung )
    {
        beschreibung->zurücksetzen();
        beschreibung->release();
    }
    if( ksgs )
    {
        dllDateien->releaseDLL( "KSGScript.dll" );
        ksgs = 0;
    }
    rahmen->release();
    auswahl->release();
}

// nicht constant
void SpielDaten::ksgsAktion( RCArray< KSGSVariable > *parameter, KSGSVariable **retVal )
{}

void SpielDaten::setSichtbar( bool sichtbar )
{
    if( sichtbar )
        animation |= 0x1;
    else
    {
        animation &= ~0x1;
        setAuswahl( 0 );
        auswahl->setFarbe( auswahl->getFarbe() & 0xFFFFFF );
    }
    if( !erlaubt && sichtbar && ausgewählt )
        updateH->setSichtbar( spielId, 1 );
    hauptScreen->lock();
    if( run && aktion == (sichtbar ? 2 : 0) )
    {
        hauptScreen->unlock();
        rend = 1;
        return;
    }
    beenden = 1;
    if( run )
        this->warteAufThread( 1000 );
    if( run )
        ende();
    beenden = 0;
    aktion = sichtbar ? 2 : 0;
    start();
    hauptScreen->unlock();
    rend = 1;
}

void SpielDaten::setSichtbar()
{
    animation |= 1;
    if( ausgewählt && geladen == 2 )
    {
        animation |= 0x4;
        beschreibung->setPosition( beschreibung->getX(), 0 );
    }
    if( !erlaubt && ausgewählt )
        updateH->setSichtbar( spielId, 1 );
    hauptScreen->lock();
    if( geladen != 2 && !( aktion == 2 && run ) )
    {
        beenden = 1;
        if( run )
            this->warteAufThread( 1000 );
        if( run )
            ende();
        beenden = 0;
        aktion = 2;
        start();
    }
    hauptScreen->unlock();
    rend = 1;
}

void SpielDaten::setAuswahl( bool auswahl )
{
    if( ausgewählt == auswahl )
        return;
    ausgewählt = auswahl;
    if( auswahl )
    {
        if( aAnimation )
            aAnimation->setSichtbar( 1 );
        if( beschreibung && ksgs )
            beschreibung->neuLaden();
        animation |= 0x4;
    }
    else
        animation &= ~0x4;
    if( !erlaubt && ausgewählt )
        updateH->setSichtbar( spielId, 1 );
    if( !erlaubt && !ausgewählt )
        updateH->setSichtbar( spielId, 0 );
    rend = 1;
}

void SpielDaten::thread()
{
    Text *pfad = new Text( "data/spiele/" );
    pfad->anhängen( name->getText() );
    pfad->anhängen( "/data/game.ini" );
    if( !DateiExistiert( pfad->getThis() ) )
    {
        if( !aktion )
        {
            if( aAnimation )
                aAnimation->setSichtbar( 0 );
            geladen = 0;
            ausgewählt = 0;
            hauptScreen->lock();
            if( aAnimation )
                aAnimation = aAnimation->release();
            hauptScreen->unlock();
            if( hintergrund )
                hintergrund = hintergrund->release();
            if( beschreibung )
            {
                beschreibung->zurücksetzen();
                beschreibung = beschreibung->release();
            }
            if( ksgs )
            {
                dllDateien->releaseDLL( "KSGScript.dll" );
                ksgs = 0;
            }
        }
        else
        {
            if( !hintergrund )
                hintergrund = new Bild();
            hintergrund->neuBild( 200, 100, 0xFF000000 );
            schrift->lock();
            schrift->setSchriftGröße( 12 );
            schrift->setDrawPosition( 10, 10 );
            schrift->renderText( name, *hintergrund, 0xFFFFFFFF );
            schrift->unlock();
            if( !geladen )
                geladen = 1;
            rend = 1;
            int dgId = infoKlient->getDateiGruppeIdVonSpiel( spielId );
            if( dgId )
            {
                KSGTDatei *dg = new KSGTDatei( "data/dg.ksgt" );
                dg->laden();
                bool gefunden = 0;
                for( int i = 0; i < dg->getZeilenAnzahl(); i++ )
                {
                    if( dg->zFeld( i, 0 ) && TextZuInt( dg->zFeld( i, 0 )->getText(), 10 ) == dgId )
                    {
                        gefunden = 1;
                        break;
                    }
                }
                if( !gefunden )
                {
                    for( int i = 0; i < dg->getZeilenAnzahl(); i++ )
                    {
                        if( dg->zFeld( i, 3 ) && !dg->zFeld( i, 3 )->istGleich( "SOFORT" ) && !dg->zFeld( i, 3 )->istGleich( "NICHT" ) )
                        {
                            int platz = TextZuInt( dg->zFeld( i, 3 )->getText(), 10 ) + 1;
                            Text *plT = new Text();
                            plT->anhängen( platz );
                            dg->zFeld( i, 3 )->setText( plT );
                        }
                    }
                    Text *idT = new Text();
                    idT->anhängen( dgId );
                    Text *pfad = infoKlient->getDateiGruppePfad( dgId );
                    if( pfad )
                    {
                        RCArray< Text > *zeile = new RCArray< Text >();
                        zeile->add( idT );
                        zeile->add( pfad );
                        zeile->add( new Text( "0" ) );
                        zeile->add( new Text( "0" ) );
                        dg->addZeile( 4, zeile );
                        zeile->release();
                    }
                    else
                        idT->release();
                }
                dg->speichern();
                dg->release();
            }
            if( aktion == 2 && !beenden )
            {
                if( beschreibung )
                {
                    beschreibung->zurücksetzen();
                    beschreibung = beschreibung->release();
                }
                if( !ksgs )
                    ksgs = dllDateien->ladeDLL( "KSGScript.dll", "data/bin/KSGScript.dll" );
                if( ksgs )
                {
                    KSGSGetZeichnung getKSGScript = (KSGSGetZeichnung)GetProcAddress( ksgs, KSGS_START_FUNKTION );
                    if( getKSGScript )
                    {
                        beschreibung = getKSGScript();
                        beschreibung->setBildschirmZ( hauptScreen->getThis() );
                        beschreibung->setSchriftZ( schrift->getThis() );
                        beschreibung->setGröße( 578, 428 );
                        beschreibung->setRückrufParam( this );
                        beschreibung->setRückrufFunktion( SpielAuswahlKSGSAktion );
                        beschreibung->setScriptDatei( "data/script/SpielNichtAktuell.ksgs" );
                    }
                    else
                    {
                        nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
                                                                      new Text( "Der Einstiegspunkt '" KSGS_START_FUNKTION "' in der DLL-Datei "
                                                                                "'data/bin/KSGScript.dll' konnte nicht gefunden werden." ),
                                                                      new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                    }
                }
                else
                {
                    nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
                                                                  new Text( "Die DLL-Datei 'data/bin/KSGScript.dll' konnte nicht geladen werden." ),
                                                                  new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                }
                if( beschreibung )
                    geladen = 2;
                if( beschreibung && ksgs && ausgewählt )
                    beschreibung->neuLaden();
            }
        }
        pfad->release();
        rend = 1;
        run = 0;
        return;
    }
    Datei *ini = new Datei();
    ini->setDatei( pfad->getText() );
    ini->öffnen( Datei::Style::lesen );
    if( !aktion )
    {
        if( aAnimation )
            aAnimation->setSichtbar( 0 );
        geladen = 0;
        ausgewählt = 0;
        hauptScreen->lock();
        if( aAnimation )
            aAnimation = aAnimation->release();
        hauptScreen->unlock();
        if( hintergrund )
            hintergrund = hintergrund->release();
        if( beschreibung )
        {
            beschreibung->zurücksetzen();
            beschreibung = beschreibung->release();
        }
        if( ksgs )
        {
            dllDateien->releaseDLL( "KSGScript.dll" );
            ksgs = 0;
        }
        rend = 1;
    }
    else
    {
        Text *pf = ini->leseZeile();
        pf->löschen( pf->getLänge() - 1 );
        pf->einfügen( 0, "/bilder/" );
        pf->einfügen( 0, name->getText() );
        pf->einfügen( 0, "data/spiele/" );
        if( pf->hat( ".ltdb/" ) )
        {
            if( !hintergrund )
            {
                LTDBDatei *bildDatei = new LTDBDatei();
                bildDatei->setDatei( pf->getTeilText( 0, pf->positionVon( ".ltdb" ) + 5 ) );
                bildDatei->leseDaten( 0 );
                hintergrund = bildDatei->laden( 0, pf->getTeilText( pf->positionVon( ".ltdb" ) + 6 ) );
                bildDatei->release();
            }
        }
        else
        {
            if( !hintergrund )
            {
                LTDBDatei *bildDatei = new LTDBDatei();
                bildDatei->setDatei( pf->getThis() );
                bildDatei->leseDaten( 0 );
                hintergrund = bildDatei->laden( 0, bildDatei->zBildListe()->get( 0 ) );
                bildDatei->release();
            }
        }
        pf->release();
        pf = ini->leseZeile();
        pf->release();
        pf = ini->leseZeile();
        pf->löschen( pf->getLänge() - 1 );
        pf->einfügen( 0, "/data/" );
        pf->einfügen( 0, name->getText() );
        pf->einfügen( 0, "data/spiele/" );
        Datei *idDatei = new Datei();
        idDatei->setDatei( pf->getText() );
        idDatei->öffnen( Datei::Style::lesen );
        idDatei->lese( (char*)&spielId, 4 );
        idDatei->schließen();
        idDatei->release();
        pf->release();
        if( !geladen )
            geladen = 1;
        rend = 1;
        ini->setLPosition( 0, 0 );
        if( aktion == 2 && !beenden )
        {
            pf = ini->leseZeile();
            pf->löschen( pf->getLänge() - 1 );
            pf->einfügen( 0, "/bilder/" );
            pf->einfügen( 0, name->getText() );
            pf->einfügen( 0, "data/spiele/" );
            if( !pf->hat( ".ltdb/" ) )
            {
                hauptScreen->lock();
                if( aAnimation )
                    aAnimation = aAnimation->release();
                hauptScreen->unlock();
                LTDBDatei *add = new LTDBDatei();
                add->setDatei( pf->getThis() );
                add->leseDaten( 0 );
                Animation2DData *ad = new Animation2DData();
                ad->ladeAnimation( add );
                ad->setWiederhohlend( 1 );
                ad->setFPS( 30 );
                aAnimation = new Animation2D();
                aAnimation->setGröße( 200, 100 );
                aAnimation->setPosition( 0, 0 );
                aAnimation->setAnimationDataZ( ad );
            }
            pf->release();
            pf = ini->leseZeile();
            pf->löschen( pf->getLänge() - 1 );
            pf->einfügen( 0, "/data/" );
            pf->einfügen( 0, name->getText() );
            pf->einfügen( 0, "data/spiele/" );
            if( beschreibung )
            {
                beschreibung->zurücksetzen();
                beschreibung = beschreibung->release();
            }
            if( !ksgs )
                ksgs = dllDateien->ladeDLL( "KSGScript.dll", "data/bin/KSGScript.dll" );
            if( ksgs )
            {
                KSGSGetZeichnung getKSGScript = (KSGSGetZeichnung)GetProcAddress( ksgs, KSGS_START_FUNKTION );
                if( getKSGScript )
                {
                    beschreibung = getKSGScript();
                    beschreibung->setBildschirmZ( hauptScreen->getThis() );
                    beschreibung->setSchriftZ( schrift->getThis() );
                    beschreibung->setGröße( 578, 428 );
                    beschreibung->setRückrufParam( this );
                    beschreibung->setRückrufFunktion( SpielAuswahlKSGSAktion );
                    beschreibung->setScriptDatei( pf->getText() );
                }
                else
                {
                    nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
                                                                  new Text( "Der Einstiegspunkt '" KSGS_START_FUNKTION "' in der DLL-Datei "
                                                                            "'data/bin/KSGScript.dll' konnte nicht gefunden werden." ),
                                                                  new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                }
            }
            else
            {
                nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
                                                              new Text( "Die DLL-Datei 'data/bin/KSGScript.dll' konnte nicht geladen werden." ),
                                                              new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
            }
            pf->release();
            if( beschreibung )
                geladen = 2;
            if( beschreibung && ksgs && ausgewählt )
                beschreibung->neuLaden();
            rend = 1;
        }
    }
    pfad->release();
    ini->schließen();
    ini->release();
    if( !erlaubt )
        updateErlaubt();
    aktion = 0;
    run = 0;
    rend = 1;
}

void SpielDaten::updateErlaubt()
{
    bool update = erlaubt;
    erlaubt = 0;
    KSGTDatei *dgt = new KSGTDatei( "data/dg.ksgt" );
    dgt->laden();
    bool ak = 0;
    int dgId = infoKlient->getDateiGruppeIdVonSpiel( spielId );
    for( int i = 0; i < dgt->getZeilenAnzahl(); i++ )
    {
        if( dgt->zFeld( i, 0 ) && TextZuInt( dgt->zFeld( i, 0 )->getText(), 10 ) == dgId )
        {
            int lv = dgt->zFeld( i, 2 ) ? TextZuInt( dgt->zFeld( i, 2 )->getText(), 10 ) : 0;
            int ov = infoKlient->getSpielVersion( spielId );
            if( lv == ov )
                ak = 1;
            break;
        }
    }
    dgt->release();
    erlaubt = ak && infoKlient->istSpielErlaubt( spielId );
    if( !erlaubt && !updateH->hat( spielId ) )
    {
        updateH->erstellen( schrift, spielId );
        if( ausgewählt )
            updateH->setSichtbar( spielId, 1 );
    }
    if( erlaubt && updateH->hat( spielId ) )
        updateH->lösche( spielId, 0 );
}

void SpielDaten::setPosition( int lPos )
{
    pos.y = lPos * 100;
    rend = 1;
}

bool SpielDaten::tick( double tickVal )
{
    if( beschreibung )
        rend |= beschreibung->tick( tickVal );
    if( !erlaubt )
        rend |= updateH->tick( spielId, tickVal );
    this->tickVal += tickVal * 500;
    int val = ( int ) this->tickVal;
    if( val < 1 )
    {
        bool ret = rend;
        rend = 0;
        return ret;
    }
    if( val > 17 )
        val = 17;
    this->tickVal -= val;
    if( aAnimation && geladen == 2 && aAnimation->istSichtbar() )
    {
        if( aAnimation->getJetzt() + 1 >= aAnimation->zAnimationData()->getBildAnzahl() )
        {
            rend |= aAnimation->tick( tickVal );
            if( aAnimation->getJetzt() + 1 < aAnimation->zAnimationData()->getBildAnzahl() )
                aAnimation->setSichtbar( 0 );
        }
        else
            rend |= aAnimation->tick( tickVal );
    }
    if( ausgewählt )
    {
        int a = ( auswahl->getFarbe() >> 24 ) & 0xFF;
        if( a != 150 )
        {
            if( a + val > 150 )
                a = 150;
            else
                a += val;
            auswahl->setFarbe( ( ( a << 24 ) & 0xFF000000 ) | ( auswahl->getFarbe() & 0xFFFFFF ) );
            rend = 1;
        }
    }
    else
    {
        int a = ( auswahl->getFarbe() >> 24 ) & 0xFF;
        if( a != 0 )
        {
            if( a - val < 0 )
                a = 0;
            else
                a -= val;
            auswahl->setFarbe( ( ( a << 24 ) & 0xFF000000 ) | ( auswahl->getFarbe() & 0xFFFFFF ) );
            rend = 1;
        }
    }
    if( ( animation | 0x1 ) == animation ) // sichtbar
    {
        if( tAlpha != 255 )
        {
            if( tAlpha + val > 255 )
                tAlpha = 255;
            else
                tAlpha += val;
            rend = 1;
        }
    }
    else // unsichtbar
    {
        if( tAlpha != 0 )
        {
            if( tAlpha - val < 0 )
                tAlpha = 0;
            else
                tAlpha -= val;
            rend = 1;
        }
    }
    if( geladen == 2 )
    {
        if( ( animation | 0x4 ) == animation ) // auswählen
        {
            if( beschreibung )
            {
                if( alpha != 255 )
                {
                    if( alpha + val < 255 )
                        alpha += val;
                    else
                        alpha = 255;
                    rend = 1;
                }
            }
        }
        else // abwählen
        {
            int a = ( auswahl->getFarbe() >> 24 ) & 0xFF;
            if( a != 0 )
            {
                a -= val;
                if( a < 0 )
                    a = 0;
                auswahl->setFarbe( ( ( a << 24 ) & 0xFF000000 ) | ( auswahl->getFarbe() & 0xFFFFFF ) );
                rend = 1;
            }
            if( beschreibung )
            {
                if( alpha != 0 )
                {
                    if( alpha - val > 0 )
                        alpha -= val;
                    else
                        alpha = 0;
                    rend = 1;
                }
            }
        }
    }
    bool ret = rend;
    rend = 0;
    return ret;
}

void SpielDaten::doMausEreignis( MausEreignis &me )
{
    if( !erlaubt && ausgewählt )
    {
        me.mx -= gr.x + 90;
        me.my -= 350;
        updateH->doMausEreignis( spielId, me );
        me.my += 440;
        if( beschreibung )
            beschreibung->doMausEreignis( me );
        me.mx += gr.x;
    }
}

void SpielDaten::render( Bild &zRObj )
{
    int x = pos.x;
    int y = pos.y;
    int br = gr.x;
    int hö = gr.y;
    if( !zRObj.setDrawOptions( x, y, br, hö ) )
        return;
    zRObj.setAlpha( tAlpha );
    rahmen->setGröße( br, hö );
    int rbr = rahmen->getRBreite();
    if( geladen && hintergrund && ( !( ausgewählt && geladen == 2 && aAnimation ) || !aAnimation->istSichtbar() ) )
        zRObj.drawBild( rbr, rbr, br - rbr * 2, hö - rbr * 2, *hintergrund );
    if( aAnimation )
        aAnimation->render( zRObj );
    rahmen->render( zRObj );
    if( auswahl && ( ( auswahl->getFarbe() >> 24 ) & 0xFF ) && ( !( ausgewählt && geladen == 2 && aAnimation ) || !aAnimation->istSichtbar() ) )
    {
        auswahl->setPosition( rbr, rbr );
        auswahl->setGröße( br - rbr * 2, hö - rbr * 2 );
        auswahl->render( zRObj );
    }
    zRObj.releaseDrawOptions();
    x = br;
    y = 0;
    br = 580;
    hö = 480;
    if( !zRObj.setDrawOptions( x, y, br, hö ) )
    {
        zRObj.releaseAlpha();
        return;
    }
    if( geladen == 2 && beschreibung )
    {
        zRObj.setAlpha( alpha );
        beschreibung->render( zRObj );
        zRObj.releaseAlpha();
    }
    if( !erlaubt )
        updateH->render( spielId, 90, 350, zRObj );
    if( ausgewählt && geladen != 2 && ladeAnimation->zAnimationData() )
    {
        ladenBild++;
        if( ladenBild >= ladeAnimation->zAnimationData()->getBildAnzahl() )
            ladenBild = 0;
        zRObj.drawBild( 275, 195, 50, 50, *ladeAnimation->zAnimationData()->zBild( ladenBild ) );
        rend = 1;
    }
    zRObj.releaseDrawOptions();
    zRObj.releaseAlpha();
}

// constant
int SpielDaten::getSpielId() const
{
    return spielId;
}

bool SpielDaten::istausgewählt() const
{
    return ausgewählt;
}

Text *SpielDaten::zName() const
{
    return name;
}

bool SpielDaten::istErlaubt() const
{
    return erlaubt;
}

// Reference Counting
SpielDaten *SpielDaten::getThis()
{
    ref++;
    return this;
}

SpielDaten *SpielDaten::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}

// Inhalt der SpielAuswahl Klasse aus SpielAuswahl.h
// Konstruktor
SpielAuswahlFenster::SpielAuswahlFenster( Schrift *zSchrift )
    : Thread()
{
    schrift = zSchrift->getThis();
    rahmen = new LRahmen();
    rahmen->setFarbe( 0xFFFFFFFF );
    rahmen->setRamenBreite( 1 );
    rahmen->setGröße( 760, 500 );
    members = new RCArray< SpielDaten >();
    anzahl = 0;
    animation = 0;
    auswahl = -1;
    tickVal = 0;
    seite = 0;
    pos = Punkt( 10, 10 );
    gr = Punkt( 780, 430 );
    rend = 0;
    ref = 1;
    alpha = 0;
    start();
}

// Destruktor
SpielAuswahlFenster::~SpielAuswahlFenster()
{
    if( run )
    {
        warteAufThread( 5000 );
        ende();
    }
    if( schrift )
        schrift->release();
    if( rahmen )
        rahmen->release();
    if( members )
        members->release();
}

// nicht constant
void SpielAuswahlFenster::setSichtbar( bool sichtbar )
{
    if( sichtbar )
    {
        animation |= 0x1;
        start();
    }
    else
    {
        auswahl = -1;
        for( int i = seite * 4; i >= 0 && i < anzahl && i < seite * 4 + 4; i++ )
            members->z( i )->setSichtbar( 0 );
        animation &= ~0x1;
    }
    rend = 1;
}

void SpielAuswahlFenster::blättern( bool oben )
{
    for( int i = seite * 4; i >= 0 && i < anzahl && i < seite * 4 + 4; i++ )
        members->z( i )->setSichtbar( 0 );
    seite += oben ? 1 : -1;
    for( int i = seite * 4; i >= 0 && i < anzahl && i < seite * 4 + 4; i++ )
    {
        members->z( i )->setPosition( i % 4 );
        members->z( i )->setSichtbar( 1 );
    }
    auswahl = -1;
    rend = 1;
}

void SpielAuswahlFenster::updateListe()
{
    if( run )
        return;
    start();
}

void SpielAuswahlFenster::thread()
{
    Array< int > *liste = infoKlient->getAccountSpielArtListe();
    if( !liste )
    {
        nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), new Text( infoKlient->getLetzterFehler() ),
                                                      new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
        run = 0;
        return;
    }
    int anz = liste->getEintragAnzahl();
    for( int i = 0; i < anz; i++ )
    {
        Text *name = infoKlient->getSpielName( liste->hat( i ) ? liste->get( i ) : 0 );
        if( name )
        {
            bool gefunden = 0;
            for( int j = 0; j < anzahl; j++ )
            {
                SpielDaten *tmp = members->z( j );
                if( liste->hat( i ) && tmp->getSpielId() == liste->get( i ) )
                {
                    gefunden = 1;
                    break;
                }
            }
            if( !gefunden )
            {
                SpielDaten *tmp = new SpielDaten( schrift, name->getText(), liste->hat( i ) ? liste->get( i ) : 0 );
                members->add( tmp, anzahl );
                anzahl++;
            }
            name->release();
        }
    }
    if( liste )
        liste->release();
    for( int i = 0; i < anzahl; i++ )
        members->z( i )->updateErlaubt();
    for( int i = seite * 4; i < anzahl && i >= 0 && i < seite * 4 + 4; i++ )
    {
        members->z( i )->setPosition( i % 4 );
        members->z( i )->setSichtbar();
    }
    rend = 1;
    run = 0;
}

bool SpielAuswahlFenster::tick( double tickVal )
{
    for( int i = 0; i < anzahl; i++ )
        rend |= members->z( i )->tick( tickVal );
    this->tickVal += tickVal * 750;
    int val = ( int )this->tickVal;
    if( val < 1 )
    {
        bool ret = rend;
        rend = 0;
        return ret;
    }
    if( val > 25 )
        val = 25;
    this->tickVal -= val;
    if( ( animation | 0x1 ) == animation ) // sichtbar
    {
        if( alpha < 255 )
        {
            if( alpha + val >= 255 )
            {
                alpha = 255;
                for( int i = seite * 4; i < anzahl && i >= 0 && i < seite * 4 + 4; i++ )
                {
                    members->z( i )->setPosition( i % 4 );
                    members->z( i )->setSichtbar( 1 );
                }
            }
            else
                alpha += val;
            rend = 1;
        }
    }
    else // unsichtbar
    {
        if( alpha > 0 )
        {
            if( alpha - val < 0 )
                alpha = 0;
            else
                alpha -= val;
            rend = 1;
        }
    }
    bool ret = rend;
    rend = 0;
    return ret;
}

void SpielAuswahlFenster::doMausEreignis( MausEreignis &me )
{
    if( pos.x != 10 )
        return;
    me.mx -= pos.x;
    me.my -= pos.y;
    for( int i = 0; i < anzahl; i++ )
        members->z( i )->doMausEreignis( me );
    if( me.mx < 0 || me.my < 0 )
    {
        me.mx += pos.x;
        me.my += pos.y;
        return;
    }
    if( me.mx > 200 || me.my > getAnzahlAufSeite() * 100 )
    {
        me.mx += pos.x;
        me.my += pos.y;
        return;
    }
    if( me.id == ME_RLinks )
    {
        int treffer = me.my / 100 + seite * 4;
        if( treffer >= anzahl )
        {
            me.mx += pos.x;
            me.my += pos.y;
            return;
        }
        if( treffer == auswahl )
        {
            me.mx += pos.x;
            me.my += pos.y;
            return;
        }
        if( auswahl >= 0 )
            members->z( auswahl )->setAuswahl( 0 );
        members->z( treffer )->setAuswahl( 1 );
        auswahl = treffer;
        rend = 1;
    }
    me.mx += pos.x;
    me.my += pos.y;
}

void SpielAuswahlFenster::render( Bild &zrObj )
{
    int x = pos.x;
    int y = pos.y;
    int br = gr.x;
    int hö = gr.y;
    if( !zrObj.setDrawOptions( x, y, br, hö ) )
        return;
    zrObj.setAlpha( alpha );
    rahmen->setGröße( br, hö );
    rahmen->render( zrObj );
    int rbr = rahmen->getRBreite();
    if( !zrObj.setDrawOptions( rbr, rbr, br - rbr * 2, hö - rbr * 2 ) )
    {
        zrObj.releaseDrawOptions();
        zrObj.releaseAlpha();
        return;
    }
    for( int i = seite * 4; i >= 0 && i < anzahl && i < seite * 4 + 4; i++ )
        members->z( i )->render( zrObj );
    zrObj.releaseDrawOptions();
    if( !anzahl )
    {
        Text t = "Dieser Account besitzt momentan noch keine Spiele.\nBesuche den Shop um neue Spiele zu erwerben!";
        schrift->lock();
        schrift->setDrawPosition( 10, 10 );
        schrift->setSchriftGröße( 12 );
        schrift->renderText( &t, zrObj, 0xFFFFFFFF );
        schrift->unlock();
    }
    zrObj.releaseDrawOptions();
    zrObj.releaseAlpha();
}

// constant
int SpielAuswahlFenster::getAnzahl() const
{
    return anzahl;
}

int SpielAuswahlFenster::getSeiteAnzahl() const
{
    return ( anzahl / 4.0 == anzahl / 4 ) ? ( anzahl / 4 ) : ( anzahl / 4 + 1 );
}

int SpielAuswahlFenster::getSeite() const
{
    return seite;
}

int SpielAuswahlFenster::getAnzahlAufSeite() const
{
    return ( anzahl < seite * 4 + 4 ) ? ( anzahl - seite * 4 ) : 4;
}

bool SpielAuswahlFenster::hatAuswahl() const
{
    return auswahl != -1;
}

SpielDaten *SpielAuswahlFenster::getAuswahl() const
{
    return members->get( auswahl );
}

SpielDaten *SpielAuswahlFenster::zAuswahl() const
{
    return members->z( auswahl );
}

bool SpielAuswahlFenster::istAuswahlErlubt() const
{
    return auswahl != -1 && members->z( auswahl )->istErlaubt();
}

// Reference Counting
SpielAuswahlFenster *SpielAuswahlFenster::getThis()
{
    ref++;
    return this;
}

SpielAuswahlFenster *SpielAuswahlFenster::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}