mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-06 03:33:21 +00:00
Update some plugins to sm1.11
This commit is contained in:
parent
6426e525db
commit
0907cc7735
6 changed files with 236 additions and 153 deletions
Binary file not shown.
Binary file not shown.
|
@ -3,14 +3,6 @@
|
|||
#endif
|
||||
#define l4d2_weapons_inc_
|
||||
|
||||
#define GETWEAPONNAME(%0) (IsValidWeaponId(WeaponId (%0)) ? (WeaponNames[(%0)]) : "")
|
||||
#define GETLONGWEAPONNAME(%0) (IsValidWeaponId(WeaponId (%0)) ? (LongWeaponNames[(%0)]) : "")
|
||||
#define GETMELEEWEAPONNAME(%0) (IsValidWeaponId(MeleeWeaponId (%0)) ? (MeleeWeaponNames[(%0)]) : "")
|
||||
#define GETLONGMELEEWEAPONNAME(%0) (IsValidWeaponId(MeleeWeaponId (%0)) ? (LongMeleeWeaponNames[(%0)]) : "")
|
||||
#define GETWEAPONMODEL(%0) (HasValidWeaponModel(WeaponId (%0)) ? (WeaponModels[(%0)]) : "")
|
||||
#define GETMELEEWEAPONMODEL(%0) (HasValidWeaponModel(MeleeWeaponId (%0)) ? (MeleeWeaponModels[(%0)]) : "")
|
||||
|
||||
|
||||
// Weapon ID enumerations.
|
||||
// These values are *NOT* arbitrary!
|
||||
// They are used in game as the weaponid for weapon_spawn entities
|
||||
|
@ -69,7 +61,8 @@ enum WeaponId {
|
|||
WEPID_ROCK, // 52
|
||||
WEPID_PHYSICS, // 53
|
||||
WEPID_AMMO, // 54
|
||||
WEPID_UPGRADE_ITEM // 55
|
||||
WEPID_UPGRADE_ITEM, // 55
|
||||
WEPID_COUNT
|
||||
};
|
||||
|
||||
// These values are arbitrary
|
||||
|
@ -89,7 +82,8 @@ enum MeleeWeaponId
|
|||
WEPID_KATANA,
|
||||
WEPID_MACHETE,
|
||||
WEPID_RIOT_SHIELD,
|
||||
WEPID_TONFA
|
||||
WEPID_TONFA,
|
||||
WEPID_MELEE_COUNT
|
||||
};
|
||||
|
||||
// Weapon names for each of the weapons, used in identification.
|
||||
|
@ -139,7 +133,7 @@ char LongWeaponNames[56][] = {
|
|||
};
|
||||
|
||||
// Internal names for melee weapons
|
||||
char MeleeWeaponNames[MeleeWeaponId][] =
|
||||
char MeleeWeaponNames[WEPID_MELEE_COUNT][] =
|
||||
{
|
||||
"",
|
||||
"knife",
|
||||
|
@ -159,7 +153,7 @@ char MeleeWeaponNames[MeleeWeaponId][] =
|
|||
};
|
||||
|
||||
// Long melee weapon names
|
||||
char LongMeleeWeaponNames[MeleeWeaponId][] =
|
||||
char LongMeleeWeaponNames[WEPID_MELEE_COUNT][] =
|
||||
{
|
||||
"None",
|
||||
"Knife",
|
||||
|
@ -332,13 +326,13 @@ static Handle hMeleeWeaponModelsTrie = INVALID_HANDLE;
|
|||
|
||||
stock void InitWeaponNamesTrie() {
|
||||
hWeaponNamesTrie = CreateTrie();
|
||||
for(int i = 0; i < view_as<int>(WeaponId); i++) {
|
||||
for(int i = 0; i < view_as<int>(WEPID_COUNT); i++) {
|
||||
SetTrieValue(hWeaponNamesTrie, WeaponNames[i], i);
|
||||
}
|
||||
|
||||
hMeleeWeaponNamesTrie = CreateTrie();
|
||||
hMeleeWeaponModelsTrie = CreateTrie();
|
||||
for (int i = 0; i < view_as<int>(MeleeWeaponId); ++i)
|
||||
for (int i = 0; i < view_as<int>(WEPID_MELEE_COUNT); ++i)
|
||||
{
|
||||
SetTrieValue(hMeleeWeaponNamesTrie, MeleeWeaponNames[i], i);
|
||||
SetTrieString(hMeleeWeaponModelsTrie, MeleeWeaponModels[i], MeleeWeaponNames[i]);
|
||||
|
@ -357,7 +351,7 @@ stock bool IsValidWeaponId(WeaponId wepid){
|
|||
}
|
||||
|
||||
stock bool IsValidMeleeWeaponId(MeleeWeaponId wepid) {
|
||||
return MeleeWeaponId:wepid >= WEPID_MELEE_NONE && MeleeWeaponId:wepid < MeleeWeaponId;
|
||||
return wepid >= WEPID_MELEE_NONE && wepid < WEPID_MELEE_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -382,9 +376,7 @@ stock bool HasValidWeaponModel(WeaponId wepid) {
|
|||
}
|
||||
|
||||
stock bool HasValidMeleeWeaponModel(MeleeWeaponId wepid) {
|
||||
if (tagType == tagof(MeleeWeaponId)) {
|
||||
return IsValidWeaponId(MeleeWeaponId:wepid) && MeleeWeaponModels[MeleeWeaponId:wepid][0] != '\0';
|
||||
}
|
||||
return IsValidMeleeWeaponId(wepid) && MeleeWeaponModels[wepid][0] != '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -429,11 +421,13 @@ stock int GetMeleeWeaponName(WeaponId wepid, char[] nameBuffer, int length) {
|
|||
* @return Number of bytes written to buffer, or 0 for invalid weaponId.
|
||||
*/
|
||||
stock int GetLongWeaponName(WeaponId wepid, char[] nameBuffer, int length) {
|
||||
strcopy(nameBuffer, length, GETLONGMELEEWEAPONNAME(wepid));
|
||||
if(!IsValidWeaponId(wepid)) return 0;
|
||||
return strcopy(nameBuffer, length, LongWeaponNames[wepid]);
|
||||
}
|
||||
|
||||
stock int GetLongMeleeWeaponName(WeaponId wepid, char[] nameBuffer, int length) {
|
||||
strcopy(nameBuffer, length, GETLONGWEAPONNAME(wepid));
|
||||
stock int GetLongMeleeWeaponName(MeleeWeaponId wepid, char[] nameBuffer, int length) {
|
||||
if(!IsValidMeleeWeaponId(wepid)) return 0;
|
||||
return strcopy(nameBuffer, length, LongMeleeWeaponNames[wepid]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -445,12 +439,14 @@ stock int GetLongMeleeWeaponName(WeaponId wepid, char[] nameBuffer, int length)
|
|||
* @param length Max length which can be written to the buffer.
|
||||
* @return Number of bytes written to buffer, or 0 for invalid weaponid or no weapon model available.
|
||||
*/
|
||||
stock int GetWeaponModel(MeleeWeaponId wepid, char[] modelBuffer, int length) {
|
||||
strcopy(modelBuffer, length, GETWEAPONMODEL(wepid));
|
||||
stock int GetWeaponModel(WeaponId wepid, char[] modelBuffer, int length) {
|
||||
if(!HasValidWeaponModel(wepid)) return 0;
|
||||
return strcopy(modelBuffer, length, WeaponModels[wepid]);
|
||||
}
|
||||
|
||||
stock int GetMeleeWeaponModel(MeleeWeaponId wepid, char[] modelBuffer, int length) {
|
||||
strcopy(modelBuffer, length, GETMELEEWEAPONMODEL(wepid));
|
||||
if(!HasValidMeleeWeaponModel(wepid)) return 0;
|
||||
return strcopy(modelBuffer, length, MeleeWeaponModels[wepid]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -533,7 +529,7 @@ stock MeleeWeaponId IdentifyMeleeWeapon(int entity) {
|
|||
|
||||
int id;
|
||||
if(GetTrieValue(hMeleeWeaponNamesTrie, sName, id)) {
|
||||
return id;
|
||||
return view_as<MeleeWeaponId>(id);
|
||||
}
|
||||
return WEPID_MELEE_NONE;
|
||||
}
|
||||
|
@ -549,14 +545,14 @@ stock MeleeWeaponId IdentifyMeleeWeapon(int entity) {
|
|||
* @param model World model to use for the weapon spawn
|
||||
* @return entity of the new weapon spawn, or -1 on errors.
|
||||
*/
|
||||
stock int ConvertWeaponSpawn(int entity, WeaponId wepid, int count = 5, const char model[] = "")
|
||||
stock int ConvertWeaponSpawn(int entity, WeaponId wepid, int count = 5, const char[] model = "")
|
||||
{
|
||||
if(!IsValidEntity(entity)) return -1;
|
||||
if(!IsValidWeaponId(wepid)) return -1;
|
||||
if(model[0] == '\0' && !HasValidWeaponModel(wepid)) return -1;
|
||||
|
||||
|
||||
new Float:origins[3], Float:angles[3];
|
||||
float origins[3], angles[3];
|
||||
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origins);
|
||||
GetEntPropVector(entity, Prop_Send, "m_angRotation", angles);
|
||||
|
||||
|
@ -567,7 +563,7 @@ stock int ConvertWeaponSpawn(int entity, WeaponId wepid, int count = 5, const ch
|
|||
|
||||
SetEntProp(entity, Prop_Send, "m_weaponID", wepid);
|
||||
|
||||
decl String:buf[64];
|
||||
char buf[64];
|
||||
if(model[0] == '\0') {
|
||||
SetEntityModel(entity, model);
|
||||
} else {
|
||||
|
|
|
@ -661,7 +661,7 @@ stock int L4D_GetPendingTankPlayer()
|
|||
* @return True if glow was set, false if entity does not support glow.
|
||||
*/
|
||||
// L4D2 only.
|
||||
stock bool L4D2_SetEntityGlow(int entity, L4D2GlowType type, int range, int minRange, colorOverride[3], bool flashing)
|
||||
stock bool L4D2_SetEntityGlow(int entity, L4D2GlowType type, int range, int minRange, int colorOverride[3], bool flashing)
|
||||
{
|
||||
if (!IsValidEntity(entity))
|
||||
{
|
||||
|
|
|
@ -463,15 +463,18 @@ public Action Timer_SpawnFinaleTank(Handle t, int user) {
|
|||
ServerCommand("sm_forcespecial tank");
|
||||
finaleStage = Stage_Inactive;
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
public Action Timer_SpawnSplitTank(Handle t, int user) {
|
||||
ServerCommand("sm_forcespecial tank");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
public Action Timer_SetHealth(Handle h, int user) {
|
||||
int client = GetClientOfUserId(user);
|
||||
if(client > 0 ) {
|
||||
SetEntProp(client, Prop_Send, "m_iHealth", extraTankHP);
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void Frame_SetExtraTankHealth(int user) {
|
||||
|
@ -591,6 +594,7 @@ public Action Timer_CheckInventory(Handle h, int client) {
|
|||
PrintToConsoleAll("[EPI] Detected mismatch inventory for %N, restoring", client);
|
||||
RestoreInventory(client);
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast) {
|
||||
|
@ -626,6 +630,7 @@ public Action Timer_DropSurvivor(Handle h, int client) {
|
|||
}
|
||||
DropDroppedInventories();
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/*public Action Timer_DropSurvivor(Handle h, DataPack pack) {
|
||||
|
@ -725,8 +730,10 @@ public void Frame_SetupNewClient(int client) {
|
|||
if(tier2Weapons.Length > 0) {
|
||||
tier2Weapons.GetString(GetRandomInt(0, tier2Weapons.Length), weaponName, sizeof(weaponName));
|
||||
Format(weaponName, sizeof(weaponName), "weapon_%s", weaponName);
|
||||
PrintToServer("[EPI/debug] Giving new client (%N) tier 2: %s", client, weaponName);
|
||||
} else {
|
||||
Format(weaponName, sizeof(weaponName), "weapon_%s", TIER1_WEAPONS[GetRandomInt(0, TIER1_WEAPON_COUNT)]);
|
||||
PrintToServer("[EPI/debug] Giving new client (%N) tier 1: %s", client, weaponName);
|
||||
}
|
||||
int item = GivePlayerItem(client, weaponName);
|
||||
if(lowestClient > 0) {
|
||||
|
@ -744,6 +751,7 @@ public void Frame_SetupNewClient(int client) {
|
|||
}
|
||||
public Action Timer_RemoveInvincibility(Handle h, int client) {
|
||||
SDKUnhook(client, SDKHook_OnTakeDamage, OnInvincibleDamageTaken);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
public Action OnInvincibleDamageTaken(int victim, int& attacker, int& inflictor, float& damage, int& damagetype, int& weapon, float damageForce[3], float damagePosition[3]) {
|
||||
damage = 0.0;
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
#define DEBUG
|
||||
#define DEBUG_SHOW_POINTS
|
||||
#define DEBUG_BOT_MOVE
|
||||
#define DEBUG_BLOCKERS
|
||||
// #define DEBUG_MOVE_ATTEMPTS
|
||||
// #define DEBUG_SEEKER_PATH_CREATION 1
|
||||
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
|
||||
#define BOT_MOVE_RANDOM_MIN_TIME 6.0 // The minimum random time for Timer_BotMove to activate (set per bot, per round)
|
||||
#define BOT_MOVE_RANDOM_MAX_TIME 8.6 // The maximum random time for Timer_BotMove to activate (set per bot, per round)
|
||||
#define BOT_MOVE_RANDOM_MIN_TIME 2.0 // The minimum random time for Timer_BotMove to activate (set per bot, per round)
|
||||
#define BOT_MOVE_RANDOM_MAX_TIME 3.0 // The maximum random time for Timer_BotMove to activate (set per bot, per round)
|
||||
#define BOT_MOVE_CHANCE 0.96 // The chance the bot will move each Timer_BotMove
|
||||
#define BOT_MOVE_AVOID_FLOW_DIST 12.0 // The flow range of flow distance that triggers avoid
|
||||
#define BOT_MOVE_AVOID_SEEKER_CHANCE 0.50 // The chance that if the bot gets too close to the seeker, it runs away
|
||||
|
@ -18,10 +20,17 @@
|
|||
#define BOT_MOVE_JUMP_CHANCE 0.001
|
||||
#define BOT_MOVE_SHOVE_CHANCE 0.0015
|
||||
#define BOT_MOVE_RUN_CHANCE 0.15
|
||||
#define BOT_MOVE_NOT_REACHED_DISTANCE 60.0 // The distance that determines if a bot reached a point
|
||||
#define BOT_MOVE_NOT_REACHED_ATTEMPT_RUNJUMP 6 // The minimum amount of attempts where bot will run or jump to dest
|
||||
#define BOT_MOVE_NOT_REACHED_ATTEMPT_RETRY 9 // The minimum amount of attempts where bot gives up and picks new
|
||||
#define DOOR_TOGGLE_INTERVAL 5.0 // Interval that loops throuh all doors to randomly toggle
|
||||
#define DOOR_TOGGLE_CHANCE 0.01 // Chance that every Timer_DoorToggles triggers a door to toggle state
|
||||
#define HIDER_SWAP_COOLDOWN 30.0 // Amount of seconds until they can swap
|
||||
#define HIDER_SWAP_LIMIT 3 // Amount of times a hider can swap per round
|
||||
#define FLOW_BOUND_BUFFER 200.0 // Amount to add to calculated bounds (Make it very generous)
|
||||
#define HIDER_MIN_AVG_DISTANCE_AUTO_VOCALIZE 300.0 // The average minimum distance a hider is from the player that triggers auto vocalizating
|
||||
#define HIDER_AUTO_VOCALIZE_GRACE_TIME 20.0 // Number of seconds between auto vocalizations
|
||||
#define DEFAULT_MAP_TIME 480
|
||||
|
||||
#if defined DEBUG
|
||||
#define SEED_TIME 1.0
|
||||
|
@ -39,6 +48,8 @@
|
|||
|
||||
float DEBUG_POINT_VIEW_MIN[3] = { -5.0, -5.0, 0.0 };
|
||||
float DEBUG_POINT_VIEW_MAX[3] = { 5.0, 5.0, 2.0 };
|
||||
int SEEKER_GLOW_COLOR[3] = { 128, 0, 0 };
|
||||
int PLAYER_GLOW_COLOR[3] = { 0, 255, 0 };
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
|
@ -49,20 +60,22 @@ float DEBUG_POINT_VIEW_MAX[3] = { 5.0, 5.0, 2.0 };
|
|||
#include <multicolors>
|
||||
|
||||
char SURVIVOR_MODELS[8][] = {
|
||||
"models/survivors/survivor_gambler.mdl",
|
||||
"models/survivors/survivor_producer.mdl",
|
||||
"models/survivors/survivor_coach.mdl",
|
||||
"models/survivors/survivor_mechanic.mdl",
|
||||
"models/survivors/survivor_namvet.mdl",
|
||||
"models/survivors/survivor_teenangst.mdl",
|
||||
"models/survivors/survivor_biker.mdl",
|
||||
"models/survivors/survivor_manager.mdl"
|
||||
"models/survivors/survivor_manager.mdl",
|
||||
"models/survivors/survivor_gambler.mdl",
|
||||
"models/survivors/survivor_producer.mdl",
|
||||
"models/survivors/survivor_coach.mdl",
|
||||
"models/survivors/survivor_mechanic.mdl"
|
||||
};
|
||||
|
||||
enum struct LocationMeta {
|
||||
float pos[3];
|
||||
float ang[3];
|
||||
bool runto;
|
||||
bool jump;
|
||||
int attempts; // # of attempts player has moved until they will try to manage
|
||||
}
|
||||
|
||||
// Game settings
|
||||
|
@ -82,10 +95,14 @@ int currentSeeker;
|
|||
bool hasBeenSeeker[MAXPLAYERS+1];
|
||||
bool ignoreSeekerBalance;
|
||||
int hiderSwapTime[MAXPLAYERS+1];
|
||||
int hiderSwapCount[MAXPLAYERS+1];
|
||||
bool isStarting;
|
||||
|
||||
// Temp Ent Materials & Timers
|
||||
Handle spawningTimer;
|
||||
Handle hiderCheckTimer;
|
||||
Handle recordTimer;
|
||||
Handle timesUpTimer;
|
||||
Handle acquireLocationsTimer;
|
||||
Handle moveTimers[MAXPLAYERS+1];
|
||||
UserMsg g_FadeUserMsgId;
|
||||
|
@ -99,7 +116,7 @@ ConVar cvar_seekerFailDamageAmount;
|
|||
|
||||
// Bot Movement specifics
|
||||
float flowMin, flowMax;
|
||||
static float seekerPos[3];
|
||||
float seekerPos[3];
|
||||
float seekerFlow = 0.0;
|
||||
|
||||
float vecLastLocation[MAXPLAYERS+1][3];
|
||||
|
@ -166,12 +183,14 @@ public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[
|
|||
HookEvent("round_start", Event_RoundStart);
|
||||
HookEvent("player_death", Event_PlayerDeath);
|
||||
HookEvent("player_bot_replace", Event_PlayerToBot);
|
||||
HookEvent("player_ledge_grab", Event_LedgeGrab);
|
||||
AddCommandListener(OnGoAwayFromKeyboard, "go_away_from_keyboard");
|
||||
} else if(!lateLoaded) {
|
||||
UnsetCvars();
|
||||
UnhookEvent("round_start", Event_RoundStart);
|
||||
UnhookEvent("player_death", Event_PlayerDeath);
|
||||
UnhookEvent("player_bot_replace", Event_PlayerToBot);
|
||||
UnhookEvent("player_ledge_grab", Event_LedgeGrab);
|
||||
Cleanup();
|
||||
PrintToChatAll("[GuessWho] Gamemode unloaded but cvars have not been reset.");
|
||||
RemoveCommandListener(OnGoAwayFromKeyboard, "go_away_from_keyboard");
|
||||
|
@ -183,6 +202,13 @@ public Action OnGoAwayFromKeyboard(int client, const char[] command, int argc) {
|
|||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
void Event_LedgeGrab(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0) {
|
||||
L4D_ReviveSurvivor(client);
|
||||
}
|
||||
}
|
||||
|
||||
void Event_PlayerToBot(Event event, const char[] name, bool dontBroadcast) {
|
||||
int player = GetClientOfUserId(event.GetInt("player"));
|
||||
int bot = GetClientOfUserId(event.GetInt("bot"));
|
||||
|
@ -197,8 +223,6 @@ void Event_PlayerToBot(Event event, const char[] name, bool dontBroadcast) {
|
|||
}
|
||||
}
|
||||
|
||||
int SEEKER_GLOW_COLOR[3] = { 128, 0, 0 };
|
||||
int PLAYER_GLOW_COLOR[3] = { 0, 255, 0 };
|
||||
|
||||
void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
|
@ -207,19 +231,7 @@ void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
|||
if(client == currentSeeker) {
|
||||
PrintToChatAll("The seeker, %N, has died. Hiders win!", currentSeeker);
|
||||
SetState(State_HidersWin);
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && IsFakeClient(i)) {
|
||||
if(IsFakeClient(i)) {
|
||||
ClearInventory(i);
|
||||
PrintToServer("PlayerDeath: Seeker kill %d", i);
|
||||
KickClient(i);
|
||||
} else {
|
||||
L4D2_SetEntityGlow(i, L4D2Glow_Constant, 0, 20, PLAYER_GLOW_COLOR, false);
|
||||
L4D2_SetPlayerSurvivorGlowState(i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
CreateTimer(5.0, Timer_ResetAll);
|
||||
EndGame(State_HidersWin);
|
||||
} else if(!IsFakeClient(client)) {
|
||||
if(attacker == currentSeeker) {
|
||||
PrintToChatAll("%N was killed", client);
|
||||
|
@ -235,46 +247,13 @@ void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
|||
if(GetPlayersLeftAlive() == 0) {
|
||||
if(GetState() == State_Active) {
|
||||
PrintToChatAll("Everyone has died. %N wins!", currentSeeker);
|
||||
CreateTimer(5.0, Timer_ResetAll);
|
||||
SetState(State_SeekerWon);
|
||||
EndGame(State_SeekerWon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Action Timer_ResetAll(Handle h) {
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
|
||||
ForcePlayerSuicide(i);
|
||||
}
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
bool isStarting;
|
||||
|
||||
void StartGame() {
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i)) {
|
||||
if(isPendingPlay[i]) {
|
||||
ChangeClientTeam(i, 2);
|
||||
} else if(IsFakeClient(i)) {
|
||||
KickClient(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!isStarting) {
|
||||
isStarting = true;
|
||||
CreateTimer(5.0, Timer_Start);
|
||||
}
|
||||
}
|
||||
|
||||
void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
|
||||
StartGame();
|
||||
}
|
||||
|
||||
Action Timer_Start(Handle h) {
|
||||
if(isStarting)
|
||||
InitGamemode();
|
||||
return Plugin_Handled;
|
||||
CreateTimer(5.0, Timer_WaitForPlayers, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
public void OnMapStart() {
|
||||
|
@ -324,7 +303,7 @@ public void OnMapStart() {
|
|||
SDKHook(i, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive);
|
||||
}
|
||||
}
|
||||
CreateTimer(0.1, Timer_Start);
|
||||
InitGamemode();
|
||||
}
|
||||
SetState(State_Unknown);
|
||||
}
|
||||
|
@ -356,25 +335,20 @@ public void OnClientPutInServer(int client) {
|
|||
isPendingPlay[client] = true;
|
||||
PrintToChatAll("%N will play next round", client);
|
||||
TeleportToSpawn(client);
|
||||
if(!IsPendingPlayers()) {
|
||||
StartGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnClientDisconnect(int client) {
|
||||
if(!isEnabled) return;
|
||||
if(client == currentSeeker) {
|
||||
if(acquireLocationsTimer != null) delete acquireLocationsTimer;
|
||||
PrintToChatAll("The seeker has disconnected");
|
||||
CreateTimer(1.0, Timer_ResetAll);
|
||||
currentSeeker = 0;
|
||||
EndGame(State_HidersWin);
|
||||
} else if(!IsFakeClient(client) && GetState() == State_Active) {
|
||||
PrintToChatAll("A hider has left (%N)", client);
|
||||
if(GetPlayersLeftAlive() == 0 && GetState() == State_Active) {
|
||||
PrintToChatAll("Game Over. %N wins!", currentSeeker);
|
||||
CreateTimer(5.0, Timer_ResetAll);
|
||||
SetState(State_SeekerWon);
|
||||
EndGame(State_SeekerWon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -423,6 +397,7 @@ void SetCvars(bool record = false) {
|
|||
SetCvarValue(cvar_sbPushScale, 0, record);
|
||||
SetCvarValue(FindConVar("sb_battlestation_give_up_range_from_human"), 5000.0, record);
|
||||
SetCvarValue(FindConVar("sb_max_battlestation_range_from_human"), 5000.0, record);
|
||||
SetCvarValue(FindConVar("sb_enforce_proximity_range"), 10000, record);
|
||||
}
|
||||
|
||||
void UnsetCvars() {
|
||||
|
@ -459,11 +434,17 @@ void InitGamemode() {
|
|||
ArrayList validPlayerIds = new ArrayList();
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
|
||||
if(IsFakeClient(i)) KickClient(i);
|
||||
else {
|
||||
ChangeClientTeam(i, 2);
|
||||
activeBotLocations[i].attempts = 0;
|
||||
if(IsFakeClient(i)) {
|
||||
ClearInventory(i);
|
||||
KickClient(i);
|
||||
} else {
|
||||
if(!IsPlayerAlive(i)) {
|
||||
L4D_RespawnPlayer(i);
|
||||
}
|
||||
hiderSwapCount[i] = 0;
|
||||
distQueue[i].Clear();
|
||||
ChangeClientTeam(i, 2);
|
||||
if(!hasBeenSeeker[i] || ignoreSeekerBalance)
|
||||
validPlayerIds.Push(GetClientUserId(i));
|
||||
|
@ -477,11 +458,12 @@ void InitGamemode() {
|
|||
ignoreSeekerBalance = false;
|
||||
int newSeeker = GetClientOfUserId(validPlayerIds.Get(GetURandomInt() % validPlayerIds.Length));
|
||||
delete validPlayerIds;
|
||||
if(newSeeker > 0) {
|
||||
if(newSeeker > 0) {
|
||||
hasBeenSeeker[newSeeker] = true;
|
||||
PrintToChatAll("%N is the seeker", newSeeker);
|
||||
SetPlayerBlind(newSeeker, 255);
|
||||
SetSeeker(newSeeker);
|
||||
SetPlayerBlind(newSeeker, 255);
|
||||
SetEntPropFloat(newSeeker, Prop_Send, "m_flLaggedMovementValue", 0.0);
|
||||
// L4D2_SetPlayerSurvivorGlowState(newSeeker, true);
|
||||
L4D2_SetEntityGlow(newSeeker, L4D2Glow_Constant, 0, 10, SEEKER_GLOW_COLOR, false);
|
||||
}
|
||||
|
@ -513,13 +495,24 @@ Action Timer_SpawnPost(Handle h) {
|
|||
PrintToChatAll("Timer_SpawnPost(): activating");
|
||||
bool isL4D1 = L4D2_GetSurvivorSetMap() == 1;
|
||||
int remainingSeekers;
|
||||
int survivorMaxIndex = isL4D1 ? 3 : 7;
|
||||
int survivorIndexBot;
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(i != currentSeeker && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
|
||||
if(!IsFakeClient(i)) {
|
||||
int survivor;
|
||||
if(IsFakeClient(i)) {
|
||||
// Set bot models uniformly
|
||||
survivor = survivorIndexBot;
|
||||
if(++survivorIndexBot > survivorMaxIndex) {
|
||||
survivorIndexBot = 0;
|
||||
}
|
||||
} else {
|
||||
// Set hiders models randomly
|
||||
survivor = GetURandomInt() % survivorMaxIndex;
|
||||
if(!hasBeenSeeker[i]) {
|
||||
remainingSeekers++;
|
||||
}
|
||||
PrintToChat(i, "You can change your model by looking at a player and pressing RELOAD");
|
||||
PrintToChat(i, "You can change your model %d times by looking at a player and pressing RELOAD", HIDER_SWAP_LIMIT);
|
||||
}
|
||||
SDKHook(i, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive);
|
||||
SDKHook(i, SDKHook_WeaponDrop, OnWeaponDrop);
|
||||
|
@ -527,9 +520,10 @@ Action Timer_SpawnPost(Handle h) {
|
|||
ClearInventory(i);
|
||||
int item = GivePlayerItem(i, "weapon_gnome");
|
||||
EquipPlayerWeapon(i, item);
|
||||
int survivor = GetRandomInt(isL4D1 ? 5 : 0, 7);
|
||||
|
||||
SetEntityModel(i, SURVIVOR_MODELS[survivor]);
|
||||
SetEntProp(i, Prop_Send, "m_survivorCharacter", isL4D1 ? (survivor - 4) : survivor);
|
||||
SetEntProp(i, Prop_Send, "m_survivorCharacter", survivor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,13 +548,15 @@ Action Timer_WaitForStart(Handle h) {
|
|||
}
|
||||
seekerFlow = L4D2Direct_GetFlowDistance(currentSeeker);
|
||||
acquireLocationsTimer = CreateTimer(0.5, Timer_AcquireLocations, _, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT);
|
||||
hiderCheckTimer = CreateTimer(5.0, Timer_CheckHiders, _, TIMER_REPEAT);
|
||||
CreateTimer(DOOR_TOGGLE_INTERVAL, Timer_DoorToggles, _, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT);
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(i != currentSeeker && IsClientConnected(i) && IsClientInGame(i)) {
|
||||
TeleportEntity(i, seekerPos, NULL_VECTOR, NULL_VECTOR);
|
||||
if(IsFakeClient(i)) {
|
||||
moveTimers[i] = CreateTimer(GetRandomFloat(BOT_MOVE_RANDOM_MIN_TIME, BOT_MOVE_RANDOM_MAX_TIME), Timer_BotMove, GetClientUserId(i), TIMER_REPEAT);
|
||||
TriggerTimer(moveTimers[i]);
|
||||
validLocations.GetArray(GetURandomInt() % validLocations.Length, activeBotLocations[i]);
|
||||
TeleportEntity(i, activeBotLocations[i].pos, activeBotLocations[i].ang, NULL_VECTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -581,10 +577,21 @@ Action Timer_StartSeeker(Handle h) {
|
|||
SetPlayerBlind(currentSeeker, 0);
|
||||
SetState(State_Active);
|
||||
SetTick(0);
|
||||
SetMapTime(1000);
|
||||
SetEntPropFloat(currentSeeker, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||
if(mapConfig.mapTime == 0) {
|
||||
mapConfig.mapTime = DEFAULT_MAP_TIME;
|
||||
}
|
||||
SetMapTime(mapConfig.mapTime);
|
||||
timesUpTimer = CreateTimer(float(mapConfig.mapTime), Timer_TimesUp, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
Action Timer_TimesUp(Handle h) {
|
||||
PrintToChatAll("The seeker ran out of time. Hiders win!");
|
||||
EndGame(State_HidersWin);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Action OnWeaponDrop(int client, int weapon) {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
@ -595,7 +602,7 @@ Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float& damag
|
|||
ClearInventory(victim);
|
||||
if(IsFakeClient(victim)) {
|
||||
PrintToChat(attacker, "That was a bot! -%.0f health", cvar_seekerFailDamageAmount.FloatValue);
|
||||
SDKHooks_TakeDamage(attacker, 0, 0, cvar_seekerFailDamageAmount.FloatValue, DMG_BURN);
|
||||
SDKHooks_TakeDamage(attacker, 0, 0, cvar_seekerFailDamageAmount.FloatValue, DMG_DIRECT);
|
||||
}
|
||||
return Plugin_Changed;
|
||||
} else if(attacker > 0 && attacker <= MaxClients) {
|
||||
|
@ -613,6 +620,7 @@ Action Timer_DoorToggles(Handle h) {
|
|||
if(GetURandomFloat() < DOOR_TOGGLE_CHANCE)
|
||||
AcceptEntityInput(entity, "Toggle");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Action Timer_AcquireLocations(Handle h) {
|
||||
|
@ -644,6 +652,15 @@ Action Timer_AcquireLocations(Handle h) {
|
|||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void GetMovePoint(int i) {
|
||||
activeBotLocations[i].runto = GetURandomFloat() < BOT_MOVE_RUN_CHANCE;
|
||||
activeBotLocations[i].attempts = 0;
|
||||
validLocations.GetArray(GetURandomInt() % validLocations.Length, activeBotLocations[i]);
|
||||
#if defined DEBUG_SHOW_POINTS
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 255, 120}, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
Action Timer_BotMove(Handle h, int userid) {
|
||||
int i = GetClientOfUserId(userid);
|
||||
if(i == 0) return Plugin_Stop;
|
||||
|
@ -659,6 +676,7 @@ Action Timer_BotMove(Handle h, int userid) {
|
|||
}
|
||||
|
||||
float botFlow = L4D2Direct_GetFlowDistance(i);
|
||||
static float pos[3];
|
||||
if(botFlow < flowMin || botFlow > flowMax) {
|
||||
activeBotLocations[i].runto = GetURandomFloat() > 0.90;
|
||||
TE_SetupBeamLaser(i, currentSeeker, g_iLaserIndex, 0, 0, 0, 8.0, 0.5, 0.1, 0, 1.0, {255, 255, 0, 125}, 1);
|
||||
|
@ -667,37 +685,83 @@ Action Timer_BotMove(Handle h, int userid) {
|
|||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] BOT %N TOO FAR (%f) BOUNDS (%f, %f)-> Moving to seeker (%f %f %f)", i, botFlow, flowMin, flowMax, seekerPos[0], seekerPos[1], seekerPos[2]);
|
||||
#endif
|
||||
activeBotLocations[i].attempts = 0;
|
||||
} else if(validLocations.Length > 0) {
|
||||
if(mapConfig.hasSpawnpoint && FloatAbs(botFlow - seekerFlow) < BOT_MOVE_AVOID_FLOW_DIST && GetURandomFloat() < BOT_MOVE_AVOID_SEEKER_CHANCE) {
|
||||
if(!FindPointAway(seekerPos, activeBotLocations[i].pos, BOT_MOVE_AVOID_MIN_DISTANCE)) {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] BOT %N TOO CLOSE -> Failed to find far point, falling back to spawn", i);
|
||||
GetAbsOrigin(i, pos);
|
||||
float distanceToPoint = GetVectorDistance(pos, activeBotLocations[i].pos);
|
||||
if(distanceToPoint < BOT_MOVE_NOT_REACHED_DISTANCE || GetURandomFloat() < 0.20) {
|
||||
activeBotLocations[i].attempts = 0;
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
L4D2_SetPlayerSurvivorGlowState(i, false);
|
||||
L4D2_RemoveEntityGlow(i);
|
||||
#endif
|
||||
// Has reached destination
|
||||
if(mapConfig.hasSpawnpoint && FloatAbs(botFlow - seekerFlow) < BOT_MOVE_AVOID_FLOW_DIST && GetURandomFloat() < BOT_MOVE_AVOID_SEEKER_CHANCE) {
|
||||
if(!FindPointAway(seekerPos, activeBotLocations[i].pos, BOT_MOVE_AVOID_MIN_DISTANCE)) {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] BOT %N TOO CLOSE -> Failed to find far point, falling back to spawn", i);
|
||||
#endif
|
||||
activeBotLocations[i].pos = mapConfig.spawnpoint;
|
||||
} else {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] BOT %N TOO CLOSE -> Moving to far point (%f %f %f) (%f units away)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2], GetVectorDistance(seekerPos, activeBotLocations[i].pos));
|
||||
#endif
|
||||
}
|
||||
activeBotLocations[i].runto = GetURandomFloat() < 0.75;
|
||||
#if defined DEBUG_SHOW_POINTS
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.2, 0.1, 0, 0.0, {255, 255, 255, 255}, 0);
|
||||
#endif
|
||||
activeBotLocations[i].pos = mapConfig.spawnpoint;
|
||||
} else {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] BOT %N TOO CLOSE -> Moving to far point (%f %f %f) (%f units away)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2], GetVectorDistance(seekerPos, activeBotLocations[i].pos));
|
||||
#endif
|
||||
GetMovePoint(i);
|
||||
}
|
||||
if(!L4D2_IsReachable(i, activeBotLocations[i].pos)) {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToChatAll("[gw/debug] POINT UNREACHABLE (Bot:%d) (%f %f %f)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
PrintToServer("[gw/debug] POINT UNREACHABLE (Bot:%d) (%f %f %f)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, view_as<float>({ 10.0, 10.0, 100.0 }), NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 400.0, 2.0, 3.0, 0, 0.0, {255, 0, 0, 255}, 0);
|
||||
#endif
|
||||
GetMovePoint(i);
|
||||
}
|
||||
activeBotLocations[i].runto = GetURandomFloat() < 0.75;
|
||||
#if defined DEBUG_SHOW_POINTS
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.2, 0.1, 0, 0.0, {255, 255, 255, 255}, 0);
|
||||
#endif
|
||||
} else {
|
||||
activeBotLocations[i].runto = GetURandomFloat() < BOT_MOVE_RUN_CHANCE;
|
||||
validLocations.GetArray(GetURandomInt() % validLocations.Length, activeBotLocations[i]);
|
||||
// Has not reached dest
|
||||
activeBotLocations[i].attempts++;
|
||||
#if defined DEBUG_MOVE_ATTEMPTS
|
||||
PrintToConsoleAll("[gw/debug] Bot %d - move attempt %d - dist: %f", i, activeBotLocations[i].attempts, distanceToPoint);
|
||||
#endif
|
||||
if(activeBotLocations[i].attempts == BOT_MOVE_NOT_REACHED_ATTEMPT_RUNJUMP) {
|
||||
if(distanceToPoint <= (BOT_MOVE_NOT_REACHED_DISTANCE * 2)) {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] Bot %d still has not reached point (%f %f %f), jumping", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
L4D2_SetPlayerSurvivorGlowState(i, true);
|
||||
L4D2_SetEntityGlow(i, L4D2Glow_Constant, 0, 10, PLAYER_GLOW_COLOR, true);
|
||||
#endif
|
||||
activeBotLocations[i].jump = true;
|
||||
} else {
|
||||
activeBotLocations[i].runto = true;
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] Bot %d not reached point (%f %f %f), running", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
L4D2_SetEntityGlow(i, L4D2Glow_Constant, 0, 10, PLAYER_GLOW_COLOR, true);
|
||||
L4D2_SetPlayerSurvivorGlowState(i, true);
|
||||
#endif
|
||||
}
|
||||
} else if(activeBotLocations[i].attempts > BOT_MOVE_NOT_REACHED_ATTEMPT_RETRY) {
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
PrintToConsoleAll("[gw/debug] Bot %d giving up at reaching point (%f %f %f)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
L4D2_SetEntityGlow(i, L4D2Glow_Constant, 0, 10, SEEKER_GLOW_COLOR, true);
|
||||
L4D2_SetPlayerSurvivorGlowState(i, true);
|
||||
#endif
|
||||
GetMovePoint(i);
|
||||
}
|
||||
#if defined DEBUG_SHOW_POINTS
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 255, 255}, 0);
|
||||
int color[4];
|
||||
color[0] = 255;
|
||||
color[2] = 255;
|
||||
color[3] = 120 + activeBotLocations[i].attempts * 45;
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, color, 0);
|
||||
#endif
|
||||
}
|
||||
#if defined DEBUG_BOT_MOVE
|
||||
if(!L4D2_IsReachable(i, activeBotLocations[i].pos)) {
|
||||
PrintToChatAll("[gw/debug] POINT UNREACHABLE (Bot:%d) (%f %f %f)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
PrintToServer("[gw/debug] POINT UNREACHABLE (Bot:%d) (%f %f %f)", i, activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]);
|
||||
Effect_DrawBeamBoxRotatableToAll(activeBotLocations[i].pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 0, 255}, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
LookAtPoint(i, activeBotLocations[i].pos);
|
||||
L4D2_RunScript("CommandABot({cmd=1,bot=GetPlayerFromUserID(%i),pos=Vector(%f,%f,%f)})",
|
||||
GetClientUserId(i),
|
||||
activeBotLocations[i].pos[0], activeBotLocations[i].pos[1], activeBotLocations[i].pos[2]
|
||||
|
@ -709,6 +773,11 @@ Action Timer_BotMove(Handle h, int userid) {
|
|||
public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) {
|
||||
if(!isEnabled) return Plugin_Continue;
|
||||
if(IsFakeClient(client)) {
|
||||
if(activeBotLocations[client].jump) {
|
||||
activeBotLocations[client].jump = false;
|
||||
buttons |= (IN_WALK | IN_JUMP | IN_FORWARD);
|
||||
return Plugin_Changed;
|
||||
}
|
||||
buttons |= (activeBotLocations[client].runto ? IN_WALK : IN_SPEED);
|
||||
if(GetURandomFloat() < BOT_MOVE_USE_CHANCE) {
|
||||
buttons |= IN_USE;
|
||||
|
@ -721,28 +790,35 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
|
|||
}
|
||||
return Plugin_Changed;
|
||||
} else if(client != currentSeeker && buttons & IN_RELOAD) {
|
||||
int target = GetClientAimTarget(client, true);
|
||||
if(target > 0) {
|
||||
int time = GetTime();
|
||||
float diff = float(time - hiderSwapTime[client]);
|
||||
if(diff > HIDER_SWAP_COOLDOWN) {
|
||||
hiderSwapTime[client] = GetTime();
|
||||
if(hiderSwapCount[client] >= HIDER_SWAP_LIMIT) {
|
||||
PrintHintText(client, "Swap limit reached");
|
||||
} else {
|
||||
int target = GetClientAimTarget(client, true);
|
||||
|
||||
if(target > 0) {
|
||||
int time = GetTime();
|
||||
float diff = float(time - hiderSwapTime[client]);
|
||||
if(diff > HIDER_SWAP_COOLDOWN) {
|
||||
hiderSwapTime[client] = GetTime();
|
||||
hiderSwapCount[client]++;
|
||||
|
||||
/*float pos[3], pos2[3];
|
||||
GetClientAbsOrigin(client, pos);
|
||||
GetClientEyePosition(client, pos2);
|
||||
TE_SetupParticle(g_iSmokeParticle, pos, pos2, .iEntity = client);
|
||||
TE_SendToAllInRange(pos, RangeType_Audibility, 0.0);*/
|
||||
/*float pos[3], pos2[3];
|
||||
GetClientAbsOrigin(client, pos);
|
||||
GetClientEyePosition(client, pos2);
|
||||
TE_SetupParticle(g_iSmokeParticle, pos, pos2, .iEntity = client);
|
||||
TE_SendToAllInRange(pos, RangeType_Audibility, 0.0);*/
|
||||
|
||||
char modelName[64];
|
||||
GetClientModel(target, modelName, sizeof(modelName));
|
||||
int type = GetEntProp(target, Prop_Send, "m_survivorCharacter");
|
||||
SetEntityModel(client, modelName);
|
||||
SetEntProp(client, Prop_Send, "m_survivorCharacter", type);
|
||||
char modelName[64];
|
||||
GetClientModel(target, modelName, sizeof(modelName));
|
||||
int type = GetEntProp(target, Prop_Send, "m_survivorCharacter");
|
||||
SetEntityModel(client, modelName);
|
||||
SetEntProp(client, Prop_Send, "m_survivorCharacter", type);
|
||||
|
||||
EmitSoundToAll("ui/pickup_secret01.wav", client, SNDCHAN_AUTO, SNDLEVEL_SCREAMING);
|
||||
} else {
|
||||
PrintHintText(client, "You can swap in %.0f seconds", HIDER_SWAP_COOLDOWN - diff);
|
||||
EmitSoundToAll("ui/pickup_secret01.wav", client, SNDCHAN_AUTO, SNDLEVEL_SCREAMING);
|
||||
PrintHintText(client, "You have %d swaps remaining", HIDER_SWAP_LIMIT - hiderSwapCount[client]);
|
||||
} else {
|
||||
PrintHintText(client, "You can swap in %.0f seconds", HIDER_SWAP_COOLDOWN - diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -755,7 +831,8 @@ void ClearInventory(int client) {
|
|||
int item = GetPlayerWeaponSlot(client, i);
|
||||
if(item > 0) {
|
||||
RemovePlayerItem(client, item);
|
||||
AcceptEntityInput(item, "Kill");
|
||||
RemoveEdict(item);
|
||||
// AcceptEntityInput(item, "Kill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -776,13 +853,15 @@ bool AddSurvivor() {
|
|||
}
|
||||
}
|
||||
|
||||
CreateTimer(0.2, Timer_Kick, i);
|
||||
CreateTimer(0.2, Timer_Kick, GetClientUserId(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Action Timer_Kick(Handle h, int i) {
|
||||
KickClient(i);
|
||||
Action Timer_Kick(Handle h, int u) {
|
||||
int i = GetClientOfUserId(u);
|
||||
if(i > 0) KickClient(i);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
stock void L4D2_RunScript(const char[] sCode, any ...) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue