This commit is contained in:
Jackz 2022-07-08 18:48:22 -05:00
parent a941649f9a
commit b62f9fd542
No known key found for this signature in database
GPG key ID: E0BBD94CF657F603
17 changed files with 503 additions and 479 deletions

View file

@ -62,4 +62,26 @@
}
}
}
"c11m4_terminal"
{
"spawnpoint" "3081.824951 4571.367187 152.031250"
"ents"
{
"ENTRANCE_BLOCKER"
{
"origin" "2700.844482 1865.502807 177.313140"
"scale" "200 100 200"
}
"fire"
{
"origin" "2700.844482 1865.502807 179.313140"
"type" "env_fire"
"scale" "1.0 256 8"
}
}
"inputs"
{
"checkpoint_entrance" "Kill"
}
}
}

View file

@ -1492,6 +1492,82 @@
"door_exitr" "Lock"
}
}
"c11m4_terminal"
{
"spawnpoint" "-482.813659 3566.486572 296.031250"
"sets"
{
"terminal"
{
"spawnpoint" "1811.834716 1570.712402 264.607604"
}
}
"ents"
{
"BAG_HOLE_A"
{
"origin" "382.787200 2708.387207 40.031250"
"rotation" "0.000000 -174.077285 0.000000"
"type" "prop_dynamic"
"model" "props_unique/airport/luggage_pile1.mdl"
}
"BAG_HOLE_B"
{
"origin" "402.307434 2415.856201 40.031250"
"rotation" "0.000000 -174.077285 0.000000"
"type" "prop_dynamic"
"model" "props_unique/airport/luggage_pile1.mdl"
}
"BAG_HOLE_C"
{
"origin" "401.137786 2110.304199 40.031250"
"rotation" "0.000000 -174.077285 0.000000"
"type" "prop_dynamic"
"model" "props_unique/airport/luggage_pile1.mdl"
}
"DETECTOR_NO_DETECT"
{
"origin" "1023.898742 1750.977294 16.031250"
"scale" "20 650 300"
"set" "terminal"
}
"DETECTOR_PROP"
{
"origin" "1030.929931 1755.157714 37.031250"
"rotation" "90 0 0"
"type" "prop_dynamic"
"model" "props_interiors\chairs_airport.mdl"
"set" "terminal"
}
"lol"
{
"origin" "2350.819335 1851.536376 152.235565"
"rotation" "10.137485 -178.424728 15.000000"
"type" "prop_dynamic"
"model" "survivors/survivor_teenangst.mdl"
"set" "terminal"
}
}
"inputs"
{
"van_blocker" "Kill"
"van_start_relay" "Trigger"
"!3098419" "Kill"
"breakwall01" "Break"
"func_breakable" "Kill"
"breakwall01_illusionary" "Kill"
"!6802112" "Open"
"!6765323" "Kill"
"!6765365" "Kill"
"securityalarmlight1" "TurnOn"
"securityspotlight1" "LightOn"
"securityrotator1" "StopSound"
"securityalarmbase1" "Skin 1"
"securityalarmsprite1" "ShowSprite"
"alarm_safety_relay" "Kill"
"env_soundscape" "Kill"
}
}
"c12m1_hilltop"
{
"sets"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -31,7 +31,68 @@ public void OnClientPutInServer(int client) {
if(IsTrollActive(client, "Voice Mute"))
BaseComm_SetClientMute(client, true);
SDKHook(client, SDKHook_OnTakeDamage, Event_TakeDamage);
SDKHook(client, SDKHook_OnTakeDamageAlive, NerfGun_OnTakeDamage);
}
public void OnEntityCreated(int entity, const char[] classname) {
if(entity >= MaxClients) {
if(StrEqual(classname, "infected", false))
SDKHook(entity, SDKHook_OnTakeDamageAlive, NerfGun_OnTakeDamage);
else if(StrContains(classname, "_projectile", true) > -1 ) {
RequestFrame(EntityCreateCallback, entity);
}
}
}
void EntityCreateCallback(int entity) {
if(!HasEntProp(entity, Prop_Send, "m_hOwnerEntity") || !IsValidEntity(entity)) return;
static char class[16];
static int badThrowID;
if(badThrowID == 0) badThrowID = GetTrollID("Bad Throw");
GetEntityClassname(entity, class, sizeof(class));
int entOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
if(entOwner > 0 && entOwner <= MaxClients) {
if(Trolls[badThrowID].IsActive(entOwner)) {
static float pos[3];
GetClientEyePosition(entOwner, pos);
if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_1) && StrContains(class, "vomitjar", true) > -1) {
AcceptEntityInput(entity, "Kill");
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
L4D_CTerrorPlayer_OnVomitedUpon(entOwner, entOwner);
EmitSoundToAll("weapons/ceda_jar/ceda_jar_explode.wav", entOwner);
FindClosestClient(entOwner, false, pos);
}
SpawnItem("vomitjar", pos);
} else if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_2) && StrContains(class, "molotov", true) > -1) {
// Burn them if no one near :)
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
GetClientAbsOrigin(entOwner, pos);
if(IsAnyPlayerNear(entOwner, 500.0)) {
AcceptEntityInput(entity, "Kill");
EmitSoundToAll("weapons/molotov/molotov_detonate_1.wav", entOwner);
} else { // or delete if there is
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
}
} else {
SpawnItem("molotov", pos);
AcceptEntityInput(entity, "Kill");
}
} else if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_3) && StrContains(class, "pipe_bomb", true) > -1) {
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
ExplodeProjectile(entity);
}
SpawnItem("pipe_bomb", pos);
}
} else if(Trolls[slipperyShoesIndex].IsActive(entOwner)) {
if(Trolls[slipperyShoesIndex].activeFlagClients[entOwner] & 4) {
L4D_StaggerPlayer(entOwner, entOwner, NULL_VECTOR);
}
}
}
}
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) {
int userid = event.GetInt("userid");
if(spIsActive)
@ -593,17 +654,22 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
return Plugin_Continue;
}
public Action NerfGun_OnTakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) {
static int nerfGunIndex;
if(nerfGunIndex == 0) nerfGunIndex = GetTrollID("Nerf Gun");
if(attacker > 0 && attacker <= MaxClients && GetClientTeam(attacker) == 2 && Trolls[nerfGunIndex].IsActive(attacker)) {
damage = 0.0;
return Plugin_Changed;
}
return Plugin_Continue;
}
public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) {
//Stop FF from marked:
static int reverseFF, nerfGunIndex;
static int reverseFF;
if(reverseFF == 0) reverseFF = GetTrollID("Reverse FF");
if(nerfGunIndex == 0) nerfGunIndex = GetTrollID("Nerf Gun");
if(attacker > 0 && attacker <= MaxClients) {
if(GetClientTeam(attacker) == 4 && IsFakeClient(attacker)) return Plugin_Continue;
else if(Trolls[nerfGunIndex].IsActive(attacker)) {
damage = 0.0;
return Plugin_Changed;
}
}
if(attacker > 0 && victim <= MaxClients && attacker <= MaxClients && IsClientInGame(attacker) && IsPlayerAlive(attacker)) {
@ -787,62 +853,6 @@ public void Event_WitchVictimSet(Event event, const char[] name, bool dontBroadc
}
}
public void OnEntityCreated(int entity, const char[] classname) {
if(IsValidEntity(entity) && StrContains(classname, "_projectile", true) > -1 ) {
RequestFrame(EntityCreateCallback, entity);
}
}
void EntityCreateCallback(int entity) {
if(!HasEntProp(entity, Prop_Send, "m_hOwnerEntity") || !IsValidEntity(entity)) return;
static char class[16];
static int badThrowID;
if(badThrowID == 0) badThrowID = GetTrollID("Bad Throw");
GetEntityClassname(entity, class, sizeof(class));
int entOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
if(entOwner > 0 && entOwner <= MaxClients) {
if(Trolls[badThrowID].IsActive(entOwner)) {
static float pos[3];
GetClientEyePosition(entOwner, pos);
if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_1) && StrContains(class, "vomitjar", true) > -1) {
AcceptEntityInput(entity, "Kill");
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
L4D_CTerrorPlayer_OnVomitedUpon(entOwner, entOwner);
EmitSoundToAll("weapons/ceda_jar/ceda_jar_explode.wav", entOwner);
FindClosestClient(entOwner, false, pos);
}
SpawnItem("vomitjar", pos);
} else if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_2) && StrContains(class, "molotov", true) > -1) {
// Burn them if no one near :)
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
GetClientAbsOrigin(entOwner, pos);
if(IsAnyPlayerNear(entOwner, 500.0)) {
AcceptEntityInput(entity, "Kill");
EmitSoundToAll("weapons/molotov/molotov_detonate_1.wav", entOwner);
} else { // or delete if there is
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
}
} else {
SpawnItem("molotov", pos);
AcceptEntityInput(entity, "Kill");
}
} else if(Trolls[badThrowID].IsFlagActive(entOwner, Flag_3) && StrContains(class, "pipe_bomb", true) > -1) {
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() <= hBadThrowHitSelf.FloatValue) {
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
ExplodeProjectile(entity);
}
SpawnItem("pipe_bomb", pos);
}
} else if(Trolls[slipperyShoesIndex].IsActive(entOwner)) {
if(Trolls[slipperyShoesIndex].activeFlagClients[entOwner] & 4) {
L4D_StaggerPlayer(entOwner, entOwner, NULL_VECTOR);
}
}
}
}
public Action L4D2_MeleeGetDamageForVictim(int client, int weapon, int victim, float &damage) {
static int dullMeleeID;
if(!dullMeleeID) dullMeleeID = GetTrollID("Dull Melee");

View file

@ -297,7 +297,7 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
SetEntProp(primaryWpn, Prop_Send, "m_iClip1", GetRandomInt(0, maxCap));
}
}
} else if(~modifier & TrollMod_Constant) {
} else if(~modifier & TrollMod_Constant) {
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
#if defined DEBUG
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");

View file

@ -12,7 +12,7 @@ char g_currentMap[64];
char nextRoundMap[64];
// Legacy:
bool isNavBlockersEnabled, isPropsEnabled, isPortalsEnabled
bool isNavBlockersEnabled = true, isPropsEnabled = true, isPortalsEnabled = true
static int _debugFlags = BaseDebug_Server;
@ -23,9 +23,9 @@ enum {
BaseDebug_ChatAll = 4
}
static bool ents_NavBlockers;
static bool ents_Props;
static bool ents_Portals;
static bool ents_NavBlockers = true;
static bool ents_Props = true;
static bool ents_Portals = true;
int g_iLaserIndex;
@ -50,23 +50,23 @@ methodmap BaseGame {
}
public void PrintToServer(const char[] format, any ...) {
VFormat(buffer, sizeof(buffer), format, 2);
VFormat(buffer, sizeof(buffer), format, 3);
PrintToServer("[%s] %s", GAMEMODE_NAME, buffer);
}
public void Warn(const char[] format, any ...) {
VFormat(buffer, sizeof(buffer), format, 2);
VFormat(buffer, sizeof(buffer), format, 3);
PrintToServer("[%s::WARN] %s", GAMEMODE_NAME, buffer);
}
public void Broadcast(const char[] format, any ...) {
VFormat(buffer, sizeof(buffer), format, 2);
VFormat(buffer, sizeof(buffer), format, 3);
PrintToChatAll("[%s] %s", GAMEMODE_NAME, buffer);
}
public void Debug(const char[] format, any ...) {
if(_debugFlags == BaseDebug_None) return;
VFormat(buffer, sizeof(buffer), format, 2);
VFormat(buffer, sizeof(buffer), format, 3);
if(_debugFlags & BaseDebug_Server)
PrintToServer("[%s/debug] %s", GAMEMODE_NAME, buffer);
if(_debugFlags & BaseDebug_ChatAll)
@ -77,7 +77,7 @@ methodmap BaseGame {
public void DebugConsole(const char[] format, any ...) {
if(_debugFlags == BaseDebug_None) return;
VFormat(buffer, sizeof(buffer), format, 2);
VFormat(buffer, sizeof(buffer), format, 3);
PrintToConsoleAll("[%s/debug] %s", GAMEMODE_NAME, buffer);
}
@ -226,12 +226,12 @@ methodmap PeekCamera {
}
public void Destroy() {
if(seekerCam == INVALID_ENT_REFERENCE || !IsValidEntity(seekerCam)) {
seekerTarget = 0;
if(seekerCam != INVALID_ENT_REFERENCE && IsValidEntity(seekerCam)) {
AcceptEntityInput(seekerCam, "Disable");
AcceptEntityInput(seekerCam, "Kill");
seekerCam = INVALID_ENT_REFERENCE
}
seekerTarget = 0;
}
}

View file

@ -30,12 +30,13 @@ methodmap GameConVarStorage < StringMap {
}
methodmap GameConVar < ConVar {
methodmap GameConVar __nullable__ < ConVar {
public GameConVar(const char[] name) {
return view_as<GameConVar>(FindConVar(name));
}
public void RecordInt(int value, GameConVarStorage storage) {
if(this == null) return;
if(storage != null) {
this.GetName(buffer, sizeof(buffer));
storage.SetValue(buffer, float(value));
@ -44,6 +45,7 @@ methodmap GameConVar < ConVar {
}
public void RecordFloat(float value, GameConVarStorage storage) {
if(this == null) return;
if(storage != null) {
this.GetName(buffer, sizeof(buffer));
storage.SetValue(buffer, value);
@ -52,6 +54,7 @@ methodmap GameConVar < ConVar {
}
public void RecordString(const char[] value, GameConVarStorage storage) {
if(this == null) return;
if(storage != null) {
char prevValue[32];
this.GetName(buffer, sizeof(buffer));

View file

@ -0,0 +1,205 @@
#if !defined ENT_PROP_NAME
#define ENT_PROP_NAME "cprop"
#endif
#if !defined ENT_BLOCKER_NAME
#define ENT_BLOCKER_NAME "cblocker"
#endif
#if !defined ENT_PORTAL_NAME
#define ENT_PORTAL_NAME "cportal"
#endif
#if !defined ENT_ENV_NAME
#define ENT_ENV_NAME "cenv"
#endif
void DeleteCustomEnts() {
EntFire(ENT_PROP_NAME, "Kill");
EntFire(ENT_BLOCKER_NAME, "Kill");
EntFire(ENT_PORTAL_NAME, "Kill");
EntFire(ENT_ENV_NAME, "Kill");
}
stock int CreateEnvBlockerScaled(const char[] entClass, const float pos[3], const float scale[3] = { 5.0, 5.0, 5.0 }, bool enabled = true) {
int entity = CreateEntityByName(entClass);
DispatchKeyValue(entity, "targetname", ENT_BLOCKER_NAME);
DispatchKeyValue(entity, "initialstate", "1");
DispatchKeyValue(entity, "BlockType", "0");
static float mins[3];
mins = scale;
NegateVector(mins);
DispatchKeyValueVector(entity, "boxmins", mins);
DispatchKeyValueVector(entity, "boxmaxs", scale);
DispatchKeyValueVector(entity, "mins", mins);
DispatchKeyValueVector(entity, "maxs", scale);
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
if(DispatchSpawn(entity)) {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn blocker scaled %.1f %.1f %.1f scale [%.0f %.0f %.0f]", pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
if(enabled)
AcceptEntityInput(entity, "Enable");
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 0, 255}, 0);
#endif
return entity;
} else {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("FAILED: spawn blocker scaled %.1f %.1f %.1f scale [%.0f %.0f %.0f]", pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
}
return -1;
}
enum PortalType {
Portal_Relative,
Portal_Teleport
}
enum struct EntData {
PortalType portalType;
float portalOffsets[3];
}
EntData entData[2048];
stock int CreatePortal(PortalType type, const char model[64], const float pos[3], const float offset[3] = { 40.0, 40.0, 0.0 }, const float scale[3] = { 5.0, 5.0, 5.0 }) {
int entity = CreateEntityByName("trigger_multiple");
if(entity == -1) return -1;
DispatchKeyValue(entity, "spawnflags", "513");
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", ENT_PORTAL_NAME);
DispatchKeyValue(entity, "wait", "0");
if(DispatchSpawn(entity)) {
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
static float mins[3];
mins = scale;
NegateVector(mins);
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
SetEntProp(entity, Prop_Send, "m_nSolidType", 2);
HookSingleEntityOutput(entity, "OnStartTouch", OnPortalTouch, false);
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 255, 255}, 0);
#endif
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn portal %d - pos %.1f %.1f %.1f - scale %.1f %.1f %.1f", entity, pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
AcceptEntityInput(entity, "Enable");
entData[entity].portalOffsets = NULL_VECTOR;
// Convert relative offset to one based off full scale:
entData[entity].portalType = type;
if(type == Portal_Relative) {
if(offset[0] != 0.0) entData[entity].portalOffsets[0] = (scale[0] * 2) + offset[0];
if(offset[1] != 0.0) entData[entity].portalOffsets[1] = (scale[1] * 2) + offset[1];
if(offset[2] != 0.0) entData[entity].portalOffsets[2] = (scale[2] * 2) + offset[2];
} else {
entData[entity].portalOffsets = offset;
}
return entity;
}
return -1;
}
void OnPortalTouch(const char[] output, int caller, int activator, float delay) {
if(entData[caller].portalType == Portal_Relative) {
float pos[3];
GetClientAbsOrigin(activator, pos);
float ang[3];
GetClientAbsAngles(activator, ang);
if(ang[0] < 0) pos[0] -= entData[caller].portalOffsets[0];
else pos[0] += entData[caller].portalOffsets[0];
if(ang[1] < 0) pos[1] -= entData[caller].portalOffsets[1];
else pos[1] += entData[caller].portalOffsets[1];
if(ang[2] < 0) pos[2] -= entData[caller].portalOffsets[2];
else pos[2] += entData[caller].portalOffsets[2];
TeleportEntity(activator, pos, NULL_VECTOR, NULL_VECTOR);
} else {
TeleportEntity(activator, entData[caller].portalOffsets, NULL_VECTOR, NULL_VECTOR);
}
}
stock int StartPropCreate(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = CreateEntityByName(entClass);
if(entity == -1) return -1;
DispatchKeyValue(entity, "model", model);
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", ENT_PROP_NAME);
DispatchKeyValue(entity, "disableshadows", "1");
TeleportEntity(entity, pos, ang, NULL_VECTOR);
return entity;
}
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = StartPropCreate(entClass, model, pos, ang);
if(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;
}
return -1;
}
stock int CreateDummy(const char[] model, const char[] anim, const float pos[3], const float ang[3] = NULL_VECTOR) {
int entity = StartPropCreate("commentary_dummy", model, pos, ang);
if(entity == -1) return -1;
DispatchKeyValue(entity, "targetname", ENT_PROP_NAME);
DispatchKeyValue(entity, "LookAtPlayers", "Yes");
DispatchKeyValue(entity, "StartingWeapons", "weapon_rifle_ak47");
DispatchKeyValue(entity, "StartingAnim", anim); //idle_calm_rifle
DispatchKeyValueFloat(entity, "LookAtPlayers", 40.0);
DispatchSpawn(entity);
return entity;
}
stock int CreateFire(const float pos[3], float damage = 10.0, float size = 256.0, float attack = 4.0) {
int entity = CreateEntityByName("env_fire");
if(entity == -1) return -1;
DispatchKeyValue(entity, "spawnflags", "13");
DispatchKeyValue(entity, "targetname", ENT_ENV_NAME);
DispatchKeyValueFloat(entity, "firesize", size);
DispatchKeyValueFloat(entity, "fireattack", attack);
DispatchKeyValueFloat(entity, "damagescale", damage);
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
DispatchSpawn(entity);
AcceptEntityInput(entity, "Enable");
AcceptEntityInput(entity, "StartFire");
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn env_fire at %.1f %.1f %.1f", pos[0], pos[1], pos[2]);
#endif
return entity;
}
// Taken from silver's https://forums.alliedmods.net/showthread.php?p=1658873
stock int CreateDynamicLight(float vOrigin[3], float vAngles[3], int color, float brightness, int style = 0) {
int entity = CreateEntityByName("light_dynamic");
if( entity == -1)
return -1;
DispatchKeyValue(entity, "_light", "0 0 0 255");
DispatchKeyValue(entity, "brightness", "1");
DispatchKeyValueFloat(entity, "spotlight_radius", 32.0);
DispatchKeyValueFloat(entity, "distance", brightness);
DispatchKeyValue(entity, "targetname", ENT_ENV_NAME);
DispatchKeyValueFloat(entity, "style", float(style));
SetEntProp(entity, Prop_Send, "m_clrRender", color);
if(DispatchSpawn(entity)) {
TeleportEntity(entity, vOrigin, vAngles, NULL_VECTOR);
AcceptEntityInput(entity, "TurnOn");
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn dynamic light %.1f %.1f %.1f", vOrigin[0], vOrigin[1], vOrigin[2]);
#endif
return entity;
}
return -1;
}
int GetHammerId(int entity) {
return HasEntProp(entity, Prop_Data, "m_iHammerID") ? GetEntProp(entity, Prop_Data, "m_iHammerID") : -1;
}

View file

@ -66,7 +66,7 @@ public Action Command_GuessWho(int client, int args) {
if(arg[0] == 'f') {
InitGamemode();
}
SetupEntities(isNavBlockersEnabled, isPropsEnabled, isPortalsEnabled);
SetupEntities(Game.Blockers, Game.Props, Game.Portals);
ReplyToCommand(client, "Reloaded map from config");
} else {
ReplyToCommand(client, "Error occurred while reloading map file");
@ -101,7 +101,7 @@ public Action Command_GuessWho(int client, int args) {
ReplyToCommand(client, "Warn: %s/%s has 0 saved movement locations", g_currentMap, g_currentSet);
}
Game.Cleanup();
SetupEntities(isNavBlockersEnabled, isPropsEnabled, isPortalsEnabled);
SetupEntities(Game.Blockers, Game.Props, Game.Portals);
PrintToChatAll("[GuessWho] Map set has been changed to \"%s\"", g_currentSet);
return Plugin_Handled;
}
@ -115,18 +115,18 @@ public Action Command_GuessWho(int client, int args) {
bool isUnknown = true;
if(doAll || StrEqual(type, "blockers", false)) {
if(isNavBlockersEnabled) {
if(Game.Blockers) {
EntFire(GAMEMODE_BLOCKER_NAME, "Disable");
ReplyToCommand(client, "Disabled all custom gamemode blockers");
} else {
EntFire(GAMEMODE_BLOCKER_NAME, "Enable");
ReplyToCommand(client, "Enabled all custom gamemode blockers");
}
isNavBlockersEnabled = !isNavBlockersEnabled;
Game.Blockers = !Game.Blockers;
isUnknown = false;
}
if(doAll || StrEqual(type, "props", false)) {
if(isPropsEnabled) {
if(Game.Props) {
EntFire(GAMEMODE_PROP_NAME, "Disable");
EntFire(GAMEMODE_PROP_NAME, "DisableCollision");
ReplyToCommand(client, "Disabled all custom gamemode props");
@ -135,10 +135,10 @@ public Action Command_GuessWho(int client, int args) {
EntFire(GAMEMODE_PROP_NAME, "EnableCollision");
ReplyToCommand(client, "Enabled all custom gamemode props");
}
isPropsEnabled = !isPropsEnabled;
Game.Props = !Game.Props;
isUnknown = false;
}
if(isUnknown) ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', 'portals', or 'all'");
if(isUnknown) ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', or 'all'");
} else if(StrEqual(subcmd, "clear", false)) {
static char arg[16];
GetCmdArg(2, arg, sizeof(arg));
@ -151,7 +151,7 @@ public Action Command_GuessWho(int client, int args) {
} else if(StrEqual(arg, "blockers")) {
EntFire(GAMEMODE_BLOCKER_NAME, "kill");
ReplyToCommand(client, "Removed all custom gamemode blockers");
} else ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', 'portals', or 'all'");
} else ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', or 'all'");
} else if(StrEqual(subcmd, "settime")) {
int prev = Game.MapTime;
static char arg[16];
@ -292,7 +292,7 @@ public Action Command_GuessWho(int client, int args) {
else
ReplyToCommand(client, "Has Spawnpoint: no (possibly map spawn %f %f %f)", mapConfig.spawnpoint[0], mapConfig.spawnpoint[1], mapConfig.spawnpoint[2]);
ReplyToCommand(client, "Map Time: %d", mapConfig.mapTime);
ReplyToCommand(client, "Flow Bounds: (%f, %f)", flowMin, flowMax);
ReplyToCommand(client, "Flow Bounds: (%f, %f)", movePoints.MinFlow, movePoints.MaxFlow);
} else {
ReplyToCommand(client, "Unknown option. Leave blank for help");
}
@ -383,6 +383,9 @@ public Action Command_Join(int client, int args) {
L4D_RespawnPlayer(client);
TeleportEntity(client, tpLoc, NULL_VECTOR, NULL_VECTOR);
CheatCommand(client, "give", "gnome");
if(!ArePlayersJoining()) {
InitGamemode();
}
}
return Plugin_Handled;
}

View file

@ -1,174 +1,8 @@
#define GAMEMODE_PROP_NAME "gwprop"
#define GAMEMODE_BLOCKER_NAME "gwblocker"
stock int CreateEnvBlockerBox(const float pos[3], bool enabled = true) {
int entity = CreateEntityByName("env_physics_blocker");
if(entity == -1) return -1;
DispatchKeyValue(entity, "targetname", GAMEMODE_BLOCKER_NAME);
DispatchKeyValue(entity, "initialstate", "1");
DispatchKeyValue(entity, "BlockType", "0");
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
if(DispatchSpawn(entity)) {
if(enabled)
AcceptEntityInput(entity, "Enable");
return entity;
}
return -1;
}
stock int CreateEnvBlockerScaled(const char[] entClass, const float pos[3], const float scale[3] = { 5.0, 5.0, 5.0 }, bool enabled = true) {
int entity = CreateEntityByName(entClass);
DispatchKeyValue(entity, "targetname", GAMEMODE_BLOCKER_NAME);
DispatchKeyValue(entity, "initialstate", "1");
DispatchKeyValue(entity, "BlockType", "0");
static float mins[3];
mins = scale;
NegateVector(mins);
DispatchKeyValueVector(entity, "boxmins", mins);
DispatchKeyValueVector(entity, "boxmaxs", scale);
DispatchKeyValueVector(entity, "mins", mins);
DispatchKeyValueVector(entity, "maxs", scale);
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
if(DispatchSpawn(entity)) {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn blocker scaled %.1f %.1f %.1f scale [%.0f %.0f %.0f]", pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
if(enabled)
AcceptEntityInput(entity, "Enable");
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 0, 255}, 0);
#endif
return entity;
}
return -1;
}
enum PortalType {
Portal_Relative,
Portal_Teleport
}
PortalType entityPortalType[2048];
float entityPortalOffsets[2048][3];
stock int CreatePortal(PortalType type, const char model[64], const float pos[3], const float offset[3] = { 40.0, 40.0, 0.0 }, const float scale[3] = { 5.0, 5.0, 5.0 }) {
int entity = CreateEntityByName("trigger_multiple");
if(entity == -1) return -1;
DispatchKeyValue(entity, "spawnflags", "513");
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", "gwportal");
DispatchKeyValue(entity, "wait", "0");
if(DispatchSpawn(entity)) {
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
static float mins[3];
mins = scale;
NegateVector(mins);
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
SetEntProp(entity, Prop_Send, "m_nSolidType", 2);
HookSingleEntityOutput(entity, "OnStartTouch", OnPortalTouch, false);
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 255, 255}, 0);
#endif
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn portal %d - pos %.1f %.1f %.1f - scale %.1f %.1f %.1f", entity, pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
AcceptEntityInput(entity, "Enable");
entityPortalOffsets[entity] = NULL_VECTOR;
// Convert relative offset to one based off full scale:
entityPortalType[entity] = type;
if(type == Portal_Relative) {
if(offset[0] != 0.0) entityPortalOffsets[entity][0] = (scale[0] * 2) + offset[0];
if(offset[1] != 0.0) entityPortalOffsets[entity][1] = (scale[1] * 2) + offset[1];
if(offset[2] != 0.0) entityPortalOffsets[entity][2] = (scale[2] * 2) + offset[2];
} else {
entityPortalOffsets[entity] = offset;
}
return entity;
}
return -1;
}
void OnPortalTouch(const char[] output, int caller, int activator, float delay) {
if(entityPortalType[caller] == Portal_Relative) {
float pos[3];
GetClientAbsOrigin(activator, pos);
float ang[3];
GetClientAbsAngles(activator, ang);
if(ang[0] < 0) pos[0] -= entityPortalOffsets[caller][0];
else pos[0] += entityPortalOffsets[caller][0];
if(ang[1] < 0) pos[1] -= entityPortalOffsets[caller][1];
else pos[1] += entityPortalOffsets[caller][1];
if(ang[2] < 0) pos[2] -= entityPortalOffsets[caller][2];
else pos[2] += entityPortalOffsets[caller][2];
TeleportEntity(activator, pos, NULL_VECTOR, NULL_VECTOR);
} else {
TeleportEntity(activator, entityPortalOffsets[caller], NULL_VECTOR, NULL_VECTOR);
}
}
stock int StartPropCreate(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = CreateEntityByName(entClass);
if(entity == -1) return -1;
DispatchKeyValue(entity, "model", model);
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", GAMEMODE_PROP_NAME);
DispatchKeyValue(entity, "disableshadows", "1");
TeleportEntity(entity, pos, ang, NULL_VECTOR);
return entity;
}
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = StartPropCreate(entClass, model, pos, ang);
if(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;
}
return -1;
}
stock int CreateDummy(const char[] model, const char[] anim, const float pos[3], const float ang[3] = NULL_VECTOR) {
int entity = StartPropCreate("commentary_dummy", model, pos, ang);
if(entity == -1) return -1;
DispatchKeyValue(entity, "LookAtPlayers", "Yes");
DispatchKeyValue(entity, "StartingWeapons", "weapon_rifle_ak47");
DispatchKeyValue(entity, "StartingAnim", anim); //idle_calm_rifle
DispatchKeyValueFloat(entity, "LookAtPlayers", 40.0);
DispatchSpawn(entity);
return entity;
}
// Taken from silver's https://forums.alliedmods.net/showthread.php?p=1658873
stock int CreateDynamicLight(float vOrigin[3], float vAngles[3], int color, float brightness, int style = 0) {
int entity = CreateEntityByName("light_dynamic");
if( entity == -1)
return -1;
DispatchKeyValue(entity, "_light", "0 0 0 255");
DispatchKeyValue(entity, "brightness", "1");
DispatchKeyValueFloat(entity, "spotlight_radius", 32.0);
DispatchKeyValueFloat(entity, "distance", brightness);
DispatchKeyValue(entity, "targetname", "gwlamp");
DispatchKeyValueFloat(entity, "style", float(style));
SetEntProp(entity, Prop_Send, "m_clrRender", color);
if(DispatchSpawn(entity)) {
TeleportEntity(entity, vOrigin, vAngles, NULL_VECTOR);
AcceptEntityInput(entity, "TurnOn");
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn dynamic light %.1f %.1f %.1f", vOrigin[0], vOrigin[1], vOrigin[2]);
#endif
return entity;
}
return -1;
}
#define ENT_PROP_NAME "gwprop"
#define ENT_BLOCKER_NAME "gwblocker"
#define ENT_PORTAL_NAME "gwportal"
#define ENT_ENV_NAME "gwenv"
#include <gamemodes/ents>
stock void CheatCommand(int client, const char[] command, const char[] argument1) {
int userFlags = GetUserFlagBits(client);
@ -180,11 +14,12 @@ stock void CheatCommand(int client, const char[] command, const char[] argument1
SetUserFlagBits(client, userFlags);
}
stock void EntFire(const char[] name, const char[] input) {
static char targetname[64];
static char cmd[32];
#if defined DEBUG_LOG_MAPSTART
PrintToServer("[GuessWho] EntFire: %s \"%s\"", name, input);
PrintToServer("EntFire: %s \"%s\"", name, input);
#endif
int len = SplitString(input, " ", cmd, sizeof(cmd));
if(len > -1) SetVariantString(input[len]);
@ -202,6 +37,7 @@ stock void EntFire(const char[] name, const char[] input) {
if(StrEqual(targetname, name, false)) {
if(len > -1) AcceptEntityInput(i, cmd);
else AcceptEntityInput(i, input);
} else {
GetEntityClassname(i, targetname, sizeof(targetname));
if(StrEqual(targetname, name, false)) {
@ -214,10 +50,6 @@ stock void EntFire(const char[] name, const char[] input) {
}
}
int GetHammerId(int entity) {
return HasEntProp(entity, Prop_Data, "m_iHammerID") ? GetEntProp(entity, Prop_Data, "m_iHammerID") : -1;
}
void SetupEntities(bool blockers = true, bool props = true, bool portals = true) {
@ -229,6 +61,7 @@ void SetupEntities(bool blockers = true, bool props = true, bool portals = true)
SetEntProp(dummy, Prop_Send, "m_CollisionGroup", 0);
SetEntProp(dummy, Prop_Send, "movetype", MOVETYPE_NONE);
}
EntFire("info_changelevel", "Kill");
#endif
if(mapConfig.entities != null) {
PrintToServer("[GuessWho] Deploying %d custom entities (Set: %s) (blockers:%b props:%b portals:%b)", mapConfig.entities.Length, g_currentSet, blockers, props, portals);
@ -240,27 +73,27 @@ void SetupEntities(bool blockers = true, bool props = true, bool portals = true)
if(StrEqual(config.type, "env_physics_blocker")) {
if(blockers && CreateEnvBlockerScaled(config.type, config.origin, config.scale, isNavBlockersEnabled) == -1) {
PrintToServer("[H&S:WARN] Failed to spawn blocker [type=%s] at (%.1f,%.1f, %.1f)", config.type, config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn blocker [type=%s] at (%.1f,%.1f, %.1f)", config.type, config.origin[0], config.origin[1], config.origin[2]);
}
} else if(StrEqual(config.type, "_relportal")) {
if(portals && CreatePortal(Portal_Relative, config.model, config.origin, config.offset, config.scale) == -1) {
PrintToServer("[H&S:WARN] Failed to spawn rel portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn rel portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]);
}
} else if(StrEqual(config.type, "_portal")) {
if(portals && CreatePortal(Portal_Teleport, config.model, config.origin, config.offset, config.scale) == -1) {
PrintToServer("[H&S:WARN] Failed to spawn portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]);
}
} else if(StrEqual(config.type, "_lantern")) {
int parent = CreateProp("prop_dynamic", config.model, config.origin, config.rotation);
if(parent == -1) {
PrintToServer("[H&S:WARN] Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]);
} else {
float pos[3];
pos = config.origin;
pos[2] += 15.0;
int child = CreateDynamicLight(pos, config.rotation, GetColorInt(255, 255, 242), 80.0, 11);
if(child == -1) {
PrintToServer("[GuessWho] Failed to spawn light source for _lantern");
Game.Warn("Failed to spawn light source for _lantern");
} else {
SetParent(child, parent);
TeleportEntity(parent, config.origin, NULL_VECTOR, NULL_VECTOR);
@ -268,11 +101,15 @@ void SetupEntities(bool blockers = true, bool props = true, bool portals = true)
}
} else if(StrEqual(config.type, "_dummy")) {
if(CreateDummy(config.model, "hitby_tankpunch", config.origin, config.rotation) == -1) {
PrintToServer("[H&S:WARN] Failed to spawn dummy [model=%s] at (%.1f,%.1f, %.1f)", config.model, config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn dummy [model=%s] at (%.1f,%.1f, %.1f)", config.model, config.origin[0], config.origin[1], config.origin[2]);
}
}else if(props) {
} else if(StrEqual(config.type, "env_fire")) {
if(props && CreateFire(config.origin, config.scale[0], config.scale[1], config.scale[2]) == -1) {
Game.Warn("Failed to spawn env_fire at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]);
}
} else if(props) {
if(CreateProp(config.type, config.model, config.origin, config.rotation) == -1) {
PrintToServer("[H&S:WARN] Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]);
Game.Warn("Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]);
}
}
}

View file

@ -116,6 +116,11 @@ methodmap GuessWhoGame < BaseGame {
public set(int seconds) {
Format(buffer, sizeof(buffer), "g_ModeScript.MutationState.MaxTime = %d", seconds);
L4D2_ExecVScriptCode(buffer);
if(timesUpTimer != null) {
float remaining = float(seconds) - float(this.Tick);
delete timesUpTimer;
timesUpTimer = CreateTimer(remaining, Timer_TimesUp, _, TIMER_FLAG_NO_MAPCHANGE);
}
}
}
@ -124,6 +129,10 @@ methodmap GuessWhoGame < BaseGame {
}
public void End(GameState state) {
if(recordTimer != null) {
PrintToChatAll("Active recording stopped due to end of game. %d ready to save. \"/guesswho points save\" to save", movePoints.Length);
delete recordTimer;
}
if(acquireLocationsTimer != null) delete acquireLocationsTimer;
if(timesUpTimer != null) delete timesUpTimer;
if(hiderCheckTimer != null) delete hiderCheckTimer;
@ -135,7 +144,6 @@ methodmap GuessWhoGame < BaseGame {
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);
@ -147,22 +155,23 @@ methodmap GuessWhoGame < BaseGame {
CreateTimer(5.0, Timer_ResetAll);
}
public void Cleanup(bool entsOnly = false) {
EntFire("gwprop", "kill");
EntFire("gwblocker", "kill");
EntFire("gwportal", "kill");
// PeekCam.Destroy();
if(entsOnly) return;
public void Cleanup(bool noClearInv = false) {
DeleteCustomEnts();
PeekCam.Destroy();
if(recordTimer != null) {
delete recordTimer;
}
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i)) {
if(isEnabled)
if(!noClearInv && isEnabled)
ClearInventory(i);
SDKUnhook(i, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive);
SDKUnhook(i, SDKHook_WeaponDrop, OnWeaponDrop);
}
}
if(recordTimer != null) {
delete recordTimer;
if(moveTimers[i] != null) {
delete moveTimers[i];
}
}
}
@ -174,7 +183,7 @@ methodmap GuessWhoGame < BaseGame {
if(uid > 0) {
return GetClientOfUserId(uid);
} else {
PrintToServer("[GuessWho] Could not find real seeker, falling back to manual check");
Game.Debug("Mutation has no seeker, manually attempting to find seeker");
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i)) {
int entity = GetPlayerWeaponSlot(i, 1);
@ -187,6 +196,7 @@ methodmap GuessWhoGame < BaseGame {
}
}
}
Game.Debug("All attempts to find a seeker failed");
return -1;
}
@ -227,7 +237,11 @@ methodmap GuessWhoGame < BaseGame {
if(movePoints != null) {
delete movePoints;
}
movePoints = points;
if(points == null) {
movePoints = new MovePoints();
} else {
movePoints = points;
}
}
// Ignores seeker
@ -406,7 +420,7 @@ enum struct HiderDistQueue {
int time = GetTime();
if(time - this.lastVocalize > HIDER_AUTO_VOCALIZE_GRACE_TIME) {
this.lastVocalize = time;
int index = GetRandomInt(0, MAX_AUTO_VOCALIZATIONS);
int index = GetRandomInt(0, MAX_AUTO_VOCALIZATIONS - 1);
PerformScene(i, AUTO_VOCALIZATIONS[index]);
}
}

View file

@ -78,13 +78,13 @@ methodmap MovePoints < ArrayList {
min -= FLOW_BOUND_BUFFER;
max += FLOW_BOUND_BUFFER;
movePoints.SetBounds(flowMin, flowMax);
movePoints.SetBounds(min, max);
PrintToServer("[GuessWho] Loaded %d locations (bounds (%.0f, %.0f)) for %s/%s", movePoints.Length, min, max, map, set);
PrintToServer("[GuessWho] Loaded %d locations with bounds [%.0f, %.0f] for %s/%s", points.Length, min, max, map, set);
delete file;
return points;
}
PrintToServer("[GuessWho] OpenFile(r+) returned null for %s", buffer);
PrintToServer("[GuessWho] No point data for %s/%s", map, set);
return null;
}
@ -101,6 +101,7 @@ methodmap MovePoints < ArrayList {
}
public void GetRandomPoint(LocationMeta meta) {
if(this.Length == 0) return;
meta.runto = GetURandomFloat() < BOT_MOVE_RUN_CHANCE;
meta.attempts = 0;
this.GetArray(GetURandomInt() % this.Length, meta);

View file

@ -17,11 +17,25 @@ Action Timer_RecordPoints(Handle h, int i) {
return Plugin_Continue;
}
bool firstCheckDone = false;
Action Timer_WaitForPlayers(Handle h) {
if(!isEnabled) return Plugin_Stop;
if(!ArePlayersJoining()) {
Game.Debug("No players pending, ready to go");
if(!firstCheckDone) {
// Wait one more iteration
firstCheckDone = true;
} else {
firstCheckDone = false;
InitGamemode();
return Plugin_Stop;
}
}
Game.Debug("Waiting for players");
return Plugin_Continue;
}
Action Timer_CheckHiders(Handle h) {
static float pos[3];
for(int i = 1; i <= MaxClients; i++) {

View file

@ -1,172 +1,8 @@
stock int CreateEnvBlockerBox(const float pos[3], bool enabled = true) {
int entity = CreateEntityByName("env_physics_blocker");
if(entity == -1) return -1;
DispatchKeyValue(entity, "targetname", "hsblocker");
DispatchKeyValue(entity, "initialstate", "1");
DispatchKeyValue(entity, "BlockType", "0");
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
if(DispatchSpawn(entity)) {
if(enabled)
AcceptEntityInput(entity, "Enable");
return entity;
}
return -1;
}
stock int CreateEnvBlockerScaled(const char[] entClass, const float pos[3], const float scale[3] = { 5.0, 5.0, 5.0 }, bool enabled = true) {
int entity = CreateEntityByName(entClass);
DispatchKeyValue(entity, "targetname", "hsblocker");
DispatchKeyValue(entity, "initialstate", "1");
DispatchKeyValue(entity, "BlockType", "0");
static float mins[3];
mins = scale;
NegateVector(mins);
DispatchKeyValueVector(entity, "boxmins", mins);
DispatchKeyValueVector(entity, "boxmaxs", scale);
DispatchKeyValueVector(entity, "mins", mins);
DispatchKeyValueVector(entity, "maxs", scale);
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
if(DispatchSpawn(entity)) {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn blocker scaled %.1f %.1f %.1f scale [%.0f %.0f %.0f]", pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
if(enabled)
AcceptEntityInput(entity, "Enable");
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 0, 255}, 0);
#endif
return entity;
}
return -1;
}
enum PortalType {
Portal_Relative,
Portal_Teleport
}
PortalType entityPortalType[2048];
float entityPortalOffsets[2048][3];
stock int CreatePortal(PortalType type, const char model[64], const float pos[3], const float offset[3] = { 40.0, 40.0, 0.0 }, const float scale[3] = { 5.0, 5.0, 5.0 }) {
int entity = CreateEntityByName("trigger_multiple");
if(entity == -1) return -1;
DispatchKeyValue(entity, "spawnflags", "513");
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", "hsportal");
DispatchKeyValue(entity, "wait", "0");
if(DispatchSpawn(entity)) {
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
static float mins[3];
mins = scale;
NegateVector(mins);
SetEntPropVector(entity, Prop_Send, "m_vecMaxs", scale);
SetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
SetEntProp(entity, Prop_Send, "m_nSolidType", 2);
HookSingleEntityOutput(entity, "OnStartTouch", OnPortalTouch, false);
#if defined DEBUG_BLOCKERS
Effect_DrawBeamBoxRotatableToAll(pos, mins, scale, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {255, 0, 255, 255}, 0);
#endif
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn portal %d - pos %.1f %.1f %.1f - scale %.1f %.1f %.1f", entity, pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);
#endif
AcceptEntityInput(entity, "Enable");
entityPortalOffsets[entity] = NULL_VECTOR;
// Convert relative offset to one based off full scale:
entityPortalType[entity] = type;
if(type == Portal_Relative) {
if(offset[0] != 0.0) entityPortalOffsets[entity][0] = (scale[0] * 2) + offset[0];
if(offset[1] != 0.0) entityPortalOffsets[entity][1] = (scale[1] * 2) + offset[1];
if(offset[2] != 0.0) entityPortalOffsets[entity][2] = (scale[2] * 2) + offset[2];
} else {
entityPortalOffsets[entity] = offset;
}
return entity;
}
return -1;
}
void OnPortalTouch(const char[] output, int caller, int activator, float delay) {
if(entityPortalType[caller] == Portal_Relative) {
float pos[3];
GetClientAbsOrigin(activator, pos);
float ang[3];
GetClientAbsAngles(activator, ang);
if(ang[0] < 0) pos[0] -= entityPortalOffsets[caller][0];
else pos[0] += entityPortalOffsets[caller][0];
if(ang[1] < 0) pos[1] -= entityPortalOffsets[caller][1];
else pos[1] += entityPortalOffsets[caller][1];
if(ang[2] < 0) pos[2] -= entityPortalOffsets[caller][2];
else pos[2] += entityPortalOffsets[caller][2];
TeleportEntity(activator, pos, NULL_VECTOR, NULL_VECTOR);
} else {
TeleportEntity(activator, entityPortalOffsets[caller], NULL_VECTOR, NULL_VECTOR);
}
}
stock int StartPropCreate(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = CreateEntityByName(entClass);
if(entity == -1) return -1;
DispatchKeyValue(entity, "model", model);
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", "hsprop");
DispatchKeyValue(entity, "disableshadows", "1");
TeleportEntity(entity, pos, ang, NULL_VECTOR);
return entity;
}
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = StartPropCreate(entClass, model, pos, ang);
if(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;
}
return -1;
}
stock int CreateDummy(const char[] model, const char[] anim, const float pos[3], const float ang[3] = NULL_VECTOR) {
int entity = StartPropCreate("commentary_dummy", model, pos, ang);
if(entity == -1) return -1;
DispatchKeyValue(entity, "LookAtPlayers", "Yes");
DispatchKeyValue(entity, "StartingWeapons", "weapon_rifle_ak47");
DispatchKeyValue(entity, "StartingAnim", anim); //idle_calm_rifle
DispatchKeyValueFloat(entity, "LookAtPlayers", 40.0);
DispatchSpawn(entity);
return entity;
}
// Taken from silver's https://forums.alliedmods.net/showthread.php?p=1658873
stock int CreateDynamicLight(float vOrigin[3], float vAngles[3], int color, float brightness, int style = 0) {
int entity = CreateEntityByName("light_dynamic");
if( entity == -1)
return -1;
DispatchKeyValue(entity, "_light", "0 0 0 255");
DispatchKeyValue(entity, "brightness", "1");
DispatchKeyValueFloat(entity, "spotlight_radius", 32.0);
DispatchKeyValueFloat(entity, "distance", brightness);
DispatchKeyValue(entity, "targetname", "hslamp");
DispatchKeyValueFloat(entity, "style", float(style));
SetEntProp(entity, Prop_Send, "m_clrRender", color);
if(DispatchSpawn(entity)) {
TeleportEntity(entity, vOrigin, vAngles, NULL_VECTOR);
AcceptEntityInput(entity, "TurnOn");
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn dynamic light %.1f %.1f %.1f", vOrigin[0], vOrigin[1], vOrigin[2]);
#endif
return entity;
}
return -1;
}
#define ENT_PROP_NAME "hsprop"
#define ENT_BLOCKER_NAME "hsblocker"
#define ENT_PORTAL_NAME "hsportal"
#define ENT_ENV_NAME "hsenv"
#include <gamemodes/ents>
stock void CheatCommand(int client, const char[] command, const char[] argument1) {
int userFlags = GetUserFlagBits(client);
@ -182,7 +18,7 @@ stock void EntFire(const char[] name, const char[] input) {
static char targetname[64];
static char cmd[32];
#if defined DEBUG_LOG_MAPSTART
PrintToServer("[H&S] EntFire: %s \"%s\"", name, input);
PrintToServer("EntFire: %s \"%s\"", name, input);
#endif
int len = SplitString(input, " ", cmd, sizeof(cmd));
if(len > -1) SetVariantString(input[len]);
@ -220,11 +56,6 @@ stock void EntFire(const char[] name, const char[] input) {
}
}
int GetHammerId(int entity) {
return HasEntProp(entity, Prop_Data, "m_iHammerID") ? GetEntProp(entity, Prop_Data, "m_iHammerID") : -1;
}
void SetupEntities(bool blockers = true, bool props = true, bool portals = true) {
#if defined DEBUG_BLOCKERS

View file

@ -5,6 +5,7 @@
#define DEBUG_SHOW_POINTS
#define DEBUG_BOT_MOVE
#define DEBUG_BLOCKERS
// #define DEBUG_LOG_MAPSTART
// #define DEBUG_MOVE_ATTEMPTS
// #define DEBUG_SEEKER_PATH_CREATION 1
@ -22,7 +23,7 @@
#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 BOT_MOVE_NOT_REACHED_ATTEMPT_RETRY 10 // 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
@ -157,11 +158,19 @@ public void OnPluginStart() {
validSets = new ArrayList(ByteCountToCells(16));
mapConfigs = new StringMap();
movePoints = new MovePoints();
g_FadeUserMsgId = GetUserMessageId("Fade");
cvarStorage = new GameConVarStorage();
cvar_survivorLimit = new GameConVar("cvar_survivorLimit");
cvar_separationMinRange = new GameConVar("sb_separation_danger_min_range");
cvar_separationMaxRange = new GameConVar("sb_separation_danger_max_range");
cvar_abmAutoHard = new GameConVar("abm_autohard");
cvar_sbFixEnabled = new GameConVar("sb_fix_enabled");
cvar_sbPushScale = new GameConVar("sb_pushscale");
cvar_battlestationGiveUp = new GameConVar("sb_battlestation_give_up_range_from_human");
cvar_sbMaxBattlestationRange = new GameConVar("sb_max_battlestation_range_from_human");
cvar_enforceProximityRange = new GameConVar("enforce_proximity_range");
ConVar hGamemode = FindConVar("mp_gamemode");
hGamemode.AddChangeHook(Event_GamemodeChange);
@ -190,6 +199,7 @@ public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[
SetCvars(cvarStorage);
Game.Broadcast("Gamemode is starting");
HookEvent("round_start", Event_RoundStart);
HookEvent("round_end", Event_RoundEnd);
HookEvent("player_death", Event_PlayerDeath);
HookEvent("player_bot_replace", Event_PlayerToBot);
HookEvent("player_ledge_grab", Event_LedgeGrab);
@ -198,6 +208,7 @@ public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[
cvarStorage.Restore();
delete cvarStorage;
UnhookEvent("round_start", Event_RoundStart);
UnhookEvent("round_end", Event_RoundEnd);
UnhookEvent("player_death", Event_PlayerDeath);
UnhookEvent("player_bot_replace", Event_PlayerToBot);
UnhookEvent("player_ledge_grab", Event_LedgeGrab);
@ -261,7 +272,12 @@ void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
}
void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) {
CreateTimer(5.0, Timer_WaitForPlayers, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
CreateTimer(2.5, Timer_WaitForPlayers, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) {
// Skip the check, everyone's loaded in
firstCheckDone = true;
}
public void OnMapStart() {
@ -297,7 +313,7 @@ public void OnMapStart() {
int seeker = Game.Seeker;
if(seeker > -1) {
currentSeeker = seeker;
Game.Debug("-Late load- Seeker: %N",currentSeeker);
Game.Debug("-Late load- Seeker: %N", currentSeeker);
}
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i)) {
@ -317,7 +333,6 @@ public void OnMapStart() {
}
public void ThinkPost(int entity) {
static int iTeamNum[MAXPLAYERS+1];
GetEntDataArray(entity, g_iTeamNum, iTeamNum, sizeof(iTeamNum));
for(int i = 1 ; i<= MaxClients; i++) {
@ -329,14 +344,6 @@ public void ThinkPost(int entity) {
SetEntDataArray(entity, g_iTeamNum, iTeamNum, sizeof(iTeamNum));
}
public void OnMapEnd() {
for(int i = 1; i <= MaxClients; i++) {
if(moveTimers[i] != null) {
delete moveTimers[i];
}
}
}
public void OnClientPutInServer(int client) {
if(isEnabled && !IsFakeClient(client)) {
ChangeClientTeam(client, 1);
@ -387,7 +394,7 @@ void InitGamemode() {
Game.DebugConsole("InitGamemode(): activating");
ArrayList validPlayerIds = new ArrayList();
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) {
if(IsClientConnected(i) && IsClientInGame(i)) {
ChangeClientTeam(i, 2);
activeBotLocations[i].attempts = 0;
if(IsFakeClient(i)) {
@ -403,6 +410,7 @@ void InitGamemode() {
if(!hasBeenSeeker[i] || ignoreSeekerBalance)
validPlayerIds.Push(GetClientUserId(i));
}
Game.TeleportToSpawn(i);
}
}
if(validPlayerIds.Length == 0) {
@ -507,15 +515,15 @@ Action Timer_WaitForStart(Handle h) {
for(int i = 1; i <= MaxClients; i++) {
if(i != currentSeeker && IsClientConnected(i) && IsClientInGame(i)) {
TeleportEntity(i, seekerPos, NULL_VECTOR, NULL_VECTOR);
if(IsFakeClient(i)) {
if(IsFakeClient(i) && movePoints.Length > 0) {
moveTimers[i] = CreateTimer(GetRandomFloat(BOT_MOVE_RANDOM_MIN_TIME, BOT_MOVE_RANDOM_MAX_TIME), Timer_BotMove, GetClientUserId(i), TIMER_REPEAT);
movePoints.GetArray(GetURandomInt() % movePoints.Length, activeBotLocations[i]);
movePoints.GetRandomPoint(activeBotLocations[i]);
TeleportEntity(i, activeBotLocations[i].pos, activeBotLocations[i].ang, NULL_VECTOR);
}
}
}
Game.Broadcast("Seeker will start in %.0f seconds", SEED_TIME);
Game.Broadcast("The Seeker (%N) will start in %.0f seconds", Game.Seeker, SEED_TIME);
Game.State = State_Starting;
Game.Tick = 0;
Game.MapTime = RoundFloat(SEED_TIME);
@ -554,7 +562,7 @@ Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float& damag
if(attacker == currentSeeker) {
damage = 100.0;
ClearInventory(victim);
if(IsFakeClient(victim)) {
if(attacker > 0 && attacker <= MaxClients && IsFakeClient(victim)) {
PrintToChat(attacker, "That was a bot! -%.0f health", cvar_seekerFailDamageAmount.FloatValue);
SDKHooks_TakeDamage(attacker, 0, 0, cvar_seekerFailDamageAmount.FloatValue, DMG_DIRECT);
}