Minor ftt spawn logic changing

This commit is contained in:
Jackzie 2022-05-14 10:40:58 -05:00
parent 29b7d12060
commit 6c63e69abf
No known key found for this signature in database
GPG key ID: 1E834FE36520537A
13 changed files with 139 additions and 37 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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) {

View file

@ -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) {

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -58,6 +58,7 @@ enum SpecialInternalFlags {
SPI_KillOnSpawn = 1
}
#define MODEL_CAR "models/props_vehicles/cara_95sedan.mdl"
#include <feedthetrolls/base>
#include <feedthetrolls/trolls>

View file

@ -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.

View file

@ -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",