Source:
/* ============================================================================ */
/* */
/* naix.sp */
/* (c) 2009 Stinkyfax */
/* */
/* Description is availible at site: */
/* http://war3source.com/index.php?topic=30.msg191#new */
/* */
/* ============================================================================ */
#include <sourcemod>
#include <sdktools_functions> //For teleport
#include <sdktools_sound> //For sound effect
#include "War3Source/War3Source_Interface"
// Colors
#define COLOR_DEFAULT 0x01
#define COLOR_LIGHTGREEN 0x03
#define COLOR_GREEN 0x04 // DOD = Red
//Skills Settings
new bool:Infest_Ignore_Immunity = false;
#define RAGE_COOLDOWN 20.0
new Float:g_Skill0_1[4] = { 0.2, 0.3, 0.35, 0.40 }; //infest settings
//Skill 1_1 really has 5 settings, so it's not a mistake
new g_Skill1_1[5] = { 30, 50, 70, 85, 100 }; //Increases Maximum health
new Float:g_Skill2_1[4] = { 0.04, 0.05, 0.06, 0.07 }; //Feast ratio
new Float:g_Skill3_1[4] = { 1.2, 1.3, 1.4, 1.5 }; //Rage Attack Rate
new Float:g_Skill3_2[4] = { 2.0, 2.5, 2.8, 3.0 }; //Rage duration
//End of skill Settings
//Ultimate temporary vars
new Float:g_fLastUlti[65]; //Stores when last ultimate was made for each player
new g_iOffs_ActiveWeapon; //offset of active weapon
new g_iOffs_NextPrimaryAttack; //offset of ... well quite obvious
new g_iWeaponRateQueue[65][2];
new g_iWeaponRateQueueLength;
new Float:g_fMulti[65], Float:g_fDuration[65];
//end of ultimate vars
new raceID;
public Plugin:myinfo =
{
name = "War3Source Race - Lifestealer",
author = "Stinkyfax",
description = "N'aix - the embodiment of lust and greed, bent on stealing the life of every living creature he encounters.",
version = "1.0",
url = "http://sugardas.lt/~jozh/"
};
public OnWar3PluginReady()
{
raceID=War3_CreateRace("Lifestealer","naix","Your new name - N'aix!",
"You will be N'aix in your next life.",
"Infest","The Lifestealer tears its way into the unfortunate body of a target unit, consume it and come to out killing the target. Regains health from the infested unit.",
"Blood Bath","Increases maximum health of the N'aix, making all his other skils be worthfy.",
"Feast","Regenerates a portion of enemy's current HP.",
"Rage","N'aix goes into a maddened rage, gaining increased attack speed.");
}
public OnPluginStart()
{
HookEvent("player_death",PlayerKill);
HookEvent("player_spawn",PlayerSpawn);
HookEvent("weapon_fire",WeaponFireEvent, EventHookMode_Pre);
g_iOffs_ActiveWeapon = FindSendPropOffs("CBasePlayer","m_hActiveWeapon");
g_iOffs_NextPrimaryAttack = FindSendPropOffs("CBaseCombatWeapon","m_flNextPrimaryAttack");
}
stock bool:IsRace(client) {
return War3_GetRace(client)==raceID;
}
/*
* I suggest this stock will be depricated soon as
* Give HP is supposed to be part of War3 Interface
*/
stock GiveHP(client, amount) {
new oldHp = GetClientHealth(client);
new health = oldHp + amount;
if(health>War3_GetMaxHP(client))
health=War3_GetMaxHP(client);
if(health>oldHp) {
SetEntityHealth(client, health);
return health-oldHp; //how much hp added
}
return 0; //didn't add anything
}
public OnMapStart() { //some precaches
PrecacheSound("npc/zombie/zombie_pain2.wav");
}
public OnWar3TakeDamage(victim,client,inflictor,Float:damage,damagetype) {
new chance=RoundFloat(100.0*War3_ChanceModifier(client,inflictor,damagetype));
if(GetRandomInt(1,100)>chance)
return;
if(!IsRace(client))
return;
//We check if attacker is a player (it might be world, c4, etc)
//Also check if both victim and attacker are alive since it is essential for skill
if( (client<0) || (client>GetMaxClients()) || (!IsPlayerAlive(client)) || (!IsPlayerAlive(victim)) )
return;
new level = War3_GetSkillLevel(client, raceID, 2);
if(level<=0)
return; //Of course don't run skill if we don't have skill
//Now apply the skill since all the checks are passed
new targetHp = GetClientHealth(victim);
new Float:ratio = g_Skill2_1[level-1];
new restore = RoundToNearest( float(targetHp) * ratio );
GiveHP(client, restore);
}
public WeaponFireEvent(Handle:event,const String:name[],bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event,"userid"));
if(!IsRace(client))
return;
if( (g_fDuration[client] < GetEngineTime()) || ( g_fMulti[client] < 1.0 ) )
return;
new ent = GetEntDataEnt2(client,g_iOffs_ActiveWeapon);
if(ent != -1)
{
//fill the stack for next frame
g_iWeaponRateQueue[g_iWeaponRateQueueLength][0] = ent;
g_iWeaponRateQueue[g_iWeaponRateQueueLength++][1] = client;
}
}
public OnGameFrame() {
if(g_iWeaponRateQueueLength<=0)
return;
decl ent, client, Float:time;
new Float:enginetime = GetGameTime();
for(new i = 0; i < g_iWeaponRateQueueLength; i++) if(IsValidEntity(g_iWeaponRateQueue[i][0])) {
ent = g_iWeaponRateQueue[i][0];
client = g_iWeaponRateQueue[i][1];
new Float:multi = 1.0/g_fMulti[client];
time = (GetEntDataFloat(ent,g_iOffs_NextPrimaryAttack) - enginetime) * multi;
SetEntDataFloat(ent,g_iOffs_NextPrimaryAttack,time + enginetime,true);
}
g_iWeaponRateQueueLength = 0;
}
public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) {
new client = GetClientOfUserId(GetEventInt(event,"userid"));
if(!IsRace(client))
return Plugin_Continue;
if(client>0 && client < 65)
g_fLastUlti[client]=0.0;
new level = War3_GetSkillLevel(client, raceID, 1);
if(level<0)
level=0;
War3_SetMaxHP(client, War3_GetMaxHP(client) +
g_Skill1_1[level]);
War3_ChatMessage(client, "Your Maximum Health now is %c%d%c.",
COLOR_LIGHTGREEN, War3_GetMaxHP(client), COLOR_DEFAULT);
return Plugin_Continue;
}
public Action:PlayerKill(Handle:event,const String:empty[],bool:dontBroadcast)
{
new userid=GetClientOfUserId(GetEventInt(event,"userid"));
new attacker=GetClientOfUserId(GetEventInt(event,"attacker"));
if(attacker<=0)
return Plugin_Continue;
if(!IsRace(attacker))
return Plugin_Continue;
new iSkillLevel=War3_GetSkillLevel(attacker,raceID,0);
if(iSkillLevel<=0)
return Plugin_Continue;
//check the users
if( (userid<0) || (userid>GetMaxClients()) || (GetClientTeam(userid) == GetClientTeam(attacker)) )
return Plugin_Continue;
decl String:name[50];
GetClientName(userid, name, sizeof(name));
if(!Infest_Ignore_Immunity) { //Check for ultimate immunity of victim
if(War3_GetImmunity(userid, War3Immunity:Immunity_Ultimates) == 1) {
War3_ChatMessage(attacker, "%c%s%c's Immunity prevented you from %cInfesting%c", COLOR_GREEN, name,
COLOR_DEFAULT, COLOR_LIGHTGREEN, COLOR_DEFAULT);
return Plugin_Continue; //Do not run skill because of Immunity
}
}
//All conditions are fine, now run the ultimate
new Float:fRatio=g_Skill0_1[iSkillLevel-1]; //so we got the hp ration now
new targetMaxHealth=War3_GetMaxHP(userid);
decl Float:location[3];
GetClientAbsOrigin(userid,location);
TeleportEntity(attacker, location, NULL_VECTOR, NULL_VECTOR);
new addHealth = RoundToNearest(float(targetMaxHealth) * fRatio);
addHealth = GiveHP(attacker, addHealth);
War3_ChatMessage(attacker, "%c%s%c's flesh has increased your health by %c%d%c",
COLOR_GREEN, name, COLOR_DEFAULT, COLOR_LIGHTGREEN, addHealth, COLOR_DEFAULT);
//Effects?
EmitAmbientSound("npc/zombie/zombie_pain2.wav",location);
return Plugin_Continue; //The happy end (skill has worked successfuly)
}
public OnUltimateCommand(client,race,bool:pressed)
{
new userid=GetClientUserId(client);
if(race==raceID && pressed && userid>1 && IsPlayerAlive(client))
{
new ultLevel=War3_GetSkillLevel(client,race,3);
if(ultLevel>0)
{
if(g_fLastUlti[client]+RAGE_COOLDOWN > GetEngineTime() ) {
PrintCenterText(client,"COOLDOWN LEFT: %.1f SECONDS", g_fLastUlti[client]+RAGE_COOLDOWN-GetEngineTime());
return;
}
/* Since this moment we assume ultimate is being run and not cancelled */
g_fLastUlti[client]=GetEngineTime();
g_fMulti[client]=g_Skill3_1[ultLevel-1];
g_fDuration[client]=GetEngineTime()+g_Skill3_2[ultLevel-1];
War3_ChatMessage(client,
"You have enabled %cRage%c for %c%.1f%c seconds and extra attack speed +%.0f percent",
COLOR_GREEN, COLOR_DEFAULT, COLOR_LIGHTGREEN, g_Skill3_2[ultLevel-1],
COLOR_DEFAULT, (g_Skill3_1[ultLevel-1]-1.0)*100.0 );
}
}
}
Race is tested and working.
Requires at least 0.9.1.5 version