#include "Spieler.h" #include "Spiel.h" #include "BosheitRune.h" #include "Enterhaken.h" #include "Geist.h" #include "Leben.h" #include "LebenRune.h" #include "Rolle.h" #include "Schild.h" #include "Schuh.h" #include "StrengthRune.h" #include "Sturm.h" #include "TempoRune.h" Inventar::Inventar() { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { slots[ i ] = KEIN_GEGENSTAND; anzahl[ i ] = 0; abklingzeit[ i ] = 0; } selected = 0; } void Inventar::addItem( GegenstandTyp typ, int anzahl ) { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == typ ) { this->anzahl[ i ] += anzahl; return; } } for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == KEIN_GEGENSTAND ) { slots[ i ] = typ; this->anzahl[ i ] = consumable( typ ) ? anzahl : 1; return; } } } void Inventar::setSelected( int slot ) { selected = slot; if( selected >= INVENTORY_SLOTS ) selected = INVENTORY_SLOTS - 1; } bool Inventar::hatAbklingzeit( GegenstandTyp typ ) const { for( int i = 0; i < INVENTORY_SLOTS; i++ ) if( slots[ i ] == typ && abklingzeit[ i ] > 0 ) return 1; return 0; } GegenstandTyp Inventar::useItem() { if( slots[ selected ] != KEIN_GEGENSTAND && abklingzeit[ selected ] <= 0 ) { if( consumable( slots[ selected ] ) ) { if( !--anzahl[ selected ] ) { GegenstandTyp typ = slots[ selected ]; slots[ selected ] = KEIN_GEGENSTAND; return typ; } } abklingzeit[ selected ] = ::abklingzeit( slots[ selected ] ); return slots[ selected ]; } return KEIN_GEGENSTAND; } void Inventar::tick( double zeit ) { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] != KEIN_GEGENSTAND && abklingzeit[ i ] > 0 ) { abklingzeit[ i ] -= (float)zeit; if( abklingzeit[ i ] < 0 ) abklingzeit[ i ] = 0; } } } bool Inventar::canAddItem( GegenstandTyp typ ) const { if( !consumable( typ ) ) { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == typ ) return 0; } } for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == KEIN_GEGENSTAND || ( slots[ i ] == typ && consumable( typ ) ) ) return 1; } return 0; } GegenstandTyp Inventar::selectedItem() const { return slots[ selected ]; } int Inventar::getItemAnzahl() const { int sum = 0; for( int i = 0; i < INVENTORY_SLOTS; i++ ) sum += anzahl[ i ]; return sum; } int Inventar::getItemAnzahl( GegenstandTyp typ ) const { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == typ ) return anzahl[ i ]; } return 0; } GegenstandTyp Inventar::getItemTyp( int index ) const { if( index < 0 || index >= INVENTORY_SLOTS ) return KEIN_GEGENSTAND; return slots[ index ]; } void Inventar::removeItem( GegenstandTyp typ, int anzahl ) { for( int i = 0; i < INVENTORY_SLOTS; i++ ) { if( slots[ i ] == typ ) { this->anzahl[ i ] -= anzahl; if( this->anzahl[ i ] < 0 ) { slots[ i ] = KEIN_GEGENSTAND; abklingzeit[ i ] = 0; } } } } Spieler::Spieler( int id, Team *team, int spawnX, int spawnY, int farbe ) : GameObject( SPIELER, spawnX, spawnY, 40, 50 ) { klient = 0; accountId = 0; spielerNummer = id; this->team = team; amLeben = 1; maxWiederbelebungsZeit = 2; wiederbelebungsZeit = 0; zuletztAufgehoben = KEIN_GEGENSTAND; zuletztAktiviert = KEIN_GEGENSTAND; this->leben = 300; this->maxLeben = 300; level = 1; erfahrung = 0; maxErfahrung = 5; this->spawnX = spawnX; this->spawnY = spawnY; laufTempo = 30; geschossTempo = 100; armor = 0; schadensBonus = 0; lebensraub = 0; lebensRegeneration = 1; abklingZeitVerringerung = 0; color = farbe; kills = 0; tode = 0; treffer = 0; getroffen = 0; schadenGenommen = 0; schadenGemacht = 0; lebenGeheilt = 0; erhalteneErfahrung = 0; itemsAufgehoben = 0; itemsVerwendet = 0; tunnelBenutzt = 0; schalterAktiviert = 0; geschosseGeschossen = 0; for( int i = 0; i < 256; i++ ) tastenStand[ i ] = 0; ausrichtung = MITTE; } Spieler::~Spieler() { if( klient ) klient->release(); if( team ) team->release(); } bool Spieler::setTastenStand( unsigned char taste, bool pressed ) { bool ret = tastenStand[ (int)taste ] != pressed; tastenStand[ (int)taste ] = pressed; if( pressed ) { if( taste == 'w' ) ausrichtung = OBEN; if( taste == 'a' ) ausrichtung = LINKS; if( taste == 's' ) ausrichtung = UNTEN; if( taste == 'd' ) ausrichtung = RECHTS; if( taste >= '1' && taste <= '8' ) inv.setSelected( taste - '1' ); } else { if( !tastenStand[ 'w' ] && !tastenStand[ 'a' ] && !tastenStand[ 's' ] && !tastenStand[ 'd' ] ) ausrichtung = MITTE; else { if( ( ausrichtung == OBEN && taste == 'w' ) || ( ausrichtung == LINKS && taste == 'a' ) || ( ausrichtung == UNTEN && taste == 's' ) || ( ausrichtung == RECHTS && taste == 'd' ) ) { if( tastenStand[ 'w' ] ) ausrichtung = OBEN; if( tastenStand[ 'a' ] ) ausrichtung = LINKS; if( tastenStand[ 's' ] ) ausrichtung = UNTEN; if( tastenStand[ 'd' ] ) ausrichtung = RECHTS; } } } return ret; } void Spieler::setTeam( Team *team ) { if( this->team ) this->team->removeSpieler(); this->team->release(); this->team = team; if( this->team ) this->team->addSpieler(); } void Spieler::setAccount( int id ) { this->accountId = id; } void Spieler::setKlient( Klient *klient ) { if( this->klient ) this->klient->release(); this->klient = klient; } void Spieler::addEffekt( Effect *e ) { effekte.add( e ); } void Spieler::setLaufTempo( float pps ) { laufTempo = pps; } void Spieler::addErfahrung( float anz, Spiel *zSpiel ) { erfahrung += anz; zSpiel->setSpielerZuletztErfahrungBekommen( (Spieler *)getThis() ); Ereignis *e = new Ereignis( SPIELER_BEKOMMT_ERFAHRUNG ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Wert", new Float( anz ) ); zSpiel->throwEvent( e ); while( erfahrung > (float)maxErfahrung ) levelUp( zSpiel ); while( erfahrung < 0 ) levelDown( zSpiel ); } void Spieler::levelUp( Spiel *zSpiel ) { level++; erfahrung -= (float)maxErfahrung; maxErfahrung += ( maxErfahrung / level ) + 2; maxLeben += 20; heilung( 20, zSpiel ); if( level <= 10 ) { laufTempo += 2; geschossTempo += 2; } if( level <= 50 ) { armor += 1; abklingZeitVerringerung += 1; } if( level <= 75 ) { schadensBonus += 1; lebensraub += 1; } if( level <= 100 ) lebensRegeneration += 0.25f; zSpiel->setSpielerZuletztLevelUp( (Spieler *)getThis() ); Ereignis *e = new Ereignis( SPIELER_LEVEL_UP ); e->addParameter( "Betroffener Spieler", getThis() ); zSpiel->throwEvent( e ); } void Spieler::levelDown( Spiel *zSpiel ) { if( level <= 100 ) lebensRegeneration -= 0.25f; if( level <= 75 ) { schadensBonus -= 1; lebensraub -= 1; } if( level <= 50 ) { armor -= 1; abklingZeitVerringerung -= 1; } if( level <= 10 ) { laufTempo -= 2; geschossTempo -= 2; } maxLeben -= 20; maxErfahrung -= ( maxErfahrung / level ) + 2; erfahrung += (float)maxErfahrung; level--; } void Spieler::addTunnelBenutzung( Spiel *zSpiel ) { tunnelBenutzt++; zSpiel->setSpielerZuletztTunnelBenutzt( (Spieler *)getThis() ); } void Spieler::addSchalterBenutzung( Spiel *zSpiel ) { schalterAktiviert++; zSpiel->setSpielerZuletztSchalterAktiviert( (Spieler *)getThis() ); } // aktualisiert auch die team statistik void Spieler::addKill() { team->addKill(); kills++; } void Spieler::addTreffer( Spiel *zSpiel ) { addErfahrung( 2, zSpiel ); treffer++; } void Spieler::addGetroffen() { getroffen++; } void Spieler::move( Richtung r, double zeit ) { if( istAmLeben() ) { if( istBeweglich( r ) ) { if( tastenStand[ 'w' ] && r == OBEN ) y -= laufTempo * (float)zeit; if( tastenStand[ 'a' ] && r == LINKS ) x -= laufTempo * (float)zeit; if( tastenStand[ 's' ] && r == UNTEN ) y += laufTempo * (float)zeit; if( tastenStand[ 'd' ] && r == RECHTS ) x += laufTempo * (float)zeit; } for( auto e = effekte.getIterator(); e; e++ ) e->move( r, zeit ); } } void Spieler::wiederbelebung( Spiel *zSpiel ) { amLeben = 1; leben = (float)maxLeben; zSpiel->setSpielerZuletztWiederbelebt( (Spieler *)getThis() ); Ereignis *e = new Ereignis( SPIELER_WIEDERBELEBT ); e->addParameter( "Betroffener Spieler", getThis() ); zSpiel->throwEvent( e ); } void Spieler::tick( double zeit, Spiel *zSpiel ) { if( istAmLeben() ) { intersectable = 1; for( int i = 0; i < effekte.getEintragAnzahl(); i++ ) { intersectable &= effekte.z( i )->istIntersectable(); if( effekte.z( i )->tick( zeit, zSpiel ) && istAmLeben() ) { effekte.remove( i ); i--; } if( !istAmLeben() ) break; } if( tastenStand[ ' ' ] ) useItem( zSpiel ); if( tastenStand[ 'e' ] ) zSpiel->spielerActivate( this ); heilung( lebensRegeneration * (float)zeit, zSpiel ); } else { intersectable = 0; effekte.leeren(); wiederbelebungsZeit -= (float)zeit; if( wiederbelebungsZeit <= 0 ) { wiederbelebung( zSpiel ); } } inv.tick( zeit ); } void Spieler::useItem( Spiel *zSpiel ) { if( istAmLeben() && inv.selectedItem() != KEIN_GEGENSTAND && istGegenstandErlaubt( inv.selectedItem() ) ) { zSpiel->setSpielerZuletztGegenstandAktiviert( (Spieler *)getThis() ); itemsVerwendet++; GegenstandTyp typ = inv.useItem(); zSpiel->setItemZuletztAktiviert( typ ); switch( typ ) { case PFEIL: geschosseGeschossen++; zSpiel->setSpielerZuletztGeschossen( (Spieler *)getThis() ); zSpiel->addGeschoss( new Geschoss( zSpiel->getNextId(), geschossTempo, GESCHOSS_PFEIL, getAusrichtung(), (int)x + (int)getWidth() / 2, (int)y + (int)getHeight() / 2, (Spieler *)getThis() ) ); break; case LEBEN: addEffekt( new LebenEffect( this ) ); break; case SCHILD: addEffekt( new SchildEffect( this ) ); break; case SCHUH: addEffekt( new SchuhEffect( this ) ); break; case GEIST: addEffekt( new GeistEffect( this ) ); break; case KUGEL: geschosseGeschossen++; zSpiel->setSpielerZuletztGeschossen( (Spieler *)getThis() ); zSpiel->addGeschoss( new Geschoss( zSpiel->getNextId(), geschossTempo, GESCHOSS_KUGEL, getAusrichtung(), (int)x + (int)getWidth() / 2, (int)y + (int)getHeight() / 2, (Spieler *)getThis() ) ); break; case ROLLE: addEffekt( new RolleEffect( this, getAusrichtung() ) ); break; case STURM: addEffekt( new SturmEffect( this, getAusrichtung() ) ); break; case DRACHENAUGE: geschosseGeschossen++; zSpiel->setSpielerZuletztGeschossen( (Spieler *)getThis() ); zSpiel->addGeschoss( new Geschoss( zSpiel->getNextId(), geschossTempo, GESCHOSS_DRACHENAUGE, getAusrichtung(), (int)x + (int)getWidth() / 2, (int)y + (int)getHeight() / 2, (Spieler *)getThis() ) ); break; case FEUERBALL: geschosseGeschossen++; zSpiel->setSpielerZuletztGeschossen( (Spieler *)getThis() ); zSpiel->addGeschoss( new Geschoss( zSpiel->getNextId(), geschossTempo, GESCHOSS_FEUERBALL, getAusrichtung(), (int)x + (int)getWidth() / 2, (int)y + (int)getHeight() / 2, (Spieler *)getThis() ) ); break; case ENTERHAKEN: addEffekt( new EnterhakenEffect( this, getAusrichtung() ) ); break; case MINE: geschosseGeschossen++; zSpiel->setSpielerZuletztGeschossen( (Spieler *)getThis() ); zSpiel->addGeschoss( new Geschoss( zSpiel->getNextId(), 0, GESCHOSS_MINE, MITTE, (int)x + (int)getWidth() / 2, (int)y + (int)getHeight() / 2, (Spieler *)getThis() ) ); break; default: break; } Ereignis *e = new Ereignis( SPIELER_BENUTZT_GEGENSTAND ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Betroffener Gegenstand", new GegenstandTypVar( typ ) ); zSpiel->throwEvent( e ); } } bool Spieler::addItem( GegenstandTyp typ, int anz, Spiel *zSpiel ) { if( storable( typ ) ) { if( inv.canAddItem( typ ) ) { zSpiel->setItemZuletztAufgehoben( typ ); zSpiel->setSpielerZuletztGegenstandAufgehoben( (Spieler *)getThis() ); itemsAufgehoben += anz; inv.addItem( typ, anz ); Ereignis *e = new Ereignis( SPIELER_BEKOMMT_GEGENSTAND ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Betroffener Gegenstand", new GegenstandTypVar( typ ) ); e->addParameter( "Anzahl", new Integer( anz ) ); zSpiel->throwEvent( e ); return 1; } else return 0; } else { zSpiel->setItemZuletztAufgehoben( typ ); zSpiel->setSpielerZuletztGegenstandAufgehoben( (Spieler *)getThis() ); itemsAufgehoben += anz; Ereignis *e = new Ereignis( SPIELER_BEKOMMT_GEGENSTAND ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Betroffener Gegenstand", new GegenstandTypVar( typ ) ); e->addParameter( "Anzahl", new Integer( anz ) ); zSpiel->throwEvent( e ); for( int i = 0; i < anz; i++ ) { Ereignis *e = new Ereignis( SPIELER_BENUTZT_GEGENSTAND ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Betroffener Gegenstand", new GegenstandTypVar( typ ) ); zSpiel->throwEvent( e ); itemsVerwendet++; switch( typ ) { case RWEISHEIT: addErfahrung( 2, zSpiel ); break; case RSTRENGTH: addEffekt( new StrengthRuneEffect( this ) ); break; case RBOSHEIT: addEffekt( new BosheitRuneEffect( this ) ); break; case RLEBEN: addEffekt( new LebenRuneEffect( this ) ); break; case RTEMPO: addEffekt( new TempoRuneEffect( this ) ); break; default: break; } } return 1; } } // heilt auch um den lebensraub prozentsatz void Spieler::addGemachterSchaden( float schaden, Spiel *zSpiel ) { zSpiel->setSpielerZuletztSchadenGemacht( (Spieler *)getThis() ); schadenGemacht += schaden; heilung( schaden / 100 * lebensraub, zSpiel ); Ereignis *e = new Ereignis( SPIELER_MACHT_SCHADEN ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Wert", new Float( schaden ) ); zSpiel->throwEvent( e ); } // zieht die rüstung ab void Spieler::nimmSchaden( float schaden, Spieler *zVerursacher, Richtung r, Spiel *zSpiel ) { if( !isVerwundbar( r ) || !istAmLeben() ) return; if( zVerursacher ) schaden += schaden / 100 * zVerursacher->getSchadenBonus(); schaden -= schaden / 100 * armor; schaden = leben < schaden ? leben : schaden; schadenGenommen += schaden; leben -= schaden; zSpiel->setSpielerZuletztSchadenGenommen( (Spieler *)getThis() ); if( zVerursacher ) zVerursacher->addGemachterSchaden( schaden, zSpiel ); Ereignis *e = new Ereignis( SPIELER_NIMMT_SCHADEN ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Wert", new Float( schaden ) ); zSpiel->throwEvent( e ); if( leben == 0 ) { wiederbelebungsZeit = (float)( (float)maxWiederbelebungsZeit + team->getMaxWiederbelebungsZeit() ); wiederbelebungsZeit -= wiederbelebungsZeit / 100 * abklingZeitVerringerung; team->addTod(); amLeben = 0; tode++; zSpiel->setSpielerZuletztGestorben( (Spieler *)getThis() ); if( zVerursacher ) zVerursacher->addKill(); Ereignis *e = new Ereignis( SPIELER_STIRBT ); e->addParameter( "Betroffener Spieler", getThis() ); zSpiel->throwEvent( e ); } } void Spieler::heilung( float heal, Spiel *zSpiel ) { if( istAmLeben() ) { heal = heal + leben > (float)maxLeben ? (float)maxLeben - leben : heal; lebenGeheilt += heal; leben += heal; zSpiel->setSpielerZuletztGeheilt( (Spieler *)getThis() ); Ereignis *e = new Ereignis( SPIELER_WIRD_GEHEILT ); e->addParameter( "Betroffener Spieler", getThis() ); e->addParameter( "Wert", new Float( heal ) ); zSpiel->throwEvent( e ); } } void Spieler::setSchadenBonus( float bonus ) { schadensBonus = bonus; } void Spieler::setLebensRaub( float raub ) { lebensraub = raub; } void Spieler::setGeschossTempo( float tempo ) { geschossTempo = tempo; } void Spieler::setArmor( float armor ) { this->armor = armor; } void Spieler::setLebensRegeneration( float reg ) { lebensRegeneration = reg; } void Spieler::setName( const char *name ) { this->name = name; } void Spieler::setLevel( int level, Spiel *zSpiel ) { if( level < 0 || level > 100 ) return; while( level > this->level ) levelUp( zSpiel ); while( level < this->level ) levelDown( zSpiel ); erfahrung = 0; } void Spieler::removeItem( GegenstandTyp typ, int anzahl ) { inv.removeItem( typ, anzahl ); } void Spieler::setLeben( float leben ) { this->leben = leben; if( this->leben < 0 ) { this->leben = 0; // the player is now undead :D } if( this->leben > ( float )maxLeben ) this->leben = (float)maxLeben; } void Spieler::setMaxLeben( int leben ) { maxLeben = leben; if( maxLeben < 1 ) maxLeben = 1; if( this->leben > ( float )maxLeben ) this->leben = (float)maxLeben; } void Spieler::setErfahrung( float erf, Spiel *zSpiel ) { erfahrung = erf; while( erfahrung < 0 ) levelDown( zSpiel ); while( erfahrung >= (float)maxErfahrung ) levelUp( zSpiel ); } void Spieler::setMaxErfahrung( int erf ) { this->maxErfahrung = erf; } void Spieler::setAbklingZeitVerringerung( float verringerung ) { abklingZeitVerringerung = verringerung; } float Spieler::getLebensRegenneration() const { return lebensRegeneration; } float Spieler::getArmor() const { return armor; } float Spieler::getGeschossTempo() const { return geschossTempo; } float Spieler::getLebensRaub() const { return lebensraub; } float Spieler::getSchadenBonus() const { return schadensBonus; } Klient *Spieler::zKlient() const { return klient; } Team *Spieler::zTeam() const { return team; } Team *Spieler::getTeam() const { return team ? (Team *)team->getThis() : 0; } int Spieler::getFarbe() const { return color; } int Spieler::getAccountId() const { return accountId; } int Spieler::getPunkte() const { return kills - tode + ( treffer - getroffen ) / 2; } bool Spieler::istAmLeben() const { return amLeben && accountId; } float Spieler::getLaufTempo() const { return laufTempo; } bool Spieler::isVerwundbar( Richtung r ) const { bool verwundbar = 1; for( auto e = effekte.getIterator(); e; e++ ) { verwundbar &= e->istSpielerVerwundbar( r ); if( !verwundbar ) return 0; } return 1; } bool Spieler::istBeweglich( Richtung r ) const { bool beweglich = 1; for( auto e = effekte.getIterator(); e; e++ ) { beweglich &= e->istSpielerBeweglich( r ); if( !beweglich ) return 0; } return 1; } bool Spieler::istSichtbar( Team *zTeam ) const { bool sichtbar = 1; for( auto e = effekte.getIterator(); e; e++ ) { sichtbar &= e->istSpielerSichtbar( zTeam ); if( !sichtbar ) return 0; } return 1; } bool Spieler::istGegenstandErlaubt( GegenstandTyp typ ) const { bool erlaubt = !brauchtRichtung( typ ) || ausrichtung != MITTE; for( auto e = effekte.getIterator(); e; e++ ) { erlaubt &= e->istGegenstandErlaubt( typ ); if( !erlaubt ) return 0; } return !inv.hatAbklingzeit( typ ); } Richtung Spieler::getAusrichtung() const { return ausrichtung; } float Spieler::getAbklingZeitVerringerung() const { return abklingZeitVerringerung; } int Spieler::getId() const { return spielerNummer; } int Spieler::getLevel() const { return level; } float Spieler::getLeben() const { return leben; } int Spieler::getMaxLeben() const { return maxLeben; } float Spieler::getErfahrung() const { return erfahrung; } int Spieler::getMaxErfahrung() const { return maxErfahrung; } int Spieler::getTode() const { return tode; } int Spieler::getKills() const { return kills; } int Spieler::getTreffer() const { return treffer; } int Spieler::getGetroffen() const { return getroffen; } float Spieler::getErlittenerSchaden() const { return schadenGenommen; } float Spieler::getGemachterSchaden() const { return schadenGemacht; } float Spieler::getGeheiltesLeben() const { return lebenGeheilt; } int Spieler::getItemsAufgehoben() const { return itemsAufgehoben; } int Spieler::getItemsVerwendet() const { return itemsVerwendet; } int Spieler::getItemsInInventory() const { return inv.getItemAnzahl(); } int Spieler::getItemsInInventory( GegenstandTyp typ ) const { return inv.getItemAnzahl( typ ); } int Spieler::getTunnelBenutzt() const { return tunnelBenutzt; } int Spieler::getSchalterAktiviert() const { return schalterAktiviert; } int Spieler::getGeschossen() const { return geschosseGeschossen; } GegenstandTyp Spieler::getInventorySlot( int index ) const { return inv.getItemTyp( index ); } const char *Spieler::getName() const { return name; }