Advertisement
Guest User

Tf2 plugin code

a guest
Aug 17th, 2023
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 78.03 KB | None | 0 0
  1. #pragma semicolon 1
  2.  
  3. #include <sourcemod>
  4. #include <sdktools>
  5. #include <tf2>
  6. #include <tf2_stocks>
  7. #include <sdkhooks>
  8. #include <tf2items>
  9. #include <tf2attributes>
  10. #include <customweaponstf>
  11. #include <smlib>
  12.  
  13. // Sounds
  14. #define SOUND_EXPLOSION_BIG "ambient/explosions/explode_8.wav"
  15. #define SOUND_1217_RELOAD "weapons/shotgun_reload.wav"
  16. #define SOUND_FIRELEAK_OIL "physics/flesh/flesh_bloody_impact_hard1.wav"
  17. #define SOUND_FLAME_ENGULF "misc/flame_engulf.wav"
  18. #define SOUND_BONEBREAK "player/pl_fleshbreak.wav"
  19.  
  20. // Particles
  21. #define PARTICLE_FIRE "buildingdamage_dispenser_fire1"
  22. #define PARTICLE_AREA_FIRE_BLUE "player_glowblue"
  23. #define PARTICLE_WHITE_PARTICLE "arm_muzzleflash_flare"
  24.  
  25. // Models
  26. #define MODEL_DEFAULTPHYSICS "models/props_2fort/coffeepot.mdl"
  27. #define MODEL_FIRELEAK "models/props_farm/haypile001.mdl"
  28.  
  29. // Teams
  30. #define TEAM_SPEC 0
  31. #define TEAM_RED 2
  32. #define TEAM_BLUE 3
  33.  
  34. #define SLOTS_MAX 7
  35.  
  36. // Damage Types
  37. #define TF_DMG_BULLET (1 << 1) // 2
  38. #define TF_DMG_BLEED (1 << 2) // 4
  39. #define TF_DMG_CRIT (1 << 20) // 1048576
  40. #define TF_DMG_UNKNOWN_1 (1 << 11) // 2048
  41. #define TF_DMG_FIRE (1 << 24) // 16777216
  42. #define TF_DMG_AFTERBURN TF_DMG_UNKNOWN_1 | (1 << 3) // 2048 + 8 = 2056
  43.  
  44. #define TF_DMG_MELEE (1 << 27) | (1 << 12) | (1 << 7) // 134217728 + 4096 + 128 = 134221952
  45. #define TF_DMG_MELEE_CRIT TF_DMG_MELEE | TF_DMG_CRIT // 134221952 + 1048576 = 135270528
  46.  
  47. #define TF_DMG_PROPAGATE (1 << 31) //Att #1212
  48.  
  49. #define MAX_EDICT_BITS 11
  50. #define MAX_EDICTS (1 << MAX_EDICT_BITS)
  51.  
  52. // Attribute Stuff
  53. #define ATTRIBUTE_1026_DISTANCE_LIMIT 600.0
  54. #define ATTRIBUTE_1026_PUSHSCALE 0.03
  55. #define ATTRIBUTE_1026_PUSHMAX 3.0
  56. #define ATTRIBUTE_1026_COOLDOWN 3.5
  57.  
  58. #define ATTRIBUTE_FIRELEAK_TIME 0.5
  59. #define ATTRIBUTE_FIRELEAK_COST 30
  60.  
  61. new Float:fAttribute_1034_Time[MAXPLAYERS+1] = 0.0;
  62.  
  63. new Float:g_fOilLeakDelay[MAXPLAYERS+1] = 0.0;
  64. new g_iOilLeakStatus[MAX_EDICTS + 1] = 0;
  65. new g_iOilLeakDamage[MAXPLAYERS+1] = 0;
  66. new g_iOilLeakDamageOwner[MAXPLAYERS+1] = 0;
  67. new Float:g_fOilLeakLife[MAX_EDICTS + 1] = 0.0;
  68.  
  69. new Handle:g_hOilLeakEntities = INVALID_HANDLE;
  70.  
  71. new g_iAchBoilerTimer1193[MAXPLAYERS+1] = 0;
  72. new g_iAchBoilerBurner1193[MAXPLAYERS+1] = 0;
  73.  
  74. new Float:g_fTotalDamage1296[MAXPLAYERS+1] = 0.0;
  75.  
  76. new bool:g_bFastCloaked[MAXPLAYERS+1] = false;
  77. new g_entitySlot[MAX_EDICTS+1] = -1;
  78. new Float:g_fEntityCreateTime[MAX_EDICTS+1] = 0.0;
  79. new g_iLastButtons[MAXPLAYERS+1] = 0;
  80. new bool:g_bWasDisguised[MAXPLAYERS+1] = false;
  81.  
  82. new bool:g_bHiddenEntities[MAX_EDICTS+1] = false;
  83.  
  84. new g_iTeamColor[4][4];
  85. new g_iTeamColorSoft[4][4];
  86.  
  87. new Handle:g_hAllowDownloads = INVALID_HANDLE;
  88. new Handle:g_hDownloadUrl = INVALID_HANDLE;
  89.  
  90. new g_iExplosionSprite;
  91. new g_iHaloSprite;
  92. new g_iWhite;
  93. new g_iBeamSprite;
  94.  
  95. // Homing rockets data
  96. #define FPS_LOGIC_RATE 22.0
  97. new Handle:g_hLogicTimer; // Logic timer
  98. new Handle:g_hProjectileList = INVALID_HANDLE;
  99.  
  100. new g_iCloakIsHook[MAXPLAYERS+1] = 0;
  101. new Float:g_fCloakIsHookTime[MAXPLAYERS+1] = 0.0;
  102. new Float:g_vCloakIsHookOrigin[MAXPLAYERS+1][3];
  103.  
  104. new oldDisguise[MAXPLAYERS+1][3];
  105.  
  106. new bool:isInfected[MAXPLAYERS+1] = false;
  107.  
  108. new bool:g_bAttWallSmash[MAXPLAYERS+1] = false;
  109. new g_iAttWallSmashAttacker[MAXPLAYERS+1] = false;
  110.  
  111. new String:g_strSound1315Ping[][PLATFORM_MAX_PATH] = {
  112. "physics/flesh/flesh_strider_impact_bullet1.wav",
  113. "physics/flesh/flesh_strider_impact_bullet2.wav",
  114. "physics/flesh/flesh_strider_impact_bullet3.wav"
  115. };
  116.  
  117. #define PLUGIN_VERSION "1.0.7e"
  118.  
  119. public Plugin:myinfo =
  120. {
  121. name = "Custom Weapons: Advanced Weaponiser 2 Attributes",
  122. author = "MechaTheSlag (Attributes & AW2) Theray070696 (Porting to CW2)",
  123. description = "Advanced Weaponiser 2's attributes, ported to Custom Weapons 2!",
  124. version = PLUGIN_VERSION,
  125. url = ""
  126. };
  127.  
  128. /* *** Attributes In This Plugin ***
  129. ! "fastcloak on backstab"
  130. Instant cloak upon backstab.
  131. -> "projectiles bounce"
  132. "bounce count"
  133. Projectiles bounce on walls, grounds and ceilings.
  134. -> "earthquake on rocket jump land"
  135. Performs an earthquake upon landing after a Rocket Jump.
  136. This weapon is pretty heavy.
  137. -> "reload clip on damage"
  138. "max clip size"
  139. On hit, reloads secondary weapon for every 50 damage dealt up to max clip size.
  140. -> "alt fire is oil"
  141. Instead of alt-fire doing what it normally would, it drops oil that can be ignited.
  142. -> "attack while cloaked"
  143. Can attack while cloaked.
  144. -> "reset afterburn"
  145. Resets afterburn on somebody that is on fire.
  146. -> "controllable projectiles"
  147. "how controllable"
  148. Projectiles are controllable.
  149. 0.25 is low control, 1.0 is full control
  150. -> "item is heavy"
  151. "force"
  152. While this item is out and the person holding it is in the air, he/she moves down with the provided force.
  153. -> "no reloading"
  154. Prevents reloading from happening.
  155. -> "cloak is hook"
  156. Cloak hooks you onto a wall or ceiling.
  157. -> "fall dmg reduced"
  158. "percentage"
  159. Reduces fall damage taken by the provided percent.
  160. -> "share damage"
  161. "range"
  162. "pencent"
  163. Takes percent damage from teammates and deals it to the holder if within range.
  164. */
  165.  
  166. // HasAttribute[2049] causes a super-marginal performance boost. Don't touch it.
  167. new bool:HasAttribute[2049];
  168.  
  169. new bool:FastcloakOnBackstab[2049];
  170.  
  171. new bool:ProjectilesBounce[2049];
  172. new Float:ProjectilesBounce_Count[2049];
  173.  
  174. new bool:Earthquake[2049];
  175.  
  176. new bool:DamageReloads[2049];
  177. new Float:DamageReloads_Max[2049];
  178.  
  179. new bool:AltFireIsOil[2049];
  180.  
  181. new bool:AttackWhileCloaked[2049];
  182.  
  183. new bool:ResetAfterburn[2049];
  184.  
  185. new bool:ControllableProjectiles[2049];
  186. new Float:ControllableProjectiles_Control[2049];
  187.  
  188. new bool:ItemIsHeavy[2049];
  189. new Float:ItemIsHeavy_Force[2049];
  190.  
  191. new bool:NoReloading[2049];
  192.  
  193. new bool:CloakIsHook[2049];
  194.  
  195. new bool:ReducedFallDamage[2049];
  196. new Float:ReducedFallDamage_Value[2049];
  197.  
  198. new bool:ShareDamage[2049];
  199. new Float:ShareDamage_Range[2049];
  200. new Float:ShareDamage_Ratio[2049];
  201.  
  202. new bool:ReflectCrits[2049];
  203.  
  204. new bool:ChargeLand[2049];
  205. new Float:ChargeLand_Value[2049];
  206.  
  207. new bool:CritCharging[2049];
  208.  
  209. new bool:CrouchCloak[2049];
  210. new Float:CrouchCloak_Value[2049];
  211.  
  212. new bool:JumpCloak[2049];
  213. new Float:JumpCloak_Value[2049];
  214.  
  215. new bool:RemoveDebuffCloak[2049];
  216.  
  217. new bool:CloakOnlyWhenFullMeter[2049];
  218.  
  219. new bool:DrawMiniCrits[2049];
  220. new Float:DrawMiniCrits_Value[2049];
  221.  
  222. new bool:DamageOnGround[2049];
  223. new Float:DamageOnGround_Value1[2049];
  224. new Float:DamageOnGround_Value2[2049];
  225.  
  226. new bool:ReducedDamageInAir[2049];
  227. new Float:ReducedDamageInAir_Value1[2049];
  228. new Float:ReducedDamageInAir_Value2[2049];
  229.  
  230. new bool:InfectVictimOnBackstab[2049];
  231. new Float:InfectVictimOnBackstab_TimeToStun[2049];
  232. new Float:InfectVictimOnBackstab_TimeToDeath[2049];
  233.  
  234. new bool:WallKill[2049];
  235. new WallKill_Damage[2049];
  236.  
  237. public OnPluginStart()
  238. {
  239. CreateConVar("sm_advanced_weaponiser_2_attributes_version", PLUGIN_VERSION, "Don't touch this!");
  240.  
  241. HookEvent("post_inventory_application", EventPlayerInventory);
  242. HookEvent("player_spawn", EventPlayerSpawn);
  243. HookEvent("rocket_jump_landed", Attributes_JumpLand);
  244. HookEvent("sticky_jump_landed", Attributes_JumpLand);
  245. HookEvent("object_deflected", Attributes_Deflect);
  246. HookEvent("player_death", Attributes_Death);
  247. HookEvent("player_healed", Attributes_Healed);
  248.  
  249. HookEntityOutput("item_healthkit_small", "OnPlayerTouch", Attributes_HealthKit);
  250. HookEntityOutput("item_healthkit_medium", "OnPlayerTouch", Attributes_HealthKit);
  251. HookEntityOutput("item_healthkit_full", "OnPlayerTouch", Attributes_HealthKit);
  252.  
  253. for(new i = 1; i <= MaxClients; i++)
  254. {
  255. if(!IsClientInGame(i)) continue;
  256. OnClientPutInServer(i);
  257. }
  258.  
  259. MiscOnPluginStart();
  260. AttributesInit();
  261.  
  262. g_hLogicTimer = INVALID_HANDLE;
  263. g_hProjectileList = CreateArray(1);
  264. }
  265.  
  266. stock MiscOnPluginStart()
  267. {
  268. g_iTeamColor[TEAM_RED][0] = 255;
  269. g_iTeamColor[TEAM_RED][1] = 0;
  270. g_iTeamColor[TEAM_RED][2] = 0;
  271. g_iTeamColor[TEAM_RED][3] = 255;
  272. g_iTeamColor[TEAM_BLUE][0] = 0;
  273. g_iTeamColor[TEAM_BLUE][1] = 0;
  274. g_iTeamColor[TEAM_BLUE][2] = 255;
  275. g_iTeamColor[TEAM_BLUE][3] = 255;
  276.  
  277. g_iTeamColorSoft[TEAM_RED][0] = 189;
  278. g_iTeamColorSoft[TEAM_RED][1] = 59;
  279. g_iTeamColorSoft[TEAM_RED][2] = 59;
  280. g_iTeamColorSoft[TEAM_RED][3] = 255;
  281. g_iTeamColorSoft[TEAM_BLUE][0] = 91;
  282. g_iTeamColorSoft[TEAM_BLUE][1] = 122;
  283. g_iTeamColorSoft[TEAM_BLUE][2] = 140;
  284. g_iTeamColorSoft[TEAM_BLUE][3] = 255;
  285. }
  286.  
  287. public OnPluginEnd()
  288. {
  289. AttributesStop();
  290. }
  291.  
  292. public OnMapStart()
  293. {
  294. g_hLogicTimer = CreateTimer(1.0 / FPS_LOGIC_RATE, OnThinkRocketHook, _, TIMER_REPEAT);
  295. ClearArray(g_hProjectileList);
  296.  
  297. MiscOnMapStart();
  298. Attributes_Precache();
  299. }
  300.  
  301. public OnMapEnd()
  302. {
  303. ClearArray(g_hProjectileList);
  304. if(g_hLogicTimer != INVALID_HANDLE) KillTimer(g_hLogicTimer);
  305. g_hLogicTimer = INVALID_HANDLE;
  306. }
  307.  
  308. MiscOnMapStart()
  309. {
  310. g_hAllowDownloads = FindConVar("sv_allowdownload");
  311. g_hDownloadUrl = FindConVar("sv_downloadurl");
  312.  
  313. g_iWhite = PrecacheModel("materials/sprites/white.vmt");
  314. g_iBeamSprite = PrecacheModel("materials/cable/rope.vmt");
  315. g_iHaloSprite = PrecacheModel("materials/sprites/halo01.vmt");
  316. g_iExplosionSprite = PrecacheModel("sprites/sprite_fire01.vmt");
  317. }
  318.  
  319. Attributes_Precache()
  320. {
  321. // Particles
  322. PrecacheParticle(PARTICLE_FIRE);
  323. PrecacheParticle(PARTICLE_AREA_FIRE_BLUE);
  324. PrecacheParticle(PARTICLE_WHITE_PARTICLE);
  325.  
  326. // Models
  327. SuperPrecacheModel(MODEL_FIRELEAK);
  328. SuperPrecacheModel(MODEL_DEFAULTPHYSICS, true);
  329.  
  330. // Sounds
  331. SuperPrecacheSound(SOUND_EXPLOSION_BIG);
  332. SuperPrecacheSound(SOUND_FIRELEAK_OIL);
  333. SuperPrecacheSound(SOUND_FLAME_ENGULF);
  334. SuperPrecacheSound(SOUND_BONEBREAK);
  335.  
  336. for(new i = 0; i < sizeof(g_strSound1315Ping); i++)
  337. {
  338. SuperPrecacheSound(g_strSound1315Ping[i]);
  339. }
  340. }
  341.  
  342. public Attributes_HealthKit(const String:output[], caller, activator, Float:delay)
  343. {
  344. if(Client_IsValid(activator) && IsClientInGame(activator) && IsPlayerAlive(activator))
  345. {
  346. if(isInfected[activator])
  347. {
  348. isInfected[activator] = false;
  349. }
  350. }
  351. }
  352.  
  353. public Attributes_Death(Handle:hEvent, const String:strName[], bool:bDontBroadcast)
  354. {
  355. new client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  356.  
  357. if(Client_IsValid(client))
  358. {
  359. oldDisguise[client][0] = 0;
  360. oldDisguise[client][1] = 0;
  361. oldDisguise[client][2] = 0;
  362.  
  363. isInfected[client] = false;
  364. }
  365. }
  366.  
  367. public Attributes_Healed(Handle:hEvent, const String:strName[], bool:bDontBroadcast)
  368. {
  369. new client = GetClientOfUserId(GetEventInt(hEvent, "patient"));
  370.  
  371. if(Client_IsValid(client) && isInfected[client])
  372. {
  373. isInfected[client] = false;
  374. }
  375. }
  376.  
  377. public TF2_OnConditionAdded(client, TFCond:condition)
  378. {
  379. if(Client_IsValid(client))
  380. {
  381. if(condition == TFCond_Disguised)
  382. {
  383. oldDisguise[client][0] = GetEntProp(client, Prop_Send, "m_nDisguiseClass");
  384. oldDisguise[client][1] = GetEntProp(client, Prop_Send, "m_nDisguiseTeam");
  385. oldDisguise[client][2] = GetEntProp(client, Prop_Send, "m_hDisguiseTarget");
  386. }
  387.  
  388. new weapon = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon");
  389. if(weapon != -1 && GetHasAttributeInAnySlot(client))
  390. {
  391. if(GetHasAttributeInAnySlot(client, _, JumpCloak) && condition == TFCond_Cloaked)
  392. {
  393. TF2Attrib_SetByName(weapon, "increased jump height", JumpCloak_Value[weapon]);
  394. } else if(GetHasAttributeInAnySlot(client, _, RemoveDebuffCloak) && condition == TFCond_Cloaked)
  395. {
  396. TF2_RemoveCondition(client, TFCond_OnFire);
  397. TF2_RemoveCondition(client, TFCond_Milked);
  398. TF2_RemoveCondition(client, TFCond_Jarated);
  399. TF2_RemoveCondition(client, TFCond_Bleeding);
  400. } else if(GetHasAttributeInAnySlot(client, _, CloakOnlyWhenFullMeter) && condition == TFCond_Cloaked)
  401. {
  402. if(GetEntProp(client, Prop_Send, "m_flChargeMeter") < 100.0)
  403. {
  404. CreateTimer(0.5, Timer_RemoveCloak, client);
  405. }
  406. }
  407. }
  408. }
  409. }
  410.  
  411. public Action:Timer_RemoveCloak(Handle:hTimer, any:client)
  412. {
  413. if(Client_IsValid(client))
  414. {
  415. TF2_RemoveCondition(client, TFCond_Cloaked);
  416. }
  417. }
  418.  
  419. public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon)
  420. {
  421. if(Client_IsValid(client))
  422. {
  423. if(GetHasAttributeInAnySlot(client, _, CrouchCloak))
  424. {
  425. if(buttons & IN_DUCK || GetEntProp(client, Prop_Send, "m_bDucking") || GetEntProp(client, Prop_Send, "m_bDucked"))
  426. {
  427. //SetEntityRenderMode(client, RENDER_TRANSCOLOR);
  428. //SetEntityRenderColor(client, 0, 0, 0, RoundToNearest(GetAttributeValueInAnySlot(client, _, CrouchCloak, CrouchCloak_Value, 255.0)));
  429. HideClientWearables(client, true);
  430. HideEntity(client, true);
  431. } else
  432. {
  433. //SetEntityRenderColor(client, 0, 0, 0, 255);
  434. HideClientWearables(client, false);
  435. HideEntity(client, false);
  436. }
  437. }
  438.  
  439. if(GetHasAttributeInAnySlot(client, _, CloakOnlyWhenFullMeter))
  440. {
  441. if(TF2_IsPlayerInCondition(client, TFCond_Cloaked)) return Plugin_Continue;
  442. new Float:m_flCloak = GetEntPropFloat(client, Prop_Send, "m_flCloakMeter");
  443.  
  444. if(m_flCloak < 100.0)
  445. {
  446. buttons &= ~IN_ATTACK2;
  447. return Plugin_Continue;
  448. }
  449. }
  450. }
  451.  
  452. return Plugin_Continue;
  453. }
  454.  
  455. public Action:EternSleep_OnTakeDamage(victim, &attacker, &damagetype, slot)
  456. {
  457. if(!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  458.  
  459. new weapon = GetPlayerWeaponSlot(attacker, slot);
  460. if(weapon == -1) return Plugin_Continue;
  461. if(!HasAttribute[weapon]) return Plugin_Continue;
  462.  
  463. if(CritCharging[weapon] && TF2_IsPlayerInCondition(victim, TFCond_Charging))
  464. {
  465. damagetype = DMG_CRIT;
  466. return Plugin_Changed;
  467. }
  468.  
  469. return Plugin_Continue;
  470. }
  471.  
  472. public Action:Attributes_JumpLand(Handle:hEvent, const String:strName[], bool:bDontBroadcast)
  473. {
  474. new client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  475.  
  476. if(!Client_IsValid(client)) return Plugin_Continue;
  477.  
  478. new slot = GetClientSlot(client);
  479.  
  480. new weapon = GetPlayerWeaponSlot(client, slot);
  481. if(weapon == -1) return Plugin_Continue;
  482. if(!HasAttribute[weapon]) return Plugin_Continue;
  483.  
  484. if(ChargeLand[weapon])
  485. {
  486. TF2_AddCondition(client, TFCond_Charging, ChargeLand_Value[weapon]);
  487. }
  488.  
  489. Attribute_1026_RocketJumpLand(client, weapon);
  490.  
  491. return Plugin_Continue;
  492. }
  493.  
  494. public Action:Attributes_Deflect(Handle:hEvent, const String:strName[], bool:bDontBroadcast)
  495. {
  496. new weapon = GetEventInt(hEvent, "weaponid");
  497.  
  498. if(weapon == -1) return Plugin_Continue;
  499. if(!HasAttribute[weapon] || !ReflectCrits[weapon]) return Plugin_Continue;
  500.  
  501. new deflector = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  502. new deflected = GetEventInt(hEvent, "object_entindex");
  503.  
  504. if(Client_IsValid(deflector))
  505. {
  506. SetEntProp(deflected, Prop_Send, "m_bCritical", 1);
  507. }
  508.  
  509. return Plugin_Continue;
  510. }
  511.  
  512. public AttributesInit()
  513. {
  514. Attribute_1056_Init();
  515. }
  516.  
  517. Attribute_1056_Init()
  518. {
  519. g_hOilLeakEntities = CreateArray();
  520. }
  521.  
  522. public Action:EventPlayerInventory(Handle:hEvent, String:strName[], bool:bDontBroadcast)
  523. {
  524. new client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  525.  
  526. if(!Client_IsValid(client)) return Plugin_Continue;
  527. if(!IsPlayerAlive(client)) return Plugin_Continue;
  528.  
  529. RefreshClientLoadout(client, true);
  530.  
  531. return Plugin_Continue;
  532. }
  533.  
  534. public Action:EventPlayerSpawn(Handle:hEvent, String:strName[], bool:bDontBroadcast)
  535. {
  536. new client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  537.  
  538. if(!Client_IsValid(client)) return Plugin_Continue;
  539. if(!Team_IsValid(client)) return Plugin_Continue;
  540.  
  541. RefreshClientLoadout(client);
  542. CreateTimer(0.1, PostSpawn, client);
  543.  
  544. return Plugin_Continue;
  545. }
  546.  
  547. public Action:PostSpawn(Handle:hTimer, any:client)
  548. {
  549. if(!Client_IsValid(client)) return Plugin_Continue;
  550. if(!Team_IsValid(client)) return Plugin_Continue;
  551. if(!IsPlayerAlive(client)) return Plugin_Continue;
  552.  
  553. TF2_RegeneratePlayer(client);
  554. RefreshClientLoadout(client, true);
  555. return Plugin_Continue;
  556. }
  557.  
  558. RefreshClientLoadout(client, bool:bSilent = false)
  559. {
  560. new TFClassType:class = TF2_GetPlayerClass(client);
  561. for(new i = 0; i <= SLOTS_MAX; i++)
  562. {
  563. ManageClientLoadoutSlot(client, class, i, bSilent);
  564. }
  565.  
  566. // bug fixes
  567. isInfected[client] = false;
  568. FastCloakRemove(client);
  569. }
  570.  
  571. bool:ManageClientLoadoutSlot(client, TFClassType:class, slot, bool:bSilent = false)
  572. {
  573. if(IsFakeClient(client)) return false;
  574.  
  575. Attribute_OnInventory(client, slot);
  576.  
  577. return true;
  578. }
  579.  
  580. Attribute_OnInventory(client, slot)
  581. {
  582. Attribute_1039_OnInventory(client, slot);
  583. }
  584.  
  585. Attribute_1039_OnInventory(client, &slot)
  586. {
  587. new weapon = GetPlayerWeaponSlot(client, slot);
  588. if(weapon == -1) return;
  589. if(!HasAttribute[weapon]) return;
  590. if(!CloakIsHook[weapon]) return;
  591.  
  592. CloakIsHookToggle(client, true);
  593. g_iCloakIsHook[client] = 0;
  594. }
  595.  
  596. Attributes_1039_Stop()
  597. {
  598. for(new i = 1; i <= MaxClients; i++)
  599. {
  600. CloakIsHookToggle(i, true);
  601. }
  602. }
  603.  
  604. CloakIsHookToggle(client, bool:bForceStop = false)
  605. {
  606. if(!Client_IsValid(client)) return;
  607.  
  608. if(bForceStop && g_iCloakIsHook[client] != 1) return;
  609. if(g_iCloakIsHook[client] > 1) return;
  610.  
  611. if(g_iCloakIsHook[client] > 0)
  612. {
  613. TF2_RemoveCondition(client, TFCond_Cloaked);
  614. g_iCloakIsHook[client] = 2;
  615. SetEntityMoveType(client, MOVETYPE_WALK);
  616.  
  617. decl Float:vEyeAngles[3], Float:vVelocity[3];
  618. GetClientEyeAngles(client, vEyeAngles);
  619. AnglesToVelocity(vEyeAngles, vVelocity, 400.0);
  620. TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, vVelocity);
  621. } else
  622. {
  623. decl Float:vEyeAngles[3];
  624. GetClientEyeAngles(client, vEyeAngles);
  625. CloakIsHookInit(client, vEyeAngles);
  626. }
  627. }
  628.  
  629. stock bool:GetClientViewTarget2(client, Float:vecClientEyeAng[3], Float:vOrigin[3], bool:bCeiling = false)
  630. {
  631. decl Float:vecClientEyePos[3];
  632. GetClientEyePosition(client, vecClientEyePos);
  633.  
  634. //Check for colliding entities
  635. TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_PLAYERSOLID_BRUSHONLY, RayType_Infinite, TraceRayDontHitPlayers);
  636.  
  637. vOrigin[0] = vecClientEyePos[0];
  638. vOrigin[1] = vecClientEyePos[1];
  639. vOrigin[2] = vecClientEyePos[2];
  640.  
  641. if(TR_DidHit())
  642. {
  643. TR_GetEndPosition(vOrigin);
  644. decl Float:fNormal[3];
  645. TR_GetPlaneNormal(INVALID_HANDLE, fNormal);
  646. GetVectorAngles(fNormal, fNormal);
  647. if(!bCeiling) return true;
  648. else
  649. {
  650. if(fNormal[0] >= 0.0 && fNormal[0] <= 90.0) return true;
  651. }
  652. }
  653. return false;
  654. }
  655.  
  656. bool:CloakIsHookInit(client, Float:vAngles[3])
  657. {
  658. if(g_iCloakIsHook[client] == 1) return false;
  659.  
  660. if(GetEntPropFloat(client, Prop_Send, "m_flCloakMeter") <= 5.0) return false;
  661. if(!GetClientViewTarget2(client, vAngles, g_vCloakIsHookOrigin[client], true)) return false;
  662.  
  663. decl Float:vOrigin[3];
  664. Entity_GetAbsOrigin(client, vOrigin);
  665. // too far away
  666. if(GetVectorDistance(vOrigin, g_vCloakIsHookOrigin[client])/50.0 > 10.0) return false;
  667. if(g_vCloakIsHookOrigin[client][2] <= vOrigin[2]) return false;
  668.  
  669. TF2_AddCondition(client, TFCond_Cloaked, 999.0);
  670. g_iCloakIsHook[client] = 1;
  671. g_fCloakIsHookTime[client] = GetEngineTime();
  672. return true;
  673. }
  674.  
  675. Attribute_1012_Prethink(client, &buttons, &slot, &buttonsLast)
  676. {
  677. if(!g_bAttWallSmash[client]) return buttons;
  678. if(OnGround(client))
  679. {
  680. g_bAttWallSmash[client] = false;
  681. g_iAttWallSmashAttacker[client] = -1;
  682. return buttons;
  683. }
  684.  
  685. // Check if smashing into wall
  686. decl Float:vClientOrigin[3];
  687. decl Float:vAngles[3];
  688. decl Float:vVelocity[3];
  689. GetClientEyePosition(client, vClientOrigin);
  690. Entity_GetLocalVelocity(client, vVelocity);
  691.  
  692. new Float:fSpeed = GetVectorLength(vVelocity);
  693.  
  694. if (fSpeed < 25.0) return buttons;
  695.  
  696. GetVectorAngles(vVelocity, vAngles);
  697. vAngles[0] = 0.0;
  698. //TR_TraceRayFilter(vClientOrigin, vAngles, MASK_PLAYERSOLID_BRUSHONLY, RayType_Infinite, TraceRayDontHitEntity, client);
  699.  
  700. //if (!TR_DidHit()) return buttons;
  701.  
  702. new attacker = g_iAttWallSmashAttacker[client];
  703.  
  704. if (!Client_IsValid(attacker))return buttons;
  705.  
  706. new slot2 = GetClientSlot(attacker);
  707. new weapon = GetPlayerWeaponSlot(attacker, slot2);
  708.  
  709. new damage = 100;
  710.  
  711. if(weapon != -1 && HasAttribute[weapon] && WallKill[weapon])
  712. {
  713. damage = WallKill_Damage[weapon];
  714. }
  715.  
  716. Entity_Hurt(client, damage, attacker);
  717. EmitSoundToClient(attacker, SOUND_BONEBREAK);
  718. EmitSoundToAll(SOUND_BONEBREAK, client);
  719.  
  720. g_bAttWallSmash[client] = false;
  721. g_iAttWallSmashAttacker[client] = -1;
  722.  
  723. return buttons;
  724. }
  725.  
  726. Attribute_1039_Prethink(client, &buttons, &slot, &buttonsLast)
  727. {
  728. if(!IsPlayerAlive(client)) return buttons;
  729.  
  730. new weapon = GetPlayerWeaponSlot(client, slot);
  731. if(weapon == -1) return buttons;
  732. if(!HasAttribute[weapon]) return buttons;
  733. if(!CloakIsHook[weapon]) return buttons;
  734.  
  735. // toggle ATTACK2
  736. new Float:fSpeed = GetEntPropFloat(client, Prop_Send, "m_flMaxspeed");
  737. if(buttonsLast & IN_ATTACK2 != IN_ATTACK2 && buttons & IN_ATTACK2 == IN_ATTACK2 && g_fCloakIsHookTime[client] < GetEngineTime() - 1.0 && fSpeed >= 5.0)
  738. {
  739. buttons &= ~IN_ATTACK2;
  740. CloakIsHookToggle(client);
  741. }
  742. if(GetEntPropFloat(client, Prop_Send, "m_flCloakMeter") <= 0.0) CloakIsHookToggle(client, true);
  743.  
  744. if(g_iCloakIsHook[client] > 1 && OnGround(client)) g_iCloakIsHook[client] = 0;
  745.  
  746. if(g_iCloakIsHook[client] != 1)
  747. {
  748. return buttons;
  749. }
  750.  
  751. if(GetEntityMoveType(client) == MOVETYPE_NONE) return buttons;
  752.  
  753. decl Float:vOrigin[3];
  754. Entity_GetAbsOrigin(client, vOrigin);
  755.  
  756. decl Float:vVelocity[3];
  757. SubtractVectors(g_vCloakIsHookOrigin[client], vOrigin, vVelocity);
  758. NormalizeVector(vVelocity, vVelocity);
  759. ScaleVector(vVelocity, 900.0);
  760. if(OnGround(client) && vVelocity[2] < 300.0 && vVelocity[2] > 0) vVelocity[2] = 300.0;
  761. else vVelocity[2] += 20.0;
  762. TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, vVelocity);
  763.  
  764. decl Float:vOriginEye[3];
  765. GetClientEyePosition(client, vOriginEye);
  766. vOrigin[2] = (vOriginEye[2] - vOrigin[2])/2.0 + vOrigin[2];
  767. new Float:fDistance = GetVectorDistance(vOrigin, g_vCloakIsHookOrigin[client]) / 50.0;
  768. if(fDistance >= 1.1 && g_fCloakIsHookTime[client] >= GetEngineTime() - 0.5)
  769. {
  770. ClientRope(client, g_vCloakIsHookOrigin[client]);
  771. } else
  772. {
  773. TF2_AddCondition(client, TFCond_Cloaked, 999.0);
  774. SetEntityMoveType(client, MOVETYPE_NONE);
  775. }
  776.  
  777. return buttons;
  778. }
  779.  
  780. public AttributesStop()
  781. {
  782. FastCloakRemoveAll();
  783. Attributes_1056_Think(true);
  784. Attributes_1039_Stop();
  785. }
  786.  
  787. public FastCloak(client)
  788. {
  789. if(g_bFastCloaked[client]) return;
  790.  
  791. HideClientWearables(client, true);
  792. HideEntity(client, true);
  793. TF2_AddCondition(client, TFCond_Cloaked, 999.0);
  794. g_bFastCloaked[client] = true;
  795. }
  796.  
  797. public FastCloakThink(client)
  798. {
  799. if(TF2_IsPlayerInCondition(client, TFCond_Cloaked)) return;
  800. if(!g_bFastCloaked[client]) return;
  801.  
  802. HideClientWearables(client, false);
  803. HideEntity(client, false);
  804. g_bFastCloaked[client] = false;
  805. }
  806.  
  807. public FastCloakRemove(client)
  808. {
  809. if(Client_IsValid(client))
  810. {
  811. HideClientWearables(client, false);
  812. HideEntity(client, false);
  813. g_bFastCloaked[client] = false;
  814. }
  815. }
  816.  
  817. public FastCloakRemoveAll()
  818. {
  819. for(new i = 1; i <= MaxClients; i++)
  820. {
  821. FastCloakRemove(i);
  822. }
  823. }
  824.  
  825. stock bool:HideClientWearables(client, bool:bHide)
  826. {
  827. for(new i = 0; i <= 5; i++)
  828. {
  829. new weapon = GetPlayerWeaponSlot(client, i);
  830. if(weapon > 0 && IsValidEdict(weapon))
  831. {
  832. if(!IsHiddenEntity(weapon)) HideEntity(weapon, bHide);
  833. }
  834. }
  835.  
  836. new String:strEntities[][50] = {"tf_wearable", "tf_wearable_demoshield"};
  837. for(new i = 0; i < sizeof(strEntities); i++)
  838. {
  839. new entity = -1;
  840. while((entity = FindEntityByClassname(entity, strEntities[i])) != -1)
  841. {
  842. if(IsClassname(entity, strEntities[i]) && Entity_GetOwner(entity) == client && !IsHiddenEntity(entity)) HideEntity(entity, bHide);
  843. }
  844. }
  845. }
  846.  
  847. stock bool:SubtractWeaponAmmo(client, slot, ammo)
  848. {
  849. new weapon = GetPlayerWeaponSlot(client, slot);
  850. if(IsValidEntity(weapon))
  851. {
  852. new realammo = GetEntData(client, FindSendPropOffs("CTFPlayer", "m_iAmmo")+4);
  853. realammo -= ammo;
  854. if(realammo < 0) return false;
  855. SetEntData(client, FindSendPropOffs("CTFPlayer", "m_iAmmo")+4, realammo);
  856. return true;
  857. }
  858. return false;
  859. }
  860.  
  861. stock HideEntity(entity, bool:bHide)
  862. {
  863. if(bHide)
  864. {
  865. SetEntityRenderMode(entity, RENDER_TRANSCOLOR);
  866. SetEntityRenderColor(entity, 255, 255, 255, 0);
  867. } else
  868. {
  869. SetEntityRenderColor(entity, 255, 255, 255, 255);
  870. SetEntityRenderMode(entity, RENDER_NORMAL);
  871. }
  872. }
  873.  
  874. bool:IsHiddenEntity(entity)
  875. {
  876. return g_bHiddenEntities[entity];
  877. }
  878.  
  879. stock bool:IsDisguised(client)
  880. {
  881. if(!Client_IsValid(client)) return false;
  882. new class = GetEntProp(client, Prop_Send, "m_nDisguiseClass");
  883. return (class != 0);
  884. }
  885.  
  886. Action:ActionApply(Action:aPrevious, Action:aNew)
  887. {
  888. if(aNew != Plugin_Continue) aPrevious = aNew;
  889. return aPrevious;
  890. }
  891.  
  892. stock GetClientPointPosition(client, Float:fEyePos[3], mask = MASK_PLAYERSOLID)
  893. {
  894. decl Float:fEyeAngle[3];
  895. GetClientEyePosition(client, fEyePos);
  896. GetClientEyeAngles(client, fEyeAngle);
  897. TR_TraceRayFilter(fEyePos, fEyeAngle, MASK_PLAYERSOLID, RayType_Infinite, TraceRayDontHitEntity, client);
  898.  
  899. if(TR_DidHit(INVALID_HANDLE))
  900. {
  901. TR_GetEndPosition(fEyePos);
  902. }
  903. }
  904.  
  905. stock Float:GetEntityLife(entity)
  906. {
  907. return GetEngineTime() - g_fEntityCreateTime[entity];
  908. }
  909.  
  910. stock ShowParticle(String:particlename[], Float:time, Float:pos[3], Float:ang[3]=NULL_VECTOR)
  911. {
  912. new particle = CreateEntityByName("info_particle_system");
  913. if(IsValidEdict(particle))
  914. {
  915. TeleportEntity(particle, pos, ang, NULL_VECTOR);
  916. DispatchKeyValue(particle, "effect_name", particlename);
  917. ActivateEntity(particle);
  918. AcceptEntityInput(particle, "start");
  919. CreateTimer(time, RemoveParticle, particle);
  920. }
  921. else
  922. {
  923. LogError("ShowParticle: could not create info_particle_system");
  924. return -1;
  925. }
  926. return particle;
  927. }
  928.  
  929. stock any:AttachParticle(ent, String:particleType[], Float:time = 0.0, Float:addPos[3]=NULL_VECTOR, Float:addAngle[3]=NULL_VECTOR, bool:bShow = true, String:strVariant[] = "", bool:bMaintain = false)
  930. {
  931. new particle = CreateEntityByName("info_particle_system");
  932. if(IsValidEdict(particle))
  933. {
  934. new Float:pos[3];
  935. new Float:ang[3];
  936. decl String:tName[32];
  937. Entity_GetAbsOrigin(ent, pos);
  938. AddVectors(pos, addPos, pos);
  939. GetEntPropVector(ent, Prop_Send, "m_angRotation", ang);
  940. AddVectors(ang, addAngle, ang);
  941.  
  942. Format(tName, sizeof(tName), "target%i", ent);
  943. DispatchKeyValue(ent, "targetname", tName);
  944.  
  945. TeleportEntity(particle, pos, ang, NULL_VECTOR);
  946. DispatchKeyValue(particle, "targetname", "tf2particle");
  947. DispatchKeyValue(particle, "parentname", tName);
  948. DispatchKeyValue(particle, "effect_name", particleType);
  949. DispatchSpawn(particle);
  950. SetEntPropEnt(particle, Prop_Send, "m_hOwnerEntity", ent);
  951. if(bShow)
  952. {
  953. SetVariantString(tName);
  954. } else
  955. {
  956. SetVariantString("!activator");
  957. }
  958. AcceptEntityInput(particle, "SetParent", ent, particle, 0);
  959. if(!StrEqual(strVariant, ""))
  960. {
  961. SetVariantString(strVariant);
  962. if(bMaintain) AcceptEntityInput(particle, "SetParentAttachmentMaintainOffset", ent, particle, 0);
  963. else AcceptEntityInput(particle, "SetParentAttachment", ent, particle, 0);
  964. }
  965. ActivateEntity(particle);
  966. AcceptEntityInput(particle, "start");
  967. if(time > 0.0) CreateTimer(time, RemoveParticle, particle);
  968. }
  969. else LogError("AttachParticle: could not create info_particle_system");
  970. return particle;
  971. }
  972.  
  973. public Action:RemoveParticle(Handle:timer, any:particle)
  974. {
  975. if(particle >= 0 && IsValidEntity(particle))
  976. {
  977. new String:classname[32];
  978. GetEdictClassname(particle, classname, sizeof(classname));
  979. if(StrEqual(classname, "info_particle_system", false))
  980. {
  981. AcceptEntityInput(particle, "Stop");
  982. AcceptEntityInput(particle, "Kill");
  983. AcceptEntityInput(particle, "Deactivate");
  984. particle = -1;
  985. }
  986. }
  987. }
  988.  
  989. stock bool:IsClassname(entity, String:strClassname[])
  990. {
  991. if(entity <= 0) return false;
  992. if(!IsValidEdict(entity)) return false;
  993.  
  994. decl String:strClassname2[32];
  995. GetEdictClassname(entity, strClassname2, sizeof(strClassname2));
  996. if(!StrEqual(strClassname, strClassname2, false)) return false;
  997.  
  998. return true;
  999. }
  1000.  
  1001. stock AnglesToVelocity(Float:fAngle[3], Float:fVelocity[3], Float:fSpeed = 1.0)
  1002. {
  1003. fVelocity[0] = Cosine(DegToRad(fAngle[1]));
  1004. fVelocity[1] = Sine(DegToRad(fAngle[1]));
  1005. fVelocity[2] = Sine(DegToRad(fAngle[0])) * -1.0;
  1006.  
  1007. NormalizeVector(fVelocity, fVelocity);
  1008.  
  1009. ScaleVector(fVelocity, fSpeed);
  1010. }
  1011.  
  1012. public bool:TraceRayDontHitEntity(entity, contentsMask, any:data)
  1013. {
  1014. return (entity != data);
  1015. }
  1016.  
  1017. public bool:TraceRayDontHitPlayers(entity, mask)
  1018. {
  1019. if(Client_IsValid(entity)) return false;
  1020.  
  1021. return true;
  1022. }
  1023.  
  1024. stock bool:IsEntityBuilding(entity)
  1025. {
  1026. if(entity <= 0) return false;
  1027. if(!IsValidEdict(entity)) return false;
  1028. if(IsClassname(entity, "obj_sentrygun")) return true;
  1029. if(IsClassname(entity, "obj_dispenser")) return true;
  1030. if(IsClassname(entity, "obj_teleporter")) return true;
  1031. return false;
  1032. }
  1033.  
  1034. stock bool:IsAfterDamage(damageType)
  1035. {
  1036. if(damageType == TF_DMG_BLEED) return true;
  1037. if(damageType == TF_DMG_AFTERBURN) return true;
  1038.  
  1039. return false;
  1040. }
  1041.  
  1042. stock bool:IsDamageTypeCrit(damageType)
  1043. {
  1044. return (damageType & TF_DMG_CRIT == TF_DMG_CRIT);
  1045. }
  1046.  
  1047. stock bool:HasFastDownload()
  1048. {
  1049. // if for whatever reason these are invalid, its pretty certain the fastdl isn't working
  1050. if(g_hAllowDownloads == INVALID_HANDLE || g_hDownloadUrl == INVALID_HANDLE)
  1051. {
  1052. return false;
  1053. }
  1054.  
  1055. // if sv_allowdownload 0, fastdl is disabled
  1056. if(!GetConVarBool(g_hAllowDownloads))
  1057. {
  1058. return false;
  1059. }
  1060.  
  1061. // if sv_downloadurl isn't set, the fastdl isn't enabled properly
  1062. decl String:strUrl[PLATFORM_MAX_PATH];
  1063. GetConVarString(g_hDownloadUrl, strUrl, sizeof(strUrl));
  1064. if(StrEqual(strUrl, ""))
  1065. {
  1066. return false;
  1067. }
  1068.  
  1069. return true;
  1070. }
  1071.  
  1072. stock GetFlamethrowerStrength(client)
  1073. {
  1074. if(!Client_IsValid(client)) return 0;
  1075. if(!IsPlayerAlive(client)) return 0;
  1076. new entity = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon");
  1077. if(!IsClassname(entity, "tf_weapon_flamethrower")) return 0;
  1078.  
  1079. new strength = GetEntProp(entity, Prop_Send, "m_iActiveFlames");
  1080. return strength;
  1081. }
  1082.  
  1083. stock GetClientSlot(client)
  1084. {
  1085. if(!Client_IsValid(client)) return -1;
  1086. if(!IsPlayerAlive(client)) return -1;
  1087.  
  1088. new slot = GetWeaponSlot(client, Client_GetActiveWeapon(client));
  1089. return slot;
  1090. }
  1091.  
  1092. public Action:OnWeaponReload(weapon)
  1093. {
  1094. if(weapon == -1) return Plugin_Continue;
  1095. if(!HasAttribute[weapon]) return Plugin_Continue;
  1096. if(!NoReloading[weapon]) return Plugin_Continue;
  1097.  
  1098. return Plugin_Handled;
  1099. }
  1100.  
  1101. public OnEntityCreated(entity, const String:strClassname[])
  1102. {
  1103. if(!IsValidEntity(entity)) return;
  1104.  
  1105. Attributes_EntityCreated(entity, String:strClassname);
  1106. }
  1107.  
  1108. public Attributes_EntityCreated(entity, const String:strClassname[])
  1109. {
  1110. if(entity <= 0) return;
  1111. if(!IsValidEdict(entity)) return;
  1112.  
  1113. g_entitySlot[entity] = -1;
  1114. g_fEntityCreateTime[entity] = GetEngineTime();
  1115.  
  1116. if(StrContains(strClassname, "tf_projectile_", false) >= 0 && !StrEqual(strClassname, "tf_projectile_syringe"))
  1117. {
  1118. SDKHook(entity, SDKHook_StartTouch, ProjectileStartTouch);
  1119. SDKHook(entity, SDKHook_Think, ProjectilePreThink);
  1120.  
  1121. // Add this entity to the projectile list, used currently for controllable projectiles
  1122. PushArrayCell(g_hProjectileList, entity);
  1123.  
  1124. CreateTimer(0.0, Attributes_ProjCreatedPost, entity);
  1125. }
  1126.  
  1127. if(StrContains(strClassname, "tf_weapon_", false) >= 0)
  1128. {
  1129. SDKHookEx(entity, SDKHook_Reload, OnWeaponReload);
  1130. }
  1131.  
  1132. Attribute_1040_EntityCreated(entity);
  1133. }
  1134.  
  1135. stock PrecacheParticle(String:strName[])
  1136. {
  1137. if(IsValidEntity(0))
  1138. {
  1139. new particle = CreateEntityByName("info_particle_system");
  1140. if(IsValidEdict(particle))
  1141. {
  1142. new String:tName[32];
  1143. GetEntPropString(0, Prop_Data, "m_iName", tName, sizeof(tName));
  1144. DispatchKeyValue(particle, "targetname", "tf2particle");
  1145. DispatchKeyValue(particle, "parentname", tName);
  1146. DispatchKeyValue(particle, "effect_name", strName);
  1147. DispatchSpawn(particle);
  1148. SetVariantString(tName);
  1149. AcceptEntityInput(particle, "SetParent", 0, particle, 0);
  1150. ActivateEntity(particle);
  1151. AcceptEntityInput(particle, "start");
  1152. CreateTimer(0.01, RemoveParticle, particle);
  1153. }
  1154. }
  1155. }
  1156.  
  1157. stock SuperPrecacheSound(String:strPath[], String:strPluginName[] = "")
  1158. {
  1159. if(strlen(strPath) == 0) return;
  1160.  
  1161. PrecacheSound(strPath, true);
  1162. decl String:strBuffer[PLATFORM_MAX_PATH];
  1163. Format(strBuffer, sizeof(strBuffer), "sound/%s", strPath);
  1164. AddFileToDownloadsTable(strBuffer);
  1165.  
  1166. if(!FileExists(strBuffer) && !FileExists(strBuffer, true))
  1167. {
  1168. if(StrEqual(strPluginName, "")) LogError("PRECACHE ERROR: Unable to precache sound at '%s'. No fastdl service detected, and file is not on the server.", strPath);
  1169. else LogError("PRECACHE ERROR: Unable to precache sound at '%s'. No fastdl service detected, and file is not on the server. It was required by the plugin '%s'", strPath, strPluginName);
  1170. }
  1171. }
  1172.  
  1173. stock SuperPrecacheModel(String:strModel[], bool:bRequiredOnServer = false, bool:bMdlOnly = false)
  1174. {
  1175. decl String:strBase[PLATFORM_MAX_PATH];
  1176. decl String:strPath[PLATFORM_MAX_PATH];
  1177. Format(strBase, sizeof(strBase), strModel);
  1178. SplitString(strBase, ".mdl", strBase, sizeof(strBase));
  1179.  
  1180. if(!bMdlOnly)
  1181. {
  1182. Format(strPath, sizeof(strPath), "%s.phy", strBase);
  1183. if(FileExists(strPath)) AddFileToDownloadsTable(strPath);
  1184.  
  1185. Format(strPath, sizeof(strPath), "%s.sw.vtx", strBase);
  1186. if(FileExists(strPath)) AddFileToDownloadsTable(strPath);
  1187.  
  1188. Format(strPath, sizeof(strPath), "%s.vvd", strBase);
  1189. if(FileExists(strPath)) AddFileToDownloadsTable(strPath);
  1190.  
  1191. Format(strPath, sizeof(strPath), "%s.dx80.vtx", strBase);
  1192. if(FileExists(strPath)) AddFileToDownloadsTable(strPath);
  1193.  
  1194. Format(strPath, sizeof(strPath), "%s.dx90.vtx", strBase);
  1195. if(FileExists(strPath)) AddFileToDownloadsTable(strPath);
  1196. }
  1197.  
  1198. AddFileToDownloadsTable(strModel);
  1199.  
  1200. if(HasFastDownload())
  1201. {
  1202. if(bRequiredOnServer && !FileExists(strModel) && !FileExists(strModel, true))
  1203. {
  1204. LogError("PRECACHE ERROR: Unable to precache REQUIRED model '%s'. File is not on the server.", strModel);
  1205. }
  1206. }
  1207.  
  1208. return PrecacheModel(strModel, true);
  1209. }
  1210.  
  1211. new g_iProjectileBounces[MAX_EDICTS+1] = 0;
  1212.  
  1213. Attribute_1040_EntityCreated(entity)
  1214. {
  1215. g_iProjectileBounces[entity] = 0;
  1216. }
  1217.  
  1218. public Action:ProjectileStartTouch(entity, other)
  1219. {
  1220. new owner = Entity_GetOwner(entity);
  1221. if(!Client_IsValid(owner)) return Plugin_Continue;
  1222.  
  1223. new Action:aReturn = Plugin_Continue;
  1224.  
  1225. aReturn = ActionApply(aReturn, Attribute_1040_PStartTouch(entity, other, owner, g_entitySlot[entity]));
  1226.  
  1227. return aReturn;
  1228. }
  1229.  
  1230. public Action:Attributes_ProjCreatedPost(Handle:hTimer, any:entity)
  1231. {
  1232. if(!IsValidEdict(entity)) return Plugin_Continue;
  1233.  
  1234. decl String:strClassname[255];
  1235. GetEdictClassname(entity, strClassname, sizeof(strClassname));
  1236. if(StrEqual(strClassname, "tf_projectile_syringe")) return Plugin_Continue;
  1237. if(StrContains(strClassname, "tf_projectile_", false) < 0) return Plugin_Continue;
  1238.  
  1239. new owner = Entity_GetOwner(entity);
  1240. if(Client_IsValid(owner))
  1241. {
  1242. new slot = GetClientSlot(owner);
  1243. g_entitySlot[entity] = slot;
  1244. }
  1245.  
  1246. return Plugin_Continue;
  1247. }
  1248.  
  1249. public Action:Attribute_1040_PStartTouch(entity, other, owner, slot)
  1250. {
  1251. new weapon = GetPlayerWeaponSlot(owner, slot);
  1252. if(weapon == -1) return Plugin_Continue;
  1253. if(!HasAttribute[weapon]) return Plugin_Continue;
  1254. if(!ProjectilesBounce[weapon]) return Plugin_Continue;
  1255. if(Client_IsValid(other)) return Plugin_Continue;
  1256. if(IsEntityBuilding(other)) return Plugin_Continue;
  1257.  
  1258. new total = RoundFloat(ProjectilesBounce_Count[weapon]);
  1259. if(g_iProjectileBounces[entity] >= total) return Plugin_Continue;
  1260. SDKHook(entity, SDKHook_Touch, Attribute_1040_OnTouchBounce);
  1261. g_iProjectileBounces[entity]++;
  1262.  
  1263. return Plugin_Handled;
  1264. }
  1265.  
  1266. public Action:Attribute_1040_OnTouchBounce(entity, other)
  1267. {
  1268. decl Float:vOrigin[3];
  1269. Entity_GetAbsOrigin(entity, vOrigin);
  1270.  
  1271. decl Float:vAngles[3];
  1272. GetEntPropVector(entity, Prop_Data, "m_angRotation", vAngles);
  1273.  
  1274. decl Float:vVelocity[3];
  1275. GetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vVelocity);
  1276.  
  1277. new Handle:hTrace = TR_TraceRayFilterEx(vOrigin, vAngles, MASK_SHOT, RayType_Infinite, TraceRayDontHitEntity, entity);
  1278.  
  1279. if(!TR_DidHit(hTrace))
  1280. {
  1281. CloseHandle(hTrace);
  1282. return Plugin_Continue;
  1283. }
  1284.  
  1285. decl Float:vNormal[3];
  1286. TR_GetPlaneNormal(hTrace, vNormal);
  1287.  
  1288. CloseHandle(hTrace);
  1289.  
  1290. new Float:dotProduct = GetVectorDotProduct(vNormal, vVelocity);
  1291.  
  1292. ScaleVector(vNormal, dotProduct);
  1293. ScaleVector(vNormal, 2.0);
  1294.  
  1295. decl Float:vBounceVec[3];
  1296. SubtractVectors(vVelocity, vNormal, vBounceVec);
  1297.  
  1298. decl Float:vNewAngles[3];
  1299. GetVectorAngles(vBounceVec, vNewAngles);
  1300.  
  1301. TeleportEntity(entity, NULL_VECTOR, vNewAngles, vBounceVec);
  1302.  
  1303. SDKUnhook(entity, SDKHook_Touch, Attribute_1040_OnTouchBounce);
  1304. return Plugin_Handled;
  1305. }
  1306.  
  1307. stock GetWeaponSlot(client, weapon)
  1308. {
  1309. if(!Client_IsValid(client)) return -1;
  1310.  
  1311. for(new i = 0; i < SLOTS_MAX; i++)
  1312. {
  1313. if(weapon == GetPlayerWeaponSlot(client, i))
  1314. {
  1315. return i;
  1316. }
  1317. }
  1318. return -1;
  1319. }
  1320.  
  1321. stock bool:OnGround(client)
  1322. {
  1323. return (GetEntityFlags(client) & FL_ONGROUND == FL_ONGROUND);
  1324. }
  1325.  
  1326. public Action:OnThinkRocketHook(Handle:timer, any:Data)
  1327. {
  1328. new index = GetArraySize(g_hProjectileList)-1;
  1329. while(index >= 0)
  1330. {
  1331. if(!ControllableProjectileThink(GetArrayCell(g_hProjectileList, index)))
  1332. RemoveFromArray(g_hProjectileList, index);
  1333. --index;
  1334. }
  1335. }
  1336.  
  1337. #define CONTROLLABLE_PROJECTILE_DELAY 0.05
  1338.  
  1339. public ControllableProjectileThink(entity)
  1340. {
  1341. if(!IsValidEntity(entity)) return false;
  1342.  
  1343. new owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
  1344. if(!Client_IsValid(owner)) return false;
  1345.  
  1346. new weapon;
  1347.  
  1348. for(new slot = 0; slot <= 4; slot++)
  1349. {
  1350. weapon = GetPlayerWeaponSlot(owner, slot);
  1351. if(weapon != -1)
  1352. {
  1353. if(HasAttribute[weapon])
  1354. {
  1355. if(ControllableProjectiles[weapon])
  1356. {
  1357. break;
  1358. }
  1359. }
  1360. }
  1361. }
  1362.  
  1363. if(weapon == -1 || !HasAttribute[weapon] || !ControllableProjectiles[weapon])
  1364. {
  1365. return false;
  1366. }
  1367.  
  1368. new Float:fLife = GetEntityLife(entity);
  1369. fLife -= CONTROLLABLE_PROJECTILE_DELAY;
  1370. if(fLife < 0.0) return true;
  1371.  
  1372. decl Float:vRocketOrigin[3];
  1373. GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", vRocketOrigin);
  1374. decl Float:vTargetOrigin[3];
  1375. GetClientPointPosition(owner, vTargetOrigin, MASK_VISIBLE);
  1376.  
  1377. decl Float:vRocketVelocity[3];
  1378. GetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vRocketVelocity);
  1379. new Float:fRocketSpeed = GetVectorLength(vRocketVelocity);
  1380.  
  1381. decl Float:vDifference[3];
  1382. SubtractVectors(vTargetOrigin, vRocketOrigin, vDifference);
  1383.  
  1384. // middle += velocity
  1385. // (aka becomes less accurate)
  1386. new Float:fBase = ControllableProjectiles_Control[weapon];
  1387. new Float:fInaccuracy = fBase - fLife*150.0;
  1388. if(fInaccuracy < 0.0) fInaccuracy = 0.0;
  1389. if(fInaccuracy > 400.0) fInaccuracy = 400.0;
  1390. NormalizeVector(vDifference, vDifference);
  1391. ScaleVector(vDifference, fInaccuracy);
  1392.  
  1393. AddVectors(vRocketVelocity, vDifference, vDifference);
  1394. NormalizeVector(vDifference, vDifference);
  1395.  
  1396. decl Float:fRocketAngle[3];
  1397. GetVectorAngles(vDifference, fRocketAngle);
  1398. SetEntPropVector(entity, Prop_Data, "m_angRotation", fRocketAngle);
  1399.  
  1400. ScaleVector(vDifference, fRocketSpeed);
  1401. SetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vDifference);
  1402.  
  1403. return true;
  1404. }
  1405.  
  1406. Attribute_1056_OnProjectile(entity, &client, &slot)
  1407. {
  1408. if(!IsClassname(entity, "tf_projectile_flare")) return;
  1409.  
  1410. decl Float:vOrigin[3];
  1411. Entity_GetAbsOrigin(entity, vOrigin);
  1412.  
  1413. Attribute_1056_IgniteLeak(vOrigin);
  1414. }
  1415.  
  1416. stock Shake(client)
  1417. {
  1418. new flags = GetCommandFlags("shake") & (~FCVAR_CHEAT);
  1419. SetCommandFlags("shake", flags);
  1420.  
  1421. FakeClientCommand(client, "shake");
  1422.  
  1423. flags = GetCommandFlags("shake") | (FCVAR_CHEAT);
  1424. SetCommandFlags("shake", flags);
  1425. }
  1426.  
  1427. stock EmitSoundFromOrigin(const String:sound[],const Float:orig[3])
  1428. {
  1429. EmitSoundToAll(sound,SOUND_FROM_WORLD,SNDCHAN_AUTO,SNDLEVEL_NORMAL,SND_NOFLAGS,SNDVOL_NORMAL,SNDPITCH_NORMAL,-1,orig,NULL_VECTOR,true,0.0);
  1430. }
  1431.  
  1432. new Float:g_f1026LastLand[MAXPLAYERS+1] = 0.0;
  1433.  
  1434. Attribute_1026_RocketJumpLand(client, weapon)
  1435. {
  1436. if(GetEngineTime() <= g_f1026LastLand[client] + ATTRIBUTE_1026_COOLDOWN) return;
  1437.  
  1438. if(!Earthquake[weapon]) return;
  1439.  
  1440. new Float:fPushMax = ATTRIBUTE_1026_PUSHMAX;
  1441.  
  1442. new Float:fDistance;
  1443.  
  1444. decl Float:vClientPos[3];
  1445. Entity_GetAbsOrigin(client, vClientPos);
  1446. decl Float:vVictimPos[3];
  1447. decl Float:vPush[3];
  1448.  
  1449. new team = GetClientTeam(client);
  1450.  
  1451. EmitSoundFromOrigin(SOUND_EXPLOSION_BIG, vClientPos);
  1452. TE_SetupExplosion(vClientPos, g_iExplosionSprite, 10.0, 1, 0, 0, 750);
  1453. TE_SendToAll();
  1454. TE_SetupBeamRingPoint(vClientPos, 10.0, ATTRIBUTE_1026_DISTANCE_LIMIT, g_iWhite, g_iHaloSprite, 0, 10, 0.2, 10.0, 0.5, g_iTeamColorSoft[team], 50, 0);
  1455. TE_SendToAll();
  1456.  
  1457. Shake(client);
  1458.  
  1459. for(new victim = 0; victim <= MaxClients; victim++)
  1460. {
  1461. if(Client_IsValid(victim) && IsClientInGame(victim) && IsPlayerAlive(victim) && team != GetClientTeam(victim) && OnGround(victim))
  1462. {
  1463. Entity_GetAbsOrigin(victim, vVictimPos);
  1464. fDistance = GetVectorDistance(vVictimPos, vClientPos);
  1465. if(fDistance <= ATTRIBUTE_1026_DISTANCE_LIMIT)
  1466. {
  1467. SubtractVectors(vVictimPos, vClientPos, vPush);
  1468. new Float:fPushScale = (ATTRIBUTE_1026_DISTANCE_LIMIT - fDistance)*ATTRIBUTE_1026_PUSHSCALE;
  1469. if(fPushScale > fPushMax) fPushScale = fPushMax;
  1470. ScaleVector(vPush, fPushScale);
  1471. Shake(victim);
  1472. if(vPush[2] < 400.0) vPush[2] = 400.0;
  1473. TeleportEntity(victim, NULL_VECTOR, NULL_VECTOR, vPush);
  1474. g_f1026LastLand[client] = GetEngineTime();
  1475. }
  1476. }
  1477. }
  1478. }
  1479.  
  1480. Attribute_1087_Prethink(client, &buttons, &slot, &buttonsLast)
  1481. {
  1482. new weapon = GetPlayerWeaponSlot(client, slot);
  1483. if(weapon == -1) return buttons;
  1484. if(!HasAttribute[weapon]) return buttons;
  1485. if(AttackWhileCloaked[weapon] && (buttons & IN_ATTACK == IN_ATTACK))
  1486. {
  1487. new Float:flTime = GetGameTime();
  1488. if(TF2_IsPlayerInCondition(client, TFCond_Cloaked))
  1489. {
  1490. TF2_RemoveCondition(client, TFCond_Cloaked);
  1491. SetEntPropFloat(client, Prop_Send, "m_flNextAttack", flTime);
  1492. }
  1493. SetEntPropFloat(client, Prop_Send, "m_flStealthNoAttackExpire", flTime);
  1494. SetEntPropFloat(client, Prop_Send, "m_flInvisChangeCompleteTime", flTime);
  1495. }
  1496.  
  1497. return buttons;
  1498. }
  1499.  
  1500. public OnClientPutInServer(client)
  1501. {
  1502. SDKHook(client, SDKHook_OnTakeDamage, Attributes_OnTakeDamage);
  1503. SDKHook(client, SDKHook_PreThink, OnClientPreThink);
  1504. SDKHook(client, SDKHook_WeaponSwitchPost, Attributes_WeaponSwitch);
  1505. }
  1506.  
  1507. public Action:Attributes_WeaponSwitch(client, weapon)
  1508. {
  1509. if(!Client_IsValid(client) || weapon == -1 || !HasAttribute[weapon]) return Plugin_Continue;
  1510.  
  1511. if(DrawMiniCrits[weapon])
  1512. {
  1513. TF2_AddCondition(client, TFCond_Buffed, DrawMiniCrits_Value[weapon]);
  1514. TF2_AddCondition(client, TFCond_MarkedForDeath, DrawMiniCrits_Value[weapon]);
  1515. }
  1516.  
  1517. return Plugin_Continue;
  1518. }
  1519.  
  1520. public Attributes_PreThink(client)
  1521. {
  1522. if(!IsPlayerAlive(client)) return;
  1523.  
  1524. new buttonsLast = g_iLastButtons[client];
  1525. new buttons = GetClientButtons(client);
  1526. new buttons2 = buttons;
  1527.  
  1528. new Handle:hArray = CreateArray();
  1529. new slot = GetClientSlot(client);
  1530. if(slot >= 0) PushArrayCell(hArray, slot);
  1531. PushArrayCell(hArray, 4);
  1532.  
  1533. new slot2;
  1534. for(new i = 0; i < GetArraySize(hArray); i++)
  1535. {
  1536. slot2 = GetArrayCell(hArray, i);
  1537. PilotProt_Think(client);
  1538. DamageGround_Prethink(client);
  1539. InfectVictim_Prethink(client);
  1540. buttons = Attribute_1034_Prethink(client, buttons, slot2, buttonsLast);
  1541. buttons = Attribute_1039_Prethink(client, buttons, slot2, buttonsLast);
  1542. buttons = Attribute_1012_Prethink(client, buttons, slot2, buttonsLast);
  1543. buttons = Attribute_1056_Prethink(client, buttons, slot2, buttonsLast);
  1544. buttons = Attribute_1087_Prethink(client, buttons, slot2, buttonsLast);
  1545. }
  1546. CloseHandle(hArray);
  1547.  
  1548. slot2 = -1;
  1549.  
  1550. for(slot2 = 0; slot2 <= SLOTS_MAX; slot2++)
  1551. {
  1552.  
  1553. }
  1554.  
  1555. if(buttons != buttons2) SetEntProp(client, Prop_Data, "m_nButtons", buttons);
  1556. g_iLastButtons[client] = buttons;
  1557.  
  1558. g_bWasDisguised[client] = IsDisguised(client);
  1559. }
  1560.  
  1561. public DamageGround_Prethink(client)
  1562. {
  1563. if(Client_IsValid(client))
  1564. {
  1565. new weapon = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon");
  1566. if(weapon != -1 && HasAttribute[weapon] && DamageOnGround[weapon])
  1567. {
  1568. if(GetEntityFlags(client) & FL_ONGROUND)
  1569. {
  1570. TF2Attrib_RemoveByName(weapon, "damage bonus");
  1571. TF2Attrib_SetByName(weapon, "damage penalty", DamageOnGround_Value2[weapon]);
  1572. } else
  1573. {
  1574. TF2Attrib_RemoveByName(weapon, "damage penalty");
  1575. TF2Attrib_SetByName(weapon, "damage bonus", DamageOnGround_Value1[weapon]);
  1576. }
  1577. }
  1578. }
  1579. }
  1580.  
  1581. public PilotProt_Think(client)
  1582. {
  1583. if(!Client_IsValid(client)) return;
  1584.  
  1585. new weapon = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon");
  1586.  
  1587. if(weapon == -1) return;
  1588. if(!HasAttribute[weapon]) return;
  1589.  
  1590. if(ReducedDamageInAir[weapon])
  1591. {
  1592. if(GetEntityFlags(client) & FL_ONGROUND)
  1593. {
  1594. TF2Attrib_RemoveByName(weapon, "dmg taken increased");
  1595. TF2Attrib_SetByName(weapon, "dmg taken increased", ReducedDamageInAir_Value1[weapon]);
  1596. }else
  1597. {
  1598. TF2Attrib_RemoveByName(weapon, "dmg taken increased");
  1599. TF2Attrib_SetByName(weapon, "dmg taken increased", ReducedDamageInAir_Value2[weapon]);
  1600. }
  1601. }
  1602. }
  1603.  
  1604. public OnClientPreThink(client)
  1605. {
  1606. Attributes_PreThink(client);
  1607. FastCloakThink(client);
  1608. }
  1609.  
  1610. public ProjectilePreThink(entity)
  1611. {
  1612. if(!IsValidEdict(entity)) return;
  1613.  
  1614. new client = Entity_GetOwner(entity);
  1615. new slot = g_entitySlot[entity];
  1616.  
  1617. Attribute_1056_OnProjectile(entity, client, slot);
  1618. }
  1619.  
  1620. Attribute_1056_Prethink(client, &buttons, &slot, &buttonsLast)
  1621. {
  1622. new weapon = GetPlayerWeaponSlot(client, slot);
  1623. if(weapon == -1) return buttons;
  1624.  
  1625. if(HasAttribute[weapon] && AltFireIsOil[weapon])
  1626. {
  1627. if(buttons & IN_ATTACK2 == IN_ATTACK2)
  1628. {
  1629. Attribute_1056_OilLeak(client, slot);
  1630. if(GetClientTeam(client) == TEAM_SPEC)
  1631. {
  1632. return buttons;
  1633. }
  1634. }
  1635. }
  1636.  
  1637. if(GetFlamethrowerStrength(client) >= 2)
  1638. {
  1639. decl Float:vOrigin[3];
  1640. Entity_GetAbsOrigin(client, vOrigin);
  1641. Attribute_1056_IgniteLeak(vOrigin);
  1642. }
  1643.  
  1644. new attacker = g_iOilLeakDamageOwner[client];
  1645. if(Client_IsValid(attacker))
  1646. {
  1647. Entity_Hurt(client, 2 + RoundFloat(g_iOilLeakDamage[client] * 1.5), attacker, TF_DMG_FIRE);
  1648. g_iOilLeakDamage[client] += 2;
  1649. } else
  1650. {
  1651. g_iOilLeakDamage[client] -= 4;
  1652. if(g_iOilLeakDamage[client] < 0) g_iOilLeakDamage[client] = 0;
  1653. }
  1654. g_iOilLeakDamageOwner[client] = -1;
  1655.  
  1656. return buttons;
  1657. }
  1658.  
  1659. Attribute_1056_OilLeak(client, slot)
  1660. {
  1661. if(g_fOilLeakDelay[client] >= GetEngineTime() - ATTRIBUTE_FIRELEAK_TIME) return;
  1662. if(!SubtractWeaponAmmo(client, slot, ATTRIBUTE_FIRELEAK_COST)) return;
  1663.  
  1664. g_fOilLeakDelay[client] = GetEngineTime();
  1665.  
  1666. new weapon = GetPlayerWeaponSlot(client, slot);
  1667. if(weapon == -1) return;
  1668.  
  1669. if(!HasAttribute[weapon]) return;
  1670. if(!AltFireIsOil[weapon])
  1671. {
  1672. return;
  1673. } else
  1674. {
  1675. EmitSoundToAll(SOUND_FIRELEAK_OIL, client, SNDCHAN_WEAPON, _, SND_CHANGEVOL|SND_CHANGEPITCH, 1.0, GetRandomInt(60, 140));
  1676. }
  1677.  
  1678. if(g_hOilLeakEntities == INVALID_HANDLE) g_hOilLeakEntities = CreateArray();
  1679.  
  1680. new entity = CreateEntityByName("prop_physics_override");
  1681. if(IsValidEdict(entity))
  1682. {
  1683. SetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity", client);
  1684. SetEntityModel(entity, MODEL_DEFAULTPHYSICS);
  1685. DispatchSpawn(entity);
  1686.  
  1687. AcceptEntityInput(entity, "DisableCollision");
  1688. SetEntityRenderMode(entity, RENDER_TRANSCOLOR);
  1689. SetEntityRenderColor(entity, _, _, _, 0);
  1690.  
  1691. decl String:strName[10];
  1692. Format(strName, sizeof(strName), "tf2leak");
  1693. DispatchKeyValue(entity, "targetname", strName);
  1694.  
  1695. decl Float:fAngles[3], Float:fVelocity[3], Float:fOrigin[3];
  1696. GetClientEyePosition(client, fOrigin);
  1697. GetClientEyeAngles(client, fAngles);
  1698. AnglesToVelocity(fAngles, fVelocity, 600.0);
  1699.  
  1700. TeleportEntity(entity, fOrigin, fAngles, fVelocity);
  1701.  
  1702. new team = GetClientTeam(client);
  1703.  
  1704. if(team == TEAM_BLUE)
  1705. {
  1706. AttachParticle(entity, "peejar_trail_blu");
  1707. AttachParticle(entity, "peejar_trail_blu");
  1708. AttachParticle(entity, "peejar_trail_blu");
  1709. AttachParticle(entity, "peejar_trail_blu");
  1710. AttachParticle(entity, "peejar_trail_blu");
  1711. AttachParticle(entity, "peejar_trail_blu");
  1712. AttachParticle(entity, "peejar_trail_blu");
  1713. } else if(team == TEAM_RED)
  1714. {
  1715. AttachParticle(entity, "peejar_trail_red");
  1716. AttachParticle(entity, "peejar_trail_red");
  1717. AttachParticle(entity, "peejar_trail_red");
  1718. AttachParticle(entity, "peejar_trail_red");
  1719. AttachParticle(entity, "peejar_trail_red");
  1720. AttachParticle(entity, "peejar_trail_red");
  1721. AttachParticle(entity, "peejar_trail_red");
  1722. }
  1723.  
  1724. g_fOilLeakLife[entity] = GetEngineTime() + 10.0;
  1725. g_iOilLeakStatus[entity] = 0;
  1726.  
  1727. PushArrayCell(g_hOilLeakEntities, entity);
  1728. }
  1729. }
  1730.  
  1731. new g_iRopeTime[MAXPLAYERS+1] = 0;
  1732.  
  1733. stock ClientRope(client, Float:vTargetOrigin[3])
  1734. {
  1735. if(g_iRopeTime[client] <= 0)
  1736. {
  1737. new team = GetClientTeam(client);
  1738. decl Float:vOrigin[3];
  1739. Entity_GetAbsOrigin(client, vOrigin);
  1740. vOrigin[2] += 30.0;
  1741. TE_SetupBeamPoints(vOrigin, vTargetOrigin, g_iBeamSprite, g_iHaloSprite, 0, 0, 0.1, 3.0, 0.1, 0, 0.0, g_iTeamColor[team], 3);
  1742. TE_SendToAll();
  1743. g_iRopeTime[client] = 4;
  1744. } else
  1745. {
  1746. g_iRopeTime[client]--;
  1747. }
  1748. }
  1749.  
  1750. Attribute_1056_IgniteLeak(Float:vPos[3])
  1751. {
  1752. decl Float:vOrigin[3];
  1753. decl Float:vFire[3];
  1754. for(new i = GetArraySize(g_hOilLeakEntities)-1; i >= 0; i--)
  1755. {
  1756. new entity = GetArrayCell(g_hOilLeakEntities, i);
  1757.  
  1758. if(IsClassname(entity, "prop_physics"))
  1759. {
  1760. Entity_GetAbsOrigin(entity, vOrigin);
  1761. if(g_iOilLeakStatus[entity] == 1 && GetVectorDistance(vOrigin, vPos) / 50.0 <= 3.0)
  1762. {
  1763. g_iOilLeakStatus[entity] = 2;
  1764. g_fOilLeakLife[entity] = GetEngineTime() + 5.0;
  1765. Attribute_1056_IgniteLeak(vOrigin);
  1766. vFire[2] = 5.0;
  1767.  
  1768. vFire[0] = 22.0;
  1769. vFire[1] = 22.0;
  1770. AttachParticle(entity, PARTICLE_FIRE, _, vFire);
  1771.  
  1772. vFire[0] = 22.0;
  1773. vFire[1] = -22.0;
  1774. AttachParticle(entity, PARTICLE_FIRE, _, vFire);
  1775.  
  1776. vFire[0] = -22.0;
  1777. vFire[1] = 22.0;
  1778. AttachParticle(entity, PARTICLE_FIRE, _, vFire);
  1779.  
  1780. vFire[0] = -22.0;
  1781. vFire[1] = -22.0;
  1782. AttachParticle(entity, PARTICLE_FIRE, _, vFire);
  1783.  
  1784. vFire[0] = 0.0;
  1785. vFire[1] = 0.0;
  1786. AttachParticle(entity, PARTICLE_FIRE, _, vFire);
  1787.  
  1788. new String:strParticle[16];
  1789. if(GetClientTeam(GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity")) == TEAM_BLUE) Format(strParticle, sizeof(strParticle), "%s", PARTICLE_AREA_FIRE_BLUE);
  1790. if(!StrEqual(strParticle, "")) AttachParticle(entity, strParticle, _, vFire);
  1791. }
  1792. }
  1793. }
  1794. }
  1795.  
  1796. Attributes_1056_Think(bool:bTerminate = false)
  1797. {
  1798. if(g_hOilLeakEntities == INVALID_HANDLE) return;
  1799.  
  1800. new iClientLeaks[MAXPLAYERS+1] = 0;
  1801.  
  1802. for(new i = GetArraySize(g_hOilLeakEntities) - 1; i >= 0; i--)
  1803. {
  1804. new entity = GetArrayCell(g_hOilLeakEntities, i);
  1805. new owner = Attribute_1056_OilThink(entity);
  1806. if(bTerminate || owner < 0 || iClientLeaks[owner] > 13)
  1807. {
  1808. if(IsClassname(entity, "prop_physics")) AcceptEntityInput(entity, "kill");
  1809. RemoveFromArray(g_hOilLeakEntities, i);
  1810. } else
  1811. {
  1812. iClientLeaks[owner]++;
  1813. }
  1814. }
  1815.  
  1816. if(bTerminate) CloseHandle(g_hOilLeakEntities);
  1817. }
  1818.  
  1819. Attribute_1056_OilThink(entity)
  1820. {
  1821. if(!IsClassname(entity, "prop_physics")) return -1;
  1822.  
  1823. new owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
  1824. if(!Client_IsValid(owner)) return -1;
  1825.  
  1826. new Float:fLife = g_fOilLeakLife[entity];
  1827. if(GetEngineTime() >= fLife) return -1;
  1828.  
  1829.  
  1830. decl Float:vOrigin[3];
  1831. Entity_GetAbsOrigin(entity, vOrigin);
  1832.  
  1833. if(g_iOilLeakStatus[entity] == 0)
  1834. {
  1835. new Float:vAngleDown[3];
  1836. vAngleDown[0] = 90.0;
  1837. new Handle:hTrace = TR_TraceRayFilterEx(vOrigin, vAngleDown, MASK_PLAYERSOLID, RayType_Infinite, TraceRayDontHitPlayers);
  1838. if(TR_DidHit(hTrace))
  1839. {
  1840. decl Float:vEnd[3];
  1841. TR_GetEndPosition(vEnd, hTrace);
  1842. if(GetVectorDistance(vEnd, vOrigin) / 50.0 <= 0.4)
  1843. {
  1844. new Float:vStop[3];
  1845. SetEntityMoveType(entity, MOVETYPE_NONE);
  1846. TeleportEntity(entity, vEnd, NULL_VECTOR, vStop);
  1847.  
  1848. SetEntityRenderColor(entity, _, _, _, 255);
  1849. SetEntityRenderMode(entity, RENDER_NONE);
  1850. SetEntityModel(entity, MODEL_FIRELEAK);
  1851. g_iOilLeakStatus[entity] = 1;
  1852. }
  1853. }
  1854. CloseHandle(hTrace);
  1855. } else if(g_iOilLeakStatus[entity] == 2)
  1856. {
  1857. for(new client = 0; client <= MaxClients; client++)
  1858. {
  1859. if(Client_IsValid(client) && IsPlayerAlive(client) && (GetClientTeam(client) != GetClientTeam(owner) || client == owner))
  1860. {
  1861. if(Entity_GetDistanceOrigin(client, vOrigin) / 50.0 <= 1.5)
  1862. {
  1863. g_iOilLeakDamageOwner[client] = owner;
  1864. }
  1865. }
  1866. }
  1867. }
  1868.  
  1869. return owner;
  1870. }
  1871.  
  1872. InfectVictim_Prethink(client)
  1873. {
  1874. if(!Client_IsValid(client)) return;
  1875.  
  1876. if(isInfected[client])
  1877. {
  1878. new healers = GetEntProp(client, Prop_Send, "m_nNumHealers");
  1879.  
  1880. if(healers > 0)
  1881. {
  1882. isInfected[client] = false;
  1883. }
  1884. }
  1885. }
  1886.  
  1887. Attribute_1034_Prethink(client, &buttons, slot, &buttonsLast)
  1888. {
  1889. new weapon = GetPlayerWeaponSlot(client, slot);
  1890. if(weapon == -1) return buttons;
  1891.  
  1892. if(!ItemIsHeavy[weapon]) return buttons;
  1893.  
  1894. if(OnGround(client))
  1895. {
  1896. fAttribute_1034_Time[client] = 0.0;
  1897. }
  1898. if(GetEntityMoveType(client) != MOVETYPE_WALK) return buttons;
  1899.  
  1900. decl Float:vVelocity[3];
  1901. Entity_GetLocalVelocity(client, vVelocity);
  1902.  
  1903. fAttribute_1034_Time[client] += 0.1;
  1904. if(fAttribute_1034_Time[client] > 1.0) fAttribute_1034_Time[client] = 1.0;
  1905.  
  1906. new Float:fPush = ItemIsHeavy_Force[weapon] * fAttribute_1034_Time[client];
  1907.  
  1908. if(vVelocity[2] > 0)
  1909. {
  1910. vVelocity[2] -= fPush * 0.3;
  1911. } else
  1912. {
  1913. vVelocity[2] -= fPush * 1.0;
  1914. }
  1915.  
  1916. TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, vVelocity);
  1917.  
  1918. return buttons;
  1919. }
  1920.  
  1921. public OnGameFrame()
  1922. {
  1923. Attributes_OnGameFrame();
  1924. }
  1925.  
  1926. Attributes_OnGameFrame()
  1927. {
  1928. Attributes_1056_Think();
  1929. }
  1930.  
  1931. public Action:CustomWeaponsTF_OnAddAttribute(weapon, client, const String:attrib[], const String:plugin[], const String:value[])
  1932. {
  1933. if(!StrEqual(plugin, "advanced-weaponiser-2-attributes")) return Plugin_Continue;
  1934.  
  1935. new Action:action;
  1936.  
  1937. if(StrEqual(attrib, "fastcloak on backstab"))
  1938. {
  1939. FastcloakOnBackstab[weapon] = true;
  1940. action = Plugin_Handled;
  1941. } else if(StrEqual(attrib, "projectiles bounce"))
  1942. {
  1943. ProjectilesBounce[weapon] = true;
  1944. ProjectilesBounce_Count[weapon] = StringToFloat(value);
  1945.  
  1946. action = Plugin_Handled;
  1947. } else if(StrEqual(attrib, "earthquake on rocket jump land"))
  1948. {
  1949. Earthquake[weapon] = true;
  1950. action = Plugin_Handled;
  1951. } else if(StrEqual(attrib, "reload clip on damage"))
  1952. {
  1953. DamageReloads[weapon] = true;
  1954. DamageReloads_Max[weapon] = StringToFloat(value);
  1955.  
  1956. g_fTotalDamage1296[client] = 0.0;
  1957.  
  1958. action = Plugin_Handled;
  1959. } else if(StrEqual(attrib, "alt fire is oil"))
  1960. {
  1961. AltFireIsOil[weapon] = true;
  1962. action = Plugin_Handled;
  1963. } else if(StrEqual(attrib, "attack while cloaked"))
  1964. {
  1965. AttackWhileCloaked[weapon] = true;
  1966. action = Plugin_Handled;
  1967. } else if(StrEqual(attrib, "reset afterburn"))
  1968. {
  1969. ResetAfterburn[weapon] = true;
  1970. action = Plugin_Handled;
  1971. } else if(StrEqual(attrib, "controllable projectiles"))
  1972. {
  1973. ControllableProjectiles[weapon] = true;
  1974.  
  1975. ControllableProjectiles_Control[weapon] = StringToFloat(value) * 1000.0;
  1976.  
  1977. action = Plugin_Handled;
  1978. } else if(StrEqual(attrib, "item is heavy"))
  1979. {
  1980. ItemIsHeavy[weapon] = true;
  1981.  
  1982. ItemIsHeavy_Force[weapon] = StringToFloat(value);
  1983.  
  1984. action = Plugin_Handled;
  1985. } else if(StrEqual(attrib, "no reloading"))
  1986. {
  1987. NoReloading[weapon] = true;
  1988.  
  1989. TF2Attrib_SetByName(weapon, "reload time increased hidden", 1001.0);
  1990.  
  1991. action = Plugin_Handled;
  1992. } else if(StrEqual(attrib, "cloak is hook"))
  1993. {
  1994. CloakIsHook[weapon] = true;
  1995. action = Plugin_Handled;
  1996. } else if(StrEqual(attrib, "fall dmg reduced"))
  1997. {
  1998. ReducedFallDamage[weapon] = true;
  1999.  
  2000. ReducedFallDamage_Value[weapon] = StringToFloat(value);
  2001.  
  2002. action = Plugin_Handled;
  2003. } else if(StrEqual(attrib, "share damage"))
  2004. {
  2005. new String:values[2][10];
  2006. ExplodeString(value, " ", values, sizeof(values), sizeof(values[]));
  2007.  
  2008. ShareDamage[weapon] = true;
  2009.  
  2010. ShareDamage_Range[weapon] = StringToFloat(values[0]);
  2011. ShareDamage_Ratio[weapon] = StringToFloat(values[1]);
  2012.  
  2013. action = Plugin_Handled;
  2014. } else if(StrEqual(attrib, "reflected projectiles crit"))
  2015. {
  2016. ReflectCrits[weapon] = true;
  2017. action = Plugin_Handled;
  2018. } else if(StrEqual(attrib, "charge on explosive jump land"))
  2019. {
  2020. ChargeLand[weapon] = true;
  2021.  
  2022. ChargeLand_Value[weapon] = StringToFloat(value);
  2023.  
  2024. action = Plugin_Handled;
  2025. } else if(StrEqual(attrib, "crit charging players"))
  2026. {
  2027. CritCharging[weapon] = true;
  2028. action = Plugin_Handled;
  2029. } else if(StrEqual(attrib, "crouch to cloak"))
  2030. {
  2031. CrouchCloak[weapon] = true;
  2032.  
  2033. CrouchCloak_Value[weapon] = StringToFloat(value);
  2034.  
  2035. action = Plugin_Handled;
  2036. } else if(StrEqual(attrib, "increased jump height while cloaked"))
  2037. {
  2038. JumpCloak[weapon] = true;
  2039.  
  2040. JumpCloak_Value[weapon] = StringToFloat(value);
  2041.  
  2042. action = Plugin_Handled;
  2043. } else if(StrEqual(attrib, "on cloak remove debuffs"))
  2044. {
  2045. RemoveDebuffCloak[weapon] = true;
  2046. action = Plugin_Handled;
  2047. } else if(StrEqual(attrib, "only cloak with full meter"))
  2048. {
  2049. CloakOnlyWhenFullMeter[weapon] = true;
  2050. action = Plugin_Handled;
  2051. } else if(StrEqual(attrib, "on switch give and take mini crits"))
  2052. {
  2053. DrawMiniCrits[weapon] = true;
  2054.  
  2055. DrawMiniCrits_Value[weapon] = StringToFloat(value);
  2056.  
  2057. action = Plugin_Handled;
  2058. } else if(StrEqual(attrib, "deal more damage in air"))
  2059. {
  2060. new String:values[2][10];
  2061. ExplodeString(value, " ", values, sizeof(values), sizeof(values[]));
  2062.  
  2063. DamageOnGround[weapon] = true;
  2064.  
  2065. DamageOnGround_Value1[weapon] = StringToFloat(values[0]);
  2066. DamageOnGround_Value2[weapon] = StringToFloat(values[1]);
  2067.  
  2068. action = Plugin_Handled;
  2069. } else if(StrEqual(attrib, "take less damage in air"))
  2070. {
  2071. new String:values[2][10];
  2072. ExplodeString(value, " ", values, sizeof(values), sizeof(values[]));
  2073.  
  2074. ReducedDamageInAir[weapon] = true;
  2075.  
  2076. ReducedDamageInAir_Value1[weapon] = StringToFloat(values[0]);
  2077. ReducedDamageInAir_Value2[weapon] = StringToFloat(values[1]);
  2078.  
  2079. action = Plugin_Handled;
  2080. } else if(StrEqual(attrib, "infect victim on backstab"))
  2081. {
  2082. new String:values[2][10];
  2083. ExplodeString(value, " ", values, sizeof(values), sizeof(values[]));
  2084.  
  2085. InfectVictimOnBackstab[weapon] = true;
  2086.  
  2087. InfectVictimOnBackstab_TimeToStun[weapon] = StringToFloat(values[0]);
  2088. InfectVictimOnBackstab_TimeToDeath[weapon] = StringToFloat(values[1]);
  2089.  
  2090. action = Plugin_Handled;
  2091. } else if(StrEqual(attrib, "kill victim on wall hit"))
  2092. {
  2093. WallKill[weapon] = true;
  2094.  
  2095. WallKill_Damage[weapon] = StringToInt(value);
  2096.  
  2097. action = Plugin_Handled;
  2098. }
  2099.  
  2100. if(!HasAttribute[weapon]) HasAttribute[weapon] = bool:action;
  2101.  
  2102. return action;
  2103. }
  2104.  
  2105. public Action:Attribute_1012_OnTakeDamage(victim, &attacker, slot, &Float:fDamage, &iDamageType, Float:fForce[3], Float:fForcePos[3], bool:bBuilding)
  2106. {
  2107. if (bBuilding) return Plugin_Continue;
  2108. if (!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  2109. if (attacker == victim) return Plugin_Continue;
  2110.  
  2111. new weapon = GetPlayerWeaponSlot(attacker, slot);
  2112. if(weapon == -1 || !HasAttribute[weapon] || !WallKill[weapon]) return Plugin_Continue;
  2113.  
  2114. if (fDamage <= 0.0) return Plugin_Continue;
  2115.  
  2116. decl Float:fVelocity[3];
  2117. decl Float:fAngle[3];
  2118. GetClientEyeAngles(attacker, fAngle);
  2119. AnglesToVelocity(fAngle, fVelocity, 230.0);
  2120. fVelocity[2] = 270.0;
  2121.  
  2122. TeleportEntity(victim, NULL_VECTOR, NULL_VECTOR, fVelocity);
  2123.  
  2124. g_bAttWallSmash[victim] = true;
  2125. g_iAttWallSmashAttacker[victim] = attacker;
  2126.  
  2127. return Plugin_Continue;
  2128. }
  2129.  
  2130. public Action:Attribute_1062_OnTakeDamage(victim, &attacker, slot, &Float:damage, &damagetype, Float:damageForce[3], Float:damagePosition[3], bool:bBuilding, damageCustom)
  2131. {
  2132. if(!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  2133. if(attacker == victim) return Plugin_Continue;
  2134. if(damage <= 0.0) return Plugin_Continue;
  2135. if(damageCustom != TF_CUSTOM_BACKSTAB) return Plugin_Continue;
  2136.  
  2137. new bool:backstabShield = false;
  2138.  
  2139. for(int i = 0; i < SLOTS_MAX; i++)
  2140. {
  2141. new weaponVictim = GetPlayerWeaponSlot(victim, i);
  2142.  
  2143. if(weaponVictim != -1 && TF2Attrib_GetByName(weaponVictim, "backstab shield") != Address_Null)
  2144. {
  2145. backstabShield = true;
  2146. break;
  2147. }
  2148. }
  2149.  
  2150. if(!backstabShield)
  2151. {
  2152. new weapon = GetPlayerWeaponSlot(attacker, slot);
  2153. if(weapon == -1) return Plugin_Continue;
  2154. if(!HasAttribute[weapon]) return Plugin_Continue;
  2155. if(!FastcloakOnBackstab[weapon]) return Plugin_Continue;
  2156.  
  2157. new weapon2 = GetPlayerWeaponSlot(attacker, 4); // Get watch
  2158.  
  2159. if(weapon2 != -1 && HasAttribute[weapon2] && CloakIsHook[weapon2])
  2160. {
  2161. new Float:vAngles[3];
  2162. vAngles[0] = -90.0;
  2163. if(CloakIsHookInit(attacker, vAngles)) return Plugin_Continue;
  2164. vAngles[0] = -45.0;
  2165. for(new i = 0; i <= 7; i++)
  2166. {
  2167. vAngles[1] = float(i) * 45.0;
  2168. if(CloakIsHookInit(attacker, vAngles)) return Plugin_Continue;
  2169. }
  2170. return Plugin_Continue;
  2171. }
  2172.  
  2173. FastCloak(attacker);
  2174. }
  2175.  
  2176. return Plugin_Continue;
  2177. }
  2178.  
  2179. public Action:Attribute_1193_OnTakeDamage(victim, &attacker, slot, &Float:damage, &damagetype, Float:damageForce[3], Float:damagePosition[3], bool:bBuilding)
  2180. {
  2181. if(bBuilding) return Plugin_Continue;
  2182. if(!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  2183. if(attacker == victim) return Plugin_Continue;
  2184. if(damage <= 0.0) return Plugin_Continue;
  2185.  
  2186. new weapon = GetPlayerWeaponSlot(attacker, slot);
  2187. if(weapon == -1) return Plugin_Continue;
  2188.  
  2189. if(GetHasAttributeInAnySlot(attacker, _, ResetAfterburn))
  2190. {
  2191. if(GetWeaponContainingAttribute(attacker, ResetAfterburn) == weapon)
  2192. {
  2193. if(g_iAchBoilerBurner1193[victim] == attacker && TF2_IsPlayerInCondition(victim, TFCond_OnFire) ) g_iAchBoilerTimer1193[victim] = 0;
  2194.  
  2195. if(TF2_IsPlayerInCondition(victim, TFCond_OnFire))
  2196. {
  2197. if(g_iAchBoilerBurner1193[victim] != attacker)
  2198. {
  2199. g_iAchBoilerBurner1193[victim] = 0;
  2200. g_iAchBoilerTimer1193[victim] = 0;
  2201. }
  2202. }
  2203.  
  2204. return Plugin_Continue;
  2205. }
  2206. }
  2207.  
  2208. if(TF2_IsPlayerInCondition(victim, TFCond_OnFire))
  2209. {
  2210. if(g_iAchBoilerBurner1193[victim] != attacker)
  2211. {
  2212. g_iAchBoilerBurner1193[victim] = 0;
  2213. g_iAchBoilerTimer1193[victim] = 0;
  2214. } else
  2215. {
  2216. g_iAchBoilerTimer1193[victim] += 1;
  2217. return Plugin_Continue;
  2218. }
  2219.  
  2220. TF2_IgnitePlayer(victim, attacker);
  2221. EmitSoundToAll(SOUND_FLAME_ENGULF, victim, _, _, SND_CHANGEVOL, SNDVOL_NORMAL * 1.5);
  2222.  
  2223. g_iAchBoilerBurner1193[victim] = attacker;
  2224.  
  2225. return Plugin_Continue;
  2226. }
  2227.  
  2228. return Plugin_Continue;
  2229. }
  2230.  
  2231. public TF2_OnConditionRemoved(client, TFCond:condition)
  2232. {
  2233. if(Client_IsValid(client))
  2234. {
  2235. new weapon = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon");
  2236. if(weapon != -1)
  2237. {
  2238. if(GetHasAttributeInAnySlot(client, _, JumpCloak) && condition == TFCond_Cloaked)
  2239. {
  2240. TF2Attrib_RemoveByName(weapon, "increased jump height");
  2241. }
  2242. }
  2243. }
  2244.  
  2245. Attribute_1193_OnConditionRemoved(client, condition);
  2246. }
  2247.  
  2248. public Attribute_1193_OnConditionRemoved(client, TFCond:condition)
  2249. {
  2250. if(!Client_IsValid(client)) return;
  2251. if(condition != TFCond_OnFire) return;
  2252. if(g_iAchBoilerTimer1193[client] == 0) return;
  2253.  
  2254. g_iAchBoilerBurner1193[client] = 0;
  2255. g_iAchBoilerTimer1193[client] = 0;
  2256. }
  2257.  
  2258. public Action:Attribute_1296_OnTakeDamage(victim, &attacker, slot, &Float:damage, &damagetype, Float:damageForce[3], Float:damagePosition[3], bool:bBuilding)
  2259. {
  2260. if(!Client_IsValid(attacker)) return Plugin_Continue;
  2261. if(GetClientTeam(attacker) == GetClientTeam(victim)) return Plugin_Continue;
  2262. if(attacker == victim) return Plugin_Continue;
  2263. if(damage <= 0.0) return Plugin_Continue;
  2264. if(slot == 1) return Plugin_Continue;
  2265.  
  2266. new weapon = GetPlayerWeaponSlot(attacker, 1);
  2267. if(weapon == -1) return Plugin_Continue;
  2268. if(!HasAttribute[weapon]) return Plugin_Continue;
  2269. if(!DamageReloads[weapon]) return Plugin_Continue;
  2270.  
  2271. g_fTotalDamage1296[attacker] += damage;
  2272.  
  2273. if(g_fTotalDamage1296[attacker] >= 50.0)
  2274. {
  2275. EmitSoundToClient(attacker, SOUND_1217_RELOAD);
  2276. }
  2277.  
  2278. while(g_fTotalDamage1296[attacker] >= 50.0)
  2279. {
  2280. g_fTotalDamage1296[attacker] -= 50.0;
  2281. new clip = GetEntProp(weapon, Prop_Send, "m_iClip1");
  2282. if(clip >= DamageReloads_Max[weapon]) return Plugin_Continue;
  2283. SetClip(weapon, clip+1);
  2284. }
  2285.  
  2286. return Plugin_Continue;
  2287. }
  2288.  
  2289. bool:GetHasAttributeInAnySlot(client, slot = -1, const attribute[] = HasAttribute)
  2290. {
  2291. if(!Client_IsValid(client)) return false;
  2292.  
  2293. for(new i = 0; i < SLOTS_MAX; i++)
  2294. {
  2295. new weapon = GetPlayerWeaponSlot(client, i);
  2296. if(weapon != -1)
  2297. {
  2298. if(HasAttribute[weapon])
  2299. {
  2300. if(attribute[weapon])
  2301. {
  2302. if(slot == -1 || slot == i) return true;
  2303. }
  2304. }
  2305. }
  2306. }
  2307.  
  2308. return false;
  2309. }
  2310.  
  2311. Float:GetAttributeValueInAnySlot(client, slot = -1, const bool:baseAttribute[], const Float:attribute[], Float:defaultValue)
  2312. {
  2313. if(!Client_IsValid(client)) return defaultValue;
  2314.  
  2315. for(new i = 0; i < SLOTS_MAX; i++)
  2316. {
  2317. new weapon = GetPlayerWeaponSlot(client, i);
  2318. if(weapon != -1)
  2319. {
  2320. if(HasAttribute[weapon])
  2321. {
  2322. if(baseAttribute[weapon])
  2323. {
  2324. if(slot == -1 || slot == i)
  2325. {
  2326. return attribute[weapon];
  2327. }
  2328. }
  2329. }
  2330. }
  2331. }
  2332.  
  2333. return defaultValue;
  2334. }
  2335.  
  2336. GetWeaponContainingAttribute(client, const attribute[] = HasAttribute)
  2337. {
  2338. if(!Client_IsValid(client)) return false;
  2339.  
  2340. for(new i = 0; i < SLOTS_MAX; i++)
  2341. {
  2342. new weapon = GetPlayerWeaponSlot(client, i);
  2343. if(weapon != -1)
  2344. {
  2345. if(HasAttribute[weapon])
  2346. {
  2347. if(attribute[weapon])
  2348. {
  2349. return weapon;
  2350. }
  2351. }
  2352. }
  2353. }
  2354.  
  2355. return -1;
  2356. }
  2357.  
  2358. public Action:Attribute_1321_OnTakeDamage(victim, &attacker, slot, &Float:fDamage, &damageType, Float:fForce[3], Float:fForcePos[3], bool:bBuilding)
  2359. {
  2360. if(!Client_IsValid(victim)) return Plugin_Continue;
  2361. if(!Client_IsValid(attacker)) return Plugin_Continue;
  2362.  
  2363. if(GetHasAttributeInAnySlot(victim, _, ShareDamage)) return Plugin_Continue;
  2364.  
  2365. if(attacker == victim) return Plugin_Continue;
  2366. if(bBuilding) return Plugin_Continue;
  2367. if(IsAfterDamage(damageType)) return Plugin_Continue;
  2368. new dmgType = damageType;
  2369.  
  2370. if(dmgType == DMG_FALL || dmgType == DMG_CRUSH) return Plugin_Continue;
  2371.  
  2372. if(TF2_GetPlayerClass(attacker) == TFClass_Spy && (damageType & TF_DMG_MELEE_CRIT == TF_DMG_MELEE_CRIT)) return Plugin_Continue;
  2373.  
  2374. new tank[MAXPLAYERS+1] = 0;
  2375. new totalTanks = 0;
  2376.  
  2377. decl Float:vClientPos[3];
  2378. Entity_GetAbsOrigin(victim, vClientPos);
  2379. vClientPos[2] += 80.0;
  2380. decl Float:vTeammatePos[3];
  2381. decl health;
  2382.  
  2383. new team = GetClientTeam(victim);
  2384.  
  2385. for(new teammate = 0; teammate <= MaxClients; teammate++)
  2386. {
  2387. if(Client_IsValid(teammate) && IsClientInGame(teammate) && IsPlayerAlive(teammate) && team == GetClientTeam(teammate))
  2388. {
  2389. Entity_GetAbsOrigin(teammate, vTeammatePos);
  2390. vTeammatePos[2] += 80.0;
  2391. TR_TraceRayFilter(vClientPos, vTeammatePos, MASK_PLAYERSOLID, RayType_EndPoint, TraceRayDontHitPlayers);
  2392. if(!TR_DidHit(INVALID_HANDLE))
  2393. {
  2394. //new weapon = GetWeaponContainingAttribute(teammate, ShareDamage);
  2395. new slotTank = GetClientSlot(teammate);
  2396. new weapon = GetPlayerWeaponSlot(teammate, slotTank);
  2397.  
  2398. health = GetClientHealth(teammate);
  2399. if(weapon > 0 && HasAttribute[weapon] && ShareDamage[weapon] && Entity_GetDistanceOrigin(teammate, vClientPos) <= ShareDamage_Range[weapon] && health > 1)
  2400. {
  2401. tank[totalTanks] = teammate;
  2402. totalTanks++;
  2403. }
  2404. }
  2405. }
  2406. }
  2407.  
  2408. if(totalTanks == 0) return Plugin_Continue;
  2409.  
  2410. new Float:fRatio = ShareDamage_Ratio[GetWeaponContainingAttribute(tank[0], ShareDamage)];
  2411. new Float:fTankDamage = fDamage*fRatio;
  2412.  
  2413. if(fTankDamage < 1.0) return Plugin_Continue;
  2414.  
  2415. if(IsDamageTypeCrit(damageType)) fTankDamage /= 3.0;
  2416. fDamage *= 1.0-fRatio;
  2417. if(totalTanks > 1) fTankDamage /= totalTanks;
  2418.  
  2419. decl Float:vVictimPos[3];
  2420. Entity_GetAbsOrigin(victim, vVictimPos);
  2421. vVictimPos[2] += 80.0;
  2422. decl Float:vTankPos[3];
  2423. decl Float:vDiff[3];
  2424. decl Float:vParticlePos[3];
  2425.  
  2426. new Float:fAngle[3];
  2427. fAngle[0] = -90.0;
  2428.  
  2429. for(new currentTank = 0; currentTank < totalTanks; currentTank++)
  2430. {
  2431. health = GetClientHealth(tank[currentTank]);
  2432. if(health > fTankDamage)
  2433. {
  2434. Entity_Hurt(tank[currentTank], RoundFloat(fTankDamage), attacker, TF_DMG_PROPAGATE);
  2435. } else
  2436. {
  2437. SetEntityHealth(tank[currentTank], 1);
  2438. }
  2439. new random = GetRandomInt(0, sizeof(g_strSound1315Ping)-1);
  2440. EmitSoundToAll(g_strSound1315Ping[random], tank[currentTank]);
  2441.  
  2442. Entity_GetAbsOrigin(tank[currentTank], vTankPos);
  2443. vTankPos[2] += 80.0;
  2444. SubtractVectors(vTankPos, vVictimPos, vDiff);
  2445. ScaleVector(vDiff, 0.2);
  2446.  
  2447. vParticlePos = vVictimPos;
  2448. AddVectors(vParticlePos, vDiff, vParticlePos);
  2449. ShowParticle(PARTICLE_WHITE_PARTICLE, 0.7, vParticlePos, fAngle);
  2450. AddVectors(vParticlePos, vDiff, vParticlePos);
  2451. ShowParticle(PARTICLE_WHITE_PARTICLE, 0.8, vParticlePos, fAngle);
  2452. AddVectors(vParticlePos, vDiff, vParticlePos);
  2453. ShowParticle(PARTICLE_WHITE_PARTICLE, 0.9, vParticlePos, fAngle);
  2454. AddVectors(vParticlePos, vDiff, vParticlePos);
  2455. ShowParticle(PARTICLE_WHITE_PARTICLE, 1.0, vParticlePos, fAngle);
  2456. }
  2457.  
  2458. return Plugin_Changed;
  2459. }
  2460.  
  2461. public Action:Attribute_1066_OnTakeDamage(victim, &attacker, slot, &Float:damage, &damagetype, Float:damageForce[3], Float:damagePosition[3], bool:bBuilding)
  2462. {
  2463. if(bBuilding) return Plugin_Continue;
  2464.  
  2465. new slotVictim = GetClientSlot(victim);
  2466. new weapon = GetPlayerWeaponSlot(victim, slotVictim);
  2467.  
  2468. if(!GetHasAttributeInAnySlot(victim, _, ReducedFallDamage)) return Plugin_Continue;
  2469.  
  2470. new Float:fValue = ReducedFallDamage_Value[weapon];
  2471.  
  2472. if(fValue < 0.0){
  2473. fValue *= -1.0; //making this attribute negative means it will check only if you have it, not if it's on the active weapon
  2474. } else
  2475. {
  2476. if(HasAttribute[weapon] && ReducedFallDamage[weapon]) return Plugin_Continue;
  2477. }
  2478.  
  2479. new dmgType = damagetype;
  2480.  
  2481. if(dmgType != DMG_FALL && dmgType != DMG_CRUSH) return Plugin_Continue;
  2482. if(attacker != victim && Client_IsValid(attacker)) return Plugin_Continue;
  2483.  
  2484. if(damage <= 0.0) return Plugin_Continue;
  2485.  
  2486. damage *= fValue;
  2487.  
  2488. return Plugin_Changed;
  2489. }
  2490.  
  2491. public Action:KeepDisguise_OnTakeDamage(victim, &attacker, &Float:damage, &damageType, slot, damageCustom)
  2492. {
  2493. if(!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  2494.  
  2495. new weapon = GetPlayerWeaponSlot(attacker, slot);
  2496. if(weapon == -1) return Plugin_Continue;
  2497.  
  2498. new bool:backstabShield = false;
  2499.  
  2500. for(int i = 0; i < SLOTS_MAX; i++)
  2501. {
  2502. new weaponVictim = GetPlayerWeaponSlot(victim, i);
  2503.  
  2504. if(weaponVictim != -1 && TF2Attrib_GetByName(weaponVictim, "backstab shield") != Address_Null)
  2505. {
  2506. backstabShield = true;
  2507. break;
  2508. }
  2509. }
  2510.  
  2511. if(damageCustom == TF_CUSTOM_BACKSTAB && !backstabShield)
  2512. {
  2513. if(Client_IsValid(oldDisguise[attacker][2]) && g_bWasDisguised[attacker])
  2514. {
  2515. new Handle:dataPack;
  2516. CreateDataTimer(0.01, KeepDisguise_Timer_Disguise, dataPack);
  2517. WritePackCell(dataPack, attacker);
  2518. }
  2519. }
  2520.  
  2521. return Plugin_Continue;
  2522. }
  2523.  
  2524. public Action:KeepDisguise_Timer_Disguise(Handle:timer, Handle:dataPack)
  2525. {
  2526. new attacker;
  2527.  
  2528. ResetPack(dataPack);
  2529. attacker = ReadPackCell(dataPack);
  2530.  
  2531. TF2_DisguisePlayer(attacker, TFTeam:oldDisguise[attacker][1], TFClassType:oldDisguise[attacker][0], oldDisguise[attacker][2]);
  2532.  
  2533. SetEntProp(attacker, Prop_Send, "m_nMaskClass", oldDisguise[attacker][0]);
  2534. SetEntProp(attacker, Prop_Send, "m_nDisguiseClass", oldDisguise[attacker][0]);
  2535. SetEntProp(attacker, Prop_Send, "m_nDesiredDisguiseClass", oldDisguise[attacker][0]);
  2536. SetEntProp(attacker, Prop_Send, "m_nDisguiseTeam", oldDisguise[attacker][1]);
  2537. SetEntProp(attacker, Prop_Send, "m_iDisguiseTargetIndex", oldDisguise[attacker][2]);
  2538.  
  2539. SetEntProp(attacker, Prop_Send, "m_iDisguiseHealth", IsPlayerAlive(oldDisguise[attacker][2]) ? GetClientHealth(oldDisguise[attacker][2]) : GetClassBaseHP(oldDisguise[attacker][2]));
  2540.  
  2541. TF2_AddCondition(attacker, TFCond_Disguised);
  2542. }
  2543.  
  2544. stock GetClassBaseHP(client)
  2545. {
  2546. switch(TF2_GetPlayerClass(client))
  2547. {
  2548. case TFClass_Scout: return 125;
  2549. case TFClass_Soldier: return 200;
  2550. case TFClass_Pyro: return 175;
  2551. case TFClass_DemoMan: return 175;
  2552. case TFClass_Heavy: return 300;
  2553. case TFClass_Engineer: return 125;
  2554. case TFClass_Medic: return 150;
  2555. case TFClass_Sniper: return 125;
  2556. case TFClass_Spy: return 125;
  2557. }
  2558. return 125;
  2559. }
  2560.  
  2561. public Action:InfectVictim_OnTakeDamage(victim, &attacker, &Float:damage, &damageType, slot, damageCustom)
  2562. {
  2563. if(!Client_IsValid(attacker) || !Client_IsValid(victim)) return Plugin_Continue;
  2564.  
  2565. new weapon = GetPlayerWeaponSlot(attacker, slot);
  2566. if(weapon == -1) return Plugin_Continue;
  2567. if(!HasAttribute[weapon] || !InfectVictimOnBackstab[weapon]) return Plugin_Continue;
  2568.  
  2569. new bool:backstabShield = false;
  2570.  
  2571. for(int i = 0; i < SLOTS_MAX; i++)
  2572. {
  2573. new weaponVictim = GetPlayerWeaponSlot(victim, i);
  2574.  
  2575. if(weaponVictim != -1 && TF2Attrib_GetByName(weaponVictim, "backstab shield") != Address_Null)
  2576. {
  2577. backstabShield = true;
  2578. break;
  2579. }
  2580. }
  2581.  
  2582. if(damageCustom == TF_CUSTOM_BACKSTAB && !backstabShield)
  2583. {
  2584. isInfected[victim] = true;
  2585.  
  2586. new Handle:dataPack;
  2587. CreateDataTimer(InfectVictimOnBackstab_TimeToStun[weapon], InfectVictim_Timer_Stun, dataPack);
  2588. WritePackCell(dataPack, victim);
  2589. WritePackCell(dataPack, weapon);
  2590. WritePackCell(dataPack, attacker);
  2591.  
  2592. damage = 10.0;
  2593.  
  2594. return Plugin_Changed;
  2595. }
  2596.  
  2597. return Plugin_Continue;
  2598. }
  2599.  
  2600. public Action:InfectVictim_Timer_Stun(Handle:timer, Handle:dataPack)
  2601. {
  2602. new victim, weapon, attacker;
  2603.  
  2604. ResetPack(dataPack);
  2605. victim = ReadPackCell(dataPack);
  2606. weapon = ReadPackCell(dataPack);
  2607. attacker = ReadPackCell(dataPack);
  2608.  
  2609. if(Client_IsValid(victim) && isInfected[victim])
  2610. {
  2611. TF2_StunPlayer(victim, InfectVictimOnBackstab_TimeToDeath[weapon] + 2.5, 0.5, TF_STUNFLAGS_LOSERSTATE);
  2612.  
  2613. CreateDataTimer(InfectVictimOnBackstab_TimeToDeath[weapon], InfectVictim_Timer_Death, dataPack);
  2614. WritePackCell(dataPack, victim);
  2615. WritePackCell(dataPack, weapon);
  2616. WritePackCell(dataPack, attacker);
  2617. }
  2618. }
  2619.  
  2620. public Action:InfectVictim_Timer_Death(Handle:timer, Handle:dataPack)
  2621. {
  2622. new victim, attacker;
  2623.  
  2624. ResetPack(dataPack);
  2625. victim = ReadPackCell(dataPack);
  2626. ReadPackCell(dataPack);
  2627. attacker = ReadPackCell(dataPack);
  2628.  
  2629. if(Client_IsValid(victim) && isInfected[victim])
  2630. {
  2631. // Bye bye, you are ded, not big surprise.
  2632. Entity_Hurt(victim, 1000000000, attacker, TF_DMG_MELEE_CRIT, "tf_weapon_knife");
  2633. }
  2634. }
  2635.  
  2636. public Action:Attributes_OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damageType, &weapon, Float:damageForce[3], Float:damagePosition[3], damageCustom)
  2637. {
  2638. if(victim <= 0) return Plugin_Continue;
  2639. if(attacker <= 0) return Plugin_Continue;
  2640. if(Client_IsValid(attacker) && Client_IsValid(victim) && attacker != victim && GetClientTeam(attacker) == GetClientTeam(victim)) return Plugin_Continue;
  2641.  
  2642. new bool:bBuilding = IsEntityBuilding(victim);
  2643. if(!bBuilding && damage <= 0.0) return Plugin_Continue;
  2644.  
  2645. // Set up return
  2646. new Action:aReturn = Plugin_Continue;
  2647.  
  2648. // Get the slot
  2649. new slot = GetClientSlot(attacker);
  2650. if(weapon > 0 && IsValidEdict(weapon))
  2651. {
  2652. slot = GetWeaponSlot(attacker, weapon);
  2653. } else
  2654. {
  2655. if(inflictor > 0 && !Client_IsValid(inflictor) && IsValidEdict(inflictor))
  2656. {
  2657. slot = GetWeaponSlot(attacker, inflictor);
  2658. }
  2659. }
  2660.  
  2661. new oldType = damageType;
  2662.  
  2663. if(IsDamageTypeCrit(oldType) && !bBuilding) damage *= 3.0;
  2664.  
  2665. // Attributes go here
  2666. aReturn = ActionApply(aReturn, Attribute_1066_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding));
  2667. aReturn = ActionApply(aReturn, Attribute_1012_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding));
  2668. aReturn = ActionApply(aReturn, Attribute_1062_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding, damageCustom));
  2669. aReturn = ActionApply(aReturn, Attribute_1193_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding));
  2670. aReturn = ActionApply(aReturn, Attribute_1296_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding));
  2671. aReturn = ActionApply(aReturn, Attribute_1321_OnTakeDamage(victim, attacker, slot, damage, damageType, damageForce, damagePosition, bBuilding));
  2672. aReturn = ActionApply(aReturn, EternSleep_OnTakeDamage(victim, attacker, damageType, slot));
  2673. aReturn = ActionApply(aReturn, InfectVictim_OnTakeDamage(victim, attacker, damage, damageType, slot, damageCustom));
  2674. aReturn = ActionApply(aReturn, KeepDisguise_OnTakeDamage(victim, attacker, damage, damageType, slot, damageCustom));
  2675.  
  2676. if(IsDamageTypeCrit(oldType)) damage /= 3.0;
  2677.  
  2678. return aReturn;
  2679. }
  2680.  
  2681. public OnEntityDestroyed(Ent)
  2682. {
  2683. if(Ent <= 0 || Ent > 2048) return;
  2684. HasAttribute[Ent] = false;
  2685.  
  2686. FastcloakOnBackstab[Ent] = false;
  2687.  
  2688. ProjectilesBounce[Ent] = false;
  2689. ProjectilesBounce_Count[Ent] = 0.0;
  2690.  
  2691. Earthquake[Ent] = false;
  2692.  
  2693. DamageReloads[Ent] = false;
  2694. DamageReloads_Max[Ent] = 0.0;
  2695.  
  2696. AltFireIsOil[Ent] = false;
  2697.  
  2698. AttackWhileCloaked[Ent] = false;
  2699.  
  2700. ResetAfterburn[Ent] = false;
  2701.  
  2702. ControllableProjectiles[Ent] = false;
  2703. ControllableProjectiles_Control[Ent] = 0.0;
  2704.  
  2705. ItemIsHeavy[Ent] = false;
  2706. ItemIsHeavy_Force[Ent] = 0.0;
  2707.  
  2708. NoReloading[Ent] = false;
  2709.  
  2710. CloakIsHook[Ent] = false;
  2711.  
  2712. ReducedFallDamage[Ent] = false;
  2713. ReducedFallDamage_Value[Ent] = 0.0;
  2714.  
  2715. ShareDamage[Ent] = false;
  2716. ShareDamage_Range[Ent] = 0.0;
  2717. ShareDamage_Ratio[Ent] = 0.0;
  2718.  
  2719. ReflectCrits[Ent] = false;
  2720.  
  2721. ChargeLand[Ent] = false;
  2722. ChargeLand_Value[Ent] = 0.0;
  2723.  
  2724. CritCharging[Ent] = false;
  2725.  
  2726. CrouchCloak[Ent] = false;
  2727. CrouchCloak_Value[Ent] = 255.0;
  2728.  
  2729. JumpCloak[Ent] = false;
  2730. JumpCloak_Value[Ent] = 0.0;
  2731.  
  2732. RemoveDebuffCloak[Ent] = false;
  2733.  
  2734. CloakOnlyWhenFullMeter[Ent] = false;
  2735.  
  2736. DrawMiniCrits[Ent] = false;
  2737. DrawMiniCrits_Value[Ent] = 0.0;
  2738.  
  2739. DamageOnGround[Ent] = false;
  2740. DamageOnGround_Value1[Ent] = 0.0;
  2741. DamageOnGround_Value2[Ent] = 0.0;
  2742.  
  2743. ReducedDamageInAir[Ent] = false;
  2744. ReducedDamageInAir_Value1[Ent] = 0.0;
  2745. ReducedDamageInAir_Value2[Ent] = 0.0;
  2746.  
  2747. InfectVictimOnBackstab[Ent] = false;
  2748. InfectVictimOnBackstab_TimeToStun[Ent] = 0.0;
  2749. InfectVictimOnBackstab_TimeToDeath[Ent] = 0.0;
  2750.  
  2751. WallKill[Ent] = false;
  2752. WallKill_Damage[Ent] = 0;
  2753. }
  2754.  
  2755. // Sets ammo in clip
  2756. stock SetClip(weapon, clip)
  2757. {
  2758. SetEntProp(weapon, Prop_Data, "m_iClip1", clip);
  2759. ChangeEdictState(weapon, FindSendPropInfo("CTFWeaponBase", "m_iClip1"));
  2760. }
  2761.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement