diff --git a/dlls/ts/tsx/CMisc.cpp b/dlls/ts/tsx/CMisc.cpp index e1f44281..0b607d5f 100755 --- a/dlls/ts/tsx/CMisc.cpp +++ b/dlls/ts/tsx/CMisc.cpp @@ -36,7 +36,8 @@ // class CPlayer // ***************************************************** -void CPlayer::Disconnect(){ +void CPlayer::Disconnect() +{ if ( ignoreBots(pEdict) || !isModuleActive() ) // ignore if he is bot and bots rank is disabled or module is paused return; rank->updatePosition( &life ); diff --git a/dlls/ts/tsx/CRank.cpp b/dlls/ts/tsx/CRank.cpp index 4b856d76..0664e0b7 100755 --- a/dlls/ts/tsx/CRank.cpp +++ b/dlls/ts/tsx/CRank.cpp @@ -36,11 +36,13 @@ // ***************************************************** // class Stats // ***************************************************** -Stats::Stats(){ +Stats::Stats() +{ hits = shots = damage = hs = tks = kills = deaths = 0; memset( bodyHits , 0 ,sizeof( bodyHits ) ); } -void Stats::commit(Stats* a){ +void Stats::commit(Stats* a) +{ hits += a->hits; shots += a->shots; damage += a->damage; @@ -48,14 +50,14 @@ void Stats::commit(Stats* a){ tks += a->tks; kills += a->kills; deaths += a->deaths; - for(int i = 1; i < 8; ++i) - bodyHits[i] += a->bodyHits[i]; + 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 ) { +RankSystem::RankStats::RankStats( const char* uu, const char* nn, RankSystem* pp ) +{ name = 0; namelen = 0; unique = 0; @@ -67,77 +69,92 @@ RankSystem::RankStats::RankStats( const char* uu, const char* nn, RankSystem* pp setName( nn ); setUnique( uu ); } -RankSystem::RankStats::~RankStats() { - delete[] name; - delete[] unique; +RankSystem::RankStats::~RankStats() +{ + delete name; + delete unique; --parent->rankNum; } -void RankSystem::RankStats::setName( const char* nn ) { +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; + + if ( name ) strcpy( name , nn ); + else namelen = 0; } -void RankSystem::RankStats::setUnique( const char* nn ) { - delete[] unique; +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; + + if ( unique ) strcpy( unique , nn ); + else uniquelen = 0; } -RankSystem::RankSystem() { +RankSystem::RankSystem() +{ head = 0; tail = 0; rankNum = 0; calc.code = 0; } -RankSystem::~RankSystem() { +RankSystem::~RankSystem() +{ clear(); } -void RankSystem::put_before( RankStats* a, RankStats* ptr ){ +void RankSystem::put_before( RankStats* a, RankStats* ptr ) +{ a->next = ptr; - if ( ptr ){ + if ( ptr ) + { a->prev = ptr->prev; ptr->prev = a; } - else{ + else + { a->prev = head; head = a; } + if ( a->prev ) a->prev->next = a; else tail = a; } -void RankSystem::put_after( RankStats* a, RankStats* ptr ) { +void RankSystem::put_after( RankStats* a, RankStats* ptr ) +{ a->prev = ptr; - if ( ptr ){ + if ( ptr ) + { a->next = ptr->next; ptr->next = a; } - else{ + else + { a->next = tail; tail = a; } + if ( a->next ) a->next->prev = a; else head = a; } -void RankSystem::unlink( RankStats* ptr ){ +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 ){ +void RankSystem::clear() +{ + while( tail ) + { head = tail->next; delete tail; tail = head; @@ -149,7 +166,8 @@ bool RankSystem::loadCalc(const char* filename, char* error) if ((MF_LoadAmxScript(&calc.amx,&calc.code,filename,error,0)!=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)){ + (MF_AmxFindPublic(&calc.amx,"get_score",&calc.func)!=AMX_ERR_NONE)) + { MF_PrintSrvConsole("Couldn't load plugin (file \"%s\")",filename); MF_UnloadAmxScript(&calc.amx, &calc.code); return false; @@ -167,14 +185,16 @@ RankSystem::RankStats* RankSystem::findEntryInRank(const char* unique, const cha while ( a ) { - if ( strcmp( a->getUnique() ,unique ) == 0 ) - return 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; } @@ -182,7 +202,8 @@ void RankSystem::updatePos( RankStats* rr , Stats* s ) { rr->addStats( s ); - if ( calc.code ) { + if ( calc.code ) + { calc.physAddr1[0] = rr->kills; calc.physAddr1[1] = rr->deaths; calc.physAddr1[2] = rr->hs; @@ -190,20 +211,25 @@ void RankSystem::updatePos( RankStats* rr , Stats* s ) calc.physAddr1[4] = rr->shots; calc.physAddr1[5] = rr->hits; calc.physAddr1[6] = rr->damage; - for(int i = 1; i < 8; ++i) - calc.physAddr2[i] = rr->bodyHits[i]; + + for(int i = 1; i < 8; ++i) calc.physAddr2[i] = rr->bodyHits[i]; cell result = 0; int err; + MF_AmxPush(&calc.amx, calc.amxAddr2); MF_AmxPush(&calc.amx, calc.amxAddr1); + if ((err = MF_AmxExec(&calc.amx,&result, calc.func)) != AMX_ERR_NONE) MF_LogError(&calc.amx, err, "Fatal error calculating stats"); + rr->score = result; } else rr->score = rr->kills - rr->deaths; RankStats* aa = rr->next; - while ( aa && (aa->score <= rr->score) ) { // try to nominate + + while ( aa && (aa->score <= rr->score) ) + { // try to nominate rr->goUp(); aa->goDown(); aa = aa->next; // go to next rank @@ -216,12 +242,14 @@ void RankSystem::updatePos( RankStats* rr , Stats* s ) else { aa = rr->prev; - while ( aa && (aa->score > rr->score) ) { // go down + while ( aa && (aa->score > rr->score) ) + { // go down rr->goDown(); aa->goUp(); aa = aa->prev; // go to prev rank } - if ( aa != rr->prev ){ + if ( aa != rr->prev ) + { unlink( rr ); put_after( rr, aa ); } diff --git a/dlls/ts/tsx/MsgFunc.h b/dlls/ts/tsx/MsgFunc.h new file mode 100644 index 00000000..747021c2 --- /dev/null +++ b/dlls/ts/tsx/MsgFunc.h @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2003-2005 Twilight Suzuka + * + * This file is part of TSXMod. + * + * TS XMod is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * TS XMod is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TS XMod; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#include "amxxmodule.h" +#include "tsx.h" + +void Client_ResetHUD_End(void* mValue) +{ + if ( mPlayer->IsAlive() ) + { + mPlayer->clearStats = gpGlobals->time + 0.25f; + } + else + { + mPlayer->items = 0; + mPlayer->is_specialist = 0; + mPlayer->killingSpree = 0; + mPlayer->killFlags = 0; + mPlayer->frags = (int)mPlayer->pEdict->v.frags; + } +} + +void Client_ScoreInfo(void* mValue) +{ + static int iId; + switch(mState++) + { + case 0: + iId = *(int*)mValue; + break; + case 4: + if ( iId && (iId < 33) ) + { + GET_PLAYER_POINTER_I(iId)->teamId = *(int*)mValue; + } + break; + } +} + +void Client_WeaponInfo(void* mValue) +{ + static int wpn; + switch(mState++) + { + case 0: + wpn = *(int*)mValue; + if ( !wpn ) wpn = 36; // kung fu + mPlayer->current = wpn; + break; + case 1: + mPlayer->weapons[wpn].clip = *(int*)mValue; + break; + case 2: + mPlayer->weapons[wpn].ammo = *(int*)mValue; + break; + case 3: + mPlayer->weapons[wpn].mode = *(int*)mValue; + break; + case 4: + mPlayer->weapons[wpn].attach = *(int*)mValue; + break; + } +} + +void Client_ClipInfo(void* mValue) +{ + int iValue = *(int*)mValue; + if ( iValue < mPlayer->weapons[mPlayer->current].clip ) + { + mPlayer->saveShot(mPlayer->current); + } + mPlayer->weapons[mPlayer->current].clip = iValue; +} + +void Client_TSHealth_End(void* mValue) +{ + edict_t *enemy = mPlayer->pEdict->v.dmg_inflictor; + int damage = (int)mPlayer->pEdict->v.dmg_take; + + if ( !damage || !enemy ) return; + + int aim = 0; + int weapon = 0; + mPlayer->pEdict->v.dmg_take = 0.0; + + CPlayer* pAttacker = NULL; + if ( enemy->v.flags & (FL_CLIENT | FL_FAKECLIENT) ) + { + pAttacker = GET_PLAYER_POINTER(enemy); + weapon = pAttacker->current; + aim = pAttacker->aiming; + pAttacker->saveHit( mPlayer , weapon , damage, aim ); + } + else + { + char szCName[16]; + strcpy( szCName,STRING(enemy->v.classname) ); + + if ( szCName[0] == 'g' ) + { + if ( enemy->v.owner && enemy->v.owner->v.flags & (FL_CLIENT | FL_FAKECLIENT) ) + { + pAttacker = GET_PLAYER_POINTER(enemy->v.owner); + weapon = 24; // grenade + if ( pAttacker != mPlayer ) pAttacker->saveHit( mPlayer , weapon , damage, 0 ); + } + } + else if ( szCName[0] == 'k' ) + { + int pOwner = *( (int*)enemy->pvPrivateData + gKnifeOffset ); + + if ( FNullEnt( (edict_t*)pOwner) ) return; + + pAttacker = GET_PLAYER_POINTER( (edict_t*)pOwner ); + + weapon = 37; // throwing knife + aim = pAttacker->aiming; + pAttacker->saveHit( mPlayer , weapon , damage, aim ); + } + } + if ( !pAttacker ) pAttacker = mPlayer; + + int TA = 0; + + if ( mPlayer->teamId || is_theonemode ) + { + if ( (mPlayer->teamId == pAttacker->teamId ) && (mPlayer != pAttacker) ) TA = 1; + } + + if ( weaponData[weapon].melee ) pAttacker->saveShot(weapon); + + MF_ExecuteForward(g_damage_info, pAttacker->index, mPlayer->index, damage, weapon, aim, TA ); + + if ( mPlayer->IsAlive() ) return; + + // death + + if ( (int)pAttacker->pEdict->v.frags - pAttacker->frags == 0 ) pAttacker = mPlayer; + + int killFlags = 0; + + if ( !TA && mPlayer!=pAttacker ) + { + + int sflags = pAttacker->pEdict->v.iuser4; + + int stuntKill = 0; + int slpos = 0; + + if ( weapon == 24 ); + + else if ( sflags == 20 || sflags == 1028 || sflags == 2052 ) stuntKill = 1; + else if ( sflags == 36) slpos = 1; + + int doubleKill = 0; + + if ( gpGlobals->time - pAttacker->lastKill < 1.0 ) doubleKill = 1; + + if ( stuntKill ) killFlags |= TSKF_STUNTKILL; + + pAttacker->lastKill = gpGlobals->time; + + pAttacker->killingSpree++; + + if ( pAttacker->killingSpree == 10 ) pAttacker->is_specialist = 1; + + pAttacker->lastFrag = weaponData[weapon].bonus + 2*stuntKill; + + if ( doubleKill ) + { + pAttacker->lastFrag *= 2; + killFlags |= TSKF_DOUBLEKILL; + } + + if ( pAttacker->is_specialist ) + { + pAttacker->lastFrag *= 2; + killFlags |= TSKF_ISSPEC; + } + + if ( mPlayer->is_specialist ) + { + pAttacker->lastFrag += 5; + killFlags |= TSKF_KILLEDSPEC; + } + + pAttacker->frags += pAttacker->lastFrag; + if ( pAttacker->frags != pAttacker->pEdict->v.frags ) + { + if ( slpos ) killFlags |= TSKF_SLIDINGKILL; + else weapon = 36; + pAttacker->lastFrag += (int)pAttacker->pEdict->v.frags - pAttacker->frags; + pAttacker->frags = (int)pAttacker->pEdict->v.frags; + } + } + + pAttacker->killFlags = killFlags; + pAttacker->saveKill(mPlayer,weapon,( aim == 1 ) ? 1:0 ,TA); + MF_ExecuteForward(g_death_info, pAttacker->index, mPlayer->index, weapon, aim, TA ); + +} + +void Client_WStatus(void* mValue) +{ + switch(mState++) + { + case 1: + if ( !*(int*)mValue ) + { + mPlayer->current = 36; // fix dla wytraconej broni + } + break; + } +} + +void Client_TSCash(void* mValue) +{ + mPlayer->money = *(int*)mValue; +} + +void Client_TSSpace(void* mValue) +{ + mPlayer->space = *(int*)mValue; +} + +void Client_PwUp(void* mValue) +{ + static int iPwType; + switch(mState++){ + case 0: + iPwType = *(int*)mValue; + + switch(iPwType) + { + case TSPWUP_KUNGFU : + mPlayer->items |= TSITEM_KUNGFU; + break; + case TSPWUP_SJUMP: + mPlayer->items |= TSITEM_SUPERJUMP; + break; + default: mPlayer->PwUp = iPwType; + } + break; + case 1: + if ( iPwType != TSPWUP_KUNGFU && iPwType != TSPWUP_SJUMP ) mPlayer->PwUpValue = *(int*)mValue; + break; + } +} \ No newline at end of file diff --git a/dlls/ts/tsx/StatsNatives.h b/dlls/ts/tsx/StatsNatives.h new file mode 100644 index 00000000..81c3efe2 --- /dev/null +++ b/dlls/ts/tsx/StatsNatives.h @@ -0,0 +1,336 @@ +/* + * TSX + * Copyright (c) 2005 Twilight Suzuka + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + + +#include "amxxmodule.h" +#include "tsx.h" + +static cell AMX_NATIVE_CALL get_user_astats(AMX *amx, cell *params) /* 6 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + int attacker = params[2]; + CHECK_PLAYERRANGE(attacker); + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if (pPlayer->attackers[attacker].hits){ + cell *cpStats = MF_GetAmxAddr(amx,params[3]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[4]); + CPlayer::PlayerWeapon* stats = &pPlayer->attackers[attacker]; + cpStats[0] = stats->kills; + cpStats[1] = stats->deaths; + cpStats[2] = stats->hs; + cpStats[3] = stats->tks; + cpStats[4] = stats->shots; + cpStats[5] = stats->hits; + cpStats[6] = stats->damage; + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = stats->bodyHits[i]; + if (params[6] && attacker && stats->name ) + MF_SetAmxString(amx,params[5],stats->name,params[6]); + return 1; + } + return 0; +} + +static cell AMX_NATIVE_CALL get_user_vstats(AMX *amx, cell *params) /* 6 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + int victim = params[2]; + CHECK_PLAYERRANGE(victim); + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if (pPlayer->victims[victim].hits){ + cell *cpStats = MF_GetAmxAddr(amx,params[3]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[4]); + CPlayer::PlayerWeapon* stats = &pPlayer->victims[victim]; + cpStats[0] = stats->kills; + cpStats[1] = stats->deaths; + cpStats[2] = stats->hs; + cpStats[3] = stats->tks; + cpStats[4] = stats->shots; + cpStats[5] = stats->hits; + cpStats[6] = stats->damage; + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = stats->bodyHits[i]; + if (params[6] && victim && stats->name) + MF_SetAmxString(amx,params[5],stats->name,params[6]); + return 1; + } + return 0; +} + +static cell AMX_NATIVE_CALL get_user_wrstats(AMX *amx, cell *params) /* 4 param */ // DEC-Weapon (round) stats (end) +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + int weapon = params[2]; + if (weapon<0||weapon>=TSMAX_WEAPONS){ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid weapon id %d", weapon); + return 0; + } + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if (pPlayer->weaponsRnd[weapon].shots){ + cell *cpStats = MF_GetAmxAddr(amx,params[3]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[4]); + Stats* stats = &pPlayer->weaponsRnd[weapon]; + cpStats[0] = stats->kills; + cpStats[1] = stats->deaths; + cpStats[2] = stats->hs; + cpStats[3] = stats->tks; + cpStats[4] = stats->shots; + cpStats[5] = stats->hits; + cpStats[6] = stats->damage; + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = stats->bodyHits[i]; + return 1; + } + return 0; +} + +static cell AMX_NATIVE_CALL get_user_wstats(AMX *amx, cell *params) /* 4 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + int weapon = params[2]; + if (weapon<0||weapon>=TSMAX_WEAPONS){ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid weapon id %d", weapon); + return 0; + } + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if (pPlayer->weapons[weapon].shots){ + cell *cpStats = MF_GetAmxAddr(amx,params[3]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[4]); + CPlayer::PlayerWeapon* stats = &pPlayer->weapons[weapon]; + cpStats[0] = stats->kills; + cpStats[1] = stats->deaths; + cpStats[2] = stats->hs; + cpStats[3] = stats->tks; + cpStats[4] = stats->shots; + cpStats[5] = stats->hits; + cpStats[6] = stats->damage; + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = stats->bodyHits[i]; + return 1; + } + return 0; +} + +static cell AMX_NATIVE_CALL reset_user_wstats(AMX *amx, cell *params) /* 6 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + GET_PLAYER_POINTER_I(index)->restartStats(); + return 1; +} + +static cell AMX_NATIVE_CALL get_user_stats(AMX *amx, cell *params) /* 3 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if ( pPlayer->rank ){ + cell *cpStats = MF_GetAmxAddr(amx,params[2]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[3]); + cpStats[0] = pPlayer->rank->kills; + cpStats[1] = pPlayer->rank->deaths; + cpStats[2] = pPlayer->rank->hs; + cpStats[3] = pPlayer->rank->tks; + cpStats[4] = pPlayer->rank->shots; + cpStats[5] = pPlayer->rank->hits; + cpStats[6] = pPlayer->rank->damage; + cpStats[7] = pPlayer->rank->getPosition(); + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = pPlayer->rank->bodyHits[i]; + return pPlayer->rank->getPosition(); + } + return 0; + +} + +static cell AMX_NATIVE_CALL get_user_rstats(AMX *amx, cell *params) /* 3 param */ +{ + int index = params[1]; + CHECK_PLAYERRANGE(index); + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + if (pPlayer->rank){ + cell *cpStats = MF_GetAmxAddr(amx,params[2]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[3]); + cpStats[0] = pPlayer->life.kills; + cpStats[1] = pPlayer->life.deaths; + cpStats[2] = pPlayer->life.hs; + cpStats[3] = pPlayer->life.tks; + cpStats[4] = pPlayer->life.shots; + cpStats[5] = pPlayer->life.hits; + cpStats[6] = pPlayer->life.damage; + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = pPlayer->life.bodyHits[i]; + return 1; + } + return 0; +} + +static cell AMX_NATIVE_CALL get_stats(AMX *amx, cell *params) /* 3 param */ +{ + + int index = params[1] + 1; + + for(RankSystem::iterator a = g_rank.front(); a ;--a){ + if ((*a).getPosition() == index) { + cell *cpStats = MF_GetAmxAddr(amx,params[2]); + cell *cpBodyHits = MF_GetAmxAddr(amx,params[3]); + cpStats[0] = (*a).kills; + cpStats[1] = (*a).deaths; + cpStats[2] = (*a).hs; + cpStats[3] = (*a).tks; + cpStats[4] = (*a).shots; + cpStats[5] = (*a).hits; + cpStats[6] = (*a).damage; + cpStats[7] = (*a).getPosition(); + MF_SetAmxString(amx,params[4],(*a).getName(),params[5]); + for(int i = 1; i < 8; ++i) + cpBodyHits[i] = (*a).bodyHits[i]; + return --a ? index : 0; + } + } + + return 0; +} + +static cell AMX_NATIVE_CALL get_statsnum(AMX *amx, cell *params) +{ + return g_rank.getRankNum(); +} + + +static cell AMX_NATIVE_CALL register_cwpn(AMX *amx, cell *params){ // name,logname,melee=0 + int i; + bool bFree = false; + for ( i=TSMAX_WEAPONS-TSMAX_CUSTOMWPNS;i 7 ){ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid aim %d", aim); + return 0; + } + + CPlayer* pAtt = GET_PLAYER_POINTER_I(att); + CPlayer* pVic = GET_PLAYER_POINTER_I(vic); + + pVic->pEdict->v.dmg_inflictor = NULL; + pAtt->saveHit( pVic , weapon , dmg, aim ); + + if ( !pAtt ) pAtt = pVic; + int TA = 0; + if ( (pVic->pEdict->v.team == pAtt->pEdict->v.team ) && ( pVic != pAtt) ) + TA = 1; + MF_ExecuteForward(g_damage_info, pAtt->index, pVic->index, dmg, weapon, aim, TA ); + + if ( pVic->IsAlive() ) + return 1; + + pAtt->saveKill(pVic,weapon,( aim == 1 ) ? 1:0 ,TA); + MF_ExecuteForward(g_death_info, pAtt->index, pVic->index, weapon, aim, TA ); + + return 1; +} + +static cell AMX_NATIVE_CALL cwpn_shot(AMX *amx, cell *params){ // player,wid + int index = params[2]; + CHECK_PLAYERRANGE(index); + + int weapon = params[1]; + if ( weapon < TSMAX_WEAPONS-TSMAX_CUSTOMWPNS ){ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid custom weapon id %d", weapon); + return 0; + } + + CPlayer* pPlayer = GET_PLAYER_POINTER_I(index); + pPlayer->saveShot(weapon); + + return 1; +} + +AMX_NATIVE_INFO stats_Natives[] = { + { "get_stats", get_stats}, + { "get_statsnum", get_statsnum}, + { "get_user_astats", get_user_astats }, + { "get_user_rstats", get_user_rstats }, + { "get_user_lstats", get_user_rstats }, // for backward compatibility + { "get_user_stats", get_user_stats }, + { "get_user_vstats", get_user_vstats }, + { "get_user_wrstats", get_user_wrstats}, // DEC-Weapon(Round) Stats + { "get_user_wstats", get_user_wstats}, + { "reset_user_wstats", reset_user_wstats }, + + // Custom Weapon Support + { "custom_weapon_add", register_cwpn }, + { "custom_weapon_dmg", cwpn_dmg }, + { "custom_weapon_shot", cwpn_shot }, + + { NULL, NULL } +}; + diff --git a/dlls/ts/tsx/UserMsg.h b/dlls/ts/tsx/UserMsg.h new file mode 100644 index 00000000..fe607e4f --- /dev/null +++ b/dlls/ts/tsx/UserMsg.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003-2005 Twilight Suzuka + * + * This file is part of TSXMod. + * + * TS XMod is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * TS XMod is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TS XMod; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#include "amxxmodule.h" +#include "tsx.h" +#include "MsgFunc.h" + +int gmsgResetHUD; +int gmsgWeaponInfo; +int gmsgClipInfo; +int gmsgScoreInfo; +int gmsgTSHealth; + +int gmsgWStatus; +int gmsgTSCash; +int gmsgTSSpace; +int gmsgPwUp; + +struct sUserMsg +{ + const char* name; + int* id; + funEventCall func; + bool endmsg; +} +g_user_msg[] = +{ + { "ResetHUD",&gmsgResetHUD,Client_ResetHUD_End,true }, + { "WeaponInfo",&gmsgWeaponInfo,Client_WeaponInfo,false }, + { "ClipInfo",&gmsgClipInfo,Client_ClipInfo,false }, + { "ScoreInfo",&gmsgScoreInfo,Client_ScoreInfo,false }, + { "TSHealth",&gmsgTSHealth,Client_TSHealth_End,true }, + + { "WStatus",&gmsgWStatus,Client_WStatus,false }, + { "TSCash",&gmsgTSCash,Client_TSCash,false }, + { "TSSpace",&gmsgTSSpace,Client_TSSpace,false }, + { "PwUp",&gmsgPwUp,Client_PwUp,false}, + + { 0,0,0,false } +}; \ No newline at end of file diff --git a/dlls/ts/tsx/Utils.cpp b/dlls/ts/tsx/Utils.cpp index fd52f9bf..0047a311 100755 --- a/dlls/ts/tsx/Utils.cpp +++ b/dlls/ts/tsx/Utils.cpp @@ -1,6 +1,6 @@ /* - * TFCX - * Copyright (c) 2004 Lukasz Wlasinski + * TSX + * Copyright (c) 2005 Melanie Maye * * * This program is free software; you can redistribute it and/or modify it @@ -73,15 +73,3 @@ weapon_t weaponData[] = { { 1,"Throwing Knife","throwing_knife",2 }, // new id 37 { 0,"breakable", "breakable", 1 }, }; - -bool ignoreBots (edict_t *pEnt, edict_t *pOther){ - if ( !rankBots && ( pEnt->v.flags & FL_FAKECLIENT || ( pOther && pOther->v.flags & FL_FAKECLIENT ) ) ) - return true; - return false; -} - -bool isModuleActive(){ - if ( !(int)CVAR_GET_FLOAT("tsstats_pause") ) - return true; - return false; -} \ No newline at end of file diff --git a/dlls/ts/tsx/amxxmodule.cpp b/dlls/ts/tsx/amxxmodule.cpp index 7355cded..e374e441 100755 --- a/dlls/ts/tsx/amxxmodule.cpp +++ b/dlls/ts/tsx/amxxmodule.cpp @@ -2502,8 +2502,6 @@ PFN_FORMAT g_fn_Format; PFN_REGISTERFUNCTION g_fn_RegisterFunction; PFN_REQ_FNPTR g_fn_RequestFunction; PFN_AMX_PUSH g_fn_AmxPush; -PFN_SET_TEAM_INFO g_fn_SetTeamInfo; -PFN_PLAYER_PROP_ADDR g_fn_PlayerPropAddr; // *** Exports *** C_DLLEXPORT int AMXX_Query(int *interfaceVersion, amxx_module_info_s *moduleInfo) @@ -2613,8 +2611,6 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC("GetPlayerFlags", g_fn_GetPlayerFlags, PFN_GETPLAYERFLAGS); REQFUNC("GetPlayerEdict", g_fn_GetPlayerEdict, PFN_GET_PLAYER_EDICT); REQFUNC("amx_Push", g_fn_AmxPush, PFN_AMX_PUSH); - REQFUNC("SetPlayerTeamInfo", g_fn_SetTeamInfo, PFN_SET_TEAM_INFO); - REQFUNC("PlayerPropAddr", g_fn_PlayerPropAddr, PFN_PLAYER_PROP_ADDR); #ifdef MEMORY_TEST // Memory @@ -2737,8 +2733,6 @@ void ValidateMacros_DontCallThis_Smiley() MF_GetPlayerEdict(0); MF_Format("", 4, "str"); MF_RegisterFunction(NULL, ""); - MF_SetPlayerTeamInfo(0, 0, ""); - MF_PlayerPropAddr(0, 0); } #endif @@ -2918,20 +2912,20 @@ void operator delete[](void *reportedAddress) #else #if !defined NO_ALLOC_OVERRIDES && !defined MEMORY_TEST && !defined WIN32 -void * operator new(size_t size) { +void * ::operator new(size_t size) { return(calloc(1, size)); } -void * operator new[](size_t size) { +void * ::operator new[](size_t size) { return(calloc(1, size)); } -void operator delete(void * ptr) { +void ::operator delete(void * ptr) { if(ptr) free(ptr); } -void operator delete[](void * ptr) { +void ::operator delete[](void * ptr) { if(ptr) free(ptr); } diff --git a/dlls/ts/tsx/amxxmodule.h b/dlls/ts/tsx/amxxmodule.h index 85f7985d..0a000d20 100755 --- a/dlls/ts/tsx/amxxmodule.h +++ b/dlls/ts/tsx/amxxmodule.h @@ -1927,28 +1927,6 @@ enum ForwardParam FP_ARRAY, // array; use the return value of prepareArray. }; -enum PlayerProp -{ - Player_Name, //String - Player_Ip, //String - Player_Team, //String - Player_Ingame, //bool - Player_Authorized, //bool - Player_Vgui, //bool - Player_Time, //float - Player_Playtime, //float - Player_MenuExpire, //float - Player_Weapons, //struct{int,int}[32] - Player_CurrentWeapon, //int - Player_TeamID, //int - Player_Deaths, //int - Player_Aiming, //int - Player_Menu, //int - Player_Keys, //int - Player_Flags, //int[32] - Player_Newmenu, //int - Player_NewmenuPage, //int -}; typedef int (*PFN_ADD_NATIVES) (const AMX_NATIVE_INFO * /*list*/); typedef char * (*PFN_BUILD_PATHNAME) (const char * /*format*/, ...); @@ -2000,7 +1978,6 @@ typedef edict_t * (*PFN_GET_PLAYER_EDICT) (int /*id*/); #else typedef void * (*PFN_GET_PLAYER_EDICT) (int /*id*/); #endif -typedef void * (*PFN_PLAYER_PROP_ADDR) (int /*id*/, int /*prop*/); #ifdef MEMORY_TEST typedef void * (*PFN_ALLOCATOR) (const char* /*filename*/, const unsigned int /*line*/, const char* /*func*/, @@ -2026,7 +2003,6 @@ typedef void (*PFN_MERGEDEFINITION_FILE) (const char * /*filename*/); typedef const char * (*PFN_FORMAT) (const char * /*fmt*/, ... /*params*/); typedef void (*PFN_REGISTERFUNCTION) (void * /*pfn*/, const char * /*desc*/); typedef int (*PFN_AMX_PUSH) (AMX * /*amx*/, cell /*value*/); -typedef int (*PFN_SET_TEAM_INFO) (int /*player */, int /*teamid */, const char */*name */); extern PFN_ADD_NATIVES g_fn_AddNatives; extern PFN_BUILD_PATHNAME g_fn_BuildPathname; @@ -2090,8 +2066,6 @@ extern PFN_GET_PLAYER_TEAM g_fn_GetPlayerTeam; extern PFN_REGISTERFUNCTION g_fn_RegisterFunction; extern PFN_REQ_FNPTR g_fn_RequestFunction; extern PFN_AMX_PUSH g_fn_AmxPush; -extern PFN_SET_TEAM_INFO g_fn_SetTeamInfo; -extern PFN_PLAYER_PROP_ADDR g_fn_PlayerPropAddr; #ifdef MAY_NEVER_BE_DEFINED // Function prototypes for intellisense and similar systems @@ -2152,8 +2126,6 @@ void MF_RegisterFunction (void *pfn, const char *description) { } void * MF_RequestFunction (const char *description) { } int MF_AmxPush (AMX *amx, cell *params) { } int MF_AmxExec (AMX *amx, cell *retval, int idx) { } -int MF_SetPlayerTeamInfo (int id, int teamid, const char *teamname) { } -void * MF_PlayerPropAddr (int id, int prop) { } #endif // MAY_NEVER_BE_DEFINED #define MF_AddNatives g_fn_AddNatives @@ -2219,8 +2191,6 @@ void MF_LogError(AMX *amx, int err, const char *fmt, ...); #define MF_RegisterFunction g_fn_RegisterFunction #define MF_RequestFunction g_fn_RequestFunction; #define MF_AmxPush g_fn_AmxPush -#define MF_SetPlayerTeamInfo g_fn_SetTeamInfo -#define MF_PlayerPropAddr g_fn_PlayerPropAddr #ifdef MEMORY_TEST /*** Memory ***/ diff --git a/dlls/ts/tsx/moduleconfig.h b/dlls/ts/tsx/moduleconfig.h index a581ad0e..1884eb48 100755 --- a/dlls/ts/tsx/moduleconfig.h +++ b/dlls/ts/tsx/moduleconfig.h @@ -6,7 +6,7 @@ // Module info #define MODULE_NAME "TSX" #define MODULE_VERSION "1.65" -#define MODULE_AUTHOR "AMX Mod X Dev Team" +#define MODULE_AUTHOR "Twilight Suzuka" #define MODULE_URL "http://www.amxmodx.org" #define MODULE_LOGTAG "TSX" // If you want the module not to be reloaded on mapchange, remove / comment out the next line diff --git a/dlls/ts/tsx/msvc/tsx_amxx.vcproj b/dlls/ts/tsx/msvc/tsx_amxx.vcproj index 944fb4c4..93c3b3ae 100755 --- a/dlls/ts/tsx/msvc/tsx_amxx.vcproj +++ b/dlls/ts/tsx/msvc/tsx_amxx.vcproj @@ -215,92 +215,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + RelativePath="..\tsx.cpp"> @@ -340,9 +255,18 @@ + + + + + + value ? true:false; + + for( int i = 1; i <= gpGlobals->maxClients; ++i ) + GET_PLAYER_POINTER_I(i)->Init( i , pEdictList + i ); + + RETURN_META(MRES_IGNORED); +} + +void PlayerPreThink_Post( edict_t *pEntity ) +{ + + if ( !isModuleActive() ) // stats only + return; + + CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity); + + if (pPlayer->clearStats && pPlayer->clearStats < gpGlobals->time && pPlayer->ingame) + { + pPlayer->clearStats = 0.0f; + pPlayer->rank->updatePosition( &pPlayer->life ); + pPlayer->restartStats(false); + } + RETURN_META(MRES_IGNORED); +} + +void ServerDeactivate() +{ + int i; + for(i = 1;i<=gpGlobals->maxClients; ++i) + { + CPlayer *pPlayer = GET_PLAYER_POINTER_I(i); + if (pPlayer->rank) pPlayer->Disconnect(); + } + + if ( (g_rank.getRankNum() >= (int)tsstats_maxsize->value) || ((int)tsstats_reset->value == 1) ) + { + CVAR_SET_FLOAT("tsstats_reset",0.0); + g_rank.clear(); + } + + g_rank.saveRank( MF_BuildPathname("%s",get_localinfo("tsstats") ) ); + + // clear custom weapons info + for ( i=TSMAX_WEAPONS-TSMAX_CUSTOMWPNS;iConnect(pszAddress); + RETURN_META_VALUE(MRES_IGNORED, TRUE); +} + +void ClientDisconnect( edict_t *pEntity ) +{ + CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity); + if (pPlayer->ingame) pPlayer->Disconnect(); + RETURN_META(MRES_IGNORED); +} + +void ClientPutInServer_Post( edict_t *pEntity ) +{ + GET_PLAYER_POINTER(pEntity)->PutInServer(); + RETURN_META(MRES_IGNORED); +} + +void ClientUserInfoChanged_Post( edict_t *pEntity, char *infobuffer ) +{ + CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity); + const char* name = INFOKEY_VALUE(infobuffer,"name"); + const char* oldname = STRING(pEntity->v.netname); + + if ( pPlayer->ingame ) + { + if ( strcmp(oldname,name) ) + { + if (!tsstats_rank->value) + pPlayer->rank = g_rank.findEntryInRank( name, name ); + else + pPlayer->rank->setName( name ); + } + } + else if ( pPlayer->IsBot() ) + { + pPlayer->PutInServer(); + } + + RETURN_META(MRES_IGNORED); +} + +void MessageBegin_Post(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed) +{ + if (ed) + { + mPlayerIndex = ENTINDEX(ed); + mPlayer = GET_PLAYER_POINTER_I(mPlayerIndex); + } + else + { + mPlayerIndex = 0; + mPlayer = NULL; + } + mState = 0; + + if ( msg_type < 0 || msg_type >= MAX_REG_MSGS ) msg_type = 0; + + function=modMsgs[msg_type]; + endfunction=modMsgsEnd[msg_type]; + RETURN_META(MRES_IGNORED); +} + +void MessageEnd_Post(void) +{ + if (endfunction) (*endfunction)(NULL); + RETURN_META(MRES_IGNORED); +} + +void WriteByte_Post(int iValue) +{ + if (function) (*function)((void *)&iValue); + RETURN_META(MRES_IGNORED); +} + +void WriteChar_Post(int iValue) +{ + if (function) (*function)((void *)&iValue); + RETURN_META(MRES_IGNORED); +} + +void WriteShort_Post(int iValue) +{ + if (function) (*function)((void *)&iValue); + RETURN_META(MRES_IGNORED); +} + +void WriteLong_Post(int iValue) +{ + if (function) (*function)((void *)&iValue); + RETURN_META(MRES_IGNORED); +} + +void WriteAngle_Post(float flValue) +{ + if (function) (*function)((void *)&flValue); + RETURN_META(MRES_IGNORED); +} + +void WriteCoord_Post(float flValue) +{ + if (function) (*function)((void *)&flValue); + RETURN_META(MRES_IGNORED); +} + +void WriteString_Post(const char *sz) +{ + if (function) (*function)((void *)sz); + RETURN_META(MRES_IGNORED); +} + +void WriteEntity_Post(int iValue) +{ + if (function) (*function)((void *)&iValue); + RETURN_META(MRES_IGNORED); +} + +void TraceLine_Post(const float *v1, const float *v2, int fNoMonsters, edict_t *e, TraceResult *ptr) +{ + if (ptr->pHit&&(ptr->pHit->v.flags& (FL_CLIENT | FL_FAKECLIENT) )&& + e&&(e->v.flags& (FL_CLIENT | FL_FAKECLIENT) )) + { + GET_PLAYER_POINTER(e)->aiming = ptr->iHitgroup; + } + RETURN_META(MRES_IGNORED); +} + +void OnMetaAttach() { + + CVAR_REGISTER (&init_tsstats_maxsize); + CVAR_REGISTER (&init_tsstats_reset); + CVAR_REGISTER (&init_tsstats_rank); + tsstats_maxsize=CVAR_GET_POINTER(init_tsstats_maxsize.name); + tsstats_reset=CVAR_GET_POINTER(init_tsstats_reset.name); + tsstats_rank=CVAR_GET_POINTER(init_tsstats_rank.name); + + CVAR_REGISTER (&init_tsstats_rankbots); + CVAR_REGISTER (&init_tsstats_pause); + tsstats_rankbots = CVAR_GET_POINTER(init_tsstats_rankbots.name); + tsstats_pause = CVAR_GET_POINTER(init_tsstats_pause.name); + +} + +void OnAmxxAttach() { + + gKnifeOffset = TSKNIFE_OFFSET; + + MF_AddNatives( stats_Natives ); + //TSFun does these now + //MF_AddNatives( base_Natives ); + + const char* path = get_localinfo("tsstats_score","addons/amxmodx/data/tsstats.amxx"); + if ( path && *path ) + { + char error[128]; + g_rank.loadCalc( MF_BuildPathname("%s",path) , error ); + } + if ( !g_rank.begin() ) + { + g_rank.loadRank( MF_BuildPathname("%s",get_localinfo("tsstats","addons/amxmodx/data/tsstats.dat") ) ); + } +} + +void OnPluginsLoaded() +{ + g_damage_info = MF_RegisterForward("client_damage", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + g_death_info = MF_RegisterForward("client_death", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); +} diff --git a/dlls/ts/tsx/tsx.h b/dlls/ts/tsx/tsx.h index c5c11af0..e2870f1a 100755 --- a/dlls/ts/tsx/tsx.h +++ b/dlls/ts/tsx/tsx.h @@ -45,31 +45,9 @@ #define GETPLAYERAUTHID (*g_engfuncs.pfnGetPlayerAuthId) #endif -extern AMX_NATIVE_INFO stats_Natives[]; +//extern AMX_NATIVE_INFO stats_Natives[]; extern AMX_NATIVE_INFO base_Natives[]; -extern int gmsgResetHUD; -extern int gmsgWeaponInfo; -extern int gmsgClipInfo; -extern int gmsgScoreInfo; -extern int gmsgTSHealth; - -extern int gmsgWStatus; -extern int gmsgTSCash; -extern int gmsgTSSpace; -extern int gmsgPwUp; - -void Client_ResetHUD_End(void*); -void Client_WeaponInfo(void*); -void Client_ClipInfo(void*); -void Client_ScoreInfo(void*); -void Client_TSHealth_End(void*); - -void Client_WStatus(void* mValue); -void Client_TSCash(void* mValue); -void Client_TSSpace(void* mValue); -void Client_PwUp(void* mValue); - typedef void (*funEventCall)(void*); extern funEventCall modMsgsEnd[MAX_REG_MSGS]; extern funEventCall modMsgs[MAX_REG_MSGS]; @@ -105,8 +83,17 @@ extern int gKnifeOffset; extern weapon_t weaponData[TSMAX_WEAPONS]; -bool isModuleActive(); -bool ignoreBots (edict_t *pEnt, edict_t *pOther = NULL); +inline bool ignoreBots (edict_t *pEnt, edict_t *pOther = NULL) +{ + if ( !rankBots && ( pEnt->v.flags & FL_FAKECLIENT || ( pOther && pOther->v.flags & FL_FAKECLIENT ) ) ) return true; + return false; +} + +inline bool isModuleActive() +{ + if ( !(int)CVAR_GET_FLOAT("tsstats_pause") ) return true; + return false; +} #define CHECK_ENTITY(x) \ if (x < 0 || x > gpGlobals->maxEntities) { \