#include <amxmodx>
#include <amxmisc>
#include <zombieplague>
#include <vault>
 
stock const ZP_BANK_FMT[] = "^x04[AC] %L"
stock const zplog[] = "zp_bank_activity.log"
 
new g_iAmmoPacks[33]
new g_iSessionMovement[33]
new g_iWithdrawLimit[33]
new g_szAuth[33][32]
new cvAnnounceTime
new cvBankMax
new cvDepositMin
new cvWithdrawMax
new cvWithdrawLimit
new cvBankSaveDays
new cvAutoSave
new cvDeBug
 
// Temporary Database vars (used to restore players stats in case they get disconnected)
new db_playerip[64][32] // player name
new db_wlimit[64] // withdraw limit
new db_slot_i // additional saved slots counter (should start on maxplayers+1)
 
// Temporary save player's stats to database
Tmp_Save(id)
{
	new PIP[32]
	get_user_ip(id, PIP, 31, 1)
 
	// Check whether there is another record already in that slot
	if (db_playerip[id][0] && !equal(PIP, db_playerip[id]))
	{
		// If DB size is exceeded, write over old records
		if (db_slot_i >= sizeof db_playerip)
			db_slot_i = get_maxplayers()+1
 
		// Move previous record onto an additional save slot
		copy(db_playerip[db_slot_i], charsmax(db_playerip[]), db_playerip[id])
		db_wlimit[db_slot_i] = db_wlimit[id]
		db_slot_i++
	}
 
	copy(db_playerip[id], charsmax(db_playerip[]), PIP) // name
	db_wlimit[id] = g_iWithdrawLimit[id]  // withdraw limit
}
 
// Load temporary saved player's stats from database (if a record is found)
Tmp_Load(id)
{
	new PIP[32]
	get_user_ip(id, PIP, 31, 1)
 
	// Look for a matching record
	static i
	for (i = 0; i < sizeof db_playerip; i++)
	{
		if (equal(PIP, db_playerip[i]))
		{
			// Bingo!
			g_iWithdrawLimit[id] = db_wlimit[i]
			return;
		}
	}
}
 
LoadClient(id, szAuth[])
{
	static szValue[11]
	new iValue = 0
	new key[38], vaultdata[56], name[34], timestamp[11]
 
	// Little memory cleanup
	szValue[0] = '^0'
	key[0] = '^0'
	vaultdata[0] = '^0'
	name[0] = '^0'
	timestamp[0] = '^0'
 
	format(key,37,"ZBANK.%s",szAuth)
 
	get_vaultdata(key,vaultdata,55)
	parse(vaultdata,name,33,timestamp,10,szValue,10)
	remove_quotes(name) 
 
	if (strlen(szValue) > 0) 
	{
		iValue = (g_iAmmoPacks[id] = str_to_num(szValue))
	}
 
	SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_LOAD", iValue, szAuth, (get_pcvar_num(cvWithdrawLimit) - g_iWithdrawLimit[id]))
 
	if (get_pcvar_num(cvDeBug) >= 2)
	{	
		if (iValue != 0) 
		{
			log_to_file(zplog,"[ZP] DBLoad: loaded ^"%d^" ammovalue for (Player ^"%s^") (IP ^"%s^")",iValue,name,szAuth)
		}
		else
		{
			log_to_file(zplog,"[ZP] DBLoad: nothing to load for (IP ^"%s^"). So sad.",szAuth)
		}
 
	}
}
 
SaveClient(id, szAuth[])
{
	static szValue[11]
	new key[38], vaultdata[56], name[32]
 
	// Little memory cleanup
	szValue[0] = '^0'
	key[0] = '^0'
	vaultdata[0] = '^0'
	name[0] = '^0'
 
	num_to_str(g_iAmmoPacks[id] + g_iSessionMovement[id], szValue, charsmax(szValue))
	get_user_name(id, name, 31)
	format(key,37,"ZBANK.%s",szAuth) 
	format(vaultdata,55,"^"%s^" %d %s",name,get_systime(),szValue)
 
	if (str_to_num(szValue) <= 0) 
	{
		remove_vaultdata(key)
	}
	else 
	{
		set_vaultdata(key,vaultdata)
	}
 
	if (get_pcvar_num(cvDeBug) >= 2)
	{
		if (str_to_num(szValue) > 0) 
		{
			log_to_file(zplog,"[ZP] DBSave: saved ^"%s^" ammovalue for (Player ^"%s^") (IP ^"%s^")",szValue,name,szAuth)
		}
		else
		{
			log_to_file(zplog,"[ZP] DBSave: nothing to save for (IP ^"%s^"). So sad.",szAuth)
		}
	}
}
 
MemClr(id)
{
	g_szAuth[id][0] = '^0'
	g_iAmmoPacks[id] = 0
	g_iSessionMovement[id] = 0
	g_iWithdrawLimit[id] = 0
}
 
cleanDB()
{
	// Open up the vault file - read line by line
	// Use vault to delete to any data over a certain age
	new gVaultFile[128]
	if ( !file_exists(gVaultFile) ) return
	get_localinfo("amxx_vault", gVaultFile, 127)
 
	new ammoSaveDays = get_pcvar_num(cvBankSaveDays)
 
	if ( ammoSaveDays < 0) return
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		log_to_file(zplog,"[ZP] DBClean: starting DB cleanup...")
	}
 
	// Create a copy of savekeys to remove
	new temp[128], pcounter
	formatex(temp, 127, "%s~", gVaultFile)
 
	new vaultFile = fopen(gVaultFile, "r")
	new tempFile = fopen(temp, "w+")
 
	// Read through the file looking for valid entries
	// Check the epoch time to see if deletion should happen
	new data[93], vaultSaveKey[38], name[34], epoch[11], value[11]
	new maxTime = ammoSaveDays * 24 * 3600
	new curTime = get_systime()
	new bool:dataFound
 
	while ( !feof(vaultFile) ) {
		data[0] = '^0'
 
		// Read the line in vault and if zp save info check to see if we should copy vault key to temp file
		// Don't need to read whole line only enough for what we need to parse
		fgets(vaultFile, data, 92)
 
		if ( equal(data, "ZBANK", 5) ) {
			vaultSaveKey[0] = '^0'
			name[0] = '^0'
			epoch[0] = '^0'
			value[0] = '^0'
 
			// Only copy keys if older than max save days
			parse(data, vaultSaveKey, 37, name, 33, epoch, 10, value, 10)
			if ( (str_to_num(epoch) + maxTime) < curTime ) {
				fprintf(tempFile, "%s^n", vaultSaveKey)
				dataFound = true
			}
		}
	}
 
	// Finished reading vault close it
	fclose(vaultFile)
 
	if ( dataFound ) {
		// Reset to top of temp file
		fseek(tempFile, 0, SEEK_SET)
 
		// Remove all entries in temp file from vault.ini
		while ( !feof(tempFile) ) {
			vaultSaveKey[0] = '^0'
 
			fgets(tempFile, vaultSaveKey, 38)
			trim(vaultSaveKey)
 
			if ( vaultSaveKey[0] != '^0' )
			{
				remove_vaultdata(vaultSaveKey)
				pcounter++
				if (get_pcvar_num(cvDeBug) >= 1)
				{	
					log_to_file(zplog,"[ZP] DBClean: Deleting %s due to defined autoprune",vaultSaveKey)
				}
			}
		}
	}
 
	fclose(tempFile)
	delete_file(temp)
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		log_to_file(zplog,"[ZP] DBClean: database prunned successfully. %d users deleted. Settings: %d days",pcounter,ammoSaveDays)
	}
}
 
// Admin set ammopacks for player bank
public cmd_zpbankset(id, level, cid)
{
	// Check for access flag
	if (!cmd_access(id, level, cid, 3))
		return PLUGIN_HANDLED;
 
	// Retrieve arguments
	static arg[32], ammo[11], player, amount
	read_argv(1, arg, sizeof arg - 1)
	read_argv(2, ammo, sizeof arg - 1)
	amount = str_to_num(ammo)
	player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
 
	// Invalid target
	if (!player) return PLUGIN_HANDLED;
 
	if (amount >= 0)
	{
		g_iAmmoPacks[player] = amount
	}
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		new PIP[32],Pname[32]
		get_user_name(player, Pname, 31)
		get_user_ip(player, PIP, 31, 1)
		log_to_file(zplog,"[ZP] BankSet: set ^"%d^" bank ammovalue for (Player ^"%s^") (IP ^"%s^")",amount,Pname,PIP)
		console_print(id,"[ZP] Set ^"%d^" bank ammovalue for ^"%s^"",amount,Pname,PIP)
	}
 
	// If autosave enabled save this bullshit to vault
	if (get_pcvar_num(cvAutoSave) == 1)
	{
		SaveClient(player, g_szAuth[player])	
	}
 
	return PLUGIN_HANDLED;
}
 
// Admin add ammopacks to player bank
public cmd_zpbankadd(id, level, cid)
{
	// Check for access flag
	if (!cmd_access(id, level, cid, 3))
		return PLUGIN_HANDLED;
 
	// Retrieve arguments
	static arg[32], ammo[11], player, amount
	read_argv(1, arg, sizeof arg - 1)
	read_argv(2, ammo, sizeof arg - 1)
	amount = str_to_num(ammo)
	player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
 
	// Invalid target
	if (!player) return PLUGIN_HANDLED;
 
	g_iAmmoPacks[player] += amount
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		new PIP[32],Pname[32]
		get_user_name(player, Pname, 31)
		get_user_ip(player, PIP, 31, 1)
		log_to_file(zplog,"[ZP] BankSet: added ^"%d^" bank ammovalue for (Player ^"%s^") (IP ^"%s^")",amount,Pname,PIP)
		console_print(id,"[ZP] Added ^"%d^" bank ammovalue for ^"%s^"",amount,Pname,PIP)
	}
 
	// If autosave enabled save this bullshit to vault
	if (get_pcvar_num(cvAutoSave) == 1)
	{
		SaveClient(player, g_szAuth[player])	
	}
 
	return PLUGIN_HANDLED;
}
 
// Admin set withdraw limit status for player
public cmd_zpbanklim(id, level, cid)
{
	// Check for access flag
	if (!cmd_access(id, level, cid, 3))
		return PLUGIN_HANDLED;
 
	// Retrieve arguments
	static arg[32], limit[11], player, amount
	read_argv(1, arg, sizeof arg - 1)
	read_argv(2, limit, sizeof arg - 1)
	amount = str_to_num(limit)
	player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
 
	// Invalid target
	if (!player) return PLUGIN_HANDLED;
 
	g_iWithdrawLimit[player] = amount
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		new PIP[32],Pname[32]
		get_user_name(player, Pname, 31)
		get_user_ip(player, PIP, 31, 1)
		log_to_file(zplog,"[ZP] BankSet: set ^"%d^" withdraw limit for (Player ^"%s^") (IP ^"%s^")",amount,Pname,PIP)
		console_print(id,"[ZP] Set ^"%d^" withdraw limit for ^"%s^"",amount,Pname,PIP)
	}
 
	return PLUGIN_HANDLED;
}
 
// Admin set ammopacks to pocket
public cmd_zpammoset(id, level, cid)
{
	// Check for access flag
	if (!cmd_access(id, level, cid, 3))
		return PLUGIN_HANDLED;
 
	// Retrieve arguments
	static arg[32], ammo[11], player, amount
	read_argv(1, arg, sizeof arg - 1)
	read_argv(2, ammo, sizeof arg - 1)
	amount = str_to_num(ammo)
	player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
 
	// Invalid target
	if (!player) return PLUGIN_HANDLED;
 
	zp_set_user_ammo_packs(player, amount)
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		new PIP[32],Pname[32]
		get_user_name(player, Pname, 31)
		get_user_ip(player, PIP, 31, 1)
		log_to_file(zplog,"[ZP] BankSet: set ^"%d^" pocket ammovalue for (Player ^"%s^") (IP ^"%s^")",amount,Pname,PIP)
		console_print(id,"[ZP] Set ^"%d^" pocket ammovalue for ^"%s^"",amount,Pname,PIP)
	}
 
	return PLUGIN_HANDLED;
}
 
// Admin add ammopacks to pocket
public cmd_zpammoadd(id, level, cid)
{
	// Check for access flag
	if (!cmd_access(id, level, cid, 3))
		return PLUGIN_HANDLED;
 
	// Retrieve arguments
	static arg[32], ammo[11], player, amount
	read_argv(1, arg, sizeof arg - 1)
	read_argv(2, ammo, sizeof arg - 1)
	amount = str_to_num(ammo)
	player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
 
	// Invalid target
	if (!player) return PLUGIN_HANDLED;
 
	zp_set_user_ammo_packs(player, zp_get_user_ammo_packs(player) + amount)
 
	if (get_pcvar_num(cvDeBug) >= 1)
	{
		new PIP[32],Pname[32]
		get_user_name(player, Pname, 31)
		get_user_ip(player, PIP, 31, 1)
		log_to_file(zplog,"[ZP] BankSet: added ^"%d^" pocket ammovalue for (Player ^"%s^") (IP ^"%s^")",amount,Pname,PIP)
		console_print(id,"[ZP] Added ^"%d^" pocket ammovalue for ^"%s^"",amount,Pname,PIP)
	}
 
	return PLUGIN_HANDLED;
}
 
 
// Admin check players bank accounts
public cmd_zpbanklist(id, level, cid)
{
	if (!cmd_access(id, level, cid, 1))
		return PLUGIN_HANDLED
 
	new playerCount
	new players[32], name[32]
 
	get_players(players, playerCount)
 
	console_print(id,"Players Bank Accounts:^n")
 
	new pid, teamName[5]
	for ( new team = 1; team >= 0; team-- ) {
		for ( new x = 0; x < playerCount; x++ ) {
			pid = players[x]
			if ( zp_get_user_zombie(pid) != team ) continue
			get_user_name(pid, name, 31)
 
			teamName[0] = '^0'
			if ( zp_get_user_zombie(pid) == 1 ) copy(teamName, 4, "ZM :")
			else if ( zp_get_user_zombie(pid) == 0 ) copy(teamName, 4, "HU :")
			else copy(teamName, 4, "S :")
 
			console_print(id, "%s%-24s (Bank: ^"%d^") (Pocket: ^"%d^") (WLimit: ^"%d^")", teamName, name, (g_iAmmoPacks[pid] + g_iSessionMovement[pid]), zp_get_user_ammo_packs(pid),  (get_pcvar_num(cvWithdrawLimit) - g_iWithdrawLimit[pid]))
		}
	}
 
	console_print(id, "")
 
	if (get_pcvar_num(cvDeBug) >= 3)
	{
		new PIP[32],Pname[32]
		get_user_name(id, Pname, 31)
		get_user_ip(id, PIP, 31, 1)
		log_to_file(zplog,"[ZP] Bank: (Player ^"%s^") (IP ^"%s^") asked for players bank account list",Pname,PIP)
	}
 
	return PLUGIN_HANDLED;
}
 
public plugin_init()
{
	register_plugin("[ZP] Ammo Bank", "1.4", "danielkza and Lethal")
 
	register_clcmd("say", "Command_Say")
	register_dictionary("zp_bank_ammo.txt")
 
	cvAnnounceTime	= register_cvar("zp_bank_announce_time", "300")
	cvBankMax		= register_cvar("zp_bank_store_max", "50000")
	cvDepositMin	= register_cvar("zp_bank_deposit_min", "25")
	cvWithdrawMax	= register_cvar("zp_bank_withdraw_max", "250")
	cvWithdrawLimit	= register_cvar("zp_bank_withdraw_limit", "750")
	cvBankSaveDays	= register_cvar("zp_bank_savedays", "14")
	cvAutoSave	= register_cvar("zp_bank_autosave", "1")
	cvDeBug	= register_cvar("zp_bank_debug", "1")
 
	register_concmd("playerbank", "cmd_zpbanklist", ADMIN_ALL, " - Show current ammo values for players")
	register_concmd("zp_bankosszeg", "cmd_zpbankset", ADMIN_IMMUNITY, "<name> <amount> - Set player ammobank value")
	register_concmd("zp_bankammo", "cmd_zpbankadd", ADMIN_IMMUNITY, "<name> <amount> - Add ammopacks to player ammobank")
	register_concmd("zp_limbank", "cmd_zpbanklim", ADMIN_IMMUNITY, "<name> <amount> - Set player ammobank withdraw limit status")
	register_concmd("zp_setammo", "cmd_zpammoset", ADMIN_IMMUNITY, "<name> <amount> - Set player pocket ammopacks")
	register_concmd("zp_addammo", "cmd_zpammoadd", ADMIN_IMMUNITY, "<name> <amount> - Add ammopacks to players pocket")
 
	// For temporarily save player stats
	register_logevent("logevent_round_end", 2, "1=Round_End")
 
	Task_Announce()
}
 
 
// For temporarily save player stats
public logevent_round_end()
{
// Prevent this from getting called twice when restarting (bugfix)
	static Float:lastendtime
	if (get_gametime() - lastendtime < 0.5) return;
	lastendtime = get_gametime()
 
	// Temporarily save player stats?
	if (get_pcvar_num(cvAutoSave))
	{
		static id
		for (id = 1; id <= get_maxplayers(); id++)
		{
			// Not connected
			if (!is_user_connected(id))
				continue;
 
			Tmp_Save(id)
		}
	}
}
 
public plugin_end()
{
	// Client's should have already been saved by now (client_disconnect is called before plugin_end).
	// But it costs nothing to be sure.
	new iPlayers[32], iNum
	get_players(iPlayers, iNum)
 
	new iPlayer
	for(new i=0; i < iNum;i++)
	{
		iPlayer = iPlayers[i]
 
		if (strlen(g_szAuth[iPlayer]) > 0)
			SaveClient(iPlayer, g_szAuth[iPlayer])
 
		MemClr(iPlayer)
	}
 
	cleanDB()
}
 
public client_putinserver(id)
{
	static szAuth[32]
	MemClr(id)
	get_user_ip(id, szAuth, 31, 1)
	copy(g_szAuth[id], charsmax(g_szAuth[]), szAuth)
 
	LoadClient(id, szAuth)	
 
	// For temporarily save player stats
	Tmp_Load(id)
}
 
public client_disconnect(id)
{	
	if (strlen(g_szAuth[id]) > 0)
		SaveClient(id, g_szAuth[id])
 
	// For temporarily save player stats
	Tmp_Save(id)
 
	MemClr(id)
}
 
new msgSayText = -1
stock bool:SayText(const receiver, sender, const msg[], any:...)
{
	if(msgSayText == -1)
		msgSayText = get_user_msgid("SayText")
 
	if(msgSayText)
	{	
		if(!sender)
			sender = receiver
 
		static buffer[512]
		vformat(buffer,charsmax(buffer),msg,4)
 
		if(receiver)
			message_begin(MSG_ONE_UNRELIABLE,msgSayText,_,receiver)
		else
			message_begin(MSG_BROADCAST,msgSayText)
 
		write_byte(sender)
		write_string(buffer)
		message_end()
 
		return true
	}
 
	return false
}
 
public Task_Announce()
{
	static iPlayers[32], iNum, iPlayer
	get_players(iPlayers, iNum)
 
	for(new i=0; i < iNum;i++)
	{
		iPlayer = iPlayers[i]
		SayText(iPlayer, iPlayer, ZP_BANK_FMT, LANG_PLAYER, "ZP_BANK_ANNOUNCE")
	}
 
	set_task(get_pcvar_float(cvAnnounceTime), "Task_Announce")
}
 
enum
{
	CMD_DEPOSIT = 1,
	CMD_WITHDRAW,
	CMD_INFO
}
 
public Command_Say(id)
{
   static szArgs[32], szArg1[32], szArg2[32]
   szArgs[0] = '^0'
   szArg1[0] = '^0'
   szArg2[0] = '^0'
   read_args(szArgs, charsmax(szArgs))
   remove_quotes(szArgs)
   parse(szArgs, szArg1, charsmax(szArg1), szArg2, charsmax(szArg2))
 
   new iCommand = 0
   if(equali(szArg1, "/berak"))
      iCommand = CMD_DEPOSIT
   else if(equali(szArg1, "/kivesz"))
      iCommand = CMD_WITHDRAW
   if(equali(szArg1, "berak"))
      iCommand = CMD_DEPOSIT
   else if(equali(szArg1, "kivesz"))
      iCommand = CMD_WITHDRAW
   else if(equali(szArg1, "/bank"))
      iCommand = CMD_INFO
 
   if(iCommand)
   {
      if(iCommand == CMD_INFO)
         Command_Info(id)
      else
      {
         new iValue;
         if (equali(szArg2, "all"))
         {   
            iValue = zp_get_user_ammo_packs(id)
            if(iValue <= 0)
            {
               SayText(id, id, ZP_BANK_FMT, id, "ZP_NO_AMMO_TO_SET")
               return PLUGIN_HANDLED
            }
         }
         else 
         {
            iValue = str_to_num(szArg2)
            if(iValue <= 0)
            {
               SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_INVALID_AMOUNT")
               return PLUGIN_HANDLED
            }
         }         
 
         if(iCommand == CMD_DEPOSIT)
            Command_Deposit(id, iValue)
         else
            Command_Withdraw(id, iValue)
      }
 
      return PLUGIN_HANDLED
 
   }
 
   return PLUGIN_CONTINUE
}
 
Command_Info(id)
{
	SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_LOAD", g_iAmmoPacks[id] + g_iSessionMovement[id], g_szAuth[id], (get_pcvar_num(cvWithdrawLimit) - g_iWithdrawLimit[id]))
}
 
Command_Deposit(id, iDeposit)
{
	new iCurrentAmount = zp_get_user_ammo_packs(id)
	new iDepositMin = get_pcvar_num(cvDepositMin)
	if(!iCurrentAmount)
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_NO_AMMO")
		return
	}
 
	if(iDeposit > iCurrentAmount)
		iDeposit = iCurrentAmount
 
	if(iCurrentAmount < iDepositMin)
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_DMIN", iDepositMin)
		return
	}
 
	if(iDeposit < iDepositMin)
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_DMIN", iDepositMin)
		return
	}
 
	new iCurrent = g_iAmmoPacks[id] + g_iSessionMovement[id]
	new iSum = iCurrent + iDeposit
	new iBankMax = get_pcvar_num(cvBankMax)
 
	if(iBankMax && (iSum > iBankMax))
	{
		iDeposit = iBankMax - iCurrent
		iSum = iBankMax
 
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_MAX", iBankMax)
	}
 
	if(iDeposit)
	{
		g_iSessionMovement[id] += iDeposit
 
		if (g_iWithdrawLimit[id] > abs(iDeposit))
		{
			g_iWithdrawLimit[id] -= abs(iDeposit)
		}
		else
		{
			g_iWithdrawLimit[id] = 0
		}
 
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_DEPOSIT", iDeposit, iSum, (get_pcvar_num(cvWithdrawLimit) - g_iWithdrawLimit[id]))
		zp_set_user_ammo_packs(id, iCurrentAmount - iDeposit)
 
		if (get_pcvar_num(cvDeBug) >= 3)
		{
			new PIP[32],Pname[32]
			get_user_ip(id, PIP, 31, 1)
			get_user_name(id, Pname, 31)
			log_to_file(zplog,"[ZP] Bank: (Player ^"%s^") (IP ^"%s^") deposited ^"%d^" ammovalue to vault",Pname,PIP,iDeposit)
		}
	}
 
	// If autosave enabled save this bullshit to vault
	if (get_pcvar_num(cvAutoSave) == 1)
	{
		SaveClient(id, g_szAuth[id])	
	}
}
 
 
Command_Withdraw(id, iWithdraw)
{
	new iDeposited = g_iAmmoPacks[id] + g_iSessionMovement[id]
	new iWithdrawMax = get_pcvar_num(cvWithdrawMax)
	new iWithdrawLimit = get_pcvar_num(cvWithdrawLimit)
 
	if(!iDeposited)
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_EMPTY")
		return
	}
 
	if(iWithdraw > iDeposited)
		iWithdraw = iDeposited
 
	if(iWithdraw > iWithdrawMax)
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_WMAX", iWithdrawMax)
		return
	}
 
	if((g_iWithdrawLimit[id] > iWithdrawLimit) || ((g_iWithdrawLimit[id] + iWithdraw) > iWithdrawLimit))
	{
		SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_WLIM", iWithdrawLimit, (iWithdrawLimit - g_iWithdrawLimit[id]))
		return
	}
 
	g_iWithdrawLimit[id] += iWithdraw
	g_iSessionMovement[id] -= iWithdraw
 
	SayText(id, id, ZP_BANK_FMT, id, "ZP_BANK_WITHDRAW", iWithdraw, iDeposited - iWithdraw, (get_pcvar_num(cvWithdrawLimit) - g_iWithdrawLimit[id]))
	zp_set_user_ammo_packs(id, zp_get_user_ammo_packs(id) + iWithdraw)
	if (get_pcvar_num(cvDeBug) >= 3)
	{
		new PIP[32],Pname[32]
		get_user_ip(id, PIP, 31, 1)
		get_user_name(id, Pname, 31)
		log_to_file(zplog,"[ZP] Bank: (Player ^"%s^") (IP ^"%s^") withdrawed ^"%d^" ammovalue from vault",Pname,PIP,iWithdraw)
	}
 
	// If autosave enabled save this bullshit to vault
	if (get_pcvar_num(cvAutoSave) == 1)
	{
		SaveClient(id, g_szAuth[id])	
	}
}
 
stock SayText(const id, const input[], any:...) 
{ 
    new count = 1, players[32] 
    static msg[191] 
    vformat(msg, 190, input, 3) 
 
    replace_all(msg, 190, "!g", "^4") // Green Color 
    replace_all(msg, 190, "!y", "^1") // Default Color 
    replace_all(msg, 190, "!t", "^3") // Team Color 
 
    if (id) players[0] = id; else get_players(players, count, "ch")  
    { 
        for ( new i = 0; i < count; i++ ) 
        { 
            if ( is_user_connected(players[i]) ) 
            { 
                message_begin(MSG_ONE_UNRELIABLE, SayText, _, players[i]) 
                write_byte(players[i]); 
                write_string(msg); 
                message_end(); 
            } 
        } 
    } 
}