#include "Spieler.h" #include "../../Initialisierung/Initialisierung.h" #include "../Karte/Karte.h" #include "../Define.h" #include #include "../Schuss/Laser.h" // Inhalt der Spieler Klasse aus Spieler.h // Konstruktor Spieler::Spieler( KSGClient::InformationServerClient *zInfoK, Schrift *zSchrift, SpielerStr *zStr ) { textur = 0; deadPlayer = 0; accountId = 0; sNum = zStr->id; current.farbe = 0; ship = new Model2D(); ship->setStyle( Model2D::Style::Sichtbar | Model2D::Style::Textur | Model2D::Style::Alpha ); team = 0; info = zInfoK->getThis(); name = 0; for( int i = 0; i < T_MAX; i++ ) tastatur[ i ] = 0; current.amLeben = 1; current.schussAbk = 0; current.energieAbk = 0; current.repAbk = 0; current.reinkAbk = 0; current.maxReinkAbk = 5; ref = 1; current.startPos = zStr->pos; current.pos = zStr->pos; current.speed = Vec2< double >( 0, 0 ); current.rotation = zStr->rot; current.beschleunigung = zStr->beschleunigung; beschleunigungStart = zStr->beschleunigung; current.energie = zStr->maxEnergie; current.stabilität = zStr->maxStabilität; current.reparatur = zStr->reparatur; current.laserIntensität = zStr->laserIntensität; current.laserEffizienz = zStr->laserEffizienz; current.akkuLeistung = zStr->akkuLeistung; akkuLeistungStart = zStr->akkuLeistung; current.maxEnergie = zStr->maxEnergie; current.maxStabilität = zStr->maxStabilität; current.laserTempo = zStr->laserTempo; current.netzwerk = zStr->netzwerk; current.wendigkeit = zStr->wendigkeit; wendigkeitStart = current.wendigkeit; current.antriebEffizienz = zStr->antriebEffizienz; skillPunkte = zStr->skillPunkte; current.schadenBekommen = 0; current.schadenGemacht = 0; current.treibstoffVerbraucht = 0; current.schüsse = 0; current.treffer = 0; current.punkte = 0; current.kills = 0; current.tode = 0; current.zeitAmLeben = 0; current.zeitTod = 0; nText = initTextFeld( 0, 0, 152, 30, zSchrift, TextFeld::Style::Text | TextFeld::Style::Rahmen | TextFeld::Style::Center | TextFeld::Style::Hintergrund | TextFeld::Style::HAlpha, "" ); current.spielZeit = 0; current.rSpeed = 0; ship->setPosition( current.pos ); ship->setDrehung( (float)current.rotation ); last = current; } // Destruktor Spieler::~Spieler() { if( textur ) textur->release(); ship->release(); info->release(); if( team ) team->release(); if( name ) name->release(); flammenL->release(); flammenR->release(); flammenM->release(); } double Spieler::calculateLaserCost() { double kosten = ( ( current.laserIntensität + team->laserIntensität ) / 2 + ( current.laserTempo + team->laserTempo ) / 13 ) * ( 1 / ( ( current.laserEffizienz + team->laserEffizienz ) / 25 ) ); if( kosten < 1 ) kosten = 1; return kosten; } // nicht constant void Spieler::setModelData( Model2DData *data, Animation2DData *zFStart, Animation2DData *zFBurn ) { for( auto i = data->polygons->getArray(); i.set; i++ ) { if( i.var.name->istGleich( "engine_l" ) ) { stL = *i.var.schwerpunkt; Vertex l, r; for( int j = 0; j < 4; j++ ) { if( i.var.tKordinaten->get( j ).y == 1.f ) { if( i.var.tKordinaten->get( j ).x == 0.f ) l = i.var.vertex->get( j ); if( i.var.tKordinaten->get( j ).x == 1.f ) r = i.var.vertex->get( j ); } } kL = ( ( l + ( r - l ) * 0.5 ) - stL ); } if( i.var.name->istGleich( "engine_r" ) ) { stR = *i.var.schwerpunkt; Vertex l, r; for( int j = 0; j < 4; j++ ) { if( i.var.tKordinaten->get( j ).y == 1.f ) { if( i.var.tKordinaten->get( j ).x == 0.f ) l = i.var.vertex->get( j ); if( i.var.tKordinaten->get( j ).x == 1.f ) r = i.var.vertex->get( j ); } } kR = ( ( l + ( r - l ) * 0.5 ) - stR ); } if( i.var.name->istGleich( "engine_m" ) ) { stM = *i.var.schwerpunkt; Vertex l, r; for( int j = 0; j < 4; j++ ) { if( i.var.tKordinaten->get( j ).y == 1.f ) { if( i.var.tKordinaten->get( j ).x == 0.f ) l = i.var.vertex->get( j ); if( i.var.tKordinaten->get( j ).x == 1.f ) r = i.var.vertex->get( j ); } } kM = ( ( l + ( r - l ) * 0.5 ) - stM ); } } kL.normalize(); kR.normalize(); kM.normalize(); ship->setModel( data ); flammenM = new Textur2D(); flammenM->addAnimationZ( zFStart->getThis() ); flammenM->addAnimationZ( zFBurn->getThis() ); flammenL = new Textur2D(); flammenL->addAnimationZ( zFStart->getThis() ); flammenL->addAnimationZ( zFBurn->getThis() ); flammenR = new Textur2D(); flammenR->addAnimationZ( zFStart->getThis() ); flammenR->addAnimationZ( zFBurn->getThis() ); ship->setTextur( flammenL->getThis(), "engine_l" ); ship->setTextur( flammenR->getThis(), "engine_r" ); ship->setTextur( flammenM->getThis(), "engine_m" ); } void Spieler::setAccountId( int accId ) { accountId = accId; name = info->getSpielerName( accountId ); if( name ) nText->setText( *name ); } void Spieler::setTeam( Team *team ) { if( this->team ) this->team->release(); this->team = team; nText->setHintergrundFarbe( 0xA0000000 | ( team->farbe & 0x00FFFFFF ) ); nText->setLinienRahmenFarbe( team->farbe ); } void Spieler::setSpielerFarbe( int fc, Bild *zTextur ) { current.farbe = fc; nText->setSchriftFarbe( fc ); Bild *shb = new Bild(); shb->neuBild( zTextur->getBreite(), zTextur->getHeight(), 0 ); int maxP = shb->getBreite() * shb->getHeight(); int *buffer = zTextur->getBuffer(); for( int i = 0; i < maxP; i++ ) { if( buffer[ i ] ) { shb->setPixelDP( i, ( buffer[ i ] & 0xFF000000 ) | ( fc & 0x00FFFFFF ) ); shb->alphaPixelDP( i, buffer[ i ] ); } } if( textur ) textur->release(); textur = new Textur2D(); textur->setTexturZ( shb ); ship->setTextur( textur->getThis(), "ship" ); } void Spieler::setGeschwindigkeit( double xSpeed, double ySpeed ) { current.speed = Vec2< double >( xSpeed, ySpeed ); } void Spieler::setPosition( Vec2< double > p ) { current.pos = p; ship->setPosition( current.pos ); } void Spieler::setTastataturStatus( TastaturStatus ts, bool aktiv, int sZ, Karte *zMap ) { if( !current.amLeben ) { tastatur[ ts ] = aktiv; return; } int z = sZ - current.spielZeit; int time = current.spielZeit; resetToSaveTime( sZ, zMap ); tastatur[ ts ] = aktiv; resetToGameTime( time, zMap ); if( flammenM && flammenR && flammenL ) { switch( ts ) { case T_GAS: if( aktiv ) flammenM->setAnimation( 0 ); else flammenM->setAnimation( -1 ); break; case T_ROT_L: if( aktiv ) flammenR->setAnimation( 0 ); else flammenR->setAnimation( -1 ); break; case T_ROT_R: if( aktiv ) flammenL->setAnimation( 0 ); else flammenL->setAnimation( -1 ); break; } } } bool Spieler::tick( int time, Karte *zMap ) { if( time <= current.spielZeit ) return 0; bool ret = 0; while( current.spielZeit != time ) { if( !team ) return 0; if( !current.spielZeit ) last = current; double tv = TICK; current.reinkAbk -= tv; if( current.reinkAbk < 0 ) current.reinkAbk = 0; flammenM->tick( tv ); flammenL->tick( tv ); flammenR->tick( tv ); if( current.amLeben ) { current.schussAbk -= tv; current.energieAbk -= tv; if( current.schussAbk < 0 ) current.schussAbk = 0; if( current.energieAbk < 0 ) current.energieAbk = 0; current.repAbk -= tv; if( current.repAbk < 0 ) current.repAbk = 0; current.spielZeit++; if( tastatur[ T_GAS ] ) { Vertex hp; Vertex mv; float r; double treibstoff = 3 * ( ( current.beschleunigung + team->beschleunigung) / 5 ) * tv * ( 100 / ( current.antriebEffizienz + team->antriebEffizienz ) ); current.treibstoffVerbraucht += treibstoff; double factor = 1; if( treibstoff > current.energie ) factor = current.energie / treibstoff; if( ship->zModel()->calcHitPoint( stM, kM * (float)( current.beschleunigung + team->beschleunigung ), "ship", hp, mv, r ) ) { current.speed += ( Vec2 )mv.rotation( (float)current.rotation ) * (float)TICK * factor; } current.energie -= treibstoff * factor; } double movementAngle = atan2( current.speed.y, current.speed.x ); bool xg0 = current.speed.x > 0; bool yg0 = current.speed.y > 0; if( current.speed.x != 0 ) current.speed.x += 5.0f * cos( movementAngle + PI ) * TICK; if( current.speed.y != 0 ) current.speed.y += 5.0f * sin( movementAngle + PI ) * TICK; if( !xg0 && current.speed.x > 0 ) current.speed.x = 0; if( !yg0 && current.speed.y > 0 ) current.speed.y = 0; if( current.rSpeed > 0 ) { current.rSpeed -= (float)(TICK * 0.5); if( current.rSpeed < 0 ) current.rSpeed = 0; } if( current.rSpeed < 0 ) { current.rSpeed += (float)(TICK * 0.5); if( current.rSpeed > 0 ) current.rSpeed = 0; } if( tastatur[ T_ROT_R ] ) { Vertex hp; Vertex mv; float r; double treibstoff = 1.5 * ( ( current.wendigkeit + team->wendigkeit ) / 5 ) * tv * ( 100 / ( current.antriebEffizienz + team->antriebEffizienz ) ); current.treibstoffVerbraucht += treibstoff; double factor = 1; if( treibstoff > current.energie ) factor = current.energie / treibstoff; if( ship->zModel()->calcHitPoint( stL, kL * (float)( current.wendigkeit + team->wendigkeit ), "ship", hp, mv, r ) ) { current.rSpeed += r * (float)TICK * (float)factor; current.speed += ( Vec2 )mv.rotation( (float)current.rotation ) * (float)TICK * factor; } current.energie -= treibstoff * factor; } if( tastatur[ T_ROT_L ] ) { Vertex hp; Vertex mv; float r; double treibstoff = 1.5 * ( ( current.wendigkeit + team->wendigkeit ) / 5 ) * tv * ( 100 / ( current.antriebEffizienz + team->antriebEffizienz ) ); current.treibstoffVerbraucht += treibstoff; double factor = 1; if( treibstoff > current.energie ) factor = current.energie / treibstoff; if( ship->zModel()->calcHitPoint( stR, kR * (float)( current.wendigkeit + team->wendigkeit ), "ship", hp, mv, r ) ) { current.rSpeed += r * (float)TICK * (float)factor; current.speed += ( Vec2 )mv.rotation( (float)current.rotation ) * (float)TICK * factor; } current.energie -= treibstoff * factor; } current.rotation += current.rSpeed * (float)TICK; ship->setDrehung( (float)current.rotation ); if( current.speed.x || current.speed.y ) current.pos += current.speed * tv; Vec2< int > gr = zMap->getSize(); while( current.pos.x < 0 ) current.pos.x += gr.x; while( current.pos.y < 0 ) current.pos.y += gr.y; while( current.pos.x >= gr.x ) current.pos.x -= gr.x; while( current.pos.y >= gr.y ) current.pos.y -= gr.y; ship->setPosition( current.pos ); if( !current.energieAbk ) { if( current.energie != ( current.maxEnergie + team->maxEnergie ) ) ret = 1; current.energie += ( current.akkuLeistung + team->akkuLeistung ) * tv; if( current.energie > ( current.maxEnergie + team->maxEnergie ) ) current.energie = ( current.maxEnergie + team->maxEnergie ); } if( !current.repAbk ) { if( current.stabilität != ( current.maxStabilität + team->maxStabilität ) ) ret = 1; current.stabilität += ( current.reparatur + team->reparatur ) * tv; if( current.stabilität > ( current.maxStabilität + team->maxStabilität ) ) current.stabilität = ( current.maxStabilität + team->maxStabilität ); } current.zeitAmLeben += tv; } else { current.zeitTod += tv; current.spielZeit++; } } return ret; } void Spieler::render( Bild &zRObj ) { if( !current.amLeben ) return; ship->render( zRObj ); } void Spieler::renderLeben( Bild &zRObj ) { if( !team || !current.amLeben ) return; nText->setPosition( ship->getPosition() - Punkt( 76, (int)( ship->zModel()->maxP.y * ship->getSize() ) + 30 ) ); nText->render( zRObj ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 4, 150, team->farbe ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 25, 150, team->farbe ); int l = (int)( current.stabilität * 100 / ( current.maxStabilität + team->maxStabilität ) * 1.5 + 0.5 ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 1, l, 0xFF00FF00 ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 2, l, 0xFF00FF00 ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 3, l, 0xFF00FF00 ); int e = (int)( current.energie * 100 / ( current.maxEnergie + team->maxEnergie ) * 1.5 + 0.5 ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 26, e, 0xFF0000FF ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 27, e, 0xFF0000FF ); zRObj.drawLinieH( nText->getX() + 1, nText->getY() + 28, e, 0xFF0000FF ); int e2 = (int)( ( current.energie - calculateLaserCost() ) * 100 / ( current.maxEnergie + team->maxEnergie ) * 1.5 + 0.5 ); if( e2 > 0 ) { zRObj.drawLinieV( nText->getX() + e2, nText->getY() + 26, 3, 0xFFFFFFFF ); zRObj.drawLinieV( nText->getX() + e2 + 1, nText->getY() + 26, 3, 0xFFFFFFFF ); } } void Spieler::renderMinimap( Bild &zRObj, Karte *zMap, int thisSpielerNummer ) { if( !team || !current.amLeben ) return; int x = (int)( ( current.pos.x / zMap->getSize().x ) * 250 + 0.5 ) - 2; int y = (int)( ( current.pos.y / zMap->getSize().y ) * 250 + 0.5 ) - 2; if( sNum == thisSpielerNummer ) zRObj.fillCircle( x + 2, y + 2, 4, 0xFFFFFFFF ); zRObj.fillRegion( x, y, 4, 4, team->farbe ); zRObj.fillRegion( x + 1, y + 1, 2, 2, current.farbe ); } void Spieler::setSkill( int art ) { skillPunkte--; switch( art ) { case 0: // Max Stabilität current.maxStabilität += 10; current.stabilität += 10; team->maxStabilität = team->getMaxStabilitätBonus(); break; case 1: // Max Energie current.maxEnergie += 10; team->maxEnergie = team->getMaxEnergieBonus(); break; case 2: // Reparatur current.reparatur += 0.15; team->reparatur = team->getReperaturBonus(); break; case 3: // Laser Intensität current.laserIntensität += 3; team->laserIntensität = team->getLaserIntensitätBonus(); break; case 4: // Laser Effizienz current.laserEffizienz += 1; team->laserEffizienz = team->getLaserEffizienzBonus(); break; case 5: // Laser Tempo current.laserTempo += 20; team->laserTempo = team->getLaserTempoBonus(); break; case 6: // Beschleunigung current.beschleunigung += 1; team->beschleunigung = team->getBeschleunigungBonus(); break; case 7: // Wendigkeit current.wendigkeit += 0.25; team->wendigkeit = team->getWendigkeitBonus(); break; case 8: // Netzwerk current.netzwerk += 1; team->maxStabilität = team->getMaxStabilitätBonus(); team->maxEnergie = team->getMaxEnergieBonus(); team->reparatur = team->getReperaturBonus(); team->laserIntensität = team->getLaserIntensitätBonus(); team->laserEffizienz = team->getLaserEffizienzBonus(); team->laserTempo = team->getLaserTempoBonus(); team->beschleunigung = team->getBeschleunigungBonus(); team->wendigkeit = team->getWendigkeitBonus(); team->akkuLeistung = team->getAkkuLeistungBonus(); team->antriebEffizienz = team->getAntriebEffizienzBonus(); break; case 9: // Akkuleistung current.akkuLeistung += 0.12; team->akkuLeistung = team->getAkkuLeistungBonus(); break; case 10: // Antrieb Effizienz current.antriebEffizienz += 10; team->antriebEffizienz = team->getAntriebEffizienzBonus(); break; } } void Spieler::nimmSchaden( double intensität ) { current.stabilität -= intensität; current.schadenBekommen += intensität; current.repAbk = 2; } void Spieler::calcDeadPlayerObject( Laser *zSchuss ) { Vertex hp; Vertex speed; Polygon2D a; Polygon2D b; Punkt pa; Punkt pb; float rot; if( ship->zModel()->calcHitPoint( ( ( zSchuss->getPos() - zSchuss->getSpeed() ) - ship->getPosition() ).rotation( -ship->getDrehung() ) / ship->getSize(), Vertex( zSchuss->getSpeed() ).rotation( -ship->getDrehung() ), "ship", hp, speed, rot ) ) { ship->zModel()->split( hp, speed.rotation( -ship->getDrehung() ) * 0.1f, "ship", a, b, pa, pb, []() { return rand() / (double)RAND_MAX; } ); hp = ( hp * ship->getSize() ).rotation( ship->getDrehung() ) + ship->getPosition(); pa += ship->getPosition(); pb += ship->getPosition(); Array< Polygon2D > *npaA = new Array< Polygon2D >(); npaA->add( a ); Model2DData *npdA = new Model2DData(); npdA->erstelleModell( npaA ); Array< Polygon2D > *npaB = new Array< Polygon2D >(); npaB->add( b ); Model2DData *npdB = new Model2DData(); npdB->erstelleModell( npaB ); if( deadPlayer ) deadPlayer->release(); deadPlayer = new DeadPlayer( npdA, npdB, pa, pb, current.speed * ( rand() / (double)RAND_MAX ), current.speed * ( rand() / (double)RAND_MAX), ship->getDrehung(), ship->getDrehung(), current.rSpeed * (rand() / (float)RAND_MAX), current.rSpeed * (rand() / (float)RAND_MAX), textur ); } } void Spieler::machSchaden( double intensität ) { current.schadenGemacht += intensität; current.treffer++; } void Spieler::addKill() { current.kills++; current.punkte++; skillPunkte += 2; current.maxReinkAbk--; if( current.maxReinkAbk < 5 ) current.maxReinkAbk = 5; } DeadPlayer *Spieler::sterben() { current.amLeben = 0; current.tode++; current.stabilität = 0; current.reinkAbk += current.maxReinkAbk; current.maxReinkAbk++; current.punkte--; return deadPlayer ? deadPlayer->getThis() : 0; } void Spieler::wiederbelebung() { current.pos = current.startPos; current.reinkAbk = current.maxReinkAbk * 2; current.energie = current.maxEnergie + team->maxEnergie; current.stabilität = current.maxStabilität + team->maxStabilität; current.schussAbk = 0; current.energieAbk = 0; current.repAbk = 0; current.speed = Vec2< double >( 0, 0 ); current.rotation = 0; current.rSpeed = 0; ship->setDrehung( (float)current.rotation ); ship->setPosition( current.pos ); for( int i = 0; i < T_MAX; i++ ) tastatur[ i ] = 0; flammenM->setAnimation( -1 ); flammenL->setAnimation( -1 ); flammenR->setAnimation( -1 ); current.amLeben = 1; } void Spieler::resetToSaveTime( int t, Karte *zMap ) { if( last.spielZeit > t ) return; // this should never be possible current = last; tick( t, zMap ); } void Spieler::resetToGameTime( int t, Karte *zMap ) { last = current; tick( t, zMap ); } void Spieler::hatGeschossen() { current.energie -= calculateLaserCost(); current.schussAbk = 1; current.energieAbk = 1.5; current.schüsse++; } // constant Vec2< double > Spieler::getSpeed() const { return current.speed; } int Spieler::getAccountId() const { return accountId; } Text *Spieler::getName() const { return name ? name->getThis() : 0; } Text *Spieler::zName() const { return name; } bool Spieler::hatSkill() const { return skillPunkte != 0; } bool Spieler::istAmLeben() const { return current.amLeben; } // Statistik Werte int Spieler::getSpielerNummer() const { return sNum; } Team *Spieler::zTeam() const { return team; } int Spieler::getSpielerFarbe() const { return current.farbe; } int Spieler::getSchadenBekommen() const { return (int)current.schadenBekommen; } int Spieler::getSchadenGemacht() const { return (int)current.schadenGemacht; } int Spieler::getTreibstoffVerbraucht() const { return (int)current.treibstoffVerbraucht; } int Spieler::getSchüsse() const { return current.schüsse; } int Spieler::getTreffer() const { return current.treffer; } int Spieler::getPunkte() const { return current.punkte; } int Spieler::getKills() const { return current.kills; } int Spieler::getTode() const { return current.tode; } int Spieler::getZeitAmLeben() const { return (int)current.zeitAmLeben; } int Spieler::getZeitTod() const { return (int)current.zeitTod; } Punkt Spieler::getPos() const { return (Punkt)current.pos; } double Spieler::getTeamMaxEnergieBonus() const { return current.maxEnergie / 100 * current.netzwerk; } double Spieler::getTeamMaxStabilitätBonus() const { return current.maxStabilität / 100 * current.netzwerk; } double Spieler::getTeamReparaturBonus() const { return current.reparatur / 100 * current.netzwerk; } double Spieler::getTeamLaserIntensitätBonus() const { return current.laserIntensität / 100 * current.netzwerk; } double Spieler::getTeamLaserEffizienzBonus() const { return current.laserEffizienz / 100 * current.netzwerk; } double Spieler::getTeamAkkuLeistungBonus() const { return current.akkuLeistung / 100 * current.netzwerk; } double Spieler::getTeamLaserTempoBonus() const { return current.laserTempo / 100 * current.netzwerk; } double Spieler::getTeamBeschleunigungBonus() const { return current.beschleunigung / 100 * current.netzwerk; } double Spieler::getTeamWendigkeitBonus() const { return current.wendigkeit / 100 * current.netzwerk; } double Spieler::getTeamAntriebEffizienzBonus() const { return current.antriebEffizienz / 100 * current.netzwerk; } // Reference Counting Spieler *Spieler::getThis() { ref++; return this; } Spieler *Spieler::release() { ref--; if( !ref ) delete this; return 0; }