Member
|
01-10-2017
, 15:06
Re: Death's Bosses and Abilities [Update: Witch Doctor]
|
#113
|
Quote:
Originally Posted by uNg0veRNab1e
in source change
PHP Code:
ShootProjectile(iClient, "tf_projectile_spelllightningorb");
to
PHP Code:
ShootProjectile(iClient, "tf_projectile_lightningorb");
|
Well, i try to do this, but when i'll compile appears this error
plugin.sp(972) : error 017: undefined symbol "DD_PerformTeleport"
plugin.sp(1184) : error 017: undefined symbol "DD_PerformTeleport"
Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdkhooks>
#include <tf2_stocks>
#include <tf2items>
#include <freak_fortress_2>
#include <freak_fortress_2_subplugin>
#undef REQUIRE_PLUGIN
#tryinclude <ff2_dynamic_defaults>
#define REQUIRE_PLUGIN
public Plugin myinfo = {
name = "Freak Fortress 2: The Witch Doctor",
author = "Deathreus",
version = "1.0"
};
#define IsEmptyString(%1) (%1[0]==0)
#define FAR_FUTURE 100000000.0
#define HUD_INTERVAL 0.2
#define HUD_LINGER 0.01
#define HUD_ALPHA 192
#define HUD_R_OK 255
#define HUD_G_OK 255
#define HUD_B_OK 255
#define HUD_R_ERROR 225
#define HUD_G_ERROR 64
#define HUD_B_ERROR 64
int BossTeam = view_as<int>(TFTeam_Blue);
int MJT_ButtonType; // Shared between Magic Jump and Magic Teleport as 4th argument, or Jump Manager as 2nd
/* Rage_SkeleSummon */
int SkeleNumberOfSpawns[MAXPLAYERS+1]; // 1
/* Charge_MagicJump */ // Intended for gaining height
float MJ_ChargeTime[MAXPLAYERS+1]; // 1
float MJ_Cooldown[MAXPLAYERS+1]; // 2
float MJ_OnCooldownUntil[MAXPLAYERS+1]; // Internal, set by arg3
float MJ_CrouchOrAltFireDownSince[MAXPLAYERS+1]; // Internal
bool MJ_EmergencyReady[MAXPLAYERS+1]; // Internal
/* Charge_MegicTele */ // Intended for catching fast players
float MT_ChargeTime[MAXPLAYERS+1]; // 1
float MT_Cooldown[MAXPLAYERS+1]; // 2
float MT_OnCooldownUntil[MAXPLAYERS+1]; // Internal, set by arg3
float MT_CrouchOrAltFireDownSince[MAXPLAYERS+1]; // Internal
bool MT_EmergencyReady[MAXPLAYERS+1]; // Internal
/* Special_JumpManager */
int JM_ButtonType; // 1
bool JM_AbilitySwitched[MAXPLAYERS+1]; // Internal
float WitchDoctorUpdateHUD[MAXPLAYERS+1]; // Internal
Handle witchdoctorHUD;
/* Special_SpellAttack */
float SS_CoolDown[MAXPLAYERS+1]; // 1
/* Ability_Management_System */
bool Orb_TriggerAMS[MAXPLAYERS+1];
bool Meteor_TriggerAMS[MAXPLAYERS+1];
bool Monoculus_TriggerAMS[MAXPLAYERS+1];
bool Invis_TriggerAMS[MAXPLAYERS+1];
bool Minify_TriggerAMS[MAXPLAYERS+1];
bool Bats_TriggerAMS[MAXPLAYERS+1];
bool Horde_TriggerAMS[MAXPLAYERS+1];
bool Meras_TriggerAMS[MAXPLAYERS+1];
bool Horse_TriggerAMS[MAXPLAYERS+1];
public void OnPluginStart2()
{
HookEvent("arena_round_start", Event_RoundStart, EventHookMode_Post);
HookEvent("arena_win_panel", Event_RoundEnd, EventHookMode_Post);
witchdoctorHUD = CreateHudSynchronizer();
if(FF2_GetRoundState()==1) // Late-load
{
HookAbilities();
}
}
public void Event_RoundStart(Event hEvent, const char[] strName, bool bDontBroadcast)
{
BossTeam = FF2_GetBossTeam();
int iBoss;
for(int iIndex = 0; (iBoss=GetClientOfUserId(FF2_GetBossUserId(iIndex)))>0; iIndex++)
{
if(FF2_HasAbility(iIndex, this_plugin_name, "special_jumpmanager"))
{
JM_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "special_jumpmanager", 1); // Button for activation, 1 = reload, 2 = special attack, 3 = secondary attack
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "special_jumpmanager", 2); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
MJ_ChargeTime[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 3); // Time it takes to charge
MJ_Cooldown[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 4); // Time it takes to refresh
MJ_OnCooldownUntil[iBoss] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 5); // Time before first use
MT_ChargeTime[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 6); // Time it takes to charge
MT_Cooldown[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 7); // Time it takes to refresh
MT_OnCooldownUntil[iBoss] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 8); // Time before first use
MJ_CrouchOrAltFireDownSince[iBoss] = FAR_FUTURE;
MT_CrouchOrAltFireDownSince[iBoss] = FAR_FUTURE;
SpawnWeapon(iBoss, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "charge_magicjump"))
{
MJ_ChargeTime[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 1); // Time it takes to charge
MJ_Cooldown[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 2); // Time it takes to refresh
MJ_OnCooldownUntil[iBoss] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 3); // Time before first use
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "charge_magicjump", 4); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
MJ_CrouchOrAltFireDownSince[iBoss] = FAR_FUTURE;
SpawnWeapon(iBoss, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "charge_magictele"))
{
MT_ChargeTime[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 1); // Time it takes to charge
MT_Cooldown[iBoss] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 2); // Time it takes to refresh
MT_OnCooldownUntil[iBoss] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 3); // Time before first use
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "charge_magictele", 4); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
MT_CrouchOrAltFireDownSince[iBoss] = FAR_FUTURE;
SpawnWeapon(iBoss, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "special_spellattack"))
{
SS_CoolDown[iBoss] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_spellattack", 1);
for(int i=1; i<=MaxClients; i++) if(IsValidClient(i))
SDKHook(i, SDKHook_OnTakeDamage, OnTakeDamage);
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_bats"))
{
Bats_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_bats", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Bats_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_bats", "BATS"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_orb"))
{
Orb_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_orb", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Orb_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_orb", "ORB"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_meteor"))
{
Meteor_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_meteor", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Meteor_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_meteor", "MET"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_invis"))
{
Invis_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_invis", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Invis_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_invis", "INV"); // Important function to tell AMS that this subplugin supports it
}
SpawnWeapon(iBoss, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_minify"))
{
Minify_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_minify", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Minify_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_minify", "MINI"); // Important function to tell AMS that this subplugin supports it
}
SpawnWeapon(iBoss, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_mono"))
{
Monoculus_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_mono", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Monoculus_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_mono", "MONO"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_horde"))
{
Horde_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_horde", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Horde_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_horde", "HORD"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_meras"))
{
Meras_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_meras", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Meras_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_meras", "MERA"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_horse"))
{
Horse_TriggerAMS[iBoss] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_horse", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Horse_TriggerAMS[iBoss])
{
AMS_InitSubability(iIndex, iBoss, this_plugin_name, "rage_horse", "HORS"); // Important function to tell AMS that this subplugin supports it
}
}
SDKHook(iBoss, SDKHook_OnTakeDamage, CheckEnvironmentalDamage);
}
}
public void Event_RoundEnd(Event hEvent, const char[] strName, bool bDontBroadcast)
{
for(int iClient = 1; iClient <= MaxClients; iClient++)
{
MJ_EmergencyReady[iClient] = false;
MT_EmergencyReady[iClient] = false;
JM_AbilitySwitched[iClient] = false;
Orb_TriggerAMS[iClient] = false;
Meteor_TriggerAMS[iClient] = false;
Monoculus_TriggerAMS[iClient] = false;
Invis_TriggerAMS[iClient] = false;
Minify_TriggerAMS[iClient] = false;
Bats_TriggerAMS[iClient] = false;
Horde_TriggerAMS[iClient] = false;
Meras_TriggerAMS[iClient] = false;
Horse_TriggerAMS[iClient] = false;
if(IsValidClient(iClient))
{
SDKUnhook(iClient, SDKHook_OnTakeDamage, OnTakeDamage);
SDKUnhook(iClient, SDKHook_OnTakeDamage, CheckEnvironmentalDamage);
}
}
}
public void HookAbilities()
{
for(int iClient=1; iClient <= MaxClients; iClient++)
{
if(!IsValidClient(iClient))
return;
Orb_TriggerAMS[iClient] = false;
Meteor_TriggerAMS[iClient] = false;
Monoculus_TriggerAMS[iClient] = false;
Invis_TriggerAMS[iClient] = false;
Minify_TriggerAMS[iClient] = false;
Bats_TriggerAMS[iClient] = false;
Horde_TriggerAMS[iClient] = false;
Meras_TriggerAMS[iClient] = false;
Horse_TriggerAMS[iClient] = false;
int iIndex = FF2_GetBossIndex(iClient);
if(iIndex>=0)
{
if(FF2_HasAbility(iIndex, this_plugin_name, "special_jumpmanager"))
{
JM_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "special_jumpmanager", 1); // Button for activation, 1 = reload, 2 = special attack, 3 = secondary attack
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "special_jumpmanager", 2); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
MJ_ChargeTime[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 3); // Time it takes to charge
MJ_Cooldown[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 4); // Time it takes to refresh
MJ_OnCooldownUntil[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 5); // Time before first use
MT_ChargeTime[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 6); // Time it takes to charge
MT_Cooldown[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 7); // Time it takes to refresh
MT_OnCooldownUntil[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_jumpmanager", 8); // Time before first use
SpawnWeapon(iClient, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "charge_magicjump"))
{
MJ_ChargeTime[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 1); // Time it takes to charge
MJ_Cooldown[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 2); // Time it takes to refresh
MJ_OnCooldownUntil[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magicjump", 3); // Time before first use
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "charge_magicjump", 4); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
SpawnWeapon(iClient, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "charge_magictele"))
{
MT_ChargeTime[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 1); // Time it takes to charge
MT_Cooldown[iClient] = FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 2); // Time it takes to refresh
MT_OnCooldownUntil[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "charge_magictele", 3); // Time before first use
MJT_ButtonType = FF2_GetAbilityArgument(iIndex, this_plugin_name, "charge_magictele", 4); // Button for activation, 1 = secondary attack, 2 = reload, 3 = special attack
SpawnWeapon(iClient, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "special_spellattack"))
{
SS_CoolDown[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iIndex, this_plugin_name, "special_spellattack", 1);
for(int i=1; i<=MaxClients; i++)
SDKHook(i, SDKHook_OnTakeDamage, OnTakeDamage);
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_orb"))
{
Orb_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_orb", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Orb_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_orb", "ORB"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_meteor"))
{
Meteor_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_meteor", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Meteor_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_meteor", "MET"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_mono"))
{
Monoculus_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_mono", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Monoculus_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_mono", "MONO"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_invis"))
{
Invis_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_invis", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Invis_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_invis", "INV"); // Important function to tell AMS that this subplugin supports it
}
SpawnWeapon(iClient, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_minify"))
{
Minify_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_minify", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Minify_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_minify", "MINI"); // Important function to tell AMS that this subplugin supports it
}
SpawnWeapon(iClient, "tf_weapon_spellbook", 1069, 0, 0, "");
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_bats"))
{
Bats_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_bats", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Bats_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_bats", "BATS"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_horde"))
{
Horde_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_horde", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Horde_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_horde", "HORDE"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_meras"))
{
Meras_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_meras", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Meras_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_meras", "MERAS"); // Important function to tell AMS that this subplugin supports it
}
}
if(FF2_HasAbility(iIndex, this_plugin_name, "rage_horse"))
{
Horse_TriggerAMS[iClient] = FF2_GetAbilityArgument(iIndex, this_plugin_name, "rage_horse", 1) == 1; // If true, this will trigger AMS_InitSubability.
if(Horse_TriggerAMS[iClient])
{
AMS_InitSubability(iIndex, iClient, this_plugin_name, "rage_horse", "HORSE"); // Important function to tell AMS that this subplugin supports it
}
}
SDKHook(iClient, SDKHook_OnTakeDamage, CheckEnvironmentalDamage);
}
}
}
public void FF2_OnAbility2(int iBoss, const char[] pluginName, const char[] abilityName, int iStatus)
{
int iClient = GetClientOfUserId(FF2_GetBossUserId(iBoss));
if (!strcmp(abilityName, "rage_orb"))
Rage_Orb(iClient);
else if (!strcmp(abilityName, "rage_meteor"))
Rage_Meteor(iClient);
else if (!strcmp(abilityName, "rage_invis"))
Rage_Invis(iClient);
else if (!strcmp(abilityName, "rage_minify"))
Rage_Minify(iClient);
else if (!strcmp(abilityName, "rage_bats"))
Rage_Bats(iClient);
else if (!strcmp(abilityName, "rage_horde"))
Rage_Horde(iClient);
else if (!strcmp(abilityName, "rage_mono"))
Rage_Monoculus(iClient);
else if (!strcmp(abilityName, "rage_meras"))
Rage_Merasmus(iClient);
else if (!strcmp(abilityName, "rage_horse"))
Rage_Horsemann(iClient);
}
public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float flVel[3], float flAng[3], int &iWep)
{
int iBoss = GetClientOfUserId(FF2_GetBossUserId(iClient));
if(!IsValidClient(iClient) || !IsPlayerAlive(iClient))
return Plugin_Continue;
if(FF2_HasAbility(iBoss, this_plugin_name, "special_jumpmanager") && GetClientTeam(iClient) == BossTeam)
{
if(!FF2_IsFF2Enabled() || FF2_GetRoundState() != 1)
return Plugin_Continue;
JM_Tick(iClient, iButtons, GetEngineTime());
char Button;
switch(JM_ButtonType)
{
case 1: Button = IN_RELOAD;
case 2: Button = IN_ATTACK3;
case 3: Button = IN_ATTACK2;
}
if(iButtons & Button)
{
if(!JM_AbilitySwitched[iClient])
JM_AbilitySwitched[iClient] = true;
else JM_AbilitySwitched[iClient] = false;
}
}
if(FF2_HasAbility(iBoss, this_plugin_name, "charge_magicjump") && GetClientTeam(iClient) == BossTeam)
{
if(!FF2_IsFF2Enabled() || FF2_GetRoundState() != 1)
return Plugin_Continue;
MJ_Tick(iClient, iButtons, GetEngineTime());
}
if(FF2_HasAbility(iBoss, this_plugin_name, "charge_magictele") && GetClientTeam(iClient) == BossTeam)
{
if(!FF2_IsFF2Enabled() || FF2_GetRoundState() != 1)
return Plugin_Continue;
MT_Tick(iClient, iButtons, GetEngineTime());
}
if(FF2_HasAbility(iBoss, this_plugin_name, "special_spellattack") && GetClientTeam(iClient) == BossTeam)
{
if(!FF2_IsFF2Enabled() || FF2_GetRoundState() != 1)
return Plugin_Continue;
if(iButtons & IN_ATTACK)
{
if(GetEngineTime() >= SS_CoolDown[iClient])
{
ShootProjectile(iClient, "tf_projectile_spellfireball");
SS_CoolDown[iClient] = GetEngineTime() + FF2_GetAbilityArgumentFloat(iBoss, this_plugin_name, "special_spellattack", 1);
float position[3];
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", position);
char sound[PLATFORM_MAX_PATH];
if (FF2_RandomSound("sound_ability", sound, PLATFORM_MAX_PATH, iBoss, 4))
{
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
for (int enemy = 1; enemy < MaxClients; enemy++)
{
if (IsClientInGame(enemy) && enemy != iClient)
{
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
}
}
}
}
else iButtons &= ~IN_ATTACK;
}
}
return Plugin_Continue;
}
public Action OnTakeDamage(int iClient, int &iAttacker, int &iInflictor, float &flDamage, int &iDamagetype, int &iWeapon, float flDamageForce[3], float flDamagePosition[3], int iDamageCustom)
{
if (!IsValidClient(iAttacker) || GetClientTeam(iAttacker)!=BossTeam)
return Plugin_Continue;
int iBoss = FF2_GetBossIndex(iAttacker);
if(FF2_HasAbility(iBoss, this_plugin_name, "special_spellattack"))
{
flDamage *= 0.2;
return Plugin_Changed;
}
return Plugin_Continue;
}
public Action:CheckEnvironmentalDamage(int iClient, int &iAttacker, int &iInflictor, float &flDmg, int &DmgType, int &iWep, float flDmgForce[3], float flDmgPos[3], int DmgCstm)
{
if (!IsValidClient(iClient, true))
return Plugin_Continue;
if (iAttacker == 0 && iInflictor == 0 && (DmgType & DMG_FALL) != 0)
return Plugin_Continue;
// ignore damage from players
if (iAttacker >= 1 && iAttacker <= MaxClients)
return Plugin_Continue;
int iBoss = GetClientOfUserId(FF2_GetBossUserId(iClient));
if (FF2_HasAbility(iBoss, this_plugin_name, "charge_magicjump") || FF2_HasAbility(iBoss, this_plugin_name, "special_jumpmanager"))
{
if (flDmg > 50.0)
{
MJ_EmergencyReady[iClient] = true;
MJ_OnCooldownUntil[iClient] = FAR_FUTURE;
}
}
if (FF2_HasAbility(iBoss, this_plugin_name, "charge_magictele") || FF2_HasAbility(iBoss, this_plugin_name, "special_jumpmanager"))
{
if (flDmg > 50.0)
{
MT_EmergencyReady[iClient] = true;
MT_OnCooldownUntil[iClient] = FAR_FUTURE;
}
}
return Plugin_Continue;
}
public bool BATS_CanInvoke(int iClient)
{
return true;
}
void Rage_Bats(int iClient)
{
if(Bats_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
BATS_Invoke(iClient);
}
public void BATS_Invoke(int iClient)
{
ShootProjectile(iClient, "tf_projectile_spellbats");
}
public bool ORB_CanInvoke(int iClient)
{
return true;
}
void Rage_Orb(int iClient)
{
if(Orb_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
ORB_Invoke(iClient);
}
public void ORB_Invoke(int iClient)
{
ShootProjectile(iClient, "tf_projectile_lightningorb");
}
public bool MET_CanInvoke(int iClient)
{
return true;
}
void Rage_Meteor(int iClient)
{
if(Meteor_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
MET_Invoke(iClient);
}
public void MET_Invoke(int iClient)
{
ShootProjectile(iClient, "tf_projectile_spellmeteorshower");
}
public bool MINI_CanInvoke(int iClient)
{
return true;
}
void Rage_Minify(int iClient)
{
if(Minify_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
MINI_Invoke(iClient);
}
public void MINI_Invoke(int iClient)
{
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 8);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
}
public bool INV_CanInvoke(int iClient)
{
return true;
}
void Rage_Invis(int iClient)
{
if(Invis_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
INV_Invoke(iClient);
}
public void INV_Invoke(int iClient)
{
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 5);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
}
public bool MONO_CanInvoke(int iClient)
{
return true;
}
void Rage_Monoculus(int iClient)
{
if(Monoculus_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
MONO_Invoke(iClient);
}
public void MONO_Invoke(int iClient)
{
ShootProjectile(iClient, "tf_projectile_spellspawnboss");
}
public bool HORDE_CanInvoke(int iClient)
{
return true;
}
void Rage_Horde(int iClient)
{
if(Horde_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
HORDE_Invoke(iClient);
}
public void HORDE_Invoke(int iClient)
{
int iBoss = FF2_GetBossIndex(iClient);
SkeleNumberOfSpawns[iClient] = FF2_GetAbilityArgument(iBoss, this_plugin_name, "rage_horde", 2);
SDKHook(ShootProjectile(iClient, "tf_projectile_spellspawnhorde"), SDKHook_StartTouch, Projectile_Touch);
}
public bool MERAS_CanInvoke(int iClient)
{
for(int iVictim = 1; iVictim <= MaxClients; iVictim++)
{
if(iClient == iVictim || !IsValidClient(iVictim))
continue;
float flAngles[3], flOrigin[3], flEnd[3];
GetClientEyePosition(iClient, flOrigin);
GetClientEyeAngles(iClient, flAngles);
Handle TraceRay = TR_TraceRayFilterEx(flOrigin, flAngles, MASK_SHOT, RayType_Infinite, TraceEntityFilterPlayer);
if(TR_DidHit(TraceRay))
TR_GetEndPosition(flEnd, TraceRay);
delete TraceRay;
float victimOrigin[3];
GetEntPropVector(iVictim, Prop_Send, "m_vecOrigin", victimOrigin);
if(CylinderCollision(flEnd, victimOrigin, 225.0, flEnd[2] - 350.0, flEnd[2] - 0.01))
{
PrintCenterText(iClient, "Location blocked by player(s)!");
return false;
}
}
return true;
}
void Rage_Merasmus(int iClient)
{
if(Meras_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
MERAS_Invoke(iClient);
}
public void MERAS_Invoke(int iClient)
{
EntCreate(iClient, "merasmus");
}
public bool HORSE_CanInvoke(int iClient)
{
for(int iVictim = 1; iVictim <= MaxClients; iVictim++)
{
if(iClient == iVictim || !IsValidClient(iVictim))
continue;
float flAngles[3], flOrigin[3], flEnd[3];
GetClientEyePosition(iClient, flOrigin);
GetClientEyeAngles(iClient, flAngles);
Handle TraceRay = TR_TraceRayFilterEx(flOrigin, flAngles, MASK_SHOT, RayType_Infinite, TraceEntityFilterPlayer);
if(TR_DidHit(TraceRay))
TR_GetEndPosition(flEnd, TraceRay);
delete TraceRay;
float victimOrigin[3];
GetEntPropVector(iVictim, Prop_Send, "m_vecOrigin", victimOrigin);
if(CylinderCollision(flEnd, victimOrigin, 225.0, flEnd[2] - 350.0, flEnd[2] - 0.01))
{
PrintCenterText(iClient, "Location blocked by player(s)!");
return false;
}
}
return true;
}
void Rage_Horsemann(int iClient)
{
if(Horse_TriggerAMS[iClient]) // Prevent normal 100% RAGE activation if using AMS
return;
HORSE_Invoke(iClient);
}
public void HORSE_Invoke(int iClient)
{
EntCreate(iClient, "headless_hatman");
}
public Action Projectile_Touch(int iProj, int iOther)
{
int iClient = GetEntPropEnt(iProj, Prop_Send, "m_hOwnerEntity");
char strClassname[11];
if((GetEntityClassname(iOther, strClassname, 11) && StrEqual(strClassname, "worldspawn")) || (iOther > 0 && iOther <= MaxClients))
{
float flPos[3], flAng[3];
GetEntPropVector(iProj, Prop_Data, "m_vecAbsOrigin", flPos);
for (int i = 0; i <= SkeleNumberOfSpawns[iClient]; i++)
{
flAng[0] = GetRandomFloat(-500.0, 500.0);
flAng[1] = GetRandomFloat(-500.0, 500.0);
flAng[2] = GetRandomFloat(0.0, 25.0);
int iTeam = GetClientTeam(iClient);
int iSpell = CreateEntityByName("tf_projectile_spellspawnhorde");
if(!IsValidEntity(iSpell))
return Plugin_Continue;
SetEntPropEnt(iSpell, Prop_Send, "m_hOwnerEntity", iClient);
SetEntProp(iSpell, Prop_Send, "m_iTeamNum", iTeam, 1);
SetEntProp(iSpell, Prop_Send, "m_nSkin", (iTeam-2));
SetVariantInt(iTeam);
AcceptEntityInput(iSpell, "TeamNum", -1, -1, 0);
SetVariantInt(iTeam);
AcceptEntityInput(iSpell, "SetTeam", -1, -1, 0);
DispatchSpawn(iSpell);
TeleportEntity(iSpell, flPos, flAng, flAng);
}
}
return Plugin_Continue;
}
public void MJ_Tick(int iClient, int iButtons, float flTime)
{
int Boss = FF2_GetBossIndex(iClient);
if(FF2_HasAbility(Boss, this_plugin_name, "special_jumpmanager")) // Prevent possible double up conflicts
return;
if (flTime >= MJ_OnCooldownUntil[iClient])
MJ_OnCooldownUntil[iClient] = FAR_FUTURE;
float flCharge = 0.0;
if (MJ_OnCooldownUntil[iClient] == FAR_FUTURE)
{
// get charge percent here, used by both the HUD and the actual jump
if (MJ_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE)
{
if (MJ_ChargeTime[iClient] <= 0.0)
flCharge = 100.0;
else
flCharge = fmin((flTime - MJ_CrouchOrAltFireDownSince[iClient]) / MJ_ChargeTime[iClient], 1.0) * 100.0;
}
char Button;
switch(MJT_ButtonType)
{
case 1: Button = IN_ATTACK2;
case 2: Button = IN_RELOAD;
case 3: Button = IN_ATTACK3;
}
// do we start the charging now?
if (MJ_CrouchOrAltFireDownSince[iClient] == FAR_FUTURE && (iButtons & Button) != 0)
MJ_CrouchOrAltFireDownSince[iClient] = flTime;
// has key been released?
if (MJ_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE && (iButtons & Button) == 0)
{
if (!IsInInvalidCondition(iClient))
{
MJ_OnCooldownUntil[iClient] = flTime + MJ_Cooldown[iClient];
// taken from default_abilities, modified only lightly
float position[3];
float velocity[3];
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", position);
GetEntPropVector(iClient, Prop_Data, "m_vecVelocity", velocity);
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 4);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
// for the sake of making this viable, I'm keeping an actual jump, but half the power of a standard jump
if (MJ_EmergencyReady[iClient])
{
velocity[2] = (750 + (flCharge / 4) * 13.0) + 2000 * 0.75;
MJ_EmergencyReady[iClient] = false;
}
else
{
velocity[2] = (750 + (flCharge / 4) * 13.0) * 0.5;
}
SetEntProp(iClient, Prop_Send, "m_bJumping", 1);
velocity[0] *= (1 + Sine((flCharge / 4) * FLOAT_PI / 50)) * 0.5;
velocity[1] *= (1 + Sine((flCharge / 4) * FLOAT_PI / 50)) * 0.5;
TeleportEntity(iClient, NULL_VECTOR, NULL_VECTOR, velocity);
char sound[PLATFORM_MAX_PATH];
if (FF2_RandomSound("sound_magjump", sound, PLATFORM_MAX_PATH, Boss))
{
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
for (new enemy = 1; enemy < MaxClients; enemy++)
{
if (IsClientInGame(enemy) && enemy != iClient)
{
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
}
}
}
}
// regardless of outcome, cancel the charge.
MJ_CrouchOrAltFireDownSince[iClient] = FAR_FUTURE;
}
}
// draw the HUD if it's time
if (flTime >= WitchDoctorUpdateHUD[iClient])
{
if (!(GetClientButtons(iClient) & IN_SCORE))
{
if (MJ_EmergencyReady[iClient])
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Super DUPER Jump ready! Press and release %s!", GetMJTButton());
}
else if (MJ_OnCooldownUntil[iClient] == FAR_FUTURE)
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_OK, HUD_G_OK, HUD_B_OK, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Jump is ready. %.0f percent charged.\nPress and release %s!", flCharge, GetMJTButton());
}
else
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Jump is not ready. %.1f seconds remaining.", MJ_OnCooldownUntil[iClient] - flTime);
}
}
WitchDoctorUpdateHUD[iClient] = flTime + HUD_INTERVAL;
}
}
public void MT_Tick(int iClient, int iButtons, float flTime)
{
int Boss = FF2_GetBossIndex(iClient);
if(FF2_HasAbility(Boss, this_plugin_name, "special_jumpmanager")) // Prevent possible double up conflicts
return;
if (flTime >= MT_OnCooldownUntil[iClient])
MT_OnCooldownUntil[iClient] = FAR_FUTURE;
float flCharge = 0.0;
if (MT_OnCooldownUntil[iClient] == FAR_FUTURE)
{
// get charge percent here, used by both the HUD and the actual jump
if (MT_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE)
{
if (MT_ChargeTime[iClient] <= 0.0)
flCharge = 100.0;
else
flCharge = fmin((flTime - MT_CrouchOrAltFireDownSince[iClient]) / MT_ChargeTime[iClient], 1.0) * 100.0;
}
char Button;
switch(MJT_ButtonType)
{
case 1: Button = IN_ATTACK2;
case 2: Button = IN_RELOAD;
case 3: Button = IN_ATTACK3;
}
// do we start the charging now?
if (MT_CrouchOrAltFireDownSince[iClient] == FAR_FUTURE && (iButtons & Button) != 0)
MT_CrouchOrAltFireDownSince[iClient] = flTime;
// has key been released?
if (MT_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE && (iButtons & Button) == 0)
{
if (!IsInInvalidCondition(iClient))
{
MT_OnCooldownUntil[iClient] = flTime + MT_Cooldown[iClient];
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 6);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
// just because I can see this becoming an immediate problem, gonna add an emergency teleport
if (MT_EmergencyReady[iClient])
{
if (DD_PerformTeleport(iClient, 2.0, _, true))
{
MT_EmergencyReady[iClient] = false;
}
}
float position[3];
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", position);
char sound[PLATFORM_MAX_PATH];
if (FF2_RandomSound("sound_magtele", sound, PLATFORM_MAX_PATH, Boss))
{
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
for (int enemy = 1; enemy < MaxClients; enemy++)
{
if (IsClientInGame(enemy) && enemy != iClient)
{
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
}
}
}
}
// regardless of outcome, cancel the charge.
MT_CrouchOrAltFireDownSince[iClient] = FAR_FUTURE;
}
}
// draw the HUD if it's time
if (flTime >= WitchDoctorUpdateHUD[iClient])
{
if (!(GetClientButtons(iClient) & IN_SCORE))
{
if (MT_EmergencyReady[iClient])
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "EMERGENCY TELEPORT! Press and release %s!", GetMJTButton());
}
else if (MT_OnCooldownUntil[iClient] == FAR_FUTURE)
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_OK, HUD_G_OK, HUD_B_OK, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Tele is ready. %.0f percent charged.\nPress and release %s!", flCharge, GetMJTButton());
}
else
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Tele is not ready. %.1f seconds remaining.", MT_OnCooldownUntil[iClient] - flTime);
}
}
WitchDoctorUpdateHUD[iClient] = flTime + HUD_INTERVAL;
}
}
public void JM_Tick(int iClient, int iButtons, float flTime)
{
if(!JM_AbilitySwitched[iClient])
{
if (flTime >= MJ_OnCooldownUntil[iClient])
MJ_OnCooldownUntil[iClient] = FAR_FUTURE;
float flCharge = 0.0;
if (MJ_OnCooldownUntil[iClient] == FAR_FUTURE)
{
// get charge percent here, used by both the HUD and the actual jump
if (MJ_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE)
{
if (MJ_ChargeTime[iClient] <= 0.0)
flCharge = 100.0;
else
flCharge = fmin((flTime - MJ_CrouchOrAltFireDownSince[iClient]) / MJ_ChargeTime[iClient], 1.0) * 100.0;
}
char Button;
switch(MJT_ButtonType)
{
case 1: Button = IN_ATTACK2;
case 2: Button = IN_RELOAD;
case 3: Button = IN_ATTACK3;
}
// do we start the charging now?
if (MJ_CrouchOrAltFireDownSince[iClient] == FAR_FUTURE && (iButtons & Button) != 0)
MJ_CrouchOrAltFireDownSince[iClient] = flTime;
// has key been released?
if (MJ_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE && (iButtons & Button) == 0)
{
if (!IsInInvalidCondition(iClient))
{
MJ_OnCooldownUntil[iClient] = flTime + MJ_Cooldown[iClient];
// taken from default_abilities, modified only lightly
int Boss = FF2_GetBossIndex(iClient);
float position[3];
float velocity[3];
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", position);
GetEntPropVector(iClient, Prop_Data, "m_vecVelocity", velocity);
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 4);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
// for the sake of making this viable, I'm keeping an actual jump, but half the power of a standard jump
if (MJ_EmergencyReady[iClient])
{
velocity[2] = (750 + (flCharge / 4) * 13.0) + 2000 * 0.75;
MJ_EmergencyReady[iClient] = false;
}
else
{
velocity[2] = (750 + (flCharge / 4) * 13.0) * 0.5;
}
SetEntProp(iClient, Prop_Send, "m_bJumping", 1);
velocity[0] *= (1 + Sine((flCharge / 4) * FLOAT_PI / 50)) * 0.5;
velocity[1] *= (1 + Sine((flCharge / 4) * FLOAT_PI / 50)) * 0.5;
TeleportEntity(iClient, NULL_VECTOR, NULL_VECTOR, velocity);
char sound[PLATFORM_MAX_PATH];
if (FF2_RandomSound("sound_magjump", sound, PLATFORM_MAX_PATH, Boss))
{
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
for (new enemy = 1; enemy < MaxClients; enemy++)
{
if (IsClientInGame(enemy) && enemy != iClient)
{
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
}
}
}
}
// regardless of outcome, cancel the charge.
MJ_CrouchOrAltFireDownSince[iClient] = FAR_FUTURE;
}
}
// draw the HUD if it's time
if (flTime >= WitchDoctorUpdateHUD[iClient])
{
if (!(GetClientButtons(iClient) & IN_SCORE))
{
if (MJ_EmergencyReady[iClient])
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Super DUPER Jump ready! Press and release %s!", GetMJTButton());
}
else if (MJ_OnCooldownUntil[iClient] == FAR_FUTURE)
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_OK, HUD_G_OK, HUD_B_OK, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Jump is ready. %.0f percent charged.\nPress and release %s!\nPress %s to change.", flCharge, GetMJTButton(), GetJMButton());
}
else
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Jump is not ready. %.1f seconds remaining.\nPress %s to change.", MJ_OnCooldownUntil[iClient] - flTime, GetJMButton());
}
}
WitchDoctorUpdateHUD[iClient] = flTime + HUD_INTERVAL;
}
}else
{
if (flTime >= MT_OnCooldownUntil[iClient])
MT_OnCooldownUntil[iClient] = FAR_FUTURE;
float flCharge = 0.0;
if (MT_OnCooldownUntil[iClient] == FAR_FUTURE)
{
// get charge percent here, used by both the HUD and the actual jump
if (MT_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE)
{
if (MT_ChargeTime[iClient] <= 0.0)
flCharge = 100.0;
else
flCharge = fmin((flTime - MT_CrouchOrAltFireDownSince[iClient]) / MT_ChargeTime[iClient], 1.0) * 100.0;
}
char Button;
switch(MJT_ButtonType)
{
case 1: Button = IN_ATTACK2;
case 2: Button = IN_RELOAD;
case 3: Button = IN_ATTACK3;
}
// do we start the charging now?
if (MT_CrouchOrAltFireDownSince[iClient] == FAR_FUTURE && (iButtons & Button) != 0)
MT_CrouchOrAltFireDownSince[iClient] = flTime;
// has key been released?
if (MT_CrouchOrAltFireDownSince[iClient] != FAR_FUTURE && (iButtons & Button) == 0)
{
if (!IsInInvalidCondition(iClient))
{
MT_OnCooldownUntil[iClient] = flTime + MT_Cooldown[iClient];
int spellbook = FindSpellBook(iClient);
SetEntProp(spellbook, Prop_Send, "m_iSelectedSpellIndex", 6);
SetEntProp(spellbook, Prop_Send, "m_iSpellCharges", 1);
FakeClientCommand(iClient, "use tf_weapon_spellbook");
// just because I can see this becoming an immediate problem, gonna add an emergency teleport
if (MT_EmergencyReady[iClient])
{
if (DD_PerformTeleport(iClient, 2.0, _, true))
{
MT_EmergencyReady[iClient] = false;
}
}
float position[3];
GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", position);
int Boss = FF2_GetBossIndex(iClient);
char sound[PLATFORM_MAX_PATH];
if (FF2_RandomSound("sound_magtele", sound, PLATFORM_MAX_PATH, Boss))
{
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToAll(sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
for (int enemy = 1; enemy < MaxClients; enemy++)
{
if (IsClientInGame(enemy) && enemy != iClient)
{
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
EmitSoundToClient(enemy, sound, iClient, _, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, iClient, position, NULL_VECTOR, true, 0.0);
}
}
}
}
// regardless of outcome, cancel the charge.
MT_CrouchOrAltFireDownSince[iClient] = FAR_FUTURE;
}
}
// draw the HUD if it's time
if (flTime >= WitchDoctorUpdateHUD[iClient])
{
if (!(GetClientButtons(iClient) & IN_SCORE))
{
if (MT_EmergencyReady[iClient])
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "EMERGENCY TELEPORT! Press and release %s!", GetMJTButton());
}
else if (MT_OnCooldownUntil[iClient] == FAR_FUTURE)
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_OK, HUD_G_OK, HUD_B_OK, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Tele is ready. %.0f percent charged.\nPress and release %s!\nPress %s to change.", flCharge, GetMJTButton(), GetJMButton());
}
else
{
SetHudTextParams(-1.0, 0.88, HUD_INTERVAL + HUD_LINGER, HUD_R_ERROR, HUD_G_ERROR, HUD_B_ERROR, HUD_ALPHA);
ShowSyncHudText(iClient, witchdoctorHUD, "Magic Tele is not ready. %.1f seconds remaining.\nPress %s to change.", MT_OnCooldownUntil[iClient] - flTime, GetJMButton());
}
}
WitchDoctorUpdateHUD[iClient] = flTime + HUD_INTERVAL;
}
}
}
public Action Timer_SwitchToSlot(Handle hTimer, any iClient)
{
if(IsValidClient(iClient, true))
SwitchtoSlot(iClient, 2);
}
stock int SpawnWeapon(int iClient, char[] strClassname, int iIndex, int iLevel, int iQuality, const char[] strAttribute = "", bool bShow = true, bool bEquip = false)
{
Handle hWeapon = TF2Items_CreateItem(OVERRIDE_ALL|FORCE_GENERATION);
if (hWeapon == null)
return -1;
TF2Items_SetClassname(hWeapon, strClassname);
TF2Items_SetItemIndex(hWeapon, iIndex);
TF2Items_SetLevel(hWeapon, iLevel);
TF2Items_SetQuality(hWeapon, iQuality);
char strAttributes[32][32];
int count=ExplodeString(strAttribute, ";", strAttributes, 32, 32);
if (count % 2)
--count;
if (count > 0)
{
TF2Items_SetNumAttributes(hWeapon, count/2);
int i2;
for(int i; i < count; i += 2)
{
int attrib = StringToInt(strAttributes[i]);
if (!attrib)
{
LogError("Bad weapon attribute passed: %s ; %s", strAttributes[i], strAttributes[i+1]);
CloseHandle(hWeapon);
return -1;
}
TF2Items_SetAttribute(hWeapon, i2, attrib, StringToFloat(strAttributes[i+1]));
i2++;
}
}
else
TF2Items_SetNumAttributes(hWeapon, 0);
int iEntity = TF2Items_GiveNamedItem(iClient, hWeapon);
delete hWeapon;
EquipPlayerWeapon(iClient, iEntity);
if(bEquip)
SetEntPropEnt(iClient, Prop_Send, "m_hActiveWeapon", iEntity);
if (!bShow)
{
SetEntProp(iEntity, Prop_Send, "m_iWorldModelIndex", -1);
SetEntPropFloat(iEntity, Prop_Send, "m_flModelScale", 0.001);
}
return iEntity;
}
stock int FindEntityByClassname2(int startEnt, const char[] strClassname)
{
/* If startEnt isn't valid shifting it back to the nearest valid one */
while (startEnt > -1 && !IsValidEntity(startEnt)) startEnt--;
return FindEntityByClassname(startEnt, strClassname);
}
int ShootProjectile(int iClient, char strEntname[48] = "")
{
float flAng[3]; // original
float flPos[3]; // original
GetClientEyeAngles(iClient, flAng);
GetClientEyePosition(iClient, flPos);
int iTeam = GetClientTeam(iClient);
int iSpell = CreateEntityByName(strEntname);
if(!IsValidEntity(iSpell))
return -1;
float flVel1[3];
float flVel2[3];
GetAngleVectors(flAng, flVel2, NULL_VECTOR, NULL_VECTOR);
flVel1[0] = flVel2[0]*1100.0; //Speed of a tf2 rocket.
flVel1[1] = flVel2[1]*1100.0;
flVel1[2] = flVel2[2]*1100.0;
SetEntPropEnt(iSpell, Prop_Send, "m_hOwnerEntity", iClient);
SetEntProp(iSpell, Prop_Send, "m_bCritical", (GetRandomInt(0, 100) <= 5)? 1 : 0, 1);
SetEntProp(iSpell, Prop_Send, "m_iTeamNum", iTeam, 1);
SetEntProp(iSpell, Prop_Send, "m_nSkin", (iTeam-2));
TeleportEntity(iSpell, flPos, flAng, NULL_VECTOR);
SetVariantInt(iTeam);
AcceptEntityInput(iSpell, "TeamNum", -1, -1, 0);
SetVariantInt(iTeam);
AcceptEntityInput(iSpell, "SetTeam", -1, -1, 0);
DispatchSpawn(iSpell);
TeleportEntity(iSpell, NULL_VECTOR, NULL_VECTOR, flVel1);
return iSpell;
}
public void EntCreate(iClient, char[] strEntity)
{
int flags = GetCommandFlags("ent_create");
SetCommandFlags("ent_create", flags & ~FCVAR_CHEAT);
ClientCommand(iClient, "ent_create %s", strEntity);
SetCommandFlags("ent_create", flags);
}
stock bool IsValidClient(int iClient, bool bAlive = false, bool bTeam = false)
{
if(iClient <= 0 || iClient > MaxClients || !IsClientInGame(iClient))
return false;
if(IsClientSourceTV(iClient) || IsClientReplay(iClient))
return false;
if(bAlive && !IsPlayerAlive(iClient))
return false;
if(bTeam && GetClientTeam(iClient) != BossTeam)
return false;
return true;
}
public bool IsInInvalidCondition(iClient)
{
return TF2_IsPlayerInCondition(iClient, TFCond_Dazed) || TF2_IsPlayerInCondition(iClient, TFCond_Taunting) || GetEntityMoveType(iClient)==MOVETYPE_NONE;
}
stock float fmin(float n1, float n2)
{
return n1 < n2 ? n1 : n2;
}
stock char GetJMButton()
{
char strBuffer[18];
switch(JM_ButtonType)
{
case 1: strBuffer = "Reload";
case 2: strBuffer = "Special Attack";
case 3: strBuffer = "Secondary Attack";
}
return strBuffer;
}
stock char GetMJTButton()
{
char strBuffer[18];
switch(MJT_ButtonType)
{
case 1: strBuffer = "Secondary Attack";
case 2: strBuffer = "Reload";
case 3: strBuffer = "Special Attack";
}
return strBuffer;
}
stock int FindSpellBook(int iClient)
{
int spellbook = -1;
while ((spellbook = FindEntityByClassname(spellbook, "tf_weapon_spellbook")) != -1)
{
if (IsValidEntity(spellbook) && GetEntPropEnt(spellbook, Prop_Send, "m_hOwnerEntity") == iClient)
if(!GetEntProp(spellbook, Prop_Send, "m_bDisguiseWeapon"))
return spellbook;
}
return -1;
}
void SwitchtoSlot(int iClient, int iSlot)
{
if (iSlot >= 0 && iSlot <= 5 && IsClientInGame(iClient) && IsPlayerAlive(iClient))
{
char strClassname[64];
int iWeapon = GetPlayerWeaponSlot(iClient, iSlot);
if (iWeapon > MaxClients && IsValidEdict(iWeapon) && GetEdictClassname(iWeapon, strClassname, sizeof(strClassname)))
{
FakeClientCommandEx(iClient, "use %s", strClassname);
SetEntPropEnt(iClient, Prop_Send, "m_hActiveWeapon", iWeapon);
}
}
}
public bool TraceEntityFilterPlayer(int iEntity, int contentsMask)
{
return (iEntity > GetMaxClients() || !iEntity);
}
stock bool CylinderCollision(float cylinderOrigin[3], float colliderOrigin[3], float maxDistance, float zMin, float zMax)
{
if (colliderOrigin[2] < zMin || colliderOrigin[2] > zMax)
return false;
static float tmpVec1[3];
tmpVec1[0] = cylinderOrigin[0];
tmpVec1[1] = cylinderOrigin[1];
tmpVec1[2] = 0.0;
static float tmpVec2[3];
tmpVec2[0] = colliderOrigin[0];
tmpVec2[1] = colliderOrigin[1];
tmpVec2[2] = 0.0;
return GetVectorDistance(tmpVec1, tmpVec2, true) <= maxDistance * maxDistance;
}
// call AMS from epic scout's subplugin via reflection:
stock Handle FindPlugin(char[] plugin_name)
{
char buffer[256];
char path[PLATFORM_MAX_PATH];
Handle iter = GetPluginIterator();
Handle pl = INVALID_HANDLE;
while (MorePlugins(iter))
{
pl = ReadPlugin(iter);
Format(path, sizeof(path), "%s.ff2", plugin_name);
GetPluginFilename(pl, buffer, sizeof(buffer));
if (StrContains(buffer, path, false) >= 0)
break;
else
pl = INVALID_HANDLE;
}
delete iter;
return pl;
}
// this will tell AMS that the abilities listed on PrepareAbilities() supports AMS
stock void AMS_InitSubability(int iBoss, int iClient, const char[] plugin_name, const char[] ability_name, const char[] prefix)
{
Handle plugin = FindPlugin("ff2_sarysapub3");
if (plugin != INVALID_HANDLE)
{
Function func = GetFunctionByName(plugin, "AMS_InitSubability");
if (func != INVALID_FUNCTION)
{
Call_StartFunction(plugin, func);
Call_PushCell(iBoss);
Call_PushCell(iClient);
Call_PushString(plugin_name);
Call_PushString(ability_name);
Call_PushString(prefix);
Call_Finish();
}
else
LogError("ERROR: Unable to initialize ff2_sarysapub3:AMS_InitSubability()");
}
else
LogError("ERROR: Unable to initialize ff2_sarysapub3:AMS_InitSubability(). Make sure this plugin exists!");
}
Edit: I fix that. Thx.
Last edited by tigocesar; 01-12-2017 at 20:37.
Reason: Fix
|
|