Spiel.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. #include "Spiel.h"
  2. #define TICK 0.03333333
  3. // Konstruktor
  4. Spiel::Spiel()
  5. {
  6. isRunning = 0;
  7. log = 0;
  8. spielerAnzahl = 0;
  9. zAccounts = 0;
  10. spielId = 0;
  11. karteId = 0;
  12. pause = 0;
  13. gameTicks = 0;
  14. ende = 1;
  15. stat = new Statistik();
  16. ref = 1;
  17. }
  18. // Destruktor
  19. Spiel::~Spiel()
  20. {
  21. stat->release();
  22. if( psqldb )
  23. psqldb->release();
  24. }
  25. // nicht constant
  26. void Spiel::setPSQLK( SSDatenbankV *psqldb )
  27. {
  28. if( this->psqldb )
  29. this->psqldb->release();
  30. this->psqldb = psqldb;
  31. stat->setPSQLDB( psqldb->getThis() );
  32. }
  33. // call 1
  34. void Spiel::setSpielId( int id )
  35. {
  36. spielId = id;
  37. stat->setSpielId( id );
  38. }
  39. // call 2
  40. void Spiel::setKarteId( int karteId )
  41. {
  42. this->karteId = karteId;
  43. stat->setKarteId( karteId );
  44. }
  45. // call 3
  46. void Spiel::setTempPfad( char *pfad )
  47. {
  48. mapPfad = pfad;
  49. mapPfad += "/";
  50. }
  51. // call 3.5
  52. void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
  53. {
  54. this->zAccounts = zAccounts->getThis();
  55. spielerAnzahl = anzahl;
  56. }
  57. // call 4
  58. void Spiel::setKlients( int anzahl, RCArray< SSKlientV > *zKlients )
  59. {
  60. this->zKlients = zKlients->getThis();
  61. }
  62. // call 5
  63. void Spiel::setSpielerNummern( int anzahl, Array< int > *spielerNummern )
  64. {
  65. MapReader *reader = new MapReader( karteId, psqldb->getThis(), mapPfad );
  66. reader->ladeKarte( this );
  67. reader->release();
  68. for( int i = 0; i < anzahl; i++ )
  69. {
  70. for( auto s = spieler.getIterator(); s; s++ )
  71. {
  72. if( s->getSpielerNummer() == spielerNummern->get( i ) )
  73. {
  74. s->setAccount( zAccounts->get( i ) );
  75. s->setKlient( new Klient( zKlients->get( i ) ) );
  76. break;
  77. }
  78. }
  79. }
  80. zAccounts = zAccounts->release();
  81. zKlients = zKlients->release();
  82. stat->setTeams( spielerAnzahl, &teams );
  83. stat->setSpieler( spielerAnzahl, &spieler );
  84. }
  85. // call 6
  86. void Spiel::run()
  87. {
  88. log = new Datei();
  89. Text *pfad = new Text( "../spiel log/" );
  90. pfad->append( spielId );
  91. pfad->append( "/verlauf.ksggl" );
  92. log->setDatei( pfad );
  93. log->remove();
  94. log->erstellen();
  95. log->open( Datei::Style::schreiben );
  96. time_t t;
  97. time( &t );
  98. srand( (unsigned int)t );
  99. log->schreibe( (char *)& spielerAnzahl, 4 );
  100. for( int i = 0; i < spielerAnzahl; i++ )
  101. {
  102. Spieler *tmp = spieler.z( i );
  103. if( tmp && tmp->zKlient() )
  104. {
  105. tmp->zKlient()->sendeInit( &spieler, -1 );
  106. log->schreibe( (char *)& i, 4 );
  107. int sNum = tmp->getSpielerNummer();
  108. log->schreibe( (char *)& sNum, 4 );
  109. tmp->zKlient()->sendeSpielerNummer( sNum, -1 );
  110. Text * name = psqldb->getAccountRufName( tmp->getAccountId() );
  111. char len = (char)( name ? name->getLength() : 0 );
  112. log->schreibe( &len, 1 );
  113. if( len )
  114. log->schreibe( name->getText(), len );
  115. if( name )
  116. name->release();
  117. }
  118. }
  119. __int64 randSeed = randG.getSeed();
  120. log->schreibe( (char *)& randSeed, 8 );
  121. Array< char > spielerStatus;
  122. ZeitMesser * zeit = new ZeitMesser();
  123. zeit->messungStart();
  124. isRunning = 1;
  125. ende = 0;
  126. double ausgleich = 0;
  127. double sZ = 0;
  128. gameTicks = -1;
  129. for( int i = 0; i < spielerAnzahl; i++ )
  130. {
  131. Spieler *tmp = spieler.z( i );
  132. if( tmp && tmp->zKlient() )
  133. tmp->zKlient()->sendeStart( gameTicks );
  134. }
  135. double rZeit = 0;
  136. while( !ende )
  137. {
  138. zeit->messungEnde();
  139. zeit->messungStart();
  140. double z = zeit->getSekunden();
  141. ausgleich += TICK - z;
  142. if( ausgleich > 0 )
  143. Sleep( (int)( ausgleich * 1000 ) );
  144. rZeit += z;
  145. while( sZ + TICK < rZeit && !ende )
  146. {
  147. c.lock();
  148. sZ += TICK;
  149. gameTicks++;
  150. char ch = 0;
  151. log->schreibe( &ch, 1 );
  152. tick( TICK );
  153. c.unlock();
  154. }
  155. }
  156. zeit->messungEnde();
  157. zeit->release();
  158. for( int i = 0; i < spielerAnzahl; i++ )
  159. {
  160. if( spieler.z( i ) && spieler.z( i )->zKlient() )
  161. {
  162. if( !spieler.z( i )->zTeam()->getPunkte() )
  163. {
  164. spielerStatus.set( 1, i ); // Datenbank Verloren
  165. spieler.z( i )->zKlient()->sendeSpielEnde( 0, 0 );
  166. }
  167. else
  168. {
  169. spielerStatus.set( 2, i ); // Datenbank Gewonnen
  170. spieler.z( i )->zKlient()->sendeSpielEnde( 1, 0 );
  171. }
  172. }
  173. if( spieler.z( i ) && ( !spieler.z( i )->zKlient() || !spieler.z( i )->zKlient()->istOnline() ) )
  174. spielerStatus.set( 3, i );
  175. }
  176. psqldb->setSpielStatusBeendet( spielId, 5 );
  177. for( int i = 0; i < spielerAnzahl; i++ )
  178. {
  179. Spieler *tmp = spieler.z( i );
  180. if( tmp )
  181. {
  182. psqldb->setSpielSpielerStatus( spielId, tmp->getAccountId(), tmp->getPunkte(), spielerStatus.get( i ) );
  183. psqldb->addSpielerStatistik( tmp->getAccountId(), spielId );
  184. }
  185. }
  186. log->close();
  187. log = log->release();
  188. isRunning = 0;
  189. }
  190. // call 7
  191. void Spiel::klientOffline( int accountId )
  192. {
  193. for( int i = 0; i < spielerAnzahl; i++ )
  194. {
  195. if( spieler.z( i )->getAccountId() == accountId )
  196. spieler.z( i )->zKlient()->offline();
  197. }
  198. }
  199. void Spiel::klientOnline( int accountId, SSKlientV * zKlient )
  200. {
  201. for( int i = 0; i < spielerAnzahl; i++ )
  202. {
  203. if( spieler.z( i )->getAccountId() == accountId )
  204. {
  205. c.lock();
  206. Spieler *s = spieler.z( i );
  207. Klient *tmp = s->zKlient();
  208. tmp->online( zKlient );
  209. tmp->sendeSpielerNummer( s->getSpielerNummer(), 0 );
  210. //--------------------------
  211. c.unlock();
  212. }
  213. }
  214. }
  215. void Spiel::nachricht( int accountId, int len, char *bytes )
  216. {
  217. if( !isRunning )
  218. return;
  219. c.lock();
  220. if( ende )
  221. {
  222. c.unlock();
  223. return;
  224. }
  225. char *msgBeg = bytes;
  226. int msgLen = len;
  227. int msgAccount = accountId;
  228. bool saveMSG = 1;
  229. len--;
  230. switch( *bytes )
  231. {
  232. case 0: // key press
  233. bytes++;
  234. len--;
  235. for( int i = 0; i < spielerAnzahl; i++ )
  236. {
  237. Spieler *tmp = spieler.z( i );
  238. if( tmp && tmp->getAccountId() == accountId )
  239. {
  240. if( !tmp->setTastenStand( *bytes, 1 ) )
  241. {
  242. saveMSG = 0;
  243. break;
  244. }
  245. for( int j = 0; j < spielerAnzahl; j++ )
  246. {
  247. Spieler *s = spieler.z( j );
  248. if( s && s->zKlient() )
  249. s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 1, gameTicks );
  250. }
  251. break;
  252. }
  253. }
  254. break;
  255. case 1: // key release
  256. bytes++;
  257. len--;
  258. for( int i = 0; i < spielerAnzahl; i++ )
  259. {
  260. Spieler *tmp = spieler.z( i );
  261. if( tmp && tmp->getAccountId() == accountId )
  262. {
  263. if( !tmp->setTastenStand( *bytes, 0 ) )
  264. {
  265. saveMSG = 0;
  266. break;
  267. }
  268. for( int j = 0; j < spielerAnzahl; j++ )
  269. {
  270. Spieler *s = spieler.z( j );
  271. if( s && s->zKlient() )
  272. s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), *bytes, 0, gameTicks );
  273. }
  274. break;
  275. }
  276. }
  277. break;
  278. case 3: // chat Nachricht
  279. if( 1 )
  280. {
  281. bytes++;
  282. Text *txt = psqldb->getAccountRufName( accountId );
  283. txt->append( ": " );
  284. txt->append( bytes, len );
  285. for( int i = 0; i < spielerAnzahl; i++ )
  286. {
  287. Spieler *tmp = spieler.z( i );
  288. if( tmp && tmp->zKlient() )
  289. tmp->zKlient()->sendeChatNachricht( txt->getText(), gameTicks );
  290. }
  291. txt->release();
  292. len = 0;
  293. }
  294. break;
  295. default:
  296. saveMSG = 0;
  297. }
  298. if( len )
  299. {
  300. // error
  301. }
  302. if( log && log->istOffen() && saveMSG )
  303. {
  304. char c = 1;
  305. log->schreibe( &c, 1 );
  306. int spielerNum = 0;
  307. for( int i = 0; i < spielerAnzahl; i++ )
  308. {
  309. Spieler *tmp = spieler.z( i );
  310. if( tmp && tmp->getAccountId() == msgAccount )
  311. {
  312. spielerNum = tmp->getSpielerNummer();
  313. break;
  314. }
  315. }
  316. log->schreibe( (char *)& spielerNum, 4 );
  317. short l = (short)msgLen;
  318. log->schreibe( (char *)& l, 2 );
  319. log->schreibe( msgBeg, l );
  320. }
  321. c.unlock();
  322. }
  323. void Spiel::setPausiert( bool pausiert )
  324. {
  325. this->pause = pausiert;
  326. }
  327. void Spiel::tick( double zeit )
  328. {
  329. // spieler bewegungen
  330. for( auto s = spieler.getIterator(); s; s++ )
  331. {
  332. s->tick( zeit );
  333. for( auto b = barieren.getIterator(); b; b++ )
  334. { // spieler - bariere intersection
  335. if( b->hatStyle( Bariere::Style::Aktiv ) && ( b->zTeam() != s->zTeam() ) && b->intersectsWith( s ) )
  336. s->tick( -zeit );
  337. else if( s->getX() < 0 || s->getY() < 0 || s->getX() + s->getWidth() >= mapSize.x || s->getY() + s->getHeight() >= mapSize.y )
  338. s->tick( -zeit );
  339. }
  340. }
  341. // barieren bewegung
  342. for( auto b = barieren.getIterator(); b; b++ )
  343. b->tick( zeit );
  344. // geschoss bewegung
  345. for( int i = 0; i < shots.getEintragAnzahl(); i++ )
  346. {
  347. Geschoss *g = shots.z( i );
  348. g->tick( zeit );
  349. bool removed = 0;
  350. // geschoss - bariere intersection
  351. bool intersectsWithBariere = 0;
  352. for( auto b = barieren.getIterator(); b; b++ )
  353. {
  354. if( b->hatStyle( Bariere::Style::Aktiv ) && b->intersectsWith( g ) )
  355. {
  356. intersectsWithBariere = 1;
  357. break;
  358. }
  359. }
  360. if( intersectsWithBariere || g->getX() < 0 || g->getY() < 0 || g->getX() + g->getWidth() >= mapSize.x || g->getY() + g->getHeight() >= mapSize.y )
  361. {
  362. g->tick( -zeit );
  363. switch( g->getTyp() )
  364. {
  365. case GESCHOSS_PFEIL:
  366. shots.remove( i );
  367. i--;
  368. removed = 1;
  369. break;
  370. case GESCHOSS_KUGEL:
  371. case GESCHOSS_DRACHENAUGE:
  372. g->invertDirection();
  373. break;
  374. case GESCHOSS_FEUERBALL:
  375. if( intersectsWithBariere )
  376. {
  377. feuer.add( new FeuerballTreffer( g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
  378. shots.remove( i );
  379. i--;
  380. removed = 1;
  381. }
  382. else
  383. g->invertDirection();
  384. break;
  385. }
  386. }
  387. if( !removed )
  388. { // geschoss - tunnel intersection
  389. for( auto t = tunnel.getIterator(); t; t++ )
  390. {
  391. if( t->istAktiv() && t->intersectsWith( g ) )
  392. {
  393. g->setX( g->getX() + t->getZielX() - t->getX() );
  394. g->setY( g->getY() + t->getZielY() - t->getY() );
  395. }
  396. }
  397. // geschoss - schalter intersection
  398. if( g->getTyp() == GESCHOSS_PFEIL )
  399. {
  400. for( auto s = schalter.getIterator(); s; s++ )
  401. {
  402. if( s->isAktive() && s->intersectsWith( g ) )
  403. {
  404. shots.remove( i );
  405. i--;
  406. removed = 1;
  407. activateShalter( s->getId() );
  408. }
  409. }
  410. }
  411. if( !removed )
  412. {
  413. // geschoss - umlenkung intersection
  414. if( g->getTyp() != GESCHOSS_PFEIL )
  415. {
  416. for( auto u = umlenkungen.getIterator(); u; u++ )
  417. {
  418. if( u->isAktive() && g->getTyp() != GESCHOSS_PFEIL && u->intersectsWith( g ) )
  419. {
  420. g->setRichtung( u->getRichtung() );
  421. u->addBenutzt();
  422. }
  423. }
  424. }
  425. // geschoss - spieler intersection
  426. for( auto s = spieler.getIterator(); s; s++ )
  427. {
  428. if( s->istAmLeben() && s != g->zBesitzer() )
  429. {
  430. switch( g->getTyp() )
  431. {
  432. case GESCHOSS_PFEIL:
  433. case GESCHOSS_KUGEL:
  434. s->nimmSchaden( 100 + ( g->zBesitzer() ? g->zBesitzer()->getSchadenBonus() : 0 ) );
  435. if( g->zBesitzer() )
  436. {
  437. g->zBesitzer()->addGemachterSchaden( 100 + g->zBesitzer()->getSchadenBonus() );
  438. if( !s->istAmLeben() )
  439. g->zBesitzer()->addKill();
  440. }
  441. case GESCHOSS_DRACHENAUGE:
  442. s->addEffekt( new DrachenAugeEffekt( g->zBesitzer(), s._, 10 ) );
  443. break;
  444. case GESCHOSS_FEUERBALL:
  445. feuer.add( new FeuerballTreffer( g->getX() - 70, g->getY() - 70, g->getBesitzer(), 10 ) );
  446. }
  447. if( g->zBesitzer() )
  448. g->zBesitzer()->addTreffer();
  449. s->addGetroffen();
  450. shots.remove( i );
  451. i--;
  452. removed = 1;
  453. }
  454. }
  455. }
  456. }
  457. }
  458. // Drop Ticks
  459. for( auto d = drops.getIterator(); d; d++ )
  460. d->tick( zeit, this );
  461. // Timer Ticks
  462. for( auto t = timer.getIterator(); t; t++ )
  463. t->tick( zeit, this );
  464. // Umlenkung Ticks
  465. for( auto u = umlenkungen.getIterator(); u; u++ )
  466. u->tick( zeit );
  467. // Base Ticks
  468. for( auto b = basen.getIterator(); b; b++ )
  469. b->tick( zeit, this );
  470. // aktive trigger Ticks
  471. for( int i = 0; i < triggerRuns.getEintragAnzahl(); i++ )
  472. {
  473. if( !triggerRuns.z( i )->runNext( zeit ) )
  474. {
  475. triggerRuns.remove( i );
  476. i--;
  477. }
  478. }
  479. }
  480. void Spiel::addVariable( const char *name, Variable * var )
  481. {
  482. bool found = 0;
  483. for( auto v = variablen.getIterator(); v; v++ )
  484. {
  485. if( v->zName()->istGleich( name ) )
  486. {
  487. found = 1;
  488. break;
  489. }
  490. }
  491. if( !found )
  492. variablen.add( new VarPointer( name, var ) );
  493. else
  494. var->release();
  495. }
  496. void Spiel::setVariable( const char *name, Variable * var )
  497. {
  498. bool found = 0;
  499. for( auto v = variablen.getIterator(); v; v++ )
  500. {
  501. if( v->zName()->istGleich( name ) )
  502. {
  503. v->setVariable( var );
  504. break;
  505. }
  506. }
  507. if( !found )
  508. var->release();
  509. }
  510. void Spiel::addTeam( Team * team )
  511. {
  512. teams.add( team );
  513. }
  514. void Spiel::addSpieler( Spieler * spieler )
  515. {
  516. this->spieler.add( spieler );
  517. }
  518. void Spiel::addBariere( Bariere * bariere )
  519. {
  520. barieren.add( bariere );
  521. }
  522. void Spiel::addBase( Base * base )
  523. {
  524. basen.add( base );
  525. }
  526. void Spiel::addDrop( Drop * drop )
  527. {
  528. drops.add( drop );
  529. }
  530. void Spiel::addGegenstand( Gegenstand * gegenstand )
  531. {
  532. items.add( gegenstand );
  533. }
  534. void Spiel::addGeschoss( Geschoss * geschoss )
  535. {
  536. shots.add( geschoss );
  537. }
  538. void Spiel::addSchalter( Schalter * schalter )
  539. {
  540. this->schalter.add( schalter );
  541. }
  542. void Spiel::addSchiene( Schiene * schiene )
  543. {
  544. schienen.add( schiene );
  545. }
  546. void Spiel::addTimer( Timer * timer )
  547. {
  548. this->timer.add( timer );
  549. }
  550. void Spiel::addTunnel( Tunnel * tunnel )
  551. {
  552. this->tunnel.add( tunnel );
  553. }
  554. void Spiel::addUmlenkung( Umlenkung * umlenkung )
  555. {
  556. umlenkungen.add( umlenkung );
  557. }
  558. void Spiel::addTrigger( Trigger * trigger )
  559. {
  560. this->trigger.add( trigger );
  561. }
  562. void Spiel::addTriggerRun( TriggerRun * tRun )
  563. {
  564. triggerRuns.add( tRun );
  565. }
  566. Team *Spiel::getTeam( int id ) const
  567. {
  568. for( auto t = teams.getIterator(); t; t++ )
  569. {
  570. if( t->getTeamNummer() == id )
  571. return (Team *)t->getThis();
  572. }
  573. return 0;
  574. }
  575. Variable *Spiel::getVariable( const char *name ) const
  576. {
  577. for( auto v = variablen.getIterator(); v; v++ )
  578. {
  579. if( v->zName()->istGleich( name ) )
  580. return v->getVariable();
  581. }
  582. return 0;
  583. }
  584. Variable *Spiel::zVariable( const char *name ) const
  585. {
  586. for( auto v = variablen.getIterator(); v; v++ )
  587. {
  588. if( v->zName()->istGleich( name ) )
  589. return v->zVariable();
  590. }
  591. return 0;
  592. }
  593. bool Spiel::istPausiert() const
  594. {
  595. return pause;
  596. }
  597. // constant
  598. StatistikV *Spiel::getStatistik() const
  599. {
  600. return stat->getThis();
  601. }
  602. // Reference Counting
  603. SpielKlasse *Spiel::getThis()
  604. {
  605. ref++;
  606. return this;
  607. }
  608. SpielKlasse *Spiel::release()
  609. {
  610. if( !--ref )
  611. delete this;
  612. return 0;
  613. }