#include "amxxmodule.h" #include "CRank.h" #include "rank.h" // ***************************************************** // class Stats // ***************************************************** Stats::Stats(){ hits = shots = damage = hs = tks = kills = deaths = bDefusions = bDefused = bPlants = bExplosions = 0; memset( bodyHits , 0 ,sizeof( bodyHits ) ); } void Stats::commit(Stats* a){ hits += a->hits; shots += a->shots; damage += a->damage; hs += a->hs; tks += a->tks; kills += a->kills; deaths += a->deaths; bDefusions += a->bDefusions; bDefused += a->bDefused; bPlants += a->bPlants; bExplosions += a->bExplosions; for(int i = 1; i < 8; ++i) bodyHits[i] += a->bodyHits[i]; } // ***************************************************** // class RankSystem // ***************************************************** RankSystem::RankStats::RankStats( const char* uu, const char* nn, RankSystem* pp ) { name = 0; namelen = 0; unique = 0; uniquelen = 0; score = 0; parent = pp; id = ++parent->rankNum; next = prev = 0; setName( nn ); setUnique( uu ); } RankSystem::RankStats::~RankStats() { delete[] name; delete[] unique; --parent->rankNum; } void RankSystem::RankStats::setName( const char* nn ) { delete[] name; namelen = strlen(nn) + 1; name = new char[namelen]; if ( name ) strcpy( name , nn ); else namelen = 0; } void RankSystem::RankStats::setUnique( const char* nn ) { delete[] unique; uniquelen = strlen(nn) + 1; unique = new char[uniquelen]; if ( unique ) strcpy( unique , nn ); else uniquelen = 0; } RankSystem::RankSystem() { head = 0; tail = 0; rankNum = 0; calc.code = 0; } RankSystem::~RankSystem() { clear(); } void RankSystem::put_before( RankStats* a, RankStats* ptr ){ a->next = ptr; if ( ptr ){ a->prev = ptr->prev; ptr->prev = a; } else{ a->prev = head; head = a; } if ( a->prev ) a->prev->next = a; else tail = a; } void RankSystem::put_after( RankStats* a, RankStats* ptr ) { a->prev = ptr; if ( ptr ){ a->next = ptr->next; ptr->next = a; } else{ a->next = tail; tail = a; } if ( a->next ) a->next->prev = a; else head = a; } void RankSystem::unlink( RankStats* ptr ){ if (ptr->prev) ptr->prev->next = ptr->next; else tail = ptr->next; if (ptr->next) ptr->next->prev = ptr->prev; else head = ptr->prev; } void RankSystem::clear(){ while( tail ){ head = tail->next; delete tail; tail = head; } } bool RankSystem::loadCalc(const char* filename, char* error) { if ((MF_LoadAmxScript(&calc.amx,&calc.code,filename,error)!=AMX_ERR_NONE)|| (MF_AmxAllot(&calc.amx, 8 , &calc.amxAddr1, &calc.physAddr1)!=AMX_ERR_NONE)|| (MF_AmxAllot(&calc.amx, 8 , &calc.amxAddr2, &calc.physAddr2)!=AMX_ERR_NONE)|| (MF_AmxFindPublic(&calc.amx,"get_score",&calc.func)!=AMX_ERR_NONE)){ LOG_CONSOLE( PLID, "Couldn't load plugin (file \"%s\")",filename); MF_UnloadAmxScript(&calc.amx, &calc.code); return false; } return true; } void RankSystem::unloadCalc() { MF_UnloadAmxScript(&calc.amx , &calc.code); } RankSystem::RankStats* RankSystem::findEntryInRank(const char* unique, const char* name ) { RankStats* a = head; while ( a ) { if ( strcmp( a->getUnique() ,unique ) == 0 ) return a; a = a->prev; } a = new RankStats( unique ,name,this ); if ( a == 0 ) return 0; put_after( a , 0 ); return a; } void RankSystem::updatePos( RankStats* rr , Stats* s ) { rr->addStats( s ); if ( calc.code ) { calc.physAddr1[0] = rr->kills; calc.physAddr1[1] = rr->deaths; calc.physAddr1[2] = rr->hs; calc.physAddr1[3] = rr->tks; calc.physAddr1[4] = rr->shots; calc.physAddr1[5] = rr->hits; calc.physAddr1[6] = rr->damage; calc.physAddr1[7] = rr->bDefusions; calc.physAddr1[8] = rr->bDefused; calc.physAddr1[9] = rr->bPlants; calc.physAddr1[10] = rr->bExplosions; for(int i = 1; i < 8; ++i) calc.physAddr2[i] = rr->bodyHits[i]; cell result = 0; int err; if ((err = MF_AmxExec(&calc.amx,&result, calc.func ,2,calc.amxAddr1,calc.amxAddr2 )) != AMX_ERR_NONE) LOG_CONSOLE( PLID, "Run time error %d on line %ld (plugin \"%s\")", err,calc.amx.curline,LOCALINFO("csstats_score")); rr->score = result; } else rr->score = rr->kills - rr->deaths; RankStats* aa = rr->next; while ( aa && (aa->score <= rr->score) ) { // try to nominate rr->goUp(); aa->goDown(); aa = aa->next; // go to next rank } if ( aa != rr->next ) { unlink( rr ); put_before( rr, aa ); } else { aa = rr->prev; while ( aa && (aa->score > rr->score) ) { // go down rr->goDown(); aa->goUp(); aa = aa->prev; // go to prev rank } if ( aa != rr->prev ){ unlink( rr ); put_after( rr, aa ); } } } void RankSystem::loadRank( const char* filename ) { FILE *bfp = fopen( filename , "rb" ); if ( !bfp ) return; short int i = 0; fread(&i, 1 , sizeof(short int) , bfp); if (i == RANK_VERSION) { Stats d; char unique[64], name[64]; fread(&i , 1, sizeof(short int), bfp); while( i ) { fread(name , i,sizeof(char) , bfp); fread(&i , 1, sizeof(short int), bfp); fread(unique , i,sizeof(char) , bfp); fread(&d.tks, 1,sizeof(int), bfp); fread(&d.damage, 1,sizeof(int), bfp); fread(&d.deaths, 1,sizeof(int), bfp); fread(&d.kills, 1,sizeof(int), bfp); fread(&d.shots, 1,sizeof(int), bfp); fread(&d.hits, 1,sizeof(int), bfp); fread(&d.hs, 1,sizeof(int), bfp); fread(&d.bDefusions, 1,sizeof(int), bfp); fread(&d.bDefused, 1,sizeof(int), bfp); fread(&d.bPlants, 1,sizeof(int), bfp); fread(&d.bExplosions, 1,sizeof(int), bfp); fread(d.bodyHits, 1,sizeof(d.bodyHits), bfp); fread(&i , 1, sizeof(short int), bfp); RankSystem::RankStats* a = findEntryInRank( unique , name ); if ( a ) a->updatePosition( &d ); } } fclose(bfp); } void RankSystem::saveRank( const char* filename ) { FILE *bfp = fopen(filename, "wb"); if ( !bfp ) return; short int i = RANK_VERSION; fwrite(&i, 1, sizeof(short int) , bfp); RankSystem::iterator a = front(); while ( a ) { if ( (*a).score != (1<<31) ) // score must be different than mincell { fwrite( &(*a).namelen , 1, sizeof(short int), bfp); fwrite( (*a).name , (*a).namelen , sizeof(char) , bfp); fwrite( &(*a).uniquelen , 1, sizeof(short int), bfp); fwrite( (*a).unique , (*a).uniquelen , sizeof(char) , bfp); fwrite( &(*a).tks, 1, sizeof(int), bfp); fwrite( &(*a).damage, 1, sizeof(int), bfp); fwrite( &(*a).deaths, 1, sizeof(int), bfp); fwrite( &(*a).kills, 1, sizeof(int), bfp); fwrite( &(*a).shots, 1, sizeof(int), bfp); fwrite( &(*a).hits, 1, sizeof(int), bfp); fwrite( &(*a).hs, 1, sizeof(int), bfp); fwrite( &(*a).bDefusions, 1, sizeof(int), bfp); fwrite( &(*a).bDefused, 1, sizeof(int), bfp); fwrite( &(*a).bPlants, 1, sizeof(int), bfp); fwrite( &(*a).bExplosions, 1, sizeof(int), bfp); fwrite( (*a).bodyHits, 1, sizeof((*a).bodyHits), bfp); } --a; } i = 0; fwrite( &i , 1, sizeof(short int), bfp); // null terminator fclose(bfp); }