// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
// Copyright (C) 2004 Lukasz Wlasinski.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
//     https://alliedmods.net/amxmodx-license

//
// TFCX Module
//

#include "amxxmodule.h"
#include "tfcx.h"


int damage;
int TA;
int weapon;
int aim;
CPlayer *pAttacker;
edict_t* tempEnt;
int tempInt;
bool ignoreDamage = false;

void Client_ResetHUD(void* mValue){
	if ( mPlayer ){
		mPlayer->clearStats = gpGlobals->time + 0.25f;
	}
}

/*
void Client_WeaponList(void* mValue){
  static int wpnList;
  static int iSlot;
  static const char* wpnName;

  switch (mState++) {
  case 0:
    wpnName = (const char*)mValue;
    break;
  case 1:
    iSlot = *(int*)mValue;
    break;
  case 7:
    int iId = *(int*)mValue;
    if ( (iId < 0 || iId >= MAX_WEAPONS ) || ( wpnList & (1<<iId) ) )
      break;

    wpnList |= (1<<iId);
    weaponData[iId].ammoSlot = iSlot;
    strcpy(weaponData[iId].fullName, wpnName );
	weaponData[iId].name = weaponData[iId].fullName;

	char* wpnPrefix = strstr( weaponData[iId].fullName ,"tf_weapon_");

	if ( wpnPrefix )
		weaponData[iId].name = wpnPrefix + 10;
  } 
}
*/

void Client_Damage(void* mValue){
  switch (mState++) {
  case 1: 
    damage = *(int*)mValue;
    break;

  case 2:
	edict_t* enemy;
    if ( !mPlayer || !damage )  
		break;

	enemy = mPlayer->pEdict->v.dmg_inflictor;

	if ( FNullEnt( enemy ) )
		break;

	if (enemy->v.flags & (FL_CLIENT | FL_FAKECLIENT) ) { // attacker is player and his active weapon

		pAttacker = GET_PLAYER_POINTER(enemy);
		
		aim = pAttacker->aiming;
		weapon = pAttacker->current;

		switch(weapon){
		case TFC_WPN_SPANNER:
		case TFC_WPN_AXE:
		case TFC_WPN_KNIFE:
			pAttacker->saveShot(weapon); // melee , save shot too
			break;

		case TFC_WPN_MEDIKIT:
			if ( pAttacker->teamId == mPlayer->teamId ) // ???
				ignoreDamage = true;
			pAttacker->saveShot(weapon); // melee , save shot too
			break;
		}
	
		pAttacker->saveHit( mPlayer , weapon , damage, aim);

	}
	else if ( !FNullEnt( enemy->v.owner ) ){
		if ( enemy->v.owner->v.flags & (FL_CLIENT | FL_FAKECLIENT)  ){ // caltrop, empgrenade, gasgrenade, napalmgrenade

			pAttacker = GET_PLAYER_POINTER(enemy->v.owner);

			const char *szClass = STRING(enemy->v.classname);
			
			switch(szClass[10]){
				case 'c':
					weapon = TFC_WPN_CALTROP;
					break;
				case 'e':
					weapon = TFC_WPN_EMPGRENADE;
					break;
				case 'g':
					weapon = TFC_WPN_GASGRENADE;
					break;
				case 'm':
					weapon = TFC_WPN_MEDIKIT;
					if ( pAttacker->teamId == mPlayer->teamId ) // ???
						ignoreDamage = true;
					pAttacker->saveShot(weapon);
					break;
				case 'n':
					weapon = TFC_WPN_NAPALMGRENADE;
					break;
				case 'a':
				case 's':
				case '_': // hmm...nailgun_nail, fastswitch and this one may not be true...
					//PRINT_CONSOLE("Nail! Class:%d wpn:%d\n",pAttacker->classId,pAttacker->current);
					weapon = pAttacker->current;
					aim = pAttacker->aiming;
					break;
				case 'r':
					weapon = TFC_WPN_FLAMETHROWER;
					break;
			}
			if ( !weapon ) {
				switch(szClass[3]){
				case 'e':
					weapon = TFC_WPN_TIMER; // TFC_WPN_MEDKIT ??

					tempInt = *( (int*)mPlayer->pEdict->pvPrivateData + pdTimerOwner );
					if (!tempInt)
						break;
					tempEnt = (edict_t*)tempInt;
					pAttacker = GET_PLAYER_POINTER(tempEnt);
					
					if ( pAttacker->teamId == mPlayer->teamId ) // ???
						ignoreDamage = true;
					
					pAttacker->saveShot(weapon); // ??? save shot too
					break;
				case 'f':
					weapon = TFC_WPN_FLAMES; // tf_fire
					break;
				}
			}

			if ( weapon )
				pAttacker->saveHit( mPlayer , weapon , damage, aim );
			//else 
			//	PRINT_CONSOLE("*** DMG! Att:%d Vic:%d unknown weapon %s\n",pAttacker->index,mPlayer->index,STRING(enemy->v.classname));
		}
		// nailgrenadenail->nailgrenade->player :))) I'm the best !
		else if ( !FNullEnt(enemy->v.owner->v.owner) && enemy->v.owner->v.owner->v.flags & (FL_CLIENT | FL_FAKECLIENT ) ){
			pAttacker = GET_PLAYER_POINTER(enemy->v.owner->v.owner);
			weapon = TFC_WPN_NAILGRENADE;
			pAttacker->saveHit( mPlayer , weapon , damage, aim );
		}
	}
    else { // nailgrenade , mirvgrenade , normalgrenade , rockets
		if ( strstr("sentrygun",STRING(enemy->v.classname)) ){
			tempInt = *( (int*)enemy->pvPrivateData + pdSentryGunOwner );
			if ( !tempInt )
				break;
			tempEnt = (edict_t*)tempInt;
			pAttacker = GET_PLAYER_POINTER(tempEnt);
			weapon = TFC_WPN_SENTRYGUN;
			pAttacker->saveShot(weapon); // save shot too
			pAttacker->saveHit( mPlayer , weapon , damage, aim );
		}
		else if( g_grenades.find(enemy , &pAttacker , &weapon ) ){
			if ( weapon == TFC_WPN_RPG && pAttacker->classId == TFC_PC_PYRO ){
				weapon = TFC_WPN_IC;
				pAttacker->saveShot(weapon);
			}
			
			pAttacker->saveHit( mPlayer , weapon , damage, aim );
		}
	}
	break;
  }
  
}

void Client_Damage_End(void* mValue){
	if ( !damage )
		return;

	if ( !pAttacker )
		pAttacker = mPlayer;

	if ( !ignoreDamage ){
		TA = 0;
		if ( (mPlayer->teamId == pAttacker->teamId) && (mPlayer != pAttacker) )
			TA = 1;
		if (g_damage_info > 0)
			MF_ExecuteForward(g_damage_info, pAttacker->index, mPlayer->index, damage, weapon, aim, TA);
	
		if( !mPlayer->IsAlive() ){
			pAttacker->saveKill(mPlayer,weapon,( aim == 1 ) ? 1:0 ,TA);
			
			if (g_death_info > 0)
				MF_ExecuteForward(g_death_info, pAttacker->index, mPlayer->index, weapon, aim, TA);
		}
	}

	damage = 0;
	aim = 0;
	weapon = 0;
	pAttacker = NULL;
	ignoreDamage = false;

}

void Client_CurWeapon(void* mValue){
  
  static int iState;
  static int iId;
  switch (mState++){
  case 0: 
    iState = *(int*)mValue;
    break;
  case 1:
    if (!iState) break; 
    iId = *(int*)mValue;
    break;
  case 2:
	if (!mPlayer || !iState ) break;
    int iClip = *(int*)mValue;
    
	if ((iClip > -1) && (iClip < mPlayer->weapons[iId].clip)){
		mPlayer->saveShot(iId);
	}
	
    mPlayer->weapons[iId].clip = iClip;
	mPlayer->current = iId;
  }
}

void Client_AmmoX(void* mValue){
  
  static int iAmmo;
  switch (mState++){
  case 0:
    iAmmo = *(int*)mValue;
    break;
  case 1:
	if (!mPlayer ) break;

	// SniperRifle, AC and AutoRifle ...
	if ( mPlayer->classId == TFC_PC_HWGUY ){
		if ( mPlayer->current == TFC_WPN_AC && mPlayer->weapons[mPlayer->current].ammo > *(int*)mValue  && iAmmo == weaponData[mPlayer->current].ammoSlot )
			mPlayer->saveShot(mPlayer->current);
	}
	else if ( mPlayer->classId == TFC_PC_SNIPER ){
		if ( (mPlayer->current == TFC_WPN_SNIPERRIFLE || mPlayer->current == TFC_WPN_AUTORIFLE) && mPlayer->weapons[mPlayer->current].ammo > *(int*)mValue && iAmmo == weaponData[mPlayer->current].ammoSlot )
			mPlayer->saveShot(mPlayer->current);
	}
	//

    for(int i = 1; i < MAX_WEAPONS ; ++i) 
      if (iAmmo == weaponData[i].ammoSlot)
        mPlayer->weapons[i].ammo = *(int*)mValue;
  }
}

void Client_AmmoPickup(void* mValue){
  
  static int iSlot;
  switch (mState++){
  case 0:
    iSlot = *(int*)mValue;
    break;
  case 1:
	if (!mPlayer ) break;
    for(int i = 1; i < MAX_WEAPONS ; ++i)
      if (weaponData[i].ammoSlot == iSlot)
        mPlayer->weapons[i].ammo += *(int*)mValue;
  }
}

void Client_ScoreInfo(void* mValue){
  static int iIndex;
  static int iClass;
  switch (mState++){
  case 0:
    iIndex = *(int*)mValue;
    break;
  case 3:
	  iClass = *(int*)mValue;
	  break;
  case 4:
	  if ( iIndex > 0 && iIndex <= gpGlobals->maxClients ){
		  GET_PLAYER_POINTER_I( iIndex )->teamId = *(int*)mValue;
		  GET_PLAYER_POINTER_I( iIndex )->classId = iClass;
	  }

  }
}