#pragma semicolon 1 ///WE RECOMMEND THE SEMICOLON
#include <sourcemod>
#include "W3SIncs/War3Source_Interface"
public Plugin:myinfo =
{
name = "War3Source Race - Necrolyte",
author = "Frans Fuchs - Vulpone",
description = "The Necrolyte race for War3Source.",
version = "1.0.0.0",
url = "www.wcs-lagerhaus.de"
};
/*
##############################
This race is based on DotA's (never played it, but the races seem fun) Rotund'Jere - The Necrolyte.
I only re-did it for w3s.
Nevertheless, enjoy it. If you encounter any errors or..badly-coded areas, please let me know.
Also, the permanent damage (aura) is based on Soul Reaper's "Presence". I didn't copy-paste it, I just used it as inspiration.
YES, aura = COPY-Paste and edited Soul Reaper. TTYL.
##############################
*/
new SKILL_PULSE, SKILL_AURA, SKILL_SADIST, U_SCYTHE;
new thisRaceID;
new BeamSprite, HaloSprite, GlowSprite;
new BeamSprite2, HaloSprite2;
new Handle:ab0CooldownCvar;
new Handle:ultCooldownCvar;
new MoneyOffsetCS;
new g_iExplosionModel;
//skills-related arrays go here
//skill #1: death pulse - recommended cooldown: 20-30 seconds.
new DealDamageArr[5]={ 0, 10, 20, 30, 30 }; //always remember: War3_DealDamage doesn't accept floats as damage value.
new HealAmountArr[5]={ 0, 10, 20, 30, 40 };
//skill #2: heartstopper aura - it passively damages nearby enemies, so no cooldown
new PresenseSkipAmount[5]={0,4,3,2,1}; //skip per .5 seconds
new Float:PresenceRange=250.0;
new PresenceSkipPlayer[MAXPLAYERS];
//skill #3: sadist - passive again, so no cooldown..
new ManaGain[5]={0, 200, 400, 500, 700};
//skill #4: ult: reapers scythe - recommended cooldown: 30 seconds..
//mana-percentage and usage-based calculations are below..
//sounds
new String:ab0a[]="weapons/explode5.wav"; //ability0 consists of 3 sounds played at once. sorry.
new String:ab0b[]="war3source/necrolyte/ability2.wav"; // used for Ultimate as well.
new String:ab0c[]="war3source/necrolyte/ability1.wav";
new String:aura1[]="player/pl_pain5.wav";
new String:aura2[]="player/heartbeat1.wav";
new String:aura3[]="war3source/necrolyte/warstomp.mp3";
new String:manaGained[]="war3source/necrolyte/TaurenWarcry1.mp3";
new String:ulti[]="war3source/necrolyte/die.wav";
public OnWar3LoadRaceOrItemOrdered(num)
{
if(num == 200)
{
thisRaceID=War3_CreateNewRace("Necrolyte","necrolyte");
SKILL_PULSE=War3_AddRaceSkill(thisRaceID,"Death Pulse","The Necrolyte releases a wave of death from the core of his being, dealing damage to enemies and healing allies.(+ability)
Heal 10-40 HP/Deal 10-30 damage. Uses 100 mana.",false,4);
SKILL_AURA=War3_AddRaceSkill(thisRaceID,"Heartstopper Aura","The deathly air stills the hearts of his opponents, causing them to lose a percentage of their max health over time.",false, 4);
SKILL_SADIST=War3_AddRaceSkill(thisRaceID,"Sadist","Reveling in death and pain, the Necrolyte gains mana back for killing units.
Gain 200-700 extra mana per kill!",false,4);
U_SCYTHE=War3_AddRaceSkill(thisRaceID,"Reaper's Scythe","Brings a target to full realization of its own mortality, dealing damage based on how much life the target is missing.
Uses 80-50% Mana!",false,4);
War3_CreateRaceEnd(thisRaceID);
}
}
public OnPluginStart()
{
ab0CooldownCvar=CreateConVar("war3_necrolyte_abi_cooldown","25.0","Cooldown duration for the Necrolyte's ability.");
ultCooldownCvar=CreateConVar("war3_necrolyte_ult_cooldown","25.0","Cooldown duration for the Necrolyte's Ultimate.");
MoneyOffsetCS=FindSendPropInfo("CCSPlayer","m_iAccount");
CreateTimer(1.5,PresenceLoop,_,TIMER_REPEAT);
}
public OnMapStart()
{
BeamSprite=PrecacheModel("materials/sprites/vortring1.vmt");
GlowSprite=PrecacheModel("materials/effects/combinemuzzle2_noz.vmt");
HaloSprite=PrecacheModel("materials/sprites/smoke.vmt");
g_iExplosionModel = PrecacheModel("materials/effects/fire_cloud1.vmt");
HaloSprite2 = PrecacheModel( "materials/sprites/halo01.vmt" );
BeamSprite2 = PrecacheModel( "materials/sprites/lgtning.vmt");
War3_PrecacheSound(ab0a);
War3_PrecacheSound(ab0b);
War3_PrecacheSound(ab0c);
War3_PrecacheSound(aura1);
War3_PrecacheSound(aura2);
War3_PrecacheSound(aura3);
War3_PrecacheSound(manaGained);
War3_PrecacheSound(ulti);
}
stock GetMoney(player)
{
return GetEntData(player,MoneyOffsetCS);
}
stock SetMoney(player,money)
{
SetEntData(player,MoneyOffsetCS,money);
}
public OnAbilityCommand(client,ability,bool:pressed)
{
if(War3_GetRace(client)==thisRaceID && ability==0 && pressed && ValidPlayer(client, true))
{
new skilllvl = War3_GetSkillLevel(client,thisRaceID,SKILL_PULSE);
if(skilllvl > 0)
{
if(War3_SkillNotInCooldown(client,thisRaceID,SKILL_PULSE,true))
{
new money = GetMoney(client);
//ability uses 100 mana for every person affected
if(money > 200)
{
SetMoney(client, money-300);
War3_CooldownMGR(client,GetConVarFloat(ab0CooldownCvar),thisRaceID,SKILL_PULSE,true,true,true);
new ShouterTeam = GetClientTeam(client);
new hpReg = HealAmountArr[skilllvl];
new pulseDamage = DealDamageArr[skilllvl];
new Float:ShouterPos[3];
GetClientAbsOrigin(client,ShouterPos);
new Float:posVec[3];
GetClientAbsOrigin(client,posVec);
new Float:endVec[3];
GetClientAbsOrigin(client, endVec);
for(new i=1;i<=MaxClients;i++)
{
if(ValidPlayer(i,true))
{
new Float:TargetPos[3];
GetClientAbsOrigin(i,TargetPos);
if(GetVectorDistance(ShouterPos,TargetPos)<= 400.0)
{
if(GetClientTeam(i)==ShouterTeam)
{
War3_HealToMaxHP(i, hpReg);
if(i != client)
{
SetMoney(client, money-100);
}
W3FlashScreen(i,RGBA_COLOR_GREEN, 0.8, 0.5);
PrintToChat(i,"\x04[War3Source] - Necrolyte: \x01You have been affected by \x03Death Pulse\x01. Gained %i hp",hpReg);
TE_Start("Bubbles");
TE_WriteVector("m_vecMins", TargetPos);
TE_WriteVector("m_vecMaxs", TargetPos);
TE_WriteFloat("m_fHeight", 00.0);
TE_WriteNum("m_nModelIndex", HaloSprite);
TE_WriteNum("m_nCount", 75);
TE_WriteFloat("m_fSpeed", 2.0);
TE_SendToAll();
}
else if(GetClientTeam(i) != ShouterTeam)
{
if(!W3HasImmunity(i, Immunity_Skills))
{
War3_DealDamage(i, pulseDamage, client, DMG_BURN, "pulse", W3DMGORIGIN_SKILL);
PrintToChat(i,"\x04[War3Source] - Necrolyte: \x01You have been affected by \x03Death Pulse\x01. Lost %i hp",pulseDamage);
EmitSoundToAll(ab0a, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL); //boom when it hits
posVec[2] += 120; //sprite goes up
//let's make a fun square-glow effect.
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 0.5, 150);
TE_SendToAll();
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 0.5, 130);
TE_SendToAll();
posVec[0] += 50; //Sprite goes right
posVec[1] += 50; //Sprite goes to upper right corner
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 1.0, 150);
TE_SendToAll();
posVec[0] -= 100; //sprite goes same distance to left (it's still up)
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 1.0, 150);
TE_SendToAll();
posVec[1] -= 100; //sprite goes to lower left corner
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 1.0, 150);
TE_SendToAll();
posVec[0] += 100; //sprite goes to lower right corner
TE_SetupGlowSprite( posVec, GlowSprite, 1.4, 1.0, 150);
TE_SendToAll();
//now that the effect is done, let's set the vector calculations back to normal!
GetClientAbsOrigin(client,posVec);
}
}
}
}
}
EmitSoundToAll(ab0b, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
EmitSoundToAll(ab0c, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
//time for the effects!
new Float:dir[3]={0.0,0.0,0.0};
new particle = CreateParticleSystem(client, "mini_fireworks", true, "forward", dir);
CreateTimer( 1.0, Timer_RemoveEntity, particle );
endVec[2] += 120;
TE_SetupBeamPoints(posVec, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 2.0, {175,201,255,222}, 20);
TE_SendToAll();
TE_SetupBeamPoints(posVec, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 2.0, {175,201,255,222}, 20);
TE_SendToAll();
posVec[2]+=120;
TE_SetupGlowSprite(posVec, GlowSprite, 1.4, 0.8, 200); //stacking 3 so the top of the beampoint isnt visible
TE_SendToAll();
TE_SetupGlowSprite(posVec, GlowSprite, 1.4, 0.8, 200);
TE_SendToAll();
TE_SetupGlowSprite(posVec, GlowSprite, 1.4, 0.8, 200);
TE_SendToAll();
posVec[2] -= 108;
TE_SetupBeamRingPoint(posVec, 1.0, 400.0, BeamSprite, HaloSprite, 0, 15, 1.2, 5.8, 4.0, {103,138,255,222}, 20, 0);
TE_SendToAll(0.2);
TE_SetupBeamRingPoint(posVec, 1.0, 400.0, BeamSprite, HaloSprite, 0, 15, 1.2, 5.8, 4.0, {103,138,255,222}, 20, 0);
TE_SendToAll(0.4);
}
else
{
PrintHintText(client, "You need at least 200 Mana!");
}
}
}
}
}
public Action:PresenceLoop(Handle:h,any:a)
{
if(thisRaceID>0){
decl team;
decl skilllevel;
for(new client=1;client<=MaxClients;client++)
{
if(PresenceSkipPlayer[client]>0)
{
PresenceSkipPlayer[client]--;
}
if(PresenceSkipPlayer[client]<=0 && ValidPlayer(client,true) && War3_GetRace(client)==thisRaceID)
{
skilllevel=War3_GetSkillLevel(client,thisRaceID,SKILL_AURA);
if(skilllevel > 0)
{
team=GetClientTeam(client);
new Float:iVec[3];
GetClientAbsOrigin(client, iVec);
for(new target=1;target<=MaxClients;target++)
{
if(ValidPlayer(target,true) && GetClientTeam(target)!=team)
{
new Float:targetVec[3];
GetClientAbsOrigin(target, targetVec);
if(!W3HasImmunity(target,Immunity_Skills))
{
if(GetVectorDistance(iVec,targetVec)<PresenceRange)
{
EmitSoundToAll(aura1, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
EmitSoundToAll(aura2, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
EmitSoundToAll(aura3, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, 0.5); //volume/2 because it was too loud..
PresenceSkipPlayer[client]=PresenseSkipAmount[skilllevel];
War3_DealDamage(target,3,client,_,"aura",_,W3DMGTYPE_TRUEDMG);
new Float:dir[3]={0.0,0.0,0.0};
new particle = CreateParticleSystem(client, "env_fire_small_coverage_c", true, "forward", dir);
CreateTimer( 1.0, Timer_RemoveEntity, particle );
iVec[2]+=35.0;
targetVec[2]+=35.0;
new dice = GetRandomInt(1,10);
//RANDOM COLOR RULES!!!!!!!!!!!!!!!!!!!!!!
if(dice == 1 || dice == 2 || dice == 3 || dice == 4)
{
new beamcolor[4];
new randcolor = GetRandomInt(55, 255);
new randomAlpha = GetRandomInt(155, 255);
beamcolor[0]=randcolor;
beamcolor[1]=randcolor;
beamcolor[2]=randcolor;
beamcolor[3]=randomAlpha;
TE_SetupBeamPoints(iVec, targetVec, BeamSprite2, HaloSprite2, 0, 15, 1.7, 2.2,2.5, 1, 2.0, beamcolor, 20);
TE_SendToClient(client, 0.0);
}
}
else
{
//no longer in range? stop teh sounds!
StopSound(client, SNDCHAN_AUTO, aura1);
StopSound(client, SNDCHAN_AUTO, aura2);
StopSound(client, SNDCHAN_AUTO, aura3);
}
}
else
{
PrintHintText(target, "Blocked skill: Heartstopper Aura");
}
}
}
}
}
}
}
}
public OnWar3EventDeath(victim,attacker)
{
new race = War3_GetRace(attacker);
new skillmana = War3_GetSkillLevel(attacker, thisRaceID, SKILL_SADIST);
if(ValidPlayer(attacker, true))
{
if(race == thisRaceID && skillmana > 0 )
{
new moneyAdd = ManaGain[skillmana];
new Float:iVec[3];
GetClientAbsOrigin(attacker, iVec);
if( GetMoney(attacker)+moneyAdd < 16000 )
{
SetMoney(attacker, GetMoney(attacker)+moneyAdd);
PrintToChat(attacker,"\x04[War3Source] - Necrolyte: \x01 Gained \x03%i\x01 mana!",moneyAdd);
//expanding higher ring when mana is gained
TE_SetupBeamRingPoint(iVec,8.0,50.0,BeamSprite,BeamSprite,1,1,3.5,10.0,2.0,{79,141,191,200},5,0);
TE_SendToAll();
iVec[2] += 25;
TE_SetupBeamRingPoint(iVec,8.0,100.0,BeamSprite,BeamSprite,1,1,3.5,10.0,2.0,{79,141,191,180},5,0);
TE_SendToAll(0.2);
iVec[2] += 25;
TE_SetupBeamRingPoint(iVec,8.0,150.0,BeamSprite,BeamSprite,1,1,3.5,10.0,2.0,{79,141,191,160},5,0);
TE_SendToAll(0.4);
new Float:dir[3]={0.0,0.0,0.0};
new particle = CreateParticleSystem(attacker, "achieved", true, "forward", dir);
CreateTimer( 1.0, Timer_RemoveEntity, particle );
EmitSoundToAll(manaGained, attacker, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, 0.7);
}
else
{
PrintHintText(attacker, "Mana limit reached!");
}
}
}
}
public OnUltimateCommand(client,race,bool:pressed)
{
if(race == thisRaceID && pressed && IsPlayerAlive(client))
{
new skill_ult = War3_GetSkillLevel(client, thisRaceID, U_SCYTHE);
if(skill_ult > 0)
{
if(War3_SkillNotInCooldown(client,thisRaceID,U_SCYTHE,true))
{
if(!Silenced(client))
{
new Float:ManaUsage[5]={0.0,0.6,0.5,0.4,0.3};
new Mana = GetMoney(client);
if(Mana < 1500)
{
PrintHintText(client,"You need at least 1500 Mana!");
}
if(Mana > 1500)
{
new Float:targetpos[3];
War3_GetAimEndPoint(client, targetpos);
new Float:endVec[3];
GetClientAbsOrigin(client, endVec);
if(GetVectorDistance(endVec, targetpos) < 950.0) {
new myInt = RoundFloat( Mana- ( Mana * ManaUsage[skill_ult]));
if(myInt > 4000) //don't want them to use tooooo much mana, so let's use this!
{
myInt = 4000;
}
SetMoney(client, Mana-myInt);
//mana calc. done, now the damage! He will lose mana regardless of enemy immunity!
War3_CooldownMGR(client,GetConVarFloat(ultCooldownCvar),thisRaceID,U_SCYTHE,true,true,true);
TE_SetupExplosion(targetpos, g_iExplosionModel, 10.0, 10, TE_EXPLFLAG_NONE, 200, 222);
TE_SendToAll();
TE_SetupExplosion(targetpos, g_iExplosionModel, 13.0, 10, TE_EXPLFLAG_NONE, 200, 222);
TE_SendToAll(0.2);
//rain stuff!
endVec[2] += 120;
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
targetpos[0] += 50;
endVec[0] += 50;
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
targetpos[0] -= 100;
endVec[0] -= 100;
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
TE_SetupBeamPoints(targetpos, endVec, BeamSprite, HaloSprite, 0, 15, 1.4, 5.0, 10.0, 1, 3.5, {175,201,255,222}, 40);
TE_SendToAll();
//time to reset them!
GetClientAbsOrigin(client, endVec);
endVec[2] +=120;
War3_GetAimEndPoint(client, targetpos);
//rings on the top..
TE_SetupBeamRingPoint(endVec,8.0,200.0,BeamSprite,BeamSprite,1,1,3.5,25.0,4.0,{79,141,191,200},5,0);
TE_SendToAll();
TE_SetupBeamRingPoint(endVec,8.0,200.0,BeamSprite,BeamSprite,1,1,3.5,25.0,4.0,{79,141,191,200},5,0);
TE_SendToAll(0.2);
TE_SetupBeamRingPoint(endVec,8.0,200.0,BeamSprite,BeamSprite,1,1,3.5,25.0,4.0,{79,141,191,200},5,0);
TE_SendToAll(0.4);
//outer rings..
targetpos[2] += 25;
TE_SetupBeamRingPoint(targetpos,8.0,200.0,BeamSprite,BeamSprite,1,1,3.5,10.0,2.0,{79,141,191,180},5,0);
TE_SendToAll();
targetpos[2] += 25;
TE_SetupBeamRingPoint(targetpos,8.0,200.0,BeamSprite,BeamSprite,1,1,3.5,10.0,2.0,{79,141,191,160},5,0);
TE_SendToAll();
targetpos[2] += 25;
TE_SetupBeamRingPoint(targetpos,8.0, 200.0, BeamSprite,BeamSprite,1,1,3.5,15.0,4.0,{79,141,191,200},5,0);
TE_SendToAll();
targetpos[0] += 50;
targetpos[2] -= 75;
EmitSoundToAll(ulti, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
EmitSoundToAll(ab0b, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL);
for(new i=1;i<=MaxClients;i++)
{
new myTeam = GetClientTeam(client);
if( ValidPlayer(i, true) && GetClientTeam(i) != myTeam )
{
new Float:EnemyVec[3];
GetClientAbsOrigin(i, EnemyVec);
//now that we know he's an enemy, let's start the damage calculation(s)!!
//formula: W = G * p/100 -- I won't explain the formula.
// With every level, the percentage of Mana used is reduced.
if(GetVectorDistance(targetpos, EnemyVec) < GetRandomFloat(150.0,200.0))
{
if(!W3HasImmunity(i, Immunity_Ultimates))
{
new healthLoss = War3_GetMaxHP(i) - GetClientHealth(i); //how much HP has he lost?
// formula: p = W/G *100
// what if he has FULL hp? Formula is 0 then! have it covered below, but to be safe...
if( healthLoss < 15) //not too little damage, please.
{
healthLoss = 35;
}
new percent = healthLoss/War3_GetMaxHP(i) * 100; //how much percent of total HP does he still have?
//let's randomize the process in certain cases, to avoid TOO heavy damage or too little damage.
if(percent < 30 || percent > 60)
{
percent = GetRandomInt(20, 40);
}
War3_DealDamage(i, percent, client, DMG_BURN, "scythe", W3DMGORIGIN_SKILL, W3DMGTYPE_MAGIC);
EmitSoundToAll(ab0a, client, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, SNDVOL_NORMAL); //boom when it hits
new String:NameAttacker[64];
GetClientName( client, NameAttacker, 64 );
new String:NameVictim[64];
GetClientName( i, NameVictim, 64 );
PrintToChat(i,"\x04[War3Source] - Necrolyte: \x01%s hit you with \x03Reaper's Scythe\x01. Lost %i hp.",NameAttacker,percent);
PrintToChat(client, "\x04[War3Source] - Necrolyte: \x01You hit %s with \x03Reaper's Scythe\x01. Did %i damage.", NameVictim, percent);
}
else
{
PrintHintText(i,"Blocked Reaper's Scythe!");
PrintHintText(client, "Target has immunity! Lost Mana!");
}
}
else
{
PrintHintText(client, "Miss! No enemy in range!");
}
}
}
}
else
{
PrintHintText(client, "Miss! No enemy in range!");
}
}
}
}
}
else
{
PrintHintText(client, "Reaper's Scythe has not been leveled!");
}
}
}
public Action:Timer_RemoveEntity( Handle:timer, any:particle )
{
if( IsValidEdict( particle ))
AcceptEntityInput( particle, "Kill" );
}
public OnWar3EventSpawn( client )
{
if( ValidPlayer( client, true ) && War3_GetRace(client) == thisRaceID)
{
new money = GetMoney(client);
if(money+2000 < 17000)
{
SetMoney(client, money+2000);
PrintToChat(client,"\x04[War3Source] - Necrolyte: \x01Gained\x03 2000 Mana!\x01");
}
}
}
// ------------------------------------------------------------------------
// CreateParticleSystem()
// ------------------------------------------------------------------------
// >> Original code by J-Factor
// ------------------------------------------------------------------------
stock CreateParticleSystem(iClient, String:strParticle[], bool:bAttach = false, String:strAttachmentPoint[]="", Float:fOffset[3]={0.0, 0.0, 0.0})
{
new iParticle = CreateEntityByName("info_particle_system");
if (IsValidEdict(iParticle))
{
decl Float:fPosition[3];
decl Float:fAngles[3];
decl Float:fForward[3];
decl Float:fRight[3];
decl Float:fUp[3];
// Retrieve entity's position and angles
GetClientAbsOrigin(iClient, fPosition);
GetClientAbsAngles(iClient, fAngles);
// Determine vectors and apply offset
GetAngleVectors(fAngles, fForward, fRight, fUp); // I assume 'x' is Right, 'y' is Forward and 'z' is Up
fPosition[0] += fRight[0]*fOffset[0] + fForward[0]*fOffset[1] + fUp[0]*fOffset[2];
fPosition[1] += fRight[1]*fOffset[0] + fForward[1]*fOffset[1] + fUp[1]*fOffset[2];
fPosition[2] += fRight[2]*fOffset[0] + fForward[2]*fOffset[1] + fUp[2]*fOffset[2];
// Teleport and attach to client
TeleportEntity(iParticle, fPosition, fAngles, NULL_VECTOR);
DispatchKeyValue(iParticle, "effect_name", strParticle);
if (bAttach == true)
{
SetVariantString("!activator");
AcceptEntityInput(iParticle, "SetParent", iClient, iParticle, 0);
if (StrEqual(strAttachmentPoint, "") == false)
{
SetVariantString(strAttachmentPoint);
AcceptEntityInput(iParticle, "SetParentAttachmentMaintainOffset", iParticle, iParticle, 0);
}
}
// Spawn and start
DispatchSpawn(iParticle);
ActivateEntity(iParticle);
AcceptEntityInput(iParticle, "Start");
}
return iParticle;
}
|