nagadomi / l4d2_scavenge_1st_round_skip Goto Github PK
View Code? Open in Web Editor NEWscavenge 1st round bugfix.
scavenge 1st round bugfix.
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <left4dhooks>
/**
* @param sMapName Map String without .bsp
* @param bShouldResetScores Reset all scores in all gamemodes
* @noreturn
*/
native void L4D2_ChangeLevel(const char[] sMapName, bool bShouldResetScores=true);
#define PLUGIN_VERSION "1.0"
#pragma newdecls required
#pragma semicolon 1
public Plugin myinfo =
{
name = "[L4D2] Scavenge Hardcore",
author = "Eyal282",
description = "Hardcore Scavenge Rules",
version = "1.0",
url = "None."
}
int ghostSpawnIncreaseByInfected[4] = {0, 10, 15, 20};
int ghostSpawnIncreasePerUnbalanced[4] = {5, 10, 15, 20};
int ghostSpawnDecreasePerUnbalanced[4] = {5, 10, 15, 20};
char g_sRemoveMapWeapons[][] =
{
"weapon_adrenaline_spawn",
"weapon_defibrillator_spawn",
"weapon_molotov_spawn",
"weapon_pain_pills_spawn",
"weapon_pipe_bomb_spawn",
"weapon_propanetank_spawn",
"weapon_vomitjar_spawn",
"weapon_item_spawn",
//"weapon_melee_spawn",
"weapon_autoshotgun_spawn",
"weapon_chainsaw_spawn",
"weapon_hunting_rifle_spawn",
"weapon_pistol_magnum_spawn",
"weapon_pistol_spawn",
"weapon_pumpshotgun_spawn",
"weapon_rifle_ak47_spawn",
"weapon_rifle_desert_spawn",
"weapon_rifle_m60_spawn",
"weapon_rifle_sg552_spawn",
"weapon_rifle_spawn",
"weapon_shotgun_chrome_spawn",
"weapon_shotgun_spas_spawn",
"weapon_smg_mp5_spawn",
"weapon_smg_silenced_spawn",
"weapon_sniper_awp_spawn",
"weapon_sniper_military_spawn",
"weapon_sniper_scout_spawn"
};
enum struct enReplaceWeapons
{
char sClassname[64];
L4D2WeaponId wepID;
// How many times can you take the new weapon before it disappears
int count;
// Maximum amount of entities to replace.
int maxReplace;
bool bSafeAreaOnly;
// Ignore this.
int currentReplace;
}
enReplaceWeapons g_sReplaceMapWeapons[] =
{
{ "weapon_spawn", L4D2WeaponId_Smg, 2, 99, true, 0 },
{ "weapon_first_aid_kit_spawn", L4D2WeaponId_PainPills, 1, 4, true, 0},
{ "weapon_melee_spawn", L4D2WeaponId_Molotov, 9999, 1, true, 0 }
};
ConVar g_hAllBotGame;
ConVar g_hGamemode;
ConVar g_hStartingClock;
ConVar g_hGhostDelayMin;
ConVar g_hGhostDelayMax;
ConVar g_hGhostDelayTrueMin;
float g_fMapStartTime;
public Action L4D_OnMaterializeFromGhostPre(int client)
{
if(!L4D_HasAnySurvivorLeftSafeArea())
return Plugin_Handled;
return Plugin_Continue;
}
public Action L4D_OnSpawnSpecial(int &zombieClass, const float vecPos[3], const float vecAng[3])
{
if(!L4D_HasAnySurvivorLeftSafeArea())
return Plugin_Handled;
return Plugin_Continue;
}
public void OnPluginStart()
{
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
HookEvent("scavenge_round_start", Event_ScavengeRoundStart, EventHookMode_Post);
HookEvent("player_spawn", Event_PlayerSpawn, EventHookMode_Post);
HookEvent("bot_player_replace", Event_PlayerReplacesABot, EventHookMode_Post);
//HookEvent("gascan_pour_completed", Event_GasCanPourCompleted, EventHookMode_PostNoCopy);
g_hAllBotGame = FindConVar("sb_all_bot_game");
g_hGamemode = FindConVar("mp_gamemode");
g_hStartingClock = FindConVar("scavenge_round_initial_time");
g_hGhostDelayMin = FindConVar("z_ghost_delay_min");
g_hGhostDelayMax = FindConVar("z_ghost_delay_max");
g_hGhostDelayTrueMin = FindConVar("z_ghost_delay_minspawn");
HookVoteMsgs();
}
public void OnMapStart()
{
g_fMapStartTime = GetGameTime();
CreateTimer(1.0, Timer_CheckConfig, _, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
}
public Action Timer_CheckConfig(Handle hTimer)
{
char MapName[32];
GetCurrentMap(MapName, sizeof(MapName));
int count, survivorCount, infectedCount;
bool bLoading = false;
for(int i=1;i <= MaxClients;i++)
{
if(IsClientConnected(i) && !IsClientInGame(i))
bLoading = true;
if(!IsClientInGame(i))
continue;
else if(IsFakeClient(i))
continue;
count++;
switch(L4D_GetClientTeam(i))
{
case L4DTeam_Survivor:
{
count++;
survivorCount++;
}
case L4DTeam_Infected:
{
count++;
infectedCount++;
}
}
}
if(count == 0 || bLoading)
{
g_hAllBotGame.BoolValue = false;
}
else
{
// Weird bug.
char sValue[32];
g_hGamemode.GetString(sValue, sizeof(sValue));
if(StrEqual(sValue, "scavenge") && GetGameTime() - g_fMapStartTime > 5.0 && GameRules_GetProp("m_nScavengeItemsRemaining") == 0 && GameRules_GetProp("m_nScavengeItemsGoal") == 0 && GetGasCanCount() == 0)
{
Scavenge_FixNoGascanSpawnBug();
return Plugin_Continue;
}
g_hAllBotGame.BoolValue = true;
g_hStartingClock.IntValue = 300;
GetCurrentMap(MapName, sizeof(MapName));
if(!StrEqual(MapName, "c8m5_rooftop") && !StrEqual(MapName, "c14m2_lighthouse"))
{
g_fMapStartTime = GetGameTime();
L4D2_ChangeLevel("c8m5_rooftop");
return Plugin_Stop;
}
}
g_hGhostDelayMin.IntValue = 0;
g_hGhostDelayMax.IntValue = 0;
if(infectedCount == 0)
return Plugin_Continue;
int timer = ghostSpawnIncreaseByInfected[infectedCount-1];
if(infectedCount > survivorCount)
{
timer += ghostSpawnIncreasePerUnbalanced[(infectedCount - survivorCount - 1)];
}
else if(survivorCount > infectedCount)
{
timer -= ghostSpawnDecreasePerUnbalanced[(survivorCount - infectedCount - 1)];
}
g_hGhostDelayTrueMin.IntValue = timer;
// Weird bug.
char sValue[32];
g_hGamemode.GetString(sValue, sizeof(sValue));
if(!StrEqual(sValue, "scavenge"))
g_hGamemode.SetString("scavenge");
return Plugin_Continue;
}
public Action Event_RoundStart(Handle hEvent, const char[] Name, bool dontBroadcast)
{
CreateTimer(1.0, Timer_ReplaceWeapons);
return Plugin_Continue;
}
public Action Event_ScavengeRoundStart(Handle hEvent, const char[] Name, bool dontBroadcast)
{
for(int i=1;i <= MaxClients;i++)
{
if(!IsClientInGame(i))
continue;
else if(L4D_GetClientTeam(i) != L4DTeam_Survivor)
continue;
SetEntityMoveType(i, MOVETYPE_WALK);
}
return Plugin_Continue;
}
public Action Event_PlayerSpawn(Handle hEvent, const char[] Name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
if(L4D_GetClientTeam(client) != L4DTeam_Survivor)
return Plugin_Continue;
else if(L4D_HasAnySurvivorLeftSafeArea())
return Plugin_Continue;
if(IsFakeClient(client))
SetEntityMoveType(client, MOVETYPE_NONE);
else
SetEntityMoveType(client, MOVETYPE_WALK);
return Plugin_Continue;
}
public Action Event_PlayerReplacesABot(Handle hEvent, const char[] Name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(hEvent, "player"));
if(L4D_GetClientTeam(client) != L4DTeam_Survivor)
return Plugin_Continue;
else if(L4D_HasAnySurvivorLeftSafeArea())
return Plugin_Continue;
SetEntityMoveType(client, MOVETYPE_WALK);
return Plugin_Continue;
}
public Action Timer_ReplaceWeapons(Handle hTimer)
{
for(int i=0;i < sizeof(g_sReplaceMapWeapons);i++)
{
g_sReplaceMapWeapons[i].currentReplace = g_sReplaceMapWeapons[i].maxReplace;
}
int count = GetEntityCount();
for(int ent=MaxClients+1;ent < count;ent++)
{
if(!IsValidEdict(ent))
continue;
char sClassname[64];
GetEdictClassname(ent, sClassname, sizeof(sClassname));
for(int i=0;i < sizeof(g_sReplaceMapWeapons);i++)
{
if(StrEqual(sClassname, g_sReplaceMapWeapons[i].sClassname))
{
OnSpawnPost_ReplaceWeaponSpawn(ent, i);
i = 999999;
}
}
}
return Plugin_Continue;
}
public void OnSpawnPost_ReplaceWeaponSpawn(int entity, int replaceIndex)
{
DataPack DP;
CreateDataTimer(0.1, Timer_ReplaceWeaponSpawn, DP, TIMER_FLAG_NO_MAPCHANGE);
WritePackCell(DP, EntIndexToEntRef(entity));
WritePackCell(DP, replaceIndex);
}
public Action Timer_ReplaceWeaponSpawn(Handle hTimer, DataPack DP)
{
ResetPack(DP);
int entity = EntRefToEntIndex(ReadPackCell(DP));
int replaceIndex = ReadPackCell(DP);
if(entity == INVALID_ENT_REFERENCE)
return Plugin_Stop;
float fOrigin[3], fAngles[3];
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", fOrigin);
GetEntPropVector(entity, Prop_Send, "m_angRotation", fAngles);
AcceptEntityInput(entity, "Kill");
if(g_sReplaceMapWeapons[replaceIndex].bSafeAreaOnly && !IsPositionInAnyCheckpoint(fOrigin))
return Plugin_Stop;
else if(g_sReplaceMapWeapons[replaceIndex].currentReplace <= 0)
return Plugin_Stop;
g_sReplaceMapWeapons[replaceIndex].currentReplace--;
int spawn = CreateEntityByName("weapon_spawn");
SetEntProp(spawn, Prop_Data, "m_weaponID", g_sReplaceMapWeapons[replaceIndex].wepID);
char sCount[11];
IntToString(g_sReplaceMapWeapons[replaceIndex].count, sCount, sizeof(sCount));
DispatchKeyValue(spawn, "count", sCount);
TeleportEntity(spawn, fOrigin, fAngles, NULL_VECTOR);
DispatchSpawn(spawn);
SetEntityMoveType(spawn, MOVETYPE_NONE);
return Plugin_Stop;
}
public void OnEntityCreated(int entity, const char[] classname)
{
// Sometimes a map will want to give RPG to continue progress.
//if(StrEqual(classname, "game_player_equip"))
// SDKHook(entity, SDKHook_Spawn, OnShouldSpawn_NeverSpawn);
for(int i=0;i < sizeof(g_sRemoveMapWeapons);i++)
{
if(StrEqual(classname, g_sRemoveMapWeapons[i]))
{
SDKHook(entity, SDKHook_Spawn, OnShouldSpawn_NeverSpawn);
}
}
}
public Action OnShouldSpawn_NeverSpawn(int entity)
{
AcceptEntityInput(entity, "Kill");
return Plugin_Handled;
}
void HookVoteMsgs()
{
char msgname[64];
int i = 1;
while( i )
{
if( GetUserMessageName(view_as<UserMsg>(i), msgname, sizeof msgname) )
{
if( strcmp(msgname, "PZEndGamePanelMsg") == 0 )
{
HookUserMessage(view_as<UserMsg>(i), OnMessage, true);
break;
}
i++;
} else {
i = 0;
}
}
}
public Action OnMessage(UserMsg msg_id, BfRead hMsg, const int[] players, int playersNum, bool reliable, bool init)
{
char MapName[32];
GetCurrentMap(MapName, sizeof(MapName));
L4D2_ChangeLevel(MapName);
g_fMapStartTime = GetGameTime();
return Plugin_Handled;
}
public Action L4D_OnSpawnTank(const float vecPos[3], const float vecAng[3])
{
return Plugin_Handled;
}
public Action L4D2_CGasCan_ShouldStartAction(int client, int gascan, int nozzle)
{
float fOrigin[3], fNozzleOrigin[3];
GetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", fOrigin);
GetEntPropVector(nozzle, Prop_Data, "m_vecOrigin", fNozzleOrigin);
if(fOrigin[2] - fNozzleOrigin[2] > -40.0)
return Plugin_Handled;
return Plugin_Continue;
}
// Be careful, this includes scavenge safe areas.
stock bool IsPositionInAnyCheckpoint(float fOrigin[3])
{
Address navarea = L4D_GetNearestNavArea(fOrigin);
if(navarea == Address_Null)
return false;
int spawnAttributes = L4D_GetNavArea_SpawnAttributes(navarea);
if(spawnAttributes & NAV_SPAWN_CHECKPOINT)
return true;
return false;
}
stock int GetGasCanCount()
{
int count;
int entCount = GetEntityCount();
for(int ent=MaxClients+1;ent < entCount;ent++)
{
if(!IsValidEdict(ent))
continue;
char sClassname[64];
GetEdictClassname(ent, sClassname, sizeof(sClassname));
if(StrEqual(sClassname, "weapon_gascan") || StrEqual(sClassname, "weapon_gascan_spawn"))
count++;
}
return count;
}
stock void Scavenge_FixNoGascanSpawnBug()
{
char sSignature[128];
sSignature = "@_ZN9CDirector21SpawnAllScavengeItemsEv";
Handle Call = INVALID_HANDLE;
if (Call == INVALID_HANDLE)
{
StartPrepSDKCall(SDKCall_Raw);
if (!PrepSDKCall_SetSignature(SDKLibrary_Server, sSignature, strlen(sSignature)-1))
{
return;
}
Call = EndPrepSDKCall();
if (Call == INVALID_HANDLE)
{
return;
}
}
SDKCall(Call, L4D_GetPointer(POINTER_DIRECTOR));
}```
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.