new const NINTENDOMOD_MARIO_PLUGIN[] = "Nintendo Mod - Mario"
new const NINTENDOMOD_MARIO_VERSION[] = "1.2"
new const NINTENDOMOD_MARIO_AUTHOR[] = "Soloist"

/*
	Passive: High Jump
		* Higher Gravity as level increases.
	Skill 1: Super Jump
		* Has the ability to muti-jump.
	Skill 2: Hammer Time
		* Knife does more damage, Also has hammer model for knife.
	Skill 3: Doctor Mario
		* Constantly giving out pills healing yourself and everyone around you every few second.
	PowerUp: Star
		* Like the Star from Super Mario, when the players touches an enemy he is killed.

	Future Plans
		Add CVARS for values

	Written By Soloist
	Version 1.2
	Last Updated On 08/26/06

	*************************************************************************************

	Changelog
		Version 1.2
			* When star is on Mario is now Godlike
		Version 1.1
			* Fixed Doctor Mario not healing teammates
		Version 1.0
			* Release of the plugin
*/

#include <amxmodx>
#include <fun>
#include <fakemeta>
#include <nintendomod>

new const Float:MARIO_HIGHJUMPGRAV[11] = {775.0, 750.0, 725.0, 700.0, 675.0, 650.0, 625.0, 600.0, 500.0, 400.0, 350.0};
new const MARIO_SUPERJUMPTIMES[3] = {1, 2, 3};
new const MARIO_HAMMERTIMEDMG[3] = {25, 50, 75}
new const Float:MARIO_DOCTERMARIOHEALTH[3] = {1.0, 2.0, 3.0}

new charName[] = "Mario";
new passiveName[] = "High Jump";
new skill1Name[] = "Super Jump";
new skill2Name[] = "Hammer Time";
new skill3Name[] = "Doctor Mario";
new powerupName[] = "Star";
new initName[] = "Mario_Init";
new keyDownName[] = "Mario_Star";

new passiveHelp[] = "Lower Gravity as level increases.";
new skill1Help[] = "Has the ability to muti-jump.";
new skill2Help[] = "Knife does more damage, Also has hammer model for knife.";
new skill3Help[] = "Constantly giving out pills healing yourself and everyone around you every few second.";
new powerupHelp[] = "Like the Star from Super Mario, when the players touches an enemy he is killed.";

new PlayerLevel[33];
new PlayerSkill1[33];
new PlayerSkill2[33];
new PlayerSkill3[33];
new PlayerPowerUp[33];

new knife_sounds[9][] =
{
    "weapons/knife_deploy1.wav",
    "weapons/knife_hit1.wav",
    "weapons/knife_hit2.wav",
    "weapons/knife_hit3.wav",
    "weapons/knife_hit4.wav",
    "weapons/knife_hitwall1.wav",
    "weapons/knife_slash1.wav",
    "weapons/knife_slash2.wav",
    "weapons/knife_stab.wav"
};

new jumpNum[33] = 0;
new bool:doJump[33] = false;
new bool:Star[33];

new healthSpr;

public plugin_init()
{
	if(is_plugin_loaded("Nintendo Mod") == -1)
	{
		server_print("**********************************");
		server_print("*** Nintendo Mod is not loaded ***");
		server_print("**********************************");
		pause("ae");
		return;
	}

	register_plugin(NINTENDOMOD_MARIO_PLUGIN, NINTENDOMOD_MARIO_VERSION, NINTENDOMOD_MARIO_AUTHOR);

	register_cvar("NintendoMod_Mario_Version", NINTENDOMOD_MARIO_VERSION, FCVAR_SERVER|FCVAR_SPONLY);

	register_event("ResetHUD", "ResetHUD", "b");

	register_event("Damage", "Mario_Damage", "b", "2!0");
	register_event("CurWeapon", "Mario_HammerTime","be","1=1");

	register_forward(FM_PlayerPreThink, "Mario_SuperJumpPre");
	register_forward(FM_PlayerPostThink, "Mario_SuperJumpPost");
	register_forward(FM_EmitSound, "Mario_HammerSound");
	register_forward(FM_Touch, "Mario_StarTouch");

	Nintendo_RegisterChar(charName, passiveName, skill1Name, skill2Name, skill3Name, powerupName, initName);
	Nintendo_RegisterHelp(charName, passiveHelp, skill1Help, skill2Help, skill3Help, powerupHelp);
	Nintendo_RegisterKeyDown(charName, keyDownName);

	register_srvcmd(initName, initName);
	register_srvcmd(keyDownName, keyDownName);
}

public plugin_precache()
{
	engfunc(EngFunc_PrecacheSound, "nintendomod/mario_hammer.wav");
	engfunc(EngFunc_PrecacheSound, "nintendomod/mario_hammertime.wav");
	engfunc(EngFunc_PrecacheModel, "models/nintendomod/mario_knife.mdl");
	healthSpr = engfunc(EngFunc_PrecacheModel, "sprites/nintendomod/mario_health.spr");
}

public client_connect(id)
{
	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	InitPlayer(id);

	return PLUGIN_CONTINUE;
}

public client_disconnect(id)
{
	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	InitPlayer(id);
	remove_task(id);

	return PLUGIN_CONTINUE;
}

public InitPlayer(id)
{
	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	PlayerLevel[id] = 0;
	PlayerSkill1[id] = 0;
	PlayerSkill2[id] = 0;
	PlayerSkill3[id] = 0;
	PlayerPowerUp[id] = 0;

	return PLUGIN_CONTINUE;
}

public Mario_Init()
{
	new temp[33];
	read_argv(1, temp, 32);
	new id = str_to_num(temp);

	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	read_argv(2, temp, 32);
	new index  = str_to_num(temp);

	if(index == 0)
	{
		read_argv(3, temp, 32);
		new level = str_to_num(temp);
		read_argv(4, temp, 32);
		new skill1 = str_to_num(temp);
		read_argv(5, temp, 32);
		new skill2 = str_to_num(temp);
		read_argv(6, temp, 32);
		new skill3 = str_to_num(temp);
		read_argv(7, temp, 32);
		new powerup = str_to_num(temp);

		PlayerLevel[id] = level;
		PlayerSkill1[id] = skill1;
		PlayerSkill2[id] = skill2;
		PlayerSkill3[id] = skill3;
		PlayerPowerUp[id] = powerup;
	}
	else
	{
		read_argv(3, temp, 32);
		new value = str_to_num(temp);

		switch(index)
		{
			case 1: PlayerLevel[id] = value;
			case 2: PlayerSkill1[id] = value;
			case 3: PlayerSkill2[id] = value;
			case 4: PlayerSkill3[id] = value;
			case 5: PlayerPowerUp[id] = value;
		}
	}

	ResetHUD(id);

	return PLUGIN_CONTINUE;
}

public ResetHUD(id)
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	Star[id] = false;

	Mario_HighJump(id);
	Mario_DocterMario(id);

	return PLUGIN_CONTINUE;
}

public Mario_Damage(id)
{
	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	new weapon, bodypart, attacker = get_user_attacker(id, weapon, bodypart)
	new headshot = bodypart == 1 ? 1 : 0

	if(!Nintendo_HasChar(attacker, charName) || !Nintendo_IsValidPlayer(attacker))
		return PLUGIN_HANDLED;

	else if(PlayerSkill2[attacker] > 0)
	{
		if(weapon == CSW_KNIFE)
			Mario_HammerDmg(id, attacker, headshot);
	}

	return PLUGIN_CONTINUE;
}

public Mario_HighJump(id) // Passive
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	Nintendo_SetGravity(id, MARIO_HIGHJUMPGRAV[PlayerLevel[id]]);

	return PLUGIN_CONTINUE;
}

public Mario_SuperJumpPre(id)
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName)  || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerSkill1[id] > 0)
	{
		new newButton = pev(id, pev_button);
		new oldButton = pev(id, pev_oldbuttons)
		if((newButton & IN_JUMP) && !(pev(id, pev_flags) &FL_ONGROUND) && !(oldButton & IN_JUMP))
		{
			if(jumpNum[id] < MARIO_SUPERJUMPTIMES[PlayerSkill1[id]-1])
			{
				doJump[id] = true
				jumpNum[id]++
				return PLUGIN_CONTINUE
			}
		}
		if((newButton & IN_JUMP) && (pev(id, pev_flags) &FL_ONGROUND))
		{
			jumpNum[id] = 0
			return PLUGIN_CONTINUE
		}
	}
	return PLUGIN_CONTINUE
}

public Mario_SuperJumpPost(id)
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName)  || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerSkill1[id] > 0)
	{
		if(doJump[id] == true)
		{
			new Float:velocity[3]
			pev(id, pev_velocity, velocity)
			velocity[2] = random_float(265.0, 285.0)
			set_pev(id, pev_velocity, velocity)
			doJump[id] = false
			return PLUGIN_CONTINUE
		}
	}
	return PLUGIN_CONTINUE
}

public Mario_HammerTime(id) // Skill 2
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerSkill2[id] > 0)
	{
		new clip, ammo, weapon = get_user_weapon(id, clip, ammo)

		if(weapon == CSW_KNIFE)
			set_pev(id, pev_viewmodel, engfunc(EngFunc_AllocString, "models/nintendomod/mario_knife.mdl"))
	}

	if(Star[id] && PlayerPowerUp[id] == 1)
	{
		engclient_cmd(id, "weapon_knife");
		Nintendo_SetSpeed(id, 375.0);
	}

	return PLUGIN_CONTINUE;
}

public Mario_HammerSound(entity, channel, const sound[])
{
	if(!Nintendo_Active() || !Nintendo_HasChar(entity, charName) || !Nintendo_IsValidPlayer(entity))
		return PLUGIN_HANDLED;

	if(PlayerSkill2[entity] > 0)
	{
		if(pev_valid(entity) && Nintendo_IsValidPlayer(entity))
		{
			if(equal(sound, knife_sounds[0]))
			{
				emit_sound(entity, channel, "nintendomod/mario_hammertime.wav", 1.0, ATTN_NORM, 0, PITCH_NORM);
				return FMRES_SUPERCEDE;
			}

			for(new i = 1; i < 9; i++)
			{
				if(equal(sound, knife_sounds[i]))
				{
					emit_sound(entity, channel, "nintendomod/mario_hammer.wav", 1.0, ATTN_NORM, 0, PITCH_NORM);
					return FMRES_SUPERCEDE;
				}
			}
		}
	}
	return FMRES_IGNORED;
}

public Mario_HammerDmg(id, attacker, headshot) // Skill 2
{
	if(!Nintendo_Active() || !Nintendo_HasChar(attacker, charName) || !Nintendo_IsValidPlayer(attacker)|| !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerSkill2[attacker] > 0)
	{
		if(Nintendo_TeamKill(id, attacker))
			Nintendo_ExtraDamage(attacker, id, MARIO_HAMMERTIMEDMG[PlayerSkill2[attacker] - 1], "Hammer Time", headshot);
	}

	return PLUGIN_CONTINUE;
}
public Mario_DocterMario(id) // Skill 3
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerSkill3[id] > 0)
	{
		new Float:newHealth, curHealth;

		curHealth = pev(id, pev_health);

		if(curHealth < 100.0)
		{
			newHealth = curHealth + MARIO_DOCTERMARIOHEALTH[PlayerSkill3[id] - 1];
			if(newHealth > 100.0) newHealth = 100.0;

			Nintendo_SetHealth(id, newHealth, false);
			Mario_DoctorMarioSprite(id);
		}

		new players[32], num, player;
		get_players(players, num);
		for(new i = 0; i <= num; i++)
		{
			player = players[i];
			if(Nintendo_IsValidPlayer(player))
			{
				if((get_user_team(id) == get_user_team(player)) && (id != player))
				{
					new healer[3], healed[3];

					get_user_origin(id, healer);
					get_user_origin(player, healed);
					if(get_distance(healer, healed) <= 500)
					{
						curHealth = pev(player, pev_health);

						if(curHealth < 100.0)
						{
							newHealth = curHealth + MARIO_DOCTERMARIOHEALTH[PlayerSkill3[id] - 1];
							if(newHealth > 100.0) newHealth = 100.0;
							Nintendo_SetHealth(player, newHealth, false);
							Mario_DoctorMarioSprite(player);
						}
					}
				}
			}
		}

		set_task(2.0,"Mario_DocterMario", id)
	}

	return PLUGIN_CONTINUE;
}

public Mario_DoctorMarioSprite(id)
{
	if(!Nintendo_Active() || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	message_begin(MSG_ALL, SVC_TEMPENTITY)
	write_byte(124)
	write_byte(id)
	write_coord(50)
	write_short(healthSpr)
	write_short(3)
	message_end()

	return PLUGIN_CONTINUE;
}

public Mario_Star()
{
	new temp[6]
	read_argv(1, temp, 5)
	new id = str_to_num(temp)

	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	if(PlayerPowerUp[id] == 1)
	{
		Nintendo_PowerUpUsed(id, 1, 30);

		Star[id] = true;

		set_user_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25);
		Nintendo_SetSpeed(id, 375.0);
		engclient_cmd(id, "weapon_knife");
		set_pev(id, pev_takedamage, 0.0);

		set_task(4.0, "Mario_StarReset", id);
	}

	return PLUGIN_CONTINUE;
}

public Mario_StarTouch(victim, attacker)
{
	if(!Nintendo_Active() || !Nintendo_HasChar(attacker, charName) || !Nintendo_IsValidPlayer(victim) || !Nintendo_IsValidPlayer(attacker))
		return PLUGIN_HANDLED;

	if(Star[attacker])
	{
		if(Nintendo_TeamKill(victim, attacker))
			Nintendo_ExtraDamage(attacker, victim, 200, "Star", 0);
	}

	return PLUGIN_CONTINUE;
}

public Mario_StarReset(id)
{
	if(!Nintendo_Active() || !Nintendo_HasChar(id, charName) || !Nintendo_IsValidPlayer(id))
		return PLUGIN_HANDLED;

	Star[id] = false;
	set_user_rendering(id);
	set_pev(id, pev_takedamage, 2.0);

	new weapons[32], numWeapons, weaponname[33];
	get_user_weapons(id, weapons, numWeapons);
	get_weaponname(weapons[0], weaponname, 32);
	engclient_cmd(id, weaponname);

	return PLUGIN_CONTINUE;
}
