Skip to content

Commit

Permalink
2023年1月1日插件正式更新
Browse files Browse the repository at this point in the history
不再使用sv_tags来作为模式判断的问题,改为使用l4d_ready_cfg_name来判断
修复单人模式默认不加载anne+武器
rpg hats插件解决无数据库情况下无法使用的问题
修复一些权限错误
  • Loading branch information
fantasylidong committed Jan 1, 2023
1 parent 3e5c014 commit 5d1d960
Show file tree
Hide file tree
Showing 38 changed files with 350 additions and 233 deletions.
18 changes: 13 additions & 5 deletions .github/workflows/CompetitiveWithAnne.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CompetitiveWithAnne Update Achieve Release

env:
TZ: Asia/Shanghai

on:
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -37,14 +40,18 @@ jobs:
cp -R anne/left4dead2/models/ CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/
cp -R anne/update/ CompetitiveWithAnne-${{ steps.date.outputs.date }}/
tar -czvf CompetitiveWithAnne-${{ steps.date.outputs.date }}.tar.gz CompetitiveWithAnne-${{ steps.date.outputs.date }}
- name: Gzip nomysql
- name: Gzip norank&&sourcebans&&lilac
run: |
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/l4d_stats.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/sbpp_*
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/lilac.smx
tar -czvf CompetitiveWithAnne-${{ steps.date.outputs.date }}-norank.tar.gz CompetitiveWithAnne-${{ steps.date.outputs.date }}
- name: Gzip nomysql
run: |
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/chat-processor.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/hextags.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/lilac.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/sbpp_*
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/rpg.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/chatlog.smx
rm CompetitiveWithAnne-${{ steps.date.outputs.date }}/left4dead2/addons/sourcemod/plugins/extend/veterans.smx
Expand All @@ -58,5 +65,6 @@ jobs:
with:
files: |
CompetitiveWithAnne-${{ steps.date.outputs.date }}.tar.gz
CompetitiveWithAnne-${{ steps.date.outputs.date }}-norank.tar.gz
CompetitiveWithAnne-${{ steps.date.outputs.date }}-nomysql.tar.gz
tag_name: CompetitiveWithAnne-stable-release-${{ steps.date.outputs.date }}
tag_name: CompetitiveWithAnne-stable-release-${{ steps.date.outputs.date }}
5 changes: 4 additions & 1 deletion README-AnneHappy-zh-cn.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# **AnneHappy 插件带上对抗插件包**
* 为了保持插件包结构和上游一样方便同步,这个插件包将不会带有nav修改文件和跳舞插件的模型与声音,~~AnneHappy的Nav修改文件请到我的[anne项目](https://github.com/fantasylidong/anne)中下载~~ 新解决方案,到[release页面](https://github.com/fantasylidong/CompetitiveWithAnne/releases)下载整合插件包,里面有
* 当前版本已经是进入stable模式,大部分核心插件更新可以通过join插件自动更新,不用那么频繁检测是否有更新了
* 如果没有数据库,建议下[release页面](https://github.com/fantasylidong/CompetitiveWithAnne/releases)里的nomysql版本,删除了必须需要数据库的插件,rpg插件更改为caibiii的rpg老插件
* 如果没有数据库,建议下[release页面](https://github.com/fantasylidong/CompetitiveWithAnne/releases)里的norank版本或者nomysql版本
* norank版本是用电信服的rpg插件,只删除了排名,作弊检测和sourcebans插件,缺点就是每次进服务器需要自己设置出门近战,不想自己写了,有需求的写完可以pull request到我的项目里
* nomysql版本是删除了所有和数据库相关的插件


## **AnneHappy 会自动更新的核心插件**
- Path_SM/plugins/optional/AnneHappy/ai_boomer_new.smx"
Expand Down
22 changes: 21 additions & 1 deletion Update_log.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,24 @@ witchparty 和 allcharger模式在普通药役的基础上小僵尸再减少17-2
- 两种模式可以投票选择,默认自动时间刷特

#### text插件
- 适配新版刷特,提示为固定6特16秒或者自动6特16秒
- 适配新版刷特,提示为固定6特16秒或者自动6特16秒
- 更换模式检测方式

#### ai_boomer_2
- 强喷功能更新,大大降低胖子喷不到人的几率,而且让胖子转动,显得很合理(其实真合理,不过用插件改变不了胖子的喷射路径,只能用这种办法

#### ai_jockey_2
- 继续降低高跳角度,降低高跳速度

#### rpg
- 自动检测有没有数据库,有无数据库都可以运行,修复因为无数据库导致的崩服问题
- 无数据库的缺点,每次进服都需要自己设置出门近战武器

#### l4d_stats
- 更换模式检测方式

#### l4d_hats
- 将排名插件改为可选插件,无排名插件的情况下也能正常运行

#### 其他
- 修改特感增强里检测是否在地面的方式
10 changes: 10 additions & 0 deletions addons/sourcemod/configs/databases.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
"port" "12345"
}

"rpg"
{
"driver" "mysql"
"host" "home.trygek.com"
"database" "l4d2stats"
"user" "morzlee"
"pass" "anne123"
"port" "12345"
}

"storage-local"
{
"driver" "sqlite"
Expand Down
Binary file modified addons/sourcemod/plugins/extend/l4d_hats.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/extend/l4d_stats.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/extend/rpg.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/extend/rygive.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/ai_boomer_2.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/ai_charger_2.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/ai_jockey_2.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/ai_tank_2.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/infected_control.smx
Binary file not shown.
Binary file modified addons/sourcemod/plugins/optional/AnneHappy/text.smx
Binary file not shown.
158 changes: 104 additions & 54 deletions addons/sourcemod/scripting/AnneHappy/ai_boomer_2.sp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,27 @@ public Plugin myinfo =
name = "Ai Boomer 2.0",
author = "夜羽真白",
description = "Ai Boomer 增强 2.0 版本",
version = "2.0.0.0",
version = "2022-12-31",
url = "https://steamcommunity.com/id/saku_ra/"
}

ConVar g_hAllowBhop, g_hBhopSpeed, g_hUpVision, g_hTurnVision, g_hForceBile, g_hBileFindRange, g_hVomitRange, g_hVomitDuration, g_hVomitInterval, g_hTurnInterval;
ConVar
g_hAllowBhop,
g_hBhopSpeed,
g_hUpVision,
g_hTurnVision,
g_hForceBile,
g_hBileFindRange,
g_hVomitRange,
g_hVomitDuration,
g_hVomitInterval,
g_hTurnInterval,
g_hAllowInDegreeForceBile;
// Bools
bool can_bile[MAXPLAYERS + 1] = { true }, in_bile_interval[MAXPLAYERS + 1] = { false };
bool
can_bile[MAXPLAYERS + 1] = { true },
in_bile_interval[MAXPLAYERS + 1] = { false },
isInBileState[MAXPLAYERS + 1] = { false };
// Ints,bile_frame 0 位:当前目标索引,1 位:循环次数
int bile_frame[MAXPLAYERS + 1][2];
// Handles
Expand All @@ -48,14 +62,17 @@ public void OnPluginStart()
g_hUpVision = CreateConVar("ai_BoomerUpVision", "1", "Boomer 喷吐时是否上抬视角", CVAR_FLAG, true, 0.0, true, 1.0);
g_hTurnVision = CreateConVar("ai_BoomerTurnVision", "1", "Boomer 喷吐时是否旋转视角", CVAR_FLAG, true, 0.0, true, 1.0);
g_hForceBile = CreateConVar("ai_BoomerForceBile", "0", "是否开启生还者到 Boomer 喷吐范围内强制被喷", CVAR_FLAG, true, 0.0, true, 1.0);
g_hBileFindRange = CreateConVar("ai_BoomerBileFindRange", "300", "在这个距离内有被控或倒地的生还 Boomer 会优先攻击,0 = 关闭此功能", CVAR_FLAG, true, 0.0);
g_hBileFindRange = CreateConVar("ai_BoomerBileFindRange", "300", "在这个距离内有被控或倒地的生还 Boomer 会优先攻击,0 = 禁用", CVAR_FLAG, true, 0.0);
g_hTurnInterval = CreateConVar("ai_BoomerTurnInterval", "5", "Boomer 喷吐旋转视角时每隔多少帧转移一个目标", CVAR_FLAG, true, 0.0);
// 在角度内是否允许强制喷吐
g_hAllowInDegreeForceBile = CreateConVar("ai_BoomerDegreeForceBile", "10", "是否允许目标和 Boomer 视角处在这个角度内且能看到目标头部强制喷吐,0 = 禁用", CVAR_FLAG, true, 0.0);
g_hVomitRange = FindConVar("z_vomit_range");
g_hVomitDuration = FindConVar("z_vomit_duration");
g_hVomitInterval = FindConVar("z_vomit_interval");
// HookEvents
HookEvent("player_spawn", evt_PlayerSpawn);
HookEvent("player_shoved", evt_PlayerShoved);
HookEvent("player_now_it", evt_PlayerNowIt);
// SetConVars
SetConVarFloat(FindConVar("boomer_exposed_time_tolerance"), 10000.0);
SetConVarFloat(FindConVar("boomer_vomit_delay"), 0.1);
Expand Down Expand Up @@ -90,44 +107,77 @@ public void evt_PlayerSpawn(Event event, const char[] name, bool dontBroadcast)
else { targetList[client] = new ArrayList(2); }
}
}
public void evt_PlayerNowIt(Event event, const char[] name, bool dontBroadcast)
{
int attacker = GetClientOfUserId(event.GetInt("attacker")), victim = GetClientOfUserId(event.GetInt("userid"));
if (!IsBoomer(attacker) || !IsPlayerAlive(attacker) || !IsValidSurvivor(victim) || !IsPlayerAlive(victim)) { return; }
CreateTimer(FindConVar("sb_vomit_blind_time").FloatValue, resetBileStateHandler, victim);
}
public Action resetBileStateHandler(Handle timer, int client)
{
isInBileState[client] = false;
return Plugin_Continue;
}

public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3])
{
if (IsBoomer(client))
{
float self_pos[3] = {0.0}, self_eye_pos[3] = {0.0}, targetPos[3] = {0.0}, target_eye_pos[3] = {0.0}, vec_speed[3] = {0.0}, cur_speed = 0.0;
int target = GetClientAimTarget(client, true), closet_survivor_dist = GetClosetSurvivorDistance(client);
bool has_sight = view_as<bool>(GetEntProp(client, Prop_Send, "m_hasVisibleThreats"));
static float self_pos[3], self_eye_pos[3], targetPos[3], target_eye_pos[3], vec_speed[3], aim_angles[3], vel_buffer[3], cur_speed, dist, height;
static int target, closet_survivor_dist, ability, isAbilityUsing, i;
static bool has_sight;
target = GetClosetSurvivor(client);
closet_survivor_dist = GetClosetSurvivorDistance(client);
ability = GetEntPropEnt(client, Prop_Send, "m_customAbility");
if (!IsValidEntity(ability)) { return Plugin_Continue; }
has_sight = view_as<bool>(GetEntProp(client, Prop_Send, "m_hasVisibleThreats"));
isAbilityUsing = GetEntProp(ability, Prop_Send, "m_isSpraying");
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vec_speed);
cur_speed = SquareRoot(Pow(vec_speed[0], 2.0) + Pow(vec_speed[1], 2.0));
GetClientAbsOrigin(client, self_pos);
GetEntPropVector(target, Prop_Send, "m_vecOrigin", targetPos);
GetClientEyePosition(client, self_eye_pos);
if (has_sight && IsValidSurvivor(target) && !in_bile_interval[client] && targetList[client].Length < 1)
{
float aim_angles[3] = {0.0}, dist = GetVectorDistance(self_pos, targetPos), height = self_pos[2] - targetPos[2];
ComputeAimAngles(client, target, aim_angles, AimEye);
if (g_hUpVision.BoolValue)
dist = GetVectorDistance(self_pos, targetPos), height = self_pos[2] - targetPos[2];
if (dist <= g_hVomitRange.FloatValue + 100.0)
{
if (height == 0.0 || height < 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 4.3); }
else if (height > 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 5); }
ComputeAimAngles(client, target, aim_angles, AimEye);
if (g_hUpVision.BoolValue)
{
if (height == 0.0 || height < 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 0.8); }
else if (height > 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 1.5); }
}
TeleportEntity(client, NULL_VECTOR, aim_angles, NULL_VECTOR);
// 第一个目标是否强行被喷
if (g_hAllowInDegreeForceBile.BoolValue && isInAimOffset(client, target, g_hAllowInDegreeForceBile.FloatValue) && !isInBileState[target] && isAbilityUsing)
{
L4D_CTerrorPlayer_OnVomitedUpon(target, client);
isInBileState[target] = true;
}
}
TeleportEntity(client, NULL_VECTOR, aim_angles, NULL_VECTOR);
}
if (targetList[client].Length >= 1 && !in_bile_interval[client] && g_hTurnVision.BoolValue)
{
if (bile_frame[client][0] < targetList[client].Length && bile_frame[client][1] < g_hTurnInterval.IntValue)
{
float aimAngles[3] = {0.0}, dist = GetVectorDistance(self_pos, targetPos), height = 0.0;
int turnTarget = targetList[client].Get(bile_frame[client][0], 1);
height = self_pos[2] - targetPos[2];
ComputeAimAngles(client, turnTarget, aimAngles, AimEye);
dist = GetVectorDistance(self_pos, targetPos), height = self_pos[2] - targetPos[2];
static int turnTarget;
turnTarget = targetList[client].Get(bile_frame[client][0], 1);
ComputeAimAngles(client, turnTarget, aim_angles, AimEye);
if (g_hUpVision.BoolValue)
{
if (height == 0.0 || height < 0.0) { aimAngles[0] -= dist / (PLAYER_HEIGHT * 4.3); }
else if (height > 0.0) { aimAngles[0] -= dist / (PLAYER_HEIGHT * 5); }
if (height == 0.0 || height < 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 0.8); }
else if (height > 0.0) { aim_angles[0] -= dist / (PLAYER_HEIGHT * 1.5); }
}
TeleportEntity(client, NULL_VECTOR, aimAngles, NULL_VECTOR);
TeleportEntity(client, NULL_VECTOR, aim_angles, NULL_VECTOR);
bile_frame[client][1] += 1;
// 其他在范围内的目标是否强行被喷
if (g_hAllowInDegreeForceBile.BoolValue && isInAimOffset(client, turnTarget, g_hAllowInDegreeForceBile.FloatValue) && !isInBileState[turnTarget] && isAbilityUsing)
{
L4D_CTerrorPlayer_OnVomitedUpon(turnTarget, client);
isInBileState[turnTarget] = true;
}
}
else if (bile_frame[client][0] >= targetList[client].Length)
{
Expand Down Expand Up @@ -158,29 +208,29 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
if (g_hForceBile.BoolValue && (buttons & IN_ATTACK) && !in_bile_interval[client] && IsValidSurvivor(target))
{
in_bile_interval[client] = true;
for (int i = 1; i <= MaxClients; i++)
for (i = 1; i <= MaxClients; i++)
{
if (IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == view_as<int>(TEAM_SURVIVOR) && IsPlayerAlive(i))
if (!IsClientInGame(i) || GetClientTeam(i) != TEAM_SURVIVOR || !IsPlayerAlive(i)) { continue; }
GetClientEyePosition(i, target_eye_pos);
Handle trace = TR_TraceRayFilterEx(self_eye_pos, target_eye_pos, MASK_VISIBLE, RayType_EndPoint, TR_RayFilter, client);
if (TR_DidHit(trace) || TR_GetEntityIndex(trace) != i)
{
GetClientEyePosition(i, target_eye_pos);
Handle hTrace = TR_TraceRayFilterEx(self_eye_pos, target_eye_pos, MASK_VISIBLE, RayType_EndPoint, TR_RayFilter, client);
if (!TR_DidHit(hTrace) || TR_GetEntityIndex(hTrace) == i)
{
if (GetVectorDistance(self_eye_pos, target_eye_pos) <= g_hVomitRange.FloatValue)
{
L4D_CTerrorPlayer_OnVomitedUpon(i, client);
}
}
delete hTrace;
delete trace;
continue;
}
if (!(GetVectorDistance(self_eye_pos, target_eye_pos) <= g_hVomitRange.FloatValue))
{
delete trace;
continue;
}
delete trace;
L4D_CTerrorPlayer_OnVomitedUpon(i, client);
}
CreateTimer(g_hVomitInterval.FloatValue, Timer_ResetAbility, client);
}
// 连跳
if (g_hAllowBhop.BoolValue && has_sight && IsGrounded(client) && 0.5 * g_hVomitRange.FloatValue < closet_survivor_dist < 10000.0 && cur_speed > 160.0 && IsValidSurvivor(target))
{
float vel_buffer[3] = {0.0};
GetClientAbsOrigin(target, targetPos);
vel_buffer = CalculateVel(self_pos, targetPos, g_hBhopSpeed.FloatValue);
buttons |= IN_JUMP;
buttons |= IN_DUCK;
Expand All @@ -199,11 +249,6 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
return Plugin_Continue;
}

//是否在地面
bool IsGrounded(int client) {
return GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1;
}

// 重置胖子能力使用限制
public Action Timer_ResetAbility(Handle timer, int client)
{
Expand Down Expand Up @@ -274,29 +319,16 @@ public Action L4D_OnVomitedUpon(int victim, int &attacker, bool &boomerExplosion
if (i != victim && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVOR && IsPlayerAlive(i))
{
GetClientEyePosition(i, targetEyePos);
eyePos[2] = targetEyePos[2] = 0.0;
dist = GetVectorDistance(eyePos, targetEyePos);
if (dist <= g_hVomitRange.FloatValue + 100.0)
{
Handle trace = TR_TraceRayFilterEx(eyePos, targetEyePos, MASK_VISIBLE, RayType_EndPoint, TR_RayFilter, attacker);
if (!TR_DidHit(trace) || TR_GetEntityIndex(trace) == i)
{
int index = targetList[attacker].Push(dist);
targetList[attacker].Set(index, i, 1);
}
if (!TR_DidHit(trace) || TR_GetEntityIndex(trace) == i) { targetList[attacker].Set(targetList[attacker].Push(dist), i, 1); }
delete trace;
}
}
}
if (targetList[attacker].Length > 1)
{
targetList[attacker].Sort(Sort_Ascending, Sort_Float);
}
/* PrintToConsoleAll("输出 boomer 目标数组");
for (int i = 0; i < targetList[attacker].Length; i++)
{
PrintToConsoleAll("第:%d 个,%d - %N,距离:%.2f", i + 1, targetList[attacker].Get(i, 1), targetList[attacker].Get(i, 1), targetList[attacker].Get(i, 0));
} */
if (targetList[attacker].Length > 1) { targetList[attacker].Sort(Sort_Ascending, Sort_Float); }
}
return Plugin_Continue;
}
Expand Down Expand Up @@ -442,3 +474,21 @@ void ComputeAimAngles(int client, int target, float angles[3], AimType type = Ai
MakeVectorFromPoints(selfpos, targetpos, lookat);
GetVectorAngles(lookat, angles);
}

static bool isInAimOffset(int attacker, int target, float offset)
{
if (!IsBoomer(attacker) || !IsPlayerAlive(attacker) || !IsValidSurvivor(target) || !IsPlayerAlive(target)) { return false; }
static float selfEyePos[3], targetEyePos[3], resultPos[3], selfEyeVector[3];
// 和目标的方向向量
GetClientEyePosition(attacker, selfEyePos);
GetClientEyePosition(target, targetEyePos);
MakeVectorFromPoints(selfEyePos, targetEyePos, resultPos);
NormalizeVector(resultPos, resultPos);
resultPos[2] = 0.0;
// 自己眼睛看的方向向量
GetClientEyeAngles(attacker, selfEyePos);
GetAngleVectors(selfEyePos, selfEyeVector, NULL_VECTOR, NULL_VECTOR);
NormalizeVector(selfEyeVector, selfEyeVector);
selfEyeVector[2] = 0.0;
return RadToDeg(ArcCosine(GetVectorDotProduct(resultPos, selfEyeVector))) <= offset;
}
4 changes: 0 additions & 4 deletions addons/sourcemod/scripting/AnneHappy/ai_charger_2.sp
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,4 @@ float Get_Player_Aim_Offset(int client, int target)
return result_angle;
}
return -1.0;
}
//是否在地上
bool IsGrounded(int client) {
return GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1;
}
13 changes: 6 additions & 7 deletions addons/sourcemod/scripting/AnneHappy/ai_jockey_2.sp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void OnPluginStart()
g_hJockeyLeapTime = FindConVar("z_jockey_leap_time");
// HookEvent
HookEvent("player_spawn", evt_PlayerSpawn, EventHookMode_Pre);
HookEvent("player_shoved", evt_PlayerShoved, EventHookMode_Pre);
HookEvent("player_shoved", evt_PlayerShoved);
HookEvent("jockey_ride", evt_JockeyRide);
// AddChangeHook
g_hActionChance.AddChangeHook(GetActionPercent_Cvars);
Expand Down Expand Up @@ -181,8 +181,11 @@ public Action OnPlayerRunCmd(int jockey, int &buttons, int &impulse, float vel[3
&& actionPercent <= g_iActionArray[ACTION_JUMP_HIGH])
{
// 高跳
angles[0] = getRandomFloatInRange(25.0, 40.0) * -1.0;
TeleportEntity(jockey, NULL_VECTOR, angles, NULL_VECTOR);
float subtractVec[3] = {0.0};
angles[0] = getRandomFloatInRange(20.0, 35.0) * -1.0;
NormalizeVector(vel, subtractVec);
ScaleVector(subtractVec, g_hBhopSpeed.FloatValue * 3.0);
TeleportEntity(jockey, NULL_VECTOR, angles, subtractVec);
buttons |= IN_ATTACK;
SetState(jockey, 0, IN_ATTACK);
#if DEBUG_ALL
Expand Down Expand Up @@ -264,10 +267,6 @@ public Action OnPlayerRunCmd(int jockey, int &buttons, int &impulse, float vel[3
return Plugin_Continue;
}

bool IsGrounded(int client) {
return GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1;
}

public Action L4D2_OnChooseVictim(int specialInfected, int &curTarget)
{
if (!IsAiJockey(specialInfected) || !IsPlayerAlive(specialInfected)) { return Plugin_Continue; }
Expand Down
Loading

0 comments on commit 5d1d960

Please sign in to comment.