mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 23:03:20 +00:00
Minor ftt spawn logic changing
This commit is contained in:
parent
29b7d12060
commit
6c63e69abf
13 changed files with 139 additions and 37 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -47,7 +47,7 @@ enum L4DModelId {
|
|||
}
|
||||
|
||||
static ArrayList LasersUsed;
|
||||
static ConVar hLaserNotice, hFinaleTimer, hFFNotice, hMPGamemode, hPingDropThres, hForceSurvivorSet;
|
||||
static ConVar hLaserNotice, hFinaleTimer, hFFNotice, hMPGamemode, hPingDropThres, hForceSurvivorSet, hPlayerLimit, hSVMaxPlayers;
|
||||
static int iFinaleStartTime, botDropMeleeWeapon[MAXPLAYERS+1], iHighPingCount[MAXPLAYERS+1];
|
||||
ReserveMode reserveMode;
|
||||
static bool isHighPingIdle[MAXPLAYERS+1], isL4D1Survivors;
|
||||
|
@ -99,6 +99,12 @@ public void OnPluginStart() {
|
|||
hPingDropThres = CreateConVar("sm_autoidle_ping_max", "0.0", "The highest ping a player can have until they will automatically go idle.\n0=OFF, Min is 30", FCVAR_NONE, true, 0.0, true, 1000.0);
|
||||
hForceSurvivorSet = FindConVar("l4d_force_survivorset");
|
||||
|
||||
hSVMaxPlayers = FindConVar("sv_maxplayers");
|
||||
hPlayerLimit = CreateConVar("sm_player_limit", "0", "Overrides sv_maxplayers. 0 = off, > 0: limit", FCVAR_NONE, true, 0.0, false);
|
||||
hPlayerLimit.AddChangeHook(Event_PlayerLimitChange);
|
||||
hSVMaxPlayers.IntValue = hPlayerLimit.IntValue;
|
||||
|
||||
|
||||
hFFNotice.AddChangeHook(CVC_FFNotice);
|
||||
if(hFFNotice.IntValue > 0) {
|
||||
HookEvent("player_hurt", Event_PlayerHurt);
|
||||
|
@ -156,6 +162,13 @@ public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[
|
|||
cvar.GetString(gamemode, sizeof(gamemode));
|
||||
}
|
||||
|
||||
public void Event_PlayerLimitChange(ConVar cvar, const char[] oldValue, const char[] newValue) {
|
||||
if(cvar.IntValue > 0) {
|
||||
hSVMaxPlayers.IntValue = cvar.IntValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnClientConnected(int client) {
|
||||
if(!IsFakeClient(client) && reserveMode == Reserve_Watch) {
|
||||
PrintChatToAdmins("%N is connecting", client);
|
||||
|
@ -658,7 +671,14 @@ public void OnMapStart() {
|
|||
|
||||
HookEntityOutput("info_changelevel", "OnStartTouch", EntityOutput_OnStartTouchSaferoom);
|
||||
HookEntityOutput("trigger_changelevel", "OnStartTouch", EntityOutput_OnStartTouchSaferoom);
|
||||
|
||||
}
|
||||
public void OnConfigsExecuted() {
|
||||
isL4D1Survivors = L4D2_GetSurvivorSetMap() == 1;
|
||||
|
||||
if(hPlayerLimit.IntValue > 0) {
|
||||
hSVMaxPlayers.IntValue = hPlayerLimit.IntValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneStageChanged(int scene, SceneStages stage) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//Allow MAX_TROLLS to be defined elsewhere
|
||||
#if defined MAX_TROLLS
|
||||
#else
|
||||
#define MAX_TROLLS 37
|
||||
#define MAX_TROLLS 38
|
||||
#endif
|
||||
|
||||
enum trollModifier {
|
||||
|
@ -358,36 +358,36 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
|
|||
bool isActive = IsTrollActive(victim, troll.name);
|
||||
if(!silent) {
|
||||
if(isActive) {
|
||||
ShowActivityEx(activator, "[FTT] ", "deactivated troll \"%s\" on %N. ", troll.name, victim);
|
||||
LogAction(activator, victim, "\"%L\" deactivated troll \"%s\" on \"%L\"", activator, troll.name, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "deactivated \"%s\" on %N. ", troll.name, victim);
|
||||
LogAction(activator, victim, "\"%L\" deactivated \"%s\" on \"%L\"", activator, troll.name, victim);
|
||||
} else {
|
||||
static char flagName[MAX_TROLL_FLAG_LENGTH];
|
||||
if(flags > 0 && flags & flags - 1 == 0) {
|
||||
if(flags > 0 && flags & flags - 1 == 0 && flags & flags + 1 == 0) {
|
||||
// Get the flag name if there is only one flag set
|
||||
troll.GetFlagName(GetIndexFromPower(flags), flagName, sizeof(flagName));
|
||||
}
|
||||
if(modifier & TrollMod_Constant) {
|
||||
if(flags > 0) {
|
||||
if(flagName[0] != '\0') {
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant troll \"%s\" (%s) for %N. ", troll.name, flagName, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant \"%s\" (%s) for %N. ", troll.name, flagName, victim);
|
||||
} else {
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant troll \"%s\" (%d) for %N. ", troll.name, flags, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant \"%s\" (%d) for %N. ", troll.name, flags, victim);
|
||||
}
|
||||
} else
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant troll \"%s\" for %N. ", troll.name, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated constant \"%s\" for %N. ", troll.name, victim);
|
||||
} else if(flags > 0) {
|
||||
if(flagName[0] != '\0') {
|
||||
ShowActivityEx(activator, "[FTT] ", "activated troll \"%s\" (%s) for %N. ", troll.name, flagName, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated \"%s\" (%s) for %N. ", troll.name, flagName, victim);
|
||||
} else {
|
||||
ShowActivityEx(activator, "[FTT] ", "activated troll \"%s\" (%d) for %N. ", troll.name, flags, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated \"%s\" (%d) for %N. ", troll.name, flags, victim);
|
||||
}
|
||||
} else
|
||||
ShowActivityEx(activator, "[FTT] ", "activated troll \"%s\" for %N. ", troll.name, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "activated \"%s\" for %N. ", troll.name, victim);
|
||||
|
||||
LogAction(activator, victim, "\"%L\" activated troll \"%s\" (%d) for \"%L\"", activator, troll.name, flags, victim);
|
||||
LogAction(activator, victim, "\"%L\" activated \"%s\" (%d) for \"%L\"", activator, troll.name, flags, victim);
|
||||
}
|
||||
} else {
|
||||
ReplyToCommand(activator, "ftt: Applied Troll \"%s\" on %N with flags=%d", troll.name, victim, flags);
|
||||
ReplyToCommand(activator, "ftt: Applied \"%s\" on %N with flags=%d", troll.name, victim, flags);
|
||||
}
|
||||
// Toggle on flags for client, if it's not a single run.
|
||||
if(modifier & TrollMod_Constant) {
|
||||
|
|
|
@ -16,6 +16,8 @@ public void OnMapStart() {
|
|||
PrecacheSound("weapons/ceda_jar/ceda_jar_explode.wav");
|
||||
PrecacheSound("weapons/molotov/molotov_detonate_1.wav");
|
||||
|
||||
PrecacheSound(MODEL_CAR);
|
||||
|
||||
g_spSpawnQueue.Clear();
|
||||
spIsActive = false;
|
||||
//CreateTimer(30.0, Timer_AutoPunishCheck, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||
|
@ -44,6 +46,7 @@ public void Event_SecondaryHealthUsed(Event event, const char[] name, bool dontB
|
|||
L4D_StaggerPlayer(client, client, NULL_VECTOR);
|
||||
}
|
||||
}
|
||||
static float SPIT_VEL[3] = { 0.0, 0.0, -1.0 };
|
||||
public Action Timer_CheckSpecial(Handle h, int specialID) {
|
||||
int special = GetClientOfUserId(specialID);
|
||||
// Check if new player is the spawned special:
|
||||
|
@ -60,9 +63,16 @@ public Action Timer_CheckSpecial(Handle h, int specialID) {
|
|||
|
||||
TeleportEntity(special, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
|
||||
if(spActiveRequest.flags & view_as<int>(SPI_KillOnSpawn)) {
|
||||
if(type == Special_Spitter) {
|
||||
float pos[3];
|
||||
GetClientEyePosition(special, pos);
|
||||
L4D2_SpitterPrj(special, pos, SPIT_VEL);
|
||||
}
|
||||
RequestFrame(Frame_Boom, special);
|
||||
}
|
||||
|
||||
g_iSpId++;
|
||||
|
||||
ProcessSpecialQueue();
|
||||
}
|
||||
}
|
||||
|
@ -96,21 +106,16 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
|
|||
shootAtTargetHP[client] = 0;
|
||||
}
|
||||
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
int userid = event.GetInt("userid");
|
||||
int client = GetClientOfUserId(userid);
|
||||
if(client > 0) {
|
||||
if(g_iAttackerTarget[client] > 0) {
|
||||
// If special died, clear & subtract one from counter
|
||||
int target = GetClientOfUserId(g_iAttackerTarget[client]);
|
||||
gInstaSpecialMagnet[target]--;
|
||||
if(gInstaSpecialMagnet[target] == 0) {
|
||||
PrintToServer("[FTT] gInstaSpecialMagnet dropped below 0");
|
||||
gInstaSpecialMagnet[target] = 0;
|
||||
}
|
||||
g_iAttackerTarget[client] = 0;
|
||||
} else {
|
||||
// If player died, stop the targetting
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(g_iAttackerTarget[i] == client) {
|
||||
if(g_iAttackerTarget[i] == userid) {
|
||||
g_iAttackerTarget[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -377,3 +377,51 @@ stock void ExplodeProjectile(int entity, bool smoke = true) {
|
|||
if(smoke)
|
||||
SetEntProp(entity, Prop_Data, "m_nNextThinkTick", 1); //for smoke
|
||||
}
|
||||
|
||||
stock bool IsAreaClear(const float pos[3], const float ang[3]) {
|
||||
float min[3] = { -30.0, -30.0, -2.0};
|
||||
float max[3] = { 30.0, 30.0, 50.0 };
|
||||
|
||||
// DebugTraceHull(pos, pos, min, max);
|
||||
TR_TraceHullFilter(pos, pos, min, max, MASK_SOLID, Filter_Solid);
|
||||
if(TR_DidHit()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpawnCarOnPlayer(int target) {
|
||||
float pos[3];
|
||||
float ang[3];
|
||||
GetClientEyePosition(target, pos);
|
||||
GetClientEyeAngles(target, ang);
|
||||
if(IsAreaClear(pos, ang)) {
|
||||
pos[2] += 40.0;
|
||||
int id = CreateProp("prop_physics", MODEL_CAR, pos, ang);
|
||||
CreateTimer(4.0, Timer_Delete, id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
|
||||
int entity = CreateEntityByName(entClass);
|
||||
DispatchKeyValue(entity, "model", model);
|
||||
DispatchKeyValue(entity, "solid", "6");
|
||||
DispatchKeyValue(entity, "targetname", "hsprop");
|
||||
DispatchKeyValue(entity, "disableshadows", "1");
|
||||
TeleportEntity(entity, pos, ang, NULL_VECTOR);
|
||||
DispatchSpawn(entity);
|
||||
#if defined DEBUG_LOG_MAPSTART
|
||||
PrintToServer("spawn prop %.1f %.1f %.1f model %s", pos[0], pos[1], pos[2], model[7]);
|
||||
#endif
|
||||
return entity;
|
||||
}
|
||||
|
||||
public bool Filter_Solid(int entity, int contentsMask, any data) {
|
||||
return entity <= 0;
|
||||
}
|
||||
|
||||
public Action Timer_Delete(Handle h, int id) {
|
||||
AcceptEntityInput(id, "Kill");
|
||||
}
|
|
@ -35,10 +35,10 @@ stock bool SpawnSpecialForTarget(SpecialType specialType, int target, SpecialSpa
|
|||
GetClientAbsOrigin(target, pos);
|
||||
GetClientEyeAngles(target, ang);
|
||||
|
||||
if(specialType == Special_Boomer)
|
||||
if(specialType == Special_Boomer || specialType == Special_Spitter)
|
||||
internalFlags |= view_as<int>(SPI_KillOnSpawn);
|
||||
|
||||
if(specialType == Special_Jockey || specialType == Special_Boomer) { // Else spawn a little bit off, and above (above for jockeys)
|
||||
if(specialType == Special_Jockey || specialType == Special_Boomer || specialType == Special_Spitter) { // Else spawn a little bit off, and above (above for jockeys)
|
||||
pos[2] += 25.0;
|
||||
pos[0] += 5.0;
|
||||
} else { //If not jockey/hunter find a suitable area that is at least 5 m away
|
||||
|
@ -75,10 +75,15 @@ stock bool SpawnSpecialAtPosition(SpecialType special, const float destination[3
|
|||
|
||||
SpecialSpawnRequest spActiveRequest;
|
||||
|
||||
// On spawn, keep id
|
||||
// timer checks if passed id still == kept id, if so, it failed.
|
||||
int g_iSpId;
|
||||
|
||||
bool ProcessSpecialQueue() {
|
||||
if(g_spSpawnQueue.Length > 0) {
|
||||
if(g_spSpawnQueue.GetArray(0, spActiveRequest, sizeof(spActiveRequest))) {
|
||||
spIsActive = true;
|
||||
CreateTimer(4.0, Timer_CheckSpecialSpawned, g_iSpId);
|
||||
}
|
||||
g_spSpawnQueue.Erase(0);
|
||||
|
||||
|
|
|
@ -140,4 +140,12 @@ public Action Timer_ShootReverse(Handle h, DataPack pack) {
|
|||
shootAtTargetHP[target] = 0;
|
||||
return Plugin_Stop;
|
||||
}
|
||||
}
|
||||
|
||||
public Action Timer_CheckSpecialSpawned(Handle h, int id) {
|
||||
if(g_iSpId == id) {
|
||||
PrintToServer("[FTT] Special did not spawn in time, continuing.");
|
||||
g_iSpId++;
|
||||
ProcessSpecialQueue();
|
||||
}
|
||||
}
|
|
@ -130,6 +130,7 @@ void SetupTrolls() {
|
|||
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
|
||||
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
|
||||
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
|
||||
index = SetupTroll("Car Splat", "Car. splats.", TrollMod_Instant);
|
||||
index = SetupTroll("Meta: Inverse", "Uhm you are not supposed to see this...", TrollMod_Instant);
|
||||
Trolls[index].hidden = true;
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
|
@ -158,8 +159,8 @@ void AddMagnetFlags(int index) {
|
|||
bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier modifier, int flags) {
|
||||
bool isActive = IsTrollActiveByRawID(victim, troll.id);
|
||||
if(StrEqual(troll.name, "Reset User")) {
|
||||
LogAction(activator, victim, "\"%L\" reset all troll effects for \"%L\"", activator, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "reset troll effects for %N. ", victim);
|
||||
LogAction(activator, victim, "\"%L\" reset all effects for \"%L\"", activator, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "reset effects for %N. ", victim);
|
||||
for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
Trolls[i].activeFlagClients[victim] = -1;
|
||||
}
|
||||
|
@ -244,6 +245,11 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
|
|||
SpawnSpecialForTarget(view_as<SpecialType>(i), victim, spawnFlag);
|
||||
}
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Car Splat")) {
|
||||
if(!SpawnCarOnPlayer(victim)) {
|
||||
ReplyToCommand(activator, "Could not find a suitable area to spawn a car");
|
||||
return false;
|
||||
}
|
||||
} else if(modifier != TrollMod_Constant) {
|
||||
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
|
||||
#if defined DEBUG
|
||||
|
@ -251,4 +257,4 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
|
|||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ enum SpecialInternalFlags {
|
|||
SPI_KillOnSpawn = 1
|
||||
}
|
||||
|
||||
#define MODEL_CAR "models/props_vehicles/cara_95sedan.mdl"
|
||||
|
||||
#include <feedthetrolls/base>
|
||||
#include <feedthetrolls/trolls>
|
||||
|
|
|
@ -32,6 +32,26 @@ stock void GetHorizontalPositionFromClient(int client, float units, float finalP
|
|||
pos[1] += -150 * Sine(theta);
|
||||
finalPosition = pos;
|
||||
}
|
||||
// Gets velocity of an entity (ent) toward new origin with speed (fSpeed) - thanks Ryan
|
||||
stock bool GetVelocityToOrigin(int entity, const float destination[3], const float fSpeed, float outVelocity[3]) {
|
||||
float srcOrigin[3];
|
||||
GetEntPropVector(entity, Prop_Data, "m_vecVelocity", srcOrigin);
|
||||
// Velocity = Distance / Time
|
||||
|
||||
float fDistance[3];
|
||||
fDistance[0] = destination[0] - srcOrigin[0];
|
||||
fDistance[1] = destination[1] - srcOrigin[1];
|
||||
fDistance[2] = destination[2] - srcOrigin[2];
|
||||
|
||||
float fTime = (GetVectorDistance(srcOrigin, destination) / fSpeed);
|
||||
|
||||
outVelocity[0] = (destination[0] - srcOrigin[0]) / fTime;
|
||||
outVelocity[1] = (destination[1] - srcOrigin[1]) / fTime;
|
||||
outVelocity[2] = (destination[2] - srcOrigin[2]) / fTime;
|
||||
|
||||
return (outVelocity[0] && outVelocity[1] && outVelocity[2]);
|
||||
}
|
||||
|
||||
//Credits to Timocop for the stock :D
|
||||
/**
|
||||
* Runs a single line of vscript code.
|
||||
|
|
|
@ -20,17 +20,6 @@
|
|||
#include <l4d_anti_rush>
|
||||
|
||||
|
||||
/*
|
||||
TODO IDEAS:
|
||||
1. [x] Instant pipebomb explosion
|
||||
2. [x] Spicy gas (instant ignite), ignite propane/gas canisters
|
||||
3. [x] Amazon Special Combo (flags, choose combinations) (NEED QUEUE)
|
||||
4. Random weapons (on interval, possible second option of random capacity)
|
||||
5. [x] Slippery shoes (periodic stagger, or on certain events)
|
||||
6. (on hold) Sticky goo (slow user down in goo, or freezes)
|
||||
7. Follow goo
|
||||
*/
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "L4D2 Feed The Trolls",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue